From f3f818113e0bd66f0103a7a3fcd04625c368ebc9 Mon Sep 17 00:00:00 2001 From: Arjan van Vught Date: Mon, 23 Sep 2024 20:08:52 +0200 Subject: [PATCH] V2.1 - Improved startup_gd32fxxx.S - CMSIS has its own project now - Upgraded to CMSIS V5.0.5 - Removed lib-debug. Now part of lib-hal - Updated to latest GD32 Firmware - Introduced debug software UART0 - Major cleanup lib-configstore - In order to support Newlib; removed lib-c, lib-c++ and added lib-clib - In order to support FreeRTOS; Added Software timers in H.A.L. framework. - Updated Art-Net with latest specifications - Improved support for RDMNet LLRP only - Moved parameter utc_offset to "env.txt" - Improved HTTP Server - Added support for remote UART shell - Removed lib-rdmdiscovery, lib-rdmnet and lib-rdmresponder - Removed lib-oscclient and lib-oscserver --- .gitignore | 19 +- CMSIS/.cproject | 63 + {lib-uuid => CMSIS}/.project | 52 +- .../.settings/language.settings.xml | 2 +- .../org.eclipse.core.resources.prefs | 0 CMSIS/Core/Include/cachel1_armv7.h | 411 + .../Core/Include}/cmsis_armcc.h | 1622 +- CMSIS/Core/Include/cmsis_armclang.h | 1503 ++ CMSIS/Core/Include/cmsis_armclang_ltm.h | 1928 ++ CMSIS/Core/Include/cmsis_compiler.h | 283 + CMSIS/Core/Include/cmsis_gcc.h | 2211 +++ CMSIS/Core/Include/cmsis_iccarm.h | 1002 + CMSIS/Core/Include/cmsis_version.h | 39 + CMSIS/Core/Include/core_cm3.h | 1943 ++ CMSIS/Core/Include/core_cm4.h | 2129 +++ CMSIS/Core/Include/core_cm7.h | 2366 +++ CMSIS/Core/Include/mpu_armv7.h | 275 + CMSIS/Core/Include/tz_context.h | 70 + CMSIS/LICENSE.txt | 201 + README.md | 2 +- firmware-template-gd32/Artnet.mk | 5 + firmware-template-gd32/Board.mk | 108 + firmware-template-gd32/FreeRTOS.mk | 35 + firmware-template-gd32/Includes.mk | 24 +- firmware-template-gd32/Mcu.mk | 71 +- firmware-template-gd32/Rules.mk | 67 +- firmware-template-gd32/Validate.mk | 33 + .../calculate_unused_ram.sh | 32 - firmware-template-gd32/gd32f207rg_flash.ld | 38 +- firmware-template-gd32/hardfault_handler.c | 30 +- .../include/software_version.h | 4 +- firmware-template-gd32/lib/Rules.mk | 58 +- firmware-template-gd32/startup_gd32f20x_cl.S | 99 +- firmware-template/libs.mk | 51 +- gd32_emac_artnet_dmx_multi/.cproject | 111 +- gd32_emac_artnet_dmx_multi/Common.mk | 19 + .../Makefile-bw-softuart0.GD32 | 21 +- gd32_emac_artnet_dmx_multi/Makefile-bw.GD32 | 21 +- gd32_emac_artnet_dmx_multi/Makefile-dmx3.GD32 | 21 +- .../Makefile-dmx4-softuart0.GD32 | 20 +- gd32_emac_artnet_dmx_multi/Makefile-dmx4.GD32 | 21 +- gd32_emac_artnet_dmx_multi/Makefile.GD32 | 20 +- gd32_emac_artnet_dmx_multi/do-tftp.sh | 56 +- gd32_emac_artnet_dmx_multi/firmware/main.cpp | 150 +- .../include/display_timeout.h | 45 - .../lib/rdmsoftwareversion.cpp | 2 +- .../lib/showfileusb.cpp | 33 +- gd32_emac_artnet_pixel_multi/.cproject | 37 +- .../Makefile-softuart0.GD32 | 36 + gd32_emac_artnet_pixel_multi/Makefile.GD32 | 11 +- .../firmware/main.cpp | 178 +- .../generate_sofware_version_id.sh | 4 - .../include/display_timeout.h | 45 - .../include/pixeldmxstartstop.h | 53 - .../include/sofware_version_id.h | 2 - .../lib/factorydefaults.cpp | 4 +- .../lib/rdmsoftwareversion.cpp | 2 +- .../lib/showfileusb.cpp | 55 + gd32_emac_ddp_pixel_multi/.cproject | 36 +- .../.settings/language.settings.xml | 2 +- gd32_emac_ddp_pixel_multi/Makefile.GD32 | 3 +- gd32_emac_ddp_pixel_multi/firmware/main.cpp | 114 +- .../generate_sofware_version_id.sh | 4 - .../include/sofware_version_id.h | 2 - .../lib/factorydefaults.cpp | 4 +- .../lib/rdmsoftwareversion.cpp | 2 +- gd32_emac_e131_dmx_multi/.cproject | 9 - gd32_emac_e131_dmx_multi/Common.mk | 10 + gd32_emac_e131_dmx_multi/Makefile.GD32 | 4 +- gd32_emac_e131_dmx_multi/firmware/main.cpp | 145 +- .../generate_sofware_version_id.sh | 4 - .../include/sofware_version_id.h | 2 - .../lib/factorydefaults.cpp | 4 +- .../lib/rdmsoftwareversion.cpp | 2 +- gd32_emac_e131_dmx_multi/lib/showfileusb.cpp | 55 + gd32_emac_e131_pixel_multi/.cproject | 9 - gd32_emac_e131_pixel_multi/Makefile.GD32 | 5 +- gd32_emac_e131_pixel_multi/firmware/main.cpp | 170 +- .../generate_sofware_version_id.sh | 4 - .../include/display_timeout.h | 45 - .../include/sofware_version_id.h | 2 - .../lib/factorydefaults.cpp | 4 +- .../lib/rdmsoftwareversion.cpp | 2 +- .../lib/showfileusb.cpp | 55 + gd32_emac_llrp/.cproject | 132 + .../.project | 59 +- gd32_emac_llrp/.pydevproject | 5 + .../.settings/language.settings.xml | 2 +- .../org.eclipse.core.resources.prefs | 0 gd32_emac_llrp/Makefile.GD32 | 33 + gd32_emac_llrp/firmware/main.cpp | 151 + .../include/factorydefaults.h | 8 +- .../lib/rdmsoftwareversion.cpp | 4 +- gd32_emac_pp_pixel_multi/.cproject | 8 - gd32_emac_pp_pixel_multi/Makefile.GD32 | 7 +- gd32_emac_pp_pixel_multi/firmware/main.cpp | 118 +- .../generate_sofware_version_id.sh | 4 - .../include/display_timeout.h | 45 - .../include/sofware_version_id.h | 2 - .../lib/factorydefaults.cpp | 4 +- .../lib/rdmsoftwareversion.cpp | 2 +- gd32_rdm_responder/.cproject | 154 - gd32_rdm_responder/Makefile.GD32 | 23 - gd32_rdm_responder/do-tftp.sh | 35 - gd32_rdm_responder/firmware/main.cpp | 257 - .../generate_sofware_version_id.sh | 4 - gd32_rdm_responder/include/display_timeout.h | 45 - gd32_rdm_responder/include/is_config_mode.h | 41 - .../include/pixeldmxstartstop.h | 53 - .../include/sofware_version_id.h | 2 - gd32_rdm_responder/lib/display.cpp | 62 - gd32_rdm_responder/lib/personalityupdate.cpp | 62 - gd32_rdm_responder/lib/rdm_selftest.cpp | 76 - gd32_rdm_responder/lib/rdmslotinfo.cpp | 65 - include/cstring | 37 +- include/dirent.h | 4 +- include/stdio.h | 71 +- include/string.h | 15 + include/time.h | 3 +- lib-artnet/.cproject | 15 +- lib-artnet/Rules.mk | 25 +- lib-artnet/include/artnet.h | 110 +- lib-artnet/include/artnetconst.h | 2 +- lib-artnet/include/artnetcontroller.h | 55 +- lib-artnet/include/artnetmsgconst.h | 6 +- lib-artnet/include/artnetnode.h | 412 +- .../include/artnetnode_ports.h | 23 +- lib-artnet/include/artnetparams.h | 29 +- lib-artnet/include/artnetpolltable.h | 53 +- lib-artnet/include/artnetrdmcontroller.h | 165 + .../include/artnetrdmresponder.h | 70 +- lib-artnet/include/artnetstore.h | 226 +- lib-artnet/include/artnettimecode.h | 15 +- lib-artnet/include/artnettrigger.h | 5 +- lib-artnet/src/artnetconst.cpp | 7 +- .../src/controller/artnetcontroller.cpp | 233 +- lib-artnet/src/controller/artnetpolltable.cpp | 153 +- .../src/controller/json_get_polltable.cpp | 93 + lib-artnet/src/node/4/artnetnode.cpp | 10 +- lib-artnet/src/node/artnetmsgconst.cpp | 8 +- lib-artnet/src/node/artnetnode.cpp | 128 +- .../src/node/artnetnodehandleaddress.cpp | 49 +- lib-artnet/src/node/artnetnodehandledmx.cpp | 6 + lib-artnet/src/node/artnetnodehandlepoll.cpp | 11 +- lib-artnet/src/node/artnetnodehandlesync.cpp | 6 - lib-artnet/src/node/artnetnodeprint.cpp | 18 +- lib-artnet/src/node/artnetparams.cpp | 128 +- lib-artnet/src/node/artnetparamsdump.cpp | 124 - lib-artnet/src/node/dmxin/handledmxin.cpp | 15 +- .../rdm/controller}/artnetrdmcontroller.cpp | 139 +- .../src/node/rdm/controller/handlerdm.cpp | 265 + .../src/node/rdm/controller/handlerdmin.cpp | 106 + .../src/node/rdm/controller/handlerdmsub.cpp | 31 +- .../rdm/controller/json_get_portstatus.cpp | 89 + .../node/rdm/controller/json_get_queue.cpp | 38 +- .../src/node/rdm/controller/json_get_rdm.cpp | 38 + .../src/node/rdm/controller/json_get_tod.cpp | 44 +- lib-artnet/src/node/rdm/controller/setrdm.cpp | 56 + lib-artnet/src/node/rdm/handlerdm.cpp | 278 +- lib-artnet/src/node/rdm/handlerdmin.cpp | 67 - .../node/rdm/responder/artnetrdmresponder.cpp | 13 +- .../src/node/rdm/responder/handlerdm.cpp | 147 + .../src/node/rdm/responder/handlerdmsub.cpp | 34 +- lib-artnet/src/node/rdm/responder/setrdm.cpp | 55 + lib-artnet/src/node/rdm/setrdm.cpp | 76 + .../src/node/timecode/handletimecode.cpp | 67 - lib-c++/.cproject | 94 - lib-c++/.settings/language.settings.xml | 12 - lib-c++/Makefile.GD32 | 2 - lib-c/.cproject | 81 - lib-c/.settings/org.eclipse.cdt.core.prefs | 6 - lib-c/Makefile.GD32 | 3 - lib-clib/.cproject | 161 + {lib-c => lib-clib}/.project | 2 +- lib-clib/.settings/language.settings.xml | 15 + .../org.eclipse.core.resources.prefs | 0 lib-clib/Makefile.GD32 | 25 + lib-clib/Rules.mk | 2 + lib-clib/src/abort.c | 15 + {lib-c => lib-clib}/src/asctime.c | 0 lib-clib/src/c++/cxa_atexit.cpp | 26 + {lib-c++/src => lib-clib/src/c++}/delete.cpp | 17 +- .../src => lib-clib/src/c++}/dso_handle.cpp | 14 +- lib-clib/src/c++/impure_prt.cpp | 11 + {lib-c++/src => lib-clib/src/c++}/new.cpp | 4 +- .../src => lib-clib/src/c++}/purecall.cpp | 2 +- {lib-c => lib-clib}/src/errno.c | 0 {lib-c/src => lib-clib/src/gd32}/assert.c | 0 .../src/gd32/malloc.h | 23 +- lib-clib/src/gd32/time_ptp/time.cpp | 99 + .../src/gd32/time_systick/time.cpp | 66 +- lib-clib/src/gd32/time_timer/time.cpp | 157 + lib-clib/src/gd32/uuid.cpp | 58 + {lib-c => lib-clib}/src/inet_aton.c | 5 +- {lib-c => lib-clib}/src/init.c | 0 {lib-c => lib-clib}/src/log.c | 0 {lib-c => lib-clib}/src/malloc.c | 38 +- lib-clib/src/memchr.c | 19 + lib-clib/src/memcmp.c | 24 + {lib-c => lib-clib}/src/memcpy.c | 0 {lib-c => lib-clib}/src/memmove.c | 0 {lib-c => lib-clib}/src/memset.c | 0 {lib-c => lib-clib}/src/perror.c | 0 {lib-c => lib-clib}/src/printf.c | 29 +- {lib-c => lib-clib}/src/putchar.c | 0 {lib-c => lib-clib}/src/puts.c | 0 {lib-c => lib-clib}/src/random.c | 0 lib-clib/src/strchr.c | 55 + {lib-c => lib-clib}/src/strlen.c | 0 lib-clib/src/strncmp.c | 51 + lib-clib/src/strstr.c | 71 + {lib-c => lib-clib}/src/strtok.c | 0 lib-clib/src/strtoul.c | 118 + lib-c/src/time.c => lib-clib/src/time.cpp | 121 +- {lib-uuid => lib-clib}/src/uuid_internal.h | 0 {lib-uuid => lib-clib}/src/uuid_parse.c | 0 {lib-uuid => lib-clib}/src/uuid_unparse.c | 0 lib-configstore/.cproject | 11 - .../.settings/language.settings.xml | 2 +- lib-configstore/Rules.mk | 156 +- lib-configstore/device/rom/storedevice.cpp | 3 +- lib-configstore/device/spi/storedevice.cpp | 11 +- lib-configstore/include/configstore.h | 82 +- .../{storedevice.h => configstoredevice.h} | 0 lib-configstore/include/envparams.h | 48 + lib-configstore/include/envparamsconst.h | 35 + lib-configstore/include/storeartnet.h | 113 - lib-configstore/include/storedisplayudf.h | 53 - lib-configstore/include/storedmxsend.h | 53 - lib-configstore/include/storee131.h | 52 - lib-configstore/include/storenetwork.h | 76 - lib-configstore/include/storepixeldmx.h | 80 - lib-configstore/include/storerdmdevice.h | 61 - lib-configstore/include/storerdmsensors.h | 67 - lib-configstore/include/storeremoteconfig.h | 53 - lib-configstore/include/storetlc59711.h | 60 - lib-configstore/src/artnet/storeartnet.cpp | 232 - lib-configstore/src/configstore.cpp | 55 +- lib-configstore/src/envparams.cpp | 132 + lib-configstore/src/envparamsconst.cpp | 30 + lib-configstore/src/platform_configstore.h | 0 lib-configstore/src/storenetwork.cpp | 41 - lib-ddp/.cproject | 8 - lib-ddp/Rules.mk | 3 +- lib-ddp/include/ddp.h | 2 +- lib-ddp/src/ddpdisplay.cpp | 10 +- lib-debug/.cproject | 80 - lib-debug/.settings/language.settings.xml | 12 - lib-debug/Makefile.GD32 | 3 - lib-device/.cproject | 5 - lib-device/include/ema.h | 77 + lib-device/include/max7219.h | 2 +- lib-device/include/mcp23s17.h | 2 +- .../utc.cpp => lib-device/include/mcp23x08.h | 45 +- lib-device/include/mcp23x17.h | 4 +- lib-device/include/mcp49x2.h | 2 +- lib-device/include/sc16is740.h | 4 +- lib-device/include/sc16is7x0.h | 2 +- lib-device/src/sc16is740.cpp | 2 +- lib-display/.cproject | 5 - lib-display/include/display.h | 11 +- lib-display/include/display7segment.h | 145 - lib-display/include/displayset.h | 8 +- lib-display/include/i2c/display.h | 116 +- lib-display/include/i2c/ssd1311.h | 2 +- lib-display/include/spi/config.h | 34 +- lib-display/include/spi/display.h | 22 +- lib-display/include/spi/ili9341.h | 75 +- lib-display/include/spi/spi_lcd.h | 18 +- lib-display/include/spi/st77xx.h | 77 +- lib-display/src/i2c/display.cpp | 28 +- lib-display/src/i2c/hd44780.cpp | 6 +- lib-display/src/i2c/ssd1306.cpp | 4 +- lib-display/src/i2c/ssd1311.cpp | 4 +- lib-display/src/spi/display.cpp | 19 +- lib-display/src/spi/ili9341.cpp | 4 +- lib-display/src/spi/st7789.cpp | 2 +- lib-display/src/spi/st7xx.cpp | 2 +- lib-displayudf/.cproject | 5 - lib-displayudf/Rules.mk | 33 +- lib-displayudf/include/displayudf.h | 95 +- lib-displayudf/include/displayudfparams.h | 24 +- .../include/displayudfparamsconst.h | 2 +- lib-displayudf/src/artnet/artnetdisplay.cpp | 34 +- .../src/artnet/displayudfshowartnet.cpp | 35 +- lib-displayudf/src/displayudf.cpp | 10 +- lib-displayudf/src/displayudfparams.cpp | 90 +- .../src/e131/displayudfshowe131.cpp | 19 +- lib-displayudf/src/network/network.cpp | 12 +- lib-displayudf/src/network/ntpclient.cpp | 26 +- .../src/node/displayudfshownode.cpp | 18 +- lib-dmx/.cproject | 188 +- lib-dmx/Makefile.GD32 | 8 +- lib-dmx/Rules.mk | 19 +- lib-dmx/include/dmxconfigudp.h | 24 +- lib-dmx/include/dmxparams.h | 44 +- lib-dmx/include/dmxparamsconst.h | 2 +- .../include/dmxreceiver.h | 52 +- lib-dmx/include/dmxsend.h | 156 + lib-dmx/include/dmxstatistics.h | 52 + lib-dmx/include/gd32/board_bw_opidmx4.h | 9 +- lib-dmx/include/gd32/board_dmx3.h | 7 +- lib-dmx/include/gd32/board_dmx4.h | 7 +- lib-dmx/include/gd32/board_gd32f207rg.h | 9 +- lib-dmx/include/gd32/dmx.h | 61 +- lib-dmx/include/gd32/dmx_config.h | 17 +- lib-dmx/src/artnet/dmxinput.cpp | 95 - lib-dmx/src/dmxparams.cpp | 143 +- lib-dmx/src/e131/dmxinput.cpp | 92 - lib-dmx/src/gd32/dmx.cpp | 2157 ++- lib-dmx/src/gd32/dmx_internal.h | 144 +- lib-dmx/src/gd32/rdm.cpp | 120 - lib-dmx/src/json_get_ports.cpp | 58 + lib-dmx/src/json_get_portstatus.cpp | 58 + lib-dmxreceiver/.cproject | 111 - lib-dmxreceiver/.project | 27 - .../.settings/language.settings.xml | 12 - lib-dmxreceiver/Makefile.GD32 | 5 - lib-dmxreceiver/src/dmxreceiver.cpp | 30 - lib-dmxsend/.cproject | 164 - lib-dmxsend/.project | 27 - lib-dmxsend/.settings/language.settings.xml | 12 - .../.settings/org.eclipse.cdt.core.prefs | 6 - .../org.eclipse.core.resources.prefs | 2 - lib-dmxsend/Makefile.GD32 | 4 - lib-dmxsend/include/dmxsend.h | 88 - lib-dmxsend/src/dmxsend.cpp | 148 - lib-e131/.cproject | 5 - lib-e131/Rules.mk | 5 + lib-e131/include/e131bridge.h | 132 +- .../{e131bridgeconst.h => e131const.h} | 12 +- lib-e131/include/e131controller.h | 2 +- lib-e131/include/e131msgconst.h | 3 +- lib-e131/include/e131packets.h | 2 +- lib-e131/include/e131params.h | 26 +- lib-e131/include/e131paramsconst.h | 2 +- lib-e131/include/e131sync.h | 4 +- lib-e131/src/controller/e131controller.cpp | 4 +- .../e131bridgeconst.cpp => e131const.cpp} | 8 +- lib-e131/src/node/dmxin/discoverypacket.cpp | 28 +- lib-e131/src/node/dmxin/handledmxin.cpp | 71 +- lib-e131/src/node/e131bridge.cpp | 25 +- .../node/e131bridgehandlesynchronization.cpp | 13 +- lib-e131/src/node/e131bridgeprint.cpp | 11 +- lib-e131/src/node/e131msgconst.cpp | 3 +- lib-e131/src/node/e131params.cpp | 95 +- lib-e131/src/node/e131paramsconst.cpp | 2 +- lib-e131/src/node/e131paramsdump.cpp | 78 - lib-flash/.cproject | 5 - lib-flash/include/spi/spi_flash.h | 2 +- lib-flash/src/spi/gd32/spi_flash.cpp | 13 +- lib-flash/src/spi/get_timer.cpp | 2 +- lib-flash/src/spi/gigadevice.cpp | 10 +- lib-flash/src/spi/macronix.cpp | 2 +- lib-flash/src/spi/spi_flash.cpp | 13 +- lib-flash/src/spi/spi_flash_internal.h | 12 +- lib-flash/src/spi/winbond.cpp | 2 +- lib-flashcode/.cproject | 6 - lib-flashcode/Makefile.GD32 | 6 +- lib-flashcode/include/flashcode.h | 2 +- lib-flashcode/src/gd32/f4xx/flashcode.cpp | 154 - lib-flashcode/src/gd32/f4xx/fmc_operation.cpp | 367 - lib-flashcode/src/gd32/f4xx/fmc_operation.h | 92 - lib-flashcode/src/gd32/flashcode.cpp | 4 +- lib-flashcode/src/gd32/fmc/flashcode.cpp | 12 +- lib-flashcode/src/gd32/h7xx/flashcode.cpp | 217 + lib-gd32/.cproject | 8 +- lib-gd32/Makefile.GD32 | 193 +- lib-gd32/device/usb/f/usb_conf.h | 101 + lib-gd32/device/usb/usb.cpp | 35 + lib-gd32/device/usb/usb_conf.h | 37 + .../device/usb/usb_vbus.cpp | 31 +- .../net.c => lib-gd32/device/usb/usbh_conf.h | 33 +- .../CMSIS/GD/GD32F20x/Include/gd32f20x.h | 73 +- .../GD/GD32F20x/Source/system_gd32f20x.c | 395 +- lib-gd32/gd32f20x/CMSIS/core_cm3.h | 1638 -- lib-gd32/gd32f20x/CMSIS/core_cmFunc.h | 616 - lib-gd32/gd32f20x/CMSIS/core_cmInstr.h | 618 - .../Include/gd32f20x_adc.h | 137 +- .../Include/gd32f20x_bkp.h | 93 +- .../Include/gd32f20x_can.h | 497 +- .../Include/gd32f20x_cau.h | 108 +- .../Include/gd32f20x_crc.h | 45 +- .../Include/gd32f20x_dac.h | 129 +- .../Include/gd32f20x_dbg.h | 97 +- .../Include/gd32f20x_dci.h | 52 +- .../Include/gd32f20x_dma.h | 234 +- .../Include/gd32f20x_enet.h | 859 +- .../Include/gd32f20x_exmc.h | 618 +- .../Include/gd32f20x_exti.h | 134 +- .../Include/gd32f20x_fmc.h | 304 +- .../Include/gd32f20x_fwdgt.h | 51 +- .../Include/gd32f20x_gpio.h | 111 +- .../Include/gd32f20x_hau.h | 89 +- .../Include/gd32f20x_i2c.h | 362 +- .../Include/gd32f20x_misc.h | 72 +- .../Include/gd32f20x_pmu.h | 57 +- .../Include/gd32f20x_rcu.h | 142 +- .../Include/gd32f20x_rtc.h | 106 +- .../Include/gd32f20x_sdio.h | 37 +- .../Include/gd32f20x_spi.h | 154 +- .../Include/gd32f20x_timer.h | 221 +- .../Include/gd32f20x_tli.h | 187 +- .../Include/gd32f20x_trng.h | 80 +- .../Include/gd32f20x_usart.h | 439 +- .../Include/gd32f20x_wwdgt.h | 53 +- .../Source/gd32f20x_adc.c | 470 +- .../Source/gd32f20x_bkp.c | 237 +- .../Source/gd32f20x_can.c | 646 +- .../Source/gd32f20x_cau.c | 107 +- .../Source/gd32f20x_cau_aes.c | 205 +- .../Source/gd32f20x_cau_des.c | 109 +- .../Source/gd32f20x_cau_tdes.c | 119 +- .../Source/gd32f20x_crc.c | 43 +- .../Source/gd32f20x_dac.c | 115 +- .../Source/gd32f20x_dbg.c | 67 +- .../Source/gd32f20x_dci.c | 89 +- .../Source/gd32f20x_dma.c | 358 +- .../Source/gd32f20x_enet.c | 1779 +- .../Source/gd32f20x_exmc.c | 727 +- .../Source/gd32f20x_exti.c | 118 +- .../Source/gd32f20x_fmc.c | 440 +- .../Source/gd32f20x_fwdgt.c | 141 +- .../Source/gd32f20x_gpio.c | 448 +- .../Source/gd32f20x_hau.c | 97 +- .../Source/gd32f20x_hau_sha_md5.c | 235 +- .../Source/gd32f20x_i2c.c | 323 +- .../Source/gd32f20x_misc.c | 75 +- .../Source/gd32f20x_pmu.c | 137 +- .../Source/gd32f20x_rcu.c | 582 +- .../Source/gd32f20x_rtc.c | 224 +- .../Source/gd32f20x_sdio.c | 51 +- .../Source/gd32f20x_spi.c | 471 +- .../Source/gd32f20x_timer.c | 619 +- .../Source/gd32f20x_tli.c | 584 +- .../Source/gd32f20x_trng.c | 69 +- .../Source/gd32f20x_usart.c | 355 +- .../Source/gd32f20x_wwdgt.c | 99 +- .../device/class/audio/Include/audio_core.h | 320 + .../class/audio/Include/audio_out_itf.h | 49 + .../device/class/audio/Source/audio_core.c | 959 + .../device/class/audio/Source/audio_out_itf.c | 168 + .../device/class/cdc/Include/cdc_acm_core.h | 66 + .../device/class/cdc/Source/cdc_acm_core.c | 529 + .../device/class/dfu/Include/dfu_core.h | 175 + .../device/class/dfu/Include/dfu_mem.h | 83 + .../device/class/dfu/Source/dfu_core.c | 733 + .../device/class/dfu/Source/dfu_mem.c | 243 + .../class/hid/Include/custom_hid_core.h | 69 + .../class/hid/Include/standard_hid_core.h | 68 + .../device/class/hid/Source/custom_hid_core.c | 488 + .../class/hid/Source/standard_hid_core.c | 389 + .../device/class/iap/Include/usb_iap_core.h | 89 + .../device/class/iap/Source/usb_iap_core.c | 561 + .../device/class/msc/Include/usbd_msc_bbb.h | 101 + .../device/class/msc/Include/usbd_msc_core.h | 59 + .../device/class/msc/Include/usbd_msc_mem.h | 59 + .../device/class/msc/Include/usbd_msc_scsi.h | 58 + .../device/class/msc/Source/usbd_msc_bbb.c | 287 + .../device/class/msc/Source/usbd_msc_core.c | 318 + .../device/class/msc/Source/usbd_msc_scsi.c | 761 + .../class/printer/Include/printer_core.h | 78 + .../class/printer/Source/printer_core.c | 310 + .../device/core/Include/usbd_core.h | 103 + .../device/core/Include/usbd_enum.h | 106 + .../device/core/Include/usbd_transc.h | 56 + .../device/core/Source/usbd_core.c | 312 + .../device/core/Source/usbd_enum.c | 764 + .../device/core/Source/usbd_transc.c | 256 + .../driver/Include/drv_usb_core.h | 347 + .../driver/Include/drv_usb_dev.h | 197 + .../driver/Include/drv_usb_host.h | 123 + .../driver/Include/drv_usb_hw.h | 63 + .../driver/Include/drv_usb_regs.h | 628 + .../driver/Include/drv_usbd_int.h | 45 + .../driver/Include/drv_usbh_int.h | 54 + .../driver/Source/drv_usb_core.c | 330 + .../driver/Source/drv_usb_dev.c | 595 + .../driver/Source/drv_usb_host.c | 446 + .../driver/Source/drv_usbd_int.c | 494 + .../driver/Source/drv_usbh_int.c | 598 + .../host/class/hid/Include/usbh_hid_core.h | 120 + .../class/hid/Include/usbh_standard_hid.h | 99 + .../host/class/hid/Source/usbh_hid_core.c | 581 + .../host/class/hid/Source/usbh_standard_hid.c | 274 + .../host/class/msc/Include/usbh_msc_bbb.h | 150 + .../host/class/msc/Include/usbh_msc_core.h | 124 + .../host/class/msc/Include/usbh_msc_scsi.h | 100 + .../host/class/msc/Source/usbh_msc_bbb.c | 362 + .../host/class/msc/Source/usbh_msc_core.c | 563 + .../host/class/msc/Source/usbh_msc_fatfs.c | 235 + .../host/class/msc/Source/usbh_msc_scsi.c | 400 + .../host/core/Include/usbh_core.h | 279 + .../host/core/Include/usbh_enum.h | 70 + .../host/core/Include/usbh_pipe.h | 102 + .../host/core/Include/usbh_transc.h | 50 + .../host/core/Source/usbh_core.c | 653 + .../host/core/Source/usbh_enum.c | 693 + .../host/core/Source/usbh_pipe.c | 181 + .../host/core/Source/usbh_transc.c | 370 + .../ustd/class/cdc/usb_cdc.h | 180 + .../ustd/class/hid/usb_hid.h | 83 + .../ustd/class/msc/msc_bbb.h | 69 + .../ustd/class/msc/msc_scsi.h | 117 + .../ustd/class/msc/usb_msc.h | 68 + .../ustd/common/usb_ch9_std.h | 248 + lib-gd32/include/FreeRTOSConfig.h | 164 + lib-gd32/include/board/bw_opidmx4.h | 61 +- lib-gd32/include/board/dmx3.h | 72 +- lib-gd32/include/board/dmx4.h | 75 +- lib-gd32/include/board/gd32f207rg.h | 153 +- lib-gd32/include/board/logic_analyzer.h | 83 +- lib-gd32/include/gd32.h | 67 +- lib-gd32/include/gd32_adc.h | 6 +- lib-gd32/include/gd32_board.h | 26 +- lib-gd32/include/gd32_dma.h | 225 + lib-gd32/include/gd32_dma_memcpy32.h | 56 + lib-gd32/include/gd32_gpio.h | 265 +- lib-gd32/include/gd32_ptp.h | 98 + lib-gd32/include/gd32_pwm.h | 43 + lib-gd32/include/gd32_spi.h | 19 +- lib-gd32/include/gd32_uart.h | 83 +- lib-gd32/include/logic_analyzer.h | 104 +- lib-gd32/include/mcu/gd32f207_mcu.h | 44 + lib-gd32/include/mcu/gd32f20x_mcu.h | 395 +- lib-gd32/src/bkp.cpp | 33 +- lib-gd32/src/{ => f}/gd32_adc.cpp | 9 +- lib-gd32/src/f/gd32_dma_memcpy32.cpp | 55 + lib-gd32/src/{ => f}/gd32_i2c.cpp | 129 +- lib-gd32/src/{ => f}/gd32_spi.cpp | 99 +- lib-gd32/src/{ => f}/i2s_psc_config_dump.cpp | 2 +- lib-gd32/src/gd32_gpio_mode_set.cpp | 75 + lib-gd32/src/gd32_pwm.cpp | 300 + lib-gd32/src/gd32_spi_dma_i2s.cpp | 246 +- lib-gd32/src/gd32_uart.cpp | 188 +- lib-gd32/src/mac_address.cpp | 13 +- lib-gd32/src/ptp/gd32_ptp.cpp | 183 + lib-gd32/src/softuart0/gd32_uart0.c | 189 - lib-gd32/src/softuart0/uart0.cpp | 234 + .../src/{systick.c => systick/systick.cpp} | 21 +- lib-gd32/src/timer6.cpp | 86 + lib-gd32/src/{gd32_uart0.c => uart0.cpp} | 23 +- .../src/uart0/{gd32_uart0.c => uart0.cpp} | 46 +- lib-gd32/src/udelay.cpp | 17 +- lib-hal/.cproject | 5 - lib-hal/.settings/language.settings.xml | 5 +- .../org.eclipse.ltk.core.refactoring.prefs | 2 + lib-hal/Makefile.GD32 | 45 +- lib-hal/Rules.mk | 36 +- lib-hal/console/h3/console.c | 381 - .../console/i2c/{console.c => console.cpp} | 73 +- lib-hal/console/null/console.cpp | 36 + .../console/uart0/{console.c => console.cpp} | 48 +- .../debug/debug_dump.cpp | 33 +- .../debug/debug_print_bits.cpp | 8 +- lib-hal/debug/emac/gd32/emac_debug.cpp | 6 +- lib-hal/debug/i2c/i2cdetect.cpp | 6 +- lib-hal/debug/i2c/i2cdetect.h | 2 +- lib-hal/debug/stack/stack_debug.cpp | 3 +- .../device/usb/host/gd32/{ => f}/usb_host.cpp | 43 +- lib-hal/device/usb/host/gd32/usb_host_msc.cpp | 99 +- lib-hal/ff14b/LICENSE.txt | 24 + lib-hal/ff14b/source/00history.txt | 359 + lib-hal/ff14b/source/00readme.txt | 21 + lib-hal/ff14b/source/diskio.h | 79 + lib-hal/ff14b/source/ff.c | 6987 +++++++ lib-hal/ff14b/source/ff.h | 422 + lib-hal/ff14b/source/ffconf.h | 308 + lib-hal/ff14b/source/ffsystem.c | 170 + lib-hal/ff14b/source/ffunicode.c | 15593 ++++++++++++++++ lib-hal/include/console.h | 20 +- {lib-debug => lib-hal}/include/debug.h | 20 +- lib-hal/include/device/usb/host.h | 43 + lib-hal/include/gd32/hal_api.h | 16 - lib-hal/include/gd32/hal_i2c.h | 1 + lib-hal/include/gd32/hal_spi.h | 8 +- lib-hal/include/gd32/hal_uart.h | 2 +- lib-hal/include/gd32/hardware.h | 258 +- lib-hal/include/gd32/panel_led.h | 39 +- .../include/hal_api.h | 46 +- lib-hal/include/hal_gpio.h | 2 +- lib-hal/include/hal_i2c.h | 2 + lib-hal/include/hal_spi.h | 6 +- lib-hal/include/hardware.h | 26 +- lib-hal/include/hwclock.h | 53 +- lib-hal/include/panel_led.h | 8 +- lib-hal/include/uart0_debug.h | 2 +- lib-hal/include/utc.h | 68 +- lib-hal/posix/file.cpp | 486 + lib-hal/rtc/gd32/hwclockrtc.cpp | 224 +- lib-hal/rtc/hwclock.cpp | 62 +- lib-hal/rtc/hwclockrun.cpp | 31 +- lib-hal/rtc/hwclockset.cpp | 17 +- lib-hal/rtc/i2c/hwclockrtc.cpp | 456 +- lib-hal/rtc/json_rtc.cpp | 155 + lib-hal/src/gd32/hardware.cpp | 217 +- lib-hal/src/hardware.cpp | 12 +- lib-hal/src/json_datetime.cpp | 125 + lib-hal/src/json_get_directory.cpp | 96 + lib-lightset/.cproject | 5 - lib-lightset/Rules.mk | 6 - lib-lightset/include/lightset.h | 70 +- lib-lightset/include/lightsetdata.h | 20 +- lib-lightset/src/dmxslotinfo.cpp | 4 +- lib-network/.cproject | 5 - lib-network/Makefile.GD32 | 40 +- lib-network/Rules.mk | 9 +- lib-network/config/apps_config.h | 8 +- lib-network/config/net_config.h | 32 +- lib-network/include/emac/emac.h | 25 +- lib-network/include/emac/network.h | 210 +- lib-network/include/emac/phy.h | 5 +- .../include/emac/phy/rtl8201f.h | 27 +- lib-network/include/ip4_address.h | 79 + lib-network/{src/net => include}/net.h | 71 +- lib-network/include/net/acd.h | 71 + lib-network/include/{ => net/apps}/mdns.h | 36 +- lib-network/include/net/apps/ntpclient.h | 147 + .../include/{ => net/apps}/tftpdaemon.h | 15 +- .../net/net_debug.h => include/net/arp.h} | 39 +- lib-network/include/net/autoip.h | 90 + lib-network/include/net/dhcp.h | 139 + lib-network/include/net/igmp.h | 13 + lib-network/include/net/protocol/acd.h | 64 + .../net/protocol/arp.h} | 73 +- lib-network/include/net/protocol/autoip.h | 43 + lib-network/include/net/protocol/dhcp.h | 120 + lib-network/include/net/protocol/dns.h | 93 + .../net/protocol/ethernet.h} | 43 +- lib-network/include/net/protocol/iana.h | 40 + lib-network/include/net/protocol/icmp.h | 65 + .../include/net/protocol/ieee.h | 21 +- .../include/net/protocol/igmp.h | 56 +- lib-network/include/net/protocol/ip4.h | 71 + lib-network/include/{ => net/protocol}/ntp.h | 84 +- lib-network/include/net/protocol/tcp.h | 62 + .../include/net/protocol/udp.h | 53 +- lib-network/include/netif.h | 168 + lib-network/include/network.h | 112 +- lib-network/include/networkconst.h | 2 +- lib-network/include/networkparams.h | 20 +- lib-network/include/networkparamsconst.h | 3 +- lib-network/include/networkstore.h | 60 + lib-network/include/ntpclient.h | 96 - lib-network/src/apps/ntp/ntpclient.cpp | 365 - lib-network/src/emac/gd32/emac.cpp | 206 +- lib-network/src/emac/gd32/f/emac.cpp | 144 + lib-network/src/emac/gd32/f/net.cpp | 244 + lib-network/src/emac/gd32/net_link_check.cpp | 1 + lib-network/src/emac/gd32/net_phy.cpp | 54 +- lib-network/src/emac/network.cpp | 383 +- .../src/emac/phy/json_get_phystatus.cpp | 4 +- .../src/emac/phy/link_handle_change.cpp | 36 +- lib-network/src/emac/phy/net_link_check.cpp | 11 +- lib-network/src/emac/phy/net_phy.cpp | 56 +- lib-network/src/emac/phy/phygen/net_phy.cpp | 12 +- lib-network/src/emac/phy/rtl8201f/net_phy.cpp | 53 +- lib-network/src/net/acd.cpp | 328 + lib-network/src/{ => net}/apps/mdns/mdns.cpp | 141 +- .../src/net/apps/ntp/gd32/ptp/net_ptp.cpp | 484 + lib-network/src/net/apps/ntp/ntpclient.cpp | 263 + .../src/{ => net}/apps/tftp/tftpdaemon.cpp | 8 +- lib-network/src/net/arp.cpp | 545 +- lib-network/src/net/arp_cache.cpp | 171 - lib-network/src/net/autoip.cpp | 172 + lib-network/src/net/dhcp.cpp | 993 +- lib-network/src/net/icmp.cpp | 54 +- lib-network/src/net/igmp.cpp | 177 +- lib-network/src/net/ip.cpp | 29 +- lib-network/src/net/net.cpp | 254 +- lib-network/src/net/net_chksum.cpp | 10 +- lib-network/src/net/net_memcpy.h | 82 +- lib-network/src/net/net_packets.h | 225 - lib-network/src/net/net_platform.h | 2 +- lib-network/src/net/net_private.h | 51 +- lib-network/src/net/net_ptp.cpp | 35 + lib-network/src/net/netif.cpp | 306 + lib-network/src/net/rfc3927.cpp | 90 - lib-network/src/net/tcp.cpp | 255 +- lib-network/src/net/udp.cpp | 231 +- lib-network/src/networkconst.cpp | 2 +- lib-network/src/params/networkparams.cpp | 76 +- .../src/{ => params}/networkparamsconst.cpp | 3 +- lib-network/src/params/networkparamsdump.cpp | 58 - lib-osc/.cproject | 216 + {lib-c++ => lib-osc}/.project | 2 +- .../.settings/language.settings.xml | 22 +- .../org.eclipse.cdt.codan.core.prefs | 107 + .../.settings/org.eclipse.cdt.core.prefs | 0 .../org.eclipse.core.resources.prefs | 0 {lib-rdmresponder => lib-osc}/Makefile.GD32 | 2 + lib-osc/Rules.mk | 24 + lib-osc/include/osc.h | 93 + .../include/oscblob.h | 59 +- lib-osc/include/oscclient.h | 147 + lib-osc/include/oscclientled.h | 36 + .../include/oscclientmsgconst.h | 26 +- lib-osc/include/oscclientparams.h | 119 + lib-osc/include/oscclientparamsconst.h | 43 + lib-osc/include/oscparamsconst.h | 34 + lib-osc/include/oscserver.h | 165 + lib-osc/include/oscserverconst.h | 35 + .../include/oscservermsgconst.h | 25 +- lib-osc/include/oscserverparams.h | 110 + .../include/oscserverparamsconst.h | 22 +- lib-osc/include/oscsimplemessage.h | 73 + lib-osc/include/oscsimplesend.h | 58 + .../include/oscstring.h | 59 +- lib-osc/src/client/oscclient.cpp | 211 + .../src/client/oscclientmsgconst.cpp | 22 +- lib-osc/src/client/oscclientparams.cpp | 292 + .../src/client/oscclientparamsconst.cpp | 22 +- .../src/client/oscclientsend.cpp | 31 +- lib-osc/src/oscparamsconst.cpp | 29 + lib-osc/src/oscsimplemessage.cpp | 106 + lib-osc/src/oscsimplesend.cpp | 126 + lib-osc/src/pattern_match.c | 263 + lib-osc/src/server/oscserver.cpp | 400 + .../src/server/oscserverconst.cpp | 16 +- lib-osc/src/server/oscservermsgconst.cpp | 30 + lib-osc/src/server/oscserverparams.cpp | 241 + lib-osc/src/server/oscserverparamsconst.cpp | 34 + lib-pp/.cproject | 5 - lib-pp/Rules.mk | 3 +- lib-pp/src/pp.cpp | 4 +- lib-properties/.cproject | 5 - lib-properties/include/devicesparamsconst.h | 4 +- lib-properties/include/propertiesbuilder.h | 18 +- lib-properties/include/readconfigfile.h | 2 +- lib-properties/include/sscan.h | 3 +- lib-properties/src/devicesparamsconst.cpp | 4 +- lib-properties/src/properties.cpp | 12 +- lib-properties/src/propertiesbuilder.cpp | 51 + .../src/propertiesbuilderaddhex.cpp | 11 +- lib-properties/src/readconfigfile.cpp | 7 +- lib-properties/src/sscanutcoffset.cpp | 101 + lib-rdm/.cproject | 5 - lib-rdm/Rules.mk | 35 +- {lib-rdmnet => lib-rdm}/include/e133.h | 11 +- .../include => lib-rdm/include/llrp}/llrp.h | 0 .../include/llrp}/llrpdevice.h | 30 +- .../include/llrp}/llrppacket.h | 2 +- lib-rdm/include/rdm.h | 183 +- lib-rdm/include/rdm_manufacturer_pid.h | 29 +- lib-rdm/include/rdm_message_print.h | 36 + lib-rdm/include/rdm_selftest.h | 2 +- lib-rdm/include/rdmconst.h | 116 +- lib-rdm/include/rdmdevice.h | 58 +- lib-rdm/include/rdmdevicecontroller.h | 7 +- lib-rdm/include/rdmdeviceparams.h | 24 +- lib-rdm/include/rdmdeviceresponder.h | 89 +- lib-rdm/include/rdmdevicestore.h | 13 +- lib-rdm/include/rdmdiscovery.h | 220 + lib-rdm/include/rdmhandler.h | 31 +- lib-rdm/include/rdmidentify.h | 2 +- lib-rdm/include/rdmmessage.h | 13 +- .../include/rdmnet}/rdmnet.h | 0 {lib-rdmnet => lib-rdm}/include/rdmnetconst.h | 0 .../include/rdmnetdevice.h | 47 +- .../include/rdmnetllrponly.h | 0 lib-rdm/include/rdmpersonality.h | 2 +- lib-rdm/include/rdmqueuedmessage.h | 2 - lib-rdm/include/rdmresponder.h | 192 + lib-rdm/include/rdmsensor.h | 206 + lib-rdm/include/rdmsensors.h | 170 + lib-rdm/include/rdmslotinfo.h | 2 +- lib-rdm/include/rdmsubdevice.h | 200 + lib-rdm/include/rdmsubdevices.h | 248 + .../include/rdmtod.h | 12 +- .../include/sensor}/cputemperature.h | 5 +- .../include/subdevice}/rdmsubdevicedummy.h | 0 .../src/controller/rdm.cpp | 11 +- lib-rdm/src/controller/rdmdiscovery.cpp | 615 + .../src => lib-rdm/src/llrp}/llrpdevice.cpp | 31 +- .../src/llrp}/llrpdevicedump.cpp | 32 +- lib-rdm/src/llrp/rdmhandlere1372.cpp | 134 +- ...messageprint.cpp => rdm_message_print.cpp} | 52 +- lib-rdm/src/rdmdevice.cpp | 32 +- lib-rdm/src/rdmdeviceparams.cpp | 92 +- lib-rdm/src/rdmdeviceresponder.cpp | 88 +- lib-rdm/src/rdmhandler.cpp | 222 +- lib-rdm/src/rdmhandlere1371.cpp | 6 +- lib-rdm/src/rdmidentify.cpp | 4 +- .../src/rdmnet}/rdmnetconst.cpp | 0 lib-rdm/src/rdmqueuedmessage.cpp | 8 +- .../src/rdmsensors.cpp | 12 +- lib-rdm/src/rdmslotinfo.cpp | 2 +- .../spi => lib-rdm/src}/rdmsubdevicedummy.cpp | 12 +- lib-rdm/src/rdmsubdevices.cpp | 39 + lib-rdm/src/responder/rdmresponder.cpp | 38 + lib-rdmdiscovery/.cproject | 146 - lib-rdmdiscovery/.project | 27 - .../.settings/org.eclipse.cdt.core.prefs | 6 - .../org.eclipse.core.resources.prefs | 2 - lib-rdmdiscovery/Makefile | 4 - lib-rdmdiscovery/Makefile.GD32 | 6 - lib-rdmdiscovery/Rules.mk | 27 - .../include/artnetrdmcontroller.h | 112 - lib-rdmdiscovery/src/artnet/rdm_send.cpp | 72 - lib-rdmdiscovery/src/rdm/rdmdiscovery.cpp | 345 - lib-rdmnet/.cproject | 154 - lib-rdmnet/.project | 27 - lib-rdmnet/.settings/language.settings.xml | 12 - .../.settings/org.eclipse.cdt.core.prefs | 6 - .../org.eclipse.core.resources.prefs | 2 - lib-rdmnet/Makefile.GD32 | 7 - lib-rdmresponder/.cproject | 150 - lib-rdmresponder/.project | 27 - .../.settings/org.eclipse.cdt.core.prefs | 6 - .../org.eclipse.core.resources.prefs | 2 - lib-rdmresponder/Rules.mk | 14 - lib-rdmresponder/include/rdmresponder.h | 119 - .../src/artnet/artnetrdmresponder.cpp | 96 - lib-rdmresponder/src/rdm/rdmresponder.cpp | 128 - lib-rdmsensor/.cproject | 5 - lib-rdmsensor/Makefile.GD32 | 3 +- lib-rdmsensor/Rules.mk | 7 + .../include/rdm_sensors.h | 26 +- lib-rdmsensor/include/rdmsensor.h | 141 - lib-rdmsensor/include/rdmsensors.h | 91 - lib-rdmsensor/include/rdmsensorsconst.h | 11 - lib-rdmsensor/include/rdmsensorsparams.h | 26 +- .../include/rdmsensorsstore.h | 37 +- lib-rdmsensor/include/rdmsensorthermistor.h | 20 +- lib-rdmsensor/src/rdm_sensors.cpp | 58 + lib-rdmsensor/src/rdmsensor.cpp | 103 - lib-rdmsensor/src/rdmsensors.cpp | 149 - lib-rdmsensor/src/rdmsensorsconst.cpp | 3 - lib-rdmsensor/src/rdmsensorsparams.cpp | 131 +- lib-rdmsubdevice/.cproject | 5 - lib-rdmsubdevice/Makefile.GD32 | 3 +- lib-rdmsubdevice/Rules.mk | 18 + lib-rdmsubdevice/include/rdm _subdevices.h | 43 + lib-rdmsubdevice/include/rdmsubdevice.h | 108 - lib-rdmsubdevice/include/rdmsubdevices.h | 97 - lib-rdmsubdevice/include/rdmsubdevicesconst.h | 14 - .../include/rdmsubdevicesparams.h | 23 +- .../include/{ => spi}/rdmsubdevicebw7fets.h | 0 .../include/{ => spi}/rdmsubdevicebwdimmer.h | 0 .../include/{ => spi}/rdmsubdevicebwdio.h | 0 .../include/{ => spi}/rdmsubdevicebwlcd.h | 2 +- .../include/{ => spi}/rdmsubdevicebwrelay.h | 0 .../include/{ => spi}/rdmsubdevicemcp23s08.h | 0 .../include/{ => spi}/rdmsubdevicemcp23s17.h | 0 .../include/{ => spi}/rdmsubdevicemcp4822.h | 2 +- .../include/{ => spi}/rdmsubdevicemcp4902.h | 2 +- lib-rdmsubdevice/src/rdm_subdevices.cpp | 61 + lib-rdmsubdevice/src/rdmsubdevice.cpp | 148 - lib-rdmsubdevice/src/rdmsubdevices.cpp | 217 - lib-rdmsubdevice/src/rdmsubdevicesconst.cpp | 5 +- lib-rdmsubdevice/src/rdmsubdevicesparams.cpp | 111 +- .../src/spi/rdmsubdevicebw7fets.cpp | 4 +- .../src/spi/rdmsubdevicebwdimmer.cpp | 4 +- .../src/spi/rdmsubdevicebwdio.cpp | 6 +- .../src/spi/rdmsubdevicebwlcd.cpp | 6 +- .../src/spi/rdmsubdevicebwrelay.cpp | 6 +- .../src/spi/rdmsubdevicemcp23s08.cpp | 2 +- .../src/spi/rdmsubdevicemcp23s17.cpp | 2 +- .../src/spi/rdmsubdevicemcp4822.cpp | 4 +- .../src/spi/rdmsubdevicemcp4902.cpp | 4 +- lib-remoteconfig/.cproject | 8 - lib-remoteconfig/Makefile.GD32 | 1 + lib-remoteconfig/Rules.mk | 41 +- lib-remoteconfig/http/content/Makefile | 8 +- lib-remoteconfig/http/content/content.h | 70 +- lib-remoteconfig/http/content/date.js | 18 + lib-remoteconfig/http/content/date.js.h | 47 + lib-remoteconfig/http/content/dmx.html | 14 + lib-remoteconfig/http/content/dmx.html.h | 36 + lib-remoteconfig/http/content/dmx.js | 37 + lib-remoteconfig/http/content/dmx.js.h | 88 + .../http/content/generate_content.cpp | 114 +- .../http/content/generate_json_switch | Bin 16528 -> 16528 bytes .../http/content/generate_json_switch.cpp | 13 +- lib-remoteconfig/http/content/includes.h | 35 +- lib-remoteconfig/http/content/json_switch.h | 9 + lib-remoteconfig/http/content/rdm.html | 34 + lib-remoteconfig/http/content/rdm.html.h | 74 + lib-remoteconfig/http/content/rdm.js | 46 + lib-remoteconfig/http/content/rdm.js.h | 64 + lib-remoteconfig/http/content/rtc.html | 27 + lib-remoteconfig/http/content/rtc.html.h | 66 + lib-remoteconfig/http/content/rtc.js | 27 + lib-remoteconfig/http/content/rtc.js.h | 55 + lib-remoteconfig/http/content/showfile.html | 31 + lib-remoteconfig/http/content/showfile.html.h | 84 + lib-remoteconfig/http/content/showfile.js | 58 + lib-remoteconfig/http/content/showfile.js.h | 92 + lib-remoteconfig/http/content/static.js | 12 +- lib-remoteconfig/http/content/static.js.h | 74 +- lib-remoteconfig/http/content/styles.css | 2 +- lib-remoteconfig/http/content/time.html | 15 + lib-remoteconfig/http/content/time.html.h | 40 + lib-remoteconfig/http/content/time.js | 13 + lib-remoteconfig/http/content/time.js.h | 27 + .../include/httpd/http.h | 53 +- lib-remoteconfig/include/httpd/httpd.h | 73 +- .../include/httpd/httpdhandlerequest.h | 77 + lib-remoteconfig/include/remoteconfig.h | 56 +- lib-remoteconfig/include/remoteconfigconst.h | 2 +- lib-remoteconfig/include/remoteconfigjson.h | 53 +- lib-remoteconfig/include/remoteconfigparams.h | 47 +- lib-remoteconfig/include/shell/shell.h | 34 +- .../include/tftp/tftpfileserver.h | 11 +- lib-remoteconfig/src/gd32/remoteconfig.cpp | 4 +- lib-remoteconfig/src/gd32/shellcmd.cpp | 31 + lib-remoteconfig/src/gd32/tftpfileserver.cpp | 2 +- .../src/httpd/get_file_content.cpp | 45 +- lib-remoteconfig/src/httpd/httd.cpp | 471 - .../src/httpd/httpd.cpp | 52 +- .../src/httpd/httpdhandlerequest.cpp | 758 + lib-remoteconfig/src/linux/tftpfileserver.cpp | 8 +- lib-remoteconfig/src/remoteconfig.cpp | 510 +- lib-remoteconfig/src/remoteconfigfactory.cpp | 6 +- lib-remoteconfig/src/remoteconfigjson.cpp | 26 +- lib-remoteconfig/src/remoteconfigparams.cpp | 154 +- .../src/remoteconfigparamsdump.cpp | 66 - lib-remoteconfig/src/remoteconfigreboot.cpp | 4 +- lib-remoteconfig/src/remoteconfigstatic.cpp | 76 +- lib-remoteconfig/src/shell/shell.cpp | 186 +- lib-remoteconfig/src/shell/shellcmd.cpp | 259 +- lib-remoteconfig/src/tftp/remoteconfig.cpp | 6 +- lib-remoteconfig/src/tftp/tftpfileserver.cpp | 8 +- lib-remoteconfig/src/uart/shell.cpp | 2 +- lib-showfile/.cproject | 208 + {lib-debug => lib-showfile}/.project | 2 +- .../.settings/language.settings.xml | 22 +- .../org.eclipse.cdt.codan.core.prefs | 107 + .../.settings/org.eclipse.cdt.core.prefs | 0 .../org.eclipse.core.resources.prefs | 0 lib-showfile/Makefile.GD32 | 7 + lib-showfile/Rules.mk | 57 + .../include/formats/showfileformatola.h | 311 + .../protocols/showfileprotocolartnet.h | 110 + .../protocols/showfileprotocolartnettrigger.h | 50 + .../include/protocols/showfileprotocole131.h | 105 + .../protocols/showfileprotocolnodeartnet.h | 118 + .../protocols/showfileprotocolnodee131.h | 129 + lib-showfile/include/showfile.h | 312 + .../include/showfileconst.h | 39 +- lib-showfile/include/showfiledisplay.h | 36 + lib-showfile/include/showfileformat.h | 35 + lib-showfile/include/showfileosc.h | 108 + lib-showfile/include/showfileparams.h | 103 + .../include/showfileparamsconst.h | 28 +- lib-showfile/include/showfileprotocol.h | 51 + .../include/showfiletftp.h | 49 +- lib-showfile/src/display/showfiledisplay.cpp | 88 + .../src/formats/ola/showfile_record.cpp | 64 + .../src/formats/ola/showfileformatola.cpp | 143 + lib-showfile/src/json_delete.cpp | 65 + lib-showfile/src/json_get_directory.cpp | 72 + lib-showfile/src/json_status.cpp | 118 + lib-showfile/src/osc/showfileosc.cpp | 296 + .../artnet/showfileprotocolartnettrigger.cpp | 59 + lib-showfile/src/showfile.cpp | 338 + lib-showfile/src/showfile_filename.cpp | 91 + lib-showfile/src/showfileparams.cpp | 389 + .../src/showfileparamsconst.cpp | 24 +- lib-showfile/src/showfiletftp.cpp | 65 + lib-uuid/.cproject | 126 - lib-uuid/.settings/language.settings.xml | 12 - .../org.eclipse.core.resources.prefs | 2 - lib-uuid/Makefile.GD32 | 4 - lib-ws28xx/.cproject | 184 +- lib-ws28xx/Makefile.GD32 | 17 +- lib-ws28xx/Rules.mk | 2 +- .../{ => gd32}/gpio/board_gd32f207rg.h | 0 .../{ => gd32}/gpio/pixelmulti_config.h | 10 +- .../include/{ => gd32}/gpio/ws28xxmulti.h | 28 +- lib-ws28xx/include/pixelconfiguration.h | 197 +- lib-ws28xx/include/pixelpatterns.h | 94 +- lib-ws28xx/include/pixelreboot.h | 2 +- lib-ws28xx/include/pixeltestpattern.h | 21 +- lib-ws28xx/include/pixeltype.h | 106 +- lib-ws28xx/include/spi/ws28xxmulti.h | 100 - lib-ws28xx/include/ws28xx.h | 31 +- lib-ws28xx/include/ws28xxmulti.h | 8 +- .../src/{ => gd32}/gpio/ws28xxmulti.cpp | 147 +- lib-ws28xx/src/{ => gd32}/i2s/ws28xx.cpp | 68 +- lib-ws28xx/src/json_get_satus.cpp | 36 + lib-ws28xx/src/patterns/pixelpatterns.cpp | 194 +- lib-ws28xx/src/patterns/pixeltestpattern.cpp | 5 +- lib-ws28xx/src/pixel/ws28xx.cpp | 32 +- lib-ws28xx/src/pixelconfiguration.cpp | 145 - lib-ws28xx/src/pixeltype.cpp | 136 +- lib-ws28xxdmx/.cproject | 5 - lib-ws28xxdmx/Makefile.GD32 | 3 +- lib-ws28xxdmx/Rules.mk | 13 +- lib-ws28xxdmx/include/pixeldmxconfiguration.h | 116 +- lib-ws28xxdmx/include/pixeldmxparams.h | 34 +- lib-ws28xxdmx/include/pixeldmxparamsrdm.h | 50 +- lib-ws28xxdmx/include/pixeldmxstore.h | 34 +- lib-ws28xxdmx/include/ws28xxdmx.h | 70 +- lib-ws28xxdmx/include/ws28xxdmxmulti.h | 114 +- lib-ws28xxdmx/src/dmx/ws28xxdmx.cpp | 99 +- lib-ws28xxdmx/src/dmx/ws28xxdmxmulti.cpp | 218 - lib-ws28xxdmx/src/dmxmulti/ws28xxdmxmulti.cpp | 232 + lib-ws28xxdmx/src/params/pixeldmxparams.cpp | 301 +- .../src/params/pixeldmxparamsdump.cpp | 105 - .../src/params/pixeldmxparamsrdm.cpp | 78 +- lib-ws28xxdmx/src/pixeldmxconfiguration.cpp | 102 - .../src/rdm/rdm_manufacturer_pid.cpp | 125 +- scripts/build_all.sh | 14 +- 1004 files changed, 101344 insertions(+), 32563 deletions(-) create mode 100644 CMSIS/.cproject rename {lib-uuid => CMSIS}/.project (93%) rename {lib-c => CMSIS}/.settings/language.settings.xml (88%) rename {gd32_rdm_responder => CMSIS}/.settings/org.eclipse.core.resources.prefs (100%) create mode 100644 CMSIS/Core/Include/cachel1_armv7.h rename {lib-gd32/gd32f20x/CMSIS => CMSIS/Core/Include}/cmsis_armcc.h (71%) create mode 100644 CMSIS/Core/Include/cmsis_armclang.h create mode 100644 CMSIS/Core/Include/cmsis_armclang_ltm.h create mode 100644 CMSIS/Core/Include/cmsis_compiler.h create mode 100644 CMSIS/Core/Include/cmsis_gcc.h create mode 100644 CMSIS/Core/Include/cmsis_iccarm.h create mode 100644 CMSIS/Core/Include/cmsis_version.h create mode 100644 CMSIS/Core/Include/core_cm3.h create mode 100644 CMSIS/Core/Include/core_cm4.h create mode 100644 CMSIS/Core/Include/core_cm7.h create mode 100644 CMSIS/Core/Include/mpu_armv7.h create mode 100644 CMSIS/Core/Include/tz_context.h create mode 100644 CMSIS/LICENSE.txt create mode 100644 firmware-template-gd32/Artnet.mk create mode 100644 firmware-template-gd32/Board.mk create mode 100644 firmware-template-gd32/FreeRTOS.mk create mode 100644 firmware-template-gd32/Validate.mk delete mode 100755 firmware-template-gd32/calculate_unused_ram.sh create mode 100644 gd32_emac_artnet_dmx_multi/Common.mk delete mode 100644 gd32_emac_artnet_dmx_multi/include/display_timeout.h rename lib-configstore/src/pixel/storepixeldmx.cpp => gd32_emac_artnet_dmx_multi/lib/showfileusb.cpp (68%) create mode 100644 gd32_emac_artnet_pixel_multi/Makefile-softuart0.GD32 delete mode 100755 gd32_emac_artnet_pixel_multi/generate_sofware_version_id.sh delete mode 100644 gd32_emac_artnet_pixel_multi/include/display_timeout.h delete mode 100644 gd32_emac_artnet_pixel_multi/include/pixeldmxstartstop.h delete mode 100644 gd32_emac_artnet_pixel_multi/include/sofware_version_id.h create mode 100644 gd32_emac_artnet_pixel_multi/lib/showfileusb.cpp delete mode 100755 gd32_emac_ddp_pixel_multi/generate_sofware_version_id.sh delete mode 100644 gd32_emac_ddp_pixel_multi/include/sofware_version_id.h create mode 100644 gd32_emac_e131_dmx_multi/Common.mk delete mode 100755 gd32_emac_e131_dmx_multi/generate_sofware_version_id.sh delete mode 100644 gd32_emac_e131_dmx_multi/include/sofware_version_id.h create mode 100644 gd32_emac_e131_dmx_multi/lib/showfileusb.cpp delete mode 100755 gd32_emac_e131_pixel_multi/generate_sofware_version_id.sh delete mode 100644 gd32_emac_e131_pixel_multi/include/display_timeout.h delete mode 100644 gd32_emac_e131_pixel_multi/include/sofware_version_id.h create mode 100644 gd32_emac_e131_pixel_multi/lib/showfileusb.cpp create mode 100644 gd32_emac_llrp/.cproject rename {gd32_rdm_responder => gd32_emac_llrp}/.project (84%) create mode 100644 gd32_emac_llrp/.pydevproject rename {gd32_rdm_responder => gd32_emac_llrp}/.settings/language.settings.xml (89%) rename {lib-c++ => gd32_emac_llrp}/.settings/org.eclipse.core.resources.prefs (100%) create mode 100644 gd32_emac_llrp/Makefile.GD32 create mode 100644 gd32_emac_llrp/firmware/main.cpp rename gd32_rdm_responder/lib/factorydefaults.cpp => gd32_emac_llrp/include/factorydefaults.h (86%) rename {gd32_rdm_responder => gd32_emac_llrp}/lib/rdmsoftwareversion.cpp (96%) delete mode 100755 gd32_emac_pp_pixel_multi/generate_sofware_version_id.sh delete mode 100644 gd32_emac_pp_pixel_multi/include/display_timeout.h delete mode 100644 gd32_emac_pp_pixel_multi/include/sofware_version_id.h delete mode 100644 gd32_rdm_responder/.cproject delete mode 100644 gd32_rdm_responder/Makefile.GD32 delete mode 100755 gd32_rdm_responder/do-tftp.sh delete mode 100644 gd32_rdm_responder/firmware/main.cpp delete mode 100755 gd32_rdm_responder/generate_sofware_version_id.sh delete mode 100644 gd32_rdm_responder/include/display_timeout.h delete mode 100644 gd32_rdm_responder/include/is_config_mode.h delete mode 100644 gd32_rdm_responder/include/pixeldmxstartstop.h delete mode 100644 gd32_rdm_responder/include/sofware_version_id.h delete mode 100644 gd32_rdm_responder/lib/display.cpp delete mode 100644 gd32_rdm_responder/lib/personalityupdate.cpp delete mode 100644 gd32_rdm_responder/lib/rdm_selftest.cpp delete mode 100644 gd32_rdm_responder/lib/rdmslotinfo.cpp mode change 100644 => 100755 lib-artnet/Rules.mk mode change 100644 => 100755 lib-artnet/include/artnetnode.h rename lib-rdmsensor/include/rdmsensorstore.h => lib-artnet/include/artnetnode_ports.h (74%) create mode 100755 lib-artnet/include/artnetrdmcontroller.h rename {lib-rdmresponder => lib-artnet}/include/artnetrdmresponder.h (55%) mode change 100644 => 100755 lib-artnet/include/artnettimecode.h create mode 100755 lib-artnet/src/controller/json_get_polltable.cpp mode change 100644 => 100755 lib-artnet/src/node/artnetnode.cpp delete mode 100644 lib-artnet/src/node/artnetparamsdump.cpp rename {lib-rdmdiscovery/src/artnet => lib-artnet/src/node/rdm/controller}/artnetrdmcontroller.cpp (56%) create mode 100755 lib-artnet/src/node/rdm/controller/handlerdm.cpp create mode 100644 lib-artnet/src/node/rdm/controller/handlerdmin.cpp rename lib-rdmsubdevice/src/rdmsubdevicesadd.cpp => lib-artnet/src/node/rdm/controller/handlerdmsub.cpp (73%) mode change 100644 => 100755 create mode 100755 lib-artnet/src/node/rdm/controller/json_get_portstatus.cpp rename lib-rdmnet/src/rdmnetdevice.cpp => lib-artnet/src/node/rdm/controller/json_get_queue.cpp (63%) mode change 100644 => 100755 create mode 100755 lib-artnet/src/node/rdm/controller/json_get_rdm.cpp rename lib-dmx/src/rdm.cpp => lib-artnet/src/node/rdm/controller/json_get_tod.cpp (57%) mode change 100644 => 100755 create mode 100755 lib-artnet/src/node/rdm/controller/setrdm.cpp delete mode 100644 lib-artnet/src/node/rdm/handlerdmin.cpp rename lib-network/src/net/ntp_internal.h => lib-artnet/src/node/rdm/responder/artnetrdmresponder.cpp (84%) create mode 100755 lib-artnet/src/node/rdm/responder/handlerdm.cpp rename lib-hal/console/null/console.c => lib-artnet/src/node/rdm/responder/handlerdmsub.cpp (72%) create mode 100755 lib-artnet/src/node/rdm/responder/setrdm.cpp create mode 100755 lib-artnet/src/node/rdm/setrdm.cpp delete mode 100644 lib-artnet/src/node/timecode/handletimecode.cpp delete mode 100644 lib-c++/.cproject delete mode 100644 lib-c++/.settings/language.settings.xml delete mode 100644 lib-c++/Makefile.GD32 delete mode 100644 lib-c/.cproject delete mode 100644 lib-c/.settings/org.eclipse.cdt.core.prefs delete mode 100644 lib-c/Makefile.GD32 create mode 100755 lib-clib/.cproject rename {lib-c => lib-clib}/.project (97%) mode change 100644 => 100755 create mode 100755 lib-clib/.settings/language.settings.xml rename {lib-c => lib-clib}/.settings/org.eclipse.core.resources.prefs (100%) mode change 100644 => 100755 create mode 100755 lib-clib/Makefile.GD32 create mode 100755 lib-clib/Rules.mk create mode 100755 lib-clib/src/abort.c rename {lib-c => lib-clib}/src/asctime.c (100%) mode change 100644 => 100755 create mode 100755 lib-clib/src/c++/cxa_atexit.cpp rename {lib-c++/src => lib-clib/src/c++}/delete.cpp (78%) mode change 100644 => 100755 rename {lib-c++/src => lib-clib/src/c++}/dso_handle.cpp (80%) mode change 100644 => 100755 create mode 100755 lib-clib/src/c++/impure_prt.cpp rename {lib-c++/src => lib-clib/src/c++}/new.cpp (92%) mode change 100644 => 100755 rename {lib-c++/src => lib-clib/src/c++}/purecall.cpp (94%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/errno.c (100%) mode change 100644 => 100755 rename {lib-c/src => lib-clib/src/gd32}/assert.c (100%) rename lib-configstore/src/rdm/storerdmsubdevices.cpp => lib-clib/src/gd32/malloc.h (74%) mode change 100644 => 100755 create mode 100644 lib-clib/src/gd32/time_ptp/time.cpp rename lib-c/src/gd32/time.c => lib-clib/src/gd32/time_systick/time.cpp (54%) create mode 100644 lib-clib/src/gd32/time_timer/time.cpp create mode 100644 lib-clib/src/gd32/uuid.cpp rename {lib-c => lib-clib}/src/inet_aton.c (94%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/init.c (100%) rename {lib-c => lib-clib}/src/log.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/malloc.c (90%) mode change 100644 => 100755 create mode 100755 lib-clib/src/memchr.c create mode 100755 lib-clib/src/memcmp.c rename {lib-c => lib-clib}/src/memcpy.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/memmove.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/memset.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/perror.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/printf.c (92%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/putchar.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/puts.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/random.c (100%) mode change 100644 => 100755 create mode 100755 lib-clib/src/strchr.c rename {lib-c => lib-clib}/src/strlen.c (100%) create mode 100755 lib-clib/src/strncmp.c create mode 100755 lib-clib/src/strstr.c rename {lib-c => lib-clib}/src/strtok.c (100%) mode change 100644 => 100755 create mode 100755 lib-clib/src/strtoul.c rename lib-c/src/time.c => lib-clib/src/time.cpp (54%) mode change 100644 => 100755 rename {lib-uuid => lib-clib}/src/uuid_internal.h (100%) mode change 100644 => 100755 rename {lib-uuid => lib-clib}/src/uuid_parse.c (100%) mode change 100644 => 100755 rename {lib-uuid => lib-clib}/src/uuid_unparse.c (100%) mode change 100644 => 100755 mode change 100644 => 100755 lib-configstore/Rules.mk mode change 100644 => 100755 lib-configstore/device/rom/storedevice.cpp mode change 100644 => 100755 lib-configstore/device/spi/storedevice.cpp rename lib-configstore/include/{storedevice.h => configstoredevice.h} (100%) mode change 100644 => 100755 create mode 100755 lib-configstore/include/envparams.h create mode 100755 lib-configstore/include/envparamsconst.h delete mode 100644 lib-configstore/include/storeartnet.h delete mode 100644 lib-configstore/include/storedisplayudf.h delete mode 100644 lib-configstore/include/storedmxsend.h delete mode 100644 lib-configstore/include/storee131.h delete mode 100644 lib-configstore/include/storenetwork.h delete mode 100644 lib-configstore/include/storepixeldmx.h delete mode 100644 lib-configstore/include/storerdmdevice.h delete mode 100644 lib-configstore/include/storerdmsensors.h delete mode 100644 lib-configstore/include/storeremoteconfig.h delete mode 100644 lib-configstore/include/storetlc59711.h delete mode 100644 lib-configstore/src/artnet/storeartnet.cpp mode change 100644 => 100755 lib-configstore/src/configstore.cpp create mode 100755 lib-configstore/src/envparams.cpp create mode 100755 lib-configstore/src/envparamsconst.cpp mode change 100644 => 100755 lib-configstore/src/platform_configstore.h delete mode 100644 lib-configstore/src/storenetwork.cpp delete mode 100644 lib-debug/.cproject delete mode 100644 lib-debug/.settings/language.settings.xml delete mode 100644 lib-debug/Makefile.GD32 create mode 100755 lib-device/include/ema.h rename lib-hal/src/utc.cpp => lib-device/include/mcp23x08.h (61%) mode change 100644 => 100755 delete mode 100644 lib-display/include/display7segment.h mode change 100755 => 100644 lib-dmx/Rules.mk rename {lib-dmxreceiver => lib-dmx}/include/dmxreceiver.h (72%) mode change 100644 => 100755 create mode 100755 lib-dmx/include/dmxsend.h create mode 100755 lib-dmx/include/dmxstatistics.h delete mode 100644 lib-dmx/src/artnet/dmxinput.cpp delete mode 100644 lib-dmx/src/e131/dmxinput.cpp delete mode 100644 lib-dmx/src/gd32/rdm.cpp create mode 100755 lib-dmx/src/json_get_ports.cpp create mode 100755 lib-dmx/src/json_get_portstatus.cpp delete mode 100644 lib-dmxreceiver/.cproject delete mode 100644 lib-dmxreceiver/.project delete mode 100644 lib-dmxreceiver/.settings/language.settings.xml delete mode 100644 lib-dmxreceiver/Makefile.GD32 delete mode 100644 lib-dmxreceiver/src/dmxreceiver.cpp delete mode 100644 lib-dmxsend/.cproject delete mode 100644 lib-dmxsend/.project delete mode 100644 lib-dmxsend/.settings/language.settings.xml delete mode 100644 lib-dmxsend/.settings/org.eclipse.cdt.core.prefs delete mode 100644 lib-dmxsend/.settings/org.eclipse.core.resources.prefs delete mode 100644 lib-dmxsend/Makefile.GD32 delete mode 100755 lib-dmxsend/include/dmxsend.h delete mode 100755 lib-dmxsend/src/dmxsend.cpp mode change 100644 => 100755 lib-e131/include/e131bridge.h rename lib-e131/include/{e131bridgeconst.h => e131const.h} (84%) rename lib-e131/src/{node/e131bridgeconst.cpp => e131const.cpp} (86%) mode change 100644 => 100755 delete mode 100644 lib-e131/src/node/e131paramsdump.cpp mode change 100644 => 100755 lib-flash/src/spi/gigadevice.cpp delete mode 100644 lib-flashcode/src/gd32/f4xx/flashcode.cpp delete mode 100644 lib-flashcode/src/gd32/f4xx/fmc_operation.cpp delete mode 100644 lib-flashcode/src/gd32/f4xx/fmc_operation.h create mode 100644 lib-flashcode/src/gd32/h7xx/flashcode.cpp create mode 100644 lib-gd32/device/usb/f/usb_conf.h create mode 100644 lib-gd32/device/usb/usb.cpp create mode 100644 lib-gd32/device/usb/usb_conf.h rename gd32_emac_e131_dmx_multi/include/display_timeout.h => lib-gd32/device/usb/usb_vbus.cpp (72%) rename lib-network/src/emac/gd32/net.c => lib-gd32/device/usb/usbh_conf.h (67%) delete mode 100644 lib-gd32/gd32f20x/CMSIS/core_cm3.h delete mode 100644 lib-gd32/gd32f20x/CMSIS/core_cmFunc.h delete mode 100644 lib-gd32/gd32f20x/CMSIS/core_cmInstr.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Include/audio_core.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Include/audio_out_itf.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Source/audio_core.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Source/audio_out_itf.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_core.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_mem.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_core.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_mem.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Include/custom_hid_core.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Include/standard_hid_core.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Source/custom_hid_core.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Source/standard_hid_core.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/iap/Include/usb_iap_core.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/iap/Source/usb_iap_core.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_core.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_core.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/printer/Include/printer_core.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/printer/Source/printer_core.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Include/usbd_core.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Include/usbd_enum.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Include/usbd_transc.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Source/usbd_core.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Source/usbd_enum.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Source/usbd_transc.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_core.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_dev.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_host.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_hw.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_regs.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usbd_int.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usbh_int.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_core.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_dev.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_host.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usbd_int.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usbh_int.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_core.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Include/usbh_standard_hid.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_core.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Source/usbh_standard_hid.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_core.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_core.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_core.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_enum.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_pipe.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_transc.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_core.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_enum.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_pipe.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_transc.c create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/cdc/usb_cdc.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/hid/usb_hid.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/msc/msc_bbb.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/msc/msc_scsi.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/msc/usb_msc.h create mode 100644 lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/common/usb_ch9_std.h create mode 100644 lib-gd32/include/FreeRTOSConfig.h create mode 100644 lib-gd32/include/gd32_dma.h create mode 100644 lib-gd32/include/gd32_dma_memcpy32.h create mode 100644 lib-gd32/include/gd32_ptp.h create mode 100644 lib-gd32/include/gd32_pwm.h create mode 100644 lib-gd32/include/mcu/gd32f207_mcu.h rename lib-gd32/src/{ => f}/gd32_adc.cpp (96%) create mode 100644 lib-gd32/src/f/gd32_dma_memcpy32.cpp rename lib-gd32/src/{ => f}/gd32_i2c.cpp (67%) rename lib-gd32/src/{ => f}/gd32_spi.cpp (70%) rename lib-gd32/src/{ => f}/i2s_psc_config_dump.cpp (96%) create mode 100644 lib-gd32/src/gd32_gpio_mode_set.cpp create mode 100644 lib-gd32/src/gd32_pwm.cpp create mode 100644 lib-gd32/src/ptp/gd32_ptp.cpp delete mode 100644 lib-gd32/src/softuart0/gd32_uart0.c create mode 100644 lib-gd32/src/softuart0/uart0.cpp rename lib-gd32/src/{systick.c => systick/systick.cpp} (77%) create mode 100644 lib-gd32/src/timer6.cpp rename lib-gd32/src/{gd32_uart0.c => uart0.cpp} (81%) rename lib-gd32/src/uart0/{gd32_uart0.c => uart0.cpp} (66%) create mode 100644 lib-hal/.settings/org.eclipse.ltk.core.refactoring.prefs mode change 100644 => 100755 lib-hal/Rules.mk delete mode 100644 lib-hal/console/h3/console.c rename lib-hal/console/i2c/{console.c => console.cpp} (77%) create mode 100755 lib-hal/console/null/console.cpp rename lib-hal/console/uart0/{console.c => console.cpp} (83%) rename lib-debug/src/debug_dump.c => lib-hal/debug/debug_dump.cpp (74%) mode change 100644 => 100755 rename lib-debug/src/debug_print_bits.c => lib-hal/debug/debug_print_bits.cpp (89%) mode change 100644 => 100755 mode change 100644 => 100755 lib-hal/debug/emac/gd32/emac_debug.cpp mode change 100644 => 100755 lib-hal/debug/i2c/i2cdetect.cpp mode change 100644 => 100755 lib-hal/debug/i2c/i2cdetect.h mode change 100644 => 100755 lib-hal/debug/stack/stack_debug.cpp rename lib-hal/device/usb/host/gd32/{ => f}/usb_host.cpp (76%) create mode 100755 lib-hal/ff14b/LICENSE.txt create mode 100755 lib-hal/ff14b/source/00history.txt create mode 100755 lib-hal/ff14b/source/00readme.txt create mode 100755 lib-hal/ff14b/source/diskio.h create mode 100755 lib-hal/ff14b/source/ff.c create mode 100755 lib-hal/ff14b/source/ff.h create mode 100755 lib-hal/ff14b/source/ffconf.h create mode 100755 lib-hal/ff14b/source/ffsystem.c create mode 100755 lib-hal/ff14b/source/ffunicode.c rename {lib-debug => lib-hal}/include/debug.h (74%) mode change 100644 => 100755 create mode 100644 lib-hal/include/device/usb/host.h rename gd32_emac_ddp_pixel_multi/include/display_timeout.h => lib-hal/include/hal_api.h (69%) mode change 100644 => 100755 create mode 100644 lib-hal/posix/file.cpp mode change 100644 => 100755 lib-hal/rtc/hwclock.cpp create mode 100755 lib-hal/rtc/json_rtc.cpp create mode 100755 lib-hal/src/json_datetime.cpp create mode 100755 lib-hal/src/json_get_directory.cpp mode change 100644 => 100755 lib-lightset/include/lightsetdata.h rename lib-lightset/src/lightsetdmx.cpp => lib-network/include/emac/phy/rtl8201f.h (73%) mode change 100644 => 100755 create mode 100755 lib-network/include/ip4_address.h rename lib-network/{src/net => include}/net.h (51%) mode change 100644 => 100755 create mode 100755 lib-network/include/net/acd.h rename lib-network/include/{ => net/apps}/mdns.h (77%) create mode 100755 lib-network/include/net/apps/ntpclient.h rename lib-network/include/{ => net/apps}/tftpdaemon.h (89%) mode change 100644 => 100755 rename lib-network/{src/net/net_debug.h => include/net/arp.h} (60%) mode change 100644 => 100755 create mode 100755 lib-network/include/net/autoip.h create mode 100755 lib-network/include/net/dhcp.h create mode 100755 lib-network/include/net/igmp.h create mode 100644 lib-network/include/net/protocol/acd.h rename lib-network/{src/net/dhcp_internal.h => include/net/protocol/arp.h} (50%) mode change 100644 => 100755 create mode 100644 lib-network/include/net/protocol/autoip.h create mode 100644 lib-network/include/net/protocol/dhcp.h create mode 100644 lib-network/include/net/protocol/dns.h rename lib-network/{src/emac/gd32/debug_print_bits.c => include/net/protocol/ethernet.h} (67%) mode change 100644 => 100755 create mode 100644 lib-network/include/net/protocol/iana.h create mode 100755 lib-network/include/net/protocol/icmp.h rename gd32_rdm_responder/lib/dmxstartaddressupdate.cpp => lib-network/include/net/protocol/ieee.h (78%) mode change 100644 => 100755 rename lib-artnet/include/artnetrdm.h => lib-network/include/net/protocol/igmp.h (55%) mode change 100644 => 100755 create mode 100755 lib-network/include/net/protocol/ip4.h rename lib-network/include/{ => net/protocol}/ntp.h (50%) mode change 100644 => 100755 create mode 100755 lib-network/include/net/protocol/tcp.h rename lib-gd32/include/gd32_micros.h => lib-network/include/net/protocol/udp.h (58%) mode change 100644 => 100755 create mode 100755 lib-network/include/netif.h create mode 100755 lib-network/include/networkstore.h delete mode 100644 lib-network/include/ntpclient.h delete mode 100644 lib-network/src/apps/ntp/ntpclient.cpp create mode 100644 lib-network/src/emac/gd32/f/emac.cpp create mode 100644 lib-network/src/emac/gd32/f/net.cpp mode change 100644 => 100755 lib-network/src/emac/phy/link_handle_change.cpp mode change 100644 => 100755 lib-network/src/emac/phy/net_link_check.cpp create mode 100755 lib-network/src/net/acd.cpp rename lib-network/src/{ => net}/apps/mdns/mdns.cpp (88%) create mode 100644 lib-network/src/net/apps/ntp/gd32/ptp/net_ptp.cpp create mode 100755 lib-network/src/net/apps/ntp/ntpclient.cpp rename lib-network/src/{ => net}/apps/tftp/tftpdaemon.cpp (96%) mode change 100644 => 100755 lib-network/src/net/arp.cpp delete mode 100644 lib-network/src/net/arp_cache.cpp create mode 100755 lib-network/src/net/autoip.cpp mode change 100644 => 100755 lib-network/src/net/dhcp.cpp mode change 100644 => 100755 lib-network/src/net/icmp.cpp mode change 100644 => 100755 lib-network/src/net/net.cpp delete mode 100644 lib-network/src/net/net_packets.h mode change 100755 => 100644 lib-network/src/net/net_private.h create mode 100755 lib-network/src/net/net_ptp.cpp create mode 100755 lib-network/src/net/netif.cpp delete mode 100644 lib-network/src/net/rfc3927.cpp rename lib-network/src/{ => params}/networkparamsconst.cpp (93%) mode change 100644 => 100755 delete mode 100644 lib-network/src/params/networkparamsdump.cpp create mode 100755 lib-osc/.cproject rename {lib-c++ => lib-osc}/.project (94%) mode change 100644 => 100755 rename {lib-rdmdiscovery => lib-osc}/.settings/language.settings.xml (93%) mode change 100644 => 100755 create mode 100755 lib-osc/.settings/org.eclipse.cdt.codan.core.prefs rename {gd32_rdm_responder => lib-osc}/.settings/org.eclipse.cdt.core.prefs (100%) mode change 100644 => 100755 rename {lib-debug => lib-osc}/.settings/org.eclipse.core.resources.prefs (100%) rename {lib-rdmresponder => lib-osc}/Makefile.GD32 (86%) mode change 100644 => 100755 create mode 100755 lib-osc/Rules.mk create mode 100644 lib-osc/include/osc.h rename lib-rdmdiscovery/include/rdmdiscovery.h => lib-osc/include/oscblob.h (57%) create mode 100755 lib-osc/include/oscclient.h create mode 100755 lib-osc/include/oscclientled.h rename lib-configstore/src/rdm/storerdmdevice.cpp => lib-osc/include/oscclientmsgconst.h (78%) mode change 100644 => 100755 create mode 100755 lib-osc/include/oscclientparams.h create mode 100755 lib-osc/include/oscclientparamsconst.h create mode 100644 lib-osc/include/oscparamsconst.h create mode 100755 lib-osc/include/oscserver.h create mode 100755 lib-osc/include/oscserverconst.h rename lib-configstore/src/rdm/storerdmsensors.cpp => lib-osc/include/oscservermsgconst.h (78%) mode change 100644 => 100755 create mode 100755 lib-osc/include/oscserverparams.h rename lib-display/src/display_timeout.cpp => lib-osc/include/oscserverparamsconst.h (77%) mode change 100644 => 100755 create mode 100644 lib-osc/include/oscsimplemessage.h create mode 100644 lib-osc/include/oscsimplesend.h rename lib-ws28xxdmx/include/ws28xxdmxstartstop.h => lib-osc/include/oscstring.h (52%) create mode 100755 lib-osc/src/client/oscclient.cpp rename lib-configstore/src/storedisplayudf.cpp => lib-osc/src/client/oscclientmsgconst.cpp (78%) mode change 100644 => 100755 create mode 100755 lib-osc/src/client/oscclientparams.cpp rename lib-configstore/src/storeremoteconfig.cpp => lib-osc/src/client/oscclientparamsconst.cpp (73%) mode change 100644 => 100755 rename lib-configstore/src/storedmxsend.cpp => lib-osc/src/client/oscclientsend.cpp (67%) mode change 100644 => 100755 create mode 100644 lib-osc/src/oscparamsconst.cpp create mode 100644 lib-osc/src/oscsimplemessage.cpp create mode 100644 lib-osc/src/oscsimplesend.cpp create mode 100644 lib-osc/src/pattern_match.c create mode 100755 lib-osc/src/server/oscserver.cpp rename lib-lightset/src/lightsetgetslotinfo.cpp => lib-osc/src/server/oscserverconst.cpp (76%) mode change 100644 => 100755 create mode 100755 lib-osc/src/server/oscservermsgconst.cpp create mode 100755 lib-osc/src/server/oscserverparams.cpp create mode 100755 lib-osc/src/server/oscserverparamsconst.cpp create mode 100755 lib-properties/src/sscanutcoffset.cpp rename {lib-rdmnet => lib-rdm}/include/e133.h (89%) mode change 100644 => 100755 rename {lib-rdmnet/include => lib-rdm/include/llrp}/llrp.h (100%) mode change 100644 => 100755 rename {lib-rdmnet/include => lib-rdm/include/llrp}/llrpdevice.h (90%) mode change 100644 => 100755 rename {lib-rdmnet/include => lib-rdm/include/llrp}/llrppacket.h (98%) mode change 100644 => 100755 create mode 100755 lib-rdm/include/rdm_message_print.h create mode 100755 lib-rdm/include/rdmdiscovery.h rename {lib-rdmnet/include => lib-rdm/include/rdmnet}/rdmnet.h (100%) mode change 100644 => 100755 rename {lib-rdmnet => lib-rdm}/include/rdmnetconst.h (100%) mode change 100644 => 100755 rename {lib-rdmnet => lib-rdm}/include/rdmnetdevice.h (70%) mode change 100644 => 100755 rename {lib-rdmnet => lib-rdm}/include/rdmnetllrponly.h (100%) mode change 100644 => 100755 create mode 100644 lib-rdm/include/rdmresponder.h create mode 100644 lib-rdm/include/rdmsensor.h create mode 100644 lib-rdm/include/rdmsensors.h create mode 100644 lib-rdm/include/rdmsubdevice.h create mode 100644 lib-rdm/include/rdmsubdevices.h rename {lib-rdmdiscovery => lib-rdm}/include/rdmtod.h (94%) rename {lib-rdmsensor/include => lib-rdm/include/sensor}/cputemperature.h (94%) mode change 100644 => 100755 rename {lib-rdmsubdevice/include => lib-rdm/include/subdevice}/rdmsubdevicedummy.h (100%) mode change 100644 => 100755 rename lib-dmx/src/emac/dmxconfigudp.cpp => lib-rdm/src/controller/rdm.cpp (84%) mode change 100644 => 100755 create mode 100755 lib-rdm/src/controller/rdmdiscovery.cpp rename {lib-rdmnet/src => lib-rdm/src/llrp}/llrpdevice.cpp (85%) mode change 100644 => 100755 rename {lib-rdmnet/src => lib-rdm/src/llrp}/llrpdevicedump.cpp (86%) mode change 100644 => 100755 mode change 100644 => 100755 lib-rdm/src/llrp/rdmhandlere1372.cpp rename lib-rdm/src/{rdmmessageprint.cpp => rdm_message_print.cpp} (81%) rename {lib-rdmnet/src => lib-rdm/src/rdmnet}/rdmnetconst.cpp (100%) mode change 100644 => 100755 rename lib-network/src/net/tftp_internal.h => lib-rdm/src/rdmsensors.cpp (83%) rename {lib-rdmsubdevice/src/spi => lib-rdm/src}/rdmsubdevicedummy.cpp (81%) create mode 100644 lib-rdm/src/rdmsubdevices.cpp create mode 100644 lib-rdm/src/responder/rdmresponder.cpp delete mode 100644 lib-rdmdiscovery/.cproject delete mode 100644 lib-rdmdiscovery/.project delete mode 100644 lib-rdmdiscovery/.settings/org.eclipse.cdt.core.prefs delete mode 100644 lib-rdmdiscovery/.settings/org.eclipse.core.resources.prefs delete mode 100644 lib-rdmdiscovery/Makefile delete mode 100644 lib-rdmdiscovery/Makefile.GD32 delete mode 100644 lib-rdmdiscovery/Rules.mk delete mode 100755 lib-rdmdiscovery/include/artnetrdmcontroller.h delete mode 100644 lib-rdmdiscovery/src/artnet/rdm_send.cpp delete mode 100755 lib-rdmdiscovery/src/rdm/rdmdiscovery.cpp delete mode 100644 lib-rdmnet/.cproject delete mode 100644 lib-rdmnet/.project delete mode 100644 lib-rdmnet/.settings/language.settings.xml delete mode 100644 lib-rdmnet/.settings/org.eclipse.cdt.core.prefs delete mode 100644 lib-rdmnet/.settings/org.eclipse.core.resources.prefs delete mode 100644 lib-rdmnet/Makefile.GD32 delete mode 100644 lib-rdmresponder/.cproject delete mode 100644 lib-rdmresponder/.project delete mode 100644 lib-rdmresponder/.settings/org.eclipse.cdt.core.prefs delete mode 100644 lib-rdmresponder/.settings/org.eclipse.core.resources.prefs delete mode 100644 lib-rdmresponder/Rules.mk delete mode 100644 lib-rdmresponder/include/rdmresponder.h delete mode 100644 lib-rdmresponder/src/artnet/artnetrdmresponder.cpp delete mode 100644 lib-rdmresponder/src/rdm/rdmresponder.cpp create mode 100755 lib-rdmsensor/Rules.mk rename lib-ws28xxdmx/include/pixeldmxhandler.h => lib-rdmsensor/include/rdm_sensors.h (71%) mode change 100644 => 100755 delete mode 100644 lib-rdmsensor/include/rdmsensor.h delete mode 100644 lib-rdmsensor/include/rdmsensors.h mode change 100644 => 100755 lib-rdmsensor/include/rdmsensorsconst.h rename lib-configstore/include/storemidi.h => lib-rdmsensor/include/rdmsensorsstore.h (63%) mode change 100644 => 100755 create mode 100755 lib-rdmsensor/src/rdm_sensors.cpp delete mode 100644 lib-rdmsensor/src/rdmsensor.cpp delete mode 100644 lib-rdmsensor/src/rdmsensors.cpp create mode 100755 lib-rdmsubdevice/Rules.mk create mode 100755 lib-rdmsubdevice/include/rdm _subdevices.h delete mode 100644 lib-rdmsubdevice/include/rdmsubdevice.h delete mode 100644 lib-rdmsubdevice/include/rdmsubdevices.h mode change 100644 => 100755 lib-rdmsubdevice/include/rdmsubdevicesconst.h rename lib-rdmsubdevice/include/{ => spi}/rdmsubdevicebw7fets.h (100%) rename lib-rdmsubdevice/include/{ => spi}/rdmsubdevicebwdimmer.h (100%) rename lib-rdmsubdevice/include/{ => spi}/rdmsubdevicebwdio.h (100%) rename lib-rdmsubdevice/include/{ => spi}/rdmsubdevicebwlcd.h (97%) rename lib-rdmsubdevice/include/{ => spi}/rdmsubdevicebwrelay.h (100%) rename lib-rdmsubdevice/include/{ => spi}/rdmsubdevicemcp23s08.h (100%) rename lib-rdmsubdevice/include/{ => spi}/rdmsubdevicemcp23s17.h (100%) rename lib-rdmsubdevice/include/{ => spi}/rdmsubdevicemcp4822.h (96%) rename lib-rdmsubdevice/include/{ => spi}/rdmsubdevicemcp4902.h (96%) create mode 100755 lib-rdmsubdevice/src/rdm_subdevices.cpp delete mode 100644 lib-rdmsubdevice/src/rdmsubdevice.cpp delete mode 100644 lib-rdmsubdevice/src/rdmsubdevices.cpp mode change 100644 => 100755 lib-remoteconfig/Rules.mk create mode 100755 lib-remoteconfig/http/content/date.js create mode 100644 lib-remoteconfig/http/content/date.js.h create mode 100755 lib-remoteconfig/http/content/dmx.html create mode 100644 lib-remoteconfig/http/content/dmx.html.h create mode 100755 lib-remoteconfig/http/content/dmx.js create mode 100644 lib-remoteconfig/http/content/dmx.js.h create mode 100755 lib-remoteconfig/http/content/rdm.html create mode 100644 lib-remoteconfig/http/content/rdm.html.h create mode 100755 lib-remoteconfig/http/content/rdm.js create mode 100644 lib-remoteconfig/http/content/rdm.js.h create mode 100755 lib-remoteconfig/http/content/rtc.html create mode 100644 lib-remoteconfig/http/content/rtc.html.h create mode 100755 lib-remoteconfig/http/content/rtc.js create mode 100644 lib-remoteconfig/http/content/rtc.js.h create mode 100755 lib-remoteconfig/http/content/showfile.html create mode 100644 lib-remoteconfig/http/content/showfile.html.h create mode 100755 lib-remoteconfig/http/content/showfile.js create mode 100644 lib-remoteconfig/http/content/showfile.js.h create mode 100755 lib-remoteconfig/http/content/time.html create mode 100644 lib-remoteconfig/http/content/time.html.h create mode 100755 lib-remoteconfig/http/content/time.js create mode 100644 lib-remoteconfig/http/content/time.js.h rename gd32_emac_e131_pixel_multi/include/pixeldmxstartstop.h => lib-remoteconfig/include/httpd/http.h (60%) mode change 100644 => 100755 create mode 100755 lib-remoteconfig/include/httpd/httpdhandlerequest.h mode change 100644 => 100755 lib-remoteconfig/include/shell/shell.h mode change 100644 => 100755 lib-remoteconfig/include/tftp/tftpfileserver.h create mode 100644 lib-remoteconfig/src/gd32/shellcmd.cpp delete mode 100755 lib-remoteconfig/src/httpd/httd.cpp rename gd32_rdm_responder/lib/rdmidentify.cpp => lib-remoteconfig/src/httpd/httpd.cpp (54%) mode change 100644 => 100755 create mode 100755 lib-remoteconfig/src/httpd/httpdhandlerequest.cpp delete mode 100644 lib-remoteconfig/src/remoteconfigparamsdump.cpp mode change 100644 => 100755 lib-remoteconfig/src/shell/shell.cpp mode change 100644 => 100755 lib-remoteconfig/src/shell/shellcmd.cpp create mode 100755 lib-showfile/.cproject rename {lib-debug => lib-showfile}/.project (96%) mode change 100644 => 100755 rename {lib-rdmresponder => lib-showfile}/.settings/language.settings.xml (87%) mode change 100644 => 100755 create mode 100755 lib-showfile/.settings/org.eclipse.cdt.codan.core.prefs rename {lib-c++ => lib-showfile}/.settings/org.eclipse.cdt.core.prefs (100%) mode change 100644 => 100755 rename {lib-dmxreceiver => lib-showfile}/.settings/org.eclipse.core.resources.prefs (100%) mode change 100644 => 100755 create mode 100644 lib-showfile/Makefile.GD32 create mode 100755 lib-showfile/Rules.mk create mode 100755 lib-showfile/include/formats/showfileformatola.h create mode 100755 lib-showfile/include/protocols/showfileprotocolartnet.h create mode 100755 lib-showfile/include/protocols/showfileprotocolartnettrigger.h create mode 100755 lib-showfile/include/protocols/showfileprotocole131.h create mode 100755 lib-showfile/include/protocols/showfileprotocolnodeartnet.h create mode 100755 lib-showfile/include/protocols/showfileprotocolnodee131.h create mode 100644 lib-showfile/include/showfile.h rename lib-network/src/net/net_timers.cpp => lib-showfile/include/showfileconst.h (65%) mode change 100644 => 100755 create mode 100644 lib-showfile/include/showfiledisplay.h create mode 100755 lib-showfile/include/showfileformat.h create mode 100644 lib-showfile/include/showfileosc.h create mode 100644 lib-showfile/include/showfileparams.h rename lib-rdmsensor/src/rmdsensorprint.cpp => lib-showfile/include/showfileparamsconst.h (71%) create mode 100755 lib-showfile/include/showfileprotocol.h rename lib-configstore/include/storerdmsubdevices.h => lib-showfile/include/showfiletftp.h (57%) create mode 100755 lib-showfile/src/display/showfiledisplay.cpp create mode 100755 lib-showfile/src/formats/ola/showfile_record.cpp create mode 100644 lib-showfile/src/formats/ola/showfileformatola.cpp create mode 100755 lib-showfile/src/json_delete.cpp create mode 100755 lib-showfile/src/json_get_directory.cpp create mode 100755 lib-showfile/src/json_status.cpp create mode 100644 lib-showfile/src/osc/showfileosc.cpp create mode 100755 lib-showfile/src/protocols/artnet/showfileprotocolartnettrigger.cpp create mode 100644 lib-showfile/src/showfile.cpp create mode 100755 lib-showfile/src/showfile_filename.cpp create mode 100644 lib-showfile/src/showfileparams.cpp rename lib-configstore/src/e131/storee131.cpp => lib-showfile/src/showfileparamsconst.cpp (63%) create mode 100644 lib-showfile/src/showfiletftp.cpp delete mode 100644 lib-uuid/.cproject delete mode 100644 lib-uuid/.settings/language.settings.xml delete mode 100644 lib-uuid/.settings/org.eclipse.core.resources.prefs delete mode 100644 lib-uuid/Makefile.GD32 mode change 100755 => 100644 lib-ws28xx/Rules.mk rename lib-ws28xx/include/{ => gd32}/gpio/board_gd32f207rg.h (100%) rename lib-ws28xx/include/{ => gd32}/gpio/pixelmulti_config.h (88%) rename lib-ws28xx/include/{ => gd32}/gpio/ws28xxmulti.h (76%) mode change 100644 => 100755 lib-ws28xx/include/pixelconfiguration.h delete mode 100644 lib-ws28xx/include/spi/ws28xxmulti.h rename lib-ws28xx/src/{ => gd32}/gpio/ws28xxmulti.cpp (88%) rename lib-ws28xx/src/{ => gd32}/i2s/ws28xx.cpp (66%) create mode 100755 lib-ws28xx/src/json_get_satus.cpp delete mode 100644 lib-ws28xx/src/pixelconfiguration.cpp mode change 100644 => 100755 lib-ws28xxdmx/include/pixeldmxstore.h delete mode 100755 lib-ws28xxdmx/src/dmx/ws28xxdmxmulti.cpp create mode 100755 lib-ws28xxdmx/src/dmxmulti/ws28xxdmxmulti.cpp delete mode 100644 lib-ws28xxdmx/src/params/pixeldmxparamsdump.cpp delete mode 100644 lib-ws28xxdmx/src/pixeldmxconfiguration.cpp diff --git a/.gitignore b/.gitignore index b1126cc3..24265f69 100644 --- a/.gitignore +++ b/.gitignore @@ -52,20 +52,25 @@ *.map *.list *.size +sofware_version_id.h *.bin udp_send do-tftp.sh -gd32f10x*.* +lib-*/src/esp8266/* +lib-*/include/esp8266/* + +lib-*/src/h3/* + +gd32f1*.* lib-gd32/gd32f10x/* -gd32f30x*.* +gd32f3*.* lib-gd32/gd32f30x/* -gd32f4xx*.* +gd32f4*.* lib-gd32/gd32f4xx/* +gd32fh*.* +lib-gd32/gd32h7xx/* -lib-*/src/esp8266/* -lib-*/include/esp8266/* -lib-*/src/h3/* -lib-*/include/h3/* +software_version_id.h diff --git a/CMSIS/.cproject b/CMSIS/.cproject new file mode 100644 index 00000000..5f16a37f --- /dev/null +++ b/CMSIS/.cproject @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib-uuid/.project b/CMSIS/.project similarity index 93% rename from lib-uuid/.project rename to CMSIS/.project index dd0edd7a..e2e0ca79 100644 --- a/lib-uuid/.project +++ b/CMSIS/.project @@ -1,26 +1,26 @@ - - - lib-uuid - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - + + + CMSIS + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/lib-c/.settings/language.settings.xml b/CMSIS/.settings/language.settings.xml similarity index 88% rename from lib-c/.settings/language.settings.xml rename to CMSIS/.settings/language.settings.xml index 4367d277..ed16b203 100644 --- a/lib-c/.settings/language.settings.xml +++ b/CMSIS/.settings/language.settings.xml @@ -1,6 +1,6 @@ - + diff --git a/gd32_rdm_responder/.settings/org.eclipse.core.resources.prefs b/CMSIS/.settings/org.eclipse.core.resources.prefs similarity index 100% rename from gd32_rdm_responder/.settings/org.eclipse.core.resources.prefs rename to CMSIS/.settings/org.eclipse.core.resources.prefs diff --git a/CMSIS/Core/Include/cachel1_armv7.h b/CMSIS/Core/Include/cachel1_armv7.h new file mode 100644 index 00000000..abebc95f --- /dev/null +++ b/CMSIS/Core/Include/cachel1_armv7.h @@ -0,0 +1,411 @@ +/****************************************************************************** + * @file cachel1_armv7.h + * @brief CMSIS Level 1 Cache API for Armv7-M and later + * @version V1.0.1 + * @date 19. April 2021 + ******************************************************************************/ +/* + * Copyright (c) 2020-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef ARM_CACHEL1_ARMV7_H +#define ARM_CACHEL1_ARMV7_H + +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_CacheFunctions Cache Functions + \brief Functions that configure Instruction and Data cache. + @{ + */ + +/* Cache Size ID Register Macros */ +#define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos) +#define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos ) + +#ifndef __SCB_DCACHE_LINE_SIZE +#define __SCB_DCACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */ +#endif + +#ifndef __SCB_ICACHE_LINE_SIZE +#define __SCB_ICACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */ +#endif + +/** + \brief Enable I-Cache + \details Turns on I-Cache + */ +__STATIC_FORCEINLINE void SCB_EnableICache (void) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + if (SCB->CCR & SCB_CCR_IC_Msk) return; /* return if ICache is already enabled */ + + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + __DSB(); + __ISB(); + SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable I-Cache + \details Turns off I-Cache + */ +__STATIC_FORCEINLINE void SCB_DisableICache (void) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */ + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate I-Cache + \details Invalidates I-Cache + */ +__STATIC_FORCEINLINE void SCB_InvalidateICache (void) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; + __DSB(); + __ISB(); + #endif +} + + +/** + \brief I-Cache Invalidate by address + \details Invalidates I-Cache for the given address. + I-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity. + I-Cache memory blocks which are part of given address + given size are invalidated. + \param[in] addr address + \param[in] isize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_InvalidateICache_by_Addr (volatile void *addr, int32_t isize) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + if ( isize > 0 ) { + int32_t op_size = isize + (((uint32_t)addr) & (__SCB_ICACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_ICACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->ICIMVAU = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_ICACHE_LINE_SIZE; + op_size -= __SCB_ICACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + + +/** + \brief Enable D-Cache + \details Turns on D-Cache + */ +__STATIC_FORCEINLINE void SCB_EnableDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + if (SCB->CCR & SCB_CCR_DC_Msk) return; /* return if DCache is already enabled */ + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + __DSB(); + + SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */ + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable D-Cache + \details Turns off D-Cache + */ +__STATIC_FORCEINLINE void SCB_DisableDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate D-Cache + \details Invalidates D-Cache + */ +__STATIC_FORCEINLINE void SCB_InvalidateDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean D-Cache + \details Cleans D-Cache + */ +__STATIC_FORCEINLINE void SCB_CleanDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCSW = (((sets << SCB_DCCSW_SET_Pos) & SCB_DCCSW_SET_Msk) | + ((ways << SCB_DCCSW_WAY_Pos) & SCB_DCCSW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean & Invalidate D-Cache + \details Cleans and Invalidates D-Cache + */ +__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Invalidate by address + \details Invalidates D-Cache for the given address. + D-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity. + D-Cache memory blocks which are part of given address + given size are invalidated. + \param[in] addr address + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_InvalidateDCache_by_Addr (volatile void *addr, int32_t dsize) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + if ( dsize > 0 ) { + int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->DCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_DCACHE_LINE_SIZE; + op_size -= __SCB_DCACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + + +/** + \brief D-Cache Clean by address + \details Cleans D-Cache for the given address + D-Cache is cleaned starting from a 32 byte aligned address in 32 byte granularity. + D-Cache memory blocks which are part of given address + given size are cleaned. + \param[in] addr address + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_CleanDCache_by_Addr (volatile void *addr, int32_t dsize) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + if ( dsize > 0 ) { + int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->DCCMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_DCACHE_LINE_SIZE; + op_size -= __SCB_DCACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + + +/** + \brief D-Cache Clean and Invalidate by address + \details Cleans and invalidates D_Cache for the given address + D-Cache is cleaned and invalidated starting from a 32 byte aligned address in 32 byte granularity. + D-Cache memory blocks which are part of given address + given size are cleaned and invalidated. + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache_by_Addr (volatile void *addr, int32_t dsize) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + if ( dsize > 0 ) { + int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->DCCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_DCACHE_LINE_SIZE; + op_size -= __SCB_DCACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + +/*@} end of CMSIS_Core_CacheFunctions */ + +#endif /* ARM_CACHEL1_ARMV7_H */ diff --git a/lib-gd32/gd32f20x/CMSIS/cmsis_armcc.h b/CMSIS/Core/Include/cmsis_armcc.h similarity index 71% rename from lib-gd32/gd32f20x/CMSIS/cmsis_armcc.h rename to CMSIS/Core/Include/cmsis_armcc.h index f2bb66a0..a955d471 100644 --- a/lib-gd32/gd32f20x/CMSIS/cmsis_armcc.h +++ b/CMSIS/Core/Include/cmsis_armcc.h @@ -1,734 +1,888 @@ -/**************************************************************************//** - * @file cmsis_armcc.h - * @brief CMSIS Cortex-M Core Function/Instruction Header File - * @version V4.30 - * @date 20. October 2015 - ******************************************************************************/ -/* Copyright (c) 2009 - 2015 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - - -#ifndef __CMSIS_ARMCC_H -#define __CMSIS_ARMCC_H - - -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) - #error "Please use ARM Compiler Toolchain V4.0.677 or later!" -#endif - -/* ########################### Core Function Access ########################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions - @{ - */ - -/* intrinsic void __enable_irq(); */ -/* intrinsic void __disable_irq(); */ - -/** - \brief Get Control Register - \details Returns the content of the Control Register. - \return Control Register value - */ -__STATIC_INLINE uint32_t __get_CONTROL(void) -{ - register uint32_t __regControl __ASM("control"); - return(__regControl); -} - - -/** - \brief Set Control Register - \details Writes the given value to the Control Register. - \param [in] control Control Register value to set - */ -__STATIC_INLINE void __set_CONTROL(uint32_t control) -{ - register uint32_t __regControl __ASM("control"); - __regControl = control; -} - - -/** - \brief Get IPSR Register - \details Returns the content of the IPSR Register. - \return IPSR Register value - */ -__STATIC_INLINE uint32_t __get_IPSR(void) -{ - register uint32_t __regIPSR __ASM("ipsr"); - return(__regIPSR); -} - - -/** - \brief Get APSR Register - \details Returns the content of the APSR Register. - \return APSR Register value - */ -__STATIC_INLINE uint32_t __get_APSR(void) -{ - register uint32_t __regAPSR __ASM("apsr"); - return(__regAPSR); -} - - -/** - \brief Get xPSR Register - \details Returns the content of the xPSR Register. - \return xPSR Register value - */ -__STATIC_INLINE uint32_t __get_xPSR(void) -{ - register uint32_t __regXPSR __ASM("xpsr"); - return(__regXPSR); -} - - -/** - \brief Get Process Stack Pointer - \details Returns the current value of the Process Stack Pointer (PSP). - \return PSP Register value - */ -__STATIC_INLINE uint32_t __get_PSP(void) -{ - register uint32_t __regProcessStackPointer __ASM("psp"); - return(__regProcessStackPointer); -} - - -/** - \brief Set Process Stack Pointer - \details Assigns the given value to the Process Stack Pointer (PSP). - \param [in] topOfProcStack Process Stack Pointer value to set - */ -__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) -{ - register uint32_t __regProcessStackPointer __ASM("psp"); - __regProcessStackPointer = topOfProcStack; -} - - -/** - \brief Get Main Stack Pointer - \details Returns the current value of the Main Stack Pointer (MSP). - \return MSP Register value - */ -__STATIC_INLINE uint32_t __get_MSP(void) -{ - register uint32_t __regMainStackPointer __ASM("msp"); - return(__regMainStackPointer); -} - - -/** - \brief Set Main Stack Pointer - \details Assigns the given value to the Main Stack Pointer (MSP). - \param [in] topOfMainStack Main Stack Pointer value to set - */ -__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) -{ - register uint32_t __regMainStackPointer __ASM("msp"); - __regMainStackPointer = topOfMainStack; -} - - -/** - \brief Get Priority Mask - \details Returns the current state of the priority mask bit from the Priority Mask Register. - \return Priority Mask value - */ -__STATIC_INLINE uint32_t __get_PRIMASK(void) -{ - register uint32_t __regPriMask __ASM("primask"); - return(__regPriMask); -} - - -/** - \brief Set Priority Mask - \details Assigns the given value to the Priority Mask Register. - \param [in] priMask Priority Mask - */ -__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) -{ - register uint32_t __regPriMask __ASM("primask"); - __regPriMask = (priMask); -} - - -#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) - -/** - \brief Enable FIQ - \details Enables FIQ interrupts by clearing the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -#define __enable_fault_irq __enable_fiq - - -/** - \brief Disable FIQ - \details Disables FIQ interrupts by setting the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -#define __disable_fault_irq __disable_fiq - - -/** - \brief Get Base Priority - \details Returns the current value of the Base Priority register. - \return Base Priority register value - */ -__STATIC_INLINE uint32_t __get_BASEPRI(void) -{ - register uint32_t __regBasePri __ASM("basepri"); - return(__regBasePri); -} - - -/** - \brief Set Base Priority - \details Assigns the given value to the Base Priority register. - \param [in] basePri Base Priority value to set - */ -__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) -{ - register uint32_t __regBasePri __ASM("basepri"); - __regBasePri = (basePri & 0xFFU); -} - - -/** - \brief Set Base Priority with condition - \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, - or the new value increases the BASEPRI priority level. - \param [in] basePri Base Priority value to set - */ -__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) -{ - register uint32_t __regBasePriMax __ASM("basepri_max"); - __regBasePriMax = (basePri & 0xFFU); -} - - -/** - \brief Get Fault Mask - \details Returns the current value of the Fault Mask register. - \return Fault Mask register value - */ -__STATIC_INLINE uint32_t __get_FAULTMASK(void) -{ - register uint32_t __regFaultMask __ASM("faultmask"); - return(__regFaultMask); -} - - -/** - \brief Set Fault Mask - \details Assigns the given value to the Fault Mask register. - \param [in] faultMask Fault Mask value to set - */ -__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) -{ - register uint32_t __regFaultMask __ASM("faultmask"); - __regFaultMask = (faultMask & (uint32_t)1); -} - -#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ - - -#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) - -/** - \brief Get FPSCR - \details Returns the current value of the Floating Point Status/Control register. - \return Floating Point Status/Control register value - */ -__STATIC_INLINE uint32_t __get_FPSCR(void) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - register uint32_t __regfpscr __ASM("fpscr"); - return(__regfpscr); -#else - return(0U); -#endif -} - - -/** - \brief Set FPSCR - \details Assigns the given value to the Floating Point Status/Control register. - \param [in] fpscr Floating Point Status/Control value to set - */ -__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) -{ -#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U) - register uint32_t __regfpscr __ASM("fpscr"); - __regfpscr = (fpscr); -#endif -} - -#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */ - - - -/*@} end of CMSIS_Core_RegAccFunctions */ - - -/* ########################## Core Instruction Access ######################### */ -/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface - Access to dedicated instructions - @{ -*/ - -/** - \brief No Operation - \details No Operation does nothing. This instruction can be used for code alignment purposes. - */ -#define __NOP __nop - - -/** - \brief Wait For Interrupt - \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. - */ -#define __WFI __wfi - - -/** - \brief Wait For Event - \details Wait For Event is a hint instruction that permits the processor to enter - a low-power state until one of a number of events occurs. - */ -#define __WFE __wfe - - -/** - \brief Send Event - \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. - */ -#define __SEV __sev - - -/** - \brief Instruction Synchronization Barrier - \details Instruction Synchronization Barrier flushes the pipeline in the processor, - so that all instructions following the ISB are fetched from cache or memory, - after the instruction has been completed. - */ -#define __ISB() do {\ - __schedule_barrier();\ - __isb(0xF);\ - __schedule_barrier();\ - } while (0U) - -/** - \brief Data Synchronization Barrier - \details Acts as a special kind of Data Memory Barrier. - It completes when all explicit memory accesses before this instruction complete. - */ -#define __DSB() do {\ - __schedule_barrier();\ - __dsb(0xF);\ - __schedule_barrier();\ - } while (0U) - -/** - \brief Data Memory Barrier - \details Ensures the apparent order of the explicit memory operations before - and after the instruction, without ensuring their completion. - */ -#define __DMB() do {\ - __schedule_barrier();\ - __dmb(0xF);\ - __schedule_barrier();\ - } while (0U) - -/** - \brief Reverse byte order (32 bit) - \details Reverses the byte order in integer value. - \param [in] value Value to reverse - \return Reversed value - */ -#define __REV __rev - - -/** - \brief Reverse byte order (16 bit) - \details Reverses the byte order in two unsigned short values. - \param [in] value Value to reverse - \return Reversed value - */ -#ifndef __NO_EMBEDDED_ASM -__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) -{ - rev16 r0, r0 - bx lr -} -#endif - -/** - \brief Reverse byte order in signed short value - \details Reverses the byte order in a signed short value with sign extension to integer. - \param [in] value Value to reverse - \return Reversed value - */ -#ifndef __NO_EMBEDDED_ASM -__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) -{ - revsh r0, r0 - bx lr -} -#endif - - -/** - \brief Rotate Right in unsigned value (32 bit) - \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. - \param [in] value Value to rotate - \param [in] value Number of Bits to rotate - \return Rotated value - */ -#define __ROR __ror - - -/** - \brief Breakpoint - \details Causes the processor to enter Debug state. - Debug tools can use this to investigate system state when the instruction at a particular address is reached. - \param [in] value is ignored by the processor. - If required, a debugger can use it to store additional information about the breakpoint. - */ -#define __BKPT(value) __breakpoint(value) - - -/** - \brief Reverse bit order of value - \details Reverses the bit order of the given value. - \param [in] value Value to reverse - \return Reversed value - */ -#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) - #define __RBIT __rbit -#else -__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) -{ - uint32_t result; - int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */ - - result = value; /* r will be reversed bits of v; first get LSB of v */ - for (value >>= 1U; value; value >>= 1U) - { - result <<= 1U; - result |= value & 1U; - s--; - } - result <<= s; /* shift when v's highest bits are zero */ - return(result); -} -#endif - - -/** - \brief Count leading zeros - \details Counts the number of leading zeros of a data value. - \param [in] value Value to count the leading zeros - \return number of leading zeros in value - */ -#define __CLZ __clz - - -#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) - -/** - \brief LDR Exclusive (8 bit) - \details Executes a exclusive LDR instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) -#else - #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop") -#endif - - -/** - \brief LDR Exclusive (16 bit) - \details Executes a exclusive LDR instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) -#else - #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop") -#endif - - -/** - \brief LDR Exclusive (32 bit) - \details Executes a exclusive LDR instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) -#else - #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop") -#endif - - -/** - \brief STR Exclusive (8 bit) - \details Executes a exclusive STR instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __STREXB(value, ptr) __strex(value, ptr) -#else - #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") -#endif - - -/** - \brief STR Exclusive (16 bit) - \details Executes a exclusive STR instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __STREXH(value, ptr) __strex(value, ptr) -#else - #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") -#endif - - -/** - \brief STR Exclusive (32 bit) - \details Executes a exclusive STR instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __STREXW(value, ptr) __strex(value, ptr) -#else - #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") -#endif - - -/** - \brief Remove the exclusive lock - \details Removes the exclusive lock which is created by LDREX. - */ -#define __CLREX __clrex - - -/** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value - */ -#define __SSAT __ssat - - -/** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value - */ -#define __USAT __usat - - -/** - \brief Rotate Right with Extend (32 bit) - \details Moves each bit of a bitstring right by one bit. - The carry input is shifted in at the left end of the bitstring. - \param [in] value Value to rotate - \return Rotated value - */ -#ifndef __NO_EMBEDDED_ASM -__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) -{ - rrx r0, r0 - bx lr -} -#endif - - -/** - \brief LDRT Unprivileged (8 bit) - \details Executes a Unprivileged LDRT instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) - - -/** - \brief LDRT Unprivileged (16 bit) - \details Executes a Unprivileged LDRT instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) - - -/** - \brief LDRT Unprivileged (32 bit) - \details Executes a Unprivileged LDRT instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) - - -/** - \brief STRT Unprivileged (8 bit) - \details Executes a Unprivileged STRT instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -#define __STRBT(value, ptr) __strt(value, ptr) - - -/** - \brief STRT Unprivileged (16 bit) - \details Executes a Unprivileged STRT instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -#define __STRHT(value, ptr) __strt(value, ptr) - - -/** - \brief STRT Unprivileged (32 bit) - \details Executes a Unprivileged STRT instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -#define __STRT(value, ptr) __strt(value, ptr) - -#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */ - -/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ - - -/* ################### Compiler specific Intrinsics ########################### */ -/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics - Access to dedicated SIMD instructions - @{ -*/ - -#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */ - -#define __SADD8 __sadd8 -#define __QADD8 __qadd8 -#define __SHADD8 __shadd8 -#define __UADD8 __uadd8 -#define __UQADD8 __uqadd8 -#define __UHADD8 __uhadd8 -#define __SSUB8 __ssub8 -#define __QSUB8 __qsub8 -#define __SHSUB8 __shsub8 -#define __USUB8 __usub8 -#define __UQSUB8 __uqsub8 -#define __UHSUB8 __uhsub8 -#define __SADD16 __sadd16 -#define __QADD16 __qadd16 -#define __SHADD16 __shadd16 -#define __UADD16 __uadd16 -#define __UQADD16 __uqadd16 -#define __UHADD16 __uhadd16 -#define __SSUB16 __ssub16 -#define __QSUB16 __qsub16 -#define __SHSUB16 __shsub16 -#define __USUB16 __usub16 -#define __UQSUB16 __uqsub16 -#define __UHSUB16 __uhsub16 -#define __SASX __sasx -#define __QASX __qasx -#define __SHASX __shasx -#define __UASX __uasx -#define __UQASX __uqasx -#define __UHASX __uhasx -#define __SSAX __ssax -#define __QSAX __qsax -#define __SHSAX __shsax -#define __USAX __usax -#define __UQSAX __uqsax -#define __UHSAX __uhsax -#define __USAD8 __usad8 -#define __USADA8 __usada8 -#define __SSAT16 __ssat16 -#define __USAT16 __usat16 -#define __UXTB16 __uxtb16 -#define __UXTAB16 __uxtab16 -#define __SXTB16 __sxtb16 -#define __SXTAB16 __sxtab16 -#define __SMUAD __smuad -#define __SMUADX __smuadx -#define __SMLAD __smlad -#define __SMLADX __smladx -#define __SMLALD __smlald -#define __SMLALDX __smlaldx -#define __SMUSD __smusd -#define __SMUSDX __smusdx -#define __SMLSD __smlsd -#define __SMLSDX __smlsdx -#define __SMLSLD __smlsld -#define __SMLSLDX __smlsldx -#define __SEL __sel -#define __QADD __qadd -#define __QSUB __qsub - -#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ - ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) - -#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ - ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) - -#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ - ((int64_t)(ARG3) << 32U) ) >> 32U)) - -#endif /* (__CORTEX_M >= 0x04) */ -/*@} end of group CMSIS_SIMD_intrinsics */ - - -#endif /* __CMSIS_ARMCC_H */ +/**************************************************************************//** + * @file cmsis_armcc.h + * @brief CMSIS compiler ARMCC (Arm Compiler 5) header file + * @version V5.3.2 + * @date 27. May 2021 + ******************************************************************************/ +/* + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_ARMCC_H +#define __CMSIS_ARMCC_H + + +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) + #error "Please use Arm Compiler Toolchain V4.0.677 or later!" +#endif + +/* CMSIS compiler control architecture macros */ +#if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \ + (defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) ) + #define __ARM_ARCH_6M__ 1 +#endif + +#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1)) + #define __ARM_ARCH_7M__ 1 +#endif + +#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1)) + #define __ARM_ARCH_7EM__ 1 +#endif + + /* __ARM_ARCH_8M_BASE__ not applicable */ + /* __ARM_ARCH_8M_MAIN__ not applicable */ + /* __ARM_ARCH_8_1M_MAIN__ not applicable */ + +/* CMSIS compiler control DSP macros */ +#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + #define __ARM_FEATURE_DSP 1 +#endif + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE static __forceinline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __declspec(noreturn) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed)) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT __packed struct +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION __packed union +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x))) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr))) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr))) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __memory_changed() +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START +#define __PROGRAM_START __main +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section("RESET"))) +#endif + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __isb(0xF) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + #define __RBIT __rbit +#else +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value != 0U; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ + return result; +} +#endif + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) +#else + #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) +#else + #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) +#else + #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXB(value, ptr) __strex(value, ptr) +#else + #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXH(value, ptr) __strex(value, ptr) +#else + #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXW(value, ptr) __strex(value, ptr) +#else + #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) +{ + rrx r0, r0 + bx lr +} +#endif + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRBT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRHT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRT(value, ptr) __strt(value, ptr) + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +/* intrinsic void __enable_irq(); */ + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +/* intrinsic void __disable_irq(); */ + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; + __ISB(); +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xFFU); +} + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + register uint32_t __regBasePriMax __ASM("basepri_max"); + __regBasePriMax = (basePri & 0xFFU); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1U); +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#else + (void)fpscr; +#endif +} + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + +#define __SADD8 __sadd8 +#define __QADD8 __qadd8 +#define __SHADD8 __shadd8 +#define __UADD8 __uadd8 +#define __UQADD8 __uqadd8 +#define __UHADD8 __uhadd8 +#define __SSUB8 __ssub8 +#define __QSUB8 __qsub8 +#define __SHSUB8 __shsub8 +#define __USUB8 __usub8 +#define __UQSUB8 __uqsub8 +#define __UHSUB8 __uhsub8 +#define __SADD16 __sadd16 +#define __QADD16 __qadd16 +#define __SHADD16 __shadd16 +#define __UADD16 __uadd16 +#define __UQADD16 __uqadd16 +#define __UHADD16 __uhadd16 +#define __SSUB16 __ssub16 +#define __QSUB16 __qsub16 +#define __SHSUB16 __shsub16 +#define __USUB16 __usub16 +#define __UQSUB16 __uqsub16 +#define __UHSUB16 __uhsub16 +#define __SASX __sasx +#define __QASX __qasx +#define __SHASX __shasx +#define __UASX __uasx +#define __UQASX __uqasx +#define __UHASX __uhasx +#define __SSAX __ssax +#define __QSAX __qsax +#define __SHSAX __shsax +#define __USAX __usax +#define __UQSAX __uqsax +#define __UHSAX __uhsax +#define __USAD8 __usad8 +#define __USADA8 __usada8 +#define __SSAT16 __ssat16 +#define __USAT16 __usat16 +#define __UXTB16 __uxtb16 +#define __UXTAB16 __uxtab16 +#define __SXTB16 __sxtb16 +#define __SXTAB16 __sxtab16 +#define __SMUAD __smuad +#define __SMUADX __smuadx +#define __SMLAD __smlad +#define __SMLADX __smladx +#define __SMLALD __smlald +#define __SMLALDX __smlaldx +#define __SMUSD __smusd +#define __SMUSDX __smusdx +#define __SMLSD __smlsd +#define __SMLSDX __smlsdx +#define __SMLSLD __smlsld +#define __SMLSLDX __smlsldx +#define __SEL __sel +#define __QADD __qadd +#define __QSUB __qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ + ((int64_t)(ARG3) << 32U) ) >> 32U)) + +#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) + +#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) + +#endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_H */ diff --git a/CMSIS/Core/Include/cmsis_armclang.h b/CMSIS/Core/Include/cmsis_armclang.h new file mode 100644 index 00000000..69114177 --- /dev/null +++ b/CMSIS/Core/Include/cmsis_armclang.h @@ -0,0 +1,1503 @@ +/**************************************************************************//** + * @file cmsis_armclang.h + * @brief CMSIS compiler armclang (Arm Compiler 6) header file + * @version V5.4.3 + * @date 27. May 2021 + ******************************************************************************/ +/* + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */ + +#ifndef __CMSIS_ARMCLANG_H +#define __CMSIS_ARMCLANG_H + +#pragma clang system_header /* treat file as system include file */ + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */ + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */ + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START +#define __PROGRAM_START __main +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section("RESET"))) +#endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#ifndef __STACK_SEAL +#define __STACK_SEAL Image$$STACKSEAL$$ZI$$Base +#endif + +#ifndef __TZ_STACK_SEAL_SIZE +#define __TZ_STACK_SEAL_SIZE 8U +#endif + +#ifndef __TZ_STACK_SEAL_VALUE +#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL +#endif + + +__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { + *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; +} +#endif + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __builtin_arm_nop + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __builtin_arm_wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __builtin_arm_wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __builtin_arm_sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF) + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __builtin_arm_dmb(0xF) + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV(value) __builtin_bswap32(value) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV16(value) __ROR(__REV(value), 16) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REVSH(value) (int16_t)__builtin_bswap16(value) + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __builtin_arm_rbit + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB (uint8_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH (uint16_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW (uint32_t)__builtin_arm_ldrex + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW (uint32_t)__builtin_arm_strex + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __builtin_arm_clrex + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __builtin_arm_ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __builtin_arm_usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDAEXH (uint16_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXB (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEX (uint32_t)__builtin_arm_stlex + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} +#endif + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} +#endif + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); + __ISB(); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); + __ISB(); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr +#else +#define __get_FPSCR() ((uint32_t)0U) +#endif + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __set_FPSCR __builtin_arm_set_fpscr +#else +#define __set_FPSCR(x) ((void)(x)) +#endif + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +#define __SADD8 __builtin_arm_sadd8 +#define __QADD8 __builtin_arm_qadd8 +#define __SHADD8 __builtin_arm_shadd8 +#define __UADD8 __builtin_arm_uadd8 +#define __UQADD8 __builtin_arm_uqadd8 +#define __UHADD8 __builtin_arm_uhadd8 +#define __SSUB8 __builtin_arm_ssub8 +#define __QSUB8 __builtin_arm_qsub8 +#define __SHSUB8 __builtin_arm_shsub8 +#define __USUB8 __builtin_arm_usub8 +#define __UQSUB8 __builtin_arm_uqsub8 +#define __UHSUB8 __builtin_arm_uhsub8 +#define __SADD16 __builtin_arm_sadd16 +#define __QADD16 __builtin_arm_qadd16 +#define __SHADD16 __builtin_arm_shadd16 +#define __UADD16 __builtin_arm_uadd16 +#define __UQADD16 __builtin_arm_uqadd16 +#define __UHADD16 __builtin_arm_uhadd16 +#define __SSUB16 __builtin_arm_ssub16 +#define __QSUB16 __builtin_arm_qsub16 +#define __SHSUB16 __builtin_arm_shsub16 +#define __USUB16 __builtin_arm_usub16 +#define __UQSUB16 __builtin_arm_uqsub16 +#define __UHSUB16 __builtin_arm_uhsub16 +#define __SASX __builtin_arm_sasx +#define __QASX __builtin_arm_qasx +#define __SHASX __builtin_arm_shasx +#define __UASX __builtin_arm_uasx +#define __UQASX __builtin_arm_uqasx +#define __UHASX __builtin_arm_uhasx +#define __SSAX __builtin_arm_ssax +#define __QSAX __builtin_arm_qsax +#define __SHSAX __builtin_arm_shsax +#define __USAX __builtin_arm_usax +#define __UQSAX __builtin_arm_uqsax +#define __UHSAX __builtin_arm_uhsax +#define __USAD8 __builtin_arm_usad8 +#define __USADA8 __builtin_arm_usada8 +#define __SSAT16 __builtin_arm_ssat16 +#define __USAT16 __builtin_arm_usat16 +#define __UXTB16 __builtin_arm_uxtb16 +#define __UXTAB16 __builtin_arm_uxtab16 +#define __SXTB16 __builtin_arm_sxtb16 +#define __SXTAB16 __builtin_arm_sxtab16 +#define __SMUAD __builtin_arm_smuad +#define __SMUADX __builtin_arm_smuadx +#define __SMLAD __builtin_arm_smlad +#define __SMLADX __builtin_arm_smladx +#define __SMLALD __builtin_arm_smlald +#define __SMLALDX __builtin_arm_smlaldx +#define __SMUSD __builtin_arm_smusd +#define __SMUSDX __builtin_arm_smusdx +#define __SMLSD __builtin_arm_smlsd +#define __SMLSDX __builtin_arm_smlsdx +#define __SMLSLD __builtin_arm_smlsld +#define __SMLSLDX __builtin_arm_smlsldx +#define __SEL __builtin_arm_sel +#define __QADD __builtin_arm_qadd +#define __QSUB __builtin_arm_qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) + +#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCLANG_H */ diff --git a/CMSIS/Core/Include/cmsis_armclang_ltm.h b/CMSIS/Core/Include/cmsis_armclang_ltm.h new file mode 100644 index 00000000..1e255d59 --- /dev/null +++ b/CMSIS/Core/Include/cmsis_armclang_ltm.h @@ -0,0 +1,1928 @@ +/**************************************************************************//** + * @file cmsis_armclang_ltm.h + * @brief CMSIS compiler armclang (Arm Compiler 6) header file + * @version V1.5.3 + * @date 27. May 2021 + ******************************************************************************/ +/* + * Copyright (c) 2018-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */ + +#ifndef __CMSIS_ARMCLANG_H +#define __CMSIS_ARMCLANG_H + +#pragma clang system_header /* treat file as system include file */ + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */ + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */ + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START +#define __PROGRAM_START __main +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section("RESET"))) +#endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#ifndef __STACK_SEAL +#define __STACK_SEAL Image$$STACKSEAL$$ZI$$Base +#endif + +#ifndef __TZ_STACK_SEAL_SIZE +#define __TZ_STACK_SEAL_SIZE 8U +#endif + +#ifndef __TZ_STACK_SEAL_VALUE +#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL +#endif + + +__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { + *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; +} +#endif + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __builtin_arm_nop + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __builtin_arm_wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __builtin_arm_wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __builtin_arm_sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF) + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __builtin_arm_dmb(0xF) + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV(value) __builtin_bswap32(value) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV16(value) __ROR(__REV(value), 16) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REVSH(value) (int16_t)__builtin_bswap16(value) + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __builtin_arm_rbit + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB (uint8_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH (uint16_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW (uint32_t)__builtin_arm_ldrex + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW (uint32_t)__builtin_arm_strex + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __builtin_arm_clrex + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __builtin_arm_ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __builtin_arm_usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDAEXH (uint16_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXB (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEX (uint32_t)__builtin_arm_stlex + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} +#endif + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} +#endif + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); + __ISB(); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); + __ISB(); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr +#else +#define __get_FPSCR() ((uint32_t)0U) +#endif + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __set_FPSCR __builtin_arm_set_fpscr +#else +#define __set_FPSCR(x) ((void)(x)) +#endif + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) + +#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCLANG_H */ diff --git a/CMSIS/Core/Include/cmsis_compiler.h b/CMSIS/Core/Include/cmsis_compiler.h new file mode 100644 index 00000000..adbf296f --- /dev/null +++ b/CMSIS/Core/Include/cmsis_compiler.h @@ -0,0 +1,283 @@ +/**************************************************************************//** + * @file cmsis_compiler.h + * @brief CMSIS compiler generic header file + * @version V5.1.0 + * @date 09. October 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_COMPILER_H +#define __CMSIS_COMPILER_H + +#include + +/* + * Arm Compiler 4/5 + */ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + + +/* + * Arm Compiler 6.6 LTM (armclang) + */ +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100) + #include "cmsis_armclang_ltm.h" + + /* + * Arm Compiler above 6.10.1 (armclang) + */ +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100) + #include "cmsis_armclang.h" + + +/* + * GNU Compiler + */ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + + +/* + * IAR Compiler + */ +#elif defined ( __ICCARM__ ) + #include + + +/* + * TI Arm Compiler + */ +#elif defined ( __TI_ARM__ ) + #include + + #ifndef __ASM + #define __ASM __asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + #define __NO_RETURN __attribute__((noreturn)) + #endif + #ifndef __USED + #define __USED __attribute__((used)) + #endif + #ifndef __WEAK + #define __WEAK __attribute__((weak)) + #endif + #ifndef __PACKED + #define __PACKED __attribute__((packed)) + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed)) + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed)) + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) + #endif + #ifndef __RESTRICT + #define __RESTRICT __restrict + #endif + #ifndef __COMPILER_BARRIER + #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. + #define __COMPILER_BARRIER() (void)0 + #endif + + +/* + * TASKING Compiler + */ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + + #ifndef __ASM + #define __ASM __asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + #define __NO_RETURN __attribute__((noreturn)) + #endif + #ifndef __USED + #define __USED __attribute__((used)) + #endif + #ifndef __WEAK + #define __WEAK __attribute__((weak)) + #endif + #ifndef __PACKED + #define __PACKED __packed__ + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __packed__ + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __packed__ + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + struct __packed__ T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #define __ALIGNED(x) __align(x) + #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif + #ifndef __COMPILER_BARRIER + #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. + #define __COMPILER_BARRIER() (void)0 + #endif + + +/* + * COSMIC Compiler + */ +#elif defined ( __CSMC__ ) + #include + + #ifndef __ASM + #define __ASM _asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + // NO RETURN is automatically detected hence no warning here + #define __NO_RETURN + #endif + #ifndef __USED + #warning No compiler specific solution for __USED. __USED is ignored. + #define __USED + #endif + #ifndef __WEAK + #define __WEAK __weak + #endif + #ifndef __PACKED + #define __PACKED @packed + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT @packed struct + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION @packed union + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + @packed struct T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. + #define __ALIGNED(x) + #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif + #ifndef __COMPILER_BARRIER + #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. + #define __COMPILER_BARRIER() (void)0 + #endif + + +#else + #error Unknown compiler. +#endif + + +#endif /* __CMSIS_COMPILER_H */ + diff --git a/CMSIS/Core/Include/cmsis_gcc.h b/CMSIS/Core/Include/cmsis_gcc.h new file mode 100644 index 00000000..67bda4ef --- /dev/null +++ b/CMSIS/Core/Include/cmsis_gcc.h @@ -0,0 +1,2211 @@ +/**************************************************************************//** + * @file cmsis_gcc.h + * @brief CMSIS compiler GCC header file + * @version V5.4.1 + * @date 27. May 2021 + ******************************************************************************/ +/* + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_GCC_H +#define __CMSIS_GCC_H + +/* ignore some GCC warnings */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +/* Fallback for __has_builtin */ +#ifndef __has_builtin + #define __has_builtin(x) (0) +#endif + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START + +/** + \brief Initializes data and bss sections + \details This default implementations initialized all data and additional bss + sections relying on .copy.table and .zero.table specified properly + in the used linker script. + + */ +__STATIC_FORCEINLINE __NO_RETURN void __cmsis_start(void) +{ + extern void _start(void) __NO_RETURN; + + typedef struct { + uint32_t const* src; + uint32_t* dest; + uint32_t wlen; + } __copy_table_t; + + typedef struct { + uint32_t* dest; + uint32_t wlen; + } __zero_table_t; + + extern const __copy_table_t __copy_table_start__; + extern const __copy_table_t __copy_table_end__; + extern const __zero_table_t __zero_table_start__; + extern const __zero_table_t __zero_table_end__; + + for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) { + for(uint32_t i=0u; iwlen; ++i) { + pTable->dest[i] = pTable->src[i]; + } + } + + for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) { + for(uint32_t i=0u; iwlen; ++i) { + pTable->dest[i] = 0u; + } + } + + _start(); +} + +#define __PROGRAM_START __cmsis_start +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP __StackTop +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT __StackLimit +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section(".vectors"))) +#endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#ifndef __STACK_SEAL +#define __STACK_SEAL __StackSeal +#endif + +#ifndef __TZ_STACK_SEAL_SIZE +#define __TZ_STACK_SEAL_SIZE 8U +#endif + +#ifndef __TZ_STACK_SEAL_VALUE +#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL +#endif + + +__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { + *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; +} +#endif + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP() __ASM volatile ("nop") + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI() __ASM volatile ("wfi":::"memory") + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE() __ASM volatile ("wfe":::"memory") + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV() __ASM volatile ("sev") + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__STATIC_FORCEINLINE void __ISB(void) +{ + __ASM volatile ("isb 0xF":::"memory"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__STATIC_FORCEINLINE void __DSB(void) +{ + __ASM volatile ("dsb 0xF":::"memory"); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__STATIC_FORCEINLINE void __DMB(void) +{ + __ASM volatile ("dmb 0xF":::"memory"); +} + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +#endif +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE int16_t __REVSH(int16_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (int16_t)__builtin_bswap16(value); +#else + int16_t result; + + __ASM ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +#endif +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) + __ASM ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value != 0U; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return result; +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM GCC 7.3 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +__STATIC_FORCEINLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1, ARG2) \ +__extension__ \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM volatile ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1, ARG2) \ +__extension__ \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM volatile ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ + __RES; \ + }) + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return(result); +} + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); + return(result); +} + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); + return(result); +} + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); + return(result); +} + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); + __ISB(); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); + __ISB(); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_FORCEINLINE uint32_t __get_FPSCR(void) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_get_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + return __builtin_arm_get_fpscr(); +#else + uint32_t result; + + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + return(result); +#endif +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_set_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + __builtin_arm_set_fpscr(fpscr); +#else + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory"); +#endif +#else + (void)fpscr; +#endif +} + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1, ARG2) \ +__extension__ \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM volatile ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ + __RES; \ + }) + +#define __USAT16(ARG1, ARG2) \ +__extension__ \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM volatile ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) : "cc" ); \ + __RES; \ + }) + +__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTB16_RORn(uint32_t op1, uint32_t rotate) +{ + uint32_t result; + if (__builtin_constant_p(rotate) && ((rotate == 8U) || (rotate == 16U) || (rotate == 24U))) { + __ASM volatile ("sxtb16 %0, %1, ROR %2" : "=r" (result) : "r" (op1), "i" (rotate) ); + } else { + result = __SXTB16(__ROR(op1, rotate)) ; + } + return result; +} + +__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTAB16_RORn(uint32_t op1, uint32_t op2, uint32_t rotate) +{ + uint32_t result; + if (__builtin_constant_p(rotate) && ((rotate == 8U) || (rotate == 16U) || (rotate == 24U))) { + __ASM volatile ("sxtab16 %0, %1, %2, ROR %3" : "=r" (result) : "r" (op1) , "r" (op2) , "i" (rotate)); + } else { + result = __SXTAB16(op1, __ROR(op2, rotate)); + } + return result; +} + + +__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +#define __PKHBT(ARG1,ARG2,ARG3) \ +__extension__ \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +__extension__ \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#pragma GCC diagnostic pop + +#endif /* __CMSIS_GCC_H */ diff --git a/CMSIS/Core/Include/cmsis_iccarm.h b/CMSIS/Core/Include/cmsis_iccarm.h new file mode 100644 index 00000000..65b824b0 --- /dev/null +++ b/CMSIS/Core/Include/cmsis_iccarm.h @@ -0,0 +1,1002 @@ +/**************************************************************************//** + * @file cmsis_iccarm.h + * @brief CMSIS compiler ICCARM (IAR Compiler for Arm) header file + * @version V5.3.0 + * @date 14. April 2021 + ******************************************************************************/ + +//------------------------------------------------------------------------------ +// +// Copyright (c) 2017-2021 IAR Systems +// Copyright (c) 2017-2021 Arm Limited. All rights reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------ + + +#ifndef __CMSIS_ICCARM_H__ +#define __CMSIS_ICCARM_H__ + +#ifndef __ICCARM__ + #error This file should only be compiled by ICCARM +#endif + +#pragma system_include + +#define __IAR_FT _Pragma("inline=forced") __intrinsic + +#if (__VER__ >= 8000000) + #define __ICCARM_V8 1 +#else + #define __ICCARM_V8 0 +#endif + +#ifndef __ALIGNED + #if __ICCARM_V8 + #define __ALIGNED(x) __attribute__((aligned(x))) + #elif (__VER__ >= 7080000) + /* Needs IAR language extensions */ + #define __ALIGNED(x) __attribute__((aligned(x))) + #else + #warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored. + #define __ALIGNED(x) + #endif +#endif + + +/* Define compiler macros for CPU architecture, used in CMSIS 5. + */ +#if __ARM_ARCH_6M__ || __ARM_ARCH_7M__ || __ARM_ARCH_7EM__ || __ARM_ARCH_8M_BASE__ || __ARM_ARCH_8M_MAIN__ +/* Macros already defined */ +#else + #if defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__) + #define __ARM_ARCH_8M_MAIN__ 1 + #elif defined(__ARM8M_BASELINE__) + #define __ARM_ARCH_8M_BASE__ 1 + #elif defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'M' + #if __ARM_ARCH == 6 + #define __ARM_ARCH_6M__ 1 + #elif __ARM_ARCH == 7 + #if __ARM_FEATURE_DSP + #define __ARM_ARCH_7EM__ 1 + #else + #define __ARM_ARCH_7M__ 1 + #endif + #endif /* __ARM_ARCH */ + #endif /* __ARM_ARCH_PROFILE == 'M' */ +#endif + +/* Alternativ core deduction for older ICCARM's */ +#if !defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_7M__) && !defined(__ARM_ARCH_7EM__) && \ + !defined(__ARM_ARCH_8M_BASE__) && !defined(__ARM_ARCH_8M_MAIN__) + #if defined(__ARM6M__) && (__CORE__ == __ARM6M__) + #define __ARM_ARCH_6M__ 1 + #elif defined(__ARM7M__) && (__CORE__ == __ARM7M__) + #define __ARM_ARCH_7M__ 1 + #elif defined(__ARM7EM__) && (__CORE__ == __ARM7EM__) + #define __ARM_ARCH_7EM__ 1 + #elif defined(__ARM8M_BASELINE__) && (__CORE == __ARM8M_BASELINE__) + #define __ARM_ARCH_8M_BASE__ 1 + #elif defined(__ARM8M_MAINLINE__) && (__CORE == __ARM8M_MAINLINE__) + #define __ARM_ARCH_8M_MAIN__ 1 + #elif defined(__ARM8EM_MAINLINE__) && (__CORE == __ARM8EM_MAINLINE__) + #define __ARM_ARCH_8M_MAIN__ 1 + #else + #error "Unknown target." + #endif +#endif + + + +#if defined(__ARM_ARCH_6M__) && __ARM_ARCH_6M__==1 + #define __IAR_M0_FAMILY 1 +#elif defined(__ARM_ARCH_8M_BASE__) && __ARM_ARCH_8M_BASE__==1 + #define __IAR_M0_FAMILY 1 +#else + #define __IAR_M0_FAMILY 0 +#endif + + +#ifndef __ASM + #define __ASM __asm +#endif + +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif + +#ifndef __INLINE + #define __INLINE inline +#endif + +#ifndef __NO_RETURN + #if __ICCARM_V8 + #define __NO_RETURN __attribute__((__noreturn__)) + #else + #define __NO_RETURN _Pragma("object_attribute=__noreturn") + #endif +#endif + +#ifndef __PACKED + #if __ICCARM_V8 + #define __PACKED __attribute__((packed, aligned(1))) + #else + /* Needs IAR language extensions */ + #define __PACKED __packed + #endif +#endif + +#ifndef __PACKED_STRUCT + #if __ICCARM_V8 + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) + #else + /* Needs IAR language extensions */ + #define __PACKED_STRUCT __packed struct + #endif +#endif + +#ifndef __PACKED_UNION + #if __ICCARM_V8 + #define __PACKED_UNION union __attribute__((packed, aligned(1))) + #else + /* Needs IAR language extensions */ + #define __PACKED_UNION __packed union + #endif +#endif + +#ifndef __RESTRICT + #if __ICCARM_V8 + #define __RESTRICT __restrict + #else + /* Needs IAR language extensions */ + #define __RESTRICT restrict + #endif +#endif + +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline +#endif + +#ifndef __FORCEINLINE + #define __FORCEINLINE _Pragma("inline=forced") +#endif + +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __FORCEINLINE __STATIC_INLINE +#endif + +#ifndef __UNALIGNED_UINT16_READ +#pragma language=save +#pragma language=extended +__IAR_FT uint16_t __iar_uint16_read(void const *ptr) +{ + return *(__packed uint16_t*)(ptr); +} +#pragma language=restore +#define __UNALIGNED_UINT16_READ(PTR) __iar_uint16_read(PTR) +#endif + + +#ifndef __UNALIGNED_UINT16_WRITE +#pragma language=save +#pragma language=extended +__IAR_FT void __iar_uint16_write(void const *ptr, uint16_t val) +{ + *(__packed uint16_t*)(ptr) = val;; +} +#pragma language=restore +#define __UNALIGNED_UINT16_WRITE(PTR,VAL) __iar_uint16_write(PTR,VAL) +#endif + +#ifndef __UNALIGNED_UINT32_READ +#pragma language=save +#pragma language=extended +__IAR_FT uint32_t __iar_uint32_read(void const *ptr) +{ + return *(__packed uint32_t*)(ptr); +} +#pragma language=restore +#define __UNALIGNED_UINT32_READ(PTR) __iar_uint32_read(PTR) +#endif + +#ifndef __UNALIGNED_UINT32_WRITE +#pragma language=save +#pragma language=extended +__IAR_FT void __iar_uint32_write(void const *ptr, uint32_t val) +{ + *(__packed uint32_t*)(ptr) = val;; +} +#pragma language=restore +#define __UNALIGNED_UINT32_WRITE(PTR,VAL) __iar_uint32_write(PTR,VAL) +#endif + +#ifndef __UNALIGNED_UINT32 /* deprecated */ +#pragma language=save +#pragma language=extended +__packed struct __iar_u32 { uint32_t v; }; +#pragma language=restore +#define __UNALIGNED_UINT32(PTR) (((struct __iar_u32 *)(PTR))->v) +#endif + +#ifndef __USED + #if __ICCARM_V8 + #define __USED __attribute__((used)) + #else + #define __USED _Pragma("__root") + #endif +#endif + +#undef __WEAK /* undo the definition from DLib_Defaults.h */ +#ifndef __WEAK + #if __ICCARM_V8 + #define __WEAK __attribute__((weak)) + #else + #define __WEAK _Pragma("__weak") + #endif +#endif + +#ifndef __PROGRAM_START +#define __PROGRAM_START __iar_program_start +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP CSTACK$$Limit +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT CSTACK$$Base +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __vector_table +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE @".intvec" +#endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#ifndef __STACK_SEAL +#define __STACK_SEAL STACKSEAL$$Base +#endif + +#ifndef __TZ_STACK_SEAL_SIZE +#define __TZ_STACK_SEAL_SIZE 8U +#endif + +#ifndef __TZ_STACK_SEAL_VALUE +#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL +#endif + +__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { + *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; +} +#endif + +#ifndef __ICCARM_INTRINSICS_VERSION__ + #define __ICCARM_INTRINSICS_VERSION__ 0 +#endif + +#if __ICCARM_INTRINSICS_VERSION__ == 2 + + #if defined(__CLZ) + #undef __CLZ + #endif + #if defined(__REVSH) + #undef __REVSH + #endif + #if defined(__RBIT) + #undef __RBIT + #endif + #if defined(__SSAT) + #undef __SSAT + #endif + #if defined(__USAT) + #undef __USAT + #endif + + #include "iccarm_builtin.h" + + #define __disable_fault_irq __iar_builtin_disable_fiq + #define __disable_irq __iar_builtin_disable_interrupt + #define __enable_fault_irq __iar_builtin_enable_fiq + #define __enable_irq __iar_builtin_enable_interrupt + #define __arm_rsr __iar_builtin_rsr + #define __arm_wsr __iar_builtin_wsr + + + #define __get_APSR() (__arm_rsr("APSR")) + #define __get_BASEPRI() (__arm_rsr("BASEPRI")) + #define __get_CONTROL() (__arm_rsr("CONTROL")) + #define __get_FAULTMASK() (__arm_rsr("FAULTMASK")) + + #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + #define __get_FPSCR() (__arm_rsr("FPSCR")) + #define __set_FPSCR(VALUE) (__arm_wsr("FPSCR", (VALUE))) + #else + #define __get_FPSCR() ( 0 ) + #define __set_FPSCR(VALUE) ((void)VALUE) + #endif + + #define __get_IPSR() (__arm_rsr("IPSR")) + #define __get_MSP() (__arm_rsr("MSP")) + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + #define __get_MSPLIM() (0U) + #else + #define __get_MSPLIM() (__arm_rsr("MSPLIM")) + #endif + #define __get_PRIMASK() (__arm_rsr("PRIMASK")) + #define __get_PSP() (__arm_rsr("PSP")) + + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + #define __get_PSPLIM() (0U) + #else + #define __get_PSPLIM() (__arm_rsr("PSPLIM")) + #endif + + #define __get_xPSR() (__arm_rsr("xPSR")) + + #define __set_BASEPRI(VALUE) (__arm_wsr("BASEPRI", (VALUE))) + #define __set_BASEPRI_MAX(VALUE) (__arm_wsr("BASEPRI_MAX", (VALUE))) + +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __arm_wsr("CONTROL", control); + __iar_builtin_ISB(); +} + + #define __set_FAULTMASK(VALUE) (__arm_wsr("FAULTMASK", (VALUE))) + #define __set_MSP(VALUE) (__arm_wsr("MSP", (VALUE))) + + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + #define __set_MSPLIM(VALUE) ((void)(VALUE)) + #else + #define __set_MSPLIM(VALUE) (__arm_wsr("MSPLIM", (VALUE))) + #endif + #define __set_PRIMASK(VALUE) (__arm_wsr("PRIMASK", (VALUE))) + #define __set_PSP(VALUE) (__arm_wsr("PSP", (VALUE))) + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + #define __set_PSPLIM(VALUE) ((void)(VALUE)) + #else + #define __set_PSPLIM(VALUE) (__arm_wsr("PSPLIM", (VALUE))) + #endif + + #define __TZ_get_CONTROL_NS() (__arm_rsr("CONTROL_NS")) + +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __arm_wsr("CONTROL_NS", control); + __iar_builtin_ISB(); +} + + #define __TZ_get_PSP_NS() (__arm_rsr("PSP_NS")) + #define __TZ_set_PSP_NS(VALUE) (__arm_wsr("PSP_NS", (VALUE))) + #define __TZ_get_MSP_NS() (__arm_rsr("MSP_NS")) + #define __TZ_set_MSP_NS(VALUE) (__arm_wsr("MSP_NS", (VALUE))) + #define __TZ_get_SP_NS() (__arm_rsr("SP_NS")) + #define __TZ_set_SP_NS(VALUE) (__arm_wsr("SP_NS", (VALUE))) + #define __TZ_get_PRIMASK_NS() (__arm_rsr("PRIMASK_NS")) + #define __TZ_set_PRIMASK_NS(VALUE) (__arm_wsr("PRIMASK_NS", (VALUE))) + #define __TZ_get_BASEPRI_NS() (__arm_rsr("BASEPRI_NS")) + #define __TZ_set_BASEPRI_NS(VALUE) (__arm_wsr("BASEPRI_NS", (VALUE))) + #define __TZ_get_FAULTMASK_NS() (__arm_rsr("FAULTMASK_NS")) + #define __TZ_set_FAULTMASK_NS(VALUE)(__arm_wsr("FAULTMASK_NS", (VALUE))) + + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + #define __TZ_get_PSPLIM_NS() (0U) + #define __TZ_set_PSPLIM_NS(VALUE) ((void)(VALUE)) + #else + #define __TZ_get_PSPLIM_NS() (__arm_rsr("PSPLIM_NS")) + #define __TZ_set_PSPLIM_NS(VALUE) (__arm_wsr("PSPLIM_NS", (VALUE))) + #endif + + #define __TZ_get_MSPLIM_NS() (__arm_rsr("MSPLIM_NS")) + #define __TZ_set_MSPLIM_NS(VALUE) (__arm_wsr("MSPLIM_NS", (VALUE))) + + #define __NOP __iar_builtin_no_operation + + #define __CLZ __iar_builtin_CLZ + #define __CLREX __iar_builtin_CLREX + + #define __DMB __iar_builtin_DMB + #define __DSB __iar_builtin_DSB + #define __ISB __iar_builtin_ISB + + #define __LDREXB __iar_builtin_LDREXB + #define __LDREXH __iar_builtin_LDREXH + #define __LDREXW __iar_builtin_LDREX + + #define __RBIT __iar_builtin_RBIT + #define __REV __iar_builtin_REV + #define __REV16 __iar_builtin_REV16 + + __IAR_FT int16_t __REVSH(int16_t val) + { + return (int16_t) __iar_builtin_REVSH(val); + } + + #define __ROR __iar_builtin_ROR + #define __RRX __iar_builtin_RRX + + #define __SEV __iar_builtin_SEV + + #if !__IAR_M0_FAMILY + #define __SSAT __iar_builtin_SSAT + #endif + + #define __STREXB __iar_builtin_STREXB + #define __STREXH __iar_builtin_STREXH + #define __STREXW __iar_builtin_STREX + + #if !__IAR_M0_FAMILY + #define __USAT __iar_builtin_USAT + #endif + + #define __WFE __iar_builtin_WFE + #define __WFI __iar_builtin_WFI + + #if __ARM_MEDIA__ + #define __SADD8 __iar_builtin_SADD8 + #define __QADD8 __iar_builtin_QADD8 + #define __SHADD8 __iar_builtin_SHADD8 + #define __UADD8 __iar_builtin_UADD8 + #define __UQADD8 __iar_builtin_UQADD8 + #define __UHADD8 __iar_builtin_UHADD8 + #define __SSUB8 __iar_builtin_SSUB8 + #define __QSUB8 __iar_builtin_QSUB8 + #define __SHSUB8 __iar_builtin_SHSUB8 + #define __USUB8 __iar_builtin_USUB8 + #define __UQSUB8 __iar_builtin_UQSUB8 + #define __UHSUB8 __iar_builtin_UHSUB8 + #define __SADD16 __iar_builtin_SADD16 + #define __QADD16 __iar_builtin_QADD16 + #define __SHADD16 __iar_builtin_SHADD16 + #define __UADD16 __iar_builtin_UADD16 + #define __UQADD16 __iar_builtin_UQADD16 + #define __UHADD16 __iar_builtin_UHADD16 + #define __SSUB16 __iar_builtin_SSUB16 + #define __QSUB16 __iar_builtin_QSUB16 + #define __SHSUB16 __iar_builtin_SHSUB16 + #define __USUB16 __iar_builtin_USUB16 + #define __UQSUB16 __iar_builtin_UQSUB16 + #define __UHSUB16 __iar_builtin_UHSUB16 + #define __SASX __iar_builtin_SASX + #define __QASX __iar_builtin_QASX + #define __SHASX __iar_builtin_SHASX + #define __UASX __iar_builtin_UASX + #define __UQASX __iar_builtin_UQASX + #define __UHASX __iar_builtin_UHASX + #define __SSAX __iar_builtin_SSAX + #define __QSAX __iar_builtin_QSAX + #define __SHSAX __iar_builtin_SHSAX + #define __USAX __iar_builtin_USAX + #define __UQSAX __iar_builtin_UQSAX + #define __UHSAX __iar_builtin_UHSAX + #define __USAD8 __iar_builtin_USAD8 + #define __USADA8 __iar_builtin_USADA8 + #define __SSAT16 __iar_builtin_SSAT16 + #define __USAT16 __iar_builtin_USAT16 + #define __UXTB16 __iar_builtin_UXTB16 + #define __UXTAB16 __iar_builtin_UXTAB16 + #define __SXTB16 __iar_builtin_SXTB16 + #define __SXTAB16 __iar_builtin_SXTAB16 + #define __SMUAD __iar_builtin_SMUAD + #define __SMUADX __iar_builtin_SMUADX + #define __SMMLA __iar_builtin_SMMLA + #define __SMLAD __iar_builtin_SMLAD + #define __SMLADX __iar_builtin_SMLADX + #define __SMLALD __iar_builtin_SMLALD + #define __SMLALDX __iar_builtin_SMLALDX + #define __SMUSD __iar_builtin_SMUSD + #define __SMUSDX __iar_builtin_SMUSDX + #define __SMLSD __iar_builtin_SMLSD + #define __SMLSDX __iar_builtin_SMLSDX + #define __SMLSLD __iar_builtin_SMLSLD + #define __SMLSLDX __iar_builtin_SMLSLDX + #define __SEL __iar_builtin_SEL + #define __QADD __iar_builtin_QADD + #define __QSUB __iar_builtin_QSUB + #define __PKHBT __iar_builtin_PKHBT + #define __PKHTB __iar_builtin_PKHTB + #endif + +#else /* __ICCARM_INTRINSICS_VERSION__ == 2 */ + + #if __IAR_M0_FAMILY + /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */ + #define __CLZ __cmsis_iar_clz_not_active + #define __SSAT __cmsis_iar_ssat_not_active + #define __USAT __cmsis_iar_usat_not_active + #define __RBIT __cmsis_iar_rbit_not_active + #define __get_APSR __cmsis_iar_get_APSR_not_active + #endif + + + #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) )) + #define __get_FPSCR __cmsis_iar_get_FPSR_not_active + #define __set_FPSCR __cmsis_iar_set_FPSR_not_active + #endif + + #ifdef __INTRINSICS_INCLUDED + #error intrinsics.h is already included previously! + #endif + + #include + + #if __IAR_M0_FAMILY + /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */ + #undef __CLZ + #undef __SSAT + #undef __USAT + #undef __RBIT + #undef __get_APSR + + __STATIC_INLINE uint8_t __CLZ(uint32_t data) + { + if (data == 0U) { return 32U; } + + uint32_t count = 0U; + uint32_t mask = 0x80000000U; + + while ((data & mask) == 0U) + { + count += 1U; + mask = mask >> 1U; + } + return count; + } + + __STATIC_INLINE uint32_t __RBIT(uint32_t v) + { + uint8_t sc = 31U; + uint32_t r = v; + for (v >>= 1U; v; v >>= 1U) + { + r <<= 1U; + r |= v & 1U; + sc--; + } + return (r << sc); + } + + __STATIC_INLINE uint32_t __get_APSR(void) + { + uint32_t res; + __asm("MRS %0,APSR" : "=r" (res)); + return res; + } + + #endif + + #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) )) + #undef __get_FPSCR + #undef __set_FPSCR + #define __get_FPSCR() (0) + #define __set_FPSCR(VALUE) ((void)VALUE) + #endif + + #pragma diag_suppress=Pe940 + #pragma diag_suppress=Pe177 + + #define __enable_irq __enable_interrupt + #define __disable_irq __disable_interrupt + #define __NOP __no_operation + + #define __get_xPSR __get_PSR + + #if (!defined(__ARM_ARCH_6M__) || __ARM_ARCH_6M__==0) + + __IAR_FT uint32_t __LDREXW(uint32_t volatile *ptr) + { + return __LDREX((unsigned long *)ptr); + } + + __IAR_FT uint32_t __STREXW(uint32_t value, uint32_t volatile *ptr) + { + return __STREX(value, (unsigned long *)ptr); + } + #endif + + + /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */ + #if (__CORTEX_M >= 0x03) + + __IAR_FT uint32_t __RRX(uint32_t value) + { + uint32_t result; + __ASM volatile("RRX %0, %1" : "=r"(result) : "r" (value)); + return(result); + } + + __IAR_FT void __set_BASEPRI_MAX(uint32_t value) + { + __asm volatile("MSR BASEPRI_MAX,%0"::"r" (value)); + } + + + #define __enable_fault_irq __enable_fiq + #define __disable_fault_irq __disable_fiq + + + #endif /* (__CORTEX_M >= 0x03) */ + + __IAR_FT uint32_t __ROR(uint32_t op1, uint32_t op2) + { + return (op1 >> op2) | (op1 << ((sizeof(op1)*8)-op2)); + } + + #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + + __IAR_FT uint32_t __get_MSPLIM(void) + { + uint32_t res; + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + res = 0U; + #else + __asm volatile("MRS %0,MSPLIM" : "=r" (res)); + #endif + return res; + } + + __IAR_FT void __set_MSPLIM(uint32_t value) + { + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)value; + #else + __asm volatile("MSR MSPLIM,%0" :: "r" (value)); + #endif + } + + __IAR_FT uint32_t __get_PSPLIM(void) + { + uint32_t res; + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + res = 0U; + #else + __asm volatile("MRS %0,PSPLIM" : "=r" (res)); + #endif + return res; + } + + __IAR_FT void __set_PSPLIM(uint32_t value) + { + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)value; + #else + __asm volatile("MSR PSPLIM,%0" :: "r" (value)); + #endif + } + + __IAR_FT uint32_t __TZ_get_CONTROL_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,CONTROL_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_CONTROL_NS(uint32_t value) + { + __asm volatile("MSR CONTROL_NS,%0" :: "r" (value)); + __iar_builtin_ISB(); + } + + __IAR_FT uint32_t __TZ_get_PSP_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,PSP_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_PSP_NS(uint32_t value) + { + __asm volatile("MSR PSP_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_MSP_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,MSP_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_MSP_NS(uint32_t value) + { + __asm volatile("MSR MSP_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_SP_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,SP_NS" : "=r" (res)); + return res; + } + __IAR_FT void __TZ_set_SP_NS(uint32_t value) + { + __asm volatile("MSR SP_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_PRIMASK_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,PRIMASK_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_PRIMASK_NS(uint32_t value) + { + __asm volatile("MSR PRIMASK_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_BASEPRI_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,BASEPRI_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_BASEPRI_NS(uint32_t value) + { + __asm volatile("MSR BASEPRI_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_FAULTMASK_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,FAULTMASK_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_FAULTMASK_NS(uint32_t value) + { + __asm volatile("MSR FAULTMASK_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_PSPLIM_NS(void) + { + uint32_t res; + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + res = 0U; + #else + __asm volatile("MRS %0,PSPLIM_NS" : "=r" (res)); + #endif + return res; + } + + __IAR_FT void __TZ_set_PSPLIM_NS(uint32_t value) + { + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)value; + #else + __asm volatile("MSR PSPLIM_NS,%0" :: "r" (value)); + #endif + } + + __IAR_FT uint32_t __TZ_get_MSPLIM_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,MSPLIM_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_MSPLIM_NS(uint32_t value) + { + __asm volatile("MSR MSPLIM_NS,%0" :: "r" (value)); + } + + #endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */ + +#endif /* __ICCARM_INTRINSICS_VERSION__ == 2 */ + +#define __BKPT(value) __asm volatile ("BKPT %0" : : "i"(value)) + +#if __IAR_M0_FAMILY + __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) + { + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; + } + + __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) + { + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; + } +#endif + +#if (__CORTEX_M >= 0x03) /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */ + + __IAR_FT uint8_t __LDRBT(volatile uint8_t *addr) + { + uint32_t res; + __ASM volatile ("LDRBT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); + return ((uint8_t)res); + } + + __IAR_FT uint16_t __LDRHT(volatile uint16_t *addr) + { + uint32_t res; + __ASM volatile ("LDRHT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); + return ((uint16_t)res); + } + + __IAR_FT uint32_t __LDRT(volatile uint32_t *addr) + { + uint32_t res; + __ASM volatile ("LDRT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); + return res; + } + + __IAR_FT void __STRBT(uint8_t value, volatile uint8_t *addr) + { + __ASM volatile ("STRBT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory"); + } + + __IAR_FT void __STRHT(uint16_t value, volatile uint16_t *addr) + { + __ASM volatile ("STRHT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory"); + } + + __IAR_FT void __STRT(uint32_t value, volatile uint32_t *addr) + { + __ASM volatile ("STRT %1, [%0]" : : "r" (addr), "r" (value) : "memory"); + } + +#endif /* (__CORTEX_M >= 0x03) */ + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + + + __IAR_FT uint8_t __LDAB(volatile uint8_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint8_t)res); + } + + __IAR_FT uint16_t __LDAH(volatile uint16_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint16_t)res); + } + + __IAR_FT uint32_t __LDA(volatile uint32_t *ptr) + { + uint32_t res; + __ASM volatile ("LDA %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return res; + } + + __IAR_FT void __STLB(uint8_t value, volatile uint8_t *ptr) + { + __ASM volatile ("STLB %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); + } + + __IAR_FT void __STLH(uint16_t value, volatile uint16_t *ptr) + { + __ASM volatile ("STLH %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); + } + + __IAR_FT void __STL(uint32_t value, volatile uint32_t *ptr) + { + __ASM volatile ("STL %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); + } + + __IAR_FT uint8_t __LDAEXB(volatile uint8_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAEXB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint8_t)res); + } + + __IAR_FT uint16_t __LDAEXH(volatile uint16_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAEXH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint16_t)res); + } + + __IAR_FT uint32_t __LDAEX(volatile uint32_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAEX %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return res; + } + + __IAR_FT uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) + { + uint32_t res; + __ASM volatile ("STLEXB %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); + return res; + } + + __IAR_FT uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) + { + uint32_t res; + __ASM volatile ("STLEXH %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); + return res; + } + + __IAR_FT uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) + { + uint32_t res; + __ASM volatile ("STLEX %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); + return res; + } + +#endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */ + +#undef __IAR_FT +#undef __IAR_M0_FAMILY +#undef __ICCARM_V8 + +#pragma diag_default=Pe940 +#pragma diag_default=Pe177 + +#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) + +#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) + +#endif /* __CMSIS_ICCARM_H__ */ diff --git a/CMSIS/Core/Include/cmsis_version.h b/CMSIS/Core/Include/cmsis_version.h new file mode 100644 index 00000000..8b4765f1 --- /dev/null +++ b/CMSIS/Core/Include/cmsis_version.h @@ -0,0 +1,39 @@ +/**************************************************************************//** + * @file cmsis_version.h + * @brief CMSIS Core(M) Version definitions + * @version V5.0.5 + * @date 02. February 2022 + ******************************************************************************/ +/* + * Copyright (c) 2009-2022 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CMSIS_VERSION_H +#define __CMSIS_VERSION_H + +/* CMSIS Version definitions */ +#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ +#define __CM_CMSIS_VERSION_SUB ( 6U) /*!< [15:0] CMSIS Core(M) sub version */ +#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ + __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ +#endif diff --git a/CMSIS/Core/Include/core_cm3.h b/CMSIS/Core/Include/core_cm3.h new file mode 100644 index 00000000..74fb87e5 --- /dev/null +++ b/CMSIS/Core/Include/core_cm3.h @@ -0,0 +1,1943 @@ +/**************************************************************************//** + * @file core_cm3.h + * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File + * @version V5.1.2 + * @date 04. June 2021 + ******************************************************************************/ +/* + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM3_H_GENERIC +#define __CORE_CM3_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M3 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM3 definitions */ +#define __CM3_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM3_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16U) | \ + __CM3_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (3U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM3_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM3_H_DEPENDANT +#define __CORE_CM3_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM3_REV + #define __CM3_REV 0x0200U + #warning "__CM3_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 1U + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M3 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t _reserved1:8; /*!< bit: 16..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RESERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#if defined (__CM3_REV) && (__CM3_REV < 0x0201U) /* core r2p1 */ +#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#else +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_CFSR_MEMFAULTSR_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ +#if defined (__CM3_REV) && (__CM3_REV >= 0x200U) + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +#else + uint32_t RESERVED1[1U]; +#endif +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#if defined (__CM3_REV) && (__CM3_REV >= 0x200U) +#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ +#endif + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + /* ARM Application Note 321 states that the M3 does not require the architectural barrier */ +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM3_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/CMSIS/Core/Include/core_cm4.h b/CMSIS/Core/Include/core_cm4.h new file mode 100644 index 00000000..e21cd149 --- /dev/null +++ b/CMSIS/Core/Include/core_cm4.h @@ -0,0 +1,2129 @@ +/**************************************************************************//** + * @file core_cm4.h + * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File + * @version V5.1.2 + * @date 04. June 2021 + ******************************************************************************/ +/* + * Copyright (c) 2009-2020 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM4_H_GENERIC +#define __CORE_CM4_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M4 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM4 definitions */ +#define __CM4_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM4_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \ + __CM4_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (4U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM4_H_DEPENDANT +#define __CORE_CM4_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM4_REV + #define __CM4_REV 0x0000U + #warning "__CM4_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 1U + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M4 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RESERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_CFSR_MEMFAULTSR_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/* Media and FP Feature Register 2 Definitions */ + +#define FPU_MVFR2_VFP_Misc_Pos 4U /*!< MVFR2: VFP Misc bits Position */ +#define FPU_MVFR2_VFP_Misc_Msk (0xFUL << FPU_MVFR2_VFP_Misc_Pos) /*!< MVFR2: VFP Misc bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ +#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ +#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */ + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + /* ARM Application Note 321 states that the M4 does not require the architectural barrier */ +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/CMSIS/Core/Include/core_cm7.h b/CMSIS/Core/Include/core_cm7.h new file mode 100644 index 00000000..010506e9 --- /dev/null +++ b/CMSIS/Core/Include/core_cm7.h @@ -0,0 +1,2366 @@ +/**************************************************************************//** + * @file core_cm7.h + * @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File + * @version V5.1.6 + * @date 04. June 2021 + ******************************************************************************/ +/* + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM7_H_GENERIC +#define __CORE_CM7_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M7 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM7 definitions */ +#define __CM7_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM7_CMSIS_VERSION_SUB ( __CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \ + __CM7_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (7U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM7_H_DEPENDANT +#define __CORE_CM7_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM7_REV + #define __CM7_REV 0x0000U + #warning "__CM7_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __ICACHE_PRESENT + #define __ICACHE_PRESENT 0U + #warning "__ICACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DCACHE_PRESENT + #define __DCACHE_PRESENT 0U + #warning "__DCACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DTCM_PRESENT + #define __DTCM_PRESENT 0U + #warning "__DTCM_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 1U + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M7 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RESERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_AFR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[1U]; + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + uint32_t RESERVED3[93U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + __OM uint32_t BPIALL; /*!< Offset: 0x278 ( /W) Branch Predictor Invalidate All */ + uint32_t RESERVED7[5U]; + __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ + __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ + __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ + __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ + __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ + uint32_t RESERVED8[1U]; + __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: Branch prediction enable bit Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: Branch prediction enable bit Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: Instruction cache enable bit Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: Instruction cache enable bit Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: Cache enable bit Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: Cache enable bit Mask */ + +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_CFSR_MEMFAULTSR_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/* Instruction Tightly-Coupled Memory Control Register Definitions */ +#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */ +#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */ + +#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */ +#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */ + +#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */ +#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */ + +#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */ +#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */ + +/* Data Tightly-Coupled Memory Control Register Definitions */ +#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */ +#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */ + +#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */ +#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */ + +#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */ +#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */ + +#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */ +#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */ + +/* AHBP Control Register Definitions */ +#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */ +#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */ + +#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */ +#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */ + +/* L1 Cache Control Register Definitions */ +#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */ +#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */ + +#define SCB_CACR_ECCEN_Pos 1U /*!< \deprecated SCB CACR: ECCEN Position */ +#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< \deprecated SCB CACR: ECCEN Mask */ + +#define SCB_CACR_ECCDIS_Pos 1U /*!< SCB CACR: ECCDIS Position */ +#define SCB_CACR_ECCDIS_Msk (1UL << SCB_CACR_ECCDIS_Pos) /*!< SCB CACR: ECCDIS Mask */ + +#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */ +#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */ + +/* AHBS Control Register Definitions */ +#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */ +#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBSCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ + +#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */ +#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBSCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ + +#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/ +#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBSCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ + +/* Auxiliary Bus Fault Status Register Definitions */ +#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/ +#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */ + +#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/ +#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */ + +#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/ +#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */ + +#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/ +#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */ + +#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/ +#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */ + +#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/ +#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISDYNADD_Pos 26U /*!< ACTLR: DISDYNADD Position */ +#define SCnSCB_ACTLR_DISDYNADD_Msk (1UL << SCnSCB_ACTLR_DISDYNADD_Pos) /*!< ACTLR: DISDYNADD Mask */ + +#define SCnSCB_ACTLR_DISISSCH1_Pos 21U /*!< ACTLR: DISISSCH1 Position */ +#define SCnSCB_ACTLR_DISISSCH1_Msk (0x1FUL << SCnSCB_ACTLR_DISISSCH1_Pos) /*!< ACTLR: DISISSCH1 Mask */ + +#define SCnSCB_ACTLR_DISDI_Pos 16U /*!< ACTLR: DISDI Position */ +#define SCnSCB_ACTLR_DISDI_Msk (0x1FUL << SCnSCB_ACTLR_DISDI_Pos) /*!< ACTLR: DISDI Mask */ + +#define SCnSCB_ACTLR_DISCRITAXIRUR_Pos 15U /*!< ACTLR: DISCRITAXIRUR Position */ +#define SCnSCB_ACTLR_DISCRITAXIRUR_Msk (1UL << SCnSCB_ACTLR_DISCRITAXIRUR_Pos) /*!< ACTLR: DISCRITAXIRUR Mask */ + +#define SCnSCB_ACTLR_DISBTACALLOC_Pos 14U /*!< ACTLR: DISBTACALLOC Position */ +#define SCnSCB_ACTLR_DISBTACALLOC_Msk (1UL << SCnSCB_ACTLR_DISBTACALLOC_Pos) /*!< ACTLR: DISBTACALLOC Mask */ + +#define SCnSCB_ACTLR_DISBTACREAD_Pos 13U /*!< ACTLR: DISBTACREAD Position */ +#define SCnSCB_ACTLR_DISBTACREAD_Msk (1UL << SCnSCB_ACTLR_DISBTACREAD_Pos) /*!< ACTLR: DISBTACREAD Mask */ + +#define SCnSCB_ACTLR_DISITMATBFLUSH_Pos 12U /*!< ACTLR: DISITMATBFLUSH Position */ +#define SCnSCB_ACTLR_DISITMATBFLUSH_Msk (1UL << SCnSCB_ACTLR_DISITMATBFLUSH_Pos) /*!< ACTLR: DISITMATBFLUSH Mask */ + +#define SCnSCB_ACTLR_DISRAMODE_Pos 11U /*!< ACTLR: DISRAMODE Position */ +#define SCnSCB_ACTLR_DISRAMODE_Msk (1UL << SCnSCB_ACTLR_DISRAMODE_Pos) /*!< ACTLR: DISRAMODE Mask */ + +#define SCnSCB_ACTLR_FPEXCODIS_Pos 10U /*!< ACTLR: FPEXCODIS Position */ +#define SCnSCB_ACTLR_FPEXCODIS_Msk (1UL << SCnSCB_ACTLR_FPEXCODIS_Pos) /*!< ACTLR: FPEXCODIS Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED3[981U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( W) Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/* Media and FP Feature Register 2 Definitions */ + +#define FPU_MVFR2_VFP_Misc_Pos 4U /*!< MVFR2: VFP Misc bits Position */ +#define FPU_MVFR2_VFP_Misc_Msk (0xFUL << FPU_MVFR2_VFP_Misc_Pos) /*!< MVFR2: VFP Misc bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ +#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ +#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */ + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + __DSB(); +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = SCB->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + +/*@} end of CMSIS_Core_FpuFunctions */ + + +/* ########################## Cache functions #################################### */ + +#if ((defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)) || \ + (defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U))) +#include "cachel1_armv7.h" +#endif + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/CMSIS/Core/Include/mpu_armv7.h b/CMSIS/Core/Include/mpu_armv7.h new file mode 100644 index 00000000..d9eedf81 --- /dev/null +++ b/CMSIS/Core/Include/mpu_armv7.h @@ -0,0 +1,275 @@ +/****************************************************************************** + * @file mpu_armv7.h + * @brief CMSIS MPU API for Armv7-M MPU + * @version V5.1.2 + * @date 25. May 2020 + ******************************************************************************/ +/* + * Copyright (c) 2017-2020 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef ARM_MPU_ARMV7_H +#define ARM_MPU_ARMV7_H + +#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes +#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes +#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes +#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes +#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes +#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte +#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes +#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes +#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes +#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes +#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes +#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes +#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes +#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes +#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes +#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte +#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes +#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes +#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes +#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes +#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes +#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes +#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes +#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes +#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes +#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte +#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes +#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes + +#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access +#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only +#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only +#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access +#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only +#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access + +/** MPU Region Base Address Register Value +* +* \param Region The region to be configured, number 0 to 15. +* \param BaseAddress The base address for the region. +*/ +#define ARM_MPU_RBAR(Region, BaseAddress) \ + (((BaseAddress) & MPU_RBAR_ADDR_Msk) | \ + ((Region) & MPU_RBAR_REGION_Msk) | \ + (MPU_RBAR_VALID_Msk)) + +/** +* MPU Memory Access Attributes +* +* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. +* \param IsShareable Region is shareable between multiple bus masters. +* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. +* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. +*/ +#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \ + ((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \ + (((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \ + (((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \ + (((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk)) + +/** +* MPU Region Attribute and Size Register Value +* +* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. +* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. +* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_. +* \param SubRegionDisable Sub-region disable field. +* \param Size Region size of the region to be configured, for example 4K, 8K. +*/ +#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \ + ((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \ + (((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \ + (((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \ + (((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \ + (((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \ + (((MPU_RASR_ENABLE_Msk)))) + +/** +* MPU Region Attribute and Size Register Value +* +* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. +* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. +* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. +* \param IsShareable Region is shareable between multiple bus masters. +* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. +* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. +* \param SubRegionDisable Sub-region disable field. +* \param Size Region size of the region to be configured, for example 4K, 8K. +*/ +#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \ + ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size) + +/** +* MPU Memory Access Attribute for strongly ordered memory. +* - TEX: 000b +* - Shareable +* - Non-cacheable +* - Non-bufferable +*/ +#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U) + +/** +* MPU Memory Access Attribute for device memory. +* - TEX: 000b (if shareable) or 010b (if non-shareable) +* - Shareable or non-shareable +* - Non-cacheable +* - Bufferable (if shareable) or non-bufferable (if non-shareable) +* +* \param IsShareable Configures the device memory as shareable or non-shareable. +*/ +#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U)) + +/** +* MPU Memory Access Attribute for normal memory. +* - TEX: 1BBb (reflecting outer cacheability rules) +* - Shareable or non-shareable +* - Cacheable or non-cacheable (reflecting inner cacheability rules) +* - Bufferable or non-bufferable (reflecting inner cacheability rules) +* +* \param OuterCp Configures the outer cache policy. +* \param InnerCp Configures the inner cache policy. +* \param IsShareable Configures the memory as shareable or non-shareable. +*/ +#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) >> 1U), ((InnerCp) & 1U)) + +/** +* MPU Memory Access Attribute non-cacheable policy. +*/ +#define ARM_MPU_CACHEP_NOCACHE 0U + +/** +* MPU Memory Access Attribute write-back, write and read allocate policy. +*/ +#define ARM_MPU_CACHEP_WB_WRA 1U + +/** +* MPU Memory Access Attribute write-through, no write allocate policy. +*/ +#define ARM_MPU_CACHEP_WT_NWA 2U + +/** +* MPU Memory Access Attribute write-back, no write allocate policy. +*/ +#define ARM_MPU_CACHEP_WB_NWA 3U + + +/** +* Struct for a single MPU Region +*/ +typedef struct { + uint32_t RBAR; //!< The region base address register value (RBAR) + uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR +} ARM_MPU_Region_t; + +/** Enable the MPU. +* \param MPU_Control Default access permissions for unconfigured regions. +*/ +__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) +{ + __DMB(); + MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; +#endif + __DSB(); + __ISB(); +} + +/** Disable the MPU. +*/ +__STATIC_INLINE void ARM_MPU_Disable(void) +{ + __DMB(); +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; +#endif + MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; + __DSB(); + __ISB(); +} + +/** Clear and disable the given MPU region. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) +{ + MPU->RNR = rnr; + MPU->RASR = 0U; +} + +/** Configure an MPU region. +* \param rbar Value for RBAR register. +* \param rasr Value for RASR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr) +{ + MPU->RBAR = rbar; + MPU->RASR = rasr; +} + +/** Configure the given MPU region. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rasr Value for RASR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr) +{ + MPU->RNR = rnr; + MPU->RBAR = rbar; + MPU->RASR = rasr; +} + +/** Memcpy with strictly ordered memory access, e.g. used by code in ARM_MPU_Load(). +* \param dst Destination data is copied to. +* \param src Source data is copied from. +* \param len Amount of data words to be copied. +*/ +__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) +{ + uint32_t i; + for (i = 0U; i < len; ++i) + { + dst[i] = src[i]; + } +} + +/** Load the given number of MPU regions from a table. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt) +{ + const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; + while (cnt > MPU_TYPE_RALIASES) { + ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize); + table += MPU_TYPE_RALIASES; + cnt -= MPU_TYPE_RALIASES; + } + ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize); +} + +#endif diff --git a/CMSIS/Core/Include/tz_context.h b/CMSIS/Core/Include/tz_context.h new file mode 100644 index 00000000..0d09749f --- /dev/null +++ b/CMSIS/Core/Include/tz_context.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * @file tz_context.h + * @brief Context Management for Armv8-M TrustZone + * @version V1.0.1 + * @date 10. January 2018 + ******************************************************************************/ +/* + * Copyright (c) 2017-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef TZ_CONTEXT_H +#define TZ_CONTEXT_H + +#include + +#ifndef TZ_MODULEID_T +#define TZ_MODULEID_T +/// \details Data type that identifies secure software modules called by a process. +typedef uint32_t TZ_ModuleId_t; +#endif + +/// \details TZ Memory ID identifies an allocated memory slot. +typedef uint32_t TZ_MemoryId_t; + +/// Initialize secure context memory system +/// \return execution status (1: success, 0: error) +uint32_t TZ_InitContextSystem_S (void); + +/// Allocate context memory for calling secure software modules in TrustZone +/// \param[in] module identifies software modules called from non-secure mode +/// \return value != 0 id TrustZone memory slot identifier +/// \return value 0 no memory available or internal error +TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module); + +/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S +/// \param[in] id TrustZone memory slot identifier +/// \return execution status (1: success, 0: error) +uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id); + +/// Load secure context (called on RTOS thread context switch) +/// \param[in] id TrustZone memory slot identifier +/// \return execution status (1: success, 0: error) +uint32_t TZ_LoadContext_S (TZ_MemoryId_t id); + +/// Store secure context (called on RTOS thread context switch) +/// \param[in] id TrustZone memory slot identifier +/// \return execution status (1: success, 0: error) +uint32_t TZ_StoreContext_S (TZ_MemoryId_t id); + +#endif // TZ_CONTEXT_H diff --git a/CMSIS/LICENSE.txt b/CMSIS/LICENSE.txt new file mode 100644 index 00000000..8dada3ed --- /dev/null +++ b/CMSIS/LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index d40e2f92..c2e54183 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ![GitHub](https://img.shields.io/github/license/vanvught/GD32F207RG-DMX512-RDM) -[![C++ Standard](https://img.shields.io/badge/C%2B%2B-11-blue.svg)](https://img.shields.io/badge/C%2B%2B-11%-blue.svg) +[![C++ Standard](https://img.shields.io/badge/C%2B%2B-20-blue.svg)](https://img.shields.io/badge/C%2B%2B-11%-blue.svg) ![GitHub issues](https://img.shields.io/github/issues-raw/vanvught/GD32F207RG-DMX512-RDM) ![GitHub contributors](https://img.shields.io/github/contributors/vanvught/GD32F207RG-DMX512-RDM) ![GitHub Sponsors](https://img.shields.io/github/sponsors/vanvught) diff --git a/firmware-template-gd32/Artnet.mk b/firmware-template-gd32/Artnet.mk new file mode 100644 index 00000000..7c46203a --- /dev/null +++ b/firmware-template-gd32/Artnet.mk @@ -0,0 +1,5 @@ +ifeq ($(findstring ARTNET_VERSION=4,$(DEFINES)),ARTNET_VERSION=4) + ifeq ($(findstring ARTNET_HAVE_DMXIN,$(DEFINES)),ARTNET_HAVE_DMXIN) + DEFINES+=-DE131_HAVE_DMXIN + endif +endif \ No newline at end of file diff --git a/firmware-template-gd32/Board.mk b/firmware-template-gd32/Board.mk new file mode 100644 index 00000000..bc44a934 --- /dev/null +++ b/firmware-template-gd32/Board.mk @@ -0,0 +1,108 @@ +$(info "Board.mk") + +ifndef BOARD + $(error BOARD is not set) +endif + +ifndef DEFINES + DEFINES= +endif + +ifeq ($(strip $(BOARD)),BOARD_GD32F103RC) + MCU=GD32F103RC + DEFINES+=-DCONFIG_STORE_USE_ROM + DEFINES+=-DNO_EMAC +endif + +ifeq ($(strip $(BOARD)),BOARD_GD32F107RC) + MCU=GD32F107RC + DEFINES+=-DCONFIG_STORE_USE_ROM +endif + +ifeq ($(strip $(BOARD)),BOARD_GD32F207RG) + MCU=GD32F207RG + DEFINES+=-DCONFIG_STORE_USE_SPI +endif + +ifeq ($(strip $(BOARD)),BOARD_GD32F207VC_2) + MCU=GD32F207VC + DEFINES+=-DCONFIG_STORE_USE_ROM + BITBANGING595=1 +endif + +ifeq ($(strip $(BOARD)),BOARD_GD32F207VC_4) + MCU=GD32F207VC + DEFINES+=-DCONFIG_STORE_USE_ROM + BITBANGING595=1 +endif + +ifeq ($(strip $(BOARD)),BOARD_GD32F303RC) + MCU=GD32F303RC + DEFINES+=-DCONFIG_STORE_USE_ROM + DEFINES+=-DNO_EMAC +endif + +ifeq ($(strip $(BOARD)),BOARD_GD32F407RE) + MCU=GD32F407RE + DEFINES+=-DCONFIG_STORE_USE_SPI +endif + +ifeq ($(strip $(BOARD)),BOARD_GD32F450VE) + MCU=GD32F450VE + DEFINES+=-DCONFIG_STORE_USE_RAM + BITBANGING595=1 +endif + +ifeq ($(strip $(BOARD)),BOARD_GD32F450VI) + MCU=GD32F450VI +endif + +ifeq ($(strip $(BOARD)),BOARD_16X4U_PIXEL) + MCU=GD32F450VI +endif + +ifeq ($(strip $(BOARD)),BOARD_GD32F470VG) + MCU=GD32F470VG +endif + +ifeq ($(strip $(BOARD)),BOARD_GD32F207C_EVAL) + MCU=GD32F207VC + DEFINES+=-DCONFIG_STORE_USE_ROM +endif + +ifeq ($(strip $(BOARD)),BOARD_GD32F470Z_EVAL) + MCU=GD32F470ZK + DEFINES+=-DCONFIG_STORE_USE_RAM +endif + +ifeq ($(strip $(BOARD)),BOARD_GD32H759I_EVAL) + MCU=GD32H759IM + DEFINES+=-DCONFIG_STORE_USE_ROM +endif + +ifeq ($(strip $(BOARD)),BOARD_BW_OPIDMX4) + BOARD_DMX=4 + DEFINES+=-DCONFIG_STORE_USE_SPI +endif + +ifeq ($(strip $(BOARD)),BOARD_DMX3) + BOARD_DMX=3 + DEFINES+=-DCONFIG_STORE_USE_SPI +endif + +ifeq ($(strip $(BOARD)),BOARD_DMX4) + DEFINES+=-DCONFIG_STORE_USE_SPI + BOARD_DMX=4 +endif + +ifdef BOARD_DMX + ifeq ($(MCU),GD32F207RG) + else ifeq ($(MCU),GD32F407RE) + else + $(error MCU is not support for BOARD_DMX) + endif +endif + +ifndef MCU + $(error BOARD is not configured) +endif \ No newline at end of file diff --git a/firmware-template-gd32/FreeRTOS.mk b/firmware-template-gd32/FreeRTOS.mk new file mode 100644 index 00000000..92ace9f2 --- /dev/null +++ b/firmware-template-gd32/FreeRTOS.mk @@ -0,0 +1,35 @@ +$(info "FreeRTOS.mk") + +ifndef ARMOPS + $(error ARMOPS is not set) +endif + +ifeq ($(findstring USE_FREE_RTOS,$(DEFINES)), USE_FREE_RTOS) + USEFREERTOS=1 +endif +ifeq ($(findstring USE_FREE_RTOS,$(MAKE_FLAGS)), USE_FREE_RTOS) + USEFREERTOS=1 +endif + +ifdef USEFREERTOS + INCLUDES+=-I../lib-gd32/FreeRTOS/FreeRTOS-Kernel/include + + ifeq ($(findstring cortex-m3,$(ARMOPS)), cortex-m3) + FREE_RTOS_PORTABLE=ARM_CM3 + endif + + ifeq ($(findstring cortex-m4,$(ARMOPS)), cortex-m4) + FREE_RTOS_PORTABLE=ARM_CM4F + endif + + ifeq ($(findstring cortex-m7,$(ARMOPS)), cortex-m7) + FREE_RTOS_PORTABLE=ARM_CM7 + endif + + ifndef FREE_RTOS_PORTABLE + $(error FREE_RTOS_PORTABLE is not set) + endif + + INCLUDES+=-I../lib-gd32/FreeRTOS/FreeRTOS-Kernel/portable/GCC/$(FREE_RTOS_PORTABLE) + DEFINES+=-D$(FREE_RTOS_PORTABLE) +endif \ No newline at end of file diff --git a/firmware-template-gd32/Includes.mk b/firmware-template-gd32/Includes.mk index ce9b5765..71aadc06 100644 --- a/firmware-template-gd32/Includes.mk +++ b/firmware-template-gd32/Includes.mk @@ -1,13 +1,14 @@ -INCLUDES:=-I./include -I../include -I../lib-hal/include -I../lib-debug/include -INCLUDES+=$(addprefix -I,$(EXTRA_INCLUDES)) +$(info "Includes.mk") + +INCLUDES:=-I./include -I../include INCLUDES+=-I../firmware-template-gd32/include INCLUDES+=-I../firmware-template-gd32/template +INCLUDES+=-I../CMSIS/Core/Include INCLUDES+=-I../lib-gd32/${FAMILY}/${FAMILY_UC}_standard_peripheral/Include -INCLUDES+=-I../lib-gd32/${FAMILY}/CMSIS INCLUDES+=-I../lib-gd32/${FAMILY}/CMSIS/GD/${FAMILY_UC}/Include INCLUDES+=-I../lib-gd32/include +INCLUDES+=$(addprefix -I,$(EXTRA_INCLUDES)) -USB_HOST= ifeq ($(findstring ENABLE_USB_HOST,$(DEFINES)), ENABLE_USB_HOST) USB_HOST=1 endif @@ -15,7 +16,6 @@ ifeq ($(findstring ENABLE_USB_HOST,$(MAKE_FLAGS)), ENABLE_USB_HOST) USB_HOST=1 endif -USB_HOST_MSC= ifeq ($(findstring ENABLE_USB_HOST,$(DEFINES)), ENABLE_USB_HOST) USB_HOST_MSC=1 endif @@ -52,6 +52,18 @@ ifeq ($(findstring gd32f4xx,$(FAMILY)), gd32f4xx) endif endif +ifeq ($(findstring gd32h7xx,$(FAMILY)), gd32h7xx) + ifdef USB_HOST + INCLUDES+=-I../lib-gd32/${FAMILY}/GD32H7xx_usbhs_library/driver/Include + INCLUDES+=-I../lib-gd32/${FAMILY}/GD32H7xx_usbhs_library/host/core/Include + INCLUDES+=-I../lib-gd32/${FAMILY}/GD32H7xx_usbhs_library/ustd/common + ifdef USB_HOST_MSC + INCLUDES+=-I../lib-gd32/${FAMILY}/GD32H7xx_usbhs_library/host/class/msc/Include + INCLUDES+=-I../lib-gd32/${FAMILY}/GD32H7xx_usbhs_library/ustd/class/msc + endif + endif +endif + ifdef USB_HOST_MSC - EXTRA_INCLUDES+=../lib-hal/ff12c + INCLUDES+=-I../lib-hal/ff14b/source endif \ No newline at end of file diff --git a/firmware-template-gd32/Mcu.mk b/firmware-template-gd32/Mcu.mk index 63127eec..46058e8f 100644 --- a/firmware-template-gd32/Mcu.mk +++ b/firmware-template-gd32/Mcu.mk @@ -1,7 +1,12 @@ +$(info "Mcu.mk") + ifndef MCU $(error MCU is not set) endif +$(info $$MCU [${MCU}]) + +# Extract upper and lower case versions of MCU name MCU_UC=$(shell echo $(MCU) | rev | cut -c3- | rev ) MCU_LC=$(shell echo $(MCU_UC) | tr A-Z a-z ) @@ -9,6 +14,8 @@ $(info $$MCU [${MCU}]) $(info $$MCU_LC [${MCU_LC}]) $(info $$MCU_UC [${MCU_UC}]) +# Set LINKER, FAMILY, and LINE based on MCU + ifeq ($(strip $(MCU)),GD32F103RC) LINKER=$(FIRMWARE_DIR)gd32f103rc_flash.ld FAMILY=gd32f10x @@ -57,16 +64,76 @@ ifeq ($(strip $(MCU)),GD32F450VI) LINE=gd32f450 endif +ifeq ($(strip $(MCU)),GD32F470VG) + LINKER=$(FIRMWARE_DIR)gd32f470vg_flash.ld + FAMILY=gd32f4xx + LINE=gd32f470 +endif + +ifeq ($(strip $(MCU)),GD32F470ZK) + LINKER=$(FIRMWARE_DIR)gd32f470zk_flash.ld + FAMILY=gd32f4xx + LINE=gd32f470 +endif + +ifeq ($(strip $(MCU)),GD32H759IM) + LINKER=$(FIRMWARE_DIR)gd32h7xx_xM_flash.ld + FAMILY=gd32h7xx + LINE=gd32h759 +endif + ifndef LINKER $(error MCU is not configured) endif +# Common ARM options for Cortex-M3 +ARMOPS_CM3=-mcpu=cortex-m3 -mthumb -mfloat-abi=soft + +# Common ARM options for Cortex-M4 +ARMOPS_CM4=-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -fsingle-precision-constant + +# Common ARM options for Cortex-M7 +ARMOPS_CM7=-mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-d16 -fsingle-precision-constant + +# CMSIS options for FPU present +CMSISOPS_FPU_PRESENT = -D__FPU_PRESENT=1 -DARM_MATH_CM4 + +# Common CMSIS options +CMSISOPS=-D__Vendor_SysTickConfig=0 + +# Set ARM options and CMSIS options based on FAMILY + +ifeq ($(FAMILY),gd32f10x) + ARMOPS=$(ARMOPS_CM3) +endif + +ifeq ($(FAMILY),gd32f20x) + ARMOPS=$(ARMOPS_CM3) +endif + +ifeq ($(FAMILY),gd32f30x) + ARMOPS=$(ARMOPS_CM4) + CMSISOPS+=$(CMSISOPS_FPU_PRESENT) +endif + +ifeq ($(FAMILY),gd32f4xx) + ARMOPS=$(ARMOPS_CM4) + CMSISOPS+=$(CMSISOPS_FPU_PRESENT) +endif + +ifeq ($(FAMILY),gd32h7xx) + ARMOPS=$(ARMOPS_CM7) + CMSISOPS+=-D__FPU_PRESENT=1 -DARM_MATH_CM7 +endif + FAMILY_UC=$(shell echo $(FAMILY) | tr a-w A-W) +FAMILY_UCA=$(shell echo $(FAMILY) | tr a-z A-Z) +LINE_UC=$(shell echo $(LINE) | tr a-z A-Z) + $(info $$FAMILY [${FAMILY}]) $(info $$FAMILY_UC [${FAMILY_UC}]) - -LINE_UC=$(shell echo $(LINE) | tr a-z A-Z) +$(info $$FAMILY_UCA [${FAMILY_UCA}]) $(info $$LINE [${LINE}]) $(info $$LINE_UC [${LINE_UC}]) \ No newline at end of file diff --git a/firmware-template-gd32/Rules.mk b/firmware-template-gd32/Rules.mk index 1ea28ce2..e0e4b61a 100644 --- a/firmware-template-gd32/Rules.mk +++ b/firmware-template-gd32/Rules.mk @@ -9,35 +9,28 @@ LD = $(PREFIX)ld AR = $(PREFIX)ar BOARD?=BOARD_GD32F207RG -ENET_PHY?=DP83848 +ENET_PHY?=RTL8201F -# Output TARGET=gd32f207.bin LIST=$(FAMILY).list MAP=$(FAMILY).map SIZE=$(FAMILY).size BUILD=build_gd32/ -# Input -SOURCE=./ FIRMWARE_DIR=./../firmware-template-gd32/ DEFINES:=$(addprefix -D,$(DEFINES)) -ifeq ($(findstring ARTNET_VERSION=4,$(DEFINES)),ARTNET_VERSION=4) - ifeq ($(findstring ARTNET_HAVE_DMXIN,$(DEFINES)),ARTNET_HAVE_DMXIN) - DEFINES+=-DE131_HAVE_DMXIN - endif -endif - MCU=GD32F207RG +include ../firmware-template-gd32/Board.mk include ../firmware-template-gd32/Mcu.mk include ../firmware-template/libs.mk - -LIBS+=c++ c gd32 - include ../firmware-template-gd32/Includes.mk +include ../firmware-template-gd32/Artnet.mk +include ../firmware-template-gd32/Validate.mk + +LIBS+=gd32 clib # The variable for the libraries include directory LIBINCDIRS:=$(addprefix -I../lib-,$(LIBS)) @@ -53,31 +46,26 @@ LDLIBS:=$(addprefix -l,$(LIBS)) # The variables for the dependency check LIBDEP=$(addprefix ../lib-,$(LIBS)) -$(info $$BOARD [${BOARD}]) -$(info $$ENET_PHY [${ENET_PHY}]) -$(info $$DEFINES [${DEFINES}]) -$(info $$LIBS [${LIBS}]) -$(info $$LIBDEP [${LIBDEP}]) - -COPS=-DBARE_METAL -DGD32 -D$(LINE_UC) -D$(MCU) -D$(BOARD) -DPHY_TYPE=$(ENET_PHY) -COPS+=$(DEFINES) $(MAKE_FLAGS) $(INCLUDES) $(LIBINCDIRS) -COPS+=-Os -mcpu=cortex-m3 -mthumb -COPS+=-nostartfiles -ffreestanding -nostdlib +COPS=-DGD32 -D$(FAMILY_UCA) -D$(LINE_UC) -D$(MCU) -D$(BOARD) -DPHY_TYPE=$(ENET_PHY) +COPS+=$(strip $(DEFINES) $(MAKE_FLAGS) $(INCLUDES) $(LIBINCDIRS)) +COPS+=$(strip $(ARMOPS) $(CMSISOPS)) +COPS+=-Os -nostartfiles -ffreestanding -nostdlib COPS+=-fstack-usage COPS+=-ffunction-sections -fdata-sections -COPS+=-Wall -Werror -Wpedantic -Wextra -Wunused -Wsign-conversion -Wconversion -COPS+=-Wduplicated-cond -Wlogical-op +COPS+=-Wall -Werror -Wpedantic -Wextra -Wunused -Wsign-conversion -Wconversion -Wduplicated-cond -Wlogical-op -CPPOPS=-std=c++11 +CPPOPS=-std=c++20 CPPOPS+=-Wnon-virtual-dtor -Woverloaded-virtual -Wnull-dereference -fno-rtti -fno-exceptions -fno-unwind-tables CPPOPS+=-Wuseless-cast -Wold-style-cast CPPOPS+=-fno-threadsafe-statics -LDOPS=--gc-sections --print-gc-sections +LDOPS=--gc-sections --print-gc-sections --print-memory-usage PLATFORM_LIBGCC+= -L $(shell dirname `$(CC) $(COPS) -print-libgcc-file-name`) +PLATFORM_LIBC+= -L $(shell dirname `$(CC) $(COPS) --print-file-name=libc.a`) $(info $$PLATFORM_LIBGCC [${PLATFORM_LIBGCC}]) +$(info $$PLATFORM_LIBC [${PLATFORM_LIBC}]) C_OBJECTS=$(foreach sdir,$(SRCDIR),$(patsubst $(sdir)/%.c,$(BUILD)$(sdir)/%.o,$(wildcard $(sdir)/*.c))) C_OBJECTS+=$(foreach sdir,$(SRCDIR),$(patsubst $(sdir)/%.cpp,$(BUILD)$(sdir)/%.o,$(wildcard $(sdir)/*.cpp))) @@ -88,13 +76,13 @@ BUILD_DIRS:=$(addprefix $(BUILD),$(SRCDIR)) OBJECTS:=$(ASM_OBJECTS) $(C_OBJECTS) define compile-objects -$(BUILD)$1/%.o: $(SOURCE)$1/%.cpp +$(BUILD)$1/%.o: $1/%.cpp $(CPP) $(COPS) $(CPPOPS) -c $$< -o $$@ -$(BUILD)$1/%.o: $(SOURCE)$1/%.c +$(BUILD)$1/%.o: $1/%.c $(CC) $(COPS) -c $$< -o $$@ -$(BUILD)$1/%.o: $(SOURCE)$1/%.S +$(BUILD)$1/%.o: $1/%.S $(CC) $(COPS) -D__ASSEMBLY__ -c $$< -o $$@ endef @@ -122,7 +110,7 @@ clean: $(LIBDEP) lisdep: $(LIBDEP) $(LIBDEP): - $(MAKE) -f Makefile.GD32 $(MAKECMDGOALS) 'FAMILY=${FAMILY}' 'MCU=${MCU}' 'BOARD=${BOARD}' 'ENET_PHY=${ENET_PHY}' 'MAKE_FLAGS=$(DEFINES)' -C $@ + $(MAKE) -f Makefile.GD32 $(MAKECMDGOALS) 'FAMILY=${FAMILY}' 'BOARD=${BOARD}' 'ENET_PHY=${ENET_PHY}' 'MAKE_FLAGS=$(DEFINES)' -C $@ # # Build bin @@ -131,23 +119,18 @@ $(LIBDEP): $(BUILD_DIRS) : mkdir -p $(BUILD_DIRS) -$(BUILD)startup_$(FAMILY)_cl.o : $(FIRMWARE_DIR)/startup_$(FAMILY)_cl.S - $(AS) $(COPS) -D__ASSEMBLY__ -c $(FIRMWARE_DIR)/startup_$(FAMILY)_cl.S -o $(BUILD)startup_$(FAMILY)_cl.o +$(BUILD)startup_$(LINE).o : $(FIRMWARE_DIR)/startup_$(LINE).S + $(AS) $(COPS) -D__ASSEMBLY__ -c $(FIRMWARE_DIR)/startup_$(LINE).S -o $(BUILD)startup_$(LINE).o $(BUILD)hardfault_handler.o : $(FIRMWARE_DIR)/hardfault_handler.c $(CC) $(COPS) -c $(FIRMWARE_DIR)/hardfault_handler.c -o $(BUILD)hardfault_handler.o -$(BUILD)main.elf: Makefile.GD32 $(LINKER) $(BUILD)startup_$(FAMILY)_cl.o $(BUILD)hardfault_handler.o $(OBJECTS) $(LIBDEP) - $(LD) $(BUILD)startup_$(FAMILY)_cl.o $(BUILD)hardfault_handler.o $(OBJECTS) -Map $(MAP) -T $(LINKER) $(LDOPS) -o $(BUILD)main.elf $(LIBGD32) $(LDLIBS) $(PLATFORM_LIBGCC) -lgcc +$(BUILD)main.elf: Makefile.GD32 $(LINKER) $(BUILD)startup_$(LINE).o $(BUILD)hardfault_handler.o $(OBJECTS) $(LIBDEP) + $(LD) $(BUILD)startup_$(LINE).o $(BUILD)hardfault_handler.o $(OBJECTS) -Map $(MAP) -T $(LINKER) $(LDOPS) -o $(BUILD)main.elf $(LIBGD32) $(LDLIBS) $(PLATFORM_LIBGCC) -lgcc $(PREFIX)objdump -D $(BUILD)main.elf | $(PREFIX)c++filt > $(LIST) - $(PREFIX)size -A -x $(BUILD)main.elf > $(FAMILY).size - $(MAKE) -f Makefile.GD32 calculate_unused_ram SIZE_FILE=$(FAMILY).size LINKER_SCRIPT=$(LINKER) + $(PREFIX)size -A -x $(BUILD)main.elf $(TARGET) : $(BUILD)main.elf - $(PREFIX)objcopy $(BUILD)main.elf -O binary $(TARGET) --remove-section=.sram1* --remove-section=.sram2* + $(PREFIX)objcopy $(BUILD)main.elf -O binary $(TARGET) --remove-section=.tcmsram* --remove-section=.ram* --remove-section=.sram1* --remove-section=.sram2* --remove-section=.ramadd* --remove-section=.bkpsram* $(foreach bdir,$(SRCDIR),$(eval $(call compile-objects,$(bdir)))) - -.PHONY: calculate_unused_ram -calculate_unused_ram: $(FAMILY).size $(LINKER) - @$(FIRMWARE_DIR)/calculate_unused_ram.sh $(FAMILY).size $(LINKER) diff --git a/firmware-template-gd32/Validate.mk b/firmware-template-gd32/Validate.mk new file mode 100644 index 00000000..9531da32 --- /dev/null +++ b/firmware-template-gd32/Validate.mk @@ -0,0 +1,33 @@ +$(info "Validate.mk") +$(info $$MAKE_FLAGS [${MAKE_FLAGS}]) +$(info $$DEFINES [${DEFINES}]) + +FLAGS:=$(MAKE_FLAGS) +ifeq ($(FLAGS),) + FLAGS:=$(DEFINES) +endif + +ifneq (,$(findstring OUTPUT_DMX_SEND,$(FLAGS))$(findstring CONFIG_RDM,$(FLAGS))$(findstring RDM_CONTROLLER,$(FLAGS))$(findstring LTC,$(FLAGS))) + TIMER6_HAVE_IRQ_HANDLER=1 + ifneq (,$(findstring CONFIG_TIMER6_HAVE_NO_IRQ_HANDLER,$(MAKE_FLAGS))) + $(error CONFIG_TIMER6_HAVE_NO_IRQ_HANDLER is set) + endif +endif + +ifndef TIMER6_HAVE_IRQ_HANDLER + DEFINES+=-DCONFIG_TIMER6_HAVE_NO_IRQ_HANDLER +endif + +ifneq ($(findstring USE_FREE_RTOS,$(FLAGS)),USE_FREE_RTOS) + DEFINES+=-DCONFIG_HAL_USE_SYSTICK +else + DEFINES+=-DCONFIG_HAL_USE_SYSTICK # Temporarily need to fix TIMER10 +endif + +ifeq ($(findstring ENABLE_TFTP_SERVER,$(FLAGS)),ENABLE_TFTP_SERVER) + ifneq ($(findstring CONFIG_HAL_USE_SYSTICK,$(FLAGS)),CONFIG_HAL_USE_SYSTICK) + DEFINES+=-DCONFIG_HAL_USE_SYSTICK + endif +endif + +$(info $$DEFINES [${DEFINES}]) diff --git a/firmware-template-gd32/calculate_unused_ram.sh b/firmware-template-gd32/calculate_unused_ram.sh deleted file mode 100755 index 6a96603f..00000000 --- a/firmware-template-gd32/calculate_unused_ram.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -if [ $# -lt 2 ]; then - echo "Usage: $0 " - exit 1 -fi - -size_file="$1" -linker_script="$2" - -used_data=$(grep '.data' "$size_file" | tail -n 1 | awk '{print $2}') -used_bss=$(grep ".bss" "$size_file" | awk '{print $2}') - -total_ram=$(grep "RAM (xrw)" "$linker_script" | awk '{print $NF}' | sed 's/K$//' | awk '{printf "%d", $0 * 1024}') -unused_ram=$(( $(echo $total_ram) - $(echo $used_data) - $(echo $used_bss) )) - -used_stack=$(grep ".stack" "$size_file" | awk '{print $2}') -used_heap=$(grep ".heap" "$size_file" | awk '{print $2}') - -total_ram1=$(grep "RAM1 (xrw)" "$linker_script" | awk '{print $NF}' | sed 's/K$//' | awk '{printf "%d", $0 * 1024}') -unused_ram1=$(( $(echo $total_ram1) - $(echo $used_stack)- $(echo $used_heap) )) - -used_ram2=$(grep ".sram2" "$size_file" | awk '{print $2}') - -total_ram2=$(grep "RAM2 (xrw)" "$linker_script" | awk '{print $NF}' | sed 's/K$//' | awk '{printf "%d", $0 * 1024}') -unused_ram2=$(( $(echo $total_ram2) - $(echo $used_ram2) )) - -cat $1 -echo "SRAM0 $total_ram bytes, Unused: $unused_ram bytes" -echo "SRAM1 $total_ram1 bytes, Unused: $unused_ram1 bytes" -echo "SRAM2 $total_ram2 bytes, Unused: $unused_ram2 bytes" -echo \ No newline at end of file diff --git a/firmware-template-gd32/gd32f207rg_flash.ld b/firmware-template-gd32/gd32f207rg_flash.ld index ac7caeb9..b5e44b19 100644 --- a/firmware-template-gd32/gd32f207rg_flash.ld +++ b/firmware-template-gd32/gd32f207rg_flash.ld @@ -36,31 +36,37 @@ SECTIONS KEEP (*(.fini)) . = ALIGN(4); _etext = .; + } >FLASH - . = ALIGN(8); - + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = ALIGN(4); + } >FLASH + + .preinit_array : + { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array*)) PROVIDE_HIDDEN (__preinit_array_end = .); - + } >FLASH + + .init_array : + { PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array*)) PROVIDE_HIDDEN (__init_array_end = .); - + } >FLASH + + .fini_array : + { PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(.fini_array*)) KEEP (*(SORT(.fini_array.*))) PROVIDE_HIDDEN (__fini_array_end = .); - - } >FLASH - - .rodata : - { - . = ALIGN(4); - *(.rodata) - *(.rodata*) - . = ALIGN(4); } >FLASH _sidata = LOADADDR(.data); @@ -108,8 +114,7 @@ SECTIONS heap_top = .; . = ALIGN(4); } >RAM1 - - + .sram2 : { . = ALIGN(4); @@ -141,5 +146,4 @@ SECTIONS } } - /* input sections */ -GROUP(libgcc.a libc.a) \ No newline at end of file +GROUP(libgcc.a) diff --git a/firmware-template-gd32/hardfault_handler.c b/firmware-template-gd32/hardfault_handler.c index 22abbdf2..039d1f9d 100644 --- a/firmware-template-gd32/hardfault_handler.c +++ b/firmware-template-gd32/hardfault_handler.c @@ -1,5 +1,5 @@ /* - * hardfault_handler.cpp + * hardfault_handler.c */ /** * Using Cortex-M3/M4/M7 Fault Exceptions @@ -50,24 +50,24 @@ void hardfault_handler(unsigned long *hardfault_args, unsigned int lr_value) { printf("[HardFault]\n"); printf("- Stack frame:\n"); - printf(" R0 = %x\n", stacked_r0); - printf(" R1 = %x\n", stacked_r1); - printf(" R2 = %x\n", stacked_r2); - printf(" R3 = %x\n", stacked_r3); - printf(" R12 = %x\n", stacked_r12); - printf(" LR = %x\n", stacked_lr); - printf(" PC = %x\n", stacked_pc); - printf(" PSR = %x\n", stacked_psr); + printf(" R0 = %x\n", (unsigned int) stacked_r0); + printf(" R1 = %x\n", (unsigned int) stacked_r1); + printf(" R2 = %x\n", (unsigned int) stacked_r2); + printf(" R3 = %x\n", (unsigned int) stacked_r3); + printf(" R12 = %x\n", (unsigned int) stacked_r12); + printf(" LR = %x\n", (unsigned int) stacked_lr); + printf(" PC = %x\n", (unsigned int) stacked_pc); + printf(" PSR = %x\n", (unsigned int) stacked_psr); printf("- FSR/FAR:\n"); - printf(" CFSR = %x\n", cfsr); - printf(" HFSR = %x\n", SCB->HFSR); - printf(" DFSR = %x\n", SCB->DFSR); - printf(" AFSR = %x\n", SCB->AFSR); + printf(" CFSR = %x\n", (unsigned int) cfsr); + printf(" HFSR = %x\n", (unsigned int) SCB->HFSR); + printf(" DFSR = %x\n", (unsigned int) SCB->DFSR); + printf(" AFSR = %x\n", (unsigned int) SCB->AFSR); if (cfsr & 0x0080) { - printf(" MMFAR = %x\n", memmanage_fault_address); + printf(" MMFAR = %x\n", (unsigned int) memmanage_fault_address); } if (cfsr & 0x8000) { - printf(" BFAR = %x\n", bus_fault_address); + printf(" BFAR = %x\n", (unsigned int) bus_fault_address); } printf("- Misc\n"); printf(" LR/EXC_RETURN= %x\n", lr_value); diff --git a/firmware-template-gd32/include/software_version.h b/firmware-template-gd32/include/software_version.h index 8c65b31d..c5152360 100644 --- a/firmware-template-gd32/include/software_version.h +++ b/firmware-template-gd32/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.0"; +constexpr char SOFTWARE_VERSION[] = "2.1"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/firmware-template-gd32/lib/Rules.mk b/firmware-template-gd32/lib/Rules.mk index f64fa048..177b8efd 100644 --- a/firmware-template-gd32/lib/Rules.mk +++ b/firmware-template-gd32/lib/Rules.mk @@ -9,49 +9,40 @@ AS = $(CC) LD = $(PREFIX)ld AR = $(PREFIX)ar -FAMILY?=gd32f20x -MCU?=GD32F207RG BOARD?=BOARD_GD32F207RG -ENET_PHY?=DP83848 +ENET_PHY?=RTL8201F -FAMILY:=$(shell echo $(FAMILY) | tr A-Z a-z) -FAMILY_UC=$(shell echo $(FAMILY) | tr a-w A-W) - -$(info $$FAMILY [${FAMILY}]) -$(info $$FAMILY_UC [${FAMILY_UC}]) $(info $$BOARD [${BOARD}]) $(info $$ENET_PHY [${ENET_PHY}]) SRCDIR=src src/gd32 $(EXTRA_SRCDIR) -include ../firmware-template-gd32/Includes.mk - DEFINES:=$(addprefix -D,$(DEFINES)) DEFINES+=-D_TIME_STAMP_YEAR_=$(shell date +"%Y") -D_TIME_STAMP_MONTH_=$(shell date +"%-m") -D_TIME_STAMP_DAY_=$(shell date +"%-d") -ifeq ($(findstring ARTNET_VERSION=4,$(DEFINES)),ARTNET_VERSION=4) - ifeq ($(findstring ARTNET_HAVE_DMXIN,$(DEFINES)),ARTNET_HAVE_DMXIN) - DEFINES+=-DE131_HAVE_DMXIN - endif -endif +MCU=GD32F207RG + +include ../firmware-template-gd32/Board.mk +include ../firmware-template-gd32/Mcu.mk +include ../firmware-template-gd32/Includes.mk +include ../firmware-template-gd32/Artnet.mk +include ../firmware-template-gd32/Validate.mk -COPS=-DBARE_METAL -DGD32 -DGD32F20X_CL -D$(MCU) -D$(BOARD) -DPHY_TYPE=$(ENET_PHY) -COPS+=$(DEFINES) $(MAKE_FLAGS) $(INCLUDES) -COPS+=-Os -mcpu=cortex-m3 -mthumb -COPS+=-nostartfiles -ffreestanding -nostdlib +INCLUDES+=-I../lib-configstore/include -I../lib-device/include -I../lib-display/include -I../lib-flash/include -I../lib-flashcode/include -I../lib-hal/include -I../lib-lightset/include -I../lib-network/include + +COPS=-DGD32 -D$(FAMILY_UCA) -D$(LINE_UC) -D$(MCU) -D$(BOARD) -DPHY_TYPE=$(ENET_PHY) +COPS+=$(strip $(DEFINES)) $(MAKE_FLAGS) $(INCLUDES) +COPS+=$(strip $(ARMOPS) $(CMSISOPS)) +COPS+=-Os -nostartfiles -ffreestanding -nostdlib COPS+=-fstack-usage COPS+=-ffunction-sections -fdata-sections -COPS+=-Wall -Werror -Wpedantic -Wextra -Wunused -Wsign-conversion -Wconversion -COPS+=-Wduplicated-cond -Wlogical-op +COPS+=-Wall -Werror -Wpedantic -Wextra -Wunused -Wsign-conversion -Wconversion -Wduplicated-cond -Wlogical-op -CPPOPS=-std=c++11 +CPPOPS=-std=c++20 CPPOPS+=-Wnon-virtual-dtor -Woverloaded-virtual -Wnull-dereference -fno-rtti -fno-exceptions -fno-unwind-tables CPPOPS+=-Wuseless-cast -Wold-style-cast CPPOPS+=-fno-threadsafe-statics -CURR_DIR:=$(notdir $(patsubst %/,%,$(CURDIR))) -LIB_NAME:=$(patsubst lib-%,%,$(CURR_DIR)) - BUILD=build_gd32/ BUILD_DIRS:=$(addprefix build_gd32/,$(SRCDIR)) $(info $$BUILD_DIRS [${BUILD_DIRS}]) @@ -66,19 +57,22 @@ EXTRA_BUILD_DIRS:=$(addsuffix $(EXTRA_C_DIRECTORIES), $(BUILD)) OBJECTS:=$(strip $(ASM_OBJECTS) $(C_OBJECTS) $(CPP_OBJECTS) $(EXTRA_C_OBJECTS)) -$(info $$OBJECTS [${OBJECTS}]) +CURR_DIR:=$(notdir $(patsubst %/,%,$(CURDIR))) +LIB_NAME:=$(patsubst lib-%,%,$(CURR_DIR)) +TARGET=lib_gd32/lib$(LIB_NAME).a -TARGET=lib_gd32/lib$(LIB_NAME).a +$(info $$DEFINES [${DEFINES}]) +$(info $$MAKE_FLAGS [${MAKE_FLAGS}]) +$(info $$OBJECTS [${OBJECTS}]) $(info $$TARGET [${TARGET}]) -LIST = lib.list - define compile-objects +$(info $1) $(BUILD)$1/%.o: $1/%.c $(CC) $(COPS) -c $$< -o $$@ $(BUILD)$1/%.o: $1/%.cpp - $(CPP) $(COPS) $(CPPOPS) -c $$< -o $$@ + $(CPP) $(COPS) $(CPPOPS) -c $$< -o $$@ $(BUILD)$1/%.o: $1/%.S $(CC) $(COPS) -D__ASSEMBLY__ -c $$< -o $$@ @@ -99,13 +93,13 @@ clean: $(BUILD)%.o: %.c $(CC) $(COPS) -c $< -o $@ - + $(BUILD_DIRS) : mkdir -p $(BUILD_DIRS) mkdir -p lib_gd32 $(TARGET): Makefile.GD32 $(OBJECTS) $(AR) -r $(TARGET) $(OBJECTS) - $(PREFIX)objdump -d $(TARGET) | $(PREFIX)c++filt > lib_gd32/$(LIST) + $(PREFIX)objdump -d $(TARGET) | $(PREFIX)c++filt > lib_gd32/lib.list $(foreach bdir,$(SRCDIR),$(eval $(call compile-objects,$(bdir)))) \ No newline at end of file diff --git a/firmware-template-gd32/startup_gd32f20x_cl.S b/firmware-template-gd32/startup_gd32f20x_cl.S index 851bf0bd..bf95a052 100644 --- a/firmware-template-gd32/startup_gd32f20x_cl.S +++ b/firmware-template-gd32/startup_gd32f20x_cl.S @@ -1,59 +1,93 @@ +/** + * @file startup_gd32f20x_cl.S + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + .syntax unified .cpu cortex-m3 .fpu softvfp .thumb - + .global Default_Handler -.word _sidata +/* Necessary symbols defined in linker script to initialize data */ .word _sdata +.word _sidata .word _edata .word _sbss .word _ebss -.section .text.Reset_Handler +.section .text.Reset_Handler .weak Reset_Handler .type Reset_Handler, %function Reset_Handler: - movs r1, #0 - b DataInit - +/* Copy .data section from FLASH to RAM */ CopyData: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -DataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyData - ldr r2, =_sbss - b Zerobss -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -Zerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss + ldr r1, =_sdata /* Load the start address of .data section (RAM) into r1 */ + ldr r2, =_sidata /* Load the start address of .data section (FLASH) into r2 */ + ldr r3, =_edata /* Load the end address of .data section (RAM) into r3 */ + subs r3, r3, r1 /* Calculate the size of .data section by subtracting start from end */ + beq ZeroBSS /* If size is zero, jump to ZeroBSS */ +CopyDataLoop: + ldrb r4, [r2], #1 /* Load a byte from Flash (source), post-increment r2 by 1 */ + strb r4, [r1], #1 /* Store the byte to RAM (destination), post-increment r1 by 1 */ + subs r3, r3, #1 /* Decrement the remaining byte count by 1 */ + bgt CopyDataLoop /* If there are still bytes left, continue looping */ +/* Initialize .bss section to zero */ +ZeroBSS: + ldr r2, =_sbss /* Load the start address of the .bss section */ + ldr r3, =_ebss /* Load the end address of the .bss section */ + sub r3, r3, r2 /* Calculate bytes count (r3 = (end - start) */ + mov r4, #0 /* Load zero into r4 */ +ZeroBSSLoop: + str r4, [r2], #4 /* Store zero to memory location, increment address */ + subs r3, r3, #4 /* Subtract 4 bytes from the remaining byte count */ + bgt ZeroBSSLoop /* If there are still bytes left, continue looping */ +/* Call stack_debug_init function if in debug mode */ #if defined (DEBUG_STACK) - bl stack_debug_init + bl stack_debug_init /* Branch to stack_debug_init if DEBUG_STACK is defined */ #endif +/* Call SystemInit function to perform system-specific initialization */ bl SystemInit +/* Call static constructors to initialize global objects */ + bl __libc_init_array +/* Call the main function to start the application */ bl main +/* Return from main (in case main returns) */ bx lr +/* NOP to align the code (optional) */ + nop /* No operation; used for code alignment and readability */ + .size Reset_Handler, .-Reset_Handler .section .text.Default_Handler,"ax",%progbits + Default_Handler: Infinite_Loop: b Infinite_Loop - .size Default_Handler, .-Default_Handler + +.size Default_Handler, .-Default_Handler .section .vectors,"a",%progbits .global __gVectors @@ -75,7 +109,6 @@ __gVectors: .word 0 /* Reserved */ .word PendSV_Handler /* 14:PendSV Handler */ .word SysTick_Handler /* 15:SysTick Handler */ - /* External Interrupts */ .word WWDGT_IRQHandler /*16,Window Watchdog Timer*/ .word LVD_IRQHandler /*17,LVD through EXTI Line detect */ @@ -170,6 +203,12 @@ __gVectors: .size __gVectors, . - __gVectors +/******************************************************************************* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +*******************************************************************************/ + .weak NMI_Handler .thumb_set NMI_Handler,Default_Handler diff --git a/firmware-template/libs.mk b/firmware-template/libs.mk index 6e68aeb2..1f0b26c5 100755 --- a/firmware-template/libs.mk +++ b/firmware-template/libs.mk @@ -27,34 +27,29 @@ ifeq ($(findstring NODE_PP,$(DEFINES)),NODE_PP) LIBS+=pp endif -RDM= +ifeq ($(findstring NODE_SHOWFILE,$(DEFINES)),NODE_SHOWFILE) + LIBS+=showfile osc +endif ifeq ($(findstring RDM_CONTROLLER,$(DEFINES)),RDM_CONTROLLER) RDM=1 - ifeq ($(findstring NO_EMAC,$(DEFINES)),NO_EMAC) - else - LIBS+=rdmdiscovery - endif + DMX=1 endif ifeq ($(findstring RDM_RESPONDER,$(DEFINES)),RDM_RESPONDER) - ifneq ($(findstring rdmresponder,$(LIBS)),rdmresponder) - LIBS+=rdmresponder - endif ifneq ($(findstring rdmsensor,$(LIBS)),rdmsensor) - LIBS+=rdmsensor device - endif - ifneq ($(findstring rdmsubdevice,$(LIBS)),rdmsubdevice) - LIBS+=rdmsubdevice + LIBS+=rdmsensor endif - LIBS+=dmxreceiver dmx RDM=1 + ifneq ($(findstring NODE_ARTNET,$(DEFINES)),NODE_ARTNET) + ifeq ($(findstring OUTPUT_DMX_,$(DEFINES)),OUTPUT_DMX_) + DMX=1 + endif + endif endif ifeq ($(findstring NODE_RDMNET_LLRP_ONLY,$(DEFINES)),NODE_RDMNET_LLRP_ONLY) - ifneq ($(findstring rdmnet,$(LIBS)),rdmnet) - LIBS+=rdmnet - endif + RDM=1 ifneq ($(findstring e131,$(LIBS)),e131) LIBS+=e131 endif @@ -64,23 +59,23 @@ ifeq ($(findstring NODE_RDMNET_LLRP_ONLY,$(DEFINES)),NODE_RDMNET_LLRP_ONLY) ifneq ($(findstring rdmsubdevice,$(LIBS)),rdmsubdevice) LIBS+=rdmsubdevice endif - RDM=1 endif -ifdef RDM - LIBS+=rdm +ifeq ($(findstring OUTPUT_DMX_MONITOR,$(DEFINES)),OUTPUT_DMX_MONITOR) + LIBS+=dmxmonitor endif -ifeq ($(findstring e131,$(LIBS)),e131) - LIBS+=uuid +ifeq ($(findstring OUTPUT_DMX_SEND,$(DEFINES)),OUTPUT_DMX_SEND) + LIBS+= + DMX=1 endif -ifeq ($(findstring OUTPUT_DMX_MONITOR,$(DEFINES)),OUTPUT_DMX_MONITOR) - LIBS+=dmxmonitor +ifdef RDM + LIBS+=rdm endif -ifeq ($(findstring OUTPUT_DMX_SEND,$(DEFINES)),OUTPUT_DMX_SEND) - LIBS+=dmxsend dmx +ifdef DMX + LIBS+=dmx endif ifeq ($(findstring OUTPUT_DDP_PIXEL_MULTI,$(DEFINES)),OUTPUT_DDP_PIXEL_MULTI) @@ -99,12 +94,12 @@ ifeq ($(findstring OUTPUT_DDP_PIXEL,$(DEFINES)),OUTPUT_DDP_PIXEL) LIBS+=ws28xx endif -LIBS+=configstore flashcode network lightset +LIBS+=configstore flashcode network ifeq ($(findstring DISPLAY_UDF,$(DEFINES)),DISPLAY_UDF) LIBS+=displayudf endif -LIBS+=flash properties display hal +LIBS+=lightset flash properties display device hal -$(info $$LIBS [${LIBS}]) \ No newline at end of file +$(info $$LIBS [${LIBS}]) diff --git a/gd32_emac_artnet_dmx_multi/.cproject b/gd32_emac_artnet_dmx_multi/.cproject index 68eb245d..d74891b4 100644 --- a/gd32_emac_artnet_dmx_multi/.cproject +++ b/gd32_emac_artnet_dmx_multi/.cproject @@ -14,7 +14,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/gd32_emac_artnet_dmx_multi/Common.mk b/gd32_emac_artnet_dmx_multi/Common.mk new file mode 100644 index 00000000..13051062 --- /dev/null +++ b/gd32_emac_artnet_dmx_multi/Common.mk @@ -0,0 +1,19 @@ +DEFINES+=NODE_ARTNET_MULTI ARTNET_VERSION=4 +DEFINES+=ARTNET_HAVE_DMXIN +DEFINES+=ARTNET_HAVE_FAILSAFE_RECORD + +DEFINES+=OUTPUT_DMX_SEND_MULTI +DEFINES+=OUTPUT_HAVE_STYLESWITCH + +DEFINES+=RDM_CONTROLLER + +DEFINES+=CONFIG_STORE_USE_SPI + +DEFINES+=RTL8201F_LED1_LINK_ALL + +DEFINES+=DISPLAY_UDF + +DEFINES+=ENABLE_HTTPD ENABLE_CONTENT + +DEFINES+=DISABLE_RTC +DEFINES+=DISABLE_FS \ No newline at end of file diff --git a/gd32_emac_artnet_dmx_multi/Makefile-bw-softuart0.GD32 b/gd32_emac_artnet_dmx_multi/Makefile-bw-softuart0.GD32 index a11187cf..1598b18e 100644 --- a/gd32_emac_artnet_dmx_multi/Makefile-bw-softuart0.GD32 +++ b/gd32_emac_artnet_dmx_multi/Makefile-bw-softuart0.GD32 @@ -1,34 +1,21 @@ BOARD=BOARD_BW_OPIDMX4 -DEFINES =NODE_ARTNET_MULTI ARTNET_VERSION=4 LIGHTSET_PORTS=4 -DEFINES+=ARTNET_PAGE_SIZE=1 -DEFINES+=ARTNET_HAVE_DMXIN -DEFINES+=ARTNET_HAVE_FAILSAFE_RECORD - -DEFINES+=RDM_CONTROLLER - -DEFINES+=OUTPUT_DMX_SEND_MULTI -DEFINES+=OUTPUT_HAVE_STYLESWITCH +DEFINES=LIGHTSET_PORTS=4 DEFINES+=ENET_RXBUF_NUM=16 ENET_TXBUF_NUM=4 -DEFINES+=DISPLAY_UDF - -DEFINES+=ENABLE_HTTPD ENABLE_CONTENT - -DEFINES+=CONFIG_STORE_USE_SPI +# DEFINES+=CONFIG_USE_SOFTUART0 -DEFINES+=DISABLE_RTC -DEFINES+=DISABLE_FS - +DEFINES+=DEBUG_STACK DEFINES+=NDEBUG LIBS= SRCDIR=firmware lib +include Common.mk include ../firmware-template-gd32/Rules.mk prerequisites: diff --git a/gd32_emac_artnet_dmx_multi/Makefile-bw.GD32 b/gd32_emac_artnet_dmx_multi/Makefile-bw.GD32 index cd358a06..c0eec0f1 100644 --- a/gd32_emac_artnet_dmx_multi/Makefile-bw.GD32 +++ b/gd32_emac_artnet_dmx_multi/Makefile-bw.GD32 @@ -1,34 +1,21 @@ BOARD=BOARD_BW_OPIDMX4 -DEFINES =NODE_ARTNET_MULTI ARTNET_VERSION=4 LIGHTSET_PORTS=4 -DEFINES+=ARTNET_PAGE_SIZE=1 -DEFINES+=ARTNET_HAVE_DMXIN -DEFINES+=ARTNET_HAVE_FAILSAFE_RECORD - -DEFINES+=RDM_CONTROLLER - -DEFINES+=OUTPUT_DMX_SEND_MULTI -DEFINES+=OUTPUT_HAVE_STYLESWITCH +DEFINES=LIGHTSET_PORTS=4 DEFINES+=ENET_RXBUF_NUM=16 ENET_TXBUF_NUM=4 -DEFINES+=DISPLAY_UDF - -DEFINES+=ENABLE_HTTPD ENABLE_CONTENT - -DEFINES+=CONFIG_STORE_USE_SPI +# DEFINES+=CONSOLE_NULL -DEFINES+=DISABLE_RTC -DEFINES+=DISABLE_FS - +DEFINES+=DEBUG_STACK DEFINES+=NDEBUG LIBS= SRCDIR=firmware lib +include Common.mk include ../firmware-template-gd32/Rules.mk prerequisites: diff --git a/gd32_emac_artnet_dmx_multi/Makefile-dmx3.GD32 b/gd32_emac_artnet_dmx_multi/Makefile-dmx3.GD32 index 9ff19d78..78ce4ffa 100644 --- a/gd32_emac_artnet_dmx_multi/Makefile-dmx3.GD32 +++ b/gd32_emac_artnet_dmx_multi/Makefile-dmx3.GD32 @@ -1,32 +1,21 @@ BOARD=BOARD_DMX3 -DEFINES =NODE_ARTNET_MULTI ARTNET_VERSION=4 LIGHTSET_PORTS=3 -DEFINES+=ARTNET_PAGE_SIZE=1 -DEFINES+=ARTNET_HAVE_DMXIN -DEFINES+=ARTNET_HAVE_FAILSAFE_RECORD - -DEFINES+=RDM_CONTROLLER - -DEFINES+=OUTPUT_DMX_SEND_MULTI -DEFINES+=OUTPUT_HAVE_STYLESWITCH +DEFINES=LIGHTSET_PORTS=3 DEFINES+=ENET_RXBUF_NUM=16 ENET_TXBUF_NUM=4 -DEFINES+=DISPLAY_UDF - -DEFINES+=ENABLE_HTTPD ENABLE_CONTENT - -DEFINES+=CONFIG_STORE_USE_SPI +# -DEFINES+=DISABLE_RTC -DEFINES+=DISABLE_FS +# +DEFINES+=DEBUG_STACK DEFINES+=NDEBUG LIBS= SRCDIR=firmware lib +include Common.mk include ../firmware-template-gd32/Rules.mk prerequisites: diff --git a/gd32_emac_artnet_dmx_multi/Makefile-dmx4-softuart0.GD32 b/gd32_emac_artnet_dmx_multi/Makefile-dmx4-softuart0.GD32 index 77a4601f..28dab1bf 100644 --- a/gd32_emac_artnet_dmx_multi/Makefile-dmx4-softuart0.GD32 +++ b/gd32_emac_artnet_dmx_multi/Makefile-dmx4-softuart0.GD32 @@ -1,35 +1,21 @@ BOARD=BOARD_DMX4 -DEFINES =NODE_ARTNET_MULTI ARTNET_VERSION=4 LIGHTSET_PORTS=4 -DEFINES+=ARTNET_PAGE_SIZE=1 -DEFINES+=ARTNET_HAVE_DMXIN -DEFINES+=ARTNET_HAVE_FAILSAFE_RECORD - -DEFINES+=RDM_CONTROLLER - -DEFINES+=OUTPUT_DMX_SEND_MULTI -DEFINES+=OUTPUT_HAVE_STYLESWITCH +DEFINES=LIGHTSET_PORTS=4 DEFINES+=ENET_RXBUF_NUM=16 ENET_TXBUF_NUM=4 -DEFINES+=DISPLAY_UDF - -DEFINES+=ENABLE_HTTPD ENABLE_CONTENT +DEFINES+=LEDPANEL_595_COUNT=2 -DEFINES+=CONFIG_STORE_USE_SPI DEFINES+=CONFIG_USE_SOFTUART0 -DEFINES+=DISABLE_RTC -DEFINES+=DISABLE_FS - DEFINES+=DEBUG_STACK - DEFINES+=NDEBUG LIBS= SRCDIR=firmware lib +include Common.mk include ../firmware-template-gd32/Rules.mk prerequisites: diff --git a/gd32_emac_artnet_dmx_multi/Makefile-dmx4.GD32 b/gd32_emac_artnet_dmx_multi/Makefile-dmx4.GD32 index 8b1f27b6..8cb4d0ac 100644 --- a/gd32_emac_artnet_dmx_multi/Makefile-dmx4.GD32 +++ b/gd32_emac_artnet_dmx_multi/Makefile-dmx4.GD32 @@ -1,36 +1,21 @@ BOARD=BOARD_DMX4 -DEFINES =NODE_ARTNET_MULTI ARTNET_VERSION=4 LIGHTSET_PORTS=4 -DEFINES+=ARTNET_PAGE_SIZE=1 -DEFINES+=ARTNET_HAVE_DMXIN -DEFINES+=ARTNET_HAVE_FAILSAFE_RECORD - -DEFINES+=RDM_CONTROLLER - -DEFINES+=OUTPUT_DMX_SEND_MULTI -DEFINES+=OUTPUT_HAVE_STYLESWITCH +DEFINES=LIGHTSET_PORTS=4 DEFINES+=ENET_RXBUF_NUM=16 ENET_TXBUF_NUM=4 -DEFINES+=DISPLAY_UDF - -DEFINES+=ENABLE_HTTPD ENABLE_CONTENT - -DEFINES+=CONFIG_STORE_USE_SPI +DEFINES+=LEDPANEL_595_COUNT=2 DEFINES+=CONSOLE_NULL -DEFINES+=DISABLE_RTC -DEFINES+=DISABLE_FS - DEFINES+=DEBUG_STACK - DEFINES+=NDEBUG LIBS= SRCDIR=firmware lib +include Common.mk include ../firmware-template-gd32/Rules.mk prerequisites: diff --git a/gd32_emac_artnet_dmx_multi/Makefile.GD32 b/gd32_emac_artnet_dmx_multi/Makefile.GD32 index e0d4c574..32823fe5 100644 --- a/gd32_emac_artnet_dmx_multi/Makefile.GD32 +++ b/gd32_emac_artnet_dmx_multi/Makefile.GD32 @@ -1,31 +1,21 @@ BOARD=BOARD_GD32F207RG -DEFINES =NODE_ARTNET_MULTI ARTNET_VERSION=4 LIGHTSET_PORTS=2 -DEFINES+=ARTNET_HAVE_DMXIN -DEFINES+=ARTNET_HAVE_FAILSAFE_RECORD - -DEFINES+=RDM_CONTROLLER - -DEFINES+=OUTPUT_DMX_SEND_MULTI -DEFINES+=OUTPUT_HAVE_STYLESWITCH +DEFINES=LIGHTSET_PORTS=2 DEFINES+=ENET_RXBUF_NUM=8 ENET_TXBUF_NUM=4 -DEFINES+=DISPLAY_UDF - -DEFINES+=ENABLE_HTTPD ENABLE_CONTENT - -DEFINES+=CONFIG_STORE_USE_SPI +# -DEFINES+=DISABLE_RTC -DEFINES+=DISABLE_FS +# +DEFINES+=DEBUG_STACK DEFINES+=NDEBUG LIBS= SRCDIR=firmware lib +include Common.mk include ../firmware-template-gd32/Rules.mk prerequisites: diff --git a/gd32_emac_artnet_dmx_multi/do-tftp.sh b/gd32_emac_artnet_dmx_multi/do-tftp.sh index 8066e8dc..66bc49c3 100755 --- a/gd32_emac_artnet_dmx_multi/do-tftp.sh +++ b/gd32_emac_artnet_dmx_multi/do-tftp.sh @@ -11,6 +11,15 @@ echo '!tftp#1' | udp_send $1 ON_LINE=$(echo '?tftp#' | udp_send $1 ) || true echo [$ON_LINE] +while [ "$ON_LINE" == "" ] + do + sleep 1 + echo '!tftp#1' | udp_send $1 + ON_LINE=$(echo '?tftp#' | udp_send $1 ) || true +done + +echo [$ON_LINE] + while [ "$ON_LINE" == "tftp:Off" ] do sleep 1 @@ -18,6 +27,8 @@ while [ "$ON_LINE" == "tftp:Off" ] ON_LINE=$(echo '?tftp#' | udp_send $1 ) || true done +echo [$ON_LINE] + sleep 1 echo -e "Rebooting..." echo '?reboot##' | udp_send $1 @@ -30,7 +41,26 @@ while [ "$ON_LINE" == "" ] done echo '!tftp#1' | udp_send $1 -echo '?tftp#' | udp_send $1 +ON_LINE=$(echo '?tftp#' | udp_send $1 ) || true +echo [$ON_LINE] + +while [ "$ON_LINE" == "" ] + do + sleep 1 + echo '!tftp#1' | udp_send $1 + ON_LINE=$(echo '?tftp#' | udp_send $1 ) || true +done + +echo [$ON_LINE] + +while [ "$ON_LINE" == "tftp:Off" ] + do + sleep 1 + echo '!tftp#1' | udp_send $1 + ON_LINE=$(echo '?tftp#' | udp_send $1 ) || true +done + +echo [$ON_LINE] tftp $1 << -EOF binary @@ -39,9 +69,27 @@ quit -EOF echo '!tftp#0' | udp_send $1 -sleep 1 -echo '?tftp#' | udp_send $1 -sleep 2 +ON_LINE=$(echo '?tftp#' | udp_send $1 ) || true +echo [$ON_LINE] + +while [ "$ON_LINE" == "" ] + do + sleep 1 + echo '!tftp#0' | udp_send $1 + ON_LINE=$(echo '?tftp#' | udp_send $1 ) || true +done + +echo [$ON_LINE] + +while [ "$ON_LINE" == "tftp:On" ] + do + sleep 1 + echo '!tftp#0' | udp_send $1 + ON_LINE=$(echo '?tftp#' | udp_send $1 ) || true +done + +echo [$ON_LINE] + echo -e "Rebooting..." echo '?reboot##' | udp_send $1 diff --git a/gd32_emac_artnet_dmx_multi/firmware/main.cpp b/gd32_emac_artnet_dmx_multi/firmware/main.cpp index 0439baa4..842d13ed 100644 --- a/gd32_emac_artnet_dmx_multi/firmware/main.cpp +++ b/gd32_emac_artnet_dmx_multi/firmware/main.cpp @@ -2,7 +2,7 @@ * @file main.cpp * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,16 +30,15 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" -#if defined (ENABLE_HTTPD) -# include "httpd/httpd.h" +#if defined (ENABLE_NTP_CLIENT) +# include "net/apps/ntpclient.h" #endif #include "displayudf.h" #include "displayudfparams.h" #include "displayhandler.h" -#include "display_timeout.h" #include "artnetnode.h" #include "artnetparams.h" @@ -51,83 +50,66 @@ #include "rdmdeviceparams.h" #include "dmxconfigudp.h" +#if defined (NODE_SHOWFILE) +# include "showfile.h" +# include "showfileparams.h" +#endif + #include "remoteconfig.h" #include "remoteconfigparams.h" #include "configstore.h" -#include "storeartnet.h" -#include "storedisplayudf.h" -#include "storedmxsend.h" -#include "storenetwork.h" -#include "storerdmdevice.h" -#include "storeremoteconfig.h" #include "firmwareversion.h" #include "software_version.h" -static constexpr uint32_t DMXPORT_OFFSET = 0; +namespace artnetnode { +namespace configstore { +uint32_t DMXPORT_OFFSET = 0; +} // namespace configstore +} // namespace artnetnode void Hardware::RebootHandler() { Dmx::Get()->Blackout(); ArtNetNode::Get()->Stop(); } -void main() { +int main() { Hardware hw; DisplayUdf display; ConfigStore configStore; - display.TextStatus(NetworkConst::MSG_NETWORK_INIT, Display7SegmentMessage::INFO_NETWORK_INIT, CONSOLE_YELLOW); - StoreNetwork storeNetwork; - Network nw(&storeNetwork); - display.TextStatus(NetworkConst::MSG_NETWORK_STARTED, Display7SegmentMessage::INFO_NONE, CONSOLE_GREEN); + display.TextStatus(NetworkConst::MSG_NETWORK_INIT, CONSOLE_YELLOW); + Network nw; + MDNS mDns; + display.TextStatus(NetworkConst::MSG_NETWORK_STARTED, CONSOLE_GREEN); FirmwareVersion fw(SOFTWARE_VERSION, __DATE__, __TIME__); fw.Print("Art-Net 4 DMX/RDM controller {" STR(LIGHTSET_PORTS) " Universes}"); - nw.Print(); - - display.TextStatus(NetworkConst::MSG_MDNS_CONFIG, Display7SegmentMessage::INFO_MDNS_CONFIG, CONSOLE_YELLOW); - - MDNS mDns; - mDns.AddServiceRecord(nullptr, mdns::Services::CONFIG, "node=Art-Net 4 DMX/RDM"); -#if defined (ENABLE_HTTPD) - mDns.AddServiceRecord(nullptr, mdns::Services::HTTP); -#endif - mDns.Print(); -#if defined (ENABLE_HTTPD) - HttpDaemon httpDaemon; +#if defined (ENABLE_NTP_CLIENT) + NtpClient ntpClient; + ntpClient.Start(); + ntpClient.Print(); #endif - display.TextStatus(ArtNetMsgConst::PARAMS, Display7SegmentMessage::INFO_NODE_PARMAMS, CONSOLE_YELLOW); - ArtNetNode node; - StoreArtNet storeArtNet(DMXPORT_OFFSET); - node.SetArtNetStore(&storeArtNet); - - ArtNetParams artnetParams(&storeArtNet); - - if (artnetParams.Load()) { - artnetParams.Dump(); - artnetParams.Set(DMXPORT_OFFSET); - } + ArtNetParams artnetParams; + artnetParams.Load(); + artnetParams.Set(); for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { node.SetUniverse(nPortIndex, artnetParams.GetDirection(nPortIndex), artnetParams.GetUniverse(nPortIndex)); } - StoreDmxSend storeDmxSend; - DmxParams dmxparams(&storeDmxSend); - Dmx dmx; - if (dmxparams.Load()) { - dmxparams.Dump(); - dmxparams.Set(&dmx); - } + DmxParams dmxparams; + dmxparams.Load(); + dmxparams.Set(&dmx); - for (uint32_t nPortIndex = DMXPORT_OFFSET; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { - const auto nDmxPortIndex = nPortIndex - DMXPORT_OFFSET; + for (uint32_t nPortIndex = artnetnode::configstore::DMXPORT_OFFSET; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { + const auto nDmxPortIndex = nPortIndex - artnetnode::configstore::DMXPORT_OFFSET; const auto portDirection = (node.GetPortDirection(nPortIndex) == lightset::PortDir::OUTPUT ? dmx::PortDirection::OUTP : dmx::PortDirection::INP); dmx.SetPortDirection(nDmxPortIndex, portDirection , false); } @@ -137,33 +119,26 @@ void main() { node.SetOutput(&dmxSend); - DmxConfigUdp dmxConfigUdp; - - StoreRDMDevice storeRdmDevice; - + RDMDeviceParams rdmDeviceParams; ArtNetRdmController artNetRdmController; - if (artnetParams.IsRdm()) { - RDMDeviceParams rdmDeviceParams(&storeRdmDevice); + rdmDeviceParams.Load(); + rdmDeviceParams.Set(&artNetRdmController); - if (rdmDeviceParams.Load()) { - rdmDeviceParams.Dump(); - rdmDeviceParams.Set(&artNetRdmController); - } + artNetRdmController.Init(); + artNetRdmController.Print(); - artNetRdmController.Init(); - artNetRdmController.Print(); + node.SetRdmController(&artNetRdmController, artnetParams.IsRdm()); - display.TextStatus(ArtNetMsgConst::RDM_RUN, Display7SegmentMessage::INFO_RDM_RUN, CONSOLE_YELLOW); +#if defined (NODE_SHOWFILE) + ShowFile showFile; - for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { - if (node.GetRdm(nPortIndex) && (node.GetPortDirection(nPortIndex) == lightset::PortDir::OUTPUT)) { - artNetRdmController.Full(nPortIndex); - } - } + ShowFileParams showFileParams; + showFileParams.Load(); + showFileParams.Set(); - node.SetRdmHandler(&artNetRdmController); - } + showFile.Print(); +#endif node.Print(); @@ -175,34 +150,29 @@ void main() { display.Set(4, displayudf::Labels::UNIVERSE_PORT_A); display.Set(5, displayudf::Labels::UNIVERSE_PORT_B); - StoreDisplayUdf storeDisplayUdf; - DisplayUdfParams displayUdfParams(&storeDisplayUdf); + DisplayUdfParams displayUdfParams; - if (displayUdfParams.Load()) { - displayUdfParams.Dump(); - displayUdfParams.Set(&display); - } + displayUdfParams.Load(); + displayUdfParams.Set(&display); - display.Show(&node); + display.Show(); RemoteConfig remoteConfig(remoteconfig::Node::ARTNET, artnetParams.IsRdm() ? remoteconfig::Output::RDM : remoteconfig::Output::DMX, nActivePorts); - StoreRemoteConfig storeRemoteConfig; - RemoteConfigParams remoteConfigParams(&storeRemoteConfig); - - if (remoteConfigParams.Load()) { - remoteConfigParams.Dump(); - remoteConfigParams.Set(&remoteConfig); - } + RemoteConfigParams remoteConfigParams; + remoteConfigParams.Load(); + remoteConfigParams.Set(&remoteConfig); while (configStore.Flash()) ; - display.TextStatus(ArtNetMsgConst::START, Display7SegmentMessage::INFO_NODE_START, CONSOLE_YELLOW); + mDns.Print(); + + display.TextStatus(ArtNetMsgConst::START, CONSOLE_YELLOW); node.Start(); - display.TextStatus(ArtNetMsgConst::STARTED, Display7SegmentMessage::INFO_NODE_STARTED, CONSOLE_GREEN); + display.TextStatus(ArtNetMsgConst::STARTED, CONSOLE_GREEN); hw.WatchdogInit(); @@ -210,14 +180,14 @@ void main() { hw.WatchdogFeed(); nw.Run(); node.Run(); +#if defined (NODE_SHOWFILE) + showFile.Run(); +#endif remoteConfig.Run(); configStore.Flash(); - if (node.GetActiveOutputPorts() != 0) { - dmxConfigUdp.Run(); - } mDns.Run(); -#if defined (ENABLE_HTTPD) - httpDaemon.Run(); +#if defined (ENABLE_NTP_CLIENT) + ntpClient.Run(); #endif display.Run(); hw.Run(); diff --git a/gd32_emac_artnet_dmx_multi/include/display_timeout.h b/gd32_emac_artnet_dmx_multi/include/display_timeout.h deleted file mode 100644 index c7ab4f3d..00000000 --- a/gd32_emac_artnet_dmx_multi/include/display_timeout.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @file display_timeout.h - * - */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef DISPLAY_TIMEOUT_H_ -#define DISPLAY_TIMEOUT_H_ - -#include "gd32.h" - -namespace display { -namespace timeout { - -void gpio_init() { - gpio_fsel(KEY2_GPIOx, KEY2_PINx, GPIO_FSEL_INPUT); -} - -bool gpio_renew() { - return (GPIO_ISTAT(KEY2_GPIOx) & KEY2_PINx) == 0; -} - -} // namespace timeout -} // namespace display - -#endif /* DISPLAY_TIMEOUT_H_ */ diff --git a/gd32_emac_artnet_dmx_multi/lib/rdmsoftwareversion.cpp b/gd32_emac_artnet_dmx_multi/lib/rdmsoftwareversion.cpp index 5149f9a1..94271597 100644 --- a/gd32_emac_artnet_dmx_multi/lib/rdmsoftwareversion.cpp +++ b/gd32_emac_artnet_dmx_multi/lib/rdmsoftwareversion.cpp @@ -29,7 +29,7 @@ #include "rdmsoftwareversion.h" #include "software_version.h" -#include "sofware_version_id.h" +#include "software_version_id.h" const char *RDMSoftwareVersion::GetVersion() { return SOFTWARE_VERSION; diff --git a/lib-configstore/src/pixel/storepixeldmx.cpp b/gd32_emac_artnet_dmx_multi/lib/showfileusb.cpp similarity index 68% rename from lib-configstore/src/pixel/storepixeldmx.cpp rename to gd32_emac_artnet_dmx_multi/lib/showfileusb.cpp index a76ec476..657929f1 100644 --- a/lib-configstore/src/pixel/storepixeldmx.cpp +++ b/gd32_emac_artnet_dmx_multi/lib/showfileusb.cpp @@ -1,8 +1,9 @@ +#if defined (NODE_SHOWFILE) /** - * @file storewpixeldmx.cpp + * @file showfileusb.cpp * */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,20 +24,32 @@ * THE SOFTWARE. */ -#include - -#include "storepixeldmx.h" +#include "showfile.h" #include "debug.h" -StorePixelDmx *StorePixelDmx::s_pThis; +namespace showfile { +void usb_ready() { + DEBUG_ENTRY + + ShowFile::Get()->SetPlayerShowFileCurrent(ShowFile::Get()->GetShowFileCurrent()); + + if (ShowFile::Get()->IsAutoStart()) { + ShowFile::Get()->Play(); + } else { + ShowFile::Get()->LoadShows(); + } + + DEBUG_EXIT +} -StorePixelDmx::StorePixelDmx() { +void usb_disconnected() { DEBUG_ENTRY - assert(s_pThis == nullptr); - s_pThis = this; + ShowFile::Get()->Stop(); + ShowFile::Get()->UnloadShows(); - DEBUG_PRINTF("%p", reinterpret_cast(s_pThis)); DEBUG_EXIT } +} // namespace showfile +#endif diff --git a/gd32_emac_artnet_pixel_multi/.cproject b/gd32_emac_artnet_pixel_multi/.cproject index f4797d14..a43372bb 100644 --- a/gd32_emac_artnet_pixel_multi/.cproject +++ b/gd32_emac_artnet_pixel_multi/.cproject @@ -22,22 +22,8 @@ - + - + - diff --git a/gd32_emac_artnet_pixel_multi/Makefile-softuart0.GD32 b/gd32_emac_artnet_pixel_multi/Makefile-softuart0.GD32 new file mode 100644 index 00000000..a83a1c33 --- /dev/null +++ b/gd32_emac_artnet_pixel_multi/Makefile-softuart0.GD32 @@ -0,0 +1,36 @@ +DEFINES =NODE_ARTNET_MULTI ARTNET_VERSION=4 LIGHTSET_PORTS=32 +DEFINES+=ARTNET_HAVE_TRIGGER +DEFINES+=ARTNET_HAVE_FAILSAFE_RECORD + +DEFINES+=NODE_RDMNET_LLRP_ONLY + +DEFINES+=OUTPUT_DMX_PIXEL_MULTI PIXELPATTERNS_MULTI +DEFINES+=CONFIG_PIXELDMX_MAX_PORTS=8 + +DEFINES+=ENET_RXBUF_NUM=34 ENET_TXBUF_NUM=3 +DEFINES+=RTL8201F_LED1_LINK_ALL + +DEFINES+=DISPLAY_UDF + +DEFINES+=ENABLE_HTTPD ENABLE_CONTENT + +DEFINES+=CONFIG_MDNS_DOMAIN_REVERSE +DEFINES+=CONFIG_STORE_USE_SPI +DEFINES+=CONFIG_USE_SOFTUART0 + +DEFINES+=DISABLE_RTC +DEFINES+=DISABLE_FS + +DEFINES+=DEBUG_STACK + +DEFINES+=NDEBUG + +LIBS= + +SRCDIR=firmware lib + +include ../firmware-template-gd32/Rules.mk + +prerequisites: + @echo "constexpr uint32_t DEVICE_SOFTWARE_VERSION_ID="$(shell date "+%s")";" > ./include/software_version_id.h + diff --git a/gd32_emac_artnet_pixel_multi/Makefile.GD32 b/gd32_emac_artnet_pixel_multi/Makefile.GD32 index 21451f7c..5792cc9a 100644 --- a/gd32_emac_artnet_pixel_multi/Makefile.GD32 +++ b/gd32_emac_artnet_pixel_multi/Makefile.GD32 @@ -8,17 +8,21 @@ DEFINES+=OUTPUT_DMX_PIXEL_MULTI PIXELPATTERNS_MULTI DEFINES+=CONFIG_PIXELDMX_MAX_PORTS=8 DEFINES+=ENET_RXBUF_NUM=34 ENET_TXBUF_NUM=3 +DEFINES+=RTL8201F_LED1_LINK_ALL DEFINES+=DISPLAY_UDF DEFINES+=ENABLE_HTTPD ENABLE_CONTENT +DEFINES+=CONFIG_STORE_USE_SPI +DEFINES+=CONFIG_MDNS_DOMAIN_REVERSE + DEFINES+=DISABLE_RTC DEFINES+=DISABLE_FS -DEFINES+=CONFIG_STORE_USE_SPI - +DEFINES+=DEBUG_HEAP DEFINES+=DEBUG_STACK +DEFINES+=DEBUG_EMAC DEFINES+=NDEBUG @@ -29,4 +33,5 @@ SRCDIR=firmware lib include ../firmware-template-gd32/Rules.mk prerequisites: - ./generate_sofware_version_id.sh + @echo "constexpr uint32_t DEVICE_SOFTWARE_VERSION_ID="$(shell date "+%s")";" > ./include/software_version_id.h + diff --git a/gd32_emac_artnet_pixel_multi/firmware/main.cpp b/gd32_emac_artnet_pixel_multi/firmware/main.cpp index 992c7fe3..cd41f706 100644 --- a/gd32_emac_artnet_pixel_multi/firmware/main.cpp +++ b/gd32_emac_artnet_pixel_multi/firmware/main.cpp @@ -2,7 +2,7 @@ * @file main.cpp * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,16 +30,19 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" -#if defined (ENABLE_HTTPD) -# include "httpd/httpd.h" +#if defined (ENABLE_NTP_CLIENT) +# include "net/apps/ntpclient.h" +#endif + +#if defined (ENABLE_SHELL) +# include "shell/shell.h" #endif #include "displayudf.h" #include "displayudfparams.h" #include "displayhandler.h" -#include "display_timeout.h" #include "artnetnode.h" #include "artnetparams.h" @@ -50,7 +53,7 @@ #include "pixeltype.h" #include "pixeltestpattern.h" #include "pixeldmxparams.h" -#include "pixeldmxstartstop.h" + #include "ws28xxmulti.h" #include "ws28xxdmxmulti.h" @@ -62,84 +65,64 @@ # include "rdm_e120.h" #endif +#if defined (NODE_SHOWFILE) +# include "showfile.h" +# include "showfileparams.h" +#endif + #include "remoteconfig.h" #include "remoteconfigparams.h" #include "configstore.h" -#include "storeartnet.h" -#include "storedisplayudf.h" -#include "storenetwork.h" -#if defined (NODE_RDMNET_LLRP_ONLY) -# include "storerdmdevice.h" -#endif -#include "storeremoteconfig.h" -#include "storepixeldmx.h" #include "firmwareversion.h" #include "software_version.h" -static constexpr uint32_t DMXPORT_OFFSET = LIGHTSET_PORTS; +namespace artnetnode { +namespace configstore { +uint32_t DMXPORT_OFFSET = LIGHTSET_PORTS; +} // namespace configstore +} // namespace artnetnode void Hardware::RebootHandler() { WS28xxMulti::Get()->Blackout(); ArtNetNode::Get()->Stop(); } -void main() { +int main() { Hardware hw; DisplayUdf display; ConfigStore configStore; - display.TextStatus(NetworkConst::MSG_NETWORK_INIT, Display7SegmentMessage::INFO_NETWORK_INIT, CONSOLE_YELLOW); - StoreNetwork storeNetwork; - Network nw(&storeNetwork); - display.TextStatus(NetworkConst::MSG_NETWORK_STARTED, Display7SegmentMessage::INFO_NONE, CONSOLE_GREEN); - FirmwareVersion fw(SOFTWARE_VERSION, __DATE__, __TIME__); - - fw.Print("Art-Net 4 Pixel controller {8x 4 Universes}"); - nw.Print(); - - display.TextStatus(NetworkConst::MSG_MDNS_CONFIG, Display7SegmentMessage::INFO_MDNS_CONFIG, CONSOLE_YELLOW); - + display.TextStatus(NetworkConst::MSG_NETWORK_INIT, CONSOLE_YELLOW); + Network nw; MDNS mDns; - mDns.AddServiceRecord(nullptr, mdns::Services::CONFIG, "node=Art-Net Pixel"); -#if defined (ENABLE_HTTPD) - mDns.AddServiceRecord(nullptr, mdns::Services::HTTP); -#endif - mDns.Print(); + display.TextStatus(NetworkConst::MSG_NETWORK_STARTED, CONSOLE_GREEN); + FirmwareVersion fw(SOFTWARE_VERSION, __DATE__, __TIME__); -#if defined (ENABLE_HTTPD) - HttpDaemon httpDaemon; + fw.Print("Art-Net 4 Pixel controller"); + +#if defined (ENABLE_NTP_CLIENT) + NtpClient ntpClient; + ntpClient.Start(); + ntpClient.Print(); #endif - display.TextStatus(ArtNetMsgConst::PARAMS, Display7SegmentMessage::INFO_NODE_PARMAMS, CONSOLE_YELLOW); - ArtNetNode node; - StoreArtNet storeArtNet(DMXPORT_OFFSET); - node.SetArtNetStore(&storeArtNet); - - ArtNetParams artnetParams(&storeArtNet); - - if (artnetParams.Load()) { - artnetParams.Dump(); - artnetParams.Set(DMXPORT_OFFSET); - } + ArtNetParams artnetParams; + artnetParams.Load(); + artnetParams.Set(); PixelDmxConfiguration pixelDmxConfiguration; - StorePixelDmx storePixelDmx; - PixelDmxParams pixelDmxParams(&storePixelDmx); + PixelDmxParams pixelDmxParams; + pixelDmxParams.Load(); + pixelDmxParams.Set(); - if (pixelDmxParams.Load()) { - pixelDmxParams.Dump(); - pixelDmxParams.Set(&pixelDmxConfiguration); - } + WS28xxDmxMulti pixelDmxMulti; - WS28xxDmxMulti pixelDmxMulti(pixelDmxConfiguration); - pixelDmxMulti.SetPixelDmxHandler(new PixelDmxStartStop); - - const auto nPixelActivePorts = pixelDmxMulti.GetOutputPorts(); - const auto nUniverses = pixelDmxMulti.GetUniverses(); + const auto nPixelActivePorts = pixelDmxConfiguration.GetOutputPorts(); + const auto nUniverses = pixelDmxConfiguration.GetUniverses(); uint32_t nPortProtocolIndex = 0; @@ -160,7 +143,7 @@ void main() { const auto nTestPattern = static_cast(pixelDmxParams.GetTestPattern()); PixelTestPattern pixelTestPattern(nTestPattern, nPixelActivePorts); - if (PixelTestPattern::GetPattern() != pixelpatterns::Pattern::NONE) { + if (PixelTestPattern::Get()->GetPattern() != pixelpatterns::Pattern::NONE) { node.SetOutput(nullptr); } else { node.SetOutput(&pixelDmxMulti); @@ -169,9 +152,9 @@ void main() { ArtNetTriggerHandler triggerHandler(&pixelDmxMulti); #if defined (NODE_RDMNET_LLRP_ONLY) - display.TextStatus(RDMNetConst::MSG_CONFIG, Display7SegmentMessage::INFO_RDMNET_CONFIG, CONSOLE_YELLOW); + display.TextStatus(RDMNetConst::MSG_CONFIG, CONSOLE_YELLOW); char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH + 1]; - snprintf(aDescription, sizeof(aDescription) - 1, "Art-Net 4 Pixel %d-%s:%d", nPixelActivePorts, PixelType::GetType(WS28xxMulti::Get()->GetType()), WS28xxMulti::Get()->GetCount()); + snprintf(aDescription, sizeof(aDescription) - 1, "Art-Net 4 Pixel %d-%s:%d", nPixelActivePorts, pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount()); char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH + 1]; const auto nLength = snprintf(aLabel, sizeof(aLabel) - 1, GD32_BOARD_NAME " Pixel"); @@ -187,41 +170,44 @@ void main() { llrpOnlyDevice.Init(); - StoreRDMDevice storeRdmDevice; - RDMDeviceParams rdmDeviceParams(&storeRdmDevice); + RDMDeviceParams rdmDeviceParams; - if (rdmDeviceParams.Load()) { - rdmDeviceParams.Dump(); - rdmDeviceParams.Set(&llrpOnlyDevice); - } + rdmDeviceParams.Load(); + rdmDeviceParams.Set(&llrpOnlyDevice); - llrpOnlyDevice.SetRDMDeviceStore(&storeRdmDevice); llrpOnlyDevice.Print(); #endif +#if defined (NODE_SHOWFILE) + ShowFile showFile; + + ShowFileParams showFileParams; + showFileParams.Load(); + showFileParams.Set(); + + showFile.Print(); +#endif + node.Print(); pixelDmxMulti.Print(); - display.SetTitle("ArtNet 4 Pixel %dx%d", nPixelActivePorts, WS28xxMulti::Get()->GetCount()); + display.SetTitle("ArtNet 4 Pixel %dx%d", nPixelActivePorts, pixelDmxConfiguration.GetCount()); display.Set(2, displayudf::Labels::IP); - display.Set(3, displayudf::Labels::VERSION); - display.Set(4, displayudf::Labels::UNIVERSE_PORT_A); + display.Set(3, displayudf::Labels::HOSTNAME); + display.Set(4, displayudf::Labels::VERSION); display.Set(5, displayudf::Labels::BOARDNAME); - StoreDisplayUdf storeDisplayUdf; - DisplayUdfParams displayUdfParams(&storeDisplayUdf); + DisplayUdfParams displayUdfParams; - if (displayUdfParams.Load()) { - displayUdfParams.Dump(); - displayUdfParams.Set(&display); - } + displayUdfParams.Load(); + displayUdfParams.Set(&display); - display.Show(&node, DMXPORT_OFFSET); + display.Show(); display.Printf(7, "%s:%d G%d %s", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); if (nTestPattern != pixelpatterns::Pattern::NONE) { display.ClearLine(6); @@ -230,22 +216,24 @@ void main() { RemoteConfig remoteConfig(remoteconfig::Node::ARTNET, remoteconfig::Output::PIXEL, node.GetActiveOutputPorts()); - StoreRemoteConfig storeRemoteConfig; - RemoteConfigParams remoteConfigParams(&storeRemoteConfig); - - if(remoteConfigParams.Load()) { - remoteConfigParams.Dump(); - remoteConfigParams.Set(&remoteConfig); - } + RemoteConfigParams remoteConfigParams; + remoteConfigParams.Load(); + remoteConfigParams.Set(&remoteConfig); while (configStore.Flash()) ; - display.TextStatus(ArtNetMsgConst::START, Display7SegmentMessage::INFO_NODE_START, CONSOLE_YELLOW); + mDns.Print(); + +#if defined (ENABLE_SHELL) + Shell shell; +#endif + + display.TextStatus(ArtNetMsgConst::START, CONSOLE_YELLOW); node.Start(); - display.TextStatus(ArtNetMsgConst::STARTED, Display7SegmentMessage::INFO_NODE_STARTED, CONSOLE_GREEN); + display.TextStatus(ArtNetMsgConst::STARTED, CONSOLE_GREEN); hw.WatchdogInit(); @@ -253,19 +241,23 @@ void main() { hw.WatchdogFeed(); nw.Run(); node.Run(); +#if defined (NODE_SHOWFILE) + showFile.Run(); +#endif remoteConfig.Run(); configStore.Flash(); - if (__builtin_expect((PixelTestPattern::GetPattern() != pixelpatterns::Pattern::NONE), 0)) { - pixelTestPattern.Run(); - } + pixelTestPattern.Run(); mDns.Run(); +#if defined (ENABLE_NTP_CLIENT) + ntpClient.Run(); +#endif #if defined (NODE_RDMNET_LLRP_ONLY) llrpOnlyDevice.Run(); -#endif -#if defined (ENABLE_HTTPD) - httpDaemon.Run(); #endif display.Run(); hw.Run(); +#if defined (ENABLE_SHELL) + shell.Run(); +#endif } } diff --git a/gd32_emac_artnet_pixel_multi/generate_sofware_version_id.sh b/gd32_emac_artnet_pixel_multi/generate_sofware_version_id.sh deleted file mode 100755 index 2f453f59..00000000 --- a/gd32_emac_artnet_pixel_multi/generate_sofware_version_id.sh +++ /dev/null @@ -1,4 +0,0 @@ -echo "// Generated "$(date) > ./include/sofware_version_id.h -var="$(date +%s)" -echo "constexpr uint32_t DEVICE_SOFTWARE_VERSION_ID="$var";" >> ./include/sofware_version_id.h - diff --git a/gd32_emac_artnet_pixel_multi/include/display_timeout.h b/gd32_emac_artnet_pixel_multi/include/display_timeout.h deleted file mode 100644 index a8556629..00000000 --- a/gd32_emac_artnet_pixel_multi/include/display_timeout.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @file display_timeout.h - * - */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef DISPLAY_TIMEOUT_H_ -#define DISPLAY_TIMEOUT_H_ - -#include "gd32.h" - -namespace display { -namespace timeout { - -void gpio_init() { - gpio_fsel(KEY2_GPIOx, KEY2_PINx, GPIO_FSEL_INPUT); -} - -bool gpio_renew() { - return (GPIO_ISTAT(KEY2_GPIOx) & KEY2_PINx) == 0; -} - -} // namespace timeout -} // namespace display - -#endif /* DISPLAY_TIMEOUT_H_ */ diff --git a/gd32_emac_artnet_pixel_multi/include/pixeldmxstartstop.h b/gd32_emac_artnet_pixel_multi/include/pixeldmxstartstop.h deleted file mode 100644 index bca3ee30..00000000 --- a/gd32_emac_artnet_pixel_multi/include/pixeldmxstartstop.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @file pixeldmxstartstop.h - * - */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef PIXELDMXSTARTSTOP_H_ -#define PIXELDMXSTARTSTOP_H_ - -#include "pixeldmxhandler.h" - -#include "gd32.h" -#include "gd32_gpio.h" - -class PixelDmxStartStop final: public PixelDmxHandler { -public: - PixelDmxStartStop() { - gd32_gpio_fsel(GD32_BOARD_LED2, GPIO_FSEL_OUTPUT); - gd32_gpio_clr(GD32_BOARD_LED2); - } - - ~PixelDmxStartStop() override { - } - - void Start() override { - gd32_gpio_set(GD32_BOARD_LED2); - } - - void Stop() override { - gd32_gpio_clr(GD32_BOARD_LED2); - } -}; - -#endif /* PIXELDMXSTARTSTOP_H_ */ diff --git a/gd32_emac_artnet_pixel_multi/include/sofware_version_id.h b/gd32_emac_artnet_pixel_multi/include/sofware_version_id.h deleted file mode 100644 index 76d37b26..00000000 --- a/gd32_emac_artnet_pixel_multi/include/sofware_version_id.h +++ /dev/null @@ -1,2 +0,0 @@ -// Generated wo 18 okt 2023 15:47:21 CEST -constexpr uint32_t DEVICE_SOFTWARE_VERSION_ID=1697636842; diff --git a/gd32_emac_artnet_pixel_multi/lib/factorydefaults.cpp b/gd32_emac_artnet_pixel_multi/lib/factorydefaults.cpp index 971fc158..1741e5e2 100644 --- a/gd32_emac_artnet_pixel_multi/lib/factorydefaults.cpp +++ b/gd32_emac_artnet_pixel_multi/lib/factorydefaults.cpp @@ -28,7 +28,7 @@ #include "remoteconfig.h" #include "configstore.h" -#include "storenetwork.h" +#include "networkstore.h" namespace rdm { namespace device { @@ -37,7 +37,7 @@ namespace responder { void factorydefaults() { RemoteConfig::Get()->SetDisable(false); ConfigStore::Get()->ResetSetList(configstore::Store::RDMDEVICE); - StoreNetwork::Get()->SaveDhcp(true); + NetworkStore::SaveDhcp(true); } } // namespace responder diff --git a/gd32_emac_artnet_pixel_multi/lib/rdmsoftwareversion.cpp b/gd32_emac_artnet_pixel_multi/lib/rdmsoftwareversion.cpp index 5149f9a1..94271597 100644 --- a/gd32_emac_artnet_pixel_multi/lib/rdmsoftwareversion.cpp +++ b/gd32_emac_artnet_pixel_multi/lib/rdmsoftwareversion.cpp @@ -29,7 +29,7 @@ #include "rdmsoftwareversion.h" #include "software_version.h" -#include "sofware_version_id.h" +#include "software_version_id.h" const char *RDMSoftwareVersion::GetVersion() { return SOFTWARE_VERSION; diff --git a/gd32_emac_artnet_pixel_multi/lib/showfileusb.cpp b/gd32_emac_artnet_pixel_multi/lib/showfileusb.cpp new file mode 100644 index 00000000..657929f1 --- /dev/null +++ b/gd32_emac_artnet_pixel_multi/lib/showfileusb.cpp @@ -0,0 +1,55 @@ +#if defined (NODE_SHOWFILE) +/** + * @file showfileusb.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "showfile.h" + +#include "debug.h" + +namespace showfile { +void usb_ready() { + DEBUG_ENTRY + + ShowFile::Get()->SetPlayerShowFileCurrent(ShowFile::Get()->GetShowFileCurrent()); + + if (ShowFile::Get()->IsAutoStart()) { + ShowFile::Get()->Play(); + } else { + ShowFile::Get()->LoadShows(); + } + + DEBUG_EXIT +} + +void usb_disconnected() { + DEBUG_ENTRY + + ShowFile::Get()->Stop(); + ShowFile::Get()->UnloadShows(); + + DEBUG_EXIT +} +} // namespace showfile +#endif diff --git a/gd32_emac_ddp_pixel_multi/.cproject b/gd32_emac_ddp_pixel_multi/.cproject index 9f2741b0..1fbb09a0 100755 --- a/gd32_emac_ddp_pixel_multi/.cproject +++ b/gd32_emac_ddp_pixel_multi/.cproject @@ -23,7 +23,6 @@ - + @@ -99,20 +80,7 @@ - + diff --git a/gd32_emac_ddp_pixel_multi/.settings/language.settings.xml b/gd32_emac_ddp_pixel_multi/.settings/language.settings.xml index 6c30e852..96cd3e7a 100755 --- a/gd32_emac_ddp_pixel_multi/.settings/language.settings.xml +++ b/gd32_emac_ddp_pixel_multi/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/gd32_emac_ddp_pixel_multi/Makefile.GD32 b/gd32_emac_ddp_pixel_multi/Makefile.GD32 index 498bca12..e52c6828 100755 --- a/gd32_emac_ddp_pixel_multi/Makefile.GD32 +++ b/gd32_emac_ddp_pixel_multi/Makefile.GD32 @@ -26,4 +26,5 @@ SRCDIR=firmware lib include ../firmware-template-gd32/Rules.mk prerequisites: - ./generate_sofware_version_id.sh + @echo "constexpr uint32_t DEVICE_SOFTWARE_VERSION_ID="$(shell date "+%s")";" > ./include/software_version_id.h + diff --git a/gd32_emac_ddp_pixel_multi/firmware/main.cpp b/gd32_emac_ddp_pixel_multi/firmware/main.cpp index 17b62f87..b4a2ddbb 100644 --- a/gd32_emac_ddp_pixel_multi/firmware/main.cpp +++ b/gd32_emac_ddp_pixel_multi/firmware/main.cpp @@ -2,7 +2,7 @@ * @file main.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,16 +31,15 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" -#if defined (ENABLE_HTTPD) -# include "httpd/httpd.h" +#if defined (ENABLE_NTP_CLIENT) +# include "net/apps/ntpclient.h" #endif #include "displayudf.h" #include "displayudfparams.h" #include "displayhandler.h" -#include "display_timeout.h" #include "ddpdisplay.h" @@ -48,9 +47,9 @@ #include "pixeltype.h" #include "pixeltestpattern.h" #include "pixeldmxparams.h" + #include "ws28xxmulti.h" #include "ws28xxdmxmulti.h" -#include "ws28xxdmxstartstop.h" #if defined (NODE_RDMNET_LLRP_ONLY) # include "rdmdeviceparams.h" @@ -64,13 +63,7 @@ #include "remoteconfigparams.h" #include "configstore.h" -#include "storedisplayudf.h" -#include "storenetwork.h" -#if defined (NODE_RDMNET_LLRP_ONLY) -# include "storerdmdevice.h" -#endif -#include "storeremoteconfig.h" -#include "storepixeldmx.h" + #include "firmwareversion.h" #include "software_version.h" @@ -80,51 +73,41 @@ void Hardware::RebootHandler() { DdpDisplay::Get()->Stop(); } -void main() { +int main() { Hardware hw; DisplayUdf display; ConfigStore configStore; - display.TextStatus(NetworkConst::MSG_NETWORK_INIT, Display7SegmentMessage::INFO_NETWORK_INIT, CONSOLE_YELLOW); - StoreNetwork storeNetwork; - Network nw(&storeNetwork); - display.TextStatus(NetworkConst::MSG_NETWORK_STARTED, Display7SegmentMessage::INFO_NONE, CONSOLE_GREEN); + display.TextStatus(NetworkConst::MSG_NETWORK_INIT, CONSOLE_YELLOW); + Network nw; + display.TextStatus(NetworkConst::MSG_NETWORK_STARTED, CONSOLE_GREEN); FirmwareVersion fw(SOFTWARE_VERSION, __DATE__, __TIME__); fw.Print("DDP Pixel controller {8x 4 Universes}"); - nw.Print(); + - display.TextStatus(NetworkConst::MSG_MDNS_CONFIG, Display7SegmentMessage::INFO_MDNS_CONFIG, CONSOLE_YELLOW); +#if defined (ENABLE_NTP_CLIENT) + NtpClient ntpClient; + ntpClient.Start(); + ntpClient.Print(); +#endif MDNS mDns; - mDns.AddServiceRecord(nullptr, mdns::Services::CONFIG, "node=DDP Pixel"); - mDns.AddServiceRecord(nullptr, mdns::Services::DDP, "type=display"); -#if defined (ENABLE_HTTPD) - mDns.AddServiceRecord(nullptr, mdns::Services::HTTP); -#endif + mDns.ServiceRecordAdd(nullptr, mdns::Services::DDP, "type=display"); mDns.Print(); -#if defined (ENABLE_HTTPD) - HttpDaemon httpDaemon; -#endif - PixelDmxConfiguration pixelDmxConfiguration; - StorePixelDmx storePixelDmx; - PixelDmxParams pixelDmxParams(&storePixelDmx); + PixelDmxParams pixelDmxParams; + pixelDmxParams.Load(); + pixelDmxParams.Set(); - if (pixelDmxParams.Load()) { - pixelDmxParams.Dump(); - pixelDmxParams.Set(&pixelDmxConfiguration); - } - - WS28xxDmxMulti pixelDmxMulti(pixelDmxConfiguration); - pixelDmxMulti.SetPixelDmxHandler(new PixelDmxStartStop); + WS28xxDmxMulti pixelDmxMulti; DdpDisplay ddpDisplay; - const auto nActivePorts = pixelDmxMulti.GetOutputPorts(); + const auto nActivePorts = pixelDmxConfiguration.GetOutputPorts(); - ddpDisplay.SetCount(pixelDmxMulti.GetGroups(), pixelDmxMulti.GetChannelsPerPixel(), nActivePorts); + ddpDisplay.SetCount(pixelDmxConfiguration.GetGroups(), pixelDmxConfiguration.GetLedsPerPixel(), nActivePorts); const auto nTestPattern = static_cast(pixelDmxParams.GetTestPattern()); PixelTestPattern pixelTestPattern(nTestPattern, nActivePorts); @@ -133,10 +116,10 @@ void main() { ddpDisplay.Print(); #if defined (NODE_RDMNET_LLRP_ONLY) - display.TextStatus(RDMNetConst::MSG_CONFIG, Display7SegmentMessage::INFO_RDMNET_CONFIG, CONSOLE_YELLOW); + display.TextStatus(RDMNetConst::MSG_CONFIG, CONSOLE_YELLOW); char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH + 1]; - snprintf(aDescription, sizeof(aDescription) - 1, "DDP Display %u-%s:%d", nActivePorts, PixelType::GetType(WS28xxMulti::Get()->GetType()), WS28xxMulti::Get()->GetCount()); + snprintf(aDescription, sizeof(aDescription) - 1, "DDP Display %u-%s:%d", nActivePorts, pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount()); char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH + 1]; const auto nLength = snprintf(aLabel, sizeof(aLabel) - 1, "Orange Pi Zero Pixel"); @@ -149,15 +132,11 @@ void main() { llrpOnlyDevice.SetProductDetail(E120_PRODUCT_DETAIL_LED); llrpOnlyDevice.Init(); - StoreRDMDevice storeRdmDevice; - RDMDeviceParams rdmDeviceParams(&storeRdmDevice); + RDMDeviceParams rdmDeviceParams; - if (rdmDeviceParams.Load()) { - rdmDeviceParams.Dump(); - rdmDeviceParams.Set(&llrpOnlyDevice); - } + rdmDeviceParams.Load(); + rdmDeviceParams.Set(&llrpOnlyDevice); - llrpOnlyDevice.SetRDMDeviceStore(&storeRdmDevice); llrpOnlyDevice.Print(); #endif @@ -168,20 +147,17 @@ void main() { display.Set(5, displayudf::Labels::DEFAULT_GATEWAY); display.Set(6, displayudf::Labels::BOARDNAME); - StoreDisplayUdf storeDisplayUdf; - DisplayUdfParams displayUdfParams(&storeDisplayUdf); + DisplayUdfParams displayUdfParams; - if (displayUdfParams.Load()) { - displayUdfParams.Dump(); - displayUdfParams.Set(&display); - } + displayUdfParams.Load(); + displayUdfParams.Set(&display); display.Show(); display.Printf(7, "%s:%d G%d %s", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); if (nTestPattern != pixelpatterns::Pattern::NONE) { display.ClearLine(6); @@ -190,22 +166,18 @@ void main() { RemoteConfig remoteConfig(remoteconfig::Node::DDP, remoteconfig::Output::PIXEL, nActivePorts); - StoreRemoteConfig storeRemoteConfig; - RemoteConfigParams remoteConfigParams(&storeRemoteConfig); - - if(remoteConfigParams.Load()) { - remoteConfigParams.Dump(); - remoteConfigParams.Set(&remoteConfig); - } + RemoteConfigParams remoteConfigParams; + remoteConfigParams.Load(); + remoteConfigParams.Set(&remoteConfig); while (configStore.Flash()) ; - display.TextStatus("Starting DDP Display", Display7SegmentMessage::INFO_BRIDGE_START, CONSOLE_YELLOW); + display.TextStatus("Starting DDP Display", CONSOLE_YELLOW); ddpDisplay.Start(); - display.TextStatus("DDP Display Started", Display7SegmentMessage::INFO_BRIDGE_START, CONSOLE_GREEN); + display.TextStatus("DDP Display Started", CONSOLE_GREEN); hw.WatchdogInit(); @@ -215,15 +187,13 @@ void main() { ddpDisplay.Run(); remoteConfig.Run(); configStore.Flash(); - if (__builtin_expect((PixelTestPattern::GetPattern() != pixelpatterns::Pattern::NONE), 0)) { - pixelTestPattern.Run(); - } + pixelTestPattern.Run(); mDns.Run(); +#if defined (ENABLE_NTP_CLIENT) + ntpClient.Run(); +#endif #if defined (NODE_RDMNET_LLRP_ONLY) llrpOnlyDevice.Run(); -#endif -#if defined (ENABLE_HTTPD) - httpDaemon.Run(); #endif display.Run(); hw.Run(); diff --git a/gd32_emac_ddp_pixel_multi/generate_sofware_version_id.sh b/gd32_emac_ddp_pixel_multi/generate_sofware_version_id.sh deleted file mode 100755 index 2f453f59..00000000 --- a/gd32_emac_ddp_pixel_multi/generate_sofware_version_id.sh +++ /dev/null @@ -1,4 +0,0 @@ -echo "// Generated "$(date) > ./include/sofware_version_id.h -var="$(date +%s)" -echo "constexpr uint32_t DEVICE_SOFTWARE_VERSION_ID="$var";" >> ./include/sofware_version_id.h - diff --git a/gd32_emac_ddp_pixel_multi/include/sofware_version_id.h b/gd32_emac_ddp_pixel_multi/include/sofware_version_id.h deleted file mode 100644 index b6751745..00000000 --- a/gd32_emac_ddp_pixel_multi/include/sofware_version_id.h +++ /dev/null @@ -1,2 +0,0 @@ -// Generated wo 18 okt 2023 15:47:29 CEST -constexpr uint32_t DEVICE_SOFTWARE_VERSION_ID=1697636849; diff --git a/gd32_emac_ddp_pixel_multi/lib/factorydefaults.cpp b/gd32_emac_ddp_pixel_multi/lib/factorydefaults.cpp index 971fc158..1741e5e2 100644 --- a/gd32_emac_ddp_pixel_multi/lib/factorydefaults.cpp +++ b/gd32_emac_ddp_pixel_multi/lib/factorydefaults.cpp @@ -28,7 +28,7 @@ #include "remoteconfig.h" #include "configstore.h" -#include "storenetwork.h" +#include "networkstore.h" namespace rdm { namespace device { @@ -37,7 +37,7 @@ namespace responder { void factorydefaults() { RemoteConfig::Get()->SetDisable(false); ConfigStore::Get()->ResetSetList(configstore::Store::RDMDEVICE); - StoreNetwork::Get()->SaveDhcp(true); + NetworkStore::SaveDhcp(true); } } // namespace responder diff --git a/gd32_emac_ddp_pixel_multi/lib/rdmsoftwareversion.cpp b/gd32_emac_ddp_pixel_multi/lib/rdmsoftwareversion.cpp index 906bb504..1f6d4aa4 100644 --- a/gd32_emac_ddp_pixel_multi/lib/rdmsoftwareversion.cpp +++ b/gd32_emac_ddp_pixel_multi/lib/rdmsoftwareversion.cpp @@ -28,7 +28,7 @@ #include "rdmsoftwareversion.h" #include "software_version.h" -#include "sofware_version_id.h" +#include "software_version_id.h" const char *RDMSoftwareVersion::GetVersion() { return SOFTWARE_VERSION; diff --git a/gd32_emac_e131_dmx_multi/.cproject b/gd32_emac_e131_dmx_multi/.cproject index d8886bc0..751c7249 100644 --- a/gd32_emac_e131_dmx_multi/.cproject +++ b/gd32_emac_e131_dmx_multi/.cproject @@ -31,11 +31,9 @@ - - diff --git a/gd32_emac_e131_dmx_multi/Common.mk b/gd32_emac_e131_dmx_multi/Common.mk new file mode 100644 index 00000000..a0da208a --- /dev/null +++ b/gd32_emac_e131_dmx_multi/Common.mk @@ -0,0 +1,10 @@ +DEFINES+=CONFIG_STORE_USE_SPI + +DEFINES+=RTL8201F_LED1_LINK_ALL + +DEFINES+=DISPLAY_UDF + +DEFINES+=ENABLE_HTTPD ENABLE_CONTENT + +DEFINES+=DISABLE_RTC +DEFINES+=DISABLE_FS \ No newline at end of file diff --git a/gd32_emac_e131_dmx_multi/Makefile.GD32 b/gd32_emac_e131_dmx_multi/Makefile.GD32 index d69a953c..e942f995 100644 --- a/gd32_emac_e131_dmx_multi/Makefile.GD32 +++ b/gd32_emac_e131_dmx_multi/Makefile.GD32 @@ -7,6 +7,7 @@ DEFINES+=OUTPUT_DMX_SEND_MULTI DEFINES+=OUTPUT_HAVE_STYLESWITCH DEFINES+=ENET_RXBUF_NUM=8 ENET_TXBUF_NUM=2 +DEFINES+=RTL8201F_LED1_LINK_ALL DEFINES+=DISPLAY_UDF @@ -28,5 +29,6 @@ SRCDIR=firmware lib include ../firmware-template-gd32/Rules.mk prerequisites: - ./generate_sofware_version_id.sh + @echo "constexpr uint32_t DEVICE_SOFTWARE_VERSION_ID="$(shell date "+%s")";" > ./include/software_version_id.h + diff --git a/gd32_emac_e131_dmx_multi/firmware/main.cpp b/gd32_emac_e131_dmx_multi/firmware/main.cpp index f1e28bb3..56247075 100644 --- a/gd32_emac_e131_dmx_multi/firmware/main.cpp +++ b/gd32_emac_e131_dmx_multi/firmware/main.cpp @@ -2,7 +2,7 @@ * @file main.cpp * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,16 +29,15 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" -#if defined (ENABLE_HTTPD) -# include "httpd/httpd.h" +#if defined (ENABLE_NTP_CLIENT) +# include "net/apps/ntpclient.h" #endif #include "displayudf.h" #include "displayudfparams.h" #include "displayhandler.h" -#include "display_timeout.h" #include "e131.h" #include "e131bridge.h" @@ -57,66 +56,53 @@ # include "rdm_e120.h" #endif +#if defined (NODE_SHOWFILE) +# include "showfile.h" +# include "showfileparams.h" +#endif + #include "remoteconfig.h" #include "remoteconfigparams.h" #include "configstore.h" -#include "storedisplayudf.h" -#include "storedmxsend.h" -#include "storee131.h" -#include "storenetwork.h" -#if defined (NODE_RDMNET_LLRP_ONLY) -# include "storerdmdevice.h" -#endif -#include "storeremoteconfig.h" #include "firmwareversion.h" #include "software_version.h" -static constexpr uint32_t DMXPORT_OFFSET = 0; +namespace e131bridge { +namespace configstore { +uint32_t DMXPORT_OFFSET = 0; +} // namespace configstore +} // namespace e131bridge void Hardware::RebootHandler() { Dmx::Get()->Blackout(); E131Bridge::Get()->Stop(); } -void main() { +int main() { Hardware hw; DisplayUdf display; ConfigStore configStore; - display.TextStatus(NetworkConst::MSG_NETWORK_INIT, Display7SegmentMessage::INFO_NETWORK_INIT, CONSOLE_YELLOW); - StoreNetwork storeNetwork; - Network nw(&storeNetwork); - display.TextStatus(NetworkConst::MSG_NETWORK_STARTED, Display7SegmentMessage::INFO_NONE, CONSOLE_GREEN); + display.TextStatus(NetworkConst::MSG_NETWORK_INIT, CONSOLE_YELLOW); + Network nw; + MDNS mDns; + display.TextStatus(NetworkConst::MSG_NETWORK_STARTED, CONSOLE_GREEN); FirmwareVersion fw(SOFTWARE_VERSION, __DATE__, __TIME__); fw.Print("sACN E1.31 DMX {" STR(LIGHTSET_PORTS) " Universes}"); - nw.Print(); - - display.TextStatus(NetworkConst::MSG_MDNS_CONFIG, Display7SegmentMessage::INFO_MDNS_CONFIG, CONSOLE_YELLOW); - - MDNS mDns; - mDns.AddServiceRecord(nullptr, mdns::Services::CONFIG, "node=sACN E1.31 DMX"); -#if defined (ENABLE_HTTPD) - mDns.AddServiceRecord(nullptr, mdns::Services::HTTP); -#endif - mDns.Print(); -#if defined (ENABLE_HTTPD) - HttpDaemon httpDaemon; +#if defined (ENABLE_NTP_CLIENT) + NtpClient ntpClient; + ntpClient.Start(); + ntpClient.Print(); #endif - display.TextStatus(E131MsgConst::PARAMS, Display7SegmentMessage::INFO_BRIDGE_PARMAMS, CONSOLE_YELLOW); - - StoreE131 storeE131; - E131Params e131params(&storeE131); - E131Bridge bridge; - if (e131params.Load()) { - e131params.Dump(); - e131params.Set(DMXPORT_OFFSET); - } + E131Params e131params; + e131params.Load(); + e131params.Set(); for (uint32_t nPortIndex = 0; nPortIndex < e131bridge::MAX_PORTS; nPortIndex++) { bool bIsSet; @@ -124,19 +110,15 @@ void main() { bridge.SetUniverse(nPortIndex, e131params.GetDirection(nPortIndex), nUniverse); } - StoreDmxSend storeDmxSend; - DmxParams dmxparams(&storeDmxSend); - Dmx dmx; - if (dmxparams.Load()) { - dmxparams.Dump(); - dmxparams.Set(&dmx); - } + DmxParams dmxparams; + dmxparams.Load(); + dmxparams.Set(&dmx); - for (uint32_t nPortIndex = DMXPORT_OFFSET; nPortIndex < e131bridge::MAX_PORTS; nPortIndex++) { + for (uint32_t nPortIndex = e131bridge::configstore::DMXPORT_OFFSET; nPortIndex < e131bridge::MAX_PORTS; nPortIndex++) { uint16_t nUniverse; - const auto nDmxPortIndex = nPortIndex - DMXPORT_OFFSET; + const auto nDmxPortIndex = nPortIndex - e131bridge::configstore::DMXPORT_OFFSET; if (bridge.GetUniverse(nPortIndex, nUniverse, lightset::PortDir::OUTPUT)) { dmx.SetPortDirection(nDmxPortIndex, dmx::PortDirection::OUTP, false); @@ -150,12 +132,10 @@ void main() { bridge.SetOutput(&dmxSend); - DmxConfigUdp dmxConfigUdp; - const auto nActivePorts = static_cast(bridge.GetActiveInputPorts() + bridge.GetActiveOutputPorts()); #if defined (NODE_RDMNET_LLRP_ONLY) - display.TextStatus(RDMNetConst::MSG_CONFIG, Display7SegmentMessage::INFO_RDMNET_CONFIG, CONSOLE_YELLOW); + display.TextStatus(RDMNetConst::MSG_CONFIG, CONSOLE_YELLOW); char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH + 1]; snprintf(aDescription, sizeof(aDescription) - 1, "sACN E1.31 DMX %d", nActivePorts); @@ -170,18 +150,24 @@ void main() { llrpOnlyDevice.SetProductDetail(E120_PRODUCT_DETAIL_ETHERNET_NODE); llrpOnlyDevice.Init(); - StoreRDMDevice storeRdmDevice; - RDMDeviceParams rdmDeviceParams(&storeRdmDevice); + RDMDeviceParams rdmDeviceParams; - if (rdmDeviceParams.Load()) { - rdmDeviceParams.Dump(); - rdmDeviceParams.Set(&llrpOnlyDevice); - } - - llrpOnlyDevice.SetRDMDeviceStore(&storeRdmDevice); + rdmDeviceParams.Load(); + rdmDeviceParams.Set(&llrpOnlyDevice); + llrpOnlyDevice.Print(); #endif +#if defined (NODE_SHOWFILE) + ShowFile showFile; + + ShowFileParams showFileParams; + showFileParams.Load(); + showFileParams.Set(); + + showFile.Print(); +#endif + bridge.Print(); display.SetTitle("sACN E1.31 DMX %u", nActivePorts); @@ -191,34 +177,29 @@ void main() { display.Set(5, displayudf::Labels::UNIVERSE_PORT_B); display.Set(6, displayudf::Labels::BOARDNAME); - StoreDisplayUdf storeDisplayUdf; - DisplayUdfParams displayUdfParams(&storeDisplayUdf); + DisplayUdfParams displayUdfParams; - if(displayUdfParams.Load()) { - displayUdfParams.Dump(); - displayUdfParams.Set(&display); - } + displayUdfParams.Load(); + displayUdfParams.Set(&display); - display.Show(&bridge); + display.Show(); RemoteConfig remoteConfig(remoteconfig::Node::E131, remoteconfig::Output::DMX, nActivePorts); - StoreRemoteConfig storeRemoteConfig; - RemoteConfigParams remoteConfigParams(&storeRemoteConfig); - - if (remoteConfigParams.Load()) { - remoteConfigParams.Dump(); - remoteConfigParams.Set(&remoteConfig); - } + RemoteConfigParams remoteConfigParams; + remoteConfigParams.Load(); + remoteConfigParams.Set(&remoteConfig); while (configStore.Flash()) ; - display.TextStatus(E131MsgConst::START, Display7SegmentMessage::INFO_BRIDGE_START, CONSOLE_YELLOW); + mDns.Print(); + + display.TextStatus(E131MsgConst::START, CONSOLE_YELLOW); bridge.Start(); - display.TextStatus(E131MsgConst::STARTED, Display7SegmentMessage::INFO_BRIDGE_STARTED, CONSOLE_GREEN); + display.TextStatus(E131MsgConst::STARTED, CONSOLE_GREEN); hw.WatchdogInit(); @@ -226,17 +207,17 @@ void main() { hw.WatchdogFeed(); nw.Run(); bridge.Run(); +#if defined (NODE_SHOWFILE) + showFile.Run(); +#endif remoteConfig.Run(); configStore.Flash(); - if (bridge.GetActiveOutputPorts() != 0) { - dmxConfigUdp.Run(); - } mDns.Run(); +#if defined (ENABLE_NTP_CLIENT) + ntpClient.Run(); +#endif #if defined (NODE_RDMNET_LLRP_ONLY) llrpOnlyDevice.Run(); -#endif -#if defined (ENABLE_HTTPD) - httpDaemon.Run(); #endif display.Run(); hw.Run(); diff --git a/gd32_emac_e131_dmx_multi/generate_sofware_version_id.sh b/gd32_emac_e131_dmx_multi/generate_sofware_version_id.sh deleted file mode 100755 index 2f453f59..00000000 --- a/gd32_emac_e131_dmx_multi/generate_sofware_version_id.sh +++ /dev/null @@ -1,4 +0,0 @@ -echo "// Generated "$(date) > ./include/sofware_version_id.h -var="$(date +%s)" -echo "constexpr uint32_t DEVICE_SOFTWARE_VERSION_ID="$var";" >> ./include/sofware_version_id.h - diff --git a/gd32_emac_e131_dmx_multi/include/sofware_version_id.h b/gd32_emac_e131_dmx_multi/include/sofware_version_id.h deleted file mode 100644 index 08e1c733..00000000 --- a/gd32_emac_e131_dmx_multi/include/sofware_version_id.h +++ /dev/null @@ -1,2 +0,0 @@ -// Generated wo 18 okt 2023 15:47:37 CEST -constexpr uint32_t DEVICE_SOFTWARE_VERSION_ID=1697636857; diff --git a/gd32_emac_e131_dmx_multi/lib/factorydefaults.cpp b/gd32_emac_e131_dmx_multi/lib/factorydefaults.cpp index 971fc158..1741e5e2 100644 --- a/gd32_emac_e131_dmx_multi/lib/factorydefaults.cpp +++ b/gd32_emac_e131_dmx_multi/lib/factorydefaults.cpp @@ -28,7 +28,7 @@ #include "remoteconfig.h" #include "configstore.h" -#include "storenetwork.h" +#include "networkstore.h" namespace rdm { namespace device { @@ -37,7 +37,7 @@ namespace responder { void factorydefaults() { RemoteConfig::Get()->SetDisable(false); ConfigStore::Get()->ResetSetList(configstore::Store::RDMDEVICE); - StoreNetwork::Get()->SaveDhcp(true); + NetworkStore::SaveDhcp(true); } } // namespace responder diff --git a/gd32_emac_e131_dmx_multi/lib/rdmsoftwareversion.cpp b/gd32_emac_e131_dmx_multi/lib/rdmsoftwareversion.cpp index 5149f9a1..94271597 100644 --- a/gd32_emac_e131_dmx_multi/lib/rdmsoftwareversion.cpp +++ b/gd32_emac_e131_dmx_multi/lib/rdmsoftwareversion.cpp @@ -29,7 +29,7 @@ #include "rdmsoftwareversion.h" #include "software_version.h" -#include "sofware_version_id.h" +#include "software_version_id.h" const char *RDMSoftwareVersion::GetVersion() { return SOFTWARE_VERSION; diff --git a/gd32_emac_e131_dmx_multi/lib/showfileusb.cpp b/gd32_emac_e131_dmx_multi/lib/showfileusb.cpp new file mode 100644 index 00000000..657929f1 --- /dev/null +++ b/gd32_emac_e131_dmx_multi/lib/showfileusb.cpp @@ -0,0 +1,55 @@ +#if defined (NODE_SHOWFILE) +/** + * @file showfileusb.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "showfile.h" + +#include "debug.h" + +namespace showfile { +void usb_ready() { + DEBUG_ENTRY + + ShowFile::Get()->SetPlayerShowFileCurrent(ShowFile::Get()->GetShowFileCurrent()); + + if (ShowFile::Get()->IsAutoStart()) { + ShowFile::Get()->Play(); + } else { + ShowFile::Get()->LoadShows(); + } + + DEBUG_EXIT +} + +void usb_disconnected() { + DEBUG_ENTRY + + ShowFile::Get()->Stop(); + ShowFile::Get()->UnloadShows(); + + DEBUG_EXIT +} +} // namespace showfile +#endif diff --git a/gd32_emac_e131_pixel_multi/.cproject b/gd32_emac_e131_pixel_multi/.cproject index f0890e8f..37455288 100644 --- a/gd32_emac_e131_pixel_multi/.cproject +++ b/gd32_emac_e131_pixel_multi/.cproject @@ -31,11 +31,9 @@ - - diff --git a/gd32_emac_e131_pixel_multi/Makefile.GD32 b/gd32_emac_e131_pixel_multi/Makefile.GD32 index edd8d64a..f89876c0 100644 --- a/gd32_emac_e131_pixel_multi/Makefile.GD32 +++ b/gd32_emac_e131_pixel_multi/Makefile.GD32 @@ -8,6 +8,8 @@ DEFINES+=OUTPUT_DMX_PIXEL_MULTI PIXELPATTERNS_MULTI DEFINES+=ENET_RXBUF_NUM=34 ENET_TXBUF_NUM=2 DEFINES+=ENABLE_HTTPD ENABLE_CONTENT +DEFINES+=RTL8201F_LED1_LINK_ALL + DEFINES+=DISPLAY_UDF DEFINES+=DISABLE_RTC @@ -26,5 +28,6 @@ SRCDIR=firmware lib include ../firmware-template-gd32/Rules.mk prerequisites: - ./generate_sofware_version_id.sh + @echo "constexpr uint32_t DEVICE_SOFTWARE_VERSION_ID="$(shell date "+%s")";" > ./include/software_version_id.h + diff --git a/gd32_emac_e131_pixel_multi/firmware/main.cpp b/gd32_emac_e131_pixel_multi/firmware/main.cpp index ddc3689e..85fb1814 100644 --- a/gd32_emac_e131_pixel_multi/firmware/main.cpp +++ b/gd32_emac_e131_pixel_multi/firmware/main.cpp @@ -2,7 +2,7 @@ * @file main.cpp * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,16 +29,19 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" -#if defined (ENABLE_HTTPD) -# include "httpd/httpd.h" +#if defined (ENABLE_NTP_CLIENT) +# include "net/apps/ntpclient.h" +#endif + +#if defined (ENABLE_SHELL) +# include "shell/shell.h" #endif #include "displayudf.h" #include "displayudfparams.h" #include "displayhandler.h" -#include "display_timeout.h" #include "e131.h" #include "e131bridge.h" @@ -49,7 +52,7 @@ #include "pixeltype.h" #include "pixeltestpattern.h" #include "pixeldmxparams.h" -#include "pixeldmxstartstop.h" + #include "ws28xxmulti.h" #include "ws28xxdmxmulti.h" @@ -61,82 +64,65 @@ # include "rdm_e120.h" #endif +#if defined (NODE_SHOWFILE) +# include "showfile.h" +# include "showfileparams.h" +#endif + #include "remoteconfig.h" #include "remoteconfigparams.h" #include "configstore.h" -#include "storedisplayudf.h" -#include "storee131.h" -#include "storenetwork.h" -#if defined (NODE_RDMNET_LLRP_ONLY) -# include "storerdmdevice.h" -#endif -#include "storeremoteconfig.h" -#include "storepixeldmx.h" + #include "firmwareversion.h" #include "software_version.h" -static constexpr uint32_t DMXPORT_OFFSET = 32; +namespace e131bridge { +namespace configstore { +uint32_t DMXPORT_OFFSET = LIGHTSET_PORTS; +} // namespace configstore +} // namespace e131bridge void Hardware::RebootHandler() { WS28xxMulti::Get()->Blackout(); E131Bridge::Get()->Stop(); } -void main() { +int main() { Hardware hw; DisplayUdf display; ConfigStore configStore; - display.TextStatus(NetworkConst::MSG_NETWORK_INIT, Display7SegmentMessage::INFO_NETWORK_INIT, CONSOLE_YELLOW); - StoreNetwork storeNetwork; - Network nw(&storeNetwork); - display.TextStatus(NetworkConst::MSG_NETWORK_STARTED, Display7SegmentMessage::INFO_NONE, CONSOLE_GREEN); + display.TextStatus(NetworkConst::MSG_NETWORK_INIT, CONSOLE_YELLOW); + Network nw; + MDNS mDns; + display.TextStatus(NetworkConst::MSG_NETWORK_STARTED, CONSOLE_GREEN); FirmwareVersion fw(SOFTWARE_VERSION, __DATE__, __TIME__); - fw.Print("sACN E1.31 Pixel controller {8x 4 Universes}"); - nw.Print(); + fw.Print("sACN E1.31 Pixel controller"); - display.TextStatus(NetworkConst::MSG_MDNS_CONFIG, Display7SegmentMessage::INFO_MDNS_CONFIG, CONSOLE_YELLOW); - - MDNS mDns; - mDns.AddServiceRecord(nullptr, mdns::Services::CONFIG, "node=sACN E1.31 Pixel"); -#if defined (ENABLE_HTTPD) - mDns.AddServiceRecord(nullptr, mdns::Services::HTTP); -#endif - mDns.Print(); - -#if defined (ENABLE_HTTPD) - HttpDaemon httpDaemon; +#if defined (ENABLE_NTP_CLIENT) + NtpClient ntpClient; + ntpClient.Start(); + ntpClient.Print(); #endif - display.TextStatus(E131MsgConst::PARAMS, Display7SegmentMessage::INFO_BRIDGE_PARMAMS, CONSOLE_YELLOW); - - StoreE131 storeE131; - E131Params e131params(&storeE131); - E131Bridge bridge; - if (e131params.Load()) { - e131params.Dump(); - e131params.Set(DMXPORT_OFFSET); - } + E131Params e131params; + e131params.Load(); + e131params.Set(); PixelDmxConfiguration pixelDmxConfiguration; - StorePixelDmx storePixelDmx; - PixelDmxParams pixelDmxParams(&storePixelDmx); - - if (pixelDmxParams.Load()) { - pixelDmxParams.Dump(); - pixelDmxParams.Set(&pixelDmxConfiguration); - } + PixelDmxParams pixelDmxParams; + pixelDmxParams.Load(); + pixelDmxParams.Set(); - WS28xxDmxMulti pixelDmxMulti(pixelDmxConfiguration); - pixelDmxMulti.SetPixelDmxHandler(new PixelDmxStartStop); + WS28xxDmxMulti pixelDmxMulti; - const auto nUniverses = pixelDmxMulti.GetUniverses(); - const auto nActivePorts = pixelDmxMulti.GetOutputPorts(); + const auto nUniverses = pixelDmxConfiguration.GetUniverses(); + const auto nActivePorts = pixelDmxConfiguration.GetOutputPorts(); uint32_t nPortProtocolIndex = 0; @@ -163,9 +149,9 @@ void main() { } #if defined (NODE_RDMNET_LLRP_ONLY) - display.TextStatus(RDMNetConst::MSG_CONFIG, Display7SegmentMessage::INFO_RDMNET_CONFIG, CONSOLE_YELLOW); + display.TextStatus(RDMNetConst::MSG_CONFIG, CONSOLE_YELLOW); char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH + 1]; - snprintf(aDescription, sizeof(aDescription) - 1, "sACN Pixel %d-%s:%d", nActivePorts, PixelType::GetType(WS28xxMulti::Get()->GetType()), WS28xxMulti::Get()->GetCount()); + snprintf(aDescription, sizeof(aDescription) - 1, "sACN Pixel %d-%s:%d", nActivePorts, pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount()); char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH + 1]; const auto nLength = snprintf(aLabel, sizeof(aLabel) - 1, GD32_BOARD_NAME " Pixel"); @@ -178,42 +164,44 @@ void main() { llrpOnlyDevice.SetProductDetail(E120_PRODUCT_DETAIL_LED); llrpOnlyDevice.Init(); - StoreRDMDevice storeRdmDevice; - RDMDeviceParams rdmDeviceParams(&storeRdmDevice); - - if (rdmDeviceParams.Load()) { - rdmDeviceParams.Dump(); - rdmDeviceParams.Set(&llrpOnlyDevice); - } + RDMDeviceParams rdmDeviceParams; - llrpOnlyDevice.SetRDMDeviceStore(&storeRdmDevice); + rdmDeviceParams.Load(); + rdmDeviceParams.Set(&llrpOnlyDevice); + llrpOnlyDevice.Print(); #endif +#if defined (NODE_SHOWFILE) + ShowFile showFile; + + ShowFileParams showFileParams; + showFileParams.Load(); + showFileParams.Set(); + + showFile.Print(); +#endif + bridge.Print(); pixelDmxMulti.Print(); - display.SetTitle("sACN Pixel 8:%dx%d", nActivePorts, WS28xxMulti::Get()->GetCount()); + display.SetTitle("sACN Pixel 8:%dx%d", nActivePorts, pixelDmxConfiguration.GetCount()); display.Set(2, displayudf::Labels::IP); display.Set(3, displayudf::Labels::HOSTNAME); display.Set(4, displayudf::Labels::VERSION); - display.Set(5, displayudf::Labels::UNIVERSE_PORT_A); - display.Set(6, displayudf::Labels::BOARDNAME); + display.Set(5, displayudf::Labels::BOARDNAME); - StoreDisplayUdf storeDisplayUdf; - DisplayUdfParams displayUdfParams(&storeDisplayUdf); + DisplayUdfParams displayUdfParams; - if (displayUdfParams.Load()) { - displayUdfParams.Dump(); - displayUdfParams.Set(&display); - } + displayUdfParams.Load(); + displayUdfParams.Set(&display); - display.Show(&bridge); + display.Show(); display.Printf(7, "%s:%d G%d %s", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); if (nTestPattern != pixelpatterns::Pattern::NONE) { display.ClearLine(6); @@ -222,22 +210,24 @@ void main() { RemoteConfig remoteConfig(remoteconfig::Node::E131, remoteconfig::Output::PIXEL, bridge.GetActiveOutputPorts()); - StoreRemoteConfig storeRemoteConfig; - RemoteConfigParams remoteConfigParams(&storeRemoteConfig); - - if (remoteConfigParams.Load()) { - remoteConfigParams.Dump(); - remoteConfigParams.Set(&remoteConfig); - } + RemoteConfigParams remoteConfigParams; + remoteConfigParams.Load(); + remoteConfigParams.Set(&remoteConfig); while (configStore.Flash()) ; - display.TextStatus(E131MsgConst::START, Display7SegmentMessage::INFO_BRIDGE_START, CONSOLE_YELLOW); + mDns.Print(); + +#if defined (ENABLE_SHELL) + Shell shell; +#endif + + display.TextStatus(E131MsgConst::START, CONSOLE_YELLOW); bridge.Start(); - display.TextStatus(E131MsgConst::STARTED, Display7SegmentMessage::INFO_BRIDGE_STARTED, CONSOLE_GREEN); + display.TextStatus(E131MsgConst::STARTED, CONSOLE_GREEN); hw.WatchdogInit(); @@ -245,19 +235,25 @@ void main() { hw.WatchdogFeed(); nw.Run(); bridge.Run(); +#if defined (NODE_SHOWFILE) + showFile.Run(); +#endif remoteConfig.Run(); configStore.Flash(); if (__builtin_expect((pPixelTestPattern != nullptr), 0)) { pPixelTestPattern->Run(); } mDns.Run(); +#if defined (ENABLE_NTP_CLIENT) + ntpClient.Run(); +#endif #if defined (NODE_RDMNET_LLRP_ONLY) llrpOnlyDevice.Run(); -#endif -#if defined (ENABLE_HTTPD) - httpDaemon.Run(); #endif display.Run(); hw.Run(); +#if defined (ENABLE_SHELL) + shell.Run(); +#endif } } diff --git a/gd32_emac_e131_pixel_multi/generate_sofware_version_id.sh b/gd32_emac_e131_pixel_multi/generate_sofware_version_id.sh deleted file mode 100755 index 2f453f59..00000000 --- a/gd32_emac_e131_pixel_multi/generate_sofware_version_id.sh +++ /dev/null @@ -1,4 +0,0 @@ -echo "// Generated "$(date) > ./include/sofware_version_id.h -var="$(date +%s)" -echo "constexpr uint32_t DEVICE_SOFTWARE_VERSION_ID="$var";" >> ./include/sofware_version_id.h - diff --git a/gd32_emac_e131_pixel_multi/include/display_timeout.h b/gd32_emac_e131_pixel_multi/include/display_timeout.h deleted file mode 100644 index a8556629..00000000 --- a/gd32_emac_e131_pixel_multi/include/display_timeout.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @file display_timeout.h - * - */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef DISPLAY_TIMEOUT_H_ -#define DISPLAY_TIMEOUT_H_ - -#include "gd32.h" - -namespace display { -namespace timeout { - -void gpio_init() { - gpio_fsel(KEY2_GPIOx, KEY2_PINx, GPIO_FSEL_INPUT); -} - -bool gpio_renew() { - return (GPIO_ISTAT(KEY2_GPIOx) & KEY2_PINx) == 0; -} - -} // namespace timeout -} // namespace display - -#endif /* DISPLAY_TIMEOUT_H_ */ diff --git a/gd32_emac_e131_pixel_multi/include/sofware_version_id.h b/gd32_emac_e131_pixel_multi/include/sofware_version_id.h deleted file mode 100644 index 8aeaced5..00000000 --- a/gd32_emac_e131_pixel_multi/include/sofware_version_id.h +++ /dev/null @@ -1,2 +0,0 @@ -// Generated wo 18 okt 2023 15:47:45 CEST -constexpr uint32_t DEVICE_SOFTWARE_VERSION_ID=1697636865; diff --git a/gd32_emac_e131_pixel_multi/lib/factorydefaults.cpp b/gd32_emac_e131_pixel_multi/lib/factorydefaults.cpp index 971fc158..1741e5e2 100644 --- a/gd32_emac_e131_pixel_multi/lib/factorydefaults.cpp +++ b/gd32_emac_e131_pixel_multi/lib/factorydefaults.cpp @@ -28,7 +28,7 @@ #include "remoteconfig.h" #include "configstore.h" -#include "storenetwork.h" +#include "networkstore.h" namespace rdm { namespace device { @@ -37,7 +37,7 @@ namespace responder { void factorydefaults() { RemoteConfig::Get()->SetDisable(false); ConfigStore::Get()->ResetSetList(configstore::Store::RDMDEVICE); - StoreNetwork::Get()->SaveDhcp(true); + NetworkStore::SaveDhcp(true); } } // namespace responder diff --git a/gd32_emac_e131_pixel_multi/lib/rdmsoftwareversion.cpp b/gd32_emac_e131_pixel_multi/lib/rdmsoftwareversion.cpp index 5149f9a1..94271597 100644 --- a/gd32_emac_e131_pixel_multi/lib/rdmsoftwareversion.cpp +++ b/gd32_emac_e131_pixel_multi/lib/rdmsoftwareversion.cpp @@ -29,7 +29,7 @@ #include "rdmsoftwareversion.h" #include "software_version.h" -#include "sofware_version_id.h" +#include "software_version_id.h" const char *RDMSoftwareVersion::GetVersion() { return SOFTWARE_VERSION; diff --git a/gd32_emac_e131_pixel_multi/lib/showfileusb.cpp b/gd32_emac_e131_pixel_multi/lib/showfileusb.cpp new file mode 100644 index 00000000..657929f1 --- /dev/null +++ b/gd32_emac_e131_pixel_multi/lib/showfileusb.cpp @@ -0,0 +1,55 @@ +#if defined (NODE_SHOWFILE) +/** + * @file showfileusb.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "showfile.h" + +#include "debug.h" + +namespace showfile { +void usb_ready() { + DEBUG_ENTRY + + ShowFile::Get()->SetPlayerShowFileCurrent(ShowFile::Get()->GetShowFileCurrent()); + + if (ShowFile::Get()->IsAutoStart()) { + ShowFile::Get()->Play(); + } else { + ShowFile::Get()->LoadShows(); + } + + DEBUG_EXIT +} + +void usb_disconnected() { + DEBUG_ENTRY + + ShowFile::Get()->Stop(); + ShowFile::Get()->UnloadShows(); + + DEBUG_EXIT +} +} // namespace showfile +#endif diff --git a/gd32_emac_llrp/.cproject b/gd32_emac_llrp/.cproject new file mode 100644 index 00000000..20833c75 --- /dev/null +++ b/gd32_emac_llrp/.cproject @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gd32_rdm_responder/.project b/gd32_emac_llrp/.project similarity index 84% rename from gd32_rdm_responder/.project rename to gd32_emac_llrp/.project index 6bb46e37..b8bfa912 100644 --- a/gd32_rdm_responder/.project +++ b/gd32_emac_llrp/.project @@ -1,27 +1,32 @@ - - - gd32_rdm_responder - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - + + + gd32_emac_llrp + + + + + + org.python.pydev.PyDevBuilder + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/gd32_emac_llrp/.pydevproject b/gd32_emac_llrp/.pydevproject new file mode 100644 index 00000000..2b045655 --- /dev/null +++ b/gd32_emac_llrp/.pydevproject @@ -0,0 +1,5 @@ + + + Default + python interpreter + diff --git a/gd32_rdm_responder/.settings/language.settings.xml b/gd32_emac_llrp/.settings/language.settings.xml similarity index 89% rename from gd32_rdm_responder/.settings/language.settings.xml rename to gd32_emac_llrp/.settings/language.settings.xml index d0a369db..e562b391 100644 --- a/gd32_rdm_responder/.settings/language.settings.xml +++ b/gd32_emac_llrp/.settings/language.settings.xml @@ -1,6 +1,6 @@ - + diff --git a/lib-c++/.settings/org.eclipse.core.resources.prefs b/gd32_emac_llrp/.settings/org.eclipse.core.resources.prefs similarity index 100% rename from lib-c++/.settings/org.eclipse.core.resources.prefs rename to gd32_emac_llrp/.settings/org.eclipse.core.resources.prefs diff --git a/gd32_emac_llrp/Makefile.GD32 b/gd32_emac_llrp/Makefile.GD32 new file mode 100644 index 00000000..2867c983 --- /dev/null +++ b/gd32_emac_llrp/Makefile.GD32 @@ -0,0 +1,33 @@ +BOARD=BOARD_GD32F207RG +ENET_PHY=RTL8201F + +DEFINES =NODE_RDMNET_LLRP_ONLY + +DEFINES+=DISPLAY_UDF +DEFINES+=ENABLE_SSD1311 + +DEFINES+=ENABLE_HTTPD ENABLE_CONTENT + +DEFINES+=ENABLE_NTP_CLIENT + +DEFINES+=ENET_LINK_CHECK_REG_POLL +DEFINES+=RTL8201F_LED1_LINK_ALL + +DEFINES+=DISABLE_FS + +DEFINES+=DEBUG_ + +DEFINES+=DEBUG_NTP_CLIENT +DEFINES+=DEBUG_I2C +DEFINES+=DEBUG_STACK + +#DEFINES+=NDEBUG + +LIBS= + +SRCDIR=firmware lib + +include ../firmware-template-gd32/Rules.mk +prerequisites: + @echo "constexpr uint32_t DEVICE_SOFTWARE_VERSION_ID="$(shell date "+%s")";" > ./include/software_version_id.h + diff --git a/gd32_emac_llrp/firmware/main.cpp b/gd32_emac_llrp/firmware/main.cpp new file mode 100644 index 00000000..b246f0b7 --- /dev/null +++ b/gd32_emac_llrp/firmware/main.cpp @@ -0,0 +1,151 @@ +/** + * @file main.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if !defined (NODE_RDMNET_LLRP_ONLY) +# error +#endif + +#include +#include +#include + +#include "hardware.h" +#include "network.h" +#include "networkconst.h" + +#include "net/apps/mdns.h" + +#if defined (ENABLE_NTP_CLIENT) +# include "net/apps/ntpclient.h" +#endif + +#include "displayudf.h" +#include "displayudfparams.h" + +#include "configstore.h" + +#include "remoteconfig.h" +#include "remoteconfigparams.h" + +#include "rdmnetllrponly.h" +#include "factorydefaults.h" + +#include "firmwareversion.h" +#include "software_version.h" + +#include "debug.h" + +void Hardware::RebootHandler() { + HwClock::Get()->SysToHc(); +} + +int main() { + Hardware hw; + DisplayUdf display; + ConfigStore configStore; + display.TextStatus(NetworkConst::MSG_NETWORK_INIT, CONSOLE_YELLOW); + Network nw; + MDNS mDns; + display.TextStatus(NetworkConst::MSG_NETWORK_STARTED, CONSOLE_GREEN); + FirmwareVersion fw(SOFTWARE_VERSION, __DATE__, __TIME__); + + fw.Print("RDMNet LLRP device only"); + + +#if defined (ENABLE_NTP_CLIENT) + NtpClient ntpClient; + ntpClient.Start(); + ntpClient.Print(); +#endif + + RDMNetLLRPOnly device; + device.Init(); + device.Print(); + + RemoteConfig remoteConfig(remoteconfig::Node::RDMNET_LLRP_ONLY, remoteconfig::Output::CONFIG, 0); + + RemoteConfigParams remoteConfigParams; + remoteConfigParams.Load(); + remoteConfigParams.Set(&remoteConfig); + + while (configStore.Flash()) + ; + + mDns.Print(); + + display.SetTitle("LLRP Only - TFTP"); + display.Set(2, displayudf::Labels::HOSTNAME); + display.Set(3, displayudf::Labels::IP); + display.Set(4, displayudf::Labels::DEFAULT_GATEWAY); + display.Set(5, displayudf::Labels::VERSION); + + DisplayUdfParams displayUdfParams; + displayUdfParams.Load(); + displayUdfParams.Set(&display); + + display.Show(); + display.Write(6, "mDNS enabled"); + display.TextStatus("Device running", CONSOLE_GREEN); + + hw.SetMode(hardware::ledblink::Mode::NORMAL); + + hw.WatchdogInit(); + + auto nTime1 = time(nullptr); + + for (;;) { + hw.WatchdogFeed(); + nw.Run(); + mDns.Run(); + device.Run(); + remoteConfig.Run(); +#if defined (ENABLE_NTP_CLIENT) + ntpClient.Run(); +#endif + configStore.Flash(); + display.Run(); + hw.Run(); + + const auto nTime2 = time(nullptr); + + if (nTime1 != nTime2) { + nTime1 = nTime2; + + auto *tm = localtime(&nTime2); + struct tm tmlocal; + memcpy(&tmlocal, tm, sizeof(struct tm)); + + struct tm tmHwClock; + HwClock::Get()->Get(&tmHwClock); + + display.Printf(7, "%.2d:%.2d:%.2d %.2d:%.2d:%.2d", + tmlocal.tm_hour, tmlocal.tm_min, tmlocal.tm_sec, + tmHwClock.tm_hour, tmHwClock.tm_min, tmHwClock.tm_sec); + printf("%.2d:%.2d:%.2d %.2d:%.2d:%.2d\n", + tmlocal.tm_hour, tmlocal.tm_min, tmlocal.tm_sec, + tmHwClock.tm_hour, tmHwClock.tm_min, tmHwClock.tm_sec); + } + } +} diff --git a/gd32_rdm_responder/lib/factorydefaults.cpp b/gd32_emac_llrp/include/factorydefaults.h similarity index 86% rename from gd32_rdm_responder/lib/factorydefaults.cpp rename to gd32_emac_llrp/include/factorydefaults.h index 5d72733b..9d9111a3 100644 --- a/gd32_rdm_responder/lib/factorydefaults.cpp +++ b/gd32_emac_llrp/include/factorydefaults.h @@ -1,8 +1,8 @@ /** - * @file factorydefaults.cpp + * @file factorydefaults.h * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,14 +26,18 @@ #ifndef FACTORYDEFAULTS_H_ #define FACTORYDEFAULTS_H_ +#include "remoteconfig.h" #include "configstore.h" +#include "networkstore.h" namespace rdm { namespace device { namespace responder { void factorydefaults() { + RemoteConfig::Get()->SetDisable(false); ConfigStore::Get()->ResetSetList(configstore::Store::RDMDEVICE); + NetworkStore::SaveDhcp(true); } } // namespace responder diff --git a/gd32_rdm_responder/lib/rdmsoftwareversion.cpp b/gd32_emac_llrp/lib/rdmsoftwareversion.cpp similarity index 96% rename from gd32_rdm_responder/lib/rdmsoftwareversion.cpp rename to gd32_emac_llrp/lib/rdmsoftwareversion.cpp index 2e5b2a03..82d38bc4 100644 --- a/gd32_rdm_responder/lib/rdmsoftwareversion.cpp +++ b/gd32_emac_llrp/lib/rdmsoftwareversion.cpp @@ -23,12 +23,12 @@ * THE SOFTWARE. */ -#include +#include #include "rdmsoftwareversion.h" #include "software_version.h" -#include "sofware_version_id.h" +#include "software_version_id.h" const char *RDMSoftwareVersion::GetVersion() { return SOFTWARE_VERSION; diff --git a/gd32_emac_pp_pixel_multi/.cproject b/gd32_emac_pp_pixel_multi/.cproject index 80b61de7..7fd357a0 100755 --- a/gd32_emac_pp_pixel_multi/.cproject +++ b/gd32_emac_pp_pixel_multi/.cproject @@ -31,14 +31,12 @@ - @@ -54,19 +56,21 @@ - + + @@ -87,9 +91,10 @@ - + + diff --git a/lib-artnet/Rules.mk b/lib-artnet/Rules.mk old mode 100644 new mode 100755 index e9d9ac2d..03b0003c --- a/lib-artnet/Rules.mk +++ b/lib-artnet/Rules.mk @@ -1,3 +1,5 @@ +EXTRA_INCLUDES+=../lib-lightset/include ../lib-properties/include ../lib-network/include + ifneq ($(MAKE_FLAGS),) ifeq ($(findstring NODE_ARTNET,$(MAKE_FLAGS)), NODE_ARTNET) EXTRA_SRCDIR+=src/node @@ -7,14 +9,17 @@ ifneq ($(MAKE_FLAGS),) EXTRA_SRCDIR+=src/node/dmxin EXTRA_INCLUDES+=../lib-dmx/include endif + ifeq ($(findstring RDM_CONTROLLER,$(MAKE_FLAGS)), RDM_CONTROLLER) EXTRA_SRCDIR+=src/node/rdm + EXTRA_SRCDIR+=src/node/rdm/controller + EXTRA_INCLUDES+=../lib-rdm/include ../lib-dmx/include endif + ifeq ($(findstring RDM_RESPONDER,$(MAKE_FLAGS)), RDM_RESPONDER) EXTRA_SRCDIR+=src/node/rdm - endif - ifeq ($(findstring ARTNET_HAVE_TIMECODE,$(MAKE_FLAGS)), ARTNET_HAVE_TIMECODE) - EXTRA_SRCDIR+=src/node/timecode + EXTRA_SRCDIR+=src/node/rdm/responder + EXTRA_INCLUDES+=../lib-rdm/include endif ifeq ($(findstring ARTNET_CONTROLLER,$(MAKE_FLAGS)), ARTNET_CONTROLLER) @@ -34,13 +39,21 @@ ifneq ($(MAKE_FLAGS),) EXTRA_SRCDIR+=src/node/4 EXTRA_INCLUDES+=../lib-e131/include endif + + ifeq ($(findstring OUTPUT_DMX_SEND,$(MAKE_FLAGS)), OUTPUT_DMX_SEND) + EXTRA_INCLUDES+=../lib-dmx/include + endif + + ifneq (,$(findstring CONFIG_STORE_USE_ROM,$(MAKE_FLAGS))) + EXTRA_INCLUDES+=../lib-flashcode/include + endif else - EXTRA_SRCDIR+=src/node src/node/failsafe src/node/dmxin src/node/rdm src/node/timecode - EXTRA_SRCDIR+=src/controller + EXTRA_SRCDIR+=src/node src/node/failsafe src/node/dmxin src/node/rdm src/node/rdm/controller src/node/timecode EXTRA_SRCDIR+=src/node/4 EXTRA_INCLUDES+=src/node/failsafe EXTRA_INCLUDES+=../lib-e131/include EXTRA_INCLUDES+=../lib-dmx/include + EXTRA_INCLUDES+=../lib-rdm/include DEFINES+=ARTNET_HAVE_TIMECODE DEFINES+=ARTNET_HAVE_FAILSAFE_RECORD DEFINES+=ARTNET_HAVE_DMXIN E131_HAVE_DMXIN @@ -50,4 +63,6 @@ else DEFINES+=RDM_CONTROLLER DEFINES+=ARTNET_VERSION=4 DEFINES+=LIGHTSET_PORTS=1 + DEFINES+=NODE_SHOWFILE + DEFINES+=CONFIG_SHOWFILE_PROTOCOL_NODE_ARTNET endif \ No newline at end of file diff --git a/lib-artnet/include/artnet.h b/lib-artnet/include/artnet.h index 0157144d..4e17fb1a 100644 --- a/lib-artnet/include/artnet.h +++ b/lib-artnet/include/artnet.h @@ -5,7 +5,7 @@ /** * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. */ -/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -62,6 +62,34 @@ enum class PortProtocol { SACN ///< Output DMX512 data from the sACN protocol and RDM data from the Art-Net protocol. }; +/** + * Table 3 – NodeReport Codes + * The NodeReport code defines generic error, advisory and status messages for both Nodes and Controllers. + * The NodeReport is returned in ArtPollReply. + */ +enum class ReportCode : uint8_t { + RCDEBUG, + RCPOWEROK, + RCPOWERFAIL, + RCSOCKETWR1, + RCPARSEFAIL, + RCUDPFAIL, + RCSHNAMEOK, + RCLONAMEOK, + RCDMXERROR, + RCDMXUDPFULL, + RCDMXRXFULL, + RCSWITCHERR, + RCCONFIGERR, + RCDMXSHORT, + RCFIRMWAREFAIL, + RCUSERFAIL +}; + +enum class Status : uint8_t { + OFF, STANDBY, ON +}; + /** * Table 4 – Style Codes * The Style code defines the general functionality of a Controller. @@ -171,6 +199,14 @@ struct PortCommand { static constexpr uint8_t RDM_DISABLE3 = 0xd3; ///< Disable RDM on output port 3 }; +struct TodControlCommand { + static constexpr uint8_t ATC_NONE = 0x00; ///< No action. + static constexpr uint8_t ATC_FLUSH = 0x01; ///< The port flushes its TOD and instigates full discovery. + static constexpr uint8_t ATC_END = 0x02; ///< The port ends current discovery but does not flush ToD. + static constexpr uint8_t ATC_INCON = 0x03; ///< The port enables incremental discovery. + static constexpr uint8_t ATC_INCOFF = 0x04; ///< The port disables incremental discovery. +}; + struct Program { static constexpr uint8_t NO_CHANGE = 0x7F; static constexpr uint8_t DEFAULTS = 0x00; @@ -211,16 +247,19 @@ struct Status2 { }; struct Status3 { - static constexpr uint8_t NETWORKLOSS_MASK = (3U << 6); ///< bit 76 - static constexpr uint8_t NETWORKLOSS_LAST_STATE = (0 << 6); ///< bit 76 = 00 If network data is lost, it will hold last state - static constexpr uint8_t NETWORKLOSS_OFF_STATE = (1U << 6); ///< bit 76 = 01 If network data is lost, it will set all outputs to off state - static constexpr uint8_t NETWORKLOSS_ON_STATE = (2U << 6); ///< bit 76 = 10 If network data is lost, it will set all outputs to full on - static constexpr uint8_t NETWORKLOSS_PLAYBACK = (3U << 6); ///< bit 76 = 11 If network data is lost, it will playback the fail-over scene - static constexpr uint8_t FAILSAFE_NO_CONTROL = (0 << 5); ///< bit 5 = 0 Node is not able to control failsafe mode by ArtCommand - static constexpr uint8_t FAILSAFE_CONTROL = (1U << 5); ///< bit 5 = 1 Node is able to control failsafe mode by ArtCommand - static constexpr uint8_t SUPPORTS_LLRP = (1U << 4); ///< bit 4 = 1 Node supports LLRP (Low Level Recovery Protocol - static constexpr uint8_t OUTPUT_NO_SWITCH = (0 << 3); ///< bit 3 = 0 Outputs cannot be switched to an input - static constexpr uint8_t OUTPUT_SWITCH = (1U << 3); ///< bit 3 = 1 Outputs can be switched to an input + static constexpr uint8_t NETWORKLOSS_MASK = (3U << 6); ///< bit 76 + static constexpr uint8_t NETWORKLOSS_LAST_STATE = (0 << 6); ///< bit 76 = 00 If network data is lost, it will hold last state + static constexpr uint8_t NETWORKLOSS_OFF_STATE = (1U << 6); ///< bit 76 = 01 If network data is lost, it will set all outputs to off state + static constexpr uint8_t NETWORKLOSS_ON_STATE = (2U << 6); ///< bit 76 = 10 If network data is lost, it will set all outputs to full on + static constexpr uint8_t NETWORKLOSS_PLAYBACK = (3U << 6); ///< bit 76 = 11 If network data is lost, it will playback the fail-over scene + static constexpr uint8_t FAILSAFE_NO_CONTROL = (0 << 5); ///< bit 5 = 0 Node is not able to control failsafe mode by ArtCommand + static constexpr uint8_t FAILSAFE_CONTROL = (1U << 5); ///< bit 5 = 1 Node is able to control failsafe mode by ArtCommand + static constexpr uint8_t SUPPORTS_LLRP = (1U << 4); ///< bit 4 = 1 Node supports LLRP (Low Level Recovery Protocol + static constexpr uint8_t OUTPUT_NO_SWITCH = (0 << 3); ///< bit 3 = 0 Outputs cannot be switched to an input + static constexpr uint8_t OUTPUT_SWITCH = (1U << 3); ///< bit 3 = 1 Outputs can be switched to an input + static constexpr uint8_t SUPPORTS_RDMNET = (1U << 2); ///< bit 2 = 1 Node supports RDMnet + static constexpr uint8_t SUPPORTS_BACKGROUNDQUEUE = (1U << 1); ///< bit 1 = 1 BackgroundQueue is supported + static constexpr uint8_t SUPPORTS_BACKGROUNDDISCOVERY = (1U << 0); ///< bit 0 = 1 Programmable background discovery is supported. }; struct Flags { @@ -253,6 +292,10 @@ struct GoodOutputB { static constexpr uint8_t RDM_ENABLED = (0 << 7); ///< bit 7 = 0 RDM is enabled. static constexpr uint8_t STYLE_CONSTANT = (1U << 6); ///< bit 6 = 1 Output style is continuous. static constexpr uint8_t STYLE_DELTA = (0 << 6); ///< bit 6 = 0 Output style is delta. + static constexpr uint8_t DISCOVERY_NOT_RUNNING = (1U << 5); ///< bit 5 = 1 Discovery is currently not running. + static constexpr uint8_t DISCOVERY_IS_RUNNING = (0 << 5); ///< bit 5 = 0 Discovery is currently running. + static constexpr uint8_t DISCOVERY_DISABLED = (1U << 4); ///< bit 4 = 1 Background discovery is disabled. + static constexpr uint8_t DISCOVERY_ENABLED = (0 << 4); ///< bit 4 = 0 Background Discovery is enabled. }; struct GoodInput { @@ -312,6 +355,7 @@ enum class OpCodes: uint16_t { OP_TODDATA = 0x8100, ///< This is an ArtTodData packet. It is used to send a Table of Devices (ToD) for RDM discovery. OP_TODCONTROL = 0x8200, ///< This is an ArtTodControl packet. It is used to send RDM discovery control messages OP_RDM = 0x8300, ///< This is an ArtRdm packet. It is used to send all non discovery RDM messages. + OP_RDMSUB = 0x8400, ///< This is an ArtRdmSub packet. It is used to send compressed, RDM Sub-Device data. OP_TIMECODE = 0x9700, ///< This is an ArtTimeCode packet. It is used to transport time code over the network. OP_TIMESYNC = 0x9800, ///< Used to synchronize real time date and clock OP_TRIGGER = 0x9900, ///< Used to send trigger macros @@ -372,7 +416,15 @@ struct ArtPollReply { uint8_t GoodOutputB[artnet::PORTS]; ///< This array defines output status of the node. uint8_t Status3; ///< General Status register uint8_t DefaultUidResponder[6]; ///< RDMnet & LLRP UID - uint8_t Filler[15]; ///< Transmit as zero. For future expansion. + uint8_t UserHi; ///< Available for user specific data + uint8_t UserLo; ///< Available for user specific data + uint8_t RefreshRateHi; ///< Hi byte of RefreshRate + uint8_t RefreshRateLo; ///< Lo Byte of RefreshRate. + ///< RefreshRate allows the device to specify the maximum refresh rate, expressed in Hz, at which it can process ArtDmx. + ///< This is designed to allow refresh rates above DMX512 rates, for gateways that implement other protocols such as SPI. + ///< A value of 0 to 44 represents the maximum DMX512 rate of 44Hz. + uint8_t BackgroundQueuePolicy; ///< The BackgroundQueuePolicy defines the method by with the node retrieves STATUS_MESSAGE and QUEUED_MESSAGE pids from the connected RDM devices. + uint8_t Filler[10]; ///< Transmit as zero. For future expansion. }PACKED; /** @@ -592,7 +644,30 @@ struct ArtRdm { uint8_t Net; ///< The top 7 bits of the 15 bit Port-Address of Nodes that must respond to this packet. uint8_t Command; ///< 0x00 ArProcess Process RDM Packet0x00 AtcNone No action. 0x01 AtcFlush The node flushes its TOD and instigates full discovery. uint8_t Address; ///< The low 8 bits of the Port-Address that should action this command. - uint8_t RdmPacket[255]; ///< The RDM data packet excluding the DMX StartCode. + uint8_t RdmPacket[256]; ///< The RDM data packet excluding the DMX StartCode with Checksum +}PACKED; + +/** + * The ArtRdmSub packet is used to transfer Get, Set, GetResponse and SetResponse data to and from multiple sub-devices within an RDM device. + */ +struct ArtRdmSub { + uint8_t Id[8]; ///< Array of 8 characters, the final character is a null termination. Value = ‘A’ ‘r’ ‘t’ ‘-‘ ‘N’ ‘e’ ‘t’ 0x00 + uint16_t OpCode; ///< OpAddress \ref TOpCodes + uint8_t ProtVerHi; ///< High byte of the Art-Net protocol revision number. + uint8_t ProtVerLo; ///< Low byte of the Art-Net protocol revision number. Current value 14. + uint8_t RdmVer; ///< Art-Net Devices that only support RDM DRAFT V1.0 set field to 0x00. Devices that support RDM STANDARD V1.0 set field to 0x01. + uint8_t Filler2; ///< Transmit as zero, receivers don’t test. + uint8_t UID[6]; ///< UID of target RDM device. + uint8_t Spare1; ///< Transmit as zero, receivers don’t test. + uint8_t CommandClass; ///< As per RDM specification. This field defines whether this is a Get, Set, GetResponse, SetResponse. + uint8_t ParameterId[2]; ///< As per RDM specification. This field defines the type of parameter contained in this packet. Big- endian. + uint8_t SubDevice[2]; ///< Defines the first device information contained in packet. This follows the RDM convention that 0 = root device and 1 = first subdevice. Big-endian. + uint8_t SubCount[2]; ///< The number of sub devices packed into packet. Zero is illegal. Big-endian. + uint8_t Spare2; ///< Transmit as zero, receivers don’t test. + uint8_t Spare3; ///< Transmit as zero, receivers don’t test. + uint8_t Spare4; ///< Transmit as zero, receivers don’t test. + uint8_t Spare5; ///< Transmit as zero, receivers don’t test. + uint8_t Data[231]; }PACKED; struct ArtIpProg { @@ -711,6 +786,15 @@ union UArtPacket { struct ArtDirectory ArtDirectory; ///< ArtDirectory packet struct ArtDirectoryReply ArtDirectoryReply;///< ArtDirectoryReply packet }; + +struct ArtPollQueue { + uint32_t ArtPollMillis; + uint32_t ArtPollReplyIpAddress; + struct { + uint16_t TargetPortAddressTop; + uint16_t TargetPortAddressBottom; + } ArtPollReply; +}; } // namespace artnet #endif /* ARTNET_H_ */ diff --git a/lib-artnet/include/artnetconst.h b/lib-artnet/include/artnetconst.h index a895d239..90ff54c9 100644 --- a/lib-artnet/include/artnetconst.h +++ b/lib-artnet/include/artnetconst.h @@ -5,7 +5,7 @@ /** * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. */ -/* Copyright (C) 2019-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-artnet/include/artnetcontroller.h b/lib-artnet/include/artnetcontroller.h index 8141b95e..689bc292 100644 --- a/lib-artnet/include/artnetcontroller.h +++ b/lib-artnet/include/artnetcontroller.h @@ -5,7 +5,7 @@ /** * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. */ -/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -41,6 +41,15 @@ #define DMX_MAX_VALUE 255 #endif +struct State { + uint32_t ArtPollIpAddress; + uint32_t ArtPollReplyCount; + uint32_t ArtPollReplyDelayMillis; + artnet::ArtPollQueue ArtPollReplyQueue[4]; + artnet::ReportCode reportCode; + artnet::Status status; +}; + struct TArtNetController { uint32_t nIPAddressLocal; uint32_t nIPAddressBroadcast; @@ -52,6 +61,12 @@ class ArtNetController: public ArtNetPollTable { ArtNetController(); ~ArtNetController(); + void GetShortNameDefault(char *pShortName); + void SetShortName(const char *pShortName); + + void GetLongNameDefault(char *pLongName); + void SetLongName(const char *pLongName); + void Start(); void Stop(); void Run(); @@ -62,24 +77,32 @@ class ArtNetController: public ArtNetPollTable { void HandleSync(); void HandleBlackout(); - void SetRunTableCleanup(bool bDoTableCleanup) { + void SetRunTableCleanup(const bool bDoTableCleanup) { m_bDoTableCleanup = bDoTableCleanup; } - void SetSynchronization(bool bSynchronization) { + void SetSynchronization(const bool bSynchronization) { m_bSynchronization = bSynchronization; } bool GetSynchronization() const { return m_bSynchronization; } - void SetUnicast(bool bUnicast) { + void SetUnicast(const bool bUnicast) { m_bUnicast = bUnicast; } bool GetUnicast() const { return m_bUnicast; } + void SetForceBroadcast(const bool bForceBroadcast) { + m_bForceBroadcast = bForceBroadcast; + } + bool GetForceBroadcast() const { + return m_bForceBroadcast; + } + +#ifdef CONFIG_ARTNET_CONTROLLER_ENABLE_MASTER void SetMaster(uint32_t nMaster = DMX_MAX_VALUE) { if (nMaster < DMX_MAX_VALUE) { m_nMaster = nMaster; @@ -90,6 +113,7 @@ class ArtNetController: public ArtNetPollTable { uint32_t GetMaster() const { return m_nMaster; } +#endif // Handler void SetArtNetTrigger(ArtNetTrigger *pArtNetTrigger) { @@ -106,6 +130,7 @@ class ArtNetController: public ArtNetPollTable { } private: + void ProcessPoll(); void HandlePoll(); void HandlePollReply(); void HandleTrigger(); @@ -113,10 +138,8 @@ class ArtNetController: public ArtNetPollTable { void ActiveUniversesClear(); private: - struct TArtNetController m_tArtNetController; - bool m_bSynchronization { true }; - bool m_bUnicast { true }; - int32_t m_nHandle { -1 }; + TArtNetController m_ArtNetController; + State m_State; struct TArtNetPacket { union artnet::UArtPacket ArtPacket; @@ -125,17 +148,27 @@ class ArtNetController: public ArtNetPollTable { artnet::OpCodes OpCode; }; - struct TArtNetPacket *m_pArtNetPacket; artnet::ArtPoll m_ArtNetPoll; + artnet::ArtPollReply m_ArtPollReply; + + TArtNetPacket *m_pArtNetPacket; + artnet::ArtDmx *m_pArtDmx; artnet::ArtSync *m_pArtSync; ArtNetTrigger *m_pArtNetTrigger { nullptr }; // Trigger handler - uint32_t m_nLastPollMillis { 0 }; + + bool m_bSynchronization { true }; + bool m_bUnicast { true }; + bool m_bForceBroadcast { false }; bool m_bDoTableCleanup { true }; bool m_bDmxHandled { false }; + + int32_t m_nHandle { -1 }; + uint32_t m_nLastPollMillis { 0 }; uint32_t m_nActiveUniverses { 0 }; +#ifdef CONFIG_ARTNET_CONTROLLER_ENABLE_MASTER uint32_t m_nMaster { DMX_MAX_VALUE }; - +#endif static ArtNetController *s_pThis; }; diff --git a/lib-artnet/include/artnetmsgconst.h b/lib-artnet/include/artnetmsgconst.h index d82df31b..18c540ee 100644 --- a/lib-artnet/include/artnetmsgconst.h +++ b/lib-artnet/include/artnetmsgconst.h @@ -2,10 +2,7 @@ * @file artnetmsgconst.h * */ -/** - * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. - */ -/* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,7 +28,6 @@ class ArtNetMsgConst { public: - static const char PARAMS[]; static const char START[]; static const char STARTED[]; static const char RDM_RUN[]; diff --git a/lib-artnet/include/artnetnode.h b/lib-artnet/include/artnetnode.h old mode 100644 new mode 100755 index 7b354711..566fc61c --- a/lib-artnet/include/artnetnode.h +++ b/lib-artnet/include/artnetnode.h @@ -5,7 +5,7 @@ /** * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. */ -/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,8 +30,8 @@ #define ARTNETNODE_H_ #include -#include #include +#include #include #include @@ -45,85 +45,58 @@ # endif #endif +#if defined (NODE_SHOWFILE) && defined (CONFIG_SHOWFILE_PROTOCOL_NODE_ARTNET) +# define ARTNET_SHOWFILE +#endif + #include "artnet.h" +#include "artnetnode_ports.h" #include "artnettimecode.h" -#include "artnetrdm.h" -#include "artnetstore.h" #include "artnetdisplay.h" #include "artnettrigger.h" - +#if defined (RDM_CONTROLLER) +# include "artnetrdmcontroller.h" +#endif +#if defined (RDM_RESPONDER) +# include "artnetrdmresponder.h" +#endif #if (ARTNET_VERSION >= 4) # include "e131bridge.h" #endif +#if defined(OUTPUT_DMX_SEND) || defined(OUTPUT_DMX_SEND_MULTI) +# if !defined(ARTNET_DISABLE_DMX_CONFIG_UDP) +# include "dmxconfigudp.h" +# endif +#endif + #include "lightset.h" #include "hardware.h" #include "network.h" -#include "debug.h" +#include "panel_led.h" -namespace artnetnode { -#if !defined(LIGHTSET_PORTS) -# define LIGHTSET_PORTS 0 -#endif +#include "debug.h" -#if (LIGHTSET_PORTS == 0) - static constexpr uint32_t MAX_PORTS = 1; // ISO C++ forbids zero-size array -#else - static constexpr uint32_t MAX_PORTS = LIGHTSET_PORTS; +#ifndef ALIGNED +# define ALIGNED __attribute__ ((aligned (4))) #endif +namespace artnetnode { enum class FailSafe : uint8_t { LAST = 0x08, OFF= 0x09, ON = 0x0a, PLAYBACK = 0x0b, RECORD = 0x0c }; -/** - * Table 3 – NodeReport Codes - * The NodeReport code defines generic error, advisory and status messages for both Nodes and Controllers. - * The NodeReport is returned in ArtPollReply. - */ -enum class ReportCode : uint8_t { - RCDEBUG, - RCPOWEROK, - RCPOWERFAIL, - RCSOCKETWR1, - RCPARSEFAIL, - RCUDPFAIL, - RCSHNAMEOK, - RCLONAMEOK, - RCDMXERROR, - RCDMXUDPFULL, - RCDMXRXFULL, - RCSWITCHERR, - RCCONFIGERR, - RCDMXSHORT, - RCFIRMWAREFAIL, - RCUSERFAIL -}; - -enum class Status : uint8_t { - OFF, STANDBY, ON -}; - -struct ArtPollQueue { - uint32_t ArtPollMillis; - uint32_t ArtPollReplyIpAddress; - struct { - uint16_t TargetPortAddressTop; - uint16_t TargetPortAddressBottom; - } ArtPollReply; -}; - struct State { uint32_t ArtDiagIpAddress; uint32_t ArtPollIpAddress; uint32_t ArtPollReplyCount; uint32_t ArtPollReplyDelayMillis; - ArtPollQueue ArtPollReplyQueue[4]; uint32_t ArtDmxIpAddress; uint32_t ArtSyncMillis; ///< Latest ArtSync received time - ReportCode reportCode; - Status status; + artnet::ArtPollQueue ArtPollReplyQueue[4]; + artnet::ReportCode reportCode; + artnet::Status status; bool SendArtPollReplyOnChange; ///< ArtPoll : Flags Bit 1 : 1 = Send ArtPollReply whenever Node conditions change. bool SendArtDiagData; ///< ArtPoll : Flags Bit 2 : 1 = Send me diagnostics messages. bool IsMultipleControllersReqDiag; ///< ArtPoll : Multiple controllers requesting diagnostics @@ -131,18 +104,21 @@ struct State { bool IsMergeMode; bool IsChanged; bool bDisableMergeTimeout; + bool DoRecord; uint8_t nReceivingDmx; uint8_t nEnabledOutputPorts; uint8_t nEnabledInputPorts; uint8_t DiagPriority; ///< ArtPoll : Field 6 : The lowest priority of diagnostics message that should be sent. + struct { + uint32_t nDiscoveryMillis; + uint32_t nDiscoveryPortIndex; + bool IsDiscoveryRunning; + bool IsEnabled; + } rdm; }; struct Node { - uint32_t IPAddressTimeCode; - bool IsRdmResponder; - bool bMapUniverse0; ///< Art-Net 4 struct { - char ShortName[artnet::SHORT_NAME_LENGTH]; uint16_t PortAddress; ///< The Port-Address is a 15 bit number composed of Net+Sub-Net+Universe. uint8_t DefaultAddress; uint8_t NetSwitch; ///< Bits 14-8 of the 15 bit Port-Address are encoded into the bottom 7 bits of this field. @@ -150,7 +126,11 @@ struct Node { lightset::PortDir direction; artnet::PortProtocol protocol; ///< Art-Net 4 bool bLocalMerge; - } Port[artnetnode::MAX_PORTS]; + char ShortName[artnet::SHORT_NAME_LENGTH] ALIGNED; + } Port[artnetnode::MAX_PORTS] ALIGNED; + + uint32_t IPAddressTimeCode; + bool bMapUniverse0; ///< Art-Net 4 }; struct Source { @@ -160,8 +140,9 @@ struct Source { }; struct OutputPort { - Source SourceA; - Source SourceB; + Source SourceA ALIGNED; + Source SourceB ALIGNED; + uint32_t nIpRdm; uint8_t GoodOutput; uint8_t GoodOutputB; uint8_t nPollReplyIndex; @@ -178,15 +159,19 @@ struct InputPort { }; inline artnetnode::FailSafe convert_failsafe(const lightset::FailSafe failsafe) { - const auto fs = static_cast(static_cast(failsafe) + static_cast(FailSafe::LAST)); - DEBUG_PRINTF("failsafe=%u, fs=%u", static_cast(failsafe), static_cast(fs)); - return fs; + if (failsafe > lightset::FailSafe::PLAYBACK) { + return artnetnode::FailSafe::LAST; + } + + return static_cast(static_cast(failsafe) + static_cast(artnetnode::FailSafe::LAST)); } inline lightset::FailSafe convert_failsafe(const artnetnode::FailSafe failsafe) { - const auto fs = static_cast(static_cast(failsafe) - static_cast(FailSafe::LAST)); - DEBUG_PRINTF("failsafe=%u, fs=%u", static_cast(failsafe), static_cast(fs)); - return fs; + if (failsafe > artnetnode::FailSafe::RECORD) { + return lightset::FailSafe::HOLD; + } + + return static_cast(static_cast(failsafe) - static_cast(artnetnode::FailSafe::LAST)); } } // namespace artnetnode @@ -204,7 +189,7 @@ class ArtNetNode { void Run() { uint16_t nForeignPort; - const auto nBytesReceived = Network::Get()->RecvFrom(m_nHandle, const_cast(reinterpret_cast(&m_pReceiveBuffer)), &m_nIpAddressFrom, &nForeignPort); + const auto nBytesReceived = Network::Get()->RecvFrom(m_nHandle, const_cast(reinterpret_cast(&m_pReceiveBuffer)), &m_nIpAddressFrom, &nForeignPort); m_nCurrentPacketMillis = Hardware::Get()->Millis(); Process(nBytesReceived); @@ -212,15 +197,84 @@ class ArtNetNode { #if (ARTNET_VERSION >= 4) E131Bridge::Run(); #endif -#if defined (LIGHTSET_HAVE_RUN) - m_pLightSet->Run(); +#if defined (RDM_CONTROLLER) + if (__builtin_expect((m_State.rdm.IsEnabled), 0)) { + assert(m_pArtNetRdmController != nullptr); + m_pArtNetRdmController->Run(); + + if (__builtin_expect((!m_State.rdm.IsDiscoveryRunning && ((m_nCurrentPacketMillis - m_State.rdm.nDiscoveryMillis) > (1000 * 60 * 15))), 0)) { + DEBUG_PUTS("RDM Discovery -> START"); + m_State.rdm.IsDiscoveryRunning = true; + } + + if (__builtin_expect((m_State.rdm.IsDiscoveryRunning), 0)) { + m_State.rdm.IsDiscoveryRunning = RdmDiscoveryRun(); + + if (!m_State.rdm.IsDiscoveryRunning) { + DEBUG_PUTS("RDM Discovery -> DONE"); + m_State.rdm.nDiscoveryPortIndex = 0; + m_State.rdm.nDiscoveryMillis = m_nCurrentPacketMillis; + } + } else { + uint32_t nPortIndex; + bool bIsIncremental; + if (m_pArtNetRdmController->IsFinished(nPortIndex, bIsIncremental)) { + SendTod(nPortIndex); + + DEBUG_PRINTF("TOD sent -> %u", static_cast(nPortIndex)); + + if (m_OutputPort[nPortIndex].IsTransmitting) { + DEBUG_PUTS("m_pLightSet->Stop/Start"); + m_pLightSet->Stop(nPortIndex); + m_pLightSet->Start(nPortIndex); + } + } + } + } +#endif + if ((m_nCurrentPacketMillis - m_nPreviousLedpanelMillis) > 200) { + m_nPreviousLedpanelMillis = m_nCurrentPacketMillis; + for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { + hal::panel_led_off(hal::panelled::PORT_A_TX << nPortIndex); +#if defined (ARTNET_HAVE_DMXIN) + hal::panel_led_off(hal::panelled::PORT_A_RX << nPortIndex); +#endif +#if defined(CONFIG_PANELLED_RDM_PORT) + hal::panel_led_off(hal::panelled::PORT_A_RDM << nPortIndex); +#elif defined(CONFIG_PANELLED_RDM_NO_PORT) + hal::panel_led_off(hal::panelled::RDM << nPortIndex); +#endif + } + } + +#if defined (DMXCONFIGUDP_H) + m_DmxConfigUdp.Run(); #endif } +#if defined (ARTNET_SHOWFILE) + void HandleShowFile(const artnet::ArtDmx *pArtDmx) { + m_nCurrentPacketMillis = Hardware::Get()->Millis(); + m_nIpAddressFrom = Network::Get()->GetIp(); + m_pReceiveBuffer = reinterpret_cast(const_cast(pArtDmx)); + HandleDmx(); + } +#endif + + void SetRecordShowfile(const bool doRecord) { + m_State.DoRecord = doRecord; + } + bool GetRecordShowfile() const { + return m_State.DoRecord; + } + uint8_t GetVersion() const { return artnet::VERSION; } + void SetOutputStyle(const uint32_t nPortIndex, lightset::OutputStyle outputStyle); + lightset::OutputStyle GetOutputStyle(const uint32_t nPortIndex) const; + void SetFailSafe(const artnetnode::FailSafe failsafe); artnetnode::FailSafe GetFailSafe() { @@ -248,58 +302,6 @@ class ArtNetNode { return artnetnode::FailSafe::OFF; } -#if defined (OUTPUT_HAVE_STYLESWITCH) - void SetOutputStyle(const uint32_t nPortIndex, lightset::OutputStyle outputStyle) { - assert(nPortIndex < artnetnode::MAX_PORTS); - - if (outputStyle == GetOutputStyle(nPortIndex)) { - return; - } - - if ((m_State.status == artnetnode::Status::ON) && (m_pLightSet != nullptr)) { - m_pLightSet->SetOutputStyle(nPortIndex, outputStyle); - outputStyle = m_pLightSet->GetOutputStyle(nPortIndex); - } - - if (outputStyle == lightset::OutputStyle::CONSTANT) { - m_OutputPort[nPortIndex].GoodOutputB |= artnet::GoodOutputB::STYLE_CONSTANT; - } else { - m_OutputPort[nPortIndex].GoodOutputB &= static_cast(~artnet::GoodOutputB::STYLE_CONSTANT); - } - -#if defined (OUTPUT_DMX_SEND) || defined (OUTPUT_DMX_SEND_MULTI) - /** - * FIXME I do not like this hack. It should be handled in dmx.cpp - */ - if ((m_Node.Port[nPortIndex].direction == lightset::PortDir::OUTPUT) - && (outputStyle == lightset::OutputStyle::CONSTANT) - && (m_pLightSet != nullptr)) { - if (m_OutputPort[nPortIndex].IsTransmitting) { - m_OutputPort[nPortIndex].IsTransmitting = false; - m_pLightSet->Stop(nPortIndex); - } - } -#endif - - m_State.IsSynchronousMode = false; - - if (m_State.status == artnetnode::Status::ON) { - if (m_pArtNetStore != nullptr) { - m_pArtNetStore->SaveOutputStyle(nPortIndex, outputStyle); - } - - artnet::display_outputstyle(nPortIndex, outputStyle); - } - } - - lightset::OutputStyle GetOutputStyle(const uint32_t nPortIndex) const { - assert(nPortIndex < artnetnode::MAX_PORTS); - - const auto isStyleConstant = (m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::STYLE_CONSTANT) == artnet::GoodOutputB::STYLE_CONSTANT; - return isStyleConstant ? lightset::OutputStyle::CONSTANT : lightset::OutputStyle::DELTA; - } -#endif - void SetOutput(LightSet *pLightSet) { m_pLightSet = pLightSet; #if (ARTNET_VERSION >= 4) @@ -382,12 +384,69 @@ class ArtNetNode { return lightset::MergeMode::HTP; } - void SetRmd(const uint32_t nPortIndex, const bool bEnable); + void SetRdm(const bool doEnable); + bool GetRdm() const { + return m_State.rdm.IsEnabled; + } + + void SetRdm(const uint32_t nPortIndex, const bool bEnable); bool GetRdm(const uint32_t nPortIndex) const { assert(nPortIndex < artnetnode::MAX_PORTS); return !((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::RDM_DISABLED) == artnet::GoodOutputB::RDM_DISABLED); } + void SetRdmDiscovery(const uint32_t nPortIndex, const bool bEnable); + bool GetRdmDiscovery(const uint32_t nPortIndex) const { + assert(nPortIndex < artnetnode::MAX_PORTS); + return !((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::DISCOVERY_DISABLED) == artnet::GoodOutputB::DISCOVERY_DISABLED); + } + +#if defined (RDM_CONTROLLER) + void SetRdmController(ArtNetRdmController *pArtNetRdmController, const bool doEnable = true); + + uint32_t RdmCopyWorkingQueue(char *pOutBuffer, const uint32_t nOutBufferSize) { + if (m_pArtNetRdmController != nullptr) { + return m_pArtNetRdmController->CopyWorkingQueue(pOutBuffer, nOutBufferSize); + } + + return 0; + } + + uint32_t RdmGetUidCount(const uint32_t nPortIndex) { + if (m_pArtNetRdmController != nullptr) { + return m_pArtNetRdmController->GetUidCount(nPortIndex); + } + + return 0; + } + + uint32_t RdmCopyTod(const uint32_t nPortIndex, char *pOutBuffer, const uint32_t nOutBufferSize) { + if (m_pArtNetRdmController != nullptr) { + return m_pArtNetRdmController->CopyTod(nPortIndex, pOutBuffer, nOutBufferSize); + } + + return 0; + } + + bool RdmIsRunning(const uint32_t nPortIndex, bool& bIsIncremental) { + uint32_t nRdmnPortIndex; + if (m_pArtNetRdmController->IsRunning(nRdmnPortIndex, bIsIncremental)) { + const auto isRunning = (nRdmnPortIndex == nPortIndex); + if (isRunning) { + assert(!((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::DISCOVERY_NOT_RUNNING) == artnet::GoodOutputB::DISCOVERY_NOT_RUNNING)); + } + return isRunning; + } + + return false; + } + +#endif + +#if defined (RDM_RESPONDER) + void SetRdmResponder(ArtNetRdmResponder *pArtNetRdmResponder, const bool doEnable = true); +#endif + void SetDisableMergeTimeout(bool bDisable) { m_State.bDisableMergeTimeout = bDisable; #if (ARTNET_VERSION >= 4) @@ -399,19 +458,27 @@ class ArtNetNode { return m_State.bDisableMergeTimeout; } - void SendTimeCode(const struct TArtNetTimeCode *); +#if defined (ARTNET_HAVE_TIMECODE) + void SendTimeCode(const struct artnet::TimeCode *pArtNetTimeCode) { + assert(pArtNetTimeCode != nullptr); + assert(pArtNetTimeCode->Frames < 30); + assert(pArtNetTimeCode->Hours < 60); + assert(pArtNetTimeCode->Minutes < 60); + assert(pArtNetTimeCode->Seconds < 60); + assert(pArtNetTimeCode->Type < 4); + + memcpy(&m_ArtTimeCode.Frames, pArtNetTimeCode, sizeof(struct artnet::TimeCode)); + Network::Get()->SendTo(m_nHandle, &m_ArtTimeCode, sizeof(struct artnet::ArtTimeCode), m_Node.IPAddressTimeCode, artnet::UDP_PORT); + } void SetTimeCodeHandler(ArtNetTimeCode *pArtNetTimeCode) { m_pArtNetTimeCode = pArtNetTimeCode; } - void SetTimeCodeIp(uint32_t nDestinationIp); - - void SetRdmHandler(ArtNetRdm *, bool isResponder = false); - - void SetArtNetStore(ArtNetStore *pArtNetStore) { - m_pArtNetStore = pArtNetStore; + void SetTimeCodeIp(const uint32_t nDestinationIp) { + m_Node.IPAddressTimeCode = nDestinationIp; } +#endif void SetArtNetTrigger(ArtNetTrigger *pArtNetTrigger) { m_pArtNetTrigger = pArtNetTrigger; @@ -419,13 +486,8 @@ class ArtNetNode { void SetDestinationIp(const uint32_t nPortIndex, const uint32_t nDestinationIp) { if (nPortIndex < artnetnode::MAX_PORTS) { - if (Network::Get()->IsValidIp(nDestinationIp)) { - m_InputPort[nPortIndex].nDestinationIp = nDestinationIp; - } else { - m_InputPort[nPortIndex].nDestinationIp = Network::Get()->GetBroadcastIp(); - } - - DEBUG_PRINTF("m_nDestinationIp=" IPSTR, IP2STR(m_InputPort[nPortIndex].nDestinationIp)); + m_InputPort[nPortIndex].nDestinationIp = nDestinationIp; + DEBUG_PRINTF("nDestinationIp=" IPSTR, IP2STR(m_InputPort[nPortIndex].nDestinationIp)); } } @@ -516,13 +578,7 @@ class ArtNetNode { void SetNetSwitch(const uint32_t nPortIndex, const uint8_t nNetSwitch); void SetSubnetSwitch(const uint32_t nPortIndex, const uint8_t nSubnetSwitch); -#if defined (ARTNET_ENABLE_SENDDIAG) -# define UNUSED -#else -# define UNUSED __attribute__((unused)) -#endif - - void SendDiag(UNUSED const artnet::PriorityCodes priorityCode, UNUSED const char *format, ...) { + void SendDiag([[maybe_unused]] const artnet::PriorityCodes priorityCode, [[maybe_unused]] const char *format, ...) { #if defined (ARTNET_ENABLE_SENDDIAG) if (!m_State.SendArtDiagData) { return; @@ -551,10 +607,6 @@ class ArtNetNode { #endif } -#if defined (ARTNET_ENABLE_SENDDIAG) -# undef UNUSED -#endif - void HandlePoll(); void HandleDmx(); void HandleSync(); @@ -565,6 +617,7 @@ class ArtNetNode { void HandleTodData(); void HandleTodRequest(); void HandleRdm(); + void HandleRdmSub(); void HandleIpProg(); void HandleDmxIn(); void HandleInput(); @@ -572,13 +625,15 @@ class ArtNetNode { void HandleRdmIn(); void HandleTrigger(); - uint16_t MakePortAddress(const uint16_t nUniverse, const uint32_t nPage); + uint16_t MakePortAddress(const uint16_t nUniverse, const uint32_t nPage) { + return artnet::make_port_address(m_Node.Port[nPage].NetSwitch, m_Node.Port[nPage].SubSwitch, nUniverse); + } void UpdateMergeStatus(const uint32_t nPortIndex); void CheckMergeTimeouts(const uint32_t nPortIndex); void ProcessPollRelply(const uint32_t nPortIndex, uint32_t& NumPortsInput, uint32_t& NumPortsOutput); - void SendPollRelply(const uint32_t nBindIndex, const uint32_t nDestinationIp, artnetnode::ArtPollQueue *pQueue = nullptr); + void SendPollRelply(const uint32_t nBindIndex, const uint32_t nDestinationIp, artnet::ArtPollQueue *pQueue = nullptr); void SendTod(uint32_t nPortIndex); void SendTodRequest(uint32_t nPortIndex); @@ -588,20 +643,62 @@ class ArtNetNode { void FailSafeRecord(); void FailSafePlayback(); - void Process(const uint16_t); + void Process(const uint32_t); + +#if defined (RDM_CONTROLLER) + bool RdmDiscoveryRun() { + if ((GetPortDirection(m_State.rdm.nDiscoveryPortIndex) == lightset::PortDir::OUTPUT) + && (GetRdm(m_State.rdm.nDiscoveryPortIndex)) + && (GetRdmDiscovery(m_State.rdm.nDiscoveryPortIndex))) + { + uint32_t nPortIndex; + bool bIsIncremental; + + if (m_pArtNetRdmController->IsFinished(nPortIndex, bIsIncremental)) { + assert(m_State.rdm.nDiscoveryPortIndex == nPortIndex); + + SendTod(nPortIndex); + + DEBUG_PUTS("TOD sent"); + + if (m_OutputPort[nPortIndex].IsTransmitting) { + DEBUG_PUTS("m_pLightSet->Stop/Start"); + m_pLightSet->Stop(nPortIndex); + m_pLightSet->Start(nPortIndex); + } + + m_OutputPort[m_State.rdm.nDiscoveryPortIndex].GoodOutputB |= artnet::GoodOutputB::DISCOVERY_NOT_RUNNING; + + m_State.rdm.nDiscoveryPortIndex++; + return (m_State.rdm.nDiscoveryPortIndex != artnetnode::MAX_PORTS); + } + + if (!m_pArtNetRdmController->IsRunning(nPortIndex, bIsIncremental)) { + DEBUG_PRINTF("RDM Discovery Incremental -> %u", static_cast(m_State.rdm.nDiscoveryPortIndex)); + m_pArtNetRdmController->Incremental(m_State.rdm.nDiscoveryPortIndex); + m_OutputPort[m_State.rdm.nDiscoveryPortIndex].GoodOutputB &= static_cast(~artnet::GoodOutputB::DISCOVERY_NOT_RUNNING); + } + + return true; + } + + m_State.rdm.nDiscoveryPortIndex++; + return (m_State.rdm.nDiscoveryPortIndex != artnetnode::MAX_PORTS); + } +#endif + private: int32_t m_nHandle { -1 }; uint8_t *m_pReceiveBuffer { nullptr }; uint32_t m_nIpAddressFrom; uint32_t m_nCurrentPacketMillis { 0 }; uint32_t m_nPreviousPacketMillis { 0 }; + uint32_t m_nPreviousLedpanelMillis { 0 }; LightSet *m_pLightSet { nullptr }; ArtNetTimeCode *m_pArtNetTimeCode { nullptr }; - ArtNetRdm *m_pArtNetRdm { nullptr }; ArtNetTrigger *m_pArtNetTrigger { nullptr }; - ArtNetStore *m_pArtNetStore { nullptr }; artnetnode::Node m_Node; artnetnode::State m_State; @@ -619,6 +716,12 @@ class ArtNetNode { artnet::ArtRdm ArtRdm; }; UArtTodPacket m_ArtTodPacket; +# if defined (RDM_CONTROLLER) + ArtNetRdmController *m_pArtNetRdmController; +# endif +# if defined (RDM_RESPONDER) + ArtNetRdmResponder *m_pArtNetRdmResponder; +# endif #endif #if defined (ARTNET_HAVE_TIMECODE) artnet::ArtTimeCode m_ArtTimeCode; @@ -626,6 +729,9 @@ class ArtNetNode { #if defined (ARTNET_ENABLE_SENDDIAG) artnet::ArtDiagData m_DiagData; #endif +#if defined (DMXCONFIGUDP_H_) + DmxConfigUdp m_DmxConfigUdp; +#endif static ArtNetNode *s_pThis; }; diff --git a/lib-rdmsensor/include/rdmsensorstore.h b/lib-artnet/include/artnetnode_ports.h similarity index 74% rename from lib-rdmsensor/include/rdmsensorstore.h rename to lib-artnet/include/artnetnode_ports.h index 59826cc3..8317f753 100755 --- a/lib-rdmsensor/include/rdmsensorstore.h +++ b/lib-artnet/include/artnetnode_ports.h @@ -1,5 +1,5 @@ /** - * @file rdmsensorstore.h + * @file artnetnode_ports.h * */ /* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl @@ -23,14 +23,19 @@ * THE SOFTWARE. */ -#ifndef RDMSENSORSTORE_H_ -#define RDMSENSORSTORE_H_ +#ifndef ARTNETNODE_PORTS_H_ +#define ARTNETNODE_PORTS_H_ -class RDMSensorStore { -public: - virtual ~RDMSensorStore() {} +namespace artnetnode { +#if !defined(LIGHTSET_PORTS) +# define LIGHTSET_PORTS 0 +#endif - virtual void SaveCalibration(uint32_t nSensor, int32_t nCalibration)=0; -}; +#if (LIGHTSET_PORTS == 0) + static constexpr uint32_t MAX_PORTS = 1; // ISO C++ forbids zero-size array +#else + static constexpr uint32_t MAX_PORTS = LIGHTSET_PORTS; +#endif +} // namespace artnetnode -#endif /* RDMSENSORSTORE_H_ */ +#endif /* IARTNETNODE_PORTS_H_ */ diff --git a/lib-artnet/include/artnetparams.h b/lib-artnet/include/artnetparams.h index 825380ba..300eec83 100644 --- a/lib-artnet/include/artnetparams.h +++ b/lib-artnet/include/artnetparams.h @@ -5,7 +5,7 @@ /** * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. */ -/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"); to deal @@ -34,7 +34,7 @@ #include #include "artnet.h" - +#include "configstore.h" #include "lightset.h" namespace artnetparams { @@ -122,27 +122,28 @@ struct Mask { class ArtNetParamsStore { public: - virtual ~ArtNetParamsStore() {} + static void Update(const struct artnetparams::Params *pParams) { + ConfigStore::Get()->Update(configstore::Store::NODE, pParams, sizeof(struct artnetparams::Params)); + } - virtual void Update(const artnetparams::Params *pArtNetParams)=0; - virtual void Copy(artnetparams::Params *pArtNetParams)=0; + static void Copy(struct artnetparams::Params *pParams) { + ConfigStore::Get()->Copy(configstore::Store::NODE, pParams, sizeof(struct artnetparams::Params)); + } }; class ArtNetParams { public: - ArtNetParams(ArtNetParamsStore *pArtNetParamsStore); + ArtNetParams(); bool Load(); void Load(const char *pBuffer, uint32_t nLength); - void Builder(const struct artnetparams::Params *pArtNetParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); + void Builder(const struct artnetparams::Params *pParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); void Save(char *pBuffer, uint32_t nLength, uint32_t& nSize) { Builder(nullptr, pBuffer, nLength, nSize); } - void Set(uint32_t nPortIndexOffset); - - void Dump(); + void Set(); bool IsRdm() const { return isMaskSet(artnetparams::Mask::ENABLE_RDM); @@ -162,12 +163,6 @@ class ArtNetParams { return lightset::PortDir::DISABLE; } -#if defined (ESP8266) - lightset::OutputType GetOutputType() const { - return static_cast(m_Params.Filler1); - } -#endif - static void staticCallbackFunction(void *p, const char *s); private: @@ -187,6 +182,7 @@ class ArtNetParams { return static_cast((m_Params.nProtocol >> (nPortIndex * 2)) & 0x3); } + void Dump(); void callbackFunction(const char *pLine); void SetBool(const uint8_t nValue, const uint32_t nMask); bool isMaskSet(uint32_t nMask) const { @@ -197,7 +193,6 @@ class ArtNetParams { } private: - ArtNetParamsStore *m_pArtNetParamsStore; artnetparams::Params m_Params; }; diff --git a/lib-artnet/include/artnetpolltable.h b/lib-artnet/include/artnetpolltable.h index 5e38eeb2..70d18b9b 100644 --- a/lib-artnet/include/artnetpolltable.h +++ b/lib-artnet/include/artnetpolltable.h @@ -5,7 +5,7 @@ /** * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. */ -/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,70 +33,71 @@ #include "artnet.h" -enum TArtNetPollInterval { - ARTNET_POLL_INTERVAL_SECONDS = 8, - ARTNET_POLL_INTERVAL_MILLIS = (ARTNET_POLL_INTERVAL_SECONDS * 1000) -}; - -enum TArtNetPollTableSizes { - ARTNET_POLL_TABLE_SIZE_ENRIES = 255, - ARTNET_POLL_TABLE_SIZE_NODE_UNIVERSES = 64, - ARTNET_POLL_TABLE_SIZE_UNIVERSES = 512 -}; +namespace artnet { +static constexpr uint32_t POLL_INTERVAL_SECONDS = 8; +static constexpr uint32_t POLL_INTERVAL_MILLIS = (POLL_INTERVAL_SECONDS * 1000U); +static constexpr uint32_t POLL_TABLE_SIZE_ENRIES = 255; +static constexpr uint32_t POLL_TABLE_SIZE_NODE_UNIVERSES = 64; +static constexpr uint32_t POLL_TABLE_SIZE_UNIVERSES = 512; -struct TArtNetNodeEntryUniverse { +struct NodeEntryUniverse { + uint8_t ShortName[artnet::SHORT_NAME_LENGTH]; uint32_t nLastUpdateMillis; uint16_t nUniverse; }; -struct TArtNetNodeEntry { +struct NodeEntry { uint32_t IPAddress; uint8_t Mac[artnet::MAC_SIZE]; - uint8_t ShortName[artnet::SHORT_NAME_LENGTH]; uint8_t LongName[artnet::LONG_NAME_LENGTH]; uint16_t nUniversesCount; - struct TArtNetNodeEntryUniverse Universe[ARTNET_POLL_TABLE_SIZE_NODE_UNIVERSES]; + struct NodeEntryUniverse Universe[artnet::POLL_TABLE_SIZE_NODE_UNIVERSES]; }; -struct TArtNetPollTableUniverses { +struct PollTableUniverses { uint16_t nUniverse; uint16_t nCount; uint32_t *pIpAddresses; }; -struct TArtNetPollTableClean { +struct PollTableClean { uint32_t nTableIndex; uint16_t nUniverseIndex; bool bOffLine; }; +} // namespace artnet class ArtNetPollTable { public: ArtNetPollTable(); ~ArtNetPollTable(); - uint32_t GetEntries() const { + const artnet::NodeEntry *GetPollTable() const { + return m_pPollTable; + } + + uint32_t GetPollTableEntries() const { return m_nPollTableEntries; } void Add(const struct artnet::ArtPollReply *ptArtPollReply); void Clean(); - const struct TArtNetPollTableUniverses *GetIpAddress(uint16_t nUniverse) const; + const struct artnet::PollTableUniverses *GetIpAddress(uint16_t nUniverse) const; void Dump(); void DumpTableUniverses(); private: - void ProcessUniverse(uint32_t nIpAddress, uint16_t nUniverse); - void RemoveIpAddress(uint16_t nUniverse, uint32_t nIpAddress); + void ProcessUniverse(const uint32_t nIpAddress, const uint16_t nUniverse); + void RemoveIpAddress(const uint16_t nUniverse, const uint32_t nIpAddress); private: - TArtNetNodeEntry *m_pPollTable; - uint32_t m_nPollTableEntries{0}; - TArtNetPollTableUniverses *m_pTableUniverses; - uint32_t m_nTableUniversesEntries{0}; - TArtNetPollTableClean m_tTableClean; + artnet::NodeEntry *m_pPollTable; + artnet::PollTableUniverses *m_pTableUniverses; + uint32_t m_nPollTableEntries { 0 }; + uint32_t m_nTableUniversesEntries { 0 }; + artnet::PollTableClean m_PollTableClean; }; #endif /* ARTNETPOLLTABLE_H_ */ diff --git a/lib-artnet/include/artnetrdmcontroller.h b/lib-artnet/include/artnetrdmcontroller.h new file mode 100755 index 00000000..437c0e1f --- /dev/null +++ b/lib-artnet/include/artnetrdmcontroller.h @@ -0,0 +1,165 @@ +/** + * @file artnetrdmcontroller.h + * + */ +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef ARTNETRDMCONTROLLER_H_ +#define ARTNETRDMCONTROLLER_H_ + +#include +#include +#include + +#include "rdmdiscovery.h" +#include "rdmdevicecontroller.h" +#include "rdm.h" + +#include "artnetnode_ports.h" + +#include "debug.h" + +class ArtNetRdmController final: public RDMDeviceController, RDMDiscovery { +public: + ArtNetRdmController(): RDMDiscovery(RDMDeviceController::GetUID()) { + DEBUG_ENTRY + DEBUG_EXIT + } + + // Discovery + + void Full(const uint32_t nPortIndex) { + DEBUG_ENTRY + assert(nPortIndex < artnetnode::MAX_PORTS); + RDMDiscovery::Full(nPortIndex, &m_pRDMTod[nPortIndex]); + DEBUG_EXIT + } + + void Incremental(const uint32_t nPortIndex) { + DEBUG_ENTRY + assert(nPortIndex < artnetnode::MAX_PORTS); + RDMDiscovery::Incremental(nPortIndex, &m_pRDMTod[nPortIndex]); + DEBUG_EXIT + } + + void Stop(const uint32_t nPortIndex) { + DEBUG_ENTRY + assert(nPortIndex < artnetnode::MAX_PORTS); + bool bIsIncremental; + uint32_t _nPortIndex; + if (IsRunning(_nPortIndex, bIsIncremental)) { + if (_nPortIndex == nPortIndex) { + RDMDiscovery::Stop(); + } + } + DEBUG_EXIT + } + + uint32_t GetUidCount(const uint32_t nPortIndex) { + assert(nPortIndex < artnetnode::MAX_PORTS); + return m_pRDMTod[nPortIndex].GetUidCount(); + } + + void TodCopy(const uint32_t nPortIndex, uint8_t *pTod) { + DEBUG_ENTRY + assert(nPortIndex < artnetnode::MAX_PORTS); + m_pRDMTod[nPortIndex].Copy(pTod); + DEBUG_EXIT + } + + void Run() { + RDMDiscovery::Run(); + } + + bool IsRunning(uint32_t& nPortIndex, bool& bIsIncremental) { + return RDMDiscovery::IsRunning(nPortIndex, bIsIncremental); + } + + bool IsFinished(uint32_t& nPortIndex, bool& bIsIncremental) { + return RDMDiscovery::IsFinished(nPortIndex, bIsIncremental); + } + + uint32_t CopyWorkingQueue(char *pOutBuffer, const uint32_t nOutBufferSize) { + return RDMDiscovery::CopyWorkingQueue(pOutBuffer, nOutBufferSize); + } + + uint32_t CopyTod(const uint32_t nPortIndex, char *pOutBuffer, const uint32_t nOutBufferSize) { + assert(nPortIndex < artnetnode::MAX_PORTS); + + const auto nSize = static_cast(nOutBufferSize); + int32_t nLength = 0; + + for (uint32_t nCount = 0; nCount < m_pRDMTod[nPortIndex].GetUidCount(); nCount++) { + uint8_t uid[RDM_UID_SIZE]; + + m_pRDMTod[nPortIndex].CopyUidEntry(nCount, uid); + + nLength += snprintf(&pOutBuffer[nLength], static_cast(nSize - nLength), + "\"%.2x%.2x:%.2x%.2x%.2x%.2x\",", + uid[0], uid[1], uid[2], uid[3], uid[4], uid[5]); + } + + if (nLength == 0) { + return 0; + } + + pOutBuffer[nLength - 1] = '\0'; + + return static_cast(nLength - 1); + + } + + // Gateway + + bool RdmReceive(const uint32_t nPortIndex, const uint8_t *pRdmData); + + void TodReset(const uint32_t nPortIndex) { + assert(nPortIndex < artnetnode::MAX_PORTS); + m_pRDMTod[nPortIndex].Reset(); + } + + bool TodAddUid(const uint32_t nPortIndex, const uint8_t *pUid) { + return m_pRDMTod[nPortIndex].AddUid(pUid); + } + + // Generic + + bool CopyTodEntry(const uint32_t nPortIndex, uint32_t nIndex, uint8_t uid[RDM_UID_SIZE]) { + assert(nPortIndex < artnetnode::MAX_PORTS); + return m_pRDMTod[nPortIndex].CopyUidEntry(nIndex, uid); + } + + void TodDump(const uint32_t nPortIndex) { + assert(nPortIndex < artnetnode::MAX_PORTS); + m_pRDMTod[nPortIndex].Dump(); + } + + RDMTod *GetTod(const uint32_t nPortIndex) { + assert(nPortIndex < artnetnode::MAX_PORTS); + return &m_pRDMTod[nPortIndex]; + } + +private: + static RDMTod m_pRDMTod[artnetnode::MAX_PORTS]; +}; + +#endif /* ARTNETRDMCONTROLLER_H_ */ diff --git a/lib-rdmresponder/include/artnetrdmresponder.h b/lib-artnet/include/artnetrdmresponder.h similarity index 55% rename from lib-rdmresponder/include/artnetrdmresponder.h rename to lib-artnet/include/artnetrdmresponder.h index de5e92c8..fa2d4845 100644 --- a/lib-rdmresponder/include/artnetrdmresponder.h +++ b/lib-artnet/include/artnetrdmresponder.h @@ -2,7 +2,7 @@ * @file artnetrdmresponder.h * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,35 +30,37 @@ #include #include -#include "artnetrdm.h" - #include "rdmdeviceresponder.h" #include "rdmpersonality.h" #include "rdmhandler.h" -#include "rdm.h" +#include "rdmconst.h" +#include "rdm_message_print.h" #include "lightset.h" +#include "debug.h" + #if defined (NODE_RDMNET_LLRP_ONLY) # error "Cannot be both RDMNet Device and RDM Responder" #endif -class ArtNetRdmResponder: public ArtNetRdm, public RDMDeviceResponder, RDMHandler { +class ArtNetRdmResponder final: public RDMDeviceResponder, RDMHandler { public: - ArtNetRdmResponder(RDMPersonality **pRDMPersonalities, uint32_t nPersonalityCount); - ~ArtNetRdmResponder() override; - - void Full(__attribute__((unused)) uint32_t nPortIndex) override { - // We are a Responder - no code needed + ArtNetRdmResponder(RDMPersonality **pRDMPersonalities, const uint32_t nPersonalityCount) : + RDMDeviceResponder(pRDMPersonalities, nPersonalityCount) + { + DEBUG_ENTRY + DEBUG_EXIT } - uint32_t GetUidCount(const uint32_t nPortIndex) override { - DEBUG_PRINTF("nPortIndex=%u", nPortIndex); - return nPortIndex == 0 ? 1 : 0; // We are a Responder + ~ArtNetRdmResponder() { + DEBUG_ENTRY + DEBUG_EXIT } - void TodCopy(const uint32_t nPortIndex, unsigned char *tod) override { + void TodCopy(const uint32_t nPortIndex, unsigned char *tod) { DEBUG_PRINTF("nPortIndex=%u", nPortIndex); + if (nPortIndex == 0) { memcpy(tod, RDMDeviceResponder::GetUID(), RDM_UID_SIZE); } else { @@ -66,31 +68,39 @@ class ArtNetRdmResponder: public ArtNetRdm, public RDMDeviceResponder, RDMHandle } } - void TodReset(__attribute__((unused)) uint32_t nPortIndex) override {} - bool TodAddUid(__attribute__((unused)) uint32_t nPortIndex, __attribute__((unused)) const uint8_t *pUid) override { return false;} + const uint8_t *Handler(const uint32_t nPortIndex, const uint8_t *pRdmDataNoSC) { + DEBUG_ENTRY - const uint8_t *Handler(uint32_t nPortIndex, const uint8_t *) override; + if (nPortIndex != 0) { + DEBUG_EXIT + return nullptr; + } - uint16_t GetDmxStartAddress(uint16_t nSubDevice = RDM_ROOT_DEVICE) { - return RDMDeviceResponder::GetDmxStartAddress(nSubDevice); - } + if (pRdmDataNoSC == nullptr) { + DEBUG_EXIT + return nullptr; + } - uint16_t GetDmxFootPrint(uint16_t nSubDevice = RDM_ROOT_DEVICE) { - return RDMDeviceResponder::GetDmxFootPrint(nSubDevice); - } +#ifndef NDEBUG + rdm::message_print_no_sc(pRdmDataNoSC); +#endif - // + RDMHandler::HandleData(pRdmDataNoSC, reinterpret_cast(&s_RdmCommand)); - bool RdmReceive(__attribute__((unused)) uint32_t nPortIndex, __attribute__((unused)) uint8_t *pRdmData) override { - return false; - } + if (s_RdmCommand.start_code != E120_SC_RDM) { + DEBUG_EXIT + return nullptr; + } + +#ifndef NDEBUG + rdm::message_print(reinterpret_cast(&s_RdmCommand)); +#endif - static ArtNetRdmResponder* Get() { - return s_pThis; + DEBUG_EXIT + return reinterpret_cast(&s_RdmCommand); } private: - static ArtNetRdmResponder *s_pThis; static TRdmMessage s_RdmCommand; }; diff --git a/lib-artnet/include/artnetstore.h b/lib-artnet/include/artnetstore.h index 23749de5..c627eb01 100644 --- a/lib-artnet/include/artnetstore.h +++ b/lib-artnet/include/artnetstore.h @@ -5,7 +5,7 @@ /** * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,28 +30,226 @@ #define ARTNETSTORE_H_ #include +#include -#include "artnet.h" -#include "lightset.h" +#include "artnetparams.h" +#include "configstore.h" +#include "artnetnode.h" + +#include "debug.h" + +namespace artnetnode { +namespace configstore { +extern uint32_t DMXPORT_OFFSET; +} // namespace configstore +} // namespace artnetnode class ArtNetStore { public: - virtual ~ArtNetStore() {} + static void SaveLongName(const char *pLongName) { + DEBUG_ENTRY + ConfigStore::Get()->Update(configstore::Store::NODE, offsetof(struct artnetparams::Params, aLongName), pLongName, artnet::LONG_NAME_LENGTH, artnetparams::Mask::LONG_NAME); + DEBUG_EXIT + + } + + static void SaveShortName(uint32_t nPortIndex, const char *pShortName) { + DEBUG_ENTRY + DEBUG_PRINTF("%u, %s", nPortIndex, pShortName); + + if (nPortIndex >= artnetnode::configstore::DMXPORT_OFFSET) { + nPortIndex -= artnetnode::configstore::DMXPORT_OFFSET; + } else { + DEBUG_EXIT + return; + } + + DEBUG_PRINTF("nPortIndex=%u", nPortIndex); + + if (nPortIndex >= artnet::PORTS) { + DEBUG_EXIT + return; + } + + ConfigStore::Get()->Update(configstore::Store::NODE, (artnet::SHORT_NAME_LENGTH * nPortIndex) + offsetof(struct artnetparams::Params, aLabel), pShortName, artnet::SHORT_NAME_LENGTH, artnetparams::Mask::LABEL_A << nPortIndex); + + DEBUG_EXIT + } + + static void SaveUniverseSwitch(const uint32_t nPortIndex, [[maybe_unused]] const uint8_t nUniverseSwitch) { + DEBUG_ENTRY + SaveUniverse(nPortIndex); + DEBUG_EXIT + } + + static void SaveNetSwitch(const uint32_t nPortIndex, [[maybe_unused]] const uint8_t nNetSwitch) { + DEBUG_ENTRY + SaveUniverse(nPortIndex); + DEBUG_EXIT + } + + static void SaveSubnetSwitch(const uint32_t nPortIndex, [[maybe_unused]] const uint8_t nSubnetSwitch) { + DEBUG_ENTRY + SaveUniverse(nPortIndex); + DEBUG_EXIT + } + + static void SaveMergeMode(uint32_t nPortIndex, const lightset::MergeMode mergeMode) { + DEBUG_ENTRY + DEBUG_PRINTF("%u, %u", nPortIndex, static_cast(mergeMode)); + + if (nPortIndex >= artnetnode::configstore::DMXPORT_OFFSET) { + nPortIndex -= artnetnode::configstore::DMXPORT_OFFSET; + } else { + DEBUG_EXIT + return; + } + + DEBUG_PRINTF("nPortIndex=%u", nPortIndex); + + if (nPortIndex >= artnet::PORTS) { + DEBUG_EXIT + return; + } + + uint16_t nMergeMode; + ConfigStore::Get()->Copy(configstore::Store::NODE, &nMergeMode, sizeof(uint16_t), offsetof(struct artnetparams::Params, nMergeMode), false); + + nMergeMode &= artnetparams::mergemode_clear(nPortIndex); + nMergeMode |= artnetparams::mergemode_set(nPortIndex, mergeMode); + + ConfigStore::Get()->Update(configstore::Store::NODE, offsetof(struct artnetparams::Params, nMergeMode), &nMergeMode, sizeof(uint16_t)); + + DEBUG_EXIT + } + + static void SavePortProtocol(uint32_t nPortIndex, const artnet::PortProtocol portProtocol) { + DEBUG_ENTRY + DEBUG_PRINTF("artnetnode::configstore::DMXPORT_OFFSET=%u, nPortIndex=%u, portProtocol=%u", artnetnode::configstore::DMXPORT_OFFSET, nPortIndex, static_cast(portProtocol)); + + if (nPortIndex >= artnetnode::configstore::DMXPORT_OFFSET) { + nPortIndex -= artnetnode::configstore::DMXPORT_OFFSET; + } else { + DEBUG_EXIT + return; + } + + DEBUG_PRINTF("nPortIndex=%u", nPortIndex); + + if (nPortIndex >= artnet::PORTS) { + DEBUG_EXIT + return; + } + + uint16_t nPortProtocol; + ConfigStore::Get()->Copy(configstore::Store::NODE, &nPortProtocol, sizeof(uint16_t), offsetof(struct artnetparams::Params, nProtocol), false); + + nPortProtocol &= artnetparams::protocol_clear(nPortIndex); + nPortProtocol |= artnetparams::protocol_set(nPortIndex, portProtocol); + + ConfigStore::Get()->Update(configstore::Store::NODE, offsetof(struct artnetparams::Params, nProtocol), &nPortProtocol, sizeof(uint16_t)); + DEBUG_EXIT + } + + static void SaveOutputStyle(uint32_t nPortIndex, const lightset::OutputStyle outputStyle) { + DEBUG_ENTRY + DEBUG_PRINTF("artnetnode::configstore::DMXPORT_OFFSET=%u, nPortIndex=%u, outputStyle=%u", artnetnode::configstore::DMXPORT_OFFSET, nPortIndex, static_cast(outputStyle)); + + if (nPortIndex >= artnetnode::configstore::DMXPORT_OFFSET) { + nPortIndex -= artnetnode::configstore::DMXPORT_OFFSET; + } else { + DEBUG_EXIT + return; + } + + DEBUG_PRINTF("nPortIndex=%u", nPortIndex); + + if (nPortIndex >= artnet::PORTS) { + DEBUG_EXIT + return; + } + + uint8_t nOutputStyle; + ConfigStore::Get()->Copy(configstore::Store::NODE, &nOutputStyle, sizeof(uint8_t), offsetof(struct artnetparams::Params, nOutputStyle), false); + + if (outputStyle == lightset::OutputStyle::CONSTANT) { + nOutputStyle |= static_cast(1U << nPortIndex); + } else { + nOutputStyle &= static_cast(~(1U << nPortIndex)); + } + + ConfigStore::Get()->Update(configstore::Store::NODE, offsetof(struct artnetparams::Params, nOutputStyle), &nOutputStyle, sizeof(uint8_t)); + + DEBUG_EXIT + } + + static void SaveRdmEnabled(uint32_t nPortIndex, const bool isEnabled) { + DEBUG_ENTRY + DEBUG_PRINTF("artnetnode::configstore::DMXPORT_OFFSET=%u, nPortIndex=%u, isEnabled=%d", artnetnode::configstore::DMXPORT_OFFSET, nPortIndex, isEnabled); + + if (nPortIndex >= artnetnode::configstore::DMXPORT_OFFSET) { + nPortIndex -= artnetnode::configstore::DMXPORT_OFFSET; + } else { + DEBUG_EXIT + return; + } + + DEBUG_PRINTF("nPortIndex=%u", nPortIndex); + + if (nPortIndex >= artnet::PORTS) { + DEBUG_EXIT + return; + } + + uint16_t nRdm; + ConfigStore::Get()->Copy(configstore::Store::NODE, &nRdm, sizeof(uint16_t), offsetof(struct artnetparams::Params, nRdm), false); + + nRdm &= artnetparams::clear_mask(nPortIndex); + + if (isEnabled) { + nRdm |= artnetparams::shift_left(1, nPortIndex); + nRdm |= static_cast(1U << (nPortIndex + 8)); + } + + ConfigStore::Get()->Update(configstore::Store::NODE, offsetof(struct artnetparams::Params, nRdm), &nRdm, sizeof(uint16_t)); + + DEBUG_EXIT + } + + static void SaveFailSafe(uint8_t nFailSafe) { + DEBUG_ENTRY + ConfigStore::Get()->Update(configstore::Store::NODE, offsetof(struct artnetparams::Params, nFailSafe), &nFailSafe, sizeof(uint8_t), artnetparams::Mask::FAILSAFE); + DEBUG_EXIT + } + +private: + void static SaveUniverse(uint32_t nPortIndex) { + DEBUG_ENTRY + DEBUG_PRINTF("artnetnode::configstore::DMXPORT_OFFSET=%u, nPortIndex=%u", artnetnode::configstore::DMXPORT_OFFSET, nPortIndex); + + uint16_t nUniverse; - virtual void SaveLongName(const char *pLongName)=0; + if (ArtNetNode::Get()->GetPortAddress(nPortIndex, nUniverse)) { + if (nPortIndex >= artnetnode::configstore::DMXPORT_OFFSET) { + nPortIndex -= artnetnode::configstore::DMXPORT_OFFSET; + } else { + DEBUG_EXIT + return; + } - virtual void SaveShortName(const uint32_t nPortIndex, const char *pShortName)=0; + DEBUG_PRINTF("nPortIndex=%u", nPortIndex); - virtual void SaveUniverseSwitch(const uint32_t nPortIndex, const uint8_t nAddress)=0; - virtual void SaveNetSwitch(const uint32_t nPage, const uint8_t nAddress)=0; - virtual void SaveSubnetSwitch(const uint32_t nPage, const uint8_t nAddress)=0; + if (nPortIndex >= artnet::PORTS) { + DEBUG_EXIT + return; + } - virtual void SaveMergeMode(const uint32_t nPortIndex, const lightset::MergeMode mergeMode)=0; - virtual void SavePortProtocol(const uint32_t nPortIndex, const artnet::PortProtocol portProtocol)=0; - virtual void SaveOutputStyle(const uint32_t nPortIndex, const lightset::OutputStyle outputStyle)=0; - virtual void SaveRdmEnabled(const uint32_t nPortIndex, const bool isEnabled)=0; + DEBUG_PRINTF("nPortIndex=%u, nUniverse=%u", nPortIndex, nUniverse); + ConfigStore::Get()->Update(configstore::Store::NODE, (sizeof(uint16_t) * nPortIndex) + offsetof(struct artnetparams::Params, nUniverse), &nUniverse, sizeof(uint16_t), artnetparams::Mask::UNIVERSE_A << nPortIndex); + } - virtual void SaveFailSafe(const uint8_t nFailsafe)=0; + DEBUG_EXIT + } }; #endif /* ARTNETSTORE_H_ */ diff --git a/lib-artnet/include/artnettimecode.h b/lib-artnet/include/artnettimecode.h old mode 100644 new mode 100755 index 5238fa3a..980e7891 --- a/lib-artnet/include/artnettimecode.h +++ b/lib-artnet/include/artnettimecode.h @@ -5,7 +5,7 @@ /** * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. */ -/* Copyright (C) 2016-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2024 by Arjan van Vught mailto:info@gd332-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,23 +31,20 @@ #include -struct TArtNetTimeCode { +namespace artnet { +struct TimeCode { uint8_t Frames; ///< Frames time. 0 – 29 depending on mode. uint8_t Seconds; ///< Seconds. 0 - 59. uint8_t Minutes; ///< Minutes. 0 - 59. uint8_t Hours; ///< Hours. 0 - 59. uint8_t Type; ///< 0 = Film (24fps) , 1 = EBU (25fps), 2 = DF (29.97fps), 3 = SMPTE (30fps) } __attribute__((packed)); +} // namespace artnet class ArtNetTimeCode { public: - virtual ~ArtNetTimeCode() { - } - - virtual void Start()= 0; - virtual void Stop()= 0; - - virtual void Handler(const struct TArtNetTimeCode*)= 0; + virtual ~ArtNetTimeCode() = default; + virtual void Handler(const struct artnet::TimeCode *)= 0; }; #endif /* ARTNETTIMECODE_H_ */ diff --git a/lib-artnet/include/artnettrigger.h b/lib-artnet/include/artnettrigger.h index a5f7d81f..98efd7bc 100644 --- a/lib-artnet/include/artnettrigger.h +++ b/lib-artnet/include/artnettrigger.h @@ -5,7 +5,7 @@ /** * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -50,8 +50,7 @@ struct TArtNetTrigger { class ArtNetTrigger { public: - virtual ~ArtNetTrigger() {} - + virtual ~ArtNetTrigger() = default; virtual void Handler(const struct TArtNetTrigger *ptArtNetTrigger)= 0; }; diff --git a/lib-artnet/src/artnetconst.cpp b/lib-artnet/src/artnetconst.cpp index ba6b0211..5e36a9fb 100644 --- a/lib-artnet/src/artnetconst.cpp +++ b/lib-artnet/src/artnetconst.cpp @@ -2,10 +2,7 @@ * @file artnetconst.cpp * */ -/** - * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. - */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,7 +28,7 @@ #include "artnetconst.h" #include "artnet.h" -const uint8_t ArtNetConst::VERSION[] = { 1, 58 }; +const uint8_t ArtNetConst::VERSION[] = { 1, 60 }; const uint8_t ArtNetConst::ESTA_ID[artnet::ESTA_SIZE] = { 0x50, 0x00 }; ///< https://tsp.esta.org/tsp/working_groups/CP/mfctrIDs.php const uint8_t ArtNetConst::OEM_ID[] = { 0xff, 0xff }; ///< Waiting OEM from Artistic Licence Holdings Ltd. diff --git a/lib-artnet/src/controller/artnetcontroller.cpp b/lib-artnet/src/controller/artnetcontroller.cpp index d13785ca..9c8f56bd 100644 --- a/lib-artnet/src/controller/artnetcontroller.cpp +++ b/lib-artnet/src/controller/artnetcontroller.cpp @@ -1,11 +1,11 @@ /** - * @file artnetcontroller.h + * @file artnetcontroller.cpp * */ /** * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. */ -/* Copyright (C) 2017-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,34 +36,89 @@ #include "artnet.h" #include "artnetconst.h" +#if (ARTNET_VERSION >= 4) +# include "e131.h" +#endif + #include "hardware.h" #include "network.h" #include "debug.h" -#define ARTNET_MIN_HEADER_SIZE 12 - -static uint16_t s_ActiveUniverses[ARTNET_POLL_TABLE_SIZE_UNIVERSES] __attribute__ ((aligned (4))); - ArtNetController *ArtNetController::s_pThis; using namespace artnet; +static constexpr uint32_t ARTNET_MIN_HEADER_SIZE = 12; +static uint16_t s_ActiveUniverses[POLL_TABLE_SIZE_UNIVERSES] __attribute__ ((aligned (4))); + ArtNetController::ArtNetController() { DEBUG_ENTRY + union uip { + uint32_t u32; + uint8_t u8[4]; + } ip; + assert(s_pThis == nullptr); s_pThis = this; m_pArtNetPacket = new struct TArtNetPacket; assert(m_pArtNetPacket != nullptr); + memset(&m_State, 0, sizeof(struct State)); + m_State.reportCode = artnet::ReportCode::RCPOWEROK; + m_State.status = artnet::Status::STANDBY; + memset(&m_ArtNetPoll, 0, sizeof(struct ArtPoll)); memcpy(&m_ArtNetPoll, artnet::NODE_ID, 8); m_ArtNetPoll.OpCode = static_cast(artnet::OpCodes::OP_POLL); m_ArtNetPoll.ProtVerLo = artnet::PROTOCOL_REVISION; m_ArtNetPoll.Flags = Flags::SEND_ARTP_ON_CHANGE; + memset(&m_ArtPollReply, 0, sizeof(struct ArtPollReply)); + memcpy(&m_ArtPollReply, artnet::NODE_ID, 8); + m_ArtPollReply.OpCode = static_cast(artnet::OpCodes::OP_POLLREPLY); + m_ArtPollReply.Port = artnet::UDP_PORT; + m_ArtPollReply.VersInfoH = ArtNetConst::VERSION[0]; + m_ArtPollReply.VersInfoL = ArtNetConst::VERSION[1]; + m_ArtPollReply.OemHi = ArtNetConst::OEM_ID[0]; + m_ArtPollReply.Oem = ArtNetConst::OEM_ID[1]; + m_ArtPollReply.EstaMan[0] = ArtNetConst::ESTA_ID[1]; + m_ArtPollReply.EstaMan[1] = ArtNetConst::ESTA_ID[0]; + m_ArtPollReply.Style = static_cast(StyleCode::SERVER); + Network::Get()->MacAddressCopyTo(m_ArtPollReply.MAC); + m_ArtPollReply.BindIndex = 1; + ip.u32 = Network::Get()->GetIp(); + memcpy(m_ArtPollReply.IPAddress, ip.u8, sizeof(m_ArtPollReply.IPAddress)); +#if (ARTNET_VERSION >= 4) + memcpy(m_ArtPollReply.BindIp, ip.u8, sizeof(m_ArtPollReply.BindIp)); + m_ArtPollReply.AcnPriority = e131::priority::DEFAULT; +#endif + /* + * Status 1 + */ + m_ArtPollReply.Status1 |= artnet::Status1::INDICATOR_NORMAL_MODE | artnet::Status1::PAP_NETWORK; + /* + * Status 2 + */ + m_ArtPollReply.Status2 &= static_cast(~artnet::Status2::SACN_ABLE_TO_SWITCH); + m_ArtPollReply.Status2 |= artnet::Status2::PORT_ADDRESS_15BIT | (artnet::VERSION >= 4 ? artnet::Status2::SACN_ABLE_TO_SWITCH : artnet::Status2::SACN_NO_SWITCH); + m_ArtPollReply.Status2 &= static_cast(~artnet::Status2::IP_DHCP); + m_ArtPollReply.Status2 |= Network::Get()->IsDhcpUsed() ? artnet::Status2::IP_DHCP : artnet::Status2::IP_MANUALY; + m_ArtPollReply.Status2 &= static_cast(~artnet::Status2::DHCP_CAPABLE); + m_ArtPollReply.Status2 |= Network::Get()->IsDhcpCapable() ? artnet::Status2::DHCP_CAPABLE : static_cast(0); + +#if defined (ENABLE_HTTPD) && defined (ENABLE_CONTENT) + m_ArtPollReply.Status2 |= artnet::Status2::WEB_BROWSER_SUPPORT; +#endif + + m_ArtPollReply.PortTypes[0] = artnet::PortType::OUTPUT_ARTNET; + m_ArtPollReply.PortTypes[1] = artnet::PortType::INPUT_ARTNET; + m_ArtPollReply.GoodOutput[0] = artnet::GoodOutput::DATA_IS_BEING_TRANSMITTED; + m_ArtPollReply.GoodInput[0] = artnet::GoodInput::DATA_RECIEVED; + m_ArtPollReply.NumPortsLo = 2; + m_pArtDmx = new struct ArtDmx; assert(m_pArtDmx != nullptr); @@ -80,11 +135,14 @@ ArtNetController::ArtNetController() { m_pArtSync->OpCode = static_cast(artnet::OpCodes::OP_SYNC); m_pArtSync->ProtVerLo = artnet::PROTOCOL_REVISION; - m_tArtNetController.Oem[0] = ArtNetConst::OEM_ID[0]; - m_tArtNetController.Oem[1] = ArtNetConst::OEM_ID[1]; + m_ArtNetController.Oem[0] = ArtNetConst::OEM_ID[0]; + m_ArtNetController.Oem[1] = ArtNetConst::OEM_ID[1]; ActiveUniversesClear(); + SetShortName(nullptr); + SetLongName(nullptr); + DEBUG_EXIT } @@ -97,16 +155,91 @@ ArtNetController::~ArtNetController() { DEBUG_EXIT } +void ArtNetController::GetShortNameDefault(char *ShortName) { +#if !defined (ARTNET_SHORT_NAME) + uint8_t nBoardNameLength; + const auto *const pBoardName = Hardware::Get()->GetBoardName(nBoardNameLength); + const auto *const pWebsiteUrl = Hardware::Get()->GetWebsiteUrl(); + snprintf(ShortName, artnet::LONG_NAME_LENGTH - 1, "%s %s %u %s", pBoardName, artnet::NODE_ID, static_cast(artnet::VERSION), pWebsiteUrl); +#else + uint32_t i; + + for (i = 0; i < (sizeof(ARTNET_SHORT_NAME) - 1) && i < (artnet::SHORT_NAME_LENGTH - 1) ; i++ ) { + if (ARTNET_SHORT_NAME[i] == '_') { + ShortName[i] = ' '; + } else { + ShortName[i] = ARTNET_SHORT_NAME[i]; + } + } + + ShortName[i] = '\0'; +#endif +} + +void ArtNetController::SetShortName(const char *ShortName) { + DEBUG_ENTRY + + if (ShortName == nullptr) { + GetShortNameDefault(reinterpret_cast(m_ArtPollReply.ShortName)); + } else { + strncpy(reinterpret_cast(m_ArtPollReply.ShortName), ShortName, artnet::SHORT_NAME_LENGTH - 1); + } + + m_ArtPollReply.LongName[artnet::SHORT_NAME_LENGTH - 1] = '\0'; + + DEBUG_PUTS(reinterpret_cast(m_ArtPollReply.ShortName)); + DEBUG_EXIT +} + +void ArtNetController::GetLongNameDefault(char *pLongName) { +#if !defined (ARTNET_LONG_NAME) + uint8_t nBoardNameLength; + const auto *const pBoardName = Hardware::Get()->GetBoardName(nBoardNameLength); + const auto *const pWebsiteUrl = Hardware::Get()->GetWebsiteUrl(); + snprintf(pLongName, artnet::LONG_NAME_LENGTH - 1, "%s %s %u %s", pBoardName, artnet::NODE_ID, static_cast(artnet::VERSION), pWebsiteUrl); +#else + uint32_t i; + + for (i = 0; i < (sizeof(ARTNET_LONG_NAME) - 1) && i < (artnet::LONG_NAME_LENGTH - 1) ; i++ ) { + if (ARTNET_LONG_NAME[i] == '_') { + pLongName[i] = ' '; + } else { + pLongName[i] = ARTNET_LONG_NAME[i]; + } + } + + pLongName[i] = '\0'; +#endif +} + +void ArtNetController::SetLongName(const char *pLongName) { + DEBUG_ENTRY + + if (pLongName == nullptr) { + GetLongNameDefault(reinterpret_cast(m_ArtPollReply.LongName)); + } else { + strncpy(reinterpret_cast(m_ArtPollReply.LongName), pLongName, artnet::LONG_NAME_LENGTH - 1); + } + + m_ArtPollReply.LongName[artnet::LONG_NAME_LENGTH - 1] = '\0'; + + DEBUG_PUTS(reinterpret_cast(m_ArtPollReply.LongName)); + DEBUG_EXIT +} + void ArtNetController::Start() { DEBUG_ENTRY - m_tArtNetController.nIPAddressLocal = Network::Get()->GetIp(); - m_tArtNetController.nIPAddressBroadcast = Network::Get()->GetBroadcastIp(); + m_ArtNetController.nIPAddressLocal = Network::Get()->GetIp(); + m_ArtNetController.nIPAddressBroadcast = Network::Get()->GetBroadcastIp(); + assert(m_nHandle == -1); m_nHandle = Network::Get()->Begin(artnet::UDP_PORT); assert(m_nHandle != -1); - Network::Get()->SendTo(m_nHandle, &m_ArtNetPoll, sizeof(struct ArtPoll), m_tArtNetController.nIPAddressBroadcast, artnet::UDP_PORT); + Network::Get()->SendTo(m_nHandle, &m_ArtNetPoll, sizeof(struct ArtPoll), m_ArtNetController.nIPAddressBroadcast, artnet::UDP_PORT); + + m_State.status = artnet::Status::ON; DEBUG_EXIT } @@ -114,7 +247,12 @@ void ArtNetController::Start() { void ArtNetController::Stop() { DEBUG_ENTRY - //FIXME ArtNetController::Stop +// FIXME ArtNetController::Stop +// +// Network::Get()->End(artnet::UDP_PORT); +// m_nHandle = -1; +// +// m_State.status = artnet::Status::OFF; DEBUG_EXIT } @@ -137,8 +275,11 @@ void ArtNetController::HandleDmxOut(uint16_t nUniverse, const uint8_t *pDmxData, m_pArtDmx->Sequence = 1; } +#if defined(CONFIG_ARTNET_CONTROLLER_ENABLE_MASTER) if (__builtin_expect((m_nMaster == DMX_MAX_VALUE), 1)) { +#endif memcpy(m_pArtDmx->Data, pDmxData, nLength); +#if defined(CONFIG_ARTNET_CONTROLLER_ENABLE_MASTER) } else if (m_nMaster == 0) { memset(m_pArtDmx->Data, 0, nLength); } else { @@ -146,11 +287,12 @@ void ArtNetController::HandleDmxOut(uint16_t nUniverse, const uint8_t *pDmxData, m_pArtDmx->Data[i] = ((m_nMaster * static_cast(pDmxData[i])) / DMX_MAX_VALUE) & 0xFF; } } +#endif uint32_t nCount = 0; - auto IpAddresses = const_cast(GetIpAddress(nUniverse)); + auto IpAddresses = const_cast(GetIpAddress(nUniverse)); - if (m_bUnicast) { + if (m_bUnicast && !m_bForceBroadcast) { if (IpAddresses != nullptr) { nCount = IpAddresses->nCount; } else { @@ -161,7 +303,7 @@ void ArtNetController::HandleDmxOut(uint16_t nUniverse, const uint8_t *pDmxData, // If the number of universe subscribers exceeds 40 for a given universe, the transmitting device may broadcast. - if (m_bUnicast && (nCount <= 40)) { + if (m_bUnicast && (nCount <= 40) && !m_bForceBroadcast) { for (uint32_t nIndex = 0; nIndex < nCount; nIndex++) { Network::Get()->SendTo(m_nHandle, m_pArtDmx, sizeof(struct ArtDmx), IpAddresses->pIpAddresses[nIndex], artnet::UDP_PORT); } @@ -172,8 +314,8 @@ void ArtNetController::HandleDmxOut(uint16_t nUniverse, const uint8_t *pDmxData, return; } - if (!m_bUnicast || (nCount > 40)) { - Network::Get()->SendTo(m_nHandle, m_pArtDmx, sizeof(struct ArtDmx), m_tArtNetController.nIPAddressBroadcast, artnet::UDP_PORT); + if (!m_bUnicast || (nCount > 40) || !m_bForceBroadcast) { + Network::Get()->SendTo(m_nHandle, m_pArtDmx, sizeof(struct ArtDmx), m_ArtNetController.nIPAddressBroadcast, artnet::UDP_PORT); m_bDmxHandled = true; } @@ -184,7 +326,7 @@ void ArtNetController::HandleDmxOut(uint16_t nUniverse, const uint8_t *pDmxData, void ArtNetController::HandleSync() { if (m_bSynchronization && m_bDmxHandled) { m_bDmxHandled = false; - Network::Get()->SendTo(m_nHandle, m_pArtSync, sizeof(struct ArtSync), m_tArtNetController.nIPAddressBroadcast, artnet::UDP_PORT); + Network::Get()->SendTo(m_nHandle, m_pArtSync, sizeof(struct ArtSync), m_ArtNetController.nIPAddressBroadcast, artnet::UDP_PORT); } } @@ -200,7 +342,7 @@ void ArtNetController::HandleBlackout() { uint32_t nCount = 0; const auto *IpAddresses = GetIpAddress(s_ActiveUniverses[nIndex]); - if (m_bUnicast) { + if (m_bUnicast && !m_bForceBroadcast) { if (IpAddresses != nullptr) { nCount = IpAddresses->nCount; } else { @@ -208,7 +350,7 @@ void ArtNetController::HandleBlackout() { } } - if (m_bUnicast && (nCount <= 40)) { + if (m_bUnicast && (nCount <= 40) && !m_bForceBroadcast) { // The sequence number is used to ensure that ArtDmx packets are used in the correct order. // This field is incremented in the range 0x01 to 0xff to allow the receiving node to resequence packets. m_pArtDmx->Sequence++; @@ -224,7 +366,7 @@ void ArtNetController::HandleBlackout() { continue; } - if (!m_bUnicast || (nCount > 40)) { + if (!m_bUnicast || (nCount > 40) || !m_bForceBroadcast) { // The sequence number is used to ensure that ArtDmx packets are used in the correct order. // This field is incremented in the range 0x01 to 0xff to allow the receiving node to resequence packets. m_pArtDmx->Sequence++; @@ -233,7 +375,7 @@ void ArtNetController::HandleBlackout() { m_pArtDmx->Sequence = 1; } - Network::Get()->SendTo(m_nHandle, m_pArtDmx, sizeof(struct ArtDmx), m_tArtNetController.nIPAddressBroadcast, artnet::UDP_PORT); + Network::Get()->SendTo(m_nHandle, m_pArtDmx, sizeof(struct ArtDmx), m_ArtNetController.nIPAddressBroadcast, artnet::UDP_PORT); } } @@ -246,7 +388,7 @@ void ArtNetController::HandleTrigger() { DEBUG_ENTRY const ArtTrigger *pArtTrigger = &m_pArtNetPacket->ArtPacket.ArtTrigger; - if ((pArtTrigger->OemCodeHi == 0xFF && pArtTrigger->OemCodeLo == 0xFF) || (pArtTrigger->OemCodeHi == m_tArtNetController.Oem[0] && pArtTrigger->OemCodeLo == m_tArtNetController.Oem[1])) { + if ((pArtTrigger->OemCodeHi == 0xFF && pArtTrigger->OemCodeLo == 0xFF) || (pArtTrigger->OemCodeHi == m_ArtNetController.Oem[0] && pArtTrigger->OemCodeLo == m_ArtNetController.Oem[1])) { DEBUG_PRINTF("Key=%d, SubKey=%d, Data[0]=%d", pArtTrigger->Key, pArtTrigger->SubKey, pArtTrigger->Data[0]); m_pArtNetTrigger->Handler(reinterpret_cast(&pArtTrigger->Key)); @@ -255,11 +397,11 @@ void ArtNetController::HandleTrigger() { DEBUG_EXIT } -void ArtNetController::HandlePoll() { +void ArtNetController::ProcessPoll() { const auto nCurrentMillis = Hardware::Get()->Millis(); - if (__builtin_expect((nCurrentMillis - m_nLastPollMillis > ARTNET_POLL_INTERVAL_MILLIS), 0)) { - Network::Get()->SendTo(m_nHandle, &m_ArtNetPoll, sizeof(struct ArtPoll), m_tArtNetController.nIPAddressBroadcast, artnet::UDP_PORT); + if (__builtin_expect((nCurrentMillis - m_nLastPollMillis > POLL_INTERVAL_MILLIS), 0)) { + Network::Get()->SendTo(m_nHandle, &m_ArtNetPoll, sizeof(struct ArtPoll), m_ArtNetController.nIPAddressBroadcast, artnet::UDP_PORT); m_nLastPollMillis= nCurrentMillis; #ifndef NDEBUG @@ -268,28 +410,45 @@ void ArtNetController::HandlePoll() { #endif } - if (m_bDoTableCleanup && (__builtin_expect((nCurrentMillis - m_nLastPollMillis > ARTNET_POLL_INTERVAL_MILLIS/4), 0))) { + if (m_bDoTableCleanup && (__builtin_expect((nCurrentMillis - m_nLastPollMillis > POLL_INTERVAL_MILLIS/4), 0))) { Clean(); } } +void ArtNetController::HandlePoll() { + DEBUG_ENTRY + + snprintf(reinterpret_cast(m_ArtPollReply.NodeReport), artnet::REPORT_LENGTH, "#%04x [%u]", static_cast(m_State.reportCode), static_cast(m_State.ArtPollReplyCount++)); + + Network::Get()->SendTo(m_nHandle, &m_ArtPollReply, sizeof(artnet::ArtPollReply), m_pArtNetPacket->IPAddressFrom, artnet::UDP_PORT); + + DEBUG_PRINTF(IPSTR, IP2STR(m_pArtNetPacket->IPAddressFrom)); + DEBUG_EXIT +} + void ArtNetController::HandlePollReply() { DEBUG_ENTRY + DEBUG_PRINTF(IPSTR, IP2STR(m_pArtNetPacket->IPAddressFrom)); - Add(&m_pArtNetPacket->ArtPacket.ArtPollReply); + if (m_pArtNetPacket->IPAddressFrom != Network::Get()->GetIp()) { + Add(&m_pArtNetPacket->ArtPacket.ArtPollReply); + + DEBUG_EXIT + return; + } DEBUG_EXIT } void ArtNetController::Run() { - char *pArtPacket = reinterpret_cast(&m_pArtNetPacket->ArtPacket); + auto *pArtPacket = reinterpret_cast(&m_pArtNetPacket->ArtPacket); uint16_t nForeignPort; if (m_bUnicast) { - HandlePoll(); + ProcessPoll(); } - const int nBytesReceived = Network::Get()->RecvFrom(m_nHandle, pArtPacket, sizeof(struct TArtNetPacket), &m_pArtNetPacket->IPAddressFrom, &nForeignPort) ; + const auto nBytesReceived = Network::Get()->RecvFrom(m_nHandle, pArtPacket, sizeof(struct TArtNetPacket), &m_pArtNetPacket->IPAddressFrom, &nForeignPort) ; if (__builtin_expect((nBytesReceived < ARTNET_MIN_HEADER_SIZE), 1)) { return; @@ -305,6 +464,9 @@ void ArtNetController::Run() { case artnet::OpCodes::OP_POLLREPLY: HandlePollReply(); break; + case artnet::OpCodes::OP_POLL: + HandlePoll(); + break; case artnet::OpCodes::OP_TRIGGER: if (m_pArtNetTrigger != nullptr) { HandleTrigger(); @@ -376,12 +538,15 @@ void ArtNetController::ActiveUniversesAdd(uint16_t nUniverse) { } void ArtNetController::Print() { - printf("Art-Net Controller\n"); - printf(" Max Node's : %u\n", ARTNET_POLL_TABLE_SIZE_ENRIES); - printf(" Max Universes : %u\n", ARTNET_POLL_TABLE_SIZE_UNIVERSES); + puts("Art-Net Controller"); + printf(" Max Node's : %u\n", POLL_TABLE_SIZE_ENRIES); + printf(" Max Universes : %u\n", POLL_TABLE_SIZE_UNIVERSES); if (!m_bUnicast) { puts(" Unicast is disabled"); } + if (!m_bForceBroadcast) { + puts(" Force broadcast is enabled"); + } if (!m_bSynchronization) { puts(" Synchronization is disabled"); } diff --git a/lib-artnet/src/controller/artnetpolltable.cpp b/lib-artnet/src/controller/artnetpolltable.cpp index 73c48d49..8b0251a1 100644 --- a/lib-artnet/src/controller/artnetpolltable.cpp +++ b/lib-artnet/src/controller/artnetpolltable.cpp @@ -5,7 +5,7 @@ /** * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. */ -/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -45,39 +45,40 @@ #include "debug.h" -using namespace artnet; - union uip { uint32_t u32; uint8_t u8[4]; } static ip; ArtNetPollTable::ArtNetPollTable() { - m_pPollTable = new TArtNetNodeEntry[ARTNET_POLL_TABLE_SIZE_ENRIES]; + DEBUG_ENTRY + + m_pPollTable = new artnet::NodeEntry[artnet::POLL_TABLE_SIZE_ENRIES]; assert(m_pPollTable != nullptr); - memset(m_pPollTable, 0, sizeof(TArtNetNodeEntry[ARTNET_POLL_TABLE_SIZE_ENRIES])); + memset(m_pPollTable, 0, sizeof(artnet::NodeEntry[artnet::POLL_TABLE_SIZE_ENRIES])); - m_pTableUniverses = new TArtNetPollTableUniverses[ARTNET_POLL_TABLE_SIZE_UNIVERSES]; + m_pTableUniverses = new artnet::PollTableUniverses[artnet::POLL_TABLE_SIZE_UNIVERSES]; assert(m_pTableUniverses != nullptr); - memset(m_pTableUniverses, 0, sizeof(TArtNetPollTableUniverses[ARTNET_POLL_TABLE_SIZE_UNIVERSES])); + memset(m_pTableUniverses, 0, sizeof(artnet::PollTableUniverses[artnet::POLL_TABLE_SIZE_UNIVERSES])); - for (uint32_t nIndex = 0; nIndex < ARTNET_POLL_TABLE_SIZE_UNIVERSES; nIndex++) { - m_pTableUniverses[nIndex].pIpAddresses = new uint32_t[ARTNET_POLL_TABLE_SIZE_ENRIES]; + for (uint32_t nIndex = 0; nIndex < artnet::POLL_TABLE_SIZE_UNIVERSES; nIndex++) { + m_pTableUniverses[nIndex].pIpAddresses = new uint32_t[artnet::POLL_TABLE_SIZE_ENRIES]; assert(m_pTableUniverses[nIndex].pIpAddresses != nullptr); } -// DEBUG_PRINTF("TArtNetNodeEntry[%d] = %u bytes [%u Kb]", ARTNET_POLL_TABLE_SIZE_ENRIES, (sizeof(TArtNetNodeEntry[ARTNET_POLL_TABLE_SIZE_ENRIES])), (sizeof(TArtNetNodeEntry[ARTNET_POLL_TABLE_SIZE_ENRIES])) / 1024); -// DEBUG_PRINTF("TArtNetPollTableUniverses[%d] = %u bytes [%u Kb]", ARTNET_POLL_TABLE_SIZE_UNIVERSES, (sizeof(TArtNetPollTableUniverses[ARTNET_POLL_TABLE_SIZE_UNIVERSES])), (sizeof(TArtNetPollTableUniverses[ARTNET_POLL_TABLE_SIZE_UNIVERSES])) / 1024); + m_PollTableClean.nTableIndex = 0; + m_PollTableClean.nUniverseIndex = 0; + m_PollTableClean.bOffLine = true; - m_tTableClean.nTableIndex = 0; - m_tTableClean.nUniverseIndex = 0; - m_tTableClean.bOffLine = true; + DEBUG_PRINTF("NodeEntry[%d] = %u bytes [%u Kb]", artnet::POLL_TABLE_SIZE_ENRIES, static_cast(sizeof(artnet::NodeEntry[artnet::POLL_TABLE_SIZE_ENRIES])), static_cast(sizeof(artnet::NodeEntry[artnet::POLL_TABLE_SIZE_ENRIES])) / 1024U); + DEBUG_PRINTF("PollTableUniverses[%d] = %u bytes [%u Kb]", artnet::POLL_TABLE_SIZE_UNIVERSES, static_cast(sizeof(artnet::PollTableUniverses[artnet::POLL_TABLE_SIZE_UNIVERSES])), static_cast(sizeof(artnet::PollTableUniverses[artnet::POLL_TABLE_SIZE_UNIVERSES])) / 1024U); + DEBUG_EXIT } ArtNetPollTable::~ArtNetPollTable() { - for (uint32_t nIndex = 0; nIndex < ARTNET_POLL_TABLE_SIZE_UNIVERSES; nIndex++) { + for (uint32_t nIndex = 0; nIndex < artnet::POLL_TABLE_SIZE_UNIVERSES; nIndex++) { delete[] m_pTableUniverses[nIndex].pIpAddresses; m_pTableUniverses[nIndex].pIpAddresses = nullptr; } @@ -89,14 +90,14 @@ ArtNetPollTable::~ArtNetPollTable() { m_pPollTable = nullptr; } -const struct TArtNetPollTableUniverses *ArtNetPollTable::GetIpAddress(uint16_t nUniverse) const { +const struct artnet::PollTableUniverses *ArtNetPollTable::GetIpAddress(uint16_t nUniverse) const { if (m_nTableUniversesEntries == 0) { return nullptr; } // FIXME Universe lookup for (uint32_t nEntry = 0; nEntry < m_nTableUniversesEntries; nEntry++) { - TArtNetPollTableUniverses *pTableUniverses = &m_pTableUniverses[nEntry]; + artnet::PollTableUniverses *pTableUniverses = &m_pTableUniverses[nEntry]; assert(pTableUniverses != nullptr); if (pTableUniverses->nUniverse == nUniverse) { @@ -108,7 +109,7 @@ const struct TArtNetPollTableUniverses *ArtNetPollTable::GetIpAddress(uint16_t n } -void ArtNetPollTable::RemoveIpAddress(uint16_t nUniverse, uint32_t nIpAddress) { +void ArtNetPollTable::RemoveIpAddress(const uint16_t nUniverse, const uint32_t nIpAddress) { if (m_nTableUniversesEntries == 0) { return; } @@ -117,7 +118,7 @@ void ArtNetPollTable::RemoveIpAddress(uint16_t nUniverse, uint32_t nIpAddress) { // FIXME Universe lookup for (nEntry = 0; nEntry < m_nTableUniversesEntries; nEntry++) { - TArtNetPollTableUniverses *pTableUniverses = &m_pTableUniverses[nEntry]; + artnet::PollTableUniverses *pTableUniverses = &m_pTableUniverses[nEntry]; assert(pTableUniverses != nullptr); if (pTableUniverses->nUniverse == nUniverse) { @@ -130,7 +131,7 @@ void ArtNetPollTable::RemoveIpAddress(uint16_t nUniverse, uint32_t nIpAddress) { return; } - TArtNetPollTableUniverses *pTableUniverses = &m_pTableUniverses[nEntry]; + artnet::PollTableUniverses *pTableUniverses = &m_pTableUniverses[nEntry]; assert(pTableUniverses->nCount > 0); uint32_t nIpAddressIndex = 0; @@ -142,7 +143,7 @@ void ArtNetPollTable::RemoveIpAddress(uint16_t nUniverse, uint32_t nIpAddress) { } } - uint32_t *p32 = pTableUniverses->pIpAddresses; + auto *p32 = pTableUniverses->pIpAddresses; int32_t i; for (i = static_cast(nIpAddressIndex); i < static_cast(pTableUniverses->nCount) - 1; i++) { @@ -156,7 +157,7 @@ void ArtNetPollTable::RemoveIpAddress(uint16_t nUniverse, uint32_t nIpAddress) { if (pTableUniverses->nCount == 0) { DEBUG_PRINTF("Delete Universe -> m_nTableUniversesEntries=%u, nEntry=%u", m_nTableUniversesEntries, nEntry); - TArtNetPollTableUniverses *p = m_pTableUniverses; + artnet::PollTableUniverses *p = m_pTableUniverses; for (i = static_cast(nEntry); i < static_cast(m_nTableUniversesEntries) - 1; i++) { p[i].nUniverse = p[i + 1].nUniverse; @@ -171,21 +172,21 @@ void ArtNetPollTable::RemoveIpAddress(uint16_t nUniverse, uint32_t nIpAddress) { } } -void ArtNetPollTable::ProcessUniverse(uint32_t nIpAddress, uint16_t nUniverse) { +void ArtNetPollTable::ProcessUniverse(const uint32_t nIpAddress, const uint16_t nUniverse) { DEBUG_ENTRY - if (ARTNET_POLL_TABLE_SIZE_UNIVERSES == m_nTableUniversesEntries) { + if (artnet::POLL_TABLE_SIZE_UNIVERSES == m_nTableUniversesEntries) { DEBUG_PUTS("m_pTableUniverses is full"); DEBUG_EXIT return; } // FIXME Universe lookup - bool bFoundUniverse = false; + auto bFoundUniverse = false; uint32_t nEntry = 0; for (nEntry = 0; nEntry < m_nTableUniversesEntries; nEntry++) { - TArtNetPollTableUniverses *pTableUniverses = &m_pTableUniverses[nEntry]; + auto *pTableUniverses = &m_pTableUniverses[nEntry]; assert(pTableUniverses != nullptr); if (pTableUniverses->nUniverse == nUniverse) { @@ -195,9 +196,8 @@ void ArtNetPollTable::ProcessUniverse(uint32_t nIpAddress, uint16_t nUniverse) { } } - TArtNetPollTableUniverses *pTableUniverses = &m_pTableUniverses[nEntry]; - - bool bFoundIp = false; + auto *pTableUniverses = &m_pTableUniverses[nEntry]; + auto bFoundIp = false; uint32_t nCount = 0; if (bFoundUniverse) { @@ -217,7 +217,7 @@ void ArtNetPollTable::ProcessUniverse(uint32_t nIpAddress, uint16_t nUniverse) { } if (!bFoundIp) { - if (pTableUniverses->nCount < ARTNET_POLL_TABLE_SIZE_ENRIES) { + if (pTableUniverses->nCount < artnet::POLL_TABLE_SIZE_ENRIES) { pTableUniverses->pIpAddresses[pTableUniverses->nCount] = nIpAddress; pTableUniverses->nCount++; DEBUG_PUTS("It is a new IP for the Universe"); @@ -232,7 +232,7 @@ void ArtNetPollTable::ProcessUniverse(uint32_t nIpAddress, uint16_t nUniverse) { void ArtNetPollTable::Add(const struct artnet::ArtPollReply *ptArtPollReply) { DEBUG_ENTRY - bool bFound = false; + auto bFound = false; memcpy(ip.u8, ptArtPollReply->IPAddress, 4); @@ -259,7 +259,7 @@ void ArtNetPollTable::Add(const struct artnet::ArtPollReply *ptArtPollReply) { } if (!bFound) { - if (m_nPollTableEntries == ARTNET_POLL_TABLE_SIZE_ENRIES) { + if (m_nPollTableEntries == artnet::POLL_TABLE_SIZE_ENRIES) { DEBUG_PUTS("Full"); return; } @@ -267,19 +267,19 @@ void ArtNetPollTable::Add(const struct artnet::ArtPollReply *ptArtPollReply) { if (m_nPollTableEntries != static_cast(nHigh)) { DEBUG_PUTS("Move"); - struct TArtNetNodeEntry *pArtNetNodeEntry = m_pPollTable; // TODO + auto *pArtNetNodeEntry = m_pPollTable; // TODO assert(m_nPollTableEntries >= 1); assert(nLow >= 0); for (int32_t i = static_cast(m_nPollTableEntries) - 1;i >= nLow; i--) { - const struct TArtNetNodeEntry *pSrc = &pArtNetNodeEntry[i]; - struct TArtNetNodeEntry *pDst = &pArtNetNodeEntry[i + 1]; - memcpy(pDst, pSrc, sizeof(struct TArtNetNodeEntry)); + const struct artnet::NodeEntry *pSrc = &pArtNetNodeEntry[i]; + struct artnet::NodeEntry *pDst = &pArtNetNodeEntry[i + 1]; + memcpy(pDst, pSrc, sizeof(struct artnet::NodeEntry)); } - struct TArtNetNodeEntry *pDst = &pArtNetNodeEntry[nLow]; - memset(pDst, 0, sizeof(struct TArtNetNodeEntry)); + auto *pDst = &pArtNetNodeEntry[nLow]; + memset(pDst, 0, sizeof(struct artnet::NodeEntry)); i = nLow; } else { @@ -291,20 +291,17 @@ void ArtNetPollTable::Add(const struct artnet::ArtPollReply *ptArtPollReply) { m_nPollTableEntries++; } -#ifndef NDEBUG if (ptArtPollReply->BindIndex <= 1) { memcpy(m_pPollTable[i].Mac, ptArtPollReply->MAC, artnet::MAC_SIZE); - - const uint8_t *pSrc = ptArtPollReply->ShortName; - uint8_t *pDst = m_pPollTable[i].ShortName; - memcpy(pDst, pSrc, artnet::SHORT_NAME_LENGTH + artnet::LONG_NAME_LENGTH); + const uint8_t *pSrc = ptArtPollReply->LongName; + uint8_t *pDst = m_pPollTable[i].LongName; + memcpy(pDst, pSrc, artnet::LONG_NAME_LENGTH); } -#endif - const uint32_t nMillis = Hardware::Get()->Millis(); + const auto nMillis = Hardware::Get()->Millis(); for (uint32_t nIndex = 0; nIndex < artnet::PORTS; nIndex++) { - const uint8_t nPortAddress = ptArtPollReply->SwOut[nIndex]; + const auto nPortAddress = ptArtPollReply->SwOut[nIndex]; if (ptArtPollReply->PortTypes[nIndex] == static_cast(artnet::PortType::OUTPUT_ARTNET)) { const auto nUniverse = artnet::make_port_address(ptArtPollReply->NetSwitch, ptArtPollReply->SubSwitch, nPortAddress); @@ -319,9 +316,12 @@ void ArtNetPollTable::Add(const struct artnet::ArtPollReply *ptArtPollReply) { if (nIndexUniverse == m_pPollTable[i].nUniversesCount) { // Not found - if (m_pPollTable[i].nUniversesCount < ARTNET_POLL_TABLE_SIZE_NODE_UNIVERSES) { + if (m_pPollTable[i].nUniversesCount < artnet::POLL_TABLE_SIZE_NODE_UNIVERSES) { m_pPollTable[i].nUniversesCount++; m_pPollTable[i].Universe[nIndexUniverse].nUniverse = nUniverse; + const uint8_t *pSrc = ptArtPollReply->ShortName; + uint8_t *pDst = m_pPollTable[i].Universe[nIndexUniverse].ShortName; + memcpy(pDst, pSrc, artnet::SHORT_NAME_LENGTH); ProcessUniverse(ip.u32, nUniverse); } else { // No room @@ -341,56 +341,55 @@ void ArtNetPollTable::Clean() { return; } - assert(m_tTableClean.nTableIndex < m_nPollTableEntries); - assert(m_tTableClean.nUniverseIndex < ARTNET_POLL_TABLE_SIZE_NODE_UNIVERSES); + assert(m_PollTableClean.nTableIndex < m_nPollTableEntries); + assert(m_PollTableClean.nUniverseIndex < artnet::POLL_TABLE_SIZE_NODE_UNIVERSES); - if (m_tTableClean.nUniverseIndex == 0) { - m_tTableClean.bOffLine = true; + if (m_PollTableClean.nUniverseIndex == 0) { + m_PollTableClean.bOffLine = true; } - struct TArtNetNodeEntryUniverse *pArtNetNodeEntryBind = &m_pPollTable[m_tTableClean.nTableIndex].Universe[m_tTableClean.nUniverseIndex]; + auto *pArtNetNodeEntryBind = &m_pPollTable[m_PollTableClean.nTableIndex].Universe[m_PollTableClean.nUniverseIndex]; if (pArtNetNodeEntryBind->nLastUpdateMillis != 0) { - if ((Hardware::Get()->Millis() - pArtNetNodeEntryBind->nLastUpdateMillis) > (1.5 * ARTNET_POLL_INTERVAL_MILLIS)) { + if ((Hardware::Get()->Millis() - pArtNetNodeEntryBind->nLastUpdateMillis) > (1.5 * artnet::POLL_INTERVAL_MILLIS)) { pArtNetNodeEntryBind->nLastUpdateMillis = 0; - RemoveIpAddress(pArtNetNodeEntryBind->nUniverse, m_pPollTable[m_tTableClean.nTableIndex].IPAddress); + RemoveIpAddress(pArtNetNodeEntryBind->nUniverse, m_pPollTable[m_PollTableClean.nTableIndex].IPAddress); } else { - m_tTableClean.bOffLine = false; + m_PollTableClean.bOffLine = false; } } - m_tTableClean.nUniverseIndex++; + m_PollTableClean.nUniverseIndex++; - if (m_tTableClean.nUniverseIndex == ARTNET_POLL_TABLE_SIZE_NODE_UNIVERSES) { - if (m_tTableClean.bOffLine) { + if (m_PollTableClean.nUniverseIndex == artnet::POLL_TABLE_SIZE_NODE_UNIVERSES) { + if (m_PollTableClean.bOffLine) { DEBUG_PUTS("Node is off-line"); - struct TArtNetNodeEntry *pArtNetNodeEntry = m_pPollTable; + auto *pArtNetNodeEntry = m_pPollTable; // Move - for (uint32_t i = m_tTableClean.nTableIndex; i < (m_nPollTableEntries - 1); i++) { - const struct TArtNetNodeEntry *pSrc = &pArtNetNodeEntry[i + 1]; - struct TArtNetNodeEntry *pDst = &pArtNetNodeEntry[i]; - - memcpy(pDst, pSrc, sizeof(struct TArtNetNodeEntry)); + for (uint32_t i = m_PollTableClean.nTableIndex; i < (m_nPollTableEntries - 1); i++) { + const auto *pSrc = &pArtNetNodeEntry[i + 1]; + auto *pDst = &pArtNetNodeEntry[i]; + memcpy(pDst, pSrc, sizeof(struct artnet::NodeEntry)); } m_nPollTableEntries--; - struct TArtNetNodeEntry *pDst = &pArtNetNodeEntry[m_nPollTableEntries]; + auto *pDst = &pArtNetNodeEntry[m_nPollTableEntries]; pDst->IPAddress = 0; pDst->nUniversesCount = 0; - memset(pDst->Universe, 0, sizeof(struct TArtNetNodeEntryUniverse[ARTNET_POLL_TABLE_SIZE_NODE_UNIVERSES])); + memset(pDst->Universe, 0, sizeof(struct artnet::NodeEntryUniverse[artnet::POLL_TABLE_SIZE_NODE_UNIVERSES])); #ifndef NDEBUG - memset(pDst->Mac, 0, artnet::MAC_SIZE + artnet::SHORT_NAME_LENGTH + artnet::LONG_NAME_LENGTH); + memset(pDst->Mac, 0, artnet::MAC_SIZE + artnet::LONG_NAME_LENGTH); #endif } - m_tTableClean.nUniverseIndex = 0; - m_tTableClean.bOffLine = true; - m_tTableClean.nTableIndex++; + m_PollTableClean.nUniverseIndex = 0; + m_PollTableClean.bOffLine = true; + m_PollTableClean.nTableIndex++; - if (m_tTableClean.nTableIndex >= m_nPollTableEntries) { - m_tTableClean.nTableIndex = 0; + if (m_PollTableClean.nTableIndex >= m_nPollTableEntries) { + m_PollTableClean.nTableIndex = 0; } } } @@ -400,11 +399,11 @@ void ArtNetPollTable::Dump() { printf("Entries : %d\n", m_nPollTableEntries); for (uint32_t i = 0; i < m_nPollTableEntries; i++) { - printf("\t" IPSTR " [" MACSTR "] |%-18s|%-64s|\n", IP2STR(m_pPollTable[i].IPAddress), MAC2STR(m_pPollTable[i].Mac), m_pPollTable[i].ShortName, m_pPollTable[i].LongName); + printf("\t" IPSTR " [" MACSTR "] |%-64s|\n", IP2STR(m_pPollTable[i].IPAddress), MAC2STR(m_pPollTable[i].Mac), m_pPollTable[i].LongName); for (uint32_t nUniverse = 0; nUniverse < m_pPollTable[i].nUniversesCount; nUniverse++) { - struct TArtNetNodeEntryUniverse *pArtNetNodeEntryUniverse = &m_pPollTable[i].Universe[nUniverse]; - printf("\t %u [%u]\n", pArtNetNodeEntryUniverse->nUniverse, (Hardware::Get()->Millis() - pArtNetNodeEntryUniverse->nLastUpdateMillis) / 1000U); + auto *pArtNetNodeEntryUniverse = &m_pPollTable[i].Universe[nUniverse]; + printf("\t %u [%u] |%-18s|\n", pArtNetNodeEntryUniverse->nUniverse, (Hardware::Get()->Millis() - pArtNetNodeEntryUniverse->nLastUpdateMillis) / 1000U, pArtNetNodeEntryUniverse->ShortName); } puts(""); } @@ -416,12 +415,12 @@ void ArtNetPollTable::DumpTableUniverses() { printf("Entries : %d\n", m_nTableUniversesEntries); for (uint32_t nEntry = 0; nEntry < m_nTableUniversesEntries; nEntry++) { - const TArtNetPollTableUniverses *pTableUniverses = &m_pTableUniverses[nEntry]; + const auto *pTableUniverses = &m_pTableUniverses[nEntry]; assert(pTableUniverses != nullptr); printf("%3d |%4u | %d ", nEntry, pTableUniverses->nUniverse, pTableUniverses->nCount); - const uint32_t *pIpAddresses = pTableUniverses->pIpAddresses; + const auto *pIpAddresses = pTableUniverses->pIpAddresses; assert(pIpAddresses != nullptr); for (uint32_t nCount = 0; nCount < pTableUniverses->nCount; nCount++) { diff --git a/lib-artnet/src/controller/json_get_polltable.cpp b/lib-artnet/src/controller/json_get_polltable.cpp new file mode 100755 index 00000000..1c8b300a --- /dev/null +++ b/lib-artnet/src/controller/json_get_polltable.cpp @@ -0,0 +1,93 @@ +/** + * @file json_status.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "artnetcontroller.h" +#include "artnet.h" +#include "network.h" + +namespace remoteconfig { +namespace artnet { +namespace controller { +static uint32_t get_port(const struct ::artnet::NodeEntryUniverse *pArtNetNodeEntryUniverse, char *pOutBuffer, const uint32_t nOutBufferSize) { + const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, + "{\"name\":\"%s\",\"universe\":%u},", + pArtNetNodeEntryUniverse->ShortName, pArtNetNodeEntryUniverse->nUniverse)); + + if (nLength <= nOutBufferSize) { + return nLength; + } + + return 0; +} + +static uint32_t get_entry(const uint32_t nIndex, char *pOutBuffer, const uint32_t nOutBufferSize) { + const auto *pPollTable = ArtNetController::Get()->GetPollTable(); + auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, + "{\"name\":\"%s\",\"ip\":\"" IPSTR "\",\"mac\":\"" MACSTR "\",\"ports\":[", + pPollTable[nIndex].LongName, IP2STR(pPollTable[nIndex].IPAddress), MAC2STR(pPollTable[nIndex].Mac))); + + for (uint32_t nUniverse = 0; nUniverse < pPollTable[nIndex].nUniversesCount; nUniverse++) { + const auto *pArtNetNodeEntryUniverse = &pPollTable[nIndex].Universe[nUniverse]; + nLength += get_port(pArtNetNodeEntryUniverse, &pOutBuffer[nLength], nLength); + } + + nLength--; + nLength += static_cast(snprintf(&pOutBuffer[nLength], nOutBufferSize - nLength, "]},")); + + if (nLength <= nOutBufferSize) { + return nLength; + } + + return 0; +} + +uint32_t json_get_polltable(char *pOutBuffer, const uint32_t nOutBufferSize) { + const auto nBufferSize = nOutBufferSize - 2U; + pOutBuffer[0] = '['; + + auto nLength = 1U; + + for (uint32_t nIndex = 0; (nIndex < ArtNetController::Get()->GetPollTableEntries()) && (nLength < nOutBufferSize); nIndex++) { + const auto nSize = nBufferSize - nLength; + nLength += get_entry(nIndex, &pOutBuffer[nLength], nSize); + } + + if (nLength != 1) { + pOutBuffer[nLength - 1] = ']'; + } else { + pOutBuffer[1] = ']'; + nLength = 2; + } + + assert(nLength <= nOutBufferSize); + return nLength; +} +} // namespace controller +} // namespace artnet +} // namespace remoteconfig diff --git a/lib-artnet/src/node/4/artnetnode.cpp b/lib-artnet/src/node/4/artnetnode.cpp index 4e04c7eb..2b6e6471 100755 --- a/lib-artnet/src/node/4/artnetnode.cpp +++ b/lib-artnet/src/node/4/artnetnode.cpp @@ -5,7 +5,7 @@ /** * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,6 +34,7 @@ #include "artnetnode.h" #include "artnet.h" +#include "artnetstore.h" #include "e131bridge.h" @@ -57,11 +58,8 @@ void ArtNetNode::SetPortProtocol4(const uint32_t nPortIndex, const artnet::PortP m_OutputPort[nPortIndex].GoodOutput &= static_cast(~artnet::GoodOutput::OUTPUT_IS_SACN); } - if (m_State.status == artnetnode::Status::ON) { - if (m_pArtNetStore != nullptr) { - m_pArtNetStore->SavePortProtocol(nPortIndex, portProtocol); - } - + if (m_State.status == artnet::Status::ON) { + ArtNetStore::SavePortProtocol(nPortIndex, portProtocol); artnet::display_port_protocol(nPortIndex, portProtocol); } diff --git a/lib-artnet/src/node/artnetmsgconst.cpp b/lib-artnet/src/node/artnetmsgconst.cpp index f697afc5..7e07038b 100644 --- a/lib-artnet/src/node/artnetmsgconst.cpp +++ b/lib-artnet/src/node/artnetmsgconst.cpp @@ -2,10 +2,7 @@ * @file artnetmsgconst.cpp * */ -/** - * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. - */ -/* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,9 +25,6 @@ #include "artnetmsgconst.h" -const char ArtNetMsgConst::PARAMS[] = "Configuring Art-Net"; const char ArtNetMsgConst::START[] = "Starting Art-Net"; const char ArtNetMsgConst::STARTED[] = "Art-Net started"; const char ArtNetMsgConst::RDM_RUN[] = "Running RDM Discovery"; - - diff --git a/lib-artnet/src/node/artnetnode.cpp b/lib-artnet/src/node/artnetnode.cpp old mode 100644 new mode 100755 index 983b39d2..13f84124 --- a/lib-artnet/src/node/artnetnode.cpp +++ b/lib-artnet/src/node/artnetnode.cpp @@ -5,7 +5,7 @@ /** * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. */ -/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,6 +34,7 @@ #include "artnetnode.h" #include "artnetconst.h" #include "artnet.h" +#include "artnetstore.h" #if defined (ARTNET_HAVE_DMXIN) # include "dmx.h" @@ -43,6 +44,13 @@ # include "e131.h" #endif +#if defined (ARTNET_SHOWFILE) +namespace showfile { +void record(const struct artnet::ArtDmx *pArtDmx, const uint32_t nMillis); +void record(const struct artnet::ArtSync *pArtSync, const uint32_t nMillis); +} // namespace showfile +#endif + #include "lightset.h" #include "lightsetdata.h" @@ -82,6 +90,12 @@ ArtNetNode::ArtNetNode() { m_ArtPollReply.AcnPriority = e131::priority::DEFAULT; #endif + memset(&m_State, 0, sizeof(struct artnetnode::State)); + m_State.reportCode = artnet::ReportCode::RCPOWEROK; + m_State.status = artnet::Status::STANDBY; + // The device should wait for a random delay of up to 1s before sending the reply. + m_State.ArtPollReplyDelayMillis = (m_ArtPollReply.MAC[5] | (static_cast(m_ArtPollReply.MAC[4]) << 8)) % 1000; + SetLongName(nullptr); // Set default long name memset(&m_Node, 0, sizeof(struct artnetnode::Node)); @@ -95,17 +109,11 @@ ArtNetNode::ArtNetNode() { SetShortName(nPortIndex, nullptr); // Set default port label } - memset(&m_State, 0, sizeof(struct artnetnode::State)); - m_State.reportCode = artnetnode::ReportCode::RCPOWEROK; - m_State.status = artnetnode::Status::STANDBY; - // The device should wait for a random delay of up to 1s before sending the reply. - m_State.ArtPollReplyDelayMillis = (m_ArtPollReply.MAC[5] | (static_cast(m_ArtPollReply.MAC[4]) << 8)) % 1000; - for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { memset(&m_OutputPort[nPortIndex], 0, sizeof(struct artnetnode::OutputPort)); m_OutputPort[nPortIndex].SourceA.nPhysical = 0x100; m_OutputPort[nPortIndex].SourceB.nPhysical = 0x100; - m_OutputPort[nPortIndex].GoodOutputB = artnet::GoodOutputB::RDM_DISABLED; + m_OutputPort[nPortIndex].GoodOutputB = artnet::GoodOutputB::RDM_DISABLED | artnet::GoodOutputB::DISCOVERY_NOT_RUNNING; memset(&m_InputPort[nPortIndex], 0, sizeof(struct artnetnode::InputPort)); m_InputPort[nPortIndex].nDestinationIp = Network::Get()->GetBroadcastIp(); } @@ -167,7 +175,7 @@ void ArtNetNode::Start() { m_ArtPollReply.Status2 &= static_cast(~artnet::Status2::DHCP_CAPABLE); m_ArtPollReply.Status2 |= Network::Get()->IsDhcpCapable() ? artnet::Status2::DHCP_CAPABLE : static_cast(0); - #if defined (ENABLE_HTTPD) && defined (ENABLE_CONTENT) +#if defined (ENABLE_HTTPD) && defined (ENABLE_CONTENT) m_ArtPollReply.Status2 |= artnet::Status2::WEB_BROWSER_SUPPORT; #endif #if defined (OUTPUT_HAVE_STYLESWITCH) @@ -179,7 +187,7 @@ void ArtNetNode::Start() { /* * Status 3 */ - m_ArtPollReply.Status3 = artnet::Status3::NETWORKLOSS_LAST_STATE | artnet::Status3::FAILSAFE_CONTROL; + m_ArtPollReply.Status3 = artnet::Status3::NETWORKLOSS_LAST_STATE | artnet::Status3::FAILSAFE_CONTROL | artnet::Status3::SUPPORTS_BACKGROUNDDISCOVERY; #if defined (ARTNET_HAVE_DMXIN) m_ArtPollReply.Status3 |= artnet::Status3::OUTPUT_SWITCH; #endif @@ -211,15 +219,11 @@ void ArtNetNode::Start() { } #endif -#if defined (RDM_CONTROLLER) || defined (RDM_RESPONDER) - if (m_pArtNetRdm != nullptr) { - for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { - const auto isRdmDisabled = ((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::RDM_DISABLED) == artnet::GoodOutputB::RDM_DISABLED); - - if (!isRdmDisabled && (m_Node.Port[nPortIndex].direction == lightset::PortDir::OUTPUT)) { - SendTod(nPortIndex); - } +#if defined (RDM_CONTROLLER) + if (m_State.rdm.IsEnabled) { + m_State.rdm.IsDiscoveryRunning = true; + for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { if (m_Node.Port[nPortIndex].direction == lightset::PortDir::INPUT) { SendTodRequest(nPortIndex); } @@ -228,10 +232,10 @@ void ArtNetNode::Start() { #endif #if (ARTNET_VERSION >= 4) - E131Bridge::Start(); + E131Bridge::Start(); #endif - m_State.status = artnetnode::Status::ON; + m_State.status = artnet::Status::ON; Hardware::Get()->SetMode(hardware::ledblink::Mode::NORMAL); DEBUG_EXIT @@ -266,7 +270,7 @@ void ArtNetNode::Stop() { hal::panel_led_off(hal::panelled::ARTNET); m_ArtPollReply.Status1 = static_cast((m_ArtPollReply.Status1 & ~artnet::Status1::INDICATOR_MASK) | artnet::Status1::INDICATOR_MUTE_MODE); - m_State.status = artnetnode::Status::STANDBY; + m_State.status = artnet::Status::STANDBY; DEBUG_EXIT } @@ -284,10 +288,8 @@ void ArtNetNode::SetShortName(const uint32_t nPortIndex, const char *pShortName) m_Node.Port[nPortIndex].ShortName[artnet::SHORT_NAME_LENGTH - 1] = '\0'; - if (m_State.status == artnetnode::Status::ON) { - if (m_pArtNetStore != nullptr) { - m_pArtNetStore->SaveShortName(nPortIndex, m_Node.Port[nPortIndex].ShortName); - } + if (m_State.status == artnet::Status::ON) { + ArtNetStore::SaveShortName(nPortIndex, m_Node.Port[nPortIndex].ShortName); } DEBUG_PUTS(m_Node.Port[nPortIndex].ShortName); @@ -299,7 +301,7 @@ void ArtNetNode::GetLongNameDefault(char *pLongName) { uint8_t nBoardNameLength; const auto *const pBoardName = Hardware::Get()->GetBoardName(nBoardNameLength); const auto *const pWebsiteUrl = Hardware::Get()->GetWebsiteUrl(); - snprintf(pLongName, artnet::LONG_NAME_LENGTH - 1, "%s %s %d %s", pBoardName, artnet::NODE_ID, artnet::VERSION, pWebsiteUrl); + snprintf(pLongName, artnet::LONG_NAME_LENGTH - 1, "%s %s %u %s", pBoardName, artnet::NODE_ID, static_cast(artnet::VERSION), pWebsiteUrl); #else uint32_t i; @@ -326,11 +328,8 @@ void ArtNetNode::SetLongName(const char *pLongName) { m_ArtPollReply.LongName[artnet::LONG_NAME_LENGTH - 1] = '\0'; - if (m_State.status == artnetnode::Status::ON) { - if (m_pArtNetStore != nullptr) { - m_pArtNetStore->SaveLongName(reinterpret_cast(m_ArtPollReply.LongName)); - } - + if (m_State.status == artnet::Status::ON) { + ArtNetStore::SaveLongName(reinterpret_cast(m_ArtPollReply.LongName)); artnet::display_longname(reinterpret_cast(m_ArtPollReply.LongName)); } @@ -338,6 +337,41 @@ void ArtNetNode::SetLongName(const char *pLongName) { DEBUG_EXIT } +#if defined (OUTPUT_HAVE_STYLESWITCH) +void ArtNetNode::SetOutputStyle(const uint32_t nPortIndex, lightset::OutputStyle outputStyle) { + assert(nPortIndex < artnetnode::MAX_PORTS); + + if ((outputStyle == GetOutputStyle(nPortIndex)) && (m_State.status == artnet::Status::ON)) { + return; + } + + if (m_pLightSet != nullptr) { + m_pLightSet->SetOutputStyle(nPortIndex, outputStyle); + outputStyle = m_pLightSet->GetOutputStyle(nPortIndex); + } + + if (outputStyle == lightset::OutputStyle::CONSTANT) { + m_OutputPort[nPortIndex].GoodOutputB |= artnet::GoodOutputB::STYLE_CONSTANT; + } else { + m_OutputPort[nPortIndex].GoodOutputB &= static_cast(~artnet::GoodOutputB::STYLE_CONSTANT); + } + + m_State.IsSynchronousMode = false; + + if (m_State.status == artnet::Status::ON) { + ArtNetStore::SaveOutputStyle(nPortIndex, outputStyle); + artnet::display_outputstyle(nPortIndex, outputStyle); + } +} + +lightset::OutputStyle ArtNetNode::GetOutputStyle(const uint32_t nPortIndex) const { + assert(nPortIndex < artnetnode::MAX_PORTS); + + const auto isStyleConstant = (m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::STYLE_CONSTANT) == artnet::GoodOutputB::STYLE_CONSTANT; + return isStyleConstant ? lightset::OutputStyle::CONSTANT : lightset::OutputStyle::DELTA; +} +#endif + void ArtNetNode::SetNetworkDataLossCondition() { m_State.IsMergeMode = false; m_State.IsSynchronousMode = false; @@ -411,7 +445,7 @@ static artnet::OpCodes get_op_code(const uint32_t nBytesReceived, const uint8_t return artnet::OpCodes::OP_NOT_DEFINED; } -void ArtNetNode::Process(const uint16_t nBytesReceived) { +void ArtNetNode::Process(const uint32_t nBytesReceived) { if (__builtin_expect((nBytesReceived == 0), 1)) { const auto nDeltaMillis = m_nCurrentPacketMillis - m_nPreviousPacketMillis; @@ -429,7 +463,7 @@ void ArtNetNode::Process(const uint16_t nBytesReceived) { #endif #if defined (RDM_CONTROLLER) - if (m_pArtNetRdm != nullptr) { + if (m_State.rdm.IsEnabled) { HandleRdmIn(); } #endif @@ -478,6 +512,11 @@ void ArtNetNode::Process(const uint16_t nBytesReceived) { if (m_pLightSet != nullptr) { HandleDmx(); m_State.ArtDmxIpAddress = m_nIpAddressFrom; +#if defined (ARTNET_SHOWFILE) + if (m_State.DoRecord) { + showfile::record(reinterpret_cast(m_pReceiveBuffer), m_nCurrentPacketMillis); + } +#endif } break; case artnet::OpCodes::OP_SYNC: @@ -496,6 +535,11 @@ void ArtNetNode::Process(const uint16_t nBytesReceived) { m_State.ArtSyncMillis = Hardware::Get()->Millis(); HandleSync(); } +#if defined (ARTNET_SHOWFILE) + if (m_State.DoRecord) { + showfile::record(reinterpret_cast(m_pReceiveBuffer), m_nCurrentPacketMillis); + } +#endif } break; #endif @@ -505,7 +549,8 @@ void ArtNetNode::Process(const uint16_t nBytesReceived) { #if defined (ARTNET_HAVE_TIMECODE) case artnet::OpCodes::OP_TIMECODE: if (m_pArtNetTimeCode != nullptr) { - HandleTimeCode(); + const auto *const pArtTimeCode = reinterpret_cast(m_pReceiveBuffer); + m_pArtNetTimeCode->Handler(reinterpret_cast(&pArtTimeCode->Frames)); } break; #endif @@ -514,25 +559,30 @@ void ArtNetNode::Process(const uint16_t nBytesReceived) { break; #if defined (RDM_CONTROLLER) || defined (RDM_RESPONDER) case artnet::OpCodes::OP_TODREQUEST: - if (m_pArtNetRdm != nullptr) { + if (m_State.rdm.IsEnabled) { HandleTodRequest(); } break; case artnet::OpCodes::OP_TODDATA: - if (m_pArtNetRdm != nullptr) { + if (m_State.rdm.IsEnabled) { HandleTodData(); } break; case artnet::OpCodes::OP_TODCONTROL: - if (m_pArtNetRdm != nullptr) { + if (m_State.rdm.IsEnabled) { HandleTodControl(); } break; case artnet::OpCodes::OP_RDM: - if (m_pArtNetRdm != nullptr) { + if (m_State.rdm.IsEnabled) { HandleRdm(); } break; + case artnet::OpCodes::OP_RDMSUB: + if (m_State.rdm.IsEnabled) { + HandleRdmSub(); + } + break; #endif case artnet::OpCodes::OP_IPPROG: HandleIpProg(); @@ -561,7 +611,7 @@ void ArtNetNode::Process(const uint16_t nBytesReceived) { #endif #if defined (RDM_CONTROLLER) - if (m_pArtNetRdm != nullptr) { + if (m_State.rdm.IsEnabled) { HandleRdmIn(); } #endif diff --git a/lib-artnet/src/node/artnetnodehandleaddress.cpp b/lib-artnet/src/node/artnetnodehandleaddress.cpp index e1d0b3c7..24d98326 100644 --- a/lib-artnet/src/node/artnetnodehandleaddress.cpp +++ b/lib-artnet/src/node/artnetnodehandleaddress.cpp @@ -5,7 +5,7 @@ /** * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,6 +33,7 @@ #include "artnetnode.h" #include "artnetconst.h" #include "artnetnode_internal.h" +#include "artnetstore.h" #include "lightsetdata.h" #include "hardware.h" @@ -86,10 +87,6 @@ void ArtNetNode::SetLocalMerging() { DEBUG_EXIT } -uint16_t ArtNetNode::MakePortAddress(const uint16_t nUniverse, const uint32_t nPage) { - return artnet::make_port_address(m_Node.Port[nPage].NetSwitch, m_Node.Port[nPage].SubSwitch, nUniverse); -} - void ArtNetNode::SetUniverse(const uint32_t nPortIndex, const lightset::PortDir dir, const uint16_t nUniverse) { assert(nPortIndex < artnetnode::MAX_PORTS); @@ -162,11 +159,8 @@ void ArtNetNode::SetUniverseSwitch(const uint32_t nPortIndex, const lightset::Po SetUniverse4(nPortIndex, dir); #endif - if (m_State.status == artnetnode::Status::ON) { - if (m_pArtNetStore != nullptr) { - m_pArtNetStore->SaveUniverseSwitch(nPortIndex, nAddress); - } - + if (m_State.status == artnet::Status::ON) { + ArtNetStore::SaveUniverseSwitch(nPortIndex, nAddress); artnet::display_universe_switch(nPortIndex, nAddress); #if defined (ARTNET_HAVE_DMXIN) @@ -184,8 +178,8 @@ void ArtNetNode::SetSubnetSwitch(const uint32_t nPortIndex, const uint8_t nSubne m_Node.Port[nPortIndex].SubSwitch = nSubnetSwitch; m_Node.Port[nPortIndex].PortAddress = MakePortAddress(m_Node.Port[nPortIndex].PortAddress, nPortIndex); - if ((m_pArtNetStore != nullptr) && (m_State.status == artnetnode::Status::ON)) { - m_pArtNetStore->SaveSubnetSwitch(nPortIndex, nSubnetSwitch); + if (m_State.status == artnet::Status::ON) { + ArtNetStore::SaveSubnetSwitch(nPortIndex, nSubnetSwitch); } DEBUG_EXIT @@ -198,8 +192,8 @@ void ArtNetNode::SetNetSwitch(const uint32_t nPortIndex, const uint8_t nNetSwitc m_Node.Port[nPortIndex].NetSwitch = nNetSwitch; m_Node.Port[nPortIndex].PortAddress = MakePortAddress(m_Node.Port[nPortIndex].PortAddress, nPortIndex); - if ((m_pArtNetStore != nullptr) && (m_State.status == artnetnode::Status::ON)) { - m_pArtNetStore->SaveNetSwitch(nPortIndex, nNetSwitch); + if (m_State.status == artnet::Status::ON) { + ArtNetStore::SaveNetSwitch(nPortIndex, nNetSwitch); } DEBUG_EXIT @@ -218,11 +212,8 @@ void ArtNetNode::SetMergeMode(const uint32_t nPortIndex, const lightset::MergeMo E131Bridge::SetMergeMode(nPortIndex, mergeMode); #endif - if (m_State.status == artnetnode::Status::ON) { - if (m_pArtNetStore != nullptr) { - m_pArtNetStore->SaveMergeMode(nPortIndex, mergeMode); - } - + if (m_State.status == artnet::Status::ON) { + ArtNetStore::SaveMergeMode(nPortIndex, mergeMode); artnet::display_merge_mode(nPortIndex, mergeMode); } } @@ -231,7 +222,7 @@ void ArtNetNode::SetFailSafe(const artnetnode::FailSafe failsafe) { DEBUG_PRINTF("failsafe=%u", static_cast(failsafe)); #if defined(ARTNET_HAVE_FAILSAFE_RECORD) - if ((m_State.status == artnetnode::Status::ON) && (failsafe == artnetnode::FailSafe::RECORD)) { + if ((m_State.status == artnet::Status::ON) && (failsafe == artnetnode::FailSafe::RECORD)) { FailSafeRecord(); return; } @@ -275,13 +266,9 @@ void ArtNetNode::SetFailSafe(const artnetnode::FailSafe failsafe) { E131Bridge::SetFailSafe(static_cast(static_cast(failsafe) & 0x3)); #endif - if (m_State.status == artnetnode::Status::ON) { + if (m_State.status == artnet::Status::ON) { const auto nFailSafe = static_cast(static_cast(failsafe) & 0x3); - - if (m_pArtNetStore != nullptr) { - m_pArtNetStore->SaveFailSafe(nFailSafe); - } - + ArtNetStore::SaveFailSafe(nFailSafe); artnet::display_failsafe(nFailSafe); } @@ -290,7 +277,7 @@ void ArtNetNode::SetFailSafe(const artnetnode::FailSafe failsafe) { void ArtNetNode::HandleAddress() { const auto *const pArtAddress = reinterpret_cast(m_pReceiveBuffer); - m_State.reportCode = artnetnode::ReportCode::RCPOWEROK; + m_State.reportCode = artnet::ReportCode::RCPOWEROK; const auto nPage = static_cast(pArtAddress->BindIndex > 0 ? pArtAddress->BindIndex - 1 : 0); @@ -298,12 +285,12 @@ void ArtNetNode::HandleAddress() { if (pArtAddress->ShortName[0] != 0) { SetShortName(nPage, reinterpret_cast(pArtAddress->ShortName)); - m_State.reportCode = artnetnode::ReportCode::RCSHNAMEOK; + m_State.reportCode = artnet::ReportCode::RCSHNAMEOK; } if (pArtAddress->LongName[0] != 0) { SetLongName(reinterpret_cast(pArtAddress->LongName)); - m_State.reportCode = artnetnode::ReportCode::RCLONAMEOK; + m_State.reportCode = artnet::ReportCode::RCLONAMEOK; } if (pArtAddress->SubSwitch == artnet::Program::DEFAULTS) { @@ -483,14 +470,14 @@ void ArtNetNode::HandleAddress() { case artnet::PortCommand::RDM_ENABLE1: case artnet::PortCommand::RDM_ENABLE2: case artnet::PortCommand::RDM_ENABLE3: - SetRmd(nPage, true); + SetRdm(nPage, true); break; case artnet::PortCommand::RDM_DISABLE0: case artnet::PortCommand::RDM_DISABLE1: case artnet::PortCommand::RDM_DISABLE2: case artnet::PortCommand::RDM_DISABLE3: - SetRmd(nPage, false); + SetRdm(nPage, false); break; #endif default: diff --git a/lib-artnet/src/node/artnetnodehandledmx.cpp b/lib-artnet/src/node/artnetnodehandledmx.cpp index 8b5546a8..c1547917 100755 --- a/lib-artnet/src/node/artnetnodehandledmx.cpp +++ b/lib-artnet/src/node/artnetnodehandledmx.cpp @@ -26,6 +26,12 @@ * THE SOFTWARE. */ +#if !defined(__clang__) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif + #include #include #include diff --git a/lib-artnet/src/node/artnetnodehandlepoll.cpp b/lib-artnet/src/node/artnetnodehandlepoll.cpp index 3b567f64..28360a1c 100644 --- a/lib-artnet/src/node/artnetnodehandlepoll.cpp +++ b/lib-artnet/src/node/artnetnodehandlepoll.cpp @@ -48,7 +48,7 @@ union uip { uint8_t u8[4]; } static ip; -void ArtNetNode::ProcessPollRelply(const uint32_t nPortIndex, __attribute__((unused)) uint32_t& NumPortsInput, uint32_t& NumPortsOutput) { +void ArtNetNode::ProcessPollRelply(const uint32_t nPortIndex, [[maybe_unused]] uint32_t& NumPortsInput, uint32_t& NumPortsOutput) { if (m_Node.Port[nPortIndex].direction == lightset::PortDir::OUTPUT) { #if (ARTNET_VERSION >= 4) if (m_Node.Port[nPortIndex].protocol == artnet::PortProtocol::SACN) { @@ -87,7 +87,7 @@ void ArtNetNode::ProcessPollRelply(const uint32_t nPortIndex, __attribute__((unu #endif } -void ArtNetNode::SendPollRelply(const uint32_t nBindIndex, const uint32_t nDestinationIp, artnetnode::ArtPollQueue *pQueue) { +void ArtNetNode::SendPollRelply(const uint32_t nBindIndex, const uint32_t nDestinationIp, artnet::ArtPollQueue *pQueue) { DEBUG_PRINTF("nBindIndex=%u", nBindIndex); ip.u32 = Network::Get()->GetIp(); @@ -130,7 +130,14 @@ void ArtNetNode::SendPollRelply(const uint32_t nBindIndex, const uint32_t nDesti ProcessPollRelply(nPortIndex, nPortsInput, nPortsOutput); + if (__builtin_expect((m_pLightSet != nullptr), 1)) { + const auto nRefreshRate = m_pLightSet->GetRefreshRate(); + m_ArtPollReply.RefreshRateLo = static_cast(nRefreshRate); + m_ArtPollReply.RefreshRateHi = static_cast(nRefreshRate >> 8); + } + m_ArtPollReply.NumPortsLo = static_cast(std::max(nPortsInput, nPortsOutput)); + m_State.ArtPollReplyCount++; uint8_t nSysNameLenght; diff --git a/lib-artnet/src/node/artnetnodehandlesync.cpp b/lib-artnet/src/node/artnetnodehandlesync.cpp index 39e6323f..17c5f0ff 100755 --- a/lib-artnet/src/node/artnetnodehandlesync.cpp +++ b/lib-artnet/src/node/artnetnodehandlesync.cpp @@ -41,12 +41,6 @@ void ArtNetNode::HandleSync() { if (!m_State.IsSynchronousMode) { m_State.IsSynchronousMode = true; - /* - * As the ArtSync is after the ArtDmx which are already processed - * we need to do a forced sync - */ - m_pLightSet->Sync(true); - SendDiag(artnet::PriorityCodes::DIAG_LOW, "Sync forced"); return; } diff --git a/lib-artnet/src/node/artnetnodeprint.cpp b/lib-artnet/src/node/artnetnodeprint.cpp index 116bfc79..06f617a7 100644 --- a/lib-artnet/src/node/artnetnodeprint.cpp +++ b/lib-artnet/src/node/artnetnodeprint.cpp @@ -45,8 +45,11 @@ #include "network.h" void ArtNetNode::Print() { - printf("Art-Net %d V%d.%d\n", artnet::VERSION, ArtNetConst::VERSION[0], ArtNetConst::VERSION[1]); - printf(" Long name : %s\n", reinterpret_cast(m_ArtPollReply.LongName)); + printf("Art-Net %u V%u.%u\n", + static_cast(artnet::VERSION), + static_cast(ArtNetConst::VERSION[0]), + static_cast(ArtNetConst::VERSION[1])); + printf(" Long name : %s\n", reinterpret_cast(m_ArtPollReply.LongName)); #if defined (ARTNET_HAVE_TIMECODE) printf(" TimeCode IP: " IPSTR "\n", IP2STR(m_Node.IPAddressTimeCode)); #endif @@ -58,15 +61,14 @@ void ArtNetNode::Print() { uint16_t nUniverse; if (GetPortAddress(nPortIndex, nUniverse, lightset::PortDir::OUTPUT)) { const auto mergeMode = ((m_OutputPort[nPortIndex].GoodOutput & artnet::GoodOutput::MERGE_MODE_LTP) == artnet::GoodOutput::MERGE_MODE_LTP) ? lightset::MergeMode::LTP : lightset::MergeMode::HTP; - printf(" Port %-2d %-4u %s %s", nPortIndex, nUniverse, lightset::get_merge_mode(mergeMode, true), GetRdm(0) ? "RDM" : ""); + printf(" Port %-2u %-4u %s", static_cast(nPortIndex), static_cast(nUniverse), lightset::get_merge_mode(mergeMode, true)); #if defined (OUTPUT_HAVE_STYLESWITCH) printf(" %s", lightset::get_output_style(GetOutputStyle(nPortIndex), true)); #endif #if (ARTNET_VERSION >= 4) - printf(" %s\n", artnet::get_protocol_mode(m_Node.Port[nPortIndex].protocol, true)); -#else - printf("\n"); + printf(" %s", artnet::get_protocol_mode(m_Node.Port[nPortIndex].protocol, true)); #endif + printf(" %s\n", GetRdm(nPortIndex) ? "RDM" : " "); } } } @@ -79,7 +81,7 @@ void ArtNetNode::Print() { uint16_t nUniverse; if (GetPortAddress(nPortIndex, nUniverse, lightset::PortDir::INPUT)) { - printf(" Port %-2d %-4u", nPortIndex, nUniverse); + printf(" Port %-2u %-4u", static_cast(nPortIndex), static_cast(nUniverse)); if (m_Node.Port[nPortIndex].protocol == artnet::PortProtocol::ARTNET) { const auto nDestinationIp = (m_InputPort[nPortIndex].nDestinationIp == 0 ? Network::Get()->GetBroadcastIp() : m_InputPort[nPortIndex].nDestinationIp); printf(" -> " IPSTR, IP2STR(nDestinationIp)); @@ -87,7 +89,7 @@ void ArtNetNode::Print() { #if (ARTNET_VERSION >= 4) printf(" %s\n", artnet::get_protocol_mode(m_Node.Port[nPortIndex].protocol, true)); #else - printf("\n"); + puts(""); #endif } } diff --git a/lib-artnet/src/node/artnetparams.cpp b/lib-artnet/src/node/artnetparams.cpp index 0c13dc27..65f593de 100644 --- a/lib-artnet/src/node/artnetparams.cpp +++ b/lib-artnet/src/node/artnetparams.cpp @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -58,6 +59,12 @@ #include "debug.h" +namespace artnetnode { +namespace configstore { +extern uint32_t DMXPORT_OFFSET; +} // namespace configstore +} // namespace artnetnode + static uint32_t s_nPortsMax; namespace artnetparams { @@ -70,7 +77,7 @@ static constexpr bool is_set(const uint16_t nValue, const uint32_t i) { using namespace artnetparams; -ArtNetParams::ArtNetParams(ArtNetParamsStore *pArtNetParamsStore): m_pArtNetParamsStore(pArtNetParamsStore) { +ArtNetParams::ArtNetParams() { DEBUG_ENTRY auto *const pArtnetNode = ArtNetNode::Get(); @@ -101,18 +108,14 @@ bool ArtNetParams::Load() { ReadConfigFile configfile(ArtNetParams::staticCallbackFunction, this); if (configfile.Read(ArtNetParamsConst::FILE_NAME)) { - // There is a configuration file - if (m_pArtNetParamsStore != nullptr) { - m_pArtNetParamsStore->Update(&m_Params); - } + ArtNetParamsStore::Update(&m_Params); } else #endif - if (m_pArtNetParamsStore != nullptr) { - m_pArtNetParamsStore->Copy(&m_Params); - } else { - return false; - } + ArtNetParamsStore::Copy(&m_Params); +#ifndef NDEBUG + Dump(); +#endif return true; } @@ -128,8 +131,11 @@ void ArtNetParams::Load(const char *pBuffer, uint32_t nLength) { config.Read(pBuffer, nLength); - assert(m_pArtNetParamsStore != nullptr); - m_pArtNetParamsStore->Update(&m_Params); + ArtNetParamsStore::Update(&m_Params); + +#ifndef NDEBUG + Dump(); +#endif DEBUG_EXIT } @@ -335,13 +341,6 @@ void ArtNetParams::callbackFunction(const char *pLine) { } } -void ArtNetParams::staticCallbackFunction(void *p, const char *s) { - assert(p != nullptr); - assert(s != nullptr); - - (static_cast(p))->callbackFunction(s); -} - void ArtNetParams::Builder(const struct Params *pParams, char *pBuffer, uint32_t nLength, uint32_t& nSize) { DEBUG_ENTRY DEBUG_PRINTF("s_nPortsMax=%u", s_nPortsMax); @@ -351,14 +350,13 @@ void ArtNetParams::Builder(const struct Params *pParams, char *pBuffer, uint32_t if (pParams != nullptr) { memcpy(&m_Params, pParams, sizeof(struct Params)); } else { - assert(m_pArtNetParamsStore != nullptr); - m_pArtNetParamsStore->Copy(&m_Params); + ArtNetParamsStore::Copy(&m_Params); } PropertiesBuilder builder(ArtNetParamsConst::FILE_NAME, pBuffer, nLength); if (!isMaskSet(Mask::LONG_NAME)) { - memcpy(m_Params.aLongName, ArtNetNode::Get()->GetLongName(), artnet::LONG_NAME_LENGTH); + ArtNetNode::Get()->GetLongNameDefault(reinterpret_cast(m_Params.aLongName)); } builder.Add(LightSetParamsConst::NODE_LONG_NAME, reinterpret_cast(m_Params.aLongName), isMaskSet(Mask::LONG_NAME)); @@ -368,6 +366,13 @@ void ArtNetParams::Builder(const struct Params *pParams, char *pBuffer, uint32_t builder.Add(LightSetParamsConst::FAILSAFE, lightset::get_failsafe(static_cast(m_Params.nFailSafe)), isMaskSet(Mask::FAILSAFE)); for (uint32_t nPortIndex = 0; nPortIndex < s_nPortsMax; nPortIndex++) { + const auto nOffset = nPortIndex + artnetnode::configstore::DMXPORT_OFFSET; + + if (nOffset >= artnetnode::MAX_PORTS) { + DEBUG_PUTS("break"); + break; + } + builder.Add(LightSetParamsConst::UNIVERSE_PORT[nPortIndex], m_Params.nUniverse[nPortIndex], isMaskSet(Mask::UNIVERSE_A << nPortIndex)); const auto portDir = portdir_get(nPortIndex); const auto isDefault = (portDir == lightset::PortDir::OUTPUT); @@ -376,8 +381,9 @@ void ArtNetParams::Builder(const struct Params *pParams, char *pBuffer, uint32_t const auto isLabelSet = isMaskSet(Mask::LABEL_A << nPortIndex); if (!isLabelSet) { - memcpy(m_Params.aLabel[nPortIndex], ArtNetNode::Get()->GetShortName(nPortIndex), artnet::SHORT_NAME_LENGTH); + memcpy(m_Params.aLabel[nPortIndex], ArtNetNode::Get()->GetShortName(nOffset), artnet::SHORT_NAME_LENGTH); } + builder.Add(LightSetParamsConst::NODE_LABEL[nPortIndex], reinterpret_cast(m_Params.aLabel[nPortIndex]), isLabelSet); } @@ -428,14 +434,14 @@ void ArtNetParams::Builder(const struct Params *pParams, char *pBuffer, uint32_t DEBUG_EXIT } -void ArtNetParams::Set(uint32_t nPortIndexOffset) { +void ArtNetParams::Set() { DEBUG_ENTRY - if (nPortIndexOffset <= artnetnode::MAX_PORTS) { - s_nPortsMax = std::min(artnet::PORTS, artnetnode::MAX_PORTS - nPortIndexOffset); + if (artnetnode::configstore::DMXPORT_OFFSET <= artnetnode::MAX_PORTS) { + s_nPortsMax = std::min(artnet::PORTS, artnetnode::MAX_PORTS - artnetnode::configstore::DMXPORT_OFFSET); } - DEBUG_PRINTF("artnetnode::MAX_PORTS=%u, nPortIndexOffset=%u, s_nPortsMax=%u", artnetnode::MAX_PORTS, nPortIndexOffset, s_nPortsMax); + DEBUG_PRINTF("artnetnode::MAX_PORTS=%u, artnetnode::configstore::DMXPORT_OFFSET=%u, s_nPortsMax=%u", artnetnode::MAX_PORTS, artnetnode::configstore::DMXPORT_OFFSET, s_nPortsMax); auto *const p = ArtNetNode::Get(); assert(p != nullptr); @@ -445,7 +451,7 @@ void ArtNetParams::Set(uint32_t nPortIndexOffset) { } for (uint32_t nPortIndex = 0; nPortIndex < s_nPortsMax; nPortIndex++) { - const auto nOffset = nPortIndex + nPortIndexOffset; + const auto nOffset = nPortIndex + artnetnode::configstore::DMXPORT_OFFSET; if (nOffset >= artnetnode::MAX_PORTS) { DEBUG_PUTS("break"); @@ -476,7 +482,7 @@ void ArtNetParams::Set(uint32_t nPortIndexOffset) { #if defined (RDM_CONTROLLER) if (artnetparams::is_set(m_Params.nRdm, nPortIndex)) { - p->SetRmd(nOffset, true); + p->SetRdm(nOffset, true); } #endif @@ -505,3 +511,67 @@ void ArtNetParams::Set(uint32_t nPortIndexOffset) { DEBUG_EXIT } + +void ArtNetParams::staticCallbackFunction(void *p, const char *s) { + assert(p != nullptr); + assert(s != nullptr); + + (static_cast(p))->callbackFunction(s); +} + +void ArtNetParams::Dump() { + printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, ArtNetParamsConst::FILE_NAME); + + printf(" %s=%d [%s]\n", LightSetParamsConst::FAILSAFE, m_Params.nFailSafe, lightset::get_failsafe(static_cast(m_Params.nFailSafe))); + + for (uint32_t i = 0; i < artnet::PORTS; i++) { + printf(" %s=%s\n", LightSetParamsConst::NODE_LABEL[i], m_Params.aLabel[i]); + } + + printf(" %s=%s\n", LightSetParamsConst::NODE_LONG_NAME, m_Params.aLongName); + printf(" %s=1 [Yes]\n", ArtNetParamsConst::ENABLE_RDM); + + + for (uint32_t i = 0; i < artnet::PORTS; i++) { + printf(" %s=%d\n", LightSetParamsConst::UNIVERSE_PORT[i], m_Params.nUniverse[i]); + } + + for (uint32_t i = 0; i < artnet::PORTS; i++) { + printf(" %s=%s\n", LightSetParamsConst::MERGE_MODE_PORT[i], lightset::get_merge_mode(mergemode_get(i))); + } + + for (uint32_t i = 0; i < artnet::PORTS; i++) { + printf(" %s=%s\n", ArtNetParamsConst::PROTOCOL_PORT[i], artnet::get_protocol_mode(i)); + } + + for (uint32_t i = 0; i < artnet::PORTS; i++) { + const auto portDir = portdir_get(i); + printf(" %s=%u [%s]\n", LightSetParamsConst::DIRECTION[i], static_cast(portDir), lightset::get_direction(portDir)); + } + + for (uint32_t i = 0; i < artnet::PORTS; i++) { + printf(" %s=" IPSTR "\n", ArtNetParamsConst::DESTINATION_IP_PORT[i], IP2STR(m_Params.nDestinationIp[i])); + + } + + for (uint32_t i = 0; i < artnet::PORTS; i++) { + const auto nOutputStyle = static_cast(isOutputStyleSet(1U << i)); + printf(" %s=%u [%s]\n", LightSetParamsConst::OUTPUT_STYLE[i], static_cast(nOutputStyle), lightset::get_output_style(static_cast(nOutputStyle))); + } + + /** + * Art-Net 4 + */ + + printf(" %s=1 [Yes]\n", ArtNetParamsConst::MAP_UNIVERSE0); + + for (uint32_t i = 0; i < artnet::PORTS; i++) { + printf(" %s=%u\n", LightSetParamsConst::PRIORITY[i], m_Params.nPriority[i]); + } + + /** + * Extra's + */ + + printf(" %s=1 [Yes]\n", LightSetParamsConst::DISABLE_MERGE_TIMEOUT); +} diff --git a/lib-artnet/src/node/artnetparamsdump.cpp b/lib-artnet/src/node/artnetparamsdump.cpp deleted file mode 100644 index 43596554..00000000 --- a/lib-artnet/src/node/artnetparamsdump.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/** - * @file artnetparamsdump.cpp - * - */ -/** - * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. - */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#if !defined(__clang__) // Needed for compiling on MacOS -# pragma GCC push_options -# pragma GCC optimize ("Os") -#endif - -#include - -#include "artnetparams.h" -#include "artnetparamsconst.h" - -#include "lightsetparamsconst.h" - -#include "network.h" - -void ArtNetParams::Dump() { -#ifndef NDEBUG - printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, ArtNetParamsConst::FILE_NAME); - - if (isMaskSet(artnetparams::Mask::FAILSAFE)) { - printf(" %s=%d [%s]\n", LightSetParamsConst::FAILSAFE, m_Params.nFailSafe, lightset::get_failsafe(static_cast(m_Params.nFailSafe))); - } - - for (uint32_t i = 0; i < artnet::PORTS; i++) { - if (isMaskSet(artnetparams::Mask::LABEL_A << i)) { - printf(" %s=%s\n", LightSetParamsConst::NODE_LABEL[i], m_Params.aLabel[i]); - } - } - - if (isMaskSet(artnetparams::Mask::LONG_NAME)) { - printf(" %s=%s\n", LightSetParamsConst::NODE_LONG_NAME, m_Params.aLongName); - } - - if (isMaskSet(artnetparams::Mask::ENABLE_RDM)) { - printf(" %s=1 [Yes]\n", ArtNetParamsConst::ENABLE_RDM); - } - - for (uint32_t i = 0; i < artnet::PORTS; i++) { - if (isMaskSet(artnetparams::Mask::UNIVERSE_A << i)) { - printf(" %s=%d\n", LightSetParamsConst::UNIVERSE_PORT[i], m_Params.nUniverse[i]); - } - } - - for (uint32_t i = 0; i < artnet::PORTS; i++) { - printf(" %s=%s\n", LightSetParamsConst::MERGE_MODE_PORT[i], lightset::get_merge_mode(mergemode_get(i))); - } - - for (uint32_t i = 0; i < artnet::PORTS; i++) { - const auto portProtocol = protocol_get(i); - const auto isDefault = (portProtocol == artnet::PortProtocol::ARTNET); - if (!isDefault) { - printf(" %s=%s\n", ArtNetParamsConst::PROTOCOL_PORT[i], artnet::get_protocol_mode(i)); - } - } - - for (uint32_t i = 0; i < artnet::PORTS; i++) { - const auto portDir = portdir_get(i); - const auto isDefault = (portDir == lightset::PortDir::OUTPUT); - if (!isDefault) { - printf(" %s=%u [%s]\n", LightSetParamsConst::DIRECTION[i], static_cast(portDir), lightset::get_direction(portDir)); - } - } - - for (uint32_t i = 0; i < artnet::PORTS; i++) { - if (isMaskSet(artnetparams::Mask::DESTINATION_IP_A << i)) { - printf(" %s=" IPSTR "\n", ArtNetParamsConst::DESTINATION_IP_PORT[i], IP2STR(m_Params.nDestinationIp[i])); - } - } - - for (uint32_t i = 0; i < artnet::PORTS; i++) { - const auto nOutputStyle = static_cast(isOutputStyleSet(1U << i)); - printf(" %s=%u [%s]\n", LightSetParamsConst::OUTPUT_STYLE[i], nOutputStyle, lightset::get_output_style(static_cast(nOutputStyle))); - } - - /** - * Art-Net 4 - */ - - if (isMaskSet(artnetparams::Mask::MAP_UNIVERSE0)) { - printf(" %s=1 [Yes]\n", ArtNetParamsConst::MAP_UNIVERSE0); - } - - for (uint32_t i = 0; i < artnet::PORTS; i++) { - if (isMaskSet(artnetparams::Mask::PRIORITY_A << i)) { - printf(" %s=%u\n", LightSetParamsConst::PRIORITY[i], m_Params.nPriority[i]); - } - } - - /** - * Extra's - */ - - if (isMaskSet(artnetparams::Mask::DISABLE_MERGE_TIMEOUT)) { - printf(" %s=1 [Yes]\n", LightSetParamsConst::DISABLE_MERGE_TIMEOUT); - } -#endif -} diff --git a/lib-artnet/src/node/dmxin/handledmxin.cpp b/lib-artnet/src/node/dmxin/handledmxin.cpp index 61a7d26f..38122538 100644 --- a/lib-artnet/src/node/dmxin/handledmxin.cpp +++ b/lib-artnet/src/node/dmxin/handledmxin.cpp @@ -5,7 +5,7 @@ /** * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,12 @@ * THE SOFTWARE. */ +#if !defined(__clang__) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif + #include #include #include @@ -47,8 +53,8 @@ static uint32_t s_ReceivingMask = 0; void ArtNetNode::HandleDmxIn() { for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { if ((m_Node.Port[nPortIndex].direction == lightset::PortDir::INPUT) - && (m_Node.Port[nPortIndex].protocol == artnet::PortProtocol::ARTNET) - && ((m_InputPort[nPortIndex].GoodInput & artnet::GoodInput::DISABLED) != artnet::GoodInput::DISABLED)) { + && (m_Node.Port[nPortIndex].protocol == artnet::PortProtocol::ARTNET) + && ((m_InputPort[nPortIndex].GoodInput & artnet::GoodInput::DISABLED) != artnet::GoodInput::DISABLED)) { const auto *const pDmxData = reinterpret_cast(Dmx::Get()->GetDmxChanged(nPortIndex)); @@ -73,6 +79,8 @@ void ArtNetNode::HandleDmxIn() { Network::Get()->SendTo(m_nHandle, &m_ArtDmx, sizeof(struct artnet::ArtDmx), m_InputPort[nPortIndex].nDestinationIp, artnet::UDP_PORT); + SendDiag(artnet::PriorityCodes::DIAG_LOW, "%u: Input DMX sent", nPortIndex); + if (m_Node.Port[nPortIndex].bLocalMerge) { m_pReceiveBuffer = reinterpret_cast(&m_ArtDmx); m_nIpAddressFrom = Network::Get()->GetIp(); @@ -148,7 +156,6 @@ void ArtNetNode::HandleDmxIn() { } } } - } } } diff --git a/lib-rdmdiscovery/src/artnet/artnetrdmcontroller.cpp b/lib-artnet/src/node/rdm/controller/artnetrdmcontroller.cpp similarity index 56% rename from lib-rdmdiscovery/src/artnet/artnetrdmcontroller.cpp rename to lib-artnet/src/node/rdm/controller/artnetrdmcontroller.cpp index 5789b50f..6ecdd327 100755 --- a/lib-rdmdiscovery/src/artnet/artnetrdmcontroller.cpp +++ b/lib-artnet/src/node/rdm/controller/artnetrdmcontroller.cpp @@ -2,7 +2,7 @@ * @file artnetrdmcontroller.cpp * */ -/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,83 +23,72 @@ * THE SOFTWARE. */ +#if !defined(__clang__) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif + #include #include #include -#include "hardware.h" - #include "artnetnode.h" #include "artnetrdmcontroller.h" #include "rdm.h" +#include "rdmconst.h" #include "rdm_e120.h" -#include "rdmdevicecontroller.h" -#include "rdmdiscovery.h" #include "debug.h" RDMTod ArtNetRdmController::m_pRDMTod[artnetnode::MAX_PORTS]; -TRdmMessage ArtNetRdmController::s_rdmMessage; - -ArtNetRdmController::ArtNetRdmController(): RDMDiscovery(RDMDeviceController::GetUID()) { - DEBUG_ENTRY - s_rdmMessage.start_code = E120_SC_RDM; - DEBUG_EXIT -} -const uint8_t *ArtNetRdmController::Handler(uint32_t nPortIndex, const uint8_t *pRdmData) { - assert(nPortIndex < artnetnode::MAX_PORTS); - - if (pRdmData == nullptr) { - return nullptr; - } +static void respond_message_ack(const uint32_t nPortIndex, struct TRdmMessage *pRdmMessage) { + assert(pRdmMessage->start_code == E120_SC_RDM); - Hardware::Get()->WatchdogFeed(); + pRdmMessage->message_count = 0; + pRdmMessage->command_class = static_cast(pRdmMessage->command_class + 1U); + pRdmMessage->message_length = static_cast(RDM_MESSAGE_MINIMUM_SIZE + pRdmMessage->param_data_length); + pRdmMessage->slot16.response_type = E120_RESPONSE_TYPE_ACK; - while (nullptr != Rdm::Receive(nPortIndex)) { - // Discard late responses - Hardware::Get()->WatchdogFeed(); + for (uint32_t i = 0; i < RDM_UID_SIZE; i++) { + auto nUid = pRdmMessage->destination_uid[i]; + pRdmMessage->destination_uid[i] = pRdmMessage->source_uid[i]; + pRdmMessage->source_uid[i] = nUid; } - const auto *pRdmMessageNoSc = reinterpret_cast(const_cast(pRdmData)); - auto *pRdmCommand = reinterpret_cast(&s_rdmMessage); - - memcpy(&pRdmCommand[1], pRdmData, static_cast(pRdmMessageNoSc->message_length + 2)); + uint16_t nChecksum = 0; + uint32_t i; -#ifndef NDEBUG - RDMMessage::Print(pRdmCommand); -#endif + auto *pRdmData = reinterpret_cast(pRdmMessage); - Rdm::SendRaw(nPortIndex, pRdmCommand, pRdmMessageNoSc->message_length + 2U); + for (i = 0; i < pRdmMessage->message_length; i++) { + nChecksum = static_cast(nChecksum + pRdmData[i]); + } - const auto *pResponse = Rdm::ReceiveTimeOut(nPortIndex, 60000); + pRdmData[i++] = static_cast(nChecksum >> 8); + pRdmData[i++] = static_cast(nChecksum & 0XFF); -#ifndef NDEBUG - RDMMessage::Print(pResponse); -#endif - return pResponse; + Rdm::SendRawRespondMessage(nPortIndex, reinterpret_cast(pRdmMessage), i); } -bool ArtNetRdmController::RdmReceive(uint32_t nPortIndex, uint8_t *pRdmData) { +bool ArtNetRdmController::RdmReceive(const uint32_t nPortIndex, const uint8_t *pRdmData) { assert(nPortIndex < artnetnode::MAX_PORTS); assert(pRdmData != nullptr); - auto *pData = Rdm::Receive(nPortIndex); - - if (pData == nullptr) { - return false; - } - - auto *pRdmMessage = reinterpret_cast(pData); - + auto *pRdmMessage = reinterpret_cast(pRdmData); auto *pUid = pRdmMessage->destination_uid; + auto bIsRdmPacketForMe = false; auto bIsRdmPacketBroadcast = (memcmp(pUid, UID_ALL, RDM_UID_SIZE) == 0); - auto bIsRdmPacketForMe = false; if (!bIsRdmPacketBroadcast) { - bIsRdmPacketForMe = m_pRDMTod[nPortIndex].Exist(pUid); + bIsRdmPacketBroadcast = (memcmp(&pRdmMessage->destination_uid[2], UID_ALL, 4) == 0); + + if (!bIsRdmPacketBroadcast) { + bIsRdmPacketForMe = m_pRDMTod[nPortIndex].Exist(pUid); + } } if ((!bIsRdmPacketForMe) && (!bIsRdmPacketBroadcast)) { @@ -107,7 +96,6 @@ bool ArtNetRdmController::RdmReceive(uint32_t nPortIndex, uint8_t *pRdmData) { } if ((pRdmMessage->command_class == E120_GET_COMMAND) || (pRdmMessage->command_class == E120_SET_COMMAND) ) { - memcpy(pRdmData, &pData[1], pRdmMessage->message_length); return true; } @@ -121,7 +109,7 @@ bool ArtNetRdmController::RdmReceive(uint32_t nPortIndex, uint8_t *pRdmData) { if (nParamId == E120_DISC_UNIQUE_BRANCH) { if (!m_pRDMTod[nPortIndex].IsMuted()) { if ((memcmp(pRdmMessage->param_data, pUid, RDM_UID_SIZE) <= 0) && (memcmp(pUid, pRdmMessage->param_data + 6, RDM_UID_SIZE) <= 0)) { - auto *pResponse = reinterpret_cast(&s_rdmMessage); + auto *pResponse = reinterpret_cast(const_cast(pRdmData)); uint16_t nChecksum = 6 * 0xFF; @@ -157,11 +145,13 @@ bool ArtNetRdmController::RdmReceive(uint32_t nPortIndex, uint8_t *pRdmData) { if (!bIsRdmPacketBroadcast && bIsRdmPacketForMe) { m_pRDMTod[nPortIndex].UnMute(); - s_rdmMessage.param_data_length = 2; - s_rdmMessage.param_data[0] = 0x00; // Control Field - s_rdmMessage.param_data[1] = 0x00; // Control Field + auto *pRdmMessage = reinterpret_cast(const_cast(pRdmData)); + + pRdmMessage->param_data_length = 2; + pRdmMessage->param_data[0] = 0x00; // Control Field + pRdmMessage->param_data[1] = 0x00; // Control Field - RespondMessageAck(nPortIndex, pUid, pRdmMessage); + respond_message_ack(nPortIndex, pRdmMessage); } else { m_pRDMTod[nPortIndex].UnMuteAll(); } @@ -178,11 +168,13 @@ bool ArtNetRdmController::RdmReceive(uint32_t nPortIndex, uint8_t *pRdmData) { if (bIsRdmPacketForMe) { m_pRDMTod[nPortIndex].Mute(); - s_rdmMessage.param_data_length = 2; - s_rdmMessage.param_data[0] = 0x00; // Control Field - s_rdmMessage.param_data[1] = 0x00; // Control Field + auto *pRdmMessage = reinterpret_cast(const_cast(pRdmData)); - RespondMessageAck(nPortIndex, pUid, pRdmMessage);; + pRdmMessage->param_data_length = 2; + pRdmMessage->param_data[0] = 0x00; // Control Field + pRdmMessage->param_data[1] = 0x00; // Control Field + + respond_message_ack(nPortIndex, pRdmMessage);; return false; } } @@ -190,38 +182,3 @@ bool ArtNetRdmController::RdmReceive(uint32_t nPortIndex, uint8_t *pRdmData) { return false; } - -void ArtNetRdmController::RespondMessageAck(uint32_t nPortIndex, const uint8_t *pUid, const struct TRdmMessage *pRdmMessage) { - s_rdmMessage.start_code = E120_SC_RDM; - s_rdmMessage.sub_start_code = pRdmMessage->sub_start_code; - s_rdmMessage.transaction_number = pRdmMessage->transaction_number; - s_rdmMessage.message_count = 0; - s_rdmMessage.sub_device[0] = pRdmMessage->sub_device[0]; - s_rdmMessage.sub_device[1] = pRdmMessage->sub_device[1]; - s_rdmMessage.command_class = static_cast(pRdmMessage->command_class + 1); - s_rdmMessage.param_id[0] = pRdmMessage->param_id[0]; - s_rdmMessage.param_id[1] = pRdmMessage->param_id[1]; - s_rdmMessage.message_length = static_cast(RDM_MESSAGE_MINIMUM_SIZE + s_rdmMessage.param_data_length); - s_rdmMessage.slot16.response_type = E120_RESPONSE_TYPE_ACK; - - for (uint32_t i = 0; i < RDM_UID_SIZE; i++) { - s_rdmMessage.destination_uid[i] = pRdmMessage->source_uid[i]; - s_rdmMessage.source_uid[i] = pUid[i]; - } - - auto *pResponse = reinterpret_cast(&s_rdmMessage); - - uint16_t nChecksum = 0; - uint32_t i; - - for (i = 0; i < s_rdmMessage.message_length; i++) { - nChecksum = static_cast(nChecksum + pResponse[i]); - } - - pResponse[i++] = static_cast(nChecksum >> 8); - pResponse[i] = static_cast(nChecksum & 0XFF); - - const auto nLength = static_cast(s_rdmMessage.message_length + RDM_MESSAGE_CHECKSUM_SIZE); - - Rdm::SendRawRespondMessage(nPortIndex, pResponse, nLength); -} diff --git a/lib-artnet/src/node/rdm/controller/handlerdm.cpp b/lib-artnet/src/node/rdm/controller/handlerdm.cpp new file mode 100755 index 00000000..a1d76007 --- /dev/null +++ b/lib-artnet/src/node/rdm/controller/handlerdm.cpp @@ -0,0 +1,265 @@ +/** + * @file handlerdm.cpp + * + */ +/** + * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. + */ +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "artnetnode.h" +#include "rdm.h" +#include "network.h" +#include "panel_led.h" + +#include "debug.h" + +/** + * ArtTodControl is used to for an Output Gateway to flush its ToD and commence full discovery. + * If the Output Gateway has physical DMX512 ports, discovery could take minutes. + */ +void ArtNetNode::HandleTodControl() { + DEBUG_ENTRY + + const auto *const pArtTodControl = reinterpret_cast(m_pReceiveBuffer); + + if (pArtTodControl->Command == artnet::TodControlCommand::ATC_NONE) { + DEBUG_EXIT + return; + } + + const auto portAddress = static_cast((pArtTodControl->Net << 8)) | static_cast((pArtTodControl->Address)); + + for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { + if (portAddress != m_Node.Port[nPortIndex].PortAddress) { + continue; + } + + if ((m_Node.Port[nPortIndex].direction == lightset::PortDir::OUTPUT) && + ((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::RDM_DISABLED) != artnet::GoodOutputB::RDM_DISABLED)) { + switch (pArtTodControl->Command) { + case artnet::TodControlCommand::ATC_FLUSH: + m_pArtNetRdmController->Full(nPortIndex); + m_OutputPort[nPortIndex].GoodOutputB &= static_cast(~artnet::GoodOutputB::DISCOVERY_NOT_RUNNING); + break; + case artnet::TodControlCommand::ATC_END: + m_pArtNetRdmController->Stop(nPortIndex); + m_OutputPort[nPortIndex].GoodOutputB |= artnet::GoodOutputB::DISCOVERY_NOT_RUNNING; + break; + case artnet::TodControlCommand::ATC_INCON: + m_OutputPort[nPortIndex].GoodOutputB &= static_cast(~artnet::GoodOutputB::DISCOVERY_DISABLED); + break; + case artnet::TodControlCommand::ATC_INCOFF: + m_OutputPort[nPortIndex].GoodOutputB |= artnet::GoodOutputB::DISCOVERY_DISABLED; + break; + default: + break; + } + } else if (m_Node.Port[nPortIndex].direction == lightset::PortDir::INPUT) { + if (pArtTodControl->Command == artnet::TodControlCommand::ATC_FLUSH) { + m_pArtNetRdmController->TodReset(nPortIndex); + } + } + } + + DEBUG_EXIT +} + +void ArtNetNode::HandleTodData() { + DEBUG_ENTRY + + const auto *const pArtTodData = reinterpret_cast(m_pReceiveBuffer); + + if (pArtTodData->RdmVer != 0x01) { + DEBUG_EXIT + return; + } + + const auto portAddress = static_cast((pArtTodData->Net << 8)) | static_cast((pArtTodData->Address)); + + for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { + if (m_Node.Port[nPortIndex].direction != lightset::PortDir::INPUT) { + continue; + } + + if (m_Node.Port[nPortIndex].PortAddress == portAddress) { + DEBUG_PRINTF("nPortIndex=%u, portAddress=%u, pArtTodData->UidCount=%u",nPortIndex, portAddress, pArtTodData->UidCount); + + for (uint32_t nUidIndex = 0; nUidIndex < pArtTodData->UidCount; nUidIndex++) { + const uint8_t *pUid = pArtTodData->Tod[nUidIndex]; + m_pArtNetRdmController->TodAddUid(nPortIndex, pUid); + } + } + } + + DEBUG_EXIT +} + +/** + * Output Gateway always Directed Broadcasts this packet. + */ +void ArtNetNode::SendTod(uint32_t nPortIndex) { + DEBUG_ENTRY + DEBUG_PRINTF("nPortIndex=%u", nPortIndex); + assert(nPortIndex < artnetnode::MAX_PORTS); + + auto *pTodData = &m_ArtTodPacket.ArtTodData; + const auto nPage = nPortIndex; + + memcpy(pTodData->Id, artnet::NODE_ID, sizeof(pTodData->Id)); + pTodData->OpCode = static_cast(artnet::OpCodes::OP_TODDATA); + pTodData->ProtVerHi = 0; + pTodData->ProtVerLo = artnet::PROTOCOL_REVISION; + pTodData->RdmVer = 0x01; // Devices that support RDM STANDARD V1.0 set field to 0x01. + + const auto nDiscovered = static_cast(m_pArtNetRdmController->GetUidCount(nPortIndex)); + + /** + * Physical Port = (BindIndex-1) * ArtPollReply- >NumPortsLo + ArtTodData->Port + * As most modern Art-Net gateways implement one universe per ArtPollReply, + * ArtTodData->Port will usually be set to a value of 1. + */ + pTodData->Port = static_cast(1U + (nPortIndex & 0x3)); + pTodData->Spare1 = 0; + pTodData->Spare2 = 0; + pTodData->Spare3 = 0; + pTodData->Spare4 = 0; + pTodData->Spare5 = 0; + pTodData->Spare6 = 0; + pTodData->BindIndex = static_cast(nPage + 1U); ///< ArtPollReplyData->BindIndex == ArtTodData- >BindIndex + pTodData->Net = m_Node.Port[nPage].NetSwitch; + pTodData->CommandResponse = 0; ///< The packet contains the entire TOD or is the first packet in a sequence of packets that contains the entire TOD. + pTodData->Address = m_Node.Port[nPortIndex].DefaultAddress; + pTodData->UidTotalHi = 0; + pTodData->UidTotalLo = nDiscovered; + pTodData->BlockCount = 0; + pTodData->UidCount = nDiscovered; + + m_pArtNetRdmController->TodCopy(nPortIndex, reinterpret_cast(pTodData->Tod)); + + const auto nLength = sizeof(struct artnet::ArtTodData) - (sizeof(pTodData->Tod)) + (nDiscovered * 6U); + + Network::Get()->SendTo(m_nHandle, pTodData, static_cast(nLength), Network::Get()->GetBroadcastIp(), artnet::UDP_PORT); + + DEBUG_EXIT +} + +void ArtNetNode::SendTodRequest(uint32_t nPortIndex) { + DEBUG_ENTRY + assert(nPortIndex < artnetnode::MAX_PORTS); + + m_pArtNetRdmController->TodReset(nPortIndex); + + auto *pTodRequest = &m_ArtTodPacket.ArtTodRequest; + const auto nPage = nPortIndex; + + memcpy(pTodRequest->Id, artnet::NODE_ID, sizeof(pTodRequest->Id)); + pTodRequest->OpCode = static_cast(artnet::OpCodes::OP_TODREQUEST); + pTodRequest->ProtVerHi = 0; + pTodRequest->ProtVerLo = artnet::PROTOCOL_REVISION; + pTodRequest->Spare1 = 0; + pTodRequest->Spare2 = 0; + pTodRequest->Spare3 = 0; + pTodRequest->Spare4 = 0; + pTodRequest->Spare5 = 0; + pTodRequest->Spare6 = 0; + pTodRequest->Spare7 = 0; + pTodRequest->Net = m_Node.Port[nPage].NetSwitch; + pTodRequest->Command = 0; + pTodRequest->AddCount = 1; + pTodRequest->Address[0] = m_Node.Port[nPortIndex].DefaultAddress; + + const auto nLength = sizeof(struct artnet::ArtTodRequest) - (sizeof(pTodRequest->Address)) + pTodRequest->AddCount; + + Network::Get()->SendTo(m_nHandle, pTodRequest, static_cast(nLength), Network::Get()->GetBroadcastIp(), artnet::UDP_PORT); + + DEBUG_EXIT +} + +void ArtNetNode::HandleRdm() { + auto *const pArtRdm = reinterpret_cast(m_pReceiveBuffer); + + if (pArtRdm->RdmVer != 0x01) { + DEBUG_EXIT + return; + } + + const auto portAddress = static_cast((pArtRdm->Net << 8)) | static_cast((pArtRdm->Address)); + + for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { + if (m_Node.Port[nPortIndex].PortAddress != portAddress) { + continue; + } + + if ((m_Node.Port[nPortIndex].direction == lightset::PortDir::OUTPUT) && + ((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::RDM_DISABLED) != artnet::GoodOutputB::RDM_DISABLED)) { +# if (ARTNET_VERSION >= 4) + if (m_Node.Port[nPortIndex].protocol == artnet::PortProtocol::SACN) { + constexpr auto nMask = artnet::GoodOutput::OUTPUT_IS_MERGING | artnet::GoodOutput::DATA_IS_BEING_TRANSMITTED | artnet::GoodOutput::OUTPUT_IS_SACN; + m_OutputPort[nPortIndex].IsTransmitting = (GetGoodOutput4(nPortIndex) & nMask) != 0; + } +# endif + if (m_OutputPort[nPortIndex].IsTransmitting) { + m_OutputPort[nPortIndex].IsTransmitting = false; + m_pLightSet->Stop(nPortIndex); // Stop DMX if was running + } + + m_OutputPort[nPortIndex].nIpRdm = m_nIpAddressFrom; + + auto *pRdmMessage = reinterpret_cast(&pArtRdm->Address); + + pArtRdm->Address = E120_SC_RDM; + Rdm::SendRaw(nPortIndex, &pArtRdm->Address, pRdmMessage->message_length + RDM_MESSAGE_CHECKSUM_SIZE); + +#ifndef NDEBUG + rdm::message_print(reinterpret_cast(pRdmMessage)); +#endif + +#if defined(CONFIG_PANELLED_RDM_PORT) + hal::panel_led_on(hal::panelled::PORT_A_RDM << nPortIndex); +#elif defined(CONFIG_PANELLED_RDM_NO_PORT) + hal::panel_led_on(hal::panelled::RDM << nPortIndex); +#endif + } else if (m_Node.Port[nPortIndex].direction == lightset::PortDir::INPUT) { + auto *pRdmMessage = reinterpret_cast(&pArtRdm->Address); + + if ((pRdmMessage->command_class == E120_GET_COMMAND_RESPONSE) || (pRdmMessage->command_class == E120_SET_COMMAND_RESPONSE)) { + pArtRdm->Address = E120_SC_RDM; + Rdm::SendRaw(nPortIndex, reinterpret_cast(pRdmMessage), pRdmMessage->message_length + RDM_MESSAGE_CHECKSUM_SIZE); + +#ifndef NDEBUG + rdm::message_print(reinterpret_cast(pRdmMessage)); +#endif + } + +#if defined(CONFIG_PANELLED_RDM_PORT) + hal::panel_led_on(hal::panelled::PORT_A_RDM << nPortIndex); +#elif defined(CONFIG_PANELLED_RDM_NO_PORT) + hal::panel_led_on(hal::panelled::RDM << nPortIndex); +#endif + } + } +} diff --git a/lib-artnet/src/node/rdm/controller/handlerdmin.cpp b/lib-artnet/src/node/rdm/controller/handlerdmin.cpp new file mode 100644 index 00000000..89ec7229 --- /dev/null +++ b/lib-artnet/src/node/rdm/controller/handlerdmin.cpp @@ -0,0 +1,106 @@ +/** + * @file handlerdmin.cpp + * + */ +/** + * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. + */ +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if !defined(__clang__) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif + +#include +#include +#include + +#include "artnetnode.h" +#include "artnet.h" +#include "artnetrdmcontroller.h" + +#include "rdm.h" +#include "network.h" +#include "hardware.h" +#include "panel_led.h" + +#include "debug.h" + +void ArtNetNode::HandleRdmIn() { + for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { + auto *const pArtRdm = &m_ArtTodPacket.ArtRdm; + + if (m_Node.Port[nPortIndex].direction == lightset::PortDir::INPUT) { + const auto *pRdmData = Rdm::Receive(nPortIndex); + if (pRdmData != nullptr) { + if (m_pArtNetRdmController->RdmReceive(nPortIndex, pRdmData)) { + pArtRdm->OpCode = static_cast(artnet::OpCodes::OP_RDM); + pArtRdm->RdmVer = 0x01; + pArtRdm->Net = m_Node.Port[nPortIndex].NetSwitch; + pArtRdm->Command = 0; + pArtRdm->Address = m_Node.Port[nPortIndex].DefaultAddress; + + auto *pMessage = reinterpret_cast(pRdmData); + memcpy(pArtRdm->RdmPacket, &pRdmData[1], pMessage->message_length + 1U); + + const auto *pRdmMessage = reinterpret_cast(pArtRdm->RdmPacket); + + Network::Get()->SendTo(m_nHandle, pArtRdm, ((sizeof(struct artnet::ArtRdm)) - 256) + pRdmMessage->message_length + 1 , m_InputPort[nPortIndex].nDestinationIp, artnet::UDP_PORT); + +#if defined(CONFIG_PANELLED_RDM_PORT) + hal::panel_led_on(hal::panelled::PORT_A_RDM << nPortIndex); +#elif defined(CONFIG_PANELLED_RDM_NO_PORT) + hal::panel_led_on(hal::panelled::RDM << nPortIndex); +#endif + } + } + } else if (m_Node.Port[nPortIndex].direction == lightset::PortDir::OUTPUT) { + if (m_OutputPort[nPortIndex].nIpRdm != 0) { + const auto *pRdmData = Rdm::Receive(nPortIndex); + if (pRdmData != nullptr) { + pArtRdm->OpCode = static_cast(artnet::OpCodes::OP_RDM); + pArtRdm->RdmVer = 0x01; + pArtRdm->Net = m_Node.Port[nPortIndex].NetSwitch; + pArtRdm->Command = 0; + pArtRdm->Address = m_Node.Port[nPortIndex].DefaultAddress; + + auto *pMessage = reinterpret_cast(pRdmData); + memcpy(pArtRdm->RdmPacket, &pRdmData[1], pMessage->message_length + 1U); + + const auto *pRdmMessage = reinterpret_cast(pArtRdm->RdmPacket); + + Network::Get()->SendTo(m_nHandle, pArtRdm, ((sizeof(struct artnet::ArtRdm)) - 256) + pRdmMessage->message_length + 1 , m_OutputPort[nPortIndex].nIpRdm, artnet::UDP_PORT); + + m_OutputPort[nPortIndex].nIpRdm = 0; + +#if defined(CONFIG_PANELLED_RDM_PORT) + hal::panel_led_on(hal::panelled::PORT_A_RDM << nPortIndex); +#elif defined(CONFIG_PANELLED_RDM_NO_PORT) + hal::panel_led_on(hal::panelled::RDM << nPortIndex); +#endif + } + } + } + } +} diff --git a/lib-rdmsubdevice/src/rdmsubdevicesadd.cpp b/lib-artnet/src/node/rdm/controller/handlerdmsub.cpp old mode 100644 new mode 100755 similarity index 73% rename from lib-rdmsubdevice/src/rdmsubdevicesadd.cpp rename to lib-artnet/src/node/rdm/controller/handlerdmsub.cpp index 797add9d..bd59d845 --- a/lib-rdmsubdevice/src/rdmsubdevicesadd.cpp +++ b/lib-artnet/src/node/rdm/controller/handlerdmsub.cpp @@ -1,8 +1,11 @@ /** - * @file rdmsubdevicesadd.cpp + * @file handlerdmsub.cpp * */ -/* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/** + * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,29 +26,27 @@ * THE SOFTWARE. */ +#include +#include #include -#include "rdmsubdevices.h" +#include "artnetnode.h" + +#include "network.h" + +#include "panel_led.h" #include "debug.h" -bool RDMSubDevices::Add(RDMSubDevice *pRDMSubDevice) { +void ArtNetNode::HandleRdmSub() { DEBUG_ENTRY - assert(m_pRDMSubDevice != nullptr); + auto *const pArtRdmSub = reinterpret_cast(m_pReceiveBuffer); - if (m_pRDMSubDevice == nullptr) { - return false; - } - - if (m_nCount == rdm::subdevices::MAX) { + if (pArtRdmSub->RdmVer != 0x01) { DEBUG_EXIT - return false; + return; } - assert(pRDMSubDevice != nullptr); - m_pRDMSubDevice[m_nCount++] = pRDMSubDevice; - DEBUG_EXIT - return true; } diff --git a/lib-artnet/src/node/rdm/controller/json_get_portstatus.cpp b/lib-artnet/src/node/rdm/controller/json_get_portstatus.cpp new file mode 100755 index 00000000..446a96a7 --- /dev/null +++ b/lib-artnet/src/node/rdm/controller/json_get_portstatus.cpp @@ -0,0 +1,89 @@ +/** + * @file json_get_portstatus.cpp + * + */ +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "artnetnode.h" +#include "lightset.h" + +namespace remoteconfig { +namespace rdm { +static uint32_t get_portstatus(const uint32_t nPortIndex, char *pOutBuffer, const uint32_t nOutBufferSize) { + const auto direction = ArtNetNode::Get()->GetPortDirection(nPortIndex); + const char *status; + + if (direction == lightset::PortDir::OUTPUT) { + if (ArtNetNode::Get()->GetRdm(nPortIndex)) { + if (ArtNetNode::Get()->GetRdmDiscovery(nPortIndex)) { + bool bIsIncremental; + if (ArtNetNode::Get()->RdmIsRunning(nPortIndex, bIsIncremental)) { + status = bIsIncremental ? "Incremental" : "Full"; + } else { + status = "Idle"; + } + } else { + status = "Disabled"; + } + } else { + return 0; + } + } else if (direction == lightset::PortDir::INPUT) { + if (ArtNetNode::Get()->RdmGetUidCount(nPortIndex) != 0) { + status = "TOD"; + } else { + return 0; + } + } else { + return 0; + } + + auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, + "{\"port\":\"%c\",\"direction\":\"%s\",\"status\":\"%s\"},", + static_cast('A' + nPortIndex), + lightset::get_direction(direction), + status)); + + return nLength; +} + +uint32_t json_get_portstatus(char *pOutBuffer, const uint32_t nOutBufferSize) { + pOutBuffer[0] = '['; + uint32_t nLength = 1; + + for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { + nLength += get_portstatus(nPortIndex, &pOutBuffer[nLength], nOutBufferSize - nLength); + } + + if (nLength == 1) { + nLength++; + } + + pOutBuffer[nLength - 1] = ']'; + + return nLength; +} +} // namespace rdm +} // namespace remoteconfig diff --git a/lib-rdmnet/src/rdmnetdevice.cpp b/lib-artnet/src/node/rdm/controller/json_get_queue.cpp old mode 100644 new mode 100755 similarity index 63% rename from lib-rdmnet/src/rdmnetdevice.cpp rename to lib-artnet/src/node/rdm/controller/json_get_queue.cpp index 60ef49c1..caa1122d --- a/lib-rdmnet/src/rdmnetdevice.cpp +++ b/lib-artnet/src/node/rdm/controller/json_get_queue.cpp @@ -1,8 +1,8 @@ /** - * @file rdmnetdevice.cpp + * @file json_get_queue.cpp * */ -/* Copyright (C) 2019-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,29 +25,25 @@ #include #include -#include +#include -#include "rdmnetdevice.h" +#include "artnetnode.h" -#include "llrpdevice.h" -#include "rdmpersonality.h" -#include "lightset.h" -#include "rdmdeviceresponder.h" -#include "rdmhandler.h" +namespace remoteconfig { +namespace rdm { +uint32_t json_get_queue(char *pOutBuffer, const uint32_t nOutBufferSize) { + const auto nBufferSize = nOutBufferSize - 2U; + auto nLength = static_cast(snprintf(pOutBuffer, nBufferSize, "{\"uid\":[" )); -static constexpr auto UUID_STRING_LENGTH = 36; + nLength += ArtNetNode::Get()->RdmCopyWorkingQueue(&pOutBuffer[nLength], nBufferSize - nLength); -TRdmMessage RDMNetDevice::s_RdmCommand; -uint8_t RDMNetDevice::s_Cid[e131::CID_LENGTH]; + pOutBuffer[nLength++] = ']'; + pOutBuffer[nLength++] = '}'; -void RDMNetDevice::Print() { - char uuid_str[UUID_STRING_LENGTH + 1]; - uuid_str[UUID_STRING_LENGTH] = '\0'; - uuid_unparse(s_Cid, uuid_str); + assert(nLength <= nOutBufferSize); + return nLength; +} +} // namespace rdm +} // namespace remoteconfig - printf("RDMNet\n"); - printf(" CID : %s\n", uuid_str); - LLRPDevice::Print(); - RDMDeviceResponder::Print(); -} diff --git a/lib-artnet/src/node/rdm/controller/json_get_rdm.cpp b/lib-artnet/src/node/rdm/controller/json_get_rdm.cpp new file mode 100755 index 00000000..06931c49 --- /dev/null +++ b/lib-artnet/src/node/rdm/controller/json_get_rdm.cpp @@ -0,0 +1,38 @@ +/** + * @file json_get_rdm.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "artnetnode.h" + +namespace remoteconfig { +namespace rdm { +uint32_t json_get_rdm(char *pOutBuffer, const uint32_t nOutBufferSize) { + auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, "{\"rdm\":\"%u\"}", ArtNetNode::Get()->GetRdm())); + return nLength; +} +} // namespace rdm +} // namespace remoteconfig diff --git a/lib-dmx/src/rdm.cpp b/lib-artnet/src/node/rdm/controller/json_get_tod.cpp old mode 100644 new mode 100755 similarity index 57% rename from lib-dmx/src/rdm.cpp rename to lib-artnet/src/node/rdm/controller/json_get_tod.cpp index 914cd716..5c19dde3 --- a/lib-dmx/src/rdm.cpp +++ b/lib-artnet/src/node/rdm/controller/json_get_tod.cpp @@ -1,8 +1,8 @@ /** - * @file rdm.cpp + * @file json_get_tod.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,34 +24,30 @@ */ #include +#include #include -#include "rdm.h" -#include "dmx.h" +#include "artnetnode.h" -#include "hardware.h" +namespace remoteconfig { +namespace rdm { +uint32_t json_get_tod(const char cPort, char *pOutBuffer, const uint32_t nOutBufferSize) { + const uint32_t nPortIndex = (cPort | 0x20) - 'a'; -#include "debug.h" + if (nPortIndex < artnetnode::MAX_PORTS) { + const auto nBufferSize = nOutBufferSize - 2U; + auto nLength = static_cast(snprintf(pOutBuffer, nBufferSize, "{\"port\":\"%c\",\"tod\":[" , static_cast(nPortIndex + 'A'))); -const uint8_t *Rdm::Receive(uint32_t nPortIndex) { - return Dmx::Get()->RdmReceive(nPortIndex); -} - -const uint8_t *Rdm::ReceiveTimeOut(uint32_t nPortIndex, uint16_t nTimeOut) { - return Dmx::Get()->RdmReceiveTimeOut(nPortIndex, nTimeOut); -} - -void Rdm::SendRaw(uint32_t nPortIndex, const uint8_t *pRdmData, uint32_t nLength) { - assert(pRdmData != nullptr); - assert(nLength != 0); - - DEBUG_PRINTF("nPortIndex=%u", nPortIndex); - - Dmx::Get()->SetPortDirection(nPortIndex, dmx::PortDirection::OUTP, false); + nLength += ArtNetNode::Get()->RdmCopyTod(nPortIndex, &pOutBuffer[nLength], nBufferSize - nLength); - Dmx::Get()->RdmSendRaw(nPortIndex, pRdmData, nLength); + pOutBuffer[nLength++] = ']'; + pOutBuffer[nLength++] = '}'; - udelay(RDM_RESPONDER_DATA_DIRECTION_DELAY); + assert(nLength <= nOutBufferSize); + return nLength; + } - Dmx::Get()->SetPortDirection(nPortIndex, dmx::PortDirection::INP, true); + return 0; } +} // namespace rdm +} // namespace remoteconfig diff --git a/lib-artnet/src/node/rdm/controller/setrdm.cpp b/lib-artnet/src/node/rdm/controller/setrdm.cpp new file mode 100755 index 00000000..48a78720 --- /dev/null +++ b/lib-artnet/src/node/rdm/controller/setrdm.cpp @@ -0,0 +1,56 @@ +/** + * @file setrdm.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "artnetnode.h" +#include "artnetrdmcontroller.h" + +#include "debug.h" + +void ArtNetNode::SetRdm(const bool doEnable) { + DEBUG_ENTRY + + SetRdmController(m_pArtNetRdmController, doEnable); + + DEBUG_EXIT +} + +void ArtNetNode::SetRdmController(ArtNetRdmController *pArtNetRdmController, const bool doEnable) { + DEBUG_ENTRY + + m_pArtNetRdmController = pArtNetRdmController; + m_State.rdm.IsEnabled = ((pArtNetRdmController != nullptr) & doEnable); + + if (m_State.rdm.IsEnabled) { + m_ArtPollReply.Status1 |= artnet::Status1::RDM_CAPABLE; + m_State.rdm.IsDiscoveryRunning = true; + } else { + m_ArtPollReply.Status1 &= static_cast(~artnet::Status1::RDM_CAPABLE); + } + + DEBUG_PRINTF("m_State.rdm.IsEnabled=%c", m_State.rdm.IsEnabled ? 'Y' : 'N'); + DEBUG_EXIT +} diff --git a/lib-artnet/src/node/rdm/handlerdm.cpp b/lib-artnet/src/node/rdm/handlerdm.cpp index 2f9af34a..7e875370 100755 --- a/lib-artnet/src/node/rdm/handlerdm.cpp +++ b/lib-artnet/src/node/rdm/handlerdm.cpp @@ -1,11 +1,8 @@ /** - * @file handlerdm.h + * @file handlerdm.cpp * */ -/** - * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. - */ -/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,86 +23,12 @@ * THE SOFTWARE. */ -#include -#include -#include +#include #include "artnetnode.h" -#include "artnetrdm.h" - -#include "network.h" #include "debug.h" -void ArtNetNode::SetRmd(const uint32_t nPortIndex, const bool bEnable) { - DEBUG_ENTRY - assert(nPortIndex < artnetnode::MAX_PORTS); - - const auto isEnabled = !((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::RDM_DISABLED) == artnet::GoodOutputB::RDM_DISABLED); - - if (isEnabled == bEnable) { - DEBUG_EXIT - return; - } - - if (!bEnable) { - m_OutputPort[nPortIndex].GoodOutputB |= artnet::GoodOutputB::RDM_DISABLED; - } else { - m_OutputPort[nPortIndex].GoodOutputB &= static_cast(~artnet::GoodOutputB::RDM_DISABLED); - } - - if (m_State.status == artnetnode::Status::ON) { - if (m_pArtNetStore != nullptr) { - m_pArtNetStore->SaveRdmEnabled(nPortIndex, bEnable); - } - - artnet::display_rdm_enabled(nPortIndex, bEnable); - } - - - DEBUG_EXIT -} - -//TODO Make RDM discovery a state-machine. - -/** - * ArtTodControl is used to for an Output Gateway to flush its ToD and commence full discovery. - * If the Output Gateway has physical DMX512 ports, discovery could take minutes. - */ -void ArtNetNode::HandleTodControl() { - DEBUG_ENTRY - - const auto *const pArtTodControl = reinterpret_cast(m_pReceiveBuffer); - const auto portAddress = static_cast((pArtTodControl->Net << 8)) | static_cast((pArtTodControl->Address)); - - for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { - if ((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::RDM_DISABLED) == artnet::GoodOutputB::RDM_DISABLED) { - DEBUG_EXIT - continue; - } - - if ((portAddress == m_Node.Port[nPortIndex].PortAddress) - && (m_Node.Port[nPortIndex].direction == lightset::PortDir::OUTPUT)) { - - if (m_OutputPort[nPortIndex].IsTransmitting && (!m_Node.IsRdmResponder)) { - m_pLightSet->Stop(nPortIndex); - } - - if (pArtTodControl->Command == 0x01) { // AtcFlush - m_pArtNetRdm->Full(nPortIndex); - } - - SendTod(nPortIndex); - - if (m_OutputPort[nPortIndex].IsTransmitting && (!m_Node.IsRdmResponder)) { - m_pLightSet->Start(nPortIndex); - } - } - } - - DEBUG_EXIT -} - /** * An Output Gateway must not interpret receipt of an ArtTodRequest * as an instruction to perform full RDM Discovery on the DMX512 physical layer; @@ -125,8 +48,7 @@ void ArtNetNode::HandleTodRequest() { continue; } - if ((portAddress == m_Node.Port[nPortIndex].PortAddress) - && (m_Node.Port[nPortIndex].direction == lightset::PortDir::OUTPUT)) { + if ((portAddress == m_Node.Port[nPortIndex].PortAddress) && (m_Node.Port[nPortIndex].direction == lightset::PortDir::OUTPUT)) { SendTod(nPortIndex); } } @@ -134,195 +56,3 @@ void ArtNetNode::HandleTodRequest() { DEBUG_EXIT } - -void ArtNetNode::HandleTodData() { - DEBUG_ENTRY - - const auto *const pArtTodData = reinterpret_cast(m_pReceiveBuffer); - - if (pArtTodData->RdmVer != 0x01) { - DEBUG_EXIT - return; - } - - const auto portAddress = static_cast((pArtTodData->Net << 8)) | static_cast((pArtTodData->Address)); - - for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { - if (m_Node.Port[nPortIndex].direction != lightset::PortDir::INPUT) { - continue; - } - - if (m_Node.Port[nPortIndex].PortAddress == portAddress) { - DEBUG_PRINTF("nPortIndex=%u, portAddress=%u, pArtTodData->UidCount=%u",nPortIndex, portAddress, pArtTodData->UidCount); - - for (uint32_t nUidIndex = 0; nUidIndex < pArtTodData->UidCount; nUidIndex++) { - const uint8_t *pUid = pArtTodData->Tod[nUidIndex]; - m_pArtNetRdm->TodAddUid(nPortIndex, pUid); - } - } - } - - DEBUG_EXIT -} - -/** - * Output Gateway always Directed Broadcasts this packet. - */ -void ArtNetNode::SendTod(uint32_t nPortIndex) { - DEBUG_ENTRY - DEBUG_PRINTF("nPortIndex=%u", nPortIndex); - assert(nPortIndex < artnetnode::MAX_PORTS); - - auto *pTodData = &m_ArtTodPacket.ArtTodData; - const auto nPage = nPortIndex; - - memcpy(pTodData->Id, artnet::NODE_ID, sizeof(pTodData->Id)); - pTodData->OpCode = static_cast(artnet::OpCodes::OP_TODDATA); - pTodData->ProtVerHi = 0; - pTodData->ProtVerLo = artnet::PROTOCOL_REVISION; - pTodData->RdmVer = 0x01; // Devices that support RDM STANDARD V1.0 set field to 0x01. - - const auto nDiscovered = static_cast(m_pArtNetRdm->GetUidCount(nPortIndex)); - - /** - * Physical Port = (BindIndex-1) * ArtPollReply- >NumPortsLo + ArtTodData->Port - * As most modern Art-Net gateways implement one universe per ArtPollReply, - * ArtTodData->Port will usually be set to a value of 1. - */ - pTodData->Port = static_cast(1U + (nPortIndex & 0x3)); - pTodData->Spare1 = 0; - pTodData->Spare2 = 0; - pTodData->Spare3 = 0; - pTodData->Spare4 = 0; - pTodData->Spare5 = 0; - pTodData->Spare6 = 0; - pTodData->BindIndex = static_cast(nPage + 1U); ///< ArtPollReplyData->BindIndex == ArtTodData- >BindIndex - pTodData->Net = m_Node.Port[nPage].NetSwitch; - pTodData->CommandResponse = 0; ///< The packet contains the entire TOD or is the first packet in a sequence of packets that contains the entire TOD. - pTodData->Address = m_Node.Port[nPortIndex].DefaultAddress; - pTodData->UidTotalHi = 0; - pTodData->UidTotalLo = nDiscovered; - pTodData->BlockCount = 0; - pTodData->UidCount = nDiscovered; - - m_pArtNetRdm->TodCopy(nPortIndex, reinterpret_cast(pTodData->Tod)); - - const auto nLength = sizeof(struct artnet::ArtTodData) - (sizeof(pTodData->Tod)) + (nDiscovered * 6U); - - Network::Get()->SendTo(m_nHandle, pTodData, static_cast(nLength), Network::Get()->GetBroadcastIp(), artnet::UDP_PORT); - - DEBUG_EXIT -} - -void ArtNetNode::SendTodRequest(uint32_t nPortIndex) { - DEBUG_ENTRY - assert(nPortIndex < artnetnode::MAX_PORTS); - - m_pArtNetRdm->TodReset(nPortIndex); - - auto *pTodRequest = &m_ArtTodPacket.ArtTodRequest; - const auto nPage = nPortIndex; - - memcpy(pTodRequest->Id, artnet::NODE_ID, sizeof(pTodRequest->Id)); - pTodRequest->OpCode = static_cast(artnet::OpCodes::OP_TODREQUEST); - pTodRequest->ProtVerHi = 0; - pTodRequest->ProtVerLo = artnet::PROTOCOL_REVISION; - pTodRequest->Spare1 = 0; - pTodRequest->Spare2 = 0; - pTodRequest->Spare3 = 0; - pTodRequest->Spare4 = 0; - pTodRequest->Spare5 = 0; - pTodRequest->Spare6 = 0; - pTodRequest->Spare7 = 0; - pTodRequest->Net = m_Node.Port[nPage].NetSwitch; - pTodRequest->Command = 0; - pTodRequest->AddCount = 1; - pTodRequest->Address[0] = m_Node.Port[nPortIndex].DefaultAddress; - - const auto nLength = sizeof(struct artnet::ArtTodRequest) - (sizeof(pTodRequest->Address)) + pTodRequest->AddCount; - - Network::Get()->SendTo(m_nHandle, pTodRequest, static_cast(nLength), Network::Get()->GetBroadcastIp(), artnet::UDP_PORT); - - DEBUG_EXIT -} - -void ArtNetNode::SetRdmHandler(ArtNetRdm *pArtNetTRdm, bool IsResponder) { - DEBUG_ENTRY - - m_pArtNetRdm = pArtNetTRdm; - - if (m_pArtNetRdm != nullptr) { - m_Node.IsRdmResponder = IsResponder; - m_ArtPollReply.Status1 |= artnet::Status1::RDM_CAPABLE; - } else { - m_ArtPollReply.Status1 &= static_cast(~artnet::Status1::RDM_CAPABLE); - } - - DEBUG_EXIT -} - -void ArtNetNode::HandleRdm() { - auto *const pArtRdm = reinterpret_cast(m_pReceiveBuffer); - - if (pArtRdm->RdmVer != 0x01) { - DEBUG_EXIT - return; - } - - const auto portAddress = static_cast((pArtRdm->Net << 8)) | static_cast((pArtRdm->Address)); - - // Output ports - for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { - if ((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::RDM_DISABLED) == artnet::GoodOutputB::RDM_DISABLED) { - continue; - } - - if ((portAddress == m_Node.Port[nPortIndex].PortAddress) && (m_Node.Port[nPortIndex].direction == lightset::PortDir::OUTPUT)) { -#if defined (RDM_CONTROLLER) -# if (ARTNET_VERSION >= 4) - if (m_Node.Port[nPortIndex].protocol == artnet::PortProtocol::SACN) { - constexpr auto nMask = artnet::GoodOutput::OUTPUT_IS_MERGING | artnet::GoodOutput::DATA_IS_BEING_TRANSMITTED | artnet::GoodOutput::OUTPUT_IS_SACN; - m_OutputPort[nPortIndex].IsTransmitting = (GetGoodOutput4(nPortIndex) & nMask) != 0; - } -# endif - if (m_OutputPort[nPortIndex].IsTransmitting) { - m_pLightSet->Stop(nPortIndex); // Stop DMX if was running - } -#endif - const auto *pRdmResponse = const_cast(m_pArtNetRdm->Handler(nPortIndex, pArtRdm->RdmPacket)); - - if (pRdmResponse != nullptr) { - pArtRdm->RdmVer = 0x01; - - const auto nMessageLength = static_cast(pRdmResponse[2] + 1); - memcpy(pArtRdm->RdmPacket, &pRdmResponse[1], nMessageLength); - - const auto nLength = sizeof(struct artnet::ArtRdm) - sizeof(pArtRdm->RdmPacket) + nMessageLength; - - Network::Get()->SendTo(m_nHandle, m_pReceiveBuffer, static_cast(nLength), m_nIpAddressFrom, artnet::UDP_PORT); - } else { - DEBUG_PUTS("No RDM response"); - } - -#if defined (RDM_CONTROLLER) - if (m_OutputPort[nPortIndex].IsTransmitting) { - m_pLightSet->Start(nPortIndex); // Start DMX if was running - } -#endif - } - } - -#if defined (RDM_CONTROLLER) - // Input ports - for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { - if ((m_Node.Port[nPortIndex].direction != lightset::PortDir::INPUT)) { - continue; - } - - if (m_Node.Port[nPortIndex].PortAddress == portAddress) { - DEBUG_PRINTF("nPortIndex=%u, portAddress=%u", nPortIndex, portAddress); - artnet::rdm_send(nPortIndex, pArtRdm->RdmPacket); - } - } -#endif -} diff --git a/lib-artnet/src/node/rdm/handlerdmin.cpp b/lib-artnet/src/node/rdm/handlerdmin.cpp deleted file mode 100644 index 200af546..00000000 --- a/lib-artnet/src/node/rdm/handlerdmin.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @file handlerdmin.cpp - * - */ -/** - * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. - */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "artnetnode.h" -#include "artnet.h" -#include "artnetrdm.h" - -#include "network.h" -#include "hardware.h" - -#include "panel_led.h" - -#include "debug.h" - -void ArtNetNode::HandleRdmIn() { - auto *const pArtRdm = &m_ArtTodPacket.ArtRdm; - - for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { - if ((m_Node.Port[nPortIndex].direction != lightset::PortDir::INPUT)) { - continue; - } - - const auto nPage = nPortIndex; - - if (m_pArtNetRdm->RdmReceive(nPortIndex, pArtRdm->RdmPacket)) { - memcpy(pArtRdm->Id, artnet::NODE_ID, sizeof(pArtRdm->Id)); - pArtRdm->OpCode = static_cast(artnet::OpCodes::OP_RDM); - pArtRdm->ProtVerHi = 0; - pArtRdm->ProtVerLo = artnet::PROTOCOL_REVISION; - pArtRdm->RdmVer = 0x01; - pArtRdm->Net = m_Node.Port[nPage].NetSwitch; - pArtRdm->Command = 0; - pArtRdm->Address = m_Node.Port[nPortIndex].DefaultAddress; - - Network::Get()->SendTo(m_nHandle, pArtRdm, sizeof(struct artnet::ArtRdm), m_InputPort[nPortIndex].nDestinationIp, artnet::UDP_PORT); - } - } -} diff --git a/lib-network/src/net/ntp_internal.h b/lib-artnet/src/node/rdm/responder/artnetrdmresponder.cpp similarity index 84% rename from lib-network/src/net/ntp_internal.h rename to lib-artnet/src/node/rdm/responder/artnetrdmresponder.cpp index 328dafab..a831f94e 100644 --- a/lib-network/src/net/ntp_internal.h +++ b/lib-artnet/src/node/rdm/responder/artnetrdmresponder.cpp @@ -1,8 +1,8 @@ /** - * @file ntp_internal.h + * @file artnetrdmresponder.cpp * */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,11 +23,6 @@ * THE SOFTWARE. */ -#ifndef NTP_INTERNAL_H_ -#define NTP_INTERNAL_H_ +#include "artnetrdmresponder.h" -enum { - NTP_PORT_SERVER = 123 -}; - -#endif /* NTP_INTERNAL_H_ */ +TRdmMessage ArtNetRdmResponder::s_RdmCommand; diff --git a/lib-artnet/src/node/rdm/responder/handlerdm.cpp b/lib-artnet/src/node/rdm/responder/handlerdm.cpp new file mode 100755 index 00000000..8398b921 --- /dev/null +++ b/lib-artnet/src/node/rdm/responder/handlerdm.cpp @@ -0,0 +1,147 @@ +/** + * @file handlerdm.h + * + */ +/** + * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. + */ +/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "artnetnode.h" +#include "artnetrdmresponder.h" + +#include "debug.h" + +void ArtNetNode::HandleRdm() { + auto *const pArtRdm = reinterpret_cast(m_pReceiveBuffer); + + if (pArtRdm->RdmVer != 0x01) { + DEBUG_EXIT + return; + } + + const auto portAddress = static_cast((pArtRdm->Net << 8)) | static_cast((pArtRdm->Address)); + + for (uint32_t nPortIndex = 0; nPortIndex < artnetnode::MAX_PORTS; nPortIndex++) { + if ((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::RDM_DISABLED) == artnet::GoodOutputB::RDM_DISABLED) { + continue; + } + + if ((portAddress == m_Node.Port[nPortIndex].PortAddress) && (m_Node.Port[nPortIndex].direction == lightset::PortDir::OUTPUT)) { + const auto *pRdmResponse = const_cast(m_pArtNetRdmResponder->Handler(nPortIndex, pArtRdm->RdmPacket)); + + if (pRdmResponse != nullptr) { + pArtRdm->RdmVer = 0x01; + + const auto nMessageLength = static_cast(pRdmResponse[2] + 1); + memcpy(pArtRdm->RdmPacket, &pRdmResponse[1], nMessageLength); + + const auto nLength = sizeof(struct artnet::ArtRdm) - sizeof(pArtRdm->RdmPacket) + nMessageLength; + + Network::Get()->SendTo(m_nHandle, m_pReceiveBuffer, nLength, m_nIpAddressFrom, artnet::UDP_PORT); + } else { + DEBUG_PUTS("No RDM response"); + } + } + } +} + +void ArtNetNode::HandleTodControl() { + DEBUG_ENTRY + + const auto *const pArtTodControl = reinterpret_cast(m_pReceiveBuffer); + const auto portAddress = static_cast((pArtTodControl->Net << 8)) | static_cast((pArtTodControl->Address)); + + const uint32_t nPortIndex = 0; + + if ((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::RDM_DISABLED) == artnet::GoodOutputB::RDM_DISABLED) { + DEBUG_EXIT + return; + } + + if ((portAddress == m_Node.Port[nPortIndex].PortAddress) && (m_Node.Port[nPortIndex].direction == lightset::PortDir::OUTPUT)) { + if (pArtTodControl->Command == 0x01) { // AtcFlush + SendTod(nPortIndex); + } + } + + DEBUG_EXIT +} + +/** + * Output Gateway always Directed Broadcasts this packet. + */ +void ArtNetNode::SendTod(uint32_t nPortIndex) { + DEBUG_ENTRY + DEBUG_PRINTF("nPortIndex=%u", nPortIndex); + assert(nPortIndex < artnetnode::MAX_PORTS); + + auto *pTodData = &m_ArtTodPacket.ArtTodData; + const auto nPage = nPortIndex; + + memcpy(pTodData->Id, artnet::NODE_ID, sizeof(pTodData->Id)); + pTodData->OpCode = static_cast(artnet::OpCodes::OP_TODDATA); + pTodData->ProtVerHi = 0; + pTodData->ProtVerLo = artnet::PROTOCOL_REVISION; + pTodData->RdmVer = 0x01; // Devices that support RDM STANDARD V1.0 set field to 0x01. + + const auto nDiscovered = static_cast(nPortIndex == 0 ? 1 : 0); + + /** + * Physical Port = (BindIndex-1) * ArtPollReply- >NumPortsLo + ArtTodData->Port + * As most modern Art-Net gateways implement one universe per ArtPollReply, + * ArtTodData->Port will usually be set to a value of 1. + */ + pTodData->Port = static_cast(1U + (nPortIndex & 0x3)); + pTodData->Spare1 = 0; + pTodData->Spare2 = 0; + pTodData->Spare3 = 0; + pTodData->Spare4 = 0; + pTodData->Spare5 = 0; + pTodData->Spare6 = 0; + pTodData->BindIndex = static_cast(nPage + 1U); ///< ArtPollReplyData->BindIndex == ArtTodData- >BindIndex + pTodData->Net = m_Node.Port[nPage].NetSwitch; + pTodData->CommandResponse = 0; ///< The packet contains the entire TOD or is the first packet in a sequence of packets that contains the entire TOD. + pTodData->Address = m_Node.Port[nPortIndex].DefaultAddress; + pTodData->UidTotalHi = 0; + pTodData->UidTotalLo = nDiscovered; + pTodData->BlockCount = 0; + pTodData->UidCount = nDiscovered; + + m_pArtNetRdmResponder->TodCopy(nPortIndex, reinterpret_cast(pTodData->Tod)); + + const auto nLength = sizeof(struct artnet::ArtTodData) - (sizeof(pTodData->Tod)) + (nDiscovered * 6U); + + Network::Get()->SendTo(m_nHandle, pTodData, nLength, Network::Get()->GetBroadcastIp(), artnet::UDP_PORT); + + DEBUG_EXIT +} + +void ArtNetNode::HandleTodData() { + DEBUG_ENTRY + + DEBUG_EXIT +} diff --git a/lib-hal/console/null/console.c b/lib-artnet/src/node/rdm/responder/handlerdmsub.cpp similarity index 72% rename from lib-hal/console/null/console.c rename to lib-artnet/src/node/rdm/responder/handlerdmsub.cpp index 49df7118..bd59d845 100755 --- a/lib-hal/console/null/console.c +++ b/lib-artnet/src/node/rdm/responder/handlerdmsub.cpp @@ -1,7 +1,10 @@ /** - * @file console.c + * @file handlerdmsub.cpp * */ +/** + * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. + */ /* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -23,22 +26,27 @@ * THE SOFTWARE. */ -#include +#include +#include +#include -void console_init(void) { -} +#include "artnetnode.h" -void console_putc(__attribute__((unused)) int i) { -} +#include "network.h" -void console_puts(__attribute__((unused)) const char *p) { -} +#include "panel_led.h" -void console_write(__attribute__((unused)) const char *p, __attribute__((unused)) unsigned int i) { -} +#include "debug.h" -void console_status(__attribute__((unused)) uint32_t i, __attribute__((unused)) const char *p) { -} +void ArtNetNode::HandleRdmSub() { + DEBUG_ENTRY + + auto *const pArtRdmSub = reinterpret_cast(m_pReceiveBuffer); + + if (pArtRdmSub->RdmVer != 0x01) { + DEBUG_EXIT + return; + } -void console_error(__attribute__((unused)) const char *p) { + DEBUG_EXIT } diff --git a/lib-artnet/src/node/rdm/responder/setrdm.cpp b/lib-artnet/src/node/rdm/responder/setrdm.cpp new file mode 100755 index 00000000..db3912e4 --- /dev/null +++ b/lib-artnet/src/node/rdm/responder/setrdm.cpp @@ -0,0 +1,55 @@ +/** + * @file setrdm.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "artnetnode.h" +#include "artnetrdmresponder.h" + +#include "debug.h" + +void ArtNetNode::SetRdm(const bool doEnable) { + DEBUG_ENTRY + + SetRdmResponder(m_pArtNetRdmResponder, doEnable); + + DEBUG_EXIT +} + +void ArtNetNode::SetRdmResponder(ArtNetRdmResponder *pArtNetRdmResponder, const bool doEnable) { + DEBUG_ENTRY + + m_pArtNetRdmResponder = pArtNetRdmResponder; + m_State.rdm.IsEnabled = ((pArtNetRdmResponder != nullptr) & doEnable); + + if (m_State.rdm.IsEnabled) { + m_ArtPollReply.Status1 |= artnet::Status1::RDM_CAPABLE; + } else { + m_ArtPollReply.Status1 &= static_cast(~artnet::Status1::RDM_CAPABLE); + } + + DEBUG_PRINTF("m_State.rdm.IsEnabled=%c", m_State.rdm.IsEnabled ? 'Y' : 'N'); + DEBUG_EXIT +} diff --git a/lib-artnet/src/node/rdm/setrdm.cpp b/lib-artnet/src/node/rdm/setrdm.cpp new file mode 100755 index 00000000..ffa774de --- /dev/null +++ b/lib-artnet/src/node/rdm/setrdm.cpp @@ -0,0 +1,76 @@ +/** + * @file setrdm.cpp + * + */ +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "artnetnode.h" +#include "artnetstore.h" + +#include "debug.h" + +void ArtNetNode::SetRdm(const uint32_t nPortIndex, const bool bEnable) { + DEBUG_ENTRY + assert(nPortIndex < artnetnode::MAX_PORTS); + + const auto isEnabled = !((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::RDM_DISABLED) == artnet::GoodOutputB::RDM_DISABLED); + + if (isEnabled == bEnable) { + DEBUG_EXIT + return; + } + + if (!bEnable) { + m_OutputPort[nPortIndex].GoodOutputB |= artnet::GoodOutputB::RDM_DISABLED; + } else { + m_OutputPort[nPortIndex].GoodOutputB &= static_cast(~artnet::GoodOutputB::RDM_DISABLED); + } + + if (m_State.status == artnet::Status::ON) { + ArtNetStore::SaveRdmEnabled(nPortIndex, bEnable); + artnet::display_rdm_enabled(nPortIndex, bEnable); + } + + DEBUG_EXIT +} + +void ArtNetNode::SetRdmDiscovery(const uint32_t nPortIndex, const bool bEnable) { + DEBUG_ENTRY + assert(nPortIndex < artnetnode::MAX_PORTS); + + const auto isEnabled = !((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::DISCOVERY_DISABLED) == artnet::GoodOutputB::DISCOVERY_DISABLED); + + if (isEnabled == bEnable) { + DEBUG_EXIT + return; + } + + if (!bEnable) { + m_OutputPort[nPortIndex].GoodOutputB |= artnet::GoodOutputB::DISCOVERY_DISABLED; + } else { + m_OutputPort[nPortIndex].GoodOutputB &= static_cast(~artnet::GoodOutputB::DISCOVERY_DISABLED); + } + + DEBUG_EXIT +} diff --git a/lib-artnet/src/node/timecode/handletimecode.cpp b/lib-artnet/src/node/timecode/handletimecode.cpp deleted file mode 100644 index 38c21137..00000000 --- a/lib-artnet/src/node/timecode/handletimecode.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @file artnetnodetimecode.cpp - * - */ -/** - * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. - */ -/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "artnetnode.h" -#include "artnet.h" -#include "artnettimecode.h" - -#include "network.h" - -#include "debug.h" - -void ArtNetNode::HandleTimeCode() { - const auto *const pArtTimeCode = reinterpret_cast(m_pReceiveBuffer); - - m_pArtNetTimeCode->Handler(reinterpret_cast(&pArtTimeCode->Frames)); -} - -void ArtNetNode::SetTimeCodeIp(uint32_t nDestinationIp) { - if (Network::Get()->IsValidIp(nDestinationIp)) { - m_Node.IPAddressTimeCode = nDestinationIp; - } else { - m_Node.IPAddressTimeCode = Network::Get()->GetBroadcastIp(); - } - - DEBUG_PRINTF("m_Node.IPAddressTimeCode=" IPSTR, IP2STR(m_Node.IPAddressTimeCode)); -} - -void ArtNetNode::SendTimeCode(const struct TArtNetTimeCode *pArtNetTimeCode) { - assert(pArtNetTimeCode != nullptr); - assert(pArtNetTimeCode->Frames < 30); - assert(pArtNetTimeCode->Hours < 60); - assert(pArtNetTimeCode->Minutes < 60); - assert(pArtNetTimeCode->Seconds < 60); - assert(pArtNetTimeCode->Type < 4); - - memcpy(&m_ArtTimeCode.Frames, pArtNetTimeCode, sizeof(struct TArtNetTimeCode)); - - Network::Get()->SendTo(m_nHandle, &m_ArtTimeCode, sizeof(struct artnet::ArtTimeCode), m_Node.IPAddressTimeCode, artnet::UDP_PORT); -} diff --git a/lib-c++/.cproject b/lib-c++/.cproject deleted file mode 100644 index 6e28cb0d..00000000 --- a/lib-c++/.cproject +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-c++/.settings/language.settings.xml b/lib-c++/.settings/language.settings.xml deleted file mode 100644 index 96fdf9df..00000000 --- a/lib-c++/.settings/language.settings.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-c++/Makefile.GD32 b/lib-c++/Makefile.GD32 deleted file mode 100644 index ff29a8db..00000000 --- a/lib-c++/Makefile.GD32 +++ /dev/null @@ -1,2 +0,0 @@ - -include ../firmware-template-gd32/lib/Rules.mk \ No newline at end of file diff --git a/lib-c/.cproject b/lib-c/.cproject deleted file mode 100644 index feebeb53..00000000 --- a/lib-c/.cproject +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-c/.settings/org.eclipse.cdt.core.prefs b/lib-c/.settings/org.eclipse.cdt.core.prefs deleted file mode 100644 index c8ec5df2..00000000 --- a/lib-c/.settings/org.eclipse.cdt.core.prefs +++ /dev/null @@ -1,6 +0,0 @@ -doxygen/doxygen_new_line_after_brief=true -doxygen/doxygen_use_brief_tag=false -doxygen/doxygen_use_javadoc_tags=true -doxygen/doxygen_use_pre_tag=false -doxygen/doxygen_use_structural_commands=false -eclipse.preferences.version=1 diff --git a/lib-c/Makefile.GD32 b/lib-c/Makefile.GD32 deleted file mode 100644 index b54ecb29..00000000 --- a/lib-c/Makefile.GD32 +++ /dev/null @@ -1,3 +0,0 @@ -#DEFINES=MEM_DEBUG - -include ../firmware-template-gd32/lib/Rules.mk \ No newline at end of file diff --git a/lib-clib/.cproject b/lib-clib/.cproject new file mode 100755 index 00000000..5ae28943 --- /dev/null +++ b/lib-clib/.cproject @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib-c/.project b/lib-clib/.project old mode 100644 new mode 100755 similarity index 97% rename from lib-c/.project rename to lib-clib/.project index 3adc2f41..47d0f02c --- a/lib-c/.project +++ b/lib-clib/.project @@ -1,6 +1,6 @@ - lib-c + lib-clib diff --git a/lib-clib/.settings/language.settings.xml b/lib-clib/.settings/language.settings.xml new file mode 100755 index 00000000..238d3a32 --- /dev/null +++ b/lib-clib/.settings/language.settings.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib-c/.settings/org.eclipse.core.resources.prefs b/lib-clib/.settings/org.eclipse.core.resources.prefs old mode 100644 new mode 100755 similarity index 100% rename from lib-c/.settings/org.eclipse.core.resources.prefs rename to lib-clib/.settings/org.eclipse.core.resources.prefs diff --git a/lib-clib/Makefile.GD32 b/lib-clib/Makefile.GD32 new file mode 100755 index 00000000..0502e1a0 --- /dev/null +++ b/lib-clib/Makefile.GD32 @@ -0,0 +1,25 @@ +DEFINES=NDEBUG + +EXTRA_INCLUDES= + +EXTRA_SRCDIR= + +ifneq ($(MAKE_FLAGS),) + ifeq ($(findstring CONFIG_ENET_ENABLE_PTP,$(MAKE_FLAGS)), CONFIG_ENET_ENABLE_PTP) + EXTRA_SRCDIR+=src/gd32/time_ptp + else + ifeq ($(findstring CONFIG_TIME_USE_TIMER,$(MAKE_FLAGS)), CONFIG_TIME_USE_TIMER) + EXTRA_SRCDIR+=src/gd32/time_timer + else + EXTRA_SRCDIR+=src/gd32/time_systick + endif + endif +else + EXTRA_SRCDIR+=src/gd32/time_systick + + EXTRA_SRCDIR+=src/gd32/time_timer + DEFINES+=CONFIG_TIME_USE_TIMER +endif + +include Rules.mk +include ../firmware-template-gd32/lib/Rules.mk \ No newline at end of file diff --git a/lib-clib/Rules.mk b/lib-clib/Rules.mk new file mode 100755 index 00000000..821b5db7 --- /dev/null +++ b/lib-clib/Rules.mk @@ -0,0 +1,2 @@ + +EXTRA_SRCDIR+=src/c++ \ No newline at end of file diff --git a/lib-clib/src/abort.c b/lib-clib/src/abort.c new file mode 100755 index 00000000..7680b690 --- /dev/null +++ b/lib-clib/src/abort.c @@ -0,0 +1,15 @@ +/* + * abort.c + */ + + +#ifdef NDEBUG +# undef NDEBUG +#endif + +#include + +void abort(void) { + assert(0); + for(;;); +} diff --git a/lib-c/src/asctime.c b/lib-clib/src/asctime.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/asctime.c rename to lib-clib/src/asctime.c diff --git a/lib-clib/src/c++/cxa_atexit.cpp b/lib-clib/src/c++/cxa_atexit.cpp new file mode 100755 index 00000000..cae8031d --- /dev/null +++ b/lib-clib/src/c++/cxa_atexit.cpp @@ -0,0 +1,26 @@ +/* + * cxa_atexit.cpp + */ + +#include + +typedef void (*exitfunc_t)(); + +static exitfunc_t atexit_funcs[32]; +static size_t atexit_count = 0; + +extern "C" int __cxa_atexit(exitfunc_t func, [[maybe_unused]] void *arg, [[maybe_unused]] void *dso_handle) { + if (atexit_count >= sizeof(atexit_funcs) / sizeof(atexit_funcs[0])) + return -1; + + atexit_funcs[atexit_count++] = func; + return 0; // Success +} + +extern "C" void __call_atexit_funcs() { + for (size_t i = atexit_count; i > 0; --i) { + exitfunc_t func = atexit_funcs[i - 1]; + if (func) + func(); + } +} diff --git a/lib-c++/src/delete.cpp b/lib-clib/src/c++/delete.cpp old mode 100644 new mode 100755 similarity index 78% rename from lib-c++/src/delete.cpp rename to lib-clib/src/c++/delete.cpp index 4f5019c3..72c4aa95 --- a/lib-c++/src/delete.cpp +++ b/lib-clib/src/c++/delete.cpp @@ -2,7 +2,7 @@ * @file delete.cpp * */ -/* Copyright (C) 2017-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,8 @@ * THE SOFTWARE. */ -#include +#include +#include void operator delete(void *p) { free(p); @@ -32,3 +33,15 @@ void operator delete(void *p) { void operator delete[](void *p) { free(p); } + +/* + * C++14 and above + */ + +void operator delete(void *p, [[maybe_unused]] std::size_t size) noexcept { + free(p); +} + +void operator delete[](void *p, [[maybe_unused]]std::size_t size) noexcept { + free(p); +} diff --git a/lib-c++/src/dso_handle.cpp b/lib-clib/src/c++/dso_handle.cpp old mode 100644 new mode 100755 similarity index 80% rename from lib-c++/src/dso_handle.cpp rename to lib-clib/src/c++/dso_handle.cpp index c6d7a803..2b06c2e4 --- a/lib-c++/src/dso_handle.cpp +++ b/lib-clib/src/c++/dso_handle.cpp @@ -2,7 +2,7 @@ * @file dso_handle.cpp * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,11 +23,11 @@ * THE SOFTWARE. */ -extern "C" int __aeabi_atexit(void *object, void (*destructor)(void *), void *dso_handle) { - static_cast(object); - static_cast(destructor); - static_cast(dso_handle); - return 0; -} +//extern "C" int __aeabi_atexit(void *object, void (*destructor)(void *), void *dso_handle) { +// static_cast(object); +// static_cast(destructor); +// static_cast(dso_handle); +// return 0; +//} void *__dso_handle = nullptr; diff --git a/lib-clib/src/c++/impure_prt.cpp b/lib-clib/src/c++/impure_prt.cpp new file mode 100755 index 00000000..98bc95e5 --- /dev/null +++ b/lib-clib/src/c++/impure_prt.cpp @@ -0,0 +1,11 @@ +/* + * impure_prt.cpp + */ + +typedef struct _reent { + int _errno; // Placeholder for the actual contents of _reent +} _reent; + +// Define the global _impure_ptr. Normally points to reentrant data. +static struct _reent _reent_data = {0}; +struct _reent *_impure_ptr = &_reent_data; diff --git a/lib-c++/src/new.cpp b/lib-clib/src/c++/new.cpp old mode 100644 new mode 100755 similarity index 92% rename from lib-c++/src/new.cpp rename to lib-clib/src/c++/new.cpp index 6cf0eb0b..64b61cca --- a/lib-c++/src/new.cpp +++ b/lib-clib/src/c++/new.cpp @@ -2,7 +2,7 @@ * @file new.cpp * */ -/* Copyright (C) 2017-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,7 @@ * THE SOFTWARE. */ -#include +#include void *operator new(unsigned size) { return malloc(size); diff --git a/lib-c++/src/purecall.cpp b/lib-clib/src/c++/purecall.cpp old mode 100644 new mode 100755 similarity index 94% rename from lib-c++/src/purecall.cpp rename to lib-clib/src/c++/purecall.cpp index b6c1dcb9..d4ff1c39 --- a/lib-c++/src/purecall.cpp +++ b/lib-clib/src/c++/purecall.cpp @@ -2,7 +2,7 @@ * @file purecall.cpp * */ -/* Copyright (C) 2017-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-c/src/errno.c b/lib-clib/src/errno.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/errno.c rename to lib-clib/src/errno.c diff --git a/lib-c/src/assert.c b/lib-clib/src/gd32/assert.c similarity index 100% rename from lib-c/src/assert.c rename to lib-clib/src/gd32/assert.c diff --git a/lib-configstore/src/rdm/storerdmsubdevices.cpp b/lib-clib/src/gd32/malloc.h old mode 100644 new mode 100755 similarity index 74% rename from lib-configstore/src/rdm/storerdmsubdevices.cpp rename to lib-clib/src/gd32/malloc.h index 5b200425..7a4109ab --- a/lib-configstore/src/rdm/storerdmsubdevices.cpp +++ b/lib-clib/src/gd32/malloc.h @@ -1,8 +1,8 @@ /** - * @file storerdmsubdevices.cpp + * @file malloc.h * */ -/* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,20 +23,9 @@ * THE SOFTWARE. */ -#include +#ifndef GD32_MALLOC_H_ +#define GD32_MALLOC_H_ -#include "storerdmsubdevices.h" +static struct block_bucket s_block_bucket[] __attribute__((aligned(4))) = {{0x10, 0}, {0x20, 0}, {0x40, 0}, {0x60, 0}, {0x80,0}, {0x100,0}, {0x140,0}, {0x180,0}, {0x200,0}, {0x300,0}, {0x400,0}, {0x500,0}, {0,0}}; -#include "debug.h" - -StoreRDMSubDevices *StoreRDMSubDevices::s_pThis = nullptr; - -StoreRDMSubDevices::StoreRDMSubDevices() { - DEBUG_ENTRY - - assert(s_pThis == nullptr); - s_pThis = this; - - DEBUG_PRINTF("%p", reinterpret_cast(s_pThis)); - DEBUG_EXIT -} +#endif /* GD32_MALLOC_H_ */ diff --git a/lib-clib/src/gd32/time_ptp/time.cpp b/lib-clib/src/gd32/time_ptp/time.cpp new file mode 100644 index 00000000..a418f743 --- /dev/null +++ b/lib-clib/src/gd32/time_ptp/time.cpp @@ -0,0 +1,99 @@ +/** + * @file time.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma GCC push_options +#pragma GCC optimize ("O2") + +#include +#include +#include +#include + +#include "gd32.h" +#include "gd32_ptp.h" + +#if defined (GD32H7XX) +# define enet_ptp_timestamp_function_config(x) enet_ptp_timestamp_function_config(ENETx, x) +# define enet_ptp_timestamp_update_config(x,y,z) enet_ptp_timestamp_update_config(ENETx, x, y, z) +# define enet_ptp_system_time_get(x) enet_ptp_system_time_get(ENETx, x) +#endif + +extern "C" { +/* + * number of seconds and microseconds since the Epoch, + * 1970-01-01 00:00:00 +0000 (UTC). + */ + +int gettimeofday(struct timeval *tv, [[maybe_unused]] struct timezone *tz) { + assert(tv != 0); + + enet_ptp_systime_struct systime; + enet_ptp_system_time_get(&systime); + + tv->tv_sec = systime.second; + +#if !defined (GD32F4XX) + const auto nNanoSecond = systime.nanosecond; +#else + const auto nNanoSecond = gd32::ptp_subsecond_2_nanosecond(systime.subsecond); +#endif + + tv->tv_usec = nNanoSecond / 1000U; + + return 0; +} + +int settimeofday(const struct timeval *tv, [[maybe_unused]] const struct timezone *tz) { + assert(tv != 0); + + const uint32_t nSign = ENET_PTP_ADD_TO_TIME; + const uint32_t nSecond = tv->tv_sec; + const uint32_t nNanoSecond = tv->tv_usec * 1000U; + const auto nSubSecond = gd32::ptp_nanosecond_2_subsecond(nNanoSecond); + + enet_ptp_timestamp_update_config(nSign, nSecond, nSubSecond); + + if (SUCCESS == enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT)) { + return 0; + } + + return -1; +} + +/* + * time() returns the time as the number of seconds since the Epoch, + 1970-01-01 00:00:00 +0000 (UTC). + */ +time_t time(time_t *__timer) { + struct timeval tv; + gettimeofday(&tv, 0); + + if (__timer != nullptr) { + *__timer = tv.tv_sec; + } + + return tv.tv_sec; +} +} diff --git a/lib-c/src/gd32/time.c b/lib-clib/src/gd32/time_systick/time.cpp similarity index 54% rename from lib-c/src/gd32/time.c rename to lib-clib/src/gd32/time_systick/time.cpp index b754cc25..024803bf 100644 --- a/lib-c/src/gd32/time.c +++ b/lib-clib/src/gd32/time_systick/time.cpp @@ -2,7 +2,7 @@ * @file time.c * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@gd32-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,50 +23,67 @@ * THE SOFTWARE. */ -#include -#include -#include -#include +#pragma GCC push_options +#pragma GCC optimize ("O2") -extern volatile uint32_t s_nSysTickMillis; +#include +#include +#include +#include -static uint32_t set_timer = 0; -static uint64_t s_micros = 0; +extern volatile uint32_t gv_nSysTickMillis; -#define MICROS_SECONDS 1000000 +static uint32_t nPreviousSysTickMillis; +static struct timeval s_tv; +extern "C" { /* * number of seconds and microseconds since the Epoch, * 1970-01-01 00:00:00 +0000 (UTC). */ -int gettimeofday(struct timeval *tv, __attribute__((unused)) struct timezone *tz) { +int gettimeofday(struct timeval *tv, __attribute__((unused)) struct timezone *tz) { assert(tv != 0); - const uint32_t timer = s_nSysTickMillis; // Millis timer + const auto nCurrentSysTickMillis = gv_nSysTickMillis; - uint32_t timer_elapsed; + uint32_t nMillisElapsed; - if (set_timer >= timer) { - timer_elapsed = set_timer - timer; + if (nCurrentSysTickMillis >= nPreviousSysTickMillis) { + nMillisElapsed = nCurrentSysTickMillis - nPreviousSysTickMillis; } else { - timer_elapsed = timer - set_timer; + nMillisElapsed = (UINT32_MAX - nPreviousSysTickMillis) + nCurrentSysTickMillis + 1; } - set_timer = timer; - s_micros += (timer_elapsed * 1000); + nPreviousSysTickMillis = nCurrentSysTickMillis; + + const auto nSeconds = nMillisElapsed / 1000U; + const auto nMicroSeconds = (nMillisElapsed % 1000U) * 1000U; - tv->tv_sec = (time_t)(s_micros / MICROS_SECONDS); - tv->tv_usec = (suseconds_t) (s_micros - ((uint64_t) tv->tv_sec * MICROS_SECONDS)); + s_tv.tv_sec += static_cast(nSeconds); + s_tv.tv_usec += static_cast(nMicroSeconds); + + if (s_tv.tv_usec >= 1000000) { + s_tv.tv_sec++; + s_tv.tv_usec -= 1000000; + } + + tv->tv_sec = s_tv.tv_sec; + tv->tv_usec = s_tv.tv_usec; return 0; } -int settimeofday(const struct timeval *tv, __attribute__((unused)) const struct timezone *tz) { +int settimeofday(const struct timeval *tv, __attribute__((unused)) const struct timezone *tz) { assert(tv != 0); - set_timer = s_nSysTickMillis; - s_micros = ((uint64_t) tv->tv_sec * MICROS_SECONDS) + (uint64_t) tv->tv_usec; + struct timeval g; + gettimeofday(&g, nullptr); + + nPreviousSysTickMillis = gv_nSysTickMillis; + + s_tv.tv_sec = tv->tv_sec; + s_tv.tv_usec = tv->tv_usec; return 0; } @@ -77,11 +94,12 @@ int settimeofday(const struct timeval *tv, __attribute__((unused)) const struct */ time_t time(time_t *__timer) { struct timeval tv; - gettimeofday(&tv, 0); + gettimeofday(&tv, nullptr); - if (__timer != NULL) { + if (__timer != nullptr) { *__timer = tv.tv_sec; } return tv.tv_sec; } +} diff --git a/lib-clib/src/gd32/time_timer/time.cpp b/lib-clib/src/gd32/time_timer/time.cpp new file mode 100644 index 00000000..8782a953 --- /dev/null +++ b/lib-clib/src/gd32/time_timer/time.cpp @@ -0,0 +1,157 @@ +/** + * @file time.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma GCC push_options +#pragma GCC optimize ("O2") + +#include +#include +#include +#include + +#include "gd32.h" + +#if defined(GD32H7XX) +# define TIMERx TIMER16 +# define RCU_TIMERx RCU_TIMER16 +# define TIMERx_IRQn TIMER16_IRQn +#else +# define TIMERx TIMER7 +# define RCU_TIMERx RCU_TIMER7 +# if defined (GD32F10X) || defined (GD32F30X) +# define TIMERx_IRQn TIMER7_IRQn +# else +# define TIMERx_IRQn TIMER7_UP_TIMER12_IRQn +# endif +#endif + +extern struct HwTimersSeconds g_Seconds; + +extern "C" { +#if !defined (CONFIG_ENET_ENABLE_PTP) +# if defined (CONFIG_TIME_USE_TIMER) +# if defined(GD32H7XX) +void TIMER16_IRQHandler() { +# elif defined (GD32F10X) || defined (GD32F30X) +void TIMER7_IRQHandler() { +# else +void TIMER7_UP_TIMER12_IRQHandler() { +# endif + const auto nIntFlag = TIMER_INTF(TIMERx); + + if ((nIntFlag & TIMER_INT_FLAG_UP) == TIMER_INT_FLAG_UP) { + g_Seconds.nTimeval++; + } + + TIMER_INTF(TIMERx) = static_cast(~nIntFlag); +} +# endif +#endif +} + +#if defined(GD32H7XX) +void timer16_config() { +#else +void timer7_config() { +#endif + g_Seconds.nTimeval = 0; + + rcu_periph_clock_enable(RCU_TIMERx); + timer_deinit(TIMERx); + + timer_parameter_struct timer_initpara; + timer_struct_para_init(&timer_initpara); + + timer_initpara.prescaler = TIMER_PSC_10KHZ; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = (10000 - 1); // 1 second + timer_init(TIMERx, &timer_initpara); + + timer_interrupt_flag_clear(TIMERx, ~0); + + timer_interrupt_enable(TIMERx, TIMER_INT_UP); + + NVIC_SetPriority(TIMERx_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); // Lowest priority + NVIC_EnableIRQ(TIMERx_IRQn); + + timer_enable(TIMERx); +} + +extern "C" { +/* + * number of seconds and microseconds since the Epoch, + * 1970-01-01 00:00:00 +0000 (UTC). + */ + +int gettimeofday(struct timeval *tv, __attribute__((unused)) struct timezone *tz) { + assert(tv != 0); + +#if __CORTEX_M == 7 + __DMB(); +#endif + + tv->tv_sec = g_Seconds.nTimeval; + tv->tv_usec = TIMER_CNT(TIMERx) * 100U; + +#if __CORTEX_M == 7 + __ISB(); +#endif + + return 0; +} + +int settimeofday(const struct timeval *tv, __attribute__((unused)) const struct timezone *tz) { + assert(tv != 0); + + // Disable the timer interrupt to prevent it from triggering while we adjust the counter + TIMER_DMAINTEN(TIMERx) &= static_cast(~TIMER_INT_UP); + TIMER_CTL0(TIMERx) &= static_cast(~TIMER_CTL0_CEN); + + g_Seconds.nTimeval = tv->tv_sec; + TIMER_CNT(TIMERx) = (tv->tv_usec / 100U) % 10000; + + TIMER_INTF(TIMERx) = static_cast(~0); + TIMER_DMAINTEN(TIMERx) |= TIMER_INT_UP; + TIMER_CTL0(TIMERx) |= TIMER_CTL0_CEN; + + return 0; +} + +/* + * time() returns the time as the number of seconds since the Epoch, + 1970-01-01 00:00:00 +0000 (UTC). + */ +time_t time(time_t *__timer) { + struct timeval tv; + gettimeofday(&tv, nullptr); + + if (__timer != nullptr) { + *__timer = tv.tv_sec; + } + + return tv.tv_sec; +} +} diff --git a/lib-clib/src/gd32/uuid.cpp b/lib-clib/src/gd32/uuid.cpp new file mode 100644 index 00000000..89f9772f --- /dev/null +++ b/lib-clib/src/gd32/uuid.cpp @@ -0,0 +1,58 @@ +/** + * @file uuid.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of thnDmxDataDirecte Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "gd32.h" + +namespace hal { +typedef union pcast32 { + uuid_t uuid; + uint32_t u32[4]; +} _pcast32; + +void uuid_init(uuid_t out) { + _pcast32 cast; + +#if defined (GD32H7XX) + cast.u32[0] = REG32(0x1FF0F7E8); + cast.u32[1] = REG32(0x1FF0F7EC); + cast.u32[2] = REG32(0x1FF0F7F0); +#elif defined (GD32F4XX) + cast.u32[0] = REG32(0x1FFF7A10); + cast.u32[1] = REG32(0x1FFF7A14); + cast.u32[2] = REG32(0x1FFF7A18); +#else + cast.u32[0] = REG32(0x1FFFF7E8); + cast.u32[1] = REG32(0x1FFFF7EC); + cast.u32[2] = REG32(0x1FFFF7F0); +#endif + cast.u32[3] = cast.u32[0] + cast.u32[1] + cast.u32[2]; + + memcpy(out, cast.uuid, sizeof(uuid_t)); +} +} // namespace hal diff --git a/lib-c/src/inet_aton.c b/lib-clib/src/inet_aton.c old mode 100644 new mode 100755 similarity index 94% rename from lib-c/src/inet_aton.c rename to lib-clib/src/inet_aton.c index 52dbfc3d..cc83bb53 --- a/lib-c/src/inet_aton.c +++ b/lib-clib/src/inet_aton.c @@ -25,13 +25,14 @@ #include #include +#include typedef union pcast32 { uint32_t u32; uint8_t u8[4]; } _pcast32; -int inet_aton(const char *cp, uint32_t *ip_address) { +int inet_aton(const char *cp, struct in_addr *ip_address) { const char *b = cp; int i, j, k; _pcast32 cast32; @@ -79,7 +80,7 @@ int inet_aton(const char *cp, uint32_t *ip_address) { cast32.u8[i] = (uint8_t)k; if (ip_address != 0) { - *ip_address = cast32.u32; + ip_address->s_addr = cast32.u32; } return 1; diff --git a/lib-c/src/init.c b/lib-clib/src/init.c similarity index 100% rename from lib-c/src/init.c rename to lib-clib/src/init.c diff --git a/lib-c/src/log.c b/lib-clib/src/log.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/log.c rename to lib-clib/src/log.c diff --git a/lib-c/src/malloc.c b/lib-clib/src/malloc.c old mode 100644 new mode 100755 similarity index 90% rename from lib-c/src/malloc.c rename to lib-clib/src/malloc.c index e6af3cb8..58676778 --- a/lib-c/src/malloc.c +++ b/lib-clib/src/malloc.c @@ -8,7 +8,7 @@ * Copyright (C) 2014-2016 R. Stange * https://github.com/rsta2/circle/blob/master/lib/alloc.cpp */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,15 +32,18 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpointer-arith" // FIXME ignored "-Wpointer-arith" #pragma GCC diagnostic ignored "-Wpedantic" // FIXME ignored "-Wpedantic" +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" #include #include #include -#ifdef MEM_DEBUG +#ifdef DEBUG_HEAP #include #endif +extern void console_error(const char *); + extern unsigned char heap_low; /* Defined by the linker */ extern unsigned char heap_top; /* Defined by the linker */ @@ -58,14 +61,20 @@ struct block_header { struct block_bucket { unsigned int size; -#ifdef MEM_DEBUG +#ifdef DEBUG_HEAP unsigned int count; unsigned int max_count; #endif struct block_header *free_list; }; -static struct block_bucket s_block_bucket[] __attribute__((aligned(4))) = {{0x10, 0}, {0x20, 0}, {0x40, 0}, {0x60, 0}, {0x80,0}, {0x100,0}, {0x140,0}, {0x180,0}, {0x200,0}, {0x300,0}, {0x400,0}, {0x500,0}, {0,0}}; +#if defined (H3) +# include "h3/malloc.h" +#elif defined (GD32) +# include "gd32/malloc.h" +#else +# include "rpi/malloc.h" +#endif size_t get_allocated(void *p) { if (p == 0) { @@ -83,9 +92,6 @@ size_t get_allocated(void *p) { } void *malloc(size_t size) { -#ifdef MEM_DEBUG - printf("malloc: %u\n", size); -#endif struct block_bucket *bucket; struct block_header *header; @@ -96,7 +102,7 @@ void *malloc(size_t size) { for (bucket = s_block_bucket; bucket->size > 0; bucket++) { if (size <= bucket->size) { size = bucket->size; -#ifdef MEM_DEBUG +#ifdef DEBUG_HEAP if (++bucket->count > bucket->max_count) { bucket->max_count = bucket->count; } @@ -120,9 +126,7 @@ void *malloc(size_t size) { assert(((unsigned)next & (unsigned)3) == 0); if (next > block_limit) { -#ifdef MEM_DEBUG - printf("malloc: next > block_limit\n"); -#endif + console_error("next > block_limit\n"); return NULL; } else { next_block = next; @@ -133,8 +137,8 @@ void *malloc(size_t size) { } header->next = 0; -#ifdef MEM_DEBUG - printf("malloc: pBlockHeader=%p, size=%d, data=%p\n", header, (int) size, (void *)header->data); +#ifdef DEBUG_HEAP + printf("malloc: pBlockHeader = %p, size = %d\n", header, (int) size); #endif assert(((unsigned)header->data & (unsigned)3) == 0); @@ -150,7 +154,7 @@ void free(void *p) { struct block_header *header = (struct block_header *) ((void *) p - sizeof(struct block_header)); -#ifdef MEM_DEBUG +#ifdef DEBUG_HEAP printf("free: pBlockHeader = %p, pBlock = %p\n", header, p); #endif @@ -164,7 +168,7 @@ void free(void *p) { header->next = bucket->free_list; bucket->free_list = header; -#ifdef MEM_DEBUG +#ifdef DEBUG_HEAP bucket->count--; #endif break; @@ -258,8 +262,8 @@ void *realloc(void *ptr, size_t size) { return newblk; } -void mem_info(void) { -#ifdef MEM_DEBUG +void debug_heap(void) { +#ifdef DEBUG_HEAP struct block_bucket *pBucket; struct block_header *pBlockHeader; printf("s_pNextBlock = %p\n", next_block); diff --git a/lib-clib/src/memchr.c b/lib-clib/src/memchr.c new file mode 100755 index 00000000..ca055d21 --- /dev/null +++ b/lib-clib/src/memchr.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +void* memchr(const void *src, int c, size_t len) { + const unsigned char *s = src; + + while (len--) { + if (*s == (unsigned char) c) + return (void*) s; + s++; + } + + return NULL; +} diff --git a/lib-clib/src/memcmp.c b/lib-clib/src/memcmp.c new file mode 100755 index 00000000..7b1a185a --- /dev/null +++ b/lib-clib/src/memcmp.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +int memcmp(const void *s1, const void *s2, size_t len) +{ + const unsigned char *s = s1; + const unsigned char *d = s2; + unsigned char sc; + unsigned char dc; + + while (len--) { + sc = *s++; + dc = *d++; + if (sc - dc) + return (sc - dc); + } + + return 0; +} diff --git a/lib-c/src/memcpy.c b/lib-clib/src/memcpy.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/memcpy.c rename to lib-clib/src/memcpy.c diff --git a/lib-c/src/memmove.c b/lib-clib/src/memmove.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/memmove.c rename to lib-clib/src/memmove.c diff --git a/lib-c/src/memset.c b/lib-clib/src/memset.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/memset.c rename to lib-clib/src/memset.c diff --git a/lib-c/src/perror.c b/lib-clib/src/perror.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/perror.c rename to lib-clib/src/perror.c diff --git a/lib-c/src/printf.c b/lib-clib/src/printf.c old mode 100644 new mode 100755 similarity index 92% rename from lib-c/src/printf.c rename to lib-clib/src/printf.c index 24b240b2..0ba67569 --- a/lib-c/src/printf.c +++ b/lib-clib/src/printf.c @@ -2,7 +2,7 @@ * @file printf.c * */ -/* Copyright (C) 2016-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,7 +29,6 @@ #include #include #include -#include extern int console_putc(int); @@ -53,7 +52,7 @@ enum { static char *outptr = NULL; -inline static void _xputch(struct context *ctx, int c) { +inline static void _xputch(struct context *ctx, const int c) { ctx->total++; if (outptr != NULL) { @@ -78,7 +77,7 @@ static int _pow10(int n) { return r; } -static int _itostr(int x, /*@out@*/char *s, int d) { +static int _itostr(int x, char *s, int d) { char buffer[64]; char *p = buffer + (sizeof(buffer) / sizeof(buffer[0])) - 1; char *o = p; @@ -123,7 +122,7 @@ static int _itostr(int x, /*@out@*/char *s, int d) { return i + 1; } -static void _round_float(/*@out@*/char *dest, int *size) { +static void _round_float(char *dest, int *size) { int i = *size - 1; char *q = (char *) dest + i; bool round_int = false; @@ -175,7 +174,7 @@ static void _round_float(/*@out@*/char *dest, int *size) { #endif static void _format_hex(struct context *ctx, unsigned int arg) { - char buffer[64] __attribute__((aligned(4))); + char buffer[64]; char *p = buffer + (sizeof(buffer) / sizeof(buffer[0])) - 1; char *o = p; char alpha; @@ -227,7 +226,7 @@ static void _format_hex(struct context *ctx, unsigned int arg) { } } -static void _format_int(struct context *ctx, uint64_t arg) { +static void _format_int(struct context *ctx, unsigned long int arg) { char buffer[64]; char *p = buffer + (sizeof(buffer) / sizeof(buffer[0])) - 1; char *o = p; @@ -281,7 +280,7 @@ static void _format_int(struct context *ctx, uint64_t arg) { #if !defined (DISABLE_PRINTF_FLOAT) static void _format_float(struct context *ctx, float f) { - char buffer[64] __attribute__((aligned(4))); + char buffer[64]; char *dest = (char *) buffer; int ipart; int precision; @@ -366,8 +365,8 @@ static int _vprintf(const int size, const char *fmt, va_list va) { #if !defined (DISABLE_PRINTF_FLOAT) float f; #endif - int64_t l; - uint64_t lu; + long int l; + unsigned long int lu; const char *s; ctx.total = 0; @@ -433,12 +432,12 @@ static int _vprintf(const int size, const char *fmt, va_list va) { /*@fallthrough@*/ /* no break */ case 'i': - l = ((ctx.flag & FLAG_LONG) != 0) ? va_arg(va, int64_t) : (int64_t) va_arg(va, int32_t); + l = ((ctx.flag & FLAG_LONG) != 0) ? va_arg(va, long int) : (long int) va_arg(va, int); if (l < 0) { ctx.flag |= FLAG_NEGATIVE; l = -l; } - _format_int(&ctx, (uint64_t) l); + _format_int(&ctx, (unsigned long int) l); break; #if !defined (DISABLE_PRINTF_FLOAT) case 'f': @@ -447,14 +446,14 @@ static int _vprintf(const int size, const char *fmt, va_list va) { break; #endif case 'p': - _format_pointer(&ctx, va_arg(va, uint32_t)); + _format_pointer(&ctx, va_arg(va, unsigned int)); break; case 's': s = va_arg(va, const char *); _format_string(&ctx, s); break; case 'u': - lu = ((ctx.flag & FLAG_LONG) != 0) ? va_arg(va, uint64_t) : va_arg(va,uint32_t); + lu = ((ctx.flag & FLAG_LONG) != 0) ? va_arg(va, unsigned long int) : va_arg(va, unsigned int); _format_int(&ctx, lu); break; case 'X': @@ -462,7 +461,7 @@ static int _vprintf(const int size, const char *fmt, va_list va) { /*@fallthrough@*/ /* no break */ case 'x': - _format_hex(&ctx, va_arg(va, uint32_t)); + _format_hex(&ctx, va_arg(va, unsigned int)); break; default: _xputch(&ctx, (int) *fmt); diff --git a/lib-c/src/putchar.c b/lib-clib/src/putchar.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/putchar.c rename to lib-clib/src/putchar.c diff --git a/lib-c/src/puts.c b/lib-clib/src/puts.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/puts.c rename to lib-clib/src/puts.c diff --git a/lib-c/src/random.c b/lib-clib/src/random.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/random.c rename to lib-clib/src/random.c diff --git a/lib-clib/src/strchr.c b/lib-clib/src/strchr.c new file mode 100755 index 00000000..750a42dc --- /dev/null +++ b/lib-clib/src/strchr.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +/* + * strchr -- + * + * PUBLIC: #ifndef HAVE_STRCHR + * PUBLIC: char *strchr __P((const char *, int)); + * PUBLIC: #endif + */ +char *strchr(const char *p, int ch) +{ + char c; + + c = (char) ch; + for (;; ++p) { + if (*p == c) + return ((char *)p); + if (*p == '\0') + return (NULL); + } + /* NOTREACHED */ +} diff --git a/lib-c/src/strlen.c b/lib-clib/src/strlen.c similarity index 100% rename from lib-c/src/strlen.c rename to lib-clib/src/strlen.c diff --git a/lib-clib/src/strncmp.c b/lib-clib/src/strncmp.c new file mode 100755 index 00000000..77d962a4 --- /dev/null +++ b/lib-clib/src/strncmp.c @@ -0,0 +1,51 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions copyright (c) 2018, Arm Limited and Contributors. + * All rights reserved. + */ + +#include + +int strncmp(const char *s1, const char *s2, size_t n) { + + if (n == 0) + return (0); + do { + if (*s1 != *s2++) + return (*(const unsigned char*) s1 + - *(const unsigned char*) (s2 - 1)); + if (*s1++ == '\0') + break; + } while (--n != 0); + return (0); +} diff --git a/lib-clib/src/strstr.c b/lib-clib/src/strstr.c new file mode 100755 index 00000000..29d74bbb --- /dev/null +++ b/lib-clib/src/strstr.c @@ -0,0 +1,71 @@ +/* + * strstr.c -- + * + * Source code for the "strstr" library routine. + * + * Copyright (c) 1988-1993 The Regents of the University of California. + * Copyright (c) 1994 Sun Microsystems, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: strstr.c,v 1.1.1.3 2003/03/06 00:09:04 landonf Exp $ + */ + +/* + *---------------------------------------------------------------------- + * + * strstr -- + * + * Locate the first instance of a substring in a string. + * + * Results: + * If string contains substring, the return value is the + * location of the first matching instance of substring + * in string. If string doesn't contain substring, the + * return value is 0. Matching is done on an exact + * character-for-character basis with no wildcards or special + * characters. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +#include + +char *strstr(const char *string, const char *substring) { + /* First scan quickly through the two strings looking for a + * single-character match. When it's found, then compare the + * rest of the substring. + */ + + const char *b = substring; + + if (*b == 0) { + return (char *)string; + } + + for (; *string != 0; string += 1) { + if (*string != *b) { + continue; + } + + const char *a = string; + + while (1) { + if (*b == 0) { + return (char *)string; + } + + if (*a++ != *b++) { + break; + } + } + + b = substring; + } + + return NULL; +} diff --git a/lib-c/src/strtok.c b/lib-clib/src/strtok.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/strtok.c rename to lib-clib/src/strtok.c diff --git a/lib-clib/src/strtoul.c b/lib-clib/src/strtoul.c new file mode 100755 index 00000000..2581ed15 --- /dev/null +++ b/lib-clib/src/strtoul.c @@ -0,0 +1,118 @@ +#pragma GCC push_options +#pragma GCC diagnostic ignored "-Wsign-conversion" +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +static int isspace(int c) { + return (c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r' || c == ' ' ? 1 : 0); +} + +/* + * Convert a string to an unsigned long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long strtoul(const char *nptr, char **endptr, int base) +{ + const char *s; + unsigned long acc; + char c; + unsigned long cutoff; + int neg, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + s = nptr; + do { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + + cutoff = ULONG_MAX / base; + cutlim = ULONG_MAX % base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + } else if (neg) + acc = -acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} diff --git a/lib-c/src/time.c b/lib-clib/src/time.cpp old mode 100644 new mode 100755 similarity index 54% rename from lib-c/src/time.c rename to lib-clib/src/time.cpp index 0f08b958..86fe621b --- a/lib-c/src/time.c +++ b/lib-clib/src/time.cpp @@ -1,8 +1,8 @@ /** - * @file time.c + * @file time.cpp * */ -/* Copyright (C) 2016-2019 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,12 +23,19 @@ * THE SOFTWARE. */ -#include +#include + +#include +#include #include -static const int days_of_month[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +namespace global { +int32_t *gp_nUtcOffset; +} // namespace global + +static constexpr int days_of_month[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -static int isleapyear(int year) { +static int isleapyear(const int year) { if (year % 100 == 0) { return year % 400 == 0; } @@ -36,7 +43,7 @@ static int isleapyear(int year) { return year % 4 == 0; } -static int getdaysofmonth(int month, int year) { +static int getdaysofmonth(const int month, const int year) { if ((month == 1) && isleapyear(year)) { return 29; } @@ -46,106 +53,120 @@ static int getdaysofmonth(int month, int year) { static struct tm Tm; +extern "C" { + struct tm *localtime(const time_t *pTime) { - int nYear; - int nMonth; + if (pTime == nullptr) { + return nullptr; + } + + auto nTime = *pTime + *global::gp_nUtcOffset; + return gmtime(&nTime); +} - if (pTime == 0) { - return NULL; +struct tm *gmtime(const time_t *pTime) { + if (pTime == nullptr) { + return nullptr; } - time_t Time = *pTime; + auto nTime = *pTime; - Tm.tm_sec = Time % 60; - Time /= 60; - Tm.tm_min = Time % 60; - Time /= 60; - Tm.tm_hour = Time % 24; - Time /= 24; + Tm.tm_sec = nTime % 60; + nTime /= 60; + Tm.tm_min = nTime % 60; + nTime /= 60; + Tm.tm_hour = nTime % 24; + nTime /= 24; - Tm.tm_wday = (Time + 4) % 7; + Tm.tm_wday = (nTime + 4) % 7; + + int nYear = 1970; - nYear = 1970; while (1) { - int nDaysOfYear = isleapyear(nYear) ? 366 : 365; - if (Time < nDaysOfYear) { + const time_t nDaysOfYear = isleapyear(nYear) ? 366 : 365; + if (nTime < nDaysOfYear) { break; } - Time -= nDaysOfYear; + nTime -= nDaysOfYear; nYear++; } Tm.tm_year = nYear - 1900; - Tm.tm_yday = Time; + Tm.tm_yday = nTime; + + int nMonth = 0; - nMonth = 0; while (1) { - int nDaysOfMonth = getdaysofmonth(nMonth, nYear); - if (Time < nDaysOfMonth) { + const time_t nDaysOfMonth = getdaysofmonth(nMonth, nYear); + if (nTime < nDaysOfMonth) { break; } - Time -= nDaysOfMonth; + nTime -= nDaysOfMonth; nMonth++; } Tm.tm_mon = nMonth; - Tm.tm_mday = Time + 1; + Tm.tm_mday = nTime + 1; return &Tm; } time_t mktime(struct tm *pTm) { - int year, month; - time_t result = 0; + time_t nResult = 0; - if (pTm == NULL) { - return (time_t) -1; + if (pTm == nullptr) { + return -1; } if (pTm->tm_year < 70 || pTm->tm_year > 139) { - return (time_t) -1; + return -1; } - for (year = 1970; year < 1900 + pTm->tm_year; year++) { - result += isleapyear(year) ? 366 : 365; + int nYear; + + for (nYear = 1970; nYear < 1900 + pTm->tm_year; nYear++) { + nResult += isleapyear(nYear) ? 366 : 365; } if (pTm->tm_mon < 0 || pTm->tm_mon > 11) { - return (time_t) -1; + return -1; } - for (month = 0; month < pTm->tm_mon; month++) { - result += getdaysofmonth(month, pTm->tm_year); + int nMonth; + + for (nMonth = 0; nMonth < pTm->tm_mon; nMonth++) { + nResult += getdaysofmonth(nMonth, pTm->tm_year); } if (pTm->tm_mday < 1 || pTm->tm_mday > getdaysofmonth(pTm->tm_mon, pTm->tm_year)) { - return (time_t) -1; + return -1; } - result += pTm->tm_mday - 1; - result *= 24; + nResult += pTm->tm_mday - 1; + nResult *= 24; if (pTm->tm_hour < 0 || pTm->tm_hour > 23) { - return (time_t) -1; + return -1; } - result += pTm->tm_hour; - result *= 60; + nResult += pTm->tm_hour; + nResult *= 60; if (pTm->tm_min < 0 || pTm->tm_min > 59) { - return (time_t) -1; + return -1; } - result += pTm->tm_min; - result *= 60; + nResult += pTm->tm_min; + nResult *= 60; if (pTm->tm_sec < 0 || pTm->tm_sec > 59) { - return (time_t) -1; + return -1; } - result += pTm->tm_sec; + nResult += pTm->tm_sec; - return result; + return nResult; +} } diff --git a/lib-uuid/src/uuid_internal.h b/lib-clib/src/uuid_internal.h old mode 100644 new mode 100755 similarity index 100% rename from lib-uuid/src/uuid_internal.h rename to lib-clib/src/uuid_internal.h diff --git a/lib-uuid/src/uuid_parse.c b/lib-clib/src/uuid_parse.c old mode 100644 new mode 100755 similarity index 100% rename from lib-uuid/src/uuid_parse.c rename to lib-clib/src/uuid_parse.c diff --git a/lib-uuid/src/uuid_unparse.c b/lib-clib/src/uuid_unparse.c old mode 100644 new mode 100755 similarity index 100% rename from lib-uuid/src/uuid_unparse.c rename to lib-clib/src/uuid_unparse.c diff --git a/lib-configstore/.cproject b/lib-configstore/.cproject index 03798c82..b20e7f9f 100755 --- a/lib-configstore/.cproject +++ b/lib-configstore/.cproject @@ -30,13 +30,10 @@ - - @@ -114,13 +106,10 @@ - - - diff --git a/lib-configstore/.settings/language.settings.xml b/lib-configstore/.settings/language.settings.xml index 04d74f25..797b2f1b 100755 --- a/lib-configstore/.settings/language.settings.xml +++ b/lib-configstore/.settings/language.settings.xml @@ -2,7 +2,7 @@ - + diff --git a/lib-configstore/Rules.mk b/lib-configstore/Rules.mk old mode 100644 new mode 100755 index 31498ee5..af700683 --- a/lib-configstore/Rules.mk +++ b/lib-configstore/Rules.mk @@ -1,7 +1,6 @@ $(info $$MAKE_FLAGS [${MAKE_FLAGS}]) -EXTRA_INCLUDES =../lib-flashcode/include ../lib-flash/include -EXTRA_INCLUDES+=../lib-hal/include ../lib-properties/include ../lib-lightset/include ../lib-network/include +EXTRA_INCLUDES+=../lib-properties/include ifneq ($(MAKE_FLAGS),) ifneq (,$(findstring CONFIG_STORE_USE_FILE,$(MAKE_FLAGS))) @@ -23,153 +22,10 @@ ifneq ($(MAKE_FLAGS),) ifneq (,$(findstring CONFIG_STORE_USE_SPI,$(MAKE_FLAGS))) EXTRA_SRCDIR+=device/spi endif - - RDM= - - ifneq (,$(findstring ESP8266,$(MAKE_FLAGS))) - EXTRA_SRCDIR+=src/network - EXTRA_INCLUDES+=../lib-network/include - # Remote config is not used with ESP8266 - EXTRA_INCLUDES+=../lib-remoteconfig/include - endif - - ifeq (,$(findstring NO_EMAC,$(MAKE_FLAGS))) - EXTRA_SRCDIR+=src/network - EXTRA_INCLUDES+=../lib-network/include - EXTRA_INCLUDES+=../lib-remoteconfig/include - endif - - ifeq ($(findstring DISPLAY_UDF,$(MAKE_FLAGS)), DISPLAY_UDF) - EXTRA_SRCDIR+=src/displayudf - EXTRA_INCLUDES+=../lib-displayudf/include - endif - - ifeq ($(findstring NODE_ARTNET,$(MAKE_FLAGS)), NODE_ARTNET) - EXTRA_SRCDIR+=src/artnet - EXTRA_INCLUDES+=../lib-artnet/include - EXTRA_SRCDIR+=src/rdm - RDM=1 - EXTRA_INCLUDES+=../lib-rdm/include ../lib-rdmsensor/include ../lib-rdmsubdevice/include - ifeq ($(findstring ARTNET_VERSION=4,$(MAKE_FLAGS)), ARTNET_VERSION=4) - EXTRA_INCLUDES+=../lib-e131/include - endif - endif - - ifeq ($(findstring NODE_E131,$(MAKE_FLAGS)), NODE_E131) - EXTRA_SRCDIR+=src/e131 - EXTRA_INCLUDES+=../lib-e131/include - endif - - ifeq ($(findstring NODE_LTC_SMPTE,$(MAKE_FLAGS)), NODE_LTC_SMPTE) - EXTRA_SRCDIR+=src/ltc - EXTRA_INCLUDES+=../lib-ltc/include ../lib-tcnet/include - EXTRA_INCLUDES+=../lib-gps/include - EXTRA_INCLUDES+=../lib-rgbpanel/include - EXTRA_INCLUDES+=../lib-ws28xx/include - endif - - ifeq ($(findstring NODE_NODE,$(MAKE_FLAGS)), NODE_NODE) - EXTRA_SRCDIR+=src/node - EXTRA_INCLUDES+=../lib-node/include - EXTRA_INCLUDES+=../lib-artnet/include ../lib-rdmdiscovery/include - EXTRA_INCLUDES+=../lib-e131/include - endif - - ifeq ($(findstring NODE_OSC_CLIENT,$(MAKE_FLAGS)), NODE_OSC_CLIENT) - EXTRA_SRCDIR+=src/oscclient - EXTRA_INCLUDES+=../lib-oscclient/include - endif - - ifeq ($(findstring OUTPUT_DMX_SEND,$(MAKE_FLAGS)),OUTPUT_DMX_SEND) - EXTRA_SRCDIR+=src/dmx - EXTRA_INCLUDES+=../lib-dmx/include - endif - - ifeq ($(findstring OUTPUT_DMX_PIXEL,$(MAKE_FLAGS)), OUTPUT_DMX_PIXEL) - EXTRA_SRCDIR+=src/pixel - EXTRA_INCLUDES+=../lib-ws28xxdmx/include ../lib-ws28xx/include - endif - - ifeq ($(findstring OUTPUT_DMX_SHOWFILE,$(MAKE_FLAGS)), OUTPUT_DMX_SHOWFILE) - EXTRA_SRCDIR+=src/showfile - EXTRA_INCLUDES+=../lib-showfile/include - endif - - ifeq ($(findstring OUTPUT_DMX_SERIAL,$(MAKE_FLAGS)), OUTPUT_DMX_SERIAL) - EXTRA_SRCDIR+=src/dmxserial - EXTRA_INCLUDES+=../lib-dmxserial/include - endif - - ifeq ($(findstring OUTPUT_DMX_STEPPER,$(MAKE_FLAGS)), OUTPUT_DMX_STEPPER) - EXTRA_SRCDIR+=src/stepper - EXTRA_INCLUDES+=../lib-l6470dmx/include ../lib-l6470/include - endif - - ifeq ($(findstring OUTPUT_DMX_TLC59711,$(MAKE_FLAGS)), OUTPUT_DMX_TLC59711) - EXTRA_SRCDIR+=src/tlc59711 - EXTRA_INCLUDES+=../lib-tlc59711dmx/include ../lib-tlc59711/include - endif - - ifeq ($(findstring RDM_CONTROLLER,$(MAKE_FLAGS)), RDM_CONTROLLER) - ifdef RDM - else - EXTRA_SRCDIR+=src/rdm - RDM=1 - endif - endif - - ifeq ($(findstring RDM_RESPONDER,$(MAKE_FLAGS)), RDM_RESPONDER) - ifdef RDM - else - EXTRA_SRCDIR+=src/rdm - RDM=1 - endif - EXTRA_INCLUDES+=../lib-rdmresponder/include - endif - - ifeq ($(findstring NODE_RDMNET_LLRP_ONLY,$(MAKE_FLAGS)), NODE_RDMNET_LLRP_ONLY) - ifdef RDM - else - EXTRA_SRCDIR+=src/rdm - RDM=1 - endif - EXTRA_INCLUDES+=../lib-rdm/include ../lib-rdmsensor/include ../lib-rdmsubdevice/include - endif - - ifeq ($(findstring WIDGET_HAVE_FLASHROM,$(MAKE_FLAGS)), WIDGET_HAVE_FLASHROM) - EXTRA_SRCDIR+=src/widget - EXTRA_INCLUDES+=../lib-widget/include - endif else - EXTRA_SRCDIR+=src/artnet - EXTRA_INCLUDES+=../lib-artnet/include - EXTRA_SRCDIR+=src/e131 - EXTRA_INCLUDES+=../lib-e131/include - EXTRA_SRCDIR+=src/node - EXTRA_INCLUDES+=../lib-node/include ../lib-rdmdiscovery/include - EXTRA_SRCDIR+=src/ltc - EXTRA_INCLUDES+=../lib-ltc/include ../lib-tcnet/include - EXTRA_INCLUDES+=../lib-gps/include - EXTRA_INCLUDES+=../lib-rgbpanel/include - EXTRA_INCLUDES+=../lib-ws28xx/include - EXTRA_SRCDIR+=src/rdm - EXTRA_INCLUDES+=../lib-rdm/include ../lib-rdmsensor/include ../lib-rdmsubdevice/include - EXTRA_SRCDIR+=src/stepper - EXTRA_INCLUDES+=../lib-l6470dmx/include ../lib-l6470/include - EXTRA_INCLUDES+=../lib-tlc59711dmx/include ../lib-tlc59711/include - - DEFINES+=ARTNET_VERSION=4 - DEFINES+=LIGHTSET_PORTS=4 - DEFINES+=CONFIG_PIXELDMX_MAX_PORTS=8 - DEFINES+=CONFIG_DDPDISPLAY_MAX_PORTS=8 + EXTRA_SRCDIR+=device/file + EXTRA_SRCDIR+=device/i2c + EXTRA_SRCDIR+=device/ram + EXTRA_SRCDIR+=device/rom + EXTRA_SRCDIR+=device/spi endif - -EXTRA_INCLUDES+=../lib-displayudf/include ../lib-display/include -EXTRA_INCLUDES+=../lib-dmxsend/include -EXTRA_INCLUDES+=../lib-dmxmonitor/include -EXTRA_INCLUDES+=../lib-dmxreceiver/include ../lib-dmx/include -EXTRA_INCLUDES+=../lib-oscserver/include -EXTRA_INCLUDES+=../lib-rdm/include ../lib-rdmsensor/include ../lib-rdmsubdevice/include -EXTRA_INCLUDES+=../lib-spiflashinstall/include -EXTRA_INCLUDES+=../lib-device/include -EXTRA_INCLUDES+=../lib-midi/include \ No newline at end of file diff --git a/lib-configstore/device/rom/storedevice.cpp b/lib-configstore/device/rom/storedevice.cpp old mode 100644 new mode 100755 index d9be65d9..f06bad45 --- a/lib-configstore/device/rom/storedevice.cpp +++ b/lib-configstore/device/rom/storedevice.cpp @@ -26,8 +26,7 @@ #include #include -#include "storedevice.h" - +#include "configstoredevice.h" #include "flashcode.h" #include "debug.h" diff --git a/lib-configstore/device/spi/storedevice.cpp b/lib-configstore/device/spi/storedevice.cpp old mode 100644 new mode 100755 index 4f3cb7f5..cb3078f6 --- a/lib-configstore/device/spi/storedevice.cpp +++ b/lib-configstore/device/spi/storedevice.cpp @@ -2,7 +2,7 @@ * @file storedevice.cpp * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,8 +26,9 @@ #include #include -#include "storedevice.h" +#include "configstoredevice.h" #include "spi/spi_flash.h" + #include "debug.h" StoreDevice::StoreDevice() { @@ -38,9 +39,9 @@ StoreDevice::StoreDevice() { } else { printf("StoreDevice: Detected %s with sector size %u total %u bytes [%u kB]\n", spi_flash_get_name(), - spi_flash_get_sector_size(), - spi_flash_get_size(), - spi_flash_get_size() / 1024U); + static_cast(spi_flash_get_sector_size()), + static_cast(spi_flash_get_size()), + static_cast(spi_flash_get_size() / 1024U)); m_IsDetected = true; } diff --git a/lib-configstore/include/configstore.h b/lib-configstore/include/configstore.h index 73b23ae1..bb69861c 100644 --- a/lib-configstore/include/configstore.h +++ b/lib-configstore/include/configstore.h @@ -2,7 +2,7 @@ * @file configstore.h * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,8 +27,14 @@ #define CONFIGSTORE_H_ #include +#include +#include -#include "storedevice.h" +#include "configstoredevice.h" + +#include "utc.h" + +#include "debug.h" namespace configstore { enum class Store { @@ -58,13 +64,13 @@ enum class Store { GPS, RGBPANEL, NODE, + PCA9685, LAST }; enum class State { IDLE, CHANGED, CHANGED_WAITING, ERASING, ERASED, ERASED_WAITING, WRITING }; - } // namespace configstore class ConfigStore: StoreDevice { @@ -75,18 +81,19 @@ class ConfigStore: StoreDevice { ; } - bool HaveFlashChip() const { - return s_bHaveFlashChip; - } - void Update(configstore::Store store, uint32_t nOffset, const void *pData, uint32_t nDataLength, uint32_t nSetList = 0, uint32_t nOffsetSetList = 0); void Update(configstore::Store store, const void *pData, uint32_t nDataLength) { Update(store, 0, pData, nDataLength); } - void Copy(const configstore::Store store, void *pData, uint32_t nDataLength, uint32_t nOffset = 0); + void Copy(const configstore::Store store, void *pData, uint32_t nDataLength, uint32_t nOffset = 0, const bool doUpdate = true); void ResetSetList(configstore::Store store); + void ResetSetListAll() { + for (uint32_t i = 0; i < static_cast(configstore::Store::LAST); i++) { + ResetSetList(static_cast(i)); + } + } bool Flash(); @@ -94,6 +101,53 @@ class ConfigStore: StoreDevice { void Delay(); + /* + * Environment + */ + + bool SetEnvUtcOffset(const int8_t nHours, const uint8_t nMinutes) { + int32_t nUtcOffset; + + DEBUG_PRINTF("nHours=%d, nMinutes =%u", nHours, nMinutes); + + if (hal::utc_validate(nHours, nMinutes, nUtcOffset)) { + auto *p = reinterpret_cast(&s_SpiFlashData[FlashStore::SIGNATURE_SIZE]); + + if (p->nUtcOffset != nUtcOffset) { + p->nUtcOffset = nUtcOffset; + s_State = configstore::State::CHANGED; + } + + DEBUG_EXIT + return true; + } + + DEBUG_EXIT + return false; + } + + void GetEnvUtcOffset(int8_t& nHours, uint8_t& nMinutes) { + const auto *p = reinterpret_cast(&s_SpiFlashData[FlashStore::SIGNATURE_SIZE]); + + DEBUG_PRINTF("p->nUtcOffset=%d", p->nUtcOffset); + + assert((p->nUtcOffset / 3600) <= INT8_MAX); + assert((p->nUtcOffset / 3600) >= INT8_MIN); + + nHours = static_cast(p->nUtcOffset / 3600); + + if (nHours > 0) { + nMinutes = static_cast(static_cast(p->nUtcOffset - (nHours * 3600)) / 60U); + } else { + nMinutes = static_cast(static_cast((nHours * 3600) - p->nUtcOffset) / 60U); + } + } + + int32_t GetEnvUtcOffset() const { + const auto *p = reinterpret_cast(&s_SpiFlashData[FlashStore::SIGNATURE_SIZE]); + return p->nUtcOffset; + } + static ConfigStore *Get() { return s_pThis; } @@ -102,10 +156,20 @@ class ConfigStore: StoreDevice { uint32_t GetStoreOffset(configstore::Store tStore); private: + struct Env { + int32_t nUtcOffset; + uint8_t filler[12]; + }; + struct FlashStore { - static constexpr auto SIZE = 4096U; + static constexpr uint32_t SIGNATURE_SIZE = 16; + static constexpr uint32_t ENV_SIZE = 16; + static constexpr uint32_t OFFSET_STORES = SIGNATURE_SIZE + ENV_SIZE; + static constexpr uint32_t SIZE = 4096; }; + static_assert(sizeof(struct Env) == FlashStore::ENV_SIZE, ""); + static bool s_bHaveFlashChip; static configstore::State s_State; diff --git a/lib-configstore/include/storedevice.h b/lib-configstore/include/configstoredevice.h old mode 100644 new mode 100755 similarity index 100% rename from lib-configstore/include/storedevice.h rename to lib-configstore/include/configstoredevice.h diff --git a/lib-configstore/include/envparams.h b/lib-configstore/include/envparams.h new file mode 100755 index 00000000..63333890 --- /dev/null +++ b/lib-configstore/include/envparams.h @@ -0,0 +1,48 @@ +/** + * @file envparams.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef ENVPARAMS_H_ +#define ENVPARAMS_H_ + +#include + +class EnvParams { +public: + EnvParams(); + + void LoadAndSet(); + void LoadAndSet(const char *pBuffer, uint32_t nLength); + + void Builder(char *pBuffer, uint32_t nLength, uint32_t& nSize); + +public: + static void staticCallbackFunction(void *p, const char *s); + +private: + void Dump(); + void callbackFunction(const char *s); +}; + +#endif /* ENVPARAMS_H_ */ diff --git a/lib-configstore/include/envparamsconst.h b/lib-configstore/include/envparamsconst.h new file mode 100755 index 00000000..dcc2ea25 --- /dev/null +++ b/lib-configstore/include/envparamsconst.h @@ -0,0 +1,35 @@ +/** + * @file envparamsconst.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef ENVPARAMSCONST_H_ +#define ENVPARAMSCONST_H_ + +struct EnvParamsConst { + static const char FILE_NAME[]; + + static const char UTC_OFFSET[]; +}; + +#endif /* ENVPARAMSCONST_H_ */ diff --git a/lib-configstore/include/storeartnet.h b/lib-configstore/include/storeartnet.h deleted file mode 100644 index ab90a6ba..00000000 --- a/lib-configstore/include/storeartnet.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * @file storeartnet.h - * - */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef STOREARTNET_H_ -#define STOREARTNET_H_ - -#include "artnetparams.h" -#include "artnetstore.h" -#include "configstore.h" - -#include "debug.h" - -class StoreArtNet final: public ArtNetParamsStore, public ArtNetStore { -public: - StoreArtNet(uint32_t nPortIndexOffset); - - void Update(const struct artnetparams::Params* pArtNetParams) override { - DEBUG_ENTRY - - ConfigStore::Get()->Update(configstore::Store::NODE, pArtNetParams, sizeof(struct artnetparams::Params)); - - DEBUG_EXIT - } - - void Copy(struct artnetparams::Params* pArtNetParams) override { - DEBUG_ENTRY - - ConfigStore::Get()->Copy(configstore::Store::NODE, pArtNetParams, sizeof(struct artnetparams::Params)); - - DEBUG_EXIT - } - - void SaveLongName(const char* pLongName) override { - DEBUG_ENTRY - - ConfigStore::Get()->Update(configstore::Store::NODE, __builtin_offsetof(struct artnetparams::Params, aLongName), pLongName, artnet::LONG_NAME_LENGTH, artnetparams::Mask::LONG_NAME); - - DEBUG_EXIT - } - - void SaveFailSafe(const uint8_t nFailSafe) override { - DEBUG_ENTRY - - ConfigStore::Get()->Update(configstore::Store::NODE, __builtin_offsetof(struct artnetparams::Params, nFailSafe), &nFailSafe, sizeof(uint8_t), artnetparams::Mask::FAILSAFE); - - DEBUG_EXIT - } - - void SaveUniverseSwitch(const uint32_t nPortIndex, __attribute__((unused)) const uint8_t nAddress) override { - DEBUG_ENTRY - - SaveUniverse(nPortIndex); - - DEBUG_EXIT - } - - void SaveNetSwitch(const uint32_t nPortIndex, __attribute__((unused)) const uint8_t nAddress) override { - DEBUG_ENTRY - - SaveUniverse(nPortIndex); - - DEBUG_EXIT - } - - void SaveSubnetSwitch(const uint32_t nPortIndex, __attribute__((unused)) const uint8_t nAddress) override { - DEBUG_ENTRY - - SaveUniverse(nPortIndex); - - DEBUG_EXIT - } - - void SaveShortName(uint32_t nPortIndex, const char *pShortName) override; - void SaveMergeMode(uint32_t nPortIndex, const lightset::MergeMode tMerge) override; - void SavePortProtocol(uint32_t nPortIndex, const artnet::PortProtocol tPortProtocol) override; - void SaveOutputStyle(uint32_t nPortIndex, const lightset::OutputStyle outputStyle) override; - void SaveRdmEnabled(uint32_t nPortIndex, bool isEnabled) override; - - static StoreArtNet *Get() { - return s_pThis; - } - -private: - void SaveUniverse(uint32_t nPortIndex); - -private: - static uint32_t s_nPortIndexOffset; - static StoreArtNet *s_pThis; -}; - -#endif /* STOREARTNET_H_ */ diff --git a/lib-configstore/include/storedisplayudf.h b/lib-configstore/include/storedisplayudf.h deleted file mode 100644 index 51241259..00000000 --- a/lib-configstore/include/storedisplayudf.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @file storedisplayudf.h - * - */ -/* Copyright (C) 2019-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef STOREDISPLAYUDF_H_ -#define STOREDISPLAYUDF_H_ - -#include "displayudfparams.h" - -#include "configstore.h" - -class StoreDisplayUdf final: public DisplayUdfParamsStore { -public: - StoreDisplayUdf(); - - void Update(const struct displayudfparams::Params *pDisplayUdfParams) override { - ConfigStore::Get()->Update(configstore::Store::DISPLAYUDF, pDisplayUdfParams, sizeof(struct displayudfparams::Params)); - } - - void Copy(struct displayudfparams::Params *pDisplayUdfParams) override { - ConfigStore::Get()->Copy(configstore::Store::DISPLAYUDF, pDisplayUdfParams, sizeof(struct displayudfparams::Params)); - } - - static StoreDisplayUdf *Get() { - return s_pThis; - } - -private: - static StoreDisplayUdf *s_pThis; -}; - -#endif /* STOREDISPLAYUDF_H_ */ diff --git a/lib-configstore/include/storedmxsend.h b/lib-configstore/include/storedmxsend.h deleted file mode 100644 index 778db640..00000000 --- a/lib-configstore/include/storedmxsend.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @file storedmxsend.h - * - */ -/* Copyright (C) 2018-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef STOREDMXSEND_H_ -#define STOREDMXSEND_H_ - -#include "dmxparams.h" - -#include "configstore.h" - -class StoreDmxSend final: public DmxParamsStore { -public: - StoreDmxSend(); - - void Update(const struct TDmxParams *pDmxParams) override { - ConfigStore::Get()->Update(configstore::Store::DMXSEND, pDmxParams, sizeof(struct TDmxParams)); - } - - void Copy(struct TDmxParams *pDmxParams) override { - ConfigStore::Get()->Copy(configstore::Store::DMXSEND, pDmxParams, sizeof(struct TDmxParams)); - } - - static StoreDmxSend *Get() { - return s_pThis; - } - -private: - static StoreDmxSend *s_pThis; -}; - -#endif /* STOREDMXSEND_H_ */ diff --git a/lib-configstore/include/storee131.h b/lib-configstore/include/storee131.h deleted file mode 100644 index dcfb131e..00000000 --- a/lib-configstore/include/storee131.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @file storee131.h - * - */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef STOREE131_H_ -#define STOREE131_H_ - -#include "e131params.h" -#include "configstore.h" - -class StoreE131 final: public E131ParamsStore { -public: - StoreE131(); - - void Update(const struct e131params::Params *pParams) override { - ConfigStore::Get()->Update(configstore::Store::NODE, pParams, sizeof(struct e131params::Params)); - } - - void Copy(struct e131params::Params *pParams) override { - ConfigStore::Get()->Copy(configstore::Store::NODE, pParams, sizeof(struct e131params::Params)); - } - - static StoreE131* Get() { - return s_pThis; - } - -private: - static StoreE131 *s_pThis; -}; - -#endif /* STOREE131_H_ */ diff --git a/lib-configstore/include/storenetwork.h b/lib-configstore/include/storenetwork.h deleted file mode 100644 index 427c05b5..00000000 --- a/lib-configstore/include/storenetwork.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @file storenetwork.h - * - */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef STORENETWORK_H_ -#define STORENETWORK_H_ - -#include - -#include "network.h" -#include "networkparams.h" -#include "configstore.h" - -class StoreNetwork final: public NetworkParamsStore, public NetworkStore { -public: - StoreNetwork(); - - void Update(const struct networkparams::Params *pNetworkParams) override { - ConfigStore::Get()->Update(configstore::Store::NETWORK, pNetworkParams, sizeof(struct networkparams::Params)); - } - - void Copy(struct networkparams::Params *pNetworkParams) override { - ConfigStore::Get()->Copy(configstore::Store::NETWORK, pNetworkParams, sizeof(struct networkparams::Params)); - } - - void SaveIp(uint32_t nIp) override { - ConfigStore::Get()->Update(configstore::Store::NETWORK, __builtin_offsetof(struct networkparams::Params, nLocalIp), &nIp, sizeof(uint32_t), networkparams::Mask::IP_ADDRESS); - } - - void SaveNetMask(uint32_t nNetMask) override { - ConfigStore::Get()->Update(configstore::Store::NETWORK, __builtin_offsetof(struct networkparams::Params, nNetmask), &nNetMask, sizeof(uint32_t), networkparams::Mask::NET_MASK); - } - - void SaveGatewayIp(uint32_t nGatewayIp) override { - ConfigStore::Get()->Update(configstore::Store::NETWORK, __builtin_offsetof(struct networkparams::Params, nGatewayIp), &nGatewayIp, sizeof(uint32_t), networkparams::Mask::DEFAULT_GATEWAY); - } - - void SaveHostName(const char *pHostName, uint32_t nLength) override { - nLength = std::min(nLength,static_cast(network::HOSTNAME_SIZE)); - ConfigStore::Get()->Update(configstore::Store::NETWORK, __builtin_offsetof(struct networkparams::Params, aHostName), pHostName, nLength, networkparams::Mask::HOSTNAME); - } - - void SaveDhcp(bool bIsDhcpUsed) override { - ConfigStore::Get()->Update(configstore::Store::NETWORK, __builtin_offsetof(struct networkparams::Params, bIsDhcpUsed), &bIsDhcpUsed, sizeof(bool), networkparams::Mask::DHCP); - } - - static StoreNetwork *Get() { - return s_pThis; - } - -private: - static StoreNetwork *s_pThis; -}; - -#endif /* STORENETWORK_H_ */ diff --git a/lib-configstore/include/storepixeldmx.h b/lib-configstore/include/storepixeldmx.h deleted file mode 100644 index 653e6fc1..00000000 --- a/lib-configstore/include/storepixeldmx.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @file storepixeldmx.h - * - */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef STOREPIXELDMX_H_ -#define STOREPIXELDMX_H_ - -#include -#include -#include - -#include "pixeldmxstore.h" -#include "configstore.h" - -class StorePixelDmx final: public PixelDmxParamsStore, public PixelDmxStore { -public: - StorePixelDmx(); - - void Update(const struct pixeldmxparams::Params *pWS28xxDmxParams) override { - ConfigStore::Get()->Update(configstore::Store::WS28XXDMX, pWS28xxDmxParams, sizeof(struct pixeldmxparams::Params)); - } - - void Copy(struct pixeldmxparams::Params *pWS28xxDmxParams) override { - ConfigStore::Get()->Copy(configstore::Store::WS28XXDMX, pWS28xxDmxParams, sizeof(struct pixeldmxparams::Params)); - } - - void SaveType(uint8_t nType) override { - ConfigStore::Get()->Update(configstore::Store::WS28XXDMX, __builtin_offsetof(struct pixeldmxparams::Params, nType), &nType, sizeof(uint8_t), pixeldmxparams::Mask::TYPE); - } - - void SaveCount(uint16_t nCount) override { - ConfigStore::Get()->Update(configstore::Store::WS28XXDMX, __builtin_offsetof(struct pixeldmxparams::Params, nCount), &nCount, sizeof(uint16_t), pixeldmxparams::Mask::COUNT); - } - - void SaveGroupingCount(uint16_t nGroupingCount) override { - ConfigStore::Get()->Update(configstore::Store::WS28XXDMX, __builtin_offsetof(struct pixeldmxparams::Params, nGroupingCount), &nGroupingCount, sizeof(uint16_t), pixeldmxparams::Mask::GROUPING_COUNT); - } - - void SaveMap(uint8_t nMap) override { - ConfigStore::Get()->Update(configstore::Store::WS28XXDMX, __builtin_offsetof(struct pixeldmxparams::Params, nMap), &nMap, sizeof(uint8_t), pixeldmxparams::Mask::MAP); - } - - void SaveTestPattern(uint8_t nTestPattern) override { - ConfigStore::Get()->Update(configstore::Store::WS28XXDMX, __builtin_offsetof(struct pixeldmxparams::Params, nTestPattern), &nTestPattern, sizeof(uint8_t), pixeldmxparams::Mask::TEST_PATTERN); - } - - void SaveDmxStartAddress(uint16_t nDmxStartAddress) override { - ConfigStore::Get()->Update(configstore::Store::WS28XXDMX, __builtin_offsetof(struct pixeldmxparams::Params, nDmxStartAddress), &nDmxStartAddress, sizeof(uint16_t), pixeldmxparams::Mask::DMX_START_ADDRESS); - } - - static StorePixelDmx *Get() { - return s_pThis; - } - -private: - static StorePixelDmx *s_pThis; -}; - -#endif /* STOREPIXELDMX_H_ */ diff --git a/lib-configstore/include/storerdmdevice.h b/lib-configstore/include/storerdmdevice.h deleted file mode 100644 index 59269875..00000000 --- a/lib-configstore/include/storerdmdevice.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @file storerdmdevice.h - * - */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef STORERDMDEVICE_H_ -#define STORERDMDEVICE_H_ - -#include - -#include "rdmdeviceparams.h" -#include "rdmdevicestore.h" - -#include "configstore.h" - -class StoreRDMDevice final: public RDMDeviceParamsStore, public RDMDeviceStore { -public: - StoreRDMDevice(); - - void Update(const struct rdm::deviceparams::Params *pParams) override { - ConfigStore::Get()->Update(configstore::Store::RDMDEVICE, pParams, sizeof(struct rdm::deviceparams::Params)); - } - - void Copy(struct rdm::deviceparams::Params *pRDMDeviceParams) override { - ConfigStore::Get()->Copy(configstore::Store::RDMDEVICE, pRDMDeviceParams, sizeof(struct rdm::deviceparams::Params)); - } - - void SaveLabel(const char *pLabel, uint8_t nLength) override { - ConfigStore::Get()->Update(configstore::Store::RDMDEVICE, __builtin_offsetof(struct rdm::deviceparams::Params, aDeviceRootLabel), pLabel, nLength, rdm::deviceparams::Mask::LABEL); - ConfigStore::Get()->Update(configstore::Store::RDMDEVICE, __builtin_offsetof(struct rdm::deviceparams::Params, nDeviceRootLabelLength), &nLength, sizeof(uint8_t), rdm::deviceparams::Mask::LABEL); - } - - static StoreRDMDevice *Get() { - return s_pThis; - } - -private: - static StoreRDMDevice *s_pThis; -}; - -#endif /* STORERDMDEVICE_H_ */ diff --git a/lib-configstore/include/storerdmsensors.h b/lib-configstore/include/storerdmsensors.h deleted file mode 100644 index d3b36a08..00000000 --- a/lib-configstore/include/storerdmsensors.h +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @file storerdmsensors.h - * - */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef STORERDMSENSORS_H_ -#define STORERDMSENSORS_H_ - -#include -#include - -#include "rdmsensorsparams.h" -#include "rdmsensorstore.h" -#include "rdmsensors.h" - -#include "configstore.h" - -#include "debug.h" //FIXME Remove - -class StoreRDMSensors final: public RDMSensorsParamsStore, public RDMSensorStore { -public: - StoreRDMSensors(); - - void Update(const rdm::sensorsparams::Params *pParams) override { - ConfigStore::Get()->Update(configstore::Store::RDMSENSORS, pParams, sizeof(struct rdm::sensorsparams::Params)); - } - - void Copy(rdm::sensorsparams::Params *pParams) override { - ConfigStore::Get()->Copy(configstore::Store::RDMSENSORS, pParams, sizeof(struct rdm::sensorsparams::Params)); - } - - void SaveCalibration(uint32_t nSensor, int32_t nCalibration) override { - assert(nSensor < rdm::sensors::MAX); - DEBUG_PRINTF("nSensor=%u, nCalibration=%d", nSensor, nCalibration); - auto c = static_cast(nCalibration); - ConfigStore::Get()->Update(configstore::Store::RDMSENSORS, (nSensor * sizeof(int16_t)) + __builtin_offsetof(struct rdm::sensorsparams::Params, nCalibrate), &c, sizeof(int16_t)); - } - - static StoreRDMSensors *Get() { - return s_pThis; - } - -private: - static StoreRDMSensors *s_pThis; -}; - -#endif /* STORERDMSENSORS_H_ */ diff --git a/lib-configstore/include/storeremoteconfig.h b/lib-configstore/include/storeremoteconfig.h deleted file mode 100644 index 46360d40..00000000 --- a/lib-configstore/include/storeremoteconfig.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @file storeremoteconfig.h - * - */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef STOREREMOTECONFIG_H_ -#define STOREREMOTECONFIG_H_ - -#include "remoteconfigparams.h" - -#include "configstore.h" - -class StoreRemoteConfig final: public RemoteConfigParamsStore { -public: - StoreRemoteConfig(); - - void Update(const struct TRemoteConfigParams *pRemoteConfigParams) override { - ConfigStore::Get()->Update(configstore::Store::RCONFIG, pRemoteConfigParams, sizeof(struct TRemoteConfigParams)); - } - - void Copy(struct TRemoteConfigParams *pRemoteConfigParams) override { - ConfigStore::Get()->Copy(configstore::Store::RCONFIG, pRemoteConfigParams, sizeof(struct TRemoteConfigParams)); - } - - static StoreRemoteConfig *Get() { - return s_pThis; - } - -private: - static StoreRemoteConfig *s_pThis; -}; - -#endif /* STOREREMOTECONFIG_H_ */ diff --git a/lib-configstore/include/storetlc59711.h b/lib-configstore/include/storetlc59711.h deleted file mode 100644 index e96e036a..00000000 --- a/lib-configstore/include/storetlc59711.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file storetlc59711.h - * - */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef STORETLC59711_H_ -#define STORETLC59711_H_ - -#include - -#include "tlc59711dmxparams.h" -#include "tlc59711dmxstore.h" - -#include "configstore.h" - -class StoreTLC59711 final: public TLC59711DmxParamsStore, public TLC59711DmxStore { -public: - StoreTLC59711(); - - void Update(const struct TTLC59711DmxParams *pTLC59711DmxParams) override { - ConfigStore::Get()->Update(configstore::Store::TLC5711DMX, pTLC59711DmxParams, sizeof(struct TTLC59711DmxParams)); - } - - void Copy(struct TTLC59711DmxParams *pTLC59711DmxParams) override { - ConfigStore::Get()->Copy(configstore::Store::TLC5711DMX, pTLC59711DmxParams, sizeof(struct TTLC59711DmxParams)); - } - - void SaveDmxStartAddress(uint16_t nDmxStartAddress) override { - ConfigStore::Get()->Update(configstore::Store::TLC5711DMX, __builtin_offsetof(struct TTLC59711DmxParams, nDmxStartAddress), &nDmxStartAddress, sizeof(uint32_t), TLC59711DmxParamsMask::START_ADDRESS); - } - - static StoreTLC59711 *Get() { - return s_pThis; - } - -private: - static StoreTLC59711 *s_pThis; -}; - -#endif /* STORETLC59711_H_ */ diff --git a/lib-configstore/src/artnet/storeartnet.cpp b/lib-configstore/src/artnet/storeartnet.cpp deleted file mode 100644 index f26d8ea9..00000000 --- a/lib-configstore/src/artnet/storeartnet.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/** - * @file storeartnet.cpp - * - */ -/** - * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. - */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "storeartnet.h" - -#include "artnetstore.h" -#include "artnetparams.h" -#include "artnet.h" -#include "artnetnode.h" - -#include "configstore.h" - -#include "debug.h" - -#define UNUSED __attribute__((unused)) - -uint32_t StoreArtNet::s_nPortIndexOffset; -StoreArtNet *StoreArtNet::s_pThis; - -StoreArtNet::StoreArtNet(uint32_t nPortIndexOffset) { - DEBUG_ENTRY - DEBUG_PRINTF("nPortIndexOffset=%u", nPortIndexOffset); - - assert(s_pThis == nullptr); - s_pThis = this; - - s_nPortIndexOffset = nPortIndexOffset; - - DEBUG_PRINTF("%p", reinterpret_cast(s_pThis)); - DEBUG_EXIT -} - -void StoreArtNet::SaveShortName(uint32_t nPortIndex, const char *pShortName) { - DEBUG_ENTRY - DEBUG_PRINTF("%u, %s", nPortIndex, pShortName); - - if (nPortIndex >= s_nPortIndexOffset) { - nPortIndex -= s_nPortIndexOffset; - } else { - DEBUG_EXIT - return; - } - - DEBUG_PRINTF("nPortIndex=%u", nPortIndex); - - if (nPortIndex >= artnet::PORTS) { - DEBUG_EXIT - return; - } - - ConfigStore::Get()->Update(configstore::Store::NODE, (artnet::SHORT_NAME_LENGTH * nPortIndex) + __builtin_offsetof(struct artnetparams::Params, aLabel), pShortName, artnet::SHORT_NAME_LENGTH, artnetparams::Mask::LABEL_A << nPortIndex); - - DEBUG_EXIT -} - -void StoreArtNet::SaveUniverse(uint32_t nPortIndex) { - DEBUG_ENTRY - DEBUG_PRINTF("s_nPortIndexOffset=%u, nPortIndex=%u", s_nPortIndexOffset, nPortIndex); - - if (nPortIndex >= s_nPortIndexOffset) { - nPortIndex -= s_nPortIndexOffset; - } else { - DEBUG_EXIT - return; - } - - DEBUG_PRINTF("nPortIndex=%u", nPortIndex); - - if (nPortIndex >= artnet::PORTS) { - DEBUG_EXIT - return; - } - - uint16_t nUniverse; - - if (ArtNetNode::Get()->GetPortAddress(nPortIndex, nUniverse)) { - DEBUG_PRINTF("nPortIndex=%u, nUniverse=%u", nPortIndex, nUniverse); - ConfigStore::Get()->Update(configstore::Store::NODE, (sizeof(uint16_t) * nPortIndex) + __builtin_offsetof(struct artnetparams::Params, nUniverse), &nUniverse, sizeof(uint16_t), artnetparams::Mask::UNIVERSE_A << nPortIndex); - } - - DEBUG_EXIT -} - -void StoreArtNet::SaveMergeMode(uint32_t nPortIndex, const lightset::MergeMode mergeMode) { - DEBUG_ENTRY - DEBUG_PRINTF("%u, %u", nPortIndex, static_cast(mergeMode)); - - if (nPortIndex >= s_nPortIndexOffset) { - nPortIndex -= s_nPortIndexOffset; - } else { - DEBUG_EXIT - return; - } - - DEBUG_PRINTF("nPortIndex=%u", nPortIndex); - - if (nPortIndex >= artnet::PORTS) { - DEBUG_EXIT - return; - } - - uint16_t nMergeMode; - ConfigStore::Get()->Copy(configstore::Store::NODE, &nMergeMode, sizeof(uint16_t), __builtin_offsetof(struct artnetparams::Params, nMergeMode)); - - nMergeMode &= artnetparams::mergemode_clear(nPortIndex); - nMergeMode |= artnetparams::mergemode_set(nPortIndex, mergeMode); - - ConfigStore::Get()->Update(configstore::Store::NODE, __builtin_offsetof(struct artnetparams::Params, nMergeMode), &nMergeMode, sizeof(uint16_t)); - - DEBUG_EXIT -} - -void StoreArtNet::SavePortProtocol(uint32_t nPortIndex, const artnet::PortProtocol portProtocol) { - DEBUG_ENTRY - DEBUG_PRINTF("s_nPortIndexOffset=%u, nPortIndex=%u, portProtocol=%u", s_nPortIndexOffset, nPortIndex, static_cast(portProtocol)); - - if (nPortIndex >= s_nPortIndexOffset) { - nPortIndex -= s_nPortIndexOffset; - } else { - DEBUG_EXIT - return; - } - - DEBUG_PRINTF("nPortIndex=%u", nPortIndex); - - if (nPortIndex >= artnet::PORTS) { - DEBUG_EXIT - return; - } - - uint16_t nPortProtocol; - ConfigStore::Get()->Copy(configstore::Store::NODE, &nPortProtocol, sizeof(uint16_t), __builtin_offsetof(struct artnetparams::Params, nProtocol)); - - nPortProtocol &= artnetparams::protocol_clear(nPortIndex); - nPortProtocol |= artnetparams::protocol_set(nPortIndex, portProtocol); - - ConfigStore::Get()->Update(configstore::Store::NODE, __builtin_offsetof(struct artnetparams::Params, nProtocol), &nPortProtocol, sizeof(uint16_t)); - DEBUG_EXIT -} - -void StoreArtNet::SaveOutputStyle(uint32_t nPortIndex, const lightset::OutputStyle outputStyle) { - DEBUG_ENTRY - DEBUG_PRINTF("s_nPortIndexOffset=%u, nPortIndex=%u, outputStyle=%u", s_nPortIndexOffset, nPortIndex, static_cast(outputStyle)); - - if (nPortIndex >= s_nPortIndexOffset) { - nPortIndex -= s_nPortIndexOffset; - } else { - DEBUG_EXIT - return; - } - - DEBUG_PRINTF("nPortIndex=%u", nPortIndex); - - if (nPortIndex >= artnet::PORTS) { - DEBUG_EXIT - return; - } - - uint8_t nOutputStyle; - ConfigStore::Get()->Copy(configstore::Store::NODE, &nOutputStyle, sizeof(uint8_t), __builtin_offsetof(struct artnetparams::Params, nOutputStyle)); - - if (outputStyle == lightset::OutputStyle::CONSTANT) { - nOutputStyle |= static_cast(1U << nPortIndex); - } else { - nOutputStyle &= static_cast(~(1U << nPortIndex)); - } - - ConfigStore::Get()->Update(configstore::Store::NODE, __builtin_offsetof(struct artnetparams::Params, nOutputStyle), &nOutputStyle, sizeof(uint8_t)); - - DEBUG_EXIT -} - -void StoreArtNet::SaveRdmEnabled(uint32_t nPortIndex, const bool isEnabled) { - DEBUG_ENTRY - DEBUG_PRINTF("s_nPortIndexOffset=%u, nPortIndex=%u, isEnabled=%d", s_nPortIndexOffset, nPortIndex, isEnabled); - - if (nPortIndex >= s_nPortIndexOffset) { - nPortIndex -= s_nPortIndexOffset; - } else { - DEBUG_EXIT - return; - } - - DEBUG_PRINTF("nPortIndex=%u", nPortIndex); - - if (nPortIndex >= artnet::PORTS) { - DEBUG_EXIT - return; - } - - uint16_t nRdm; - ConfigStore::Get()->Copy(configstore::Store::NODE, &nRdm, sizeof(uint16_t), __builtin_offsetof(struct artnetparams::Params, nRdm)); - - nRdm &= artnetparams::clear_mask(nPortIndex); - - if (isEnabled) { - nRdm |= artnetparams::shift_left(1, nPortIndex); - nRdm |= static_cast(1U << (nPortIndex + 8)); - } - - ConfigStore::Get()->Update(configstore::Store::NODE, __builtin_offsetof(struct artnetparams::Params, nRdm), &nRdm, sizeof(uint16_t)); - - DEBUG_EXIT -} diff --git a/lib-configstore/src/configstore.cpp b/lib-configstore/src/configstore.cpp old mode 100644 new mode 100755 index 5e325d4a..4b6bbf26 --- a/lib-configstore/src/configstore.cpp +++ b/lib-configstore/src/configstore.cpp @@ -2,7 +2,7 @@ * @file configstore.cpp * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,13 +36,16 @@ #include "debug.h" +namespace global { +extern int32_t *gp_nUtcOffset; +} // namespace global + using namespace configstore; static constexpr uint8_t s_aSignature[] = {'A', 'v', 'V', 0x01}; -static constexpr auto OFFSET_STORES = ((((sizeof(s_aSignature) + 15) / 16) * 16) + 16); // +16 is reserved for future use -static constexpr uint32_t s_aStorSize[static_cast(Store::LAST)] = {96, 32, 64, 64, 32, 32, 480, 64, 32, 96, 48, 32, 944, 48, 64, 32, 96, 32, 1024, 32, 32, 64, 96, 32, 32, 320}; +static constexpr uint32_t s_aStorSize[static_cast(Store::LAST)] = {96, 32, 64, 64, 32, 32, 480, 64, 32, 96, 48, 32, 944, 48, 64, 32, 96, 32, 1024, 32, 32, 64, 96, 32, 32, 320, 32}; #ifndef NDEBUG -static constexpr char s_aStoreName[static_cast(Store::LAST)][16] = {"Network", "DMX", "Pixel", "LTC", "MIDI", "LTC ETC", "OSC Server", "TLC59711", "USB Pro", "RDM Device", "RConfig", "TCNet", "OSC Client", "Display", "LTC Display", "Monitor", "SparkFun", "Slush", "Motors", "Show", "Serial", "RDM Sensors", "RDM SubDevices", "GPS", "RGB Panel", "Node"}; +static constexpr char s_aStoreName[static_cast(Store::LAST)][16] = {"Network", "DMX", "Pixel", "LTC", "MIDI", "LTC ETC", "OSC Server", "TLC59711", "USB Pro", "RDM Device", "RConfig", "TCNet", "OSC Client", "Display", "LTC Display", "Monitor", "SparkFun", "Slush", "Motors", "Show", "Serial", "RDM Sensors", "RDM SubDevices", "GPS", "RGB Panel", "Node", "PCA9685"}; #endif bool ConfigStore::s_bHaveFlashChip; @@ -57,9 +60,13 @@ ConfigStore *ConfigStore::s_pThis; ConfigStore::ConfigStore() { DEBUG_ENTRY + static_assert(sizeof(s_aSignature) <= FlashStore::SIGNATURE_SIZE); + assert(s_pThis == nullptr); s_pThis = this; + global::gp_nUtcOffset = reinterpret_cast(&s_SpiFlashData[FlashStore::SIGNATURE_SIZE]); + s_bHaveFlashChip = StoreDevice::IsDetected(); assert(FlashStore::SIZE <= StoreDevice::GetSize()); @@ -94,20 +101,32 @@ ConfigStore::ConfigStore() { if (!bSignatureOK) { DEBUG_PUTS("No signature"); - memset(&s_SpiFlashData[OFFSET_STORES], 0, FlashStore::SIZE - OFFSET_STORES); + memset(&s_SpiFlashData[FlashStore::SIGNATURE_SIZE], 0, FlashStore::SIZE - FlashStore::SIGNATURE_SIZE); s_State = State::CHANGED; } - s_nSpiFlashStoreSize = OFFSET_STORES; + s_nSpiFlashStoreSize = FlashStore::OFFSET_STORES; for (uint32_t j = 0; j < static_cast(Store::LAST); j++) { s_nSpiFlashStoreSize += s_aStorSize[j]; } - DEBUG_PRINTF("OFFSET_STORES=%d, m_nSpiFlashStoreSize=%d", static_cast(OFFSET_STORES), s_nSpiFlashStoreSize); + DEBUG_PRINTF("FlashStore::OFFSET_STORES=%d, m_nSpiFlashStoreSize=%d", static_cast(FlashStore::OFFSET_STORES), s_nSpiFlashStoreSize); assert(s_nSpiFlashStoreSize <= FlashStore::SIZE); + for (uint32_t nStore = 0; nStore < static_cast(Store::LAST); nStore++) { + auto *pSet = reinterpret_cast((&s_SpiFlashData[GetStoreOffset(static_cast(nStore))])); + if (*pSet == UINT32_MAX) { + *pSet = 0; + } + } + + auto *p = reinterpret_cast(&s_SpiFlashData[FlashStore::SIGNATURE_SIZE]); + if (p->nUtcOffset == -1) { + p->nUtcOffset = 0; + } + DEBUG_PUTS(""); debug_dump(s_SpiFlashData, FlashStore::SIZE); @@ -117,7 +136,7 @@ ConfigStore::ConfigStore() { uint32_t ConfigStore::GetStoreOffset(Store store) { assert(store < Store::LAST); - uint32_t nOffset = OFFSET_STORES; + uint32_t nOffset = FlashStore::OFFSET_STORES; for (uint32_t i = 0; i < static_cast(store); i++) { nOffset += s_aStorSize[i]; @@ -171,9 +190,8 @@ void ConfigStore::Update(Store store, uint32_t nOffset, const void *pData, uint3 pSrc++; } - if ((0 != nOffset) && (bIsChanged) && (nSetList != 0)) { - auto *pSet = reinterpret_cast((&s_SpiFlashData[GetStoreOffset(store)] + nOffsetSetList)); - + if (bIsChanged){ + auto *pSet = reinterpret_cast((&s_SpiFlashData[GetStoreOffset(store)] + nOffsetSetList)); *pSet |= nSetList; } @@ -181,12 +199,13 @@ void ConfigStore::Update(Store store, uint32_t nOffset, const void *pData, uint3 s_State = State::CHANGED; } + debug_dump(&s_SpiFlashData[GetStoreOffset(store)] + nOffsetSetList, 8); DEBUG_EXIT } -void ConfigStore::Copy(const Store store, void *pData, uint32_t nDataLength, uint32_t nOffset) { +void ConfigStore::Copy(const Store store, void *pData, uint32_t nDataLength, uint32_t nOffset, const bool doUpdate) { DEBUG_ENTRY - DEBUG_PRINTF("[%s]:%u pData=%p, nDataLength=%u, nOffset=%u", s_aStoreName[static_cast(store)], static_cast(store), pData, nDataLength, nOffset); + DEBUG_PRINTF("[%s]:%u pData=%p, nDataLength=%u, nOffset=%u, doUpdate=%u", s_aStoreName[static_cast(store)], static_cast(store), pData, nDataLength, nOffset, doUpdate); assert(store < Store::LAST); assert(pData != nullptr); @@ -210,7 +229,9 @@ void ConfigStore::Copy(const Store store, void *pData, uint32_t nDataLength, uin return; } - Update(store, pData, nDataLength); + if (doUpdate) { + Update(store, pData, nDataLength); + } DEBUG_EXIT } @@ -293,8 +314,8 @@ void ConfigStore::Dump() { Hardware::Get()->WatchdogStop(); } - debug_dump(s_SpiFlashData, OFFSET_STORES); - printf("\n"); + debug_dump(s_SpiFlashData, FlashStore::OFFSET_STORES); + puts(""); for (uint32_t j = 0; j < static_cast(Store::LAST); j++) { printf("Store [%s]:%d\n", s_aStoreName[j], j); @@ -302,7 +323,7 @@ void ConfigStore::Dump() { auto *p = &s_SpiFlashData[GetStoreOffset(static_cast(j))]; debug_dump(p, static_cast(s_aStorSize[j])); - printf("\n"); + puts(""); } if (IsWatchDog) { diff --git a/lib-configstore/src/envparams.cpp b/lib-configstore/src/envparams.cpp new file mode 100755 index 00000000..cead222f --- /dev/null +++ b/lib-configstore/src/envparams.cpp @@ -0,0 +1,132 @@ +/** + * @file envparams.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if !defined(__clang__) // Needed for compiling on MacOS +# pragma GCC push_options +# pragma GCC optimize ("Os") +#endif + +#include +#include +#include + +#include "envparams.h" +#include "envparamsconst.h" + +#include "readconfigfile.h" +#include "sscan.h" + +#include "propertiesbuilder.h" + +#include "configstore.h" + +#include "debug.h" + +EnvParams::EnvParams() { + DEBUG_ENTRY + + DEBUG_EXIT +} + +void EnvParams::LoadAndSet() { + DEBUG_ENTRY + + assert(ConfigStore::Get() != nullptr); + +#if !defined(DISABLE_FS) + ReadConfigFile configfile(EnvParams::staticCallbackFunction, this); + configfile.Read(EnvParamsConst::FILE_NAME); +#endif + +#ifndef NDEBUG + Dump(); +#endif + + DEBUG_EXIT +} + +void EnvParams::LoadAndSet(const char *pBuffer, uint32_t nLength) { + DEBUG_ENTRY + + assert(ConfigStore::Get() != nullptr); + + assert(pBuffer != nullptr); + assert(nLength != 0); + + ReadConfigFile config(EnvParams::staticCallbackFunction, this); + config.Read(pBuffer, nLength); + +#ifndef NDEBUG + Dump(); +#endif + DEBUG_EXIT +} + +void EnvParams::callbackFunction(const char *pLine) { + assert(pLine != nullptr); + + int8_t nHours; + uint8_t nMinutes; + + if (Sscan::UtcOffset(pLine, EnvParamsConst::UTC_OFFSET, nHours, nMinutes) == Sscan::OK) { + ConfigStore::Get()->SetEnvUtcOffset(nHours, nMinutes); + return; + } +} + +void EnvParams::staticCallbackFunction(void *p, const char *s) { + assert(p != nullptr); + assert(s != nullptr); + + (static_cast(p))->callbackFunction(s); +} + +void EnvParams::Builder(char *pBuffer, uint32_t nLength, uint32_t& nSize) { + DEBUG_ENTRY + + assert(pBuffer != nullptr); + + PropertiesBuilder builder(EnvParamsConst::FILE_NAME, pBuffer, nLength); + + int8_t nHours; + uint8_t nMinutes; + ConfigStore::Get()->GetEnvUtcOffset(nHours, nMinutes); + builder.AddUtcOffset(EnvParamsConst::UTC_OFFSET, nHours, nMinutes); + + nSize = builder.GetSize(); + + DEBUG_PRINTF("nSize=%d", nSize); + DEBUG_EXIT +} + +void EnvParams::Dump() { + printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, EnvParamsConst::FILE_NAME); + + puts("UTC Offset"); + int8_t nHours; + uint8_t nMinutes; + ConfigStore::Get()->GetEnvUtcOffset(nHours, nMinutes); + printf(" %s=%.2d:%.2u [%d]\n", EnvParamsConst::UTC_OFFSET, nHours, nMinutes, ConfigStore::Get()->GetEnvUtcOffset()); +} diff --git a/lib-configstore/src/envparamsconst.cpp b/lib-configstore/src/envparamsconst.cpp new file mode 100755 index 00000000..37880705 --- /dev/null +++ b/lib-configstore/src/envparamsconst.cpp @@ -0,0 +1,30 @@ +/** + * @file envparamsconst.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "envparamsconst.h" + +const char EnvParamsConst::FILE_NAME[] = "env.txt"; + +const char EnvParamsConst::UTC_OFFSET[] = "utc_offset"; diff --git a/lib-configstore/src/platform_configstore.h b/lib-configstore/src/platform_configstore.h old mode 100644 new mode 100755 diff --git a/lib-configstore/src/storenetwork.cpp b/lib-configstore/src/storenetwork.cpp deleted file mode 100644 index 0ed3c4a4..00000000 --- a/lib-configstore/src/storenetwork.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @file storenetwork.cpp - * - */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include - -#include "storenetwork.h" -#include "debug.h" - -StoreNetwork *StoreNetwork::s_pThis = nullptr; - -StoreNetwork::StoreNetwork() { - DEBUG_ENTRY - - assert(s_pThis == nullptr); - s_pThis = this; - - DEBUG_PRINTF("%p", reinterpret_cast(s_pThis)); - DEBUG_EXIT -} diff --git a/lib-ddp/.cproject b/lib-ddp/.cproject index ccec8dad..e0b1ea2d 100755 --- a/lib-ddp/.cproject +++ b/lib-ddp/.cproject @@ -31,13 +31,11 @@ - @@ -177,7 +170,6 @@ - diff --git a/lib-ddp/Rules.mk b/lib-ddp/Rules.mk index 801e1e34..aa2f9f54 100644 --- a/lib-ddp/Rules.mk +++ b/lib-ddp/Rules.mk @@ -4,5 +4,4 @@ else DEFINES+=LIGHTSET_PORTS=32 endif -EXTRA_INCLUDES =../lib-properties/include ../lib-hal/include ../lib-network/include -EXTRA_INCLUDES+=../lib-lightset/include +EXTRA_INCLUDES =../lib-properties/include ../lib-network/include ../lib-lightset/include diff --git a/lib-ddp/include/ddp.h b/lib-ddp/include/ddp.h index 96a00177..f0cc9a73 100644 --- a/lib-ddp/include/ddp.h +++ b/lib-ddp/include/ddp.h @@ -3,7 +3,7 @@ * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-ddp/src/ddpdisplay.cpp b/lib-ddp/src/ddpdisplay.cpp index eb4cc814..13c4a6f8 100644 --- a/lib-ddp/src/ddpdisplay.cpp +++ b/lib-ddp/src/ddpdisplay.cpp @@ -2,7 +2,7 @@ * @file ddpdisplay.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -169,7 +169,7 @@ void DdpDisplay::HandleQuery() { m_Packet.header.len[0] = static_cast(nLength >> 8); m_Packet.header.len[1] = static_cast(nLength); - Network::Get()->SendTo(m_nHandle, &m_Packet, static_cast(HEADER_LEN + static_cast(nLength)), Network::Get()->GetIp() | ~(Network::Get()->GetNetmask()), ddp::UDP_PORT); + Network::Get()->SendTo(m_nHandle, &m_Packet, (HEADER_LEN + static_cast(nLength)), Network::Get()->GetIp() | ~(Network::Get()->GetNetmask()), ddp::UDP_PORT); } if ((m_Packet.header.id & id::STATUS) == id::CONFIG) { @@ -206,9 +206,9 @@ void DdpDisplay::HandleQuery() { m_Packet.header.len[0] = static_cast(nLength >> 8); m_Packet.header.len[1] = static_cast(nLength); - Network::Get()->SendTo(m_nHandle, &m_Packet, static_cast(HEADER_LEN + static_cast(nLength)), m_nFromIp, ddp::UDP_PORT); + Network::Get()->SendTo(m_nHandle, &m_Packet, HEADER_LEN + nLength, m_nFromIp, ddp::UDP_PORT); - debug_dump(&m_Packet, static_cast(HEADER_LEN + static_cast(nLength))); + debug_dump(&m_Packet, HEADER_LEN + nLength); } DEBUG_EXIT @@ -318,7 +318,7 @@ void DdpDisplay::Run() { } void DdpDisplay::Print() { - puts("DDP Display:"); + puts("DDP Display"); printf(" Count : %u\n", m_nCount); printf(" Channels per pixel: %u\n", GetChannelsPerPixel()); printf(" Active ports : %u\n", m_nActivePorts); diff --git a/lib-debug/.cproject b/lib-debug/.cproject deleted file mode 100644 index d6b8345f..00000000 --- a/lib-debug/.cproject +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-debug/.settings/language.settings.xml b/lib-debug/.settings/language.settings.xml deleted file mode 100644 index e2081f3a..00000000 --- a/lib-debug/.settings/language.settings.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-debug/Makefile.GD32 b/lib-debug/Makefile.GD32 deleted file mode 100644 index e62a5089..00000000 --- a/lib-debug/Makefile.GD32 +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_SRCDIR= - -include ../firmware-template-gd32/lib/Rules.mk \ No newline at end of file diff --git a/lib-device/.cproject b/lib-device/.cproject index 86026fac..5011551b 100644 --- a/lib-device/.cproject +++ b/lib-device/.cproject @@ -30,12 +30,10 @@ - diff --git a/lib-device/include/ema.h b/lib-device/include/ema.h new file mode 100755 index 00000000..169d8763 --- /dev/null +++ b/lib-device/include/ema.h @@ -0,0 +1,77 @@ +/** + * @file ema.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef EMA_H_ +#define EMA_H_ + +#include + +/** + * @brief + * The EMA class template implements an Exponential Moving Average (EMA) filter in a compact and efficient manner, + * suitable for real-time applications where resource constraints may be a consideration. + * The class uses unsigned integer arithmetic to achieve the filtering, + * which is beneficial for systems that do not have floating-point units or where performance is critical. + * + * @tparam K + * A compile-time constant that determines the weight of the EMA. + * Higher K values mean a slower response to changes in the input, making the EMA smoother. + */ + +template +class EMA { +public: + EMA(uint16_t nIntitial = 0) : nState(static_cast(nIntitial << K) - nIntitial) {} + + /** + * @brief + * This method allows resetting the internal state nState of the filter to a specific value nValue. + * It sets the state in the same way as the constructor, + * preparing the filter to start processing new inputs from the given value. + * @param nValue + */ + void Reset(const uint16_t nValue = 0) { + nState = static_cast(nValue << K) - nValue; + } + + uint16_t Filter(const uint16_t nInput) { + nState += nInput; + const auto nOutput = static_cast((nState + nHalf) >> K); + nState -= nOutput; + return nOutput; + } + + /* + * This static constant is used for rounding during the shift operation. + * It ensures that when you shift the value right by K bits, + * it rounds to the nearest integer rather than truncating. + */ + static constexpr uint16_t nHalf = K > 0 ? 1 << (K - 1) : 0; + +private: + uint16_t nState; +}; + +#endif /* EMA_H_ */ diff --git a/lib-device/include/max7219.h b/lib-device/include/max7219.h index e23fa9b6..b7e57e42 100644 --- a/lib-device/include/max7219.h +++ b/lib-device/include/max7219.h @@ -2,7 +2,7 @@ * @file max7219.h * */ -/* Copyright (C) 2020-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-device/include/mcp23s17.h b/lib-device/include/mcp23s17.h index d0c36ad2..d9641037 100644 --- a/lib-device/include/mcp23s17.h +++ b/lib-device/include/mcp23s17.h @@ -2,7 +2,7 @@ * @file mcp23s17.h * */ -/* Copyright (C) 2020-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-hal/src/utc.cpp b/lib-device/include/mcp23x08.h old mode 100644 new mode 100755 similarity index 61% rename from lib-hal/src/utc.cpp rename to lib-device/include/mcp23x08.h index ba6e01b2..b05a33ab --- a/lib-hal/src/utc.cpp +++ b/lib-device/include/mcp23x08.h @@ -1,8 +1,8 @@ /** - * @file utc.cpp + * @file mcp23x08.h * */ -/* Copyright (C) 2019-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -10,8 +10,10 @@ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,28 +23,23 @@ * THE SOFTWARE. */ -#include - -#include "utc.h" +#ifndef MCP23X08_H_ +#define MCP23X08_H_ -// https://en.wikipedia.org/wiki/List_of_UTC_time_offsets - -static const float s_ValidOffets[] = { -9.5, -3.5, 3.5, 4.5, 5.5, 5.75, 6.5, 8.75, 9.5, 10.5, 12.75 }; - -int32_t Utc::Validate(float fOffset) { - auto nInt = static_cast(fOffset); +#include - if ((nInt >= -12) && (nInt <= 14)) { - if (fOffset == static_cast(nInt)) { - return (nInt * 3600); - } else { - for (uint32_t i = 0; i < sizeof(s_ValidOffets) / sizeof(s_ValidOffets[0]); i++) { - if (fOffset == s_ValidOffets[i]) { - return static_cast(fOffset * 3600.0f); - } - } - } - } +namespace mcp23x08 { +static constexpr uint8_t REG_IODIR = 0x00; +static constexpr uint8_t REG_IPOL = 0x01; +static constexpr uint8_t REG_GPINTEN = 0x02; +static constexpr uint8_t REG_DEFVAL = 0x03; +static constexpr uint8_t REG_INTCON = 0x04; +static constexpr uint8_t REG_IOCON = 0x05; +static constexpr uint8_t REG_GPPU = 0x06; +static constexpr uint8_t REG_INTF = 0x07; +static constexpr uint8_t REG_INTCAP = 0x08; +static constexpr uint8_t REG_GPIO = 0x09; +static constexpr uint8_t REG_OLAT = 0x0A; +} // namespace mcp23x08 - return 0; -} +#endif /* MCP23X08_H_ */ diff --git a/lib-device/include/mcp23x17.h b/lib-device/include/mcp23x17.h index 489b0ea6..4b6f2ef2 100644 --- a/lib-device/include/mcp23x17.h +++ b/lib-device/include/mcp23x17.h @@ -2,7 +2,7 @@ * @file mcp23x17.h * */ -/* Copyright (C) 2020-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,6 +27,7 @@ #include namespace mcp23x17 { +///< IOCON.BANK = 0 static constexpr uint8_t REG_IODIRA = 0x00; ///< I/O DIRECTION (IODIRA) REGISTER, 1 = Input (default), 0 = Output static constexpr uint8_t REG_IODIRB = 0x01; ///< I/O DIRECTION (IODIRB) REGISTER, 1 = Input (default), 0 = Output static constexpr uint8_t REG_IPOLA = 0x02; ///< INPUT POLARITY (IPOLA) REGISTER, 0 = Normal (default)(low reads as 0), 1 = Inverted (low reads as 1) @@ -51,6 +52,7 @@ static constexpr uint8_t REG_OLATA = 0x14; ///< OUTPUT LATCH REGISTER (OLATA), static constexpr uint8_t REG_OLATB = 0x15; ///< OUTPUT LATCH REGISTER (OLATB), 1 = Latch High, 0 = Latch Low (default) Reading Returns Latch State, Not Port Value static constexpr uint8_t IOCON_HAEN = (1U << 3); +static constexpr uint8_t IOCON_BANK = (1U << 7); static constexpr uint8_t DEFAULT_I2C_ADDRESS = 0x20; diff --git a/lib-device/include/mcp49x2.h b/lib-device/include/mcp49x2.h index 977a8dbf..9d48e184 100644 --- a/lib-device/include/mcp49x2.h +++ b/lib-device/include/mcp49x2.h @@ -2,7 +2,7 @@ * @file mcp49x2.h * */ -/* Copyright (C) 2014-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2014-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-device/include/sc16is740.h b/lib-device/include/sc16is740.h index 2313ceee..903ab353 100644 --- a/lib-device/include/sc16is740.h +++ b/lib-device/include/sc16is740.h @@ -2,7 +2,7 @@ * @file sc16is740.h * */ -/* Copyright (C) 2020-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -49,7 +49,7 @@ class SC16IS740: HAL_I2C { }; SC16IS740(uint8_t nAddress = sc16is740::I2C_ADDRESS, uint32_t nOnBoardCrystal = sc16is740::CRISTAL_HZ); - ~SC16IS740() {} + ~SC16IS740() = default; void SetOnBoardCrystal(uint32_t nOnBoardCrystalHz) { m_nOnBoardCrystal = nOnBoardCrystalHz; diff --git a/lib-device/include/sc16is7x0.h b/lib-device/include/sc16is7x0.h index 13a8736c..2df3ad32 100644 --- a/lib-device/include/sc16is7x0.h +++ b/lib-device/include/sc16is7x0.h @@ -2,7 +2,7 @@ * @file sc16is7x0.h * */ -/* Copyright (C) 2020-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-device/src/sc16is740.cpp b/lib-device/src/sc16is740.cpp index b803b770..381b234b 100644 --- a/lib-device/src/sc16is740.cpp +++ b/lib-device/src/sc16is740.cpp @@ -2,7 +2,7 @@ * @file sc16is740.cpp * */ -/* Copyright (C) 2020-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-display/.cproject b/lib-display/.cproject index 6a561161..a86bfdbf 100644 --- a/lib-display/.cproject +++ b/lib-display/.cproject @@ -30,12 +30,10 @@ - diff --git a/lib-display/include/display.h b/lib-display/include/display.h index c8d92152..ab4d374b 100644 --- a/lib-display/include/display.h +++ b/lib-display/include/display.h @@ -2,7 +2,7 @@ * @file display.h * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,17 +26,14 @@ #ifndef DISPLAY_H_ #define DISPLAY_H_ -#include "display7segment.h" +#include + #include "console.h" namespace display { struct Defaults { - static constexpr auto SEEP_TIMEOUT = 5; + static constexpr uint32_t SEEP_TIMEOUT = 5; }; -namespace timeout { -void gpio_init(); -bool gpio_renew(); -} // namespace timeout } // namespace display #if !defined (CONFIG_DISPLAY_USE_CUSTOM) diff --git a/lib-display/include/display7segment.h b/lib-display/include/display7segment.h deleted file mode 100644 index cbc545b2..00000000 --- a/lib-display/include/display7segment.h +++ /dev/null @@ -1,145 +0,0 @@ -/** - * @file display7segment.h - * - */ -/* Copyright (C) 2019-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef DISPLAY7SEGMENT_H_ -#define DISPLAY7SEGMENT_H_ - -#include - -namespace display7segment { -static constexpr uint8_t CH_0 = 0x3F; // 0b00111111 -static constexpr uint8_t CH_1 = 0x06; // 0b00000110 -static constexpr uint8_t CH_2 = 0x5B; // 0b01011011 -static constexpr uint8_t CH_3 = 0x4F; // 0b01001111 -static constexpr uint8_t CH_4 = 0x66; // 0b01100110 -static constexpr uint8_t CH_5 = 0x6D; // 0b01101101 -static constexpr uint8_t CH_6 = 0x7D; // 0b01111101 -static constexpr uint8_t CH_7 = 0x07; // 0b00000111 -static constexpr uint8_t CH_8 = 0x7F; // 0b01111111 -static constexpr uint8_t CH_9 = 0x6F; // 0b01101111 -static constexpr uint8_t CH_A = 0x77; // 0b01110111 -static constexpr uint8_t CH_B = 0x7C; // 0b01111100 -static constexpr uint8_t CH_C = 0x39; // 0b00111001 -static constexpr uint8_t CH_D = 0x5E; // 0b01011110 -static constexpr uint8_t CH_E = 0x79; // 0b01111001 -static constexpr uint8_t CH_F = 0x71; // 0b01110001 -static constexpr uint8_t CH_P = 0x73; // 0b01110011 -static constexpr uint8_t CH_MIN = 0x40; // 0b01000000 -static constexpr uint8_t CH_DP = 0x80; // 0b10000000 -static constexpr uint8_t CH_BLANK = 0x00; // 0b00000000 - -static constexpr uint16_t Msg(uint8_t nDigitRight, uint8_t nDigitLeft) { - return static_cast((nDigitLeft << 8) | nDigitRight); -} -} // namespace display7segment - -enum class Display7SegmentMessage { - // Generic Digits - GENERIC_0 = display7segment::Msg(display7segment::CH_0, display7segment::CH_BLANK), - GENERIC_1 = display7segment::Msg(display7segment::CH_1, display7segment::CH_BLANK), - GENERIC_2 = display7segment::Msg(display7segment::CH_2, display7segment::CH_BLANK), - GENERIC_3 = display7segment::Msg(display7segment::CH_3, display7segment::CH_BLANK), - GENERIC_4 = display7segment::Msg(display7segment::CH_4, display7segment::CH_BLANK), - GENERIC_5 = display7segment::Msg(display7segment::CH_5, display7segment::CH_BLANK), - GENERIC_6 = display7segment::Msg(display7segment::CH_6, display7segment::CH_BLANK), - GENERIC_7 = display7segment::Msg(display7segment::CH_7, display7segment::CH_BLANK), - GENERIC_8 = display7segment::Msg(display7segment::CH_8, display7segment::CH_BLANK), - GENERIC_9 = display7segment::Msg(display7segment::CH_9, display7segment::CH_BLANK), - // Startup messages - INFO_STARTUP = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_0), - INFO_NETWORK_INIT = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_1), - INFO_DHCP = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_2), - INFO_IP = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_3), - INFO_NTP = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_4), - INFO_SPARKFUN = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_5), - INFO_CPLD = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_6), - INFO_MDNS_CONFIG = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_7), - INFO_RDMNET_CONFIG = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_8), - // - INFO_NETWORK_SHUTDOWN = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_9), - // - INFO_NODE_PARMAMS = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_4), - INFO_BRIDGE_PARMAMS = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_4), - INFO_OSCCLIENT_PARMAMS = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_4), - // - INFO_RDM_RUN = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_5), - INFO_NODE_START = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_6), - INFO_BRIDGE_START = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_6), - INFO_OSCCLIENT_START = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_6), - INFO_RDMNET_START = display7segment::Msg(display7segment::CH_BLANK, display7segment::CH_6), - // - INFO_NONE = display7segment::Msg(display7segment::CH_DP, display7segment::CH_DP), - INFO_NODE_STARTED = display7segment::Msg(display7segment::CH_DP, display7segment::CH_DP), - INFO_BRIDGE_STARTED = display7segment::Msg(display7segment::CH_DP, display7segment::CH_DP), - INFO_OSCCLIENT_STARTED = display7segment::Msg(display7segment::CH_DP, display7segment::CH_DP), - INFO_RDMNET_STARTED = display7segment::Msg(display7segment::CH_DP, display7segment::CH_DP), - // SPI Flash messages - INFO_SPI_NONE = display7segment::Msg(display7segment::CH_C, display7segment::CH_MIN), - INFO_SPI_CHECK = display7segment::Msg(display7segment::CH_C, display7segment::CH_0), - INFO_SPI_ERASE = display7segment::Msg(display7segment::CH_C, display7segment::CH_1), - INFO_SPI_WRITING = display7segment::Msg(display7segment::CH_C, display7segment::CH_2), - INFO_SPI_NODIFF = display7segment::Msg(display7segment::CH_C, display7segment::CH_3), - INFO_SPI_DONE = display7segment::Msg(display7segment::CH_C, display7segment::CH_C), - INFO_SPI_UPDATE = display7segment::Msg(display7segment::CH_C, display7segment::CH_F), - // Firmware TFTP messages - INFO_TFTP_ON = display7segment::Msg(display7segment::CH_F, display7segment::CH_MIN), - INFO_TFTP_STARTED = display7segment::Msg(display7segment::CH_F, display7segment::CH_1), - INFO_TFTP_ENDED = display7segment::Msg(display7segment::CH_F, display7segment::CH_2), - INFO_TFTP_OFF = display7segment::Msg(display7segment::CH_F, display7segment::CH_DP), - // Informational / Warning messages - INFO_REBOOTING = display7segment::Msg(display7segment::CH_MIN, display7segment::CH_MIN), - INFO_DATALOSS = display7segment::Msg(display7segment::CH_D, display7segment::CH_MIN), - // Error messages - ERROR_DHCP = display7segment::Msg(display7segment::CH_E, display7segment::CH_2), - ERROR_NTP = display7segment::Msg(display7segment::CH_E, display7segment::CH_4), - ERROR_SPARKFUN = display7segment::Msg(display7segment::CH_E, display7segment::CH_5), - ERROR_MCP23S017 = display7segment::Msg(display7segment::CH_E, display7segment::CH_8), - ERROR_SI5351A = display7segment::Msg(display7segment::CH_E, display7segment::CH_9), - ERROR_NEXTION = display7segment::Msg(display7segment::CH_E, display7segment::CH_A), - ERROR_SPI = display7segment::Msg(display7segment::CH_E, display7segment::CH_C), - ERROR_FATAL = display7segment::Msg(display7segment::CH_E, display7segment::CH_E), - ERROR_TFTP = display7segment::Msg(display7segment::CH_E, display7segment::CH_F), - // LTC messages - LTC_WAITING = display7segment::Msg(display7segment::CH_DP, display7segment::CH_DP), - LTC_FILM = display7segment::Msg(display7segment::CH_2, display7segment::CH_4), - LTC_EBU = display7segment::Msg(display7segment::CH_2, display7segment::CH_5), - LTC_DF = display7segment::Msg(display7segment::CH_2, display7segment::CH_9), - LTC_SMPTE = display7segment::Msg(display7segment::CH_3, display7segment::CH_0), - // OSC Client messages - INFO_OSCCLIENT_PING_PONG = display7segment::Msg(display7segment::CH_P, display7segment::CH_P), - ERROR_OSCCLIENT_PING_PONG = display7segment::Msg(display7segment::CH_P, display7segment::CH_E), - // Apple MIDI - rtpMIDI messages - // TODO Apple MIDI - rtpMIDI messages - // Show File player - INFO_PLAYER_IDLE = display7segment::Msg(display7segment::CH_P, display7segment::CH_0), - INFO_PLAYER_RUNNING = display7segment::Msg(display7segment::CH_P, display7segment::CH_1), - INFO_PLAYER_RUNNING_LOOP = display7segment::Msg(display7segment::CH_P, display7segment::CH_2), - INFO_PLAYER_STOPPED = display7segment::Msg(display7segment::CH_P, display7segment::CH_3), - INFO_PLAYER_STOPPED_LOOP = display7segment::Msg(display7segment::CH_P, display7segment::CH_4), - INFO_PLAYER_ENDED = display7segment::Msg(display7segment::CH_P, display7segment::CH_9), - ERROR_PLAYER = display7segment::Msg(display7segment::CH_P, display7segment::CH_E) -}; - -#endif /* DISPLAY7SEGMENT_H_ */ diff --git a/lib-display/include/displayset.h b/lib-display/include/displayset.h index 52ac2ddb..ee7cbb2f 100644 --- a/lib-display/include/displayset.h +++ b/lib-display/include/displayset.h @@ -39,7 +39,7 @@ static constexpr uint32_t BLINK_ON = (1U << 1); class DisplaySet { public: - virtual ~DisplaySet() {} + virtual ~DisplaySet() = default; uint32_t GetColumns() const { return m_nCols; @@ -66,9 +66,9 @@ class DisplaySet { virtual void SetCursorPos(uint32_t nCol, uint32_t nRow)= 0; virtual void SetCursor(uint32_t)= 0; - virtual void SetSleep(__attribute__((unused)) bool bSleep) {} - virtual void SetContrast(__attribute__((unused)) uint8_t nContrast) {} - virtual void SetFlipVertically(__attribute__((unused)) bool doFlipVertically) {} + virtual void SetSleep([[maybe_unused]] bool bSleep) {} + virtual void SetContrast([[maybe_unused]] uint8_t nContrast) {} + virtual void SetFlipVertically([[maybe_unused]] bool doFlipVertically) {} virtual void PrintInfo() {} diff --git a/lib-display/include/i2c/display.h b/lib-display/include/i2c/display.h index 56ba79d3..24f7671d 100644 --- a/lib-display/include/i2c/display.h +++ b/lib-display/include/i2c/display.h @@ -2,7 +2,7 @@ * @file display.h * */ -/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,11 +36,14 @@ #include #include "displayset.h" -#include "display7segment.h" -#include "hal_i2c.h" #include "hardware.h" +#include "hal_i2c.h" +#if defined (DISPLAYTIMEOUT_GPIO) +# include "hal_gpio.h" +#endif + namespace display { enum class Type { PCF8574T_1602, PCF8574T_2004, SSD1306, SSD1311, UNKNOWN @@ -182,9 +185,8 @@ class Display { Write(nRows, pText); } - void TextStatus(const char *pText, Display7SegmentMessage message, uint32_t nConsoleColor = UINT32_MAX) { + void TextStatus(const char *pText, uint32_t nConsoleColor) { TextStatus(pText); - Status(message); if (nConsoleColor == UINT32_MAX) { return; @@ -193,11 +195,6 @@ class Display { console_status(nConsoleColor, pText); } - void TextStatus(const char *pText, uint32_t nValue7Segment, bool bHex = false) { - TextStatus(pText); - Status(nValue7Segment, bHex); - } - void SetCursor(uint32_t nMode) { if (m_LcdDisplay == nullptr) { return; @@ -274,28 +271,6 @@ class Display { return m_LcdDisplay->GetRows(); } - void Status(Display7SegmentMessage nData) { - if (m_bHave7Segment) { - m_I2C.WriteRegister(display::segment7::MCP23017_GPIOA, static_cast(~static_cast(nData))); - } - } - - void Status(uint32_t nValue, bool bHex) { - if (m_bHave7Segment) { - uint16_t nData; - - if (!bHex) { - nData = GetData(nValue / 10); - nData = static_cast(nData | GetData(nValue % 10) << 8U); - } else { - nData = GetData(nValue & 0x0F); - nData = static_cast(nData | GetData((nValue >> 4) & 0x0F) << 8U); - } - - m_I2C.WriteRegister(display::segment7::MCP23017_GPIOA, static_cast(~nData)); - } - } - void Progress() { static constexpr char SYMBOLS[] = { '/' , '-', '\\' , '|' }; static uint32_t nSymbolsIndex; @@ -336,9 +311,11 @@ class Display { SetSleep(true); } } else { - if (__builtin_expect((display::timeout::gpio_renew()), 0)) { +#if defined (DISPLAYTIMEOUT_GPIO) + if (__builtin_expect(((FUNC_PREFIX(gpio_lev(DISPLAYTIMEOUT_GPIO)) == LOW)), 0)) { SetSleep(false); } +#endif } } @@ -349,82 +326,19 @@ class Display { private: void Detect(display::Type tDisplayType); void Detect(uint32_t nRows); - void Detect7Segment() { - m_bHave7Segment = m_I2C.IsConnected(); - - if (m_bHave7Segment) { - m_I2C.WriteRegister(display::segment7::MCP23017_IODIRA, static_cast(0x0000)); // All output - Status(Display7SegmentMessage::INFO_STARTUP); - } - } - - uint16_t GetData(const uint32_t nHexValue) const { - switch (nHexValue) { - case 0: - return display7segment::CH_0; - break; - case 1: - return display7segment::CH_1; - break; - case 2: - return display7segment::CH_2; - break; - case 3: - return display7segment::CH_3; - break; - case 4: - return display7segment::CH_4; - break; - case 5: - return display7segment::CH_5; - break; - case 6: - return display7segment::CH_6; - break; - case 7: - return display7segment::CH_7; - break; - case 8: - return display7segment::CH_8; - break; - case 9: - return display7segment::CH_9; - break; - case 0xa: - return display7segment::CH_A; - break; - case 0xb: - return display7segment::CH_B; - break; - case 0xc: - return display7segment::CH_C; - break; - case 0xd: - return display7segment::CH_D; - break; - case 0xe: - return display7segment::CH_E; - break; - case 0xf: - return display7segment::CH_F; - break; - default: - break; - } - - return display7segment::CH_BLANK; - } private: display::Type m_tType { display::Type::UNKNOWN }; uint32_t m_nMillis { 0 }; HAL_I2C m_I2C; - bool m_bIsSleep { false }; - bool m_bHave7Segment { false }; uint32_t m_nSleepTimeout { 1000 * 60 * display::Defaults::SEEP_TIMEOUT }; - uint8_t m_nContrast { 0x7F }; + + bool m_bIsSleep { false }; bool m_bIsFlippedVertically { false }; +#if defined (CONFIG_DISPLAY_HAVE_7SEGMENT) + bool m_bHave7Segment { false }; +#endif DisplaySet *m_LcdDisplay { nullptr }; static Display *s_pThis; diff --git a/lib-display/include/i2c/ssd1311.h b/lib-display/include/i2c/ssd1311.h index 667f1249..d3d50e40 100644 --- a/lib-display/include/i2c/ssd1311.h +++ b/lib-display/include/i2c/ssd1311.h @@ -34,7 +34,7 @@ class Ssd1311 final: public DisplaySet { public: Ssd1311 (); - ~Ssd1311 () override {} + ~Ssd1311 () override = default; bool Start() override; diff --git a/lib-display/include/spi/config.h b/lib-display/include/spi/config.h index 5cfe2729..1cccce64 100755 --- a/lib-display/include/spi/config.h +++ b/lib-display/include/spi/config.h @@ -2,7 +2,7 @@ * @file config.h * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,33 +26,35 @@ #ifndef CONFIG_H #define CONFIG_H +#include + namespace config { #if defined (SPI_LCD_240X240) -static constexpr auto WIDTH = 240U; -static constexpr auto HEIGHT = 240U; +static constexpr uint32_t WIDTH = 240; +static constexpr uint32_t HEIGHT = 240; #elif defined (SPI_LCD_240X320) -static constexpr auto WIDTH = 240U; -static constexpr auto HEIGHT = 320U; +static constexpr uint32_t WIDTH = 240; +static constexpr uint32_t HEIGHT = 320; #else # error lib-display spi config #endif } // namespace config #if defined (H3) -# define SPI_LCD_RST_PIN GPIO_EXT_7 // GPIO6 -# define SPI_LCD_DC_PIN GPIO_EXT_26 // GPIO10 -# define SPI_LCD_BL_PIN GPIO_EXT_22 // GPIO2 -# if defined(SPI_LCD_HAVE_CS_PIN) -# define SPI_LCD_CS_PIN GPIO_EXT_24 // GPIO13 / SPI CS0 +# define SPI_LCD_RST_GPIO GPIO_EXT_7 // GPIO6 +# define SPI_LCD_DC_GPIO GPIO_EXT_26 // GPIO10 +# define SPI_LCD_BL_GPIO GPIO_EXT_22 // GPIO2 +# if defined(SPI_LCD_HAVE_CS_GPIO) +# define SPI_LCD_CS_GPIO GPIO_EXT_24 // GPIO13 / SPI CS0 # endif -#elif defined (GD32) //See board file +#elif defined (GD32) //See board file #else # include "bcm2835.h" -# define SPI_LCD_RST_PIN RPI_V2_GPIO_P1_07 // GPIO4 -# define SPI_LCD_DC_PIN RPI_V2_GPIO_P1_31 // GPIO6 -# define SPI_LCD_BL_PIN RPI_V2_GPIO_P1_29 // GPIO5 -# if defined(SPI_LCD_HAVE_CS_PIN) -# define SPI_LCD_CS_PIN RPI_V2_GPIO_P1_24 // GPIO8 / SPI CS0 +# define SPI_LCD_RST_GPIO RPI_V2_GPIO_P1_07 // GPIO4 +# define SPI_LCD_DC_GPIO RPI_V2_GPIO_P1_31 // GPIO6 +# define SPI_LCD_BL_GPIO RPI_V2_GPIO_P1_29 // GPIO5 +# if defined(SPI_LCD_HAVE_CS_GPIO) +# define SPI_LCD_CS_GPIO RPI_V2_GPIO_P1_24 // GPIO8 / SPI CS0 # endif #endif diff --git a/lib-display/include/spi/display.h b/lib-display/include/spi/display.h index 6ecee92d..0db5ee37 100644 --- a/lib-display/include/spi/display.h +++ b/lib-display/include/spi/display.h @@ -2,7 +2,7 @@ * @file display.h * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -41,6 +41,10 @@ # include "spi/st7789.h" #endif +#if defined (DISPLAYTIMEOUT_GPIO) +# include "hal_gpio.h" +#endif + #include "hardware.h" class Display { @@ -101,10 +105,6 @@ class Display { m_bClearEndOfLine = true; } - void Status(__attribute__((unused)) Display7SegmentMessage nValue) { } - - void Status(__attribute__((unused)) uint8_t nValue, __attribute__((unused)) bool bHex) {} - void Text(const char *pData, uint32_t nLength) { if (nLength > m_nCols) { nLength = m_nCols; @@ -158,9 +158,8 @@ class Display { Write(m_nRows, pText); } - void TextStatus(const char *pText, Display7SegmentMessage message, uint32_t nConsoleColor = UINT32_MAX) { + void TextStatus(const char *pText, uint32_t nConsoleColor) { TextStatus(pText); - Status(message); if (nConsoleColor == UINT32_MAX) { return; @@ -169,11 +168,6 @@ class Display { console_status(nConsoleColor, pText); } - void TextStatus(const char *pText, uint8_t nValue7Segment, bool bHex = false) { - TextStatus(pText); - Status(nValue7Segment, bHex); - } - void Progress() { static constexpr char SYMBOLS[] = { '/' , '-', '\\' , '|' }; static uint32_t nSymbolsIndex; @@ -242,9 +236,11 @@ class Display { SetSleep(true); } } else { - if (__builtin_expect((display::timeout::gpio_renew()), 0)) { +#if defined (DISPLAYTIMEOUT_GPIO) + if (__builtin_expect(((FUNC_PREFIX(gpio_lev(DISPLAYTIMEOUT_GPIO)) == LOW)), 0)) { SetSleep(false); } +#endif } } diff --git a/lib-display/include/spi/ili9341.h b/lib-display/include/spi/ili9341.h index fe72a20e..ea0eccca 100644 --- a/lib-display/include/spi/ili9341.h +++ b/lib-display/include/spi/ili9341.h @@ -2,7 +2,7 @@ * @file ili9341.h * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,25 +32,25 @@ namespace ili9341 { namespace cmd { -static constexpr uint8_t NOP = 0x00; -static constexpr uint8_t SWRESET = 0x01; -static constexpr uint8_t RDDID = 0x04; -static constexpr uint8_t RDDST = 0x09; -static constexpr uint8_t SLPIN = 0x10; -static constexpr uint8_t SLPOUT = 0x11; -static constexpr uint8_t PTLON = 0x12; -static constexpr uint8_t NORON = 0x13; -static constexpr uint8_t INVOFF = 0x20; -static constexpr uint8_t INVON = 0x21; -static constexpr uint8_t DISPOFF = 0x28; -static constexpr uint8_t DISPON = 0x29; -static constexpr uint8_t CASET = 0x2A; -static constexpr uint8_t RASET = 0x2B; -static constexpr uint8_t RAMWR = 0x2C; -static constexpr uint8_t RAMRD = 0x2E; -static constexpr uint8_t PTLAR = 0x30; -static constexpr uint8_t MADCTL = 0x36; -static constexpr uint8_t PIXFMT = 0x3A; +static constexpr uint8_t NOP = 0x00; +static constexpr uint8_t SWRESET = 0x01; +static constexpr uint8_t RDDID = 0x04; +static constexpr uint8_t RDDST = 0x09; +static constexpr uint8_t SLPIN = 0x10; +static constexpr uint8_t SLPOUT = 0x11; +static constexpr uint8_t PTLON = 0x12; +static constexpr uint8_t NORON = 0x13; +static constexpr uint8_t INVOFF = 0x20; +static constexpr uint8_t INVON = 0x21; +static constexpr uint8_t DISPOFF = 0x28; +static constexpr uint8_t DISPON = 0x29; +static constexpr uint8_t CASET = 0x2A; +static constexpr uint8_t RASET = 0x2B; +static constexpr uint8_t RAMWR = 0x2C; +static constexpr uint8_t RAMRD = 0x2E; +static constexpr uint8_t PTLAR = 0x30; +static constexpr uint8_t MADCTL = 0x36; +static constexpr uint8_t PIXFMT = 0x3A; } // namespace cmd namespace data { /** @@ -59,27 +59,26 @@ namespace data { * param: MY MX MV ML RGB MH - - * */ -static constexpr uint8_t MADCTL_MY = 0x80; ///< Page Address Order ('0': Top to Bottom, '1': the opposite) -static constexpr uint8_t MADCTL_MX = 0x40; ///< Column Address Order ('0': Left to Right, '1': the opposite) -static constexpr uint8_t MADCTL_MV = 0x20; ///< Page/Column Order ('0' = Normal Mode, '1' = Reverse Mode) -static constexpr uint8_t MADCTL_ML = 0x10; ///< Line Address Order ('0' = LCD Refresh Top to Bottom, '1' = the opposite) -static constexpr uint8_t MADCTL_RGB = 0x00; ///< Red-Green-Blue pixel order -static constexpr uint8_t MADCTL_BGR = 0x08; ///< Blue-Green-Red pixel order +static constexpr uint8_t MADCTL_MY = 0x80; ///< Page Address Order ('0': Top to Bottom, '1': the opposite) +static constexpr uint8_t MADCTL_MX = 0x40; ///< Column Address Order ('0': Left to Right, '1': the opposite) +static constexpr uint8_t MADCTL_MV = 0x20; ///< Page/Column Order ('0' = Normal Mode, '1' = Reverse Mode) +static constexpr uint8_t MADCTL_ML = 0x10; ///< Line Address Order ('0' = LCD Refresh Top to Bottom, '1' = the opposite) +static constexpr uint8_t MADCTL_RGB = 0x00; ///< Red-Green-Blue pixel order +static constexpr uint8_t MADCTL_BGR = 0x08; ///< Blue-Green-Red pixel order } // namespace data -//TODO Need to sort here namespace colour { -static constexpr uint16_t BLACK = 0x0000; -static constexpr uint16_t WHITE = 0xFFFF; -static constexpr uint16_t RED = 0xF800; -static constexpr uint16_t GREEN = 0x07E0; -static constexpr uint16_t BLUE = 0x001F; -static constexpr uint16_t DARKBLUE = 0X01CF; -static constexpr uint16_t CYAN = 0x07FF; -static constexpr uint16_t MAGENTA = 0xF81F; -static constexpr uint16_t YELLOW = 0xFFE0; -static constexpr uint16_t ORANGE = 0xFC00; -static constexpr uint16_t GRAY = 0X8430; +static constexpr uint16_t BLACK = 0x0000; +static constexpr uint16_t BLUE = 0x001F; +static constexpr uint16_t CYAN = 0x07FF; +static constexpr uint16_t DARKBLUE = 0X01CF; +static constexpr uint16_t GRAY = 0X8430; +static constexpr uint16_t GREEN = 0x07E0; +static constexpr uint16_t MAGENTA = 0xF81F; +static constexpr uint16_t ORANGE = 0xFC00; +static constexpr uint16_t RED = 0xF800; +static constexpr uint16_t WHITE = 0xFFFF; +static constexpr uint16_t YELLOW = 0xFFE0; } // namespace colour } // namespace ili9341 diff --git a/lib-display/include/spi/spi_lcd.h b/lib-display/include/spi/spi_lcd.h index b15481a0..9e379148 100644 --- a/lib-display/include/spi/spi_lcd.h +++ b/lib-display/include/spi/spi_lcd.h @@ -38,31 +38,31 @@ inline static void ms_delay(const uint32_t ms) { } inline static void CS_Set() { -#if defined(SPI_LCD_HAVE_CS_PIN) - FUNC_PREFIX(gpio_set(SPI_LCD_CS_PIN)); +#if defined(SPI_LCD_HAVE_CS_GPIO) + FUNC_PREFIX(gpio_set(SPI_LCD_CS_GPIO)); #endif } inline static void CS_Clear() { -#if defined(SPI_LCD_HAVE_CS_PIN) - FUNC_PREFIX(gpio_clr(SPI_LCD_CS_PIN)); +#if defined(SPI_LCD_HAVE_CS_GPIO) + FUNC_PREFIX(gpio_clr(SPI_LCD_CS_GPIO)); #endif } inline static void DC_Set() { - FUNC_PREFIX(gpio_set(SPI_LCD_DC_PIN)); + FUNC_PREFIX(gpio_set(SPI_LCD_DC_GPIO)); } inline static void DC_Clear() { - FUNC_PREFIX(gpio_clr(SPI_LCD_DC_PIN)); + FUNC_PREFIX(gpio_clr(SPI_LCD_DC_GPIO)); } inline static void HW_Reset() { -#if defined (SPI_LCD_RST_PIN) +#if defined (SPI_LCD_RST_GPIO) ms_delay(200); - FUNC_PREFIX(gpio_clr(SPI_LCD_RST_PIN)); + FUNC_PREFIX(gpio_clr(SPI_LCD_RST_GPIO)); ms_delay(200); - FUNC_PREFIX(gpio_set(SPI_LCD_RST_PIN)); + FUNC_PREFIX(gpio_set(SPI_LCD_RST_GPIO)); ms_delay(200); #endif } diff --git a/lib-display/include/spi/st77xx.h b/lib-display/include/spi/st77xx.h index 0371d4ab..af61b9b7 100644 --- a/lib-display/include/spi/st77xx.h +++ b/lib-display/include/spi/st77xx.h @@ -2,7 +2,7 @@ * @file st77xx.h * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,27 +34,27 @@ namespace st77xx { namespace cmd { -static constexpr uint8_t NOP = 0x00; -static constexpr uint8_t SWRESET = 0x01; -static constexpr uint8_t RDDID = 0x04; -static constexpr uint8_t RDDST = 0x09; -static constexpr uint8_t SLPIN = 0x10; -static constexpr uint8_t SLPOUT = 0x11; -static constexpr uint8_t PTLON = 0x12; -static constexpr uint8_t NORON = 0x13; -static constexpr uint8_t INVOFF = 0x20; -static constexpr uint8_t INVON = 0x21; -static constexpr uint8_t DISPOFF = 0x28; -static constexpr uint8_t DISPON = 0x29; -static constexpr uint8_t CASET = 0x2A; -static constexpr uint8_t RASET = 0x2B; -static constexpr uint8_t RAMWR = 0x2C; -static constexpr uint8_t RAMRD = 0x2E; -static constexpr uint8_t PTLAR = 0x30; -static constexpr uint8_t TEOFF = 0x34; -static constexpr uint8_t TEON = 0x35; -static constexpr uint8_t MADCTL = 0x36; -static constexpr uint8_t COLMOD = 0x3A; +static constexpr uint8_t NOP = 0x00; +static constexpr uint8_t SWRESET = 0x01; +static constexpr uint8_t RDDID = 0x04; +static constexpr uint8_t RDDST = 0x09; +static constexpr uint8_t SLPIN = 0x10; +static constexpr uint8_t SLPOUT = 0x11; +static constexpr uint8_t PTLON = 0x12; +static constexpr uint8_t NORON = 0x13; +static constexpr uint8_t INVOFF = 0x20; +static constexpr uint8_t INVON = 0x21; +static constexpr uint8_t DISPOFF = 0x28; +static constexpr uint8_t DISPON = 0x29; +static constexpr uint8_t CASET = 0x2A; +static constexpr uint8_t RASET = 0x2B; +static constexpr uint8_t RAMWR = 0x2C; +static constexpr uint8_t RAMRD = 0x2E; +static constexpr uint8_t PTLAR = 0x30; +static constexpr uint8_t TEOFF = 0x34; +static constexpr uint8_t TEON = 0x35; +static constexpr uint8_t MADCTL = 0x36; +static constexpr uint8_t COLMOD = 0x3A; } // namespace cmd namespace data { /** @@ -64,30 +64,29 @@ namespace data { * */ /* Page Address Order ('0': Top to Bottom, '1': the opposite) */ -static constexpr uint8_t MADCTL_MY = 0x80; +static constexpr uint8_t MADCTL_MY = 0x80; /* Column Address Order ('0': Left to Right, '1': the opposite) */ -static constexpr uint8_t MADCTL_MX = 0x40; +static constexpr uint8_t MADCTL_MX = 0x40; /* Page/Column Order ('0' = Normal Mode, '1' = Reverse Mode) */ -static constexpr uint8_t MADCTL_MV = 0x20; +static constexpr uint8_t MADCTL_MV = 0x20; /* Line Address Order ('0' = LCD Refresh Top to Bottom, '1' = the opposite) */ -static constexpr uint8_t MADCTL_ML = 0x10; +static constexpr uint8_t MADCTL_ML = 0x10; /* RGB/BGR Order ('0' = RGB, '1' = BGR) */ -static constexpr uint8_t MADCTL_RGB = 0x00; +static constexpr uint8_t MADCTL_RGB = 0x00; } // namespace data -//TODO Need to sort here namespace colour { -static constexpr uint16_t BLACK = 0x0000; -static constexpr uint16_t WHITE = 0xFFFF; -static constexpr uint16_t RED = 0xF800; -static constexpr uint16_t GREEN = 0x07E0; -static constexpr uint16_t BLUE = 0x001F; -static constexpr uint16_t DARKBLUE = 0X01CF; -static constexpr uint16_t CYAN = 0x07FF; -static constexpr uint16_t MAGENTA = 0xF81F; -static constexpr uint16_t YELLOW = 0xFFE0; -static constexpr uint16_t ORANGE = 0xFC00; -static constexpr uint16_t GRAY = 0X8430; +static constexpr uint16_t BLACK = 0x0000; +static constexpr uint16_t BLUE = 0x001F; +static constexpr uint16_t CYAN = 0x07FF; +static constexpr uint16_t DARKBLUE = 0X01CF; +static constexpr uint16_t GRAY = 0X8430; +static constexpr uint16_t GREEN = 0x07E0; +static constexpr uint16_t MAGENTA = 0xF81F; +static constexpr uint16_t ORANGE = 0xFC00; +static constexpr uint16_t RED = 0xF800; +static constexpr uint16_t WHITE = 0xFFFF; +static constexpr uint16_t YELLOW = 0xFFE0; } // namespace colour } // namespace st77xx diff --git a/lib-display/src/i2c/display.cpp b/lib-display/src/i2c/display.cpp index 649b43b9..ba2efcb1 100644 --- a/lib-display/src/i2c/display.cpp +++ b/lib-display/src/i2c/display.cpp @@ -2,7 +2,7 @@ * @file display.cpp * */ -/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,17 +29,27 @@ #include "display.h" #include "displayset.h" -#if defined(CONFIG_DISPLAY_ENABLE_HD44780) -# include "i2c/hd44780.h" -#endif #include "i2c/ssd1306.h" #if defined(CONFIG_DISPLAY_ENABLE_SSD1311) # include "i2c/ssd1311.h" #endif - -#include "display7segment.h" +#if defined(CONFIG_DISPLAY_ENABLE_HD44780) +# include "i2c/hd44780.h" +#endif #include "hal_i2c.h" +#include "hal_gpio.h" + +namespace display { +namespace timeout { +static void gpio_init() { +#if defined (DISPLAYTIMEOUT_GPIO) + FUNC_PREFIX(gpio_fsel(DISPLAYTIMEOUT_GPIO, GPIO_FSEL_INPUT)); + FUNC_PREFIX(gpio_set_pud(DISPLAYTIMEOUT_GPIO, GPIO_PULL_UP)); +#endif +} +} // namespace timeout +} // namespace display Display *Display::s_pThis; @@ -55,8 +65,6 @@ Display::Display() : m_nMillis(Hardware::Get()->Millis()), m_I2C(display::segmen Detect(display::Type::SSD1306); } - Detect7Segment(); - if (m_LcdDisplay != nullptr) { display::timeout::gpio_init(); } @@ -70,8 +78,6 @@ Display::Display(uint32_t nRows) : m_nMillis(Hardware::Get()->Millis()), m_I2C(d Detect(nRows); - Detect7Segment(); - if (m_LcdDisplay != nullptr) { display::timeout::gpio_init(); } @@ -85,8 +91,6 @@ Display::Display(display::Type type): m_tType(type), m_nMillis(Hardware::Get()-> Detect(type); - Detect7Segment(); - if (m_LcdDisplay != nullptr) { display::timeout::gpio_init(); } diff --git a/lib-display/src/i2c/hd44780.cpp b/lib-display/src/i2c/hd44780.cpp index 070476ec..43990fc2 100644 --- a/lib-display/src/i2c/hd44780.cpp +++ b/lib-display/src/i2c/hd44780.cpp @@ -2,7 +2,7 @@ * @file hd44780.cpp * */ -/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -168,7 +168,7 @@ void Hd44780::ClearLine(uint32_t nLine) { } void Hd44780::PrintInfo() { - printf("HD44780 [PCF8574T] (%d,%d)\n", m_nRows, m_nCols); + printf("HD44780 [PCF8574T] (%u,%u)\n", static_cast(m_nRows), static_cast(m_nCols)); } void Hd44780::SetCursorPos(uint32_t nCol, uint32_t nRow) { @@ -200,7 +200,7 @@ void Hd44780::WriteReg(const uint8_t nReg) { #if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) # define UNUSED #else -# define UNUSED __attribute__((unused)) +# define UNUSED [[maybe_unused]] #endif void Hd44780::SetCursor(UNUSED uint32_t nMode) { diff --git a/lib-display/src/i2c/ssd1306.cpp b/lib-display/src/i2c/ssd1306.cpp index 5281a4fe..1829c105 100644 --- a/lib-display/src/i2c/ssd1306.cpp +++ b/lib-display/src/i2c/ssd1306.cpp @@ -233,7 +233,7 @@ Ssd1306::Ssd1306(uint8_t nSlaveAddress, TOledPanel tOledPanel) : m_I2C(nSlaveAdd } void Ssd1306::PrintInfo() { - printf("%s (%d,%d)\n", m_bHaveSH1106 ? "SH1106" : "SSD1306", m_nRows, m_nCols); + printf("%s (%u,%u)\n", m_bHaveSH1106 ? "SH1106" : "SSD1306", static_cast(m_nRows), static_cast(m_nCols)); } void Ssd1306::CheckSH1106() { @@ -513,7 +513,7 @@ void Ssd1306::SendData(const uint8_t *pData, uint32_t nLength) { #if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) # define UNUSED #else -# define UNUSED __attribute__((unused)) +# define UNUSED [[maybe_unused]] #endif void Ssd1306::SetCursor(UNUSED uint32_t nCursorMode) { diff --git a/lib-display/src/i2c/ssd1311.cpp b/lib-display/src/i2c/ssd1311.cpp index 5c9c76d8..712e48ad 100644 --- a/lib-display/src/i2c/ssd1311.cpp +++ b/lib-display/src/i2c/ssd1311.cpp @@ -101,7 +101,7 @@ bool Ssd1311::Start() { } void Ssd1311::PrintInfo() { - printf("SSD1311 (%d,%d)\n", m_nRows, m_nCols); + printf("SSD1311 (%u,%u)\n", static_cast(m_nRows), static_cast(m_nCols)); } void Ssd1311::Cls() { @@ -338,7 +338,7 @@ void Ssd1311::SetContrast(uint8_t nContrast) { #if defined(CONFIG_DISPLAY_ENABLE_CURSOR_MODE) # define UNUSED #else -# define UNUSED __attribute__((unused)) +# define UNUSED [[maybe_unused]] #endif void Ssd1311::SetCursor(UNUSED uint32_t nMode) { diff --git a/lib-display/src/spi/display.cpp b/lib-display/src/spi/display.cpp index 23f91db0..33018c23 100644 --- a/lib-display/src/spi/display.cpp +++ b/lib-display/src/spi/display.cpp @@ -2,7 +2,7 @@ * @file display.cpp * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -58,13 +58,13 @@ Display::Display() : m_nMillis(Hardware::Get()->Millis()) { FUNC_PREFIX(spi_set_speed_hz(20000000)); FUNC_PREFIX(spi_setDataMode(SPI_MODE0)); -#if defined (SPI_LCD_RST_PIN) - FUNC_PREFIX(gpio_fsel(SPI_LCD_RST_PIN, GPIO_FSEL_OUTPUT)); +#if defined (SPI_LCD_RST_GPIO) + FUNC_PREFIX(gpio_fsel(SPI_LCD_RST_GPIO, GPIO_FSEL_OUTPUT)); #endif - FUNC_PREFIX(gpio_fsel(SPI_LCD_DC_PIN, GPIO_FSEL_OUTPUT)); - FUNC_PREFIX(gpio_fsel(SPI_LCD_BL_PIN, GPIO_FSEL_OUTPUT)); -#if defined(SPI_LCD_HAVE_CS_PIN) - FUNC_PREFIX(gpio_fsel(SPI_LCD_CS_PIN, GPIO_FSEL_OUTPUT)); + FUNC_PREFIX(gpio_fsel(SPI_LCD_DC_GPIO, GPIO_FSEL_OUTPUT)); + FUNC_PREFIX(gpio_fsel(SPI_LCD_BL_GPIO, GPIO_FSEL_OUTPUT)); +#if defined(SPI_LCD_HAVE_CS_GPIO) + FUNC_PREFIX(gpio_fsel(SPI_LCD_CS_GPIO, GPIO_FSEL_OUTPUT)); #endif SpiLcd.SetBackLight(1); @@ -75,7 +75,10 @@ Display::Display() : m_nMillis(Hardware::Get()->Millis()) { m_nCols = static_cast(SpiLcd.GetWidth() / s_pFONT->Width); m_nRows = static_cast(SpiLcd.GetHeight() / s_pFONT->Height); - display::timeout::gpio_init(); +#if defined (DISPLAYTIMEOUT_GPIO) + FUNC_PREFIX(gpio_fsel(DISPLAYTIMEOUT_GPIO, GPIO_FSEL_INPUT)); + FUNC_PREFIX(gpio_set_pud(DISPLAYTIMEOUT_GPIO, GPIO_PULL_UP)); +#endif PrintInfo(); DEBUG_EXIT diff --git a/lib-display/src/spi/ili9341.cpp b/lib-display/src/spi/ili9341.cpp index f79903ed..2a9b40f1 100644 --- a/lib-display/src/spi/ili9341.cpp +++ b/lib-display/src/spi/ili9341.cpp @@ -50,7 +50,7 @@ ILI9341::~ILI9341() { void ILI9341::Init() { DEBUG_ENTRY -#if defined(SPI_LCD_RST_PIN) +#if defined(SPI_LCD_RST_GPIO) HW_Reset(); #endif @@ -161,7 +161,7 @@ void ILI9341::SetRotation(uint32_t nRotation) { } void ILI9341::SetBackLight(uint32_t nValue) { - FUNC_PREFIX(gpio_write(SPI_LCD_BL_PIN, nValue == 0 ? LOW : HIGH)); + FUNC_PREFIX(gpio_write(SPI_LCD_BL_GPIO, nValue == 0 ? LOW : HIGH)); } void ILI9341::EnableDisplay(bool bEnable) { diff --git a/lib-display/src/spi/st7789.cpp b/lib-display/src/spi/st7789.cpp index 4a340097..0a25be27 100644 --- a/lib-display/src/spi/st7789.cpp +++ b/lib-display/src/spi/st7789.cpp @@ -51,7 +51,7 @@ ST7789::~ST7789() { void ST7789::Init() { DEBUG_ENTRY -#if defined(SPI_LCD_RST_PIN) +#if defined(SPI_LCD_RST_GPIO) HW_Reset(); #endif diff --git a/lib-display/src/spi/st7xx.cpp b/lib-display/src/spi/st7xx.cpp index d4ddaefc..cf613c97 100644 --- a/lib-display/src/spi/st7xx.cpp +++ b/lib-display/src/spi/st7xx.cpp @@ -58,7 +58,7 @@ void ST77XX::EnableSleep(bool bEnable) { //TODO This should be a PWM pin void ST77XX::SetBackLight(uint32_t nValue) { - FUNC_PREFIX(gpio_write(SPI_LCD_BL_PIN, nValue == 0 ? LOW : HIGH)); + FUNC_PREFIX(gpio_write(SPI_LCD_BL_GPIO, nValue == 0 ? LOW : HIGH)); } void ST77XX::SetAddressWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { diff --git a/lib-displayudf/.cproject b/lib-displayudf/.cproject index ed8e9c9d..73bad53a 100644 --- a/lib-displayudf/.cproject +++ b/lib-displayudf/.cproject @@ -30,12 +30,10 @@ - diff --git a/lib-displayudf/Rules.mk b/lib-displayudf/Rules.mk index 582d95d9..4ef90723 100644 --- a/lib-displayudf/Rules.mk +++ b/lib-displayudf/Rules.mk @@ -6,21 +6,31 @@ ifneq ($(MAKE_FLAGS),) EXTRA_INCLUDES+=../lib-rdm/include ../lib-rdmdiscovery/include EXTRA_SRCDIR+=src/node endif + ifneq (,$(findstring NODE_ARTNET,$(MAKE_FLAGS))) EXTRA_INCLUDES+=../lib-artnet/include EXTRA_SRCDIR+=src/artnet ifeq ($(findstring ARTNET_VERSION=4,$(MAKE_FLAGS)), ARTNET_VERSION=4) EXTRA_INCLUDES+=../lib-e131/include endif + EXTRA_INCLUDES+=../lib-dmx/include endif + ifneq (,$(findstring NODE_E131,$(MAKE_FLAGS))) EXTRA_INCLUDES+=../lib-e131/include + EXTRA_INCLUDES+=../lib-dmx/include EXTRA_SRCDIR+=src/e131 endif + ifeq (,$(findstring NO_EMAC,$(MAKE_FLAGS))) EXTRA_INCLUDES+=../lib-network/include EXTRA_SRCDIR+=src/network endif + + ifneq (,$(findstring RDM_CONTROLLER,$(MAKE_FLAGS))) + EXTRA_INCLUDES+=../lib-rdm/include + endif + ifneq (,$(findstring RDM_RESPONDER,$(MAKE_FLAGS))) EXTRA_INCLUDES+=../lib-rdmresponder/include ../lib-rdm/include ../lib-rdmsensor/include ../lib-rdmsubdevice/include ifneq (,$(findstring NODE_ARTNET,$(MAKE_FLAGS))) @@ -28,16 +38,25 @@ ifneq ($(MAKE_FLAGS),) EXTRA_INCLUDES+=../lib-dmxreceiver/include ../lib-dmx/include endif endif + + ifneq (,$(findstring CONFIG_STORE_USE_ROM,$(MAKE_FLAGS))) + EXTRA_INCLUDES+=../lib-flashcode/include + endif else - DEFINES+=NODE_ARTNET NODE_E131 OUTPUT_DMX_ARTNET RDM_RESPONDER + ifneq (, $(shell test -d '../lib-network/src/noemac' && echo -n yes)) + DEFINES+=NO_EMAC + else + DEFINES+=NODE_ARTNET NODE_E131 OUTPUT_DMX_ARTNET + DEFINES+=ARTNET_VERSION=4 + EXTRA_SRCDIR+=src/artnet src/e131 src/network + EXTRA_INCLUDES+=../lib-artnet/include ../lib-e131/include ../lib-network/include + EXTRA_INCLUDES+=../lib-node/include + endif + + DEFINES+=RDM_RESPONDER DEFINES+=LIGHTSET_PORTS=4 - DEFINES+=ARTNET_VERSION=4 - EXTRA_INCLUDES+=../lib-node/include - EXTRA_INCLUDES+=../lib-artnet/include ../lib-e131/include ../lib-network/include EXTRA_INCLUDES+=../lib-dmxreceiver/include ../lib-dmx/include EXTRA_INCLUDES+=../lib-rdmdiscovery/include - EXTRA_INCLUDES+=../lib-rdmresponder/include ../lib-rdm/include ../lib-rdmsensor/include ../lib-rdmsubdevice/include - - EXTRA_SRCDIR+=src/artnet src/e131 src/network + EXTRA_INCLUDES+=../lib-rdm/include ../lib-rdmsensor/include ../lib-rdmsubdevice/include endif \ No newline at end of file diff --git a/lib-displayudf/include/displayudf.h b/lib-displayudf/include/displayudf.h index 1aae9355..d36ac873 100644 --- a/lib-displayudf/include/displayudf.h +++ b/lib-displayudf/include/displayudf.h @@ -2,7 +2,7 @@ * @file displayudf.h * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,6 +33,7 @@ #if !defined (NO_EMAC) # include "network.h" +# include "net/protocol/dhcp.h" #endif #if defined (NODE_ARTNET_MULTI) @@ -60,11 +61,7 @@ #endif #if defined (RDM_RESPONDER) -# if defined (NODE_ARTNET) -# include "artnetrdmresponder.h" -# else -# include "rdmresponder.h" -# endif +# include "rdmdeviceresponder.h" #endif namespace displayudf { @@ -164,33 +161,12 @@ class DisplayUdf final: public Display { void Show(); - /** - * Node - */ - -#if defined (NODE_NODE) - void Show(Node *pNode); - void ShowNodeName(); - void ShowUniverse(); - void ShowDestinationIp(); -#endif - /** * Art-Net */ #if defined (NODE_ARTNET) - void Show(ArtNetNode *pArtNetNode, uint32_t nPortIndexOffset = 0); - void ShowUniverse(ArtNetNode *pArtNetNode); - void ShowDestinationIp(ArtNetNode *pArtNetNode); -#endif - - /** - * sACN E1.31 - */ - -#if defined (NODE_E131) - void Show(E131Bridge *pE131Bridge, uint32_t nPortIndexOffset = 0); + void ShowUniverseArtNetNode(); #endif /** @@ -219,13 +195,8 @@ class DisplayUdf final: public Display { #if defined (RDM_RESPONDER) void ShowDmxStartAddress() { -# if defined (NODE_ARTNET) - const auto nDmxStartAddress = ArtNetRdmResponder::Get()->GetDmxStartAddress(); - const auto nDmxFootprint = ArtNetRdmResponder::Get()->GetDmxFootPrint(); -# else - const auto nDmxStartAddress = RDMResponder::Get()->GetDmxStartAddress(); - const auto nDmxFootprint = RDMResponder::Get()->GetDmxFootPrint(); -# endif + const auto nDmxStartAddress = RDMDeviceResponder::Get()->GetDmxStartAddress(); + const auto nDmxFootprint = RDMDeviceResponder::Get()->GetDmxFootPrint(); Printf(m_aLabels[static_cast(displayudf::Labels::DMX_START_ADDRESS)], "DMX S:%3u F:%3u", nDmxStartAddress, nDmxFootprint); } #endif @@ -271,25 +242,15 @@ class DisplayUdf final: public Display { Write(m_aLabels[static_cast(displayudf::Labels::HOSTNAME)], Network::Get()->GetHostName()); } - void ShowDhcpStatus(network::dhcp::ClientStatus nStatus) { - switch (nStatus) { - case network::dhcp::ClientStatus::IDLE: + void ShowDhcpStatus(net::dhcp::State state) { + switch (state) { + case net::dhcp::State::STATE_OFF: break; - case network::dhcp::ClientStatus::RENEW: - Display::Get()->Status(Display7SegmentMessage::INFO_DHCP); + case net::dhcp::State::STATE_RENEWING: ClearEndOfLine(); Printf(m_aLabels[static_cast(displayudf::Labels::IP)], "DHCP renewing"); break; - case network::dhcp::ClientStatus::GOT_IP: - Display::Get()->Status(Display7SegmentMessage::INFO_NONE); - break; - case network::dhcp::ClientStatus::RETRYING: - Display::Get()->Status(Display7SegmentMessage::INFO_DHCP); - ClearEndOfLine(); - Printf(m_aLabels[static_cast(displayudf::Labels::IP)], "DHCP retrying"); - break; - case network::dhcp::ClientStatus::FAILED: - Display::Get()->Status(Display7SegmentMessage::ERROR_DHCP); + case net::dhcp::State::STATE_BOUND: break; default: break; @@ -297,7 +258,7 @@ class DisplayUdf final: public Display { } void ShowShutdown() { - TextStatus("Network shutdown", Display7SegmentMessage::INFO_NETWORK_SHUTDOWN); + TextStatus("Network shutdown"); } #endif @@ -305,12 +266,38 @@ class DisplayUdf final: public Display { return s_pThis; } +private: + /** + * Art-Net + */ + +#if defined (NODE_ARTNET) + void ShowArtNetNode(); + void ShowDestinationIpArtNetNode(); +#endif + + /** + * sACN E1.31 + */ + +#if defined (NODE_E131) + void ShowE131Bridge(); +#endif + + /** + * Node + */ + +#if defined (NODE_NODE) + void ShowNode(); + void ShowNodeNameNode(); + void ShowUniverseNode(); + void ShowDestinationIpNode(); +#endif + private: char m_aTitle[32]; uint8_t m_aLabels[static_cast(displayudf::Labels::UNKNOWN)]; -#if defined (NODE_ARTNET) || defined (NODE_E131) - uint32_t m_nPortIndexOffset { 0 }; -#endif #if defined (DISPLAYUDF_DMX_INFO) struct DmxInfo { displayudf::dmx::PortDir portDir; diff --git a/lib-displayudf/include/displayudfparams.h b/lib-displayudf/include/displayudfparams.h index f50d4a66..b2c85c5b 100644 --- a/lib-displayudf/include/displayudfparams.h +++ b/lib-displayudf/include/displayudfparams.h @@ -29,6 +29,7 @@ #include #include "displayudf.h" +#include "configstore.h" namespace displayudfparams { struct Params { @@ -50,39 +51,40 @@ struct Mask { class DisplayUdfParamsStore { public: - virtual ~DisplayUdfParamsStore() {} + static void Update(const struct displayudfparams::Params *pParams) { + ConfigStore::Get()->Update(configstore::Store::DISPLAYUDF, pParams, sizeof(struct displayudfparams::Params)); + } - virtual void Update(const struct displayudfparams::Params *ptDisplayUdfParams)=0; - virtual void Copy(struct displayudfparams::Params *ptDisplayUdfParams)=0; + static void Copy(struct displayudfparams::Params *pParams) { + ConfigStore::Get()->Copy(configstore::Store::DISPLAYUDF, pParams, sizeof(struct displayudfparams::Params)); + } }; class DisplayUdfParams { public: - DisplayUdfParams(DisplayUdfParamsStore *pDisplayUdfParamsStore); + DisplayUdfParams(); - bool Load(); + void Load(); void Load(const char *pBuffer, uint32_t nLength); - void Builder(const struct displayudfparams::Params *ptDisplayUdfParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); + void Builder(const struct displayudfparams::Params *pParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); void Save(char *pBuffer, uint32_t nLength, uint32_t& nSize) { Builder(nullptr, pBuffer, nLength, nSize); } void Set(DisplayUdf *pDisplayUdf); - void Dump(); - static void staticCallbackFunction(void *p, const char *s); private: + void Dump(); void callbackFunction(const char *s); bool isMaskSet(uint32_t nMask) const { - return (m_tDisplayUdfParams.nSetList & nMask) == nMask; + return (m_Params.nSetList & nMask) == nMask; } private: - DisplayUdfParamsStore *m_pDisplayUdfParamsStore; - displayudfparams::Params m_tDisplayUdfParams; + displayudfparams::Params m_Params; }; #endif /* DISPLAYUDFPARAMS_H_ */ diff --git a/lib-displayudf/include/displayudfparamsconst.h b/lib-displayudf/include/displayudfparamsconst.h index bb5c9a22..993f92c5 100644 --- a/lib-displayudf/include/displayudfparamsconst.h +++ b/lib-displayudf/include/displayudfparamsconst.h @@ -2,7 +2,7 @@ * @file displayudfparamsconst.h * */ -/* Copyright (C) 2019-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-displayudf/src/artnet/artnetdisplay.cpp b/lib-displayudf/src/artnet/artnetdisplay.cpp index d173f76d..2a73757e 100644 --- a/lib-displayudf/src/artnet/artnetdisplay.cpp +++ b/lib-displayudf/src/artnet/artnetdisplay.cpp @@ -2,7 +2,7 @@ * @file artnetdisplay.cpp * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,38 +30,38 @@ #include "lightset.h" namespace artnet { -void display_longname(__attribute__((unused)) const char *pLongName) { +void display_longname([[maybe_unused]] const char *pLongName) { } -void display_universe_switch(__attribute__((unused)) uint32_t nPortIndex, __attribute__((unused)) uint8_t nAddress) { - DisplayUdf::Get()->ShowUniverse(ArtNetNode::Get()); +void display_universe_switch([[maybe_unused]] uint32_t nPortIndex, [[maybe_unused]] uint8_t nAddress) { + DisplayUdf::Get()->ShowUniverseArtNetNode(); } -void display_net_switch(__attribute__((unused)) uint8_t nAddress) { - DisplayUdf::Get()->ShowUniverse(ArtNetNode::Get()); +void display_net_switch([[maybe_unused]] uint8_t nAddress) { + DisplayUdf::Get()->ShowUniverseArtNetNode(); } -void display_subnet_switch(__attribute__((unused)) uint8_t nAddress) { - DisplayUdf::Get()->ShowUniverse(ArtNetNode::Get()); +void display_subnet_switch([[maybe_unused]] uint8_t nAddress) { + DisplayUdf::Get()->ShowUniverseArtNetNode(); } -void display_merge_mode(__attribute__((unused)) uint32_t nPortIndex, __attribute__((unused)) lightset::MergeMode mergeMode) { - DisplayUdf::Get()->ShowUniverse(ArtNetNode::Get()); +void display_merge_mode([[maybe_unused]] uint32_t nPortIndex, [[maybe_unused]] lightset::MergeMode mergeMode) { + DisplayUdf::Get()->ShowUniverseArtNetNode(); } -void display_outputstyle(__attribute__((unused)) const uint32_t nPortIndex, __attribute__((unused)) const lightset::OutputStyle outputStyle) { - DisplayUdf::Get()->ShowUniverse(ArtNetNode::Get()); +void display_outputstyle([[maybe_unused]] const uint32_t nPortIndex, [[maybe_unused]] const lightset::OutputStyle outputStyle) { + DisplayUdf::Get()->ShowUniverseArtNetNode(); } -void display_port_protocol(__attribute__((unused)) uint32_t nPortIndex, __attribute__((unused)) artnet::PortProtocol tPortProtocol) { - DisplayUdf::Get()->ShowUniverse(ArtNetNode::Get()); +void display_port_protocol([[maybe_unused]] uint32_t nPortIndex, [[maybe_unused]] artnet::PortProtocol tPortProtocol) { + DisplayUdf::Get()->ShowUniverseArtNetNode(); } -void display_rdm_enabled(__attribute__((unused)) uint32_t nPortIndex, __attribute__((unused)) bool isEnabled) { - DisplayUdf::Get()->ShowUniverse(ArtNetNode::Get()); +void display_rdm_enabled([[maybe_unused]] uint32_t nPortIndex, [[maybe_unused]] bool isEnabled) { + DisplayUdf::Get()->ShowUniverseArtNetNode(); } -void display_failsafe(__attribute__((unused)) uint8_t nFailsafe) { +void display_failsafe([[maybe_unused]] uint8_t nFailsafe) { //TODO ShowFailSafe } } // namespace artnet diff --git a/lib-displayudf/src/artnet/displayudfshowartnet.cpp b/lib-displayudf/src/artnet/displayudfshowartnet.cpp index 93195b16..3f4039ed 100644 --- a/lib-displayudf/src/artnet/displayudfshowartnet.cpp +++ b/lib-displayudf/src/artnet/displayudfshowartnet.cpp @@ -2,7 +2,7 @@ * @file displayudfshowartnet.cpp * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,18 +35,21 @@ #include "debug.h" -void DisplayUdf::Show(ArtNetNode *pArtNetNode, uint32_t nDmxPortIndexOffset) { - DEBUG_ENTRY - - m_nPortIndexOffset = nDmxPortIndexOffset; +namespace artnetnode { +namespace configstore { +extern uint32_t DMXPORT_OFFSET; +} // namespace configstore +} // namespace artnetnode - DEBUG_PRINTF("m_nPortIndexOffset=%u", m_nPortIndexOffset); +void DisplayUdf::ShowArtNetNode() { + DEBUG_ENTRY + DEBUG_PRINTF("artnetnode::configstore::DMXPORT_OFFSET=%u", artnetnode::configstore::DMXPORT_OFFSET); - Show(); + auto *pArtNetNode = ArtNetNode::Get(); - ShowUniverse(pArtNetNode); + ShowUniverseArtNetNode(); #if defined (ARTNET_HAVE_DMXIN) - ShowDestinationIp(pArtNetNode); + ShowDestinationIpArtNetNode(); #endif Printf(m_aLabels[static_cast(displayudf::Labels::AP)], "AP: %d", pArtNetNode->GetActiveOutputPorts() + pArtNetNode->GetActiveInputPorts()); @@ -55,12 +58,14 @@ void DisplayUdf::Show(ArtNetNode *pArtNetNode, uint32_t nDmxPortIndexOffset) { DEBUG_EXIT } -void DisplayUdf::ShowUniverse(ArtNetNode *pArtNetNode) { +void DisplayUdf::ShowUniverseArtNetNode() { DEBUG_ENTRY + + auto *pArtNetNode = ArtNetNode::Get(); uint16_t nUniverse; for (uint32_t nArtNetPortIndex = 0; nArtNetPortIndex < std::min(artnet::PORTS, artnetnode::MAX_PORTS); nArtNetPortIndex++) { - const auto nPortIndex = nArtNetPortIndex + m_nPortIndexOffset; + const auto nPortIndex = nArtNetPortIndex + artnetnode::configstore::DMXPORT_OFFSET; if (nPortIndex >= std::min(artnet::PORTS, artnetnode::MAX_PORTS)) { break; @@ -80,7 +85,11 @@ void DisplayUdf::ShowUniverse(ArtNetNode *pArtNetNode) { 'A' + nArtNetPortIndex, nUniverse, lightset::get_merge_mode(pArtNetNode->GetMergeMode(nPortIndex), true), +#if (ARTNET_VERSION >= 4) artnet::get_protocol_mode(pArtNetNode->GetPortProtocol4(nPortIndex), true), +#else + "Art-Net", +#endif #if defined (OUTPUT_HAVE_STYLESWITCH) pArtNetNode->GetOutputStyle(nPortIndex) == lightset::OutputStyle::CONSTANT ? 'C' : 'D', #endif @@ -93,9 +102,11 @@ void DisplayUdf::ShowUniverse(ArtNetNode *pArtNetNode) { DEBUG_EXIT } -void DisplayUdf::ShowDestinationIp(ArtNetNode *pArtNetNode) { +void DisplayUdf::ShowDestinationIpArtNetNode() { DEBUG_ENTRY + auto *pArtNetNode = ArtNetNode::Get(); + for (uint32_t nPortIndex = 0; nPortIndex < std::min(artnet::PORTS, artnetnode::MAX_PORTS); nPortIndex++) { Printf(m_aLabels[static_cast(displayudf::Labels::DESTINATION_IP_PORT_A) + nPortIndex], "%c: " IPSTR, 'A' + nPortIndex, IP2STR(pArtNetNode->GetDestinationIp(nPortIndex))); } diff --git a/lib-displayudf/src/displayudf.cpp b/lib-displayudf/src/displayudf.cpp index 4917c844..2548254e 100644 --- a/lib-displayudf/src/displayudf.cpp +++ b/lib-displayudf/src/displayudf.cpp @@ -29,9 +29,7 @@ #include #include "displayudf.h" - #include "display.h" -#include "display7segment.h" #include "lightset.h" #include "network.h" @@ -87,6 +85,14 @@ void DisplayUdf::Set(uint32_t nLine, Labels label) { } void DisplayUdf::Show() { +#if defined (NODE_ARTNET) + ShowArtNetNode(); +#elif defined (NODE_E131) + ShowE131Bridge(); +#elif defined (NODE_NODE) + ShowNode(); +#endif + for (uint32_t i = 0; i < static_cast(Labels::UNKNOWN); i++) { if (m_aLabels[i] > LABEL_MAX_ROWS) { m_aLabels[i] = 0xFF; diff --git a/lib-displayudf/src/displayudfparams.cpp b/lib-displayudf/src/displayudfparams.cpp index 00e122a6..50081b1b 100644 --- a/lib-displayudf/src/displayudfparams.cpp +++ b/lib-displayudf/src/displayudfparams.cpp @@ -51,7 +51,6 @@ #include "readconfigfile.h" #include "sscan.h" - #include "propertiesbuilder.h" #include "display.h" @@ -140,31 +139,34 @@ static constexpr const char *pArray[static_cast(Labels::UNKNOWN)] = { # undef MAX_ARRAY #endif -DisplayUdfParams::DisplayUdfParams(DisplayUdfParamsStore *pDisplayUdfParamsStore): m_pDisplayUdfParamsStore(pDisplayUdfParamsStore) { - memset(&m_tDisplayUdfParams, 0, sizeof(struct displayudfparams::Params)); - m_tDisplayUdfParams.nSleepTimeout = display::Defaults::SEEP_TIMEOUT; - m_tDisplayUdfParams.nIntensity = defaults::INTENSITY; +DisplayUdfParams::DisplayUdfParams() { + DEBUG_ENTRY + + memset(&m_Params, 0, sizeof(struct displayudfparams::Params)); + m_Params.nSleepTimeout = display::Defaults::SEEP_TIMEOUT; + m_Params.nIntensity = defaults::INTENSITY; + + DEBUG_EXIT } -bool DisplayUdfParams::Load() { - m_tDisplayUdfParams.nSetList = 0; +void DisplayUdfParams::Load() { + DEBUG_ENTRY + + m_Params.nSetList = 0; #if !defined(DISABLE_FS) ReadConfigFile configfile(DisplayUdfParams::staticCallbackFunction, this); if (configfile.Read(DisplayUdfParamsConst::FILE_NAME)) { - if (m_pDisplayUdfParamsStore != nullptr) { - m_pDisplayUdfParamsStore->Update(&m_tDisplayUdfParams); - } + DisplayUdfParamsStore::Update(&m_Params); } else #endif - if (m_pDisplayUdfParamsStore != nullptr) { - m_pDisplayUdfParamsStore->Copy(&m_tDisplayUdfParams); - } else { - return false; - } + DisplayUdfParamsStore::Copy(&m_Params); - return true; +#ifndef NDEBUG + Dump(); +#endif + DEBUG_EXIT } void DisplayUdfParams::Load(const char *pBuffer, uint32_t nLength) { @@ -173,15 +175,17 @@ void DisplayUdfParams::Load(const char *pBuffer, uint32_t nLength) { assert(pBuffer != nullptr); assert(nLength != 0); - m_tDisplayUdfParams.nSetList = 0; + m_Params.nSetList = 0; ReadConfigFile config(DisplayUdfParams::staticCallbackFunction, this); config.Read(pBuffer, nLength); - assert(m_pDisplayUdfParamsStore != nullptr); - m_pDisplayUdfParamsStore->Update(&m_tDisplayUdfParams); + DisplayUdfParamsStore::Update(&m_Params); +#ifndef NDEBUG + Dump(); +#endif DEBUG_EXIT } @@ -190,32 +194,32 @@ void DisplayUdfParams::callbackFunction(const char *pLine) { uint8_t value8; if (Sscan::Uint8(pLine, DisplayUdfParamsConst::INTENSITY, value8) == Sscan::OK) { - m_tDisplayUdfParams.nIntensity = value8; + m_Params.nIntensity = value8; if (value8 != defaults::INTENSITY) { - m_tDisplayUdfParams.nSetList |= displayudfparams::Mask::INTENSITY; + m_Params.nSetList |= displayudfparams::Mask::INTENSITY; } else { - m_tDisplayUdfParams.nSetList &= ~displayudfparams::Mask::INTENSITY; + m_Params.nSetList &= ~displayudfparams::Mask::INTENSITY; } return; } if (Sscan::Uint8(pLine, DisplayUdfParamsConst::SLEEP_TIMEOUT, value8) == Sscan::OK) { - m_tDisplayUdfParams.nSleepTimeout = value8; + m_Params.nSleepTimeout = value8; if (value8 != display::Defaults::SEEP_TIMEOUT) { - m_tDisplayUdfParams.nSetList |= displayudfparams::Mask::SLEEP_TIMEOUT; + m_Params.nSetList |= displayudfparams::Mask::SLEEP_TIMEOUT; } else { - m_tDisplayUdfParams.nSetList &= ~displayudfparams::Mask::SLEEP_TIMEOUT; + m_Params.nSetList &= ~displayudfparams::Mask::SLEEP_TIMEOUT; } return; } if (Sscan::Uint8(pLine, DisplayUdfParamsConst::FLIP_VERTICALLY, value8) == Sscan::OK) { if (value8 != 0) { - m_tDisplayUdfParams.nSetList |= displayudfparams::Mask::FLIP_VERTICALLY; + m_Params.nSetList |= displayudfparams::Mask::FLIP_VERTICALLY; } else { - m_tDisplayUdfParams.nSetList &= ~displayudfparams::Mask::FLIP_VERTICALLY; + m_Params.nSetList &= ~displayudfparams::Mask::FLIP_VERTICALLY; } return; } @@ -223,11 +227,11 @@ void DisplayUdfParams::callbackFunction(const char *pLine) { for (uint32_t i = 0; i < static_cast(Labels::UNKNOWN); i++) { if (Sscan::Uint8(pLine, pArray[i], value8) == Sscan::OK) { if ((value8 > 0) && (value8 <= LABEL_MAX_ROWS)) { - m_tDisplayUdfParams.nLabelIndex[i] = value8; - m_tDisplayUdfParams.nSetList |= (1U << i); + m_Params.nLabelIndex[i] = value8; + m_Params.nSetList |= (1U << i); } else { - m_tDisplayUdfParams.nLabelIndex[i] = 0; - m_tDisplayUdfParams.nSetList &= ~(1U << i); + m_Params.nLabelIndex[i] = 0; + m_Params.nSetList &= ~(1U << i); } return; } @@ -238,21 +242,21 @@ void DisplayUdfParams::Builder(const struct displayudfparams::Params *ptDisplayU assert(pBuffer != nullptr); if (ptDisplayUdfParams != nullptr) { - memcpy(&m_tDisplayUdfParams, ptDisplayUdfParams, sizeof(struct displayudfparams::Params)); + memcpy(&m_Params, ptDisplayUdfParams, sizeof(struct displayudfparams::Params)); } else { assert(m_pDisplayUdfParamsStore != nullptr); - m_pDisplayUdfParamsStore->Copy(&m_tDisplayUdfParams); + DisplayUdfParamsStore::Copy(&m_Params); } PropertiesBuilder builder(DisplayUdfParamsConst::FILE_NAME, pBuffer, nLength); - builder.Add(DisplayUdfParamsConst::INTENSITY, m_tDisplayUdfParams.nIntensity , isMaskSet(displayudfparams::Mask::INTENSITY)); - builder.Add(DisplayUdfParamsConst::SLEEP_TIMEOUT, m_tDisplayUdfParams.nSleepTimeout , isMaskSet(displayudfparams::Mask::SLEEP_TIMEOUT)); + builder.Add(DisplayUdfParamsConst::INTENSITY, m_Params.nIntensity , isMaskSet(displayudfparams::Mask::INTENSITY)); + builder.Add(DisplayUdfParamsConst::SLEEP_TIMEOUT, m_Params.nSleepTimeout , isMaskSet(displayudfparams::Mask::SLEEP_TIMEOUT)); builder.Add(DisplayUdfParamsConst::FLIP_VERTICALLY, isMaskSet(displayudfparams::Mask::FLIP_VERTICALLY) , isMaskSet(displayudfparams::Mask::FLIP_VERTICALLY)); for (uint32_t i = 0; i < static_cast(Labels::UNKNOWN); i++) { if (pArray[i][0] != '\0') { - builder.Add(pArray[i], m_tDisplayUdfParams.nLabelIndex[i] , isMaskSet(1U << i)); + builder.Add(pArray[i], m_Params.nLabelIndex[i] , isMaskSet(1U << i)); } } @@ -263,18 +267,18 @@ void DisplayUdfParams::Set(DisplayUdf *pDisplayUdf) { assert(pDisplayUdf != nullptr); if (isMaskSet(displayudfparams::Mask::INTENSITY)) { - pDisplayUdf->SetContrast(m_tDisplayUdfParams.nIntensity); + pDisplayUdf->SetContrast(m_Params.nIntensity); } if (isMaskSet(displayudfparams::Mask::SLEEP_TIMEOUT)) { - pDisplayUdf->SetSleepTimeout(m_tDisplayUdfParams.nSleepTimeout); + pDisplayUdf->SetSleepTimeout(m_Params.nSleepTimeout); } pDisplayUdf->SetFlipVertically(isMaskSet(displayudfparams::Mask::FLIP_VERTICALLY)); for (uint32_t i = 0; i < static_cast(Labels::UNKNOWN); i++) { if (isMaskSet(1U << i)) { - pDisplayUdf->Set(m_tDisplayUdfParams.nLabelIndex[i], static_cast(i)); + pDisplayUdf->Set(m_Params.nLabelIndex[i], static_cast(i)); } } } @@ -287,15 +291,14 @@ void DisplayUdfParams::staticCallbackFunction(void *p, const char *s) { } void DisplayUdfParams::Dump() { -#ifndef NDEBUG printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, DisplayUdfParamsConst::FILE_NAME); if (isMaskSet(displayudfparams::Mask::INTENSITY)) { - printf(" %s=%d\n", DisplayUdfParamsConst::INTENSITY, m_tDisplayUdfParams.nIntensity); + printf(" %s=%d\n", DisplayUdfParamsConst::INTENSITY, m_Params.nIntensity); } if (isMaskSet(displayudfparams::Mask::SLEEP_TIMEOUT)) { - printf(" %s=%d\n", DisplayUdfParamsConst::SLEEP_TIMEOUT, m_tDisplayUdfParams.nSleepTimeout); + printf(" %s=%d\n", DisplayUdfParamsConst::SLEEP_TIMEOUT, m_Params.nSleepTimeout); } if (isMaskSet(displayudfparams::Mask::FLIP_VERTICALLY)) { @@ -304,8 +307,7 @@ void DisplayUdfParams::Dump() { for (uint32_t i = 0; i < static_cast(Labels::UNKNOWN); i++) { if (isMaskSet(1U << i)) { - printf(" %s=%d\n", pArray[i], m_tDisplayUdfParams.nLabelIndex[i]); + printf(" %s=%d\n", pArray[i], m_Params.nLabelIndex[i]); } } -#endif } diff --git a/lib-displayudf/src/e131/displayudfshowe131.cpp b/lib-displayudf/src/e131/displayudfshowe131.cpp index 3dced559..52dac38d 100644 --- a/lib-displayudf/src/e131/displayudfshowe131.cpp +++ b/lib-displayudf/src/e131/displayudfshowe131.cpp @@ -2,7 +2,7 @@ * @file displayudfshowe131.cpp * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,19 +32,22 @@ #include "debug.h" -void DisplayUdf::Show(E131Bridge *pE131Bridge, uint32_t nDmxPortIndexOffset) { - DEBUG_ENTRY - - m_nPortIndexOffset = nDmxPortIndexOffset; +namespace e131bridge { +namespace configstore { +extern uint32_t DMXPORT_OFFSET; +} // namespace configstore +} // namespace e131bridge - DEBUG_PRINTF("m_nDmxPortIndexOffset=%u", m_nPortIndexOffset); +void DisplayUdf::ShowE131Bridge() { + DEBUG_ENTRY + DEBUG_PRINTF("e131bridge::configstore::DMXPORT_OFFSET=%u", e131bridge::configstore::DMXPORT_OFFSET); - Show(); + auto *pE131Bridge = E131Bridge::Get(); Printf(m_aLabels[static_cast(displayudf::Labels::AP)], "AP: %d", pE131Bridge->GetActiveOutputPorts() + pE131Bridge->GetActiveInputPorts()); for (uint32_t nBridgePortIndex = 0; nBridgePortIndex < std::min(static_cast(4), e131bridge::MAX_PORTS); nBridgePortIndex++) { - const auto nPortIndex = nBridgePortIndex + m_nPortIndexOffset; + const auto nPortIndex = nBridgePortIndex + e131bridge::configstore::DMXPORT_OFFSET; if (nPortIndex >= std::min(static_cast(4), e131bridge::MAX_PORTS)) { break; diff --git a/lib-displayudf/src/network/network.cpp b/lib-displayudf/src/network/network.cpp index 2dd21847..4e4aa13e 100644 --- a/lib-displayudf/src/network/network.cpp +++ b/lib-displayudf/src/network/network.cpp @@ -2,7 +2,7 @@ * @file network.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,10 +23,12 @@ * THE SOFTWARE. */ -#include "network.h" +#undef NDEBUG + #include "displayudf.h" +#include "net/protocol/dhcp.h" -namespace network { +namespace net { void display_emac_config() { DisplayUdf::Get()->ShowEmacInit(); } @@ -59,7 +61,7 @@ void display_emac_shutdown() { DisplayUdf::Get()->ShowShutdown(); } -void display_dhcp_status(network::dhcp::ClientStatus status) { - DisplayUdf::Get()->ShowDhcpStatus(status); +void display_dhcp_status(net::dhcp::State state) { + DisplayUdf::Get()->ShowDhcpStatus(state); } } // namespace network diff --git a/lib-displayudf/src/network/ntpclient.cpp b/lib-displayudf/src/network/ntpclient.cpp index a6b8c76f..6d9d9149 100644 --- a/lib-displayudf/src/network/ntpclient.cpp +++ b/lib-displayudf/src/network/ntpclient.cpp @@ -2,7 +2,7 @@ * @file ntpclient.cpp * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,19 +23,23 @@ * THE SOFTWARE. */ -#include "ntpclient.h" +#include "net/protocol/ntp.h" #include "display.h" namespace ntpclient { -void display_status(ntpclient::Status status) { - if (status == ntpclient::Status::IDLE) { - Display::Get()->TextStatus("NTP Client", Display7SegmentMessage::INFO_NTP); - return; - } - - if (status == ntpclient::Status::FAILED) { - Display::Get()->TextStatus("Error: NTP", Display7SegmentMessage::ERROR_NTP); - return; +void display_status(const ::ntp::Status status) { + switch (status) { + case ::ntp::Status::STOPPED: + Display::Get()->TextStatus("No NTP Client"); + break; + case ::ntp::Status::IDLE: + Display::Get()->TextStatus("NTP Client"); + break; + case ::ntp::Status::FAILED: + Display::Get()->TextStatus("Error: NTP"); + break; + default: + break; } } } // namespace ntpclient diff --git a/lib-displayudf/src/node/displayudfshownode.cpp b/lib-displayudf/src/node/displayudfshownode.cpp index 0f178e9b..515667a8 100644 --- a/lib-displayudf/src/node/displayudfshownode.cpp +++ b/lib-displayudf/src/node/displayudfshownode.cpp @@ -2,7 +2,7 @@ * @file displayudfshownode.cpp * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,30 +35,28 @@ static constexpr auto MAX_PORTS = LIGHTSET_PORTS > 4U ? 4U : LIGHTSET_PORTS; -void DisplayUdf::Show(__attribute__((unused)) Node *pNode) { +void DisplayUdf::ShowNode() { DEBUG_ENTRY - Show(); - - ShowNodeName(); - ShowUniverse(); - ShowDestinationIp(); + ShowNodeNameNode(); + ShowUniverseNode(); + ShowDestinationIpNode(); DEBUG_EXIT } -void DisplayUdf::ShowNodeName() { +void DisplayUdf::ShowNodeNameNode() { ClearEndOfLine(); Write(m_aLabels[static_cast(displayudf::Labels::NODE_NAME)], Node::Get()->GetShortName()); } -void DisplayUdf::ShowUniverse() { +void DisplayUdf::ShowUniverseNode() { for (uint32_t nPortIndex = 0; nPortIndex < MAX_PORTS; nPortIndex++) { } } -void DisplayUdf::ShowDestinationIp() { +void DisplayUdf::ShowDestinationIpNode() { for (uint32_t i = 0; i < MAX_PORTS; i++) { Printf(m_aLabels[static_cast(displayudf::Labels::DESTINATION_IP_PORT_A) + i], "%c: " IPSTR, 'A' + i, IP2STR(Node::Get()->GetDestinationIp(i))); } diff --git a/lib-dmx/.cproject b/lib-dmx/.cproject index 6be7f39b..4520a6e3 100644 --- a/lib-dmx/.cproject +++ b/lib-dmx/.cproject @@ -5,7 +5,7 @@ - + @@ -14,15 +14,87 @@ - + - - @@ -113,10 +203,10 @@ - + - + @@ -128,25 +218,28 @@ - + - + - + - + - + - + + + + @@ -155,7 +248,10 @@ - + + + + diff --git a/lib-dmx/Makefile.GD32 b/lib-dmx/Makefile.GD32 index 3463847f..aef96da3 100644 --- a/lib-dmx/Makefile.GD32 +++ b/lib-dmx/Makefile.GD32 @@ -1,7 +1,11 @@ -DEFINES=OUTPUT_DMX_SEND_MULTI -DEFINES+=NDEBUG +DEFINES=NDEBUG EXTRA_INCLUDES=../lib-rdm/include ../lib-properties/include +ifneq ($(MAKE_FLAGS),) +else + DEFINES+=OUTPUT_DMX_SEND +endif + include Rules.mk include ../firmware-template-gd32/lib/Rules.mk diff --git a/lib-dmx/Rules.mk b/lib-dmx/Rules.mk old mode 100755 new mode 100644 index b51fbc3d..908ae815 --- a/lib-dmx/Rules.mk +++ b/lib-dmx/Rules.mk @@ -1,20 +1,3 @@ $(info $$MAKE_FLAGS [${MAKE_FLAGS}]) -ifneq ($(MAKE_FLAGS),) - ifeq ($(findstring NO_EMAC,$(MAKE_FLAGS)), NO_EMAC) - else - EXTRA_SRCDIR+=src/emac - EXTRA_INCLUDES+=../lib-network/include - endif - ifeq ($(findstring ARTNET_HAVE_DMXIN,$(MAKE_FLAGS)), ARTNET_HAVE_DMXIN) - EXTRA_SRCDIR+=src/artnet - endif - ifeq ($(findstring E131_HAVE_DMXIN,$(MAKE_FLAGS)), E131_HAVE_DMXIN) - EXTRA_SRCDIR+=src/e131 - endif -else - EXTRA_SRCDIR+=src/emac - EXTRA_SRCDIR+=src/artnet - EXTRA_SRCDIR+=src/e131 - EXTRA_INCLUDES+=../lib-network/include -endif +EXTRA_INCLUDES+=../lib-lightset/include \ No newline at end of file diff --git a/lib-dmx/include/dmxconfigudp.h b/lib-dmx/include/dmxconfigudp.h index 8de7f409..a0b92831 100755 --- a/lib-dmx/include/dmxconfigudp.h +++ b/lib-dmx/include/dmxconfigudp.h @@ -2,7 +2,7 @@ * @file dmxconfigudp.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -83,7 +83,7 @@ class DmxConfigUdp { uint16_t nForeignPort; auto nBytesReceived = Network::Get()->RecvFrom(s_nHandle, const_cast(reinterpret_cast(&s_pUdpBuffer)), &nIPAddressFrom, &nForeignPort); - if (__builtin_expect((!dmxconfigudp::validate(static_cast(nBytesReceived), dmxconfigudp::MIN_SIZE, dmxconfigudp::MAX_SIZE)), 1)) { + if (__builtin_expect((!dmxconfigudp::validate(nBytesReceived, dmxconfigudp::MIN_SIZE, dmxconfigudp::MAX_SIZE)), 1)) { return; } @@ -99,24 +99,24 @@ class DmxConfigUdp { const auto *pCmd = &s_pUdpBuffer[4]; - if (dmxconfigudp::validate(nBytesReceived, static_cast(12), static_cast(13)) && (memcmp("break#", pCmd, 6) == 0)) { - const auto nBreakTime = dmxconfigudp::atoi(reinterpret_cast(&s_pUdpBuffer[10]), nBytesReceived - 10); + if (dmxconfigudp::validate(nBytesReceived, static_cast(12), static_cast(13)) && (memcmp("break#", pCmd, 6) == 0)) { + const auto nBreakTime = dmxconfigudp::atoi(reinterpret_cast(&s_pUdpBuffer[10]), nBytesReceived - 10U); if (nBreakTime >= dmx::transmit::BREAK_TIME_MIN) { Dmx::Get()->SetDmxBreakTime(nBreakTime); } return; } - if (dmxconfigudp::validate(nBytesReceived, static_cast(10), static_cast(16)) && (memcmp("mab#", pCmd, 4) == 0)) { - const auto nMapTime = dmxconfigudp::atoi(reinterpret_cast(&s_pUdpBuffer[8]), nBytesReceived - 8); + if (dmxconfigudp::validate(nBytesReceived, static_cast(10), static_cast(16)) && (memcmp("mab#", pCmd, 4) == 0)) { + const auto nMapTime = dmxconfigudp::atoi(reinterpret_cast(&s_pUdpBuffer[8]), nBytesReceived - 8U); if (dmxconfigudp::validate(nMapTime, dmx::transmit::MAB_TIME_MIN, dmx::transmit::MAB_TIME_MAX)) { Dmx::Get()->SetDmxMabTime(nMapTime); } return; } - if (dmxconfigudp::validate(nBytesReceived, static_cast(13), static_cast(14)) && (memcmp("refresh#", pCmd, 8) == 0)) { - const auto nRefreshRate = dmxconfigudp::atoi(reinterpret_cast(&s_pUdpBuffer[12]), nBytesReceived - 12); + if (dmxconfigudp::validate(nBytesReceived, static_cast(13), static_cast(14)) && (memcmp("refresh#", pCmd, 8) == 0)) { + const auto nRefreshRate = dmxconfigudp::atoi(reinterpret_cast(&s_pUdpBuffer[12]), nBytesReceived - 12U); uint32_t nPeriodTime = 0; if (nRefreshRate != 0) { nPeriodTime = 1000000U / nRefreshRate; @@ -125,8 +125,8 @@ class DmxConfigUdp { return; } - if (dmxconfigudp::validate(nBytesReceived, static_cast(11), static_cast(13)) && (memcmp("slots#", pCmd, 6) == 0)) { - const auto nSlots = dmxconfigudp::atoi(reinterpret_cast(&s_pUdpBuffer[10]), nBytesReceived - 10); + if (dmxconfigudp::validate(nBytesReceived, static_cast(11), static_cast(13)) && (memcmp("slots#", pCmd, 6) == 0)) { + const auto nSlots = dmxconfigudp::atoi(reinterpret_cast(&s_pUdpBuffer[10]), nBytesReceived - 10U); if (dmxconfigudp::validate(nSlots, dmx::min::CHANNELS, dmx::max::CHANNELS)) { Dmx::Get()->SetDmxSlots(static_cast(nSlots)); } @@ -135,8 +135,8 @@ class DmxConfigUdp { } private: - static int32_t s_nHandle; - static char *s_pUdpBuffer; + int32_t s_nHandle { -1 }; + char *s_pUdpBuffer { nullptr }; }; #endif /* DMXCONFIGUDP_H_ */ diff --git a/lib-dmx/include/dmxparams.h b/lib-dmx/include/dmxparams.h index ec403189..c5a3f434 100644 --- a/lib-dmx/include/dmxparams.h +++ b/lib-dmx/include/dmxparams.h @@ -29,8 +29,10 @@ #include #include "dmx.h" +#include "configstore.h" -struct TDmxParams { +namespace dmxsendparams { +struct Params { uint32_t nSetList; uint16_t nBreakTime; uint16_t nMabTime; @@ -38,59 +40,59 @@ struct TDmxParams { uint8_t nSlotsCount; }__attribute__((packed)); -static_assert(sizeof(struct TDmxParams) <= 32, "struct TDmxParams is too large"); +static_assert(sizeof(struct Params) <= 32, "struct Params is too large"); -struct DmxParamsMask { - static constexpr auto BREAK_TIME = (1U << 0); - static constexpr auto MAB_TIME = (1U << 1); - static constexpr auto REFRESH_RATE = (1U << 2); - static constexpr auto SLOTS_COUNT = (1U << 3); +struct Mask { + static constexpr uint32_t BREAK_TIME = (1U << 0); + static constexpr uint32_t MAB_TIME = (1U << 1); + static constexpr uint32_t REFRESH_RATE = (1U << 2); + static constexpr uint32_t SLOTS_COUNT = (1U << 3); }; -namespace dmxparams { static constexpr uint8_t rounddown_slots(uint16_t n) { return static_cast((n / 2U) - 1); } static constexpr uint16_t roundup_slots(uint8_t n) { return static_cast((n + 1U) * 2U); } -} // namespace dmxparams +} // namespace dmxsendparams] -class DmxParamsStore { +class StoreDmxSend { public: - virtual ~DmxParamsStore() {} + static void Update(const struct dmxsendparams::Params *pParams) { + ConfigStore::Get()->Update(configstore::Store::DMXSEND, pParams, sizeof(struct dmxsendparams::Params)); + } - virtual void Update(const struct TDmxParams *pDmxParams)=0; - virtual void Copy(struct TDmxParams *pDmxParams)=0; + static void Copy(struct dmxsendparams::Params *pParams) { + ConfigStore::Get()->Copy(configstore::Store::DMXSEND, pParams, sizeof(struct dmxsendparams::Params)); + } }; class DmxParams { public: - DmxParams(DmxParamsStore *pDMXParamsStore); + DmxParams(); - bool Load(); + void Load(); void Load(const char *pBuffer, uint32_t nLength); - void Builder(const struct TDmxParams *pTDmxParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); + void Builder(const struct dmxsendparams::Params *pTDmxParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); void Save(char *pBuffer, uint32_t nLength, uint32_t& nSize) { Builder(nullptr, pBuffer, nLength, nSize); } void Set(Dmx *); - void Dump(); - static void staticCallbackFunction(void *p, const char *s); private: + void Dump(); void callbackFunction(const char *s); bool isMaskSet(uint32_t nMask) const { - return (m_tDmxParams.nSetList & nMask) == nMask; + return (m_Params.nSetList & nMask) == nMask; } private: - DmxParamsStore *m_pDmxParamsStore; - struct TDmxParams m_tDmxParams; + dmxsendparams::Params m_Params; }; #endif /* DMXPARAMS_H_ */ diff --git a/lib-dmx/include/dmxparamsconst.h b/lib-dmx/include/dmxparamsconst.h index 0ff53d36..e96041a7 100644 --- a/lib-dmx/include/dmxparamsconst.h +++ b/lib-dmx/include/dmxparamsconst.h @@ -3,7 +3,7 @@ * * */ -/* Copyright (C) 2019-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-dmxreceiver/include/dmxreceiver.h b/lib-dmx/include/dmxreceiver.h old mode 100644 new mode 100755 similarity index 72% rename from lib-dmxreceiver/include/dmxreceiver.h rename to lib-dmx/include/dmxreceiver.h index e0d7fa01..63543f2e --- a/lib-dmxreceiver/include/dmxreceiver.h +++ b/lib-dmx/include/dmxreceiver.h @@ -2,7 +2,7 @@ * @file dmxreceiver.h * */ -/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,12 +39,12 @@ class DMXReceiver: Dmx { public: DMXReceiver(LightSet *pLightSet) { - s_pLightSet = pLightSet; + m_pLightSet = pLightSet; } ~DMXReceiver() { DMXReceiver::Stop(); - s_IsActive = false; + m_IsActive = false; } void Start() { @@ -53,28 +53,28 @@ class DMXReceiver: Dmx { void Stop() { Dmx::SetPortDirection(0, dmx::PortDirection::INP, false); - s_pLightSet->Stop(0); + m_pLightSet->Stop(0); } void SetLightSet(LightSet *pLightSet) { - if (pLightSet != s_pLightSet) { - s_pLightSet->Stop(0); - s_pLightSet = pLightSet; - s_IsActive = false; + if (pLightSet != m_pLightSet) { + m_pLightSet->Stop(0); + m_pLightSet = pLightSet; + m_IsActive = false; } } - const uint8_t* Run(int16_t &nLength) { - if (__builtin_expect((s_bDisableOutput), 0)) { + const uint8_t *Run(int16_t &nLength) { + if (__builtin_expect((m_bDisableOutput), 0)) { nLength = 0; return nullptr; } if (Dmx::GetDmxUpdatesPerSecond(0) == 0) { - if (s_IsActive) { - s_pLightSet->Stop(0); - s_IsActive = false; + if (m_IsActive) { + m_pLightSet->Stop(0); + m_IsActive = false; Hardware::Get()->SetMode(hardware::ledblink::Mode::NORMAL); } @@ -83,21 +83,21 @@ class DMXReceiver: Dmx { } else { const auto *pDmx = Dmx::GetDmxAvailable(0); - if (pDmx != nullptr) { - const auto *pDmxStatistics = reinterpret_cast(pDmx); + if (__builtin_expect((pDmx != nullptr), 0)) { + const auto *pDmxStatistics = reinterpret_cast(pDmx); nLength = static_cast(pDmxStatistics->Statistics.nSlotsInPacket); ++pDmx; - s_pLightSet->SetData(0, pDmx, static_cast(nLength)); + m_pLightSet->SetData(0, pDmx, static_cast(nLength)); - if (!s_IsActive) { - s_pLightSet->Start(0); - s_IsActive = true; + if (!m_IsActive) { + m_pLightSet->Start(0); + m_IsActive = true; Hardware::Get()->SetMode(hardware::ledblink::Mode::DATA); } - return const_cast(pDmx); + return const_cast(pDmx); } } @@ -106,25 +106,25 @@ class DMXReceiver: Dmx { } void SetDisableOutput(const bool bDisable = true) { - s_bDisableOutput = bDisable; + m_bDisableOutput = bDisable; } uint32_t GetUpdatesPerSecond(const uint32_t nPortIndex) { return Dmx::GetDmxUpdatesPerSecond(nPortIndex); } - const uint8_t* GetDmxCurrentData(const uint32_t nPortIndex) { + const uint8_t *GetDmxCurrentData(const uint32_t nPortIndex) { return Dmx::GetDmxCurrentData(nPortIndex); } void Print() { - printf(" Output %s\n", s_bDisableOutput ? "disabled" : "enabled"); + printf(" Output %s\n", m_bDisableOutput ? "disabled" : "enabled"); } private: - static LightSet *s_pLightSet; - static bool s_IsActive; - static bool s_bDisableOutput; + LightSet *m_pLightSet { nullptr }; + bool m_IsActive { false }; + bool m_bDisableOutput { false }; }; #endif /* DMXRECEIVER_H */ diff --git a/lib-dmx/include/dmxsend.h b/lib-dmx/include/dmxsend.h new file mode 100755 index 00000000..ed44a85d --- /dev/null +++ b/lib-dmx/include/dmxsend.h @@ -0,0 +1,156 @@ +/** + * @file dmxsend.h + * + */ +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef DMXSEND_H_ +#define DMXSEND_H_ + +#include +#include +#include + +#include "lightset.h" +#include "lightsetdata.h" + +#include "dmx.h" +#include "panel_led.h" +#include "hardware.h" + +#include "debug.h" + +class DmxSend final: public LightSet { +public: + void Start(const uint32_t nPortIndex) override { + DEBUG_ENTRY + DEBUG_PRINTF("nPortIndex=%d", nPortIndex); + + assert(nPortIndex < CHAR_BIT); + + if (is_started(m_nStarted, nPortIndex)) { + DEBUG_EXIT + return; + } + + m_nStarted = static_cast(m_nStarted | (1U << nPortIndex)); + + Dmx::Get()->SetPortDirection(nPortIndex, dmx::PortDirection::OUTP, true); + + if (Dmx::Get()->GetOutputStyle(nPortIndex) == dmx::OutputStyle::CONTINOUS) { + hal::panel_led_on(hal::panelled::PORT_A_TX << nPortIndex); + } + + DEBUG_EXIT + } + + void Stop(const uint32_t nPortIndex) override { + DEBUG_ENTRY + DEBUG_PRINTF("nPortIndex=%d -> %u", nPortIndex, is_started(m_nStarted, static_cast(nPortIndex))); + + assert(nPortIndex < CHAR_BIT); + + if (!is_started(m_nStarted, nPortIndex)) { + DEBUG_EXIT + return; + } + + m_nStarted = static_cast(m_nStarted & ~(1U << nPortIndex)); + + Dmx::Get()->SetPortDirection(nPortIndex, dmx::PortDirection::OUTP, false); + + hal::panel_led_off(hal::panelled::PORT_A_TX << nPortIndex); + + DEBUG_EXIT + } + + void SetData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate) override { + assert(nPortIndex < CHAR_BIT); + assert(pData != nullptr); + assert(nLength != 0); + + if (doUpdate) { + Dmx::Get()->SetSendDataWithoutSC(nPortIndex, pData, nLength); + Dmx::Get()->StartOutput(nPortIndex); + hal::panel_led_on(hal::panelled::PORT_A_TX << nPortIndex); + } + } + + void Sync(uint32_t const nPortIndex) override { + assert(lightset::Data::GetLength(nPortIndex) != 0); + Dmx::Get()->SetSendDataWithoutSC(nPortIndex, lightset::Data::Backup(nPortIndex), lightset::Data::GetLength(nPortIndex)); + } + + void Sync() override { + Dmx::Get()->Sync(); + + for (uint32_t nPortIndex = 0; nPortIndex < dmx::config::max::PORTS; nPortIndex++) { + if (lightset::Data::GetLength(nPortIndex) != 0) { + lightset::Data::ClearLength(nPortIndex); + hal::panel_led_on(hal::panelled::PORT_A_TX << nPortIndex); + if (!is_started(m_nStarted, nPortIndex)) { + Start(nPortIndex); + } + } + } + } + +#if defined (OUTPUT_HAVE_STYLESWITCH) + void SetOutputStyle(const uint32_t nPortIndex, const lightset::OutputStyle outputStyle) override { + Dmx::Get()->SetOutputStyle(nPortIndex, outputStyle == lightset::OutputStyle::CONSTANT ? dmx::OutputStyle::CONTINOUS : dmx::OutputStyle::DELTA); + } + + lightset::OutputStyle GetOutputStyle(const uint32_t nPortIndex) const override { + return Dmx::Get()->GetOutputStyle(nPortIndex) == dmx::OutputStyle::CONTINOUS ? lightset::OutputStyle::CONSTANT : lightset::OutputStyle::DELTA; + } +#endif + + uint32_t GetRefreshRate() override { + return 1000000U / Dmx::Get()->GetDmxPeriodTime(); + } + + void Blackout([[maybe_unused]] bool bBlackout) override { + Dmx::Get()->Blackout(); + } + + void FullOn() override { + Dmx::Get()->FullOn(); + } + + void Print() override { + puts("DMX Send"); + printf(" Break time : %u\n", static_cast(Dmx::Get()->GetDmxBreakTime())); + printf(" MAB time : %u\n", static_cast(Dmx::Get()->GetDmxMabTime())); + printf(" Refresh rate : %u\n", static_cast(1000000U / Dmx::Get()->GetDmxPeriodTime())); + printf(" Slots : %u\n", Dmx::Get()->GetDmxSlots()); + } + +private: + static constexpr bool is_started(const uint8_t v, const uint32_t p) { + return (v & (1U << p)) == (1U << p); + } + +private: + uint8_t m_nStarted { 0 }; +}; + +#endif /* DMXSEND_H_ */ diff --git a/lib-dmx/include/dmxstatistics.h b/lib-dmx/include/dmxstatistics.h new file mode 100755 index 00000000..7bc1615b --- /dev/null +++ b/lib-dmx/include/dmxstatistics.h @@ -0,0 +1,52 @@ +/** + * @file dmxstatistics.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef DMXSTATISTICS_H_ +#define DMXSTATISTICS_H_ + +#include + +namespace dmx { +struct TotalStatistics { + struct { + uint32_t Sent; + uint32_t Received; + } Dmx; + + struct { + struct { + uint32_t Good; + uint32_t Bad; + uint32_t DiscoveryResponse; + } Received; + struct { + uint32_t Class; + uint32_t DiscoveryResponse; + } Sent; + } Rdm; +}; +} // namespace dmx + +#endif /* DMXSTATISTICS_H_ */ diff --git a/lib-dmx/include/gd32/board_bw_opidmx4.h b/lib-dmx/include/gd32/board_bw_opidmx4.h index 22946a62..1c084248 100644 --- a/lib-dmx/include/gd32/board_bw_opidmx4.h +++ b/lib-dmx/include/gd32/board_bw_opidmx4.h @@ -26,15 +26,16 @@ #ifndef GD32_BOARD_BW_OPIDMX4_H_ #define GD32_BOARD_BW_OPIDMX4_H_ +#include + #include "gd32_board.h" +#define DMX_MAX_PORTS 4 + namespace max { -static constexpr auto OUT = 4U; -static constexpr auto IN = 4U; + static const uint32_t PORTS = DMX_MAX_PORTS; } // namespace max -#define DMX_MAX_PORTS 4 - #define DMX_USE_USART0 #define DMX_USE_USART2 #define DMX_USE_UART4 diff --git a/lib-dmx/include/gd32/board_dmx3.h b/lib-dmx/include/gd32/board_dmx3.h index e2c0a716..e781db03 100644 --- a/lib-dmx/include/gd32/board_dmx3.h +++ b/lib-dmx/include/gd32/board_dmx3.h @@ -28,13 +28,12 @@ #include "gd32_board.h" +#define DMX_MAX_PORTS 3 + namespace max { -static constexpr auto OUT = 3U; -static constexpr auto IN = 3U; + static const uint32_t PORTS = DMX_MAX_PORTS; } // namespace max -#define DMX_MAX_PORTS 3 - #define DMX_USE_USART2 #define DMX_USE_UART4 #define DMX_USE_USART5 diff --git a/lib-dmx/include/gd32/board_dmx4.h b/lib-dmx/include/gd32/board_dmx4.h index 64c2a6f8..42d98a2d 100644 --- a/lib-dmx/include/gd32/board_dmx4.h +++ b/lib-dmx/include/gd32/board_dmx4.h @@ -28,13 +28,12 @@ #include "gd32_board.h" +#define DMX_MAX_PORTS 4 + namespace max { -static constexpr auto OUT = 4U; -static constexpr auto IN = 4U; + static const uint32_t PORTS = DMX_MAX_PORTS; } // namespace max -#define DMX_MAX_PORTS 4 - #define DMX_USE_USART0 #define DMX_USE_USART2 #define DMX_USE_UART4 diff --git a/lib-dmx/include/gd32/board_gd32f207rg.h b/lib-dmx/include/gd32/board_gd32f207rg.h index 19a28957..82aa812f 100644 --- a/lib-dmx/include/gd32/board_gd32f207rg.h +++ b/lib-dmx/include/gd32/board_gd32f207rg.h @@ -28,13 +28,12 @@ #include "gd32_board.h" -namespace max { -static constexpr auto OUT = 2U; -static constexpr auto IN = 2U; -} - #define DMX_MAX_PORTS 2 +namespace max { + static const uint32_t PORTS = DMX_MAX_PORTS; +} // namespace max + #define DMX_USE_USART2 #define DMX_USE_USART5 diff --git a/lib-dmx/include/gd32/dmx.h b/lib-dmx/include/gd32/dmx.h index cfca1402..0d3c60a2 100644 --- a/lib-dmx/include/gd32/dmx.h +++ b/lib-dmx/include/gd32/dmx.h @@ -2,7 +2,7 @@ * @file dmx.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,10 +30,10 @@ #include "dmxconst.h" #include "dmx_config.h" +#include "dmxstatistics.h" struct Statistics { uint32_t nSlotsInPacket; - uint32_t nSlotToSlot; }; struct Data { @@ -50,40 +50,27 @@ class Dmx { return m_dmxPortDirection[nPortIndex]; } - void ClearData(uint32_t nPortIndex = 0); + void ClearData(const uint32_t nPortIndex); + + volatile dmx::TotalStatistics& GetTotalStatistics(const uint32_t nPortIndex); // RDM Send - void RdmSendRaw(uint32_t nPortIndex, const uint8_t *pRdmData, uint32_t nLength); + void RdmSendRaw(const uint32_t nPortIndex, const uint8_t *pRdmData, uint32_t nLength); + void RdmSendDiscoveryRespondMessage(const uint32_t nPortIndex, const uint8_t *pRdmData, uint32_t nLength); // RDM Receive - const uint8_t *RdmReceive(uint32_t nPortIndex); - const uint8_t *RdmReceiveTimeOut(uint32_t nPortIndex, uint16_t nTimeOut); + const uint8_t *RdmReceive(const uint32_t nPortIndex); + const uint8_t *RdmReceiveTimeOut(const uint32_t nPortIndex, uint16_t nTimeOut); // DMX Send - void SetSendData(uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength); - void SetSendDataWithoutSC(uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength); - - void StartOutput(const uint32_t nPortIndex); - void SetOutput(const bool doForce); - - void SetOutputStyle(const uint32_t nPortIndex, const dmx::OutputStyle outputStyle); - dmx::OutputStyle GetOutputStyle(const uint32_t nPortIndex) const; - - void Blackout(); - void FullOn(); - void SetDmxBreakTime(uint32_t nBreakTime); - uint32_t GetDmxBreakTime() const { - return m_nDmxTransmitBreakTime; - } + uint32_t GetDmxBreakTime() const; void SetDmxMabTime(uint32_t nMabTime); - uint32_t GetDmxMabTime() const { - return m_nDmxTransmitMabTime; - } + uint32_t GetDmxMabTime() const; void SetDmxPeriodTime(uint32_t nPeriodTime); uint32_t GetDmxPeriodTime() const { @@ -95,6 +82,18 @@ class Dmx { return m_nDmxTransmitSlots; } + void SetSendData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength); + void SetSendDataWithoutSC(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength); + + void StartOutput(const uint32_t nPortIndex); + void Sync(); + + void SetOutputStyle(const uint32_t nPortIndex, const dmx::OutputStyle outputStyle); + dmx::OutputStyle GetOutputStyle(const uint32_t nPortIndex) const; + + void Blackout(); + void FullOn(); + // DMX Receive const uint8_t *GetDmxAvailable(const uint32_t nPortIndex); @@ -102,25 +101,23 @@ class Dmx { const uint8_t *GetDmxCurrentData(const uint32_t nPortIndex); uint32_t GetDmxUpdatesPerSecond(const uint32_t nPortIndex); - uint32_t GetDmxReceivedCount(const uint32_t nPortIndex); static Dmx* Get() { return s_pThis; } private: - void StartData(const uint32_t nUart, const uint32_t nPortIndex); - void StopData(const uint32_t nUart, const uint32_t nPortIndex); + void StartData(const uint32_t nPortIndex); + void StopData(const uint32_t nPortIndex); void StartDmxOutput(const uint32_t nPortIndex); private: - uint32_t m_nDmxTransmitBreakTime { dmx::transmit::BREAK_TIME_MIN }; - uint32_t m_nDmxTransmitMabTime { dmx::transmit::MAB_TIME_MIN }; uint32_t m_nDmxTransmitPeriod { dmx::transmit::PERIOD_DEFAULT }; uint32_t m_nDmxTransmitPeriodRequested { dmx::transmit::PERIOD_DEFAULT }; - uint32_t m_nDmxTransmissionLength[dmx::config::max::OUT]; - uint16_t m_nDmxTransmitSlots { dmx::max::CHANNELS }; - dmx::PortDirection m_dmxPortDirection[dmx::config::max::OUT]; + uint32_t m_nDmxTransmissionLength[dmx::config::max::PORTS]; + uint32_t m_nDmxTransmitSlots { dmx::max::CHANNELS }; + dmx::PortDirection m_dmxPortDirection[dmx::config::max::PORTS]; + bool m_bHasContinuosOutput { false }; static Dmx *s_pThis; }; diff --git a/lib-dmx/include/gd32/dmx_config.h b/lib-dmx/include/gd32/dmx_config.h index a5350a96..440a29ca 100644 --- a/lib-dmx/include/gd32/dmx_config.h +++ b/lib-dmx/include/gd32/dmx_config.h @@ -2,7 +2,7 @@ * @file dmx_config.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -48,8 +48,12 @@ namespace config { # include "board_gd32f450ve.h" #elif defined (BOARD_GD32F450VI) # include "board_gd32f450vi.h" +#elif defined (BOARD_GD32F470Z_EVAL) +# include "board_gd32f470z_eval.h" #elif defined (BOARD_GD32F207C_EVAL) # include "board_gd32f207c_eval.h" +#elif defined (BOARD_GD32H759I_EVAL) +# include "board_gd32h759i_eval.h" #elif defined (BOARD_BW_OPIDMX4) # include "board_bw_opidmx4.h" #elif defined (BOARD_DMX3) @@ -64,19 +68,16 @@ namespace config { namespace dmx { namespace buffer { -static constexpr auto SIZE = 514; // multiple of uint16_t +static constexpr auto SIZE = 516; // multiple of uint32_t } // namespace buffer } // namespace dmx -/** - * PORTs check - */ -static_assert(DMX_MAX_PORTS <= dmx::config::max::IN, "IN: DMX_MAX_PORTS"); -static_assert(DMX_MAX_PORTS <= dmx::config::max::OUT, "OUT: DMX_MAX_PORTS"); - #if defined(GD32F10X_HD) || defined (GD32F10X_CL) static_assert(DMX_MAX_PORTS <= 4, "Too many ports defined"); #endif +#if defined (GD32F20X_CL) + static_assert(DMX_MAX_PORTS <= 6, "Too many ports defined"); +#endif /** * DMA channel check diff --git a/lib-dmx/src/artnet/dmxinput.cpp b/lib-dmx/src/artnet/dmxinput.cpp deleted file mode 100644 index 6e9a1495..00000000 --- a/lib-dmx/src/artnet/dmxinput.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @file dmxinput.cpp - * - */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "dmx.h" - -#include "debug.h" - -namespace artnet { -static uint8_t s_nStarted; - -static constexpr bool is_started(const uint8_t v, const uint32_t p) { - return (v & (1U << p)) == (1U << p); -} - -void dmx_start(const uint32_t nPortIndex) { - DEBUG_ENTRY - - assert(nPortIndex < CHAR_BIT); - - DEBUG_PRINTF("nPortIndex=%d", nPortIndex); - - if (is_started(s_nStarted, nPortIndex)) { - DEBUG_EXIT - return; - } - - s_nStarted = static_cast(s_nStarted | (1U << nPortIndex)); - - Dmx::Get()->SetPortDirection(nPortIndex, dmx::PortDirection::INP, true); - - DEBUG_EXIT -} - -void dmx_stop(const uint32_t nPortIndex) { - DEBUG_ENTRY - - assert(nPortIndex < CHAR_BIT); - - DEBUG_PRINTF("nPortIndex=%d -> %u", nPortIndex, is_started(s_nStarted, nPortIndex)); - - if (!is_started(s_nStarted, nPortIndex)) { - DEBUG_EXIT - return; - } - - s_nStarted = static_cast(s_nStarted & ~(1U << nPortIndex)); - - Dmx::Get()->SetPortDirection(nPortIndex, dmx::PortDirection::INP, false); - - DEBUG_EXIT -} - -const uint8_t *dmx_handler(const uint32_t nPortIndex, uint32_t& nLength, uint32_t& nUpdatesPerSecond) { - assert(nPortIndex < CHAR_BIT); - - const auto *pDmx = Dmx::Get()->GetDmxAvailable(nPortIndex); - - nUpdatesPerSecond = Dmx::Get()->GetDmxUpdatesPerSecond(nPortIndex); - - if (pDmx != nullptr) { - const auto *pDmxData = reinterpret_cast(pDmx); - nLength = pDmxData->Statistics.nSlotsInPacket; - return (pDmx + 1); - } - - nLength = 0; - return nullptr; -} -} // namespace artnet diff --git a/lib-dmx/src/dmxparams.cpp b/lib-dmx/src/dmxparams.cpp index 755147e1..36856ff9 100644 --- a/lib-dmx/src/dmxparams.cpp +++ b/lib-dmx/src/dmxparams.cpp @@ -2,7 +2,7 @@ * @file dmxparams.cpp * */ -/* Copyright (C) 2017-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -46,36 +46,34 @@ #include "debug.h" -DmxParams::DmxParams(DmxParamsStore *pDMXParamsStore) : m_pDmxParamsStore(pDMXParamsStore) { - m_tDmxParams.nSetList = 0; - m_tDmxParams.nBreakTime = dmx::transmit::BREAK_TIME_TYPICAL; - m_tDmxParams.nMabTime = dmx::transmit::MAB_TIME_MIN; - m_tDmxParams.nRefreshRate = dmx::transmit::REFRESH_RATE_DEFAULT; - m_tDmxParams.nSlotsCount = dmxparams::rounddown_slots(dmx::max::CHANNELS); +DmxParams::DmxParams() { + m_Params.nSetList = 0; + m_Params.nBreakTime = dmx::transmit::BREAK_TIME_TYPICAL; + m_Params.nMabTime = dmx::transmit::MAB_TIME_MIN; + m_Params.nRefreshRate = dmx::transmit::REFRESH_RATE_DEFAULT; + m_Params.nSlotsCount = dmxsendparams::rounddown_slots(dmx::max::CHANNELS); - DEBUG_PRINTF("m_tDmxParams.nSlotsCount=%d", m_tDmxParams.nSlotsCount); + DEBUG_PRINTF("m_Params.nSlotsCount=%d", m_Params.nSlotsCount); } -bool DmxParams::Load() { - m_tDmxParams.nSetList = 0; +void DmxParams::Load() { + DEBUG_ENTRY + + m_Params.nSetList = 0; #if !defined(DISABLE_FS) ReadConfigFile configfile(DmxParams::staticCallbackFunction, this); if (configfile.Read(DmxParamsConst::FILE_NAME)) { - // There is a configuration file - if (m_pDmxParamsStore != nullptr) { - m_pDmxParamsStore->Update(&m_tDmxParams); - } + StoreDmxSend::Update(&m_Params); } else #endif - if (m_pDmxParamsStore != nullptr) { - m_pDmxParamsStore->Copy(&m_tDmxParams); - } else { - return false; - } + StoreDmxSend::Copy(&m_Params); - return true; +#ifndef NDEBUG + Dump(); +#endif + DEBUG_EXIT } void DmxParams::Load(const char* pBuffer, uint32_t nLength) { @@ -84,15 +82,17 @@ void DmxParams::Load(const char* pBuffer, uint32_t nLength) { assert(pBuffer != nullptr); assert(nLength != 0); - m_tDmxParams.nSetList = 0; + m_Params.nSetList = 0; ReadConfigFile config(DmxParams::staticCallbackFunction, this); config.Read(pBuffer, nLength); - assert(m_pDmxParamsStore != nullptr); - m_pDmxParamsStore->Update(&m_tDmxParams); + StoreDmxSend::Update(&m_Params); +#ifndef NDEBUG + Dump(); +#endif DEBUG_EXIT } @@ -103,22 +103,22 @@ void DmxParams::callbackFunction(const char *pLine) { if (Sscan::Uint16(pLine, DmxParamsConst::BREAK_TIME, nValue16) == Sscan::OK) { if ((nValue16 >= dmx::transmit::BREAK_TIME_MIN) && (nValue16 != dmx::transmit::BREAK_TIME_TYPICAL)) { - m_tDmxParams.nBreakTime = nValue16; - m_tDmxParams.nSetList |= DmxParamsMask::BREAK_TIME; + m_Params.nBreakTime = nValue16; + m_Params.nSetList |= dmxsendparams::Mask::BREAK_TIME; } else { - m_tDmxParams.nBreakTime = dmx::transmit::BREAK_TIME_TYPICAL; - m_tDmxParams.nSetList &= ~DmxParamsMask::BREAK_TIME; + m_Params.nBreakTime = dmx::transmit::BREAK_TIME_TYPICAL; + m_Params.nSetList &= ~dmxsendparams::Mask::BREAK_TIME; } return; } if (Sscan::Uint16(pLine, DmxParamsConst::MAB_TIME, nValue16) == Sscan::OK) { if (nValue16 > dmx::transmit::MAB_TIME_MIN) { // && (nValue32 <= dmx::transmit::MAB_TIME_MAX)) { - m_tDmxParams.nMabTime = nValue16; - m_tDmxParams.nSetList |= DmxParamsMask::MAB_TIME; + m_Params.nMabTime = nValue16; + m_Params.nSetList |= dmxsendparams::Mask::MAB_TIME; } else { - m_tDmxParams.nMabTime = dmx::transmit::MAB_TIME_MIN; - m_tDmxParams.nSetList &= ~DmxParamsMask::MAB_TIME; + m_Params.nMabTime = dmx::transmit::MAB_TIME_MIN; + m_Params.nSetList &= ~dmxsendparams::Mask::MAB_TIME; } return; } @@ -127,45 +127,44 @@ void DmxParams::callbackFunction(const char *pLine) { if (Sscan::Uint8(pLine, DmxParamsConst::REFRESH_RATE, nValue8) == Sscan::OK) { if (nValue8 != dmx::transmit::REFRESH_RATE_DEFAULT) { - m_tDmxParams.nRefreshRate = nValue8; - m_tDmxParams.nSetList |= DmxParamsMask::REFRESH_RATE; + m_Params.nRefreshRate = nValue8; + m_Params.nSetList |= dmxsendparams::Mask::REFRESH_RATE; } else { - m_tDmxParams.nRefreshRate = dmx::transmit::REFRESH_RATE_DEFAULT; - m_tDmxParams.nSetList &= ~DmxParamsMask::REFRESH_RATE; + m_Params.nRefreshRate = dmx::transmit::REFRESH_RATE_DEFAULT; + m_Params.nSetList &= ~dmxsendparams::Mask::REFRESH_RATE; } return; } if (Sscan::Uint16(pLine, DmxParamsConst::SLOTS_COUNT, nValue16) == Sscan::OK) { if ((nValue16 >= 2) && (nValue16 < dmx::max::CHANNELS)) { - m_tDmxParams.nSlotsCount = dmxparams::rounddown_slots(nValue16); - m_tDmxParams.nSetList |= DmxParamsMask::SLOTS_COUNT; + m_Params.nSlotsCount = dmxsendparams::rounddown_slots(nValue16); + m_Params.nSetList |= dmxsendparams::Mask::SLOTS_COUNT; } else { - m_tDmxParams.nSlotsCount = dmxparams::rounddown_slots(dmx::max::CHANNELS); - m_tDmxParams.nSetList &= ~DmxParamsMask::SLOTS_COUNT; + m_Params.nSlotsCount = dmxsendparams::rounddown_slots(dmx::max::CHANNELS); + m_Params.nSetList &= ~dmxsendparams::Mask::SLOTS_COUNT; } return; } } -void DmxParams::Builder(const struct TDmxParams *ptDMXParams, char *pBuffer, uint32_t nLength, uint32_t& nSize) { +void DmxParams::Builder(const struct dmxsendparams::Params *ptDMXParams, char *pBuffer, uint32_t nLength, uint32_t& nSize) { DEBUG_ENTRY assert(pBuffer != nullptr); if (ptDMXParams != nullptr) { - memcpy(&m_tDmxParams, ptDMXParams, sizeof(struct TDmxParams)); + memcpy(&m_Params, ptDMXParams, sizeof(struct dmxsendparams::Params)); } else { - assert(m_pDmxParamsStore != nullptr); - m_pDmxParamsStore->Copy(&m_tDmxParams); + StoreDmxSend::Copy(&m_Params); } PropertiesBuilder builder(DmxParamsConst::FILE_NAME, pBuffer, nLength); - builder.Add(DmxParamsConst::BREAK_TIME, m_tDmxParams.nBreakTime, isMaskSet(DmxParamsMask::BREAK_TIME)); - builder.Add(DmxParamsConst::MAB_TIME, m_tDmxParams.nMabTime, isMaskSet(DmxParamsMask::MAB_TIME)); - builder.Add(DmxParamsConst::REFRESH_RATE, m_tDmxParams.nRefreshRate, isMaskSet(DmxParamsMask::REFRESH_RATE)); - builder.Add(DmxParamsConst::SLOTS_COUNT, dmxparams::roundup_slots(m_tDmxParams.nSlotsCount), isMaskSet(DmxParamsMask::SLOTS_COUNT)); + builder.Add(DmxParamsConst::BREAK_TIME, m_Params.nBreakTime, isMaskSet(dmxsendparams::Mask::BREAK_TIME)); + builder.Add(DmxParamsConst::MAB_TIME, m_Params.nMabTime, isMaskSet(dmxsendparams::Mask::MAB_TIME)); + builder.Add(DmxParamsConst::REFRESH_RATE, m_Params.nRefreshRate, isMaskSet(dmxsendparams::Mask::REFRESH_RATE)); + builder.Add(DmxParamsConst::SLOTS_COUNT, dmxsendparams::roundup_slots(m_Params.nSlotsCount), isMaskSet(dmxsendparams::Mask::SLOTS_COUNT)); nSize = builder.GetSize(); @@ -176,52 +175,50 @@ void DmxParams::Builder(const struct TDmxParams *ptDMXParams, char *pBuffer, uin void DmxParams::Set(Dmx *p) { assert(p != nullptr); - if (isMaskSet(DmxParamsMask::BREAK_TIME)) { - p->SetDmxBreakTime(m_tDmxParams.nBreakTime); + if (isMaskSet(dmxsendparams::Mask::BREAK_TIME)) { + p->SetDmxBreakTime(m_Params.nBreakTime); } - if (isMaskSet(DmxParamsMask::MAB_TIME)) { - p->SetDmxMabTime(m_tDmxParams.nMabTime); + if (isMaskSet(dmxsendparams::Mask::MAB_TIME)) { + p->SetDmxMabTime(m_Params.nMabTime); } - if (isMaskSet(DmxParamsMask::REFRESH_RATE)) { + if (isMaskSet(dmxsendparams::Mask::REFRESH_RATE)) { uint32_t period = 0; - if (m_tDmxParams.nRefreshRate != 0) { - period = 1000000U / m_tDmxParams.nRefreshRate; + if (m_Params.nRefreshRate != 0) { + period = 1000000U / m_Params.nRefreshRate; } p->SetDmxPeriodTime(period); } - if (isMaskSet(DmxParamsMask::SLOTS_COUNT)) { - p->SetDmxSlots(dmxparams::roundup_slots(m_tDmxParams.nSlotsCount)); + if (isMaskSet(dmxsendparams::Mask::SLOTS_COUNT)) { + p->SetDmxSlots(dmxsendparams::roundup_slots(m_Params.nSlotsCount)); } } +void DmxParams::staticCallbackFunction(void *p, const char *s) { + assert(p != nullptr); + assert(s != nullptr); + + (static_cast(p))->callbackFunction(s); +} + void DmxParams::Dump() { -#ifndef NDEBUG printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, DmxParamsConst::FILE_NAME); - if (isMaskSet(DmxParamsMask::BREAK_TIME)) { - printf(" %s=%d\n", DmxParamsConst::BREAK_TIME, m_tDmxParams.nBreakTime); + if (isMaskSet(dmxsendparams::Mask::BREAK_TIME)) { + printf(" %s=%d\n", DmxParamsConst::BREAK_TIME, m_Params.nBreakTime); } - if (isMaskSet(DmxParamsMask::MAB_TIME)) { - printf(" %s=%d\n", DmxParamsConst::MAB_TIME, m_tDmxParams.nMabTime); + if (isMaskSet(dmxsendparams::Mask::MAB_TIME)) { + printf(" %s=%d\n", DmxParamsConst::MAB_TIME, m_Params.nMabTime); } - if (isMaskSet(DmxParamsMask::REFRESH_RATE)) { - printf(" %s=%d\n", DmxParamsConst::REFRESH_RATE, m_tDmxParams.nRefreshRate); + if (isMaskSet(dmxsendparams::Mask::REFRESH_RATE)) { + printf(" %s=%d\n", DmxParamsConst::REFRESH_RATE, m_Params.nRefreshRate); } - if (isMaskSet(DmxParamsMask::SLOTS_COUNT)) { - printf(" %s=%d [%d]\n", DmxParamsConst::SLOTS_COUNT, m_tDmxParams.nSlotsCount, dmxparams::roundup_slots(m_tDmxParams.nSlotsCount)); + if (isMaskSet(dmxsendparams::Mask::SLOTS_COUNT)) { + printf(" %s=%d [%d]\n", DmxParamsConst::SLOTS_COUNT, m_Params.nSlotsCount, dmxsendparams::roundup_slots(m_Params.nSlotsCount)); } -#endif -} - -void DmxParams::staticCallbackFunction(void *p, const char *s) { - assert(p != nullptr); - assert(s != nullptr); - - (static_cast(p))->callbackFunction(s); } diff --git a/lib-dmx/src/e131/dmxinput.cpp b/lib-dmx/src/e131/dmxinput.cpp deleted file mode 100644 index 10d35ef7..00000000 --- a/lib-dmx/src/e131/dmxinput.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @file dmxinput.cpp - * - */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "dmx.h" - -#include "debug.h" - -namespace e131 { -static uint8_t s_nStarted; - -static constexpr bool is_started(const uint8_t v, const uint32_t p) { - return (v & (1U << p)) == (1U << p); -} - -void dmx_start(const uint32_t nPortIndex) { - DEBUG_ENTRY - - assert(nPortIndex < CHAR_BIT); - - DEBUG_PRINTF("nPortIndex=%d", nPortIndex); - - if (is_started(s_nStarted, nPortIndex)) { - DEBUG_EXIT - return; - } - - s_nStarted = static_cast(s_nStarted | (1U << nPortIndex)); - - Dmx::Get()->SetPortDirection(nPortIndex, dmx::PortDirection::INP, true); - - DEBUG_EXIT -} - -void dmx_stop(const uint32_t nPortIndex) { - DEBUG_ENTRY - assert(nPortIndex < CHAR_BIT); - - DEBUG_PRINTF("nPortIndex=%d -> %u", nPortIndex, is_started(s_nStarted, nPortIndex)); - - if (!is_started(s_nStarted, nPortIndex)) { - DEBUG_EXIT - return; - } - - s_nStarted = static_cast(s_nStarted & ~(1U << nPortIndex)); - - Dmx::Get()->SetPortDirection(nPortIndex, dmx::PortDirection::INP, false); - - DEBUG_EXIT -} - -const uint8_t *dmx_handler(const uint32_t nPortIndex, uint32_t& nLength, uint32_t &nUpdatesPerSecond) { - const auto *pDmx = Dmx::Get()->GetDmxAvailable(nPortIndex); - - nUpdatesPerSecond = Dmx::Get()->GetDmxUpdatesPerSecond(nPortIndex); - - if (pDmx != nullptr) { - const auto *pDmxData = reinterpret_cast(pDmx); - nLength = (1U + pDmxData->Statistics.nSlotsInPacket); // Add 1 for SC - return pDmx; - } - - nLength = 0; - return nullptr; -} -} // namespace e131 diff --git a/lib-dmx/src/gd32/dmx.cpp b/lib-dmx/src/gd32/dmx.cpp index 67ab9dd6..67d5b2b9 100644 --- a/lib-dmx/src/gd32/dmx.cpp +++ b/lib-dmx/src/gd32/dmx.cpp @@ -1,8 +1,7 @@ /** * @file dmx.cpp - * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,24 +22,14 @@ * THE SOFTWARE. */ +#if defined (CONFIG_TIMER6_HAVE_NO_IRQ_HANDLER) +# error +#endif + #pragma GCC push_options #pragma GCC optimize ("O3") -#pragma GCC optimize ("-funroll-loops") #pragma GCC optimize ("-fprefetch-loop-arrays") -#if 0 -# if defined (GD32F207RG) -# define LOGIC_ANALYZER -# if defined (NDEBUG) -# undef NDEBUG -# endif -# endif -#endif - -extern "C" { -void console_error(const char *); -} - #include #include #include @@ -53,6 +42,7 @@ void console_error(const char *); #include "rdm_e120.h" #include "gd32.h" +#include "gd32_dma.h" #include "gd32_uart.h" #include "gd32/dmx_config.h" #include "dmx_internal.h" @@ -61,24 +51,7 @@ void console_error(const char *); #include "debug.h" -#ifndef ALIGNED -# define ALIGNED __attribute__ ((aligned (4))) -#endif - -#if !defined(CONFIG_DMX_TRANSMIT_ONLY) -# define UNUSED -# else -# define UNUSED __attribute__((unused)) -#endif - -/** - * https://www.gd32-dmx.org/memory.html - */ -#if defined (GD32F20X) ||defined (GD32F4XX) -# define SECTION_DMA_BUFFER __attribute__ ((section (".dmx"))) -#else -# define SECTION_DMA_BUFFER -#endif +extern struct HwTimersSeconds g_Seconds; namespace dmx { enum class TxRxState { @@ -90,37 +63,45 @@ enum class PortState { }; struct TxDmxPacket { - uint8_t data[dmx::buffer::SIZE]; // multiple of uint16_t - uint16_t nLength; + uint8_t data[dmx::buffer::SIZE]; // multiple of uint32_t + uint32_t nLength; + bool bDataPending; }; struct TxData { - struct TxDmxPacket dmx; - OutputStyle outputStyle; + TxDmxPacket dmx; + OutputStyle outputStyle ALIGNED; volatile TxRxState State; }; +struct DmxTransmit { + uint32_t nBreakTime; + uint32_t nMabTime; + uint32_t nInterTime; +}; + struct RxDmxPackets { uint32_t nPerSecond; uint32_t nCount; uint32_t nCountPrevious; - uint16_t nTimerCounterPrevious; }; -struct RxRdmPackets { - uint32_t nIndex; - uint16_t nChecksum; // This must be uint16_t - uint16_t nDiscIndex; +struct RxDmxData { + uint8_t data[dmx::buffer::SIZE] ALIGNED; // multiple of uint32_t + uint32_t nSlotsInPacket; }; struct RxData { - uint8_t data[dmx::buffer::SIZE]; // multiple of uint16_t - union { - volatile RxRdmPackets Rdm; - volatile Statistics Dmx; - }; + struct { + volatile RxDmxData current; + RxDmxData previous; + } Dmx ALIGNED; + struct { + volatile uint8_t data[sizeof(struct TRdmMessage)] ALIGNED; + volatile uint32_t nIndex; + } Rdm ALIGNED; volatile TxRxState State; -}; +} ALIGNED; struct DirGpio { uint32_t nPort; @@ -155,272 +136,157 @@ static constexpr DirGpio s_DirGpio[DMX_MAX_PORTS] = { #endif }; -static volatile PortState sv_PortState[config::max::OUT] ALIGNED; +static volatile PortState sv_PortState[dmx::config::max::PORTS] ALIGNED; + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) +static volatile dmx::TotalStatistics sv_TotalStatistics[dmx::config::max::PORTS] ALIGNED; +#endif // DMX RX -static uint8_t UNUSED s_RxDmxPrevious[config::max::IN][dmx::buffer::SIZE] ALIGNED; -static volatile RxDmxPackets sv_nRxDmxPackets[config::max::IN] ALIGNED; +static volatile RxDmxPackets sv_nRxDmxPackets[dmx::config::max::PORTS] ALIGNED; // RDM RX -volatile uint32_t gv_RdmDataReceiveEnd; +volatile uint32_t gsv_RdmDataReceiveEnd; // DMX RDM RX -static RxData s_RxBuffer[config::max::IN] ALIGNED; +static RxData sv_RxBuffer[dmx::config::max::PORTS] ALIGNED; // DMX TX -static TxData s_TxBuffer[config::max::OUT] ALIGNED SECTION_DMA_BUFFER; +static TxData s_TxBuffer[dmx::config::max::PORTS] ALIGNED SECTION_DMA_BUFFER; +static DmxTransmit s_nDmxTransmit; -static uint32_t s_nDmxTransmitBreakTime { dmx::transmit::BREAK_TIME_TYPICAL }; -static uint32_t s_nDmxTransmitMabTime { dmx::transmit::MAB_TIME_MIN }; ///< MAB_TIME_MAX = 1000000U; -static uint32_t s_nDmxTransmitInterTime { dmx::transmit::PERIOD_DEFAULT - dmx::transmit::MAB_TIME_MIN - dmx::transmit::BREAK_TIME_TYPICAL - (dmx::max::CHANNELS * 44) - 44 }; +template +void irq_handler_dmx_rdm_input() { + const auto isFlagIdleFrame = (USART_REG_VAL(uart, USART_FLAG_IDLE) & BIT(USART_BIT_POS(USART_FLAG_IDLE))) == BIT(USART_BIT_POS(USART_FLAG_IDLE)); + /* + * Software can clear this bit by reading the USART_STAT and USART_DATA registers one by one. + */ + if (isFlagIdleFrame) { + static_cast(GET_BITS(USART_RDATA(uart), 0U, 8U)); + + if (sv_RxBuffer[nPortIndex].State == TxRxState::DMXDATA) { + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; + sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket |= 0x8000; -static void irq_handler_dmx_rdm_input(const uint32_t uart, const uint32_t nPortIndex) { - uint32_t nIndex; - uint16_t nCounter; + return; + } + + if (sv_RxBuffer[0].State == TxRxState::RDMDISC) { + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; + sv_RxBuffer[nPortIndex].Rdm.nIndex |= 0x4000; - if (RESET != (USART_REG_VAL(uart, USART_FLAG_FERR) & BIT(USART_BIT_POS(USART_FLAG_FERR)))) { - USART_REG_VAL(uart, USART_FLAG_FERR) &= ~BIT(USART_BIT_POS(USART_FLAG_FERR)); - static_cast(GET_BITS(USART_DATA(uart), 0U, 8U)); - if (s_RxBuffer[nPortIndex].State == TxRxState::IDLE) { - s_RxBuffer[nPortIndex].Dmx.nSlotsInPacket = 0; - s_RxBuffer[nPortIndex].State = TxRxState::BREAK; + return; } + return; } - const auto data = static_cast(GET_BITS(USART_DATA(uart), 0U, 8U)); + const auto isFlagFrameError = (USART_REG_VAL(uart, USART_FLAG_FERR) & BIT(USART_BIT_POS(USART_FLAG_FERR))) == BIT(USART_BIT_POS(USART_FLAG_FERR)); + /* + * Software can clear this bit by reading the USART_STAT and USART_DATA registers one by one. + */ + if (isFlagFrameError) { + static_cast(GET_BITS(USART_RDATA(uart), 0U, 8U)); - switch (s_RxBuffer[nPortIndex].State) { - case TxRxState::IDLE: - s_RxBuffer[nPortIndex].State = TxRxState::RDMDISC; - s_RxBuffer[nPortIndex].data[0] = data; - s_RxBuffer[nPortIndex].Rdm.nIndex = 1; -#if DMX_MAX_PORTS >= 5 - if (nPortIndex < 4) { -#endif - sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious = static_cast(TIMER_CNT(TIMER2)); -#if DMX_MAX_PORTS >= 5 - } else { - sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious = static_cast(TIMER_CNT(TIMER3)); + if (sv_RxBuffer[nPortIndex].State == TxRxState::IDLE) { + sv_RxBuffer[nPortIndex].State = TxRxState::BREAK; } -#endif + + return; + } + + const auto data = static_cast(GET_BITS(USART_RDATA(uart), 0U, 8U)); + + switch (sv_RxBuffer[nPortIndex].State) { + case TxRxState::IDLE: + sv_RxBuffer[nPortIndex].State = TxRxState::RDMDISC; + sv_RxBuffer[nPortIndex].Rdm.data[0] = data; + sv_RxBuffer[nPortIndex].Rdm.nIndex = 1; break; case TxRxState::BREAK: switch (data) { case START_CODE: - s_RxBuffer[nPortIndex].data[0] = START_CODE; - s_RxBuffer[nPortIndex].Dmx.nSlotsInPacket = 1; + sv_RxBuffer[nPortIndex].Dmx.current.data[0] = START_CODE; + sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket = 1; sv_nRxDmxPackets[nPortIndex].nCount++; - s_RxBuffer[nPortIndex].State = TxRxState::DMXDATA; -#if DMX_MAX_PORTS >= 5 - if (nPortIndex < 4) { -#endif - sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious = static_cast(TIMER_CNT(TIMER2)); -#if DMX_MAX_PORTS >= 5 - } else { - sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious = static_cast(TIMER_CNT(TIMER3)); - } -#endif + sv_RxBuffer[nPortIndex].State = TxRxState::DMXDATA; break; case E120_SC_RDM: - s_RxBuffer[nPortIndex].data[0] = E120_SC_RDM; - s_RxBuffer[nPortIndex].Rdm.nChecksum = E120_SC_RDM; - s_RxBuffer[nPortIndex].Rdm.nIndex = 1; - s_RxBuffer[nPortIndex].State = TxRxState::RDMDATA; + sv_RxBuffer[nPortIndex].Rdm.data[0] = E120_SC_RDM; + sv_RxBuffer[nPortIndex].Rdm.nIndex = 1; + sv_RxBuffer[nPortIndex].State = TxRxState::RDMDATA; break; default: - s_RxBuffer[nPortIndex].State = TxRxState::IDLE; + sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket = 0; + sv_RxBuffer[nPortIndex].Rdm.nIndex = 0; + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; break; } break; - case TxRxState::DMXDATA: - nIndex = s_RxBuffer[nPortIndex].Dmx.nSlotsInPacket; - s_RxBuffer[nPortIndex].data[nIndex] = data; - s_RxBuffer[nPortIndex].Dmx.nSlotsInPacket++; - - if (s_RxBuffer[nPortIndex].Dmx.nSlotsInPacket > dmx::max::CHANNELS) { - s_RxBuffer[nPortIndex].Dmx.nSlotsInPacket |= 0x8000; - s_RxBuffer[nPortIndex].State = TxRxState::IDLE; - break; - } -#if DMX_MAX_PORTS >= 5 - if (nPortIndex < 4) { -#endif - nCounter = static_cast(TIMER_CNT(TIMER2)); -#if DMX_MAX_PORTS >= 5 - } else { - nCounter = static_cast(TIMER_CNT(TIMER3)); - } -#endif - { - const uint16_t nDelta = nCounter - sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious; - sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious = nCounter; - const auto nPulse = static_cast(nCounter + nDelta + 4); - - switch(nPortIndex){ - case 0: - TIMER_CH0CV(TIMER2) = nPulse; - break; -#if DMX_MAX_PORTS >= 2 - case 1: - TIMER_CH1CV(TIMER2) = nPulse; - break; -#endif -#if DMX_MAX_PORTS >= 3 - case 2: - TIMER_CH2CV(TIMER2) = nPulse; - break; -#endif -#if DMX_MAX_PORTS >= 4 - case 3: - TIMER_CH3CV(TIMER2) = nPulse; - break; -#endif -#if DMX_MAX_PORTS >= 5 - case 4: - TIMER_CH0CV(TIMER3) = nPulse; - break; -#endif -#if DMX_MAX_PORTS >= 6 - case 5: - TIMER_CH1CV(TIMER3) = nPulse; - break; -#endif -#if DMX_MAX_PORTS >= 7 - case 6: - TIMER_CH2CV(TIMER3) = nPulse; - break; -#endif -#if DMX_MAX_PORTS == 8 - case 7: - TIMER_CH3CV(TIMER3) = nPulse; - break; -#endif - default: - assert(0); - __builtin_unreachable(); - break; - } - } + case TxRxState::DMXDATA: { + auto nIndex = sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket; + sv_RxBuffer[nPortIndex].Dmx.current.data[nIndex] = data; + nIndex++; + sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket = nIndex; + + if (nIndex > dmx::max::CHANNELS) { + nIndex |= 0x8000; + sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket = nIndex; + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; break; - case TxRxState::RDMDATA: { - nIndex = s_RxBuffer[nPortIndex].Rdm.nIndex; - s_RxBuffer[nPortIndex].data[nIndex] = data; - s_RxBuffer[nPortIndex].Rdm.nIndex++; - - s_RxBuffer[nPortIndex].Rdm.nChecksum = static_cast(s_RxBuffer[nPortIndex].Rdm.nChecksum + data); - - const auto *p = reinterpret_cast(&s_RxBuffer[nPortIndex].data[0]); - - nIndex = s_RxBuffer[nPortIndex].Rdm.nIndex; - - if ((nIndex >= 24) && (nIndex <= sizeof(struct TRdmMessage)) && (nIndex == p->message_length)) { - s_RxBuffer[nPortIndex].State = TxRxState::CHECKSUMH; - } else if (nIndex > sizeof(struct TRdmMessage)) { - s_RxBuffer[nPortIndex].State = TxRxState::IDLE; - } } + } break; - case TxRxState::CHECKSUMH: - nIndex = s_RxBuffer[nPortIndex].Rdm.nIndex; - s_RxBuffer[nPortIndex].data[nIndex] = data; - s_RxBuffer[nPortIndex].Rdm.nIndex++; - s_RxBuffer[nPortIndex].Rdm.nChecksum = static_cast(s_RxBuffer[nPortIndex].Rdm.nChecksum - static_cast(data << 8)); - s_RxBuffer[nPortIndex].State = TxRxState::CHECKSUML; - break; - case TxRxState::CHECKSUML: { - nIndex = s_RxBuffer[nPortIndex].Rdm.nIndex; - s_RxBuffer[nPortIndex].data[nIndex] = data; - s_RxBuffer[nPortIndex].Rdm.nIndex++; - s_RxBuffer[nPortIndex].Rdm.nChecksum = static_cast(s_RxBuffer[nPortIndex].Rdm.nChecksum - data); - - const auto *p = reinterpret_cast(&s_RxBuffer[nPortIndex].data[0]); - - if (!((s_RxBuffer[nPortIndex].Rdm.nChecksum == 0) && (p->sub_start_code == E120_SC_SUB_MESSAGE))) { - s_RxBuffer[nPortIndex].Dmx.nSlotsInPacket= 0; // This is correct. - } else { - s_RxBuffer[nPortIndex].Rdm.nIndex |= 0x4000; - gv_RdmDataReceiveEnd = DWT->CYCCNT; - } - - s_RxBuffer[nPortIndex].State = TxRxState::IDLE; + case TxRxState::RDMDATA: { + auto nIndex = sv_RxBuffer[nPortIndex].Rdm.nIndex; + sv_RxBuffer[nPortIndex].Rdm.data[nIndex] = data; + nIndex++; + sv_RxBuffer[nPortIndex].Rdm.nIndex = nIndex; + + const auto *p = reinterpret_cast(&sv_RxBuffer[nPortIndex].Rdm.data[0]); + + if ((nIndex >= 24) && (nIndex <= sizeof(struct TRdmMessage)) && (nIndex == p->message_length)) { + sv_RxBuffer[nPortIndex].State = TxRxState::CHECKSUMH; + } else if (nIndex > sizeof(struct TRdmMessage)) { + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; } + } break; - case TxRxState::RDMDISC: - nIndex = s_RxBuffer[nPortIndex].Rdm.nIndex; - - if (nIndex < 24) { - s_RxBuffer[nPortIndex].data[nIndex] = data; - s_RxBuffer[nPortIndex].Rdm.nIndex++; - } - -#if DMX_MAX_PORTS >= 5 - if (nPortIndex < 4) { -#endif - nCounter = static_cast(TIMER_CNT(TIMER2)); -#if DMX_MAX_PORTS >= 5 - } else { - nCounter = static_cast(TIMER_CNT(TIMER3)); - } -#endif - { - const uint16_t nDelta = nCounter - sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious; - sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious = nCounter; - const auto nPulse = static_cast(nCounter + nDelta + 4); + case TxRxState::CHECKSUMH: { + auto nIndex = sv_RxBuffer[nPortIndex].Rdm.nIndex; + sv_RxBuffer[nPortIndex].Rdm.data[nIndex] = data; + nIndex++; + sv_RxBuffer[nPortIndex].Rdm.nIndex = nIndex; + sv_RxBuffer[nPortIndex].State = TxRxState::CHECKSUML; + } + break; + case TxRxState::CHECKSUML: { + auto nIndex = sv_RxBuffer[nPortIndex].Rdm.nIndex; + sv_RxBuffer[nPortIndex].Rdm.data[nIndex] = data; + nIndex |= 0x4000; + sv_RxBuffer[nPortIndex].Rdm.nIndex = nIndex; + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; + gsv_RdmDataReceiveEnd = DWT->CYCCNT; + } + break; + case TxRxState::RDMDISC: { + auto nIndex = sv_RxBuffer[nPortIndex].Rdm.nIndex; - switch(nPortIndex){ - case 0: - TIMER_CH0CV(TIMER2) = nPulse; - break; -#if DMX_MAX_PORTS >= 2 - case 1: - TIMER_CH1CV(TIMER2) = nPulse; - break; -#endif -#if DMX_MAX_PORTS >= 3 - case 2: - TIMER_CH2CV(TIMER2) = nPulse; - break; -#endif -#if DMX_MAX_PORTS >= 4 - case 3: - TIMER_CH3CV(TIMER2) = nPulse; - break; -#endif -#if DMX_MAX_PORTS >= 5 - case 4: - TIMER_CH0CV(TIMER3) = nPulse; - break; -#endif -#if DMX_MAX_PORTS >= 6 - case 5: - TIMER_CH1CV(TIMER3) = nPulse; - break; -#endif -#if DMX_MAX_PORTS >= 7 - case 6: - TIMER_CH2CV(TIMER3) = nPulse; - break; -#endif -#if DMX_MAX_PORTS == 8 - case 7: - TIMER_CH3CV(TIMER3) = nPulse; - break; -#endif - default: - assert(0); - __builtin_unreachable(); - break; - } - } - break; - default: - s_RxBuffer[nPortIndex].Dmx.nSlotsInPacket= 0; // This is correct. - s_RxBuffer[nPortIndex].State = TxRxState::IDLE; - break; + if (nIndex < 24) { + sv_RxBuffer[nPortIndex].Rdm.data[nIndex] = data; + nIndex++; + sv_RxBuffer[nPortIndex].Rdm.nIndex = nIndex; + } + } + break; + default: + sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket = 0; + sv_RxBuffer[nPortIndex].Rdm.nIndex = 0; + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; + break; } } @@ -428,42 +294,42 @@ extern "C" { #if !defined(CONFIG_DMX_TRANSMIT_ONLY) #if defined (DMX_USE_USART0) void USART0_IRQHandler(void) { - irq_handler_dmx_rdm_input(USART0, config::USART0_PORT); + irq_handler_dmx_rdm_input(); } #endif #if defined (DMX_USE_USART1) void USART1_IRQHandler(void) { - irq_handler_dmx_rdm_input(USART1, config::USART1_PORT); + irq_handler_dmx_rdm_input(); } #endif #if defined (DMX_USE_USART2) void USART2_IRQHandler(void) { - irq_handler_dmx_rdm_input(USART2, config::USART2_PORT); + irq_handler_dmx_rdm_input(); } #endif #if defined (DMX_USE_UART3) void UART3_IRQHandler(void) { - irq_handler_dmx_rdm_input(UART3, config::UART3_PORT); + irq_handler_dmx_rdm_input(); } #endif #if defined (DMX_USE_UART4) void UART4_IRQHandler(void) { - irq_handler_dmx_rdm_input(UART4, config::UART4_PORT); + irq_handler_dmx_rdm_input(); } #endif #if defined (DMX_USE_USART5) void USART5_IRQHandler(void) { - irq_handler_dmx_rdm_input(USART5, config::USART5_PORT); + irq_handler_dmx_rdm_input(); } #endif #if defined (DMX_USE_UART6) void UART6_IRQHandler(void) { - irq_handler_dmx_rdm_input(UART6, config::UART6_PORT); + irq_handler_dmx_rdm_input(); } #endif #if defined (DMX_USE_UART7) void UART7_IRQHandler(void) { - irq_handler_dmx_rdm_input(UART7, config::UART7_PORT); + irq_handler_dmx_rdm_input(); } #endif #endif @@ -474,6 +340,7 @@ static void timer1_config() { timer_deinit(TIMER1); timer_parameter_struct timer_initpara; + timer_struct_para_init(&timer_initpara); timer_initpara.prescaler = TIMER_PSC_1MHZ; timer_initpara.alignedmode = TIMER_COUNTER_EDGE; @@ -489,22 +356,26 @@ static void timer1_config() { #if defined (DMX_USE_USART0) timer_channel_output_mode_config(TIMER1, TIMER_CH_0, TIMER_OC_MODE_ACTIVE); timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, ~0); -#endif + timer_interrupt_enable(TIMER1, TIMER_INT_CH0); +#endif /* DMX_USE_USART0 */ #if defined (DMX_USE_USART1) timer_channel_output_mode_config(TIMER1, TIMER_CH_1, TIMER_OC_MODE_ACTIVE); timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, ~0); -#endif + timer_interrupt_enable(TIMER1, TIMER_INT_CH1); +#endif /* DMX_USE_USART1 */ #if defined (DMX_USE_USART2) timer_channel_output_mode_config(TIMER1, TIMER_CH_2, TIMER_OC_MODE_ACTIVE); timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2, ~0); -#endif + timer_interrupt_enable(TIMER1, TIMER_INT_CH2); +#endif /* DMX_USE_USART2 */ #if defined (DMX_USE_UART3) - timer_channel_output_mode_config(TIMER1, TIMER_CH_2, TIMER_OC_MODE_ACTIVE); + timer_channel_output_mode_config(TIMER1, TIMER_CH_3, TIMER_OC_MODE_ACTIVE); timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_3, ~0); -#endif + timer_interrupt_enable(TIMER1, TIMER_INT_CH3); +#endif /* DMX_USE_UART3 */ NVIC_SetPriority(TIMER1_IRQn, 0); NVIC_EnableIRQ(TIMER1_IRQn); @@ -517,6 +388,7 @@ static void timer4_config() { timer_deinit(TIMER4); timer_parameter_struct timer_initpara; + timer_struct_para_init(&timer_initpara); timer_initpara.prescaler = TIMER_PSC_1MHZ; timer_initpara.alignedmode = TIMER_COUNTER_EDGE; @@ -532,22 +404,26 @@ static void timer4_config() { #if defined (DMX_USE_UART4) timer_channel_output_mode_config(TIMER4, TIMER_CH_0, TIMER_OC_MODE_ACTIVE); timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_0, ~0); -#endif + timer_interrupt_enable(TIMER4, TIMER_INT_CH0); +#endif /* DMX_USE_UART4 */ #if defined (DMX_USE_USART5) timer_channel_output_mode_config(TIMER4, TIMER_CH_1, TIMER_OC_MODE_ACTIVE); timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_1, ~0); -#endif + timer_interrupt_enable(TIMER4, TIMER_INT_CH1); +#endif /* DMX_USE_USART5 */ #if defined (DMX_USE_UART6) timer_channel_output_mode_config(TIMER4, TIMER_CH_2, TIMER_OC_MODE_ACTIVE); timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2, ~0); -#endif + timer_interrupt_enable(TIMER4, TIMER_INT_CH2); +#endif /* DMX_USE_UART6 */ #if defined (DMX_USE_UART7) timer_channel_output_mode_config(TIMER4, TIMER_CH_3, TIMER_OC_MODE_ACTIVE); timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_3, ~0); -#endif + timer_interrupt_enable(TIMER4, TIMER_INT_CH3); +#endif /* DMX_USE_UART7 */ NVIC_SetPriority(TIMER4_IRQn, 0); NVIC_EnableIRQ(TIMER4_IRQn); @@ -555,116 +431,47 @@ static void timer4_config() { timer_enable(TIMER4); } -#if !defined(CONFIG_DMX_TRANSMIT_ONLY) -static void timer2_config() { - rcu_periph_clock_enable(RCU_TIMER2); - timer_deinit(TIMER2); - - timer_parameter_struct timer_initpara; - - timer_initpara.prescaler = TIMER_PSC_1MHZ; - timer_initpara.alignedmode = TIMER_COUNTER_EDGE; - timer_initpara.counterdirection = TIMER_COUNTER_UP; - timer_initpara.period = static_cast(~0); - timer_initpara.clockdivision = TIMER_CKDIV_DIV1; - timer_initpara.repetitioncounter = 0; - timer_init(TIMER2, &timer_initpara); - - timer_flag_clear(TIMER2, ~0); - timer_interrupt_flag_clear(TIMER2, ~0); - - timer_channel_output_mode_config(TIMER2, TIMER_CH_0, TIMER_OC_MODE_ACTIVE); - timer_channel_output_mode_config(TIMER2, TIMER_CH_1, TIMER_OC_MODE_ACTIVE); - timer_channel_output_mode_config(TIMER2, TIMER_CH_2, TIMER_OC_MODE_ACTIVE); - timer_channel_output_mode_config(TIMER2, TIMER_CH_3, TIMER_OC_MODE_ACTIVE); - - NVIC_SetPriority(TIMER2_IRQn, 1); - NVIC_EnableIRQ(TIMER2_IRQn); - - timer_enable(TIMER2); -} - -static void timer3_config() { -#if DMX_MAX_PORTS >= 5 - rcu_periph_clock_enable(RCU_TIMER3); - timer_deinit(TIMER3); - - timer_parameter_struct timer_initpara; - - timer_initpara.prescaler = TIMER_PSC_1MHZ; - timer_initpara.alignedmode = TIMER_COUNTER_EDGE; - timer_initpara.counterdirection = TIMER_COUNTER_UP; - timer_initpara.period = static_cast(~0); - timer_initpara.clockdivision = TIMER_CKDIV_DIV1; - timer_initpara.repetitioncounter = 0; - timer_init(TIMER3, &timer_initpara); - - timer_flag_clear(TIMER3, ~0); - timer_interrupt_flag_clear(TIMER3, ~0); - - timer_channel_output_mode_config(TIMER3, TIMER_CH_0, TIMER_OC_MODE_ACTIVE); - timer_channel_output_mode_config(TIMER3, TIMER_CH_1, TIMER_OC_MODE_ACTIVE); - timer_channel_output_mode_config(TIMER3, TIMER_CH_2, TIMER_OC_MODE_ACTIVE); - timer_channel_output_mode_config(TIMER3, TIMER_CH_3, TIMER_OC_MODE_ACTIVE); - - NVIC_SetPriority(TIMER3_IRQn, 1); - NVIC_EnableIRQ(TIMER3_IRQn); - - timer_enable(TIMER3); -#endif -} - -static void timer6_config() { - rcu_periph_clock_enable(RCU_TIMER6); - timer_deinit(TIMER6); - - timer_parameter_struct timer_initpara; - timer_initpara.prescaler = TIMER_PSC_10KHZ; - timer_initpara.period = 10000; // 1 second - timer_init(TIMER6, &timer_initpara); - - timer_flag_clear(TIMER6, ~0); - timer_interrupt_flag_clear(TIMER6, ~0); - - timer_interrupt_enable(TIMER6, TIMER_INT_UP); - - NVIC_SetPriority(TIMER6_IRQn, 0); - NVIC_EnableIRQ(TIMER6_IRQn); - - timer_enable(TIMER6); -} -#endif - static void usart_dma_config(void) { DMA_PARAMETER_STRUCT dma_init_struct; rcu_periph_clock_enable(RCU_DMA0); rcu_periph_clock_enable(RCU_DMA1); +#if defined (GD32H7XX) + rcu_periph_clock_enable(RCU_DMAMUX); +#endif +#if defined (DMX_USE_USART0) /* - * USART 0 + * USART 0 TX */ -#if defined (DMX_USE_USART0) - dma_deinit(USART0_DMA, USART0_TX_DMA_CH); + dma_deinit(USART0_DMAx, USART0_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_USART0_TX; +# endif dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; -#if !defined (GD32F4XX) +# if defined (GD32F4XX) || defined (GD32H7XX) +# else dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; -#endif +# endif +# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(USART0); +# else dma_init_struct.periph_addr = USART0 + 0x04U; +# endif dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; -#if !defined (GD32F4XX) - dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; -#else +# if defined (GD32F4XX) || defined (GD32H7XX) dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; -#endif +# else + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; +# endif dma_init_struct.priority = DMA_PRIORITY_HIGH; - dma_init(USART0_DMA, USART0_TX_DMA_CH, &dma_init_struct); + dma_init(USART0_DMAx, USART0_TX_DMA_CHx, &dma_init_struct); /* configure DMA mode */ - dma_circulation_disable(USART0_DMA, USART0_TX_DMA_CH); - dma_memory_to_memory_disable(USART0_DMA, USART0_TX_DMA_CH); + dma_circulation_disable(USART0_DMAx, USART0_TX_DMA_CHx); + dma_memory_to_memory_disable(USART0_DMAx, USART0_TX_DMA_CHx); # if defined (GD32F4XX) - dma_channel_subperipheral_select(USART0_DMA, USART0_TX_DMA_CH, USART0_TX_DMA_SUBPERIx); + dma_channel_subperipheral_select(USART0_DMAx, USART0_TX_DMA_CHx, USART0_TX_DMA_SUBPERIx); # endif - dma_interrupt_disable(USART0_DMA, USART0_TX_DMA_CH, DMA_INTERRUPT_DISABLE); + gd32_dma_interrupt_disable(); # if !defined (GD32F4XX) NVIC_SetPriority(DMA0_Channel3_IRQn, 1); NVIC_EnableIRQ(DMA0_Channel3_IRQn); @@ -672,91 +479,120 @@ static void usart_dma_config(void) { NVIC_SetPriority(DMA1_Channel7_IRQn, 1); NVIC_EnableIRQ(DMA1_Channel7_IRQn); # endif -#endif +#endif /* DMX_USE_USART0 */ +#if defined (DMX_USE_USART1) /* - * USART 1 + * USART 1 TX */ -#if defined (DMX_USE_USART1) - dma_deinit(USART1_DMA, USART1_TX_DMA_CH); + dma_deinit(USART1_DMAx, USART1_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_USART1_TX; +# endif dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; -#if !defined (GD32F4XX) +# if defined (GD32F4XX) || defined (GD32H7XX) +# else dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; -#endif +# endif +# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(USART1); +# else dma_init_struct.periph_addr = USART1 + 0x04U; +# endif dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; -#if !defined (GD32F4XX) - dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; -#else +# if defined (GD32F4XX) || defined (GD32H7XX) dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; -#endif +# else + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; +# endif dma_init_struct.priority = DMA_PRIORITY_HIGH; - dma_init(USART1_DMA, USART1_TX_DMA_CH, &dma_init_struct); + dma_init(USART1_DMAx, USART1_TX_DMA_CHx, &dma_init_struct); /* configure DMA mode */ - dma_circulation_disable(USART1_DMA, USART1_TX_DMA_CH); - dma_memory_to_memory_disable(USART1_DMA, USART1_TX_DMA_CH); + dma_circulation_disable(USART1_DMAx, USART1_TX_DMA_CHx); + dma_memory_to_memory_disable(USART1_DMAx, USART1_TX_DMA_CHx); # if defined (GD32F4XX) - dma_channel_subperipheral_select(USART1_DMA, USART1_TX_DMA_CH, USART1_TX_DMA_SUBPERIx); + dma_channel_subperipheral_select(USART1_DMAx, USART1_TX_DMA_CHx, USART1_TX_DMA_SUBPERIx); # endif - dma_interrupt_disable(USART1_DMA, USART1_TX_DMA_CH, DMA_INTERRUPT_DISABLE); + gd32_dma_interrupt_disable(); NVIC_SetPriority(DMA0_Channel6_IRQn, 1); NVIC_EnableIRQ(DMA0_Channel6_IRQn); -#endif +#endif /* DMX_USE_USART1 */ +#if defined (DMX_USE_USART2) /* - * USART 2 + * USART 2 TX */ -#if defined (DMX_USE_USART2) - dma_deinit(USART2_DMA, USART2_TX_DMA_CH); + dma_deinit(USART2_DMAx, USART2_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_USART2_TX; +# endif dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; -# if !defined (GD32F4XX) +# if defined (GD32F4XX) || defined (GD32H7XX) +# else dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; # endif - dma_init_struct.periph_addr = USART2 + 0x04U; +//# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(USART2); +//# else +// dma_init_struct.periph_addr = USART2 + 0x04U; +//# endif dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; -# if !defined (GD32F4XX) - dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; -# else +# if defined (GD32F4XX) || defined (GD32H7XX) dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; +# else + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; # endif dma_init_struct.priority = DMA_PRIORITY_HIGH; - dma_init(USART2_DMA, USART2_TX_DMA_CH, &dma_init_struct); + dma_init(USART2_DMAx, USART2_TX_DMA_CHx, &dma_init_struct); /* configure DMA mode */ - dma_circulation_disable(USART2_DMA, USART2_TX_DMA_CH); - dma_memory_to_memory_disable(USART2_DMA, USART2_TX_DMA_CH); + dma_circulation_disable(USART2_DMAx, USART2_TX_DMA_CHx); + dma_memory_to_memory_disable(USART2_DMAx, USART2_TX_DMA_CHx); # if defined (GD32F4XX) - dma_channel_subperipheral_select(USART2_DMA, USART2_TX_DMA_CH, USART2_TX_DMA_SUBPERIx); + dma_channel_subperipheral_select(USART2_DMAx, USART2_TX_DMA_CHx, USART2_TX_DMA_SUBPERIx); # endif - dma_interrupt_disable(USART2_DMA, USART2_TX_DMA_CH, DMA_INTERRUPT_DISABLE); + gd32_dma_interrupt_disable(); +#if defined (GD32F4XX) || defined (GD32H7XX) + NVIC_SetPriority(DMA0_Channel3_IRQn, 1); + NVIC_EnableIRQ(DMA0_Channel3_IRQn); +# else NVIC_SetPriority(DMA0_Channel1_IRQn, 1); NVIC_EnableIRQ(DMA0_Channel1_IRQn); -#endif +# endif +#endif /* DMX_USE_USART2 */ +#if defined (DMX_USE_UART3) /* - * UART 3 + * UART 3 TX */ -#if defined (DMX_USE_UART3) - dma_deinit(DMA1, DMA_CH4); + dma_deinit(UART3_DMAx, UART3_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_UART3_TX; +# endif dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; -#if !defined (GD32F4XX) +# if defined (GD32F4XX) || defined (GD32H7XX) +# else dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; -#endif +# endif +# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(UART3); +# else dma_init_struct.periph_addr = UART3 + 0x04U; +# endif dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; -#if !defined (GD32F4XX) - dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; -#else +# if defined (GD32F4XX) || defined (GD32H7XX) dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; -#endif +# else + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; +# endif dma_init_struct.priority = DMA_PRIORITY_HIGH; - dma_init(DMA1, DMA_CH4, &dma_init_struct); + dma_init(UART3_DMAx, UART3_TX_DMA_CHx, &dma_init_struct); /* configure DMA mode */ - dma_circulation_disable(DMA1, DMA_CH4); - dma_memory_to_memory_disable(DMA1, DMA_CH4); + dma_circulation_disable(UART3_DMAx, UART3_TX_DMA_CHx); + dma_memory_to_memory_disable(UART3_DMAx, UART3_TX_DMA_CHx); # if defined (GD32F4XX) - dma_channel_subperipheral_select(UART3_DMA, UART3_TX_DMA_CH, UART3_TX_DMA_SUBPERIx); + dma_channel_subperipheral_select(UART3_DMAx, UART3_TX_DMA_CHx, UART3_TX_DMA_SUBPERIx); # endif - dma_interrupt_disable(USART0_DMA, USART0_TX_DMA_CH, DMA_INTERRUPT_DISABLE); + gd32_dma_interrupt_disable(); # if !defined (GD32F4XX) NVIC_SetPriority(DMA1_Channel4_IRQn, 1); NVIC_EnableIRQ(DMA1_Channel4_IRQn); @@ -764,96 +600,118 @@ static void usart_dma_config(void) { NVIC_SetPriority(DMA0_Channel4_IRQn, 1); NVIC_EnableIRQ(DMA0_Channel4_IRQn); # endif -#endif +#endif /* DMX_USE_UART3 */ +#if defined (DMX_USE_UART4) /* - * UART 4 + * UART 4 TX */ -#if defined (DMX_USE_UART4) - dma_deinit(UART4_DMA, UART4_TX_DMA_CH); + dma_deinit(UART4_DMAx, UART4_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_UART4_TX; +# endif dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; -#if !defined (GD32F4XX) +# if defined (GD32F4XX) || defined (GD32H7XX) +# else dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; -#endif +# endif +# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(UART4); +# else dma_init_struct.periph_addr = UART4 + 0x04U; +# endif dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; -#if !defined (GD32F4XX) - dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; -#else +#if defined (GD32F4XX) || defined (GD32H7XX) dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; +#else + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; #endif dma_init_struct.priority = DMA_PRIORITY_HIGH; - dma_init(UART4_DMA, UART4_TX_DMA_CH, &dma_init_struct); + dma_init(UART4_DMAx, UART4_TX_DMA_CHx, &dma_init_struct); /* configure DMA mode */ - dma_circulation_disable(UART4_DMA, UART4_TX_DMA_CH); - dma_memory_to_memory_disable(UART4_DMA, UART4_TX_DMA_CH); + dma_circulation_disable(UART4_DMAx, UART4_TX_DMA_CHx); + dma_memory_to_memory_disable(UART4_DMAx, UART4_TX_DMA_CHx); # if defined (GD32F4XX) - dma_channel_subperipheral_select(UART4_DMA, UART4_TX_DMA_CH, UART4_TX_DMA_SUBPERIx); + dma_channel_subperipheral_select(UART4_DMAx, UART4_TX_DMA_CHx, UART4_TX_DMA_SUBPERIx); # endif - dma_interrupt_disable(UART4_DMA, UART4_TX_DMA_CH, DMA_INTERRUPT_DISABLE); -# if defined (GD32F20X) + gd32_dma_interrupt_disable(); +# if !defined (GD32F4XX) NVIC_SetPriority(DMA1_Channel3_IRQn, 1); NVIC_EnableIRQ(DMA1_Channel3_IRQn); # else NVIC_SetPriority(DMA0_Channel7_IRQn, 1); NVIC_EnableIRQ(DMA0_Channel7_IRQn); # endif -#endif +#endif /* DMX_USE_UART4 */ +#if defined (DMX_USE_USART5) /* - * USART 5 + * USART 5 TX */ -#if defined (DMX_USE_USART5) - dma_deinit(USART5_DMA, USART5_TX_DMA_CH); + dma_deinit(USART5_DMAx, USART5_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_USART5_TX; +# endif dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; -#if !defined (GD32F4XX) +# if defined (GD32F20X) dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; -#endif +# endif +# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(USART5); +# else dma_init_struct.periph_addr = USART5 + 0x04U; +# endif dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; -#if !defined (GD32F4XX) +#if defined (GD32F20X) dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; -#else +# else dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; #endif dma_init_struct.priority = DMA_PRIORITY_HIGH; - dma_init(USART5_DMA, USART5_TX_DMA_CH, &dma_init_struct); + dma_init(USART5_DMAx, USART5_TX_DMA_CHx, &dma_init_struct); /* configure DMA mode */ - dma_circulation_disable(USART5_DMA, USART5_TX_DMA_CH); - dma_memory_to_memory_disable(USART5_DMA, USART5_TX_DMA_CH); + dma_circulation_disable(USART5_DMAx, USART5_TX_DMA_CHx); + dma_memory_to_memory_disable(USART5_DMAx, USART5_TX_DMA_CHx); # if defined (GD32F4XX) - dma_channel_subperipheral_select(USART5_DMA, USART5_TX_DMA_CH, USART5_TX_DMA_SUBPERIx); + dma_channel_subperipheral_select(USART5_DMAx, USART5_TX_DMA_CHx, USART5_TX_DMA_SUBPERIx); # endif - dma_interrupt_disable(USART5_DMA, USART5_TX_DMA_CH, DMA_INTERRUPT_DISABLE); + gd32_dma_interrupt_disable(); NVIC_SetPriority(DMA1_Channel6_IRQn, 1); NVIC_EnableIRQ(DMA1_Channel6_IRQn); -#endif +#endif /* DMX_USE_USART5 */ +#if defined (DMX_USE_UART6) /* - * UART 6 + * UART 6 TX */ -#if defined (DMX_USE_UART6) - dma_deinit(UART6_DMA, UART6_TX_DMA_CH); + dma_deinit(UART6_DMAx, UART6_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_UART6_TX; +# endif dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; -#if !defined (GD32F4XX) +# if defined (GD32F20X) dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; -#endif +# endif +# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(UART6); +# else dma_init_struct.periph_addr = UART6 + 0x04U; +# endif dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; -#if !defined (GD32F4XX) +# if defined (GD32F20X) dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; -#else +# else dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; -#endif +# endif dma_init_struct.priority = DMA_PRIORITY_HIGH; - dma_init(UART6_DMA, UART6_TX_DMA_CH, &dma_init_struct); + dma_init(UART6_DMAx, UART6_TX_DMA_CHx, &dma_init_struct); /* configure DMA mode */ - dma_circulation_disable(UART6_DMA, UART6_TX_DMA_CH); - dma_memory_to_memory_disable(UART6_DMA, UART6_TX_DMA_CH); + dma_circulation_disable(UART6_DMAx, UART6_TX_DMA_CHx); + dma_memory_to_memory_disable(UART6_DMAx, UART6_TX_DMA_CHx); # if defined (GD32F4XX) - dma_channel_subperipheral_select(UART6_DMA, UART6_TX_DMA_CH, UART6_TX_DMA_SUBPERIx); + dma_channel_subperipheral_select(UART6_DMAx, UART6_TX_DMA_CHx, UART6_TX_DMA_SUBPERIx); # endif - dma_interrupt_disable(UART6_DMA, UART4_TX_DMA_CH, DMA_INTERRUPT_DISABLE); + gd32_dma_interrupt_disable(); # if defined (GD32F20X) NVIC_SetPriority(DMA1_Channel4_IRQn, 1); NVIC_EnableIRQ(DMA1_Channel4_IRQn); @@ -861,40 +719,47 @@ static void usart_dma_config(void) { NVIC_SetPriority(DMA0_Channel1_IRQn, 1); NVIC_EnableIRQ(DMA0_Channel1_IRQn); # endif -#endif +#endif /* DMX_USE_UART6 */ +#if defined (DMX_USE_UART7) /* - * UART 7 + * UART 7 TX */ -#if defined (DMX_USE_UART7) - dma_deinit(UART7_DMA, UART7_TX_DMA_CH); + dma_deinit(UART7_DMAx, UART7_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_UART7_TX; +# endif dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; -#if !defined (GD32F4XX) +# if defined (GD32F20X) dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; -#endif +# endif +# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(UART7); +# else dma_init_struct.periph_addr = UART7 + 0x04U; +# endif dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; -#if !defined (GD32F4XX) +# if defined (GD32F20X) dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; -#else +# else dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; -#endif +# endif dma_init_struct.priority = DMA_PRIORITY_HIGH; - dma_init(UART7_DMA, UART7_TX_DMA_CH, &dma_init_struct); + dma_init(UART7_DMAx, UART7_TX_DMA_CHx, &dma_init_struct); /* configure DMA mode */ - dma_circulation_disable(UART7_DMA, UART7_TX_DMA_CH); - dma_memory_to_memory_disable(UART7_DMA, UART7_TX_DMA_CH); + dma_circulation_disable(UART7_DMAx, UART7_TX_DMA_CHx); + dma_memory_to_memory_disable(UART7_DMAx, UART7_TX_DMA_CHx); # if defined (GD32F4XX) - dma_channel_subperipheral_select(UART7_DMA, UART7_TX_DMA_CH, UART7_TX_DMA_SUBPERIx); + dma_channel_subperipheral_select(UART7_DMAx, UART7_TX_DMA_CHx, UART7_TX_DMA_SUBPERIx); # endif -# if defined (GD32F20X) +#if defined (GD32F20X) NVIC_SetPriority(DMA1_Channel3_IRQn, 1); NVIC_EnableIRQ(DMA1_Channel3_IRQn); # else NVIC_SetPriority(DMA0_Channel0_IRQn, 1); NVIC_EnableIRQ(DMA0_Channel0_IRQn); # endif -#endif +#endif /* DMX_USE_UART7 */ } extern "C" { @@ -906,36 +771,35 @@ void TIMER1_IRQHandler() { if ((TIMER_INTF(TIMER1) & TIMER_INT_FLAG_CH0) == TIMER_INT_FLAG_CH0) { switch (s_TxBuffer[dmx::config::USART0_PORT].State) { case TxRxState::DMXINTER: - _gpio_mode_output(USART0_GPIO_PORT, USART0_TX_PIN); - GPIO_BC(USART0_GPIO_PORT) = USART0_TX_PIN; + gd32_gpio_mode_output(); + GPIO_BC(USART0_GPIOx) = USART0_TX_GPIO_PINx; s_TxBuffer[dmx::config::USART0_PORT].State = TxRxState::BREAK; - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime); + TIMER_CH0CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmit.nBreakTime; break; case TxRxState::BREAK: - _gpio_mode_af(USART0_GPIO_PORT, USART0_TX_PIN, USART0); + gd32_gpio_mode_af(); s_TxBuffer[dmx::config::USART0_PORT].State = TxRxState::MAB; - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, TIMER_CNT(TIMER1) + s_nDmxTransmitMabTime); + TIMER_CH0CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmit.nMabTime; break; case TxRxState::MAB: { - uint32_t dmaCHCTL = DMA_CHCTL(USART0_DMA, USART0_TX_DMA_CH); + uint32_t dmaCHCTL = DMA_CHCTL(USART0_DMAx, USART0_TX_DMA_CHx); dmaCHCTL &= ~DMA_CHXCTL_CHEN; - DMA_CHCTL(USART0_DMA, USART0_TX_DMA_CH) = dmaCHCTL; - dma_interrupt_flag_clear(USART0_DMA, USART0_TX_DMA_CH, DMA_INTF_FTFIF); + DMA_CHCTL(USART0_DMAx, USART0_TX_DMA_CHx) = dmaCHCTL; + gd32_dma_interrupt_flag_clear(); const auto *p = &s_TxBuffer[dmx::config::USART0_PORT].dmx; - DMA_CHMADDR(USART0_DMA, USART0_TX_DMA_CH) = (uint32_t) p->data; - DMA_CHCNT(USART0_DMA, USART0_TX_DMA_CH) = (p->nLength & DMA_CHXCNT_CNT); + DMA_CHMADDR(USART0_DMAx, USART0_TX_DMA_CHx) = (uint32_t) p->data; + DMA_CHCNT(USART0_DMAx, USART0_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); dmaCHCTL |= DMA_CHXCTL_CHEN; dmaCHCTL |= DMA_INTERRUPT_ENABLE; - DMA_CHCTL(USART0_DMA, USART0_TX_DMA_CH) = dmaCHCTL; - usart_dma_transmit_config(USART0, USART_DENT_ENABLE); + DMA_CHCTL(USART0_DMAx, USART0_TX_DMA_CHx) = dmaCHCTL; + USART_CTL2(USART0) |= USART_TRANSMIT_DMA_ENABLE; } - break; + break; default: break; } - timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_CH0); - return; + TIMER_INTF(TIMER1) = static_cast(~TIMER_INT_FLAG_CH0); } #endif /* @@ -945,36 +809,35 @@ void TIMER1_IRQHandler() { if ((TIMER_INTF(TIMER1) & TIMER_INT_FLAG_CH1) == TIMER_INT_FLAG_CH1) { switch (s_TxBuffer[dmx::config::USART1_PORT].State) { case TxRxState::DMXINTER: - _gpio_mode_output(USART1_GPIO_PORT, USART1_TX_PIN); - GPIO_BC(USART1_GPIO_PORT) = USART1_TX_PIN; + gd32_gpio_mode_output(); + GPIO_BC(USART1_GPIOx) = USART1_TX_GPIO_PINx; s_TxBuffer[dmx::config::USART1_PORT].State = TxRxState::BREAK; - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime); + TIMER_CH1CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmit.nBreakTime; break; case TxRxState::BREAK: - _gpio_mode_af(USART1_GPIO_PORT, USART1_TX_PIN, USART1); + gd32_gpio_mode_af(); s_TxBuffer[dmx::config::USART1_PORT].State = TxRxState::MAB; - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, TIMER_CNT(TIMER1) + s_nDmxTransmitMabTime); + TIMER_CH1CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmit.nMabTime; break; case TxRxState::MAB: { - uint32_t dmaCHCTL = DMA_CHCTL(USART1_DMA, USART1_TX_DMA_CH); + uint32_t dmaCHCTL = DMA_CHCTL(USART1_DMAx, USART1_TX_DMA_CHx); dmaCHCTL &= ~DMA_CHXCTL_CHEN; - DMA_CHCTL(USART1_DMA, USART1_TX_DMA_CH) = dmaCHCTL; - dma_interrupt_flag_clear(USART1_DMA, USART1_TX_DMA_CH, DMA_INTF_FTFIF); + DMA_CHCTL(USART1_DMAx, USART1_TX_DMA_CHx) = dmaCHCTL; + gd32_dma_interrupt_flag_clear(); const auto *p = &s_TxBuffer[dmx::config::USART1_PORT].dmx; - DMA_CHMADDR(USART1_DMA, USART1_TX_DMA_CH) = (uint32_t) p->data; - DMA_CHCNT(USART1_DMA, USART1_TX_DMA_CH) = (p->nLength & DMA_CHXCNT_CNT); + DMA_CHMADDR(USART1_DMAx, USART1_TX_DMA_CHx) = (uint32_t) p->data; + DMA_CHCNT(USART1_DMAx, USART1_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); dmaCHCTL |= DMA_CHXCTL_CHEN; dmaCHCTL |= DMA_INTERRUPT_ENABLE; - DMA_CHCTL(USART1_DMA, USART1_TX_DMA_CH) = dmaCHCTL; - usart_dma_transmit_config(USART1, USART_DENT_ENABLE); + DMA_CHCTL(USART1_DMAx, USART1_TX_DMA_CHx) = dmaCHCTL; + USART_CTL2(USART1) |= USART_TRANSMIT_DMA_ENABLE; } - break; + break; default: break; } - timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_CH1); - return; + TIMER_INTF(TIMER1) = static_cast(~TIMER_INT_FLAG_CH1); } #endif /* @@ -984,39 +847,35 @@ void TIMER1_IRQHandler() { if ((TIMER_INTF(TIMER1) & TIMER_INT_FLAG_CH2) == TIMER_INT_FLAG_CH2) { switch (s_TxBuffer[dmx::config::USART2_PORT].State) { case TxRxState::DMXINTER: - _gpio_mode_output(USART2_GPIO_PORT, USART2_TX_PIN); - GPIO_BC(USART2_GPIO_PORT) = USART2_TX_PIN; - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2, TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime); + gd32_gpio_mode_output(); + GPIO_BC(USART2_GPIOx) = USART2_TX_GPIO_PINx; s_TxBuffer[dmx::config::USART2_PORT].State = TxRxState::BREAK; + TIMER_CH2CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmit.nBreakTime; break; case TxRxState::BREAK: - _gpio_mode_af(USART2_GPIO_PORT, USART2_TX_PIN, USART2); - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2, TIMER_CNT(TIMER1) + s_nDmxTransmitMabTime); + gd32_gpio_mode_af(); s_TxBuffer[dmx::config::USART2_PORT].State = TxRxState::MAB; + TIMER_CH2CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmit.nMabTime; break; case TxRxState::MAB: { - uint32_t dmaCHCTL = DMA_CHCTL(USART2_DMA, USART2_TX_DMA_CH); + uint32_t dmaCHCTL = DMA_CHCTL(USART2_DMAx, USART2_TX_DMA_CHx); dmaCHCTL &= ~DMA_CHXCTL_CHEN; - DMA_CHCTL(USART2_DMA, USART2_TX_DMA_CH) = dmaCHCTL; + DMA_CHCTL(USART2_DMAx, USART2_TX_DMA_CHx) = dmaCHCTL; + gd32_dma_interrupt_flag_clear(); const auto *p = &s_TxBuffer[dmx::config::USART2_PORT].dmx; - DMA_CHMADDR(USART2_DMA, USART2_TX_DMA_CH) = (uint32_t) p->data; - DMA_CHCNT(USART2_DMA, USART2_TX_DMA_CH) = (p->nLength & DMA_CHXCNT_CNT); + DMA_CHMADDR(USART2_DMAx, USART2_TX_DMA_CHx) = (uint32_t) p->data; + DMA_CHCNT(USART2_DMAx, USART2_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); dmaCHCTL |= DMA_CHXCTL_CHEN; dmaCHCTL |= DMA_INTERRUPT_ENABLE; - DMA_CHCTL(USART2_DMA, USART2_TX_DMA_CH) = dmaCHCTL; - usart_dma_transmit_config(USART2, USART_DENT_ENABLE); - s_TxBuffer[dmx::config::USART2_PORT].State = TxRxState::DMXDATA; + DMA_CHCTL(USART2_DMAx, USART2_TX_DMA_CHx) = dmaCHCTL; + USART_CTL2(USART2) |= USART_TRANSMIT_DMA_ENABLE; } - break; - case TxRxState::DMXDATA: - console_error("DMXDATA:USART2"); - break; + break; default: break; } - timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_CH2); - return; + TIMER_INTF(TIMER1) = static_cast(~TIMER_INT_FLAG_CH2); } #endif /* @@ -1026,38 +885,39 @@ void TIMER1_IRQHandler() { if ((TIMER_INTF(TIMER1) & TIMER_INT_FLAG_CH3) == TIMER_INT_FLAG_CH3) { switch (s_TxBuffer[dmx::config::UART3_PORT].State) { case TxRxState::DMXINTER: - _gpio_mode_output(UART3_GPIO_PORT, UART3_TX_PIN); - GPIO_BC(UART3_GPIO_PORT) = UART3_TX_PIN; + gd32_gpio_mode_output(); + GPIO_BC(UART3_GPIOx) = UART3_TX_GPIO_PINx; s_TxBuffer[dmx::config::UART3_PORT].State = TxRxState::BREAK; - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_3, TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime); + TIMER_CH3CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmit.nBreakTime; break; case TxRxState::BREAK: - _gpio_mode_af(UART3_GPIO_PORT, UART3_TX_PIN, UART3); + gd32_gpio_mode_af(); s_TxBuffer[dmx::config::UART3_PORT].State = TxRxState::MAB; - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_3, TIMER_CNT(TIMER1) + s_nDmxTransmitMabTime); + TIMER_CH3CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmit.nMabTime; break; case TxRxState::MAB: { - uint32_t dmaCHCTL = DMA_CHCTL(UART3_DMA, UART3_TX_DMA_CH); + uint32_t dmaCHCTL = DMA_CHCTL(UART3_DMAx, UART3_TX_DMA_CHx); dmaCHCTL &= ~DMA_CHXCTL_CHEN; - DMA_CHCTL(UART3_DMA, UART3_TX_DMA_CH) = dmaCHCTL; - dma_interrupt_flag_clear(UART3_DMA, UART3_TX_DMA_CH, DMA_INTF_FTFIF); + DMA_CHCTL(UART3_DMAx, UART3_TX_DMA_CHx) = dmaCHCTL; + gd32_dma_interrupt_flag_clear(); const auto *p = &s_TxBuffer[dmx::config::UART3_PORT].dmx; - DMA_CHMADDR(UART3_DMA, UART3_TX_DMA_CH) = (uint32_t) p->data; - DMA_CHCNT(UART3_DMA, UART3_TX_DMA_CH) = (p->nLength & DMA_CHXCNT_CNT); + DMA_CHMADDR(UART3_DMAx, UART3_TX_DMA_CHx) = (uint32_t) p->data; + DMA_CHCNT(UART3_DMAx, UART3_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); dmaCHCTL |= DMA_CHXCTL_CHEN; dmaCHCTL |= DMA_INTERRUPT_ENABLE; - DMA_CHCTL(UART3_DMA, UART3_TX_DMA_CH) = dmaCHCTL; - usart_dma_transmit_config(UART3, USART_DENT_ENABLE); + DMA_CHCTL(UART3_DMAx, UART3_TX_DMA_CHx) = dmaCHCTL; + USART_CTL2(UART3) |= USART_TRANSMIT_DMA_ENABLE; } - break; + break; default: break; } - timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_CH3); - return; + TIMER_INTF(TIMER1) = static_cast(~TIMER_INT_FLAG_CH3); } #endif + // Clear all remaining interrupt flags (safety measure) + TIMER_INTF(TIMER1) = static_cast(~0); } void TIMER4_IRQHandler() { @@ -1068,35 +928,35 @@ void TIMER4_IRQHandler() { if ((TIMER_INTF(TIMER4) & TIMER_INT_FLAG_CH0) == TIMER_INT_FLAG_CH0) { switch (s_TxBuffer[dmx::config::UART4_PORT].State) { case TxRxState::DMXINTER: - _gpio_mode_output(UART4_GPIO_TX_PORT, UART4_TX_PIN); - GPIO_BC(UART4_GPIO_TX_PORT) = UART4_TX_PIN; + gd32_gpio_mode_output(); + GPIO_BC(UART4_TX_GPIOx) = UART4_TX_GPIO_PINx; s_TxBuffer[dmx::config::UART4_PORT].State = TxRxState::BREAK; - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_0, TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime); + TIMER_CH0CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmit.nBreakTime; break; case TxRxState::BREAK: - _gpio_mode_af(UART4_GPIO_TX_PORT, UART4_TX_PIN, UART4); + gd32_gpio_mode_af(); s_TxBuffer[dmx::config::UART4_PORT].State = TxRxState::MAB; - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_0, TIMER_CNT(TIMER4) + s_nDmxTransmitMabTime); + TIMER_CH0CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmit.nMabTime; break; case TxRxState::MAB: { - uint32_t dmaCHCTL = DMA_CHCTL(UART4_DMA, UART4_TX_DMA_CH); + uint32_t dmaCHCTL = DMA_CHCTL(UART4_DMAx, UART4_TX_DMA_CHx); dmaCHCTL &= ~DMA_CHXCTL_CHEN; - DMA_CHCTL(UART4_DMA, UART4_TX_DMA_CH) = dmaCHCTL; + DMA_CHCTL(UART4_DMAx, UART4_TX_DMA_CHx) = dmaCHCTL; + gd32_dma_interrupt_flag_clear(); const auto *p = &s_TxBuffer[dmx::config::UART4_PORT].dmx; - DMA_CHMADDR(UART4_DMA, UART4_TX_DMA_CH) = (uint32_t) p->data; - DMA_CHCNT(UART4_DMA, UART4_TX_DMA_CH) = (p->nLength & DMA_CHXCNT_CNT); + DMA_CHMADDR(UART4_DMAx, UART4_TX_DMA_CHx) = (uint32_t) p->data; + DMA_CHCNT(UART4_DMAx, UART4_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); dmaCHCTL |= DMA_CHXCTL_CHEN; dmaCHCTL |= DMA_INTERRUPT_ENABLE; - DMA_CHCTL(UART4_DMA, UART4_TX_DMA_CH) = dmaCHCTL; - usart_dma_transmit_config(UART4, USART_DENT_ENABLE); + DMA_CHCTL(UART4_DMAx, UART4_TX_DMA_CHx) = dmaCHCTL; + USART_CTL2(UART4) |= USART_TRANSMIT_DMA_ENABLE; } - break; + break; default: break; } - timer_interrupt_flag_clear(TIMER4, TIMER_INT_FLAG_CH0); - return; + TIMER_INTF(TIMER4) = static_cast(~TIMER_INT_FLAG_CH0); } #endif /* @@ -1106,35 +966,35 @@ void TIMER4_IRQHandler() { if ((TIMER_INTF(TIMER4) & TIMER_INT_FLAG_CH1) == TIMER_INT_FLAG_CH1) { switch (s_TxBuffer[dmx::config::USART5_PORT].State) { case TxRxState::DMXINTER: - _gpio_mode_output(USART5_GPIO_PORT, USART5_TX_PIN); - GPIO_BC(USART5_GPIO_PORT) = USART5_TX_PIN; + gd32_gpio_mode_output(); + GPIO_BC(USART5_GPIOx) = USART5_TX_GPIO_PINx; s_TxBuffer[dmx::config::USART5_PORT].State = TxRxState::BREAK; - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_1, TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime); + TIMER_CH1CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmit.nBreakTime; break; case TxRxState::BREAK: - _gpio_mode_af(USART5_GPIO_PORT, USART5_TX_PIN, USART5); + gd32_gpio_mode_af(); s_TxBuffer[dmx::config::USART5_PORT].State = TxRxState::MAB; - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_1, TIMER_CNT(TIMER4) + s_nDmxTransmitMabTime); + TIMER_CH1CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmit.nMabTime; break; case TxRxState::MAB: { - uint32_t dmaCHCTL = DMA_CHCTL(USART5_DMA, USART5_TX_DMA_CH); + uint32_t dmaCHCTL = DMA_CHCTL(USART5_DMAx, USART5_TX_DMA_CHx); dmaCHCTL &= ~DMA_CHXCTL_CHEN; - DMA_CHCTL(USART5_DMA, USART5_TX_DMA_CH) = dmaCHCTL; + DMA_CHCTL(USART5_DMAx, USART5_TX_DMA_CHx) = dmaCHCTL; + gd32_dma_interrupt_flag_clear(); const auto *p = &s_TxBuffer[dmx::config::USART5_PORT].dmx; - DMA_CHMADDR(USART5_DMA, USART5_TX_DMA_CH) = (uint32_t) p->data; - DMA_CHCNT(USART5_DMA, USART5_TX_DMA_CH) = (p->nLength & DMA_CHXCNT_CNT); + DMA_CHMADDR(USART5_DMAx, USART5_TX_DMA_CHx) = (uint32_t) p->data; + DMA_CHCNT(USART5_DMAx, USART5_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); dmaCHCTL |= DMA_CHXCTL_CHEN; dmaCHCTL |= DMA_INTERRUPT_ENABLE; - DMA_CHCTL(USART5_DMA, USART5_TX_DMA_CH) = dmaCHCTL; - usart_dma_transmit_config(USART5, USART_DENT_ENABLE); + DMA_CHCTL(USART5_DMAx, USART5_TX_DMA_CHx) = dmaCHCTL; + USART_CTL2(USART5) |= USART_TRANSMIT_DMA_ENABLE; } - break; + break; default: break; } - timer_interrupt_flag_clear(TIMER4, TIMER_INT_FLAG_CH1); - return; + TIMER_INTF(TIMER4) = static_cast(~TIMER_INT_FLAG_CH1); } #endif /* @@ -1144,36 +1004,35 @@ void TIMER4_IRQHandler() { if ((TIMER_INTF(TIMER4) & TIMER_INT_FLAG_CH2) == TIMER_INT_FLAG_CH2) { switch (s_TxBuffer[dmx::config::UART6_PORT].State) { case TxRxState::DMXINTER: - _gpio_mode_output(UART6_GPIO_PORT, UART6_TX_PIN); - GPIO_BC(UART6_GPIO_PORT) = UART6_TX_PIN; + gd32_gpio_mode_output(); + GPIO_BC(UART6_GPIOx) = UART6_TX_GPIO_PINx; s_TxBuffer[dmx::config::UART6_PORT].State = TxRxState::BREAK; - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2, TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime); + TIMER_CH2CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmit.nBreakTime; break; case TxRxState::BREAK: - _gpio_mode_af(UART6_GPIO_PORT, UART6_TX_PIN, UART6); + gd32_gpio_mode_af(); s_TxBuffer[dmx::config::UART6_PORT].State = TxRxState::MAB; - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2, TIMER_CNT(TIMER4) + s_nDmxTransmitMabTime); + TIMER_CH2CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmit.nMabTime; break; case TxRxState::MAB: { - uint32_t dmaCHCTL = DMA_CHCTL(UART6_DMA, UART6_TX_DMA_CH); + uint32_t dmaCHCTL = DMA_CHCTL(UART6_DMAx, UART6_TX_DMA_CHx); dmaCHCTL &= ~DMA_CHXCTL_CHEN; - DMA_CHCTL(UART6_DMA, UART6_TX_DMA_CH)= dmaCHCTL; - dma_interrupt_flag_clear(UART6_DMA, UART6_TX_DMA_CH, DMA_INTF_FTFIF); + DMA_CHCTL(UART6_DMAx, UART6_TX_DMA_CHx)= dmaCHCTL; + gd32_dma_interrupt_flag_clear(); const auto *p = &s_TxBuffer[dmx::config::UART6_PORT].dmx; - DMA_CHMADDR(UART6_DMA, UART6_TX_DMA_CH) = (uint32_t) p->data; - DMA_CHCNT(UART6_DMA, UART6_TX_DMA_CH) = (p->nLength & DMA_CHXCNT_CNT); + DMA_CHMADDR(UART6_DMAx, UART6_TX_DMA_CHx) = (uint32_t) p->data; + DMA_CHCNT(UART6_DMAx, UART6_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); dmaCHCTL |= DMA_CHXCTL_CHEN; dmaCHCTL |= DMA_INTERRUPT_ENABLE; - DMA_CHCTL(UART6_DMA, UART6_TX_DMA_CH)= dmaCHCTL; - usart_dma_transmit_config(UART6, USART_DENT_ENABLE); + DMA_CHCTL(UART6_DMAx, UART6_TX_DMA_CHx)= dmaCHCTL; + USART_CTL2(UART6) |= USART_TRANSMIT_DMA_ENABLE; } - break; + break; default: break; } - timer_interrupt_flag_clear(TIMER4, TIMER_INT_FLAG_CH2); - return; + TIMER_INTF(TIMER4) = static_cast(~TIMER_INT_FLAG_CH2); } #endif /* @@ -1183,184 +1042,102 @@ void TIMER4_IRQHandler() { if ((TIMER_INTF(TIMER4) & TIMER_INT_FLAG_CH3) == TIMER_INT_FLAG_CH3) { switch (s_TxBuffer[dmx::config::UART7_PORT].State) { case TxRxState::DMXINTER: - _gpio_mode_output(UART7_GPIO_PORT, UART7_TX_PIN); - GPIO_BC(UART7_GPIO_PORT) = UART7_TX_PIN; + gd32_gpio_mode_output(); + GPIO_BC(UART7_GPIOx) = UART7_TX_GPIO_PINx; s_TxBuffer[dmx::config::UART7_PORT].State = TxRxState::BREAK; - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2, TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime); + TIMER_CH3CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmit.nBreakTime; break; case TxRxState::BREAK: - _gpio_mode_af(UART7_GPIO_PORT, UART7_TX_PIN, UART7); + gd32_gpio_mode_af(); s_TxBuffer[dmx::config::UART7_PORT].State = TxRxState::MAB; - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2, TIMER_CNT(TIMER4) + s_nDmxTransmitMabTime); + TIMER_CH3CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmit.nMabTime; break; case TxRxState::MAB: { - uint32_t dmaCHCTL = DMA_CHCTL(UART7_DMA, UART7_TX_DMA_CH); + uint32_t dmaCHCTL = DMA_CHCTL(UART7_DMAx, UART7_TX_DMA_CHx); dmaCHCTL &= ~DMA_CHXCTL_CHEN; - DMA_CHCTL(UART7_DMA, UART7_TX_DMA_CH) = dmaCHCTL; - dma_interrupt_flag_clear(UART7_DMA, UART7_TX_DMA_CH, DMA_INTF_FTFIF); + DMA_CHCTL(UART7_DMAx, UART7_TX_DMA_CHx) = dmaCHCTL; + gd32_dma_interrupt_flag_clear(); const auto *p = &s_TxBuffer[dmx::config::UART7_PORT].dmx; - DMA_CHMADDR(UART7_DMA, UART7_TX_DMA_CH) = (uint32_t) p->data; - DMA_CHCNT(UART7_DMA, UART7_TX_DMA_CH) = (p->nLength & DMA_CHXCNT_CNT); + DMA_CHMADDR(UART7_DMAx, UART7_TX_DMA_CHx) = (uint32_t) p->data; + DMA_CHCNT(UART7_DMAx, UART7_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); dmaCHCTL |= DMA_CHXCTL_CHEN; dmaCHCTL |= DMA_INTERRUPT_ENABLE; - usart_dma_transmit_config(UART7, USART_DENT_ENABLE); + DMA_CHCTL(UART7_DMAx, UART7_TX_DMA_CHx)= dmaCHCTL; + USART_CTL2(UART7) |= USART_TRANSMIT_DMA_ENABLE; } - break; + break; default: break; } - timer_interrupt_flag_clear(TIMER4, TIMER_INT_FLAG_CH3); - return; + TIMER_INTF(TIMER4) = static_cast(~TIMER_INT_FLAG_CH3); } #endif + // Clear all remaining interrupt flags (safety measure) + TIMER_INTF(TIMER4) = static_cast(~0); } -#if !defined(CONFIG_DMX_TRANSMIT_ONLY) -void TIMER2_IRQHandler() { - const auto nIntFlag = TIMER_INTF(TIMER2); - - if ((nIntFlag & TIMER_INT_FLAG_CH0) == TIMER_INT_FLAG_CH0) { - if (s_RxBuffer[0].State == TxRxState::DMXDATA) { - s_RxBuffer[0].State = TxRxState::IDLE; - s_RxBuffer[0].Dmx.nSlotsInPacket |= 0x8000; - } else if (s_RxBuffer[0].State == TxRxState::RDMDISC) { - s_RxBuffer[0].State = TxRxState::IDLE; - s_RxBuffer[0].Dmx.nSlotsInPacket |= 0x4000; - } - } -#if DMX_MAX_PORTS >= 2 - else if ((nIntFlag & TIMER_INT_FLAG_CH1) == TIMER_INT_FLAG_CH1) { - if (s_RxBuffer[1].State == TxRxState::DMXDATA) { - s_RxBuffer[1].State = TxRxState::IDLE; - s_RxBuffer[1].Dmx.nSlotsInPacket |= 0x8000; - } else if (s_RxBuffer[1].State == TxRxState::RDMDISC) { - s_RxBuffer[1].State = TxRxState::IDLE; - s_RxBuffer[1].Dmx.nSlotsInPacket |= 0x4000; - } - } -#endif -#if DMX_MAX_PORTS >= 3 - else if ((nIntFlag & TIMER_INT_FLAG_CH2) == TIMER_INT_FLAG_CH2) { - if (s_RxBuffer[2].State == TxRxState::DMXDATA) { - s_RxBuffer[2].State = TxRxState::IDLE; - s_RxBuffer[2].Dmx.nSlotsInPacket |= 0x8000; - } else if (s_RxBuffer[2].State == TxRxState::RDMDISC) { - s_RxBuffer[2].State = TxRxState::IDLE; - s_RxBuffer[2].Dmx.nSlotsInPacket |= 0x4000; - } - } -#endif -#if DMX_MAX_PORTS >= 4 - else if ((nIntFlag & TIMER_INT_FLAG_CH3) == TIMER_INT_FLAG_CH3) { - if (s_RxBuffer[3].State == TxRxState::DMXDATA) { - s_RxBuffer[3].State = TxRxState::IDLE; - s_RxBuffer[3].Dmx.nSlotsInPacket |= 0x8000; - } else if (s_RxBuffer[3].State == TxRxState::RDMDISC) { - s_RxBuffer[3].State = TxRxState::IDLE; - s_RxBuffer[3].Dmx.nSlotsInPacket |= 0x4000; - } - } -#endif - timer_interrupt_flag_clear(TIMER2, nIntFlag); -} +void TIMER6_IRQHandler() { + const auto nIntFlag = TIMER_INTF(TIMER6); -void TIMER3_IRQHandler() { - const auto nIntFlag = TIMER_INTF(TIMER3); -#if DMX_MAX_PORTS >= 5 - if ((nIntFlag & TIMER_INT_FLAG_CH0) == TIMER_INT_FLAG_CH0) { - if (s_RxBuffer[4].State == TxRxState::DMXDATA) { - s_RxBuffer[4].State = TxRxState::IDLE; - s_RxBuffer[4].Dmx.nSlotsInPacket |= 0x8000; - } else if (s_RxBuffer[4].State == TxRxState::RDMDISC) { - s_RxBuffer[4].State = TxRxState::IDLE; - s_RxBuffer[4].Dmx.nSlotsInPacket |= 0x4000; - } - } -# if DMX_MAX_PORTS >= 6 - else if ((nIntFlag & TIMER_INT_FLAG_CH1) == TIMER_INT_FLAG_CH1) { - if (s_RxBuffer[5].State == TxRxState::DMXDATA) { - s_RxBuffer[5].State = TxRxState::IDLE; - s_RxBuffer[5].Dmx.nSlotsInPacket |= 0x8000; - } else if (s_RxBuffer[5].State == TxRxState::RDMDISC) { - s_RxBuffer[5].State = TxRxState::IDLE; - s_RxBuffer[5].Dmx.nSlotsInPacket |= 0x4000; - } - } -# endif -# if DMX_MAX_PORTS >= 7 - else if ((nIntFlag & TIMER_INT_FLAG_CH2) == TIMER_INT_FLAG_CH2) { - if (s_RxBuffer[6].State == TxRxState::DMXDATA) { - s_RxBuffer[6].State = TxRxState::IDLE; - s_RxBuffer[6].Dmx.nSlotsInPacket |= 0x8000; - } else if (s_RxBuffer[6].State == TxRxState::RDMDISC) { - s_RxBuffer[6].State = TxRxState::IDLE; - s_RxBuffer[6].Dmx.nSlotsInPacket |= 0x4000; - } - } -# endif -# if DMX_MAX_PORTS == 8 - else if ((nIntFlag & TIMER_INT_FLAG_CH3) == TIMER_INT_FLAG_CH3) { - if (s_RxBuffer[7].State == TxRxState::DMXDATA) { - s_RxBuffer[7].State = TxRxState::IDLE; - s_RxBuffer[7].Dmx.nSlotsInPacket |= 0x8000; - } else if (s_RxBuffer[7].State == TxRxState::RDMDISC) { - s_RxBuffer[7].State = TxRxState::IDLE; - s_RxBuffer[7].Dmx.nSlotsInPacket |= 0x4000; + if ((nIntFlag & TIMER_INT_FLAG_UP) == TIMER_INT_FLAG_UP) { +#if !defined(CONFIG_DMX_TRANSMIT_ONLY) + for (uint32_t i = 0; i < DMX_MAX_PORTS; i++) { + auto &packet = sv_nRxDmxPackets[i]; + packet.nPerSecond = sv_nRxDmxPackets[i].nCount - packet.nCountPrevious; + packet.nCountPrevious = packet.nCount; } - } -# endif #endif - timer_interrupt_flag_clear(TIMER3, nIntFlag); -} - -void TIMER6_IRQHandler() { - for (auto i = 0; i < DMX_MAX_PORTS; i++) { - sv_nRxDmxPackets[i].nPerSecond = sv_nRxDmxPackets[i].nCount - sv_nRxDmxPackets[i].nCountPrevious; - sv_nRxDmxPackets[i].nCountPrevious = sv_nRxDmxPackets[i].nCount; + g_Seconds.nUptime++; } - timer_interrupt_flag_clear(TIMER6, TIMER_INT_FLAG_UP); + // Clear all remaining interrupt flags (safety measure) + TIMER_INTF(TIMER6) = static_cast(~nIntFlag); } -#endif } -#include - extern "C" { /* * USART 0 */ #if defined (DMX_USE_USART0) -# if !defined (GD32F4XX) -void DMA0_Channel3_IRQHandler() { - if (dma_interrupt_flag_get(DMA0, DMA_CH3, DMA_INTERRUPT_FLAG_GET) == SET) { - dma_interrupt_disable(DMA0, DMA_CH3, DMA_INTERRUPT_DISABLE); +# if defined (GD32F4XX) || defined (GD32H7XX) +void DMA1_Channel7_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); if (s_TxBuffer[dmx::config::USART0_PORT].outputStyle == dmx::OutputStyle::DELTA) { s_TxBuffer[dmx::config::USART0_PORT].State = TxRxState::IDLE; } else { - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0 , TIMER_CNT(TIMER1) + s_nDmxTransmitInterTime); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0 , TIMER_CNT(TIMER1) + s_nDmxTransmit.nInterTime); s_TxBuffer[dmx::config::USART0_PORT].State = TxRxState::DMXINTER; } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::USART0_PORT].Dmx.Sent++; +#endif } - dma_interrupt_flag_clear(DMA0, DMA_CH3, DMA_INTERRUPT_FLAG_CLEAR); + gd32_dma_interrupt_flag_clear(); } # else -void DMA1_Channel7_IRQHandler() { - if (dma_interrupt_flag_get(DMA1, DMA_CH7, DMA_INTERRUPT_FLAG_GET) == SET) { - dma_interrupt_disable(DMA1, DMA_CH7, DMA_INTERRUPT_DISABLE); +void DMA0_Channel3_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); if (s_TxBuffer[dmx::config::USART0_PORT].outputStyle == dmx::OutputStyle::DELTA) { s_TxBuffer[dmx::config::USART0_PORT].State = TxRxState::IDLE; } else { - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0 , TIMER_CNT(TIMER1) + s_nDmxTransmitInterTime); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0 , TIMER_CNT(TIMER1) + s_nDmxTransmit.nInterTime); s_TxBuffer[dmx::config::USART0_PORT].State = TxRxState::DMXINTER; } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::USART0_PORT].Dmx.Sent++; +#endif } - dma_interrupt_flag_clear(DMA1, DMA_CH7, DMA_INTERRUPT_FLAG_CLEAR); + gd32_dma_interrupt_flag_clear(); } # endif #endif @@ -1369,55 +1146,65 @@ void DMA1_Channel7_IRQHandler() { */ #if defined (DMX_USE_USART1) void DMA0_Channel6_IRQHandler() { - if (dma_interrupt_flag_get(DMA0, DMA_CH6, DMA_INTERRUPT_FLAG_GET) == SET) { - dma_interrupt_disable(DMA0, DMA_CH6, DMA_INTERRUPT_DISABLE); + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); if (s_TxBuffer[dmx::config::USART1_PORT].outputStyle == dmx::OutputStyle::DELTA) { s_TxBuffer[dmx::config::USART1_PORT].State = TxRxState::IDLE; } else { - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1 , TIMER_CNT(TIMER1) + s_nDmxTransmitInterTime); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1 , TIMER_CNT(TIMER1) + s_nDmxTransmit.nInterTime); s_TxBuffer[dmx::config::USART1_PORT].State = TxRxState::DMXINTER; } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::USART1_PORT].Dmx.Sent++; +#endif } - dma_interrupt_flag_clear(DMA0, DMA_CH6, DMA_INTERRUPT_FLAG_CLEAR); + gd32_dma_interrupt_flag_clear(); } #endif /* * USART 2 */ #if defined (DMX_USE_USART2) -# if !defined (GD32F4XX) -void DMA0_Channel1_IRQHandler() { - if (dma_interrupt_flag_get(DMA0, DMA_CH1, DMA_INTERRUPT_FLAG_GET) == SET) { - dma_interrupt_disable(DMA0, DMA_CH1, DMA_INTERRUPT_DISABLE); - - usart_flag_clear(USART2, USART_FLAG_TC); +# if defined (GD32F4XX) || defined (GD32H7XX) +void DMA0_Channel3_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); if (s_TxBuffer[dmx::config::USART2_PORT].outputStyle == dmx::OutputStyle::DELTA) { s_TxBuffer[dmx::config::USART2_PORT].State = TxRxState::IDLE; } else { - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2 , TIMER_CNT(TIMER1) + s_nDmxTransmitInterTime); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2 , TIMER_CNT(TIMER1) + s_nDmxTransmit.nInterTime); s_TxBuffer[dmx::config::USART2_PORT].State = TxRxState::DMXINTER; } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::USART2_PORT].Dmx.Sent++; +#endif } - dma_interrupt_flag_clear(DMA0, DMA_CH1, DMA_INTERRUPT_FLAG_CLEAR); + gd32_dma_interrupt_flag_clear(); } # else -void DMA0_Channel3_IRQHandler() { - if (dma_interrupt_flag_get(DMA0, DMA_CH3, DMA_INTERRUPT_FLAG_GET) == SET) { - dma_interrupt_disable(DMA0, DMA_CH3, DMA_INTERRUPT_DISABLE); +void DMA0_Channel1_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); if (s_TxBuffer[dmx::config::USART2_PORT].outputStyle == dmx::OutputStyle::DELTA) { s_TxBuffer[dmx::config::USART2_PORT].State = TxRxState::IDLE; } else { - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2 , TIMER_CNT(TIMER1) + s_nDmxTransmitInterTime); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2 , TIMER_CNT(TIMER1) + s_nDmxTransmit.nInterTime); s_TxBuffer[dmx::config::USART2_PORT].State = TxRxState::DMXINTER; } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::USART2_PORT].Dmx.Sent++; +#endif } - dma_interrupt_flag_clear(DMA0, DMA_CH3, DMA_INTERRUPT_FLAG_CLEAR); + gd32_dma_interrupt_flag_clear(); } # endif #endif @@ -1425,36 +1212,43 @@ void DMA0_Channel3_IRQHandler() { * UART 3 */ #if defined (DMX_USE_UART3) -# if !defined (GD32F4XX) -void DMA1_Channel4_IRQHandler() { - if (dma_interrupt_flag_get(DMA1, DMA_CH4, DMA_INTERRUPT_FLAG_GET) == SET) { - dma_interrupt_disable(DMA1, DMA_CH4, DMA_INTERRUPT_DISABLE); +# if defined (GD32F4XX) || defined (GD32H7XX) +void DMA0_Channel4_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); if (s_TxBuffer[dmx::config::UART3_PORT].outputStyle == dmx::OutputStyle::DELTA) { s_TxBuffer[dmx::config::UART3_PORT].State = TxRxState::IDLE; } else { - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_3 , TIMER_CNT(TIMER1) + s_nDmxTransmitInterTime); + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_3 , TIMER_CNT(TIMER4) + s_nDmxTransmit.nInterTime); s_TxBuffer[dmx::config::UART3_PORT].State = TxRxState::DMXINTER; } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART3_PORT].Dmx.Sent++; +#endif } - dma_interrupt_flag_clear(DMA1, DMA_CH4, DMA_INTERRUPT_FLAG_CLEAR); + gd32_dma_interrupt_flag_clear(); } -# endif -# if defined (GD32F4XX) -void DMA0_Channel4_IRQHandler() { - if (dma_interrupt_flag_get(DMA0, DMA_CH4, DMA_INTERRUPT_FLAG_GET) == SET) { - dma_interrupt_disable(DMA0, DMA_CH4, DMA_INTERRUPT_DISABLE); +# else +void DMA1_Channel4_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); if (s_TxBuffer[dmx::config::UART3_PORT].outputStyle == dmx::OutputStyle::DELTA) { s_TxBuffer[dmx::config::UART3_PORT].State = TxRxState::IDLE; } else { - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_3 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_3 , TIMER_CNT(TIMER1) + s_nDmxTransmit.nInterTime); s_TxBuffer[dmx::config::UART3_PORT].State = TxRxState::DMXINTER; } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART3_PORT].Dmx.Sent++; +#endif } - dma_interrupt_flag_clear(DMA0, DMA_CH4, DMA_INTERRUPT_FLAG_CLEAR); + gd32_dma_interrupt_flag_clear(); } # endif #endif @@ -1464,34 +1258,42 @@ void DMA0_Channel4_IRQHandler() { #if defined (DMX_USE_UART4) # if defined (GD32F20X) void DMA1_Channel3_IRQHandler() { - if (dma_interrupt_flag_get(DMA1, DMA_CH3, DMA_INTERRUPT_FLAG_GET) == SET) { - dma_interrupt_disable(DMA1, DMA_CH3, DMA_INTERRUPT_DISABLE); + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); if (s_TxBuffer[dmx::config::UART4_PORT].outputStyle == dmx::OutputStyle::DELTA) { s_TxBuffer[dmx::config::UART4_PORT].State = TxRxState::IDLE; } else { - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_0 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_0 , TIMER_CNT(TIMER4) + s_nDmxTransmit.nInterTime); s_TxBuffer[dmx::config::UART4_PORT].State = TxRxState::DMXINTER; } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART4_PORT].Dmx.Sent++; +#endif } - dma_interrupt_flag_clear(DMA1, DMA_CH3, DMA_INTERRUPT_FLAG_CLEAR); + gd32_dma_interrupt_flag_clear(); } # endif -# if defined (GD32F4XX) +# if defined (GD32F4XX) || defined (GD32H7XX) void DMA0_Channel7_IRQHandler() { - if (dma_interrupt_flag_get(DMA0, DMA_CH7, DMA_INTERRUPT_FLAG_GET) == SET) { - dma_interrupt_disable(DMA0, DMA_CH7, DMA_INTERRUPT_DISABLE); + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); if (s_TxBuffer[dmx::config::UART4_PORT].outputStyle == dmx::OutputStyle::DELTA) { s_TxBuffer[dmx::config::UART4_PORT].State = TxRxState::IDLE; } else { - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_0 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_0 , TIMER_CNT(TIMER4) + s_nDmxTransmit.nInterTime); s_TxBuffer[dmx::config::UART4_PORT].State = TxRxState::DMXINTER; } } - dma_interrupt_flag_clear(DMA0, DMA_CH7, DMA_INTERRUPT_FLAG_CLEAR); +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART4_PORT].Dmx.Sent++; +#endif + + gd32_dma_interrupt_flag_clear(); } # endif #endif @@ -1500,18 +1302,22 @@ void DMA0_Channel7_IRQHandler() { */ #if defined (DMX_USE_USART5) void DMA1_Channel6_IRQHandler() { - if (dma_interrupt_flag_get(DMA1, DMA_CH6, DMA_INTERRUPT_FLAG_GET) == SET) { - dma_interrupt_disable(DMA1, DMA_CH6, DMA_INTERRUPT_DISABLE); + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); if (s_TxBuffer[dmx::config::USART5_PORT].outputStyle == dmx::OutputStyle::DELTA) { s_TxBuffer[dmx::config::USART5_PORT].State = TxRxState::IDLE; } else { - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_1 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_1 , TIMER_CNT(TIMER4) + s_nDmxTransmit.nInterTime); s_TxBuffer[dmx::config::USART5_PORT].State = TxRxState::DMXINTER; } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::USART5_PORT].Dmx.Sent++; +#endif } - dma_interrupt_flag_clear(DMA1, DMA_CH6, DMA_INTERRUPT_FLAG_CLEAR); + gd32_dma_interrupt_flag_clear(); } #endif /* @@ -1520,34 +1326,42 @@ void DMA1_Channel6_IRQHandler() { #if defined (DMX_USE_UART6) # if defined (GD32F20X) void DMA1_Channel4_IRQHandler() { - if (dma_interrupt_flag_get(DMA1, DMA_CH4, DMA_INTERRUPT_FLAG_GET) == SET) { - dma_interrupt_disable(DMA1, DMA_CH4, DMA_INTERRUPT_DISABLE); + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); if (s_TxBuffer[dmx::config::UART6_PORT].outputStyle == dmx::OutputStyle::DELTA) { s_TxBuffer[dmx::config::UART6_PORT].State = TxRxState::IDLE; } else { - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2 , TIMER_CNT(TIMER4) + s_nDmxTransmit.nInterTime); s_TxBuffer[dmx::config::UART6_PORT].State = TxRxState::DMXINTER; } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART6_PORT].Dmx.Sent++; +#endif } - dma_interrupt_flag_clear(DMA1, DMA_CH4, DMA_INTERRUPT_FLAG_CLEAR); + gd32_dma_interrupt_flag_clear(); } # endif -# if defined (GD32F4XX) +# if defined (GD32F4XX) || defined (GD32H7XX) void DMA0_Channel1_IRQHandler() { - if (dma_interrupt_flag_get(DMA0, DMA_CH1, DMA_INTERRUPT_FLAG_GET) == SET) { - dma_interrupt_disable(DMA0, DMA_CH1, DMA_INTERRUPT_DISABLE); + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); if (s_TxBuffer[dmx::config::UART6_PORT].outputStyle == dmx::OutputStyle::DELTA) { s_TxBuffer[dmx::config::UART6_PORT].State = TxRxState::IDLE; } else { - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2 , TIMER_CNT(TIMER4) + s_nDmxTransmit.nInterTime); s_TxBuffer[dmx::config::UART6_PORT].State = TxRxState::DMXINTER; } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART6_PORT].Dmx.Sent++; +#endif } - dma_interrupt_flag_clear(DMA0, DMA_CH1, DMA_INTERRUPT_FLAG_CLEAR); + gd32_dma_interrupt_flag_clear(); } # endif #endif @@ -1557,44 +1371,52 @@ void DMA0_Channel1_IRQHandler() { #if defined (DMX_USE_UART7) # if defined (GD32F20X) void DMA1_Channel3_IRQHandler() { - if (dma_interrupt_flag_get(DMA1, DMA_CH3, DMA_INTERRUPT_FLAG_GET) == SET) { - dma_interrupt_disable(DMA1, DMA_CH3, DMA_INTERRUPT_DISABLE); + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); if (s_TxBuffer[dmx::config::UART7_PORT].outputStyle == dmx::OutputStyle::DELTA) { s_TxBuffer[dmx::config::UART7_PORT].State = TxRxState::IDLE; } else { - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_3 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_3 , TIMER_CNT(TIMER4) + s_nDmxTransmit.nInterTime); s_TxBuffer[dmx::config::UART7_PORT].State = TxRxState::DMXINTER; } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART7_PORT].Dmx.Sent++; +#endif } - dma_interrupt_flag_clear(DMA1, DMA_CH3, DMA_INTERRUPT_FLAG_CLEAR); + gd32_dma_interrupt_flag_clear(); } # endif -# if defined (GD32F4XX) +# if defined (GD32F4XX) || defined (GD32H7XX) void DMA0_Channel0_IRQHandler() { - if (dma_interrupt_flag_get(DMA0, DMA_CH0, DMA_INTERRUPT_FLAG_GET) == SET) { - dma_interrupt_disable(DMA0, DMA_CH0, DMA_INTERRUPT_DISABLE); + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); if (s_TxBuffer[dmx::config::UART7_PORT].outputStyle == dmx::OutputStyle::DELTA) { s_TxBuffer[dmx::config::UART7_PORT].State = TxRxState::IDLE; } else { - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_3 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_3 , TIMER_CNT(TIMER4) + s_nDmxTransmit.nInterTime); s_TxBuffer[dmx::config::UART7_PORT].State = TxRxState::DMXINTER; } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART7_PORT].Dmx.Sent++; +#endif } - dma_interrupt_flag_clear(DMA0, DMA_CH0, DMA_INTERRUPT_FLAG_CLEAR); + gd32_dma_interrupt_flag_clear(); } # endif #endif } -static void uart_dmx_config(uint32_t usart_periph) { +static void uart_dmx_config(const uint32_t usart_periph) { gd32_uart_begin(usart_periph, 250000U, GD32_UART_BITS_8, GD32_UART_PARITY_NONE, GD32_UART_STOP_2BITS); } -Dmx *Dmx::s_pThis = nullptr; +Dmx *Dmx::s_pThis; Dmx::Dmx() { DEBUG_ENTRY @@ -1602,17 +1424,20 @@ Dmx::Dmx() { assert(s_pThis == nullptr); s_pThis = this; + s_nDmxTransmit.nBreakTime = dmx::transmit::BREAK_TIME_TYPICAL; + s_nDmxTransmit.nMabTime = dmx::transmit::MAB_TIME_MIN; + s_nDmxTransmit.nInterTime = dmx::transmit::PERIOD_DEFAULT - s_nDmxTransmit.nBreakTime - s_nDmxTransmit.nMabTime - (dmx::max::CHANNELS * 44) - 44; + for (auto i = 0; i < DMX_MAX_PORTS; i++) { -#if !defined (GD32F4XX) +#if defined (GPIO_INIT) gpio_init(s_DirGpio[i].nPort, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, s_DirGpio[i].nPin); #else gpio_mode_set(s_DirGpio[i].nPort, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, s_DirGpio[i].nPin); - gpio_output_options_set(s_DirGpio[i].nPort, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, s_DirGpio[i].nPin); - gpio_af_set(s_DirGpio[i].nPort, GPIO_AF_0, s_DirGpio[i].nPin); + gpio_output_options_set(s_DirGpio[i].nPort, GPIO_OTYPE_PP, GPIO_OSPEED, s_DirGpio[i].nPin); #endif m_nDmxTransmissionLength[i] = dmx::max::CHANNELS; SetPortDirection(i, PortDirection::INP, false); - s_RxBuffer[i].State = TxRxState::IDLE; + sv_RxBuffer[i].State = TxRxState::IDLE; s_TxBuffer[i].State = TxRxState::IDLE; s_TxBuffer[i].outputStyle = dmx::OutputStyle::DELTA; ClearData(i); @@ -1625,59 +1450,58 @@ Dmx::Dmx() { #if defined (DMX_USE_UART4) || defined (DMX_USE_USART5) || defined (DMX_USE_UART6) || defined (DMX_USE_UART7) timer4_config(); // DMX Transmit -> UART4, USART5, UART6, UART7 #endif -#if !defined(CONFIG_DMX_TRANSMIT_ONLY) - timer2_config(); // DMX Receive -> Slot time-out Port 0,1,2,3 - timer3_config(); // DMX Receive -> Slot time-out Port 4,5,6,7 - timer6_config(); // DMX Receive -> Updates per second -#endif #if defined (DMX_USE_USART0) uart_dmx_config(USART0); + NVIC_SetPriority(USART0_IRQn, 0); NVIC_EnableIRQ(USART0_IRQn); #endif #if defined (DMX_USE_USART1) uart_dmx_config(USART1); + NVIC_SetPriority(USART1_IRQn, 0); NVIC_EnableIRQ(USART1_IRQn); #endif #if defined (DMX_USE_USART2) uart_dmx_config(USART2); + NVIC_SetPriority(USART2_IRQn, 0); NVIC_EnableIRQ(USART2_IRQn); #endif #if defined (DMX_USE_UART3) uart_dmx_config(UART3); + NVIC_SetPriority(UART3_IRQn, 0); NVIC_EnableIRQ(UART3_IRQn); #endif #if defined (DMX_USE_UART4) uart_dmx_config(UART4); + NVIC_SetPriority(UART4_IRQn, 0); NVIC_EnableIRQ(UART4_IRQn); #endif #if defined (DMX_USE_USART5) uart_dmx_config(USART5); + NVIC_SetPriority(USART5_IRQn, 0); NVIC_EnableIRQ(USART5_IRQn); #endif #if defined (DMX_USE_UART6) uart_dmx_config(UART6); + NVIC_SetPriority(UART6_IRQn, 0); NVIC_EnableIRQ(UART6_IRQn); #endif #if defined (DMX_USE_UART7) uart_dmx_config(UART7); + NVIC_SetPriority(UART7_IRQn, 0); NVIC_EnableIRQ(UART7_IRQn); #endif - logic_analyzer::init(); DEBUG_EXIT } void Dmx::SetPortDirection(const uint32_t nPortIndex, PortDirection portDirection, bool bEnableData) { -// DEBUG_PRINTF("nPortIndex=%u %s %c", nPortIndex, portDirection == PortDirection::INP ? "Input" : "Output", bEnableData ? 'Y' : 'N'); - assert(nPortIndex < DMX_MAX_PORTS); - - const auto nUart = _port_to_uart(nPortIndex); + assert(nPortIndex < dmx::config::max::PORTS); if (m_dmxPortDirection[nPortIndex] != portDirection) { m_dmxPortDirection[nPortIndex] = portDirection; - StopData(nUart, nPortIndex); + StopData(nPortIndex); if (portDirection == PortDirection::OUTP) { GPIO_BOP(s_DirGpio[nPortIndex].nPort) = s_DirGpio[nPortIndex].nPin; @@ -1687,33 +1511,31 @@ void Dmx::SetPortDirection(const uint32_t nPortIndex, PortDirection portDirectio assert(0); } } else if (!bEnableData) { - StopData(nUart, nPortIndex); + StopData(nPortIndex); } if (bEnableData) { - StartData(nUart, nPortIndex); + StartData(nPortIndex); } } void Dmx::ClearData(const uint32_t nPortIndex) { - assert(nPortIndex < DMX_MAX_PORTS); + assert(nPortIndex < dmx::config::max::PORTS); auto *p = &s_TxBuffer[nPortIndex]; - auto *p16 = reinterpret_cast(p->dmx.data); - - for (auto i = 0; i < dmx::buffer::SIZE / 2; i++) { - *p16++ = 0; - } - p->dmx.nLength = 513; // Including START Code + __builtin_memset(p->dmx.data, 0, dmx::buffer::SIZE); } -void Dmx::StartDmxOutput(const uint32_t nPortIndex) { - logic_analyzer::ch2_set(); - - assert(nPortIndex < dmx::config::max::OUT); - const auto nUart = _port_to_uart(nPortIndex); +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) +volatile dmx::TotalStatistics& Dmx::GetTotalStatistics(const uint32_t nPortIndex) { + sv_TotalStatistics[nPortIndex].Dmx.Received = sv_nRxDmxPackets[nPortIndex].nCount; + return sv_TotalStatistics[nPortIndex]; +} +#endif +template +static void start_dmx_output() { /* * USART_FLAG_TC is set after power on. * The flag is cleared by DMA interrupt when maximum slots - 1 are transmitted. @@ -1727,211 +1549,228 @@ void Dmx::StartDmxOutput(const uint32_t nPortIndex) { /* TIMER 1 */ #if defined (DMX_USE_USART0) case USART0: - _gpio_mode_output(USART0_GPIO_PORT, USART0_TX_PIN); - GPIO_BC(USART0_GPIO_PORT) = USART0_TX_PIN; - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime); - timer_interrupt_enable(TIMER1, TIMER_INT_CH0); + gd32_gpio_mode_output(); + GPIO_BC(USART0_GPIOx) = USART0_TX_GPIO_PINx; + TIMER_CH0CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmit.nBreakTime; + s_TxBuffer[dmx::config::USART0_PORT].State = TxRxState::BREAK; + return; break; #endif #if defined (DMX_USE_USART1) case USART1: - _gpio_mode_output(USART1_GPIO_PORT, USART1_TX_PIN); - GPIO_BC(USART1_GPIO_PORT) = USART1_TX_PIN; - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime); - timer_interrupt_enable(TIMER1, TIMER_INT_CH1); + gd32_gpio_mode_output(); + GPIO_BC(USART1_GPIOx) = USART1_TX_GPIO_PINx; + TIMER_CH1CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmit.nBreakTime; + s_TxBuffer[dmx::config::USART1_PORT].State = TxRxState::BREAK; + return; break; #endif #if defined (DMX_USE_USART2) case USART2: - _gpio_mode_output(USART2_GPIO_PORT, USART2_TX_PIN); - GPIO_BC(USART2_GPIO_PORT) = USART2_TX_PIN; - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2, TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime); - timer_interrupt_enable(TIMER1, TIMER_INT_CH2); + gd32_gpio_mode_output(); + GPIO_BC(USART2_GPIOx) = USART2_TX_GPIO_PINx; + TIMER_CH2CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmit.nBreakTime; + s_TxBuffer[dmx::config::USART2_PORT].State = TxRxState::BREAK; + return; break; #endif #if defined (DMX_USE_UART3) case UART3: - _gpio_mode_output(UART3_GPIO_PORT, UART3_TX_PIN); - GPIO_BC(UART3_GPIO_PORT) = UART3_TX_PIN; - timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_3, TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime); - timer_interrupt_enable(TIMER1, TIMER_INT_CH3); + gd32_gpio_mode_output(); + GPIO_BC(UART3_GPIOx) = UART3_TX_GPIO_PINx; + TIMER_CH3CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmit.nBreakTime; + s_TxBuffer[dmx::config::UART3_PORT].State = TxRxState::BREAK; + return; break; #endif /* TIMER 4 */ #if defined (DMX_USE_UART4) case UART4: - _gpio_mode_output(UART4_GPIO_TX_PORT, UART4_TX_PIN); - GPIO_BC(UART4_GPIO_TX_PORT) = UART4_TX_PIN; - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_0, TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime); - timer_interrupt_enable(TIMER4, TIMER_INT_CH0); + gd32_gpio_mode_output(); + GPIO_BC(UART4_TX_GPIOx) = UART4_TX_GPIO_PINx; + TIMER_CH0CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmit.nBreakTime; + s_TxBuffer[dmx::config::UART4_PORT].State = TxRxState::BREAK; + return; break; #endif #if defined (DMX_USE_USART5) case USART5: - _gpio_mode_output(USART5_GPIO_PORT, USART5_TX_PIN); - GPIO_BC(USART5_GPIO_PORT) = USART5_TX_PIN; - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_1, TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime); - timer_interrupt_enable(TIMER4, TIMER_INT_CH1); + gd32_gpio_mode_output(); + GPIO_BC(USART5_GPIOx) = USART5_TX_GPIO_PINx; + TIMER_CH1CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmit.nBreakTime; + s_TxBuffer[dmx::config::USART5_PORT].State = TxRxState::BREAK; + return; break; #endif #if defined (DMX_USE_UART6) case UART6: - _gpio_mode_output(UART6_GPIO_PORT, UART6_TX_PIN); - GPIO_BC(UART6_GPIO_PORT) = UART6_TX_PIN; - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2, TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime); - timer_interrupt_enable(TIMER4, TIMER_INT_CH2); + gd32_gpio_mode_output(); + GPIO_BC(UART6_GPIOx) = UART6_TX_GPIO_PINx; + TIMER_CH2CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmit.nBreakTime; + s_TxBuffer[dmx::config::UART6_PORT].State = TxRxState::BREAK; + return; break; #endif #if defined (DMX_USE_UART7) case UART7: - _gpio_mode_output(UART7_GPIO_PORT, UART7_TX_PIN); - GPIO_BC(UART7_GPIO_PORT) = UART7_TX_PIN; - timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_3, TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime); - timer_interrupt_enable(TIMER4, TIMER_INT_CH3); + gd32_gpio_mode_output(); + GPIO_BC(UART7_GPIOx) = UART7_TX_GPIO_PINx; + TIMER_CH3CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmit.nBreakTime; + s_TxBuffer[dmx::config::UART7_PORT].State = TxRxState::BREAK; + return; break; #endif default: assert(0); + __builtin_unreachable(); break; } - s_TxBuffer[nPortIndex].State = TxRxState::BREAK; + assert(0); + __builtin_unreachable(); +} - logic_analyzer::ch2_clear(); +template +static void start_dmx_output_port() { + if constexpr (portIndex < dmx::config::max::PORTS) { + start_dmx_output(); + } } +void Dmx::StartDmxOutput(const uint32_t nPortIndex) { + assert(nPortIndex < dmx::config::max::PORTS); + + switch (nPortIndex) { + case 0: + start_dmx_output_port<0>(); + break; + case 1: + start_dmx_output_port<1>(); + break; + case 2: + start_dmx_output_port<2>(); + break; + case 3: + start_dmx_output_port<3>(); + break; + case 4: + start_dmx_output_port<4>(); + break; + case 5: + start_dmx_output_port<5>(); + break; + case 6: + start_dmx_output_port<6>(); + break; + case 7: + start_dmx_output_port<7>(); + break; + default: + break; + } +} -void Dmx::StopData(const uint32_t nUart, const uint32_t nPortIndex) { - assert(nPortIndex < DMX_MAX_PORTS); +void Dmx::StopData(const uint32_t nPortIndex) { + assert(nPortIndex < dmx::config::max::PORTS); if (sv_PortState[nPortIndex] == PortState::IDLE) { return; } + sv_PortState[nPortIndex] = PortState::IDLE; + + const auto nUart = dmx_port_to_uart(nPortIndex); + if (m_dmxPortDirection[nPortIndex] == PortDirection::OUTP) { do { if (s_TxBuffer[nPortIndex].State == dmx::TxRxState::DMXINTER) { - usart_flag_clear(nUart, USART_FLAG_TC); - while (SET != usart_flag_get(nUart, USART_FLAG_TC)) - ; + gd32_usart_flag_clear(nUart); + do { + __DMB(); + } while (!gd32_usart_flag_get(nUart)); + s_TxBuffer[nPortIndex].State = dmx::TxRxState::IDLE; } } while (s_TxBuffer[nPortIndex].State != dmx::TxRxState::IDLE); - } else if (m_dmxPortDirection[nPortIndex] == PortDirection::INP) { - usart_interrupt_disable(nUart, USART_INT_RBNE); - s_RxBuffer[nPortIndex].State = TxRxState::IDLE; -#if !defined(CONFIG_DMX_TRANSMIT_ONLY) - switch (nPortIndex) { - case 0: - TIMER_DMAINTEN(TIMER2) &= (~(uint32_t) TIMER_INT_CH0); - break; -#if DMX_MAX_PORTS >= 2 - case 1: - TIMER_DMAINTEN(TIMER2) &= (~(uint32_t) TIMER_INT_CH1); - break; -#endif -#if DMX_MAX_PORTS >= 3 - case 2: - TIMER_DMAINTEN(TIMER2) &= (~(uint32_t) TIMER_INT_CH2); - break; -#endif -#if DMX_MAX_PORTS >= 4 - case 3: - TIMER_DMAINTEN(TIMER2) &= (~(uint32_t) TIMER_INT_CH3); - break; -#endif -#if DMX_MAX_PORTS >= 5 - case 4: - TIMER_DMAINTEN(TIMER3) &= (~(uint32_t) TIMER_INT_CH0); - break; -#endif -#if DMX_MAX_PORTS >= 6 - case 5: - TIMER_DMAINTEN(TIMER3) &= (~(uint32_t) TIMER_INT_CH1); - break; -#endif -#if DMX_MAX_PORTS >= 7 - case 6: - TIMER_DMAINTEN(TIMER3) &= (~(uint32_t) TIMER_INT_CH2); - break; -#endif -#if DMX_MAX_PORTS == 8 - case 7: - TIMER_DMAINTEN(TIMER3) &= (~(uint32_t) TIMER_INT_CH3); - break; -#endif - default: - assert(0); - __builtin_unreachable(); - break; - } -#endif - } else { - assert(0); - __builtin_unreachable(); + return; } - sv_PortState[nPortIndex] = PortState::IDLE; + if (m_dmxPortDirection[nPortIndex] == PortDirection::INP) { + gd32_usart_interrupt_disable(nUart); + gd32_usart_interrupt_disable(nUart); + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; + return; + } + + assert(0); + __builtin_unreachable(); } // DMX Send void Dmx::SetDmxBreakTime(uint32_t nBreakTime) { - s_nDmxTransmitBreakTime = std::max(transmit::BREAK_TIME_MIN, nBreakTime); + s_nDmxTransmit.nBreakTime = std::max(transmit::BREAK_TIME_MIN, nBreakTime); SetDmxPeriodTime(m_nDmxTransmitPeriodRequested); } +uint32_t Dmx::GetDmxBreakTime() const { + return s_nDmxTransmit.nBreakTime; +} + void Dmx::SetDmxMabTime(uint32_t nMabTime) { - s_nDmxTransmitMabTime = std::max(transmit::MAB_TIME_MIN, nMabTime); + s_nDmxTransmit.nMabTime = std::max(transmit::MAB_TIME_MIN, nMabTime); SetDmxPeriodTime(m_nDmxTransmitPeriodRequested); } +uint32_t Dmx::GetDmxMabTime() const { + return s_nDmxTransmit.nMabTime; +} + void Dmx::SetDmxPeriodTime(uint32_t nPeriod) { m_nDmxTransmitPeriodRequested = nPeriod; auto nLengthMax = s_TxBuffer[0].dmx.nLength; - for (uint32_t nPortIndex = 1; nPortIndex < config::max::OUT; nPortIndex++) { + for (uint32_t nPortIndex = 1; nPortIndex < dmx::config::max::PORTS; nPortIndex++) { const auto nLength = s_TxBuffer[nPortIndex].dmx.nLength; if (nLength > nLengthMax) { nLengthMax = nLength; } } - auto nPackageLengthMicroSeconds = s_nDmxTransmitBreakTime + s_nDmxTransmitMabTime + (nLengthMax * 44U); + auto nPackageLengthMicroSeconds = s_nDmxTransmit.nBreakTime + s_nDmxTransmit.nMabTime + (nLengthMax * 44U); - // The GD32F4xx Timer 1 has a 32-bit counter -#if ! defined(GD32F4XX) + // The GD32F4xx/GD32H7XX Timer 1 has a 32-bit counter +#if defined(GD32F4XX) || defined (GD32H7XX) +#else if (nPackageLengthMicroSeconds > (static_cast(~0) - 44U)) { - s_nDmxTransmitBreakTime = std::min(transmit::BREAK_TIME_TYPICAL, s_nDmxTransmitBreakTime); - s_nDmxTransmitMabTime = transmit::MAB_TIME_MIN; - nPackageLengthMicroSeconds = s_nDmxTransmitBreakTime + s_nDmxTransmitMabTime + (nLengthMax * 44U); + s_nDmxTransmit.nBreakTime = std::min(transmit::BREAK_TIME_TYPICAL, s_nDmxTransmit.nBreakTime); + s_nDmxTransmit.nMabTime = transmit::MAB_TIME_MIN; + nPackageLengthMicroSeconds = s_nDmxTransmit.nBreakTime + s_nDmxTransmit.nMabTime + (nLengthMax * 44U); } #endif - uint32_t nDmxTransmitPeriod; - if (nPeriod != 0) { if (nPeriod < nPackageLengthMicroSeconds) { - nDmxTransmitPeriod = std::max(transmit::BREAK_TO_BREAK_TIME_MIN, nPackageLengthMicroSeconds + 44U); + m_nDmxTransmitPeriod = std::max(transmit::BREAK_TO_BREAK_TIME_MIN, nPackageLengthMicroSeconds + 44U); } else { - nDmxTransmitPeriod = nPeriod; + m_nDmxTransmitPeriod = nPeriod; } } else { - nDmxTransmitPeriod = std::max(transmit::BREAK_TO_BREAK_TIME_MIN, nPackageLengthMicroSeconds + 44U); + m_nDmxTransmitPeriod = std::max(transmit::BREAK_TO_BREAK_TIME_MIN, nPackageLengthMicroSeconds + 44U); } - s_nDmxTransmitInterTime = nDmxTransmitPeriod - nPackageLengthMicroSeconds; + s_nDmxTransmit.nInterTime = m_nDmxTransmitPeriod - nPackageLengthMicroSeconds; - DEBUG_PRINTF("nPeriod=%u, nLengthMax=%u, s_nDmxTransmitPeriod=%u, nPackageLengthMicroSeconds=%u -> s_nDmxTransmitInterTime=%u", nPeriod, nLengthMax, nDmxTransmitPeriod, nPackageLengthMicroSeconds, s_nDmxTransmitInterTime); + DEBUG_PRINTF("nPeriod=%u, nLengthMax=%u, m_nDmxTransmitPeriod=%u, nPackageLengthMicroSeconds=%u -> s_nDmxTransmit.nInterTime=%u", nPeriod, nLengthMax, m_nDmxTransmitPeriod, nPackageLengthMicroSeconds, s_nDmxTransmit.nInterTime); } void Dmx::SetDmxSlots(uint16_t nSlots) { if ((nSlots >= 2) && (nSlots <= dmx::max::CHANNELS)) { m_nDmxTransmitSlots = nSlots; - for (uint32_t i = 0; i < config::max::OUT; i++) { + for (uint32_t i = 0; i < dmx::config::max::PORTS; i++) { m_nDmxTransmissionLength[i] = std::min(m_nDmxTransmissionLength[i], static_cast(nSlots)); } @@ -1940,26 +1779,55 @@ void Dmx::SetDmxSlots(uint16_t nSlots) { } void Dmx::SetOutputStyle(const uint32_t nPortIndex, const dmx::OutputStyle outputStyle) { - assert(nPortIndex < dmx::config::max::OUT); - + assert(nPortIndex < dmx::config::max::PORTS); s_TxBuffer[nPortIndex].outputStyle = outputStyle; + + if (outputStyle == dmx::OutputStyle::CONTINOUS) { + if (!m_bHasContinuosOutput) { + m_bHasContinuosOutput = true; + if (m_dmxPortDirection[nPortIndex] == dmx::PortDirection::OUTP) { + StartDmxOutput(nPortIndex); + } + return; + } + + for (uint32_t nIndex = 0; nIndex < dmx::config::max::PORTS; nIndex++) { + if ((s_TxBuffer[nIndex].outputStyle == dmx::OutputStyle::CONTINOUS) && (m_dmxPortDirection[nIndex] == dmx::PortDirection::OUTP)) { + StopData(nIndex); + } + } + + for (uint32_t nIndex = 0; nIndex < dmx::config::max::PORTS; nIndex++) { + if ((s_TxBuffer[nIndex].outputStyle == dmx::OutputStyle::CONTINOUS) && (m_dmxPortDirection[nIndex] == dmx::PortDirection::OUTP)) { + StartDmxOutput(nIndex); + } + } + } else { + m_bHasContinuosOutput = false; + for (uint32_t nIndex = 0; nIndex < dmx::config::max::PORTS; nIndex++) { + if (s_TxBuffer[nIndex].outputStyle == dmx::OutputStyle::CONTINOUS) { + m_bHasContinuosOutput = true; + return; + } + } + } } dmx::OutputStyle Dmx::GetOutputStyle(const uint32_t nPortIndex) const { - assert(nPortIndex < dmx::config::max::OUT); + assert(nPortIndex < dmx::config::max::PORTS); return s_TxBuffer[nPortIndex].outputStyle; } void Dmx::SetSendData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength) { - assert(nPortIndex < DMX_MAX_PORTS); + assert(nPortIndex < dmx::config::max::PORTS); - auto *p = &s_TxBuffer[nPortIndex]; - auto *pDst = p->dmx.data; + auto &p = s_TxBuffer[nPortIndex]; + auto *pDst = p.dmx.data; nLength = std::min(nLength, static_cast(m_nDmxTransmitSlots)); - p->dmx.nLength = static_cast(nLength + 1); + p.dmx.nLength = nLength + 1; - memcpy(pDst, pData, nLength); + memcpy(pDst, pData, nLength); if (nLength != m_nDmxTransmissionLength[nPortIndex]) { m_nDmxTransmissionLength[nPortIndex] = nLength; @@ -1968,25 +1836,22 @@ void Dmx::SetSendData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t } void Dmx::SetSendDataWithoutSC(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength) { - logic_analyzer::ch0_set(); + assert(nPortIndex < dmx::config::max::PORTS); - assert(nPortIndex < DMX_MAX_PORTS); - - auto *p = &s_TxBuffer[nPortIndex]; - auto *pDst = p->dmx.data; + auto &p = s_TxBuffer[nPortIndex]; + auto *pDst = p.dmx.data; nLength = std::min(nLength, static_cast(m_nDmxTransmitSlots)); - p->dmx.nLength = static_cast(nLength + 1); + p.dmx.nLength = nLength + 1; + p.dmx.bDataPending = true; pDst[0] = START_CODE; - memcpy(&pDst[1], pData, nLength); + memcpy(&pDst[1], pData, nLength); if (nLength != m_nDmxTransmissionLength[nPortIndex]) { m_nDmxTransmissionLength[nPortIndex] = nLength; SetDmxPeriodTime(m_nDmxTransmitPeriodRequested); } - - logic_analyzer::ch0_clear(); } void Dmx::Blackout() { @@ -1994,11 +1859,9 @@ void Dmx::Blackout() { for (uint32_t nPortIndex = 0; nPortIndex < DMX_MAX_PORTS; nPortIndex++) { if (m_dmxPortDirection[nPortIndex] == dmx::PortDirection::OUTP) { - const auto nUart = _port_to_uart(nPortIndex); - - StopData(nUart, nPortIndex); + StopData(nPortIndex); ClearData(nPortIndex); - StartData(nUart, nPortIndex); + StartData(nPortIndex); } } @@ -2010,21 +1873,19 @@ void Dmx::FullOn() { for (uint32_t nPortIndex = 0; nPortIndex < DMX_MAX_PORTS; nPortIndex++) { if (m_dmxPortDirection[nPortIndex] == dmx::PortDirection::OUTP) { - const auto nUart = _port_to_uart(nPortIndex); + StopData(nPortIndex); - StopData(nUart, nPortIndex); + auto * __restrict__ p = &s_TxBuffer[nPortIndex]; + auto *p32 = reinterpret_cast(p->dmx.data); - auto *p = &s_TxBuffer[nPortIndex]; - auto *p16 = reinterpret_cast(p->dmx.data); - - for (auto i = 0; i < dmx::buffer::SIZE / 2; i++) { - *p16++ = UINT16_MAX; + for (auto i = 0; i < dmx::buffer::SIZE / 4; i++) { + *p32++ = UINT32_MAX; } p->dmx.data[0] = dmx::START_CODE; p->dmx.nLength = 513; - StartData(nUart, nPortIndex); + StartData(nPortIndex); } } @@ -2035,138 +1896,93 @@ void Dmx::StartOutput(const uint32_t nPortIndex) { if ((sv_PortState[nPortIndex] == dmx::PortState::TX) && (s_TxBuffer[nPortIndex].outputStyle == dmx::OutputStyle::DELTA) && (s_TxBuffer[nPortIndex].State == dmx::TxRxState::IDLE)) { - StartDmxOutput(nPortIndex); } } -static bool s_doForce; +void Dmx::Sync() { + for (uint32_t nPortIndex = 0; nPortIndex < dmx::config::max::PORTS; nPortIndex++) { + auto &txBuffer = s_TxBuffer[nPortIndex]; -void Dmx::SetOutput(const bool doForce) { - logic_analyzer::ch1_set(); - - if (doForce) { - s_doForce = true; - for (uint32_t nPortIndex = 0; nPortIndex < dmx::config::max::OUT; nPortIndex++) { - if ((sv_PortState[nPortIndex] == dmx::PortState::TX) - && (s_TxBuffer[nPortIndex].outputStyle == dmx::OutputStyle::CONTINOUS)) { - StopData(_port_to_uart(nPortIndex), nPortIndex); - } + if (!txBuffer.dmx.bDataPending) { + continue; } - logic_analyzer::ch1_clear(); - return; - } + txBuffer.dmx.bDataPending = false; - for (uint32_t nPortIndex = 0; nPortIndex < dmx::config::max::OUT; nPortIndex++) { - if (sv_PortState[nPortIndex] == dmx::PortState::TX) { - const auto b = ((s_TxBuffer[nPortIndex].outputStyle == dmx::OutputStyle::CONTINOUS) && s_doForce); - if (b || ((s_TxBuffer[nPortIndex].outputStyle == dmx::OutputStyle::DELTA) && (s_TxBuffer[nPortIndex].State == dmx::TxRxState::IDLE))) { + if ((sv_PortState[nPortIndex] == dmx::PortState::TX)) { + if ((txBuffer.outputStyle == dmx::OutputStyle::DELTA) && (txBuffer.State == dmx::TxRxState::IDLE)) { StartDmxOutput(nPortIndex); } } } - - s_doForce = false; - logic_analyzer::ch1_clear(); } -void Dmx::StartData(const uint32_t nUart, const uint32_t nPortIndex) { -// DEBUG_PRINTF("sv_PortState[%u]=%u", nPortIndex, sv_PortState[nPortIndex]); - assert(nPortIndex < DMX_MAX_PORTS); +void Dmx::StartData(const uint32_t nPortIndex) { + assert(nPortIndex < dmx::config::max::PORTS); assert(sv_PortState[nPortIndex] == PortState::IDLE); if (m_dmxPortDirection[nPortIndex] == dmx::PortDirection::OUTP) { sv_PortState[nPortIndex] = PortState::TX; - if (s_TxBuffer[nPortIndex].outputStyle == dmx::OutputStyle::CONTINOUS) { - StartDmxOutput(nPortIndex); - } - } else if (m_dmxPortDirection[nPortIndex] == dmx::PortDirection::INP) { - s_RxBuffer[nPortIndex].State = TxRxState::IDLE; + return; + } - while (RESET == usart_flag_get(nUart, USART_FLAG_TBE)) - ; + if (m_dmxPortDirection[nPortIndex] == dmx::PortDirection::INP) { + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; - usart_interrupt_flag_clear(nUart, USART_INT_FLAG_RBNE); - usart_interrupt_enable(nUart, USART_INT_RBNE); + const auto nUart = dmx_port_to_uart(nPortIndex); - sv_PortState[nPortIndex] = PortState::RX; + do { + __DMB(); + } while (!gd32_usart_flag_get(nUart)); -#if !defined(CONFIG_DMX_TRANSMIT_ONLY) - switch (nPortIndex) { - case 0: - TIMER_DMAINTEN(TIMER2) |= (uint32_t) TIMER_INT_CH0; - break; -#if DMX_MAX_PORTS >= 2 - case 1: - TIMER_DMAINTEN(TIMER2) |= (uint32_t) TIMER_INT_CH1; - break; -#endif -#if DMX_MAX_PORTS >= 3 - case 2: - TIMER_DMAINTEN(TIMER2) |= (uint32_t) TIMER_INT_CH2; - break; -#endif -#if DMX_MAX_PORTS >= 4 - case 3: - TIMER_DMAINTEN(TIMER2) |= (uint32_t) TIMER_INT_CH3; - break; -#endif -#if DMX_MAX_PORTS >= 5 - case 4: - TIMER_DMAINTEN(TIMER3) |= (uint32_t) TIMER_INT_CH0; - break; -#endif -#if DMX_MAX_PORTS >= 6 - case 5: - TIMER_DMAINTEN(TIMER3) |= (uint32_t) TIMER_INT_CH1; - break; -#endif -#if DMX_MAX_PORTS >= 7 - case 6: - TIMER_DMAINTEN(TIMER3) |= (uint32_t) TIMER_INT_CH2; - break; -#endif -#if DMX_MAX_PORTS == 8 - case 7: - TIMER_DMAINTEN(TIMER3) |= (uint32_t) TIMER_INT_CH3; - break; -#endif - default: - assert(0); - __builtin_unreachable(); - break; - } -#endif - } else { - assert(0); - __builtin_unreachable(); + gd32_usart_interrupt_flag_clear(nUart); + gd32_usart_interrupt_flag_clear(nUart); + gd32_usart_interrupt_enable(nUart); + gd32_usart_interrupt_enable(nUart); + + sv_PortState[nPortIndex] = PortState::RX; + return; } + + assert(0); + __builtin_unreachable(); } // DMX Receive -const uint8_t* Dmx::GetDmxChanged(UNUSED uint32_t nPortIndex) { +const uint8_t *Dmx::GetDmxChanged(const uint32_t nPortIndex) { #if !defined(CONFIG_DMX_TRANSMIT_ONLY) - const auto *p = GetDmxAvailable(nPortIndex); + const auto * __restrict__ p = GetDmxAvailable(nPortIndex); if (p == nullptr) { return nullptr; } - const auto *pSrc16 = reinterpret_cast(p); - auto *pDst16 = reinterpret_cast(&s_RxDmxPrevious[nPortIndex][0]); + const auto * __restrict__ pSrc32 = reinterpret_cast(sv_RxBuffer[nPortIndex].Dmx.current.data); + auto * __restrict__ pDst32 = reinterpret_cast(sv_RxBuffer[nPortIndex].Dmx.previous.data); - auto isChanged = false; + if (sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket != sv_RxBuffer[nPortIndex].Dmx.previous.nSlotsInPacket) { + sv_RxBuffer[nPortIndex].Dmx.previous.nSlotsInPacket = sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket; - for (auto i = 0; i < buffer::SIZE / 2; i++) { - if (*pDst16 != *pSrc16) { - *pDst16 = *pSrc16; - isChanged = true; + for (size_t i = 0; i < buffer::SIZE / 4; ++i) { + pDst32[i] = pSrc32[i]; } - pDst16++; - pSrc16++; + + return p; + } + + bool isChanged = false; + + for (size_t i = 0; i < buffer::SIZE / 4; ++i) { + const auto srcVal = pSrc32[i]; + auto dstVal = pDst32[i]; + + if (srcVal != dstVal) { + pDst32[i] = srcVal; + isChanged = true; + } } return (isChanged ? p : nullptr); @@ -2175,28 +1991,31 @@ const uint8_t* Dmx::GetDmxChanged(UNUSED uint32_t nPortIndex) { #endif } -const uint8_t *Dmx::GetDmxAvailable(UNUSED uint32_t nPortIndex) { - assert(nPortIndex < DMX_MAX_PORTS); +const uint8_t *Dmx::GetDmxAvailable([[maybe_unused]] const uint32_t nPortIndex) { + assert(nPortIndex < dmx::config::max::PORTS); #if !defined(CONFIG_DMX_TRANSMIT_ONLY) - if ((s_RxBuffer[nPortIndex].Dmx.nSlotsInPacket & 0x8000) != 0x8000) { + auto nSlotsInPacket = sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket; + + if ((nSlotsInPacket & 0x8000) != 0x8000) { return nullptr; } - s_RxBuffer[nPortIndex].Dmx.nSlotsInPacket &= ~0x8000; - s_RxBuffer[nPortIndex].Dmx.nSlotsInPacket--; // Remove SC from length + nSlotsInPacket &= ~0x8000; + nSlotsInPacket--; // Remove SC from length + sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket = nSlotsInPacket; - return s_RxBuffer[nPortIndex].data; + return const_cast(sv_RxBuffer[nPortIndex].Dmx.current.data); #else return nullptr; #endif } -const uint8_t* Dmx::GetDmxCurrentData(const uint32_t nPortIndex) { - return s_RxBuffer[nPortIndex].data; +const uint8_t *Dmx::GetDmxCurrentData(const uint32_t nPortIndex) { + return const_cast(sv_RxBuffer[nPortIndex].Dmx.current.data); } -uint32_t Dmx::GetDmxUpdatesPerSecond(UNUSED uint32_t nPortIndex) { - assert(nPortIndex < DMX_MAX_PORTS); +uint32_t Dmx::GetDmxUpdatesPerSecond([[maybe_unused]] uint32_t nPortIndex) { + assert(nPortIndex < dmx::config::max::PORTS); #if !defined(CONFIG_DMX_TRANSMIT_ONLY) return sv_nRxDmxPackets[nPortIndex].nPerSecond; #else @@ -2204,74 +2023,61 @@ uint32_t Dmx::GetDmxUpdatesPerSecond(UNUSED uint32_t nPortIndex) { #endif } -uint32_t GetDmxReceivedCount(UNUSED uint32_t nPortIndex) { - assert(nPortIndex < DMX_MAX_PORTS); -#if !defined(CONFIG_DMX_TRANSMIT_ONLY) - return sv_nRxDmxPackets[nPortIndex].nCount; -#else - return 0; -#endif -} - // RDM Send -void Dmx::RdmSendRaw(const uint32_t nPortIndex, const uint8_t* pRdmData, uint32_t nLength) { - assert(nPortIndex < DMX_MAX_PORTS); +template +static void rdm_send_raw(const uint8_t *const pRdmData, const uint32_t nLength) { + assert(nPortIndex < dmx::config::max::PORTS); assert(pRdmData != nullptr); assert(nLength != 0); - const auto nUart = _port_to_uart(nPortIndex); - - while (SET != usart_flag_get(nUart, USART_FLAG_TC)) - ; - switch (nUart) { #if defined (DMX_USE_USART0) case USART0: - _gpio_mode_output(USART0_GPIO_PORT, USART0_TX_PIN); - GPIO_BC(USART0_GPIO_PORT) = USART0_TX_PIN; + gd32_gpio_mode_output(); + GPIO_BC(USART0_GPIOx) = USART0_TX_GPIO_PINx; break; #endif #if defined (DMX_USE_USART1) case USART1: - _gpio_mode_output(USART1_GPIO_PORT, USART1_TX_PIN); - GPIO_BC(USART1_GPIO_PORT) = USART1_TX_PIN; + gd32_gpio_mode_output(); + GPIO_BC(USART1_GPIOx) = USART1_TX_GPIO_PINx; break; #endif #if defined (DMX_USE_USART2) case USART2: - _gpio_mode_output(USART2_GPIO_PORT, USART2_TX_PIN); - GPIO_BC(USART2_GPIO_PORT) = USART2_TX_PIN; + gd32_gpio_mode_output(); + GPIO_BC(USART2_GPIOx) = USART2_TX_GPIO_PINx; break; #endif #if defined (DMX_USE_UART3) case UART3: - _gpio_mode_output(UART3_GPIO_PORT, UART3_TX_PIN); - GPIO_BC(UART3_GPIO_PORT) = UART3_TX_PIN; + gd32_gpio_mode_output(); + GPIO_BC(UART3_GPIOx) = UART3_TX_GPIO_PINx; break; #endif #if defined (DMX_USE_UART4) case UART4: - _gpio_mode_output(UART4_GPIO_TX_PORT, UART4_TX_PIN); - GPIO_BC(UART4_GPIO_TX_PORT) = UART4_TX_PIN; + gd32_gpio_mode_output(); + GPIO_BC(UART4_TX_GPIOx) = UART4_TX_GPIO_PINx; break; #endif #if defined (DMX_USE_USART5) case USART5: - _gpio_mode_output(USART5_GPIO_PORT, USART5_TX_PIN); - GPIO_BC(USART5_GPIO_PORT) = USART5_TX_PIN; + gd32_gpio_mode_output(); + GPIO_BC(USART5_GPIOx) = USART5_TX_GPIO_PINx; break; #endif #if defined (DMX_USE_UART6) case UART6: - _gpio_mode_output(UART6_GPIO_PORT, UART6_TX_PIN); - GPIO_BC(UART6_GPIO_PORT) = UART6_TX_PIN; + gd32_gpio_mode_output(); + GPIO_BC(UART6_GPIOx) = UART6_TX_GPIO_PINx; break; #endif #if defined (DMX_USE_UART7) case UART7: - _gpio_mode_output(UART7_GPIO_PORT, UART7_TX_PIN); - GPIO_BC(UART7_GPIO_PORT) = UART7_TX_PIN; + gd32_gpio_mode_output(); + GPIO_BC(UART7_GPIOx) = UART7_TX_GPIO_PINx; break; #endif default: @@ -2280,47 +2086,50 @@ void Dmx::RdmSendRaw(const uint32_t nPortIndex, const uint8_t* pRdmData, uint32_ break; } - udelay(RDM_TRANSMIT_BREAK_TIME); + TIMER_CNT(TIMER5) = 0; + do { + __DMB(); + } while (TIMER_CNT(TIMER5) < RDM_TRANSMIT_BREAK_TIME); switch (nUart) { #if defined (DMX_USE_USART0) case USART0: - _gpio_mode_af(USART0_GPIO_PORT, USART0_TX_PIN, USART0); + gd32_gpio_mode_af(); break; #endif #if defined (DMX_USE_USART1) case USART1: - _gpio_mode_af(USART1_GPIO_PORT, USART1_TX_PIN, USART1); + gd32_gpio_mode_af(); break; #endif #if defined (DMX_USE_USART2) case USART2: - _gpio_mode_af(USART2_GPIO_PORT, USART2_TX_PIN, USART2); + gd32_gpio_mode_af(); break; #endif #if defined (DMX_USE_UART3) case UART3: - _gpio_mode_af(UART3_GPIO_PORT, UART3_TX_PIN, UART3); + gd32_gpio_mode_af(); break; #endif #if defined (DMX_USE_UART4) case UART4: - _gpio_mode_af(UART4_GPIO_TX_PORT, UART4_TX_PIN, UART4); + gd32_gpio_mode_af(); break; #endif #if defined (DMX_USE_USART5) case USART5: - _gpio_mode_af(USART5_GPIO_PORT, USART5_TX_PIN, USART5); + gd32_gpio_mode_af(); break; #endif #if defined (DMX_USE_UART6) case UART6: - _gpio_mode_af(UART6_GPIO_PORT, UART6_TX_PIN, UART6); + gd32_gpio_mode_af(); break; #endif #if defined (DMX_USE_UART7) case UART7: - _gpio_mode_af(UART7_GPIO_PORT, UART7_TX_PIN, UART7); + gd32_gpio_mode_af(); break; #endif default: @@ -2329,40 +2138,166 @@ void Dmx::RdmSendRaw(const uint32_t nPortIndex, const uint8_t* pRdmData, uint32_ break; } - udelay(RDM_TRANSMIT_MAB_TIME); + TIMER_CNT(TIMER5) = 0; + do { + __DMB(); + } while (TIMER_CNT(TIMER5) < RDM_TRANSMIT_MAB_TIME); + + for (uint32_t i = 0; i < nLength; i++) { + do { + __DMB(); + } while (!gd32_usart_flag_get(nUart)); + + USART_TDATA(nUart) = USART_TDATA_TDATA & pRdmData[i]; + } + + while (!gd32_usart_flag_get(nUart)) { + static_cast(GET_BITS(USART_RDATA(nUart), 0U, 8U)); + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[nPortIndex].Rdm.Sent.Class++; +#endif +} + +void Dmx::RdmSendRaw(const uint32_t nPortIndex, const uint8_t *pRdmData, uint32_t nLength) { + switch (nPortIndex) { + case 0: + rdm_send_raw<0, dmx_port_to_uart(0)>(pRdmData, nLength); + break; +#if DMX_MAX_PORTS >= 2 + case 1: + rdm_send_raw<1, dmx_port_to_uart(1)>(pRdmData, nLength); + break; +#endif +#if DMX_MAX_PORTS >= 3 + case 2: + rdm_send_raw<2, dmx_port_to_uart(2)>(pRdmData, nLength); + break; +#endif +#if DMX_MAX_PORTS >= 4 + case 3: + rdm_send_raw<3, dmx_port_to_uart(3)>(pRdmData, nLength); + break; +#endif +#if DMX_MAX_PORTS >= 5 + case 4: + rdm_send_raw<4, dmx_port_to_uart(4)>(pRdmData, nLength); + break; +#endif +#if DMX_MAX_PORTS >= 6 + case 5: + rdm_send_raw<5, dmx_port_to_uart(5)>(pRdmData, nLength); + break; +#endif +#if DMX_MAX_PORTS >= 7 + case 6: + rdm_send_raw<6, dmx_port_to_uart(6)>(pRdmData, nLength); + break; +#endif +#if DMX_MAX_PORTS == 8 + case 7: + rdm_send_raw<7, dmx_port_to_uart(7)>(pRdmData, nLength); + break; +#endif + default: + break; + } +} + +void Dmx::RdmSendDiscoveryRespondMessage(uint32_t nPortIndex, const uint8_t *pRdmData, uint32_t nLength) { + assert(nPortIndex < dmx::config::max::PORTS); + assert(pRdmData != nullptr); + assert(nLength != 0); + + // 3.2.2 Responder Packet spacing + udelay(RDM_RESPONDER_PACKET_SPACING, gsv_RdmDataReceiveEnd); + + SetPortDirection(nPortIndex, dmx::PortDirection::OUTP, false); + + const auto nUart = dmx_port_to_uart(nPortIndex); for (uint32_t i = 0; i < nLength; i++) { - while (RESET == usart_flag_get(nUart, USART_FLAG_TBE)) - ; - USART_DATA(nUart) = static_cast(USART_DATA_DATA & pRdmData[i]); + do { + __DMB(); + } while (!gd32_usart_flag_get(nUart)); + + USART_TDATA(nUart) = USART_TDATA_TDATA & pRdmData[i]; } - while (SET != usart_flag_get(nUart, USART_FLAG_TC)) { - static_cast(GET_BITS(USART_DATA(nUart), 0U, 8U)); + while (!gd32_usart_flag_get(nUart)) { + static_cast(GET_BITS(USART_RDATA(nUart), 0U, 8U)); } + + TIMER_CNT(TIMER5) = 0; + do { + __DMB(); + } while (TIMER_CNT(TIMER5) < RDM_RESPONDER_DATA_DIRECTION_DELAY); + + + SetPortDirection(nPortIndex, dmx::PortDirection::INP, true); + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[nPortIndex].Rdm.Sent.DiscoveryResponse++; +#endif } // RDM Receive const uint8_t *Dmx::RdmReceive(const uint32_t nPortIndex) { - assert(nPortIndex < DMX_MAX_PORTS); + assert(nPortIndex < dmx::config::max::PORTS); + + if ((sv_RxBuffer[nPortIndex].Rdm.nIndex & 0x4000) != 0x4000) { + return nullptr; + } + + sv_RxBuffer[nPortIndex].Rdm.nIndex = 0; + + const auto *p = const_cast(sv_RxBuffer[nPortIndex].Rdm.data); + + if (p[0] == E120_SC_RDM) { + const auto *pRdmCommand = reinterpret_cast(p); + + uint32_t i; + uint16_t nChecksum = 0; + + for (i = 0; i < 24; i++) { + nChecksum = static_cast(nChecksum + p[i]); + } - if ((s_RxBuffer[nPortIndex].Rdm.nIndex & 0x4000) != 0x4000) { + for (; i < pRdmCommand->message_length; i++) { + nChecksum = static_cast(nChecksum + p[i]); + } + + if (p[i++] == static_cast(nChecksum >> 8)) { + if (p[i] == static_cast(nChecksum)) { +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[nPortIndex].Rdm.Received.Good++; +#endif + return p; + } + } +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[nPortIndex].Rdm.Received.Bad++; +#endif return nullptr; + } else { +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[nPortIndex].Rdm.Received.DiscoveryResponse++; +#endif } - s_RxBuffer[nPortIndex].Dmx.nSlotsInPacket = 0; // This is correct. - return s_RxBuffer[nPortIndex].data; + return p; } const uint8_t *Dmx::RdmReceiveTimeOut(const uint32_t nPortIndex, uint16_t nTimeOut) { - assert(nPortIndex < DMX_MAX_PORTS); + assert(nPortIndex < dmx::config::max::PORTS); uint8_t *p = nullptr; TIMER_CNT(TIMER5) = 0; do { - if ((p = const_cast(RdmReceive(nPortIndex))) != nullptr) { + if ((p = const_cast(RdmReceive(nPortIndex))) != nullptr) { return p; } } while (TIMER_CNT(TIMER5) < nTimeOut); diff --git a/lib-dmx/src/gd32/dmx_internal.h b/lib-dmx/src/gd32/dmx_internal.h index 8a6dd883..6a298924 100644 --- a/lib-dmx/src/gd32/dmx_internal.h +++ b/lib-dmx/src/gd32/dmx_internal.h @@ -2,7 +2,7 @@ * @file dmx_internal.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,9 +30,50 @@ #include #include "gd32.h" +#include "gd32_gpio.h" #include "gd32/dmx_config.h" -static uint32_t _port_to_uart(const uint32_t nPort) { +#ifdef ALIGNED +#undef ALIGNED +#endif +#define ALIGNED __attribute__ ((aligned (4))) + +/** + * Needed for older GD32F firmware + */ +#if !defined(USART_TRANSMIT_DMA_ENABLE) +# define USART_TRANSMIT_DMA_ENABLE USART_DENT_ENABLE +#endif + +/** + * GD32F10X is different + */ +#if defined(GD32F10X) +# define USART_FLAG_IDLE USART_FLAG_IDLEF +#endif + +/** + * https://www.gd32-dmx.org/memory.html + */ +#if defined (GD32F20X) || defined (GD32F4XX) || defined (GD32H7XX) +# define SECTION_DMA_BUFFER __attribute__ ((section (".dmx"))) +#else +# define SECTION_DMA_BUFFER +#endif + +#if defined (GD32F4XX) || defined (GD32H7XX) +# define DMA_INTERRUPT_ENABLE (DMA_CHXCTL_FTFIE) +# define DMA_INTERRUPT_DISABLE (DMA_CHXCTL_FTFIE | DMA_CHXCTL_HTFIE | DMA_CHXFCTL_FEEIE) +# define DMA_INTERRUPT_FLAG_GET (DMA_INT_FLAG_FTF) +# define DMA_INTERRUPT_FLAG_CLEAR (DMA_INT_FLAG_FTF | DMA_INT_FLAG_TAE) +#else +# define DMA_INTERRUPT_ENABLE (DMA_INT_FTF) +# define DMA_INTERRUPT_DISABLE (DMA_INT_FTF | DMA_INT_HTF | DMA_INT_ERR) +# define DMA_INTERRUPT_FLAG_GET (DMA_INT_FLAG_FTF) +# define DMA_INTERRUPT_FLAG_CLEAR (DMA_INT_FLAG_FTF | DMA_INT_FLAG_G) +#endif + +inline constexpr uint32_t dmx_port_to_uart(const uint32_t nPort) { switch (nPort) { #if defined (DMX_USE_USART0) case dmx::config::USART0_PORT: @@ -85,79 +126,72 @@ static uint32_t _port_to_uart(const uint32_t nPort) { return 0; } -#if defined (GD32F4XX) -// GPIO -static void _gpio_mode_output(uint32_t gpio_periph, uint32_t pin) { - gpio_af_set(gpio_periph, GPIO_AF_0, pin); //TODO This needs some research. Is it really needed? - gpio_mode_set(gpio_periph, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, pin); -} -static void _gpio_mode_af(const uint32_t gpio_periph, uint32_t pin, const uint32_t usart_periph) { - gpio_mode_set(gpio_periph, GPIO_MODE_AF, GPIO_PUPD_PULLUP, pin); - +#if defined (GD32F4XX) || defined (GD32H7XX) +constexpr uint32_t get_usart_af(const uint32_t usart_periph) { switch (usart_periph) { -#if defined (DMX_USE_USART0) - case USART0: -#endif -#if defined (DMX_USE_USART1) +#if defined(DMX_USE_USART0) + case USART0: return USART0_GPIO_AFx; + #endif +#if defined(DMX_USE_USART1) case USART1: + return USART1_GPIO_AFx; #endif -#if defined (DMX_USE_USART2) +#if defined(DMX_USE_USART2) case USART2: + return USART2_GPIO_AFx; #endif -#if defined (DMX_USE_USART0) || defined (DMX_USE_USART1) || defined(DMX_USE_USART2) - gpio_af_set(gpio_periph, GPIO_AF_7, pin); - break; -#endif -#if defined (DMX_USE_UART3) - case UART3: -#endif -#if defined (DMX_USE_UART4) +#if defined(DMX_USE_UART3) + case UART3: return UART3_GPIO_AFx; + #endif +#if defined(DMX_USE_UART4) case UART4: + return UART4_GPIO_AFx; #endif -#if defined (DMX_USE_USART5) +#if defined(DMX_USE_USART5) case USART5: + return USART5_GPIO_AFx; #endif -#if defined (DMX_USE_UART6) +#if defined(DMX_USE_UART6) case UART6: + return UART6_GPIO_AFx; #endif -#if defined (DMX_USE_UART7) +#if defined(DMX_USE_UART7) case UART7: -#endif -#if defined (DMX_USE_UART3) || defined (DMX_USE_UART4) || defined(DMX_USE_USART5) || defined (DMX_USE_UART6) || defined (DMX_USE_UART7) - gpio_af_set(gpio_periph, GPIO_AF_8, pin); - break; + return UART7_GPIO_AFx; #endif default: - assert(0); __builtin_unreachable(); - break; + return 0; } + + __builtin_unreachable(); + return 0; +} + +template +inline void gd32_gpio_mode_output() { + gd32_gpio_mode_set(); +} + +template +inline void gd32_gpio_mode_af() { + gd32_gpio_mode_set(); + + constexpr uint32_t af = get_usart_af(usart_periph); + static_assert(af != 0, "Invalid USART peripheral"); + + gd32_gpio_af_set(); } -// DMA -# define DMA_PARAMETER_STRUCT dma_single_data_parameter_struct -# define DMA_CHMADDR DMA_CHM0ADDR -# define DMA_MEMORY_TO_PERIPHERAL DMA_MEMORY_TO_PERIPH -# define DMA_PERIPHERAL_WIDTH_8BIT DMA_PERIPH_WIDTH_8BIT -# define dma_init dma_single_data_mode_init -# define dma_memory_to_memory_disable(x,y) -# define DMA_INTERRUPT_ENABLE (DMA_CHXCTL_FTFIE) -# define DMA_INTERRUPT_DISABLE (DMA_CHXCTL_FTFIE | DMA_CHXCTL_HTFIE | DMA_CHXFCTL_FEEIE) -# define DMA_INTERRUPT_FLAG_GET (DMA_INT_FLAG_FTF) -# define DMA_INTERRUPT_FLAG_CLEAR (DMA_INT_FLAG_FTF | DMA_INT_FLAG_TAE) #else -// GPIO -static void _gpio_mode_output(uint32_t gpio_periph, uint32_t pin) { - gpio_init(gpio_periph, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, pin); +template +inline void gd32_gpio_mode_output() { + gd32_gpio_init(); } -static void _gpio_mode_af(uint32_t gpio_periph, uint32_t pin, __attribute__((unused)) const uint32_t usart_periph ) { - gpio_init(gpio_periph, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, pin); + +template +inline void gd32_gpio_mode_af() { + gd32_gpio_init(); } -// DMA -# define DMA_PARAMETER_STRUCT dma_parameter_struct -# define DMA_INTERRUPT_ENABLE (DMA_INT_FTF) -# define DMA_INTERRUPT_DISABLE (DMA_INT_FTF | DMA_INT_HTF | DMA_INT_ERR) -# define DMA_INTERRUPT_FLAG_GET (DMA_INT_FLAG_FTF) -# define DMA_INTERRUPT_FLAG_CLEAR (DMA_INT_FLAG_FTF | DMA_INT_FLAG_G) #endif #endif /* GD32_DMX_INTERNAL_H_ */ diff --git a/lib-dmx/src/gd32/rdm.cpp b/lib-dmx/src/gd32/rdm.cpp deleted file mode 100644 index 67145d60..00000000 --- a/lib-dmx/src/gd32/rdm.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/** - * @file rdm.cpp - * - */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "rdm.h" - -#include "dmx.h" -#include "dmxconst.h" -#include "dmx_internal.h" - -#include "gd32.h" -#include "gd32_micros.h" -#include "gd32/dmx_config.h" - -#include "debug.h" - -static uint8_t s_TransactionNumber[dmx::config::max::OUT]; -static uint32_t s_nLastSendMicros[dmx::config::max::OUT]; - -extern volatile uint32_t gv_RdmDataReceiveEnd; - -void Rdm::Send(uint32_t nPort, struct TRdmMessage *pRdmMessage, uint32_t nSpacingMicros) { - DEBUG_PRINTF("nPort=%u, pRdmData=%p, nSpacingMicros=%u", nPort, pRdmMessage, nSpacingMicros); - assert(nPort < DMX_MAX_PORTS); - assert(pRdmMessage != nullptr); - - if (nSpacingMicros != 0) { - const auto nMicros = micros(); - const auto nDeltaMicros = nMicros - s_nLastSendMicros[nPort]; - if (nDeltaMicros < nSpacingMicros) { - const auto nWait = nSpacingMicros - nDeltaMicros; - do { - } while ((micros() - nMicros) < nWait); - } - } - - auto *pData = reinterpret_cast(pRdmMessage); - uint32_t i; - uint16_t nChecksum = 0; - - pRdmMessage->transaction_number = s_TransactionNumber[nPort]; - - for (i = 0; i < pRdmMessage->message_length; i++) { - nChecksum = static_cast(nChecksum + pData[i]); - } - - pData[i++] = static_cast(nChecksum >> 8); - pData[i] = static_cast(nChecksum & 0XFF); - - SendRaw(nPort, reinterpret_cast(pRdmMessage), pRdmMessage->message_length + RDM_MESSAGE_CHECKSUM_SIZE); - - s_nLastSendMicros[nPort] = micros(); - s_TransactionNumber[nPort]++; - - DEBUG_EXIT -} - -void Rdm::SendRawRespondMessage(uint32_t nPort, const uint8_t *pRdmData, uint32_t nLength) { - DEBUG_PRINTF("nPort=%u, pRdmData=%p, nLength=%u", nPort, pRdmData, nLength); - assert(nPort < DMX_MAX_PORTS); - assert(pRdmData != nullptr); - assert(nLength != 0); - - // 3.2.2 Responder Packet spacing - udelay(RDM_RESPONDER_PACKET_SPACING, gv_RdmDataReceiveEnd); - - SendRaw(nPort, pRdmData, nLength); -} - -void Rdm::SendDiscoveryRespondMessage(uint32_t nPort, const uint8_t *pRdmData, uint32_t nLength) { - DEBUG_PRINTF("nPort=%u, pRdmData=%p, nLength=%u", nPort, pRdmData, nLength); - assert(nPort < DMX_MAX_PORTS); - assert(pRdmData != nullptr); - assert(nLength != 0); - - // 3.2.2 Responder Packet spacing - udelay(RDM_RESPONDER_PACKET_SPACING, gv_RdmDataReceiveEnd); - - Dmx::Get()->SetPortDirection(nPort, dmx::PortDirection::OUTP, false); - - const auto nUart = _port_to_uart(nPort); - - for (uint32_t i = 0; i < nLength; i++) { - while (RESET == usart_flag_get(nUart, USART_FLAG_TBE)) - ; - USART_DATA(nUart) = static_cast(USART_DATA_DATA & pRdmData[i]); - } - - while (SET != usart_flag_get(nUart, USART_FLAG_TC)) { - static_cast(GET_BITS(USART_DATA(nUart), 0U, 8U)); - } - - udelay(RDM_RESPONDER_DATA_DIRECTION_DELAY); - - Dmx::Get()->SetPortDirection(nPort, dmx::PortDirection::INP, true); -} diff --git a/lib-dmx/src/json_get_ports.cpp b/lib-dmx/src/json_get_ports.cpp new file mode 100755 index 00000000..bf83b23a --- /dev/null +++ b/lib-dmx/src/json_get_ports.cpp @@ -0,0 +1,58 @@ +/** + * @file json_get_ports.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "dmx.h" +#include "dmxconst.h" +#include "lightset.h" + +namespace remoteconfig { +namespace dmx { +static uint32_t get_portstatus(const uint32_t nPortIndex, char *pOutBuffer, const uint32_t nOutBufferSize) { + const auto direction = Dmx::Get()->GetPortDirection(nPortIndex) == ::dmx::PortDirection::INP ? ::lightset::PortDir::INPUT : ::lightset::PortDir::OUTPUT; + auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, + "{\"port\":\"%c\",\"direction\":\"%s\"},", + static_cast('A' + nPortIndex), + lightset::get_direction(direction))); + + return nLength; +} + +uint32_t json_get_ports(char *pOutBuffer, const uint32_t nOutBufferSize) { + pOutBuffer[0] = '['; + uint32_t nLength = 1; + + for (uint32_t nPortIndex = 0; nPortIndex < ::dmx::config::max::PORTS; nPortIndex++) { + nLength += get_portstatus(nPortIndex, &pOutBuffer[nLength], nOutBufferSize - nLength); + } + + pOutBuffer[nLength - 1] = ']'; + + return nLength; +} +} // namespace dmx +} // namespace remoteconfig diff --git a/lib-dmx/src/json_get_portstatus.cpp b/lib-dmx/src/json_get_portstatus.cpp new file mode 100755 index 00000000..90f5965a --- /dev/null +++ b/lib-dmx/src/json_get_portstatus.cpp @@ -0,0 +1,58 @@ +/** + * @file json_get_portstatus.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "dmx.h" +#include "dmxconst.h" + +namespace remoteconfig { +namespace dmx { +uint32_t json_get_portstatus(const char cPort, char *pOutBuffer, const uint32_t nOutBufferSize) { + const uint32_t nPortIndex = (cPort | 0x20) - 'a'; + + if (nPortIndex < ::dmx::config::max::PORTS) { + auto& statistics = Dmx::Get()->GetTotalStatistics(nPortIndex); + auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, + "{\"port\":\"%c\"," + "\"dmx\":{\"sent\":\"%u\",\"received\":\"%u\"}," + "\"rdm\":{\"sent\":{\"class\":\"%u\",\"discovery\":\"%u\"},\"received\":{\"good\":\"%u\",\"bad\":\"%u\",\"discovery\":\"%u\"}}}", + static_cast('A' + nPortIndex), + static_cast(statistics.Dmx.Sent), + static_cast(statistics.Dmx.Received), + static_cast(statistics.Rdm.Sent.Class), + static_cast(statistics.Rdm.Sent.DiscoveryResponse), + static_cast(statistics.Rdm.Received.Good), + static_cast(statistics.Rdm.Received.Bad), + static_cast(statistics.Rdm.Received.DiscoveryResponse))); + + return nLength; + } + + return 0; +} +} // namespace dmx +} // namespace remoteconfig diff --git a/lib-dmxreceiver/.cproject b/lib-dmxreceiver/.cproject deleted file mode 100644 index 5a1b73db..00000000 --- a/lib-dmxreceiver/.cproject +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-dmxreceiver/.project b/lib-dmxreceiver/.project deleted file mode 100644 index 7e096b38..00000000 --- a/lib-dmxreceiver/.project +++ /dev/null @@ -1,27 +0,0 @@ - - - lib-dmxreceiver - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/lib-dmxreceiver/.settings/language.settings.xml b/lib-dmxreceiver/.settings/language.settings.xml deleted file mode 100644 index 55660b04..00000000 --- a/lib-dmxreceiver/.settings/language.settings.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-dmxreceiver/Makefile.GD32 b/lib-dmxreceiver/Makefile.GD32 deleted file mode 100644 index 08083275..00000000 --- a/lib-dmxreceiver/Makefile.GD32 +++ /dev/null @@ -1,5 +0,0 @@ -DEFINES=NDEBUG - -EXTRA_INCLUDES=../lib-dmx/include ../lib-lightset/include - -include ../firmware-template-gd32/lib/Rules.mk \ No newline at end of file diff --git a/lib-dmxreceiver/src/dmxreceiver.cpp b/lib-dmxreceiver/src/dmxreceiver.cpp deleted file mode 100644 index 3a9da4ca..00000000 --- a/lib-dmxreceiver/src/dmxreceiver.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @file dmxreceiver.cpp - * - */ -/* Copyright (C) 2017-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEconst uint8_t*MENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "dmxreceiver.h" - -LightSet *DMXReceiver::s_pLightSet; -bool DMXReceiver::s_IsActive; -bool DMXReceiver::s_bDisableOutput; diff --git a/lib-dmxsend/.cproject b/lib-dmxsend/.cproject deleted file mode 100644 index 84e9fc95..00000000 --- a/lib-dmxsend/.cproject +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-dmxsend/.project b/lib-dmxsend/.project deleted file mode 100644 index 505bc290..00000000 --- a/lib-dmxsend/.project +++ /dev/null @@ -1,27 +0,0 @@ - - - lib-dmxsend - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/lib-dmxsend/.settings/language.settings.xml b/lib-dmxsend/.settings/language.settings.xml deleted file mode 100644 index 8e3748f8..00000000 --- a/lib-dmxsend/.settings/language.settings.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-dmxsend/.settings/org.eclipse.cdt.core.prefs b/lib-dmxsend/.settings/org.eclipse.cdt.core.prefs deleted file mode 100644 index c8ec5df2..00000000 --- a/lib-dmxsend/.settings/org.eclipse.cdt.core.prefs +++ /dev/null @@ -1,6 +0,0 @@ -doxygen/doxygen_new_line_after_brief=true -doxygen/doxygen_use_brief_tag=false -doxygen/doxygen_use_javadoc_tags=true -doxygen/doxygen_use_pre_tag=false -doxygen/doxygen_use_structural_commands=false -eclipse.preferences.version=1 diff --git a/lib-dmxsend/.settings/org.eclipse.core.resources.prefs b/lib-dmxsend/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 99f26c02..00000000 --- a/lib-dmxsend/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -encoding/=UTF-8 diff --git a/lib-dmxsend/Makefile.GD32 b/lib-dmxsend/Makefile.GD32 deleted file mode 100644 index bf629e65..00000000 --- a/lib-dmxsend/Makefile.GD32 +++ /dev/null @@ -1,4 +0,0 @@ -DEFINES=NDEBUG -EXTRA_INCLUDES=../lib-dmx/include ../lib-lightset/include - -include ../firmware-template-gd32/lib/Rules.mk \ No newline at end of file diff --git a/lib-dmxsend/include/dmxsend.h b/lib-dmxsend/include/dmxsend.h deleted file mode 100755 index 340a5728..00000000 --- a/lib-dmxsend/include/dmxsend.h +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @file dmxsend.h - * - */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef DMXSEND_H_ -#define DMXSEND_H_ - -#include - -#include "lightset.h" -#include "dmx.h" -#include "hardware.h" - -class DmxSend final: public LightSet { -public: - void Start(const uint32_t nPortIndex) override; - void Stop(const uint32_t nPortIndex) override; - - void SetData(uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate = true) override; - void Sync(const uint32_t nPortIndex) override; - void Sync(const bool doForce = false) override; - -#if defined (OUTPUT_HAVE_STYLESWITCH) - void SetOutputStyle(const uint32_t nPortIndex, const lightset::OutputStyle outputStyle) override { - Dmx::Get()->SetOutputStyle(nPortIndex, outputStyle == lightset::OutputStyle::CONSTANT ? dmx::OutputStyle::CONTINOUS : dmx::OutputStyle::DELTA); - } - - lightset::OutputStyle GetOutputStyle(const uint32_t nPortIndex) const override { - return Dmx::Get()->GetOutputStyle(nPortIndex) == dmx::OutputStyle::CONTINOUS ? lightset::OutputStyle::CONSTANT : lightset::OutputStyle::DELTA; - } -#endif - - void Blackout(__attribute__((unused)) bool bBlackout) override { - Dmx::Get()->Blackout(); - } - - void FullOn() override { - Dmx::Get()->FullOn(); - } - -#if defined(LIGHTSET_HAVE_RUN) - void Run() override { - const auto nMillis = Hardware::Get()->Millis(); - if ((nMillis - s_nMillis) > 200) { - s_nMillis = nMillis; - for (uint32_t nPortIndex = 0; nPortIndex < dmx::config::max::OUT; nPortIndex++) { - hal::panel_led_off(hal::panelled::PORT_A_TX << nPortIndex); - } - } - } -#endif - - void Print() override; - -private: - static uint32_t s_nMillis; - - struct TxData { - uint8_t data[dmx::buffer::SIZE]; - uint32_t nLength; - }; - static struct TxData s_TxData[dmx::config::max::OUT]; - - static uint8_t s_nStarted; -}; - -#endif /* DMXSEND_H_ */ diff --git a/lib-dmxsend/src/dmxsend.cpp b/lib-dmxsend/src/dmxsend.cpp deleted file mode 100755 index 1cdb00dc..00000000 --- a/lib-dmxsend/src/dmxsend.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/** - * @file dmxsend.cpp - * - */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#include - -#include "dmxsend.h" -#include "dmx.h" - -#include "panel_led.h" - -#include "debug.h" - -uint32_t DmxSend::s_nMillis; -uint8_t DmxSend::s_nStarted; -struct DmxSend::TxData DmxSend::s_TxData[dmx::config::max::OUT]; - -static constexpr bool is_started(const uint8_t v, const uint32_t p) { - return (v & (1U << p)) == (1U << p); -} - -void DmxSend::Start(const uint32_t nPortIndex) { - DEBUG_ENTRY - DEBUG_PRINTF("nPortIndex=%d", nPortIndex); - - assert(nPortIndex < CHAR_BIT); - - if (is_started(s_nStarted, nPortIndex)) { - DEBUG_EXIT - return; - } - - s_nStarted = static_cast(s_nStarted | (1U << nPortIndex)); - - Dmx::Get()->SetPortDirection(nPortIndex, dmx::PortDirection::OUTP, true); - - if (Dmx::Get()->GetOutputStyle(nPortIndex) == dmx::OutputStyle::CONTINOUS) { - hal::panel_led_on(hal::panelled::PORT_A_TX << nPortIndex); - } - - DEBUG_EXIT -} - -void DmxSend::Stop(const uint32_t nPortIndex) { - DEBUG_ENTRY - DEBUG_PRINTF("nPortIndex=%d -> %u", nPortIndex, is_started(s_nStarted, static_cast(nPortIndex))); - - assert(nPortIndex < CHAR_BIT); - - if (!is_started(s_nStarted, nPortIndex)) { - DEBUG_EXIT - return; - } - - s_nStarted = static_cast(s_nStarted & ~(1U << nPortIndex)); - - Dmx::Get()->SetPortDirection(nPortIndex, dmx::PortDirection::OUTP, false); - - hal::panel_led_off(hal::panelled::PORT_A_TX << nPortIndex); - - DEBUG_EXIT -} - -/** - * - * @param [in] nPortIndex - * @param [in] pData - * @param [in] nLength - * @param [in] doUpdate - */ -void DmxSend::SetData(uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate) { - assert(nPortIndex < CHAR_BIT); - assert(pData != nullptr); - - if (__builtin_expect((nLength == 0), 0)) { - return; - } - - if (doUpdate) { - Dmx::Get()->SetSendDataWithoutSC(nPortIndex, pData, nLength); - Dmx::Get()->StartOutput(nPortIndex); - hal::panel_led_on(hal::panelled::PORT_A_TX << nPortIndex); - } else { - memcpy(s_TxData[nPortIndex].data, pData, nLength); - s_TxData[nPortIndex].nLength = nLength; - } -} - -/** - * - * @param [in] nPortIndex - */ -void DmxSend::Sync(uint32_t const nPortIndex) { - assert(s_TxData[nPortIndex].nLength != 0); - - Dmx::Get()->SetSendDataWithoutSC(nPortIndex, s_TxData[nPortIndex].data, s_TxData[nPortIndex].nLength); -} - -/** - * - * @param [in] doForce - */ -void DmxSend::Sync(const bool doForce) { - Dmx::Get()->SetOutput(doForce); - - for (uint32_t nPortIndex = 0; nPortIndex < dmx::config::max::OUT; nPortIndex++) { - if (s_TxData[nPortIndex].nLength != 0) { - s_TxData[nPortIndex].nLength = 0; - if (!is_started(s_nStarted, nPortIndex)) { - Start(nPortIndex); - } - } - } -} - -#include - -void DmxSend::Print() { - printf("DMX Send\n"); - printf(" Break time : %u\n", Dmx::Get()->GetDmxBreakTime()); - printf(" MAB time : %u\n", Dmx::Get()->GetDmxMabTime()); - printf(" Refresh rate : %u\n", 1000000U / Dmx::Get()->GetDmxPeriodTime()); - printf(" Slots : %u\n", Dmx::Get()->GetDmxSlots()); -} diff --git a/lib-e131/.cproject b/lib-e131/.cproject index d56bc12c..01631fdf 100644 --- a/lib-e131/.cproject +++ b/lib-e131/.cproject @@ -30,11 +30,9 @@ - diff --git a/lib-e131/Rules.mk b/lib-e131/Rules.mk index 17779edd..4dd754e4 100644 --- a/lib-e131/Rules.mk +++ b/lib-e131/Rules.mk @@ -17,6 +17,9 @@ ifneq ($(MAKE_FLAGS),) ifeq ($(findstring NODE_NODE,$(MAKE_FLAGS)), NODE_NODE) EXTRA_SRCDIR+=src/node endif + ifeq ($(findstring OUTPUT_DMX_SEND,$(MAKE_FLAGS)), OUTPUT_DMX_SEND) + EXTRA_INCLUDES+=../lib-dmx/include + endif else EXTRA_SRCDIR+=src/node src/node/dmxin src/controller DEFINES+=E131_HAVE_DMXIN @@ -24,4 +27,6 @@ else DEFINES+=OUTPUT_DMX_SEND DEFINES+=LIGHTSET_PORTS=4 EXTRA_INCLUDES+=../lib-dmx/include + DEFINES+=NODE_SHOWFILE + DEFINES+=CONFIG_SHOWFILE_PROTOCOL_NODE_E131 endif \ No newline at end of file diff --git a/lib-e131/include/e131bridge.h b/lib-e131/include/e131bridge.h old mode 100644 new mode 100755 index 3c09ca8a..bac902a8 --- a/lib-e131/include/e131bridge.h +++ b/lib-e131/include/e131bridge.h @@ -2,7 +2,7 @@ * @file e131bridge.h * */ -/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -37,11 +37,24 @@ #include "lightset.h" #include "lightsetdata.h" +#if !(ARTNET_VERSION >= 4) +# if defined(OUTPUT_DMX_SEND) || defined(OUTPUT_DMX_SEND_MULTI) +# if !defined(E131_DISABLE_DMX_CONFIG_UDP) +# include "dmxconfigudp.h" +# endif +# endif +#endif + #include "network.h" #include "hardware.h" +#include "panel_led.h" #include "debug.h" +#ifndef ALIGNED +# define ALIGNED __attribute__ ((aligned (4))) +#endif + namespace e131bridge { #if !defined(LIGHTSET_PORTS) # error LIGHTSET_PORTS is not defined @@ -58,13 +71,6 @@ namespace e131bridge { }; struct State { - bool IsNetworkDataLoss; - bool IsMergeMode; - bool IsSynchronized; - bool IsForcedSynchronized; - bool IsChanged; - bool bDisableMergeTimeout; - bool bDisableSynchronize; uint32_t SynchronizationTime; uint32_t DiscoveryTime; uint16_t DiscoveryPacketLength; @@ -76,6 +82,13 @@ struct State { uint8_t nReceivingDmx; lightset::FailSafe failsafe; e131bridge::Status status; + bool IsNetworkDataLoss; + bool IsMergeMode; + bool IsSynchronized; + bool IsForcedSynchronized; + bool IsChanged; + bool bDisableMergeTimeout; + bool bDisableSynchronize; }; struct Bridge { @@ -83,7 +96,7 @@ struct Bridge { uint16_t nUniverse; lightset::PortDir direction; bool bLocalMerge; - } Port[e131bridge::MAX_PORTS]; + } Port[e131bridge::MAX_PORTS] ALIGNED; }; struct Source { @@ -94,12 +107,13 @@ struct Source { }; struct OutputPort { - Source sourceA; - Source sourceB; + Source sourceA ALIGNED; + Source sourceB ALIGNED; lightset::MergeMode mergeMode; lightset::OutputStyle outputStyle; bool IsMerging; bool IsTransmitting; + bool IsDataPending; }; struct InputPort { @@ -215,19 +229,6 @@ class E131Bridge { m_pE131Sync = pE131Sync; } - const uint8_t *GetCid() const { - return m_Cid; - } - - void SetSourceName(const char *pSourceName) { - assert(pSourceName != nullptr); - strncpy(m_SourceName, pSourceName, e131::SOURCE_NAME_LENGTH - 1); - m_SourceName[e131::SOURCE_NAME_LENGTH - 1] = '\0'; - } - const char *GetSourceName() const { - return m_SourceName; - } - void SetPriority(const uint32_t nPortIndex, uint8_t nPriority) { assert(nPortIndex < e131bridge::MAX_PORTS); if ((nPriority >= e131::priority::LOWEST) && (nPriority <= e131::priority::HIGHEST)) { @@ -251,27 +252,12 @@ class E131Bridge { void SetOutputStyle(const uint32_t nPortIndex, lightset::OutputStyle outputStyle) { assert(nPortIndex < e131bridge::MAX_PORTS); - if ((m_State.status == e131bridge::Status::ON) && (m_pLightSet != nullptr)) { + if (m_pLightSet != nullptr) { m_pLightSet->SetOutputStyle(nPortIndex, outputStyle); outputStyle = m_pLightSet->GetOutputStyle(nPortIndex); } m_OutputPort[nPortIndex].outputStyle = outputStyle; - -#if defined (OUTPUT_DMX_SEND) || defined (OUTPUT_DMX_SEND_MULTI) - /** - * FIXME I do not like this hack. It should be handled in dmx.cpp - */ - if (m_Bridge.Port[nPortIndex].direction == lightset::PortDir::OUTPUT - && (outputStyle == lightset::OutputStyle::CONSTANT) - && (m_pLightSet != nullptr)) { - if (m_OutputPort[nPortIndex].IsTransmitting) { - m_OutputPort[nPortIndex].IsTransmitting = false; - m_pLightSet->Stop(nPortIndex); - } - } -#endif - } lightset::OutputStyle GetOutputStyle(const uint32_t nPortIndex) const { @@ -293,6 +279,21 @@ class E131Bridge { m_State.IsNetworkDataLoss = false; // Force timeout } +#if defined (E131_HAVE_DMXIN) || defined (NODE_SHOWFILE) + void SetSourceName(const char *pSourceName) { + assert(pSourceName != nullptr); + strncpy(m_SourceName, pSourceName, e131::SOURCE_NAME_LENGTH - 1); + m_SourceName[e131::SOURCE_NAME_LENGTH - 1] = '\0'; + } + const char *GetSourceName() const { + return m_SourceName; + } + + const uint8_t *GetCid() const { + return m_Cid; + } +#endif + void Start(); void Stop(); @@ -339,13 +340,31 @@ class E131Bridge { Process(); -#if defined (LIGHTSET_HAVE_RUN) -# if (ARTNET_VERSION < 4) - m_pLightSet->Run(); -# endif +#if !(ARTNET_VERSION >= 4) + if ((m_nCurrentPacketMillis - m_nPreviousLedpanelMillis) > 200) { + m_nPreviousLedpanelMillis = m_nCurrentPacketMillis; + for (uint32_t nPortIndex = 0; nPortIndex < e131bridge::MAX_PORTS; nPortIndex++) { + hal::panel_led_off(hal::panelled::PORT_A_TX << nPortIndex); +#if defined (E131_HAVE_DMXIN) + hal::panel_led_off(hal::panelled::PORT_A_RX << nPortIndex); +#endif + } + } +#endif +#if defined (DMXCONFIGUDP_H) + m_DmxConfigUdp.Run(); #endif } +#if defined (NODE_SHOWFILE) && defined (CONFIG_SHOWFILE_PROTOCOL_NODE_E131) + void HandleShowFile(const TE131DataPacket *pE131DataPacket) { + m_nCurrentPacketMillis = Hardware::Get()->Millis(); + m_nIpAddressFrom = Network::Get()->GetIp(); + m_pReceiveBuffer = reinterpret_cast(const_cast(pE131DataPacket)); + HandleDmx(); + } +#endif + void Print(); static E131Bridge* Get() { @@ -382,12 +401,7 @@ class E131Bridge { uint32_t m_nCurrentPacketMillis { 0 }; uint32_t m_nPreviousPacketMillis { 0 }; - - TE131DataPacket *m_pE131DataPacket { nullptr }; - TE131DiscoveryPacket *m_pE131DiscoveryPacket { nullptr }; - uint32_t m_DiscoveryIpAddress { 0 }; - uint8_t m_Cid[e131::CID_LENGTH]; - char m_SourceName[e131::SOURCE_NAME_LENGTH]; + uint32_t m_nPreviousLedpanelMillis { 0 }; e131bridge::State m_State; e131bridge::Bridge m_Bridge; @@ -403,6 +417,24 @@ class E131Bridge { // Synchronization handler E131Sync *m_pE131Sync { nullptr }; +#if defined (E131_HAVE_DMXIN) || defined (NODE_SHOWFILE) + char m_SourceName[e131::SOURCE_NAME_LENGTH]; + uint8_t m_Cid[e131::CID_LENGTH]; +#endif + +#if defined (E131_HAVE_DMXIN) + TE131DataPacket m_E131DataPacket; + TE131DiscoveryPacket m_E131DiscoveryPacket; + uint32_t m_DiscoveryIpAddress { 0 }; +#endif + +#if defined (DMXCONFIGUDP_H_) +# if defined (ARTNET_VERSION) +# error +# endif + DmxConfigUdp m_DmxConfigUdp; +#endif + static E131Bridge *s_pThis; }; diff --git a/lib-e131/include/e131bridgeconst.h b/lib-e131/include/e131const.h similarity index 84% rename from lib-e131/include/e131bridgeconst.h rename to lib-e131/include/e131const.h index 79ea3246..a23212e5 100644 --- a/lib-e131/include/e131bridgeconst.h +++ b/lib-e131/include/e131const.h @@ -1,8 +1,8 @@ /** - * @file e131bridgeconst.h + * @file e131const.h * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,13 +23,13 @@ * THE SOFTWARE. */ -#ifndef E131BRIDGECONST_H_ -#define E131BRIDGECONST_H_ +#ifndef E131CONST_H_ +#define E131CONST_H_ #include -struct E131BridgeConst { +struct E131Const { static const uint8_t VERSION[]; }; -#endif /* E131BRIDGECONST_H_ */ +#endif /* E131CONST_H_ */ diff --git a/lib-e131/include/e131controller.h b/lib-e131/include/e131controller.h index 13b24f00..ef6f6d3d 100644 --- a/lib-e131/include/e131controller.h +++ b/lib-e131/include/e131controller.h @@ -2,7 +2,7 @@ * @file e131controller.h * */ -/* Copyright (C) 2020-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-e131/include/e131msgconst.h b/lib-e131/include/e131msgconst.h index 3b656c37..c0c4e5e4 100644 --- a/lib-e131/include/e131msgconst.h +++ b/lib-e131/include/e131msgconst.h @@ -2,7 +2,7 @@ * @file e131msgconst.h * */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,7 +27,6 @@ #define E131MSGCONST_H_ struct E131MsgConst { - static const char PARAMS[]; static const char START[]; static const char STARTED[]; }; diff --git a/lib-e131/include/e131packets.h b/lib-e131/include/e131packets.h index 3f0bae68..e13d3091 100644 --- a/lib-e131/include/e131packets.h +++ b/lib-e131/include/e131packets.h @@ -2,7 +2,7 @@ * @file e131packets.h * */ -/* Copyright (C) 2016-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-e131/include/e131params.h b/lib-e131/include/e131params.h index 24fdfee6..003f62be 100644 --- a/lib-e131/include/e131params.h +++ b/lib-e131/include/e131params.h @@ -2,7 +2,7 @@ * @file e131params.h * */ -/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,6 +29,7 @@ #include #include "e131bridge.h" +#include "configstore.h" #include "lightset.h" #if !defined(LIGHTSET_PORTS) @@ -112,15 +113,18 @@ struct Mask { class E131ParamsStore { public: - virtual ~E131ParamsStore() {} + static void Update(const struct e131params::Params *pParams) { + ConfigStore::Get()->Update(configstore::Store::NODE, pParams, sizeof(struct e131params::Params)); + } - virtual void Update(const e131params::Params *pParams)=0; - virtual void Copy(e131params::Params *pParams)=0; + static void Copy(struct e131params::Params *pParams) { + ConfigStore::Get()->Copy(configstore::Store::NODE, pParams, sizeof(struct e131params::Params)); + } }; class E131Params { public: - E131Params(E131ParamsStore *pE131ParamsStore); + E131Params(); bool Load(); void Load(const char *pBuffer, uint32_t nLength); @@ -130,9 +134,7 @@ class E131Params { Builder(nullptr, pBuffer, nLength, nSize); } - void Set(uint32_t nPortIndexOffset); - - void Dump(); + void Set(); uint16_t GetUniverse(uint32_t nPortIndex, bool &IsSet) const { if (nPortIndex < e131params::MAX_PORTS) { @@ -162,15 +164,10 @@ class E131Params { } #endif -#if defined (ESP8266) - lightset::OutputType GetOutputType() const { - return static_cast(m_Params.Filler1); - } -#endif - static void staticCallbackFunction(void *p, const char *s); private: + void Dump(); void callbackFunction(const char *s); bool isMaskSet(uint32_t nMask) const { return (m_Params.nSetList & nMask) == nMask; @@ -184,7 +181,6 @@ class E131Params { } private: - E131ParamsStore *m_pE131ParamsStore; e131params::Params m_Params; }; diff --git a/lib-e131/include/e131paramsconst.h b/lib-e131/include/e131paramsconst.h index b2154b14..403e274e 100644 --- a/lib-e131/include/e131paramsconst.h +++ b/lib-e131/include/e131paramsconst.h @@ -2,7 +2,7 @@ * @file e131paramsconst.h * */ -/* Copyright (C) 2019-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-e131/include/e131sync.h b/lib-e131/include/e131sync.h index e7da3b34..6d19c69e 100644 --- a/lib-e131/include/e131sync.h +++ b/lib-e131/include/e131sync.h @@ -3,7 +3,7 @@ * */ -/* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,7 +29,7 @@ class E131Sync { public: - virtual ~E131Sync() {} + virtual ~E131Sync() = default; virtual void Handler()=0; }; diff --git a/lib-e131/src/controller/e131controller.cpp b/lib-e131/src/controller/e131controller.cpp index 0f185ea1..fe0c66ca 100644 --- a/lib-e131/src/controller/e131controller.cpp +++ b/lib-e131/src/controller/e131controller.cpp @@ -2,7 +2,7 @@ * @file e131controller.cpp * */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -362,7 +362,7 @@ uint8_t E131Controller::GetSequenceNumber(uint16_t nUniverse, uint32_t &nMultica } void E131Controller::Print() { - printf("sACN E1.31 Controller\n"); + puts("sACN E1.31 Controller"); printf(" Max Universes : %d\n", static_cast(sizeof(s_SequenceNumbers) / sizeof(s_SequenceNumbers[0]))); if (m_State.SynchronizationPacket.nUniverseNumber != 0) { printf(" Synchronization Universe : %u\n", m_State.SynchronizationPacket.nUniverseNumber); diff --git a/lib-e131/src/node/e131bridgeconst.cpp b/lib-e131/src/e131const.cpp old mode 100644 new mode 100755 similarity index 86% rename from lib-e131/src/node/e131bridgeconst.cpp rename to lib-e131/src/e131const.cpp index eb5ad36e..23696402 --- a/lib-e131/src/node/e131bridgeconst.cpp +++ b/lib-e131/src/e131const.cpp @@ -1,8 +1,8 @@ /** - * @file e131bridgeconst.cpp + * @file e131const.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,6 +25,6 @@ #include -#include "e131bridgeconst.h" +#include "e131const.h" -const uint8_t E131BridgeConst::VERSION[] = { 1, 27 }; +const uint8_t E131Const::VERSION[] = { 1, 27 }; diff --git a/lib-e131/src/node/dmxin/discoverypacket.cpp b/lib-e131/src/node/dmxin/discoverypacket.cpp index ecc78115..95a6fc27 100644 --- a/lib-e131/src/node/dmxin/discoverypacket.cpp +++ b/lib-e131/src/node/dmxin/discoverypacket.cpp @@ -2,7 +2,7 @@ * @file e131bridgediscoverypacket * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,23 +36,23 @@ void E131Bridge::FillDiscoveryPacket() { m_State.DiscoveryPacketLength = static_cast(DISCOVERY_PACKET_SIZE(m_State.nEnabledInputPorts)); - memset(m_pE131DiscoveryPacket, 0, sizeof(struct TE131DiscoveryPacket)); + memset(&m_E131DiscoveryPacket, 0, sizeof(struct TE131DiscoveryPacket)); // Root Layer (See Section 5) - m_pE131DiscoveryPacket->RootLayer.PreAmbleSize = __builtin_bswap16(0x10); - memcpy(m_pE131DiscoveryPacket->RootLayer.ACNPacketIdentifier, E117Const::ACN_PACKET_IDENTIFIER, e117::PACKET_IDENTIFIER_LENGTH); - m_pE131DiscoveryPacket->RootLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DISCOVERY_ROOT_LAYER_LENGTH(m_State.nEnabledInputPorts)))); - m_pE131DiscoveryPacket->RootLayer.Vector = __builtin_bswap32(e131::vector::root::EXTENDED); - memcpy(m_pE131DiscoveryPacket->RootLayer.Cid, m_Cid, e131::CID_LENGTH); + m_E131DiscoveryPacket.RootLayer.PreAmbleSize = __builtin_bswap16(0x10); + memcpy(m_E131DiscoveryPacket.RootLayer.ACNPacketIdentifier, E117Const::ACN_PACKET_IDENTIFIER, e117::PACKET_IDENTIFIER_LENGTH); + m_E131DiscoveryPacket.RootLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DISCOVERY_ROOT_LAYER_LENGTH(m_State.nEnabledInputPorts)))); + m_E131DiscoveryPacket.RootLayer.Vector = __builtin_bswap32(e131::vector::root::EXTENDED); + memcpy(m_E131DiscoveryPacket.RootLayer.Cid, m_Cid, e131::CID_LENGTH); // E1.31 Framing Layer (See Section 6) - m_pE131DiscoveryPacket->FrameLayer.FLagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DISCOVERY_FRAME_LAYER_LENGTH(m_State.nEnabledInputPorts)))); - m_pE131DiscoveryPacket->FrameLayer.Vector = __builtin_bswap32(e131::vector::extended::DISCOVERY); - memcpy(m_pE131DiscoveryPacket->FrameLayer.SourceName, m_SourceName, e131::SOURCE_NAME_LENGTH); + m_E131DiscoveryPacket.FrameLayer.FLagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DISCOVERY_FRAME_LAYER_LENGTH(m_State.nEnabledInputPorts)))); + m_E131DiscoveryPacket.FrameLayer.Vector = __builtin_bswap32(e131::vector::extended::DISCOVERY); + memcpy(m_E131DiscoveryPacket.FrameLayer.SourceName, m_SourceName, e131::SOURCE_NAME_LENGTH); // Universe Discovery Layer (See Section 8) - m_pE131DiscoveryPacket->UniverseDiscoveryLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | DISCOVERY_LAYER_LENGTH(m_State.nEnabledInputPorts))); - m_pE131DiscoveryPacket->UniverseDiscoveryLayer.Vector = __builtin_bswap32(e131::vector::universe::DISCOVERY_UNIVERSE_LIST); + m_E131DiscoveryPacket.UniverseDiscoveryLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | DISCOVERY_LAYER_LENGTH(m_State.nEnabledInputPorts))); + m_E131DiscoveryPacket.UniverseDiscoveryLayer.Vector = __builtin_bswap32(e131::vector::universe::DISCOVERY_UNIVERSE_LIST); } void E131Bridge::SendDiscoveryPacket() { @@ -67,11 +67,11 @@ void E131Bridge::SendDiscoveryPacket() { for (uint32_t i = 0; i < e131bridge::MAX_PORTS; i++) { uint16_t nUniverse; if (GetUniverse(i, nUniverse, lightset::PortDir::INPUT)) { - m_pE131DiscoveryPacket->UniverseDiscoveryLayer.ListOfUniverses[nListOfUniverses++] = __builtin_bswap16(nUniverse); + m_E131DiscoveryPacket.UniverseDiscoveryLayer.ListOfUniverses[nListOfUniverses++] = __builtin_bswap16(nUniverse); } } - Network::Get()->SendTo(m_nHandle, m_pE131DiscoveryPacket, m_State.DiscoveryPacketLength, m_DiscoveryIpAddress, e131::UDP_PORT); + Network::Get()->SendTo(m_nHandle, &m_E131DiscoveryPacket, m_State.DiscoveryPacketLength, m_DiscoveryIpAddress, e131::UDP_PORT); } } } diff --git a/lib-e131/src/node/dmxin/handledmxin.cpp b/lib-e131/src/node/dmxin/handledmxin.cpp index bf292b9f..1c304ce5 100644 --- a/lib-e131/src/node/dmxin/handledmxin.cpp +++ b/lib-e131/src/node/dmxin/handledmxin.cpp @@ -2,7 +2,7 @@ * @file e131bridgehandledmxin.cpp * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -43,50 +43,49 @@ void E131Bridge::FillDataPacket() { // Root Layer (See Section 5) - m_pE131DataPacket->RootLayer.PreAmbleSize = __builtin_bswap16(0x0010); - m_pE131DataPacket->RootLayer.PostAmbleSize = __builtin_bswap16(0x0000); - memcpy(m_pE131DataPacket->RootLayer.ACNPacketIdentifier, E117Const::ACN_PACKET_IDENTIFIER, e117::PACKET_IDENTIFIER_LENGTH); - m_pE131DataPacket->RootLayer.Vector = __builtin_bswap32(e131::vector::root::DATA); - memcpy(m_pE131DataPacket->RootLayer.Cid, m_Cid, e131::CID_LENGTH); + m_E131DataPacket.RootLayer.PreAmbleSize = __builtin_bswap16(0x0010); + m_E131DataPacket.RootLayer.PostAmbleSize = __builtin_bswap16(0x0000); + memcpy(m_E131DataPacket.RootLayer.ACNPacketIdentifier, E117Const::ACN_PACKET_IDENTIFIER, e117::PACKET_IDENTIFIER_LENGTH); + m_E131DataPacket.RootLayer.Vector = __builtin_bswap32(e131::vector::root::DATA); + memcpy(m_E131DataPacket.RootLayer.Cid, m_Cid, e131::CID_LENGTH); // E1.31 Framing Layer (See Section 6) - m_pE131DataPacket->FrameLayer.Vector = __builtin_bswap32(e131::vector::data::PACKET); - memcpy(m_pE131DataPacket->FrameLayer.SourceName, m_SourceName, e131::SOURCE_NAME_LENGTH); - m_pE131DataPacket->FrameLayer.SynchronizationAddress = __builtin_bswap16(0); // Currently not supported - m_pE131DataPacket->FrameLayer.Options = 0; + m_E131DataPacket.FrameLayer.Vector = __builtin_bswap32(e131::vector::data::PACKET); + memcpy(m_E131DataPacket.FrameLayer.SourceName, m_SourceName, e131::SOURCE_NAME_LENGTH); + m_E131DataPacket.FrameLayer.SynchronizationAddress = __builtin_bswap16(0); // Currently not supported + m_E131DataPacket.FrameLayer.Options = 0; // Data Layer - m_pE131DataPacket->DMPLayer.Vector = e131::vector::dmp::SET_PROPERTY; - m_pE131DataPacket->DMPLayer.Type = 0xa1; - m_pE131DataPacket->DMPLayer.FirstAddressProperty = __builtin_bswap16(0x0000); - m_pE131DataPacket->DMPLayer.AddressIncrement = __builtin_bswap16(0x0001); + m_E131DataPacket.DMPLayer.Vector = e131::vector::dmp::SET_PROPERTY; + m_E131DataPacket.DMPLayer.Type = 0xa1; + m_E131DataPacket.DMPLayer.FirstAddressProperty = __builtin_bswap16(0x0000); + m_E131DataPacket.DMPLayer.AddressIncrement = __builtin_bswap16(0x0001); } static uint32_t s_ReceivingMask = 0; void E131Bridge::HandleDmxIn() { for (uint32_t nPortIndex = 0 ; nPortIndex < e131bridge::MAX_PORTS; nPortIndex++) { - if ((m_Bridge.Port[nPortIndex].direction == lightset::PortDir::INPUT) - && (!m_InputPort[nPortIndex].IsDisabled)) { + if ((m_Bridge.Port[nPortIndex].direction == lightset::PortDir::INPUT) && (!m_InputPort[nPortIndex].IsDisabled)) { const auto *const pDmxData = reinterpret_cast(Dmx::Get()->GetDmxChanged(nPortIndex)); if (pDmxData != nullptr) { // Root Layer (See Section 5) auto nLength = (1U + pDmxData->Statistics.nSlotsInPacket); // Add 1 for SC - m_pE131DataPacket->RootLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_ROOT_LAYER_LENGTH(nLength)))); + m_E131DataPacket.RootLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_ROOT_LAYER_LENGTH(nLength)))); // E1.31 Framing Layer (See Section 6) - m_pE131DataPacket->FrameLayer.FLagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_FRAME_LAYER_LENGTH(nLength)))); - m_pE131DataPacket->FrameLayer.Priority = m_InputPort[nPortIndex].nPriority; - m_pE131DataPacket->FrameLayer.SequenceNumber = m_InputPort[nPortIndex].nSequenceNumber++; - m_pE131DataPacket->FrameLayer.Universe = __builtin_bswap16(m_Bridge.Port[nPortIndex].nUniverse); + m_E131DataPacket.FrameLayer.FLagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_FRAME_LAYER_LENGTH(nLength)))); + m_E131DataPacket.FrameLayer.Priority = m_InputPort[nPortIndex].nPriority; + m_E131DataPacket.FrameLayer.SequenceNumber = m_InputPort[nPortIndex].nSequenceNumber++; + m_E131DataPacket.FrameLayer.Universe = __builtin_bswap16(m_Bridge.Port[nPortIndex].nUniverse); // Data Layer - m_pE131DataPacket->DMPLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_LAYER_LENGTH(nLength)))); - memcpy(m_pE131DataPacket->DMPLayer.PropertyValues, pDmxData, nLength); - m_pE131DataPacket->DMPLayer.PropertyValueCount = __builtin_bswap16(static_cast(nLength)); + m_E131DataPacket.DMPLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_LAYER_LENGTH(nLength)))); + memcpy(m_E131DataPacket.DMPLayer.PropertyValues, pDmxData, nLength); + m_E131DataPacket.DMPLayer.PropertyValueCount = __builtin_bswap16(static_cast(nLength)); - Network::Get()->SendTo(m_nHandle, m_pE131DataPacket, static_cast(DATA_PACKET_SIZE(nLength)), m_InputPort[nPortIndex].nMulticastIp, e131::UDP_PORT); + Network::Get()->SendTo(m_nHandle, &m_E131DataPacket, DATA_PACKET_SIZE(nLength), m_InputPort[nPortIndex].nMulticastIp, e131::UDP_PORT); if (m_Bridge.Port[nPortIndex].bLocalMerge) { - m_pReceiveBuffer = reinterpret_cast(m_pE131DataPacket); + m_pReceiveBuffer = reinterpret_cast(&m_E131DataPacket); m_nIpAddressFrom = Network::Get()->GetIp(); HandleDmx(); } @@ -124,21 +123,21 @@ void E131Bridge::HandleDmxIn() { const auto *const pDmxData = reinterpret_cast(Dmx::Get()->GetDmxCurrentData(nPortIndex)); // Root Layer (See Section 5) auto nLength = (1U + pDmxData->Statistics.nSlotsInPacket); // Add 1 for SC - m_pE131DataPacket->RootLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_ROOT_LAYER_LENGTH(nLength)))); + m_E131DataPacket.RootLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_ROOT_LAYER_LENGTH(nLength)))); // E1.31 Framing Layer (See Section 6) - m_pE131DataPacket->FrameLayer.FLagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_FRAME_LAYER_LENGTH(nLength)))); - m_pE131DataPacket->FrameLayer.Priority = m_InputPort[nPortIndex].nPriority; - m_pE131DataPacket->FrameLayer.SequenceNumber = m_InputPort[nPortIndex].nSequenceNumber++; - m_pE131DataPacket->FrameLayer.Universe = __builtin_bswap16(m_Bridge.Port[nPortIndex].nUniverse); + m_E131DataPacket.FrameLayer.FLagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_FRAME_LAYER_LENGTH(nLength)))); + m_E131DataPacket.FrameLayer.Priority = m_InputPort[nPortIndex].nPriority; + m_E131DataPacket.FrameLayer.SequenceNumber = m_InputPort[nPortIndex].nSequenceNumber++; + m_E131DataPacket.FrameLayer.Universe = __builtin_bswap16(m_Bridge.Port[nPortIndex].nUniverse); // Data Layer - m_pE131DataPacket->DMPLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_LAYER_LENGTH(nLength)))); - memcpy(m_pE131DataPacket->DMPLayer.PropertyValues, pDmxData, nLength); - m_pE131DataPacket->DMPLayer.PropertyValueCount = __builtin_bswap16(static_cast(nLength)); + m_E131DataPacket.DMPLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_LAYER_LENGTH(nLength)))); + memcpy(m_E131DataPacket.DMPLayer.PropertyValues, pDmxData, nLength); + m_E131DataPacket.DMPLayer.PropertyValueCount = __builtin_bswap16(static_cast(nLength)); - Network::Get()->SendTo(m_nHandle, m_pE131DataPacket, static_cast(DATA_PACKET_SIZE(nLength)), m_InputPort[nPortIndex].nMulticastIp, e131::UDP_PORT); + Network::Get()->SendTo(m_nHandle, &m_E131DataPacket, DATA_PACKET_SIZE(nLength), m_InputPort[nPortIndex].nMulticastIp, e131::UDP_PORT); if (m_Bridge.Port[nPortIndex].bLocalMerge) { - m_pReceiveBuffer = reinterpret_cast(&m_pE131DataPacket); + m_pReceiveBuffer = reinterpret_cast(&m_E131DataPacket); m_nIpAddressFrom = Network::Get()->GetIp(); HandleDmx(); } diff --git a/lib-e131/src/node/e131bridge.cpp b/lib-e131/src/node/e131bridge.cpp index bb1e06d3..01e97c19 100755 --- a/lib-e131/src/node/e131bridge.cpp +++ b/lib-e131/src/node/e131bridge.cpp @@ -23,6 +23,12 @@ * THE SOFTWARE. */ +#if !defined(__clang__) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif + #include #include #include @@ -71,7 +77,7 @@ E131Bridge::E131Bridge() { m_InputPort[i].nPriority = 100; } -#if defined (E131_HAVE_DMXIN) +#if defined (E131_HAVE_DMXIN) || defined (NODE_SHOWFILE) char aSourceName[e131::SOURCE_NAME_LENGTH]; uint8_t nLength; snprintf(aSourceName, e131::SOURCE_NAME_LENGTH, "%.48s %s", Network::Get()->GetHostName(), Hardware::Get()->GetBoardName(nLength)); @@ -94,18 +100,10 @@ E131Bridge::~E131Bridge() { void E131Bridge::Start() { #if defined (E131_HAVE_DMXIN) - if (m_pE131DataPacket == nullptr) { - const auto nIpMulticast = network::convert_to_uint(239, 255, 0, 0); - m_DiscoveryIpAddress = nIpMulticast | ((e131::universe::DISCOVERY & static_cast(0xFF)) << 24) | ((e131::universe::DISCOVERY & 0xFF00) << 8); - // TE131DataPacket - m_pE131DataPacket = new TE131DataPacket; - assert(m_pE131DataPacket != nullptr); - FillDataPacket(); - // TE131DiscoveryPacket - m_pE131DiscoveryPacket = new TE131DiscoveryPacket; - assert(m_pE131DiscoveryPacket != nullptr); - FillDiscoveryPacket(); - } + const auto nIpMulticast = network::convert_to_uint(239, 255, 0, 0); + m_DiscoveryIpAddress = nIpMulticast | ((e131::universe::DISCOVERY & static_cast(0xFF)) << 24) | ((e131::universe::DISCOVERY & 0xFF00) << 8); + FillDataPacket(); + FillDiscoveryPacket(); for (uint32_t nPortIndex = 0; nPortIndex < e131bridge::MAX_PORTS; nPortIndex++) { if (m_Bridge.Port[nPortIndex].direction == lightset::PortDir::INPUT) { @@ -580,6 +578,7 @@ void E131Bridge::HandleDmx() { } } else { lightset::Data::Set(m_pLightSet, nPortIndex); + m_OutputPort[nPortIndex].IsDataPending = true; } m_State.nReceivingDmx |= (1U << static_cast(lightset::PortDir::OUTPUT)); diff --git a/lib-e131/src/node/e131bridgehandlesynchronization.cpp b/lib-e131/src/node/e131bridgehandlesynchronization.cpp index c38b404d..5692e280 100755 --- a/lib-e131/src/node/e131bridgehandlesynchronization.cpp +++ b/lib-e131/src/node/e131bridgehandlesynchronization.cpp @@ -2,7 +2,7 @@ * @file e131bridgehandlesynchronization.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -52,17 +52,18 @@ void E131Bridge::HandleSynchronization() { m_State.SynchronizationTime = m_nCurrentPacketMillis; for (uint32_t nPortIndex = 0; nPortIndex < e131bridge::MAX_PORTS; nPortIndex++) { - if (m_Bridge.Port[nPortIndex].direction == lightset::PortDir::OUTPUT) { + if (m_OutputPort[nPortIndex].IsDataPending) { m_pLightSet->Sync(nPortIndex); } } m_pLightSet->Sync(); - for (uint32_t nPortIndex = 0; nPortIndex < e131bridge::MAX_PORTS; nPortIndex++) { - if (m_Bridge.Port[nPortIndex].direction == lightset::PortDir::OUTPUT) { - if (!m_OutputPort[nPortIndex].IsTransmitting) { - m_OutputPort[nPortIndex].IsTransmitting = true; + for (auto &outputPort : m_OutputPort) { + if (outputPort.IsDataPending) { + outputPort.IsDataPending = false; + if (!outputPort.IsTransmitting) { + outputPort.IsTransmitting = true; m_State.IsChanged = true; } } diff --git a/lib-e131/src/node/e131bridgeprint.cpp b/lib-e131/src/node/e131bridgeprint.cpp index 8450877e..55029594 100644 --- a/lib-e131/src/node/e131bridgeprint.cpp +++ b/lib-e131/src/node/e131bridgeprint.cpp @@ -2,7 +2,7 @@ * @file e131bridgeprint.cpp * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,7 +33,7 @@ #include #include "e131bridge.h" -#include "e131bridgeconst.h" +#include "e131const.h" #include "e131.h" #if defined (E131_HAVE_DMXIN) @@ -46,8 +46,7 @@ void E131Bridge::Print() { uuid_str[UUID_STRING_LENGTH] = '\0'; uuid_unparse(m_Cid, uuid_str); #endif - printf("Bridge\n"); - printf(" Firmware : %d.%d\n", E131BridgeConst::VERSION[0], E131BridgeConst::VERSION[1]); + printf("sACN E1.31 V%d.%d\n", E131Const::VERSION[0], E131Const::VERSION[1]); #if defined (E131_HAVE_DMXIN) printf(" CID : %s\n", uuid_str); #endif @@ -57,7 +56,7 @@ void E131Bridge::Print() { for (uint32_t nPortIndex = 0; nPortIndex < e131bridge::MAX_PORTS; nPortIndex++) { uint16_t nUniverse; if (GetUniverse(nPortIndex, nUniverse, lightset::PortDir::OUTPUT)) { - printf(" Port %-2d %-4u %s\n", nPortIndex, nUniverse, lightset::get_merge_mode(m_OutputPort[nPortIndex].mergeMode, true)); + printf(" Port %-2u %-4u %s\n", static_cast(nPortIndex), static_cast(nUniverse), lightset::get_merge_mode(m_OutputPort[nPortIndex].mergeMode, true)); } } } @@ -69,7 +68,7 @@ void E131Bridge::Print() { for (uint32_t nPortIndex = 0; nPortIndex < e131bridge::MAX_PORTS; nPortIndex++) { uint16_t nUniverse; if (GetUniverse(nPortIndex, nUniverse, lightset::PortDir::INPUT)) { - printf(" Port %-2d %-4u %-3u\n", nPortIndex, nUniverse, GetPriority(nPortIndex)); + printf(" Port %-2u %-4u %-3u\n", static_cast(nPortIndex), static_cast(nUniverse), GetPriority(nPortIndex)); } } } diff --git a/lib-e131/src/node/e131msgconst.cpp b/lib-e131/src/node/e131msgconst.cpp index 9044fdc5..82af7dd6 100644 --- a/lib-e131/src/node/e131msgconst.cpp +++ b/lib-e131/src/node/e131msgconst.cpp @@ -2,7 +2,7 @@ * @file e131mgsconst.cpp * */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,6 +25,5 @@ #include "e131msgconst.h" -const char E131MsgConst::PARAMS[] = "Configuring sACN E1.31"; const char E131MsgConst::START[] = "Starting sACN E1.31"; const char E131MsgConst::STARTED[] = "sACN E1.31 started"; diff --git a/lib-e131/src/node/e131params.cpp b/lib-e131/src/node/e131params.cpp index 2084edb8..f06c99cc 100644 --- a/lib-e131/src/node/e131params.cpp +++ b/lib-e131/src/node/e131params.cpp @@ -2,7 +2,7 @@ * @file e131params.cpp * */ -/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -48,6 +48,12 @@ #include "debug.h" +namespace e131bridge { +namespace configstore { +extern uint32_t DMXPORT_OFFSET; +} // namespace configstore +} // namespace e131bridge + static uint32_t s_nPortsMax; namespace e131params { @@ -62,7 +68,7 @@ static constexpr uint16_t portdir_clear(const uint32_t i) { using namespace e131params; -E131Params::E131Params(E131ParamsStore *pE131ParamsStore):m_pE131ParamsStore(pE131ParamsStore) { +E131Params::E131Params() { DEBUG_ENTRY DEBUG_PRINTF("sizeof(struct Params)=%d", static_cast(sizeof(struct Params))); @@ -92,18 +98,14 @@ bool E131Params::Load() { ReadConfigFile configfile(E131Params::staticCallbackFunction, this); if (configfile.Read(E131ParamsConst::FILE_NAME)) { - if (m_pE131ParamsStore != nullptr) { - m_pE131ParamsStore->Update(&m_Params); - } + E131ParamsStore::Update(&m_Params); } else #endif - if (m_pE131ParamsStore != nullptr) { - m_pE131ParamsStore->Copy(&m_Params); - } else { - DEBUG_EXIT - return false; - } + E131ParamsStore::Copy(&m_Params); +#ifndef NDEBUG + Dump(); +#endif DEBUG_EXIT return true; } @@ -120,9 +122,11 @@ void E131Params::Load(const char* pBuffer, uint32_t nLength) { config.Read(pBuffer, nLength); - assert(m_pE131ParamsStore != nullptr); - m_pE131ParamsStore->Update(&m_Params); + E131ParamsStore::Update(&m_Params); +#ifndef NDEBUG + Dump(); +#endif DEBUG_EXIT } @@ -247,21 +251,13 @@ void E131Params::callbackFunction(const char *pLine) { } } -void E131Params::staticCallbackFunction(void *p, const char *s) { - assert(p != nullptr); - assert(s != nullptr); - - (static_cast(p))->callbackFunction(s); -} - void E131Params::Builder(const struct Params *pParams, char *pBuffer, uint32_t nLength, uint32_t& nSize) { DEBUG_ENTRY if (pParams != nullptr) { memcpy(&m_Params, pParams, sizeof(struct Params)); } else { - assert(m_pE131ParamsStore != nullptr); - m_pE131ParamsStore->Copy(&m_Params); + E131ParamsStore::Copy(&m_Params); } PropertiesBuilder builder(E131ParamsConst::FILE_NAME, pBuffer, nLength); @@ -310,14 +306,14 @@ void E131Params::Builder(const struct Params *pParams, char *pBuffer, uint32_t n DEBUG_EXIT } -void E131Params::Set(uint32_t nPortIndexOffset) { +void E131Params::Set() { DEBUG_ENTRY - if (nPortIndexOffset <= e131bridge::MAX_PORTS) { - s_nPortsMax = std::min(e131params::MAX_PORTS, e131bridge::MAX_PORTS - nPortIndexOffset); + if (e131bridge::configstore::DMXPORT_OFFSET <= e131bridge::MAX_PORTS) { + s_nPortsMax = std::min(e131params::MAX_PORTS, e131bridge::MAX_PORTS - e131bridge::configstore::DMXPORT_OFFSET); } - DEBUG_PRINTF("e131bridge::MAX_PORTS=%u, nPortIndexOffset=%u, s_nPortsMax=%u", e131bridge::MAX_PORTS, nPortIndexOffset, s_nPortsMax); + DEBUG_PRINTF("e131bridge::MAX_PORTS=%u, e131bridge::configstore::DMXPORT_OFFSET=%u, s_nPortsMax=%u", e131bridge::MAX_PORTS, e131bridge::configstore::DMXPORT_OFFSET, s_nPortsMax); if (m_Params.nSetList == 0) { return; @@ -327,7 +323,7 @@ void E131Params::Set(uint32_t nPortIndexOffset) { assert(p != nullptr); for (uint32_t nPortIndex = 0; nPortIndex < s_nPortsMax; nPortIndex++) { - const auto nOffset = nPortIndex + nPortIndexOffset; + const auto nOffset = nPortIndex + e131bridge::configstore::DMXPORT_OFFSET; if (nOffset >= e131bridge::MAX_PORTS) { DEBUG_EXIT @@ -353,3 +349,48 @@ void E131Params::Set(uint32_t nPortIndexOffset) { p->SetDisableMergeTimeout(true); } } + +void E131Params::staticCallbackFunction(void *p, const char *s) { + assert(p != nullptr); + assert(s != nullptr); + + (static_cast(p))->callbackFunction(s); +} + +void E131Params::Dump() { + printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, E131ParamsConst::FILE_NAME); + + if (isMaskSet(e131params::Mask::FAILSAFE)) { + printf(" %s=%d [%s]\n", LightSetParamsConst::FAILSAFE, m_Params.nFailSafe, lightset::get_failsafe(static_cast(m_Params.nFailSafe))); + } + + for (uint32_t i = 0; i < e131params::MAX_PORTS; i++) { + if (isMaskSet(e131params::Mask::UNIVERSE_A << i)) { + printf(" %s=%d\n", LightSetParamsConst::UNIVERSE_PORT[i], m_Params.nUniverse[i]); + } + } + + for (uint32_t i = 0; i < e131params::MAX_PORTS; i++) { + printf(" %s=%s\n", LightSetParamsConst::MERGE_MODE_PORT[i], lightset::get_merge_mode(mergemode_get(i))); + } + + for (uint32_t i = 0; i < e131params::MAX_PORTS; i++) { + const auto portDir = static_cast(e131params::portdir_shif_right(m_Params.nDirection, i)); + printf(" %s=%d [%s]\n", LightSetParamsConst::DIRECTION[i], e131params::portdir_shif_right(m_Params.nDirection, i), lightset::get_direction(portDir)); + } + + for (uint32_t i = 0; i < e131params::MAX_PORTS; i++) { + if (isMaskSet(e131params::Mask::PRIORITY_A << i)) { + printf(" %s=%d\n", E131ParamsConst::PRIORITY[i], m_Params.nPriority[i]); + } + } + + for (uint32_t i = 0; i < e131params::MAX_PORTS; i++) { + const auto nOutputStyle = static_cast(isOutputStyleSet(1U << i)); + printf(" %s=%u [%s]\n", LightSetParamsConst::OUTPUT_STYLE[i], static_cast(nOutputStyle), lightset::get_output_style(static_cast(nOutputStyle))); + } + + if (isMaskSet(e131params::Mask::DISABLE_MERGE_TIMEOUT)) { + printf(" %s=1 [Yes]\n", LightSetParamsConst::DISABLE_MERGE_TIMEOUT); + } +} diff --git a/lib-e131/src/node/e131paramsconst.cpp b/lib-e131/src/node/e131paramsconst.cpp index 6654a31f..3b6cd51c 100644 --- a/lib-e131/src/node/e131paramsconst.cpp +++ b/lib-e131/src/node/e131paramsconst.cpp @@ -2,7 +2,7 @@ * @file e131paramsconst.cpp * */ -/* Copyright (C) 2019-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-e131/src/node/e131paramsdump.cpp b/lib-e131/src/node/e131paramsdump.cpp deleted file mode 100644 index 7486385c..00000000 --- a/lib-e131/src/node/e131paramsdump.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file e131paramsdump.cpp - * - */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#if !defined(__clang__) // Needed for compiling on MacOS -# pragma GCC push_options -# pragma GCC optimize ("Os") -#endif - -#include -#include - -#include "e131params.h" -#include "e131paramsconst.h" - -#include "lightset.h" -#include "lightsetparamsconst.h" - -void E131Params::Dump() { -#ifndef NDEBUG - printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, E131ParamsConst::FILE_NAME); - - if (isMaskSet(e131params::Mask::FAILSAFE)) { - printf(" %s=%d [%s]\n", LightSetParamsConst::FAILSAFE, m_Params.nFailSafe, lightset::get_failsafe(static_cast(m_Params.nFailSafe))); - } - - for (uint32_t i = 0; i < e131params::MAX_PORTS; i++) { - if (isMaskSet(e131params::Mask::UNIVERSE_A << i)) { - printf(" %s=%d\n", LightSetParamsConst::UNIVERSE_PORT[i], m_Params.nUniverse[i]); - } - } - - for (uint32_t i = 0; i < e131params::MAX_PORTS; i++) { - printf(" %s=%s\n", LightSetParamsConst::MERGE_MODE_PORT[i], lightset::get_merge_mode(mergemode_get(i))); - } - - for (uint32_t i = 0; i < e131params::MAX_PORTS; i++) { - const auto portDir = static_cast(e131params::portdir_shif_right(m_Params.nDirection, i)); - printf(" %s=%d [%s]\n", LightSetParamsConst::DIRECTION[i], e131params::portdir_shif_right(m_Params.nDirection, i), lightset::get_direction(portDir)); - } - - for (uint32_t i = 0; i < e131params::MAX_PORTS; i++) { - if (isMaskSet(e131params::Mask::PRIORITY_A << i)) { - printf(" %s=%d\n", E131ParamsConst::PRIORITY[i], m_Params.nPriority[i]); - } - } - - for (uint32_t i = 0; i < e131params::MAX_PORTS; i++) { - const auto nOutputStyle = static_cast(isOutputStyleSet(1U << i)); - printf(" %s=%u [%s]\n", LightSetParamsConst::OUTPUT_STYLE[i], nOutputStyle, lightset::get_output_style(static_cast(nOutputStyle))); - } - - if (isMaskSet(e131params::Mask::DISABLE_MERGE_TIMEOUT)) { - printf(" %s=1 [Yes]\n", LightSetParamsConst::DISABLE_MERGE_TIMEOUT); - } -#endif -} diff --git a/lib-flash/.cproject b/lib-flash/.cproject index deefab79..f3bf1ec5 100755 --- a/lib-flash/.cproject +++ b/lib-flash/.cproject @@ -31,12 +31,10 @@ - diff --git a/lib-flash/include/spi/spi_flash.h b/lib-flash/include/spi/spi_flash.h index 50df49c1..729a61f6 100644 --- a/lib-flash/include/spi/spi_flash.h +++ b/lib-flash/include/spi/spi_flash.h @@ -2,7 +2,7 @@ * @file spi_flash.h * */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-flash/src/spi/gd32/spi_flash.cpp b/lib-flash/src/spi/gd32/spi_flash.cpp index 7b2597ea..a719e284 100644 --- a/lib-flash/src/spi/gd32/spi_flash.cpp +++ b/lib-flash/src/spi/gd32/spi_flash.cpp @@ -2,7 +2,7 @@ * @file spi_flash.cpp * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,6 +28,7 @@ #include "./../../spi/spi_flash_internal.h" #include "gd32_spi.h" +#include "gd32_gpio.h" #include "gd32.h" #include "debug.h" @@ -41,6 +42,16 @@ int spi_init() { gpio_fsel(SPI_FLASH_CS_GPIOx, SPI_FLASH_CS_GPIO_PINx, GPIO_FSEL_OUTPUT); gpio_bit_set(SPI_FLASH_CS_GPIOx, SPI_FLASH_CS_GPIO_PINx); +#if defined (SPI_FLASH_WP_GPIO_PINx) + gpio_fsel(SPI_GPIOx, SPI_FLASH_WP_GPIO_PINx, GPIO_FSEL_OUTPUT); + gpio_bit_set(SPI_GPIOx, SPI_FLASH_WP_GPIO_PINx); +#endif + +#if defined (SPI_FLASH_HOLD_GPIO_PINx) + gpio_fsel(SPI_GPIOx, SPI_FLASH_HOLD_GPIO_PINx, GPIO_FSEL_OUTPUT); + gpio_bit_set(SPI_GPIOx, SPI_FLASH_HOLD_GPIO_PINx); +#endif + return 0; } diff --git a/lib-flash/src/spi/get_timer.cpp b/lib-flash/src/spi/get_timer.cpp index 91bc169e..3edf77d5 100644 --- a/lib-flash/src/spi/get_timer.cpp +++ b/lib-flash/src/spi/get_timer.cpp @@ -2,7 +2,7 @@ * @file get_timer.cpp * */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-flash/src/spi/gigadevice.cpp b/lib-flash/src/spi/gigadevice.cpp old mode 100644 new mode 100755 index d32ec219..9c72f30a --- a/lib-flash/src/spi/gigadevice.cpp +++ b/lib-flash/src/spi/gigadevice.cpp @@ -12,7 +12,7 @@ /* * Original code : https://github.com/martinezjavier/u-boot/blob/master/drivers/mtd/spi/gigadevice.c */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -50,6 +50,11 @@ static constexpr struct gigadevice_spi_flash_params gigadevice_spi_flash_table[] 64, "GD25LQ", }, + { + 0x4015, + 8, + "GD25Q40", + }, { 0x4017, 128, @@ -68,10 +73,11 @@ int spi_flash_probe_gigadevice(struct spi_flash *flash, uint8_t *idcode) { } if (i == ARRAY_SIZE(gigadevice_spi_flash_table)) { - DEBUG_PRINTF("SF: Unsupported Gigadevice ID %02x%02x", idcode[1], idcode[2]); + DEBUG_PRINTF("SF: Unsupported GigaDevice ID %02x%02x", idcode[1], idcode[2]); return -1; } + flash->name = params->name; flash->page_size = 256; flash->sector_size = flash->page_size * 16; flash->size = flash->sector_size * 16 * params->nr_blocks; diff --git a/lib-flash/src/spi/macronix.cpp b/lib-flash/src/spi/macronix.cpp index 3a2ceb2b..ebff01c6 100644 --- a/lib-flash/src/spi/macronix.cpp +++ b/lib-flash/src/spi/macronix.cpp @@ -19,7 +19,7 @@ /* * Original code : https://github.com/martinezjavier/u-boot/blob/master/drivers/mtd/spi/macronix.c */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-flash/src/spi/spi_flash.cpp b/lib-flash/src/spi/spi_flash.cpp index bcb15794..ab0e11c2 100644 --- a/lib-flash/src/spi/spi_flash.cpp +++ b/lib-flash/src/spi/spi_flash.cpp @@ -5,7 +5,7 @@ /* * Original code : https://github.com/martinezjavier/u-boot/blob/master/drivers/mtd/spi/spi_flash.c */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,6 +33,7 @@ #include #include #include +#include #include "spi/spi_flash.h" @@ -90,6 +91,14 @@ static const struct { }; #define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN) +static uint32_t get_timer(uint32_t base) { + if (0 == base) { + return static_cast(time(nullptr)); + } + + return static_cast(time(nullptr)) - base; +} + uint32_t spi_flash_get_size() { return s_flash.size; } @@ -356,7 +365,7 @@ int spi_flash_cmd_write_status(uint8_t sr) { return 0; } -int spi_flash_probe(__attribute__((unused)) unsigned int cs, __attribute__((unused)) unsigned int max_hz, __attribute__((unused)) unsigned int spi_mode) { +int spi_flash_probe([[maybe_unused]] unsigned int cs, [[maybe_unused]] unsigned int max_hz, [[maybe_unused]] unsigned int spi_mode) { int shift; unsigned i; uint8_t idcode[IDCODE_LEN] = {0, }; diff --git a/lib-flash/src/spi/spi_flash_internal.h b/lib-flash/src/spi/spi_flash_internal.h index 6b6af846..019fff1a 100644 --- a/lib-flash/src/spi/spi_flash_internal.h +++ b/lib-flash/src/spi/spi_flash_internal.h @@ -2,7 +2,7 @@ * @file spi_internal.h * */ -/* Copyright (C) 2019-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@g32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -74,18 +74,16 @@ struct spi_flash { #define SPI_XFER_SPEED_HZ 6000000 ///< 6MHz -extern uint32_t get_timer(uint32_t base); //TODO Remove - extern int spi_init(); extern int spi_xfer(uint32_t bitlen, const uint8_t *dout, uint8_t *din, uint32_t flags); -#define CONFIG_SPI_FLASH_MACRONIX -int spi_flash_probe_macronix(struct spi_flash *flash, uint8_t *idcode); +//#define CONFIG_SPI_FLASH_MACRONIX +//int spi_flash_probe_macronix(struct spi_flash *flash, uint8_t *idcode); #define CONFIG_SPI_FLASH_WINBOND extern int spi_flash_probe_winbond(struct spi_flash *spi, uint8_t *idcode); -#define CONFIG_SPI_FLASH_GIGADEVICE -extern int spi_flash_probe_gigadevice(struct spi_flash *spi, uint8_t *idcode); +//#define CONFIG_SPI_FLASH_GIGADEVICE +//extern int spi_flash_probe_gigadevice(struct spi_flash *spi, uint8_t *idcode); #endif /* SPI_FLASH_INTERNAL_H_ */ diff --git a/lib-flash/src/spi/winbond.cpp b/lib-flash/src/spi/winbond.cpp index 249308d4..e821a3c1 100644 --- a/lib-flash/src/spi/winbond.cpp +++ b/lib-flash/src/spi/winbond.cpp @@ -10,7 +10,7 @@ /* * Original code : https://github.com/martinezjavier/u-boot/blob/master/drivers/mtd/spi/winbond.c */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-flashcode/.cproject b/lib-flashcode/.cproject index 4bcd643d..fdc205e6 100755 --- a/lib-flashcode/.cproject +++ b/lib-flashcode/.cproject @@ -31,11 +31,9 @@ - @@ -95,7 +90,6 @@ - diff --git a/lib-flashcode/Makefile.GD32 b/lib-flashcode/Makefile.GD32 index e0ac7451..3808855c 100755 --- a/lib-flashcode/Makefile.GD32 +++ b/lib-flashcode/Makefile.GD32 @@ -4,7 +4,11 @@ ifneq ($(MAKE_FLAGS),) ifeq ($(findstring gd32f4xx,$(FAMILY)), gd32f4xx) EXTRA_SRCDIR=src/gd32/f4xx else - EXTRA_SRCDIR=src/gd32/fmc + ifeq ($(findstring gd32h7xx,$(FAMILY)), gd32h7xx) + EXTRA_SRCDIR=src/gd32/h7xx + else + EXTRA_SRCDIR=src/gd32/fmc + endif endif else EXTRA_SRCDIR=src/gd32/fmc diff --git a/lib-flashcode/include/flashcode.h b/lib-flashcode/include/flashcode.h index 95eacb77..de55e14e 100644 --- a/lib-flashcode/include/flashcode.h +++ b/lib-flashcode/include/flashcode.h @@ -2,7 +2,7 @@ * @file flashcode.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-flashcode/src/gd32/f4xx/flashcode.cpp b/lib-flashcode/src/gd32/f4xx/flashcode.cpp deleted file mode 100644 index 3a133f69..00000000 --- a/lib-flashcode/src/gd32/f4xx/flashcode.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/** - * @file flashcode.cpp - * - */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@gd32-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "flashcode.h" - -#include "gd32.h" -#include "fmc_operation.h" - -#include "debug.h" - -uint32_t FlashCode::GetSize() const { - return FMC_SIZE * 1024U; -} - -uint32_t FlashCode::GetSectorSize() const { - return SIZE_16KB; -} - -bool FlashCode::Read(uint32_t nOffset, uint32_t nLength, uint8_t *pBuffer, flashcode::result& nResult) { - DEBUG_ENTRY - DEBUG_PRINTF("nOffset=%p[%d], nLength=%u[%d], data=%p[%d]", nOffset, (((uint32_t)(nOffset) & 0x3) == 0), nLength, (((uint32_t)(nLength) & 0x3) == 0), data, (((uint32_t)(data) & 0x3) == 0)); - - const uint32_t *src = (uint32_t *)(nOffset + FLASH_BASE); - uint32_t *dst = (uint32_t *)pBuffer; - - while (nLength > 0) { - *dst++ = *src++; - nLength -= 4; - } - - debug_dump((uint8_t *)(nOffset + FLASH_BASE), 64); - debug_dump(pBuffer, 64); - - nResult = flashcode::result::OK; - - DEBUG_EXIT - return 0; -} - -bool FlashCode::Write(uint32_t nOffset, uint32_t nLength, const uint8_t *pBuffer, flashcode::result& nResult) { - DEBUG_ENTRY - DEBUG_PRINTF("nOffset=%p[%d], nLength=%u[%d], data=%p[%d]", nOffset, (((uint32_t)(nOffset) & 0x3) == 0), nLength, (((uint32_t)(nLength) & 0x3) == 0), pBuffer, (((uint32_t)(pBuffer) & 0x3) == 0)); - - nResult = flashcode::result::ERROR; - - fmc_unlock(); - fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR); - - uint32_t address = nOffset + FLASH_BASE; - const uint32_t *data = (uint32_t *)pBuffer; - - while (nLength >= 4) { - - fmc_state_enum state = fmc_word_program(address, *data); - - if (FMC_READY != state) { - DEBUG_PRINTF("state=%d [%p]", state, address); - DEBUG_EXIT - return true; - } - - data++; - address += 4; - nLength -= 4; - } - - if (nLength > 0) { - fmc_state_enum state = fmc_word_program(address, *data); - - if (FMC_READY != state) { - DEBUG_PRINTF("state=%d [%p]", state, address); - DEBUG_EXIT - return true; - } - } - - fmc_lock(); - - debug_dump(pBuffer, 64); - debug_dump((uint8_t *)(nOffset + FLASH_BASE), 64); - - nResult = flashcode::result::OK; - - DEBUG_EXIT - return true; -} - -bool FlashCode::Erase(uint32_t nOffset, uint32_t nLength, flashcode::result& nResult) { - DEBUG_ENTRY - DEBUG_PRINTF("nOffset=%p[%d], nLength=%x[%d]", nOffset, (((uint32_t)(nOffset) & 0x3) == 0), nLength, (((uint32_t)(nLength) & 0x3) == 0)); - - nResult = flashcode::result::ERROR; - - fmc_sector_info_struct sector_info; - uint32_t address = nOffset + FLASH_BASE; - - int size = (int) nLength; - - while (size > 0) { - sector_info = fmc_sector_info_get(address); - - if (FMC_WRONG_SECTOR_NAME == sector_info.sector_name) { - return true; - } - - DEBUG_PRINTF("Address 0x%08X is located in the : SECTOR_NUMBER_%d", address, sector_info.sector_name); - DEBUG_PRINTF("Sector range: 0x%08X to 0x%08X", sector_info.sector_start_addr, sector_info.sector_end_addr); - DEBUG_PRINTF("nSector size: %d KB\n", (sector_info.sector_size/1024)); - - fmc_unlock(); - fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR); - - if (FMC_READY != fmc_sector_erase(sector_info.sector_num)) { - return true; - } - - fmc_lock(); - - size -= sector_info.sector_size; - address += sector_info.sector_size; - } - - - nResult = flashcode::result::OK; - - DEBUG_EXIT - return true; -} diff --git a/lib-flashcode/src/gd32/f4xx/fmc_operation.cpp b/lib-flashcode/src/gd32/f4xx/fmc_operation.cpp deleted file mode 100644 index 32470238..00000000 --- a/lib-flashcode/src/gd32/f4xx/fmc_operation.cpp +++ /dev/null @@ -1,367 +0,0 @@ -/*! - \file fmc_operation.c - \brief flash program, erase - - \version 2016-08-15, V1.0.0, firmware for GD32F4xx - \version 2018-12-12, V2.0.0, firmware for GD32F4xx - \version 2020-09-30, V2.1.0, firmware for GD32F4xx -*/ - -/* - Copyright (c) 2020, GigaDevice Semiconductor Inc. - - Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -OF SUCH DAMAGE. -*/ - -#include "gd32.h" -#include "fmc_operation.h" - -/*! - \brief get the sector number, size and range of the given address - \param[in] address: The flash address - \param[out] none - \retval fmc_sector_info_struct: The information of a sector -*/ -fmc_sector_info_struct fmc_sector_info_get(uint32_t addr) -{ - fmc_sector_info_struct sector_info; - uint32_t temp = 0x00000000U; - if((FMC_START_ADDRESS <= addr)&&(FMC_END_ADDRESS >= addr)) { - if ((FMC_BANK1_START_ADDRESS > addr)) { - /* bank0 area */ - temp = (addr - FMC_BANK0_START_ADDRESS) / SIZE_16KB; - if (4U > temp) { - sector_info.sector_name = (uint32_t)temp; - sector_info.sector_num = CTL_SN(temp); - sector_info.sector_size = SIZE_16KB; - sector_info.sector_start_addr = FMC_BANK0_START_ADDRESS + (SIZE_16KB * temp); - sector_info.sector_end_addr = sector_info.sector_start_addr + SIZE_16KB - 1; - } else if (8U > temp) { - sector_info.sector_name = 0x00000004U; - sector_info.sector_num = CTL_SN(4); - sector_info.sector_size = SIZE_64KB; - sector_info.sector_start_addr = 0x08010000U; - sector_info.sector_end_addr = 0x0801FFFFU; - } else { - temp = (addr - FMC_BANK0_START_ADDRESS) / SIZE_128KB; - sector_info.sector_name = (uint32_t)(temp + 4); - sector_info.sector_num = CTL_SN(temp + 4); - sector_info.sector_size = SIZE_128KB; - sector_info.sector_start_addr = FMC_BANK0_START_ADDRESS + (SIZE_128KB * temp); - sector_info.sector_end_addr = sector_info.sector_start_addr + SIZE_128KB - 1; - } - } else { - /* bank1 area */ - temp = (addr - FMC_BANK1_START_ADDRESS) / SIZE_16KB; - if (4U > temp) { - sector_info.sector_name = (uint32_t)(temp + 12); - sector_info.sector_num = CTL_SN(temp + 16); - sector_info.sector_size = SIZE_16KB; - sector_info.sector_start_addr = FMC_BANK0_START_ADDRESS + (SIZE_16KB * temp); - sector_info.sector_end_addr = sector_info.sector_start_addr + SIZE_16KB - 1; - } else if (8U > temp) { - sector_info.sector_name = 0x00000010; - sector_info.sector_num = CTL_SN(20); - sector_info.sector_size = SIZE_64KB; - sector_info.sector_start_addr = 0x08110000U; - sector_info.sector_end_addr = 0x0811FFFFU; - } else if (64U > temp){ - temp = (addr - FMC_BANK1_START_ADDRESS) / SIZE_128KB; - sector_info.sector_name = (uint32_t)(temp + 16); - sector_info.sector_num = CTL_SN(temp + 20); - sector_info.sector_size = SIZE_128KB; - sector_info.sector_start_addr = FMC_BANK1_START_ADDRESS + (SIZE_128KB * temp); - sector_info.sector_end_addr = sector_info.sector_start_addr + SIZE_128KB - 1; - } else { - temp = (addr - FMC_BANK1_START_ADDRESS) / SIZE_256KB; - sector_info.sector_name = (uint32_t)(temp + 20); - sector_info.sector_num = CTL_SN(temp + 8); - sector_info.sector_size = SIZE_256KB; - sector_info.sector_start_addr = FMC_BANK1_START_ADDRESS + (SIZE_256KB * temp); - sector_info.sector_end_addr = sector_info.sector_start_addr + SIZE_256KB - 1; - } - } - } else { - /* invalid address */ - sector_info.sector_name = FMC_WRONG_SECTOR_NAME; - sector_info.sector_num = FMC_WRONG_SECTOR_NUM; - sector_info.sector_size = FMC_INVALID_SIZE; - sector_info.sector_start_addr = FMC_INVALID_ADDR; - sector_info.sector_end_addr = FMC_INVALID_ADDR; - } - return sector_info; -} - -/*! - \brief get the sector number by a given sector name - \param[in] address: a given sector name - \param[out] none - \retval uint32_t: sector number -*/ -uint32_t sector_name_to_number(uint32_t sector_name) -{ - if(11 >= sector_name){ - return CTL_SN(sector_name); - }else if(23 >= sector_name){ - return CTL_SN(sector_name + 4); - }else if(27 >= sector_name){ - return CTL_SN(sector_name - 12); - }else{ - while(1); - } -} - -/*! - \brief erases the sector of a given address - \param[in] address: a given address - \param[out] none - \retval none -*/ -void fmc_erase_sector_by_address(uint32_t address) -{ - fmc_sector_info_struct sector_info; - printf("\r\nFMC erase operation:\n"); - /* get information about the sector in which the specified address is located */ - sector_info = fmc_sector_info_get(address); - if(FMC_WRONG_SECTOR_NAME == sector_info.sector_name){ - printf("\r\nWrong address!\n"); - while(1); - }else{ - printf("\r\nErase start ......\n"); - /* unlock the flash program erase controller */ - fmc_unlock(); - /* clear pending flags */ - fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR); - /* wait the erase operation complete*/ - if(FMC_READY != fmc_sector_erase(sector_info.sector_num)){ - while(1); - } - /* lock the flash program erase controller */ - fmc_lock(); - printf("\r\nAddress 0x%08X is located in the : SECTOR_NUMBER_%d !\n", address, sector_info.sector_name); - printf("\r\nSector range: 0x%08X to 0x%08X\n", sector_info.sector_start_addr, sector_info.sector_end_addr); - printf("\r\nSector size: %d KB\n", (sector_info.sector_size/1024)); - printf("\r\nErase success!\n"); - printf("\r\n"); - } -} - -/*! - \brief write 32 bit length data to a given address - \param[in] address: a given address(0x08000000~0x082FFFFF) - \param[in] length: data length - \param[in] data_32: data pointer - \param[out] none - \retval none -*/ -void fmc_write_32bit_data(uint32_t address, uint16_t length, int32_t* data_32) -{ - fmc_sector_info_struct start_sector_info; - fmc_sector_info_struct end_sector_info; - uint32_t sector_num,i; - - printf("\r\nFMC word programe operation:\n"); - /* unlock the flash program erase controller */ - fmc_unlock(); - /* clear pending flags */ - fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR); - /* get the information of the start and end sectors */ - start_sector_info = fmc_sector_info_get(address); - end_sector_info = fmc_sector_info_get(address + 4*length); - /* erase sector */ - for(i = start_sector_info.sector_name; i <= end_sector_info.sector_name; i++){ - sector_num = sector_name_to_number(i); - if(FMC_READY != fmc_sector_erase(sector_num)){ - while(1); - } - } - - /* write data_32 to the corresponding address */ - for(i=0; i -#include "gd32f4xx.h" - -/* FMC sector information */ -typedef struct -{ - uint32_t sector_name; /*!< the name of the sector */ - uint32_t sector_num; /*!< the number of the sector */ - uint32_t sector_size; /*!< the size of the sector */ - uint32_t sector_start_addr; /*!< the start address of the sector */ - uint32_t sector_end_addr; /*!< the end address of the sector */ -} fmc_sector_info_struct; - -/* sector size */ -#define SIZE_16KB ((uint32_t)0x00004000U) /*!< size of 16KB*/ -#define SIZE_64KB ((uint32_t)0x00010000U) /*!< size of 64KB*/ -#define SIZE_128KB ((uint32_t)0x00020000U) /*!< size of 128KB*/ -#define SIZE_256KB ((uint32_t)0x00040000U) /*!< size of 256KB*/ - -/* FMC BANK address */ -#define FMC_START_ADDRESS FLASH_BASE /*!< FMC start address */ -#define FMC_BANK0_START_ADDRESS FMC_START_ADDRESS /*!< FMC BANK0 start address */ -#define FMC_BANK1_START_ADDRESS ((uint32_t)0x08100000U) /*!< FMC BANK1 start address */ -#define FMC_SIZE (*(uint16_t *)0x1FFF7A22U) /*!< FMC SIZE */ -#define FMC_END_ADDRESS (FLASH_BASE + (FMC_SIZE * 1024) - 1) /*!< FMC end address */ -#define FMC_MAX_END_ADDRESS ((uint32_t)0x08300000U) /*!< FMC maximum end address */ - -/* FMC error message */ -#define FMC_WRONG_SECTOR_NAME ((uint32_t)0xFFFFFFFFU) /*!< wrong sector name*/ -#define FMC_WRONG_SECTOR_NUM ((uint32_t)0xFFFFFFFFU) /*!< wrong sector number*/ -#define FMC_INVALID_SIZE ((uint32_t)0xFFFFFFFFU) /*!< invalid sector size*/ -#define FMC_INVALID_ADDR ((uint32_t)0xFFFFFFFFU) /*!< invalid sector address*/ - -/* get the sector number, size and range of the given address */ -fmc_sector_info_struct fmc_sector_info_get(uint32_t addr); -/* get the sector number by sector name */ -uint32_t sector_name_to_number(uint32_t sector_name); -/* erases the sector of a given sector number */ -void fmc_erase_sector_by_address(uint32_t address); -/* write 32 bit length data to a given address */ -void fmc_write_32bit_data(uint32_t address, uint16_t length, int32_t* data_32); -/* read 32 bit length data from a given address */ -void fmc_read_32bit_data(uint32_t address, uint16_t length, int32_t* data_32); -/* write 16 bit length data to a given address */ -void fmc_write_16bit_data(uint32_t address, uint16_t length, int16_t* data_16); -/* read 16 bit length data from a given address */ -void fmc_read_16bit_data(uint32_t address, uint16_t length, int16_t* data_16); -/* write 8 bit length data to a given address */ -void fmc_write_8bit_data(uint32_t address, uint16_t length, int8_t* data_8); -/* read 8 bit length data from a given address */ -void fmc_read_8bit_data(uint32_t address, uint16_t length, int8_t* data_8); - -#endif/* __FMC_OPERATION_H */ diff --git a/lib-flashcode/src/gd32/flashcode.cpp b/lib-flashcode/src/gd32/flashcode.cpp index 449e416f..f423d045 100644 --- a/lib-flashcode/src/gd32/flashcode.cpp +++ b/lib-flashcode/src/gd32/flashcode.cpp @@ -2,7 +2,7 @@ * @file flashcode.cpp * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -41,7 +41,7 @@ FlashCode::FlashCode() { m_IsDetected = true; - printf("FMC: Detected %s with total %d bytes [%d kB]\n", GetName(), GetSize(), GetSize() / 1024U); + printf("FMC: %s %u [%u]\n", GetName(), static_cast(GetSize()), static_cast(GetSize() / 1024U)); DEBUG_EXIT } diff --git a/lib-flashcode/src/gd32/fmc/flashcode.cpp b/lib-flashcode/src/gd32/fmc/flashcode.cpp index 9338ba59..46c8e3a9 100644 --- a/lib-flashcode/src/gd32/fmc/flashcode.cpp +++ b/lib-flashcode/src/gd32/fmc/flashcode.cpp @@ -2,7 +2,7 @@ * @file flashcode.cpp * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,6 +31,16 @@ #include "gd32.h" +/** + * With the latest GD32F firmware, this function is declared as static. + */ +#if defined (GD32F20X) +extern "C" { +fmc_state_enum fmc_bank0_state_get(void); +fmc_state_enum fmc_bank1_state_get(void); +} +#endif + #include "debug.h" namespace flashcode { diff --git a/lib-flashcode/src/gd32/h7xx/flashcode.cpp b/lib-flashcode/src/gd32/h7xx/flashcode.cpp new file mode 100644 index 00000000..47cc26a5 --- /dev/null +++ b/lib-flashcode/src/gd32/h7xx/flashcode.cpp @@ -0,0 +1,217 @@ +/** + * @file flashcode.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include "flashcode.h" + +#include "gd32.h" + +#include "debug.h" + +namespace flashcode { +/* Backwards compatibility with SPI FLASH */ +static constexpr auto FLASH_SECTOR_SIZE = 4096U; +/* The flash page size is 4KB for bank1 */ +static constexpr auto BANK1_FLASH_PAGE = (4U * 1024U); + +enum class State { + IDLE, + ERASE_BUSY, + ERASE_PROGAM, + WRITE_BUSY, + WRITE_PROGRAM, + ERROR +}; + +static State s_State = State::IDLE; +static uint32_t s_nPage; +static uint32_t s_nLength; +static uint32_t s_nAddress; +static uint32_t *s_pData; +} // namespace flashcode + +using namespace flashcode; + +uint32_t FlashCode::GetSize() const { + const auto FLASH_DENSITY = ((REG32(0x1FF0F7E0) >> 16) & 0xFFFF) * 1024U; + return FLASH_DENSITY; +} + +uint32_t FlashCode::GetSectorSize() const { + return flashcode::FLASH_SECTOR_SIZE; +} + +bool FlashCode::Read(uint32_t nOffset, uint32_t nLength, uint8_t *pBuffer, flashcode::result& nResult) { + DEBUG_ENTRY + DEBUG_PRINTF("offset=%p[%d], len=%u[%d], data=%p[%d]", nOffset, (((uint32_t)(nOffset) & 0x3) == 0), nLength, (((uint32_t)(nLength) & 0x3) == 0), pBuffer, (((uint32_t)(pBuffer) & 0x3) == 0)); + + const auto *pSrc = reinterpret_cast(nOffset + FLASH_BASE); + auto *pDst = reinterpret_cast(pBuffer); + + while (nLength > 0) { + *pDst++ = *pSrc++; + nLength -= 4; + } + + nResult = flashcode::result::OK; + + DEBUG_EXIT + return true; +} + +bool FlashCode::Erase(uint32_t nOffset, uint32_t nLength, flashcode::result& nResult) { + DEBUG_ENTRY + DEBUG_PRINTF("State=%d", static_cast(s_State)); + + nResult = result::OK; + + switch (s_State) { + case State::IDLE: + s_nPage = nOffset + FLASH_BASE; + s_nLength = nLength; + fmc_unlock(); + s_State = State::ERASE_BUSY; + DEBUG_EXIT + return false; + break; + case State::ERASE_BUSY: + if (SET == fmc_flag_get(FMC_FLAG_BUSY)) { + DEBUG_EXIT + return false; + } + + if (s_nLength == 0) { + s_State = State::IDLE; + fmc_lock(); + DEBUG_EXIT + return true; + } + + s_State = State::ERASE_PROGAM; + DEBUG_EXIT + return false; + break; + case State::ERASE_PROGAM: + if (s_nLength > 0) { + DEBUG_PRINTF("s_nPage=%p", s_nPage); + + fmc_sector_erase(s_nPage); + + s_nLength -= BANK1_FLASH_PAGE; + s_nPage += BANK1_FLASH_PAGE; + } + + s_State = State::ERASE_BUSY; + DEBUG_EXIT + return false; + break; + default: + assert(0); + __builtin_unreachable(); + break; + } + + assert(0); + __builtin_unreachable(); + return true; +} + +bool FlashCode::Write(uint32_t nOffset, uint32_t nLength, const uint8_t *pBuffer, flashcode::result& nResult) { + if ((s_State == flashcode::State::WRITE_PROGRAM) || (s_State == flashcode::State::WRITE_BUSY)) { + } else { + DEBUG_ENTRY + } + nResult = result::OK; + + switch (s_State) { + case flashcode::State::IDLE: + DEBUG_PUTS("State::IDLE"); + flashcode::s_nAddress = nOffset + FLASH_BASE; + s_pData = const_cast(reinterpret_cast(pBuffer)); + s_nLength = nLength; + fmc_unlock(); + s_State = State::WRITE_BUSY; + DEBUG_EXIT + return false; + break; + case flashcode::State::WRITE_BUSY: + if (SET == fmc_flag_get(FMC_FLAG_BUSY)) { + DEBUG_EXIT + return false; + } + + if (s_nLength == 0) { + fmc_lock(); + s_State = State::IDLE; + + if( memcmp(reinterpret_cast(nOffset + FLASH_BASE), pBuffer, nLength) == 0) { + DEBUG_PUTS("memcmp OK"); + } else { + DEBUG_PUTS("memcmp failed"); + } + + DEBUG_EXIT + return true; + } + + s_State = flashcode::State::WRITE_PROGRAM; + return false; + break; + case flashcode::State::WRITE_PROGRAM: + if (s_nLength >= 4) { + if (FMC_READY == fmc_ready_wait(0xFF)) { + /* set the PG bit to start program */ + FMC_CTL |= FMC_CTL_PG; + __ISB(); + __DSB(); + REG32(s_nAddress) = *s_pData; + __ISB(); + __DSB(); + /* reset the PG bit */ + FMC_CTL &= ~FMC_CTL_PG; + s_pData++; + s_nAddress += 4; + s_nLength -= 4; + } + } else if (s_nLength > 0) { + DEBUG_PUTS("Error!"); + } + s_State = flashcode::State::WRITE_BUSY; + return false; + break; + default: + assert(0); + __builtin_unreachable(); + break; + } + + assert(0); + __builtin_unreachable(); + return true; +} diff --git a/lib-gd32/.cproject b/lib-gd32/.cproject index bc32b5f4..15476525 100644 --- a/lib-gd32/.cproject +++ b/lib-gd32/.cproject @@ -14,7 +14,7 @@ - + @@ -100,7 +95,6 @@ - diff --git a/lib-gd32/Makefile.GD32 b/lib-gd32/Makefile.GD32 index 3bbe2a4b..a3896d58 100644 --- a/lib-gd32/Makefile.GD32 +++ b/lib-gd32/Makefile.GD32 @@ -1,79 +1,87 @@ +$(info "lib-gd32/Makefile.GD32") $(info $$FAMILY [${FAMILY}]) +$(info $$MAKE_FLAGS [${MAKE_FLAGS}]) -ifeq ($(FAMILY),) - FAMILY=gd32f20x -endif - -$(info $$FAMILY [${FAMILY}]) +DEFINES=NDEBUG -ifeq ($(findstring gd32f10x,$(FAMILY)), gd32f10x) - EXTRA_SRCDIR=gd32f10x/CMSIS/GD/GD32F10x/Source - EXTRA_SRCDIR+=gd32f10x/GD32F10x_standard_peripheral/Source -endif +EXTRA_SRCDIR= -ifeq ($(findstring gd32f20x,$(FAMILY)), gd32f20x) - EXTRA_SRCDIR=gd32f20x/CMSIS/GD/GD32F20x/Source - EXTRA_SRCDIR+=gd32f20x/GD32F20x_standard_peripheral/Source - ifeq ($(findstring ENABLE_USB_HOST,$(MAKE_FLAGS)), ENABLE_USB_HOST) - EXTRA_SRCDIR+=gd32f20x/GD32F20x_usbfs_library/host/core/Source - - EXTRA_C_SOURCE_FILES=gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_core.c - EXTRA_C_SOURCE_FILES+=gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_host.c - EXTRA_C_SOURCE_FILES+=gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usbh_int.c - - EXTRA_INCLUDES+=gd32f20x/GD32F20x_usbfs_library/driver/Include - EXTRA_INCLUDES+=gd32f20x/GD32F20x_usbfs_library/host/core/Include - EXTRA_INCLUDES+=gd32f20x/GD32F20x_usbfs_library/ustd/common - - ifeq ($(findstring CONFIG_USB_HOST_MSC,$(MAKE_FLAGS)), CONFIG_USB_HOST_MSC) - EXTRA_SRCDIR+=gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source - - EXTRA_INCLUDES+=gd32f20x/GD32F20x_usbfs_library/host/class/msc/Include - EXTRA_INCLUDES+=gd32f20x/GD32F20x_usbfs_library/ustd/class/msc - - EXTRA_INCLUDES+=../lib-hal/ff12c - endif - - endif -endif +ifneq ($(MAKE_FLAGS),) + ifeq ($(findstring CONFIG_HAL_USE_SYSTICK,$(MAKE_FLAGS)), CONFIG_HAL_USE_SYSTICK) + EXTRA_SRCDIR+=src/systick + endif -ifeq ($(findstring gd32f30x,$(FAMILY)), gd32f30x) - EXTRA_SRCDIR=gd32f30x/CMSIS/GD/GD32F30x/Source - EXTRA_SRCDIR+=gd32f30x/GD32F30x_standard_peripheral/Source -endif + ifeq ($(findstring gd32f10x,$(FAMILY)), gd32f10x) + EXTRA_SRCDIR+=gd32f10x/CMSIS/GD/GD32F10x/Source + EXTRA_SRCDIR+=gd32f10x/GD32F10x_standard_peripheral/Source + EXTRA_SRCDIR+=src/f + endif -ifeq ($(findstring gd32f4xx,$(FAMILY)), gd32f4xx) - EXTRA_SRCDIR=gd32f4xx/CMSIS/GD/GD32F4xx/Source - EXTRA_SRCDIR+=gd32f4xx/GD32F4xx_standard_peripheral/Source - ifeq ($(findstring ENABLE_USB_HOST,$(MAKE_FLAGS)), ENABLE_USB_HOST) - EXTRA_SRCDIR+=gd32f4xx/GD32F4xx_usb_library/host/core/Source + ifeq ($(findstring gd32f20x,$(FAMILY)), gd32f20x) + EXTRA_SRCDIR+=gd32f20x/CMSIS/GD/GD32F20x/Source + EXTRA_SRCDIR+=gd32f20x/GD32F20x_standard_peripheral/Source - EXTRA_C_SOURCE_FILES=gd32f4xx/GD32F4xx_usb_library/driver/Source/drv_usb_core.c - EXTRA_C_SOURCE_FILES+=gd32f4xx/GD32F4xx_usb_library/driver/Source/drv_usb_host.c - EXTRA_C_SOURCE_FILES+=gd32f4xx/GD32F4xx_usb_library/driver/Source/drv_usbh_int.c - - EXTRA_INCLUDES+=gd32f4xx/GD32F4xx_usb_library/driver/Include - EXTRA_INCLUDES+=gd32f4xx/GD32F4xx_usb_library/host/core/Include - EXTRA_INCLUDES+=gd32f4xx/GD32F4xx_usb_library/ustd/common - - ifeq ($(findstring CONFIG_USB_HOST_MSC,$(MAKE_FLAGS)), CONFIG_USB_HOST_MSC) - EXTRA_SRCDIR+=gd32f4xx/GD32F4xx_usb_library/host/class/msc/Source - - EXTRA_INCLUDES+=gd32f4xx/GD32F4xx_usb_library/host/class/msc/Include - EXTRA_INCLUDES+=gd32f4xx/GD32F4xx_usb_library/ustd/class/msc - - EXTRA_INCLUDES+=../lib-hal/ff12c - endif - - endif -endif + ifeq ($(findstring ENABLE_USB_HOST,$(MAKE_FLAGS)), ENABLE_USB_HOST) + EXTRA_SRCDIR+=device/usb/f + EXTRA_SRCDIR+=gd32f20x/GD32F20x_usbfs_library/host/core/Source + EXTRA_C_SOURCE_FILES=gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_core.c + EXTRA_C_SOURCE_FILES+=gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_host.c + EXTRA_C_SOURCE_FILES+=gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usbh_int.c + + ifeq ($(findstring CONFIG_USB_HOST_MSC,$(MAKE_FLAGS)), CONFIG_USB_HOST_MSC) + EXTRA_SRCDIR+=gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source + endif + endif + EXTRA_SRCDIR+=src/f + endif -$(info $$MAKE_FLAGS [${MAKE_FLAGS}]) + ifeq ($(findstring gd32f30x,$(FAMILY)), gd32f30x) + EXTRA_SRCDIR+=gd32f30x/CMSIS/GD/GD32F30x/Source + EXTRA_SRCDIR+=gd32f30x/GD32F30x_standard_peripheral/Source + EXTRA_SRCDIR+=src/f + endif + + ifeq ($(findstring gd32f4xx,$(FAMILY)), gd32f4xx) + EXTRA_SRCDIR+=gd32f4xx/CMSIS/GD/GD32F4xx/Source + EXTRA_SRCDIR+=gd32f4xx/GD32F4xx_standard_peripheral/Source + + ifeq ($(findstring ENABLE_USB_HOST,$(MAKE_FLAGS)), ENABLE_USB_HOST) + EXTRA_SRCDIR+=device/usb/f + EXTRA_SRCDIR+=gd32f4xx/GD32F4xx_usb_library/host/core/Source + EXTRA_C_SOURCE_FILES=gd32f4xx/GD32F4xx_usb_library/driver/Source/drv_usb_core.c + EXTRA_C_SOURCE_FILES+=gd32f4xx/GD32F4xx_usb_library/driver/Source/drv_usb_host.c + EXTRA_C_SOURCE_FILES+=gd32f4xx/GD32F4xx_usb_library/driver/Source/drv_usbh_int.c + + ifeq ($(findstring CONFIG_USB_HOST_MSC,$(MAKE_FLAGS)), CONFIG_USB_HOST_MSC) + EXTRA_SRCDIR+=gd32f4xx/GD32F4xx_usb_library/host/class/msc/Source + endif + endif + EXTRA_SRCDIR+=src/f + endif + + ifeq ($(findstring gd32h7xx,$(FAMILY)), gd32h7xx) + EXTRA_SRCDIR+=gd32h7xx/CMSIS/GD/GD32H7xx/Source + EXTRA_SRCDIR+=gd32h7xx/GD32H7xx_standard_peripheral/Source + + ifeq ($(findstring ENABLE_USB_HOST,$(MAKE_FLAGS)), ENABLE_USB_HOST) + EXTRA_SRCDIR+=device/usb/h + EXTRA_SRCDIR+=gd32h7xx/GD32H7xx_usbhs_library/host/core/Source + EXTRA_C_SOURCE_FILES=gd32h7xx/GD32H7xx_usbhs_library/driver/Source/drv_usb_core.c + EXTRA_C_SOURCE_FILES+=gd32h7xx/GD32H7xx_usbhs_library/driver/Source/drv_usb_host.c + EXTRA_C_SOURCE_FILES+=gd32h7xx/GD32H7xx_usbhs_library/driver/Source/drv_usbh_int.c + + ifeq ($(findstring CONFIG_USB_HOST_MSC,$(MAKE_FLAGS)), CONFIG_USB_HOST_MSC) + EXTRA_SRCDIR+=gd32h7xx/GD32H7xx_usbhs_library/host/class/msc/Source + endif + endif + EXTRA_SRCDIR+=src/h + endif -ifneq ($(MAKE_FLAGS),) ifeq ($(findstring NO_EMAC,$(MAKE_FLAGS)), NO_EMAC) else - EXTRA_SRCDIR+=device/emac + ifeq ($(findstring CONFIG_ENET_ENABLE_PTP,$(MAKE_FLAGS)), CONFIG_ENET_ENABLE_PTP) + EXTRA_SRCDIR+=src/ptp + endif endif ifeq ($(findstring CONFIG_USE_SOFTUART0,$(MAKE_FLAGS)), CONFIG_USE_SOFTUART0) @@ -85,19 +93,60 @@ ifneq ($(MAKE_FLAGS),) endif endif - ifeq ($(findstring ENABLE_PHY_SWITCH,$(MAKE_FLAGS)), ENABLE_PHY_SWITCH) - EXTRA_SRCDIR+=device/emac/dsa - endif - ifeq ($(findstring ENABLE_USB_HOST,$(MAKE_FLAGS)), ENABLE_USB_HOST) EXTRA_SRCDIR+=device/usb - endif + endif + + ifeq ($(findstring USE_FREE_RTOS,$(MAKE_FLAGS)), USE_FREE_RTOS) + EXTRA_SRCDIR+=FreeRTOS/FreeRTOS-Kernel + EXTRA_SRCDIR+=FreeRTOS/FreeRTOS-Kernel/portable/Common + ifeq ($(findstring ARM_CM3,$(MAKE_FLAGS)), ARM_CM3) +# EXTRA_SRCDIR+=FreeRTOS/FreeRTOS-Kernel/portable/GCC/ARM_CM3 + endif + ifeq ($(findstring ARM_CM3,$(MAKE_FLAGS)), ARM_CM4F) + # EXTRA_SRCDIR+=FreeRTOS/FreeRTOS-Kernel/portable/GCC/ARM_CM4F + endif + ifeq ($(findstring ARM_CM3,$(MAKE_FLAGS)), ARM_CM7) + # EXTRA_SRCDIR+=FreeRTOS/FreeRTOS-Kernel/portable/GCC/ARM_CM7/r0p1 + endif + endif else - EXTRA_SRCDIR+=device/emac device/emac/dsa + ifeq ($(FAMILY),) + ifneq (, $(shell test -d '../lib-gd32/gd32f10x' && echo -n yes)) + FAMILY=gd32f10x + EXTRA_SRCDIR+=src/f + endif + ifneq (, $(shell test -d '../lib-gd32/gd32f20x' && echo -n yes)) + FAMILY=gd32f20x + HAVE_SOFTUART=1 + # EXTRA_SRCDIR+=src/f + endif + ifneq (, $(shell test -d '../lib-gd32/gd32f30x' && echo -n yes)) + FAMILY=gd32f30x +# EXTRA_SRCDIR+=src/f + endif + ifneq (, $(shell test -d '../lib-gd32/gd32f4xx' && echo -n yes)) + FAMILY=gd32f4xx + HAVE_SOFTUART=1 +# EXTRA_SRCDIR+=src/f + endif + ifneq (, $(shell test -d '../lib-gd32/gd32h7xx' && echo -n yes)) + FAMILY=gd32h7xx + HAVE_SOFTUART=1 +# EXTRA_SRCDIR+=src/h + endif + endif + + EXTRA_SRCDIR+=device/emac EXTRA_SRCDIR+=device/usb - EXTRA_SRCDIR+=src/uart0 src/softuart0 + EXTRA_SRCDIR+=src/uart0 + ifdef HAVE_SOFTUART + EXTRA_SRCDIR+=src/softuart0 + endif DEFINES=ENABLE_USB_HOST CONFIG_USB_HOST_MSC endif +$(info $$FAMILY [${FAMILY}]) + include ../firmware-template-gd32/lib/Rules.mk \ No newline at end of file diff --git a/lib-gd32/device/usb/f/usb_conf.h b/lib-gd32/device/usb/f/usb_conf.h new file mode 100644 index 00000000..996d9704 --- /dev/null +++ b/lib-gd32/device/usb/f/usb_conf.h @@ -0,0 +1,101 @@ +/** + * usb_conf.h + * + */ +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef F_USB_CONF_H_ +#define F_USB_CONF_H_ + +#include + +#include "gd32.h" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wattributes" + +#if !defined (USE_USB_FS) +# define USE_USB_FS +#endif +#define USB_FS_CORE + +/******************************************************************************* + * FIFO Size Configuration in Host mode + * + * (i) Receive data FIFO size = (Largest Packet Size / 4) + 1 or + * 2x (Largest Packet Size / 4) + 1, If a + * high-bandwidth channel or multiple isochronous + * channels are enabled. + * + * (ii) For the host non periodic Transmit FIFO is the largest maximum packet size + * for all supported non periodic OUT channels. Typically, a space + * corresponding to two Largest Packet Size is recommended. + * + * (iii) The minimum amount of RAM required for Host periodic Transmit FIFO is + * the largest maximum packet size for all supported periodic OUT channels. + * If there is at least one High Bandwidth Isochronous OUT endpoint, + * then the space must be at least two times the maximum packet size for + * that channel. +*******************************************************************************/ + +#define USB_RX_FIFO_FS_SIZE 128 +#define USB_HTX_NPFIFO_FS_SIZE 96 +#define USB_HTX_PFIFO_FS_SIZE 96 + +#define USB_SOF_OUTPUT 0 +#define USB_LOW_POWER 0 + +#if defined (USB_FS_CORE) +# define USBFS_SOF_OUTPUT 0 +# define USBFS_LOW_POWER 0 +#endif + +#define USE_HOST_MODE + +#ifndef USB_FS_CORE + #ifndef USB_HS_CORE + #error "USB_HS_CORE or USB_FS_CORE should be defined" + #endif +#endif + +#ifndef USE_DEVICE_MODE + #ifndef USE_HOST_MODE + #error "USE_DEVICE_MODE or USE_HOST_MODE should be defined" + #endif +#endif + +#ifndef USE_USB_HS + #ifndef USE_USB_FS + #error "USE_USB_HS or USE_USB_FS should be defined" + #endif +#endif + +/* __packed keyword used to decrease the data type alignment to 1-byte */ +#if defined ( __GNUC__ ) /* GNU Compiler */ + #ifndef __packed + #define __packed __attribute__ ((__packed__)) + #endif +#elif defined (__TASKING__) /* TASKING Compiler */ + #define __packed __unaligned +#endif /* __GNUC__ */ + +#endif /* F_USB_CONF_H_ */ diff --git a/lib-gd32/device/usb/usb.cpp b/lib-gd32/device/usb/usb.cpp new file mode 100644 index 00000000..5faa51a4 --- /dev/null +++ b/lib-gd32/device/usb/usb.cpp @@ -0,0 +1,35 @@ +/** + * usb.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "gd32.h" + +extern "C" { +void usb_udelay(uint32_t nMicros) { + udelay(nMicros); +} +void usb_mdelay(uint32_t nMillis) { + udelay(nMillis * 1000U); +} +} diff --git a/lib-gd32/device/usb/usb_conf.h b/lib-gd32/device/usb/usb_conf.h new file mode 100644 index 00000000..0dcf2980 --- /dev/null +++ b/lib-gd32/device/usb/usb_conf.h @@ -0,0 +1,37 @@ +/** + * usb_conf.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef USB_CONF_H_ +#define USB_CONF_H_ + +#include "gd32.h" + +#if defined (GD32H7XX) +# include "h/usb_conf.h" +#else +# include "f/usb_conf.h" +#endif + +#endif /* USB_CONF_H_ */ diff --git a/gd32_emac_e131_dmx_multi/include/display_timeout.h b/lib-gd32/device/usb/usb_vbus.cpp similarity index 72% rename from gd32_emac_e131_dmx_multi/include/display_timeout.h rename to lib-gd32/device/usb/usb_vbus.cpp index a8556629..fc92386e 100644 --- a/gd32_emac_e131_dmx_multi/include/display_timeout.h +++ b/lib-gd32/device/usb/usb_vbus.cpp @@ -1,8 +1,8 @@ /** - * @file display_timeout.h + * usb_vbus.cpp * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,23 +23,20 @@ * THE SOFTWARE. */ -#ifndef DISPLAY_TIMEOUT_H_ -#define DISPLAY_TIMEOUT_H_ +#include +#include #include "gd32.h" -namespace display { -namespace timeout { - -void gpio_init() { - gpio_fsel(KEY2_GPIOx, KEY2_PINx, GPIO_FSEL_INPUT); +extern "C" { +void usb_vbus_drive (uint8_t state) { + printf("usb_vbus_drive: %u\n", state); +#if defined(USB_HOST_VBUS_GPIOx) + if (0U == state) { + gpio_bit_reset(USB_HOST_VBUS_GPIOx, USB_HOST_VBUS_GPIO_PINx); + } else { + gpio_bit_set(USB_HOST_VBUS_GPIOx, USB_HOST_VBUS_GPIO_PINx); + } +#endif } - -bool gpio_renew() { - return (GPIO_ISTAT(KEY2_GPIOx) & KEY2_PINx) == 0; } - -} // namespace timeout -} // namespace display - -#endif /* DISPLAY_TIMEOUT_H_ */ diff --git a/lib-network/src/emac/gd32/net.c b/lib-gd32/device/usb/usbh_conf.h similarity index 67% rename from lib-network/src/emac/gd32/net.c rename to lib-gd32/device/usb/usbh_conf.h index 5c180de9..8683ce0c 100644 --- a/lib-network/src/emac/gd32/net.c +++ b/lib-gd32/device/usb/usbh_conf.h @@ -1,8 +1,8 @@ /** - * net.c + * usbh_conf.h * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,27 +23,22 @@ * THE SOFTWARE. */ +#ifndef USBH_CONF_H_ +#define USBH_CONF_H_ + #include #include "gd32.h" -extern enet_descriptors_struct *dma_current_rxdesc; - -int emac_eth_recv(uint8_t **packet) { - const uint32_t size = enet_rxframe_size_get(); - - if (size > 0) { - *packet = (uint8_t *) (enet_desc_information_get(dma_current_rxdesc, RXDESC_BUFFER_1_ADDR)); - return size; - } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" - return -1; -} +#define USBH_MAX_EP_NUM 2 +#define USBH_MAX_INTERFACES_NUM 2 +#define USBH_MAX_ALT_SETTING 2 +#define USBH_MAX_SUPPORTED_CLASS 2 -void emac_free_pkt(void) { - ENET_NOCOPY_FRAME_RECEIVE(); -} +#define USBH_DATA_BUF_MAX_LEN 0x200 +#define USBH_CFGSET_MAX_LEN 0x200 -void emac_eth_send(void *packet, int len) { - enet_frame_transmit((uint8_t *) packet, len); -} +#endif /* USBH_CONF_H_ */ diff --git a/lib-gd32/gd32f20x/CMSIS/GD/GD32F20x/Include/gd32f20x.h b/lib-gd32/gd32f20x/CMSIS/GD/GD32F20x/Include/gd32f20x.h index 1df45888..cfc73ab7 100644 --- a/lib-gd32/gd32f20x/CMSIS/GD/GD32F20x/Include/gd32f20x.h +++ b/lib-gd32/gd32f20x/CMSIS/GD/GD32F20x/Include/gd32f20x.h @@ -2,14 +2,11 @@ \file gd32f20x.h \brief general definitions for GD32F20x - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -55,42 +52,37 @@ OF SUCH DAMAGE. #error "Please select first the target gd32f20x device used in your application (in gd32f20x.h file)" #endif /* GD32F20X */ -/* enum definitions */ -typedef enum {DISABLE = 0, ENABLE = !DISABLE} EventStatus, ControlStatus; -typedef enum {RESET = 0, SET = !RESET} FlagStatus; -typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrStatus; - /* define value of high speed crystal oscillator (HXTAL) in Hz */ #if !defined HXTAL_VALUE #ifdef GD32F20X_CL #define HXTAL_VALUE ((uint32_t)25000000) /*!< value of the external oscillator in Hz */ +#endif /* GD32F20X_CL */ #endif /* HXTAL_VALUE */ -#endif /* high speed crystal oscillator value */ /* define startup timeout value of high speed crystal oscillator (HXTAL) */ #if !defined (HXTAL_STARTUP_TIMEOUT) #define HXTAL_STARTUP_TIMEOUT ((uint16_t)0xFFFF) -#endif /* high speed crystal oscillator startup timeout */ +#endif /*HXTAL_STARTUP_TIMEOUT */ /* define value of internal 8MHz RC oscillator (IRC8M) in Hz */ #if !defined (IRC8M_VALUE) #define IRC8M_VALUE ((uint32_t)8000000) -#endif /* internal 8MHz RC oscillator value */ +#endif /* IRC8M_VALUE */ /* define startup timeout value of internal 8MHz RC oscillator (IRC8M) */ #if !defined (IRC8M_STARTUP_TIMEOUT) #define IRC8M_STARTUP_TIMEOUT ((uint16_t)0x0500) -#endif /* internal 8MHz RC oscillator startup timeout */ +#endif /* IRC8M_STARTUP_TIMEOUT */ /* define value of internal 40KHz RC oscillator(IRC40K) in Hz */ #if !defined (IRC40K_VALUE) #define IRC40K_VALUE ((uint32_t)40000) -#endif /* internal 40KHz RC oscillator value */ +#endif /* IRC40K_VALUE */ /* define value of low speed crystal oscillator (LXTAL)in Hz */ #if !defined (LXTAL_VALUE) #define LXTAL_VALUE ((uint32_t)32768) -#endif /* low speed crystal oscillator value */ +#endif /* LXTAL_VALUE */ /* GD32F20x firmware library version number V2.0 */ #define __GD32F20x_STDPERIPH_VERSION_MAIN (0x01) /*!< [31:24] main version */ @@ -105,13 +97,13 @@ typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrStatus; /* configuration of the Cortex-M3 processor and core peripherals */ #define __MPU_PRESENT 0 /*!< GD32 devices does not provide an MPU */ #define __NVIC_PRIO_BITS 4 /*!< GD32F20X uses 4 bits for the Priority levels */ -#define __VENDOR_SYSTICKCONFIG 0 /*!< set to 1 if different systick config is used */ +#define __Vendor_SysTickConfig 0 /*!< set to 1 if different systick config is used */ /* define interrupt number */ typedef enum IRQn { /* Cortex-M3 processor exceptions numbers */ - NonMaskableInt_IRQn = -14, /*!< 2 non maskable interrupt */ + NonMaskableInt_IRQn = -14, /*!< 2 non mask-able interrupt */ MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 memory management interrupt */ BusFault_IRQn = -11, /*!< 5 Cortex-M3 bus fault interrupt */ UsageFault_IRQn = -10, /*!< 6 Cortex-M3 usage fault interrupt */ @@ -119,7 +111,7 @@ typedef enum IRQn DebugMonitor_IRQn = -4, /*!< 12 Cortex-M3 debug monitor interrupt */ PendSV_IRQn = -2, /*!< 14 Cortex-M3 pend SV interrupt */ SysTick_IRQn = -1, /*!< 15 Cortex-M3 system tick interrupt */ - /* interruput numbers */ + /* interrupt numbers */ WWDGT_IRQn = 0, /*!< WWDGT interrupt */ LVD_IRQn = 1, /*!< LVD from EXTI line interrupt */ TAMPER_IRQn = 2, /*!< tamper interrupt */ @@ -147,7 +139,7 @@ typedef enum IRQn TIMER0_BRK_TIMER8_IRQn = 24, /*!< TIMER0 break interrupt and TIMER8 global interrupt */ TIMER0_UP_TIMER9_IRQn = 25, /*!< TIMER0 update Interrupt and TIMER9 global interrupt */ TIMER0_TRG_CMT_TIMER10_IRQn = 26, /*!< TIMER0 trigger and commutation interrupt and TIMER10 global interrupt */ - TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupt */ + TIMER0_Channel_IRQn = 27, /*!< TIMER0 channel capture compare interrupt */ TIMER1_IRQn = 28, /*!< TIMER1 global interrupt */ TIMER2_IRQn = 29, /*!< TIMER2 global interrupt */ TIMER3_IRQn = 30, /*!< TIMER3 global interrupt */ @@ -166,7 +158,7 @@ typedef enum IRQn TIMER7_BRK_TIMER11_IRQn = 43, /*!< TIMER7 break interrupt and TIMER11 global interrupt */ TIMER7_UP_TIMER12_IRQn = 44, /*!< TIMER7 update interrupt and TIMER12 global interrupt */ TIMER7_TRG_CMT_TIMER13_IRQn = 45, /*!< TIMER7 trigger and commutation interrupt and TIMER13 global interrupt */ - TIMER7_Channel_IRQn = 46, /*!< TIMER7 Channel Capture Compare Interrupt */ + TIMER7_Channel_IRQn = 46, /*!< TIMER7 Channel Capture Compare Interrupt */ ADC2_IRQn = 47, /*!< ADC2 global interrupt */ EXMC_IRQn = 48, /*!< EXMC global interrupt */ SDIO_IRQn = 49, /*!< SDIO global interrupt */ @@ -187,19 +179,19 @@ typedef enum IRQn CAN1_RX0_IRQn = 64, /*!< CAN1 RX0 interrupt */ CAN1_RX1_IRQn = 65, /*!< CAN1 RX1 interrupt */ CAN1_EWMC_IRQn = 66, /*!< CAN1 EWMC interrupt */ - USBFS_IRQn = 67, /*!< USBFS global interrupt */ - DMA1_Channel5_IRQn = 69, /*!< DMA1 Channel 5 global interrupt */ - DMA1_Channel6_IRQn = 70, /*!< DMA1 Channel 6 global interrupt */ - USART5_IRQn = 71, /*!< USART5 global interrupt */ - I2C2_EV_IRQn = 72, /*!< I2C2 event interrupt */ - I2C2_ER_IRQn = 73, /*!< I2C2 error interrupt */ - DCI_IRQn = 78, /*!< DCI global interrupt */ - CAU_IRQn = 79, /*!< CAU global interrupt */ - HAU_TRNG_IRQn = 80, /*!< HAU or TRNG global interrupt */ - UART6_IRQn = 82, /*!< UART6 global interrupt */ - UART7_IRQn = 83, /*!< UART7 global interrupt */ - TLI_IRQn = 88, /*!< TLI global interrupt */ - TLI_ER_IRQn = 89 /*!< TLI global error interrupt */ + USBFS_IRQn = 67, /*!< USBFS global interrupt */ + DMA1_Channel5_IRQn = 69, /*!< DMA1 Channel 5 global interrupt */ + DMA1_Channel6_IRQn = 70, /*!< DMA1 Channel 6 global interrupt */ + USART5_IRQn = 71, /*!< USART5 global interrupt */ + I2C2_EV_IRQn = 72, /*!< I2C2 event interrupt */ + I2C2_ER_IRQn = 73, /*!< I2C2 error interrupt */ + DCI_IRQn = 78, /*!< DCI global interrupt */ + CAU_IRQn = 79, /*!< CAU global interrupt */ + HAU_TRNG_IRQn = 80, /*!< HAU or TRNG global interrupt */ + UART6_IRQn = 82, /*!< UART6 global interrupt */ + UART7_IRQn = 83, /*!< UART7 global interrupt */ + TLI_IRQn = 88, /*!< TLI global interrupt */ + TLI_ER_IRQn = 89 /*!< TLI global error interrupt */ } IRQn_Type; /* includes */ @@ -207,6 +199,12 @@ typedef enum IRQn #include "system_gd32f20x.h" #include +/* enum definitions */ +typedef enum {DISABLE = 0, ENABLE = !DISABLE} EventStatus, ControlStatus; +// typedef enum {FALSE = 0, TRUE = !FALSE} bool; /** AvV **/ +typedef enum {RESET = 0, SET = !RESET} FlagStatus; +typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrStatus; + /* bit operations */ #define REG32(addr) (*(volatile uint32_t *)(uint32_t)(addr)) #define REG16(addr) (*(volatile uint16_t *)(uint32_t)(addr)) @@ -265,10 +263,10 @@ typedef enum IRQn #define HAU_BASE (AHB2_BUS_BASE + 0x00060400U) /*!< HAU base address */ #define TRNG_BASE (AHB2_BUS_BASE + 0x00060800U) /*!< TRNG base address */ -/* define marco USE_STDPERIPH_DRIVER */ +/* define macro USE_STDPERIPH_DRIVER */ #if !defined USE_STDPERIPH_DRIVER #define USE_STDPERIPH_DRIVER -#endif +#endif /* USE_STDPERIPH_DRIVER */ #ifdef USE_STDPERIPH_DRIVER #include "gd32f20x_libopt.h" #endif /* USE_STDPERIPH_DRIVER */ @@ -276,4 +274,5 @@ typedef enum IRQn #ifdef __cplusplus } #endif -#endif + +#endif /* GD32F20X_H */ diff --git a/lib-gd32/gd32f20x/CMSIS/GD/GD32F20x/Source/system_gd32f20x.c b/lib-gd32/gd32f20x/CMSIS/GD/GD32F20x/Source/system_gd32f20x.c index 37004d45..39beb930 100644 --- a/lib-gd32/gd32f20x/CMSIS/GD/GD32F20x/Source/system_gd32f20x.c +++ b/lib-gd32/gd32f20x/CMSIS/GD/GD32F20x/Source/system_gd32f20x.c @@ -59,6 +59,17 @@ //#define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000) #define __SYSTEM_CLOCK_120M_PLL_HXTAL (uint32_t)(120000000) +#define RCU_MODIFY(__delay) do{ \ + volatile uint32_t i; \ + if(0 != __delay){ \ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV2; \ + for(i=0; i<__delay; i++){ \ + } \ + RCU_CFG0 |= RCU_AHB_CKSYS_DIV4; \ + for(i=0; i<__delay; i++){ \ + } \ + } \ + }while(0) #define SEL_IRC8M 0x00U #define SEL_HXTAL 0x01U @@ -114,27 +125,33 @@ static void system_clock_120m_hxtal(void); static void system_clock_config(void); /*! - \brief setup the microcontroller system, initialize the system + \brief setup the micro-controller system, initialize the system \param[in] none \param[out] none \retval none */ -void SystemInit (void) +void SystemInit(void) { /* reset the RCC clock configuration to the default reset state */ /* enable IRC8M */ RCU_CTL |= RCU_CTL_IRC8MEN; + while(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ + } + RCU_MODIFY(0x50); + RCU_CFG0 &= ~RCU_CFG0_SCS; + /* reset HXTALEN, CKMEN, PLLEN bits */ + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); /* reset SCS, AHBPSC, APB1PSC, APB2PSC, ADCPSC, CKOUT0SEL bits */ RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | RCU_CFG0_ADCPSC | RCU_CFG0_ADCPSC_2 | RCU_CFG0_CKOUT0SEL); /* reset HXTALEN, CKMEN, PLLEN bits */ - RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN ); + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); /* Reset HXTALBPS bit */ RCU_CTL &= ~(RCU_CTL_HXTALBPS); - + /* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */ RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4); @@ -147,20 +164,20 @@ void SystemInit (void) /* reset INT register */ RCU_INT = 0x00FF0000U; - + /* reset CFG2 register */ RCU_CFG2 = 0x00000000U; - + /* reset PLLTCTL register */ - RCU_PLLTCTL &= (~RCU_PLLTCTL_PLLTEN); - + RCU_PLLTCTL &= (~RCU_PLLTCTL_PLLTEN); + /* reset PLLTINT register */ RCU_PLLTINT = 0x00400000U; - /* Reset PLLTCFG register */ + /* reset PLLTCFG register */ RCU_PLLTCFG = 0x20003010U; - /* Configure the System clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */ + /* configure the system clock source, PLL multiplier, AHB/APBx prescalers and flash settings */ system_clock_config(); } /*! @@ -214,36 +231,35 @@ static void system_clock_8m_irc8m(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable IRC8M */ RCU_CTL |= RCU_CTL_IRC8MEN; - + /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ - do{ + do { timeout++; stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); - } - while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); - + } while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - while(1){ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)) { + while(1) { } } - + /* AHB = SYSCLK */ RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; /* APB2 = AHB/1 */ RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; /* APB1 = AHB/2 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - + /* select IRC8M as system clock */ RCU_CFG0 &= ~RCU_CFG0_SCS; RCU_CFG0 |= RCU_CKSYSSRC_IRC8M; - + /* wait until IRC8M is selected as system clock */ - while(0U != (RCU_CFG0 & RCU_SCSS_IRC8M)){ + while(RCU_SCSS_IRC8M != (RCU_CFG0 & RCU_CFG0_SCSS)) { } } @@ -258,21 +274,20 @@ static void system_clock_48m_irc8m(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable IRC8M */ RCU_CTL |= RCU_CTL_IRC8MEN; /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ - do{ + do { timeout++; stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); - } - while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + } while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - while(1){ - } + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)) { + while(1) { + } } /* IRC8M is stable */ @@ -284,14 +299,14 @@ static void system_clock_48m_irc8m(void) RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; /* CK_PLL = (CK_IRC8M/2) * 12 = 48 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL); RCU_CFG0 |= (RCU_PLLSRC_IRC8M_DIV2 | RCU_PLL_MUL12); /* enable PLL */ RCU_CTL |= RCU_CTL_PLLEN; /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) { } /* select PLL as system clock */ @@ -299,7 +314,7 @@ static void system_clock_48m_irc8m(void) RCU_CFG0 |= RCU_CKSYSSRC_PLL; /* wait until PLL is selected as system clock */ - while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)) { } } @@ -314,19 +329,19 @@ static void system_clock_72m_irc8m(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable IRC8M */ RCU_CTL |= RCU_CTL_IRC8MEN; /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ - do{ + do { timeout++; stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); - }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + } while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - while(1){ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)) { + while(1) { } } @@ -339,14 +354,14 @@ static void system_clock_72m_irc8m(void) RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; /* CK_PLL = (CK_IRC8M/2) * 18 = 72 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL); RCU_CFG0 |= (RCU_PLLSRC_IRC8M_DIV2 | RCU_PLL_MUL18); /* enable PLL */ RCU_CTL |= RCU_CTL_PLLEN; /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) { } /* select PLL as system clock */ @@ -354,7 +369,7 @@ static void system_clock_72m_irc8m(void) RCU_CFG0 |= RCU_CKSYSSRC_PLL; /* wait until PLL is selected as system clock */ - while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)) { } } @@ -369,19 +384,19 @@ static void system_clock_108m_irc8m(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable IRC8M */ RCU_CTL |= RCU_CTL_IRC8MEN; /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ - do{ + do { timeout++; stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); - }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + } while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - while(1){ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)) { + while(1) { } } @@ -394,14 +409,14 @@ static void system_clock_108m_irc8m(void) RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; /* CK_PLL = (CK_IRC8M/2) * 27 = 108 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL); RCU_CFG0 |= (RCU_PLLSRC_IRC8M_DIV2 | RCU_PLL_MUL27); /* enable PLL */ RCU_CTL |= RCU_CTL_PLLEN; /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) { } /* select PLL as system clock */ @@ -409,7 +424,7 @@ static void system_clock_108m_irc8m(void) RCU_CFG0 |= RCU_CKSYSSRC_PLL; /* wait until PLL is selected as system clock */ - while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)) { } } @@ -424,19 +439,19 @@ static void system_clock_120m_irc8m(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable IRC8M */ RCU_CTL |= RCU_CTL_IRC8MEN; /* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */ - do{ + do { timeout++; stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB); - }while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); + } while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout)); /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){ - while(1){ + if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)) { + while(1) { } } @@ -449,14 +464,14 @@ static void system_clock_120m_irc8m(void) RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; /* CK_PLL = (CK_IRC8M/2) * 30 = 120 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL); RCU_CFG0 |= (RCU_PLLSRC_IRC8M_DIV2 | RCU_PLL_MUL30); - + /* enable PLL */ RCU_CTL |= RCU_CTL_PLLEN; /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) { } /* select PLL as system clock */ @@ -464,7 +479,7 @@ static void system_clock_120m_irc8m(void) RCU_CFG0 |= RCU_CKSYSSRC_PLL; /* wait until PLL is selected as system clock */ - while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)) { } } @@ -479,41 +494,41 @@ static void system_clock_hxtal(void) { uint32_t timeout = 0U; uint32_t stab_flag = 0U; - + /* enable HXTAL */ RCU_CTL |= RCU_CTL_HXTALEN; - + /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ + do { timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); - + } while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while(1) { } } - + /* AHB = SYSCLK */ RCU_CFG0 |= RCU_AHB_CKSYS_DIV1; /* APB2 = AHB/1 */ RCU_CFG0 |= RCU_APB2_CKAHB_DIV1; /* APB1 = AHB/2 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - + /* select HXTAL as system clock */ RCU_CFG0 &= ~RCU_CFG0_SCS; RCU_CFG0 |= RCU_CKSYSSRC_HXTAL; - + /* wait until HXTAL is selected as system clock */ - while(0 == (RCU_CFG0 & RCU_SCSS_HXTAL)){ + while(RCU_SCSS_HXTAL != (RCU_CFG0 & RCU_CFG0_SCSS)) { } } #elif defined (__SYSTEM_CLOCK_24M_PLL_HXTAL) /*! - \brief configure the system clock to 24M by PLL which selects HXTAL(8M) as its clock source + \brief configure the system clock to 24M by PLL which selects HXTAL(25M) as its clock source \param[in] none \param[out] none \retval none @@ -527,14 +542,14 @@ static void system_clock_24m_hxtal(void) RCU_CTL |= RCU_CTL_HXTALEN; /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ + do { timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + } while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while(1) { } } @@ -546,25 +561,25 @@ static void system_clock_24m_hxtal(void) /* APB1 = AHB/2 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - /* CK_PLL = (CK_PREDIV0) * 6 = 24 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + /* CK_PLL = (CK_PREDIV0) * 6 = 24 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL); RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL6); - /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); - + /* enable PLL1 */ RCU_CTL |= RCU_CTL_PLL1EN; /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0) { } /* enable PLL */ RCU_CTL |= RCU_CTL_PLLEN; /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) { } /* select PLL as system clock */ @@ -572,14 +587,14 @@ static void system_clock_24m_hxtal(void) RCU_CFG0 |= RCU_CKSYSSRC_PLL; /* wait until PLL is selected as system clock */ - while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)) { } } #elif defined (__SYSTEM_CLOCK_36M_PLL_HXTAL) /*! - \brief configure the system clock to 36M by PLL which selects HXTAL(8M) as its clock source + \brief configure the system clock to 36M by PLL which selects HXTAL(25M) as its clock source \param[in] none \param[out] none \retval none @@ -593,14 +608,14 @@ static void system_clock_36m_hxtal(void) RCU_CTL |= RCU_CTL_HXTALEN; /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ + do { timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + } while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while(1) { } } @@ -612,25 +627,25 @@ static void system_clock_36m_hxtal(void) /* APB1 = AHB/2 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - /* CK_PLL = (CK_PREDIV0) * 9 = 36 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + /* CK_PLL = (CK_PREDIV0) * 9 = 36 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL); RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9); - /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ + /* CK_PREDIV0 = (CK_HXTAL)/5 *8 /10 = 4 MHz */ RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV10); - + /* enable PLL1 */ RCU_CTL |= RCU_CTL_PLL1EN; /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0) { } /* enable PLL */ RCU_CTL |= RCU_CTL_PLLEN; /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) { } /* select PLL as system clock */ @@ -638,14 +653,14 @@ static void system_clock_36m_hxtal(void) RCU_CFG0 |= RCU_CKSYSSRC_PLL; /* wait until PLL is selected as system clock */ - while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)) { } } #elif defined (__SYSTEM_CLOCK_48M_PLL_HXTAL) /*! - \brief configure the system clock to 48M by PLL which selects HXTAL(8M) as its clock source + \brief configure the system clock to 48M by PLL which selects HXTAL(25M) as its clock source \param[in] none \param[out] none \retval none @@ -659,14 +674,14 @@ static void system_clock_48m_hxtal(void) RCU_CTL |= RCU_CTL_HXTALEN; /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ + do { timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + } while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while(1) { } } @@ -678,25 +693,25 @@ static void system_clock_48m_hxtal(void) /* APB1 = AHB/2 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - /* CK_PLL = (CK_PREDIV0) * 6 = 48 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + /* CK_PLL = (CK_PREDIV0) * 6 = 48 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL); RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL6); - - /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); - + /* enable PLL1 */ RCU_CTL |= RCU_CTL_PLL1EN; /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0) { } /* enable PLL */ RCU_CTL |= RCU_CTL_PLLEN; /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) { } /* select PLL as system clock */ @@ -704,13 +719,13 @@ static void system_clock_48m_hxtal(void) RCU_CFG0 |= RCU_CKSYSSRC_PLL; /* wait until PLL is selected as system clock */ - while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)) { } } #elif defined (__SYSTEM_CLOCK_56M_PLL_HXTAL) /*! - \brief configure the system clock to 56M by PLL which selects HXTAL(8M) as its clock source + \brief configure the system clock to 56M by PLL which selects HXTAL(25M) as its clock source \param[in] none \param[out] none \retval none @@ -724,14 +739,14 @@ static void system_clock_56m_hxtal(void) RCU_CTL |= RCU_CTL_HXTALEN; /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ + do { timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + } while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while(1) { } } @@ -743,25 +758,25 @@ static void system_clock_56m_hxtal(void) /* APB1 = AHB/2 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - /* CK_PLL = (CK_PREDIV0) * 7 = 56 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + /* CK_PLL = (CK_PREDIV0) * 7 = 56 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL); RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL7); - - /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); - + /* enable PLL1 */ RCU_CTL |= RCU_CTL_PLL1EN; /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0) { } /* enable PLL */ RCU_CTL |= RCU_CTL_PLLEN; /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) { } /* select PLL as system clock */ @@ -769,13 +784,13 @@ static void system_clock_56m_hxtal(void) RCU_CFG0 |= RCU_CKSYSSRC_PLL; /* wait until PLL is selected as system clock */ - while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)) { } } #elif defined (__SYSTEM_CLOCK_72M_PLL_HXTAL) /*! - \brief configure the system clock to 72M by PLL which selects HXTAL(8M) as its clock source + \brief configure the system clock to 72M by PLL which selects HXTAL(25M) as its clock source \param[in] none \param[out] none \retval none @@ -789,14 +804,14 @@ static void system_clock_72m_hxtal(void) RCU_CTL |= RCU_CTL_HXTALEN; /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ + do { timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + } while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while(1) { } } @@ -808,26 +823,26 @@ static void system_clock_72m_hxtal(void) /* APB1 = AHB/2 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - /* CK_PLL = (CK_PREDIV0) * 9 = 72 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + /* CK_PLL = (CK_PREDIV0) * 9 = 72 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL); RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9); - - /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); - - + + /* enable PLL1 */ RCU_CTL |= RCU_CTL_PLL1EN; /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0) { } /* enable PLL */ RCU_CTL |= RCU_CTL_PLLEN; /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) { } /* select PLL as system clock */ @@ -835,13 +850,13 @@ static void system_clock_72m_hxtal(void) RCU_CFG0 |= RCU_CKSYSSRC_PLL; /* wait until PLL is selected as system clock */ - while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)) { } } #elif defined (__SYSTEM_CLOCK_96M_PLL_HXTAL) /*! - \brief configure the system clock to 96M by PLL which selects HXTAL(8M) as its clock source + \brief configure the system clock to 96M by PLL which selects HXTAL(25M) as its clock source \param[in] none \param[out] none \retval none @@ -855,14 +870,14 @@ static void system_clock_96m_hxtal(void) RCU_CTL |= RCU_CTL_HXTALEN; /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ + do { timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + } while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while(1) { } } @@ -874,25 +889,25 @@ static void system_clock_96m_hxtal(void) /* APB1 = AHB/2 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - /* CK_PLL = (CK_PREDIV0) * 12 = 96 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + /* CK_PLL = (CK_PREDIV0) * 12 = 96 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL); RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL12); - - /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 8 /5 = 8 MHz */ RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL8 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); /* enable PLL1 */ RCU_CTL |= RCU_CTL_PLL1EN; /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0) { } /* enable PLL */ RCU_CTL |= RCU_CTL_PLLEN; /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) { } /* select PLL as system clock */ @@ -900,13 +915,13 @@ static void system_clock_96m_hxtal(void) RCU_CFG0 |= RCU_CKSYSSRC_PLL; /* wait until PLL is selected as system clock */ - while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)) { } } #elif defined (__SYSTEM_CLOCK_108M_PLL_HXTAL) /*! - \brief configure the system clock to 108M by PLL which selects HXTAL(8M) as its clock source + \brief configure the system clock to 108M by PLL which selects HXTAL(25M) as its clock source \param[in] none \param[out] none \retval none @@ -920,14 +935,14 @@ static void system_clock_108m_hxtal(void) RCU_CTL |= RCU_CTL_HXTALEN; /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ + do { timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + } while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while(1) { } } @@ -939,25 +954,25 @@ static void system_clock_108m_hxtal(void) /* APB1 = AHB/2 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - /* CK_PLL = (CK_PREDIV0) * 9 = 108 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + /* CK_PLL = (CK_PREDIV0) * 9 = 108 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL); RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL9); - - /* CK_PREDIV0 = (CK_HXTAL) / 5 * 12 /5 = 12 MHz */ + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 12 /5 = 12 MHz */ RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL12 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); /* enable PLL1 */ RCU_CTL |= RCU_CTL_PLL1EN; /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0){ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0) { } /* enable PLL */ RCU_CTL |= RCU_CTL_PLLEN; /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) { } /* select PLL as system clock */ @@ -965,13 +980,13 @@ static void system_clock_108m_hxtal(void) RCU_CFG0 |= RCU_CKSYSSRC_PLL; /* wait until PLL is selected as system clock */ - while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)) { } } #elif defined (__SYSTEM_CLOCK_120M_PLL_HXTAL) /*! - \brief configure the system clock to 120M by PLL which selects HXTAL(8M) as its clock source + \brief configure the system clock to 120M by PLL which selects HXTAL(25M) as its clock source \param[in] none \param[out] none \retval none @@ -985,14 +1000,14 @@ static void system_clock_120m_hxtal(void) RCU_CTL |= RCU_CTL_HXTALEN; /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */ - do{ + do { timeout++; stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB); - }while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); + } while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */ - if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){ - while(1){ + if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)) { + while(1) { } } @@ -1004,25 +1019,25 @@ static void system_clock_120m_hxtal(void) /* APB1 = AHB/2 */ RCU_CFG0 |= RCU_APB1_CKAHB_DIV2; - /* CK_PLL = (CK_PREDIV0) * 10 = 120 MHz */ - RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL ); + /* CK_PLL = (CK_PREDIV0) * 10 = 120 MHz */ + RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLSEL); RCU_CFG0 |= (RCU_PLLSRC_HXTAL | RCU_PLL_MUL10); - - /* CK_PREDIV0 = (CK_HXTAL) / 5 * 12 /5 = 12 MHz */ + + /* CK_PREDIV0 = (CK_HXTAL) / 5 * 12 /5 = 12 MHz */ RCU_CFG1 &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PLL1MF | RCU_CFG1_PREDV1 | RCU_CFG1_PREDV0); RCU_CFG1 |= (RCU_PREDV0SRC_CKPLL1 | RCU_PLL1_MUL12 | RCU_PREDV1_DIV5 | RCU_PREDV0_DIV5); /* enable PLL1 */ RCU_CTL |= RCU_CTL_PLL1EN; /* wait till PLL1 is ready */ - while((RCU_CTL & RCU_CTL_PLL1STB) == 0U){ + while((RCU_CTL & RCU_CTL_PLL1STB) == 0U) { } - + /* enable PLL */ RCU_CTL |= RCU_CTL_PLLEN; /* wait until PLL is stable */ - while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){ + while(0U == (RCU_CTL & RCU_CTL_PLLSTB)) { } /* select PLL as system clock */ @@ -1030,26 +1045,28 @@ static void system_clock_120m_hxtal(void) RCU_CFG0 |= RCU_CKSYSSRC_PLL; /* wait until PLL is selected as system clock */ - while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){ + while(RCU_SCSS_PLL != (RCU_CFG0 & RCU_CFG0_SCSS)) { } } #endif /* __SYSTEM_CLOCK_IRC8M */ /*! - \brief update the SystemCoreClock with current core clock retrieved from cpu registers + \brief update the SystemCoreClock with current core clock retrieved from CPU registers \param[in] none \param[out] none \retval none */ -void SystemCoreClockUpdate (void) +void SystemCoreClockUpdate(void) { uint32_t sws; - uint32_t pllsel, predv0sel, pllmf,ck_src; + uint32_t pllsel, predv0sel, pllmf, ck_src, idx, clk_exp; uint32_t predv0, predv1, pll1mf; + /* exponent of AHB, APB1 and APB2 clock divider */ + const uint8_t ahb_exp[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; sws = GET_BITS(RCU_CFG0, 2, 3); - switch(sws){ + switch(sws) { /* IRC8M is selected as CK_SYS */ case SEL_IRC8M: SystemCoreClock = IRC8M_VALUE; @@ -1063,46 +1080,46 @@ void SystemCoreClockUpdate (void) /* PLL clock source selection, HXTAL or IRC8M/2 */ pllsel = (RCU_CFG0 & RCU_CFG0_PLLSEL); - if (RCU_PLLSRC_HXTAL == pllsel) { + if(RCU_PLLSRC_HXTAL == pllsel) { /* PLL clock source is HXTAL */ ck_src = HXTAL_VALUE; predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); /* source clock use PLL1 */ - if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel) { predv1 = (uint32_t)((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; - if(17U == pll1mf){ + if(17U == pll1mf) { pll1mf = 20U; } - ck_src = (ck_src/predv1)*pll1mf; + ck_src = (ck_src / predv1) * pll1mf; } predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; ck_src /= predv0; - }else{ + } else { /* PLL clock source is IRC8M/2 */ - ck_src = IRC8M_VALUE/2U; + ck_src = IRC8M_VALUE / 2U; } /* PLL multiplication factor */ pllmf = GET_BITS(RCU_CFG0, 18, 21); - if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)) { pllmf |= 0x10U; } - if(13U == pllmf){ + if(13U == pllmf) { /* PLL source clock multiply by 6.5 */ - SystemCoreClock = ck_src*6U + ck_src/2U; - }else{ - if(pllmf < 15U){ + SystemCoreClock = ck_src * 6U + ck_src / 2U; + } else { + if(pllmf < 15U) { pllmf += 2U; - }else{ + } else { pllmf += 1U; } - SystemCoreClock = ck_src*pllmf; + SystemCoreClock = ck_src * pllmf; } - + break; /* IRC8M is selected as CK_SYS */ default: @@ -1110,4 +1127,8 @@ void SystemCoreClockUpdate (void) break; } + /* calculate AHB clock frequency */ + idx = GET_BITS(RCU_CFG0, 4, 7); + clk_exp = ahb_exp[idx]; + SystemCoreClock = SystemCoreClock >> clk_exp; } diff --git a/lib-gd32/gd32f20x/CMSIS/core_cm3.h b/lib-gd32/gd32f20x/CMSIS/core_cm3.h deleted file mode 100644 index 248d1e4c..00000000 --- a/lib-gd32/gd32f20x/CMSIS/core_cm3.h +++ /dev/null @@ -1,1638 +0,0 @@ -/**************************************************************************//** - * @file core_cm3.h - * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File - * @version V3.30 - * @date 17. February 2014 - * - * @note - * - ******************************************************************************/ -/* Copyright (c) 2009 - 2014 ARM LIMITED - - All rights reserved. - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - Neither the name of ARM nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - * - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------*/ - - -#if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#endif - -#ifdef __cplusplus - extern "C" { -#endif - -#ifndef __CORE_CM3_H_GENERIC -#define __CORE_CM3_H_GENERIC - -/** \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions - CMSIS violates the following MISRA-C:2004 rules: - - \li Required Rule 8.5, object/function definition in header file.
- Function definitions in header files are used to allow 'inlining'. - - \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
- Unions are used for effective representation of core registers. - - \li Advisory Rule 19.7, Function-like macro defined.
- Function-like macros are used to allow more efficient code. - */ - - -/******************************************************************************* - * CMSIS definitions - ******************************************************************************/ -/** \ingroup Cortex_M3 - @{ - */ - -/* CMSIS CM3 definitions */ -#define __CM3_CMSIS_VERSION_MAIN (0x03) /*!< [31:16] CMSIS HAL main version */ -#define __CM3_CMSIS_VERSION_SUB (0x20) /*!< [15:0] CMSIS HAL sub version */ -#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16) | \ - __CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */ - -#define __CORTEX_M (0x03) /*!< Cortex-M Core */ - - -#if defined ( __CC_ARM ) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - #define __STATIC_INLINE static __inline - -#elif defined ( __GNUC__ ) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __ICCARM__ ) - #define __ASM __asm /*!< asm keyword for IAR Compiler */ - #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */ - #define __STATIC_INLINE static inline - -#elif defined ( __TMS470__ ) - #define __ASM __asm /*!< asm keyword for TI CCS Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __TASKING__ ) - #define __ASM __asm /*!< asm keyword for TASKING Compiler */ - #define __INLINE inline /*!< inline keyword for TASKING Compiler */ - #define __STATIC_INLINE static inline - -#elif defined ( __CSMC__ ) /* Cosmic */ - #define __packed - #define __ASM _asm /*!< asm keyword for COSMIC Compiler */ - #define __INLINE inline /*use -pc99 on compile line !< inline keyword for COSMIC Compiler */ - #define __STATIC_INLINE static inline - -#endif - -/** __FPU_USED indicates whether an FPU is used or not. This core does not support an FPU at all -*/ -#define __FPU_USED 0 - -#if defined ( __CC_ARM ) - #if defined __TARGET_FPU_VFP - #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#elif defined ( __GNUC__ ) - #if defined (__VFP_FP__) && !defined(__SOFTFP__) - #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#elif defined ( __ICCARM__ ) - #if defined __ARMVFP__ - #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#elif defined ( __TMS470__ ) - #if defined __TI__VFP_SUPPORT____ - #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#elif defined ( __TASKING__ ) - #if defined __FPU_VFP__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#elif defined ( __CSMC__ ) /* Cosmic */ - #if ( __CSMC__ & 0x400) // FPU present for parser - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif -#endif - -#include /* standard types definitions */ -#include /* Core Instruction Access */ -#include /* Core Function Access */ - -#endif /* __CORE_CM3_H_GENERIC */ - -#ifndef __CMSIS_GENERIC - -#ifndef __CORE_CM3_H_DEPENDANT -#define __CORE_CM3_H_DEPENDANT - -/* check device defines and use defaults */ -#if defined __CHECK_DEVICE_DEFINES - #ifndef __CM3_REV - #define __CM3_REV 0x0200 - #warning "__CM3_REV not defined in device header file; using default!" - #endif - - #ifndef __MPU_PRESENT - #define __MPU_PRESENT 0 - #warning "__MPU_PRESENT not defined in device header file; using default!" - #endif - - #ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 4 - #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" - #endif - - #ifndef __Vendor_SysTickConfig - #define __Vendor_SysTickConfig 0 - #warning "__Vendor_SysTickConfig not defined in device header file; using default!" - #endif -#endif - -/* IO definitions (access restrictions to peripheral registers) */ -/** - \defgroup CMSIS_glob_defs CMSIS Global Defines - - IO Type Qualifiers are used - \li to specify the access to peripheral variables. - \li for automatic generation of peripheral register debug information. -*/ -#ifdef __cplusplus - #define __I volatile /*!< Defines 'read only' permissions */ -#else - #define __I volatile const /*!< Defines 'read only' permissions */ -#endif -#define __O volatile /*!< Defines 'write only' permissions */ -#define __IO volatile /*!< Defines 'read / write' permissions */ - -/*@} end of group Cortex_M3 */ - - - -/******************************************************************************* - * Register Abstraction - Core Register contain: - - Core Register - - Core NVIC Register - - Core SCB Register - - Core SysTick Register - - Core Debug Register - - Core MPU Register - ******************************************************************************/ -/** \defgroup CMSIS_core_register Defines and Type Definitions - \brief Type definitions and defines for Cortex-M processor based devices. -*/ - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_CORE Status and Control Registers - \brief Core Register type definitions. - @{ - */ - -/** \brief Union type to access the Application Program Status Register (APSR). - */ -typedef union -{ - struct - { -#if (__CORTEX_M != 0x04) - uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ -#else - uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ - uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ -#endif - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} APSR_Type; - - -/** \brief Union type to access the Interrupt Program Status Register (IPSR). - */ -typedef union -{ - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} IPSR_Type; - - -/** \brief Union type to access the Special-Purpose Program Status Registers (xPSR). - */ -typedef union -{ - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ -#if (__CORTEX_M != 0x04) - uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ -#else - uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ - uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ - uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ -#endif - uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ - uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} xPSR_Type; - - -/** \brief Union type to access the Control Registers (CONTROL). - */ -typedef union -{ - struct - { - uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ - uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ - uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ - uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} CONTROL_Type; - -/*@} end of group CMSIS_CORE */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) - \brief Type definitions for the NVIC Registers - @{ - */ - -/** \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). - */ -typedef struct -{ - __IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ - uint32_t RESERVED0[24]; - __IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RSERVED1[24]; - __IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ - uint32_t RESERVED2[24]; - __IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ - uint32_t RESERVED3[24]; - __IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ - uint32_t RESERVED4[56]; - __IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ - uint32_t RESERVED5[644]; - __O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ -} NVIC_Type; - -/* Software Triggered Interrupt Register Definitions */ -#define NVIC_STIR_INTID_Pos 0 /*!< STIR: INTLINESNUM Position */ -#define NVIC_STIR_INTID_Msk (0x1FFUL << NVIC_STIR_INTID_Pos) /*!< STIR: INTLINESNUM Mask */ - -/*@} end of group CMSIS_NVIC */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_SCB System Control Block (SCB) - \brief Type definitions for the System Control Block Registers - @{ - */ - -/** \brief Structure type to access the System Control Block (SCB). - */ -typedef struct -{ - __I uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ - __IO uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ - __IO uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ - __IO uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ - __IO uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ - __IO uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ - __IO uint8_t SHP[12]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ - __IO uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ - __IO uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ - __IO uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ - __IO uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ - __IO uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ - __IO uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ - __IO uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ - __I uint32_t PFR[2]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ - __I uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ - __I uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ - __I uint32_t MMFR[4]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ - __I uint32_t ISAR[5]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ - uint32_t RESERVED0[5]; - __IO uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ -} SCB_Type; - -/* SCB CPUID Register Definitions */ -#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ -#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ - -#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ -#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ - -#define SCB_CPUID_ARCHITECTURE_Pos 16 /*!< SCB CPUID: ARCHITECTURE Position */ -#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ - -#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ -#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ - -#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ -#define SCB_CPUID_REVISION_Msk (0xFUL << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ - -/* SCB Interrupt Control State Register Definitions */ -#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ -#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ - -#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ -#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ - -#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ -#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ - -#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ -#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ - -#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ -#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ - -#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ -#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ - -#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ -#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ - -#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ -#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ - -#define SCB_ICSR_RETTOBASE_Pos 11 /*!< SCB ICSR: RETTOBASE Position */ -#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ - -#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ -#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ - -/* SCB Vector Table Offset Register Definitions */ -#if (__CM3_REV < 0x0201) /* core r2p1 */ -#define SCB_VTOR_TBLBASE_Pos 29 /*!< SCB VTOR: TBLBASE Position */ -#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ - -#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ -#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ -#else -#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ -#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ -#endif - -/* SCB Application Interrupt and Reset Control Register Definitions */ -#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ -#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ - -#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ -#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ - -#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ -#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ - -#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */ -#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ - -#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ -#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ - -#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ -#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ - -#define SCB_AIRCR_VECTRESET_Pos 0 /*!< SCB AIRCR: VECTRESET Position */ -#define SCB_AIRCR_VECTRESET_Msk (1UL << SCB_AIRCR_VECTRESET_Pos) /*!< SCB AIRCR: VECTRESET Mask */ - -/* SCB System Control Register Definitions */ -#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ -#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ - -#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ -#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ - -#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ -#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ - -/* SCB Configuration Control Register Definitions */ -#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ -#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ - -#define SCB_CCR_BFHFNMIGN_Pos 8 /*!< SCB CCR: BFHFNMIGN Position */ -#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ - -#define SCB_CCR_DIV_0_TRP_Pos 4 /*!< SCB CCR: DIV_0_TRP Position */ -#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ - -#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ -#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ - -#define SCB_CCR_USERSETMPEND_Pos 1 /*!< SCB CCR: USERSETMPEND Position */ -#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ - -#define SCB_CCR_NONBASETHRDENA_Pos 0 /*!< SCB CCR: NONBASETHRDENA Position */ -#define SCB_CCR_NONBASETHRDENA_Msk (1UL << SCB_CCR_NONBASETHRDENA_Pos) /*!< SCB CCR: NONBASETHRDENA Mask */ - -/* SCB System Handler Control and State Register Definitions */ -#define SCB_SHCSR_USGFAULTENA_Pos 18 /*!< SCB SHCSR: USGFAULTENA Position */ -#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ - -#define SCB_SHCSR_BUSFAULTENA_Pos 17 /*!< SCB SHCSR: BUSFAULTENA Position */ -#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ - -#define SCB_SHCSR_MEMFAULTENA_Pos 16 /*!< SCB SHCSR: MEMFAULTENA Position */ -#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ - -#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ -#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ - -#define SCB_SHCSR_BUSFAULTPENDED_Pos 14 /*!< SCB SHCSR: BUSFAULTPENDED Position */ -#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ - -#define SCB_SHCSR_MEMFAULTPENDED_Pos 13 /*!< SCB SHCSR: MEMFAULTPENDED Position */ -#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ - -#define SCB_SHCSR_USGFAULTPENDED_Pos 12 /*!< SCB SHCSR: USGFAULTPENDED Position */ -#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ - -#define SCB_SHCSR_SYSTICKACT_Pos 11 /*!< SCB SHCSR: SYSTICKACT Position */ -#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ - -#define SCB_SHCSR_PENDSVACT_Pos 10 /*!< SCB SHCSR: PENDSVACT Position */ -#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ - -#define SCB_SHCSR_MONITORACT_Pos 8 /*!< SCB SHCSR: MONITORACT Position */ -#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ - -#define SCB_SHCSR_SVCALLACT_Pos 7 /*!< SCB SHCSR: SVCALLACT Position */ -#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ - -#define SCB_SHCSR_USGFAULTACT_Pos 3 /*!< SCB SHCSR: USGFAULTACT Position */ -#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ - -#define SCB_SHCSR_BUSFAULTACT_Pos 1 /*!< SCB SHCSR: BUSFAULTACT Position */ -#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ - -#define SCB_SHCSR_MEMFAULTACT_Pos 0 /*!< SCB SHCSR: MEMFAULTACT Position */ -#define SCB_SHCSR_MEMFAULTACT_Msk (1UL << SCB_SHCSR_MEMFAULTACT_Pos) /*!< SCB SHCSR: MEMFAULTACT Mask */ - -/* SCB Configurable Fault Status Registers Definitions */ -#define SCB_CFSR_USGFAULTSR_Pos 16 /*!< SCB CFSR: Usage Fault Status Register Position */ -#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ - -#define SCB_CFSR_BUSFAULTSR_Pos 8 /*!< SCB CFSR: Bus Fault Status Register Position */ -#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ - -#define SCB_CFSR_MEMFAULTSR_Pos 0 /*!< SCB CFSR: Memory Manage Fault Status Register Position */ -#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL << SCB_CFSR_MEMFAULTSR_Pos) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ - -/* SCB Hard Fault Status Registers Definitions */ -#define SCB_HFSR_DEBUGEVT_Pos 31 /*!< SCB HFSR: DEBUGEVT Position */ -#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ - -#define SCB_HFSR_FORCED_Pos 30 /*!< SCB HFSR: FORCED Position */ -#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ - -#define SCB_HFSR_VECTTBL_Pos 1 /*!< SCB HFSR: VECTTBL Position */ -#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ - -/* SCB Debug Fault Status Register Definitions */ -#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */ -#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ - -#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */ -#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ - -#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */ -#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ - -#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */ -#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ - -#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */ -#define SCB_DFSR_HALTED_Msk (1UL << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */ - -/*@} end of group CMSIS_SCB */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) - \brief Type definitions for the System Control and ID Register not in the SCB - @{ - */ - -/** \brief Structure type to access the System Control and ID Register not in the SCB. - */ -typedef struct -{ - uint32_t RESERVED0[1]; - __I uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ -#if ((defined __CM3_REV) && (__CM3_REV >= 0x200)) - __IO uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ -#else - uint32_t RESERVED1[1]; -#endif -} SCnSCB_Type; - -/* Interrupt Controller Type Register Definitions */ -#define SCnSCB_ICTR_INTLINESNUM_Pos 0 /*!< ICTR: INTLINESNUM Position */ -#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL << SCnSCB_ICTR_INTLINESNUM_Pos) /*!< ICTR: INTLINESNUM Mask */ - -/* Auxiliary Control Register Definitions */ - -#define SCnSCB_ACTLR_DISFOLD_Pos 2 /*!< ACTLR: DISFOLD Position */ -#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ - -#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1 /*!< ACTLR: DISDEFWBUF Position */ -#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ - -#define SCnSCB_ACTLR_DISMCYCINT_Pos 0 /*!< ACTLR: DISMCYCINT Position */ -#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL << SCnSCB_ACTLR_DISMCYCINT_Pos) /*!< ACTLR: DISMCYCINT Mask */ - -/*@} end of group CMSIS_SCnotSCB */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_SysTick System Tick Timer (SysTick) - \brief Type definitions for the System Timer Registers. - @{ - */ - -/** \brief Structure type to access the System Timer (SysTick). - */ -typedef struct -{ - __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ - __IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ - __IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ - __I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ -} SysTick_Type; - -/* SysTick Control / Status Register Definitions */ -#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ -#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ - -#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ -#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ - -#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ -#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ - -#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ -#define SysTick_CTRL_ENABLE_Msk (1UL << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ - -/* SysTick Reload Register Definitions */ -#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ -#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ - -/* SysTick Current Register Definitions */ -#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ -#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ - -/* SysTick Calibration Register Definitions */ -#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ -#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ - -#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ -#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ - -#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ -#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ - -/*@} end of group CMSIS_SysTick */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) - \brief Type definitions for the Instrumentation Trace Macrocell (ITM) - @{ - */ - -/** \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). - */ -typedef struct -{ - __O union - { - __O uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ - __O uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ - __O uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ - } PORT [32]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ - uint32_t RESERVED0[864]; - __IO uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ - uint32_t RESERVED1[15]; - __IO uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ - uint32_t RESERVED2[15]; - __IO uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ - uint32_t RESERVED3[29]; - __O uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ - __I uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ - __IO uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ - uint32_t RESERVED4[43]; - __O uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ - __I uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ - uint32_t RESERVED5[6]; - __I uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ - __I uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ - __I uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ - __I uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ - __I uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ - __I uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ - __I uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ - __I uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ - __I uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ - __I uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ - __I uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ - __I uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ -} ITM_Type; - -/* ITM Trace Privilege Register Definitions */ -#define ITM_TPR_PRIVMASK_Pos 0 /*!< ITM TPR: PRIVMASK Position */ -#define ITM_TPR_PRIVMASK_Msk (0xFUL << ITM_TPR_PRIVMASK_Pos) /*!< ITM TPR: PRIVMASK Mask */ - -/* ITM Trace Control Register Definitions */ -#define ITM_TCR_BUSY_Pos 23 /*!< ITM TCR: BUSY Position */ -#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ - -#define ITM_TCR_TraceBusID_Pos 16 /*!< ITM TCR: ATBID Position */ -#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ - -#define ITM_TCR_GTSFREQ_Pos 10 /*!< ITM TCR: Global timestamp frequency Position */ -#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ - -#define ITM_TCR_TSPrescale_Pos 8 /*!< ITM TCR: TSPrescale Position */ -#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ - -#define ITM_TCR_SWOENA_Pos 4 /*!< ITM TCR: SWOENA Position */ -#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ - -#define ITM_TCR_DWTENA_Pos 3 /*!< ITM TCR: DWTENA Position */ -#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ - -#define ITM_TCR_SYNCENA_Pos 2 /*!< ITM TCR: SYNCENA Position */ -#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ - -#define ITM_TCR_TSENA_Pos 1 /*!< ITM TCR: TSENA Position */ -#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ - -#define ITM_TCR_ITMENA_Pos 0 /*!< ITM TCR: ITM Enable bit Position */ -#define ITM_TCR_ITMENA_Msk (1UL << ITM_TCR_ITMENA_Pos) /*!< ITM TCR: ITM Enable bit Mask */ - -/* ITM Integration Write Register Definitions */ -#define ITM_IWR_ATVALIDM_Pos 0 /*!< ITM IWR: ATVALIDM Position */ -#define ITM_IWR_ATVALIDM_Msk (1UL << ITM_IWR_ATVALIDM_Pos) /*!< ITM IWR: ATVALIDM Mask */ - -/* ITM Integration Read Register Definitions */ -#define ITM_IRR_ATREADYM_Pos 0 /*!< ITM IRR: ATREADYM Position */ -#define ITM_IRR_ATREADYM_Msk (1UL << ITM_IRR_ATREADYM_Pos) /*!< ITM IRR: ATREADYM Mask */ - -/* ITM Integration Mode Control Register Definitions */ -#define ITM_IMCR_INTEGRATION_Pos 0 /*!< ITM IMCR: INTEGRATION Position */ -#define ITM_IMCR_INTEGRATION_Msk (1UL << ITM_IMCR_INTEGRATION_Pos) /*!< ITM IMCR: INTEGRATION Mask */ - -/* ITM Lock Status Register Definitions */ -#define ITM_LSR_ByteAcc_Pos 2 /*!< ITM LSR: ByteAcc Position */ -#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ - -#define ITM_LSR_Access_Pos 1 /*!< ITM LSR: Access Position */ -#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ - -#define ITM_LSR_Present_Pos 0 /*!< ITM LSR: Present Position */ -#define ITM_LSR_Present_Msk (1UL << ITM_LSR_Present_Pos) /*!< ITM LSR: Present Mask */ - -/*@}*/ /* end of group CMSIS_ITM */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) - \brief Type definitions for the Data Watchpoint and Trace (DWT) - @{ - */ - -/** \brief Structure type to access the Data Watchpoint and Trace Register (DWT). - */ -typedef struct -{ - __IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ - __IO uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ - __IO uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ - __IO uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ - __IO uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ - __IO uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ - __IO uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ - __I uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ - __IO uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ - __IO uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ - __IO uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ - uint32_t RESERVED0[1]; - __IO uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ - __IO uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ - __IO uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ - uint32_t RESERVED1[1]; - __IO uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ - __IO uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ - __IO uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ - uint32_t RESERVED2[1]; - __IO uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ - __IO uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ - __IO uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ -} DWT_Type; - -/* DWT Control Register Definitions */ -#define DWT_CTRL_NUMCOMP_Pos 28 /*!< DWT CTRL: NUMCOMP Position */ -#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ - -#define DWT_CTRL_NOTRCPKT_Pos 27 /*!< DWT CTRL: NOTRCPKT Position */ -#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ - -#define DWT_CTRL_NOEXTTRIG_Pos 26 /*!< DWT CTRL: NOEXTTRIG Position */ -#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ - -#define DWT_CTRL_NOCYCCNT_Pos 25 /*!< DWT CTRL: NOCYCCNT Position */ -#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ - -#define DWT_CTRL_NOPRFCNT_Pos 24 /*!< DWT CTRL: NOPRFCNT Position */ -#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ - -#define DWT_CTRL_CYCEVTENA_Pos 22 /*!< DWT CTRL: CYCEVTENA Position */ -#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ - -#define DWT_CTRL_FOLDEVTENA_Pos 21 /*!< DWT CTRL: FOLDEVTENA Position */ -#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ - -#define DWT_CTRL_LSUEVTENA_Pos 20 /*!< DWT CTRL: LSUEVTENA Position */ -#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ - -#define DWT_CTRL_SLEEPEVTENA_Pos 19 /*!< DWT CTRL: SLEEPEVTENA Position */ -#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ - -#define DWT_CTRL_EXCEVTENA_Pos 18 /*!< DWT CTRL: EXCEVTENA Position */ -#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ - -#define DWT_CTRL_CPIEVTENA_Pos 17 /*!< DWT CTRL: CPIEVTENA Position */ -#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ - -#define DWT_CTRL_EXCTRCENA_Pos 16 /*!< DWT CTRL: EXCTRCENA Position */ -#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ - -#define DWT_CTRL_PCSAMPLENA_Pos 12 /*!< DWT CTRL: PCSAMPLENA Position */ -#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ - -#define DWT_CTRL_SYNCTAP_Pos 10 /*!< DWT CTRL: SYNCTAP Position */ -#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ - -#define DWT_CTRL_CYCTAP_Pos 9 /*!< DWT CTRL: CYCTAP Position */ -#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ - -#define DWT_CTRL_POSTINIT_Pos 5 /*!< DWT CTRL: POSTINIT Position */ -#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ - -#define DWT_CTRL_POSTPRESET_Pos 1 /*!< DWT CTRL: POSTPRESET Position */ -#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ - -#define DWT_CTRL_CYCCNTENA_Pos 0 /*!< DWT CTRL: CYCCNTENA Position */ -#define DWT_CTRL_CYCCNTENA_Msk (0x1UL << DWT_CTRL_CYCCNTENA_Pos) /*!< DWT CTRL: CYCCNTENA Mask */ - -/* DWT CPI Count Register Definitions */ -#define DWT_CPICNT_CPICNT_Pos 0 /*!< DWT CPICNT: CPICNT Position */ -#define DWT_CPICNT_CPICNT_Msk (0xFFUL << DWT_CPICNT_CPICNT_Pos) /*!< DWT CPICNT: CPICNT Mask */ - -/* DWT Exception Overhead Count Register Definitions */ -#define DWT_EXCCNT_EXCCNT_Pos 0 /*!< DWT EXCCNT: EXCCNT Position */ -#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL << DWT_EXCCNT_EXCCNT_Pos) /*!< DWT EXCCNT: EXCCNT Mask */ - -/* DWT Sleep Count Register Definitions */ -#define DWT_SLEEPCNT_SLEEPCNT_Pos 0 /*!< DWT SLEEPCNT: SLEEPCNT Position */ -#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL << DWT_SLEEPCNT_SLEEPCNT_Pos) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ - -/* DWT LSU Count Register Definitions */ -#define DWT_LSUCNT_LSUCNT_Pos 0 /*!< DWT LSUCNT: LSUCNT Position */ -#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL << DWT_LSUCNT_LSUCNT_Pos) /*!< DWT LSUCNT: LSUCNT Mask */ - -/* DWT Folded-instruction Count Register Definitions */ -#define DWT_FOLDCNT_FOLDCNT_Pos 0 /*!< DWT FOLDCNT: FOLDCNT Position */ -#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL << DWT_FOLDCNT_FOLDCNT_Pos) /*!< DWT FOLDCNT: FOLDCNT Mask */ - -/* DWT Comparator Mask Register Definitions */ -#define DWT_MASK_MASK_Pos 0 /*!< DWT MASK: MASK Position */ -#define DWT_MASK_MASK_Msk (0x1FUL << DWT_MASK_MASK_Pos) /*!< DWT MASK: MASK Mask */ - -/* DWT Comparator Function Register Definitions */ -#define DWT_FUNCTION_MATCHED_Pos 24 /*!< DWT FUNCTION: MATCHED Position */ -#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ - -#define DWT_FUNCTION_DATAVADDR1_Pos 16 /*!< DWT FUNCTION: DATAVADDR1 Position */ -#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ - -#define DWT_FUNCTION_DATAVADDR0_Pos 12 /*!< DWT FUNCTION: DATAVADDR0 Position */ -#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ - -#define DWT_FUNCTION_DATAVSIZE_Pos 10 /*!< DWT FUNCTION: DATAVSIZE Position */ -#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ - -#define DWT_FUNCTION_LNK1ENA_Pos 9 /*!< DWT FUNCTION: LNK1ENA Position */ -#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ - -#define DWT_FUNCTION_DATAVMATCH_Pos 8 /*!< DWT FUNCTION: DATAVMATCH Position */ -#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ - -#define DWT_FUNCTION_CYCMATCH_Pos 7 /*!< DWT FUNCTION: CYCMATCH Position */ -#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ - -#define DWT_FUNCTION_EMITRANGE_Pos 5 /*!< DWT FUNCTION: EMITRANGE Position */ -#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ - -#define DWT_FUNCTION_FUNCTION_Pos 0 /*!< DWT FUNCTION: FUNCTION Position */ -#define DWT_FUNCTION_FUNCTION_Msk (0xFUL << DWT_FUNCTION_FUNCTION_Pos) /*!< DWT FUNCTION: FUNCTION Mask */ - -/*@}*/ /* end of group CMSIS_DWT */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_TPI Trace Port Interface (TPI) - \brief Type definitions for the Trace Port Interface (TPI) - @{ - */ - -/** \brief Structure type to access the Trace Port Interface Register (TPI). - */ -typedef struct -{ - __IO uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ - __IO uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ - uint32_t RESERVED0[2]; - __IO uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ - uint32_t RESERVED1[55]; - __IO uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ - uint32_t RESERVED2[131]; - __I uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ - __IO uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ - __I uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ - uint32_t RESERVED3[759]; - __I uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ - __I uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ - __I uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ - uint32_t RESERVED4[1]; - __I uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ - __I uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ - __IO uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ - uint32_t RESERVED5[39]; - __IO uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ - __IO uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ - uint32_t RESERVED7[8]; - __I uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ - __I uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ -} TPI_Type; - -/* TPI Asynchronous Clock Prescaler Register Definitions */ -#define TPI_ACPR_PRESCALER_Pos 0 /*!< TPI ACPR: PRESCALER Position */ -#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL << TPI_ACPR_PRESCALER_Pos) /*!< TPI ACPR: PRESCALER Mask */ - -/* TPI Selected Pin Protocol Register Definitions */ -#define TPI_SPPR_TXMODE_Pos 0 /*!< TPI SPPR: TXMODE Position */ -#define TPI_SPPR_TXMODE_Msk (0x3UL << TPI_SPPR_TXMODE_Pos) /*!< TPI SPPR: TXMODE Mask */ - -/* TPI Formatter and Flush Status Register Definitions */ -#define TPI_FFSR_FtNonStop_Pos 3 /*!< TPI FFSR: FtNonStop Position */ -#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ - -#define TPI_FFSR_TCPresent_Pos 2 /*!< TPI FFSR: TCPresent Position */ -#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ - -#define TPI_FFSR_FtStopped_Pos 1 /*!< TPI FFSR: FtStopped Position */ -#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ - -#define TPI_FFSR_FlInProg_Pos 0 /*!< TPI FFSR: FlInProg Position */ -#define TPI_FFSR_FlInProg_Msk (0x1UL << TPI_FFSR_FlInProg_Pos) /*!< TPI FFSR: FlInProg Mask */ - -/* TPI Formatter and Flush Control Register Definitions */ -#define TPI_FFCR_TrigIn_Pos 8 /*!< TPI FFCR: TrigIn Position */ -#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ - -#define TPI_FFCR_EnFCont_Pos 1 /*!< TPI FFCR: EnFCont Position */ -#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ - -/* TPI TRIGGER Register Definitions */ -#define TPI_TRIGGER_TRIGGER_Pos 0 /*!< TPI TRIGGER: TRIGGER Position */ -#define TPI_TRIGGER_TRIGGER_Msk (0x1UL << TPI_TRIGGER_TRIGGER_Pos) /*!< TPI TRIGGER: TRIGGER Mask */ - -/* TPI Integration ETM Data Register Definitions (FIFO0) */ -#define TPI_FIFO0_ITM_ATVALID_Pos 29 /*!< TPI FIFO0: ITM_ATVALID Position */ -#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ - -#define TPI_FIFO0_ITM_bytecount_Pos 27 /*!< TPI FIFO0: ITM_bytecount Position */ -#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ - -#define TPI_FIFO0_ETM_ATVALID_Pos 26 /*!< TPI FIFO0: ETM_ATVALID Position */ -#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ - -#define TPI_FIFO0_ETM_bytecount_Pos 24 /*!< TPI FIFO0: ETM_bytecount Position */ -#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ - -#define TPI_FIFO0_ETM2_Pos 16 /*!< TPI FIFO0: ETM2 Position */ -#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ - -#define TPI_FIFO0_ETM1_Pos 8 /*!< TPI FIFO0: ETM1 Position */ -#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ - -#define TPI_FIFO0_ETM0_Pos 0 /*!< TPI FIFO0: ETM0 Position */ -#define TPI_FIFO0_ETM0_Msk (0xFFUL << TPI_FIFO0_ETM0_Pos) /*!< TPI FIFO0: ETM0 Mask */ - -/* TPI ITATBCTR2 Register Definitions */ -#define TPI_ITATBCTR2_ATREADY_Pos 0 /*!< TPI ITATBCTR2: ATREADY Position */ -#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL << TPI_ITATBCTR2_ATREADY_Pos) /*!< TPI ITATBCTR2: ATREADY Mask */ - -/* TPI Integration ITM Data Register Definitions (FIFO1) */ -#define TPI_FIFO1_ITM_ATVALID_Pos 29 /*!< TPI FIFO1: ITM_ATVALID Position */ -#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ - -#define TPI_FIFO1_ITM_bytecount_Pos 27 /*!< TPI FIFO1: ITM_bytecount Position */ -#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ - -#define TPI_FIFO1_ETM_ATVALID_Pos 26 /*!< TPI FIFO1: ETM_ATVALID Position */ -#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ - -#define TPI_FIFO1_ETM_bytecount_Pos 24 /*!< TPI FIFO1: ETM_bytecount Position */ -#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ - -#define TPI_FIFO1_ITM2_Pos 16 /*!< TPI FIFO1: ITM2 Position */ -#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ - -#define TPI_FIFO1_ITM1_Pos 8 /*!< TPI FIFO1: ITM1 Position */ -#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ - -#define TPI_FIFO1_ITM0_Pos 0 /*!< TPI FIFO1: ITM0 Position */ -#define TPI_FIFO1_ITM0_Msk (0xFFUL << TPI_FIFO1_ITM0_Pos) /*!< TPI FIFO1: ITM0 Mask */ - -/* TPI ITATBCTR0 Register Definitions */ -#define TPI_ITATBCTR0_ATREADY_Pos 0 /*!< TPI ITATBCTR0: ATREADY Position */ -#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL << TPI_ITATBCTR0_ATREADY_Pos) /*!< TPI ITATBCTR0: ATREADY Mask */ - -/* TPI Integration Mode Control Register Definitions */ -#define TPI_ITCTRL_Mode_Pos 0 /*!< TPI ITCTRL: Mode Position */ -#define TPI_ITCTRL_Mode_Msk (0x1UL << TPI_ITCTRL_Mode_Pos) /*!< TPI ITCTRL: Mode Mask */ - -/* TPI DEVID Register Definitions */ -#define TPI_DEVID_NRZVALID_Pos 11 /*!< TPI DEVID: NRZVALID Position */ -#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ - -#define TPI_DEVID_MANCVALID_Pos 10 /*!< TPI DEVID: MANCVALID Position */ -#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ - -#define TPI_DEVID_PTINVALID_Pos 9 /*!< TPI DEVID: PTINVALID Position */ -#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ - -#define TPI_DEVID_MinBufSz_Pos 6 /*!< TPI DEVID: MinBufSz Position */ -#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ - -#define TPI_DEVID_AsynClkIn_Pos 5 /*!< TPI DEVID: AsynClkIn Position */ -#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ - -#define TPI_DEVID_NrTraceInput_Pos 0 /*!< TPI DEVID: NrTraceInput Position */ -#define TPI_DEVID_NrTraceInput_Msk (0x1FUL << TPI_DEVID_NrTraceInput_Pos) /*!< TPI DEVID: NrTraceInput Mask */ - -/* TPI DEVTYPE Register Definitions */ -#define TPI_DEVTYPE_SubType_Pos 0 /*!< TPI DEVTYPE: SubType Position */ -#define TPI_DEVTYPE_SubType_Msk (0xFUL << TPI_DEVTYPE_SubType_Pos) /*!< TPI DEVTYPE: SubType Mask */ - -#define TPI_DEVTYPE_MajorType_Pos 4 /*!< TPI DEVTYPE: MajorType Position */ -#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ - -/*@}*/ /* end of group CMSIS_TPI */ - - -#if (__MPU_PRESENT == 1) -/** \ingroup CMSIS_core_register - \defgroup CMSIS_MPU Memory Protection Unit (MPU) - \brief Type definitions for the Memory Protection Unit (MPU) - @{ - */ - -/** \brief Structure type to access the Memory Protection Unit (MPU). - */ -typedef struct -{ - __I uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ - __IO uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ - __IO uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ - __IO uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ - __IO uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ - __IO uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ - __IO uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ - __IO uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ - __IO uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ - __IO uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ - __IO uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ -} MPU_Type; - -/* MPU Type Register */ -#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ -#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ - -#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ -#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ - -#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ -#define MPU_TYPE_SEPARATE_Msk (1UL << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ - -/* MPU Control Register */ -#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ -#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ - -#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ -#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ - -#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ -#define MPU_CTRL_ENABLE_Msk (1UL << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ - -/* MPU Region Number Register */ -#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ -#define MPU_RNR_REGION_Msk (0xFFUL << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ - -/* MPU Region Base Address Register */ -#define MPU_RBAR_ADDR_Pos 5 /*!< MPU RBAR: ADDR Position */ -#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ - -#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ -#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ - -#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ -#define MPU_RBAR_REGION_Msk (0xFUL << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ - -/* MPU Region Attribute and Size Register */ -#define MPU_RASR_ATTRS_Pos 16 /*!< MPU RASR: MPU Region Attribute field Position */ -#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ - -#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: ATTRS.XN Position */ -#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ - -#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: ATTRS.AP Position */ -#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ - -#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: ATTRS.TEX Position */ -#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ - -#define MPU_RASR_S_Pos 18 /*!< MPU RASR: ATTRS.S Position */ -#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ - -#define MPU_RASR_C_Pos 17 /*!< MPU RASR: ATTRS.C Position */ -#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ - -#define MPU_RASR_B_Pos 16 /*!< MPU RASR: ATTRS.B Position */ -#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ - -#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ -#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ - -#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ -#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ - -#define MPU_RASR_ENABLE_Pos 0 /*!< MPU RASR: Region enable bit Position */ -#define MPU_RASR_ENABLE_Msk (1UL << MPU_RASR_ENABLE_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ - -/*@} end of group CMSIS_MPU */ -#endif - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) - \brief Type definitions for the Core Debug Registers - @{ - */ - -/** \brief Structure type to access the Core Debug Register (CoreDebug). - */ -typedef struct -{ - __IO uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ - __O uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ - __IO uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ - __IO uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ -} CoreDebug_Type; - -/* Debug Halting Control and Status Register */ -#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */ -#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ - -#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */ -#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ - -#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ -#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ - -#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */ -#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ - -#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */ -#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ - -#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */ -#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ - -#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */ -#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ - -#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5 /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ -#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ - -#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */ -#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ - -#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */ -#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ - -#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */ -#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ - -#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */ -#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ - -/* Debug Core Register Selector Register */ -#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */ -#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ - -#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */ -#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */ - -/* Debug Exception and Monitor Control Register */ -#define CoreDebug_DEMCR_TRCENA_Pos 24 /*!< CoreDebug DEMCR: TRCENA Position */ -#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ - -#define CoreDebug_DEMCR_MON_REQ_Pos 19 /*!< CoreDebug DEMCR: MON_REQ Position */ -#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ - -#define CoreDebug_DEMCR_MON_STEP_Pos 18 /*!< CoreDebug DEMCR: MON_STEP Position */ -#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ - -#define CoreDebug_DEMCR_MON_PEND_Pos 17 /*!< CoreDebug DEMCR: MON_PEND Position */ -#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ - -#define CoreDebug_DEMCR_MON_EN_Pos 16 /*!< CoreDebug DEMCR: MON_EN Position */ -#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ - -#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */ -#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ - -#define CoreDebug_DEMCR_VC_INTERR_Pos 9 /*!< CoreDebug DEMCR: VC_INTERR Position */ -#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ - -#define CoreDebug_DEMCR_VC_BUSERR_Pos 8 /*!< CoreDebug DEMCR: VC_BUSERR Position */ -#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ - -#define CoreDebug_DEMCR_VC_STATERR_Pos 7 /*!< CoreDebug DEMCR: VC_STATERR Position */ -#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ - -#define CoreDebug_DEMCR_VC_CHKERR_Pos 6 /*!< CoreDebug DEMCR: VC_CHKERR Position */ -#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ - -#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5 /*!< CoreDebug DEMCR: VC_NOCPERR Position */ -#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ - -#define CoreDebug_DEMCR_VC_MMERR_Pos 4 /*!< CoreDebug DEMCR: VC_MMERR Position */ -#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ - -#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */ -#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ - -/*@} end of group CMSIS_CoreDebug */ - - -/** \ingroup CMSIS_core_register - \defgroup CMSIS_core_base Core Definitions - \brief Definitions for base addresses, unions, and structures. - @{ - */ - -/* Memory mapping of Cortex-M3 Hardware */ -#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ -#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ -#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ -#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ -#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ -#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ -#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ -#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ - -#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ -#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ -#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ -#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ -#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ -#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ -#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ -#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ - -#if (__MPU_PRESENT == 1) - #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ - #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ -#endif - -/*@} */ - - - -/******************************************************************************* - * Hardware Abstraction Layer - Core Function Interface contains: - - Core NVIC Functions - - Core SysTick Functions - - Core Debug Functions - - Core Register Access Functions - ******************************************************************************/ -/** \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference -*/ - - - -/* ########################## NVIC functions #################################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_NVICFunctions NVIC Functions - \brief Functions that manage interrupts and exceptions via the NVIC. - @{ - */ - -/** \brief Set Priority Grouping - - The function sets the priority grouping field using the required unlock sequence. - The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. - Only values from 0..7 are used. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. - - \param [in] PriorityGroup Priority grouping field. - */ -__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) -{ - uint32_t reg_value; - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07); /* only values 0..7 are used */ - - reg_value = SCB->AIRCR; /* read old register configuration */ - reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ - reg_value = (reg_value | - ((uint32_t)0x5FA << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ - SCB->AIRCR = reg_value; -} - - -/** \brief Get Priority Grouping - - The function reads the priority grouping field from the NVIC Interrupt Controller. - - \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). - */ -__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void) -{ - return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos); /* read priority grouping field */ -} - - -/** \brief Enable External Interrupt - - The function enables a device-specific interrupt in the NVIC interrupt controller. - - \param [in] IRQn External interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) -{ - NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */ -} - - -/** \brief Disable External Interrupt - - The function disables a device-specific interrupt in the NVIC interrupt controller. - - \param [in] IRQn External interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) -{ - NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ -} - - -/** \brief Get Pending Interrupt - - The function reads the pending register in the NVIC and returns the pending bit - for the specified interrupt. - - \param [in] IRQn Interrupt number. - - \return 0 Interrupt status is not pending. - \return 1 Interrupt status is pending. - */ -__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) -{ - return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */ -} - - -/** \brief Set Pending Interrupt - - The function sets the pending bit of an external interrupt. - - \param [in] IRQn Interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) -{ - NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ -} - - -/** \brief Clear Pending Interrupt - - The function clears the pending bit of an external interrupt. - - \param [in] IRQn External interrupt number. Value cannot be negative. - */ -__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) -{ - NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ -} - - -/** \brief Get Active Interrupt - - The function reads the active register in NVIC and returns the active bit. - - \param [in] IRQn Interrupt number. - - \return 0 Interrupt status is not active. - \return 1 Interrupt status is active. - */ -__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) -{ - return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */ -} - - -/** \brief Set Interrupt Priority - - The function sets the priority of an interrupt. - - \note The priority cannot be set for every core interrupt. - - \param [in] IRQn Interrupt number. - \param [in] priority Priority to set. - */ -__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) -{ - if(IRQn < 0) { - SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M System Interrupts */ - else { - NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ -} - - -/** \brief Get Interrupt Priority - - The function reads the priority of an interrupt. The interrupt - number can be positive to specify an external (device specific) - interrupt, or negative to specify an internal (core) interrupt. - - - \param [in] IRQn Interrupt number. - \return Interrupt Priority. Value is aligned automatically to the implemented - priority bits of the microcontroller. - */ -__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) -{ - - if(IRQn < 0) { - return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M system interrupts */ - else { - return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ -} - - -/** \brief Encode Priority - - The function encodes the priority for an interrupt with the given priority group, - preemptive priority value, and subpriority value. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS), the samllest possible priority group is set. - - \param [in] PriorityGroup Used priority group. - \param [in] PreemptPriority Preemptive priority value (starting from 0). - \param [in] SubPriority Subpriority value (starting from 0). - \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). - */ -__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) -{ - uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; - - PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; - SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; - - return ( - ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | - ((SubPriority & ((1 << (SubPriorityBits )) - 1))) - ); -} - - -/** \brief Decode Priority - - The function decodes an interrupt priority value with a given priority group to - preemptive priority value and subpriority value. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. - - \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). - \param [in] PriorityGroup Used priority group. - \param [out] pPreemptPriority Preemptive priority value (starting from 0). - \param [out] pSubPriority Subpriority value (starting from 0). - */ -__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) -{ - uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; - - PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; - SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; - - *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); - *pSubPriority = (Priority ) & ((1 << (SubPriorityBits )) - 1); -} - - -/** \brief System Reset - - The function initiates a system reset request to reset the MCU. - */ -__STATIC_INLINE void NVIC_SystemReset(void) -{ - __DSB(); /* Ensure all outstanding memory accesses included - buffered write are completed before reset */ - SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | - (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | - SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ - __DSB(); /* Ensure completion of memory access */ - while(1); /* wait until reset */ -} - -/*@} end of CMSIS_Core_NVICFunctions */ - - - -/* ################################## SysTick function ############################################ */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_SysTickFunctions SysTick Functions - \brief Functions that configure the System. - @{ - */ - -#if (__Vendor_SysTickConfig == 0) - -/** \brief System Tick Configuration - - The function initializes the System Timer and its interrupt, and starts the System Tick Timer. - Counter is in free running mode to generate periodic interrupts. - - \param [in] ticks Number of ticks between two interrupts. - - \return 0 Function succeeded. - \return 1 Function failed. - - \note When the variable __Vendor_SysTickConfig is set to 1, then the - function SysTick_Config is not included. In this case, the file device.h - must contain a vendor-specific implementation of this function. - - */ -__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) -{ - if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ - - SysTick->LOAD = ticks - 1; /* set reload register */ - NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */ - SysTick->VAL = 0; /* Load the SysTick Counter Value */ - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0); /* Function successful */ -} - -#endif - -/*@} end of CMSIS_Core_SysTickFunctions */ - - - -/* ##################################### Debug In/Output function ########################################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_core_DebugFunctions ITM Functions - \brief Functions that access the ITM debug interface. - @{ - */ - -extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ -#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ - - -/** \brief ITM Send Character - - The function transmits a character via the ITM channel 0, and - \li Just returns when no debugger is connected that has booked the output. - \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. - - \param [in] ch Character to transmit. - - \returns Character to transmit. - */ -__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) -{ - if ((ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ - (ITM->TER & (1UL << 0) ) ) /* ITM Port #0 enabled */ - { - while (ITM->PORT[0].u32 == 0); - ITM->PORT[0].u8 = (uint8_t) ch; - } - return (ch); -} - - -/** \brief ITM Receive Character - - The function inputs a character via the external variable \ref ITM_RxBuffer. - - \return Received character. - \return -1 No character pending. - */ -__STATIC_INLINE int32_t ITM_ReceiveChar (void) { - int32_t ch = -1; /* no character available */ - - if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { - ch = ITM_RxBuffer; - ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ - } - - return (ch); -} - - -/** \brief ITM Check Character - - The function checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. - - \return 0 No character available. - \return 1 Character available. - */ -__STATIC_INLINE int32_t ITM_CheckChar (void) { - - if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { - return (0); /* no character available */ - } else { - return (1); /* character available */ - } -} - -/*@} end of CMSIS_core_DebugFunctions */ - -#endif /* __CORE_CM3_H_DEPENDANT */ - -#endif /* __CMSIS_GENERIC */ - -#ifdef __cplusplus -} -#endif diff --git a/lib-gd32/gd32f20x/CMSIS/core_cmFunc.h b/lib-gd32/gd32f20x/CMSIS/core_cmFunc.h deleted file mode 100644 index adb07b5d..00000000 --- a/lib-gd32/gd32f20x/CMSIS/core_cmFunc.h +++ /dev/null @@ -1,616 +0,0 @@ -/**************************************************************************//** - * @file core_cmFunc.h - * @brief CMSIS Cortex-M Core Function Access Header File - * @version V3.01 - * @date 06. March 2012 - * - * @note - * Copyright (C) 2009-2012 ARM Limited. All rights reserved. - * - * @par - * ARM Limited (ARM) is supplying this software for use with Cortex-M - * processor based microcontrollers. This file can be freely distributed - * within development tools that are supporting such ARM based processors. - * - * @par - * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED - * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. - * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR - * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. - * - ******************************************************************************/ - -#ifndef __CORE_CMFUNC_H -#define __CORE_CMFUNC_H - - -/* ########################### Core Function Access ########################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions - @{ - */ - -#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ -/* ARM armcc specific functions */ - -#if (__ARMCC_VERSION < 400677) - #error "Please use ARM Compiler Toolchain V4.0.677 or later!" -#endif - -/* intrinsic void __enable_irq(); */ -/* intrinsic void __disable_irq(); */ - -/** \brief Get Control Register - - This function returns the content of the Control Register. - - \return Control Register value - */ -__STATIC_INLINE uint32_t __get_CONTROL(void) -{ - register uint32_t __regControl __ASM("control"); - return(__regControl); -} - - -/** \brief Set Control Register - - This function writes the given value to the Control Register. - - \param [in] control Control Register value to set - */ -__STATIC_INLINE void __set_CONTROL(uint32_t control) -{ - register uint32_t __regControl __ASM("control"); - __regControl = control; -} - - -/** \brief Get IPSR Register - - This function returns the content of the IPSR Register. - - \return IPSR Register value - */ -__STATIC_INLINE uint32_t __get_IPSR(void) -{ - register uint32_t __regIPSR __ASM("ipsr"); - return(__regIPSR); -} - - -/** \brief Get APSR Register - - This function returns the content of the APSR Register. - - \return APSR Register value - */ -__STATIC_INLINE uint32_t __get_APSR(void) -{ - register uint32_t __regAPSR __ASM("apsr"); - return(__regAPSR); -} - - -/** \brief Get xPSR Register - - This function returns the content of the xPSR Register. - - \return xPSR Register value - */ -__STATIC_INLINE uint32_t __get_xPSR(void) -{ - register uint32_t __regXPSR __ASM("xpsr"); - return(__regXPSR); -} - - -/** \brief Get Process Stack Pointer - - This function returns the current value of the Process Stack Pointer (PSP). - - \return PSP Register value - */ -__STATIC_INLINE uint32_t __get_PSP(void) -{ - register uint32_t __regProcessStackPointer __ASM("psp"); - return(__regProcessStackPointer); -} - - -/** \brief Set Process Stack Pointer - - This function assigns the given value to the Process Stack Pointer (PSP). - - \param [in] topOfProcStack Process Stack Pointer value to set - */ -__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) -{ - register uint32_t __regProcessStackPointer __ASM("psp"); - __regProcessStackPointer = topOfProcStack; -} - - -/** \brief Get Main Stack Pointer - - This function returns the current value of the Main Stack Pointer (MSP). - - \return MSP Register value - */ -__STATIC_INLINE uint32_t __get_MSP(void) -{ - register uint32_t __regMainStackPointer __ASM("msp"); - return(__regMainStackPointer); -} - - -/** \brief Set Main Stack Pointer - - This function assigns the given value to the Main Stack Pointer (MSP). - - \param [in] topOfMainStack Main Stack Pointer value to set - */ -__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) -{ - register uint32_t __regMainStackPointer __ASM("msp"); - __regMainStackPointer = topOfMainStack; -} - - -/** \brief Get Priority Mask - - This function returns the current state of the priority mask bit from the Priority Mask Register. - - \return Priority Mask value - */ -__STATIC_INLINE uint32_t __get_PRIMASK(void) -{ - register uint32_t __regPriMask __ASM("primask"); - return(__regPriMask); -} - - -/** \brief Set Priority Mask - - This function assigns the given value to the Priority Mask Register. - - \param [in] priMask Priority Mask - */ -__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) -{ - register uint32_t __regPriMask __ASM("primask"); - __regPriMask = (priMask); -} - - -#if (__CORTEX_M >= 0x03) - -/** \brief Enable FIQ - - This function enables FIQ interrupts by clearing the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -#define __enable_fault_irq __enable_fiq - - -/** \brief Disable FIQ - - This function disables FIQ interrupts by setting the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -#define __disable_fault_irq __disable_fiq - - -/** \brief Get Base Priority - - This function returns the current value of the Base Priority register. - - \return Base Priority register value - */ -__STATIC_INLINE uint32_t __get_BASEPRI(void) -{ - register uint32_t __regBasePri __ASM("basepri"); - return(__regBasePri); -} - - -/** \brief Set Base Priority - - This function assigns the given value to the Base Priority register. - - \param [in] basePri Base Priority value to set - */ -__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) -{ - register uint32_t __regBasePri __ASM("basepri"); - __regBasePri = (basePri & 0xff); -} - - -/** \brief Get Fault Mask - - This function returns the current value of the Fault Mask register. - - \return Fault Mask register value - */ -__STATIC_INLINE uint32_t __get_FAULTMASK(void) -{ - register uint32_t __regFaultMask __ASM("faultmask"); - return(__regFaultMask); -} - - -/** \brief Set Fault Mask - - This function assigns the given value to the Fault Mask register. - - \param [in] faultMask Fault Mask value to set - */ -__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) -{ - register uint32_t __regFaultMask __ASM("faultmask"); - __regFaultMask = (faultMask & (uint32_t)1); -} - -#endif /* (__CORTEX_M >= 0x03) */ - - -#if (__CORTEX_M == 0x04) - -/** \brief Get FPSCR - - This function returns the current value of the Floating Point Status/Control register. - - \return Floating Point Status/Control register value - */ -__STATIC_INLINE uint32_t __get_FPSCR(void) -{ -#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) - register uint32_t __regfpscr __ASM("fpscr"); - return(__regfpscr); -#else - return(0); -#endif -} - - -/** \brief Set FPSCR - - This function assigns the given value to the Floating Point Status/Control register. - - \param [in] fpscr Floating Point Status/Control value to set - */ -__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) -{ -#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) - register uint32_t __regfpscr __ASM("fpscr"); - __regfpscr = (fpscr); -#endif -} - -#endif /* (__CORTEX_M == 0x04) */ - - -#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ -/* IAR iccarm specific functions */ - -#include - - -#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ -/* TI CCS specific functions */ - -#include - - -#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ -/* GNU gcc specific functions */ - -/** \brief Enable IRQ Interrupts - - This function enables IRQ interrupts by clearing the I-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) -{ - __ASM volatile ("cpsie i"); -} - - -/** \brief Disable IRQ Interrupts - - This function disables IRQ interrupts by setting the I-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) -{ - __ASM volatile ("cpsid i"); -} - - -/** \brief Get Control Register - - This function returns the content of the Control Register. - - \return Control Register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, control" : "=r" (result) ); - return(result); -} - - -/** \brief Set Control Register - - This function writes the given value to the Control Register. - - \param [in] control Control Register value to set - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) -{ - __ASM volatile ("MSR control, %0" : : "r" (control) ); -} - - -/** \brief Get IPSR Register - - This function returns the content of the IPSR Register. - - \return IPSR Register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); - return(result); -} - - -/** \brief Get APSR Register - - This function returns the content of the APSR Register. - - \return APSR Register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, apsr" : "=r" (result) ); - return(result); -} - - -/** \brief Get xPSR Register - - This function returns the content of the xPSR Register. - - \return xPSR Register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); - return(result); -} - - -/** \brief Get Process Stack Pointer - - This function returns the current value of the Process Stack Pointer (PSP). - - \return PSP Register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) -{ - register uint32_t result; - - __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); - return(result); -} - - -/** \brief Set Process Stack Pointer - - This function assigns the given value to the Process Stack Pointer (PSP). - - \param [in] topOfProcStack Process Stack Pointer value to set - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) -{ - __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) ); -} - - -/** \brief Get Main Stack Pointer - - This function returns the current value of the Main Stack Pointer (MSP). - - \return MSP Register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) -{ - register uint32_t result; - - __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); - return(result); -} - - -/** \brief Set Main Stack Pointer - - This function assigns the given value to the Main Stack Pointer (MSP). - - \param [in] topOfMainStack Main Stack Pointer value to set - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) -{ - __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) ); -} - - -/** \brief Get Priority Mask - - This function returns the current state of the priority mask bit from the Priority Mask Register. - - \return Priority Mask value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, primask" : "=r" (result) ); - return(result); -} - - -/** \brief Set Priority Mask - - This function assigns the given value to the Priority Mask Register. - - \param [in] priMask Priority Mask - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) -{ - __ASM volatile ("MSR primask, %0" : : "r" (priMask) ); -} - - -#if (__CORTEX_M >= 0x03) - -/** \brief Enable FIQ - - This function enables FIQ interrupts by clearing the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) -{ - __ASM volatile ("cpsie f"); -} - - -/** \brief Disable FIQ - - This function disables FIQ interrupts by setting the F-bit in the CPSR. - Can only be executed in Privileged modes. - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) -{ - __ASM volatile ("cpsid f"); -} - - -/** \brief Get Base Priority - - This function returns the current value of the Base Priority register. - - \return Base Priority register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); - return(result); -} - - -/** \brief Set Base Priority - - This function assigns the given value to the Base Priority register. - - \param [in] basePri Base Priority value to set - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) -{ - __ASM volatile ("MSR basepri, %0" : : "r" (value) ); -} - - -/** \brief Get Fault Mask - - This function returns the current value of the Fault Mask register. - - \return Fault Mask register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); - return(result); -} - - -/** \brief Set Fault Mask - - This function assigns the given value to the Fault Mask register. - - \param [in] faultMask Fault Mask value to set - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) -{ - __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) ); -} - -#endif /* (__CORTEX_M >= 0x03) */ - - -#if (__CORTEX_M == 0x04) - -/** \brief Get FPSCR - - This function returns the current value of the Floating Point Status/Control register. - - \return Floating Point Status/Control register value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) -{ -#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) - uint32_t result; - - __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); - return(result); -#else - return(0); -#endif -} - - -/** \brief Set FPSCR - - This function assigns the given value to the Floating Point Status/Control register. - - \param [in] fpscr Floating Point Status/Control value to set - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) -{ -#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) - __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) ); -#endif -} - -#endif /* (__CORTEX_M == 0x04) */ - - -#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ -/* TASKING carm specific functions */ - -/* - * The CMSIS functions have been implemented as intrinsics in the compiler. - * Please use "carm -?i" to get an up to date list of all instrinsics, - * Including the CMSIS ones. - */ - -#endif - -/*@} end of CMSIS_Core_RegAccFunctions */ - - -#endif /* __CORE_CMFUNC_H */ diff --git a/lib-gd32/gd32f20x/CMSIS/core_cmInstr.h b/lib-gd32/gd32f20x/CMSIS/core_cmInstr.h deleted file mode 100644 index 624c175f..00000000 --- a/lib-gd32/gd32f20x/CMSIS/core_cmInstr.h +++ /dev/null @@ -1,618 +0,0 @@ -/**************************************************************************//** - * @file core_cmInstr.h - * @brief CMSIS Cortex-M Core Instruction Access Header File - * @version V3.01 - * @date 06. March 2012 - * - * @note - * Copyright (C) 2009-2012 ARM Limited. All rights reserved. - * - * @par - * ARM Limited (ARM) is supplying this software for use with Cortex-M - * processor based microcontrollers. This file can be freely distributed - * within development tools that are supporting such ARM based processors. - * - * @par - * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED - * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. - * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR - * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. - * - ******************************************************************************/ - -#ifndef __CORE_CMINSTR_H -#define __CORE_CMINSTR_H - - -/* ########################## Core Instruction Access ######################### */ -/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface - Access to dedicated instructions - @{ -*/ - -#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ -/* ARM armcc specific functions */ - -#if (__ARMCC_VERSION < 400677) - #error "Please use ARM Compiler Toolchain V4.0.677 or later!" -#endif - - -/** \brief No Operation - - No Operation does nothing. This instruction can be used for code alignment purposes. - */ -#define __NOP __nop - - -/** \brief Wait For Interrupt - - Wait For Interrupt is a hint instruction that suspends execution - until one of a number of events occurs. - */ -#define __WFI __wfi - - -/** \brief Wait For Event - - Wait For Event is a hint instruction that permits the processor to enter - a low-power state until one of a number of events occurs. - */ -#define __WFE __wfe - - -/** \brief Send Event - - Send Event is a hint instruction. It causes an event to be signaled to the CPU. - */ -#define __SEV __sev - - -/** \brief Instruction Synchronization Barrier - - Instruction Synchronization Barrier flushes the pipeline in the processor, - so that all instructions following the ISB are fetched from cache or - memory, after the instruction has been completed. - */ -#define __ISB() __isb(0xF) - - -/** \brief Data Synchronization Barrier - - This function acts as a special kind of Data Memory Barrier. - It completes when all explicit memory accesses before this instruction complete. - */ -#define __DSB() __dsb(0xF) - - -/** \brief Data Memory Barrier - - This function ensures the apparent order of the explicit memory operations before - and after the instruction, without ensuring their completion. - */ -#define __DMB() __dmb(0xF) - - -/** \brief Reverse byte order (32 bit) - - This function reverses the byte order in integer value. - - \param [in] value Value to reverse - \return Reversed value - */ -#define __REV __rev - - -/** \brief Reverse byte order (16 bit) - - This function reverses the byte order in two unsigned short values. - - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) -{ - rev16 r0, r0 - bx lr -} - - -/** \brief Reverse byte order in signed short value - - This function reverses the byte order in a signed short value with sign extension to integer. - - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) -{ - revsh r0, r0 - bx lr -} - - -/** \brief Rotate Right in unsigned value (32 bit) - - This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. - - \param [in] value Value to rotate - \param [in] value Number of Bits to rotate - \return Rotated value - */ -#define __ROR __ror - - -#if (__CORTEX_M >= 0x03) - -/** \brief Reverse bit order of value - - This function reverses the bit order of the given value. - - \param [in] value Value to reverse - \return Reversed value - */ -#define __RBIT __rbit - - -/** \brief LDR Exclusive (8 bit) - - This function performs a exclusive LDR command for 8 bit value. - - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) - - -/** \brief LDR Exclusive (16 bit) - - This function performs a exclusive LDR command for 16 bit values. - - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) - - -/** \brief LDR Exclusive (32 bit) - - This function performs a exclusive LDR command for 32 bit values. - - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) - - -/** \brief STR Exclusive (8 bit) - - This function performs a exclusive STR command for 8 bit values. - - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#define __STREXB(value, ptr) __strex(value, ptr) - - -/** \brief STR Exclusive (16 bit) - - This function performs a exclusive STR command for 16 bit values. - - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#define __STREXH(value, ptr) __strex(value, ptr) - - -/** \brief STR Exclusive (32 bit) - - This function performs a exclusive STR command for 32 bit values. - - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#define __STREXW(value, ptr) __strex(value, ptr) - - -/** \brief Remove the exclusive lock - - This function removes the exclusive lock which is created by LDREX. - - */ -#define __CLREX __clrex - - -/** \brief Signed Saturate - - This function saturates a signed value. - - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value - */ -#define __SSAT __ssat - - -/** \brief Unsigned Saturate - - This function saturates an unsigned value. - - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value - */ -#define __USAT __usat - - -/** \brief Count leading zeros - - This function counts the number of leading zeros of a data value. - - \param [in] value Value to count the leading zeros - \return number of leading zeros in value - */ -#define __CLZ __clz - -#endif /* (__CORTEX_M >= 0x03) */ - - - -#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ -/* IAR iccarm specific functions */ - -#include - - -#elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ -/* TI CCS specific functions */ - -#include - - -#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ -/* GNU gcc specific functions */ - -/** \brief No Operation - - No Operation does nothing. This instruction can be used for code alignment purposes. - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) -{ - __ASM volatile ("nop"); -} - - -/** \brief Wait For Interrupt - - Wait For Interrupt is a hint instruction that suspends execution - until one of a number of events occurs. - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) -{ - __ASM volatile ("wfi"); -} - - -/** \brief Wait For Event - - Wait For Event is a hint instruction that permits the processor to enter - a low-power state until one of a number of events occurs. - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) -{ - __ASM volatile ("wfe"); -} - - -/** \brief Send Event - - Send Event is a hint instruction. It causes an event to be signaled to the CPU. - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) -{ - __ASM volatile ("sev"); -} - - -/** \brief Instruction Synchronization Barrier - - Instruction Synchronization Barrier flushes the pipeline in the processor, - so that all instructions following the ISB are fetched from cache or - memory, after the instruction has been completed. - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) -{ - __ASM volatile ("isb"); -} - - -/** \brief Data Synchronization Barrier - - This function acts as a special kind of Data Memory Barrier. - It completes when all explicit memory accesses before this instruction complete. - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) -{ - __ASM volatile ("dsb"); -} - - -/** \brief Data Memory Barrier - - This function ensures the apparent order of the explicit memory operations before - and after the instruction, without ensuring their completion. - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) -{ - __ASM volatile ("dmb"); -} - - -/** \brief Reverse byte order (32 bit) - - This function reverses the byte order in integer value. - - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) -{ - uint32_t result; - - __ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) ); - return(result); -} - - -/** \brief Reverse byte order (16 bit) - - This function reverses the byte order in two unsigned short values. - - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) -{ - uint32_t result; - - __ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) ); - return(result); -} - - -/** \brief Reverse byte order in signed short value - - This function reverses the byte order in a signed short value with sign extension to integer. - - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) -{ - uint32_t result; - - __ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) ); - return(result); -} - - -/** \brief Rotate Right in unsigned value (32 bit) - - This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. - - \param [in] value Value to rotate - \param [in] value Number of Bits to rotate - \return Rotated value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) -{ - - __ASM volatile ("ror %0, %0, %1" : "+r" (op1) : "r" (op2) ); - return(op1); -} - - -#if (__CORTEX_M >= 0x03) - -/** \brief Reverse bit order of value - - This function reverses the bit order of the given value. - - \param [in] value Value to reverse - \return Reversed value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) -{ - uint32_t result; - - __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); - return(result); -} - - -/** \brief LDR Exclusive (8 bit) - - This function performs a exclusive LDR command for 8 bit value. - - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) -{ - uint8_t result; - - __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) ); - return(result); -} - - -/** \brief LDR Exclusive (16 bit) - - This function performs a exclusive LDR command for 16 bit values. - - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) -{ - uint16_t result; - - __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) ); - return(result); -} - - -/** \brief LDR Exclusive (32 bit) - - This function performs a exclusive LDR command for 32 bit values. - - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) -{ - uint32_t result; - - __ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) ); - return(result); -} - - -/** \brief STR Exclusive (8 bit) - - This function performs a exclusive STR command for 8 bit values. - - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) -{ - uint32_t result; - - __ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); - return(result); -} - - -/** \brief STR Exclusive (16 bit) - - This function performs a exclusive STR command for 16 bit values. - - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) -{ - uint32_t result; - - __ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); - return(result); -} - - -/** \brief STR Exclusive (32 bit) - - This function performs a exclusive STR command for 32 bit values. - - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) -{ - uint32_t result; - - __ASM volatile ("strex %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); - return(result); -} - - -/** \brief Remove the exclusive lock - - This function removes the exclusive lock which is created by LDREX. - - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) -{ - __ASM volatile ("clrex"); -} - - -/** \brief Signed Saturate - - This function saturates a signed value. - - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value - */ -#define __SSAT(ARG1,ARG2) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1); \ - __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ - __RES; \ - }) - - -/** \brief Unsigned Saturate - - This function saturates an unsigned value. - - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value - */ -#define __USAT(ARG1,ARG2) \ -({ \ - uint32_t __RES, __ARG1 = (ARG1); \ - __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ - __RES; \ - }) - - -/** \brief Count leading zeros - - This function counts the number of leading zeros of a data value. - - \param [in] value Value to count the leading zeros - \return number of leading zeros in value - */ -__attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) -{ - uint8_t result; - - __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); - return(result); -} - -#endif /* (__CORTEX_M >= 0x03) */ - - - - -#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ -/* TASKING carm specific functions */ - -/* - * The CMSIS functions have been implemented as intrinsics in the compiler. - * Please use "carm -?i" to get an up to date list of all intrinsics, - * Including the CMSIS ones. - */ - -#endif - -/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ - -#endif /* __CORE_CMINSTR_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_adc.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_adc.h index 265cbfa0..fb18a2bc 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_adc.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_adc.h @@ -2,36 +2,33 @@ \file gd32f20x_adc.h \brief definitions for the ADC - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -42,31 +39,31 @@ OF SUCH DAMAGE. /* ADC definitions */ #define ADC0 ADC_BASE -#define ADC1 (ADC_BASE + 0x400U) -#define ADC2 (ADC_BASE + 0x1800U) +#define ADC1 (ADC_BASE + 0x00000400U) +#define ADC2 (ADC_BASE + 0x00001800U) /* registers definitions */ -#define ADC_STAT(adcx) REG32((adcx) + 0x00U) /*!< ADC status register */ -#define ADC_CTL0(adcx) REG32((adcx) + 0x04U) /*!< ADC control register 0 */ -#define ADC_CTL1(adcx) REG32((adcx) + 0x08U) /*!< ADC control register 1 */ -#define ADC_SAMPT0(adcx) REG32((adcx) + 0x0CU) /*!< ADC sampling time register 0 */ -#define ADC_SAMPT1(adcx) REG32((adcx) + 0x10U) /*!< ADC sampling time register 1 */ -#define ADC_IOFF0(adcx) REG32((adcx) + 0x14U) /*!< ADC inserted channel data offset register 0 */ -#define ADC_IOFF1(adcx) REG32((adcx) + 0x18U) /*!< ADC inserted channel data offset register 1 */ -#define ADC_IOFF2(adcx) REG32((adcx) + 0x1CU) /*!< ADC inserted channel data offset register 2 */ -#define ADC_IOFF3(adcx) REG32((adcx) + 0x20U) /*!< ADC inserted channel data offset register 3 */ -#define ADC_WDHT(adcx) REG32((adcx) + 0x24U) /*!< ADC watchdog high threshold register */ -#define ADC_WDLT(adcx) REG32((adcx) + 0x28U) /*!< ADC watchdog low threshold register */ -#define ADC_RSQ0(adcx) REG32((adcx) + 0x2CU) /*!< ADC regular sequence register 0 */ -#define ADC_RSQ1(adcx) REG32((adcx) + 0x30U) /*!< ADC regular sequence register 1 */ -#define ADC_RSQ2(adcx) REG32((adcx) + 0x34U) /*!< ADC regular sequence register 2 */ -#define ADC_ISQ(adcx) REG32((adcx) + 0x38U) /*!< ADC inserted sequence register */ -#define ADC_IDATA0(adcx) REG32((adcx) + 0x3CU) /*!< ADC inserted data register 0 */ -#define ADC_IDATA1(adcx) REG32((adcx) + 0x40U) /*!< ADC inserted data register 1 */ -#define ADC_IDATA2(adcx) REG32((adcx) + 0x44U) /*!< ADC inserted data register 2 */ -#define ADC_IDATA3(adcx) REG32((adcx) + 0x48U) /*!< ADC inserted data register 3 */ -#define ADC_RDATA(adcx) REG32((adcx) + 0x4CU) /*!< ADC regular data register */ -#define ADC_OVSAMPCTL(adcx) REG32((adcx) + 0x80U) /*!< ADC oversampling control register */ +#define ADC_STAT(adcx) REG32((adcx) + 0x00000000U) /*!< ADC status register */ +#define ADC_CTL0(adcx) REG32((adcx) + 0x00000004U) /*!< ADC control register 0 */ +#define ADC_CTL1(adcx) REG32((adcx) + 0x00000008U) /*!< ADC control register 1 */ +#define ADC_SAMPT0(adcx) REG32((adcx) + 0x0000000CU) /*!< ADC sampling time register 0 */ +#define ADC_SAMPT1(adcx) REG32((adcx) + 0x00000010U) /*!< ADC sampling time register 1 */ +#define ADC_IOFF0(adcx) REG32((adcx) + 0x00000014U) /*!< ADC inserted channel data offset register 0 */ +#define ADC_IOFF1(adcx) REG32((adcx) + 0x00000018U) /*!< ADC inserted channel data offset register 1 */ +#define ADC_IOFF2(adcx) REG32((adcx) + 0x0000001CU) /*!< ADC inserted channel data offset register 2 */ +#define ADC_IOFF3(adcx) REG32((adcx) + 0x00000020U) /*!< ADC inserted channel data offset register 3 */ +#define ADC_WDHT(adcx) REG32((adcx) + 0x00000024U) /*!< ADC watchdog high threshold register */ +#define ADC_WDLT(adcx) REG32((adcx) + 0x00000028U) /*!< ADC watchdog low threshold register */ +#define ADC_RSQ0(adcx) REG32((adcx) + 0x0000002CU) /*!< ADC regular sequence register 0 */ +#define ADC_RSQ1(adcx) REG32((adcx) + 0x00000030U) /*!< ADC regular sequence register 1 */ +#define ADC_RSQ2(adcx) REG32((adcx) + 0x00000034U) /*!< ADC regular sequence register 2 */ +#define ADC_ISQ(adcx) REG32((adcx) + 0x00000038U) /*!< ADC inserted sequence register */ +#define ADC_IDATA0(adcx) REG32((adcx) + 0x0000003CU) /*!< ADC inserted data register 0 */ +#define ADC_IDATA1(adcx) REG32((adcx) + 0x00000040U) /*!< ADC inserted data register 1 */ +#define ADC_IDATA2(adcx) REG32((adcx) + 0x00000044U) /*!< ADC inserted data register 2 */ +#define ADC_IDATA3(adcx) REG32((adcx) + 0x00000048U) /*!< ADC inserted data register 3 */ +#define ADC_RDATA(adcx) REG32((adcx) + 0x0000004CU) /*!< ADC regular data register */ +#define ADC_OVSAMPCTL(adcx) REG32((adcx) + 0x00000080U) /*!< ADC oversampling control register */ /* bits definitions */ /* ADC_STAT */ @@ -96,7 +93,7 @@ OF SUCH DAMAGE. #define ADC_CTL1_CTN BIT(1) /*!< continuous conversion */ #define ADC_CTL1_CLB BIT(2) /*!< ADC calibration */ #define ADC_CTL1_RSTCLB BIT(3) /*!< reset calibration */ -#define ADC_CTL1_DMA BIT(8) /*!< direct memory access mode */ +#define ADC_CTL1_DMA BIT(8) /*!< DMA request enable */ #define ADC_CTL1_DAL BIT(11) /*!< data alignment */ #define ADC_CTL1_ETSIC BITS(12,14) /*!< external trigger select for inserted channel */ #define ADC_CTL1_ETEIC BIT(15) /*!< external trigger enable for inserted channel */ @@ -138,15 +135,15 @@ OF SUCH DAMAGE. #define ADC_OVSAMPCTL_OVSR BITS(2,4) /*!< oversampling ratio */ #define ADC_OVSAMPCTL_OVSS BITS(5,8) /*!< oversampling shift */ #define ADC_OVSAMPCTL_TOVS BIT(9) /*!< triggered oversampling */ -#define ADC_OVSAMPCTL_DRES BITS(12,13) /*!< oversampling shift */ +#define ADC_OVSAMPCTL_DRES BITS(12, 13) /*!< ADC resolution */ /* constants definitions */ -/* adc_stat register value */ -#define ADC_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event flag */ -#define ADC_FLAG_EOC ADC_STAT_EOC /*!< end of group conversion flag */ -#define ADC_FLAG_EOIC ADC_STAT_EOIC /*!< end of inserted channel group conversion flag */ -#define ADC_FLAG_STIC ADC_STAT_STIC /*!< inserted channel start flag */ -#define ADC_FLAG_STRC ADC_STAT_STRC /*!< regular channel start flag */ +/* ADC flag definitions */ +#define ADC_FLAG_WDE ADC_STAT_WDE /*!< analog watchdog event flag */ +#define ADC_FLAG_EOC ADC_STAT_EOC /*!< end of conversion */ +#define ADC_FLAG_EOIC ADC_STAT_EOIC /*!< end of inserted channel group conversion flag */ +#define ADC_FLAG_STIC ADC_STAT_STIC /*!< inserted channel start flag */ +#define ADC_FLAG_STRC ADC_STAT_STRC /*!< regular channel start flag */ /* adc_ctl0 register value */ #define CTL0_DISNUM(regval) (BITS(13,15) & ((uint32_t)(regval) << 13)) /*!< write value to ADC_CTL0_DISNUM bit field */ @@ -198,7 +195,7 @@ OF SUCH DAMAGE. #define ADC2_EXTTRIG_REGULAR_T4_CH0 CTL1_ETSRC(5) /*!< TIMER4 CH0 event select */ #define ADC2_EXTTRIG_REGULAR_T4_CH2 CTL1_ETSRC(6) /*!< TIMER4 CH2 event select */ -/* external trigger mode for inserted channel */ +/* ADC external trigger select for inserted channel */ #define CTL1_ETSIC(regval) (BITS(12,14) & ((uint32_t)(regval) << 12)) /*!< write value to ADC_CTL1_ETSIC bit field */ /* for ADC0 and ADC1 inserted channel */ #define ADC0_1_EXTTRIG_INSERTED_T0_TRGO CTL1_ETSIC(0) /*!< TIMER0 TRGO event select */ @@ -246,12 +243,14 @@ OF SUCH DAMAGE. #define ISQ_IL(regval) (BITS(20,21) & ((uint32_t)(regval) << 20)) /*!< write value to ADC_ISQ_IL bit field */ /* adc_ovsampctl register value */ +/* ADC resolution */ #define OVSAMPCTL_DRES(regval) (BITS(12,13) & ((uint32_t)(regval) << 12)) /*!< write value to ADC_OVSAMPCTL_DRES bit field */ #define ADC_RESOLUTION_12B OVSAMPCTL_DRES(0) /*!< 12-bit ADC resolution */ #define ADC_RESOLUTION_10B OVSAMPCTL_DRES(1) /*!< 10-bit ADC resolution */ #define ADC_RESOLUTION_8B OVSAMPCTL_DRES(2) /*!< 8-bit ADC resolution */ #define ADC_RESOLUTION_6B OVSAMPCTL_DRES(3) /*!< 6-bit ADC resolution */ +/* oversampling shift */ #define OVSAMPCTL_OVSS(regval) (BITS(5,8) & ((uint32_t)(regval) << 5)) /*!< write value to ADC_OVSAMPCTL_OVSS bit field */ #define ADC_OVERSAMPLING_SHIFT_NONE OVSAMPCTL_OVSS(0) /*!< no oversampling shift */ #define ADC_OVERSAMPLING_SHIFT_1B OVSAMPCTL_OVSS(1) /*!< 1-bit oversampling shift */ @@ -263,6 +262,7 @@ OF SUCH DAMAGE. #define ADC_OVERSAMPLING_SHIFT_7B OVSAMPCTL_OVSS(7) /*!< 7-bit oversampling shift */ #define ADC_OVERSAMPLING_SHIFT_8B OVSAMPCTL_OVSS(8) /*!< 8-bit oversampling shift */ +/* oversampling ratio */ #define OVSAMPCTL_OVSR(regval) (BITS(2,4) & ((uint32_t)(regval) << 2)) /*!< write value to ADC_OVSAMPCTL_OVSR bit field */ #define ADC_OVERSAMPLING_RATIO_MUL2 OVSAMPCTL_OVSR(0) /*!< oversampling ratio multiple 2 */ #define ADC_OVERSAMPLING_RATIO_MUL4 OVSAMPCTL_OVSR(1) /*!< oversampling ratio multiple 4 */ @@ -273,6 +273,7 @@ OF SUCH DAMAGE. #define ADC_OVERSAMPLING_RATIO_MUL128 OVSAMPCTL_OVSR(6) /*!< oversampling ratio multiple 128 */ #define ADC_OVERSAMPLING_RATIO_MUL256 OVSAMPCTL_OVSR(7) /*!< oversampling ratio multiple 256 */ +/* triggered oversampling */ #define ADC_OVERSAMPLING_ALL_CONVERT 0U /*!< all oversampled conversions for a channel are done consecutively after a trigger */ #define ADC_OVERSAMPLING_ONE_CONVERT 1U /*!< each oversampled conversion for a channel needs a trigger */ @@ -367,7 +368,7 @@ void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, /* enable ADC software trigger */ void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group); -/* get channel data */ +/* ADC data read functions */ /* read ADC regular group data register */ uint16_t adc_regular_data_read(uint32_t adc_periph); /* read ADC inserted group data register */ @@ -375,7 +376,7 @@ uint16_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel); /* read the last ADC0 and ADC1 conversion result data in sync mode */ uint32_t adc_sync_mode_convert_value_read(void); -/* watchdog configure */ +/* ADC analog watchdog functions */ /* configure ADC analog watchdog single channel */ void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel); /* configure ADC analog watchdog group channel */ @@ -385,20 +386,6 @@ void adc_watchdog_disable(uint32_t adc_periph); /* configure ADC analog watchdog threshold */ void adc_watchdog_threshold_config(uint32_t adc_periph, uint16_t low_threshold, uint16_t high_threshold); -/* interrupt & flag functions */ -/* get the ADC flag bits */ -FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag); -/* clear the ADC flag bits */ -void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag); -/* get the ADC interrupt flag */ -FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt); -/* clear the ADC interrupt flag */ -void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt); -/* enable ADC interrupt */ -void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt); -/* disable ADC interrupt */ -void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt); - /* configure ADC resolution */ void adc_resolution_config(uint32_t adc_periph, uint32_t resolution); /* configure ADC oversample mode */ @@ -408,4 +395,18 @@ void adc_oversample_mode_enable(uint32_t adc_periph); /* disable ADC oversample mode */ void adc_oversample_mode_disable(uint32_t adc_periph); +/* interrupt & flag functions */ +/* get the ADC flag */ +FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag); +/* clear the ADC flag */ +void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag); +/* enable ADC interrupt */ +void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt); +/* disable ADC interrupt */ +void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt); +/* get the ADC interrupt flag */ +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt); +/* clear the ADC interrupt flag */ +void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt); + #endif /* GD32F20X_ADC_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_bkp.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_bkp.h index fe853a8a..2453d790 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_bkp.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_bkp.h @@ -2,36 +2,33 @@ \file gd32f20x_bkp.h \brief definitions for the BKP - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -111,13 +108,13 @@ OF SUCH DAMAGE. #define BKP_TPCS_TER0 BIT(0) /*!< tamper0 event reset */ #define BKP_TPCS_TIR0 BIT(1) /*!< tamper0 interrupt reset */ #define BKP_TPCS_TPIE0 BIT(2) /*!< tamper0 interrupt enable */ -#define BKP_TPCS_TER1 BIT(5) /*!< tamper1 event reset */ -#define BKP_TPCS_TIR1 BIT(6) /*!< tamper1 interrupt reset */ -#define BKP_TPCS_TPIE1 BIT(7) /*!< tamper1 interrupt enable */ +#define BKP_TPCS_TER1 BIT(5) /*!< tamper1/waveform detect event reset */ +#define BKP_TPCS_TIR1 BIT(6) /*!< tamper1/waveform detect interrupt reset */ +#define BKP_TPCS_TPIE1 BIT(7) /*!< tamper1/waveform detect interrupt enable */ #define BKP_TPCS_TEF0 BIT(8) /*!< tamper0 event flag */ #define BKP_TPCS_TIF0 BIT(9) /*!< tamper0 interrupt flag */ -#define BKP_TPCS_TEF1 BIT(14) /*!< tamper1 event flag */ -#define BKP_TPCS_TIF1 BIT(15) /*!< tamper1 interrupt flag */ +#define BKP_TPCS_TEF1 BIT(14) /*!< tamper1/waveform detect event flag */ +#define BKP_TPCS_TIF1 BIT(15) /*!< tamper1/waveform detect interrupt flag */ /* BKP_TPCTL1 */ #define BKP_TPCTL1_TPEN1 BIT(8) /*!< tamper1 detection enable */ @@ -126,16 +123,8 @@ OF SUCH DAMAGE. #define BKP_TPCTL1_TPM1 BIT(15) /*!< the first waveform detection enable */ /* constants definitions */ -/* tamperx definitions */ -typedef enum -{ - TAMPER_0 = 0, /*!< BKP tamper0 */ - TAMPER_1, /*!< BKP tamper1 */ -}bkp_tamper_enum; - /* BKP data register number */ -typedef enum -{ +typedef enum { BKP_DATA_0 = 1, /*!< BKP data register 0 */ BKP_DATA_1, /*!< BKP data register 1 */ BKP_DATA_2, /*!< BKP data register 2 */ @@ -177,8 +166,14 @@ typedef enum BKP_DATA_38, /*!< BKP data register 38 */ BKP_DATA_39, /*!< BKP data register 39 */ BKP_DATA_40, /*!< BKP data register 40 */ - BKP_DATA_41, /*!< BKP data register 41 */ -}bkp_data_register_enum; + BKP_DATA_41 /*!< BKP data register 41 */ +} bkp_data_register_enum; + +/* tamperx definitions */ +typedef enum { + TAMPER_0 = 0, /*!< BKP tamper0 */ + TAMPER_1 /*!< BKP tamper1 */ +} bkp_tamper_enum; /* BKP register */ #define BKP_DATA0_9(number) REG16((BKP) + 0x04U + (number) * 0x04U) @@ -199,7 +194,7 @@ typedef enum #define RTC_CLOCK_DIV1 ((uint16_t)0x4000U) /*!< RTC clock div 1 */ /* RTC clock calibration direction */ -#define RTC_CLOCK_SLOWED_DOWN ((uint16_t)0x0000U) /*!< RTC clock slow down */ +#define RTC_CLOCK_SLOW_DOWN ((uint16_t)0x0000U) /*!< RTC clock slow down */ #define RTC_CLOCK_SPEED_UP ((uint16_t)0x8000U) /*!< RTC clock speed up */ /* tamper pin active level */ @@ -210,6 +205,10 @@ typedef enum #define BKP_FLAG_TAMPER0 BKP_TPCS_TEF0 /*!< tamper0 event flag */ #define BKP_FLAG_TAMPER1_WAVEDETECT BKP_TPCS_TEF1 /*!< tamper1/waveform detect event flag */ +/* tamper interrupt */ +#define BKP_INT_TAMPER0 BKP_TPCS_TPIE0 /*!< tamper0 interrupt */ +#define BKP_INT_TAMPER1_WAVEDETECT BKP_TPCS_TPIE1 /*!< tamper1/waveform detect interrupt */ + /* tamper interrupt flag */ #define BKP_INT_FLAG_TAMPER0 BKP_TPCS_TIF0 /*!< tamper0 interrupt flag */ #define BKP_INT_FLAG_TAMPER1_WAVEDETECT BKP_TPCS_TIF1 /*!< tamper1/waveform detect interrupt flag */ @@ -253,21 +252,21 @@ void bkp_tamper_detection_enable(bkp_tamper_enum tamperx); void bkp_tamper_detection_disable(bkp_tamper_enum tamperx); /* set tamper pin active level */ void bkp_tamper_active_level_set(bkp_tamper_enum tamperx, uint16_t level); +/* waveform detect configure */ +void bkp_waveform_detect_config(uint16_t waveform_detect_mode, ControlStatus newvalue); /* interrupt & flag functions */ -/* enable tamper pin interrupt */ -void bkp_tamper_interrupt_enable(bkp_tamper_enum tamperx); -/* disable tamper pin interrupt */ -void bkp_tamper_interrupt_disable(bkp_tamper_enum tamperx); -/* waveform detect configure */ -void bkp_waveform_detect_enable(uint16_t waveform_detect_mode, ControlStatus newvalue); -/* get BKP flag state */ +/* get BKP flag */ FlagStatus bkp_flag_get(uint16_t flag); -/* clear BKP flag state */ +/* clear BKP flag */ void bkp_flag_clear(uint16_t flag); -/* get BKP interrupt flag state */ +/* enable tamper interrupt */ +void bkp_tamper_interrupt_enable(uint16_t bkp_interrupt); +/* disable tamper interrupt */ +void bkp_tamper_interrupt_disable(uint16_t bkp_interrupt); +/* get BKP interrupt flag */ FlagStatus bkp_interrupt_flag_get(uint16_t flag); -/* clear BKP interrupt flag state */ +/* clear BKP interrupt flag */ void bkp_interrupt_flag_clear(uint16_t flag); #endif /* GD32F20X_BKP_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_can.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_can.h index 0f25d4a8..c4e089cf 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_can.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_can.h @@ -2,37 +2,33 @@ \file gd32f20x_can.h \brief definitions for the CAN - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x - \version 2019-11-27, V2.1.1, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -42,115 +38,115 @@ OF SUCH DAMAGE. #include "gd32f20x.h" /* CAN definitions */ -#define CAN0 CAN_BASE /*!< CAN0 base address */ -#define CAN1 (CAN0 + 0x00000400U) /*!< CAN1 base address */ +#define CAN0 CAN_BASE /*!< CAN0 base address */ +#define CAN1 (CAN0 + 0x00000400U) /*!< CAN1 base address */ /* registers definitions */ -#define CAN_CTL(canx) REG32((canx) + 0x00U) /*!< CAN control register */ -#define CAN_STAT(canx) REG32((canx) + 0x04U) /*!< CAN status register */ -#define CAN_TSTAT(canx) REG32((canx) + 0x08U) /*!< CAN transmit status register*/ -#define CAN_RFIFO0(canx) REG32((canx) + 0x0CU) /*!< CAN receive FIFO0 register */ -#define CAN_RFIFO1(canx) REG32((canx) + 0x10U) /*!< CAN receive FIFO1 register */ -#define CAN_INTEN(canx) REG32((canx) + 0x14U) /*!< CAN interrupt enable register */ -#define CAN_ERR(canx) REG32((canx) + 0x18U) /*!< CAN error register */ -#define CAN_BT(canx) REG32((canx) + 0x1CU) /*!< CAN bit timing register */ -#define CAN_TMI0(canx) REG32((canx) + 0x180U) /*!< CAN transmit mailbox0 identifier register */ -#define CAN_TMP0(canx) REG32((canx) + 0x184U) /*!< CAN transmit mailbox0 property register */ -#define CAN_TMDATA00(canx) REG32((canx) + 0x188U) /*!< CAN transmit mailbox0 data0 register */ -#define CAN_TMDATA10(canx) REG32((canx) + 0x18CU) /*!< CAN transmit mailbox0 data1 register */ -#define CAN_TMI1(canx) REG32((canx) + 0x190U) /*!< CAN transmit mailbox1 identifier register */ -#define CAN_TMP1(canx) REG32((canx) + 0x194U) /*!< CAN transmit mailbox1 property register */ -#define CAN_TMDATA01(canx) REG32((canx) + 0x198U) /*!< CAN transmit mailbox1 data0 register */ -#define CAN_TMDATA11(canx) REG32((canx) + 0x19CU) /*!< CAN transmit mailbox1 data1 register */ -#define CAN_TMI2(canx) REG32((canx) + 0x1A0U) /*!< CAN transmit mailbox2 identifier register */ -#define CAN_TMP2(canx) REG32((canx) + 0x1A4U) /*!< CAN transmit mailbox2 property register */ -#define CAN_TMDATA02(canx) REG32((canx) + 0x1A8U) /*!< CAN transmit mailbox2 data0 register */ -#define CAN_TMDATA12(canx) REG32((canx) + 0x1ACU) /*!< CAN transmit mailbox2 data1 register */ -#define CAN_RFIFOMI0(canx) REG32((canx) + 0x1B0U) /*!< CAN receive FIFO0 mailbox identifier register */ -#define CAN_RFIFOMP0(canx) REG32((canx) + 0x1B4U) /*!< CAN receive FIFO0 mailbox property register */ -#define CAN_RFIFOMDATA00(canx) REG32((canx) + 0x1B8U) /*!< CAN receive FIFO0 mailbox data0 register */ -#define CAN_RFIFOMDATA10(canx) REG32((canx) + 0x1BCU) /*!< CAN receive FIFO0 mailbox data1 register */ -#define CAN_RFIFOMI1(canx) REG32((canx) + 0x1C0U) /*!< CAN receive FIFO1 mailbox identifier register */ -#define CAN_RFIFOMP1(canx) REG32((canx) + 0x1C4U) /*!< CAN receive FIFO1 mailbox property register */ -#define CAN_RFIFOMDATA01(canx) REG32((canx) + 0x1C8U) /*!< CAN receive FIFO1 mailbox data0 register */ -#define CAN_RFIFOMDATA11(canx) REG32((canx) + 0x1CCU) /*!< CAN receive FIFO1 mailbox data1 register */ -#define CAN_FCTL(canx) REG32((canx) + 0x200U) /*!< CAN filter control register */ -#define CAN_FMCFG(canx) REG32((canx) + 0x204U) /*!< CAN filter mode register */ -#define CAN_FSCFG(canx) REG32((canx) + 0x20CU) /*!< CAN filter scale register */ -#define CAN_FAFIFO(canx) REG32((canx) + 0x214U) /*!< CAN filter associated FIFO register */ -#define CAN_FW(canx) REG32((canx) + 0x21CU) /*!< CAN filter working register */ -#define CAN_F0DATA0(canx) REG32((canx) + 0x240U) /*!< CAN filter 0 data 0 register */ -#define CAN_F1DATA0(canx) REG32((canx) + 0x248U) /*!< CAN filter 1 data 0 register */ -#define CAN_F2DATA0(canx) REG32((canx) + 0x250U) /*!< CAN filter 2 data 0 register */ -#define CAN_F3DATA0(canx) REG32((canx) + 0x258U) /*!< CAN filter 3 data 0 register */ -#define CAN_F4DATA0(canx) REG32((canx) + 0x260U) /*!< CAN filter 4 data 0 register */ -#define CAN_F5DATA0(canx) REG32((canx) + 0x268U) /*!< CAN filter 5 data 0 register */ -#define CAN_F6DATA0(canx) REG32((canx) + 0x270U) /*!< CAN filter 6 data 0 register */ -#define CAN_F7DATA0(canx) REG32((canx) + 0x278U) /*!< CAN filter 7 data 0 register */ -#define CAN_F8DATA0(canx) REG32((canx) + 0x280U) /*!< CAN filter 8 data 0 register */ -#define CAN_F9DATA0(canx) REG32((canx) + 0x288U) /*!< CAN filter 9 data 0 register */ -#define CAN_F10DATA0(canx) REG32((canx) + 0x290U) /*!< CAN filter 10 data 0 register */ -#define CAN_F11DATA0(canx) REG32((canx) + 0x298U) /*!< CAN filter 11 data 0 register */ -#define CAN_F12DATA0(canx) REG32((canx) + 0x2A0U) /*!< CAN filter 12 data 0 register */ -#define CAN_F13DATA0(canx) REG32((canx) + 0x2A8U) /*!< CAN filter 13 data 0 register */ -#define CAN_F14DATA0(canx) REG32((canx) + 0x2B0U) /*!< CAN filter 14 data 0 register */ -#define CAN_F15DATA0(canx) REG32((canx) + 0x2B8U) /*!< CAN filter 15 data 0 register */ -#define CAN_F16DATA0(canx) REG32((canx) + 0x2C0U) /*!< CAN filter 16 data 0 register */ -#define CAN_F17DATA0(canx) REG32((canx) + 0x2C8U) /*!< CAN filter 17 data 0 register */ -#define CAN_F18DATA0(canx) REG32((canx) + 0x2D0U) /*!< CAN filter 18 data 0 register */ -#define CAN_F19DATA0(canx) REG32((canx) + 0x2D8U) /*!< CAN filter 19 data 0 register */ -#define CAN_F20DATA0(canx) REG32((canx) + 0x2E0U) /*!< CAN filter 20 data 0 register */ -#define CAN_F21DATA0(canx) REG32((canx) + 0x2E8U) /*!< CAN filter 21 data 0 register */ -#define CAN_F22DATA0(canx) REG32((canx) + 0x2F0U) /*!< CAN filter 22 data 0 register */ -#define CAN_F23DATA0(canx) REG32((canx) + 0x3F8U) /*!< CAN filter 23 data 0 register */ -#define CAN_F24DATA0(canx) REG32((canx) + 0x300U) /*!< CAN filter 24 data 0 register */ -#define CAN_F25DATA0(canx) REG32((canx) + 0x308U) /*!< CAN filter 25 data 0 register */ -#define CAN_F26DATA0(canx) REG32((canx) + 0x310U) /*!< CAN filter 26 data 0 register */ -#define CAN_F27DATA0(canx) REG32((canx) + 0x318U) /*!< CAN filter 27 data 0 register */ -#define CAN_F0DATA1(canx) REG32((canx) + 0x244U) /*!< CAN filter 0 data 1 register */ -#define CAN_F1DATA1(canx) REG32((canx) + 0x24CU) /*!< CAN filter 1 data 1 register */ -#define CAN_F2DATA1(canx) REG32((canx) + 0x254U) /*!< CAN filter 2 data 1 register */ -#define CAN_F3DATA1(canx) REG32((canx) + 0x25CU) /*!< CAN filter 3 data 1 register */ -#define CAN_F4DATA1(canx) REG32((canx) + 0x264U) /*!< CAN filter 4 data 1 register */ -#define CAN_F5DATA1(canx) REG32((canx) + 0x26CU) /*!< CAN filter 5 data 1 register */ -#define CAN_F6DATA1(canx) REG32((canx) + 0x274U) /*!< CAN filter 6 data 1 register */ -#define CAN_F7DATA1(canx) REG32((canx) + 0x27CU) /*!< CAN filter 7 data 1 register */ -#define CAN_F8DATA1(canx) REG32((canx) + 0x284U) /*!< CAN filter 8 data 1 register */ -#define CAN_F9DATA1(canx) REG32((canx) + 0x28CU) /*!< CAN filter 9 data 1 register */ -#define CAN_F10DATA1(canx) REG32((canx) + 0x294U) /*!< CAN filter 10 data 1 register */ -#define CAN_F11DATA1(canx) REG32((canx) + 0x29CU) /*!< CAN filter 11 data 1 register */ -#define CAN_F12DATA1(canx) REG32((canx) + 0x2A4U) /*!< CAN filter 12 data 1 register */ -#define CAN_F13DATA1(canx) REG32((canx) + 0x2ACU) /*!< CAN filter 13 data 1 register */ -#define CAN_F14DATA1(canx) REG32((canx) + 0x2B4U) /*!< CAN filter 14 data 1 register */ -#define CAN_F15DATA1(canx) REG32((canx) + 0x2BCU) /*!< CAN filter 15 data 1 register */ -#define CAN_F16DATA1(canx) REG32((canx) + 0x2C4U) /*!< CAN filter 16 data 1 register */ -#define CAN_F17DATA1(canx) REG32((canx) + 0x24CU) /*!< CAN filter 17 data 1 register */ -#define CAN_F18DATA1(canx) REG32((canx) + 0x2D4U) /*!< CAN filter 18 data 1 register */ -#define CAN_F19DATA1(canx) REG32((canx) + 0x2DCU) /*!< CAN filter 19 data 1 register */ -#define CAN_F20DATA1(canx) REG32((canx) + 0x2E4U) /*!< CAN filter 20 data 1 register */ -#define CAN_F21DATA1(canx) REG32((canx) + 0x2ECU) /*!< CAN filter 21 data 1 register */ -#define CAN_F22DATA1(canx) REG32((canx) + 0x2F4U) /*!< CAN filter 22 data 1 register */ -#define CAN_F23DATA1(canx) REG32((canx) + 0x2FCU) /*!< CAN filter 23 data 1 register */ -#define CAN_F24DATA1(canx) REG32((canx) + 0x304U) /*!< CAN filter 24 data 1 register */ -#define CAN_F25DATA1(canx) REG32((canx) + 0x30CU) /*!< CAN filter 25 data 1 register */ -#define CAN_F26DATA1(canx) REG32((canx) + 0x314U) /*!< CAN filter 26 data 1 register */ -#define CAN_F27DATA1(canx) REG32((canx) + 0x31CU) /*!< CAN filter 27 data 1 register */ +#define CAN_CTL(canx) REG32((canx) + 0x00000000U) /*!< CAN control register */ +#define CAN_STAT(canx) REG32((canx) + 0x00000004U) /*!< CAN status register */ +#define CAN_TSTAT(canx) REG32((canx) + 0x00000008U) /*!< CAN transmit status register*/ +#define CAN_RFIFO0(canx) REG32((canx) + 0x0000000CU) /*!< CAN receive FIFO0 register */ +#define CAN_RFIFO1(canx) REG32((canx) + 0x00000010U) /*!< CAN receive FIFO1 register */ +#define CAN_INTEN(canx) REG32((canx) + 0x00000014U) /*!< CAN interrupt enable register */ +#define CAN_ERR(canx) REG32((canx) + 0x00000018U) /*!< CAN error register */ +#define CAN_BT(canx) REG32((canx) + 0x0000001CU) /*!< CAN bit timing register */ +#define CAN_TMI0(canx) REG32((canx) + 0x00000180U) /*!< CAN transmit mailbox0 identifier register */ +#define CAN_TMP0(canx) REG32((canx) + 0x00000184U) /*!< CAN transmit mailbox0 property register */ +#define CAN_TMDATA00(canx) REG32((canx) + 0x00000188U) /*!< CAN transmit mailbox0 data0 register */ +#define CAN_TMDATA10(canx) REG32((canx) + 0x0000018CU) /*!< CAN transmit mailbox0 data1 register */ +#define CAN_TMI1(canx) REG32((canx) + 0x00000190U) /*!< CAN transmit mailbox1 identifier register */ +#define CAN_TMP1(canx) REG32((canx) + 0x00000194U) /*!< CAN transmit mailbox1 property register */ +#define CAN_TMDATA01(canx) REG32((canx) + 0x00000198U) /*!< CAN transmit mailbox1 data0 register */ +#define CAN_TMDATA11(canx) REG32((canx) + 0x0000019CU) /*!< CAN transmit mailbox1 data1 register */ +#define CAN_TMI2(canx) REG32((canx) + 0x000001A0U) /*!< CAN transmit mailbox2 identifier register */ +#define CAN_TMP2(canx) REG32((canx) + 0x000001A4U) /*!< CAN transmit mailbox2 property register */ +#define CAN_TMDATA02(canx) REG32((canx) + 0x000001A8U) /*!< CAN transmit mailbox2 data0 register */ +#define CAN_TMDATA12(canx) REG32((canx) + 0x000001ACU) /*!< CAN transmit mailbox2 data1 register */ +#define CAN_RFIFOMI0(canx) REG32((canx) + 0x000001B0U) /*!< CAN receive FIFO0 mailbox identifier register */ +#define CAN_RFIFOMP0(canx) REG32((canx) + 0x000001B4U) /*!< CAN receive FIFO0 mailbox property register */ +#define CAN_RFIFOMDATA00(canx) REG32((canx) + 0x000001B8U) /*!< CAN receive FIFO0 mailbox data0 register */ +#define CAN_RFIFOMDATA10(canx) REG32((canx) + 0x000001BCU) /*!< CAN receive FIFO0 mailbox data1 register */ +#define CAN_RFIFOMI1(canx) REG32((canx) + 0x000001C0U) /*!< CAN receive FIFO1 mailbox identifier register */ +#define CAN_RFIFOMP1(canx) REG32((canx) + 0x000001C4U) /*!< CAN receive FIFO1 mailbox property register */ +#define CAN_RFIFOMDATA01(canx) REG32((canx) + 0x000001C8U) /*!< CAN receive FIFO1 mailbox data0 register */ +#define CAN_RFIFOMDATA11(canx) REG32((canx) + 0x000001CCU) /*!< CAN receive FIFO1 mailbox data1 register */ +#define CAN_FCTL(canx) REG32((canx) + 0x00000200U) /*!< CAN filter control register */ +#define CAN_FMCFG(canx) REG32((canx) + 0x00000204U) /*!< CAN filter mode register */ +#define CAN_FSCFG(canx) REG32((canx) + 0x0000020CU) /*!< CAN filter scale register */ +#define CAN_FAFIFO(canx) REG32((canx) + 0x00000214U) /*!< CAN filter associated FIFO register */ +#define CAN_FW(canx) REG32((canx) + 0x0000021CU) /*!< CAN filter working register */ +#define CAN_F0DATA0(canx) REG32((canx) + 0x00000240U) /*!< CAN filter 0 data 0 register */ +#define CAN_F1DATA0(canx) REG32((canx) + 0x00000248U) /*!< CAN filter 1 data 0 register */ +#define CAN_F2DATA0(canx) REG32((canx) + 0x00000250U) /*!< CAN filter 2 data 0 register */ +#define CAN_F3DATA0(canx) REG32((canx) + 0x00000258U) /*!< CAN filter 3 data 0 register */ +#define CAN_F4DATA0(canx) REG32((canx) + 0x00000260U) /*!< CAN filter 4 data 0 register */ +#define CAN_F5DATA0(canx) REG32((canx) + 0x00000268U) /*!< CAN filter 5 data 0 register */ +#define CAN_F6DATA0(canx) REG32((canx) + 0x00000270U) /*!< CAN filter 6 data 0 register */ +#define CAN_F7DATA0(canx) REG32((canx) + 0x00000278U) /*!< CAN filter 7 data 0 register */ +#define CAN_F8DATA0(canx) REG32((canx) + 0x00000280U) /*!< CAN filter 8 data 0 register */ +#define CAN_F9DATA0(canx) REG32((canx) + 0x00000288U) /*!< CAN filter 9 data 0 register */ +#define CAN_F10DATA0(canx) REG32((canx) + 0x00000290U) /*!< CAN filter 10 data 0 register */ +#define CAN_F11DATA0(canx) REG32((canx) + 0x00000298U) /*!< CAN filter 11 data 0 register */ +#define CAN_F12DATA0(canx) REG32((canx) + 0x000002A0U) /*!< CAN filter 12 data 0 register */ +#define CAN_F13DATA0(canx) REG32((canx) + 0x000002A8U) /*!< CAN filter 13 data 0 register */ +#define CAN_F14DATA0(canx) REG32((canx) + 0x000002B0U) /*!< CAN filter 14 data 0 register */ +#define CAN_F15DATA0(canx) REG32((canx) + 0x000002B8U) /*!< CAN filter 15 data 0 register */ +#define CAN_F16DATA0(canx) REG32((canx) + 0x000002C0U) /*!< CAN filter 16 data 0 register */ +#define CAN_F17DATA0(canx) REG32((canx) + 0x000002C8U) /*!< CAN filter 17 data 0 register */ +#define CAN_F18DATA0(canx) REG32((canx) + 0x000002D0U) /*!< CAN filter 18 data 0 register */ +#define CAN_F19DATA0(canx) REG32((canx) + 0x000002D8U) /*!< CAN filter 19 data 0 register */ +#define CAN_F20DATA0(canx) REG32((canx) + 0x000002E0U) /*!< CAN filter 20 data 0 register */ +#define CAN_F21DATA0(canx) REG32((canx) + 0x000002E8U) /*!< CAN filter 21 data 0 register */ +#define CAN_F22DATA0(canx) REG32((canx) + 0x000002F0U) /*!< CAN filter 22 data 0 register */ +#define CAN_F23DATA0(canx) REG32((canx) + 0x000003F8U) /*!< CAN filter 23 data 0 register */ +#define CAN_F24DATA0(canx) REG32((canx) + 0x00000300U) /*!< CAN filter 24 data 0 register */ +#define CAN_F25DATA0(canx) REG32((canx) + 0x00000308U) /*!< CAN filter 25 data 0 register */ +#define CAN_F26DATA0(canx) REG32((canx) + 0x00000310U) /*!< CAN filter 26 data 0 register */ +#define CAN_F27DATA0(canx) REG32((canx) + 0x00000318U) /*!< CAN filter 27 data 0 register */ +#define CAN_F0DATA1(canx) REG32((canx) + 0x00000244U) /*!< CAN filter 0 data 1 register */ +#define CAN_F1DATA1(canx) REG32((canx) + 0x0000024CU) /*!< CAN filter 1 data 1 register */ +#define CAN_F2DATA1(canx) REG32((canx) + 0x00000254U) /*!< CAN filter 2 data 1 register */ +#define CAN_F3DATA1(canx) REG32((canx) + 0x0000025CU) /*!< CAN filter 3 data 1 register */ +#define CAN_F4DATA1(canx) REG32((canx) + 0x00000264U) /*!< CAN filter 4 data 1 register */ +#define CAN_F5DATA1(canx) REG32((canx) + 0x0000026CU) /*!< CAN filter 5 data 1 register */ +#define CAN_F6DATA1(canx) REG32((canx) + 0x00000274U) /*!< CAN filter 6 data 1 register */ +#define CAN_F7DATA1(canx) REG32((canx) + 0x0000027CU) /*!< CAN filter 7 data 1 register */ +#define CAN_F8DATA1(canx) REG32((canx) + 0x00000284U) /*!< CAN filter 8 data 1 register */ +#define CAN_F9DATA1(canx) REG32((canx) + 0x0000028CU) /*!< CAN filter 9 data 1 register */ +#define CAN_F10DATA1(canx) REG32((canx) + 0x00000294U) /*!< CAN filter 10 data 1 register */ +#define CAN_F11DATA1(canx) REG32((canx) + 0x0000029CU) /*!< CAN filter 11 data 1 register */ +#define CAN_F12DATA1(canx) REG32((canx) + 0x000002A4U) /*!< CAN filter 12 data 1 register */ +#define CAN_F13DATA1(canx) REG32((canx) + 0x000002ACU) /*!< CAN filter 13 data 1 register */ +#define CAN_F14DATA1(canx) REG32((canx) + 0x000002B4U) /*!< CAN filter 14 data 1 register */ +#define CAN_F15DATA1(canx) REG32((canx) + 0x000002BCU) /*!< CAN filter 15 data 1 register */ +#define CAN_F16DATA1(canx) REG32((canx) + 0x000002C4U) /*!< CAN filter 16 data 1 register */ +#define CAN_F17DATA1(canx) REG32((canx) + 0x0000024CU) /*!< CAN filter 17 data 1 register */ +#define CAN_F18DATA1(canx) REG32((canx) + 0x000002D4U) /*!< CAN filter 18 data 1 register */ +#define CAN_F19DATA1(canx) REG32((canx) + 0x000002DCU) /*!< CAN filter 19 data 1 register */ +#define CAN_F20DATA1(canx) REG32((canx) + 0x000002E4U) /*!< CAN filter 20 data 1 register */ +#define CAN_F21DATA1(canx) REG32((canx) + 0x000002ECU) /*!< CAN filter 21 data 1 register */ +#define CAN_F22DATA1(canx) REG32((canx) + 0x000002F4U) /*!< CAN filter 22 data 1 register */ +#define CAN_F23DATA1(canx) REG32((canx) + 0x000002FCU) /*!< CAN filter 23 data 1 register */ +#define CAN_F24DATA1(canx) REG32((canx) + 0x00000304U) /*!< CAN filter 24 data 1 register */ +#define CAN_F25DATA1(canx) REG32((canx) + 0x0000030CU) /*!< CAN filter 25 data 1 register */ +#define CAN_F26DATA1(canx) REG32((canx) + 0x00000314U) /*!< CAN filter 26 data 1 register */ +#define CAN_F27DATA1(canx) REG32((canx) + 0x0000031CU) /*!< CAN filter 27 data 1 register */ /* CAN transmit mailbox bank */ -#define CAN_TMI(canx, bank) REG32((canx) + 0x180U + ((bank) * 0x10U)) /*!< CAN transmit mailbox identifier register */ -#define CAN_TMP(canx, bank) REG32((canx) + 0x184U + ((bank) * 0x10U)) /*!< CAN transmit mailbox property register */ -#define CAN_TMDATA0(canx, bank) REG32((canx) + 0x188U + ((bank) * 0x10U)) /*!< CAN transmit mailbox data0 register */ -#define CAN_TMDATA1(canx, bank) REG32((canx) + 0x18CU + ((bank) * 0x10U)) /*!< CAN transmit mailbox data1 register */ +#define CAN_TMI(canx, bank) REG32((canx) + 0x180U + ((bank) * 0x10U)) /*!< CAN transmit mailbox identifier register */ +#define CAN_TMP(canx, bank) REG32((canx) + 0x184U + ((bank) * 0x10U)) /*!< CAN transmit mailbox property register */ +#define CAN_TMDATA0(canx, bank) REG32((canx) + 0x188U + ((bank) * 0x10U)) /*!< CAN transmit mailbox data0 register */ +#define CAN_TMDATA1(canx, bank) REG32((canx) + 0x18CU + ((bank) * 0x10U)) /*!< CAN transmit mailbox data1 register */ /* CAN filter bank */ -#define CAN_FDATA0(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x0U) /*!< CAN filter data 0 register */ -#define CAN_FDATA1(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x4U) /*!< CAN filter data 1 register */ +#define CAN_FDATA0(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x0U) /*!< CAN filter data 0 register */ +#define CAN_FDATA1(canx, bank) REG32((canx) + 0x240U + ((bank) * 0x8U) + 0x4U) /*!< CAN filter data 1 register */ -/* CAN receive fifo mailbox bank */ -#define CAN_RFIFOMI(canx, bank) REG32((canx) + 0x1B0U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox identifier register */ -#define CAN_RFIFOMP(canx, bank) REG32((canx) + 0x1B4U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox property register */ -#define CAN_RFIFOMDATA0(canx, bank) REG32((canx) + 0x1B8U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data0 register */ -#define CAN_RFIFOMDATA1(canx, bank) REG32((canx) + 0x1BCU + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data1 register */ +/* CAN receive FIFO mailbox bank */ +#define CAN_RFIFOMI(canx, bank) REG32((canx) + 0x1B0U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox identifier register */ +#define CAN_RFIFOMP(canx, bank) REG32((canx) + 0x1B4U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox property register */ +#define CAN_RFIFOMDATA0(canx, bank) REG32((canx) + 0x1B8U + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data0 register */ +#define CAN_RFIFOMDATA1(canx, bank) REG32((canx) + 0x1BCU + ((bank) * 0x10U)) /*!< CAN receive FIFO mailbox data1 register */ /* bits definitions */ /* CAN_CTL */ @@ -296,10 +292,10 @@ OF SUCH DAMAGE. #define CAN_FCTL_HBC1F BITS(8,13) /*!< header bank of CAN1 filter */ /* CAN_FMCFG */ -#define CAN_FMCFG_FMOD(regval) BIT(regval) /*!< filter mode, list or mask*/ +#define CAN_FMCFG_FMOD(regval) BIT(regval) /*!< filter mode, list or mask */ /* CAN_FSCFG */ -#define CAN_FSCFG_FS(regval) BIT(regval) /*!< filter scale, 32 bits or 16 bits*/ +#define CAN_FSCFG_FS(regval) BIT(regval) /*!< filter scale, 32 bits or 16 bits */ /* CAN_FAFIFO */ #define CAN_FAFIFOR_FAF(regval) BIT(regval) /*!< filter associated with FIFO */ @@ -329,56 +325,54 @@ OF SUCH DAMAGE. #define ERR_REG_OFFSET ((uint8_t)0x18U) /*!< ERR register offset */ /* CAN flags */ -typedef enum -{ +typedef enum { /* flags in STAT register */ - CAN_FLAG_RXL = CAN_REGIDX_BIT(STAT_REG_OFFSET, 11U), /*!< RX level */ - CAN_FLAG_LASTRX = CAN_REGIDX_BIT(STAT_REG_OFFSET, 10U), /*!< last sample value of RX pin */ - CAN_FLAG_RS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 9U), /*!< receiving state */ - CAN_FLAG_TS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 8U), /*!< transmitting state */ - CAN_FLAG_SLPIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 4U), /*!< status change flag of entering sleep working mode */ - CAN_FLAG_WUIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 3U), /*!< status change flag of wakeup from sleep working mode */ - CAN_FLAG_ERRIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 2U), /*!< error flag */ - CAN_FLAG_SLPWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 1U), /*!< sleep working state */ - CAN_FLAG_IWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 0U), /*!< initial working state */ + CAN_FLAG_RXL = CAN_REGIDX_BIT(STAT_REG_OFFSET, 11U), /*!< RX level */ + CAN_FLAG_LASTRX = CAN_REGIDX_BIT(STAT_REG_OFFSET, 10U), /*!< last sample value of RX pin */ + CAN_FLAG_RS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 9U), /*!< receiving state */ + CAN_FLAG_TS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 8U), /*!< transmitting state */ + CAN_FLAG_SLPIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 4U), /*!< status change flag of entering sleep working mode */ + CAN_FLAG_WUIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 3U), /*!< status change flag of wakeup from sleep working mode */ + CAN_FLAG_ERRIF = CAN_REGIDX_BIT(STAT_REG_OFFSET, 2U), /*!< error flag */ + CAN_FLAG_SLPWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 1U), /*!< sleep working state */ + CAN_FLAG_IWS = CAN_REGIDX_BIT(STAT_REG_OFFSET, 0U), /*!< initial working state */ /* flags in TSTAT register */ - CAN_FLAG_TMLS2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 31U), /*!< transmit mailbox 2 last sending in Tx FIFO */ - CAN_FLAG_TMLS1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 30U), /*!< transmit mailbox 1 last sending in Tx FIFO */ - CAN_FLAG_TMLS0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 29U), /*!< transmit mailbox 0 last sending in Tx FIFO */ - CAN_FLAG_TME2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 28U), /*!< transmit mailbox 2 empty */ - CAN_FLAG_TME1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 27U), /*!< transmit mailbox 1 empty */ - CAN_FLAG_TME0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 26U), /*!< transmit mailbox 0 empty */ - CAN_FLAG_MTE2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 19U), /*!< mailbox 2 transmit error */ - CAN_FLAG_MTE1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 11U), /*!< mailbox 1 transmit error */ - CAN_FLAG_MTE0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 3U), /*!< mailbox 0 transmit error */ - CAN_FLAG_MAL2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 18U), /*!< mailbox 2 arbitration lost */ - CAN_FLAG_MAL1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 10U), /*!< mailbox 1 arbitration lost */ - CAN_FLAG_MAL0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 2U), /*!< mailbox 0 arbitration lost */ - CAN_FLAG_MTFNERR2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 17U), /*!< mailbox 2 transmit finished with no error */ - CAN_FLAG_MTFNERR1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 9U), /*!< mailbox 1 transmit finished with no error */ - CAN_FLAG_MTFNERR0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 1U), /*!< mailbox 0 transmit finished with no error */ - CAN_FLAG_MTF2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 16U), /*!< mailbox 2 transmit finished */ - CAN_FLAG_MTF1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 8U), /*!< mailbox 1 transmit finished */ - CAN_FLAG_MTF0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 0U), /*!< mailbox 0 transmit finished */ + CAN_FLAG_TMLS2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 31U), /*!< transmit mailbox 2 last sending in TX FIFO */ + CAN_FLAG_TMLS1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 30U), /*!< transmit mailbox 1 last sending in TX FIFO */ + CAN_FLAG_TMLS0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 29U), /*!< transmit mailbox 0 last sending in TX FIFO */ + CAN_FLAG_TME2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 28U), /*!< transmit mailbox 2 empty */ + CAN_FLAG_TME1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 27U), /*!< transmit mailbox 1 empty */ + CAN_FLAG_TME0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 26U), /*!< transmit mailbox 0 empty */ + CAN_FLAG_MTE2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 19U), /*!< mailbox 2 transmit error */ + CAN_FLAG_MTE1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 11U), /*!< mailbox 1 transmit error */ + CAN_FLAG_MTE0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 3U), /*!< mailbox 0 transmit error */ + CAN_FLAG_MAL2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 18U), /*!< mailbox 2 arbitration lost */ + CAN_FLAG_MAL1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 10U), /*!< mailbox 1 arbitration lost */ + CAN_FLAG_MAL0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 2U), /*!< mailbox 0 arbitration lost */ + CAN_FLAG_MTFNERR2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 17U), /*!< mailbox 2 transmit finished with no error */ + CAN_FLAG_MTFNERR1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 9U), /*!< mailbox 1 transmit finished with no error */ + CAN_FLAG_MTFNERR0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 1U), /*!< mailbox 0 transmit finished with no error */ + CAN_FLAG_MTF2 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 16U), /*!< mailbox 2 transmit finished */ + CAN_FLAG_MTF1 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 8U), /*!< mailbox 1 transmit finished */ + CAN_FLAG_MTF0 = CAN_REGIDX_BIT(TSTAT_REG_OFFSET, 0U), /*!< mailbox 0 transmit finished */ /* flags in RFIFO0 register */ - CAN_FLAG_RFO0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 4U), /*!< receive FIFO0 overfull */ - CAN_FLAG_RFF0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 3U), /*!< receive FIFO0 full */ + CAN_FLAG_RFO0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 4U), /*!< receive FIFO0 overfull */ + CAN_FLAG_RFF0 = CAN_REGIDX_BIT(RFIFO0_REG_OFFSET, 3U), /*!< receive FIFO0 full */ /* flags in RFIFO1 register */ - CAN_FLAG_RFO1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 4U), /*!< receive FIFO1 overfull */ - CAN_FLAG_RFF1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 3U), /*!< receive FIFO1 full */ + CAN_FLAG_RFO1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 4U), /*!< receive FIFO1 overfull */ + CAN_FLAG_RFF1 = CAN_REGIDX_BIT(RFIFO1_REG_OFFSET, 3U), /*!< receive FIFO1 full */ /* flags in ERR register */ - CAN_FLAG_BOERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 2U), /*!< bus-off error */ - CAN_FLAG_PERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 1U), /*!< passive error */ - CAN_FLAG_WERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 0U), /*!< warning error */ -}can_flag_enum; + CAN_FLAG_BOERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 2U), /*!< bus-off error */ + CAN_FLAG_PERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 1U), /*!< passive error */ + CAN_FLAG_WERR = CAN_REGIDX_BIT(ERR_REG_OFFSET, 0U), /*!< warning error */ +} can_flag_enum; /* CAN interrupt flags */ -typedef enum -{ +typedef enum { /* interrupt flags in STAT register */ - CAN_INT_FLAG_SLPIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 4U, 17U), /*!< status change interrupt flag of sleep working mode entering */ - CAN_INT_FLAG_WUIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 3U, 16), /*!< status change interrupt flag of wakeup from sleep working mode */ - CAN_INT_FLAG_ERRIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 2U, 15), /*!< error interrupt flag */ + CAN_INT_FLAG_SLPIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 4U, 17U), /*!< status change interrupt flag of sleep working mode entering */ + CAN_INT_FLAG_WUIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 3U, 16), /*!< status change interrupt flag of wakeup from sleep working mode */ + CAN_INT_FLAG_ERRIF = CAN_REGIDX_BITS(STAT_REG_OFFSET, 2U, 15), /*!< error interrupt flag */ /* interrupt flags in TSTAT register */ CAN_INT_FLAG_MTF2 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 16U, 0U), /*!< mailbox 2 transmit finished interrupt flag */ CAN_INT_FLAG_MTF1 = CAN_REGIDX_BITS(TSTAT_REG_OFFSET, 8U, 0U), /*!< mailbox 1 transmit finished interrupt flag */ @@ -392,42 +386,39 @@ typedef enum CAN_INT_FLAG_RFF1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 3U, 5U), /*!< receive FIFO1 full interrupt flag */ CAN_INT_FLAG_RFL1 = CAN_REGIDX_BITS(RFIFO1_REG_OFFSET, 2U, 4U), /*!< receive FIFO1 not empty interrupt flag */ /* interrupt flags in ERR register */ - CAN_INT_FLAG_ERRN = CAN_REGIDX_BITS(ERR_REG_OFFSET, 3U, 11U), /*!< error number interrupt flag */ - CAN_INT_FLAG_BOERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 2U, 10U), /*!< bus-off error interrupt flag */ - CAN_INT_FLAG_PERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 1U, 9U), /*!< passive error interrupt flag */ - CAN_INT_FLAG_WERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 0U, 8U), /*!< warning error interrupt flag */ -}can_interrupt_flag_enum; + CAN_INT_FLAG_ERRN = CAN_REGIDX_BITS(ERR_REG_OFFSET, 3U, 11U), /*!< error number interrupt flag */ + CAN_INT_FLAG_BOERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 2U, 10U), /*!< bus-off error interrupt flag */ + CAN_INT_FLAG_PERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 1U, 9U), /*!< passive error interrupt flag */ + CAN_INT_FLAG_WERR = CAN_REGIDX_BITS(ERR_REG_OFFSET, 0U, 8U), /*!< warning error interrupt flag */ +} can_interrupt_flag_enum; /* CAN initiliaze parameters structure */ -typedef struct -{ - uint8_t working_mode; /*!< CAN working mode */ +typedef struct { + uint8_t working_mode; /*!< CAN working mode */ uint8_t resync_jump_width; /*!< CAN resynchronization jump width */ uint8_t time_segment_1; /*!< time segment 1 */ uint8_t time_segment_2; /*!< time segment 2 */ ControlStatus time_triggered; /*!< time triggered communication mode */ ControlStatus auto_bus_off_recovery; /*!< automatic bus-off recovery */ ControlStatus auto_wake_up; /*!< automatic wake-up mode */ - ControlStatus no_auto_retrans; /*!< automatic retransmission mode disable */ + ControlStatus auto_retrans; /*!< automatic retransmission mode */ ControlStatus rec_fifo_overwrite; /*!< receive FIFO overwrite mode */ ControlStatus trans_fifo_order; /*!< transmit FIFO order */ uint16_t prescaler; /*!< baudrate prescaler */ -}can_parameter_struct; +} can_parameter_struct; /* CAN transmit message structure */ -typedef struct -{ +typedef struct { uint32_t tx_sfid; /*!< standard format frame identifier */ uint32_t tx_efid; /*!< extended format frame identifier */ uint8_t tx_ff; /*!< format of frame, standard or extended format */ uint8_t tx_ft; /*!< type of frame, data or remote */ uint8_t tx_dlen; /*!< data length */ uint8_t tx_data[8]; /*!< transmit data */ -}can_trasnmit_message_struct; +} can_trasnmit_message_struct; /* CAN receive message structure */ -typedef struct -{ +typedef struct { uint32_t rx_sfid; /*!< standard format frame identifier */ uint32_t rx_efid; /*!< extended format frame identifier */ uint8_t rx_ff; /*!< format of frame, standard or extended format */ @@ -438,9 +429,8 @@ typedef struct } can_receive_message_struct; /* CAN filter parameters structure */ -typedef struct -{ - uint16_t filter_list_high; /*!< filter list number high bits*/ +typedef struct { + uint16_t filter_list_high; /*!< filter list number high bits */ uint16_t filter_list_low; /*!< filter list number low bits */ uint16_t filter_mask_high; /*!< filter mask number high bits */ uint16_t filter_mask_low; /*!< filter mask number low bits */ @@ -449,11 +439,10 @@ typedef struct uint16_t filter_mode; /*!< filter mode, list or mask */ uint16_t filter_bits; /*!< filter scale */ ControlStatus filter_enable; /*!< filter work or not */ -}can_filter_parameter_struct; +} can_filter_parameter_struct; /* CAN errors */ -typedef enum -{ +typedef enum { CAN_ERROR_NONE = 0, /*!< no error */ CAN_ERROR_FILL, /*!< fill error */ CAN_ERROR_FORMATE, /*!< format error */ @@ -462,38 +451,36 @@ typedef enum CAN_ERROR_BITDOMINANTER, /*!< bit dominant error */ CAN_ERROR_CRC, /*!< CRC error */ CAN_ERROR_SOFTWARECFG, /*!< software configure */ -}can_error_enum; +} can_error_enum; /* transmit states */ -typedef enum -{ - CAN_TRANSMIT_FAILED = 0, /*!< CAN transmitted failure */ - CAN_TRANSMIT_OK = 1, /*!< CAN transmitted success */ - CAN_TRANSMIT_PENDING = 2, /*!< CAN transmitted pending */ - CAN_TRANSMIT_NOMAILBOX = 4, /*!< no empty mailbox to be used for CAN */ -}can_transmit_state_enum; - -typedef enum -{ - CAN_INIT_STRUCT = 0, /* CAN initiliaze parameters struct */ +typedef enum { + CAN_TRANSMIT_FAILED = 0U, /*!< CAN transmitted failure */ + CAN_TRANSMIT_OK = 1U, /*!< CAN transmitted success */ + CAN_TRANSMIT_PENDING = 2U, /*!< CAN transmitted pending */ + CAN_TRANSMIT_NOMAILBOX = 4U, /*!< no empty mailbox to be used for CAN */ +} can_transmit_state_enum; + +typedef enum { + CAN_INIT_STRUCT = 0, /* CAN initialize parameters struct */ CAN_FILTER_STRUCT, /* CAN filter parameters struct */ CAN_TX_MESSAGE_STRUCT, /* CAN transmit message struct */ CAN_RX_MESSAGE_STRUCT, /* CAN receive message struct */ -}can_struct_type_enum; +} can_struct_type_enum; -/* CAN baudrate prescaler*/ +/* CAN baudrate prescaler */ #define BT_BAUDPSC(regval) (BITS(0,9) & ((uint32_t)(regval) << 0)) -/* CAN bit segment 1*/ +/* CAN bit segment 1 */ #define BT_BS1(regval) (BITS(16,19) & ((uint32_t)(regval) << 16)) -/* CAN bit segment 2*/ +/* CAN bit segment 2 */ #define BT_BS2(regval) (BITS(20,22) & ((uint32_t)(regval) << 20)) -/* CAN resynchronization jump width*/ +/* CAN resynchronization jump width */ #define BT_SJW(regval) (BITS(24,25) & ((uint32_t)(regval) << 24)) -/* CAN communication mode*/ +/* CAN communication mode */ #define BT_MODE(regval) (BITS(30,31) & ((uint32_t)(regval) << 30)) /* CAN FDATA high 16 bits */ @@ -502,13 +489,13 @@ typedef enum /* CAN FDATA low 16 bits */ #define FDATA_MASK_LOW(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) -/* CAN1 filter start bank_number*/ +/* CAN1 filter start bank_number */ #define FCTL_HBC1F(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) -/* CAN transmit mailbox extended identifier*/ +/* CAN transmit mailbox extended identifier */ #define TMI_EFID(regval) (BITS(3,31) & ((uint32_t)(regval) << 3)) -/* CAN transmit mailbox standard identifier*/ +/* CAN transmit mailbox standard identifier */ #define TMI_SFID(regval) (BITS(21,31) & ((uint32_t)(regval) << 21)) /* transmit data byte 0 */ @@ -520,76 +507,76 @@ typedef enum /* transmit data byte 2 */ #define TMDATA0_DB2(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) -/* transmit data byte 3 */ +/* transmit data byte 3 */ #define TMDATA0_DB3(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) -/* transmit data byte 4 */ +/* transmit data byte 4 */ #define TMDATA1_DB4(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) -/* transmit data byte 5 */ +/* transmit data byte 5 */ #define TMDATA1_DB5(regval) (BITS(8,15) & ((uint32_t)(regval) << 8)) -/* transmit data byte 6 */ +/* transmit data byte 6 */ #define TMDATA1_DB6(regval) (BITS(16,23) & ((uint32_t)(regval) << 16)) -/* transmit data byte 7 */ +/* transmit data byte 7 */ #define TMDATA1_DB7(regval) (BITS(24,31) & ((uint32_t)(regval) << 24)) -/* receive mailbox extended identifier*/ -#define GET_RFIFOMI_EFID(regval) GET_BITS((uint32_t)(regval), 3, 31) +/* receive mailbox extended identifier */ +#define GET_RFIFOMI_EFID(regval) GET_BITS((uint32_t)(regval), 3U, 31U) -/* receive mailbox standrad identifier*/ -#define GET_RFIFOMI_SFID(regval) GET_BITS((uint32_t)(regval), 21, 31) +/* receive mailbox standard identifier */ +#define GET_RFIFOMI_SFID(regval) GET_BITS((uint32_t)(regval), 21U, 31U) /* receive data length */ -#define GET_RFIFOMP_DLENC(regval) GET_BITS((uint32_t)(regval), 0, 3) +#define GET_RFIFOMP_DLENC(regval) GET_BITS((uint32_t)(regval), 0U, 3U) /* the index of the filter by which the frame is passed */ -#define GET_RFIFOMP_FI(regval) GET_BITS((uint32_t)(regval), 8, 15) +#define GET_RFIFOMP_FI(regval) GET_BITS((uint32_t)(regval), 8U, 15U) /* receive data byte 0 */ -#define GET_RFIFOMDATA0_DB0(regval) GET_BITS((uint32_t)(regval), 0, 7) +#define GET_RFIFOMDATA0_DB0(regval) GET_BITS((uint32_t)(regval), 0U, 7U) /* receive data byte 1 */ -#define GET_RFIFOMDATA0_DB1(regval) GET_BITS((uint32_t)(regval), 8, 15) +#define GET_RFIFOMDATA0_DB1(regval) GET_BITS((uint32_t)(regval), 8U, 15U) /* receive data byte 2 */ -#define GET_RFIFOMDATA0_DB2(regval) GET_BITS((uint32_t)(regval), 16, 23) +#define GET_RFIFOMDATA0_DB2(regval) GET_BITS((uint32_t)(regval), 16U, 23U) /* receive data byte 3 */ -#define GET_RFIFOMDATA0_DB3(regval) GET_BITS((uint32_t)(regval), 24, 31) +#define GET_RFIFOMDATA0_DB3(regval) GET_BITS((uint32_t)(regval), 24U, 31U) /* receive data byte 4 */ -#define GET_RFIFOMDATA1_DB4(regval) GET_BITS((uint32_t)(regval), 0, 7) +#define GET_RFIFOMDATA1_DB4(regval) GET_BITS((uint32_t)(regval), 0U, 7U) /* receive data byte 5 */ -#define GET_RFIFOMDATA1_DB5(regval) GET_BITS((uint32_t)(regval), 8, 15) +#define GET_RFIFOMDATA1_DB5(regval) GET_BITS((uint32_t)(regval), 8U, 15U) /* receive data byte 6 */ -#define GET_RFIFOMDATA1_DB6(regval) GET_BITS((uint32_t)(regval), 16, 23) +#define GET_RFIFOMDATA1_DB6(regval) GET_BITS((uint32_t)(regval), 16U, 23U) /* receive data byte 7 */ -#define GET_RFIFOMDATA1_DB7(regval) GET_BITS((uint32_t)(regval), 24, 31) +#define GET_RFIFOMDATA1_DB7(regval) GET_BITS((uint32_t)(regval), 24U, 31U) -/* error number */ -#define GET_ERR_ERRN(regval) GET_BITS((uint32_t)(regval), 4, 6) +/* error number */ +#define GET_ERR_ERRN(regval) GET_BITS((uint32_t)(regval), 4U, 6U) -/* transmit error count */ -#define GET_ERR_TECNT(regval) GET_BITS((uint32_t)(regval), 16, 23) +/* transmit error count */ +#define GET_ERR_TECNT(regval) GET_BITS((uint32_t)(regval), 16U, 23U) -/* receive error count */ -#define GET_ERR_RECNT(regval) GET_BITS((uint32_t)(regval), 24, 31) +/* receive error count */ +#define GET_ERR_RECNT(regval) GET_BITS((uint32_t)(regval), 24U, 31U) /* CAN errors */ #define ERR_ERRN(regval) (BITS(4,6) & ((uint32_t)(regval) << 4)) -#define CAN_ERRN_0 ERR_ERRN(0) /*!< no error */ -#define CAN_ERRN_1 ERR_ERRN(1) /*!< fill error */ -#define CAN_ERRN_2 ERR_ERRN(2) /*!< format error */ -#define CAN_ERRN_3 ERR_ERRN(3) /*!< ACK error */ -#define CAN_ERRN_4 ERR_ERRN(4) /*!< bit recessive error */ -#define CAN_ERRN_5 ERR_ERRN(5) /*!< bit dominant error */ -#define CAN_ERRN_6 ERR_ERRN(6) /*!< CRC error */ -#define CAN_ERRN_7 ERR_ERRN(7) /*!< software error */ +#define CAN_ERRN_0 ERR_ERRN(0U) /*!< no error */ +#define CAN_ERRN_1 ERR_ERRN(1U) /*!< fill error */ +#define CAN_ERRN_2 ERR_ERRN(2U) /*!< format error */ +#define CAN_ERRN_3 ERR_ERRN(3U) /*!< ACK error */ +#define CAN_ERRN_4 ERR_ERRN(4U) /*!< bit recessive error */ +#define CAN_ERRN_5 ERR_ERRN(5U) /*!< bit dominant error */ +#define CAN_ERRN_6 ERR_ERRN(6U) /*!< CRC error */ +#define CAN_ERRN_7 ERR_ERRN(7U) /*!< software error */ #define CAN_STATE_PENDING ((uint32_t)0x00000000U) /*!< CAN pending */ @@ -643,11 +630,11 @@ typedef enum #define CAN_FF_STANDARD ((uint32_t)0x00000000U) /*!< standard frame */ #define CAN_FF_EXTENDED ((uint32_t)0x00000004U) /*!< extended frame */ -/* CAN receive fifo */ +/* CAN receive FIFO */ #define CAN_FIFO0 ((uint8_t)0x00U) /*!< receive FIFO0 */ #define CAN_FIFO1 ((uint8_t)0x01U) /*!< receive FIFO1 */ -/* frame number of receive fifo */ +/* frame number of receive FIFO */ #define CAN_RFIF_RFL_MASK ((uint32_t)0x00000003U) /*!< mask for frame number in receive FIFOx */ #define CAN_SFID_MASK ((uint32_t)0x000007FFU) /*!< mask of standard identifier */ @@ -697,11 +684,11 @@ typedef enum /* deinitialize CAN */ void can_deinit(uint32_t can_periph); /* initialize CAN structure */ -void can_struct_para_init(can_struct_type_enum type, void* p_struct); +void can_struct_para_init(can_struct_type_enum type, void *p_struct); /* initialize CAN */ -ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init); +ErrStatus can_init(uint32_t can_periph, can_parameter_struct *can_parameter_init); /* CAN filter initialization */ -void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init); +void can_filter_init(can_filter_parameter_struct *can_filter_parameter_init); /* function configuration */ /* set can1 filter start bank number */ @@ -718,14 +705,14 @@ void can_time_trigger_mode_disable(uint32_t can_periph); /* transmit functions */ /* transmit CAN message */ -uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message); +uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct *transmit_message); /* get CAN transmit state */ can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number); /* stop CAN transmission */ void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number); /* CAN receive message */ -void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message); -/* CAN release fifo */ +void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct *receive_message); +/* CAN release FIFO */ void can_fifo_release(uint32_t can_periph, uint8_t fifo_number); /* CAN receive message length */ uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number); @@ -734,7 +721,7 @@ ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode); /* CAN wakeup from sleep mode */ ErrStatus can_wakeup(uint32_t can_periph); -/* CAN get error */ +/* CAN get error type */ can_error_enum can_error_get(uint32_t can_periph); /* get CAN receive error number */ uint8_t can_receive_error_number_get(uint32_t can_periph); @@ -742,14 +729,14 @@ uint8_t can_receive_error_number_get(uint32_t can_periph); uint8_t can_transmit_error_number_get(uint32_t can_periph); /* interrupt & flag functions */ -/* CAN interrupt enable */ -void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt); -/* CAN interrupt disable */ -void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt); /* CAN get flag state */ FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag); /* CAN clear flag state */ void can_flag_clear(uint32_t can_periph, can_flag_enum flag); +/* CAN interrupt enable */ +void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt); +/* CAN interrupt disable */ +void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt); /* CAN get interrupt flag state */ FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum flag); /* CAN clear interrupt flag state */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_cau.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_cau.h index 35946b61..a6776afb 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_cau.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_cau.h @@ -2,36 +2,33 @@ \file gd32f20x_cau.h \brief definitions for the CAU - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -41,29 +38,29 @@ OF SUCH DAMAGE. #include "gd32f20x.h" /* CAU definitions */ -#define CAU CAU_BASE +#define CAU CAU_BASE /*!< CAU base address */ /* registers definitions */ -#define CAU_CTL REG32(CAU + 0x00U) /*!< control register */ -#define CAU_STAT0 REG32(CAU + 0x04U) /*!< status register 0 */ -#define CAU_DI REG32(CAU + 0x08U) /*!< data input register */ -#define CAU_DO REG32(CAU + 0x0CU) /*!< data output register */ -#define CAU_DMAEN REG32(CAU + 0x10U) /*!< DMA enable register */ -#define CAU_INTEN REG32(CAU + 0x14U) /*!< interrupt enable register */ -#define CAU_STAT1 REG32(CAU + 0x18U) /*!< status register 1 */ -#define CAU_INTF REG32(CAU + 0x1CU) /*!< interrupt flag register */ -#define CAU_KEY0H REG32(CAU + 0x20U) /*!< key 0 high register */ -#define CAU_KEY0L REG32(CAU + 0x24U) /*!< key 0 low register */ -#define CAU_KEY1H REG32(CAU + 0x28U) /*!< key 1 high register */ -#define CAU_KEY1L REG32(CAU + 0x2CU) /*!< key 1 low register */ -#define CAU_KEY2H REG32(CAU + 0x30U) /*!< key 2 high register */ -#define CAU_KEY2L REG32(CAU + 0x34U) /*!< key 2 low register */ -#define CAU_KEY3H REG32(CAU + 0x38U) /*!< key 3 high register */ -#define CAU_KEY3L REG32(CAU + 0x3CU) /*!< key 3 low register */ -#define CAU_IV0H REG32(CAU + 0x40U) /*!< initial vector 0 high register */ -#define CAU_IV0L REG32(CAU + 0x44U) /*!< initial vector 0 low register */ -#define CAU_IV1H REG32(CAU + 0x48U) /*!< initial vector 1 high register */ -#define CAU_IV1L REG32(CAU + 0x4CU) /*!< initial vector 1 low register */ +#define CAU_CTL REG32(CAU + 0x00000000U) /*!< control register */ +#define CAU_STAT0 REG32(CAU + 0x00000004U) /*!< status register 0 */ +#define CAU_DI REG32(CAU + 0x00000008U) /*!< data input register */ +#define CAU_DO REG32(CAU + 0x0000000CU) /*!< data output register */ +#define CAU_DMAEN REG32(CAU + 0x00000010U) /*!< DMA enable register */ +#define CAU_INTEN REG32(CAU + 0x00000014U) /*!< interrupt enable register */ +#define CAU_STAT1 REG32(CAU + 0x00000018U) /*!< status register 1 */ +#define CAU_INTF REG32(CAU + 0x0000001CU) /*!< interrupt flag register */ +#define CAU_KEY0H REG32(CAU + 0x00000020U) /*!< key 0 high register */ +#define CAU_KEY0L REG32(CAU + 0x00000024U) /*!< key 0 low register */ +#define CAU_KEY1H REG32(CAU + 0x00000028U) /*!< key 1 high register */ +#define CAU_KEY1L REG32(CAU + 0x0000002CU) /*!< key 1 low register */ +#define CAU_KEY2H REG32(CAU + 0x00000030U) /*!< key 2 high register */ +#define CAU_KEY2L REG32(CAU + 0x00000034U) /*!< key 2 low register */ +#define CAU_KEY3H REG32(CAU + 0x00000038U) /*!< key 3 high register */ +#define CAU_KEY3L REG32(CAU + 0x0000003CU) /*!< key 3 low register */ +#define CAU_IV0H REG32(CAU + 0x00000040U) /*!< initial vector 0 high register */ +#define CAU_IV0L REG32(CAU + 0x00000044U) /*!< initial vector 0 low register */ +#define CAU_IV1H REG32(CAU + 0x00000048U) /*!< initial vector 1 high register */ +#define CAU_IV1L REG32(CAU + 0x0000004CU) /*!< initial vector 1 low register */ /* bits definitions */ /* CAU_CTL */ @@ -117,8 +114,7 @@ OF SUCH DAMAGE. /* constants definitions */ /* structure for keys initialization of the cau */ -typedef struct -{ +typedef struct { uint32_t key_0_high; /*!< key 0 high */ uint32_t key_0_low; /*!< key 0 low */ uint32_t key_1_high; /*!< key 1 high */ @@ -127,28 +123,26 @@ typedef struct uint32_t key_2_low; /*!< key 2 low */ uint32_t key_3_high; /*!< key 3 high */ uint32_t key_3_low; /*!< key 3 low */ -}cau_key_parameter_struct; +} cau_key_parameter_struct; /* structure for vectors initialization of the cau */ -typedef struct -{ +typedef struct { uint32_t iv_0_high; /*!< init vector 0 high */ uint32_t iv_0_low; /*!< init vector 0 low */ uint32_t iv_1_high; /*!< init vector 1 high */ uint32_t iv_1_low; /*!< init vector 1 low */ -}cau_iv_parameter_struct; +} cau_iv_parameter_struct; /* structure for vectors initialization of the cau */ -typedef struct -{ +typedef struct { uint8_t *input; /*!< pointer to the input buffer */ - uint32_t in_length; /*!< length of the input buffer, + uint32_t in_length; /*!< length of the input buffer, must be a multiple of 8(DES and TDES) or 16(AES) */ uint8_t *output; /*!< pointer to the returned buffer */ -}cau_text_struct; +} cau_text_struct; /* cau_ctl register value */ -#define CAU_ENCRYPT ((uint32_t)0x00000000) /*!< encrypt */ +#define CAU_ENCRYPT ((uint32_t)0x00000000U) /*!< encrypt */ #define CAU_DECRYPT CAU_CTL_CAUDIR /*!< decrypt */ #define CTL_ALGM(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) /*!< write value to CAU_CTL_ALGM bit field */ @@ -172,7 +166,7 @@ typedef struct #define CAU_KEYSIZE_192BIT CTL_KEYM(1) /*!< 192 bit key length */ #define CAU_KEYSIZE_256BIT CTL_KEYM(2) /*!< 256 bit key length */ -/* cau_stat0 register value */ +/* cau_stat0 register value */ #define CAU_FLAG_INFIFO_EMPTY CAU_STAT0_IEM /*!< IN FIFO empty */ #define CAU_FLAG_INFIFO_NO_FULL CAU_STAT0_INF /*!< IN FIFO is not full */ #define CAU_FLAG_OUTFIFO_NO_EMPTY CAU_STAT0_ONE /*!< OUT FIFO not empty */ @@ -212,13 +206,13 @@ void cau_init(uint32_t algo_dir, uint32_t algo_mode, uint32_t swapping); /* configure key size if used AES algorithm */ void cau_aes_keysize_config(uint32_t key_size); /* initialize the key parameters */ -void cau_key_init(cau_key_parameter_struct* key_initpara); +void cau_key_init(cau_key_parameter_struct *key_initpara); /* initialize the structure cau_key_initpara */ -void cau_key_parameter_init(cau_key_parameter_struct* key_initpara); +void cau_key_parameter_init(cau_key_parameter_struct *key_initpara); /* initialize the vectors parameters */ -void cau_iv_init(cau_iv_parameter_struct* iv_initpara); +void cau_iv_init(cau_iv_parameter_struct *iv_initpara); /* initialize the vectors parameters */ -void cau_iv_parameter_init(cau_iv_parameter_struct* iv_initpara); +void cau_iv_parameter_init(cau_iv_parameter_struct *iv_initpara); /* flush the IN and OUT FIFOs */ void cau_fifo_flush(void); /* return whether CAU peripheral is enabled or disabled */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_crc.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_crc.h index 4980cd33..721c2306 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_crc.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_crc.h @@ -2,36 +2,33 @@ \file gd32f20x_crc.h \brief definitions for the CRC - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -41,12 +38,12 @@ OF SUCH DAMAGE. #include "gd32f20x.h" /* CRC definitions */ -#define CRC CRC_BASE +#define CRC CRC_BASE /*!< CRC base address */ /* registers definitions */ -#define CRC_DATA REG32(CRC + 0x00U) /*!< CRC data register */ -#define CRC_FDATA REG32(CRC + 0x04U) /*!< CRC free data register */ -#define CRC_CTL REG32(CRC + 0x08U) /*!< CRC control register */ +#define CRC_DATA REG32(CRC + 0x00000000U) /*!< CRC data register */ +#define CRC_FDATA REG32(CRC + 0x00000004U) /*!< CRC free data register */ +#define CRC_CTL REG32(CRC + 0x00000008U) /*!< CRC control register */ /* bits definitions */ /* CRC_DATA */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dac.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dac.h index 0ef9fbfb..c4dd08a6 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dac.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dac.h @@ -2,36 +2,33 @@ \file gd32f20x_dac.h \brief definitions for the DAC - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -46,76 +43,76 @@ OF SUCH DAMAGE. #define DAC1 1U /* registers definitions */ -#define DAC_CTL REG32(DAC + 0x00U) /*!< DAC control register */ -#define DAC_SWT REG32(DAC + 0x04U) /*!< DAC software trigger register */ -#define DAC0_R12DH REG32(DAC + 0x08U) /*!< DAC0 12-bit right-aligned data holding register */ -#define DAC0_L12DH REG32(DAC + 0x0CU) /*!< DAC0 12-bit left-aligned data holding register */ -#define DAC0_R8DH REG32(DAC + 0x10U) /*!< DAC0 8-bit right-aligned data holding register */ -#define DAC1_R12DH REG32(DAC + 0x14U) /*!< DAC1 12-bit right-aligned data holding register */ -#define DAC1_L12DH REG32(DAC + 0x18U) /*!< DAC1 12-bit left-aligned data holding register */ -#define DAC1_R8DH REG32(DAC + 0x1CU) /*!< DAC1 8-bit right-aligned data holding register */ -#define DACC_R12DH REG32(DAC + 0x20U) /*!< DAC concurrent mode 12-bit right-aligned data holding register */ -#define DACC_L12DH REG32(DAC + 0x24U) /*!< DAC concurrent mode 12-bit left-aligned data holding register */ -#define DACC_R8DH REG32(DAC + 0x28U) /*!< DAC concurrent mode 8-bit right-aligned data holding register */ -#define DAC0_DO REG32(DAC + 0x2CU) /*!< DAC0 data output register */ -#define DAC1_DO REG32(DAC + 0x30U) /*!< DAC1 data output register */ +#define DAC_CTL REG32(DAC + 0x00000000U) /*!< DAC control register */ +#define DAC_SWT REG32(DAC + 0x00000004U) /*!< DAC software trigger register */ +#define DAC0_R12DH REG32(DAC + 0x00000008U) /*!< DAC0 12-bit right-aligned data holding register */ +#define DAC0_L12DH REG32(DAC + 0x0000000CU) /*!< DAC0 12-bit left-aligned data holding register */ +#define DAC0_R8DH REG32(DAC + 0x00000010U) /*!< DAC0 8-bit right-aligned data holding register */ +#define DAC1_R12DH REG32(DAC + 0x00000014U) /*!< DAC1 12-bit right-aligned data holding register */ +#define DAC1_L12DH REG32(DAC + 0x00000018U) /*!< DAC1 12-bit left-aligned data holding register */ +#define DAC1_R8DH REG32(DAC + 0x0000001CU) /*!< DAC1 8-bit right-aligned data holding register */ +#define DACC_R12DH REG32(DAC + 0x00000020U) /*!< DAC concurrent mode 12-bit right-aligned data holding register */ +#define DACC_L12DH REG32(DAC + 0x00000024U) /*!< DAC concurrent mode 12-bit left-aligned data holding register */ +#define DACC_R8DH REG32(DAC + 0x00000028U) /*!< DAC concurrent mode 8-bit right-aligned data holding register */ +#define DAC0_DO REG32(DAC + 0x0000002CU) /*!< DAC0 data output register */ +#define DAC1_DO REG32(DAC + 0x00000030U) /*!< DAC1 data output register */ /* bits definitions */ /* DAC_CTL */ -#define DAC_CTL_DEN0 BIT(0) /*!< DAC0 enable/disable bit */ -#define DAC_CTL_DBOFF0 BIT(1) /*!< DAC0 output buffer turn on/off bit */ -#define DAC_CTL_DTEN0 BIT(2) /*!< DAC0 trigger enable/disable bit */ -#define DAC_CTL_DTSEL0 BITS(3,5) /*!< DAC0 trigger source selection enable/disable bits */ -#define DAC_CTL_DWM0 BITS(6,7) /*!< DAC0 noise wave mode */ -#define DAC_CTL_DWBW0 BITS(8,11) /*!< DAC0 noise wave bit width */ -#define DAC_CTL_DDMAEN0 BIT(12) /*!< DAC0 DMA enable/disable bit */ -#define DAC_CTL_DEN1 BIT(16) /*!< DAC1 enable/disable bit */ -#define DAC_CTL_DBOFF1 BIT(17) /*!< DAC1 output buffer turn on/turn off bit */ -#define DAC_CTL_DTEN1 BIT(18) /*!< DAC1 trigger enable/disable bit */ -#define DAC_CTL_DTSEL1 BITS(19,21) /*!< DAC1 trigger source selection enable/disable bits */ -#define DAC_CTL_DWM1 BITS(22,23) /*!< DAC1 noise wave mode */ -#define DAC_CTL_DWBW1 BITS(24,27) /*!< DAC1 noise wave bit width */ -#define DAC_CTL_DDMAEN1 BIT(28) /*!< DAC1 DMA enable/disable bit */ +#define DAC_CTL_DEN0 BIT(0) /*!< DAC0 enable/disable bit */ +#define DAC_CTL_DBOFF0 BIT(1) /*!< DAC0 output buffer turn on/off bit */ +#define DAC_CTL_DTEN0 BIT(2) /*!< DAC0 trigger enable/disable bit */ +#define DAC_CTL_DTSEL0 BITS(3,5) /*!< DAC0 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM0 BITS(6,7) /*!< DAC0 noise wave mode */ +#define DAC_CTL_DWBW0 BITS(8,11) /*!< DAC0 noise wave bit width */ +#define DAC_CTL_DDMAEN0 BIT(12) /*!< DAC0 DMA enable/disable bit */ +#define DAC_CTL_DEN1 BIT(16) /*!< DAC1 enable/disable bit */ +#define DAC_CTL_DBOFF1 BIT(17) /*!< DAC1 output buffer turn on/turn off bit */ +#define DAC_CTL_DTEN1 BIT(18) /*!< DAC1 trigger enable/disable bit */ +#define DAC_CTL_DTSEL1 BITS(19,21) /*!< DAC1 trigger source selection enable/disable bits */ +#define DAC_CTL_DWM1 BITS(22,23) /*!< DAC1 noise wave mode */ +#define DAC_CTL_DWBW1 BITS(24,27) /*!< DAC1 noise wave bit width */ +#define DAC_CTL_DDMAEN1 BIT(28) /*!< DAC1 DMA enable/disable bit */ /* DAC_SWT */ -#define DAC_SWT_SWTR0 BIT(0) /*!< DAC0 software trigger bit, cleared by hardware */ -#define DAC_SWT_SWTR1 BIT(1) /*!< DAC1 software trigger bit, cleared by hardware */ +#define DAC_SWT_SWTR0 BIT(0) /*!< DAC0 software trigger bit, cleared by hardware */ +#define DAC_SWT_SWTR1 BIT(1) /*!< DAC1 software trigger bit, cleared by hardware */ /* DAC0_R12DH */ -#define DAC0_R12DH_DAC0_DH BITS(0,11) /*!< DAC0 12-bit right-aligned data bits */ +#define DAC0_R12DH_DAC0_DH BITS(0,11) /*!< DAC0 12-bit right-aligned data bits */ /* DAC0_L12DH */ -#define DAC0_L12DH_DAC0_DH BITS(4,15) /*!< DAC0 12-bit left-aligned data bits */ +#define DAC0_L12DH_DAC0_DH BITS(4,15) /*!< DAC0 12-bit left-aligned data bits */ /* DAC0_R8DH */ -#define DAC0_R8DH_DAC0_DH BITS(0,7) /*!< DAC0 8-bit right-aligned data bits */ +#define DAC0_R8DH_DAC0_DH BITS(0,7) /*!< DAC0 8-bit right-aligned data bits */ /* DAC1_R12DH */ -#define DAC1_R12DH_DAC1_DH BITS(0,11) /*!< DAC1 12-bit right-aligned data bits */ +#define DAC1_R12DH_DAC1_DH BITS(0,11) /*!< DAC1 12-bit right-aligned data bits */ /* DAC1_L12DH */ -#define DAC1_L12DH_DAC1_DH BITS(4,15) /*!< DAC1 12-bit left-aligned data bits */ +#define DAC1_L12DH_DAC1_DH BITS(4,15) /*!< DAC1 12-bit left-aligned data bits */ /* DAC1_R8DH */ -#define DAC1_R8DH_DAC1_DH BITS(0,7) /*!< DAC1 8-bit right-aligned data bits */ +#define DAC1_R8DH_DAC1_DH BITS(0,7) /*!< DAC1 8-bit right-aligned data bits */ /* DACC_R12DH */ -#define DACC_R12DH_DAC0_DH BITS(0,11) /*!< DAC concurrent mode DAC0 12-bit right-aligned data bits */ -#define DACC_R12DH_DAC1_DH BITS(16,27) /*!< DAC concurrent mode DAC1 12-bit right-aligned data bits */ +#define DACC_R12DH_DAC0_DH BITS(0,11) /*!< DAC concurrent mode DAC0 12-bit right-aligned data bits */ +#define DACC_R12DH_DAC1_DH BITS(16,27) /*!< DAC concurrent mode DAC1 12-bit right-aligned data bits */ /* DACC_L12DH */ -#define DACC_L12DH_DAC0_DH BITS(4,15) /*!< DAC concurrent mode DAC0 12-bit left-aligned data bits */ -#define DACC_L12DH_DAC1_DH BITS(20,31) /*!< DAC concurrent mode DAC1 12-bit left-aligned data bits */ +#define DACC_L12DH_DAC0_DH BITS(4,15) /*!< DAC concurrent mode DAC0 12-bit left-aligned data bits */ +#define DACC_L12DH_DAC1_DH BITS(20,31) /*!< DAC concurrent mode DAC1 12-bit left-aligned data bits */ /* DACC_R8DH */ -#define DACC_R8DH_DAC0_DH BITS(0,7) /*!< DAC concurrent mode DAC0 8-bit right-aligned data bits */ -#define DACC_R8DH_DAC1_DH BITS(8,15) /*!< DAC concurrent mode DAC1 8-bit right-aligned data bits */ +#define DACC_R8DH_DAC0_DH BITS(0,7) /*!< DAC concurrent mode DAC0 8-bit right-aligned data bits */ +#define DACC_R8DH_DAC1_DH BITS(8,15) /*!< DAC concurrent mode DAC1 8-bit right-aligned data bits */ /* DAC0_DO */ -#define DAC0_DO_DAC0_DO BITS(0,11) /*!< DAC0 12-bit output data bits */ +#define DAC0_DO_DAC0_DO BITS(0,11) /*!< DAC0 12-bit output data bits */ /* DAC1_DO */ -#define DAC1_DO_DAC1_DO BITS(0,11) /*!< DAC1 12-bit output data bits */ +#define DAC1_DO_DAC1_DO BITS(0,11) /*!< DAC1 12-bit output data bits */ /* constants definitions */ /* DAC trigger source */ @@ -195,12 +192,12 @@ void dac_disable(uint32_t dac_periph); /* enable DAC DMA */ void dac_dma_enable(uint32_t dac_periph); /* disable DAC DMA */ -void dac_dma_disable(uint32_t dac_periph); +void dac_dma_disable(uint32_t dac_periph); /* enable DAC output buffer */ void dac_output_buffer_enable(uint32_t dac_periph); /* disable DAC output buffer */ void dac_output_buffer_disable(uint32_t dac_periph); -/* get the last data output value */ +/* get DAC output value */ uint16_t dac_output_value_get(uint32_t dac_periph); /* set DAC data holding register value */ void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data); @@ -242,6 +239,6 @@ void dac_concurrent_output_buffer_enable(void); /* disable DAC concurrent buffer function */ void dac_concurrent_output_buffer_disable(void); /* set DAC concurrent mode data holding register value */ -void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1); +void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1); #endif /* GD32F20X_DAC_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dbg.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dbg.h index 0029be42..93adde35 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dbg.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dbg.h @@ -2,37 +2,33 @@ \file gd32f20x_dbg.h \brief definitions for the DBG - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x - \version 2020-12-14, V2.2.1, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -42,15 +38,15 @@ OF SUCH DAMAGE. #include "gd32f20x.h" /* DBG definitions */ -#define DBG DBG_BASE +#define DBG DBG_BASE /* registers definitions */ -#define DBG_ID REG32(DBG + 0x00U) /*!< DBG_ID code register */ -#define DBG_CTL REG32(DBG + 0x04U) /*!< DBG control register */ +#define DBG_ID REG32(DBG + 0x00000000U) /*!< DBG_ID code register */ +#define DBG_CTL REG32(DBG + 0x00000004U) /*!< DBG control register */ /* bits definitions */ /* DBG_ID */ -#define DBG_ID_ID_CODE BITS(0,31) /*!< DBG ID code values */ +#define DBG_ID_ID_CODE BITS(0,31) /*!< DBG ID code values */ /* DBG_CTL */ #define DBG_CTL_SLP_HOLD BIT(0) /*!< keep debugger connection during sleep mode */ @@ -78,32 +74,33 @@ OF SUCH DAMAGE. #define DBG_CTL_TIMER8_HOLD BIT(28) /*!< hold TIMER8 counter when core is halted */ #define DBG_CTL_TIMER9_HOLD BIT(29) /*!< hold TIMER9 counter when core is halted */ #define DBG_CTL_TIMER10_HOLD BIT(30) /*!< hold TIMER10 counter when core is halted */ +#define DBG_CTL_I2C2_HOLD BIT(31) /*!< hold I2C2 smbus when core is halted */ /* constants definitions */ /* debug hold when core is halted */ -typedef enum -{ - DBG_FWDGT_HOLD = BIT(8), /*!< debug FWDGT kept when core is halted */ - DBG_WWDGT_HOLD = BIT(9), /*!< debug WWDGT kept when core is halted */ - DBG_TIMER0_HOLD = BIT(10), /*!< hold TIMER0 counter when core is halted */ - DBG_TIMER1_HOLD = BIT(11), /*!< hold TIMER1 counter when core is halted */ - DBG_TIMER2_HOLD = BIT(12), /*!< hold TIMER2 counter when core is halted */ - DBG_TIMER3_HOLD = BIT(13), /*!< hold TIMER3 counter when core is halted */ - DBG_CAN0_HOLD = BIT(14), /*!< debug CAN0 kept when core is halted */ - DBG_I2C0_HOLD = BIT(15), /*!< hold I2C0 smbus when core is halted */ - DBG_I2C1_HOLD = BIT(16), /*!< hold I2C1 smbus when core is halted */ - DBG_TIMER7_HOLD = BIT(17), /*!< hold TIMER7 counter when core is halted */ - DBG_TIMER4_HOLD = BIT(18), /*!< hold TIMER4 counter when core is halted */ - DBG_TIMER5_HOLD = BIT(19), /*!< hold TIMER5 counter when core is halted */ - DBG_TIMER6_HOLD = BIT(20), /*!< hold TIMER6 counter when core is halted */ - DBG_CAN1_HOLD = BIT(21), /*!< debug CAN1 kept when core is halted */ - DBG_TIMER11_HOLD = BIT(25), /*!< hold TIMER11 counter when core is halted */ - DBG_TIMER12_HOLD = BIT(26), /*!< hold TIMER12 counter when core is halted */ - DBG_TIMER13_HOLD = BIT(27), /*!< hold TIMER13 counter when core is halted */ - DBG_TIMER8_HOLD = BIT(28), /*!< hold TIMER8 counter when core is halted */ - DBG_TIMER9_HOLD = BIT(29), /*!< hold TIMER9 counter when core is halted */ - DBG_TIMER10_HOLD = BIT(30), /*!< hold TIMER10 counter when core is halted */ -}dbg_periph_enum; +typedef enum { + DBG_FWDGT_HOLD = (int)BIT(8), /*!< debug FWDGT kept when core is halted */ + DBG_WWDGT_HOLD = (int)BIT(9), /*!< debug WWDGT kept when core is halted */ + DBG_TIMER0_HOLD = (int)BIT(10), /*!< hold TIMER0 counter when core is halted */ + DBG_TIMER1_HOLD = (int)BIT(11), /*!< hold TIMER1 counter when core is halted */ + DBG_TIMER2_HOLD = (int)BIT(12), /*!< hold TIMER2 counter when core is halted */ + DBG_TIMER3_HOLD = (int)BIT(13), /*!< hold TIMER3 counter when core is halted */ + DBG_CAN0_HOLD = (int)BIT(14), /*!< debug CAN0 kept when core is halted */ + DBG_I2C0_HOLD = (int)BIT(15), /*!< hold I2C0 smbus when core is halted */ + DBG_I2C1_HOLD = (int)BIT(16), /*!< hold I2C1 smbus when core is halted */ + DBG_TIMER7_HOLD = (int)BIT(17), /*!< hold TIMER7 counter when core is halted */ + DBG_TIMER4_HOLD = (int)BIT(18), /*!< hold TIMER4 counter when core is halted */ + DBG_TIMER5_HOLD = (int)BIT(19), /*!< hold TIMER5 counter when core is halted */ + DBG_TIMER6_HOLD = (int)BIT(20), /*!< hold TIMER6 counter when core is halted */ + DBG_CAN1_HOLD = (int)BIT(21), /*!< debug CAN1 kept when core is halted */ + DBG_TIMER11_HOLD = (int)BIT(25), /*!< hold TIMER11 counter when core is halted */ + DBG_TIMER12_HOLD = (int)BIT(26), /*!< hold TIMER12 counter when core is halted */ + DBG_TIMER13_HOLD = (int)BIT(27), /*!< hold TIMER13 counter when core is halted */ + DBG_TIMER8_HOLD = (int)BIT(28), /*!< hold TIMER8 counter when core is halted */ + DBG_TIMER9_HOLD = (int)BIT(29), /*!< hold TIMER9 counter when core is halted */ + DBG_TIMER10_HOLD = (int)BIT(30), /*!< hold TIMER10 counter when core is halted */ + DBG_I2C2_HOLD = (int)BIT(31), /*!< hold I2C2 smbus when core is halted */ +} dbg_periph_enum; /* DBG low power mode configurations */ #define DBG_LOW_POWER_SLEEP DBG_CTL_SLP_HOLD /*!< keep debugger connection during sleep mode */ @@ -111,7 +108,7 @@ typedef enum #define DBG_LOW_POWER_STANDBY DBG_CTL_STB_HOLD /*!< keep debugger connection during standby mode */ /* DBG_CTL0_TRACE_MODE configurations */ -#define CTL_TRACE_MODE(regval) (BITS(6,7) & ((uint32_t)(regval) << 6U)) +#define CTL_TRACE_MODE(regval) (BITS(6,7) & ((uint32_t)(regval) << 6U)) #define TRACE_MODE_ASYNC CTL_TRACE_MODE(0) /*!< trace pin used for async mode */ #define TRACE_MODE_SYNC_DATASIZE_1 CTL_TRACE_MODE(1) /*!< trace pin used for sync mode and data size is 1 */ #define TRACE_MODE_SYNC_DATASIZE_2 CTL_TRACE_MODE(2) /*!< trace pin used for sync mode and data size is 2 */ @@ -119,7 +116,7 @@ typedef enum /* function declarations */ /* initialization functions */ -/* read DBG_ID code register */ +/* read DBG_ID register */ uint32_t dbg_id_get(void); /* function configuration */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dci.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dci.h index 1e779a2e..8b9d8181 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dci.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dci.h @@ -2,36 +2,33 @@ \file gd32f20x_dci.h \brief definitions for the DCI - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -125,15 +122,14 @@ OF SUCH DAMAGE. /* constants definitions */ /* DCI parameter structure definitions */ -typedef struct -{ +typedef struct { uint32_t capture_mode; /*!< DCI capture mode: continuous or snapshot */ uint32_t clock_polarity; /*!< clock polarity selection */ uint32_t hsync_polarity; /*!< horizontal polarity selection */ uint32_t vsync_polarity; /*!< vertical polarity selection */ uint32_t frame_rate; /*!< frame capture rate */ uint32_t interface_format; /*!< digital camera interface format */ -}dci_parameter_struct; +} dci_parameter_struct; #define DCI_CAPTURE_MODE_CONTINUOUS ((uint32_t)0x00000000U) /*!< continuous capture mode */ #define DCI_CAPTURE_MODE_SNAPSHOT DCI_CTL_SNAP /*!< snapshot capture mode */ @@ -146,13 +142,13 @@ typedef struct #define DCI_VSYNC_POLARITY_LOW ((uint32_t)0x00000000U) /*!< low level during blanking period */ #define DCI_VSYNC_POLARITY_HIGH DCI_CTL_VPS /*!< high level during blanking period*/ - -#define CTL_FR(regval) (BITS(8,9)&((uint32_t)(regval) << 8U)) + +#define CTL_FR(regval) (BITS(8,9)&((uint32_t)(regval) << 8U)) #define DCI_FRAME_RATE_ALL CTL_FR(0) /*!< capture all frames */ #define DCI_FRAME_RATE_1_2 CTL_FR(1) /*!< capture one in 2 frames */ #define DCI_FRAME_RATE_1_4 CTL_FR(2) /*!< capture one in 4 frames */ -#define CTL_DCIF(regval) (BITS(10,11)&((uint32_t)(regval) << 10U)) +#define CTL_DCIF(regval) (BITS(10,11)&((uint32_t)(regval) << 10U)) #define DCI_INTERFACE_FORMAT_8BITS CTL_DCIF(0) /*!< 8-bit data on every pixel clock */ #define DCI_INTERFACE_FORMAT_10BITS CTL_DCIF(1) /*!< 10-bit data on every pixel clock */ #define DCI_INTERFACE_FORMAT_12BITS CTL_DCIF(2) /*!< 12-bit data on every pixel clock */ @@ -172,7 +168,7 @@ typedef struct #define DCI_INT_FLAG_VSYNC BIT(3) /*!< vsync interrupt flag */ #define DCI_INT_FLAG_EL BIT(4) /*!< end of line interrupt flag */ -/* DCI flag definitions */ +/* DCI flag definitions */ #define DCI_FLAG_HS DCI_STAT0_HS /*!< HS line status */ #define DCI_FLAG_VS DCI_STAT0_VS /*!< VS line status */ #define DCI_FLAG_FV DCI_STAT0_FV /*!< FIFO valid */ @@ -187,7 +183,7 @@ typedef struct /* DCI deinit */ void dci_deinit(void); /* initialize DCI registers */ -void dci_init(dci_parameter_struct* dci_struct); +void dci_init(dci_parameter_struct *dci_struct); /* enable DCI function */ void dci_enable(void); diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dma.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dma.h index aefef267..c1ffc259 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dma.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_dma.h @@ -2,36 +2,33 @@ \file gd32f20x_dma.h \brief definitions for the DMA - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -41,118 +38,115 @@ OF SUCH DAMAGE. #include "gd32f20x.h" /* DMA definitions */ -#define DMA0 (DMA_BASE) /*!< DMA0 base address */ -#define DMA1 (DMA_BASE + 0x0400U) /*!< DMA1 base address */ +#define DMA0 (DMA_BASE) /*!< DMA0 base address */ +#define DMA1 (DMA_BASE + 0x00000400U) /*!< DMA1 base address */ /* registers definitions */ -#define DMA_INTF(dmax) REG32((dmax) + 0x00U) /*!< DMA interrupt flag register */ -#define DMA_INTC(dmax) REG32((dmax) + 0x04U) /*!< DMA interrupt flag clear register */ - -#define DMA_CH0CTL(dmax) REG32((dmax) + 0x08U) /*!< DMA channel 0 control register */ -#define DMA_CH0CNT(dmax) REG32((dmax) + 0x0CU) /*!< DMA channel 0 counter register */ -#define DMA_CH0PADDR(dmax) REG32((dmax) + 0x10U) /*!< DMA channel 0 peripheral base address register */ -#define DMA_CH0MADDR(dmax) REG32((dmax) + 0x14U) /*!< DMA channel 0 memory base address register */ - -#define DMA_CH1CTL(dmax) REG32((dmax) + 0x1CU) /*!< DMA channel 1 control register */ -#define DMA_CH1CNT(dmax) REG32((dmax) + 0x20U) /*!< DMA channel 1 counter register */ -#define DMA_CH1PADDR(dmax) REG32((dmax) + 0x24U) /*!< DMA channel 1 peripheral base address register */ -#define DMA_CH1MADDR(dmax) REG32((dmax) + 0x28U) /*!< DMA channel 1 memory base address register */ - -#define DMA_CH2CTL(dmax) REG32((dmax) + 0x30U) /*!< DMA channel 2 control register */ -#define DMA_CH2CNT(dmax) REG32((dmax) + 0x34U) /*!< DMA channel 2 counter register */ -#define DMA_CH2PADDR(dmax) REG32((dmax) + 0x38U) /*!< DMA channel 2 peripheral base address register */ -#define DMA_CH2MADDR(dmax) REG32((dmax) + 0x3CU) /*!< DMA channel 2 memory base address register */ - -#define DMA_CH3CTL(dmax) REG32((dmax) + 0x44U) /*!< DMA channel 3 control register */ -#define DMA_CH3CNT(dmax) REG32((dmax) + 0x48U) /*!< DMA channel 3 counter register */ -#define DMA_CH3PADDR(dmax) REG32((dmax) + 0x4CU) /*!< DMA channel 3 peripheral base address register */ -#define DMA_CH3MADDR(dmax) REG32((dmax) + 0x50U) /*!< DMA channel 3 memory base address register */ - -#define DMA_CH4CTL(dmax) REG32((dmax) + 0x58U) /*!< DMA channel 4 control register */ -#define DMA_CH4CNT(dmax) REG32((dmax) + 0x5CU) /*!< DMA channel 4 counter register */ -#define DMA_CH4PADDR(dmax) REG32((dmax) + 0x60U) /*!< DMA channel 4 peripheral base address register */ -#define DMA_CH4MADDR(dmax) REG32((dmax) + 0x64U) /*!< DMA channel 4 memory base address register */ - -#define DMA_CH5CTL(dmax) REG32((dmax) + 0x6CU) /*!< DMA channel 5 control register */ -#define DMA_CH5CNT(dmax) REG32((dmax) + 0x70U) /*!< DMA channel 5 counter register */ -#define DMA_CH5PADDR(dmax) REG32((dmax) + 0x74U) /*!< DMA channel 5 peripheral base address register */ -#define DMA_CH5MADDR(dmax) REG32((dmax) + 0x78U) /*!< DMA channel 5 memory base address register */ - -#define DMA_CH6CTL(dmax) REG32((dmax) + 0x80U) /*!< DMA channel 6 control register */ -#define DMA_CH6CNT(dmax) REG32((dmax) + 0x84U) /*!< DMA channel 6 counter register */ -#define DMA_CH6PADDR(dmax) REG32((dmax) + 0x88U) /*!< DMA channel 6 peripheral base address register */ -#define DMA_CH6MADDR(dmax) REG32((dmax) + 0x8CU) /*!< DMA channel 6 memory base address register */ - -#define DMA_ACFG REG32((DMA1) + 0x300U) /*!< DMA additional configuration register */ +#define DMA_INTF(dmax) REG32((dmax) + 0x00000000U) /*!< DMA interrupt flag register */ +#define DMA_INTC(dmax) REG32((dmax) + 0x00000004U) /*!< DMA interrupt flag clear register */ + +#define DMA_CH0CTL(dmax) REG32((dmax) + 0x00000008U) /*!< DMA channel 0 control register */ +#define DMA_CH0CNT(dmax) REG32((dmax) + 0x0000000CU) /*!< DMA channel 0 counter register */ +#define DMA_CH0PADDR(dmax) REG32((dmax) + 0x00000010U) /*!< DMA channel 0 peripheral base address register */ +#define DMA_CH0MADDR(dmax) REG32((dmax) + 0x00000014U) /*!< DMA channel 0 memory base address register */ + +#define DMA_CH1CTL(dmax) REG32((dmax) + 0x0000001CU) /*!< DMA channel 1 control register */ +#define DMA_CH1CNT(dmax) REG32((dmax) + 0x00000020U) /*!< DMA channel 1 counter register */ +#define DMA_CH1PADDR(dmax) REG32((dmax) + 0x00000024U) /*!< DMA channel 1 peripheral base address register */ +#define DMA_CH1MADDR(dmax) REG32((dmax) + 0x00000028U) /*!< DMA channel 1 memory base address register */ + +#define DMA_CH2CTL(dmax) REG32((dmax) + 0x00000030U) /*!< DMA channel 2 control register */ +#define DMA_CH2CNT(dmax) REG32((dmax) + 0x00000034U) /*!< DMA channel 2 counter register */ +#define DMA_CH2PADDR(dmax) REG32((dmax) + 0x00000038U) /*!< DMA channel 2 peripheral base address register */ +#define DMA_CH2MADDR(dmax) REG32((dmax) + 0x0000003CU) /*!< DMA channel 2 memory base address register */ + +#define DMA_CH3CTL(dmax) REG32((dmax) + 0x00000044U) /*!< DMA channel 3 control register */ +#define DMA_CH3CNT(dmax) REG32((dmax) + 0x00000048U) /*!< DMA channel 3 counter register */ +#define DMA_CH3PADDR(dmax) REG32((dmax) + 0x0000004CU) /*!< DMA channel 3 peripheral base address register */ +#define DMA_CH3MADDR(dmax) REG32((dmax) + 0x00000050U) /*!< DMA channel 3 memory base address register */ + +#define DMA_CH4CTL(dmax) REG32((dmax) + 0x00000058U) /*!< DMA channel 4 control register */ +#define DMA_CH4CNT(dmax) REG32((dmax) + 0x0000005CU) /*!< DMA channel 4 counter register */ +#define DMA_CH4PADDR(dmax) REG32((dmax) + 0x00000060U) /*!< DMA channel 4 peripheral base address register */ +#define DMA_CH4MADDR(dmax) REG32((dmax) + 0x00000064U) /*!< DMA channel 4 memory base address register */ + +#define DMA_CH5CTL(dmax) REG32((dmax) + 0x0000006CU) /*!< DMA channel 5 control register */ +#define DMA_CH5CNT(dmax) REG32((dmax) + 0x00000070U) /*!< DMA channel 5 counter register */ +#define DMA_CH5PADDR(dmax) REG32((dmax) + 0x00000074U) /*!< DMA channel 5 peripheral base address register */ +#define DMA_CH5MADDR(dmax) REG32((dmax) + 0x00000078U) /*!< DMA channel 5 memory base address register */ + +#define DMA_CH6CTL(dmax) REG32((dmax) + 0x00000080U) /*!< DMA channel 6 control register */ +#define DMA_CH6CNT(dmax) REG32((dmax) + 0x00000084U) /*!< DMA channel 6 counter register */ +#define DMA_CH6PADDR(dmax) REG32((dmax) + 0x00000088U) /*!< DMA channel 6 peripheral base address register */ +#define DMA_CH6MADDR(dmax) REG32((dmax) + 0x0000008CU) /*!< DMA channel 6 memory base address register */ + +#define DMA_ACFG REG32((DMA1) + 0x00000300U) /*!< DMA additional configuration register */ /* bits definitions */ /* DMA_INTF */ -#define DMA_INTF_GIF BIT(0) /*!< global interrupt flag of channel */ -#define DMA_INTF_FTFIF BIT(1) /*!< full transfer finish flag of channel */ -#define DMA_INTF_HTFIF BIT(2) /*!< half transfer finish flag of channel */ -#define DMA_INTF_ERRIF BIT(3) /*!< error flag of channel */ +#define DMA_INTF_GIF BIT(0) /*!< global interrupt flag of channel */ +#define DMA_INTF_FTFIF BIT(1) /*!< full transfer finish flag of channel */ +#define DMA_INTF_HTFIF BIT(2) /*!< half transfer finish flag of channel */ +#define DMA_INTF_ERRIF BIT(3) /*!< error flag of channel */ /* DMA_INTC */ -#define DMA_INTC_GIFC BIT(0) /*!< clear global interrupt flag of channel */ -#define DMA_INTC_FTFIFC BIT(1) /*!< clear transfer finish flag of channel */ -#define DMA_INTC_HTFIFC BIT(2) /*!< clear half transfer finish flag of channel */ -#define DMA_INTC_ERRIFC BIT(3) /*!< clear error flag of channel */ +#define DMA_INTC_GIFC BIT(0) /*!< clear global interrupt flag of channel */ +#define DMA_INTC_FTFIFC BIT(1) /*!< clear transfer finish flag of channel */ +#define DMA_INTC_HTFIFC BIT(2) /*!< clear half transfer finish flag of channel */ +#define DMA_INTC_ERRIFC BIT(3) /*!< clear error flag of channel */ /* DMA_CHxCTL, x=0..6 */ -#define DMA_CHXCTL_CHEN BIT(0) /*!< channel enable */ -#define DMA_CHXCTL_FTFIE BIT(1) /*!< enable bit for channel full transfer finish interrupt */ -#define DMA_CHXCTL_HTFIE BIT(2) /*!< enable bit for channel half transfer finish interrupt */ -#define DMA_CHXCTL_ERRIE BIT(3) /*!< enable bit for channel error interrupt */ -#define DMA_CHXCTL_DIR BIT(4) /*!< transfer direction */ -#define DMA_CHXCTL_CMEN BIT(5) /*!< circular mode enable */ -#define DMA_CHXCTL_PNAGA BIT(6) /*!< next address generation algorithm of peripheral */ -#define DMA_CHXCTL_MNAGA BIT(7) /*!< next address generation algorithm of memory */ -#define DMA_CHXCTL_PWIDTH BITS(8,9) /*!< transfer data width of peripheral */ -#define DMA_CHXCTL_MWIDTH BITS(10,11) /*!< transfer data width of memory */ -#define DMA_CHXCTL_PRIO BITS(12,13) /*!< priority level */ -#define DMA_CHXCTL_M2M BIT(14) /*!< memory to memory mode */ +#define DMA_CHXCTL_CHEN BIT(0) /*!< channel enable */ +#define DMA_CHXCTL_FTFIE BIT(1) /*!< enable bit for channel full transfer finish interrupt */ +#define DMA_CHXCTL_HTFIE BIT(2) /*!< enable bit for channel half transfer finish interrupt */ +#define DMA_CHXCTL_ERRIE BIT(3) /*!< enable bit for channel error interrupt */ +#define DMA_CHXCTL_DIR BIT(4) /*!< transfer direction */ +#define DMA_CHXCTL_CMEN BIT(5) /*!< enable circular mode */ +#define DMA_CHXCTL_PNAGA BIT(6) /*!< next address generation algorithm of peripheral */ +#define DMA_CHXCTL_MNAGA BIT(7) /*!< next address generation algorithm of memory */ +#define DMA_CHXCTL_PWIDTH BITS(8,9) /*!< transfer data width of peripheral */ +#define DMA_CHXCTL_MWIDTH BITS(10,11) /*!< transfer data width of memory */ +#define DMA_CHXCTL_PRIO BITS(12,13) /*!< priority level */ +#define DMA_CHXCTL_M2M BIT(14) /*!< memory to memory mode */ /* DMA_CHxCNT, x=0..6 */ -#define DMA_CHXCNT_CNT BITS(0,15) /*!< transfer counter */ +#define DMA_CHXCNT_CNT BITS(0,15) /*!< transfer counter */ /* DMA_CHxPADDR, x=0..6 */ -#define DMA_CHXPADDR_PADDR BITS(0,31) /*!< peripheral base address */ +#define DMA_CHXPADDR_PADDR BITS(0,31) /*!< peripheral base address */ /* DMA_CHxMADDR, x=0..6 */ -#define DMA_CHXMADDR_MADDR BITS(0,31) /*!< memory base address */ +#define DMA_CHXMADDR_MADDR BITS(0,31) /*!< memory base address */ /* DMA_ACFG */ -#define DMA_ACFG_FD_CH5EN BIT(5) /*!< enable bit for DMA1 channel 5 Full_Data transfer mode */ +#define DMA_ACFG_FD_CH5EN BIT(5) /*!< enable bit for DMA1 channel 5 Full_Data transfer mode */ /* constants definitions */ -/* DMA channel select */ -typedef enum -{ - DMA_CH0 = 0, /*!< DMA channel 0 */ - DMA_CH1, /*!< DMA channel 1 */ - DMA_CH2, /*!< DMA channel 2 */ - DMA_CH3, /*!< DMA channel 3 */ - DMA_CH4, /*!< DMA channel 4 */ - DMA_CH5, /*!< DMA channel 5 */ - DMA_CH6 /*!< DMA channel 6 */ +/* DMA channel selection */ +typedef enum { + DMA_CH0 = 0, /*!< DMA channel 0 */ + DMA_CH1, /*!< DMA channel 1 */ + DMA_CH2, /*!< DMA channel 2 */ + DMA_CH3, /*!< DMA channel 3 */ + DMA_CH4, /*!< DMA channel 4 */ + DMA_CH5, /*!< DMA channel 5 */ + DMA_CH6 /*!< DMA channel 6 */ } dma_channel_enum; -/* DMA initialize struct */ -typedef struct -{ - uint32_t periph_addr; /*!< peripheral base address */ - uint32_t periph_width; /*!< transfer data size of peripheral */ - uint32_t memory_addr; /*!< memory base address */ - uint32_t memory_width; /*!< transfer data size of memory */ - uint32_t number; /*!< channel transfer number */ - uint32_t priority; /*!< channel priority level */ - uint8_t periph_inc; /*!< peripheral increasing mode */ - uint8_t memory_inc; /*!< memory increasing mode */ - uint8_t direction; /*!< channel data transfer direction */ - +/* DMA initialize structure */ +typedef struct { + uint32_t periph_addr; /*!< peripheral base address */ + uint32_t periph_width; /*!< transfer data size of peripheral */ + uint32_t memory_addr; /*!< memory base address */ + uint32_t memory_width; /*!< transfer data size of memory */ + uint32_t number; /*!< channel transfer number */ + uint32_t priority; /*!< channel priority level */ + uint8_t periph_inc; /*!< peripheral increasing mode */ + uint8_t memory_inc; /*!< memory increasing mode */ + uint8_t direction; /*!< channel data transfer direction */ } dma_parameter_struct; -#define DMA_FLAG_ADD(flag, shift) ((flag) << ((shift) * 4U)) /*!< DMA channel flag shift */ +#define DMA_FLAG_ADD(flag, shift) ((flag) << ((shift) * 4U)) /*!< DMA channel flag shift */ /* DMA_register address */ #define DMA_CHCTL(dma, channel) REG32(((dma) + 0x08U) + 0x14U * (uint32_t)(channel)) /*!< the address of DMA channel CHXCTL register */ @@ -233,10 +227,10 @@ typedef struct /* function declarations */ /* initialization functions */ -/* deinitialize DMA a channel registers */ +/* deinitialize a DMA channel registers */ void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx); /* initialize the parameters of DMA structure with the default values */ -void dma_struct_para_init(dma_parameter_struct* init_struct); +void dma_struct_para_init(dma_parameter_struct *init_struct); /* initialize DMA channel */ void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_struct *init_struct); /* enable DMA circulation mode */ @@ -278,23 +272,23 @@ void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) /* configure the direction of data transfer on the channel */ void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction); +/* enable the DMA1 channel 5 Full_Data transfer mode */ +void dma_1_channel_5_fulldata_transfer_enable(void); +/* disable the DMA1 channel 5 Full_Data transfer mode */ +void dma_1_channel_5_fulldata_transfer_disable(void); + /* flag and interrupt functions */ /* check DMA flag is set or not */ FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); /* clear the flag of a DMA channel */ void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); -/* check DMA flag and interrupt enable bit is set or not */ -FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); -/* clear the interrupt flag of a DMA channel */ -void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); /* enable DMA interrupt */ void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); /* disable DMA interrupt */ void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint32_t source); - -/* enable the DMA1 channel 5 Full_Data transfer mode */ -void dma_1_channel_5_fulldata_transfer_enable(void); -/* disable the DMA1 channel 5 Full_Data transfer mode */ -void dma_1_channel_5_fulldata_transfer_disable(void); +/* check DMA flag and interrupt enable bit is set or not */ +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); +/* clear the interrupt flag of a DMA channel */ +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag); #endif /* GD32F20X_DMA_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_enet.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_enet.h index 689448a1..822ef36e 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_enet.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_enet.h @@ -2,36 +2,33 @@ \file gd32f20x_enet.h \brief definitions for the ENET - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -41,17 +38,17 @@ OF SUCH DAMAGE. #include "gd32f20x.h" #include -#define IF_USE_EXTERNPHY_LIB 0 +#define IF_USE_EXTERNPHY_LIB 0U #if (1 == IF_USE_EXTERNPHY_LIB) #include "phy.h" #endif #ifndef ENET_RXBUF_NUM -#define ENET_RXBUF_NUM 2U /*!< ethernet Rx DMA descriptor number */ +#define ENET_RXBUF_NUM 5U /*!< ethernet Rx DMA descriptor number */ #endif #ifndef ENET_TXBUF_NUM -#define ENET_TXBUF_NUM 1U /*!< ethernet Tx DMA descriptor number */ +#define ENET_TXBUF_NUM 5U /*!< ethernet Tx DMA descriptor number */ #endif #ifndef ENET_RXBUF_SIZE @@ -74,7 +71,7 @@ OF SUCH DAMAGE. #define PHY_ADDRESS ((uint16_t)1U) /*!< phy address determined by the hardware */ -/* PHY read write timeouts */ +/* PHY read write timeouts */ #define PHY_READ_TO ((uint32_t)0x0004FFFFU) /*!< PHY read timeout */ #define PHY_WRITE_TO ((uint32_t)0x0004FFFFU) /*!< PHY write timeout */ @@ -82,35 +79,35 @@ OF SUCH DAMAGE. #define PHY_RESETDELAY ((uint32_t)0x008FFFFFU) /*!< PHY reset delay */ #define PHY_CONFIGDELAY ((uint32_t)0x00FFFFFFU) /*!< PHY configure delay */ -/* PHY register address */ +/* PHY register address */ #define PHY_REG_BCR 0U /*!< tranceiver basic control register */ #define PHY_REG_BSR 1U /*!< tranceiver basic status register */ /* PHY basic control register */ -#define PHY_RESET ((uint16_t)0x8000) /*!< PHY reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< enable phy loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< configure speed to 100 Mbit/s and the full-duplex mode */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< configure speed to 100 Mbit/s and the half-duplex mode */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< configure speed to 10 Mbit/s and the full-duplex mode */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< configure speed to 10 Mbit/s and the half-duplex mode */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< enable the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400) /*!< isolate PHY from MII */ +#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< enable phy loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< configure speed to 100 Mbit/s and the full-duplex mode */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< configure speed to 100 Mbit/s and the half-duplex mode */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< configure speed to 10 Mbit/s and the full-duplex mode */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< configure speed to 10 Mbit/s and the half-duplex mode */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< enable the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< isolate PHY from MII */ /* PHY basic status register */ -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< auto-negotioation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< jabber condition detected */ +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< auto-negotioation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< jabber condition detected */ -#if(PHY_TYPE == LAN8700) +#if(PHY_TYPE == LAN8700) #define PHY_SR 31U /*!< tranceiver status register */ -#define PHY_SPEED_STATUS ((uint16_t)0x0004) /*!< configured information of speed: 10Mbit/s */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0010) /*!< configured information of duplex: full-duplex */ +#define PHY_SPEED_STATUS ((uint16_t)0x0004U) /*!< configured information of speed: 10Mbit/s */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0010U) /*!< configured information of duplex: full-duplex */ #elif(PHY_TYPE == DP83848) #define PHY_SR 16U /*!< tranceiver status register */ -#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< configured information of speed: 10Mbit/s */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< configured information of duplex: full-duplex */ +#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< configured information of speed: 10Mbit/s */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< configured information of duplex: full-duplex */ #elif(PHY_TYPE == RTL8201F) /** AvV **/ # define PHY_SR 0U /*!< tranceiver status register */ # define PHY_SPEED_STATUS ((uint16_t)0x2000) /*!< configured information of speed: 100Mbit/s */ @@ -124,63 +121,63 @@ OF SUCH DAMAGE. #define ENET ENET_BASE /* registers definitions */ -#define ENET_MAC_CFG REG32((ENET) + 0x00U) /*!< ethernet MAC configuration register */ -#define ENET_MAC_FRMF REG32((ENET) + 0x04U) /*!< ethernet MAC frame filter register */ -#define ENET_MAC_HLH REG32((ENET) + 0x08U) /*!< ethernet MAC hash list high register */ -#define ENET_MAC_HLL REG32((ENET) + 0x0CU) /*!< ethernet MAC hash list low register */ -#define ENET_MAC_PHY_CTL REG32((ENET) + 0x10U) /*!< ethernet MAC PHY control register */ -#define ENET_MAC_PHY_DATA REG32((ENET) + 0x14U) /*!< ethernet MAC MII data register */ -#define ENET_MAC_FCTL REG32((ENET) + 0x18U) /*!< ethernet MAC flow control register */ -#define ENET_MAC_FCTH REG32((ENET) + 0x1080U) /*!< ethernet MAC flow control threshold register */ -#define ENET_MAC_VLT REG32((ENET) + 0x1CU) /*!< ethernet MAC VLAN tag register */ -#define ENET_MAC_RWFF REG32((ENET) + 0x28U) /*!< ethernet MAC remote wakeup frame filter register */ -#define ENET_MAC_WUM REG32((ENET) + 0x2CU) /*!< ethernet MAC wakeup management register */ -#define ENET_MAC_INTF REG32((ENET) + 0x38U) /*!< ethernet MAC interrupt flag register */ -#define ENET_MAC_INTMSK REG32((ENET) + 0x3CU) /*!< ethernet MAC interrupt mask register */ -#define ENET_MAC_ADDR0H REG32((ENET) + 0x40U) /*!< ethernet MAC address 0 high register */ -#define ENET_MAC_ADDR0L REG32((ENET) + 0x44U) /*!< ethernet MAC address 0 low register */ -#define ENET_MAC_ADDR1H REG32((ENET) + 0x48U) /*!< ethernet MAC address 1 high register */ -#define ENET_MAC_ADDR1L REG32((ENET) + 0x4CU) /*!< ethernet MAC address 1 low register */ -#define ENET_MAC_ADDT2H REG32((ENET) + 0x50U) /*!< ethernet MAC address 2 high register */ -#define ENET_MAC_ADDR2L REG32((ENET) + 0x54U) /*!< ethernet MAC address 2 low register */ -#define ENET_MAC_ADDR3H REG32((ENET) + 0x58U) /*!< ethernet MAC address 3 high register */ -#define ENET_MAC_ADDR3L REG32((ENET) + 0x5CU) /*!< ethernet MAC address 3 low register */ - -#define ENET_MSC_CTL REG32((ENET) + 0x100U) /*!< ethernet MSC control register */ -#define ENET_MSC_RINTF REG32((ENET) + 0x104U) /*!< ethernet MSC receive interrupt flag register */ -#define ENET_MSC_TINTF REG32((ENET) + 0x108U) /*!< ethernet MSC transmit interrupt flag register */ -#define ENET_MSC_RINTMSK REG32((ENET) + 0x10CU) /*!< ethernet MSC receive interrupt mask register */ -#define ENET_MSC_TINTMSK REG32((ENET) + 0x110U) /*!< ethernet MSC transmit interrupt mask register */ -#define ENET_MSC_SCCNT REG32((ENET) + 0x14CU) /*!< ethernet MSC transmitted good frames after a single collision counter register */ -#define ENET_MSC_MSCCNT REG32((ENET) + 0x150U) /*!< ethernet MSC transmitted good frames after more than a single collision counter register */ -#define ENET_MSC_TGFCNT REG32((ENET) + 0x168U) /*!< ethernet MSC transmitted good frames counter register */ -#define ENET_MSC_RFCECNT REG32((ENET) + 0x194U) /*!< ethernet MSC received frames with CRC error counter register */ -#define ENET_MSC_RFAECNT REG32((ENET) + 0x198U) /*!< ethernet MSC received frames with alignment error counter register */ -#define ENET_MSC_RGUFCNT REG32((ENET) + 0x1C4U) /*!< ethernet MSC received good unicast frames counter register */ - -#define ENET_PTP_TSCTL REG32((ENET) + 0x700U) /*!< ethernet PTP time stamp control register */ -#define ENET_PTP_SSINC REG32((ENET) + 0x704U) /*!< ethernet PTP subsecond increment register */ -#define ENET_PTP_TSH REG32((ENET) + 0x708U) /*!< ethernet PTP time stamp high register */ -#define ENET_PTP_TSL REG32((ENET) + 0x70CU) /*!< ethernet PTP time stamp low register */ -#define ENET_PTP_TSUH REG32((ENET) + 0x710U) /*!< ethernet PTP time stamp update high register */ -#define ENET_PTP_TSUL REG32((ENET) + 0x714U) /*!< ethernet PTP time stamp update low register */ -#define ENET_PTP_TSADDEND REG32((ENET) + 0x718U) /*!< ethernet PTP time stamp addend register */ -#define ENET_PTP_ETH REG32((ENET) + 0x71CU) /*!< ethernet PTP expected time high register */ -#define ENET_PTP_ETL REG32((ENET) + 0x720U) /*!< ethernet PTP expected time low register */ - -#define ENET_DMA_BCTL REG32((ENET) + 0x1000U) /*!< ethernet DMA bus control register */ -#define ENET_DMA_TPEN REG32((ENET) + 0x1004U) /*!< ethernet DMA transmit poll enable register */ -#define ENET_DMA_RPEN REG32((ENET) + 0x1008U) /*!< ethernet DMA receive poll enable register */ -#define ENET_DMA_RDTADDR REG32((ENET) + 0x100CU) /*!< ethernet DMA receive descriptor table address register */ -#define ENET_DMA_TDTADDR REG32((ENET) + 0x1010U) /*!< ethernet DMA transmit descriptor table address register */ -#define ENET_DMA_STAT REG32((ENET) + 0x1014U) /*!< ethernet DMA status register */ -#define ENET_DMA_CTL REG32((ENET) + 0x1018U) /*!< ethernet DMA control register */ -#define ENET_DMA_INTEN REG32((ENET) + 0x101CU) /*!< ethernet DMA interrupt enable register */ -#define ENET_DMA_MFBOCNT REG32((ENET) + 0x1020U) /*!< ethernet DMA missed frame and buffer overflow counter register */ -#define ENET_DMA_CTDADDR REG32((ENET) + 0x1048U) /*!< ethernet DMA current transmit descriptor address register */ -#define ENET_DMA_CRDADDR REG32((ENET) + 0x104CU) /*!< ethernet DMA current receive descriptor address register */ -#define ENET_DMA_CTBADDR REG32((ENET) + 0x1050U) /*!< ethernet DMA current transmit buffer address register */ -#define ENET_DMA_CRBADDR REG32((ENET) + 0x1054U) /*!< ethernet DMA current receive buffer address register */ +#define ENET_MAC_CFG REG32((ENET) + 0x00000000U) /*!< ethernet MAC configuration register */ +#define ENET_MAC_FRMF REG32((ENET) + 0x00000004U) /*!< ethernet MAC frame filter register */ +#define ENET_MAC_HLH REG32((ENET) + 0x00000008U) /*!< ethernet MAC hash list high register */ +#define ENET_MAC_HLL REG32((ENET) + 0x0000000CU) /*!< ethernet MAC hash list low register */ +#define ENET_MAC_PHY_CTL REG32((ENET) + 0x00000010U) /*!< ethernet MAC PHY control register */ +#define ENET_MAC_PHY_DATA REG32((ENET) + 0x00000014U) /*!< ethernet MAC PHY data register */ +#define ENET_MAC_FCTL REG32((ENET) + 0x00000018U) /*!< ethernet MAC flow control register */ +#define ENET_MAC_FCTH REG32((ENET) + 0x00001080U) /*!< ethernet MAC flow control threshold register */ +#define ENET_MAC_VLT REG32((ENET) + 0x0000001CU) /*!< ethernet MAC VLAN tag register */ +#define ENET_MAC_RWFF REG32((ENET) + 0x00000028U) /*!< ethernet MAC remote wakeup frame filter register */ +#define ENET_MAC_WUM REG32((ENET) + 0x0000002CU) /*!< ethernet MAC wakeup management register */ +#define ENET_MAC_INTF REG32((ENET) + 0x00000038U) /*!< ethernet MAC interrupt flag register */ +#define ENET_MAC_INTMSK REG32((ENET) + 0x0000003CU) /*!< ethernet MAC interrupt mask register */ +#define ENET_MAC_ADDR0H REG32((ENET) + 0x00000040U) /*!< ethernet MAC address 0 high register */ +#define ENET_MAC_ADDR0L REG32((ENET) + 0x00000044U) /*!< ethernet MAC address 0 low register */ +#define ENET_MAC_ADDR1H REG32((ENET) + 0x00000048U) /*!< ethernet MAC address 1 high register */ +#define ENET_MAC_ADDR1L REG32((ENET) + 0x0000004CU) /*!< ethernet MAC address 1 low register */ +#define ENET_MAC_ADDT2H REG32((ENET) + 0x00000050U) /*!< ethernet MAC address 2 high register */ +#define ENET_MAC_ADDR2L REG32((ENET) + 0x00000054U) /*!< ethernet MAC address 2 low register */ +#define ENET_MAC_ADDR3H REG32((ENET) + 0x00000058U) /*!< ethernet MAC address 3 high register */ +#define ENET_MAC_ADDR3L REG32((ENET) + 0x0000005CU) /*!< ethernet MAC address 3 low register */ + +#define ENET_MSC_CTL REG32((ENET) + 0x00000100U) /*!< ethernet MSC control register */ +#define ENET_MSC_RINTF REG32((ENET) + 0x00000104U) /*!< ethernet MSC receive interrupt flag register */ +#define ENET_MSC_TINTF REG32((ENET) + 0x00000108U) /*!< ethernet MSC transmit interrupt flag register */ +#define ENET_MSC_RINTMSK REG32((ENET) + 0x0000010CU) /*!< ethernet MSC receive interrupt mask register */ +#define ENET_MSC_TINTMSK REG32((ENET) + 0x00000110U) /*!< ethernet MSC transmit interrupt mask register */ +#define ENET_MSC_SCCNT REG32((ENET) + 0x0000014CU) /*!< ethernet MSC transmitted good frames after a single collision counter register */ +#define ENET_MSC_MSCCNT REG32((ENET) + 0x00000150U) /*!< ethernet MSC transmitted good frames after more than a single collision counter register */ +#define ENET_MSC_TGFCNT REG32((ENET) + 0x00000168U) /*!< ethernet MSC transmitted good frames counter register */ +#define ENET_MSC_RFCECNT REG32((ENET) + 0x00000194U) /*!< ethernet MSC received frames with CRC error counter register */ +#define ENET_MSC_RFAECNT REG32((ENET) + 0x00000198U) /*!< ethernet MSC received frames with alignment error counter register */ +#define ENET_MSC_RGUFCNT REG32((ENET) + 0x000001C4U) /*!< ethernet MSC received good unicast frames counter register */ + +#define ENET_PTP_TSCTL REG32((ENET) + 0x00000700U) /*!< ethernet PTP time stamp control register */ +#define ENET_PTP_SSINC REG32((ENET) + 0x00000704U) /*!< ethernet PTP subsecond increment register */ +#define ENET_PTP_TSH REG32((ENET) + 0x00000708U) /*!< ethernet PTP time stamp high register */ +#define ENET_PTP_TSL REG32((ENET) + 0x0000070CU) /*!< ethernet PTP time stamp low register */ +#define ENET_PTP_TSUH REG32((ENET) + 0x00000710U) /*!< ethernet PTP time stamp update high register */ +#define ENET_PTP_TSUL REG32((ENET) + 0x00000714U) /*!< ethernet PTP time stamp update low register */ +#define ENET_PTP_TSADDEND REG32((ENET) + 0x00000718U) /*!< ethernet PTP time stamp addend register */ +#define ENET_PTP_ETH REG32((ENET) + 0x0000071CU) /*!< ethernet PTP expected time high register */ +#define ENET_PTP_ETL REG32((ENET) + 0x00000720U) /*!< ethernet PTP expected time low register */ + +#define ENET_DMA_BCTL REG32((ENET) + 0x00001000U) /*!< ethernet DMA bus control register */ +#define ENET_DMA_TPEN REG32((ENET) + 0x00001004U) /*!< ethernet DMA transmit poll enable register */ +#define ENET_DMA_RPEN REG32((ENET) + 0x00001008U) /*!< ethernet DMA receive poll enable register */ +#define ENET_DMA_RDTADDR REG32((ENET) + 0x0000100CU) /*!< ethernet DMA receive descriptor table address register */ +#define ENET_DMA_TDTADDR REG32((ENET) + 0x00001010U) /*!< ethernet DMA transmit descriptor table address register */ +#define ENET_DMA_STAT REG32((ENET) + 0x00001014U) /*!< ethernet DMA status register */ +#define ENET_DMA_CTL REG32((ENET) + 0x00001018U) /*!< ethernet DMA control register */ +#define ENET_DMA_INTEN REG32((ENET) + 0x0000101CU) /*!< ethernet DMA interrupt enable register */ +#define ENET_DMA_MFBOCNT REG32((ENET) + 0x00001020U) /*!< ethernet DMA missed frame and buffer overflow counter register */ +#define ENET_DMA_CTDADDR REG32((ENET) + 0x00001048U) /*!< ethernet DMA current transmit descriptor address register */ +#define ENET_DMA_CRDADDR REG32((ENET) + 0x0000104CU) /*!< ethernet DMA current receive descriptor address register */ +#define ENET_DMA_CTBADDR REG32((ENET) + 0x00001050U) /*!< ethernet DMA current transmit buffer address register */ +#define ENET_DMA_CRBADDR REG32((ENET) + 0x00001054U) /*!< ethernet DMA current receive buffer address register */ /* bits definitions */ /* ENET_MAC_CFG */ @@ -196,60 +193,60 @@ OF SUCH DAMAGE. #define ENET_MAC_CFG_ROD BIT(13) /*!< receive own disable */ #define ENET_MAC_CFG_SPD BIT(14) /*!< fast eneternet speed */ #define ENET_MAC_CFG_CSD BIT(16) /*!< carrier sense disable */ -#define ENET_MAC_CFG_IGBS BITS(17,19) /*!< inter-frame gap bit selection */ +#define ENET_MAC_CFG_IGBS BITS(17,19) /*!< inter-frame gap bit selection */ #define ENET_MAC_CFG_JBD BIT(22) /*!< jabber disable */ #define ENET_MAC_CFG_WDD BIT(23) /*!< watchdog disable */ /* ENET_MAC_FRMF */ #define ENET_MAC_FRMF_PM BIT(0) /*!< promiscuous mode */ #define ENET_MAC_FRMF_HUF BIT(1) /*!< hash unicast filter */ -#define ENET_MAC_FRMF_HMF BIT(2) /*!< hash multicast filter */ -#define ENET_MAC_FRMF_DAIFLT BIT(3) /*!< destination address inverse filtering enable */ -#define ENET_MAC_FRMF_MFD BIT(4) /*!< multicast filter disable */ -#define ENET_MAC_FRMF_BFRMD BIT(5) /*!< broadcast frame disable */ -#define ENET_MAC_FRMF_PCFRM BITS(6,7) /*!< pass control frames */ -#define ENET_MAC_FRMF_SAIFLT BIT(8) /*!< source address inverse filtering */ -#define ENET_MAC_FRMF_SAFLT BIT(9) /*!< source address filter */ -#define ENET_MAC_FRMF_HPFLT BIT(10) /*!< hash or perfect filter */ -#define ENET_MAC_FRMF_FAR BIT(31) /*!< frames all receive */ - +#define ENET_MAC_FRMF_HMF BIT(2) /*!< hash multicast filter */ +#define ENET_MAC_FRMF_DAIFLT BIT(3) /*!< destination address inverse filtering enable */ +#define ENET_MAC_FRMF_MFD BIT(4) /*!< multicast filter disable */ +#define ENET_MAC_FRMF_BFRMD BIT(5) /*!< broadcast frame disable */ +#define ENET_MAC_FRMF_PCFRM BITS(6,7) /*!< pass control frames */ +#define ENET_MAC_FRMF_SAIFLT BIT(8) /*!< source address inverse filtering */ +#define ENET_MAC_FRMF_SAFLT BIT(9) /*!< source address filter */ +#define ENET_MAC_FRMF_HPFLT BIT(10) /*!< hash or perfect filter */ +#define ENET_MAC_FRMF_FAR BIT(31) /*!< frames all receive */ + /* ENET_MAC_HLH */ #define ENET_MAC_HLH_HLH BITS(0,31) /*!< hash list high */ - + /* ENET_MAC_HLL */ #define ENET_MAC_HLL_HLL BITS(0,31) /*!< hash list low */ - + /* ENET_MAC_PHY_CTL */ -#define ENET_MAC_PHY_CTL_PB BIT(0) /*!< PHY busy */ -#define ENET_MAC_PHY_CTL_PW BIT(1) /*!< PHY write */ -#define ENET_MAC_PHY_CTL_CLR BITS(2,4) /*!< clock range */ -#define ENET_MAC_PHY_CTL_PR BITS(6,10) /*!< PHY register */ -#define ENET_MAC_PHY_CTL_PA BITS(11,15) /*!< PHY address */ - +#define ENET_MAC_PHY_CTL_PB BIT(0) /*!< PHY busy */ +#define ENET_MAC_PHY_CTL_PW BIT(1) /*!< PHY write */ +#define ENET_MAC_PHY_CTL_CLR BITS(2,4) /*!< clock range */ +#define ENET_MAC_PHY_CTL_PR BITS(6,10) /*!< PHY register */ +#define ENET_MAC_PHY_CTL_PA BITS(11,15) /*!< PHY address */ + /* ENET_MAC_PHY_DATA */ #define ENET_MAC_PHY_DATA_PD BITS(0,15) /*!< PHY data */ - + /* ENET_MAC_FCTL */ #define ENET_MAC_FCTL_FLCBBKPA BIT(0) /*!< flow control busy(in full duplex mode)/backpressure activate(in half duplex mode) */ #define ENET_MAC_FCTL_TFCEN BIT(1) /*!< transmit flow control enable */ #define ENET_MAC_FCTL_RFCEN BIT(2) /*!< receive flow control enable */ #define ENET_MAC_FCTL_UPFDT BIT(3) /*!< unicast pause frame detect */ -#define ENET_MAC_FCTL_PLTS BITS(4,5) /*!< pause low threshold */ +#define ENET_MAC_FCTL_PLTS BITS(4,5) /*!< pause low threshold */ #define ENET_MAC_FCTL_DZQP BIT(7) /*!< disable zero-quanta pause */ #define ENET_MAC_FCTL_PTM BITS(16,31) /*!< pause time */ - + /* ENET_MAC_FCTH */ #define ENET_MAC_FCTH_RFA BITS(0,2) /*!< threshold of active flow control */ #define ENET_MAC_FCTH_RFD BITS(4,6) /*!< threshold of deactive flow control */ - + /* ENET_MAC_VLT */ #define ENET_MAC_VLT_VLTI BITS(0,15) /*!< VLAN tag identifier(for receive frames) */ #define ENET_MAC_VLT_VLTC BIT(16) /*!< 12-bit VLAN tag comparison */ - + /* ENET_MAC_RWFF */ #define ENET_MAC_RWFF_DATA BITS(0,31) /*!< wakeup frame filter register data */ - -/* ENET_MAC_WUM */ + +/* ENET_MAC_WUM */ #define ENET_MAC_WUM_PWD BIT(0) /*!< power down */ #define ENET_MAC_WUM_MPEN BIT(1) /*!< magic packet enable */ #define ENET_MAC_WUM_WFEN BIT(2) /*!< wakeup frame enable */ @@ -258,7 +255,7 @@ OF SUCH DAMAGE. #define ENET_MAC_WUM_GU BIT(9) /*!< global unicast */ #define ENET_MAC_WUM_WUFFRPR BIT(31) /*!< wakeup frame filter register pointer reset */ -/* ENET_MAC_INTF */ +/* ENET_MAC_INTF */ #define ENET_MAC_INTF_WUM BIT(3) /*!< WUM status */ #define ENET_MAC_INTF_MSC BIT(4) /*!< MSC status */ #define ENET_MAC_INTF_MSCR BIT(5) /*!< MSC receive status */ @@ -272,28 +269,28 @@ OF SUCH DAMAGE. /* ENET_MAC_ADDR0H */ #define ENET_MAC_ADDR0H_ADDR0H BITS(0,15) /*!< MAC address0 high */ #define ENET_MAC_ADDR0H_MO BIT(31) /*!< always read 1 and must be kept */ - + /* ENET_MAC_ADDR0L */ #define ENET_MAC_ADDR0L_ADDR0L BITS(0,31) /*!< MAC address0 low */ - + /* ENET_MAC_ADDR1H */ #define ENET_MAC_ADDR1H_ADDR1H BITS(0,15) /*!< MAC address1 high */ -#define ENET_MAC_ADDR1H_MB BITS(24,29) /*!< mask byte */ +#define ENET_MAC_ADDR1H_MB BITS(24,29) /*!< mask byte */ #define ENET_MAC_ADDR1H_SAF BIT(30) /*!< source address filter */ #define ENET_MAC_ADDR1H_AFE BIT(31) /*!< address filter enable */ - + /* ENET_MAC_ADDR1L */ #define ENET_MAC_ADDR1L_ADDR1L BITS(0,31) /*!< MAC address1 low */ - + /* ENET_MAC_ADDR2H */ #define ENET_MAC_ADDR2H_ADDR2H BITS(0,15) /*!< MAC address2 high */ #define ENET_MAC_ADDR2H_MB BITS(24,29) /*!< mask byte */ #define ENET_MAC_ADDR2H_SAF BIT(30) /*!< source address filter */ #define ENET_MAC_ADDR2H_AFE BIT(31) /*!< address filter enable */ - + /* ENET_MAC_ADDR2L */ #define ENET_MAC_ADDR2L_ADDR2L BITS(0,31) /*!< MAC address2 low */ - + /* ENET_MAC_ADDR3H */ #define ENET_MAC_ADDR3H_ADDR3H BITS(0,15) /*!< MAC address3 high */ #define ENET_MAC_ADDR3H_MB BITS(24,29) /*!< mask byte */ @@ -302,7 +299,7 @@ OF SUCH DAMAGE. /* ENET_MAC_ADDR3L */ #define ENET_MAC_ADDR3L_ADDR3L BITS(0,31) /*!< MAC address3 low */ - + /* ENET_MSC_CTL */ #define ENET_MSC_CTL_CTR BIT(0) /*!< counter reset */ #define ENET_MSC_CTL_CTSR BIT(1) /*!< counter stop rollover */ @@ -313,7 +310,7 @@ OF SUCH DAMAGE. #define ENET_MSC_RINTF_RFCE BIT(5) /*!< received frames CRC error */ #define ENET_MSC_RINTF_RFAE BIT(6) /*!< received frames alignment error */ #define ENET_MSC_RINTF_RGUF BIT(17) /*!< receive good unicast frames */ - + /* ENET_MSC_TINTF */ #define ENET_MSC_TINTF_TGFSC BIT(14) /*!< transmitted good frames single collision */ #define ENET_MSC_TINTF_TGFMSC BIT(15) /*!< transmitted good frames more single collision */ @@ -323,30 +320,30 @@ OF SUCH DAMAGE. #define ENET_MSC_RINTMSK_RFCEIM BIT(5) /*!< received frame CRC error interrupt mask */ #define ENET_MSC_RINTMSK_RFAEIM BIT(6) /*!< received frames alignment error interrupt mask */ #define ENET_MSC_RINTMSK_RGUFIM BIT(17) /*!< received good unicast frames interrupt mask */ - + /* ENET_MSC_TINTMSK */ #define ENET_MSC_TINTMSK_TGFSCIM BIT(14) /*!< transmitted good frames single collision interrupt mask */ #define ENET_MSC_TINTMSK_TGFMSCIM BIT(15) /*!< transmitted good frames more single collision interrupt mask */ #define ENET_MSC_TINTMSK_TGFIM BIT(21) /*!< transmitted good frames interrupt mask */ - + /* ENET_MSC_SCCNT */ #define ENET_MSC_SCCNT_SCC BITS(0,31) /*!< transmitted good frames single collision counter */ - + /* ENET_MSC_MSCCNT */ #define ENET_MSC_MSCCNT_MSCC BITS(0,31) /*!< transmitted good frames more one single collision counter */ - + /* ENET_MSC_TGFCNT */ #define ENET_MSC_TGFCNT_TGF BITS(0,31) /*!< transmitted good frames counter */ - + /* ENET_MSC_RFCECNT */ #define ENET_MSC_RFCECNT_RFCER BITS(0,31) /*!< received frames with CRC error counter */ - + /* ENET_MSC_RFAECNT */ #define ENET_MSC_RFAECNT_RFAER BITS(0,31) /*!< received frames alignment error counter */ - + /* ENET_MSC_RGUFCNT */ #define ENET_MSC_RGUFCNT_RGUF BITS(0,31) /*!< received good unicast frames counter */ - + /* ENET_PTP_TSCTL */ #define ENET_PTP_TSCTL_TMSEN BIT(0) /*!< timestamp enable */ #define ENET_PTP_TSCTL_TMSFCU BIT(1) /*!< timestamp fine or coarse update */ @@ -357,30 +354,30 @@ OF SUCH DAMAGE. /* ENET_PTP_SSINC */ #define ENET_PTP_SSINC_STMSSI BITS(0,7) /*!< system time subsecond increment */ - + /* ENET_PTP_TSH */ #define ENET_PTP_TSH_STMS BITS(0,31) /*!< system time second */ - + /* ENET_PTP_TSL */ #define ENET_PTP_TSL_STMSS BITS(0,30) /*!< system time subseconds */ #define ENET_PTP_TSL_STS BIT(31) /*!< system time sign */ - + /* ENET_PTP_TSUH */ #define ENET_PTP_TSUH_TMSUS BITS(0,31) /*!< timestamp update seconds */ - + /* ENET_PTP_TSUL */ #define ENET_PTP_TSUL_TMSUSS BITS(0,30) /*!< timestamp update subseconds */ #define ENET_PTP_TSUL_TMSUPNS BIT(31) /*!< timestamp update positive or negative sign */ /* ENET_PTP_TSADDEND */ #define ENET_PTP_TSADDEND_TMSA BITS(0,31) /*!< timestamp addend */ - + /* ENET_PTP_ETH */ #define ENET_PTP_ETH_ETSH BITS(0,31) /*!< expected time high */ - + /* ENET_PTP_ETL */ #define ENET_PTP_ETL_ETSL BITS(0,31) /*!< expected time low */ - + /* ENET_DMA_BCTL */ #define ENET_DMA_BCTL_SWR BIT(0) /*!< software reset */ #define ENET_DMA_BCTL_DAB BIT(1) /*!< DMA arbitration */ @@ -392,19 +389,19 @@ OF SUCH DAMAGE. #define ENET_DMA_BCTL_UIP BIT(23) /*!< use independent PGBL */ #define ENET_DMA_BCTL_FPBL BIT(24) /*!< four times PGBL mode */ #define ENET_DMA_BCTL_AA BIT(25) /*!< address-aligned */ - + /* ENET_DMA_TPEN */ #define ENET_DMA_TPEN_TPE BITS(0,31) /*!< transmit poll enable */ - + /* ENET_DMA_RPEN */ #define ENET_DMA_RPEN_RPE BITS(0,31) /*!< receive poll enable */ /* ENET_DMA_RDTADDR */ #define ENET_DMA_RDTADDR_SRT BITS(0,31) /*!< start address of receive table */ - + /* ENET_DMA_TDTADDR */ #define ENET_DMA_TDTADDR_STT BITS(0,31) /*!< start address of transmit table */ - + /* ENET_DMA_STAT */ #define ENET_DMA_STAT_TS BIT(0) /*!< transmit status */ #define ENET_DMA_STAT_TPS BIT(1) /*!< transmit process stopped status */ @@ -427,7 +424,7 @@ OF SUCH DAMAGE. #define ENET_DMA_STAT_MSC BIT(27) /*!< MSC status */ #define ENET_DMA_STAT_WUM BIT(28) /*!< WUM status */ #define ENET_DMA_STAT_TST BIT(29) /*!< timestamp trigger status */ - + /* ENET_DMA_CTL */ #define ENET_DMA_CTL_SRE BIT(1) /*!< start/stop receive enable */ #define ENET_DMA_CTL_OSF BIT(2) /*!< operate on second frame */ @@ -441,7 +438,7 @@ OF SUCH DAMAGE. #define ENET_DMA_CTL_DAFRF BIT(24) /*!< disable flushing of received frames */ #define ENET_DMA_CTL_RSFD BIT(25) /*!< receive store-and-forward */ #define ENET_DMA_CTL_DTCERFD BIT(26) /*!< dropping of TCP/IP checksum error frames disable */ - + /* ENET_DMA_INTEN */ #define ENET_DMA_INTEN_TIE BIT(0) /*!< transmit interrupt enable */ #define ENET_DMA_INTEN_TPSIE BIT(1) /*!< transmit process stopped interrupt enable */ @@ -458,7 +455,7 @@ OF SUCH DAMAGE. #define ENET_DMA_INTEN_ERIE BIT(14) /*!< early receive interrupt enable */ #define ENET_DMA_INTEN_AIE BIT(15) /*!< abnormal interrupt summary enable */ #define ENET_DMA_INTEN_NIE BIT(16) /*!< normal interrupt summary enable */ - + /* ENET_DMA_MFBOCNT */ #define ENET_DMA_MFBOCNT_MSFC BITS(0,15) /*!< missed frames by the controller */ #define ENET_DMA_MFBOCNT_OBMFC BIT(16) /*!< overflow bit for missed frame counter */ @@ -470,10 +467,10 @@ OF SUCH DAMAGE. /* ENET_DMA_CRDADDR */ #define ENET_DMA_CRDADDR_RDAP BITS(0,31) /*!< receive descriptor address pointer */ - + /* ENET_DMA_CTBADDR */ #define ENET_DMA_CTBADDR_TBAP BITS(0,31) /*!< transmit buffer address pointer */ - + /* ENET_DMA_CRBADDR */ #define ENET_DMA_CRBADDR_RBAP BITS(0,31) /*!< receive buffer address pointer */ @@ -523,7 +520,7 @@ OF SUCH DAMAGE. #define ENET_RDES0_FRMT BIT(5) /*!< frame type */ #define ENET_RDES0_LCO BIT(6) /*!< late collision */ #define ENET_RDES0_IPHERR BIT(7) /*!< IP frame header error */ -#define ENET_RDES0_LDES BIT(8) /*!< last descriptor */ +#define ENET_RDES0_LDES BIT(8) /*!< last descriptor */ #define ENET_RDES0_FDES BIT(9) /*!< first descriptor */ #define ENET_RDES0_VTAG BIT(10) /*!< VLAN tag */ #define ENET_RDES0_OERR BIT(11) /*!< overflow Error */ @@ -535,7 +532,7 @@ OF SUCH DAMAGE. #define ENET_RDES0_DAFF BIT(30) /*!< destination address filter fail */ #define ENET_RDES0_DAV BIT(31) /*!< descriptor available */ -/* ENET DMA Rx descriptor RDES1 */ +/* ENET DMA Rx descriptor RDES1 */ #define ENET_RDES1_RB1S BITS(0,12) /*!< receive buffer 1 size */ #define ENET_RDES1_RCHM BIT(14) /*!< receive chained mode for second address */ #define ENET_RDES1_RERM BIT(15) /*!< receive end of ring mode*/ @@ -550,52 +547,51 @@ OF SUCH DAMAGE. /* constants definitions */ /* define bit position and its register index offset */ -#define ENET_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) -#define ENET_REG_VAL(periph) (REG32(ENET + ((uint32_t)(periph)>>6))) -#define ENET_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define ENET_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6U) | (uint32_t)(bitpos)) +#define ENET_REG_VAL(periph) (REG32(ENET + ((uint32_t)(periph) >> 6U))) +#define ENET_BIT_POS(val) ((uint32_t)(val) & 0x0000001FU) /* ENET clock range judgement */ #define ENET_RANGE(hclk, n, m) (((hclk) >= (n))&&((hclk) < (m))) /* define MAC address configuration and reference address */ -#define ENET_SET_MACADDRH(p) (((uint32_t)(p)[5] << 8) | (uint32_t)(p)[4]) -#define ENET_SET_MACADDRL(p) (((uint32_t)(p)[3] << 24) | ((uint32_t)(p)[2] << 16) | ((uint32_t)(p)[1] << 8) | (uint32_t)(p)[0]) -#define ENET_ADDRH_BASE ((ENET) + 0x40U) -#define ENET_ADDRL_BASE ((ENET) + 0x44U) +#define ENET_SET_MACADDRH(p) (((uint32_t)(p)[5] << 8U) | (uint32_t)(p)[4]) +#define ENET_SET_MACADDRL(p) (((uint32_t)(p)[3] << 24U) | ((uint32_t)(p)[2] << 16U) | ((uint32_t)(p)[1] << 8U) | (uint32_t)(p)[0]) +#define ENET_ADDRH_BASE ((ENET) + 0x00000040U) +#define ENET_ADDRL_BASE ((ENET) + 0x00000044U) #define ENET_GET_MACADDR(offset, n) ((uint8_t)((REG32((ENET_ADDRL_BASE + (offset)) - (((n) / 4U) * 4U)) >> (8U * ((n) % 4U))) & 0xFFU)) /* register offset */ -#define MAC_FCTL_REG_OFFSET 0x0018U /*!< MAC flow control register offset */ -#define MAC_WUM_REG_OFFSET 0x002CU /*!< MAC wakeup management register offset */ -#define MAC_INTF_REG_OFFSET 0x0038U /*!< MAC interrupt flag register offset */ -#define MAC_INTMSK_REG_OFFSET 0x003CU /*!< MAC interrupt mask register offset */ - -#define MSC_RINTF_REG_OFFSET 0x0104U /*!< MSC receive interrupt flag register offset */ -#define MSC_TINTF_REG_OFFSET 0x0108U /*!< MSC transmit interrupt flag register offset */ -#define MSC_RINTMSK_REG_OFFSET 0x010CU /*!< MSC receive interrupt mask register offset */ -#define MSC_TINTMSK_REG_OFFSET 0x0110U /*!< MSC transmit interrupt mask register offset */ -#define MSC_SCCNT_REG_OFFSET 0x014CU /*!< MSC transmitted good frames after a single collision counter register offset */ -#define MSC_MSCCNT_REG_OFFSET 0x0150U /*!< MSC transmitted good frames after more than a single collision counter register offset */ -#define MSC_TGFCNT_REG_OFFSET 0x0168U /*!< MSC transmitted good frames counter register offset */ -#define MSC_RFCECNT_REG_OFFSET 0x0194U /*!< MSC received frames with CRC error counter register offset */ -#define MSC_RFAECNT_REG_OFFSET 0x0198U /*!< MSC received frames with alignment error counter register offset */ -#define MSC_RGUFCNT_REG_OFFSET 0x01C4U /*!< MSC received good unicast frames counter register offset */ - -#define DMA_STAT_REG_OFFSET 0x1014U /*!< DMA status register offset */ -#define DMA_INTEN_REG_OFFSET 0x101CU /*!< DMA interrupt enable register offset */ -#define DMA_TDTADDR_REG_OFFSET 0x1010U /*!< DMA transmit descriptor table address register offset */ -#define DMA_CTDADDR_REG_OFFSET 0x1048U /*!< DMA current transmit descriptor address register */ -#define DMA_CTBADDR_REG_OFFSET 0x1050U /*!< DMA current transmit buffer address register */ -#define DMA_RDTADDR_REG_OFFSET 0x100CU /*!< DMA receive descriptor table address register */ -#define DMA_CRDADDR_REG_OFFSET 0x104CU /*!< DMA current receive descriptor address register */ -#define DMA_CRBADDR_REG_OFFSET 0x1054U /*!< DMA current receive buffer address register */ +#define MAC_FCTL_REG_OFFSET 0x00000018U /*!< MAC flow control register offset */ +#define MAC_WUM_REG_OFFSET 0x0000002CU /*!< MAC wakeup management register offset */ +#define MAC_INTF_REG_OFFSET 0x00000038U /*!< MAC interrupt flag register offset */ +#define MAC_INTMSK_REG_OFFSET 0x0000003CU /*!< MAC interrupt mask register offset */ + +#define MSC_RINTF_REG_OFFSET 0x00000104U /*!< MSC receive interrupt flag register offset */ +#define MSC_TINTF_REG_OFFSET 0x00000108U /*!< MSC transmit interrupt flag register offset */ +#define MSC_RINTMSK_REG_OFFSET 0x0000010CU /*!< MSC receive interrupt mask register offset */ +#define MSC_TINTMSK_REG_OFFSET 0x00000110U /*!< MSC transmit interrupt mask register offset */ +#define MSC_SCCNT_REG_OFFSET 0x0000014CU /*!< MSC transmitted good frames after a single collision counter register offset */ +#define MSC_MSCCNT_REG_OFFSET 0x00000150U /*!< MSC transmitted good frames after more than a single collision counter register offset */ +#define MSC_TGFCNT_REG_OFFSET 0x00000168U /*!< MSC transmitted good frames counter register offset */ +#define MSC_RFCECNT_REG_OFFSET 0x00000194U /*!< MSC received frames with CRC error counter register offset */ +#define MSC_RFAECNT_REG_OFFSET 0x00000198U /*!< MSC received frames with alignment error counter register offset */ +#define MSC_RGUFCNT_REG_OFFSET 0x000001C4U /*!< MSC received good unicast frames counter register offset */ + +#define DMA_STAT_REG_OFFSET 0x00001014U /*!< DMA status register offset */ +#define DMA_INTEN_REG_OFFSET 0x0000101CU /*!< DMA interrupt enable register offset */ +#define DMA_TDTADDR_REG_OFFSET 0x00001010U /*!< DMA transmit descriptor table address register offset */ +#define DMA_CTDADDR_REG_OFFSET 0x00001048U /*!< DMA current transmit descriptor address register */ +#define DMA_CTBADDR_REG_OFFSET 0x00001050U /*!< DMA current transmit buffer address register */ +#define DMA_RDTADDR_REG_OFFSET 0x0000100CU /*!< DMA receive descriptor table address register */ +#define DMA_CRDADDR_REG_OFFSET 0x0000104CU /*!< DMA current receive descriptor address register */ +#define DMA_CRBADDR_REG_OFFSET 0x00001054U /*!< DMA current receive buffer address register */ /* ENET status flag get */ -typedef enum -{ +typedef enum { /* ENET_MAC_WUM register */ ENET_MAC_FLAG_MPKR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 5U), /*!< magic packet received flag */ - ENET_MAC_FLAG_WUFR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 6U), /*!< wakeup frame received flag */ + ENET_MAC_FLAG_WUFR = ENET_REGIDX_BIT(MAC_WUM_REG_OFFSET, 6U), /*!< wakeup frame received flag */ /* ENET_MAC_FCTL register */ ENET_MAC_FLAG_FLOWCONTROL = ENET_REGIDX_BIT(MAC_FCTL_REG_OFFSET, 0U), /*!< flow control status flag */ /* ENET_MAC_INTF register */ @@ -608,7 +604,7 @@ typedef enum ENET_MSC_FLAG_RFCE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 5U), /*!< received frames CRC error flag */ ENET_MSC_FLAG_RFAE = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 6U), /*!< received frames alignment error flag */ ENET_MSC_FLAG_RGUF = ENET_REGIDX_BIT(MSC_RINTF_REG_OFFSET, 17U), /*!< received good unicast frames flag */ - /* ENET_MSC_TINTF register */ + /* ENET_MSC_TINTF register */ ENET_MSC_FLAG_TGFSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 14U), /*!< transmitted good frames single collision flag */ ENET_MSC_FLAG_TGFMSC = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 15U), /*!< transmitted good frames more single collision flag */ ENET_MSC_FLAG_TGF = ENET_REGIDX_BIT(MSC_TINTF_REG_OFFSET, 21U), /*!< transmitted good frames flag */ @@ -633,12 +629,11 @@ typedef enum ENET_DMA_FLAG_EB_ACCESS_ERROR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 25U), /*!< error during data buffer/descriptor access flag */ ENET_DMA_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ ENET_DMA_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ - ENET_DMA_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ -}enet_flag_enum; + ENET_DMA_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U) /*!< timestamp trigger status flag */ +} enet_flag_enum; /* ENET status flag clear */ -typedef enum -{ +typedef enum { /* ENET_DMA_STAT register */ ENET_DMA_FLAG_TS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ ENET_DMA_FLAG_TPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ @@ -654,24 +649,23 @@ typedef enum ENET_DMA_FLAG_FBE_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ ENET_DMA_FLAG_ER_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ ENET_DMA_FLAG_AI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ - ENET_DMA_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ -}enet_flag_clear_enum; + ENET_DMA_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U) /*!< normal interrupt summary flag */ +} enet_flag_clear_enum; /* ENET interrupt enable/disable */ -typedef enum -{ +typedef enum { /* ENET_MAC_INTMSK register */ ENET_MAC_INT_WUMIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 3U), /*!< WUM interrupt mask */ ENET_MAC_INT_TMSTIM = ENET_REGIDX_BIT(MAC_INTMSK_REG_OFFSET, 9U), /*!< timestamp trigger interrupt mask */ - /* ENET_MSC_RINTMSK register */ + /* ENET_MSC_RINTMSK register */ ENET_MSC_INT_RFCEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 5U), /*!< received frame CRC error interrupt mask */ ENET_MSC_INT_RFAEIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 6U), /*!< received frames alignment error interrupt mask */ ENET_MSC_INT_RGUFIM = ENET_REGIDX_BIT(MSC_RINTMSK_REG_OFFSET, 17U), /*!< received good unicast frames interrupt mask */ - /* ENET_MSC_TINTMSK register */ + /* ENET_MSC_TINTMSK register */ ENET_MSC_INT_TGFSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 14U), /*!< transmitted good frames single collision interrupt mask */ ENET_MSC_INT_TGFMSCIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 15U), /*!< transmitted good frames more single collision interrupt mask */ ENET_MSC_INT_TGFIM = ENET_REGIDX_BIT(MSC_TINTMSK_REG_OFFSET, 21U), /*!< transmitted good frames interrupt mask */ - /* ENET_DMA_INTEN register */ + /* ENET_DMA_INTEN register */ ENET_DMA_INT_TIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 0U), /*!< transmit interrupt enable */ ENET_DMA_INT_TPSIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 1U), /*!< transmit process stopped interrupt enable */ ENET_DMA_INT_TBUIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 2U), /*!< transmit buffer unavailable interrupt enable */ @@ -686,12 +680,11 @@ typedef enum ENET_DMA_INT_FBEIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 13U), /*!< fatal bus error interrupt enable */ ENET_DMA_INT_ERIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 14U), /*!< early receive interrupt enable */ ENET_DMA_INT_AIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 15U), /*!< abnormal interrupt summary enable */ - ENET_DMA_INT_NIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 16U), /*!< normal interrupt summary enable */ -}enet_int_enum; - + ENET_DMA_INT_NIE = ENET_REGIDX_BIT(DMA_INTEN_REG_OFFSET, 16U) /*!< normal interrupt summary enable */ +} enet_int_enum; + /* ENET interrupt flag get */ -typedef enum -{ +typedef enum { /* ENET_MAC_INTF register */ ENET_MAC_INT_FLAG_WUM = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 3U), /*!< WUM status flag */ ENET_MAC_INT_FLAG_MSC = ENET_REGIDX_BIT(MAC_INTF_REG_OFFSET, 4U), /*!< MSC status flag */ @@ -724,12 +717,11 @@ typedef enum ENET_DMA_INT_FLAG_NI = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ ENET_DMA_INT_FLAG_MSC = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 27U), /*!< MSC status flag */ ENET_DMA_INT_FLAG_WUM = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 28U), /*!< WUM status flag */ - ENET_DMA_INT_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U), /*!< timestamp trigger status flag */ -}enet_int_flag_enum; + ENET_DMA_INT_FLAG_TST = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 29U) /*!< timestamp trigger status flag */ +} enet_int_flag_enum; /* ENET interrupt flag clear */ -typedef enum -{ +typedef enum { /* ENET_DMA_STAT register */ ENET_DMA_INT_FLAG_TS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 0U), /*!< transmit status flag */ ENET_DMA_INT_FLAG_TPS_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 1U), /*!< transmit process stopped status flag */ @@ -745,34 +737,31 @@ typedef enum ENET_DMA_INT_FLAG_FBE_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 13U), /*!< fatal bus error status flag */ ENET_DMA_INT_FLAG_ER_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 14U), /*!< early receive status flag */ ENET_DMA_INT_FLAG_AI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 15U), /*!< abnormal interrupt summary flag */ - ENET_DMA_INT_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U), /*!< normal interrupt summary flag */ -}enet_int_flag_clear_enum; + ENET_DMA_INT_FLAG_NI_CLR = ENET_REGIDX_BIT(DMA_STAT_REG_OFFSET, 16U) /*!< normal interrupt summary flag */ +} enet_int_flag_clear_enum; /* current RX/TX descriptor/buffer/descriptor table address get */ -typedef enum -{ +typedef enum { ENET_RX_DESC_TABLE = DMA_RDTADDR_REG_OFFSET, /*!< RX descriptor table */ ENET_RX_CURRENT_DESC = DMA_CRDADDR_REG_OFFSET, /*!< current RX descriptor */ ENET_RX_CURRENT_BUFFER = DMA_CRBADDR_REG_OFFSET, /*!< current RX buffer */ ENET_TX_DESC_TABLE = DMA_TDTADDR_REG_OFFSET, /*!< TX descriptor table */ ENET_TX_CURRENT_DESC = DMA_CTDADDR_REG_OFFSET, /*!< current TX descriptor */ ENET_TX_CURRENT_BUFFER = DMA_CTBADDR_REG_OFFSET /*!< current TX buffer */ -}enet_desc_reg_enum; +} enet_desc_reg_enum; /* MAC statistics counter get */ -typedef enum -{ +typedef enum { ENET_MSC_TX_SCCNT = MSC_SCCNT_REG_OFFSET, /*!< MSC transmitted good frames after a single collision counter */ ENET_MSC_TX_MSCCNT = MSC_MSCCNT_REG_OFFSET, /*!< MSC transmitted good frames after more than a single collision counter */ ENET_MSC_TX_TGFCNT = MSC_TGFCNT_REG_OFFSET, /*!< MSC transmitted good frames counter */ ENET_MSC_RX_RFCECNT = MSC_RFCECNT_REG_OFFSET, /*!< MSC received frames with CRC error counter */ ENET_MSC_RX_RFAECNT = MSC_RFAECNT_REG_OFFSET, /*!< MSC received frames with alignment error counter */ ENET_MSC_RX_RGUFCNT = MSC_RGUFCNT_REG_OFFSET /*!< MSC received good unicast frames counter */ -}enet_msc_counter_enum; +} enet_msc_counter_enum; /* function option, used for ENET initialization */ -typedef enum -{ +typedef enum { FORWARD_OPTION = BIT(0), /*!< configure the frame forward related parameters */ DMABUS_OPTION = BIT(1), /*!< configure the DMA bus mode related parameters */ DMA_MAXBURST_OPTION = BIT(2), /*!< configure the DMA max burst related parameters */ @@ -786,152 +775,140 @@ typedef enum FILTER_OPTION = BIT(10), /*!< configure the frame filter control related parameters */ HALFDUPLEX_OPTION = BIT(11), /*!< configure the halfduplex related parameters */ TIMER_OPTION = BIT(12), /*!< configure the frame timer related parameters */ - INTERFRAMEGAP_OPTION = BIT(13), /*!< configure the inter frame gap related parameters */ -}enet_option_enum; + INTERFRAMEGAP_OPTION = BIT(13) /*!< configure the inter frame gap related parameters */ +} enet_option_enum; /* phy mode and mac loopback configurations */ -typedef enum -{ +typedef enum { ENET_AUTO_NEGOTIATION = 0x01U, /*!< PHY auto negotiation */ ENET_100M_FULLDUPLEX = (ENET_MAC_CFG_SPD | ENET_MAC_CFG_DPM), /*!< 100Mbit/s, full-duplex */ - ENET_100M_HALFDUPLEX = ENET_MAC_CFG_SPD , /*!< 100Mbit/s, half-duplex */ + ENET_100M_HALFDUPLEX = ENET_MAC_CFG_SPD, /*!< 100Mbit/s, half-duplex */ ENET_10M_FULLDUPLEX = ENET_MAC_CFG_DPM, /*!< 10Mbit/s, full-duplex */ ENET_10M_HALFDUPLEX = (uint32_t)0x00000000U, /*!< 10Mbit/s, half-duplex */ ENET_LOOPBACKMODE = (ENET_MAC_CFG_LBM | ENET_MAC_CFG_DPM) /*!< MAC in loopback mode at the MII */ -}enet_mediamode_enum; +} enet_mediamode_enum; /* IP frame checksum function */ -typedef enum -{ +typedef enum { ENET_NO_AUTOCHECKSUM = (uint32_t)0x00000000U, /*!< disable IP frame checksum function */ ENET_AUTOCHECKSUM_DROP_FAILFRAMES = ENET_MAC_CFG_IPFCO, /*!< enable IP frame checksum function */ - ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES = (ENET_MAC_CFG_IPFCO|ENET_DMA_CTL_DTCERFD) /*!< enable IP frame checksum function, and the received frame + ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES = (ENET_MAC_CFG_IPFCO | ENET_DMA_CTL_DTCERFD) /*!< enable IP frame checksum function, and the received frame with only payload error but no other errors will not be dropped */ -}enet_chksumconf_enum; +} enet_chksumconf_enum; /* received frame filter function */ -typedef enum -{ +typedef enum { ENET_PROMISCUOUS_MODE = ENET_MAC_FRMF_PM, /*!< promiscuous mode enabled */ ENET_RECEIVEALL = (int32_t)ENET_MAC_FRMF_FAR, /*!< all received frame are forwarded to application */ - ENET_CUSTOM = BIT(4), + ENET_CUSTOM = BIT(4), /** AvV **/ ENET_BROADCAST_FRAMES_PASS = (uint32_t)0x00000000U, /*!< the address filters pass all received broadcast frames */ ENET_BROADCAST_FRAMES_DROP = ENET_MAC_FRMF_BFRMD /*!< the address filters filter all incoming broadcast frames */ -}enet_frmrecept_enum; +} enet_frmrecept_enum; /* register group value get */ -typedef enum -{ - ALL_MAC_REG = 0, /*!< MAC register group */ - ALL_MSC_REG = 22, /*!< MSC register group */ - ALL_PTP_REG = 33, /*!< PTP register group */ - ALL_DMA_REG = 44, /*!< DMA register group */ -}enet_registers_type_enum; +typedef enum { + ALL_MAC_REG = 0U, /*!< MAC register group */ + ALL_MSC_REG = 22U, /*!< MSC register group */ + ALL_PTP_REG = 33U, /*!< PTP register group */ + ALL_DMA_REG = 44U /*!< DMA register group */ +} enet_registers_type_enum; /* dma direction select */ -typedef enum -{ +typedef enum { ENET_DMA_TX = ENET_DMA_STAT_TP, /*!< DMA transmit direction */ ENET_DMA_RX = ENET_DMA_STAT_RP /*!< DMA receive direction */ -}enet_dmadirection_enum; +} enet_dmadirection_enum; /* PHY operation direction select */ -typedef enum -{ - ENET_PHY_READ = (uint32_t)0x00000000, /*!< read PHY */ +typedef enum { + ENET_PHY_READ = (uint32_t)0x00000000U, /*!< read PHY */ ENET_PHY_WRITE = ENET_MAC_PHY_CTL_PW /*!< write PHY */ -}enet_phydirection_enum; +} enet_phydirection_enum; /* register operation direction select */ -typedef enum -{ +typedef enum { ENET_REG_READ, /*!< read register */ ENET_REG_WRITE /*!< write register */ -}enet_regdirection_enum; +} enet_regdirection_enum; -/* ENET MAC addresses */ -typedef enum -{ - ENET_MAC_ADDRESS0 = ((uint32_t)0x00000000), /*!< MAC address0 */ - ENET_MAC_ADDRESS1 = ((uint32_t)0x00000008), /*!< MAC address1 */ - ENET_MAC_ADDRESS2 = ((uint32_t)0x00000010), /*!< MAC address2 */ - ENET_MAC_ADDRESS3 = ((uint32_t)0x00000018) /*!< MAC address3 */ -}enet_macaddress_enum; +/* ENET MAC addresses */ +typedef enum { + ENET_MAC_ADDRESS0 = ((uint32_t)0x00000000U), /*!< MAC address0 */ + ENET_MAC_ADDRESS1 = ((uint32_t)0x00000008U), /*!< MAC address1 */ + ENET_MAC_ADDRESS2 = ((uint32_t)0x00000010U), /*!< MAC address2 */ + ENET_MAC_ADDRESS3 = ((uint32_t)0x00000018U) /*!< MAC address3 */ +} enet_macaddress_enum; /* descriptor information */ -typedef enum -{ +typedef enum { TXDESC_COLLISION_COUNT, /*!< the number of collisions occurred before the frame was transmitted */ TXDESC_BUFFER_1_ADDR, /*!< transmit frame buffer 1 address */ RXDESC_FRAME_LENGTH, /*!< the byte length of the received frame that was transferred to the buffer */ RXDESC_BUFFER_1_SIZE, /*!< receive buffer 1 size */ RXDESC_BUFFER_2_SIZE, /*!< receive buffer 2 size */ RXDESC_BUFFER_1_ADDR /*!< receive frame buffer 1 address */ -}enet_descstate_enum; +} enet_descstate_enum; /* structure for initialization of the ENET */ -typedef struct -{ +typedef struct { uint32_t option_enable; /*!< select which function to configure */ - uint32_t forward_frame; /*!< frame forward related parameters */ + uint32_t forward_frame; /*!< frame forward related parameters */ uint32_t dmabus_mode; /*!< DMA bus mode related parameters */ uint32_t dma_maxburst; /*!< DMA max burst related parameters */ uint32_t dma_arbitration; /*!< DMA Tx and Rx arbitration related parameters */ uint32_t store_forward_mode; /*!< store forward mode related parameters */ uint32_t dma_function; /*!< DMA control related parameters */ - uint32_t vlan_config; /*!< VLAN tag related parameters */ + uint32_t vlan_config; /*!< VLAN tag related parameters */ uint32_t flow_control; /*!< flow control related parameters */ uint32_t hashtable_high; /*!< hash list high 32-bit related parameters */ uint32_t hashtable_low; /*!< hash list low 32-bit related parameters */ uint32_t framesfilter_mode; /*!< frame filter control related parameters */ - uint32_t halfduplex_param; /*!< halfduplex related parameters */ + uint32_t halfduplex_param; /*!< halfduplex related parameters */ uint32_t timer_config; /*!< frame timer related parameters */ uint32_t interframegap; /*!< inter frame gap related parameters */ -}enet_initpara_struct; +} enet_initpara_struct; -/* structure for ENET DMA descriptors */ -typedef struct -{ +/* structure for ENET DMA descriptors */ +typedef struct { uint32_t status; /*!< status */ uint32_t control_buffer_size; /*!< control and buffer1, buffer2 lengths */ uint32_t buffer1_addr; /*!< buffer1 address pointer/timestamp low */ uint32_t buffer2_next_desc_addr; /*!< buffer2 or next descriptor address pointer/timestamp high */ } enet_descriptors_struct; -/* structure of PTP system time */ -typedef struct -{ +/* structure of PTP system time */ +typedef struct { uint32_t second; /*!< second of system time */ uint32_t nanosecond; /*!< nanosecond of system time */ uint32_t sign; /*!< sign of system time */ -}enet_ptp_systime_struct; +} enet_ptp_systime_struct; /* mac_cfg register value */ -#define MAC_CFG_BOL(regval) (BITS(5,6) & ((uint32_t)(regval) << 5)) /*!< write value to ENET_MAC_CFG_BOL bit field */ +#define MAC_CFG_BOL(regval) (BITS(5,6) & ((uint32_t)(regval) << 5U)) /*!< write value to ENET_MAC_CFG_BOL bit field */ #define ENET_BACKOFFLIMIT_10 MAC_CFG_BOL(0) /*!< min (n, 10) */ #define ENET_BACKOFFLIMIT_8 MAC_CFG_BOL(1) /*!< min (n, 8) */ #define ENET_BACKOFFLIMIT_4 MAC_CFG_BOL(2) /*!< min (n, 4) */ -#define ENET_BACKOFFLIMIT_1 MAC_CFG_BOL(3) /*!< min (n, 1) */ +#define ENET_BACKOFFLIMIT_1 MAC_CFG_BOL(3) /*!< min (n, 1) */ -#define MAC_CFG_IGBS(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) /*!< write value to ENET_MAC_CFG_IGBS bit field */ -#define ENET_INTERFRAMEGAP_96BIT MAC_CFG_IGBS(0) /*!< minimum 96 bit times */ +#define MAC_CFG_IGBS(regval) (BITS(17,19) & ((uint32_t)(regval) << 17U)) /*!< write value to ENET_MAC_CFG_IGBS bit field */ +#define ENET_INTERFRAMEGAP_96BIT MAC_CFG_IGBS(0) /*!< minimum 96 bit times */ #define ENET_INTERFRAMEGAP_88BIT MAC_CFG_IGBS(1) /*!< minimum 88 bit times */ #define ENET_INTERFRAMEGAP_80BIT MAC_CFG_IGBS(2) /*!< minimum 80 bit times */ #define ENET_INTERFRAMEGAP_72BIT MAC_CFG_IGBS(3) /*!< minimum 72 bit times */ -#define ENET_INTERFRAMEGAP_64BIT MAC_CFG_IGBS(4) /*!< minimum 64 bit times */ +#define ENET_INTERFRAMEGAP_64BIT MAC_CFG_IGBS(4) /*!< minimum 64 bit times */ #define ENET_INTERFRAMEGAP_56BIT MAC_CFG_IGBS(5) /*!< minimum 56 bit times */ #define ENET_INTERFRAMEGAP_48BIT MAC_CFG_IGBS(6) /*!< minimum 48 bit times */ -#define ENET_INTERFRAMEGAP_40BIT MAC_CFG_IGBS(7) /*!< minimum 40 bit times */ +#define ENET_INTERFRAMEGAP_40BIT MAC_CFG_IGBS(7) /*!< minimum 40 bit times */ #define ENET_WATCHDOG_ENABLE ((uint32_t)0x00000000U) /*!< the MAC allows no more than 2048 bytes of the frame being received */ #define ENET_WATCHDOG_DISABLE ENET_MAC_CFG_WDD /*!< the MAC disables the watchdog timer on the receiver, and can receive frames of up to 16384 bytes */ - + #define ENET_JABBER_ENABLE ((uint32_t)0x00000000U) /*!< the maximum transmission byte is 2048 */ #define ENET_JABBER_DISABLE ENET_MAC_CFG_JBD /*!< the maximum transmission byte can be 16384 */ #define ENET_CARRIERSENSE_ENABLE ((uint32_t)0x00000000U) /*!< the MAC transmitter generates carrier sense error and aborts the transmission */ #define ENET_CARRIERSENSE_DISABLE ENET_MAC_CFG_CSD /*!< the MAC transmitter ignores the MII CRS signal during frame transmission in half-duplex mode */ - + #define ENET_SPEEDMODE_10M ((uint32_t)0x00000000U) /*!< 10 Mbit/s */ #define ENET_SPEEDMODE_100M ENET_MAC_CFG_SPD /*!< 100 Mbit/s */ @@ -958,15 +935,15 @@ typedef struct #define ENET_DEFERRALCHECK_DISABLE ((uint32_t)0x00000000U) /*!< the deferral check function is disabled */ /* mac_frmf register value */ -#define MAC_FRMF_PCFRM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6)) /*!< write value to ENET_MAC_FRMF_PCFRM bit field */ +#define MAC_FRMF_PCFRM(regval) (BITS(6,7) & ((uint32_t)(regval) << 6U)) /*!< write value to ENET_MAC_FRMF_PCFRM bit field */ #define ENET_PCFRM_PREVENT_ALL MAC_FRMF_PCFRM(0) /*!< MAC prevents all control frames from reaching the application */ #define ENET_PCFRM_PREVENT_PAUSEFRAME MAC_FRMF_PCFRM(1) /*!< MAC only forwards all other control frames except pause control frame */ #define ENET_PCFRM_FORWARD_ALL MAC_FRMF_PCFRM(2) /*!< MAC forwards all control frames to application even if they fail the address filter */ #define ENET_PCFRM_FORWARD_FILTERED MAC_FRMF_PCFRM(3) /*!< MAC forwards control frames that only pass the address filter */ - + #define ENET_RX_FILTER_DISABLE ENET_MAC_FRMF_FAR /*!< all received frame are forwarded to application */ #define ENET_RX_FILTER_ENABLE ((uint32_t)0x00000000U) /*!< only the frame passed the filter can be forwarded to application */ - + #define ENET_SRC_FILTER_NORMAL_ENABLE ENET_MAC_FRMF_SAFLT /*!< filter source address */ #define ENET_SRC_FILTER_INVERSE_ENABLE (ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT) /*!< inverse source address filtering result */ #define ENET_SRC_FILTER_DISABLE ((uint32_t)0x00000000U) /*!< source address function in filter disable */ @@ -975,14 +952,14 @@ typedef struct #define ENET_BROADCASTFRAMES_ENABLE ((uint32_t)0x00000000U) /*!< the address filters pass all received broadcast frames */ #define ENET_BROADCASTFRAMES_DISABLE ENET_MAC_FRMF_BFRMD /*!< the address filters filter all incoming broadcast frames */ - + #define ENET_DEST_FILTER_INVERSE_ENABLE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result */ #define ENET_DEST_FILTER_INVERSE_DISABLE ((uint32_t)0x00000000U) /*!< not inverse DA filtering result */ #define ENET_DEST_FILTER_INVERSE ENET_MAC_FRMF_DAIFLT /*!< inverse DA filtering result function */ #define ENET_PROMISCUOUS_ENABLE ENET_MAC_FRMF_PM /*!< promiscuous mode enabled */ #define ENET_PROMISCUOUS_DISABLE ((uint32_t)0x00000000U) /*!< promiscuous mode disabled */ - + #define ENET_MULTICAST_FILTER_HASH_OR_PERFECT (ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT) /*!< pass multicast frames that match either the perfect or the hash filtering */ #define ENET_MULTICAST_FILTER_HASH ENET_MAC_FRMF_HMF /*!< pass multicast frames that match the hash filtering */ #define ENET_MULTICAST_FILTER_PERFECT ((uint32_t)0x00000000U) /*!< pass multicast frames that match the perfect filtering */ @@ -997,25 +974,25 @@ typedef struct #define ENET_UNICAST_FILTER_HASH_MODE ENET_MAC_FRMF_HUF /*!< HASH unicast filter function */ /* mac_phy_ctl register value */ -#define MAC_PHY_CTL_CLR(regval) (BITS(2,4) & ((uint32_t)(regval) << 2)) /*!< write value to ENET_MAC_PHY_CTL_CLR bit field */ +#define MAC_PHY_CTL_CLR(regval) (BITS(2,4) & ((uint32_t)(regval) << 2U)) /*!< write value to ENET_MAC_PHY_CTL_CLR bit field */ #define ENET_MDC_HCLK_DIV42 MAC_PHY_CTL_CLR(0) /*!< HCLK:60-100 MHz; MDC clock= HCLK/42 */ #define ENET_MDC_HCLK_DIV62 MAC_PHY_CTL_CLR(1) /*!< HCLK:100-120 MHz; MDC clock= HCLK/62 */ #define ENET_MDC_HCLK_DIV16 MAC_PHY_CTL_CLR(2) /*!< HCLK:20-35 MHz; MDC clock= HCLK/16 */ #define ENET_MDC_HCLK_DIV26 MAC_PHY_CTL_CLR(3) /*!< HCLK:35-60 MHz; MDC clock= HCLK/26 */ -#define MAC_PHY_CTL_PR(regval) (BITS(6,10) & ((uint32_t)(regval) << 6)) /*!< write value to ENET_MAC_PHY_CTL_PR bit field */ +#define MAC_PHY_CTL_PR(regval) (BITS(6,10) & ((uint32_t)(regval) << 6U)) /*!< write value to ENET_MAC_PHY_CTL_PR bit field */ -#define MAC_PHY_CTL_PA(regval) (BITS(11,15) & ((uint32_t)(regval) << 11)) /*!< write value to ENET_MAC_PHY_CTL_PA bit field */ +#define MAC_PHY_CTL_PA(regval) (BITS(11,15) & ((uint32_t)(regval) << 11U)) /*!< write value to ENET_MAC_PHY_CTL_PA bit field */ /* mac_phy_data register value */ -#define MAC_PHY_DATA_PD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_PHY_DATA_PD bit field */ +#define MAC_PHY_DATA_PD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0U)) /*!< write value to ENET_MAC_PHY_DATA_PD bit field */ /* mac_fctl register value */ -#define MAC_FCTL_PLTS(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) /*!< write value to ENET_MAC_FCTL_PLTS bit field */ +#define MAC_FCTL_PLTS(regval) (BITS(4,5) & ((uint32_t)(regval) << 4U)) /*!< write value to ENET_MAC_FCTL_PLTS bit field */ #define ENET_PAUSETIME_MINUS4 MAC_FCTL_PLTS(0) /*!< pause time minus 4 slot times */ #define ENET_PAUSETIME_MINUS28 MAC_FCTL_PLTS(1) /*!< pause time minus 28 slot times */ #define ENET_PAUSETIME_MINUS144 MAC_FCTL_PLTS(2) /*!< pause time minus 144 slot times */ -#define ENET_PAUSETIME_MINUS256 MAC_FCTL_PLTS(3) /*!< pause time minus 256 slot times */ +#define ENET_PAUSETIME_MINUS256 MAC_FCTL_PLTS(3) /*!< pause time minus 256 slot times */ #define ENET_ZERO_QUANTA_PAUSE_ENABLE ((uint32_t)0x00000000U) /*!< enable the automatic zero-quanta generation function */ #define ENET_ZERO_QUANTA_PAUSE_DISABLE ENET_MAC_FCTL_DZQP /*!< disable the automatic zero-quanta generation function */ @@ -1023,7 +1000,7 @@ typedef struct #define ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT ENET_MAC_FCTL_UPFDT /*!< besides the unique multicast address, MAC also use the MAC0 address to detect pause frame */ #define ENET_UNIQUE_PAUSEDETECT ((uint32_t)0x00000000U) /*!< only the unique multicast address for pause frame which is specified in IEEE802.3 can be detected */ - + #define ENET_RX_FLOWCONTROL_ENABLE ENET_MAC_FCTL_RFCEN /*!< enable decoding function for the received pause frame and process it */ #define ENET_RX_FLOWCONTROL_DISABLE ((uint32_t)0x00000000U) /*!< decode function for pause frame is disabled */ #define ENET_RX_FLOWCONTROL ENET_MAC_FCTL_RFCEN /*!< decoding function for the received pause frame and process it */ @@ -1035,28 +1012,28 @@ typedef struct #define ENET_BACK_PRESSURE_ENABLE ENET_MAC_FCTL_FLCBBKPA /*!< enable the back pressure operation in the MAC */ #define ENET_BACK_PRESSURE_DISABLE ((uint32_t)0x00000000U) /*!< disable the back pressure operation in the MAC */ #define ENET_BACK_PRESSURE ENET_MAC_FCTL_FLCBBKPA /*!< the back pressure operation in the MAC */ - -#define MAC_FCTL_PTM(regval) (BITS(16,31) & ((uint32_t)(regval) << 16)) /*!< write value to ENET_MAC_FCTL_PTM bit field */ + +#define MAC_FCTL_PTM(regval) (BITS(16,31) & ((uint32_t)(regval) << 16U)) /*!< write value to ENET_MAC_FCTL_PTM bit field */ /* mac_vlt register value */ -#define MAC_VLT_VLTI(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_VLT_VLTI bit field */ - +#define MAC_VLT_VLTI(regval) (BITS(0,15) & ((uint32_t)(regval) << 0U)) /*!< write value to ENET_MAC_VLT_VLTI bit field */ + #define ENET_VLANTAGCOMPARISON_12BIT ENET_MAC_VLT_VLTC /*!< only low 12 bits of the VLAN tag are used for comparison */ #define ENET_VLANTAGCOMPARISON_16BIT ((uint32_t)0x00000000U) /*!< all 16 bits of the VLAN tag are used for comparison */ -/* mac_wum register value */ +/* mac_wum register value */ #define ENET_WUM_FLAG_WUFFRPR ENET_MAC_WUM_WUFFRPR /*!< wakeup frame filter register poniter reset */ #define ENET_WUM_FLAG_WUFR ENET_MAC_WUM_WUFR /*!< wakeup frame received */ #define ENET_WUM_FLAG_MPKR ENET_MAC_WUM_MPKR /*!< magic packet received */ -#define ENET_WUM_POWER_DOWN ENET_MAC_WUM_PWD /*!< power down mode */ -#define ENET_WUM_MAGIC_PACKET_FRAME ENET_MAC_WUM_MPEN /*!< enable a wakeup event due to magic packet reception */ -#define ENET_WUM_WAKE_UP_FRAME ENET_MAC_WUM_WFEN /*!< enable a wakeup event due to wakeup frame reception */ +#define ENET_WUM_POWER_DOWN ENET_MAC_WUM_PWD /*!< power down mode */ +#define ENET_WUM_MAGIC_PACKET_FRAME ENET_MAC_WUM_MPEN /*!< enable a wakeup event due to magic packet reception */ +#define ENET_WUM_WAKE_UP_FRAME ENET_MAC_WUM_WFEN /*!< enable a wakeup event due to wakeup frame reception */ #define ENET_WUM_GLOBAL_UNICAST ENET_MAC_WUM_GU /*!< any received unicast frame passed filter is considered to be a wakeup frame */ /* mac_addr0h register value */ -#define MAC_ADDR0H_ADDR0H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_ADDR0H_ADDR0H bit field */ +#define MAC_ADDR0H_ADDR0H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0U)) /*!< write value to ENET_MAC_ADDR0H_ADDR0H bit field */ /* mac_addrxh register value, x = 1,2,3 */ -#define MAC_ADDR123H_ADDR123H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_MAC_ADDRxH_ADDRxH(x=1,2,3) bit field */ +#define MAC_ADDR123H_ADDR123H(regval) (BITS(0,15) & ((uint32_t)(regval) << 0U)) /*!< write value to ENET_MAC_ADDRxH_ADDRxH(x=1,2,3) bit field */ #define ENET_ADDRESS_MASK_BYTE0 BIT(24) /*!< low register bits [7:0] */ #define ENET_ADDRESS_MASK_BYTE1 BIT(25) /*!< low register bits [15:8] */ @@ -1066,10 +1043,10 @@ typedef struct #define ENET_ADDRESS_MASK_BYTE5 BIT(29) /*!< high register bits [15:8] */ #define ENET_ADDRESS_FILTER_SA BIT(30) /*!< use MAC address[47:0] is to compare with the SA fields of the received frame */ -#define ENET_ADDRESS_FILTER_DA ((uint32_t)0x00000000) /*!< use MAC address[47:0] is to compare with the DA fields of the received frame */ - +#define ENET_ADDRESS_FILTER_DA ((uint32_t)0x00000000U) /*!< use MAC address[47:0] is to compare with the DA fields of the received frame */ + /* mac_fcth register value */ -#define MAC_FCTH_RFA(regval) ((BITS(0,2) & ((uint32_t)(regval) << 0))<<8) /*!< write value to ENET_MAC_FCTH_RFA bit field */ +#define MAC_FCTH_RFA(regval) ((BITS(0,2) & ((uint32_t)(regval) << 0U)) << 8U) /*!< write value to ENET_MAC_FCTH_RFA bit field */ #define ENET_ACTIVE_THRESHOLD_256BYTES MAC_FCTH_RFA(0) /*!< threshold level is 256 bytes */ #define ENET_ACTIVE_THRESHOLD_512BYTES MAC_FCTH_RFA(1) /*!< threshold level is 512 bytes */ #define ENET_ACTIVE_THRESHOLD_768BYTES MAC_FCTH_RFA(2) /*!< threshold level is 768 bytes */ @@ -1078,7 +1055,7 @@ typedef struct #define ENET_ACTIVE_THRESHOLD_1536BYTES MAC_FCTH_RFA(5) /*!< threshold level is 1536 bytes */ #define ENET_ACTIVE_THRESHOLD_1792BYTES MAC_FCTH_RFA(6) /*!< threshold level is 1792 bytes */ -#define MAC_FCTH_RFD(regval) ((BITS(4,6) & ((uint32_t)(regval) << 4))<<8) /*!< write value to ENET_MAC_FCTH_RFD bit field */ +#define MAC_FCTH_RFD(regval) ((BITS(4,6) & ((uint32_t)(regval) << 4U)) << 8U) /*!< write value to ENET_MAC_FCTH_RFD bit field */ #define ENET_DEACTIVE_THRESHOLD_256BYTES MAC_FCTH_RFD(0) /*!< threshold level is 256 bytes */ #define ENET_DEACTIVE_THRESHOLD_512BYTES MAC_FCTH_RFD(1) /*!< threshold level is 512 bytes */ #define ENET_DEACTIVE_THRESHOLD_768BYTES MAC_FCTH_RFD(2) /*!< threshold level is 768 bytes */ @@ -1097,100 +1074,100 @@ typedef struct #define ENET_PTP_TIMESTAMP_INT ENET_PTP_TSCTL_TMSITEN /*!< timestamp interrupt trigger enable */ /* ptp_ssinc register value */ -#define PTP_SSINC_STMSSI(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_SSINC_STMSSI bit field */ +#define PTP_SSINC_STMSSI(regval) (BITS(0,7) & ((uint32_t)(regval) << 0U)) /*!< write value to ENET_PTP_SSINC_STMSSI bit field */ /* ptp_tsl register value */ -#define GET_PTP_TSL_STMSS(regval) GET_BITS((uint32_t)(regval),0,30) /*!< get value of ENET_PTP_TSL_STMSS bit field */ - -#define ENET_PTP_TIME_POSITIVE ((uint32_t)0x00000000) /*!< time value is positive */ -#define ENET_PTP_TIME_NEGATIVE ENET_PTP_TSL_STS /*!< time value is negative */ +#define GET_PTP_TSL_STMSS(regval) GET_BITS((uint32_t)(regval), 0U, 30U) /*!< get value of ENET_PTP_TSL_STMSS bit field */ -#define GET_PTP_TSL_STS(regval) (((regval) & BIT(31)) >> (31U)) /*!< get value of ENET_PTP_TSL_STS bit field */ +#define ENET_PTP_TIME_POSITIVE ((uint32_t)0x00000000U) /*!< time value is positive */ +#define ENET_PTP_TIME_NEGATIVE ENET_PTP_TSL_STS /*!< time value is negative */ + +#define GET_PTP_TSL_STS(regval) (((regval) & BIT(31)) >> (31U)) /*!< get value of ENET_PTP_TSL_STS bit field */ /* ptp_tsul register value */ -#define PTP_TSUL_TMSUSS(regval) (BITS(0,30) & ((uint32_t)(regval) << 0)) /*!< write value to ENET_PTP_TSUL_TMSUSS bit field */ +#define PTP_TSUL_TMSUSS(regval) (BITS(0,30) & ((uint32_t)(regval) << 0U)) /*!< write value to ENET_PTP_TSUL_TMSUSS bit field */ -#define ENET_PTP_ADD_TO_TIME ((uint32_t)0x00000000) /*!< timestamp update value is added to system time */ -#define ENET_PTP_SUBSTRACT_FROM_TIME ENET_PTP_TSUL_TMSUPNS /*!< timestamp update value is subtracted from system time */ +#define ENET_PTP_ADD_TO_TIME ((uint32_t)0x00000000U) /*!< timestamp update value is added to system time */ +#define ENET_PTP_SUBSTRACT_FROM_TIME ENET_PTP_TSUL_TMSUPNS /*!< timestamp update value is subtracted from system time */ /* dma_bctl register value */ -#define DMA_BCTL_DPSL(regval) (BITS(2,6) & ((uint32_t)(regval) << 2)) /*!< write value to ENET_DMA_BCTL_DPSL bit field */ -#define GET_DMA_BCTL_DPSL(regval) GET_BITS((regval),2,6) /*!< get value of ENET_DMA_BCTL_DPSL bit field */ - -#define DMA_BCTL_PGBL(regval) (BITS(8,13) & ((uint32_t)(regval) << 8)) /*!< write value to ENET_DMA_BCTL_PGBL bit field */ -#define ENET_PGBL_1BEAT DMA_BCTL_PGBL(1) /*!< maximum number of beats is 1 */ -#define ENET_PGBL_2BEAT DMA_BCTL_PGBL(2) /*!< maximum number of beats is 2 */ -#define ENET_PGBL_4BEAT DMA_BCTL_PGBL(4) /*!< maximum number of beats is 4 */ -#define ENET_PGBL_8BEAT DMA_BCTL_PGBL(8) /*!< maximum number of beats is 8 */ -#define ENET_PGBL_16BEAT DMA_BCTL_PGBL(16) /*!< maximum number of beats is 16 */ -#define ENET_PGBL_32BEAT DMA_BCTL_PGBL(32) /*!< maximum number of beats is 32 */ -#define ENET_PGBL_4xPGBL_4BEAT (DMA_BCTL_PGBL(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 4 */ -#define ENET_PGBL_4xPGBL_8BEAT (DMA_BCTL_PGBL(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 8 */ -#define ENET_PGBL_4xPGBL_16BEAT (DMA_BCTL_PGBL(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 16 */ -#define ENET_PGBL_4xPGBL_32BEAT (DMA_BCTL_PGBL(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 32 */ -#define ENET_PGBL_4xPGBL_64BEAT (DMA_BCTL_PGBL(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 64 */ -#define ENET_PGBL_4xPGBL_128BEAT (DMA_BCTL_PGBL(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 128 */ - -#define DMA_BCTL_RTPR(regval) (BITS(14,15) & ((uint32_t)(regval) << 14)) /*!< write value to ENET_DMA_BCTL_RTPR bit field */ -#define ENET_ARBITRATION_RXTX_1_1 DMA_BCTL_RTPR(0) /*!< receive and transmit priority ratio is 1:1*/ -#define ENET_ARBITRATION_RXTX_2_1 DMA_BCTL_RTPR(1) /*!< receive and transmit priority ratio is 2:1*/ -#define ENET_ARBITRATION_RXTX_3_1 DMA_BCTL_RTPR(2) /*!< receive and transmit priority ratio is 3:1 */ -#define ENET_ARBITRATION_RXTX_4_1 DMA_BCTL_RTPR(3) /*!< receive and transmit priority ratio is 4:1 */ -#define ENET_ARBITRATION_RXPRIORTX ENET_DMA_BCTL_DAB /*!< RxDMA has higher priority than TxDMA */ - -#define ENET_FIXED_BURST_ENABLE ENET_DMA_BCTL_FB /*!< AHB can only use SINGLE/INCR4/INCR8/INCR16 during start of normal burst transfers */ -#define ENET_FIXED_BURST_DISABLE ((uint32_t)0x00000000) /*!< AHB can use SINGLE/INCR burst transfer operations */ - -#define DMA_BCTL_RXDP(regval) (BITS(17,22) & ((uint32_t)(regval) << 17)) /*!< write value to ENET_DMA_BCTL_RXDP bit field */ -#define ENET_RXDP_1BEAT DMA_BCTL_RXDP(1) /*!< maximum number of beats 1 */ -#define ENET_RXDP_2BEAT DMA_BCTL_RXDP(2) /*!< maximum number of beats 2 */ -#define ENET_RXDP_4BEAT DMA_BCTL_RXDP(4) /*!< maximum number of beats 4 */ -#define ENET_RXDP_8BEAT DMA_BCTL_RXDP(8) /*!< maximum number of beats 8 */ -#define ENET_RXDP_16BEAT DMA_BCTL_RXDP(16) /*!< maximum number of beats 16 */ -#define ENET_RXDP_32BEAT DMA_BCTL_RXDP(32) /*!< maximum number of beats 32 */ -#define ENET_RXDP_4xPGBL_4BEAT (DMA_BCTL_RXDP(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 4 */ -#define ENET_RXDP_4xPGBL_8BEAT (DMA_BCTL_RXDP(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 8 */ -#define ENET_RXDP_4xPGBL_16BEAT (DMA_BCTL_RXDP(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 16 */ -#define ENET_RXDP_4xPGBL_32BEAT (DMA_BCTL_RXDP(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 32 */ -#define ENET_RXDP_4xPGBL_64BEAT (DMA_BCTL_RXDP(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 64 */ -#define ENET_RXDP_4xPGBL_128BEAT (DMA_BCTL_RXDP(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 128 */ - -#define ENET_RXTX_DIFFERENT_PGBL ENET_DMA_BCTL_UIP /*!< RxDMA uses the RXDP[5:0], while TxDMA uses the PGBL[5:0] */ -#define ENET_RXTX_SAME_PGBL ((uint32_t)0x00000000) /*!< RxDMA/TxDMA uses PGBL[5:0] */ - -#define ENET_ADDRESS_ALIGN_ENABLE ENET_DMA_BCTL_AA /*!< enabled address-aligned */ -#define ENET_ADDRESS_ALIGN_DISABLE ((uint32_t)0x00000000) /*!< disable address-aligned */ +#define DMA_BCTL_DPSL(regval) (BITS(2,6) & ((uint32_t)(regval) << 2U)) /*!< write value to ENET_DMA_BCTL_DPSL bit field */ +#define GET_DMA_BCTL_DPSL(regval) GET_BITS((regval), 2U, 6U) /*!< get value of ENET_DMA_BCTL_DPSL bit field */ + +#define DMA_BCTL_PGBL(regval) (BITS(8,13) & ((uint32_t)(regval) << 8U)) /*!< write value to ENET_DMA_BCTL_PGBL bit field */ +#define ENET_PGBL_1BEAT DMA_BCTL_PGBL(1) /*!< maximum number of beats is 1 */ +#define ENET_PGBL_2BEAT DMA_BCTL_PGBL(2) /*!< maximum number of beats is 2 */ +#define ENET_PGBL_4BEAT DMA_BCTL_PGBL(4) /*!< maximum number of beats is 4 */ +#define ENET_PGBL_8BEAT DMA_BCTL_PGBL(8) /*!< maximum number of beats is 8 */ +#define ENET_PGBL_16BEAT DMA_BCTL_PGBL(16) /*!< maximum number of beats is 16 */ +#define ENET_PGBL_32BEAT DMA_BCTL_PGBL(32) /*!< maximum number of beats is 32 */ +#define ENET_PGBL_4xPGBL_4BEAT (DMA_BCTL_PGBL(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 4 */ +#define ENET_PGBL_4xPGBL_8BEAT (DMA_BCTL_PGBL(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 8 */ +#define ENET_PGBL_4xPGBL_16BEAT (DMA_BCTL_PGBL(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 16 */ +#define ENET_PGBL_4xPGBL_32BEAT (DMA_BCTL_PGBL(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 32 */ +#define ENET_PGBL_4xPGBL_64BEAT (DMA_BCTL_PGBL(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 64 */ +#define ENET_PGBL_4xPGBL_128BEAT (DMA_BCTL_PGBL(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats is 128 */ + +#define DMA_BCTL_RTPR(regval) (BITS(14,15) & ((uint32_t)(regval) << 14U)) /*!< write value to ENET_DMA_BCTL_RTPR bit field */ +#define ENET_ARBITRATION_RXTX_1_1 DMA_BCTL_RTPR(0) /*!< receive and transmit priority ratio is 1:1*/ +#define ENET_ARBITRATION_RXTX_2_1 DMA_BCTL_RTPR(1) /*!< receive and transmit priority ratio is 2:1*/ +#define ENET_ARBITRATION_RXTX_3_1 DMA_BCTL_RTPR(2) /*!< receive and transmit priority ratio is 3:1 */ +#define ENET_ARBITRATION_RXTX_4_1 DMA_BCTL_RTPR(3) /*!< receive and transmit priority ratio is 4:1 */ +#define ENET_ARBITRATION_RXPRIORTX ENET_DMA_BCTL_DAB /*!< RxDMA has higher priority than TxDMA */ + +#define ENET_FIXED_BURST_ENABLE ENET_DMA_BCTL_FB /*!< AHB can only use SINGLE/INCR4/INCR8/INCR16 during start of normal burst transfers */ +#define ENET_FIXED_BURST_DISABLE ((uint32_t)0x00000000U) /*!< AHB can use SINGLE/INCR burst transfer operations */ + +#define DMA_BCTL_RXDP(regval) (BITS(17,22) & ((uint32_t)(regval) << 17U)) /*!< write value to ENET_DMA_BCTL_RXDP bit field */ +#define ENET_RXDP_1BEAT DMA_BCTL_RXDP(1) /*!< maximum number of beats 1 */ +#define ENET_RXDP_2BEAT DMA_BCTL_RXDP(2) /*!< maximum number of beats 2 */ +#define ENET_RXDP_4BEAT DMA_BCTL_RXDP(4) /*!< maximum number of beats 4 */ +#define ENET_RXDP_8BEAT DMA_BCTL_RXDP(8) /*!< maximum number of beats 8 */ +#define ENET_RXDP_16BEAT DMA_BCTL_RXDP(16) /*!< maximum number of beats 16 */ +#define ENET_RXDP_32BEAT DMA_BCTL_RXDP(32) /*!< maximum number of beats 32 */ +#define ENET_RXDP_4xPGBL_4BEAT (DMA_BCTL_RXDP(1)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 4 */ +#define ENET_RXDP_4xPGBL_8BEAT (DMA_BCTL_RXDP(2)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 8 */ +#define ENET_RXDP_4xPGBL_16BEAT (DMA_BCTL_RXDP(4)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 16 */ +#define ENET_RXDP_4xPGBL_32BEAT (DMA_BCTL_RXDP(8)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 32 */ +#define ENET_RXDP_4xPGBL_64BEAT (DMA_BCTL_RXDP(16)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 64 */ +#define ENET_RXDP_4xPGBL_128BEAT (DMA_BCTL_RXDP(32)|ENET_DMA_BCTL_FPBL) /*!< maximum number of beats 128 */ + +#define ENET_RXTX_DIFFERENT_PGBL ENET_DMA_BCTL_UIP /*!< RxDMA uses the RXDP[5:0], while TxDMA uses the PGBL[5:0] */ +#define ENET_RXTX_SAME_PGBL ((uint32_t)0x00000000U) /*!< RxDMA/TxDMA uses PGBL[5:0] */ + +#define ENET_ADDRESS_ALIGN_ENABLE ENET_DMA_BCTL_AA /*!< enabled address-aligned */ +#define ENET_ADDRESS_ALIGN_DISABLE ((uint32_t)0x00000000U) /*!< disable address-aligned */ /* dma_stat register value */ -#define GET_DMA_STAT_RP(regval) GET_BITS((uint32_t)(regval),17,19) /*!< get value of ENET_DMA_STAT_RP bit field */ -#define ENET_RX_STATE_STOPPED ((uint32_t)0x00000000) /*!< reset or stop rx command issued */ +#define GET_DMA_STAT_RP(regval) GET_BITS((uint32_t)(regval), 17U, 19U) /*!< get value of ENET_DMA_STAT_RP bit field */ +#define ENET_RX_STATE_STOPPED ((uint32_t)0x00000000U) /*!< reset or stop rx command issued */ #define ENET_RX_STATE_FETCHING BIT(17) /*!< fetching the Rx descriptor */ #define ENET_RX_STATE_WAITING (BIT(17)|BIT(18)) /*!< waiting for receive packet */ #define ENET_RX_STATE_SUSPENDED BIT(19) /*!< Rx descriptor unavailable */ #define ENET_RX_STATE_CLOSING (BIT(17)|BIT(19)) /*!< closing receive descriptor */ #define ENET_RX_STATE_QUEUING ENET_DMA_STAT_RP /*!< transferring the receive packet data from recevie buffer to host memory */ -#define GET_DMA_STAT_TP(regval) GET_BITS((uint32_t)(regval),20,22) /*!< get value of ENET_DMA_STAT_TP bit field */ -#define ENET_TX_STATE_STOPPED ((uint32_t)0x00000000) /*!< reset or stop Tx Command issued */ +#define GET_DMA_STAT_TP(regval) GET_BITS((uint32_t)(regval), 20U, 22U) /*!< get value of ENET_DMA_STAT_TP bit field */ +#define ENET_TX_STATE_STOPPED ((uint32_t)0x00000000U) /*!< reset or stop Tx Command issued */ #define ENET_TX_STATE_FETCHING BIT(20) /*!< fetching the Tx descriptor */ #define ENET_TX_STATE_WAITING BIT(21) /*!< waiting for status */ #define ENET_TX_STATE_READING (BIT(20)|BIT(21)) /*!< reading the data from host memory buffer and queuing it to transmit buffer */ #define ENET_TX_STATE_SUSPENDED (BIT(21)|BIT(22)) /*!< Tx descriptor unavailabe or transmit buffer underflow */ #define ENET_TX_STATE_CLOSING ENET_DMA_STAT_TP /*!< closing Tx descriptor */ -#define GET_DMA_STAT_EB(regval) GET_BITS((uint32_t)(regval),23,25) /*!< get value of ENET_DMA_STAT_EB bit field */ +#define GET_DMA_STAT_EB(regval) GET_BITS((uint32_t)(regval), 23U, 25U) /*!< get value of ENET_DMA_STAT_EB bit field */ #define ENET_ERROR_TXDATA_TRANSFER BIT(23) /*!< error during data transfer by TxDMA or RxDMA */ #define ENET_ERROR_READ_TRANSFER BIT(24) /*!< error during write transfer or read transfer */ #define ENET_ERROR_DESC_ACCESS BIT(25) /*!< error during descriptor or buffer access */ /* dma_ctl register value */ -#define DMA_CTL_RTHC(regval) (BITS(3,4) & ((uint32_t)(regval) << 3)) /*!< write value to ENET_DMA_CTL_RTHC bit field */ +#define DMA_CTL_RTHC(regval) (BITS(3,4) & ((uint32_t)(regval) << 3U)) /*!< write value to ENET_DMA_CTL_RTHC bit field */ #define ENET_RX_THRESHOLD_64BYTES DMA_CTL_RTHC(0) /*!< threshold level is 64 Bytes */ #define ENET_RX_THRESHOLD_32BYTES DMA_CTL_RTHC(1) /*!< threshold level is 32 Bytes */ #define ENET_RX_THRESHOLD_96BYTES DMA_CTL_RTHC(2) /*!< threshold level is 96 Bytes */ #define ENET_RX_THRESHOLD_128BYTES DMA_CTL_RTHC(3) /*!< threshold level is 128 Bytes */ -#define DMA_CTL_TTHC(regval) (BITS(14,16) & ((uint32_t)(regval) << 14)) /*!< write value to ENET_DMA_CTL_TTHC bit field */ +#define DMA_CTL_TTHC(regval) (BITS(14,16) & ((uint32_t)(regval) << 14U)) /*!< write value to ENET_DMA_CTL_TTHC bit field */ #define ENET_TX_THRESHOLD_64BYTES DMA_CTL_TTHC(0) /*!< threshold level is 64 Bytes */ #define ENET_TX_THRESHOLD_128BYTES DMA_CTL_TTHC(1) /*!< threshold level is 128 Bytes */ #define ENET_TX_THRESHOLD_192BYTES DMA_CTL_TTHC(2) /*!< threshold level is 192 Bytes */ @@ -1201,68 +1178,68 @@ typedef struct #define ENET_TX_THRESHOLD_16BYTES DMA_CTL_TTHC(7) /*!< threshold level is 16 Bytes */ #define ENET_TCPIP_CKSUMERROR_ACCEPT ENET_DMA_CTL_DTCERFD /*!< Rx frame with only payload error but no other errors will not be dropped */ -#define ENET_TCPIP_CKSUMERROR_DROP ((uint32_t)0x00000000) /*!< all error frames will be dropped when FERF = 0 */ +#define ENET_TCPIP_CKSUMERROR_DROP ((uint32_t)0x00000000U) /*!< all error frames will be dropped when FERF = 0 */ #define ENET_RX_MODE_STOREFORWARD ENET_DMA_CTL_RSFD /*!< RxFIFO operates in store-and-forward mode */ -#define ENET_RX_MODE_CUTTHROUGH ((uint32_t)0x00000000) /*!< RxFIFO operates in cut-through mode */ +#define ENET_RX_MODE_CUTTHROUGH ((uint32_t)0x00000000U) /*!< RxFIFO operates in cut-through mode */ -#define ENET_FLUSH_RXFRAME_ENABLE ((uint32_t)0x00000000) /*!< RxDMA flushes all frames */ +#define ENET_FLUSH_RXFRAME_ENABLE ((uint32_t)0x00000000U) /*!< RxDMA flushes all frames */ #define ENET_FLUSH_RXFRAME_DISABLE ENET_DMA_CTL_DAFRF /*!< RxDMA does not flush any frames */ #define ENET_NO_FLUSH_RXFRAME ENET_DMA_CTL_DAFRF /*!< RxDMA does not flush frames function */ #define ENET_TX_MODE_STOREFORWARD ENET_DMA_CTL_TSFD /*!< TxFIFO operates in store-and-forward mode */ -#define ENET_TX_MODE_CUTTHROUGH ((uint32_t)0x00000000) /*!< TxFIFO operates in cut-through mode */ +#define ENET_TX_MODE_CUTTHROUGH ((uint32_t)0x00000000U) /*!< TxFIFO operates in cut-through mode */ -#define ENET_FORWARD_ERRFRAMES_ENABLE (ENET_DMA_CTL_FERF<<2) /*!< all frame received with error except runt error are forwarded to memory */ +#define ENET_FORWARD_ERRFRAMES_ENABLE (ENET_DMA_CTL_FERF << 2U) /*!< all frame received with error except runt error are forwarded to memory */ #define ENET_FORWARD_ERRFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drop error frame */ -#define ENET_FORWARD_ERRFRAMES (ENET_DMA_CTL_FERF<<2) /*!< the function that all frame received with error except runt error are forwarded to memory */ +#define ENET_FORWARD_ERRFRAMES (ENET_DMA_CTL_FERF << 2U) /*!< the function that all frame received with error except runt error are forwarded to memory */ -#define ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE (ENET_DMA_CTL_FUF<<2) /*!< forward undersized good frames */ -#define ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE ((uint32_t)0x00000000) /*!< RxFIFO drops all frames whose length is less than 64 bytes */ -#define ENET_FORWARD_UNDERSZ_GOODFRAMES (ENET_DMA_CTL_FUF<<2) /*!< the function that forwarding undersized good frames */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE (ENET_DMA_CTL_FUF << 2U) /*!< forward undersized good frames */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE ((uint32_t)0x00000000U) /*!< RxFIFO drops all frames whose length is less than 64 bytes */ +#define ENET_FORWARD_UNDERSZ_GOODFRAMES (ENET_DMA_CTL_FUF << 2U) /*!< the function that forwarding undersized good frames */ -#define ENET_SECONDFRAME_OPT_ENABLE ENET_DMA_CTL_OSF /*!< TxDMA controller operate on second frame mode enable*/ -#define ENET_SECONDFRAME_OPT_DISABLE ((uint32_t)0x00000000) /*!< TxDMA controller operate on second frame mode disable */ -#define ENET_SECONDFRAME_OPT ENET_DMA_CTL_OSF /*!< TxDMA controller operate on second frame function */ +#define ENET_SECONDFRAME_OPT_ENABLE ENET_DMA_CTL_OSF /*!< TxDMA controller operate on second frame mode enable*/ +#define ENET_SECONDFRAME_OPT_DISABLE ((uint32_t)0x00000000U) /*!< TxDMA controller operate on second frame mode disable */ +#define ENET_SECONDFRAME_OPT ENET_DMA_CTL_OSF /*!< TxDMA controller operate on second frame function */ /* dma_mfbocnt register value */ -#define GET_DMA_MFBOCNT_MSFC(regval) GET_BITS((regval),0,15) /*!< get value of ENET_DMA_MFBOCNT_MSFC bit field */ +#define GET_DMA_MFBOCNT_MSFC(regval) GET_BITS((regval), 0U, 15U) /*!< get value of ENET_DMA_MFBOCNT_MSFC bit field */ -#define GET_DMA_MFBOCNT_MSFA(regval) GET_BITS((regval),17,27) /*!< get value of ENET_DMA_MFBOCNT_MSFA bit field */ +#define GET_DMA_MFBOCNT_MSFA(regval) GET_BITS((regval), 17U, 27U) /*!< get value of ENET_DMA_MFBOCNT_MSFA bit field */ /* dma tx descriptor tdes0 register value */ -#define TDES0_CONT(regval) (BITS(3,6) & ((uint32_t)(regval) << 3)) /*!< write value to ENET DMA TDES0 CONT bit field */ -#define GET_TDES0_COCNT(regval) GET_BITS((regval),3,6) /*!< get value of ENET DMA TDES0 CONT bit field */ +#define TDES0_CONT(regval) (BITS(3,6) & ((uint32_t)(regval) << 3U)) /*!< write value to ENET DMA TDES0 CONT bit field */ +#define GET_TDES0_COCNT(regval) GET_BITS((regval), 3U, 6U) /*!< get value of ENET DMA TDES0 CONT bit field */ -#define TDES0_CM(regval) (BITS(22,23) & ((uint32_t)(regval) << 22)) /*!< write value to ENET DMA TDES0 CM bit field */ -#define ENET_CHECKSUM_DISABLE TDES0_CM(0) /*!< checksum insertion disabled */ -#define ENET_CHECKSUM_IPV4HEADER TDES0_CM(1) /*!< only IP header checksum calculation and insertion are enabled */ -#define ENET_CHECKSUM_TCPUDPICMP_SEGMENT TDES0_CM(2) /*!< TCP/UDP/ICMP checksum insertion calculated but pseudo-header */ -#define ENET_CHECKSUM_TCPUDPICMP_FULL TDES0_CM(3) /*!< TCP/UDP/ICMP checksum insertion fully calculated */ +#define TDES0_CM(regval) (BITS(22,23) & ((uint32_t)(regval) << 22U)) /*!< write value to ENET DMA TDES0 CM bit field */ +#define ENET_CHECKSUM_DISABLE TDES0_CM(0) /*!< checksum insertion disabled */ +#define ENET_CHECKSUM_IPV4HEADER TDES0_CM(1) /*!< only IP header checksum calculation and insertion are enabled */ +#define ENET_CHECKSUM_TCPUDPICMP_SEGMENT TDES0_CM(2) /*!< TCP/UDP/ICMP checksum insertion calculated but pseudo-header */ +#define ENET_CHECKSUM_TCPUDPICMP_FULL TDES0_CM(3) /*!< TCP/UDP/ICMP checksum insertion fully calculated */ /* dma tx descriptor tdes1 register value */ -#define TDES1_TB1S(regval) (BITS(0,12) & ((uint32_t)(regval) << 0)) /*!< write value to ENET DMA TDES1 TB1S bit field */ +#define TDES1_TB1S(regval) (BITS(0,12) & ((uint32_t)(regval) << 0U)) /*!< write value to ENET DMA TDES1 TB1S bit field */ -#define TDES1_TB2S(regval) (BITS(16,28) & ((uint32_t)(regval) << 16)) /*!< write value to ENET DMA TDES1 TB2S bit field */ +#define TDES1_TB2S(regval) (BITS(16,28) & ((uint32_t)(regval) << 16U)) /*!< write value to ENET DMA TDES1 TB2S bit field */ /* dma rx descriptor rdes0 register value */ -#define RDES0_FRML(regval) (BITS(16,29) & ((uint32_t)(regval) << 16)) /*!< write value to ENET DMA RDES0 FRML bit field */ -#define GET_RDES0_FRML(regval) GET_BITS((regval),16,29) /*!< get value of ENET DMA RDES0 FRML bit field */ +#define RDES0_FRML(regval) (BITS(16,29) & ((uint32_t)(regval) << 16U)) /*!< write value to ENET DMA RDES0 FRML bit field */ +#define GET_RDES0_FRML(regval) GET_BITS((regval), 16U, 29U) /*!< get value of ENET DMA RDES0 FRML bit field */ /* dma rx descriptor rdes1 register value */ -#define ENET_RECEIVE_COMPLETE_INT_ENABLE ((uint32_t)0x00000000U) /*!< RS bit immediately set after Rx completed */ -#define ENET_RECEIVE_COMPLETE_INT_DISABLE ENET_RDES1_DINTC /*!< RS bit not immediately set after Rx completed */ +#define ENET_RECEIVE_COMPLETE_INT_ENABLE ((uint32_t)0x00000000U) /*!< RS bit immediately set after Rx completed */ +#define ENET_RECEIVE_COMPLETE_INT_DISABLE ENET_RDES1_DINTC /*!< RS bit not immediately set after Rx completed */ -#define GET_RDES1_RB1S(regval) GET_BITS((regval),0,12) /*!< get value of ENET DMA RDES1 RB1S bit field */ +#define GET_RDES1_RB1S(regval) GET_BITS((regval), 0U, 12U) /*!< get value of ENET DMA RDES1 RB1S bit field */ -#define GET_RDES1_RB2S(regval) GET_BITS((regval),16,28) /*!< get value of ENET DMA RDES1 RB2S bit field */ +#define GET_RDES1_RB2S(regval) GET_BITS((regval), 16U, 28U) /*!< get value of ENET DMA RDES1 RB2S bit field */ /* dma rx descriptor rdes4 register value */ -#define RDES4_IPPLDT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0)) /*!< write value to ENET DMA RDES4 IPPLDT bit field */ -#define GET_RDES4_IPPLDT(regval) GET_BITS((regval),0,2) /*!< get value of ENET DMA RDES4 IPPLDT bit field */ +#define RDES4_IPPLDT(regval) (BITS(0,2) & ((uint32_t)(regval) << 0U)) /*!< write value to ENET DMA RDES4 IPPLDT bit field */ +#define GET_RDES4_IPPLDT(regval) GET_BITS((regval),0,2) /*!< get value of ENET DMA RDES4 IPPLDT bit field */ -#define RDES4_PTPMT(regval) (BITS(8,11) & ((uint32_t)(regval) << 8)) /*!< write value to ENET DMA RDES4 PTPMT bit field */ -#define GET_RDES4_PTPMT(regval) GET_BITS((regval),8,11) /*!< get value of ENET DMA RDES4 PTPMT bit field */ +#define RDES4_PTPMT(regval) (BITS(8,11) & ((uint32_t)(regval) << 8U)) /*!< write value to ENET DMA RDES4 PTPMT bit field */ +#define GET_RDES4_PTPMT(regval) GET_BITS((regval),8,11) /*!< get value of ENET DMA RDES4 PTPMT bit field */ /* ENET register mask value */ #define MAC_CFG_MASK ((uint32_t)0xFD30810FU) /*!< ENET_MAC_CFG register mask */ @@ -1270,23 +1247,23 @@ typedef struct #define DMA_CTL_MASK ((uint32_t)0xF8DE3F23U) /*!< ENET_DMA_CTL register mask */ #define DMA_BCTL_MASK ((uint32_t)0xF800007DU) /*!< ENET_DMA_BCTL register mask */ -#define ETH_DMATXDESC_SIZE 0x10U /*!< TxDMA descriptor size */ -#define ETH_DMARXDESC_SIZE 0x10U /*!< RxDMA descriptor size */ +#define ETH_DMATXDESC_SIZE 0x00000010U /*!< TxDMA descriptor size */ +#define ETH_DMARXDESC_SIZE 0x00000010U /*!< RxDMA descriptor size */ -typedef enum{ +typedef enum { ENET_PTP_SYSTIME_INIT = ENET_PTP_TSCTL_TMSSTI, /*!< timestamp initialize */ - ENET_PTP_SYSTIME_UPDATE = ENET_PTP_TSCTL_TMSSTU, /*!< timestamp update */ + ENET_PTP_SYSTIME_UPDATE = ENET_PTP_TSCTL_TMSSTU, /*!< timestamp update */ ENET_PTP_ADDEND_UPDATE = ENET_PTP_TSCTL_TMSARU, /*!< addend register update */ - ENET_PTP_FINEMODE = (int32_t)(ENET_PTP_TSCTL_TMSFCU| BIT(31)), /*!< the system timestamp uses the fine method for updating */ + ENET_PTP_FINEMODE = (int32_t)(ENET_PTP_TSCTL_TMSFCU | BIT(31)), /*!< the system timestamp uses the fine method for updating */ ENET_PTP_COARSEMODE = ENET_PTP_TSCTL_TMSFCU, /*!< the system timestamp uses the coarse method for updating */ -}enet_ptp_function_enum; +} enet_ptp_function_enum; /* ENET remote wake-up frame register length */ #define ETH_WAKEUP_REGISTER_LENGTH 8U /*!< remote wake-up frame register length */ -/* ENET frame size */ -#define ENET_MAX_FRAME_SIZE 1524U /*!< header + frame_extra + payload + CRC */ +/* ENET frame size */ +#define ENET_MAX_FRAME_SIZE 1524U /*!< header + frame_extra + payload + CRC */ /* ENET delay timeout */ #define ENET_DELAY_TO ((uint32_t)0x0004FFFFU) /*!< ENET delay timeout */ @@ -1319,27 +1296,14 @@ ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length); /* configure the transmit IP frame checksum offload calculation and insertion */ void enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum); /* ENET Tx and Rx function enable (include MAC and DMA module) */ -void enet_enable(void); +void enet_enable(void); /* ENET Tx and Rx function disable (include MAC and DMA module) */ void enet_disable(void); /* configure MAC address */ void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]); -/* get MAC address */ +/* get MAC address */ void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[]); -/* get the ENET MAC/MSC/PTP/DMA status flag */ -FlagStatus enet_flag_get(enet_flag_enum enet_flag); -/* clear the ENET DMA status flag */ -void enet_flag_clear(enet_flag_clear_enum enet_flag); -/* enable ENET MAC/MSC/DMA interrupt */ -void enet_interrupt_enable(enet_int_enum enet_int); -/* disable ENET MAC/MSC/DMA interrupt */ -void enet_interrupt_disable(enet_int_enum enet_int); -/* get ENET MAC/MSC/DMA interrupt flag */ -FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag); -/* clear ENET DMA interrupt flag */ -void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear); - /* MAC function */ /* ENET Tx function enable (include MAC and DMA module) */ void enet_tx_enable(void); @@ -1392,7 +1356,7 @@ void enet_flowcontrol_feature_disable(uint32_t feature); /* DMA function */ /* get the dma transmit/receive process state */ -uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction); +uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction); /* poll the dma transmission/reception enable */ void enet_dmaprocess_resume(enet_dmadirection_enum direction); /* check and recover the Rx process */ @@ -1412,7 +1376,7 @@ FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag) /* set the bit flag of ENET dma tx descriptor */ void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag); /* clear the bit flag of ENET dma tx descriptor */ -void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag); +void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag); /* when receiving the completed, set RS bit in ENET_DMA_STAT register will set */ void enet_desc_receive_complete_bit_enable(enet_descriptors_struct *desc); /* when receiving the completed, set RS bit in ENET_DMA_STAT register will not set */ @@ -1450,11 +1414,11 @@ void enet_wum_feature_disable(uint32_t feature); /* MSC function */ /* reset the MAC statistics counters */ void enet_msc_counters_reset(void); -/* enable the MAC statistics counter features */ +/* enable the MAC statistics counter features */ void enet_msc_feature_enable(uint32_t feature); -/* disable the MAC statistics counter features */ +/* disable the MAC statistics counter features */ void enet_msc_feature_disable(uint32_t feature); -/* get MAC statistics counter */ +/* get MAC statistics counter */ uint32_t enet_msc_counters_get(enet_msc_counter_enum counter); /* PTP function */ @@ -1485,7 +1449,7 @@ void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg); /* update system time in coarse method */ void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_struct); /* set system time in fine method */ -void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct); +void enet_ptp_finecorrection_settime(enet_ptp_systime_struct *systime_struct); /* get the ptp flag status */ FlagStatus enet_ptp_flag_get(uint32_t flag); @@ -1496,7 +1460,7 @@ void enet_initpara_reset(void); static void enet_default_init(void); #ifdef USE_DELAY /* user can provide more timing precise _ENET_DELAY_ function */ -#define _ENET_DELAY_ delay_ms +#define _ENET_DELAY_ delay_ms #else /* insert a delay time */ static void enet_delay(uint32_t ncount); @@ -1504,4 +1468,17 @@ static void enet_delay(uint32_t ncount); #define _ENET_DELAY_ enet_delay #endif +/* get the ENET MAC/MSC/PTP/DMA status flag */ +FlagStatus enet_flag_get(enet_flag_enum enet_flag); +/* clear the ENET DMA status flag */ +void enet_flag_clear(enet_flag_clear_enum enet_flag); +/* enable ENET MAC/MSC/DMA interrupt */ +void enet_interrupt_enable(enet_int_enum enet_int); +/* disable ENET MAC/MSC/DMA interrupt */ +void enet_interrupt_disable(enet_int_enum enet_int); +/* get ENET MAC/MSC/DMA interrupt flag */ +FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag); +/* clear ENET DMA interrupt flag */ +void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear); + #endif /* GD32F20X_ENET_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_exmc.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_exmc.h index 691e8351..0f05d115 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_exmc.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_exmc.h @@ -2,36 +2,33 @@ \file gd32f20x_exmc.h \brief definitions for the EXMC - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -42,66 +39,66 @@ OF SUCH DAMAGE. /* EXMC definitions */ #define EXMC (EXMC_BASE) /*!< EXMC register base address */ -#define EXMC_NOR_PSRAM (EXMC_BASE - 0x40000000) /*!< EXMC NOR/PSRAM base address */ -#define EXMC_NAND (EXMC_BASE - 0x30000000) /*!< EXMC NAND base address */ -#define EXMC_PCCARD (EXMC_BASE - 0x10000000) /*!< EXMC PC card base address */ -#define EXMC_SDRAM (EXMC_BASE + 0x20000000) /*!< EXMC SDRAM base address */ +#define EXMC_NOR_PSRAM (EXMC_BASE - 0x40000000U) /*!< EXMC NOR/PSRAM base address */ +#define EXMC_NAND (EXMC_BASE - 0x30000000U) /*!< EXMC NAND base address */ +#define EXMC_PCCARD (EXMC_BASE - 0x10000000U) /*!< EXMC PC card base address */ +#define EXMC_SDRAM (EXMC_BASE + 0x20000000U) /*!< EXMC SDRAM base address */ /* registers definitions */ /* NOR/PSRAM */ -#define EXMC_SNCTL0 REG32(EXMC + 0x00U) /*!< EXMC SRAM/NOR flash control register */ -#define EXMC_SNTCFG0 REG32(EXMC + 0x04U) /*!< EXMC SRAM/NOR flash timing configuration register */ -#define EXMC_SNWTCFG0 REG32(EXMC + 0x104U) /*!< EXMC SRAM/NOR flash write timing configuration register */ +#define EXMC_SNCTL0 REG32(EXMC + 0x00000000U) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG0 REG32(EXMC + 0x00000004U) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG0 REG32(EXMC + 0x00000104U) /*!< EXMC SRAM/NOR flash write timing configuration register */ -#define EXMC_SNCTL1 REG32(EXMC + 0x08U) /*!< EXMC SRAM/NOR flash control register */ -#define EXMC_SNTCFG1 REG32(EXMC + 0x0CU) /*!< EXMC SRAM/NOR flash timing configuration register */ -#define EXMC_SNWTCFG1 REG32(EXMC + 0x10CU) /*!< EXMC SRAM/NOR flash write timing configuration register */ +#define EXMC_SNCTL1 REG32(EXMC + 0x00000008U) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG1 REG32(EXMC + 0x0000000CU) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG1 REG32(EXMC + 0x0000010CU) /*!< EXMC SRAM/NOR flash write timing configuration register */ -#define EXMC_SNCTL2 REG32(EXMC + 0x10U) /*!< EXMC SRAM/NOR flash control register */ -#define EXMC_SNTCFG2 REG32(EXMC + 0x14U) /*!< EXMC SRAM/NOR flash timing configuration register */ -#define EXMC_SNWTCFG2 REG32(EXMC + 0x114U) /*!< EXMC SRAM/NOR flash write timing configuration register */ +#define EXMC_SNCTL2 REG32(EXMC + 0x00000010U) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG2 REG32(EXMC + 0x00000014U) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG2 REG32(EXMC + 0x00000114U) /*!< EXMC SRAM/NOR flash write timing configuration register */ -#define EXMC_SNCTL3 REG32(EXMC + 0x18U) /*!< EXMC SRAM/NOR flash control register */ -#define EXMC_SNTCFG3 REG32(EXMC + 0x1CU) /*!< EXMC SRAM/NOR flash timing configuration register */ -#define EXMC_SNWTCFG3 REG32(EXMC + 0x11CU) /*!< EXMC SRAM/NOR flash write timing configuration register */ +#define EXMC_SNCTL3 REG32(EXMC + 0x00000018U) /*!< EXMC SRAM/NOR flash control register */ +#define EXMC_SNTCFG3 REG32(EXMC + 0x0000001CU) /*!< EXMC SRAM/NOR flash timing configuration register */ +#define EXMC_SNWTCFG3 REG32(EXMC + 0x0000011CU) /*!< EXMC SRAM/NOR flash write timing configuration register */ /* NAND/PC card */ -#define EXMC_NPCTL1 REG32(EXMC + 0x60U) /*!< EXMC NAND/PC card control register */ -#define EXMC_NPINTEN1 REG32(EXMC + 0x64U) /*!< EXMC NAND/PC card interrupt enable register */ -#define EXMC_NPCTCFG1 REG32(EXMC + 0x68U) /*!< EXMC NAND/PC card common space timing configuration register */ -#define EXMC_NPATCFG1 REG32(EXMC + 0x6CU) /*!< EXMC NAND/PC card attribute space timing configuration register */ -#define EXMC_NECC1 REG32(EXMC + 0x74U) /*!< EXMC NAND ECC register */ - -#define EXMC_NPCTL2 REG32(EXMC + 0x80U) /*!< EXMC NAND/PC card control register */ -#define EXMC_NPINTEN2 REG32(EXMC + 0x84U) /*!< EXMC NAND/PC card interrupt enable register */ -#define EXMC_NPCTCFG2 REG32(EXMC + 0x88U) /*!< EXMC NAND/PC card common space timing configuration register */ -#define EXMC_NPATCFG2 REG32(EXMC + 0x8CU) /*!< EXMC NAND/PC card attribute space timing configuration register */ -#define EXMC_NECC2 REG32(EXMC + 0x94U) /*!< EXMC NAND ECC register */ - -#define EXMC_NPCTL3 REG32(EXMC + 0xA0U) /*!< EXMC NAND/PC card control register */ -#define EXMC_NPINTEN3 REG32(EXMC + 0xA4U) /*!< EXMC NAND/PC card interrupt enable register */ -#define EXMC_NPCTCFG3 REG32(EXMC + 0xA8U) /*!< EXMC NAND/PC card common space timing configuration register */ -#define EXMC_NPATCFG3 REG32(EXMC + 0xACU) /*!< EXMC NAND/PC card attribute space timing configuration register */ -#define EXMC_PIOTCFG3 REG32(EXMC + 0xB0U) /*!< EXMC PC card I/O space timing configuration register */ +#define EXMC_NPCTL1 REG32(EXMC + 0x00000060U) /*!< EXMC NAND/PC card control register */ +#define EXMC_NPINTEN1 REG32(EXMC + 0x00000064U) /*!< EXMC NAND/PC card interrupt enable register */ +#define EXMC_NPCTCFG1 REG32(EXMC + 0x00000068U) /*!< EXMC NAND/PC card common space timing configuration register */ +#define EXMC_NPATCFG1 REG32(EXMC + 0x0000006CU) /*!< EXMC NAND/PC card attribute space timing configuration register */ +#define EXMC_NECC1 REG32(EXMC + 0x00000074U) /*!< EXMC NAND ECC register */ + +#define EXMC_NPCTL2 REG32(EXMC + 0x00000080U) /*!< EXMC NAND/PC card control register */ +#define EXMC_NPINTEN2 REG32(EXMC + 0x00000084U) /*!< EXMC NAND/PC card interrupt enable register */ +#define EXMC_NPCTCFG2 REG32(EXMC + 0x00000088U) /*!< EXMC NAND/PC card common space timing configuration register */ +#define EXMC_NPATCFG2 REG32(EXMC + 0x0000008CU) /*!< EXMC NAND/PC card attribute space timing configuration register */ +#define EXMC_NECC2 REG32(EXMC + 0x00000094U) /*!< EXMC NAND ECC register */ + +#define EXMC_NPCTL3 REG32(EXMC + 0x000000A0U) /*!< EXMC NAND/PC card control register */ +#define EXMC_NPINTEN3 REG32(EXMC + 0x000000A4U) /*!< EXMC NAND/PC card interrupt enable register */ +#define EXMC_NPCTCFG3 REG32(EXMC + 0x000000A8U) /*!< EXMC NAND/PC card common space timing configuration register */ +#define EXMC_NPATCFG3 REG32(EXMC + 0x000000ACU) /*!< EXMC NAND/PC card attribute space timing configuration register */ +#define EXMC_PIOTCFG3 REG32(EXMC + 0x000000B0U) /*!< EXMC PC card I/O space timing configuration register */ /* SDRAM */ -#define EXMC_SDCTL0 REG32(EXMC + 0x140U) /*!< EXMC SDRAM control register */ -#define EXMC_SDTCFG0 REG32(EXMC + 0x148U) /*!< EXMC SDRAM timing configuration register register */ +#define EXMC_SDCTL0 REG32(EXMC + 0x000000140U) /*!< EXMC SDRAM control register */ +#define EXMC_SDTCFG0 REG32(EXMC + 0x000000148U) /*!< EXMC SDRAM timing configuration register register */ -#define EXMC_SDCTL1 REG32(EXMC + 0x144U) /*!< EXMC SDRAM control register */ -#define EXMC_SDTCFG1 REG32(EXMC + 0x14CU) /*!< EXMC SDRAM timing configuration register register */ +#define EXMC_SDCTL1 REG32(EXMC + 0x00000144U) /*!< EXMC SDRAM control register */ +#define EXMC_SDTCFG1 REG32(EXMC + 0x0000014CU) /*!< EXMC SDRAM timing configuration register register */ -#define EXMC_SDCMD REG32(EXMC + 0x150U) /*!< EXMC SDRAM command register */ -#define EXMC_SDARI REG32(EXMC + 0x154U) /*!< EXMC SDRAM auto-refresh interval register */ -#define EXMC_SDSTAT REG32(EXMC + 0x158U) /*!< EXMC SDRAM status register */ -#define EXMC_SDRSCTL REG32(EXMC + 0x180U) /*!< EXMC SDRAM read sample control register */ +#define EXMC_SDCMD REG32(EXMC + 0x00000150U) /*!< EXMC SDRAM command register */ +#define EXMC_SDARI REG32(EXMC + 0x00000154U) /*!< EXMC SDRAM auto-refresh interval register */ +#define EXMC_SDSTAT REG32(EXMC + 0x00000158U) /*!< EXMC SDRAM status register */ +#define EXMC_SDRSCTL REG32(EXMC + 0x00000180U) /*!< EXMC SDRAM read sample control register */ /* SQPI PSRAM */ -#define EXMC_SINIT REG32(EXMC + 0x310U) /*!< EXMC SPI initialization register */ -#define EXMC_SRCMD REG32(EXMC + 0x320U) /*!< EXMC SPI read command register */ -#define EXMC_SWCMD REG32(EXMC + 0x330U) /*!< EXMC SPI write command register */ -#define EXMC_SIDL REG32(EXMC + 0x340U) /*!< EXMC SPI ID low register */ -#define EXMC_SIDH REG32(EXMC + 0x350U) /*!< EXMC SPI ID high register */ +#define EXMC_SINIT REG32(EXMC + 0x00000310U) /*!< EXMC SPI initialization register */ +#define EXMC_SRCMD REG32(EXMC + 0x00000320U) /*!< EXMC SPI read command register */ +#define EXMC_SWCMD REG32(EXMC + 0x00000330U) /*!< EXMC SPI write command register */ +#define EXMC_SIDL REG32(EXMC + 0x00000340U) /*!< EXMC SPI ID low register */ +#define EXMC_SIDH REG32(EXMC + 0x00000350U) /*!< EXMC SPI ID high register */ /* bits definitions */ /* NOR/PSRAM */ @@ -250,234 +247,227 @@ OF SUCH DAMAGE. /* constants definitions */ /* EXMC NOR/SRAM timing initialize structure */ -typedef struct -{ +typedef struct { uint32_t asyn_access_mode; /*!< asynchronous access mode */ - + uint32_t syn_data_latency; /*!< configure the data latency */ - /*!< the range is EXMC_DATALAT_2_CLK to EXMC_DATALAT_17_CLK */ - + /*!< the range is EXMC_DATALAT_2_CLK to EXMC_DATALAT_17_CLK */ + uint32_t syn_clk_division; /*!< configure the clock divide ratio */ - /*!< the range is EXMC_SYN_CLOCK_RATIO_2_CLK to EXMC_SYN_CLOCK_RATIO_16_CLK */ - + /*!< the range is EXMC_SYN_CLOCK_RATIO_2_CLK to EXMC_SYN_CLOCK_RATIO_16_CLK */ + uint32_t bus_latency; /*!< configure the bus latency */ - /*!< the range is 1 to 16 HCLK */ - + /*!< the range is 1 to 16 HCLK */ + uint32_t asyn_data_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ - /*!< the range is 2 to 256 HCLK */ - + /*!< the range is 2 to 256 HCLK */ + uint32_t asyn_address_holdtime; /*!< configure the address hold time,asynchronous access mode valid */ - /*!< the range is 2 to 16 HCLK */ - + /*!< the range is 2 to 16 HCLK */ + uint32_t asyn_address_setuptime; /*!< configure the data setup time,asynchronous access mode valid */ - /*!< the range is 1 to 16 HCLK */ -}exmc_norsram_timing_parameter_struct; + /*!< the range is 1 to 16 HCLK */ +} exmc_norsram_timing_parameter_struct; /* EXMC NOR/SRAM initialize structure */ -typedef struct -{ +typedef struct { uint32_t norsram_region; /*!< select the region of EXMC NOR/SRAM bank */ - /*!< norsram_region: EXMC_BANK0_NORSRAM_REGIONx,x=0..3 */ - + /*!< norsram_region: EXMC_BANK0_NORSRAM_REGIONx,x=0..3 */ + uint32_t write_mode; /*!< the write mode, synchronous mode or asynchronous mode */ - /*!< write_mode: EXMC_ASYN_WRITE or EXMC_SYN_WRITE */ - + /*!< write_mode: EXMC_ASYN_WRITE or EXMC_SYN_WRITE */ + uint32_t extended_mode; /*!< enable or disable the extended mode */ - /*!< extended_mode: ENABLE or DISABLE */ - + /*!< extended_mode: ENABLE or DISABLE */ + uint32_t asyn_wait; /*!< enable or disable the asynchronous wait function */ - /*!< asyn_wait: ENABLE or DISABLE */ - + /*!< asyn_wait: ENABLE or DISABLE */ + uint32_t nwait_signal; /*!< enable or disable the NWAIT signal while in synchronous bust mode */ - /*!< nwait_signal: ENABLE or DISABLE */ - + /*!< nwait_signal: ENABLE or DISABLE */ + uint32_t memory_write; /*!< enable or disable the write operation */ - /*!< memory_write: ENABLE or DISABLE */ - + /*!< memory_write: ENABLE or DISABLE */ + uint32_t nwait_config; /*!< NWAIT signal configuration */ - /*!< nwait_config: EXMC_NWAIT_CONFIG_BEFORE or EXMC_NWAIT_CONFIG_DURING */ - + /*!< nwait_config: EXMC_NWAIT_CONFIG_BEFORE or EXMC_NWAIT_CONFIG_DURING */ + uint32_t wrap_burst_mode; /*!< enable or disable the wrap burst mode */ - /*!< wrap_burst_mode: ENABLE or DISABLE */ - + /*!< wrap_burst_mode: ENABLE or DISABLE */ + uint32_t nwait_polarity; /*!< specifies the polarity of NWAIT signal from memory */ - /*!< nwait_polarity: EXMC_NWAIT_POLARITY_LOW or EXMC_NWAIT_POLARITY_HIGH */ - + /*!< nwait_polarity: EXMC_NWAIT_POLARITY_LOW or EXMC_NWAIT_POLARITY_HIGH */ + uint32_t burst_mode; /*!< enable or disable the burst mode */ - /*!< burst_mode: ENABLE or DISABLE */ - + /*!< burst_mode: ENABLE or DISABLE */ + uint32_t databus_width; /*!< specifies the databus width of external memory */ - /*!< databus_width: EXMC_NOR_DATABUS_WIDTH_8B or EXMC_NOR_DATABUS_WIDTH_16B */ - + /*!< databus_width: EXMC_NOR_DATABUS_WIDTH_8B or EXMC_NOR_DATABUS_WIDTH_16B */ + uint32_t memory_type; /*!< specifies the type of external memory */ - /*!< memory_type: EXMC_MEMORY_TYPE_SRAM / EXMC_MEMORY_TYPE_PSRAM / EXMC_MEMORY_TYPE_NOR */ - + /*!< memory_type: EXMC_MEMORY_TYPE_SRAM / EXMC_MEMORY_TYPE_PSRAM / EXMC_MEMORY_TYPE_NOR */ + uint32_t address_data_mux; /*!< specifies whether the data bus and address bus are multiplexed */ - /*!< address_data_mux: ENABLE or DISABLE */ - - exmc_norsram_timing_parameter_struct* read_write_timing; /*!< timing parameters for read and write if the extendedmode is not used or the timing + /*!< address_data_mux: ENABLE or DISABLE */ + + exmc_norsram_timing_parameter_struct + *read_write_timing; /*!< timing parameters for read and write if the extendedmode is not used or the timing parameters for read if the extendedmode is used. */ - - exmc_norsram_timing_parameter_struct* write_timing; /*!< timing parameters for write when the extendedmode is used. */ -}exmc_norsram_parameter_struct; + + exmc_norsram_timing_parameter_struct *write_timing; /*!< timing parameters for write when the extendedmode is used. */ +} exmc_norsram_parameter_struct; /* EXMC NAND/PC card timing initialize struct */ -typedef struct -{ - uint32_t databus_hiztime; /*!< configure the dadtabus HiZ time for write operation */ - /*!< the range is 1 to 256 HCLK */ - +typedef struct { + uint32_t databus_hiztime; /*!< configure the databus HiZ time for write operation */ + /*!< the range is 1 to 256 HCLK */ + uint32_t holdtime; /*!< configure the address hold time(or the data hold time for write operation) */ - /*!< the range is 1 to 255 HCLK */ - + /*!< the range is 1 to 255 HCLK */ + uint32_t waittime; /*!< configure the minimum wait time */ - /*!< the range is 2 to 256 HCLK (+NWAIT active cycles) */ - + /*!< the range is 2 to 256 HCLK (+NWAIT active cycles) */ + uint32_t setuptime; /*!< configure the address setup time */ - /*!< the range is 1 to 256 HCLK */ -}exmc_nand_pccard_timing_parameter_struct; + /*!< the range is 1 to 256 HCLK */ +} exmc_nand_pccard_timing_parameter_struct; /* EXMC NAND initialize structure */ -typedef struct -{ +typedef struct { uint32_t nand_bank; /*!< select the bank of NAND */ - /*!< nand_bank: EXMC_BANK1_NAND or EXMC_BANK2_NAND */ - + /*!< nand_bank: EXMC_BANK1_NAND or EXMC_BANK2_NAND */ + uint32_t ecc_size; /*!< the page size for the ECC calculation */ - /*!< ecc_size: EXMC_ECC_SIZE_xBYTES,x=256,512,1024,2048,4096 */ - - uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ - /*!< atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 */ - + /*!< ecc_size: EXMC_ECC_SIZE_xBYTES,x=256,512,1024,2048,4096 */ + + uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ + /*!< atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 */ + uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ - /*!< ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 */ - + /*!< ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 */ + uint32_t ecc_logic; /*!< enable or disable the ECC calculation logic */ - /*!< ecc_logic: ENABLE or DISABLE */ - + /*!< ecc_logic: ENABLE or DISABLE */ + uint32_t databus_width; /*!< the NAND flash databus width */ - /*!< databus_width: EXMC_NAND_DATABUS_WIDTH_8B or EXMC_NAND_DATABUS_WIDTH_16B */ - - uint32_t wait_feature; /*!< enables or disables the wait feature */ - /*!< wait_feature: ENABLE or DISABLE */ - - exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash Common Space */ - - exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash Attribute Space */ -}exmc_nand_parameter_struct; + /*!< databus_width: EXMC_NAND_DATABUS_WIDTH_8B or EXMC_NAND_DATABUS_WIDTH_16B */ + + uint32_t wait_feature; /*!< enable or disable the wait feature */ + /*!< wait_feature: ENABLE or DISABLE */ + + exmc_nand_pccard_timing_parameter_struct *common_space_timing; /*!< the timing parameters for NAND flash common space */ + + exmc_nand_pccard_timing_parameter_struct *attribute_space_timing; /*!< the timing parameters for NAND flash attribute space */ +} exmc_nand_parameter_struct; /* EXMC PC card initialize structure */ -typedef struct -{ +typedef struct { uint32_t atr_latency; /*!< configure the latency of ALE low to RB low */ - /*!< atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 */ - + /*!< atr_latency: EXMC_ALE_RE_DELAY_x_HCLK,x=1..16 */ + uint32_t ctr_latency; /*!< configure the latency of CLE low to RB low */ - /*!< ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 */ - - uint32_t wait_feature; /*!< enables or disables the Wait feature */ - /*!< wait_feature: ENABLE or DISABLE */ - - exmc_nand_pccard_timing_parameter_struct* common_space_timing; /*!< the timing parameters for NAND flash Common Space */ - - exmc_nand_pccard_timing_parameter_struct* attribute_space_timing; /*!< the timing parameters for NAND flash Attribute Space */ - - exmc_nand_pccard_timing_parameter_struct* io_space_timing; /*!< the timing parameters for NAND flash IO Space */ -}exmc_pccard_parameter_struct; + /*!< ctr_latency: EXMC_CLE_RE_DELAY_x_HCLK,x=1..16 */ + + uint32_t wait_feature; /*!< enable or disable the wait feature */ + /*!< wait_feature: ENABLE or DISABLE */ + + exmc_nand_pccard_timing_parameter_struct *common_space_timing; /*!< the timing parameters for NAND flash common space */ + + exmc_nand_pccard_timing_parameter_struct *attribute_space_timing; /*!< the timing parameters for NAND flash attribute space */ + + exmc_nand_pccard_timing_parameter_struct *io_space_timing; /*!< the timing parameters for NAND flash IO Space */ +} exmc_pccard_parameter_struct; /* EXMC SDRAM timing initialize structure */ -typedef struct -{ +typedef struct { uint32_t row_to_column_delay; /*!< configure the row to column delay */ - /*!< the range is 1 to 16 cycles */ - + /*!< the range is 1 to 16 cycles */ + uint32_t row_precharge_delay; /*!< configure the row precharge delay */ - /*!< the range is 1 to 16 cycles */ - + /*!< the range is 1 to 16 cycles */ + uint32_t write_recovery_delay; /*!< configure the write recovery delay */ - /*!< the range is 1 to 16 cycles */ - - uint32_t auto_refresh_delay; /*!< configure the auto refresh delay */ - /*!< the range is 1 to 16 cycles */ - + /*!< the range is 1 to 16 cycles */ + + uint32_t auto_refresh_delay; /*!< configure the auto refresh delay */ + /*!< the range is 1 to 16 cycles */ + uint32_t row_address_select_delay; /*!< configure the row address select delay */ - /*!< the range is 1 to 16 cycles */ - + /*!< the range is 1 to 16 cycles */ + uint32_t exit_selfrefresh_delay; /*!< configure the exit self-refresh delay */ - /*!< the range is 1 to 16 cycles */ - + /*!< the range is 1 to 16 cycles */ + uint32_t load_mode_register_delay; /*!< configure the load mode register delay */ - /*!< the range is 1 to 16 cycles */ -}exmc_sdram_timing_parameter_struct; + /*!< the range is 1 to 16 cycles */ +} exmc_sdram_timing_parameter_struct; /* EXMC SDRAM initialize structure */ -typedef struct -{ +typedef struct { uint32_t sdram_device; /*!< device of SDRAM */ - /*!< sdram_device: EXMC_SDRAM_DEVICE0 or EXMC_SDRAM_DEVICE1 */ - + /*!< sdram_device: EXMC_SDRAM_DEVICE0 or EXMC_SDRAM_DEVICE1 */ + uint32_t pipeline_read_delay; /*!< the delay for reading data after CAS latency in HCLK clock cycles */ - /*!< pipeline_read_delay: EXMC_PIPELINE_DELAY_x_HCLK, x=0..2 */ - - uint32_t brust_read_switch; /*!< enable or disable the burst read */ - /*!< brust_read_switch: ENABLE or DISABLE */ - + /*!< pipeline_read_delay: EXMC_PIPELINE_DELAY_x_HCLK, x=0..2 */ + + uint32_t burst_read_switch; /*!< enable or disable the burst read */ + /*!< burst_read_switch: ENABLE or DISABLE */ + uint32_t sdclock_config; /*!< the SDCLK memory clock for both SDRAM banks */ - /*!< sdclock_config: EXMC_SDCLK_DISABLE,EXMC_SDCLK_PERIODS_2_HCLK,EXMC_SDCLK_PERIODS_3_HCLK */ - + /*!< sdclock_config: EXMC_SDCLK_DISABLE,EXMC_SDCLK_PERIODS_2_HCLK,EXMC_SDCLK_PERIODS_3_HCLK */ + uint32_t write_protection; /*!< enable or disable SDRAM bank write protection function */ - /*!< write_protection: ENABLE or DISABLE */ - + /*!< write_protection: ENABLE or DISABLE */ + uint32_t cas_latency; /*!< configure the SDRAM CAS latency */ - /*!< cas_latency: EXMC_CAS_LATENCY_x_SDCLK, x=1..3 */ - + /*!< cas_latency: EXMC_CAS_LATENCY_x_SDCLK, x=1..3 */ + uint32_t internal_bank_number; /*!< the number internal banks */ - /*!< internal_bank_number: EXMC_SDRAM_2_INTER_BANK or EXMC_SDRAM_4_INTER_BANK */ - + /*!< internal_bank_number: EXMC_SDRAM_2_INTER_BANK or EXMC_SDRAM_4_INTER_BANK */ + uint32_t data_width; /*!< the databus width of SDRAM memory */ - /*!< data_width: EXMC_SDRAM_DATABUS_WIDTH_8B,EXMC_SDRAM_DATABUS_WIDTH_16B,EXMC_SDRAM_DATABUS_WIDTH_32B */ - + /*!< data_width: EXMC_SDRAM_DATABUS_WIDTH_8B,EXMC_SDRAM_DATABUS_WIDTH_16B,EXMC_SDRAM_DATABUS_WIDTH_32B */ + uint32_t row_address_width; /*!< the bit width of a row address */ - /*!< row_address_width: EXMC_SDRAM_ROW_ADDRESS_x, x=11..13 */ - + /*!< row_address_width: EXMC_SDRAM_ROW_ADDRESS_x, x=11..13 */ + uint32_t column_address_width; /*!< the bit width of a column address */ - /*!< column_address_width: EXMC_SDRAM_COW_ADDRESS_x, x=8..11 */ - - exmc_sdram_timing_parameter_struct* timing; /*!< the timing parameters for write and read SDRAM */ -}exmc_sdram_parameter_struct; + /*!< column_address_width: EXMC_SDRAM_COW_ADDRESS_x, x=8..11 */ + + exmc_sdram_timing_parameter_struct *timing; /*!< the timing parameters for write and read SDRAM */ +} exmc_sdram_parameter_struct; /* EXMC SDRAM command initialize structure */ -typedef struct -{ +typedef struct { uint32_t mode_register_content; /*!< the SDRAM mode register content */ - /*!< mode_register_content: */ - + /*!< mode_register_content: */ + uint32_t auto_refresh_number; /*!< the number of successive auto-refresh cycles will be send when CMD = 011 */ - /*!< auto_refresh_number: EXMC_SDRAM_AUTO_REFLESH_x_SDCLK, x=1..15 */ - + /*!< auto_refresh_number: EXMC_SDRAM_AUTO_REFLESH_x_SDCLK, x=1..15 */ + uint32_t bank_select; /*!< the bank which command will be sent to */ - /*!< bank_select: EXMC_SDRAM_DEVICE0_SELECT, EXMC_SDRAM_DEVICE1_SELECT, EXMC_SDRAM_DEVICE0_1_SELECT */ - + /*!< bank_select: EXMC_SDRAM_DEVICE0_SELECT, EXMC_SDRAM_DEVICE1_SELECT, EXMC_SDRAM_DEVICE0_1_SELECT */ + uint32_t command; /*!< the commands that will be sent to SDRAM */ - /*!< command: EXMC_SDRAM_NORMAL_OPERATION, EXMC_SDRAM_CLOCK_ENABLE, EXMC_SDRAM_PRECHARGE_ALL, - EXMC_SDRAM_AUTO_REFRESH, EXMC_SDRAM_LOAD_MODE_REGISTER, EXMC_SDRAM_SELF_REFRESH, - EXMC_SDRAM_POWERDOWN_ENTRY */ -}exmc_sdram_command_parameter_struct; + /*!< command: EXMC_SDRAM_NORMAL_OPERATION, EXMC_SDRAM_CLOCK_ENABLE, EXMC_SDRAM_PRECHARGE_ALL, + EXMC_SDRAM_AUTO_REFRESH, EXMC_SDRAM_LOAD_MODE_REGISTER, EXMC_SDRAM_SELF_REFRESH, + EXMC_SDRAM_POWERDOWN_ENTRY */ +} exmc_sdram_command_parameter_struct; /* EXMC SQPISRAM initialize structure */ -typedef struct{ +typedef struct { uint32_t sample_polarity; /*!< read data sample polarity */ - /*!< sample_polarity: EXMC_SDRAM_SAMPLE_RISING_EDGE,EXMC_SDRAM_SAMPLE_FALLING_EDGE */ - + /*!< sample_polarity: EXMC_SDRAM_SAMPLE_RISING_EDGE,EXMC_SDRAM_SAMPLE_FALLING_EDGE */ + uint32_t id_length; /*!< SPI PSRAM ID length */ - /*!< id_length: EXMC_SQPIPSRAM_ID_LENGTH_xB,x=8,16,32,64 */ - + /*!< id_length: EXMC_SQPIPSRAM_ID_LENGTH_xB,x=8,16,32,64 */ + uint32_t address_bits; /*!< bit number of SPI PSRAM address phase */ - /*!< address_bits: EXMC_SQPIPSRAM_ADDR_LENGTH_xB,x=1..26 */ - + /*!< address_bits: EXMC_SQPIPSRAM_ADDR_LENGTH_xB,x=1..26 */ + uint32_t command_bits; /*!< bit number of SPI PSRAM command phase */ - /*!< command_bits: EXMC_SQPIPSRAM_COMMAND_LENGTH_xB,x=4,8,16 */ -}exmc_sqpipsram_parameter_struct; + /*!< command_bits: EXMC_SQPIPSRAM_COMMAND_LENGTH_xB,x=4,8,16 */ +} exmc_sqpipsram_parameter_struct; /* EXMC NOR/SRAM bank region definition */ #define EXMC_BANK0_NORSRAM_REGION0 ((uint32_t)0x00000000U) /*!< bank0 NOR/SRAM region0 */ @@ -548,21 +538,23 @@ typedef struct{ /* synchronous clock divide ratio */ #define SNTCFG_CKDIV(regval) (BITS(20,23) & ((uint32_t)(regval) << 20)) -#define EXMC_SYN_CLOCK_RATIO_2_CLK SNTCFG_CKDIV(1) /*!< EXMC_CLK = 2*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_3_CLK SNTCFG_CKDIV(2) /*!< EXMC_CLK = 3*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_4_CLK SNTCFG_CKDIV(3) /*!< EXMC_CLK = 4*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_5_CLK SNTCFG_CKDIV(4) /*!< EXMC_CLK = 5*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_6_CLK SNTCFG_CKDIV(5) /*!< EXMC_CLK = 6*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_7_CLK SNTCFG_CKDIV(6) /*!< EXMC_CLK = 7*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_8_CLK SNTCFG_CKDIV(7) /*!< EXMC_CLK = 8*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_9_CLK SNTCFG_CKDIV(8) /*!< EXMC_CLK = 9*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_10_CLK SNTCFG_CKDIV(9) /*!< EXMC_CLK = 10*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_11_CLK SNTCFG_CKDIV(10) /*!< EXMC_CLK = 11*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_12_CLK SNTCFG_CKDIV(11) /*!< EXMC_CLK = 12*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_13_CLK SNTCFG_CKDIV(12) /*!< EXMC_CLK = 13*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_14_CLK SNTCFG_CKDIV(13) /*!< EXMC_CLK = 14*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_15_CLK SNTCFG_CKDIV(14) /*!< EXMC_CLK = 15*HCLK */ -#define EXMC_SYN_CLOCK_RATIO_16_CLK SNTCFG_CKDIV(15) /*!< EXMC_CLK = 16*HCLK */ +#define EXMC_SYN_CLOCK_RATIO_DISABLE SNTCFG_CKDIV(0) /*!< EXMC_CLK disable */ +#define EXMC_SYN_CLOCK_RATIO_2_CLK SNTCFG_CKDIV(1) /*!< EXMC_CLK = HCLK/2 */ +#define EXMC_SYN_CLOCK_RATIO_3_CLK SNTCFG_CKDIV(2) /*!< EXMC_CLK = HCLK/3 */ +#define EXMC_SYN_CLOCK_RATIO_4_CLK SNTCFG_CKDIV(3) /*!< EXMC_CLK = HCLK/4 */ +#define EXMC_SYN_CLOCK_RATIO_5_CLK SNTCFG_CKDIV(4) /*!< EXMC_CLK = HCLK/5 */ +#define EXMC_SYN_CLOCK_RATIO_6_CLK SNTCFG_CKDIV(5) /*!< EXMC_CLK = HCLK/6 */ +#define EXMC_SYN_CLOCK_RATIO_7_CLK SNTCFG_CKDIV(6) /*!< EXMC_CLK = HCLK/7 */ +#define EXMC_SYN_CLOCK_RATIO_8_CLK SNTCFG_CKDIV(7) /*!< EXMC_CLK = HCLK/8 */ +#define EXMC_SYN_CLOCK_RATIO_9_CLK SNTCFG_CKDIV(8) /*!< EXMC_CLK = HCLK/9 */ +#define EXMC_SYN_CLOCK_RATIO_10_CLK SNTCFG_CKDIV(9) /*!< EXMC_CLK = HCLK/10 */ +#define EXMC_SYN_CLOCK_RATIO_11_CLK SNTCFG_CKDIV(10) /*!< EXMC_CLK = HCLK/11 */ +#define EXMC_SYN_CLOCK_RATIO_12_CLK SNTCFG_CKDIV(11) /*!< EXMC_CLK = HCLK/12 */ +#define EXMC_SYN_CLOCK_RATIO_13_CLK SNTCFG_CKDIV(12) /*!< EXMC_CLK = HCLK/13 */ +#define EXMC_SYN_CLOCK_RATIO_14_CLK SNTCFG_CKDIV(13) /*!< EXMC_CLK = HCLK/14 */ +#define EXMC_SYN_CLOCK_RATIO_15_CLK SNTCFG_CKDIV(14) /*!< EXMC_CLK = HCLK/15 */ +#define EXMC_SYN_CLOCK_RATIO_16_CLK SNTCFG_CKDIV(15) /*!< EXMC_CLK = HCLK/16 */ + /* EXMC NOR/SRAM write mode */ #define EXMC_ASYN_WRITE ((uint32_t)0x00000000U) /*!< asynchronous write mode */ #define EXMC_SYN_WRITE EXMC_SNCTL_SYNCWR /*!< synchronous write mode */ @@ -578,50 +570,50 @@ typedef struct{ /* NAND/PC card */ /* ECC size */ #define NPCTL_ECCSZ(regval) (BITS(17,19) & ((uint32_t)(regval) << 17)) -#define EXMC_ECC_SIZE_256BYTES NPCTL_ECCSZ(0) /* 256 bytes */ -#define EXMC_ECC_SIZE_512BYTES NPCTL_ECCSZ(1) /* 512 bytes */ -#define EXMC_ECC_SIZE_1024BYTES NPCTL_ECCSZ(2) /* 1024 bytes */ -#define EXMC_ECC_SIZE_2048BYTES NPCTL_ECCSZ(3) /* 2048 bytes */ -#define EXMC_ECC_SIZE_4096BYTES NPCTL_ECCSZ(4) /* 4096 bytes */ -#define EXMC_ECC_SIZE_8192BYTES NPCTL_ECCSZ(5) /* 8192 bytes */ +#define EXMC_ECC_SIZE_256BYTES NPCTL_ECCSZ(0) /*!< ECC size is 256 bytes */ +#define EXMC_ECC_SIZE_512BYTES NPCTL_ECCSZ(1) /*!< ECC size is 512 bytes */ +#define EXMC_ECC_SIZE_1024BYTES NPCTL_ECCSZ(2) /*!< ECC size is 1024 bytes */ +#define EXMC_ECC_SIZE_2048BYTES NPCTL_ECCSZ(3) /*!< ECC size is 2048 bytes */ +#define EXMC_ECC_SIZE_4096BYTES NPCTL_ECCSZ(4) /*!< ECC size is 4096 bytes */ +#define EXMC_ECC_SIZE_8192BYTES NPCTL_ECCSZ(5) /*!< ECC size is 8192 bytes */ /* ALE to RE delay */ #define NPCTL_ATR(regval) (BITS(13,16) & ((uint32_t)(regval) << 13)) -#define EXMC_ALE_RE_DELAY_1_HCLK NPCTL_ATR(0) /* ALE to RE delay = 1*HCLK */ -#define EXMC_ALE_RE_DELAY_2_HCLK NPCTL_ATR(1) /* ALE to RE delay = 2*HCLK */ -#define EXMC_ALE_RE_DELAY_3_HCLK NPCTL_ATR(2) /* ALE to RE delay = 3*HCLK */ -#define EXMC_ALE_RE_DELAY_4_HCLK NPCTL_ATR(3) /* ALE to RE delay = 4*HCLK */ -#define EXMC_ALE_RE_DELAY_5_HCLK NPCTL_ATR(4) /* ALE to RE delay = 5*HCLK */ -#define EXMC_ALE_RE_DELAY_6_HCLK NPCTL_ATR(5) /* ALE to RE delay = 6*HCLK */ -#define EXMC_ALE_RE_DELAY_7_HCLK NPCTL_ATR(6) /* ALE to RE delay = 7*HCLK */ -#define EXMC_ALE_RE_DELAY_8_HCLK NPCTL_ATR(7) /* ALE to RE delay = 8*HCLK */ -#define EXMC_ALE_RE_DELAY_9_HCLK NPCTL_ATR(8) /* ALE to RE delay = 9*HCLK */ -#define EXMC_ALE_RE_DELAY_10_HCLK NPCTL_ATR(9) /* ALE to RE delay = 10*HCLK */ -#define EXMC_ALE_RE_DELAY_11_HCLK NPCTL_ATR(10) /* ALE to RE delay = 11*HCLK */ -#define EXMC_ALE_RE_DELAY_12_HCLK NPCTL_ATR(11) /* ALE to RE delay = 12*HCLK */ -#define EXMC_ALE_RE_DELAY_13_HCLK NPCTL_ATR(12) /* ALE to RE delay = 13*HCLK */ -#define EXMC_ALE_RE_DELAY_14_HCLK NPCTL_ATR(13) /* ALE to RE delay = 14*HCLK */ -#define EXMC_ALE_RE_DELAY_15_HCLK NPCTL_ATR(14) /* ALE to RE delay = 15*HCLK */ -#define EXMC_ALE_RE_DELAY_16_HCLK NPCTL_ATR(15) /* ALE to RE delay = 16*HCLK */ +#define EXMC_ALE_RE_DELAY_1_HCLK NPCTL_ATR(0) /*!< ALE to RE delay = 1*HCLK */ +#define EXMC_ALE_RE_DELAY_2_HCLK NPCTL_ATR(1) /*!< ALE to RE delay = 2*HCLK */ +#define EXMC_ALE_RE_DELAY_3_HCLK NPCTL_ATR(2) /*!< ALE to RE delay = 3*HCLK */ +#define EXMC_ALE_RE_DELAY_4_HCLK NPCTL_ATR(3) /*!< ALE to RE delay = 4*HCLK */ +#define EXMC_ALE_RE_DELAY_5_HCLK NPCTL_ATR(4) /*!< ALE to RE delay = 5*HCLK */ +#define EXMC_ALE_RE_DELAY_6_HCLK NPCTL_ATR(5) /*!< ALE to RE delay = 6*HCLK */ +#define EXMC_ALE_RE_DELAY_7_HCLK NPCTL_ATR(6) /*!< ALE to RE delay = 7*HCLK */ +#define EXMC_ALE_RE_DELAY_8_HCLK NPCTL_ATR(7) /*!< ALE to RE delay = 8*HCLK */ +#define EXMC_ALE_RE_DELAY_9_HCLK NPCTL_ATR(8) /*!< ALE to RE delay = 9*HCLK */ +#define EXMC_ALE_RE_DELAY_10_HCLK NPCTL_ATR(9) /*!< ALE to RE delay = 10*HCLK */ +#define EXMC_ALE_RE_DELAY_11_HCLK NPCTL_ATR(10) /*!< ALE to RE delay = 11*HCLK */ +#define EXMC_ALE_RE_DELAY_12_HCLK NPCTL_ATR(11) /*!< ALE to RE delay = 12*HCLK */ +#define EXMC_ALE_RE_DELAY_13_HCLK NPCTL_ATR(12) /*!< ALE to RE delay = 13*HCLK */ +#define EXMC_ALE_RE_DELAY_14_HCLK NPCTL_ATR(13) /*!< ALE to RE delay = 14*HCLK */ +#define EXMC_ALE_RE_DELAY_15_HCLK NPCTL_ATR(14) /*!< ALE to RE delay = 15*HCLK */ +#define EXMC_ALE_RE_DELAY_16_HCLK NPCTL_ATR(15) /*!< ALE to RE delay = 16*HCLK */ /* CLE to RE delay */ #define NPCTL_CTR(regval) (BITS(9,12) & ((uint32_t)(regval) << 9)) -#define EXMC_CLE_RE_DELAY_1_HCLK NPCTL_CTR(0) /* CLE to RE delay = 1*HCLK */ -#define EXMC_CLE_RE_DELAY_2_HCLK NPCTL_CTR(1) /* CLE to RE delay = 2*HCLK */ -#define EXMC_CLE_RE_DELAY_3_HCLK NPCTL_CTR(2) /* CLE to RE delay = 3*HCLK */ -#define EXMC_CLE_RE_DELAY_4_HCLK NPCTL_CTR(3) /* CLE to RE delay = 4*HCLK */ -#define EXMC_CLE_RE_DELAY_5_HCLK NPCTL_CTR(4) /* CLE to RE delay = 5*HCLK */ -#define EXMC_CLE_RE_DELAY_6_HCLK NPCTL_CTR(5) /* CLE to RE delay = 6*HCLK */ -#define EXMC_CLE_RE_DELAY_7_HCLK NPCTL_CTR(6) /* CLE to RE delay = 7*HCLK */ -#define EXMC_CLE_RE_DELAY_8_HCLK NPCTL_CTR(7) /* CLE to RE delay = 8*HCLK */ -#define EXMC_CLE_RE_DELAY_9_HCLK NPCTL_CTR(8) /* CLE to RE delay = 9*HCLK */ -#define EXMC_CLE_RE_DELAY_10_HCLK NPCTL_CTR(9) /* CLE to RE delay = 10*HCLK */ -#define EXMC_CLE_RE_DELAY_11_HCLK NPCTL_CTR(10) /* CLE to RE delay = 11*HCLK */ -#define EXMC_CLE_RE_DELAY_12_HCLK NPCTL_CTR(11) /* CLE to RE delay = 12*HCLK */ -#define EXMC_CLE_RE_DELAY_13_HCLK NPCTL_CTR(12) /* CLE to RE delay = 13*HCLK */ -#define EXMC_CLE_RE_DELAY_14_HCLK NPCTL_CTR(13) /* CLE to RE delay = 14*HCLK */ -#define EXMC_CLE_RE_DELAY_15_HCLK NPCTL_CTR(14) /* CLE to RE delay = 15*HCLK */ -#define EXMC_CLE_RE_DELAY_16_HCLK NPCTL_CTR(15) /* CLE to RE delay = 16*HCLK */ +#define EXMC_CLE_RE_DELAY_1_HCLK NPCTL_CTR(0) /*!< CLE to RE delay = 1*HCLK */ +#define EXMC_CLE_RE_DELAY_2_HCLK NPCTL_CTR(1) /*!< CLE to RE delay = 2*HCLK */ +#define EXMC_CLE_RE_DELAY_3_HCLK NPCTL_CTR(2) /*!< CLE to RE delay = 3*HCLK */ +#define EXMC_CLE_RE_DELAY_4_HCLK NPCTL_CTR(3) /*!< CLE to RE delay = 4*HCLK */ +#define EXMC_CLE_RE_DELAY_5_HCLK NPCTL_CTR(4) /*!< CLE to RE delay = 5*HCLK */ +#define EXMC_CLE_RE_DELAY_6_HCLK NPCTL_CTR(5) /*!< CLE to RE delay = 6*HCLK */ +#define EXMC_CLE_RE_DELAY_7_HCLK NPCTL_CTR(6) /*!< CLE to RE delay = 7*HCLK */ +#define EXMC_CLE_RE_DELAY_8_HCLK NPCTL_CTR(7) /*!< CLE to RE delay = 8*HCLK */ +#define EXMC_CLE_RE_DELAY_9_HCLK NPCTL_CTR(8) /*!< CLE to RE delay = 9*HCLK */ +#define EXMC_CLE_RE_DELAY_10_HCLK NPCTL_CTR(9) /*!< CLE to RE delay = 10*HCLK */ +#define EXMC_CLE_RE_DELAY_11_HCLK NPCTL_CTR(10) /*!< CLE to RE delay = 11*HCLK */ +#define EXMC_CLE_RE_DELAY_12_HCLK NPCTL_CTR(11) /*!< CLE to RE delay = 12*HCLK */ +#define EXMC_CLE_RE_DELAY_13_HCLK NPCTL_CTR(12) /*!< CLE to RE delay = 13*HCLK */ +#define EXMC_CLE_RE_DELAY_14_HCLK NPCTL_CTR(13) /*!< CLE to RE delay = 14*HCLK */ +#define EXMC_CLE_RE_DELAY_15_HCLK NPCTL_CTR(14) /*!< CLE to RE delay = 15*HCLK */ +#define EXMC_CLE_RE_DELAY_16_HCLK NPCTL_CTR(15) /*!< CLE to RE delay = 16*HCLK */ /* NAND bank memory data bus width */ #define NPCTL_NDW(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) @@ -713,7 +705,7 @@ typedef struct{ #define EXMC_SDRAM_14_DELAY_CELL SDRSCTL_SDSC(14) /*!< select the clock after 14 delay cell */ #define EXMC_SDRAM_15_DELAY_CELL SDRSCTL_SDSC(15) /*!< select the clock after 15 delay cell */ - /* EXMC SDRAM internal banks */ +/* EXMC SDRAM internal banks */ #define EXMC_SDRAM_2_INTER_BANK ((uint32_t)0x00000000U) /*!< 2 internal banks */ #define EXMC_SDRAM_4_INTER_BANK EXMC_SDCTL_NBK /*!< 4 internal banks */ @@ -821,57 +813,62 @@ typedef struct{ #define EXMC_SDRAM_INT_FLAG_REFRESH EXMC_SDARI_REIE /*!< interrupt refresh error enable */ /* function declarations */ -/* function configuration */ +/* NOR/SRAM */ /* deinitialize EXMC NOR/SRAM region */ void exmc_norsram_deinit(uint32_t exmc_norsram_region); -/* exmc_norsram_parameter_struct parameter initialize */ -void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); +/* initialize exmc_norsram_parameter_struct with the default values */ +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct *exmc_norsram_init_struct); /* initialize EXMC NOR/SRAM region */ -void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct); -/* EXMC NOR/SRAM bank enable */ +void exmc_norsram_init(exmc_norsram_parameter_struct *exmc_norsram_init_struct); +/* enable EXMC NOR/SRAM bank region */ void exmc_norsram_enable(uint32_t exmc_norsram_region); -/* EXMC NOR/SRAM bank disable */ +/* disable EXMC NOR/SRAM bank region */ void exmc_norsram_disable(uint32_t exmc_norsram_region); +/* NAND */ /* deinitialize EXMC NAND bank */ void exmc_nand_deinit(uint32_t exmc_nand_bank); -/* exmc_nand_init_struct parameter initialize */ -void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct); +/* initialize exmc_nand_parameter_struct with the default values */ +void exmc_nand_struct_para_init(exmc_nand_parameter_struct *exmc_nand_init_struct); /* initialize EXMC NAND bank */ -void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct); -/* EXMC NAND bank enable */ +void exmc_nand_init(exmc_nand_parameter_struct *exmc_nand_init_struct); +/* enable EXMC NAND bank */ void exmc_nand_enable(uint32_t exmc_nand_bank); -/* EXMC NAND bank disable */ +/* disable EXMC NAND bank */ void exmc_nand_disable(uint32_t exmc_nand_bank); /* enable or disable the EXMC NAND ECC function */ void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue); /* get the EXMC ECC value */ uint32_t exmc_ecc_get(uint32_t exmc_nand_bank); +/* PC card */ /* deinitialize EXMC PC card bank */ void exmc_pccard_deinit(void); +/* initialize exmc_pccard_parameter_struct with the default values */ +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct *exmc_pccard_init_struct); /* initialize EXMC PC card bank */ -void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); -/* exmc_pccard_parameter_struct parameter initialize */ -void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct); -/* EXMC PC card bank enable */ +void exmc_pccard_init(exmc_pccard_parameter_struct *exmc_pccard_init_struct); +/* enable EXMC PC card bank */ void exmc_pccard_enable(void); -/* EXMC PC card bank disable */ +/* disable EXMC PC card bank */ void exmc_pccard_disable(void); +/* SDRAM */ /* deinitialize EXMC SDRAM device */ void exmc_sdram_deinit(uint32_t exmc_sdram_device); +/* initialize exmc_sdram_init_struct with the default values */ +void exmc_sdram_struct_para_init(exmc_sdram_parameter_struct *exmc_sdram_init_struct); /* initialize EXMC SDRAM device */ -void exmc_sdram_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct); -/* exmc_sdram_parameter_struct parameter initialize */ -void exmc_sdram_parameter_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct); +void exmc_sdram_init(exmc_sdram_parameter_struct *exmc_sdram_init_struct); +/* initialize exmc_sdram_command_parameter_struct with the default values */ +void exmc_sdram_struct_command_para_init(exmc_sdram_command_parameter_struct *exmc_sdram_command_init_struct); /* configure the SDRAM memory command */ -void exmc_sdram_command_config(exmc_sdram_command_parameter_struct* exmc_sdram_command_init_struct); +void exmc_sdram_command_config(exmc_sdram_command_parameter_struct *exmc_sdram_command_init_struct); /* set auto-refresh interval */ void exmc_sdram_refresh_count_set(uint32_t exmc_count); /* set the number of successive auto-refresh command */ void exmc_sdram_autorefresh_number_set(uint32_t exmc_number); -/* config the write protection function */ +/* configure the write protection function */ void exmc_sdram_write_protection_config(uint32_t exmc_sdram_device, ControlStatus newvalue); /* get the status of SDRAM device0 or device1 */ uint32_t exmc_sdram_bankstatus_get(uint32_t exmc_sdram_device); @@ -882,12 +879,13 @@ void exmc_sdram_readsample_enable(void); /* disable read sample */ void exmc_sdram_readsample_disable(void); +/* SQPIPSARM */ /* deinitialize EXMC SQPIPSRAM */ void exmc_sqpipsram_deinit(void); +/* initialize exmc_sqpipsram_init_struct with the default values */ +void exmc_sqpipsram_struct_para_init(exmc_sqpipsram_parameter_struct *exmc_sqpipsram_init_struct); /* initialize EXMC SQPIPSRAM */ -void exmc_sqpipsram_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct); -/* exmc_sqpipsram_parameter_struct parameter initialize */ -void exmc_sqpipsram_parameter_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct); +void exmc_sqpipsram_init(exmc_sqpipsram_parameter_struct *exmc_sqpipsram_init_struct); /* set the read command */ void exmc_sqpipsram_read_command_set(uint32_t read_command_mode, uint32_t read_wait_cycle, uint32_t read_command_code); /* set the write command */ @@ -904,17 +902,17 @@ uint32_t exmc_sqpipsram_high_id_get(void); FlagStatus exmc_sqpipsram_send_command_state_get(uint32_t send_command_flag); /* interrupt & flag functions */ -/* check EXMC flag is set or not */ +/* get EXMC flag status */ FlagStatus exmc_flag_get(uint32_t bank, uint32_t flag); -/* clear EXMC flag */ +/* clear EXMC flag status */ void exmc_flag_clear(uint32_t bank, uint32_t flag); -/* check EXMC flag is set or not */ -FlagStatus exmc_interrupt_flag_get(uint32_t bank, uint32_t interrupt_source); -/* clear EXMC flag */ -void exmc_interrupt_flag_clear(uint32_t bank, uint32_t interrupt_source); /* enable EXMC interrupt */ -void exmc_interrupt_enable(uint32_t bank, uint32_t interrupt_source); +void exmc_interrupt_enable(uint32_t bank, uint32_t interrupt); /* disable EXMC interrupt */ -void exmc_interrupt_disable(uint32_t bank, uint32_t interrupt_source); +void exmc_interrupt_disable(uint32_t bank, uint32_t interrupt); +/* get EXMC interrupt flag */ +FlagStatus exmc_interrupt_flag_get(uint32_t bank, uint32_t interrupt); +/* clear EXMC interrupt flag */ +void exmc_interrupt_flag_clear(uint32_t bank, uint32_t interrupt); #endif /* GD32F20X_EXMC_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_exti.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_exti.h index 34ff3974..79c4f43b 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_exti.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_exti.h @@ -2,36 +2,33 @@ \file gd32f20x_exti.h \brief definitions for the EXTI - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -44,12 +41,12 @@ OF SUCH DAMAGE. #define EXTI EXTI_BASE /* registers definitions */ -#define EXTI_INTEN REG32(EXTI + 0x00U) /*!< interrupt enable register */ -#define EXTI_EVEN REG32(EXTI + 0x04U) /*!< event enable register */ -#define EXTI_RTEN REG32(EXTI + 0x08U) /*!< rising edge trigger enable register */ -#define EXTI_FTEN REG32(EXTI + 0x0CU) /*!< falling trigger enable register */ -#define EXTI_SWIEV REG32(EXTI + 0x10U) /*!< software interrupt event register */ -#define EXTI_PD REG32(EXTI + 0x14U) /*!< pending register */ +#define EXTI_INTEN REG32(EXTI + 0x00000000U) /*!< interrupt enable register */ +#define EXTI_EVEN REG32(EXTI + 0x00000004U) /*!< event enable register */ +#define EXTI_RTEN REG32(EXTI + 0x00000008U) /*!< rising edge trigger enable register */ +#define EXTI_FTEN REG32(EXTI + 0x0000000CU) /*!< falling edge trigger enable register */ +#define EXTI_SWIEV REG32(EXTI + 0x00000010U) /*!< software interrupt event register */ +#define EXTI_PD REG32(EXTI + 0x00000014U) /*!< pending register */ /* bits definitions */ /* EXTI_INTEN */ @@ -163,31 +160,30 @@ OF SUCH DAMAGE. #define EXTI_SWIEV_SWIEV19 BIT(19) /*!< software interrupt/event request from line 19 */ /* EXTI_PD */ -#define EXTI_PD_PD0 BIT(0) /*!< interrupt/event pending status from line 0 */ -#define EXTI_PD_PD1 BIT(1) /*!< interrupt/event pending status from line 1 */ -#define EXTI_PD_PD2 BIT(2) /*!< interrupt/event pending status from line 2 */ -#define EXTI_PD_PD3 BIT(3) /*!< interrupt/event pending status from line 3 */ -#define EXTI_PD_PD4 BIT(4) /*!< interrupt/event pending status from line 4 */ -#define EXTI_PD_PD5 BIT(5) /*!< interrupt/event pending status from line 5 */ -#define EXTI_PD_PD6 BIT(6) /*!< interrupt/event pending status from line 6 */ -#define EXTI_PD_PD7 BIT(7) /*!< interrupt/event pending status from line 7 */ -#define EXTI_PD_PD8 BIT(8) /*!< interrupt/event pending status from line 8 */ -#define EXTI_PD_PD9 BIT(9) /*!< interrupt/event pending status from line 9 */ -#define EXTI_PD_PD10 BIT(10) /*!< interrupt/event pending status from line 10 */ -#define EXTI_PD_PD11 BIT(11) /*!< interrupt/event pending status from line 11 */ -#define EXTI_PD_PD12 BIT(12) /*!< interrupt/event pending status from line 12 */ -#define EXTI_PD_PD13 BIT(13) /*!< interrupt/event pending status from line 13 */ -#define EXTI_PD_PD14 BIT(14) /*!< interrupt/event pending status from line 14 */ -#define EXTI_PD_PD15 BIT(15) /*!< interrupt/event pending status from line 15 */ -#define EXTI_PD_PD16 BIT(16) /*!< interrupt/event pending status from line 16 */ -#define EXTI_PD_PD17 BIT(17) /*!< interrupt/event pending status from line 17 */ -#define EXTI_PD_PD18 BIT(18) /*!< interrupt/event pending status from line 18 */ -#define EXTI_PD_PD19 BIT(19) /*!< interrupt/event pending status from line 19 */ +#define EXTI_PD_PD0 BIT(0) /*!< interrupt pending status from line 0 */ +#define EXTI_PD_PD1 BIT(1) /*!< interrupt pending status from line 1 */ +#define EXTI_PD_PD2 BIT(2) /*!< interrupt pending status from line 2 */ +#define EXTI_PD_PD3 BIT(3) /*!< interrupt pending status from line 3 */ +#define EXTI_PD_PD4 BIT(4) /*!< interrupt pending status from line 4 */ +#define EXTI_PD_PD5 BIT(5) /*!< interrupt pending status from line 5 */ +#define EXTI_PD_PD6 BIT(6) /*!< interrupt pending status from line 6 */ +#define EXTI_PD_PD7 BIT(7) /*!< interrupt pending status from line 7 */ +#define EXTI_PD_PD8 BIT(8) /*!< interrupt pending status from line 8 */ +#define EXTI_PD_PD9 BIT(9) /*!< interrupt pending status from line 9 */ +#define EXTI_PD_PD10 BIT(10) /*!< interrupt pending status from line 10 */ +#define EXTI_PD_PD11 BIT(11) /*!< interrupt pending status from line 11 */ +#define EXTI_PD_PD12 BIT(12) /*!< interrupt pending status from line 12 */ +#define EXTI_PD_PD13 BIT(13) /*!< interrupt pending status from line 13 */ +#define EXTI_PD_PD14 BIT(14) /*!< interrupt pending status from line 14 */ +#define EXTI_PD_PD15 BIT(15) /*!< interrupt pending status from line 15 */ +#define EXTI_PD_PD16 BIT(16) /*!< interrupt pending status from line 16 */ +#define EXTI_PD_PD17 BIT(17) /*!< interrupt pending status from line 17 */ +#define EXTI_PD_PD18 BIT(18) /*!< interrupt pending status from line 18 */ +#define EXTI_PD_PD19 BIT(19) /*!< interrupt pending status from line 19 */ /* constants definitions */ /* EXTI line number */ -typedef enum -{ +typedef enum { EXTI_0 = BIT(0), /*!< EXTI line 0 */ EXTI_1 = BIT(1), /*!< EXTI line 1 */ EXTI_2 = BIT(2), /*!< EXTI line 2 */ @@ -207,52 +203,50 @@ typedef enum EXTI_16 = BIT(16), /*!< EXTI line 16 */ EXTI_17 = BIT(17), /*!< EXTI line 17 */ EXTI_18 = BIT(18), /*!< EXTI line 18 */ - EXTI_19 = BIT(19), /*!< EXTI line 19 */ -}exti_line_enum; + EXTI_19 = BIT(19) /*!< EXTI line 19 */ +} exti_line_enum; /* external interrupt and event */ -typedef enum -{ +typedef enum { EXTI_INTERRUPT = 0, /*!< EXTI interrupt mode */ EXTI_EVENT /*!< EXTI event mode */ -}exti_mode_enum; +} exti_mode_enum; -/* interrupt trigger mode */ -typedef enum -{ +/* interrupt and event trigger mode */ +typedef enum { EXTI_TRIG_RISING = 0, /*!< EXTI rising edge trigger */ EXTI_TRIG_FALLING, /*!< EXTI falling edge trigger */ - EXTI_TRIG_BOTH /*!< EXTI rising and falling edge trigger */ -}exti_trig_type_enum; + EXTI_TRIG_BOTH, /*!< EXTI rising and falling edge trigger */ + EXTI_TRIG_NONE /*!< without rising edge or falling edge trigger */ +} exti_trig_type_enum; /* function declarations */ /* initialization, EXTI lines configuration functions */ /* deinitialize the EXTI */ void exti_deinit(void); -/* enable the configuration of EXTI initialize */ +/* initialize the EXTI line x */ void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum trig_type); /* enable the interrupts from EXTI line x */ void exti_interrupt_enable(exti_line_enum linex); -/* enable the events from EXTI line x */ -void exti_event_enable(exti_line_enum linex); /* disable the interrupts from EXTI line x */ void exti_interrupt_disable(exti_line_enum linex); +/* enable the events from EXTI line x */ +void exti_event_enable(exti_line_enum linex); /* disable the events from EXTI line x */ void exti_event_disable(exti_line_enum linex); +/* enable the software interrupt event from EXTI line x */ +void exti_software_interrupt_enable(exti_line_enum linex); +/* disable the software interrupt event from EXTI line x */ +void exti_software_interrupt_disable(exti_line_enum linex); /* interrupt & flag functions */ -/* get EXTI lines pending flag */ +/* get EXTI line x interrupt pending flag */ FlagStatus exti_flag_get(exti_line_enum linex); -/* clear EXTI lines pending flag */ +/* clear EXTI line x interrupt pending flag */ void exti_flag_clear(exti_line_enum linex); -/* get EXTI lines flag when the interrupt flag is set */ +/* get EXTI line x interrupt pending flag */ FlagStatus exti_interrupt_flag_get(exti_line_enum linex); -/* clear EXTI lines pending flag */ +/* clear EXTI line x interrupt pending flag */ void exti_interrupt_flag_clear(exti_line_enum linex); -/* enable the EXTI software interrupt event */ -void exti_software_interrupt_enable(exti_line_enum linex); -/* disable the EXTI software interrupt event */ -void exti_software_interrupt_disable(exti_line_enum linex); #endif /* GD32F20X_EXTI_H */ - diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_fmc.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_fmc.h index f070ffe1..585ed656 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_fmc.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_fmc.h @@ -2,36 +2,33 @@ \file gd32f20x_fmc.h \brief definitions for the FMC - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -45,27 +42,27 @@ OF SUCH DAMAGE. #define OB OB_BASE /*!< option bytes base address */ /* registers definitions */ -#define FMC_WS REG32((FMC) + 0x00U) /*!< FMC wait state register */ -#define FMC_KEY0 REG32((FMC) + 0x04U) /*!< FMC unlock key register 0 */ -#define FMC_OBKEY REG32((FMC) + 0x08U) /*!< FMC option bytes unlock key register */ -#define FMC_STAT0 REG32((FMC) + 0x0CU) /*!< FMC status register 0 */ -#define FMC_CTL0 REG32((FMC) + 0x10U) /*!< FMC control register 0 */ -#define FMC_ADDR0 REG32((FMC) + 0x14U) /*!< FMC address register 0 */ -#define FMC_OBSTAT REG32((FMC) + 0x1CU) /*!< FMC option bytes status register */ -#define FMC_WP REG32((FMC) + 0x20U) /*!< FMC erase/program protection register */ -#define FMC_KEY1 REG32((FMC) + 0x44U) /*!< FMC unlock key register 1 */ -#define FMC_STAT1 REG32((FMC) + 0x4CU) /*!< FMC status register 1 */ -#define FMC_CTL1 REG32((FMC) + 0x50U) /*!< FMC control register 1 */ -#define FMC_ADDR1 REG32((FMC) + 0x54U) /*!< FMC address register 1 */ -#define FMC_WSEN REG32((FMC) + 0xFCU) /*!< FMC wait state enable register */ -#define FMC_PID REG32((FMC) + 0x100U) /*!< FMC product ID register */ - -#define OB_SPC REG16((OB) + 0x00U) /*!< option byte security protection value */ -#define OB_USER REG16((OB) + 0x02U) /*!< option byte user value*/ -#define OB_WP0 REG16((OB) + 0x08U) /*!< option byte write protection 0 */ -#define OB_WP1 REG16((OB) + 0x0AU) /*!< option byte write protection 1 */ -#define OB_WP2 REG16((OB) + 0x0CU) /*!< option byte write protection 2 */ -#define OB_WP3 REG16((OB) + 0x0EU) /*!< option byte write protection 3 */ +#define FMC_WS REG32((FMC) + 0x00000000U) /*!< FMC wait state register */ +#define FMC_KEY0 REG32((FMC) + 0x00000004U) /*!< FMC unlock key register 0 */ +#define FMC_OBKEY REG32((FMC) + 0x00000008U) /*!< FMC option bytes unlock key register */ +#define FMC_STAT0 REG32((FMC) + 0x0000000CU) /*!< FMC status register 0 */ +#define FMC_CTL0 REG32((FMC) + 0x00000010U) /*!< FMC control register 0 */ +#define FMC_ADDR0 REG32((FMC) + 0x00000014U) /*!< FMC address register 0 */ +#define FMC_OBSTAT REG32((FMC) + 0x0000001CU) /*!< FMC option bytes status register */ +#define FMC_WP REG32((FMC) + 0x00000020U) /*!< FMC erase/program protection register */ +#define FMC_KEY1 REG32((FMC) + 0x00000044U) /*!< FMC unlock key register 1 */ +#define FMC_STAT1 REG32((FMC) + 0x0000004CU) /*!< FMC status register 1 */ +#define FMC_CTL1 REG32((FMC) + 0x00000050U) /*!< FMC control register 1 */ +#define FMC_ADDR1 REG32((FMC) + 0x00000054U) /*!< FMC address register 1 */ +#define FMC_WSEN REG32((FMC) + 0x000000FCU) /*!< FMC wait state enable register */ +#define FMC_PID REG32((FMC) + 0x00000100U) /*!< FMC product ID register */ + +#define OB_SPC REG16((OB) + 0x0000U) /*!< option byte security protection value */ +#define OB_USER REG16((OB) + 0x0002U) /*!< option byte user value*/ +#define OB_WP0 REG16((OB) + 0x0008U) /*!< option byte write protection 0 */ +#define OB_WP1 REG16((OB) + 0x000AU) /*!< option byte write protection 1 */ +#define OB_WP2 REG16((OB) + 0x000CU) /*!< option byte write protection 2 */ +#define OB_WP3 REG16((OB) + 0x000EU) /*!< option byte write protection 3 */ /* bits definitions */ /* FMC_WS */ @@ -96,7 +93,7 @@ OF SUCH DAMAGE. #define FMC_CTL0_ENDIE BIT(12) /*!< end of operation interrupt enable bit */ /* FMC_ADDR0 */ -#define FMC_ADDR0_ADDR BITS(0,31) /*!< Flash erase/program command address bits */ +#define FMC_ADDR0_ADDR BITS(0,31) /*!< flash erase/program command address bits */ /* FMC_OBSTAT */ #define FMC_OBSTAT_OBERR BIT(0) /*!< option bytes read error bit. */ @@ -126,7 +123,7 @@ OF SUCH DAMAGE. #define FMC_CTL1_ENDIE BIT(12) /*!< end of operation interrupt enable bit */ /* FMC_ADDR1 */ -#define FMC_ADDR1_ADDR BITS(0,31) /*!< Flash erase/program command address bits */ +#define FMC_ADDR1_ADDR BITS(0,31) /*!< flash erase/program command address bits */ /* FMC_WSEN */ #define FMC_WSEN_WSEN BIT(0) /*!< FMC wait state enable bit */ @@ -146,34 +143,31 @@ OF SUCH DAMAGE. #define FMC_REG_OFFSET_GET(flag) ((uint32_t)(flag) >> 12) /* configuration register */ -#define FMC_STAT0_REG_OFFSET 0x0CU /*!< status register 0 offset */ -#define FMC_CTL0_REG_OFFSET 0x10U /*!< control register 0 offset */ -#define FMC_STAT1_REG_OFFSET 0x4CU /*!< status register 1 offset */ -#define FMC_CTL1_REG_OFFSET 0x50U /*!< control register 1 offset */ -#define FMC_OBSTAT_REG_OFFSET 0x1CU /*!< option byte status register offset */ +#define FMC_STAT0_REG_OFFSET ((uint32_t)0x0000000CU) /*!< status register 0 offset */ +#define FMC_CTL0_REG_OFFSET ((uint32_t)0x00000010U) /*!< control register 0 offset */ +#define FMC_STAT1_REG_OFFSET ((uint32_t)0x0000004CU) /*!< status register 1 offset */ +#define FMC_CTL1_REG_OFFSET ((uint32_t)0x00000050U) /*!< control register 1 offset */ +#define FMC_OBSTAT_REG_OFFSET ((uint32_t)0x0000001CU) /*!< option byte status register offset */ /* fmc state */ -typedef enum -{ - FMC_READY, /*!< the operation has been completed */ - FMC_BUSY, /*!< the operation is in progress */ - FMC_PGERR, /*!< program error */ - FMC_WPERR, /*!< erase/program protection error */ - FMC_TOERR, /*!< timeout error */ -}fmc_state_enum; - -/* FMC interrupt enable */ -typedef enum -{ - FMC_INT_BANK0_END = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 12U), /*!< enable FMC end of program interrupt */ - FMC_INT_BANK0_ERR = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 10U), /*!< enable FMC error interrupt */ - FMC_INT_BANK1_END = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 12U), /*!< enable FMC bank1 end of program interrupt */ - FMC_INT_BANK1_ERR = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 10U), /*!< enable FMC bank1 error interrupt */ -}fmc_int_enum; +typedef enum { + FMC_READY = 0, /*!< the operation has been completed */ + FMC_BUSY, /*!< the operation is in progress */ + FMC_PGERR, /*!< program error */ + FMC_WPERR, /*!< erase/program protection error */ + FMC_TOERR /*!< timeout error */ +} fmc_state_enum; + +/* FMC interrupt */ +typedef enum { + FMC_INT_BANK0_END = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 12U), /*!< FMC bank0 end of program interrupt */ + FMC_INT_BANK0_ERR = FMC_REGIDX_BIT(FMC_CTL0_REG_OFFSET, 10U), /*!< FMC bank0 error interrupt */ + FMC_INT_BANK1_END = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 12U), /*!< FMC bank1 end of program interrupt */ + FMC_INT_BANK1_ERR = FMC_REGIDX_BIT(FMC_CTL1_REG_OFFSET, 10U) /*!< FMC bank1 error interrupt */ +} fmc_interrupt_enum; /* FMC flags */ -typedef enum -{ +typedef enum { FMC_FLAG_BANK0_BUSY = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 0U), /*!< FMC bank0 busy flag */ FMC_FLAG_BANK0_PGERR = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 2U), /*!< FMC bank0 operation error flag bit */ FMC_FLAG_BANK0_WPERR = FMC_REGIDX_BIT(FMC_STAT0_REG_OFFSET, 4U), /*!< FMC bank0 erase/program protection error flag bit */ @@ -182,114 +176,114 @@ typedef enum FMC_FLAG_BANK1_BUSY = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 0U), /*!< FMC bank1 busy flag */ FMC_FLAG_BANK1_PGERR = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 2U), /*!< FMC bank1 operation error flag bit */ FMC_FLAG_BANK1_WPERR = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 4U), /*!< FMC bank1 erase/program protection error flag bit */ - FMC_FLAG_BANK1_END = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 5U), /*!< FMC bank1 end of operation flag bit */ -}fmc_flag_enum; + FMC_FLAG_BANK1_END = FMC_REGIDX_BIT(FMC_STAT1_REG_OFFSET, 5U) /*!< FMC bank1 end of operation flag bit */ +} fmc_flag_enum; /* FMC interrupt flags */ -typedef enum -{ +typedef enum { FMC_INT_FLAG_BANK0_PGERR = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 2U, 10U), /*!< FMC bank0 operation error interrupt flag bit */ FMC_INT_FLAG_BANK0_WPERR = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 4U, 10U), /*!< FMC bank0 erase/program protection error interrupt flag bit */ FMC_INT_FLAG_BANK0_END = FMC_REGIDX_BITS(FMC_STAT0_REG_OFFSET, 5U, 12U), /*!< FMC bank0 end of operation interrupt flag bit */ FMC_INT_FLAG_BANK1_PGERR = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 2U, 10U), /*!< FMC bank1 operation error interrupt flag bit */ FMC_INT_FLAG_BANK1_WPERR = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 4U, 10U), /*!< FMC bank1 erase/program protection error interrupt flag bit */ - FMC_INT_FLAG_BANK1_END = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 5U, 12U), /*!< FMC bank1 end of operation interrupt flag bit */ -}fmc_interrupt_flag_enum; + FMC_INT_FLAG_BANK1_END = FMC_REGIDX_BITS(FMC_STAT1_REG_OFFSET, 5U, 12U) /*!< FMC bank1 end of operation interrupt flag bit */ +} fmc_interrupt_flag_enum; /* unlock key */ -#define UNLOCK_KEY0 ((uint32_t)0x45670123U) /*!< unlock key 0 */ -#define UNLOCK_KEY1 ((uint32_t)0xCDEF89ABU) /*!< unlock key 1 */ +#define UNLOCK_KEY0 ((uint32_t)0x45670123U) /*!< unlock key 0 */ +#define UNLOCK_KEY1 ((uint32_t)0xCDEF89ABU) /*!< unlock key 1 */ /* FMC wait state counter */ #define WS_WSCNT(regval) (BITS(0,2) & ((uint32_t)(regval))) -#define WS_WSCNT_0 WS_WSCNT(0) /*!< FMC 0 wait */ -#define WS_WSCNT_1 WS_WSCNT(1) /*!< FMC 1 wait */ -#define WS_WSCNT_2 WS_WSCNT(2) /*!< FMC 2 wait */ +#define WS_WSCNT_0 WS_WSCNT(0) /*!< FMC 0 wait */ +#define WS_WSCNT_1 WS_WSCNT(1) /*!< FMC 1 wait */ +#define WS_WSCNT_2 WS_WSCNT(2) /*!< FMC 2 wait */ -/* option bytes software/hardware free watch dog timer */ -#define OB_FWDGT_SW ((uint8_t)0x01U) /*!< software free watchdog */ -#define OB_FWDGT_HW ((uint8_t)0x00U) /*!< hardware free watchdog */ +/* option bytes software/hardware free watch dog timer */ +#define OB_FWDGT_SW ((uint8_t)0x01U) /*!< software free watchdog */ +#define OB_FWDGT_HW ((uint8_t)0x00U) /*!< hardware free watchdog */ /* option bytes reset or not entering deep sleep mode */ -#define OB_DEEPSLEEP_NRST ((uint8_t)0x02U) /*!< no reset when entering deepsleep mode */ -#define OB_DEEPSLEEP_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering deepsleep mode */ +#define OB_DEEPSLEEP_NRST ((uint8_t)0x02U) /*!< no reset when entering deepsleep mode */ +#define OB_DEEPSLEEP_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering deepsleep mode */ /* option bytes reset or not entering standby mode */ -#define OB_STDBY_NRST ((uint8_t)0x04U) /*!< no reset when entering deepsleep mode */ -#define OB_STDBY_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering standby mode */ +#define OB_STDBY_NRST ((uint8_t)0x04U) /*!< no reset when entering deepsleep mode */ +#define OB_STDBY_RST ((uint8_t)0x00U) /*!< generate a reset instead of entering standby mode */ /* option bytes boot bank value */ -#define OB_BOOT_B0 ((uint8_t)0x08U) /*!< boot from bank0 */ -#define OB_BOOT_B1 ((uint8_t)0x00U) /*!< boot from bank1 */ +#define OB_BOOT_B0 ((uint8_t)0x08U) /*!< boot from bank0 */ +#define OB_BOOT_B1 ((uint8_t)0x00U) /*!< boot from bank1 */ -#define OB_USER_MASK ((uint8_t)0xF0U) /*!< MASK value */ +#define OB_USER_MASK ((uint8_t)0xF0U) /*!< mask value */ /* read protect configure */ -#define FMC_NSPC ((uint8_t)0xA5U) /*!< no security protection */ -#define FMC_USPC ((uint8_t)0xBBU) /*!< under security protection */ +#define FMC_NSPC ((uint8_t)0xA5U) /*!< no security protection */ +#define FMC_USPC ((uint8_t)0xBBU) /*!< under security protection */ /* OB_SPC */ -#define OB_SPC_SPC ((uint32_t)0x000000FFU) /*!< option byte security protection value */ -#define OB_SPC_SPC_N ((uint32_t)0x0000FF00U) /*!< option byte security protection complement value */ +#define OB_SPC_SPC ((uint32_t)0x000000FFU) /*!< option byte security protection value */ +#define OB_SPC_SPC_N ((uint32_t)0x0000FF00U) /*!< option byte security protection complement value */ /* OB_USER */ -#define OB_USER_USER ((uint32_t)0x00FF0000U) /*!< user option value */ -#define OB_USER_USER_N ((uint32_t)0xFF000000U) /*!< user option complement value */ +#define OB_USER_USER ((uint32_t)0x00FF0000U) /*!< user option value */ +#define OB_USER_USER_N ((uint32_t)0xFF000000U) /*!< user option complement value */ /* OB_WP0 */ -#define OB_WP0_WP0 ((uint32_t)0x000000FFU) /*!< FMC write protection option value */ +#define OB_WP0_WP0 ((uint32_t)0x000000FFU) /*!< FMC write protection option value */ /* OB_WP1 */ -#define OB_WP1_WP1 ((uint32_t)0x0000FF00U) /*!< FMC write protection option complement value */ +#define OB_WP1_WP1 ((uint32_t)0x0000FF00U) /*!< FMC write protection option complement value */ /* OB_WP2 */ -#define OB_WP2_WP2 ((uint32_t)0x00FF0000U) /*!< FMC write protection option value */ +#define OB_WP2_WP2 ((uint32_t)0x00FF0000U) /*!< FMC write protection option value */ /* OB_WP3 */ -#define OB_WP3_WP3 ((uint32_t)0xFF000000U) /*!< FMC write protection option complement value */ +#define OB_WP3_WP3 ((uint32_t)0xFF000000U) /*!< FMC write protection option complement value */ /* option bytes write protection */ -#define OB_WP_0 ((uint32_t)0x00000001U) /*!< erase/program protection of sector 0 */ -#define OB_WP_1 ((uint32_t)0x00000002U) /*!< erase/program protection of sector 1 */ -#define OB_WP_2 ((uint32_t)0x00000004U) /*!< erase/program protection of sector 2 */ -#define OB_WP_3 ((uint32_t)0x00000008U) /*!< erase/program protection of sector 3 */ -#define OB_WP_4 ((uint32_t)0x00000010U) /*!< erase/program protection of sector 4 */ -#define OB_WP_5 ((uint32_t)0x00000020U) /*!< erase/program protection of sector 5 */ -#define OB_WP_6 ((uint32_t)0x00000040U) /*!< erase/program protection of sector 6 */ -#define OB_WP_7 ((uint32_t)0x00000080U) /*!< erase/program protection of sector 7 */ -#define OB_WP_8 ((uint32_t)0x00000100U) /*!< erase/program protection of sector 8 */ -#define OB_WP_9 ((uint32_t)0x00000200U) /*!< erase/program protection of sector 9 */ -#define OB_WP_10 ((uint32_t)0x00000400U) /*!< erase/program protection of sector 10 */ -#define OB_WP_11 ((uint32_t)0x00000800U) /*!< erase/program protection of sector 11 */ -#define OB_WP_12 ((uint32_t)0x00001000U) /*!< erase/program protection of sector 12 */ -#define OB_WP_13 ((uint32_t)0x00002000U) /*!< erase/program protection of sector 13 */ -#define OB_WP_14 ((uint32_t)0x00004000U) /*!< erase/program protection of sector 14 */ -#define OB_WP_15 ((uint32_t)0x00008000U) /*!< erase/program protection of sector 15 */ -#define OB_WP_16 ((uint32_t)0x00010000U) /*!< erase/program protection of sector 16 */ -#define OB_WP_17 ((uint32_t)0x00020000U) /*!< erase/program protection of sector 17 */ -#define OB_WP_18 ((uint32_t)0x00040000U) /*!< erase/program protection of sector 18 */ -#define OB_WP_19 ((uint32_t)0x00080000U) /*!< erase/program protection of sector 19 */ -#define OB_WP_20 ((uint32_t)0x00100000U) /*!< erase/program protection of sector 20 */ -#define OB_WP_21 ((uint32_t)0x00200000U) /*!< erase/program protection of sector 21 */ -#define OB_WP_22 ((uint32_t)0x00400000U) /*!< erase/program protection of sector 22 */ -#define OB_WP_23 ((uint32_t)0x00800000U) /*!< erase/program protection of sector 23 */ -#define OB_WP_24 ((uint32_t)0x01000000U) /*!< erase/program protection of sector 24 */ -#define OB_WP_25 ((uint32_t)0x02000000U) /*!< erase/program protection of sector 25 */ -#define OB_WP_26 ((uint32_t)0x04000000U) /*!< erase/program protection of sector 26 */ -#define OB_WP_27 ((uint32_t)0x08000000U) /*!< erase/program protection of sector 27 */ -#define OB_WP_28 ((uint32_t)0x10000000U) /*!< erase/program protection of sector 28 */ -#define OB_WP_29 ((uint32_t)0x20000000U) /*!< erase/program protection of sector 29 */ -#define OB_WP_30 ((uint32_t)0x40000000U) /*!< erase/program protection of sector 30 */ -#define OB_WP_31 ((uint32_t)0x80000000U) /*!< erase/program protection of sector 31 */ -#define OB_WP_ALL ((uint32_t)0xFFFFFFFFU) /*!< erase/program protection of all sectors */ +#define OB_WP_NONE ((uint32_t)0x00000000U) /*!< disable all erase/program protection */ +#define OB_WP_0 ((uint32_t)0x00000001U) /*!< erase/program protection of sector 0 */ +#define OB_WP_1 ((uint32_t)0x00000002U) /*!< erase/program protection of sector 1 */ +#define OB_WP_2 ((uint32_t)0x00000004U) /*!< erase/program protection of sector 2 */ +#define OB_WP_3 ((uint32_t)0x00000008U) /*!< erase/program protection of sector 3 */ +#define OB_WP_4 ((uint32_t)0x00000010U) /*!< erase/program protection of sector 4 */ +#define OB_WP_5 ((uint32_t)0x00000020U) /*!< erase/program protection of sector 5 */ +#define OB_WP_6 ((uint32_t)0x00000040U) /*!< erase/program protection of sector 6 */ +#define OB_WP_7 ((uint32_t)0x00000080U) /*!< erase/program protection of sector 7 */ +#define OB_WP_8 ((uint32_t)0x00000100U) /*!< erase/program protection of sector 8 */ +#define OB_WP_9 ((uint32_t)0x00000200U) /*!< erase/program protection of sector 9 */ +#define OB_WP_10 ((uint32_t)0x00000400U) /*!< erase/program protection of sector 10 */ +#define OB_WP_11 ((uint32_t)0x00000800U) /*!< erase/program protection of sector 11 */ +#define OB_WP_12 ((uint32_t)0x00001000U) /*!< erase/program protection of sector 12 */ +#define OB_WP_13 ((uint32_t)0x00002000U) /*!< erase/program protection of sector 13 */ +#define OB_WP_14 ((uint32_t)0x00004000U) /*!< erase/program protection of sector 14 */ +#define OB_WP_15 ((uint32_t)0x00008000U) /*!< erase/program protection of sector 15 */ +#define OB_WP_16 ((uint32_t)0x00010000U) /*!< erase/program protection of sector 16 */ +#define OB_WP_17 ((uint32_t)0x00020000U) /*!< erase/program protection of sector 17 */ +#define OB_WP_18 ((uint32_t)0x00040000U) /*!< erase/program protection of sector 18 */ +#define OB_WP_19 ((uint32_t)0x00080000U) /*!< erase/program protection of sector 19 */ +#define OB_WP_20 ((uint32_t)0x00100000U) /*!< erase/program protection of sector 20 */ +#define OB_WP_21 ((uint32_t)0x00200000U) /*!< erase/program protection of sector 21 */ +#define OB_WP_22 ((uint32_t)0x00400000U) /*!< erase/program protection of sector 22 */ +#define OB_WP_23 ((uint32_t)0x00800000U) /*!< erase/program protection of sector 23 */ +#define OB_WP_24 ((uint32_t)0x01000000U) /*!< erase/program protection of sector 24 */ +#define OB_WP_25 ((uint32_t)0x02000000U) /*!< erase/program protection of sector 25 */ +#define OB_WP_26 ((uint32_t)0x04000000U) /*!< erase/program protection of sector 26 */ +#define OB_WP_27 ((uint32_t)0x08000000U) /*!< erase/program protection of sector 27 */ +#define OB_WP_28 ((uint32_t)0x10000000U) /*!< erase/program protection of sector 28 */ +#define OB_WP_29 ((uint32_t)0x20000000U) /*!< erase/program protection of sector 29 */ +#define OB_WP_30 ((uint32_t)0x40000000U) /*!< erase/program protection of sector 30 */ +#define OB_WP_31 ((uint32_t)0x80000000U) /*!< erase/program protection of sector 31 */ +#define OB_WP_ALL ((uint32_t)0xFFFFFFFFU) /*!< erase/program protection of all sectors */ /* FMC timeout */ -#define FMC_TIMEOUT_COUNT ((uint32_t)0x000F0000U) /*!< FMC timeout count value */ +#define FMC_TIMEOUT_COUNT ((uint32_t)0x000F0000U) /*!< FMC timeout count value */ /* FMC BANK address */ -#define FMC_BANK0_END_ADDRESS ((uint32_t)0x0807FFFFU) /*!< FMC bank0 end address */ -#define FMC_BANK0_SIZE ((uint32_t)0x00000200U) /*!< FMC bank0 size */ -#define FMC_SIZE (*(uint16_t *)0x1FFFF7E0U) /*!< FMC size */ +#define FMC_BANK0_END_ADDRESS ((uint32_t)0x0807FFFFU) /*!< FMC bank0 end address */ +#define FMC_BANK0_SIZE ((uint32_t)0x00000200U) /*!< FMC bank0 size */ +#define FMC_SIZE (*(uint16_t *)0x1FFFF7E0U) /*!< FMC size */ /* function declarations */ /* FMC main memory programming functions */ @@ -307,17 +301,17 @@ void fmc_lock(void); void fmc_bank0_lock(void); /* lock the bank1 FMC operation */ void fmc_bank1_lock(void); -/* FMC erase page */ +/* erase page */ fmc_state_enum fmc_page_erase(uint32_t page_address); -/* FMC erase whole chip */ +/* erase whole chip */ fmc_state_enum fmc_mass_erase(void); -/* FMC erase whole bank0 */ +/* erase whole bank0 */ fmc_state_enum fmc_bank0_erase(void); -/* FMC erase whole bank1 */ +/* erase whole bank1 */ fmc_state_enum fmc_bank1_erase(void); -/* FMC program a word at the corresponding address */ +/* program a word at the corresponding address */ fmc_state_enum fmc_word_program(uint32_t address, uint32_t data); -/* FMC program a half word at the corresponding address */ +/* program a half word at the corresponding address */ fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data); /* FMC option bytes programming functions */ @@ -327,17 +321,17 @@ void ob_unlock(void); void ob_lock(void); /* erase the option byte */ fmc_state_enum ob_erase(void); -/* enable write protect */ +/* enable write protection */ fmc_state_enum ob_write_protection_enable(uint32_t ob_wp); /* configure the option byte security protection */ fmc_state_enum ob_security_protection_config(uint8_t ob_spc); -/* write the FMC option byte */ +/* program option bytes user */ fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_stdby, uint8_t ob_boot); /* program option bytes data */ fmc_state_enum ob_data_program(uint32_t address, uint8_t data); -/* get the FMC option byte user */ +/* get the FMC option bytes user */ uint8_t ob_user_get(void); -/* get OB_DATA in register FMC_OBSTAT */ +/* get the FMC option bytes data */ uint16_t ob_data_get(void); /* get the FMC option byte write protection */ uint32_t ob_write_protection_get(void); @@ -345,25 +339,17 @@ uint32_t ob_write_protection_get(void); FlagStatus ob_spc_get(void); /* FMC interrupts and flags management functions */ -/* enable FMC interrupt */ -void fmc_interrupt_enable(uint32_t interrupt); -/* disable FMC interrupt */ -void fmc_interrupt_disable(uint32_t interrupt); /* check flag is set or not */ FlagStatus fmc_flag_get(uint32_t flag); /* clear the FMC flag */ void fmc_flag_clear(uint32_t flag); +/* enable FMC interrupt */ +void fmc_interrupt_enable(fmc_interrupt_enum interrupt); +/* disable FMC interrupt */ +void fmc_interrupt_disable(fmc_interrupt_enum interrupt); /* get FMC interrupt flag state */ -FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag); +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum int_flag); /* clear FMC interrupt flag state */ -void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag); -/* return the FMC bank0 state */ -fmc_state_enum fmc_bank0_state_get(void); -/* return the FMC bank1 state */ -fmc_state_enum fmc_bank1_state_get(void); -/* check FMC bank0 ready or not */ -fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout); -/* check FMC bank1 ready or not */ -fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout); +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum int_flag); #endif /* GD32F20X_FMC_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_fwdgt.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_fwdgt.h index 1cc6c00f..b5f4b1e6 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_fwdgt.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_fwdgt.h @@ -2,36 +2,33 @@ \file gd32f20x_fwdgt.h \brief definitions for the FWDGT - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -88,12 +85,10 @@ OF SUCH DAMAGE. #define FWDGT_FLAG_PUD FWDGT_STAT_PUD /*!< FWDGT prescaler divider value update flag */ #define FWDGT_FLAG_RUD FWDGT_STAT_RUD /*!< FWDGT counter reload value update flag */ -#ifdef __cplusplus - extern "C" { -#endif +/* write value to FWDGT_RLD_RLD bit field */ +#define RLD_RLD(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) /* function declarations */ -/* function configuration */ /* enable write access to FWDGT_PSC and FWDGT_RLD */ void fwdgt_write_enable(void); /* disable write access to FWDGT_PSC and FWDGT_RLD */ @@ -101,16 +96,16 @@ void fwdgt_write_disable(void); /* start the free watchdog timer counter */ void fwdgt_enable(void); +/* configure the free watchdog timer counter prescaler value */ +ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value); +/* configure the free watchdog timer counter reload value */ +ErrStatus fwdgt_reload_value_config(uint16_t reload_value); /* reload the counter of FWDGT */ void fwdgt_counter_reload(void); /* configure counter reload value, and prescaler divider value */ ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div); -/* interrupt & flag functions */ /* get flag state of FWDGT */ FlagStatus fwdgt_flag_get(uint16_t flag); -#ifdef __cplusplus -} -#endif #endif /* GD32F20X_FWDGT_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_gpio.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_gpio.h index dc249900..5b6f8f05 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_gpio.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_gpio.h @@ -2,36 +2,33 @@ \file gd32f20x_gpio.h \brief definitions for the GPIO - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -41,45 +38,45 @@ OF SUCH DAMAGE. #include "gd32f20x.h" /* GPIOx(x=A,B,C,D,E,F,G,H,I) definitions */ -#define GPIOA (GPIO_BASE + 0x00000000U) -#define GPIOB (GPIO_BASE + 0x00000400U) -#define GPIOC (GPIO_BASE + 0x00000800U) -#define GPIOD (GPIO_BASE + 0x00000C00U) -#define GPIOE (GPIO_BASE + 0x00001000U) -#define GPIOF (GPIO_BASE + 0x00001400U) -#define GPIOG (GPIO_BASE + 0x00001800U) -#define GPIOH (GPIO_BASE + 0x00006C00U) -#define GPIOI (GPIO_BASE + 0x00007000U) +#define GPIOA (GPIO_BASE + 0x00000000U) /*!< GPIOA bsae address */ +#define GPIOB (GPIO_BASE + 0x00000400U) /*!< GPIOB bsae address */ +#define GPIOC (GPIO_BASE + 0x00000800U) /*!< GPIOC bsae address */ +#define GPIOD (GPIO_BASE + 0x00000C00U) /*!< GPIOD bsae address */ +#define GPIOE (GPIO_BASE + 0x00001000U) /*!< GPIOE bsae address */ +#define GPIOF (GPIO_BASE + 0x00001400U) /*!< GPIOF bsae address */ +#define GPIOG (GPIO_BASE + 0x00001800U) /*!< GPIOG bsae address */ +#define GPIOH (GPIO_BASE + 0x00006C00U) /*!< GPIOH bsae address */ +#define GPIOI (GPIO_BASE + 0x00007000U) /*!< GPIOI bsae address */ /* AFIO definitions */ -#define AFIO AFIO_BASE +#define AFIO AFIO_BASE /*!< AFIO bsae address */ /* registers definitions */ /* GPIO registers definitions */ -#define GPIO_CTL0(gpiox) REG32((gpiox) + 0x00U) /*!< GPIO port control register 0 */ -#define GPIO_CTL1(gpiox) REG32((gpiox) + 0x04U) /*!< GPIO port control register 1 */ -#define GPIO_ISTAT(gpiox) REG32((gpiox) + 0x08U) /*!< GPIO port input status register */ -#define GPIO_OCTL(gpiox) REG32((gpiox) + 0x0CU) /*!< GPIO port output control register */ -#define GPIO_BOP(gpiox) REG32((gpiox) + 0x10U) /*!< GPIO port bit operation register */ -#define GPIO_BC(gpiox) REG32((gpiox) + 0x14U) /*!< GPIO bit clear register */ -#define GPIO_LOCK(gpiox) REG32((gpiox) + 0x18U) /*!< GPIO port configuration lock register */ +#define GPIO_CTL0(gpiox) REG32((gpiox) + 0x00000000U) /*!< GPIO port control register 0 */ +#define GPIO_CTL1(gpiox) REG32((gpiox) + 0x00000004U) /*!< GPIO port control register 1 */ +#define GPIO_ISTAT(gpiox) REG32((gpiox) + 0x00000008U) /*!< GPIO port input status register */ +#define GPIO_OCTL(gpiox) REG32((gpiox) + 0x0000000CU) /*!< GPIO port output control register */ +#define GPIO_BOP(gpiox) REG32((gpiox) + 0x00000010U) /*!< GPIO port bit operation register */ +#define GPIO_BC(gpiox) REG32((gpiox) + 0x00000014U) /*!< GPIO bit clear register */ +#define GPIO_LOCK(gpiox) REG32((gpiox) + 0x00000018U) /*!< GPIO port configuration lock register */ /* AFIO registers definitions */ -#define AFIO_EC REG32(AFIO + 0x00U) /*!< AFIO event control register */ -#define AFIO_PCF0 REG32(AFIO + 0x04U) /*!< AFIO port configuration register 0 */ -#define AFIO_EXTISS0 REG32(AFIO + 0x08U) /*!< AFIO port EXTI sources selection register 0 */ -#define AFIO_EXTISS1 REG32(AFIO + 0x0CU) /*!< AFIO port EXTI sources selection register 1 */ -#define AFIO_EXTISS2 REG32(AFIO + 0x10U) /*!< AFIO port EXTI sources selection register 2 */ -#define AFIO_EXTISS3 REG32(AFIO + 0x14U) /*!< AFIO port EXTI sources selection register 3 */ -#define AFIO_PCF1 REG32(AFIO + 0x1CU) /*!< AFIO port configuration register 1 */ -#define AFIO_PCF2 REG32(AFIO + 0x3CU) /*!< AFIO port configuration register 2 */ -#define AFIO_PCF3 REG32(AFIO + 0x40U) /*!< AFIO port configuration register 3 */ -#define AFIO_PCF4 REG32(AFIO + 0x44U) /*!< AFIO port configuration register 4 */ -#define AFIO_PCF5 REG32(AFIO + 0x48U) /*!< AFIO port configuration register 5 */ +#define AFIO_EC REG32(AFIO + 0x00000000U) /*!< AFIO event control register */ +#define AFIO_PCF0 REG32(AFIO + 0x00000004U) /*!< AFIO port configuration register 0 */ +#define AFIO_EXTISS0 REG32(AFIO + 0x00000008U) /*!< AFIO port EXTI sources selection register 0 */ +#define AFIO_EXTISS1 REG32(AFIO + 0x0000000CU) /*!< AFIO port EXTI sources selection register 1 */ +#define AFIO_EXTISS2 REG32(AFIO + 0x00000010U) /*!< AFIO port EXTI sources selection register 2 */ +#define AFIO_EXTISS3 REG32(AFIO + 0x00000014U) /*!< AFIO port EXTI sources selection register 3 */ +#define AFIO_PCF1 REG32(AFIO + 0x0000001CU) /*!< AFIO port configuration register 1 */ +#define AFIO_PCF2 REG32(AFIO + 0x0000003CU) /*!< AFIO port configuration register 2 */ +#define AFIO_PCF3 REG32(AFIO + 0x00000040U) /*!< AFIO port configuration register 3 */ +#define AFIO_PCF4 REG32(AFIO + 0x00000044U) /*!< AFIO port configuration register 4 */ +#define AFIO_PCF5 REG32(AFIO + 0x00000048U) /*!< AFIO port configuration register 5 */ /* bits definitions */ /* GPIO_CTL0 */ -#define GPIO_CTL0_MD0 BITS(0,1) /*!< port 0 mode bits */ +#define GPIO_CTL0_MD0 BITS(0,1) /*!< port 0 mode bits */ #define GPIO_CTL0_CTL0 BITS(2,3) /*!< pin 0 configuration bits */ #define GPIO_CTL0_MD1 BITS(4,5) /*!< port 1 mode bits */ #define GPIO_CTL0_CTL1 BITS(6,7) /*!< pin 1 configuration bits */ @@ -97,7 +94,7 @@ OF SUCH DAMAGE. #define GPIO_CTL0_CTL7 BITS(30,31) /*!< pin 7 configuration bits */ /* GPIO_CTL1 */ -#define GPIO_CTL1_MD8 BITS(0,1) /*!< port 8 mode bits */ +#define GPIO_CTL1_MD8 BITS(0,1) /*!< port 8 mode bits */ #define GPIO_CTL1_CTL8 BITS(2,3) /*!< pin 8 configuration bits */ #define GPIO_CTL1_MD9 BITS(4,5) /*!< port 9 mode bits */ #define GPIO_CTL1_CTL9 BITS(6,7) /*!< pin 9 configuration bits */ @@ -636,7 +633,7 @@ typedef FlagStatus bit_status; #define GPIO_PCF5_SPI1_NSCK_REMAP0 ((uint32_t)0x00000400U) /*!< SPI1 NSS/SCK remapping 0 */ #define GPIO_PCF5_SPI1_NSCK_REMAP1 ((uint32_t)0x00000600U) /*!< SPI1 NSS/SCK remapping 1 */ #define GPIO_PCF5_SPI1_IO_REMAP0 ((uint32_t)0x00000800U) /*!< SPI1 MISO/MOSI remapping 0 */ -#define GPIO_PCF5_SPI1_IO_REMAP1 ((uint32_t)0x00001800U) /*!< SPI1 MISO/MOSI remapping 1 */ +#define GPIO_PCF5_SPI1_IO_REMAP1 ((uint32_t)0x00001000U) /*!< SPI1 MISO/MOSI remapping 1 */ #define GPIO_PCF5_UART3_REMAP ((uint32_t)0x00002000U) /*!< UART3 remapping */ #define GPIO_PCF5_TIMER11_REMAP ((uint32_t)0x00004000U) /*!< TIMER11 remapping */ #define GPIO_PCF5_CAN0_ADD_REMAP ((uint32_t)0x00008000U) /*!< CAN0 addition remapping */ @@ -677,9 +674,9 @@ void gpio_afio_deinit(void); void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin); /* function configuration */ -/* set GPIO pin bit */ +/* set GPIO pin */ void gpio_bit_set(uint32_t gpio_periph, uint32_t pin); -/* reset GPIO pin bit */ +/* reset GPIO pin */ void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin); /* write data to the specified GPIO pin */ void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value); @@ -696,10 +693,13 @@ FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin); uint16_t gpio_output_port_get(uint32_t gpio_periph); /* configure GPIO pin remap */ -void gpio_pin_remap_config(uint32_t gpio_remap, ControlStatus newvalue); +void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue); /* configure GPIO pin remap1 */ void gpio_pin_remap1_config(uint8_t remap_reg, uint32_t remap, ControlStatus newvalue); +/* select ethernet MII or RMII PHY */ +void gpio_ethernet_phy_select(uint32_t enet_sel); + /* select GPIO pin exti sources */ void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin); /* configure GPIO pin event output */ @@ -712,7 +712,4 @@ void gpio_event_output_disable(void); /* lock GPIO pin bit */ void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin); -/* select ethernet MII or RMII PHY */ -void gpio_ethernet_phy_select(uint32_t enet_sel); - #endif /* GD32F20X_GPIO_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_hau.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_hau.h index 043342c1..2d7e9c2d 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_hau.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_hau.h @@ -2,36 +2,33 @@ \file gd32f20x_hau.h \brief definitions for the HAU - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -41,22 +38,22 @@ OF SUCH DAMAGE. #include "gd32f20x.h" /* HAU definitions */ -#define HAU HAU_BASE +#define HAU HAU_BASE /*!< HAU base address */ /* registers definitions */ -#define HAU_CTL REG32(HAU + 0x00U) /*!< control register */ -#define HAU_DI REG32(HAU + 0x04U) /*!< data input register */ -#define HAU_CFG REG32(HAU + 0x08U) /*!< configuration register */ -#define HAU_DO0 REG32(HAU + 0x0CU) /*!< data output register 0 */ -#define HAU_DO1 REG32(HAU + 0x10U) /*!< data output register 1 */ -#define HAU_DO2 REG32(HAU + 0x14U) /*!< data output register 2 */ -#define HAU_DO3 REG32(HAU + 0x18U) /*!< data output register 3 */ -#define HAU_DO4 REG32(HAU + 0x1CU) /*!< data output register 4 */ -#define HAU_DO5 REG32(HAU + 0x324U) /*!< data output register 5 */ -#define HAU_DO6 REG32(HAU + 0x328U) /*!< data output register 6 */ -#define HAU_DO7 REG32(HAU + 0x32CU) /*!< data output register 7 */ -#define HAU_INTEN REG32(HAU + 0x20U) /*!< interrupt enable register */ -#define HAU_STAT REG32(HAU + 0x24U) /*!< status and interrupt flag register */ +#define HAU_CTL REG32(HAU + 0x00000000U) /*!< control register */ +#define HAU_DI REG32(HAU + 0x00000004U) /*!< data input register */ +#define HAU_CFG REG32(HAU + 0x00000008U) /*!< configuration register */ +#define HAU_DO0 REG32(HAU + 0x0000000CU) /*!< data output register 0 */ +#define HAU_DO1 REG32(HAU + 0x00000010U) /*!< data output register 1 */ +#define HAU_DO2 REG32(HAU + 0x00000014U) /*!< data output register 2 */ +#define HAU_DO3 REG32(HAU + 0x00000018U) /*!< data output register 3 */ +#define HAU_DO4 REG32(HAU + 0x0000001CU) /*!< data output register 4 */ +#define HAU_DO5 REG32(HAU + 0x00000324U) /*!< data output register 5 */ +#define HAU_DO6 REG32(HAU + 0x00000328U) /*!< data output register 6 */ +#define HAU_DO7 REG32(HAU + 0x0000032CU) /*!< data output register 7 */ +#define HAU_INTEN REG32(HAU + 0x00000020U) /*!< interrupt enable register */ +#define HAU_STAT REG32(HAU + 0x00000024U) /*!< status and interrupt flag register */ /* bits definitions */ /* HAU_CTL */ @@ -92,28 +89,26 @@ OF SUCH DAMAGE. #define HAU_STAT_BUSY BIT(3) /*!< busy bit */ /* constants definitions */ -/* structure for initialization of the hau */ -typedef struct -{ +/* structure for initialization of the hau */ +typedef struct { uint32_t algo; /*!< algorithm selection */ uint32_t mode; /*!< HAU mode selection */ uint32_t datatype; /*!< data type mode */ uint32_t keytype; /*!< key length mode */ -}hau_init_parameter_struct; +} hau_init_parameter_struct; /* structure for message digest result of the hau */ -typedef struct -{ +typedef struct { uint32_t out[8]; /* message digest result 0-7 */ -}hau_digest_parameter_struct; +} hau_digest_parameter_struct; -/* hau_ctl register value */ +/* hau_ctl register value */ #define HAU_ALGO_SHA1 ((uint32_t)0x00000000U) /*!< HAU function is SHA1 */ #define HAU_ALGO_SHA224 HAU_CTL_ALGM_1 /*!< HAU function is SHA224 */ #define HAU_ALGO_SHA256 (HAU_CTL_ALGM_1 | HAU_CTL_ALGM_0) /*!< HAU function is SHA256 */ #define HAU_ALGO_MD5 HAU_CTL_ALGM_0 /*!< HAU function is MD5 */ -#define HAU_MODE_HASH ((uint32_t)0x00000000U) /*!< HAU mode is HASH */ +#define HAU_MODE_HASH ((uint32_t)0x00000000U) /*!< HAU mode is HASH */ #define HAU_MODE_HMAC HAU_CTL_HMS /*!< HAU mode is HMAC */ #define CTL_DATAM_1(regval) (BITS(4,5) & ((uint32_t)(regval) << 4)) /*!< write value to HAU_CTL_DATAM bit field */ @@ -141,7 +136,7 @@ typedef struct #define HAU_FLAG_CALCULATION_COMPLETE HAU_STAT_CINT /*!< digest calculation is completed */ #define HAU_FLAG_DMA HAU_STAT_DMAS /*!< DMA is enabled (DMAE =1) or a transfer is processing */ #define HAU_FLAG_BUSY HAU_STAT_BUSY /*!< data block is in process */ -#define HAU_FLAG_INFIFO_NO_EMPTY HAU_CTL_DINE /*!< the input FIFO is not empty */ +#define HAU_FLAG_INFIFO_NO_EMPTY HAU_CTL_DINE /*!< the input FIFO is not empty */ #define HAU_INT_FLAG_DATA_INPUT HAU_STAT_DINT /*!< there is enough space (16 bytes) in the input FIFO */ #define HAU_INT_FLAG_CALCULATION_COMPLETE HAU_STAT_CINT /*!< digest calculation is completed */ @@ -151,9 +146,9 @@ typedef struct /* reset the HAU peripheral */ void hau_deinit(void); /* initialize the HAU peripheral parameters */ -void hau_init(hau_init_parameter_struct* initpara); +void hau_init(hau_init_parameter_struct *initpara); /* initialize the structure hau_initpara */ -void hau_init_parameter_init(hau_init_parameter_struct* initpara); +void hau_init_struct_para_init(hau_init_parameter_struct *initpara); /* reset the HAU processor core */ void hau_reset(void); /* configure the number of valid bits in last word of the message */ @@ -163,7 +158,7 @@ void hau_data_write(uint32_t data); /* return the number of words already written into the IN FIFO */ uint32_t hau_infifo_words_num_get(void); /* read the message digest result */ -void hau_digest_read(hau_digest_parameter_struct* digestpara); +void hau_digest_read(hau_digest_parameter_struct *digestpara); /* enable digest calculation */ void hau_digest_calculation_enable(void); /* configure single or multiple DMA is used, and digest calculation at the end of a DMA transfer or not */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_i2c.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_i2c.h index 414e089d..f9404c2d 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_i2c.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_i2c.h @@ -2,37 +2,33 @@ \file gd32f20x_i2c.h \brief definitions for the I2C - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x - \version 2019-04-16, V2.1.1, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -42,228 +38,221 @@ OF SUCH DAMAGE. #include "gd32f20x.h" /* I2Cx(x=0,1,2) definitions */ -#define I2C0 I2C_BASE /*!< I2C0 base address */ -#define I2C1 (I2C_BASE + 0x00000400U) /*!< I2C1 base address */ -#define I2C2 (I2C_BASE + 0x00006C00U) /*!< I2C2 base address */ +#define I2C0 I2C_BASE /*!< I2C0 base address */ +#define I2C1 (I2C_BASE + 0x00000400U) /*!< I2C1 base address */ +#define I2C2 (I2C_BASE + 0x00006C00U) /*!< I2C2 base address */ /* registers definitions */ -#define I2C_CTL0(i2cx) REG32((i2cx) + 0x00U) /*!< I2C control register 0 */ -#define I2C_CTL1(i2cx) REG32((i2cx) + 0x04U) /*!< I2C control register 1 */ -#define I2C_SADDR0(i2cx) REG32((i2cx) + 0x08U) /*!< I2C slave address register 0*/ -#define I2C_SADDR1(i2cx) REG32((i2cx) + 0x0CU) /*!< I2C slave address register */ -#define I2C_DATA(i2cx) REG32((i2cx) + 0x10U) /*!< I2C transfer buffer register */ -#define I2C_STAT0(i2cx) REG32((i2cx) + 0x14U) /*!< I2C transfer status register 0 */ -#define I2C_STAT1(i2cx) REG32((i2cx) + 0x18U) /*!< I2C transfer status register */ -#define I2C_CKCFG(i2cx) REG32((i2cx) + 0x1CU) /*!< I2C clock configure register */ -#define I2C_RT(i2cx) REG32((i2cx) + 0x20U) /*!< I2C rise time register */ +#define I2C_CTL0(i2cx) REG32((i2cx) + 0x00000000U) /*!< I2C control register 0 */ +#define I2C_CTL1(i2cx) REG32((i2cx) + 0x00000004U) /*!< I2C control register 1 */ +#define I2C_SADDR0(i2cx) REG32((i2cx) + 0x00000008U) /*!< I2C slave address register 0 */ +#define I2C_SADDR1(i2cx) REG32((i2cx) + 0x0000000CU) /*!< I2C slave address register 1 */ +#define I2C_DATA(i2cx) REG32((i2cx) + 0x00000010U) /*!< I2C transfer buffer register */ +#define I2C_STAT0(i2cx) REG32((i2cx) + 0x00000014U) /*!< I2C transfer status register 0 */ +#define I2C_STAT1(i2cx) REG32((i2cx) + 0x00000018U) /*!< I2C transfer status register */ +#define I2C_CKCFG(i2cx) REG32((i2cx) + 0x0000001CU) /*!< I2C clock configure register */ +#define I2C_RT(i2cx) REG32((i2cx) + 0x00000020U) /*!< I2C rise time register */ /* bits definitions */ /* I2Cx_CTL0 */ -#define I2C_CTL0_I2CEN BIT(0) /*!< peripheral enable */ -#define I2C_CTL0_SMBEN BIT(1) /*!< SMBus mode */ -#define I2C_CTL0_SMBSEL BIT(3) /*!< SMBus type */ -#define I2C_CTL0_ARPEN BIT(4) /*!< ARP enable */ -#define I2C_CTL0_PECEN BIT(5) /*!< PEC enable */ -#define I2C_CTL0_GCEN BIT(6) /*!< general call enable */ -#define I2C_CTL0_DISSTRC BIT(7) /*!< clock stretching disable (slave mode) */ -#define I2C_CTL0_START BIT(8) /*!< start generation */ -#define I2C_CTL0_STOP BIT(9) /*!< stop generation */ -#define I2C_CTL0_ACKEN BIT(10) /*!< acknowledge enable */ -#define I2C_CTL0_POAP BIT(11) /*!< acknowledge/PEC position (for data reception) */ -#define I2C_CTL0_PECTRANS BIT(12) /*!< packet error checking */ -#define I2C_CTL0_SALT BIT(13) /*!< SMBus alert */ -#define I2C_CTL0_SRESET BIT(15) /*!< software reset */ +#define I2C_CTL0_I2CEN BIT(0) /*!< peripheral enable */ +#define I2C_CTL0_SMBEN BIT(1) /*!< SMBus mode */ +#define I2C_CTL0_SMBSEL BIT(3) /*!< SMBus type */ +#define I2C_CTL0_ARPEN BIT(4) /*!< ARP enable */ +#define I2C_CTL0_PECEN BIT(5) /*!< PEC enable */ +#define I2C_CTL0_GCEN BIT(6) /*!< general call enable */ +#define I2C_CTL0_SS BIT(7) /*!< clock stretching disable (slave mode) */ +#define I2C_CTL0_START BIT(8) /*!< start generation */ +#define I2C_CTL0_STOP BIT(9) /*!< stop generation */ +#define I2C_CTL0_ACKEN BIT(10) /*!< acknowledge enable */ +#define I2C_CTL0_POAP BIT(11) /*!< acknowledge/PEC position (for data reception) */ +#define I2C_CTL0_PECTRANS BIT(12) /*!< packet error checking */ +#define I2C_CTL0_SALT BIT(13) /*!< SMBus alert */ +#define I2C_CTL0_SRESET BIT(15) /*!< software reset */ /* I2Cx_CTL1 */ -#define I2C_CTL1_I2CCLK BITS(0,5) /*!< I2CCLK[5:0] bits (peripheral clock frequency) */ -#define I2C_CTL1_ERRIE BIT(8) /*!< error interrupt enable */ -#define I2C_CTL1_EVIE BIT(9) /*!< event interrupt enable */ -#define I2C_CTL1_BUFIE BIT(10) /*!< buffer interrupt enable */ -#define I2C_CTL1_DMAON BIT(11) /*!< DMA requests enable */ -#define I2C_CTL1_DMALST BIT(12) /*!< DMA last transfer */ +#define I2C_CTL1_I2CCLK BITS(0,5) /*!< I2CCLK[5:0] bits (peripheral clock frequency) */ +#define I2C_CTL1_ERRIE BIT(8) /*!< error interrupt enable */ +#define I2C_CTL1_EVIE BIT(9) /*!< event interrupt enable */ +#define I2C_CTL1_BUFIE BIT(10) /*!< buffer interrupt enable */ +#define I2C_CTL1_DMAON BIT(11) /*!< DMA requests enable */ +#define I2C_CTL1_DMALST BIT(12) /*!< DMA last transfer */ /* I2Cx_SADDR0 */ -#define I2C_SADDR0_ADDRESS0 BIT(0) /*!< bit 0 of a 10-bit address */ -#define I2C_SADDR0_ADDRESS BITS(1,7) /*!< 7-bit address or bits 7:1 of a 10-bit address */ -#define I2C_SADDR0_ADDRESS_H BITS(8,9) /*!< highest two bits of a 10-bit address */ -#define I2C_SADDR0_ADDFORMAT BIT(15) /*!< address mode for the I2C slave */ +#define I2C_SADDR0_ADDRESS0 BIT(0) /*!< bit 0 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS BITS(1,7) /*!< 7-bit address or bits 7:1 of a 10-bit address */ +#define I2C_SADDR0_ADDRESS_H BITS(8,9) /*!< highest two bits of a 10-bit address */ +#define I2C_SADDR0_ADDFORMAT BIT(15) /*!< address mode for the I2C slave */ /* I2Cx_SADDR1 */ -#define I2C_SADDR1_DUADEN BIT(0) /*!< aual-address mode switch */ -#define I2C_SADDR1_ADDRESS2 BITS(1,7) /*!< second I2C address for the slave in dual-address mode */ +#define I2C_SADDR1_DUADEN BIT(0) /*!< aual-address mode switch */ +#define I2C_SADDR1_ADDRESS2 BITS(1,7) /*!< second I2C address for the slave in dual-address mode */ /* I2Cx_DATA */ -#define I2C_DATA_TRB BITS(0,7) /*!< 8-bit data register */ +#define I2C_DATA_TRB BITS(0,7) /*!< 8-bit data register */ /* I2Cx_STAT0 */ -#define I2C_STAT0_SBSEND BIT(0) /*!< start bit (master mode) */ -#define I2C_STAT0_ADDSEND BIT(1) /*!< address sent (master mode)/matched (slave mode) */ -#define I2C_STAT0_BTC BIT(2) /*!< byte transfer finished */ -#define I2C_STAT0_ADD10SEND BIT(3) /*!< 10-bit header sent (master mode) */ -#define I2C_STAT0_STPDET BIT(4) /*!< stop detection (slave mode) */ -#define I2C_STAT0_RBNE BIT(6) /*!< data register not empty (receivers) */ -#define I2C_STAT0_TBE BIT(7) /*!< data register empty (transmitters) */ -#define I2C_STAT0_BERR BIT(8) /*!< bus error */ -#define I2C_STAT0_LOSTARB BIT(9) /*!< arbitration lost (master mode) */ -#define I2C_STAT0_AERR BIT(10) /*!< acknowledge failure */ -#define I2C_STAT0_OUERR BIT(11) /*!< overrun/underrun */ -#define I2C_STAT0_PECERR BIT(12) /*!< PEC error in reception */ -#define I2C_STAT0_SMBTO BIT(14) /*!< timeout signal in SMBus mode */ -#define I2C_STAT0_SMBALT BIT(15) /*!< SMBus alert status */ +#define I2C_STAT0_SBSEND BIT(0) /*!< start bit (master mode) */ +#define I2C_STAT0_ADDSEND BIT(1) /*!< address sent (master mode)/matched (slave mode) */ +#define I2C_STAT0_BTC BIT(2) /*!< byte transfer finished */ +#define I2C_STAT0_ADD10SEND BIT(3) /*!< 10-bit header sent (master mode) */ +#define I2C_STAT0_STPDET BIT(4) /*!< stop detection (slave mode) */ +#define I2C_STAT0_RBNE BIT(6) /*!< data register not empty (receivers) */ +#define I2C_STAT0_TBE BIT(7) /*!< data register empty (transmitters) */ +#define I2C_STAT0_BERR BIT(8) /*!< bus error */ +#define I2C_STAT0_LOSTARB BIT(9) /*!< arbitration lost (master mode) */ +#define I2C_STAT0_AERR BIT(10) /*!< acknowledge failure */ +#define I2C_STAT0_OUERR BIT(11) /*!< overrun/underrun */ +#define I2C_STAT0_PECERR BIT(12) /*!< PEC error in reception */ +#define I2C_STAT0_SMBTO BIT(14) /*!< timeout signal in SMBus mode */ +#define I2C_STAT0_SMBALT BIT(15) /*!< SMBus alert status */ /* I2Cx_STAT1 */ -#define I2C_STAT1_MASTER BIT(0) /*!< master/slave */ -#define I2C_STAT1_I2CBSY BIT(1) /*!< bus busy */ -#define I2C_STAT1_TRS BIT(2) /*!< transmitter/receiver */ -#define I2C_STAT1_RXGC BIT(4) /*!< general call address (slave mode) */ -#define I2C_STAT1_DEFSMB BIT(5) /*!< SMBus device default address (slave mode) */ -#define I2C_STAT1_HSTSMB BIT(6) /*!< SMBus host header (slave mode) */ -#define I2C_STAT1_DUMODF BIT(7) /*!< dual flag (slave mode) */ -#define I2C_STAT1_ECV BITS(8,15) /*!< packet error checking register */ +#define I2C_STAT1_MASTER BIT(0) /*!< master/slave */ +#define I2C_STAT1_I2CBSY BIT(1) /*!< bus busy */ +#define I2C_STAT1_TR BIT(2) /*!< transmitter/receiver */ +#define I2C_STAT1_RXGC BIT(4) /*!< general call address (slave mode) */ +#define I2C_STAT1_DEFSMB BIT(5) /*!< SMBus device default address (slave mode) */ +#define I2C_STAT1_HSTSMB BIT(6) /*!< SMBus host header (slave mode) */ +#define I2C_STAT1_DUMODF BIT(7) /*!< dual flag (slave mode) */ +#define I2C_STAT1_PECV BITS(8,15) /*!< packet error checking value */ /* I2Cx_CKCFG */ -#define I2C_CKCFG_CLKC BITS(0,11) /*!< clock control register in fast/standard mode (master mode) */ -#define I2C_CKCFG_DTCY BIT(14) /*!< fast mode duty cycle */ -#define I2C_CKCFG_FAST BIT(15) /*!< I2C speed selection in master mode */ +#define I2C_CKCFG_CLKC BITS(0,11) /*!< clock control register in fast/standard mode (master mode) */ +#define I2C_CKCFG_DTCY BIT(14) /*!< fast mode duty cycle */ +#define I2C_CKCFG_FAST BIT(15) /*!< I2C speed selection in master mode */ /* I2Cx_RT */ -#define I2C_RT_RISETIME BITS(0,5) /*!< maximum rise time in fast/standard mode (Master mode) */ +#define I2C_RT_RISETIME BITS(0,5) /*!< maximum rise time in fast/standard mode (Master mode) */ /* constants definitions */ /* define the I2C bit position and its register index offset */ #define I2C_REGIDX_BIT(regidx, bitpos) (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos)) -#define I2C_REG_VAL(i2cx, offset) (REG32((i2cx) + (((uint32_t)(offset) & 0xFFFFU) >> 6))) -#define I2C_BIT_POS(val) ((uint32_t)(val) & 0x1FU) +#define I2C_REG_VAL(i2cx, offset) (REG32((i2cx) + (((uint32_t)(offset) & 0x0000FFFFU) >> 6))) +#define I2C_BIT_POS(val) ((uint32_t)(val) & 0x0000001FU) #define I2C_REGIDX_BIT2(regidx, bitpos, regidx2, bitpos2) (((uint32_t)(regidx2) << 22) | (uint32_t)((bitpos2) << 16)\ - | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) + | (((uint32_t)(regidx) << 6) | (uint32_t)(bitpos))) #define I2C_REG_VAL2(i2cx, offset) (REG32((i2cx) + ((uint32_t)(offset) >> 22))) -#define I2C_BIT_POS2(val) (((uint32_t)(val) & 0x1F0000U) >> 16) +#define I2C_BIT_POS2(val) (((uint32_t)(val) & 0x001F0000U) >> 16) /* register offset */ -#define I2C_CTL1_REG_OFFSET 0x04U /*!< CTL1 register offset */ -#define I2C_STAT0_REG_OFFSET 0x14U /*!< STAT0 register offset */ -#define I2C_STAT1_REG_OFFSET 0x18U /*!< STAT1 register offset */ -#define I2C_SAMCS_REG_OFFSET 0x80U /*!< SAMCS register offset */ +#define I2C_CTL1_REG_OFFSET ((uint32_t)0x00000004U) /*!< CTL1 register offset */ +#define I2C_STAT0_REG_OFFSET ((uint32_t)0x00000014U) /*!< STAT0 register offset */ +#define I2C_STAT1_REG_OFFSET ((uint32_t)0x00000018U) /*!< STAT1 register offset */ +#define I2C_SAMCS_REG_OFFSET ((uint32_t)0x00000080U) /*!< SAMCS register offset */ /* I2C flags */ -typedef enum -{ +typedef enum { /* flags in STAT0 register */ - I2C_FLAG_SBSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode */ - I2C_FLAG_ADDSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode */ - I2C_FLAG_BTC = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ - I2C_FLAG_ADD10SEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode */ - I2C_FLAG_STPDET = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode */ - I2C_FLAG_RBNE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving */ - I2C_FLAG_TBE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting */ - I2C_FLAG_BERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus */ - I2C_FLAG_LOSTARB = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode */ - I2C_FLAG_AERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error */ - I2C_FLAG_OUERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode */ - I2C_FLAG_PECERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data */ - I2C_FLAG_SMBTO = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode */ - I2C_FLAG_SMBALT = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus alert status */ + I2C_FLAG_SBSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode */ + I2C_FLAG_ADDSEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode */ + I2C_FLAG_BTC = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_FLAG_ADD10SEND = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode */ + I2C_FLAG_STPDET = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode */ + I2C_FLAG_RBNE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not empty during receiving */ + I2C_FLAG_TBE = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting */ + I2C_FLAG_BERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus */ + I2C_FLAG_LOSTARB = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode */ + I2C_FLAG_AERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error */ + I2C_FLAG_OUERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode */ + I2C_FLAG_PECERR = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data */ + I2C_FLAG_SMBTO = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode */ + I2C_FLAG_SMBALT = I2C_REGIDX_BIT(I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus alert status */ /* flags in STAT1 register */ - I2C_FLAG_MASTER = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 0U), /*!< a flag indicating whether I2C block is in master or slave mode */ - I2C_FLAG_I2CBSY = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 1U), /*!< busy flag */ - I2C_FLAG_TRS = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 2U), /*!< whether the I2C is a transmitter or a receiver */ - I2C_FLAG_RXGC = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 4U), /*!< general call address (00h) received */ - I2C_FLAG_DEFSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 5U), /*!< default address of SMBus device */ - I2C_FLAG_HSTSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 6U), /*!< SMBus host header detected in slave mode */ - I2C_FLAG_DUMOD = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 7U) /*!< dual flag in slave mode indicating which address is matched in dual-address mode */ -}i2c_flag_enum; + I2C_FLAG_MASTER = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 0U), /*!< a flag indicating whether I2C block is in master or slave mode */ + I2C_FLAG_I2CBSY = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 1U), /*!< busy flag */ + I2C_FLAG_TR = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 2U), /*!< whether the I2C is a transmitter or a receiver */ + I2C_FLAG_RXGC = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 4U), /*!< general call address (00h) received */ + I2C_FLAG_DEFSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 5U), /*!< default address of SMBus device */ + I2C_FLAG_HSTSMB = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 6U), /*!< SMBus host header detected in slave mode */ + I2C_FLAG_DUMOD = I2C_REGIDX_BIT(I2C_STAT1_REG_OFFSET, 7U) /*!< dual flag in slave mode indicating which address is matched in dual-address mode */ +} i2c_flag_enum; /* I2C interrupt flags */ -typedef enum -{ +typedef enum { /* interrupt flags in CTL1 register */ I2C_INT_FLAG_SBSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 0U), /*!< start condition sent out in master mode interrupt flag */ I2C_INT_FLAG_ADDSEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 1U), /*!< address is sent in master mode or received and matches in slave mode interrupt flag */ - I2C_INT_FLAG_BTC = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes */ + I2C_INT_FLAG_BTC = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 2U), /*!< byte transmission finishes interrupt flag */ I2C_INT_FLAG_ADD10SEND = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 3U), /*!< header of 10-bit address is sent in master mode interrupt flag */ I2C_INT_FLAG_STPDET = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 4U), /*!< stop condition detected in slave mode interrupt flag */ I2C_INT_FLAG_RBNE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 6U), /*!< I2C_DATA is not Empty during receiving interrupt flag */ - I2C_INT_FLAG_TBE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting interrupt flag */ + I2C_INT_FLAG_TBE = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 9U, I2C_STAT0_REG_OFFSET, 7U), /*!< I2C_DATA is empty during transmitting interrupt flag */ I2C_INT_FLAG_BERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 8U), /*!< a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag */ I2C_INT_FLAG_LOSTARB = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 9U), /*!< arbitration lost in master mode interrupt flag */ I2C_INT_FLAG_AERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 10U), /*!< acknowledge error interrupt flag */ I2C_INT_FLAG_OUERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 11U), /*!< over-run or under-run situation occurs in slave mode interrupt flag */ I2C_INT_FLAG_PECERR = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 12U), /*!< PEC error when receiving data interrupt flag */ I2C_INT_FLAG_SMBTO = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 14U), /*!< timeout signal in SMBus mode interrupt flag */ - I2C_INT_FLAG_SMBALT = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus Alert status interrupt flag */ -}i2c_interrupt_flag_enum; + I2C_INT_FLAG_SMBALT = I2C_REGIDX_BIT2(I2C_CTL1_REG_OFFSET, 8U, I2C_STAT0_REG_OFFSET, 15U), /*!< SMBus alert status interrupt flag */ +} i2c_interrupt_flag_enum; -/* I2C interrupt enable or disable */ -typedef enum -{ +/* I2C interrupt */ +typedef enum { /* interrupt in CTL1 register */ - I2C_INT_ERR = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 8U), /*!< error interrupt enable */ - I2C_INT_EV = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 9U), /*!< event interrupt enable */ - I2C_INT_BUF = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 10U), /*!< buffer interrupt enable */ -}i2c_interrupt_enum; + I2C_INT_ERR = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 8U), /*!< error interrupt */ + I2C_INT_EV = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 9U), /*!< event interrupt */ + I2C_INT_BUF = I2C_REGIDX_BIT(I2C_CTL1_REG_OFFSET, 10U), /*!< buffer interrupt */ +} i2c_interrupt_enum; /* SMBus/I2C mode switch and SMBus type selection */ -#define I2C_I2CMODE_ENABLE ((uint32_t)0x00000000U) /*!< I2C mode */ -#define I2C_SMBUSMODE_ENABLE I2C_CTL0_SMBEN /*!< SMBus mode */ +#define I2C_I2CMODE_ENABLE ((uint32_t)0x00000000U) /*!< I2C mode */ +#define I2C_SMBUSMODE_ENABLE I2C_CTL0_SMBEN /*!< SMBus mode */ /* SMBus/I2C mode switch and SMBus type selection */ -#define I2C_SMBUS_DEVICE ((uint32_t)0x00000000U) /*!< SMBus mode device type */ -#define I2C_SMBUS_HOST I2C_CTL0_SMBSEL /*!< SMBus mode host type */ +#define I2C_SMBUS_DEVICE ((uint32_t)0x00000000U) /*!< SMBus mode device type */ +#define I2C_SMBUS_HOST I2C_CTL0_SMBSEL /*!< SMBus mode host type */ /* I2C transfer direction */ -#define I2C_RECEIVER ((uint32_t)0x00000001U) /*!< receiver */ -#define I2C_TRANSMITTER ((uint32_t)0xFFFFFFFEU) /*!< transmitter */ +#define I2C_RECEIVER ((uint32_t)0x00000001U) /*!< receiver */ +#define I2C_TRANSMITTER ((uint32_t)0xFFFFFFFEU) /*!< transmitter */ /* whether or not to send an ACK */ -#define I2C_ACK_DISABLE ((uint32_t)0x00000000U) /*!< ACK will be not sent */ -#define I2C_ACK_ENABLE ((uint32_t)0x00000001U) /*!< ACK will be sent */ +#define I2C_ACK_DISABLE ((uint32_t)0x00000000U) /*!< ACK will be not sent */ +#define I2C_ACK_ENABLE I2C_CTL0_ACKEN /*!< ACK will be sent */ /* I2C POAP position*/ -#define I2C_ACKPOS_NEXT ((uint32_t)0x00000000U) /*!< ACKEN bit decides whether or not to send ACK for the next byte */ -#define I2C_ACKPOS_CURRENT ((uint32_t)0x00000001U) /*!< ACKEN bit decides whether or not to send ACK or not for the current byte */ - -/* I2C dual-address mode switch */ -#define I2C_DUADEN_DISABLE ((uint32_t)0x00000000U) /*!< dual-address mode disabled */ -#define I2C_DUADEN_ENABLE ((uint32_t)0x00000001U) /*!< dual-address mode enabled */ +#define I2C_ACKPOS_CURRENT ((uint32_t)0x00000000U) /*!< ACKEN bit decides whether or not to send ACK or not for the current byte */ +#define I2C_ACKPOS_NEXT I2C_CTL0_POAP /*!< ACKEN bit decides whether or not to send ACK for the next byte */ /* whether or not to stretch SCL low */ -#define I2C_SCLSTRETCH_DISABLE ((uint32_t)0x00000000U) /*!< SCL stretching is disabled */ -#define I2C_SCLSTRETCH_ENABLE I2C_CTL0_DISSTRC /*!< SCL stretching is enabled */ +#define I2C_SCLSTRETCH_ENABLE ((uint32_t)0x00000000U) /*!< enable SCL stretching */ +#define I2C_SCLSTRETCH_DISABLE I2C_CTL0_SS /*!< disable SCL stretching */ /* whether or not to response to a general call */ -#define I2C_GCEN_ENABLE I2C_CTL0_GCEN /*!< slave will response to a general call */ -#define I2C_GCEN_DISABLE ((uint32_t)0x00000000U) /*!< slave will not response to a general call */ +#define I2C_GCEN_ENABLE I2C_CTL0_GCEN /*!< slave will response to a general call */ +#define I2C_GCEN_DISABLE ((uint32_t)0x00000000U) /*!< slave will not response to a general call */ /* software reset I2C */ -#define I2C_SRESET_SET I2C_CTL0_SRESET /*!< I2C is under reset */ -#define I2C_SRESET_RESET ((uint32_t)0x00000000U) /*!< I2C is not under reset */ +#define I2C_SRESET_RESET ((uint32_t)0x00000000U) /*!< I2C is not under reset */ +#define I2C_SRESET_SET I2C_CTL0_SRESET /*!< I2C is under reset */ /* I2C DMA mode configure */ /* DMA mode switch */ -#define I2C_DMA_ON I2C_CTL1_DMAON /*!< DMA mode enabled */ -#define I2C_DMA_OFF ((uint32_t)0x00000000U) /*!< DMA mode disabled */ +#define I2C_DMA_OFF ((uint32_t)0x00000000U) /*!< disable DMA mode */ +#define I2C_DMA_ON I2C_CTL1_DMAON /*!< enable DMA mode */ /* flag indicating DMA last transfer */ -#define I2C_DMALST_ON I2C_CTL1_DMALST /*!< next DMA EOT is the last transfer */ -#define I2C_DMALST_OFF ((uint32_t)0x00000000U) /*!< next DMA EOT is not the last transfer */ +#define I2C_DMALST_OFF ((uint32_t)0x00000000U) /*!< next DMA EOT is not the last transfer */ +#define I2C_DMALST_ON I2C_CTL1_DMALST /*!< next DMA EOT is the last transfer */ /* I2C PEC configure */ /* PEC enable */ -#define I2C_PEC_ENABLE I2C_CTL0_PECEN /*!< PEC calculation on */ -#define I2C_PEC_DISABLE ((uint32_t)0x00000000U) /*!< PEC calculation off */ +#define I2C_PEC_DISABLE ((uint32_t)0x00000000U) /*!< PEC calculation off */ +#define I2C_PEC_ENABLE I2C_CTL0_PECEN /*!< PEC calculation on */ /* PEC transfer */ -#define I2C_PECTRANS_ENABLE I2C_CTL0_PECTRANS /*!< transfer PEC */ -#define I2C_PECTRANS_DISABLE ((uint32_t)0x00000000U) /*!< not transfer PEC value */ +#define I2C_PECTRANS_DISABLE ((uint32_t)0x00000000U) /*!< not transfer PEC value */ +#define I2C_PECTRANS_ENABLE I2C_CTL0_PECTRANS /*!< transfer PEC value */ /* I2C SMBus configure */ /* issue or not alert through SMBA pin */ -#define I2C_SALTSEND_ENABLE I2C_CTL0_SALT /*!< issue alert through SMBA pin */ -#define I2C_SALTSEND_DISABLE ((uint32_t)0x00000000U) /*!< not issue alert through SMBA */ +#define I2C_SALTSEND_DISABLE ((uint32_t)0x00000000U) /*!< not issue alert through SMBA */ +#define I2C_SALTSEND_ENABLE I2C_CTL0_SALT /*!< issue alert through SMBA pin */ /* ARP protocol in SMBus switch */ -#define I2C_ARP_ENABLE I2C_CTL0_ARPEN /*!< ARP is enabled */ -#define I2C_ARP_DISABLE ((uint32_t)0x00000000U) /*!< ARP is disabled */ +#define I2C_ARP_DISABLE ((uint32_t)0x00000000U) /*!< disable ARP */ +#define I2C_ARP_ENABLE I2C_CTL0_ARPEN /*!< enable ARP */ /* transmit I2C data */ #define DATA_TRANS(regval) (BITS(0,7) & ((uint32_t)(regval) << 0)) @@ -272,12 +261,12 @@ typedef enum #define DATA_RECV(regval) GET_BITS((uint32_t)(regval), 0, 7) /* I2C duty cycle in fast mode */ -#define I2C_DTCY_2 ((uint32_t)0x00000000U) /*!< I2C fast mode Tlow/Thigh = 2 */ -#define I2C_DTCY_16_9 I2C_CKCFG_DTCY /*!< I2C fast mode Tlow/Thigh = 16/9 */ +#define I2C_DTCY_2 ((uint32_t)0x00000000U) /*!< T_low/T_high = 2 in fast mode */ +#define I2C_DTCY_16_9 I2C_CKCFG_DTCY /*!< T_low/T_high = 16/9 in fast mode */ /* address mode for the I2C slave */ -#define I2C_ADDFORMAT_7BITS ((uint32_t)0x00000000U) /*!< address:7 bits */ -#define I2C_ADDFORMAT_10BITS I2C_SADDR0_ADDFORMAT /*!< address:10 bits */ +#define I2C_ADDFORMAT_7BITS ((uint32_t)0x00000000U) /*!< address format is 7 bits */ +#define I2C_ADDFORMAT_10BITS I2C_SADDR0_ADDFORMAT /*!< address format is 10 bits */ /* function declarations */ /* initialization functions */ @@ -287,7 +276,9 @@ void i2c_deinit(uint32_t i2c_periph); void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc); /* configure I2C address */ void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr); -/* SMBus type selection */ + +/* application function declarations */ +/* select SMBus type */ void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type); /* whether or not to send an ACK */ void i2c_ack_config(uint32_t i2c_periph, uint32_t ack); @@ -299,8 +290,6 @@ void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandire void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr); /* disable dual-address mode */ void i2c_dualaddr_disable(uint32_t i2c_periph); - -/* function configuration */ /* enable I2C */ void i2c_enable(uint32_t i2c_periph); /* disable I2C */ @@ -313,40 +302,39 @@ void i2c_stop_on_bus(uint32_t i2c_periph); void i2c_data_transmit(uint32_t i2c_periph, uint8_t data); /* I2C receive data function */ uint8_t i2c_data_receive(uint32_t i2c_periph); -/* enable I2C DMA mode */ -void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate); +/* configure I2C DMA mode */ +void i2c_dma_config(uint32_t i2c_periph, uint32_t dmastate); /* configure whether next DMA EOT is DMA last transfer or not */ void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast); /* whether to stretch SCL low when data is not ready in slave mode */ void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara); /* whether or not to response to a general call */ void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara); -/* software reset I2C */ +/* configure software reset of I2C */ void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset); - -/* I2C PEC calculation on or off */ -void i2c_pec_enable(uint32_t i2c_periph, uint32_t pecstate); -/* I2C whether to transfer PEC value */ -void i2c_pec_transfer_enable(uint32_t i2c_periph, uint32_t pecpara); -/* packet error checking value */ +/* configure I2C PEC calculation */ +void i2c_pec_config(uint32_t i2c_periph, uint32_t pecstate); +/* configure whether to transfer PEC value */ +void i2c_pec_transfer_config(uint32_t i2c_periph, uint32_t pecpara); +/* get packet error checking value */ uint8_t i2c_pec_value_get(uint32_t i2c_periph); -/* I2C issue alert through SMBA pin */ -void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara); -/* I2C ARP protocol in SMBus switch */ -void i2c_smbus_arp_enable(uint32_t i2c_periph, uint32_t arpstate); +/* configure I2C alert through SMBA pin */ +void i2c_smbus_alert_config(uint32_t i2c_periph, uint32_t smbuspara); +/* configure I2C ARP protocol in SMBus */ +void i2c_smbus_arp_config(uint32_t i2c_periph, uint32_t arpstate); /* interrupt & flag functions */ -/* check I2C flag is set or not */ +/* get I2C flag status */ FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag); -/* clear I2C flag */ +/* clear I2C flag status */ void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag); /* enable I2C interrupt */ void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); /* disable I2C interrupt */ void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt); -/* check I2C interrupt flag */ +/* get I2C interrupt flag status */ FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); -/* clear I2C interrupt flag */ +/* clear I2C interrupt flag status */ void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag); #endif /* GD32F20X_I2C_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_misc.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_misc.h index 93bdc821..640da184 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_misc.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_misc.h @@ -2,36 +2,33 @@ \file gd32f20x_misc.h \brief definitions for the MISC - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -42,26 +39,26 @@ OF SUCH DAMAGE. /* constants definitions */ /* set the RAM and FLASH base address */ -#define NVIC_VECTTAB_RAM ((uint32_t)0x20000000) /*!< RAM base address */ -#define NVIC_VECTTAB_FLASH ((uint32_t)0x08000000) /*!< Flash base address */ +#define NVIC_VECTTAB_RAM ((uint32_t)0x20000000U) /*!< RAM base address */ +#define NVIC_VECTTAB_FLASH ((uint32_t)0x08000000U) /*!< Flash base address */ /* set the NVIC vector table offset mask */ -#define NVIC_VECTTAB_OFFSET_MASK ((uint32_t)0x1FFFFF80) /*!< NVIC vector table offset mask */ +#define NVIC_VECTTAB_OFFSET_MASK ((uint32_t)0x1FFFFF80U) /*!< NVIC vector table offset mask */ /* the register key mask, if you want to do the write operation, you should write 0x5FA to VECTKEY bits */ -#define NVIC_AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) /*!< NVIC VECTKEY mask */ +#define NVIC_AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000U) /*!< NVIC VECTKEY mask */ /* priority group - define the pre-emption priority and the subpriority */ -#define NVIC_PRIGROUP_PRE0_SUB4 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority 4 bits for subpriority */ -#define NVIC_PRIGROUP_PRE1_SUB3 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority 3 bits for subpriority */ -#define NVIC_PRIGROUP_PRE2_SUB2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority 2 bits for subpriority */ -#define NVIC_PRIGROUP_PRE3_SUB1 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority 1 bits for subpriority */ -#define NVIC_PRIGROUP_PRE4_SUB0 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority 0 bits for subpriority */ +#define NVIC_PRIGROUP_PRE0_SUB4 ((uint32_t)0x00000700U) /*!< 0 bits for pre-emption priority, 4 bits for subpriority */ +#define NVIC_PRIGROUP_PRE1_SUB3 ((uint32_t)0x00000600U) /*!< 1 bits for pre-emption priority, 3 bits for subpriority */ +#define NVIC_PRIGROUP_PRE2_SUB2 ((uint32_t)0x00000500U) /*!< 2 bits for pre-emption priority, 2 bits for subpriority */ +#define NVIC_PRIGROUP_PRE3_SUB1 ((uint32_t)0x00000400U) /*!< 3 bits for pre-emption priority, 1 bits for subpriority */ +#define NVIC_PRIGROUP_PRE4_SUB0 ((uint32_t)0x00000300U) /*!< 4 bits for pre-emption priority, 0 bits for subpriority */ -/* choose the method to enter or exit the lowpower mode */ -#define SCB_SCR_SLEEPONEXIT ((uint8_t)0x02) /*!< choose the the system whether enter low power mode by exiting from ISR */ -#define SCB_SCR_SLEEPDEEP ((uint8_t)0x04) /*!< choose the the system enter the DEEPSLEEP mode or SLEEP mode */ -#define SCB_SCR_SEVONPEND ((uint8_t)0x10) /*!< choose the interrupt source that can wake up the lowpower mode */ +/* choose the method to enter or exit the low power mode */ +#define SCB_SCR_SLEEPONEXIT ((uint8_t)0x02U) /*!< choose the system whether enter low power mode by exiting from ISR */ +#define SCB_SCR_SLEEPDEEP ((uint8_t)0x04U) /*!< choose the system enter the DEEPSLEEP mode or SLEEP mode */ +#define SCB_SCR_SEVONPEND ((uint8_t)0x10U) /*!< choose the interrupt source that can wake up the low power mode */ #define SCB_LPM_SLEEP_EXIT_ISR SCB_SCR_SLEEPONEXIT /*!< low power mode by exiting from ISR */ #define SCB_LPM_DEEPSLEEP SCB_SCR_SLEEPDEEP /*!< DEEPSLEEP mode or SLEEP mode */ @@ -72,25 +69,20 @@ OF SUCH DAMAGE. #define SYSTICK_CLKSOURCE_HCLK ((uint32_t)0x00000004U) /*!< systick clock source is from HCLK */ /* function declarations */ -/* function configuration */ /* set the priority group */ void nvic_priority_group_set(uint32_t nvic_prigroup); -/* enable NVIC request */ +/* enable NVIC interrupt request */ void nvic_irq_enable(uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, uint8_t nvic_irq_sub_priority); -/* disable NVIC request */ +/* disable NVIC interrupt request */ void nvic_irq_disable(uint8_t nvic_irq); - /* set the NVIC vector table base address */ void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset); - /* set the state of the low power mode */ void system_lowpower_set(uint8_t lowpower_mode); /* reset the state of the low power mode */ void system_lowpower_reset(uint8_t lowpower_mode); - /* set the systick clock source */ void systick_clksource_set(uint32_t systick_clksource); #endif /* GD32F20X_MISC_H */ - diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_pmu.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_pmu.h index 56487285..839bc672 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_pmu.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_pmu.h @@ -2,36 +2,33 @@ \file gd32f20x_pmu.h \brief definitions for the PMU - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -64,6 +61,10 @@ OF SUCH DAMAGE. #define PMU_CS_WUPEN BIT(8) /*!< wakeup pin enable */ /* constants definitions */ +/* PMU ldo definitions */ +#define PMU_LDO_NORMAL ((uint32_t)0x00000000U) /*!< LDO normal work when PMU enter deepsleep mode */ +#define PMU_LDO_LOWPOWER PMU_CTL_LDOLP /*!< LDO work at low power status when PMU enter deepsleep mode */ + /* PMU low voltage detector threshold definitions */ #define CTL_LVDT(regval) (BITS(5,7)&((uint32_t)(regval) << 5)) #define PMU_LVDT_0 CTL_LVDT(0) /*!< voltage threshold is 2.2V */ @@ -80,10 +81,6 @@ OF SUCH DAMAGE. #define PMU_FLAG_STANDBY PMU_CS_STBF /*!< standby flag status */ #define PMU_FLAG_LVD PMU_CS_LVDF /*!< lvd flag status */ -/* PMU ldo definitions */ -#define PMU_LDO_NORMAL ((uint32_t)0x00000000U) /*!< LDO normal work when PMU enter deepsleep mode */ -#define PMU_LDO_LOWPOWER PMU_CTL_LDOLP /*!< LDO work at low power status when PMU enter deepsleep mode */ - /* PMU flag reset definitions */ #define PMU_FLAG_RESET_WAKEUP ((uint8_t)0x00U) /*!< wakeup flag reset */ #define PMU_FLAG_RESET_STANDBY ((uint8_t)0x01U) /*!< standby flag reset */ @@ -93,22 +90,22 @@ OF SUCH DAMAGE. #define WFE_CMD ((uint8_t)0x01U) /*!< use WFE command */ /* function declarations */ -/* initialization functions */ /* reset PMU registers */ void pmu_deinit(void); +/* LVD functions */ /* select low voltage detector threshold */ void pmu_lvd_select(uint32_t lvdt_n); /* disable PMU lvd */ void pmu_lvd_disable(void); /* set PMU mode */ -/* PMU work at sleep mode */ +/* PMU work in sleep mode */ void pmu_to_sleepmode(uint8_t sleepmodecmd); -/* PMU work at deepsleep mode */ +/* PMU work in deepsleep mode */ void pmu_to_deepsleepmode(uint32_t ldo, uint8_t deepsleepmodecmd); -/* PMU work at standby mode */ -void pmu_to_standbymode(uint8_t standbymodecmd); +/* PMU work in standby mode */ +void pmu_to_standbymode(void); /* enable PMU wakeup pin */ void pmu_wakeup_pin_enable(void); /* disable PMU wakeup pin */ @@ -124,6 +121,6 @@ void pmu_backup_write_disable(void); /* get flag state */ FlagStatus pmu_flag_get(uint32_t flag); /* clear flag bit */ -void pmu_flag_clear(uint32_t flag_reset); +void pmu_flag_clear(uint32_t flag); #endif /* GD32F20X_PMU_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_rcu.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_rcu.h index 4ac9bfa5..4b94875c 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_rcu.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_rcu.h @@ -2,36 +2,33 @@ \file gd32f20x_rcu.h \brief definitions for the RCU - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -359,8 +356,7 @@ OF SUCH DAMAGE. #define PLLTCFG_REG_OFFSET 0x98U /*!< PLLT configuration register offset */ /* peripheral clock enable */ -typedef enum -{ +typedef enum { /* AHB peripherals */ RCU_DMA0 = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 0U), /*!< DMA0 clock */ RCU_DMA1 = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 1U), /*!< DMA1 clock */ @@ -371,12 +367,12 @@ typedef enum RCU_ENET = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 14U), /*!< ENET clock */ RCU_ENETTX = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 15U), /*!< ENETTX clock */ RCU_ENETRX = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 16U), /*!< ENETRX clock */ - + RCU_DCI = RCU_REGIDX_BIT(AHB2EN_REG_OFFSET, 0U), /*!< DCI clock */ RCU_CAU = RCU_REGIDX_BIT(AHB2EN_REG_OFFSET, 4U), /*!< CAU clock */ RCU_HAU = RCU_REGIDX_BIT(AHB2EN_REG_OFFSET, 5U), /*!< HAU clock */ RCU_TRNG = RCU_REGIDX_BIT(AHB2EN_REG_OFFSET, 6U), /*!< TRNG clock */ - + /* APB1 peripherals */ RCU_TIMER1 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 0U), /*!< TIMER1 clock */ RCU_TIMER2 = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 1U), /*!< TIMER2 clock */ @@ -401,13 +397,13 @@ typedef enum RCU_BKPI = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 27U), /*!< BKPI clock */ RCU_PMU = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 28U), /*!< PMU clock */ RCU_DAC = RCU_REGIDX_BIT(APB1EN_REG_OFFSET, 29U), /*!< DAC clock */ - + RCU_RTC = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 15U), /*!< RTC clock */ - + RCU_I2C2 = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 23U), /*!< I2C2 clock */ RCU_UART6 = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 30U), /*!< UART6 clock */ RCU_UART7 = RCU_REGIDX_BIT(ADD_APB1EN_REG_OFFSET, 31U), /*!< UART7 clock */ - + /* APB2 peripherals */ RCU_AF = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 0U), /*!< alternate function clock */ RCU_GPIOA = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 2U), /*!< GPIOA clock */ @@ -427,34 +423,32 @@ typedef enum RCU_TIMER8 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 19U), /*!< TIMER8 clock */ RCU_TIMER9 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 20U), /*!< TIMER9 clock */ RCU_TIMER10 = RCU_REGIDX_BIT(APB2EN_REG_OFFSET, 21U), /*!< TIMER10 clock */ - + RCU_USART5 = RCU_REGIDX_BIT(ADD_APB2EN_REG_OFFSET, 24U), /*!< USART5 clock */ RCU_TLI = RCU_REGIDX_BIT(ADD_APB2EN_REG_OFFSET, 26U), /*!< TLI clock */ RCU_GPIOH = RCU_REGIDX_BIT(ADD_APB2EN_REG_OFFSET, 30U), /*!< GPIOH clock */ RCU_GPIOI = RCU_REGIDX_BIT(ADD_APB2EN_REG_OFFSET, 31U), /*!< GPIOI clock */ -}rcu_periph_enum; +} rcu_periph_enum; /* peripheral clock enable when sleep mode*/ -typedef enum -{ +typedef enum { /* AHB peripherals */ RCU_SRAM_SLP = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 2U), /*!< SRAM clock */ RCU_FMC_SLP = RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, 4U), /*!< FMC clock */ -}rcu_periph_sleep_enum; +} rcu_periph_sleep_enum; /* peripherals reset */ -typedef enum -{ +typedef enum { /* AHB peripherals */ RCU_USBFSRST = RCU_REGIDX_BIT(AHB1RST_REG_OFFSET, 12U), /*!< USBFS clock reset */ RCU_ENETRST = RCU_REGIDX_BIT(AHB1RST_REG_OFFSET, 14U), /*!< ENET clock reset */ - + RCU_DCIRST = RCU_REGIDX_BIT(AHB2RST_REG_OFFSET, 0U), /*!< DCI clock reset */ RCU_CAURST = RCU_REGIDX_BIT(AHB2RST_REG_OFFSET, 4U), /*!< CAU clock reset */ RCU_HAURST = RCU_REGIDX_BIT(AHB2RST_REG_OFFSET, 5U), /*!< HAU clock reset */ RCU_TRNGRST = RCU_REGIDX_BIT(AHB2RST_REG_OFFSET, 6U), /*!< TRNG clock reset */ - + /* APB1 peripherals */ RCU_TIMER1RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 0U), /*!< TIMER1 clock reset */ RCU_TIMER2RST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 1U), /*!< TIMER2 clock reset */ @@ -479,7 +473,7 @@ typedef enum RCU_BKPIRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 27U), /*!< BKPI clock reset */ RCU_PMURST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 28U), /*!< PMU clock reset */ RCU_DACRST = RCU_REGIDX_BIT(APB1RST_REG_OFFSET, 29U), /*!< DAC clock reset */ - + RCU_I2C2RST = RCU_REGIDX_BIT(ADD_APB1RST_REG_OFFSET, 23U), /*!< I2C2 clock reset */ RCU_UART6RST = RCU_REGIDX_BIT(ADD_APB1RST_REG_OFFSET, 30U), /*!< UART6 clock reset */ RCU_UART7RST = RCU_REGIDX_BIT(ADD_APB1RST_REG_OFFSET, 31U), /*!< UART7 clock reset */ @@ -509,11 +503,10 @@ typedef enum RCU_GPIOHRST = RCU_REGIDX_BIT(ADD_APB2RST_REG_OFFSET, 30U), /*!< GPIOH clock reset */ RCU_GPIOIRST = RCU_REGIDX_BIT(ADD_APB2RST_REG_OFFSET, 31U), /*!< GPIOI clock reset */ -}rcu_periph_reset_enum; +} rcu_periph_reset_enum; /* clock stabilization and peripheral reset flags */ -typedef enum -{ +typedef enum { /* clock stabilization flags */ RCU_FLAG_IRC8MSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 1U), /*!< IRC8M stabilization flags */ RCU_FLAG_HXTALSTB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 17U), /*!< HXTAL stabilization flags */ @@ -522,7 +515,7 @@ typedef enum RCU_FLAG_PLL2STB = RCU_REGIDX_BIT(CTL_REG_OFFSET, 29U), /*!< PLL2 stabilization flags */ RCU_FLAG_LXTALSTB = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 1U), /*!< LXTAL stabilization flags */ - + RCU_FLAG_IRC40KSTB = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 1U), /*!< IRC40K stabilization flags */ RCU_FLAG_PLLTSTB = RCU_REGIDX_BIT(PLLTCTL_REG_OFFSET, 29U), /*!< PLLT stabilization flags */ @@ -534,11 +527,10 @@ typedef enum RCU_FLAG_FWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 29U), /*!< FWDGT reset flags */ RCU_FLAG_WWDGTRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 30U), /*!< WWDGT reset flags */ RCU_FLAG_LPRST = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 31U), /*!< low-power reset flags */ -}rcu_flag_enum; +} rcu_flag_enum; /* clock stabilization and ckm interrupt flags */ -typedef enum -{ +typedef enum { RCU_INT_FLAG_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 0U), /*!< IRC40K stabilization interrupt flag */ RCU_INT_FLAG_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 1U), /*!< LXTAL stabilization interrupt flag */ RCU_INT_FLAG_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 2U), /*!< IRC8M stabilization interrupt flag */ @@ -548,11 +540,10 @@ typedef enum RCU_INT_FLAG_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 6U), /*!< PLL2 stabilization interrupt flag */ RCU_INT_FLAG_CKM = RCU_REGIDX_BIT(INT_REG_OFFSET, 7U), /*!< HXTAL clock stuck interrupt flag */ RCU_INT_FLAG_PLLTSTB = RCU_REGIDX_BIT(PLLTINT_REG_OFFSET, 6U), /*!< PLLT stabilization interrupt flag */ -}rcu_int_flag_enum; +} rcu_int_flag_enum; /* clock stabilization and stuck interrupt flags clear */ -typedef enum -{ +typedef enum { RCU_INT_FLAG_IRC40KSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 16U), /*!< IRC40K stabilization interrupt flags clear */ RCU_INT_FLAG_LXTALSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 17U), /*!< LXTAL stabilization interrupt flags clear */ RCU_INT_FLAG_IRC8MSTB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 18U), /*!< IRC8M stabilization interrupt flags clear */ @@ -562,11 +553,10 @@ typedef enum RCU_INT_FLAG_PLL2STB_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 22U), /*!< PLL2 stabilization interrupt flags clear */ RCU_INT_FLAG_CKM_CLR = RCU_REGIDX_BIT(INT_REG_OFFSET, 23U), /*!< CKM interrupt flags clear */ RCU_INT_FLAG_PLLTSTB_CLR = RCU_REGIDX_BIT(PLLTINT_REG_OFFSET, 22U), /*!< PLLT stabilization interrupt clear */ -}rcu_int_flag_clear_enum; +} rcu_int_flag_clear_enum; /* clock stabilization interrupt enable or disable */ -typedef enum -{ +typedef enum { RCU_INT_IRC40KSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 8U), /*!< IRC40K stabilization interrupt */ RCU_INT_LXTALSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 9U), /*!< LXTAL stabilization interrupt */ RCU_INT_IRC8MSTB = RCU_REGIDX_BIT(INT_REG_OFFSET, 10U), /*!< IRC8M stabilization interrupt */ @@ -575,33 +565,31 @@ typedef enum RCU_INT_PLL1STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 13U), /*!< PLL1 stabilization interrupt */ RCU_INT_PLL2STB = RCU_REGIDX_BIT(INT_REG_OFFSET, 14U), /*!< PLL2 stabilization interrupt */ RCU_INT_PLLTSTB = RCU_REGIDX_BIT(PLLTINT_REG_OFFSET, 14U), /*!< PLLT stabilization interrupt */ -}rcu_int_enum; +} rcu_int_enum; /* oscillator types */ -typedef enum -{ +typedef enum { RCU_IRC8M = RCU_REGIDX_BIT(CTL_REG_OFFSET, 0U), /*!< IRC8M */ RCU_HXTAL = RCU_REGIDX_BIT(CTL_REG_OFFSET, 16U), /*!< HXTAL */ RCU_PLL_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 24U), /*!< PLL */ RCU_PLL1_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 26U), /*!< PLL1 */ RCU_PLL2_CK = RCU_REGIDX_BIT(CTL_REG_OFFSET, 28U), /*!< PLL2 */ - + RCU_LXTAL = RCU_REGIDX_BIT(BDCTL_REG_OFFSET, 0U), /*!< LXTAL */ RCU_IRC40K = RCU_REGIDX_BIT(RSTSCK_REG_OFFSET, 0U), /*!< IRC40K */ RCU_PLLT_CK = RCU_REGIDX_BIT(PLLTCTL_REG_OFFSET, 28U), /*!< PLLT */ -}rcu_osci_type_enum; +} rcu_osci_type_enum; /* rcu clock frequency */ -typedef enum -{ +typedef enum { CK_SYS = 0, /*!< system clock */ CK_AHB, /*!< AHB clock */ CK_APB1, /*!< APB1 clock */ CK_APB2, /*!< APB2 clock */ -}rcu_clock_freq_enum; +} rcu_clock_freq_enum; /* RCU_CFG0 register bit define */ /* system clock source selection */ @@ -975,10 +963,6 @@ typedef enum #define RCU_PLLTSRC_IRC8M ((uint32_t)0x00000000U) /*!< IRC8M selected as source clock of PLLT */ #define RCU_PLLTSRC_HXTAL RCU_PLLTCFG_PLLTSEL /*!< HXTAL selected as source clock of PLLT */ -#ifdef __cplusplus - extern "C" { -#endif - /* function declarations */ /* initialization, peripheral clock enable/disable functions */ /* deinitialize the RCU */ @@ -1018,7 +1002,7 @@ void rcu_ckout0_config(uint32_t ckout0_src, uint32_t ckout0_div); void rcu_ckout1_config(uint32_t ckout1_src, uint32_t ckout1_div); /* configure the PLL clock source selection and PLL multiply factor */ -void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul); +void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul); /* configure the PREDV0 division factor and clock source */ void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div); @@ -1048,19 +1032,6 @@ ErrStatus rcu_pllt_vco_config(uint32_t pllt_psc, uint32_t pllt_mul, uint32_t ppl /* configure the TLI prescaler factor */ void rcu_tli_clock_config(uint32_t tli_psc); -/* get the clock stabilization and periphral reset flags */ -FlagStatus rcu_flag_get(rcu_flag_enum flag); -/* clear the reset flag */ -void rcu_all_reset_flag_clear(void); -/* get the clock stabilization interrupt and ckm flags */ -FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag); -/* clear the interrupt flags */ -void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear); -/* enable the stabilization interrupt */ -void rcu_interrupt_enable(rcu_int_enum stab_int); -/* disable the stabilization interrupt */ -void rcu_interrupt_disable(rcu_int_enum stab_int); - /* configure the LXTAL drive capability */ void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap); /* wait for oscillator stabilization flags is SET or oscillator startup is timeout */ @@ -1077,17 +1048,24 @@ void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci); void rcu_hxtal_clock_monitor_enable(void); /* disable the HXTAL clock monitor */ void rcu_hxtal_clock_monitor_disable(void); - /* set the IRC8M adjust value */ void rcu_irc8m_adjust_value_set(uint8_t irc8m_adjval); - /* set the deep sleep mode voltage */ void rcu_deepsleep_voltage_set(uint32_t dsvol); - /* get the system clock, bus and peripheral clock frequency */ uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock); -#ifdef __cplusplus -} -#endif +/* get the clock stabilization and peripheral reset flags */ +FlagStatus rcu_flag_get(rcu_flag_enum flag); +/* clear the reset flag */ +void rcu_all_reset_flag_clear(void); +/* enable the stabilization interrupt */ +void rcu_interrupt_enable(rcu_int_enum stab_int); +/* disable the stabilization interrupt */ +void rcu_interrupt_disable(rcu_int_enum stab_int); +/* get the clock stabilization interrupt and ckm flags */ +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag); +/* clear the interrupt flags */ +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear); + #endif /* GD32F20X_RCU_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_rtc.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_rtc.h index 3f7bab19..6d45c3de 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_rtc.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_rtc.h @@ -2,36 +2,33 @@ \file gd32f20x_rtc.h \brief definitions for the RTC - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -41,19 +38,19 @@ OF SUCH DAMAGE. #include "gd32f20x.h" /* RTC definitions */ -#define RTC RTC_BASE +#define RTC RTC_BASE /*!< RTC base address */ /* registers definitions */ -#define RTC_INTEN REG32(RTC + 0x00U) /*!< interrupt enable register */ -#define RTC_CTL REG32(RTC + 0x04U) /*!< control register */ -#define RTC_PSCH REG32(RTC + 0x08U) /*!< prescaler high register */ -#define RTC_PSCL REG32(RTC + 0x0CU) /*!< prescaler low register */ -#define RTC_DIVH REG32(RTC + 0x10U) /*!< divider high register */ -#define RTC_DIVL REG32(RTC + 0x14U) /*!< divider low register */ -#define RTC_CNTH REG32(RTC + 0x18U) /*!< counter high register */ -#define RTC_CNTL REG32(RTC + 0x1CU) /*!< counter low register */ -#define RTC_ALRMH REG32(RTC + 0x20U) /*!< alarm high register */ -#define RTC_ALRML REG32(RTC + 0x24U) /*!< alarm low register */ +#define RTC_INTEN REG32(RTC + 0x00000000U) /*!< interrupt enable register */ +#define RTC_CTL REG32(RTC + 0x00000004U) /*!< control register */ +#define RTC_PSCH REG32(RTC + 0x00000008U) /*!< prescaler high register */ +#define RTC_PSCL REG32(RTC + 0x0000000CU) /*!< prescaler low register */ +#define RTC_DIVH REG32(RTC + 0x00000010U) /*!< divider high register */ +#define RTC_DIVL REG32(RTC + 0x00000014U) /*!< divider low register */ +#define RTC_CNTH REG32(RTC + 0x00000018U) /*!< counter high register */ +#define RTC_CNTL REG32(RTC + 0x0000001CU) /*!< counter low register */ +#define RTC_ALRMH REG32(RTC + 0x00000020U) /*!< alarm high register */ +#define RTC_ALRML REG32(RTC + 0x00000024U) /*!< alarm low register */ /* bits definitions */ /* RTC_INTEN */ @@ -69,28 +66,20 @@ OF SUCH DAMAGE. #define RTC_CTL_CMF BIT(4) /*!< configuration mode flag */ #define RTC_CTL_LWOFF BIT(5) /*!< last write operation finished flag */ -/* RTC_PSCH */ +/* RTC_PSC */ #define RTC_PSCH_PSC BITS(0,3) /*!< prescaler high value */ - -/* RTC_PSCL */ #define RTC_PSCL_PSC BITS(0,15) /*!< prescaler low value */ -/* RTC_DIVH */ +/* RTC_DIV */ #define RTC_DIVH_DIV BITS(0,3) /*!< divider high value */ - -/* RTC_DIVL */ #define RTC_DIVL_DIV BITS(0,15) /*!< divider low value */ -/* RTC_CNTH */ +/* RTC_CNT */ #define RTC_CNTH_CNT BITS(0,15) /*!< counter high value */ - -/* RTC_CNTL */ #define RTC_CNTL_CNT BITS(0,15) /*!< counter low value */ -/* RTC_ALRMH */ +/* RTC_ALRM */ #define RTC_ALRMH_ALRM BITS(0,15) /*!< alarm high value */ - -/* RTC_ALRML */ #define RTC_ALRML_ALRM BITS(0,15) /*!< alarm low value */ /* constants definitions */ @@ -99,11 +88,6 @@ OF SUCH DAMAGE. #define RTC_INT_ALARM RTC_INTEN_ALRMIE /*!< alarm interrupt enable */ #define RTC_INT_OVERFLOW RTC_INTEN_OVIE /*!< overflow interrupt enable */ -/* RTC interrupt flag definitions */ -#define RTC_INT_FLAG_SECOND RTC_CTL_SCIF /*!< second interrupt flag */ -#define RTC_INT_FLAG_ALARM RTC_CTL_ALRMIF /*!< alarm interrupt flag */ -#define RTC_INT_FLAG_OVERFLOW RTC_CTL_OVIF /*!< overflow interrupt flag */ - /* RTC flag definitions */ #define RTC_FLAG_SECOND RTC_CTL_SCIF /*!< second interrupt flag */ #define RTC_FLAG_ALARM RTC_CTL_ALRMIF /*!< alarm interrupt flag */ @@ -112,40 +96,36 @@ OF SUCH DAMAGE. #define RTC_FLAG_LWOF RTC_CTL_LWOFF /*!< last write operation finished flag */ /* function declarations */ -/* initialization functions */ /* enter RTC configuration mode */ void rtc_configuration_mode_enter(void); /* exit RTC configuration mode */ void rtc_configuration_mode_exit(void); -/* set RTC counter value */ -void rtc_counter_set(uint32_t cnt); -/* set RTC prescaler value */ -void rtc_prescaler_set(uint32_t psc); /* operation functions */ /* wait RTC last write operation finished flag set */ void rtc_lwoff_wait(void); /* wait RTC registers synchronized flag set */ void rtc_register_sync_wait(void); -/* set RTC alarm value */ -void rtc_alarm_config(uint32_t alarm); + /* get RTC counter value */ uint32_t rtc_counter_get(void); +/* set RTC counter value */ +void rtc_counter_set(uint32_t cnt); +/* set RTC prescaler value */ +void rtc_prescaler_set(uint32_t psc); +/* set RTC alarm value */ +void rtc_alarm_config(uint32_t alarm); /* get RTC divider value */ uint32_t rtc_divider_get(void); +/* enable RTC interrupt */ +void rtc_interrupt_enable(uint32_t interrupt); +/* disable RTC interrupt */ +void rtc_interrupt_disable(uint32_t interrupt); /* flag & interrupt functions */ /* get RTC flag status */ FlagStatus rtc_flag_get(uint32_t flag); /* clear RTC flag status */ void rtc_flag_clear(uint32_t flag); -/* get RTC interrupt flag status */ -FlagStatus rtc_interrupt_flag_get(uint32_t flag); -/* clear RTC interrupt flag status */ -void rtc_interrupt_flag_clear(uint32_t flag); -/* enable RTC interrupt */ -void rtc_interrupt_enable(uint32_t interrupt); -/* disable RTC interrupt */ -void rtc_interrupt_disable(uint32_t interrupt); #endif /* GD32F20X_RTC_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_sdio.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_sdio.h index d33510b6..6e85d251 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_sdio.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_sdio.h @@ -2,36 +2,33 @@ \file gd32f20x_sdio.h \brief definitions for the SDIO - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_spi.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_spi.h index bf27bfe2..80d03c7a 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_spi.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_spi.h @@ -2,36 +2,33 @@ \file gd32f20x_spi.h \brief definitions for the SPI - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -45,17 +42,17 @@ OF SUCH DAMAGE. #define SPI1 SPI_BASE #define SPI2 (SPI_BASE + 0x00000400U) -/* SPI registers definitions */ -#define SPI_CTL0(spix) REG32((spix) + 0x00U) /*!< SPI control register 0 */ -#define SPI_CTL1(spix) REG32((spix) + 0x04U) /*!< SPI control register 1*/ -#define SPI_STAT(spix) REG32((spix) + 0x08U) /*!< SPI status register */ -#define SPI_DATA(spix) REG32((spix) + 0x0CU) /*!< SPI data register */ -#define SPI_CRCPOLY(spix) REG32((spix) + 0x10U) /*!< SPI CRC polynomial register */ -#define SPI_RCRC(spix) REG32((spix) + 0x14U) /*!< SPI receive CRC register */ -#define SPI_TCRC(spix) REG32((spix) + 0x18U) /*!< SPI transmit CRC register */ -#define SPI_I2SCTL(spix) REG32((spix) + 0x1CU) /*!< SPI I2S control register */ -#define SPI_I2SPSC(spix) REG32((spix) + 0x20U) /*!< SPI I2S clock prescaler register */ -#define SPI_QCTL(spix) REG32((spix) + 0x80U) /*!< SPI quad mode control register(only SPI0) */ +/* registers definitions */ +#define SPI_CTL0(spix) REG32((spix) + 0x00000000U) /*!< SPI control register 0 */ +#define SPI_CTL1(spix) REG32((spix) + 0x00000004U) /*!< SPI control register 1*/ +#define SPI_STAT(spix) REG32((spix) + 0x00000008U) /*!< SPI status register */ +#define SPI_DATA(spix) REG32((spix) + 0x0000000CU) /*!< SPI data register */ +#define SPI_CRCPOLY(spix) REG32((spix) + 0x00000010U) /*!< SPI CRC polynomial register */ +#define SPI_RCRC(spix) REG32((spix) + 0x00000014U) /*!< SPI receive CRC register */ +#define SPI_TCRC(spix) REG32((spix) + 0x00000018U) /*!< SPI transmit CRC register */ +#define SPI_I2SCTL(spix) REG32((spix) + 0x0000001CU) /*!< SPI I2S control register */ +#define SPI_I2SPSC(spix) REG32((spix) + 0x00000020U) /*!< SPI I2S clock prescaler register */ +#define SPI_QCTL(spix) REG32((spix) + 0x00000080U) /*!< SPI quad mode control register(only available in SPI0) */ /* bits definitions */ /* SPI_CTL0 */ @@ -75,8 +72,8 @@ OF SUCH DAMAGE. #define SPI_CTL0_BDEN BIT(15) /*!< bidirectional enable */ /* SPI_CTL1 */ -#define SPI_CTL1_DMAREN BIT(0) /*!< receive buffer dma enable */ -#define SPI_CTL1_DMATEN BIT(1) /*!< transmit buffer dma enable */ +#define SPI_CTL1_DMAREN BIT(0) /*!< receive buffer DMA enable */ +#define SPI_CTL1_DMATEN BIT(1) /*!< transmit buffer DMA enable */ #define SPI_CTL1_NSSDRV BIT(2) /*!< drive NSS output */ #define SPI_CTL1_ERRIE BIT(5) /*!< errors interrupt enable */ #define SPI_CTL1_RBNEIE BIT(6) /*!< receive buffer not empty interrupt enable */ @@ -119,15 +116,14 @@ OF SUCH DAMAGE. #define SPI_I2SPSC_OF BIT(8) /*!< odd factor for the prescaler */ #define SPI_I2SPSC_MCKOEN BIT(9) /*!< I2S MCK output enable */ -/* SPI_QCTL(only for SPI0) */ +/* SPI_QCTL(only available in SPI0) */ #define SPI_QCTL_QMOD BIT(0) /*!< quad-SPI mode enable */ #define SPI_QCTL_QRD BIT(1) /*!< quad-SPI mode read select */ #define SPI_QCTL_IO23_DRV BIT(2) /*!< drive SPI_IO2 and SPI_IO3 enable */ /* constants definitions */ /* SPI and I2S parameter struct definitions */ -typedef struct -{ +typedef struct { uint32_t device_mode; /*!< SPI master or slave */ uint32_t trans_mode; /*!< SPI transfer type */ uint32_t frame_size; /*!< SPI frame size */ @@ -135,7 +131,7 @@ typedef struct uint32_t endian; /*!< SPI big endian or little endian */ uint32_t clock_polarity_phase; /*!< SPI clock phase and polarity */ uint32_t prescale; /*!< SPI prescaler factor */ -}spi_parameter_struct; +} spi_parameter_struct; /* SPI mode definitions */ #define SPI_MASTER (SPI_CTL0_MSTMOD | SPI_CTL0_SWNSS) /*!< SPI as master */ @@ -143,7 +139,7 @@ typedef struct /* SPI bidirectional transfer direction */ #define SPI_BIDIRECTIONAL_TRANSMIT SPI_CTL0_BDOEN /*!< SPI work in transmit-only mode */ -#define SPI_BIDIRECTIONAL_RECEIVE ~SPI_CTL0_BDOEN /*!< SPI work in receive-only mode */ +#define SPI_BIDIRECTIONAL_RECEIVE (~SPI_CTL0_BDOEN) /*!< SPI work in receive-only mode */ /* SPI transmit type */ #define SPI_TRANSMODE_FULLDUPLEX ((uint32_t)0x00000000U) /*!< SPI receive and send data at fullduplex communication */ @@ -169,16 +165,16 @@ typedef struct #define SPI_CK_PL_LOW_PH_2EDGE SPI_CTL0_CKPH /*!< SPI clock polarity is low level and phase is second edge */ #define SPI_CK_PL_HIGH_PH_2EDGE (SPI_CTL0_CKPL | SPI_CTL0_CKPH) /*!< SPI clock polarity is high level and phase is second edge */ -/* SPI clock prescale factor */ +/* SPI clock prescaler factor */ #define CTL0_PSC(regval) (BITS(3,5) & ((uint32_t)(regval) << 3)) -#define SPI_PSC_2 CTL0_PSC(0) /*!< SPI clock prescale factor is 2 */ -#define SPI_PSC_4 CTL0_PSC(1) /*!< SPI clock prescale factor is 4 */ -#define SPI_PSC_8 CTL0_PSC(2) /*!< SPI clock prescale factor is 8 */ -#define SPI_PSC_16 CTL0_PSC(3) /*!< SPI clock prescale factor is 16 */ -#define SPI_PSC_32 CTL0_PSC(4) /*!< SPI clock prescale factor is 32 */ -#define SPI_PSC_64 CTL0_PSC(5) /*!< SPI clock prescale factor is 64 */ -#define SPI_PSC_128 CTL0_PSC(6) /*!< SPI clock prescale factor is 128 */ -#define SPI_PSC_256 CTL0_PSC(7) /*!< SPI clock prescale factor is 256 */ +#define SPI_PSC_2 CTL0_PSC(0) /*!< SPI clock prescaler factor is 2 */ +#define SPI_PSC_4 CTL0_PSC(1) /*!< SPI clock prescaler factor is 4 */ +#define SPI_PSC_8 CTL0_PSC(2) /*!< SPI clock prescaler factor is 8 */ +#define SPI_PSC_16 CTL0_PSC(3) /*!< SPI clock prescaler factor is 16 */ +#define SPI_PSC_32 CTL0_PSC(4) /*!< SPI clock prescaler factor is 32 */ +#define SPI_PSC_64 CTL0_PSC(5) /*!< SPI clock prescaler factor is 64 */ +#define SPI_PSC_128 CTL0_PSC(6) /*!< SPI clock prescaler factor is 128 */ +#define SPI_PSC_256 CTL0_PSC(7) /*!< SPI clock prescaler factor is 256 */ /* I2S audio sample rate */ #define I2S_AUDIOSAMPLE_8K ((uint32_t)8000U) /*!< I2S audio sample rate is 8KHz */ @@ -221,7 +217,7 @@ typedef struct #define I2S_CKPL_LOW ((uint32_t)0x00000000U) /*!< I2S clock polarity low level */ #define I2S_CKPL_HIGH SPI_I2SCTL_CKPL /*!< I2S clock polarity high level */ -/* SPI DMA constants definitions */ +/* SPI DMA constants definitions */ #define SPI_DMA_TRANSMIT ((uint8_t)0x00U) /*!< SPI transmit data use DMA */ #define SPI_DMA_RECEIVE ((uint8_t)0x01U) /*!< SPI receive data use DMA */ @@ -230,9 +226,9 @@ typedef struct #define SPI_CRC_RX ((uint8_t)0x01U) /*!< SPI receive CRC value */ /* SPI/I2S interrupt enable/disable constants definitions */ -#define SPI_I2S_INT_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt */ -#define SPI_I2S_INT_RBNE ((uint8_t)0x01U) /*!< receive buffer not empty interrupt */ -#define SPI_I2S_INT_ERR ((uint8_t)0x02U) /*!< error interrupt */ +#define SPI_I2S_INT_TBE SPI_CTL1_TBEIE /*!< transmit buffer empty interrupt */ +#define SPI_I2S_INT_RBNE SPI_CTL1_RBNEIE /*!< receive buffer not empty interrupt */ +#define SPI_I2S_INT_ERR SPI_CTL1_ERRIE /*!< error interrupt */ /* SPI/I2S interrupt flag constants definitions */ #define SPI_I2S_INT_FLAG_TBE ((uint8_t)0x00U) /*!< transmit buffer empty interrupt flag */ @@ -242,7 +238,7 @@ typedef struct #define SPI_INT_FLAG_CRCERR ((uint8_t)0x04U) /*!< CRC error interrupt flag */ #define I2S_INT_FLAG_TXURERR ((uint8_t)0x05U) /*!< underrun error interrupt flag */ -/* SPI/I2S flag definitions */ +/* SPI/I2S flag definitions */ #define SPI_FLAG_RBNE SPI_STAT_RBNE /*!< receive buffer not empty flag */ #define SPI_FLAG_TBE SPI_STAT_TBE /*!< transmit buffer empty flag */ #define SPI_FLAG_CRCERR SPI_STAT_CRCERR /*!< CRC error flag */ @@ -257,18 +253,19 @@ typedef struct #define I2S_FLAG_TRANS SPI_STAT_TRANS /*!< transmit on-going flag */ /* function declarations */ -/* SPI/I2S deinitialization and initialization functions */ +/* SPI deinitialization and initialization functions */ /* reset SPI and I2S */ void spi_i2s_deinit(uint32_t spi_periph); /* initialize the parameters of SPI structure with the default values */ -void spi_struct_para_init(spi_parameter_struct* spi_struct); -/* initialize SPI parameter */ -void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct); +void spi_struct_para_init(spi_parameter_struct *spi_struct); +/* initialize SPI parameters */ +void spi_init(uint32_t spi_periph, spi_parameter_struct *spi_struct); /* enable SPI */ void spi_enable(uint32_t spi_periph); /* disable SPI */ void spi_disable(uint32_t spi_periph); +/* I2S initialization functions */ /* initialize I2S parameter */ void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ckpl); /* configure I2S prescaler */ @@ -288,21 +285,21 @@ void spi_nss_internal_high(uint32_t spi_periph); /* SPI NSS pin low level in software mode */ void spi_nss_internal_low(uint32_t spi_periph); -/* DMA communication */ +/* DMA functions */ /* enable SPI DMA */ void spi_dma_enable(uint32_t spi_periph, uint8_t dma); /* disable SPI DMA */ void spi_dma_disable(uint32_t spi_periph, uint8_t dma); -/* normal mode communication */ -/* configure SPI/I2S data frame format */ +/* communication functions */ +/* configure SPI data frame format */ void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format); +/* configure SPI bidirectional transfer direction */ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction); /* SPI transmit data */ void spi_i2s_data_transmit(uint32_t spi_periph, uint16_t data); /* SPI receive data */ uint16_t spi_i2s_data_receive(uint32_t spi_periph); -/* configure SPI bidirectional transfer direction */ -void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction); /* SPI CRC functions */ /* set SPI CRC polynomial */ @@ -317,30 +314,31 @@ void spi_crc_off(uint32_t spi_periph); void spi_crc_next(uint32_t spi_periph); /* get SPI CRC send value or receive value */ uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc); +/* clear SPI CRC error flag status */ +void spi_crc_error_clear(uint32_t spi_periph); + +/* quad wire SPI functions */ +/* enable quad wire SPI */ +void spi_quad_enable(uint32_t spi_periph); +/* disable quad wire SPI */ +void spi_quad_disable(uint32_t spi_periph); +/* enable quad wire SPI write */ +void spi_quad_write_enable(uint32_t spi_periph); +/* enable quad wire SPI read */ +void spi_quad_read_enable(uint32_t spi_periph); +/* enable SPI_IO2 and SPI_IO3 pin output */ +void spi_quad_io23_output_enable(uint32_t spi_periph); +/* disable SPI_IO2 and SPI_IO3 pin output */ +void spi_quad_io23_output_disable(uint32_t spi_periph); /* flag and interrupt functions */ +/* get SPI and I2S flag status */ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag); /* enable SPI and I2S interrupt */ void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt); /* disable SPI and I2S interrupt */ void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt); /* get SPI and I2S interrupt status */ FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt); -/* get SPI and I2S flag status */ -FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag); -/* clear SPI CRC error flag status */ -void spi_crc_error_clear(uint32_t spi_periph); - -/* enable quad wire SPI */ -void qspi_enable(uint32_t spi_periph); -/* disable quad wire SPI */ -void qspi_disable(uint32_t spi_periph); -/* enable quad wire SPI write */ -void qspi_write_enable(uint32_t spi_periph); -/* enable quad wire SPI read */ -void qspi_read_enable(uint32_t spi_periph); -/* enable quad wire SPI_IO2 and SPI_IO3 pin output */ -void qspi_io23_output_enable(uint32_t spi_periph); -/* disable quad wire SPI_IO2 and SPI_IO3 pin output */ -void qspi_io23_output_disable(uint32_t spi_periph); #endif /* GD32F20X_SPI_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_timer.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_timer.h index d83f771c..a04b85ae 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_timer.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_timer.h @@ -2,36 +2,33 @@ \file gd32f20x_timer.h \brief definitions for the TIMER - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -74,7 +71,7 @@ OF SUCH DAMAGE. #define TIMER_CH1CV(timerx) REG32((timerx) + 0x38U) /*!< TIMER channel 1 capture/compare value register */ #define TIMER_CH2CV(timerx) REG32((timerx) + 0x3CU) /*!< TIMER channel 2 capture/compare value register */ #define TIMER_CH3CV(timerx) REG32((timerx) + 0x40U) /*!< TIMER channel 3 capture/compare value register */ -#define TIMER_CCHP(timerx) REG32((timerx) + 0x44U) /*!< TIMER channel complementary protection register */ +#define TIMER_CCHP(timerx) REG32((timerx) + 0x44U) /*!< TIMER complementary channel protection register */ #define TIMER_DMACFG(timerx) REG32((timerx) + 0x48U) /*!< TIMER DMA configuration register */ #define TIMER_DMATB(timerx) REG32((timerx) + 0x4CU) /*!< TIMER DMA transfer buffer register */ @@ -111,7 +108,7 @@ OF SUCH DAMAGE. #define TIMER_SMCFG_ETPSC BITS(12,13) /*!< external trigger prescaler */ #define TIMER_SMCFG_SMC1 BIT(14) /*!< part of SMC for enable external clock mode 1 */ #define TIMER_SMCFG_ETP BIT(15) /*!< external trigger polarity */ - + /* TIMER_DMAINTEN */ #define TIMER_DMAINTEN_UPIE BIT(0) /*!< update interrupt enable */ #define TIMER_DMAINTEN_CH0IE BIT(1) /*!< channel 0 capture/compare interrupt enable */ @@ -122,10 +119,10 @@ OF SUCH DAMAGE. #define TIMER_DMAINTEN_TRGIE BIT(6) /*!< trigger interrupt enable */ #define TIMER_DMAINTEN_BRKIE BIT(7) /*!< break interrupt enable */ #define TIMER_DMAINTEN_UPDEN BIT(8) /*!< update DMA request enable */ -#define TIMER_DMAINTEN_CH0DEN BIT(9) /*!< channel 0 capture/compare DMA request enable */ -#define TIMER_DMAINTEN_CH1DEN BIT(10) /*!< channel 1 capture/compare DMA request enable */ -#define TIMER_DMAINTEN_CH2DEN BIT(11) /*!< channel 2 capture/compare DMA request enable */ -#define TIMER_DMAINTEN_CH3DEN BIT(12) /*!< channel 3 capture/compare DMA request enable */ +#define TIMER_DMAINTEN_CH0DEN BIT(9) /*!< channel 0 DMA request enable */ +#define TIMER_DMAINTEN_CH1DEN BIT(10) /*!< channel 1 DMA request enable */ +#define TIMER_DMAINTEN_CH2DEN BIT(11) /*!< channel 2 DMA request enable */ +#define TIMER_DMAINTEN_CH3DEN BIT(12) /*!< channel 3 DMA request enable */ #define TIMER_DMAINTEN_CMTDEN BIT(13) /*!< commutation DMA request enable */ #define TIMER_DMAINTEN_TRGDEN BIT(14) /*!< trigger DMA request enable */ @@ -248,19 +245,17 @@ OF SUCH DAMAGE. /* constants definitions */ /* TIMER init parameter structure definitions */ -typedef struct -{ +typedef struct { uint16_t prescaler; /*!< prescaler value */ uint16_t alignedmode; /*!< aligned mode */ uint16_t counterdirection; /*!< counter direction */ uint32_t period; /*!< period value */ uint16_t clockdivision; /*!< clock division value */ uint8_t repetitioncounter; /*!< the counter repetition value */ -}timer_parameter_struct; +} timer_parameter_struct; /* break parameter structure definitions*/ -typedef struct -{ +typedef struct { uint16_t runoffstate; /*!< run mode off-state */ uint16_t ideloffstate; /*!< idle mode off-state */ uint16_t deadtime; /*!< dead time */ @@ -268,27 +263,25 @@ typedef struct uint16_t outputautostate; /*!< output automatic enable */ uint16_t protectmode; /*!< complementary register protect control */ uint16_t breakstate; /*!< break enable */ -}timer_break_parameter_struct; +} timer_break_parameter_struct; /* channel output parameter structure definitions */ -typedef struct -{ +typedef struct { uint16_t outputstate; /*!< channel output state */ uint16_t outputnstate; /*!< channel complementary output state */ uint16_t ocpolarity; /*!< channel output polarity */ uint16_t ocnpolarity; /*!< channel complementary output polarity */ uint16_t ocidlestate; /*!< idle state of channel output */ uint16_t ocnidlestate; /*!< idle state of channel complementary output */ -}timer_oc_parameter_struct; +} timer_oc_parameter_struct; /* channel input parameter structure definitions */ -typedef struct -{ +typedef struct { uint16_t icpolarity; /*!< channel input polarity */ uint16_t icselection; /*!< channel input mode selection */ uint16_t icprescaler; /*!< channel input capture prescaler */ uint16_t icfilter; /*!< channel input capture filter control */ -}timer_ic_parameter_struct; +} timer_ic_parameter_struct; /* TIMER interrupt enable or disable */ #define TIMER_INT_UP TIMER_DMAINTEN_UPIE /*!< update interrupt */ @@ -296,20 +289,10 @@ typedef struct #define TIMER_INT_CH1 TIMER_DMAINTEN_CH1IE /*!< channel 1 interrupt */ #define TIMER_INT_CH2 TIMER_DMAINTEN_CH2IE /*!< channel 2 interrupt */ #define TIMER_INT_CH3 TIMER_DMAINTEN_CH3IE /*!< channel 3 interrupt */ -#define TIMER_INT_CMT TIMER_DMAINTEN_CMTIE /*!< channel commutation interrupt flag */ +#define TIMER_INT_CMT TIMER_DMAINTEN_CMTIE /*!< channel commutation interrupt */ #define TIMER_INT_TRG TIMER_DMAINTEN_TRGIE /*!< trigger interrupt */ #define TIMER_INT_BRK TIMER_DMAINTEN_BRKIE /*!< break interrupt */ -/* TIMER interrupt flag */ -#define TIMER_INT_FLAG_UP TIMER_INT_UP /*!< update interrupt */ -#define TIMER_INT_FLAG_CH0 TIMER_INT_CH0 /*!< channel 0 interrupt */ -#define TIMER_INT_FLAG_CH1 TIMER_INT_CH1 /*!< channel 1 interrupt */ -#define TIMER_INT_FLAG_CH2 TIMER_INT_CH2 /*!< channel 2 interrupt */ -#define TIMER_INT_FLAG_CH3 TIMER_INT_CH3 /*!< channel 3 interrupt */ -#define TIMER_INT_FLAG_CMT TIMER_INT_CMT /*!< channel commutation interrupt flag */ -#define TIMER_INT_FLAG_TRG TIMER_INT_TRG /*!< trigger interrupt */ -#define TIMER_INT_FLAG_BRK TIMER_INT_BRK - /* TIMER flag */ #define TIMER_FLAG_UP TIMER_INTF_UPIF /*!< update flag */ #define TIMER_FLAG_CH0 TIMER_INTF_CH0IF /*!< channel 0 flag */ @@ -324,6 +307,16 @@ typedef struct #define TIMER_FLAG_CH2O TIMER_INTF_CH2OF /*!< channel 2 overcapture flag */ #define TIMER_FLAG_CH3O TIMER_INTF_CH3OF /*!< channel 3 overcapture flag */ +/* TIMER interrupt flag */ +#define TIMER_INT_FLAG_UP TIMER_INTF_UPIF /*!< update interrupt flag */ +#define TIMER_INT_FLAG_CH0 TIMER_INTF_CH0IF /*!< channel 0 interrupt flag */ +#define TIMER_INT_FLAG_CH1 TIMER_INTF_CH1IF /*!< channel 1 interrupt flag */ +#define TIMER_INT_FLAG_CH2 TIMER_INTF_CH2IF /*!< channel 2 interrupt flag */ +#define TIMER_INT_FLAG_CH3 TIMER_INTF_CH3IF /*!< channel 3 interrupt flag */ +#define TIMER_INT_FLAG_CMT TIMER_INTF_CMTIF /*!< channel commutation interrupt flag */ +#define TIMER_INT_FLAG_TRG TIMER_INTF_TRGIF /*!< trigger interrupt flag */ +#define TIMER_INT_FLAG_BRK TIMER_INTF_BRKIF /*!< break interrupt */ + /* TIMER DMA source enable */ #define TIMER_DMA_UPD ((uint16_t)TIMER_DMAINTEN_UPDEN) /*!< update DMA enable */ #define TIMER_DMA_CH0D ((uint16_t)TIMER_DMAINTEN_CH0DEN) /*!< channel 0 DMA enable */ @@ -333,12 +326,12 @@ typedef struct #define TIMER_DMA_CMTD ((uint16_t)TIMER_DMAINTEN_CMTDEN) /*!< commutation DMA request enable */ #define TIMER_DMA_TRGD ((uint16_t)TIMER_DMAINTEN_TRGDEN) /*!< trigger DMA enable */ -/* channel DMA request source selection */ -#define TIMER_DMAREQUEST_UPDATEEVENT TIMER_CTL1_DMAS /*!< DMA request of channel n is sent when update event occurs */ -#define TIMER_DMAREQUEST_CHANNELEVENT ((uint32_t)0x00000000U) /*!< DMA request of channel n is sent when channel n event occurs */ +/* channel DMA request source selection */ +#define TIMER_DMAREQUEST_UPDATEEVENT ((uint32_t)0x00000000U) /*!< DMA request of channel y is sent when update event occurs */ +#define TIMER_DMAREQUEST_CHANNELEVENT ((uint32_t)0x00000001U) /*!< DMA request of channel y is sent when channel y event occurs */ /* DMA access base address */ -#define DMACFG_DMATA(regval) (BITS(0, 4) & ((uint32_t)(regval) << 0U)) +#define DMACFG_DMATA(regval) (BITS(0,4) & ((uint32_t)(regval) << 0U)) #define TIMER_DMACFG_DMATA_CTL0 DMACFG_DMATA(0) /*!< DMA transfer address is TIMER_CTL0 */ #define TIMER_DMACFG_DMATA_CTL1 DMACFG_DMATA(1) /*!< DMA transfer address is TIMER_CTL1 */ #define TIMER_DMACFG_DMATA_SMCFG DMACFG_DMATA(2) /*!< DMA transfer address is TIMER_SMCFG */ @@ -361,7 +354,7 @@ typedef struct #define TIMER_DMACFG_DMATA_DMATB DMACFG_DMATA(19) /*!< DMA transfer address is TIMER_DMATB */ /* DMA access burst length */ -#define DMACFG_DMATC(regval) (BITS(8, 12) & ((uint32_t)(regval) << 8U)) +#define DMACFG_DMATC(regval) (BITS(8,12) & ((uint32_t)(regval) << 8U)) #define TIMER_DMACFG_DMATC_1TRANSFER DMACFG_DMATC(0) /*!< DMA transfer 1 time */ #define TIMER_DMACFG_DMATC_2TRANSFER DMACFG_DMATC(1) /*!< DMA transfer 2 times */ #define TIMER_DMACFG_DMATC_3TRANSFER DMACFG_DMATC(2) /*!< DMA transfer 3 times */ @@ -392,39 +385,39 @@ typedef struct #define TIMER_EVENT_SRC_BRKG ((uint16_t)0x0080U) /*!< break event generation */ /* center-aligned mode selection */ -#define CTL0_CAM(regval) ((uint16_t)(BITS(5, 6) & ((uint32_t)(regval) << 5U))) +#define CTL0_CAM(regval) ((uint16_t)(BITS(5,6) & ((uint32_t)(regval) << 5U))) #define TIMER_COUNTER_EDGE CTL0_CAM(0) /*!< edge-aligned mode */ #define TIMER_COUNTER_CENTER_DOWN CTL0_CAM(1) /*!< center-aligned and counting down assert mode */ #define TIMER_COUNTER_CENTER_UP CTL0_CAM(2) /*!< center-aligned and counting up assert mode */ #define TIMER_COUNTER_CENTER_BOTH CTL0_CAM(3) /*!< center-aligned and counting up/down assert mode */ /* TIMER prescaler reload mode */ -#define TIMER_PSC_RELOAD_NOW TIMER_SWEVG_UPG /*!< the prescaler is loaded right now */ -#define TIMER_PSC_RELOAD_UPDATE ((uint32_t)0x00000000U) /*!< the prescaler is loaded at the next update event */ +#define TIMER_PSC_RELOAD_NOW ((uint32_t)0x00000000U) /*!< the prescaler is loaded right now */ +#define TIMER_PSC_RELOAD_UPDATE ((uint32_t)0x00000001U) /*!< the prescaler is loaded at the next update event */ /* count direction */ #define TIMER_COUNTER_UP ((uint16_t)0x0000U) /*!< counter up direction */ #define TIMER_COUNTER_DOWN ((uint16_t)TIMER_CTL0_DIR) /*!< counter down direction */ /* specify division ratio between TIMER clock and dead-time and sampling clock */ -#define CTL0_CKDIV(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define CTL0_CKDIV(regval) ((uint16_t)(BITS(8,9) & ((uint32_t)(regval) << 8U))) #define TIMER_CKDIV_DIV1 CTL0_CKDIV(0) /*!< clock division value is 1,fDTS=fTIMER_CK */ #define TIMER_CKDIV_DIV2 CTL0_CKDIV(1) /*!< clock division value is 2,fDTS= fTIMER_CK/2 */ #define TIMER_CKDIV_DIV4 CTL0_CKDIV(2) /*!< clock division value is 4, fDTS= fTIMER_CK/4 */ /* single pulse mode */ -#define TIMER_SP_MODE_SINGLE TIMER_CTL0_SPM /*!< single pulse mode */ -#define TIMER_SP_MODE_REPETITIVE ((uint32_t)0x00000000U) /*!< repetitive pulse mode */ +#define TIMER_SP_MODE_SINGLE ((uint32_t)0x00000000U) /*!< single pulse mode */ +#define TIMER_SP_MODE_REPETITIVE ((uint32_t)0x00000001U) /*!< repetitive pulse mode */ /* update source */ -#define TIMER_UPDATE_SRC_REGULAR TIMER_CTL0_UPS /*!< update generate only by counter overflow/underflow */ -#define TIMER_UPDATE_SRC_GLOBAL ((uint32_t)0x00000000U) /*!< update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger */ +#define TIMER_UPDATE_SRC_REGULAR ((uint32_t)0x00000000U) /*!< update generate only by counter overflow/underflow */ +#define TIMER_UPDATE_SRC_GLOBAL ((uint32_t)0x00000001U) /*!< update generate by setting of UPG bit or the counter overflow/underflow,or the slave mode controller trigger */ /* run mode off-state configure */ #define TIMER_ROS_STATE_ENABLE ((uint16_t)TIMER_CCHP_ROS) /*!< when POEN bit is set, the channel output signals(CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ #define TIMER_ROS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is set, the channel output signals(CHx_O/CHx_ON) are disabled */ -/* idle mode off-state configure */ +/* idle mode off-state configure */ #define TIMER_IOS_STATE_ENABLE ((uint16_t)TIMER_CCHP_IOS) /*!< when POEN bit is reset, he channel output signals(CHx_O/CHx_ON) are enabled, with relationship to CHxEN/CHxNEN bits */ #define TIMER_IOS_STATE_DISABLE ((uint16_t)0x0000U) /*!< when POEN bit is reset, the channel output signals(CHx_O/CHx_ON) are disabled */ @@ -437,7 +430,7 @@ typedef struct #define TIMER_OUTAUTO_DISABLE ((uint16_t)0x0000U) /*!< output automatic disable */ /* complementary register protect control */ -#define CCHP_PROT(regval) ((uint16_t)(BITS(8, 9) & ((uint32_t)(regval) << 8U))) +#define CCHP_PROT(regval) ((uint16_t)(BITS(8,9) & ((uint32_t)(regval) << 8U))) #define TIMER_CCHP_PROT_OFF CCHP_PROT(0) /*!< protect disable */ #define TIMER_CCHP_PROT_0 CCHP_PROT(1) /*!< PROT mode 0 */ #define TIMER_CCHP_PROT_1 CCHP_PROT(2) /*!< PROT mode 1 */ @@ -469,19 +462,19 @@ typedef struct #define TIMER_OCN_POLARITY_HIGH ((uint16_t)0x0000U) /*!< channel complementary output polarity is high */ #define TIMER_OCN_POLARITY_LOW ((uint16_t)0x0008U) /*!< channel complementary output polarity is low */ -/* idle state of channel output */ +/* idle state of channel output */ #define TIMER_OC_IDLE_STATE_HIGH ((uint16_t)0x0100) /*!< idle state of channel output is high */ #define TIMER_OC_IDLE_STATE_LOW ((uint16_t)0x0000) /*!< idle state of channel output is low */ -/* idle state of channel complementary output */ +/* idle state of channel complementary output */ #define TIMER_OCN_IDLE_STATE_HIGH ((uint16_t)0x0200U) /*!< idle state of channel complementary output is high */ #define TIMER_OCN_IDLE_STATE_LOW ((uint16_t)0x0000U) /*!< idle state of channel complementary output is low */ /* channel output compare mode */ -#define TIMER_OC_MODE_TIMING ((uint16_t)0x0000U) /*!< frozen mode */ -#define TIMER_OC_MODE_ACTIVE ((uint16_t)0x0010U) /*!< set the channel output */ -#define TIMER_OC_MODE_INACTIVE ((uint16_t)0x0020U) /*!< clear the channel output */ -#define TIMER_OC_MODE_TOGGLE ((uint16_t)0x0030U) /*!< toggle on match */ +#define TIMER_OC_MODE_TIMING ((uint16_t)0x0000U) /*!< timing mode */ +#define TIMER_OC_MODE_ACTIVE ((uint16_t)0x0010U) /*!< active mode */ +#define TIMER_OC_MODE_INACTIVE ((uint16_t)0x0020U) /*!< inactive mode */ +#define TIMER_OC_MODE_TOGGLE ((uint16_t)0x0030U) /*!< toggle mode */ #define TIMER_OC_MODE_LOW ((uint16_t)0x0040U) /*!< force low mode */ #define TIMER_OC_MODE_HIGH ((uint16_t)0x0050U) /*!< force high mode */ #define TIMER_OC_MODE_PWM0 ((uint16_t)0x0060U) /*!< PWM0 mode */ @@ -499,16 +492,16 @@ typedef struct #define TIMER_OC_CLEAR_ENABLE ((uint16_t)0x0080U) /*!< channel output clear function enable */ #define TIMER_OC_CLEAR_DISABLE ((uint16_t)0x0000U) /*!< channel output clear function disable */ -/* channel control shadow register update control */ -#define TIMER_UPDATECTL_CCU ((uint32_t)0x00000000U) /*!< the shadow registers update by when CMTG bit is set */ -#define TIMER_UPDATECTL_CCUTRI TIMER_CTL1_CCUC /*!< the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs */ +/* channel control shadow register update control */ +#define TIMER_UPDATECTL_CCU ((uint32_t)0x00000000U) /*!< the shadow registers are updated when CMTG bit is set */ +#define TIMER_UPDATECTL_CCUTRI ((uint32_t)0x00000001U) /*!< the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs */ /* channel input capture polarity */ #define TIMER_IC_POLARITY_RISING ((uint16_t)0x0000U) /*!< input capture rising edge */ #define TIMER_IC_POLARITY_FALLING ((uint16_t)0x0002U) /*!< input capture falling edge */ #define TIMER_IC_POLARITY_BOTH_EDGE ((uint16_t)0x000AU) /*!< input capture both edge */ -/* timer input capture selection */ +/* TIMER input capture selection */ #define TIMER_IC_SELECTION_DIRECTTI ((uint16_t)0x0001U) /*!< channel y is configured as input and icy is mapped on CIy */ #define TIMER_IC_SELECTION_INDIRECTTI ((uint16_t)0x0002U) /*!< channel y is configured as input and icy is mapped on opposite input */ #define TIMER_IC_SELECTION_ITS ((uint16_t)0x0003U) /*!< channel y is configured as input and icy is mapped on ITS */ @@ -520,7 +513,7 @@ typedef struct #define TIMER_IC_PSC_DIV8 ((uint16_t)0x000CU) /*!< divided by 8 */ /* trigger selection */ -#define SMCFG_TRGSEL(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define SMCFG_TRGSEL(regval) (BITS(4,6) & ((uint32_t)(regval) << 4U)) #define TIMER_SMCFG_TRGSEL_ITI0 SMCFG_TRGSEL(0) /*!< internal trigger 0 */ #define TIMER_SMCFG_TRGSEL_ITI1 SMCFG_TRGSEL(1) /*!< internal trigger 1 */ #define TIMER_SMCFG_TRGSEL_ITI2 SMCFG_TRGSEL(2) /*!< internal trigger 2 */ @@ -528,10 +521,10 @@ typedef struct #define TIMER_SMCFG_TRGSEL_CI0F_ED SMCFG_TRGSEL(4) /*!< TI0 Edge Detector */ #define TIMER_SMCFG_TRGSEL_CI0FE0 SMCFG_TRGSEL(5) /*!< filtered TIMER input 0 */ #define TIMER_SMCFG_TRGSEL_CI1FE1 SMCFG_TRGSEL(6) /*!< filtered TIMER input 1 */ -#define TIMER_SMCFG_TRGSEL_ETIFP SMCFG_TRGSEL(7) /*!< external trigger */ +#define TIMER_SMCFG_TRGSEL_ETIFP SMCFG_TRGSEL(7) /*!< filtered external trigger input */ /* master mode control */ -#define CTL1_MMC(regval) (BITS(4, 6) & ((uint32_t)(regval) << 4U)) +#define CTL1_MMC(regval) (BITS(4,6) & ((uint32_t)(regval) << 4U)) #define TIMER_TRI_OUT_SRC_RESET CTL1_MMC(0) /*!< the UPG bit as trigger output */ #define TIMER_TRI_OUT_SRC_ENABLE CTL1_MMC(1) /*!< the counter enable signal TIMER_CTL0_CEN as trigger output */ #define TIMER_TRI_OUT_SRC_UPDATE CTL1_MMC(2) /*!< update event as trigger output */ @@ -542,22 +535,22 @@ typedef struct #define TIMER_TRI_OUT_SRC_O3CPRE CTL1_MMC(7) /*!< O3CPRE as trigger output */ /* slave mode control */ -#define SMCFG_SMC(regval) (BITS(0, 2) & ((uint32_t)(regval) << 0U)) +#define SMCFG_SMC(regval) (BITS(0,2) & ((uint32_t)(regval) << 0U)) #define TIMER_SLAVE_MODE_DISABLE SMCFG_SMC(0) /*!< slave mode disable */ -#define TIMER_ENCODER_MODE0 SMCFG_SMC(1) /*!< encoder mode 0 */ -#define TIMER_ENCODER_MODE1 SMCFG_SMC(2) /*!< encoder mode 1 */ -#define TIMER_ENCODER_MODE2 SMCFG_SMC(3) /*!< encoder mode 2 */ +#define TIMER_QUAD_DECODER_MODE0 SMCFG_SMC(1) /*!< quadrature decoder mode 0 */ +#define TIMER_QUAD_DECODER_MODE1 SMCFG_SMC(2) /*!< quadrature decoder mode 1 */ +#define TIMER_QUAD_DECODER_MODE2 SMCFG_SMC(3) /*!< quadrature decoder mode 2 */ #define TIMER_SLAVE_MODE_RESTART SMCFG_SMC(4) /*!< restart mode */ #define TIMER_SLAVE_MODE_PAUSE SMCFG_SMC(5) /*!< pause mode */ #define TIMER_SLAVE_MODE_EVENT SMCFG_SMC(6) /*!< event mode */ #define TIMER_SLAVE_MODE_EXTERNAL0 SMCFG_SMC(7) /*!< external clock mode 0 */ -/* master slave mode selection */ -#define TIMER_MASTER_SLAVE_MODE_ENABLE TIMER_SMCFG_MSM /*!< master slave mode enable */ -#define TIMER_MASTER_SLAVE_MODE_DISABLE ((uint32_t)0x00000000U) /*!< master slave mode disable */ +/* master slave mode selection */ +#define TIMER_MASTER_SLAVE_MODE_ENABLE ((uint32_t)0x00000000U) /*!< master slave mode enable */ +#define TIMER_MASTER_SLAVE_MODE_DISABLE ((uint32_t)0x00000001U) /*!< master slave mode disable */ /* external trigger prescaler */ -#define SMCFG_ETPSC(regval) (BITS(12, 13) & ((uint32_t)(regval) << 12U)) +#define SMCFG_ETPSC(regval) (BITS(12,13) & ((uint32_t)(regval) << 12U)) #define TIMER_EXT_TRI_PSC_OFF SMCFG_ETPSC(0) /*!< no divided */ #define TIMER_EXT_TRI_PSC_DIV2 SMCFG_ETPSC(1) /*!< divided by 2 */ #define TIMER_EXT_TRI_PSC_DIV4 SMCFG_ETPSC(2) /*!< divided by 4 */ @@ -567,22 +560,18 @@ typedef struct #define TIMER_ETP_FALLING TIMER_SMCFG_ETP /*!< active low or falling edge active */ #define TIMER_ETP_RISING ((uint32_t)0x00000000U) /*!< active high or rising edge active */ -/* channel 0 trigger input selection */ -#define TIMER_HALLINTERFACE_ENABLE TIMER_CTL1_TI0S /*!< TIMER hall sensor mode enable */ -#define TIMER_HALLINTERFACE_DISABLE ((uint32_t)0x00000000U) /*!< TIMER hall sensor mode disable */ - -/* TIMERx(x=0..4,7..13) write CHxVAL register selection */ -#define TIMER_CHVSEL_ENABLE ((uint16_t)TIMER_CFG_OUTSEL) /*!< write CHxVAL register selection enable */ -#define TIMER_CHVSEL_DISABLE ((uint16_t)0x0000U) /*!< write CHxVAL register selection disable */ +/* channel 0 trigger input selection */ +#define TIMER_HALLINTERFACE_ENABLE ((uint32_t)0x00000000U) /*!< TIMER hall sensor mode enable */ +#define TIMER_HALLINTERFACE_DISABLE ((uint32_t)0x00000001U) /*!< TIMER hall sensor mode disable */ /* function declarations */ /* TIMER timebase */ /* deinit a TIMER */ void timer_deinit(uint32_t timer_periph); /* initialize TIMER init parameter structure */ -void timer_struct_para_init(timer_parameter_struct* initpara); +void timer_struct_para_init(timer_parameter_struct *initpara); /* initialize TIMER counter */ -void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara); +void timer_init(uint32_t timer_periph, timer_parameter_struct *initpara); /* enable a TIMER */ void timer_enable(uint32_t timer_periph); /* disable a TIMER */ @@ -604,7 +593,7 @@ void timer_counter_down_direction(uint32_t timer_periph); /* configure TIMER prescaler */ void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload); /* configure TIMER repetition register value */ -void timer_repetition_value_config(uint32_t timer_periph, uint8_t repetition); +void timer_repetition_value_config(uint32_t timer_periph, uint16_t repetition); /* configure TIMER autoreload register value */ void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload); /* configure TIMER counter register value */ @@ -618,7 +607,7 @@ void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode); /* configure TIMER update source */ void timer_update_source_config(uint32_t timer_periph, uint32_t update); -/* timer DMA and event */ +/* TIMER DMA and event */ /* enable the TIMER DMA */ void timer_dma_enable(uint32_t timer_periph, uint16_t dma); /* disable the TIMER DMA */ @@ -632,9 +621,9 @@ void timer_event_software_generate(uint32_t timer_periph, uint16_t event); /* TIMER channel complementary protection */ /* initialize TIMER break parameter struct */ -void timer_break_struct_para_init(timer_break_parameter_struct* breakpara); +void timer_break_struct_para_init(timer_break_parameter_struct *breakpara); /* configure TIMER break function */ -void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara); +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct *breakpara); /* enable TIMER break function */ void timer_break_enable(uint32_t timer_periph); /* disable TIMER break function */ @@ -652,13 +641,13 @@ void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t /* TIMER channel output */ /* initialize TIMER channel output parameter struct */ -void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara); +void timer_channel_output_struct_para_init(timer_oc_parameter_struct *ocpara); /* configure TIMER channel output function */ -void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara); +void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct *ocpara); /* configure TIMER channel output compare mode */ void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode); /* configure TIMER channel output pulse value */ -void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint16_t pulse); +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint32_t pulse); /* configure TIMER channel output shadow function */ void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow); /* configure TIMER channel output fast function */ @@ -676,15 +665,15 @@ void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint /* TIMER channel input */ /* initialize TIMER channel input parameter structure */ -void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara); +void timer_channel_input_struct_para_init(timer_ic_parameter_struct *icpara); /* configure TIMER input capture parameter */ -void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara); +void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct *icpara); /* configure TIMER channel input capture prescaler value */ void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler); /* read TIMER channel capture compare register value */ uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel); /* configure TIMER input pwm capture function */ -void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm); +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct *icpwm); /* configure TIMER hall sensor mode */ void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode); @@ -698,7 +687,7 @@ void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode); /* configure TIMER master slave mode */ void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave); /* configure TIMER external trigger input */ -void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter); +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter); /* configure TIMER quadrature decoder mode */ void timer_quadrature_decoder_mode_config(uint32_t timer_periph, uint32_t decomode, uint16_t ic0polarity, uint16_t ic1polarity); /* configure TIMER internal clock mode */ @@ -706,26 +695,26 @@ void timer_internal_clock_config(uint32_t timer_periph); /* configure TIMER the internal trigger as external clock input */ void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger); /* configure TIMER the external trigger as external clock input */ -void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint8_t extfilter); +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint32_t extfilter); /* configure TIMER the external clock mode 0 */ -void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter); +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter); /* configure TIMER the external clock mode 1 */ -void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter); +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter); /* disable TIMER the external clock mode 1 */ void timer_external_clock_mode1_disable(uint32_t timer_periph); /* TIMER interrupt and flag */ +/* get TIMER flags */ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag); +/* clear TIMER flags */ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag); /* enable the TIMER interrupt */ void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt); /* disable the TIMER interrupt */ void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt); -/* get TIMER interrupt flag */ -FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt); -/* clear TIMER interrupt flag */ -void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt); -/* get TIMER flag */ -FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag); -/* clear TIMER flag */ -void timer_flag_clear(uint32_t timer_periph, uint32_t flag); +/* get TIMER interrupt flags */ +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t int_flag); +/* clear TIMER interrupt flags */ +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t int_flag); #endif /* GD32F20X_TIMER_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_tli.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_tli.h index 55bfc902..00efc28e 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_tli.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_tli.h @@ -2,36 +2,33 @@ \file gd32f20x_tli.h \brief definitions for the TLI - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -193,12 +190,11 @@ OF SUCH DAMAGE. /* constants definitions */ /* TLI parameter structure definitions */ -typedef struct -{ - uint32_t synpsz_vpsz; /*!< size of the vertical synchronous pulse */ - uint32_t synpsz_hpsz; /*!< size of the horizontal synchronous pulse */ - uint32_t backpsz_vbpsz; /*!< size of the vertical back porch plus synchronous pulse */ - uint32_t backpsz_hbpsz; /*!< size of the horizontal back porch plus synchronous pulse */ +typedef struct { + uint16_t synpsz_vpsz; /*!< size of the vertical synchronous pulse */ + uint16_t synpsz_hpsz; /*!< size of the horizontal synchronous pulse */ + uint16_t backpsz_vbpsz; /*!< size of the vertical back porch plus synchronous pulse */ + uint16_t backpsz_hbpsz; /*!< size of the horizontal back porch plus synchronous pulse */ uint32_t activesz_vasz; /*!< size of the vertical active area width plus back porch and synchronous pulse */ uint32_t activesz_hasz; /*!< size of the horizontal active area width plus back porch and synchronous pulse */ uint32_t totalsz_vtsz; /*!< vertical total size of the display */ @@ -210,49 +206,46 @@ typedef struct uint32_t signalpolarity_vs; /*!< vertical pulse polarity selection */ uint32_t signalpolarity_de; /*!< data enable polarity selection */ uint32_t signalpolarity_pixelck; /*!< pixel clock polarity selection */ -}tli_parameter_struct; +} tli_parameter_struct; /* TLI layer parameter structure definitions */ -typedef struct -{ - uint32_t layer_window_rightpos; /*!< window right position */ - uint32_t layer_window_leftpos; /*!< window left position */ - uint32_t layer_window_bottompos; /*!< window bottom position */ - uint32_t layer_window_toppos; /*!< window top position */ +typedef struct { + uint16_t layer_window_rightpos; /*!< window right position */ + uint16_t layer_window_leftpos; /*!< window left position */ + uint16_t layer_window_bottompos; /*!< window bottom position */ + uint16_t layer_window_toppos; /*!< window top position */ uint32_t layer_ppf; /*!< packeted pixel format */ - uint32_t layer_sa; /*!< specified alpha */ - uint32_t layer_default_alpha; /*!< the default color alpha */ - uint32_t layer_default_red; /*!< the default color red */ - uint32_t layer_default_green; /*!< the default color green */ - uint32_t layer_default_blue; /*!< the default color blue */ + uint8_t layer_sa; /*!< specified alpha */ + uint8_t layer_default_alpha; /*!< the default color alpha */ + uint8_t layer_default_red; /*!< the default color red */ + uint8_t layer_default_green; /*!< the default color green */ + uint8_t layer_default_blue; /*!< the default color blue */ uint32_t layer_acf1; /*!< alpha calculation factor 1 of blending method */ uint32_t layer_acf2; /*!< alpha calculation factor 2 of blending method */ uint32_t layer_frame_bufaddr; /*!< frame buffer base address */ - uint32_t layer_frame_buf_stride_offset; /*!< frame buffer stride offset */ - uint32_t layer_frame_line_length; /*!< frame line length */ - uint32_t layer_frame_total_line_number; /*!< frame total line number */ -}tli_layer_parameter_struct; + uint16_t layer_frame_buf_stride_offset; /*!< frame buffer stride offset */ + uint16_t layer_frame_line_length; /*!< frame line length */ + uint16_t layer_frame_total_line_number; /*!< frame total line number */ +} tli_layer_parameter_struct; /* TLI layer LUT parameter structure definitions */ -typedef struct -{ +typedef struct { uint32_t layer_table_addr; /*!< look up table write address */ - uint32_t layer_lut_channel_red; /*!< red channel of a LUT entry */ - uint32_t layer_lut_channel_green; /*!< green channel of a LUT entry */ - uint32_t layer_lut_channel_blue; /*!< blue channel of a LUT entry */ -}tli_layer_lut_parameter_struct; + uint8_t layer_lut_channel_red; /*!< red channel of a LUT entry */ + uint8_t layer_lut_channel_green; /*!< green channel of a LUT entry */ + uint8_t layer_lut_channel_blue; /*!< blue channel of a LUT entry */ +} tli_layer_lut_parameter_struct; /* packeted pixel format */ -typedef enum -{ - LAYER_PPF_ARGB8888, /*!< layerx packeted pixel format ARGB8888 */ - LAYER_PPF_RGB888, /*!< layerx packeted pixel format RGB888 */ - LAYER_PPF_RGB565, /*!< layerx packeted pixel format RGB565 */ - LAYER_PPF_ARGB1555, /*!< layerx packeted pixel format ARGB1555 */ - LAYER_PPF_ARGB4444, /*!< layerx packeted pixel format ARGB4444 */ - LAYER_PPF_L8, /*!< layerx packeted pixel format L8 */ - LAYER_PPF_AL44, /*!< layerx packeted pixel format AL44 */ - LAYER_PPF_AL88 /*!< layerx packeted pixel format AL88 */ +typedef enum { + LAYER_PPF_ARGB8888 = 0U, /*!< layerx packeted pixel format ARGB8888 */ + LAYER_PPF_RGB888, /*!< layerx packeted pixel format RGB888 */ + LAYER_PPF_RGB565, /*!< layerx packeted pixel format RGB565 */ + LAYER_PPF_ARGB1555, /*!< layerx packeted pixel format ARGB1555 */ + LAYER_PPF_ARGB4444, /*!< layerx packeted pixel format ARGB4444 */ + LAYER_PPF_L8, /*!< layerx packeted pixel format L8 */ + LAYER_PPF_AL44, /*!< layerx packeted pixel format AL44 */ + LAYER_PPF_AL88 /*!< layerx packeted pixel format AL88 */ } tli_layer_ppf_enum; /* TLI flags and states */ @@ -288,10 +281,12 @@ typedef enum /* horizontal pulse polarity selection */ #define TLI_HSYN_ACTLIVE_LOW ((uint32_t)0x00000000U) /*!< horizontal synchronous pulse active low */ #define TLI_HSYN_ACTLIVE_HIGHT TLI_CTL_HPPS /*!< horizontal synchronous pulse active high */ +#define TLI_HSYN_ACTLIVE_HIGH TLI_HSYN_ACTLIVE_HIGHT /*!< horizontal synchronous pulse active high */ /* vertical pulse polarity selection */ #define TLI_VSYN_ACTLIVE_LOW ((uint32_t)0x00000000U) /*!< vertical synchronous pulse active low */ #define TLI_VSYN_ACTLIVE_HIGHT TLI_CTL_VPPS /*!< vertical synchronous pulse active high */ +#define TLI_VSYN_ACTLIVE_HIGH TLI_VSYN_ACTLIVE_HIGHT /*!< vertical synchronous pulse active high */ /* pixel clock polarity selection */ #define TLI_PIXEL_CLOCK_TLI ((uint32_t)0x00000000U) /*!< pixel clock is TLI clock */ @@ -300,69 +295,79 @@ typedef enum /* data enable polarity selection */ #define TLI_DE_ACTLIVE_LOW ((uint32_t)0x00000000U) /*!< data enable active low */ #define TLI_DE_ACTLIVE_HIGHT TLI_CTL_DEPS /*!< data enable active high */ +#define TLI_DE_ACTLIVE_HIGH TLI_DE_ACTLIVE_HIGHT /*!< data enable active high */ /* alpha calculation factor 1 of blending method */ -#define LxBLEND_ACF1(regval) (BITS(8,10) & ((regval)<<8)) +#define LxBLEND_ACF1(regval) (BITS(8,10) & ((uint32_t)(regval)<<8)) #define LAYER_ACF1_SA LxBLEND_ACF1(4) /*!< normalization specified alpha */ #define LAYER_ACF1_PASA LxBLEND_ACF1(6) /*!< normalization pixel alpha * normalization specified alpha */ /* alpha calculation factor 2 of blending method */ -#define LxBLEND_ACF2(regval) (BITS(0,2) & ((regval))) +#define LxBLEND_ACF2(regval) (BITS(0,2) & ((uint32_t)(regval))) #define LAYER_ACF2_SA LxBLEND_ACF2(5) /*!< normalization specified alpha */ #define LAYER_ACF2_PASA LxBLEND_ACF2(7) /*!< normalization pixel alpha * normalization specified alpha */ /* function declarations */ /* initialization functions */ -/* deinitialize TLI */ +/* deinitialize TLI registers */ void tli_deinit(void); -/* initialize TLI */ +/* initialize the parameters of TLI parameter structure with the default values, it is suggested + that call this function after a tli_parameter_struct structure is defined */ +void tli_struct_para_init(tli_parameter_struct *tli_struct); +/* initialize TLI display timing parameters */ void tli_init(tli_parameter_struct *tli_struct); /* configure TLI dither function */ -void tli_dither_config(uint8_t ditherstat); +void tli_dither_config(uint8_t dither_stat); /* enable TLI */ void tli_enable(void); /* disable TLI */ void tli_disable(void); /* configure TLI reload mode */ -void tli_reload_config(uint8_t reloadmode); - -/* set line mark value */ -void tli_line_mark_set(uint32_t linenum); -/* get current displayed position */ -uint32_t tli_current_pos_get(void); - -/* function configuration */ -/* TLI layer enable */ +void tli_reload_config(uint8_t reload_mod); + +/* TLI layer configuration functions */ +/* initialize the parameters of TLI layer structure with the default values, it is suggested + that call this function after a tli_layer_parameter_struct structure is defined */ +void tli_layer_struct_para_init(tli_layer_parameter_struct *layer_struct); +/* initialize TLI layer */ +void tli_layer_init(uint32_t layerx, tli_layer_parameter_struct *layer_struct); +/* reconfigure window position */ +void tli_layer_window_offset_modify(uint32_t layerx, uint16_t offset_x, uint16_t offset_y); +/* initialize the parameters of TLI layer LUT structure with the default values, it is suggested + that call this function after a tli_layer_lut_parameter_struct structure is defined */ +void tli_lut_struct_para_init(tli_layer_lut_parameter_struct *lut_struct); +/* initialize TLI layer LUT */ +void tli_lut_init(uint32_t layerx, tli_layer_lut_parameter_struct *lut_struct); +/* initialize TLI layer color key */ +void tli_color_key_init(uint32_t layerx, uint8_t redkey, uint8_t greenkey, uint8_t bluekey); +/* enable TLI layer */ void tli_layer_enable(uint32_t layerx); -/* TLI layer disable */ +/* disable TLI layer */ void tli_layer_disable(uint32_t layerx); -/* TLI layer color keying enable */ +/* enable TLI layer color keying */ void tli_color_key_enable(uint32_t layerx); -/* TLI layer color keying disable */ +/* disable TLI layer color keying */ void tli_color_key_disable(uint32_t layerx); -/* TLI layer LUT enable */ +/* enable TLI layer LUT */ void tli_lut_enable(uint32_t layerx); -/* TLI layer LUT disable */ +/* disable TLI layer LUT */ void tli_lut_disable(uint32_t layerx); -/* TLI layer initialize */ -void tli_layer_init(uint32_t layerx,tli_layer_parameter_struct *layer_struct); -/* TLI layer initialize */ -void tli_layer_window_offset_modify(uint32_t layerx,uint32_t offset_x,uint32_t offset_y); -/* TLI layer LUT initialize */ -void tli_lut_init(uint32_t layerx,tli_layer_lut_parameter_struct *lut_struct); -/* TLI layer key initialize */ -void tli_ckey_init(uint32_t layerx,uint32_t redkey,uint32_t greenkey,uint32_t bluekey); - -/* interrupt & flag functions */ -/* get TLI flag or state */ -FlagStatus tli_flag_get(uint32_t flag); + +/* set line mark value */ +void tli_line_mark_set(uint16_t line_num); +/* get current displayed position */ +uint32_t tli_current_pos_get(void); + +/* flag and interrupt functions */ /* enable TLI interrupt */ -void tli_interrupt_enable(uint32_t interrupt); +void tli_interrupt_enable(uint32_t int_flag); /* disable TLI interrupt */ -void tli_interrupt_disable(uint32_t interrupt); +void tli_interrupt_disable(uint32_t int_flag); /* get TLI interrupt flag */ FlagStatus tli_interrupt_flag_get(uint32_t int_flag); /* clear TLI interrupt flag */ void tli_interrupt_flag_clear(uint32_t int_flag); +/* get TLI flag or state in TLI_INTF register or TLI_STAT register */ +FlagStatus tli_flag_get(uint32_t flag); #endif /* GD32F20X_TLI_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_trng.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_trng.h index da2edeb0..3db15e46 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_trng.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_trng.h @@ -2,36 +2,33 @@ \file gd32f20x_trng.h \brief definitions for the TRNG - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -41,17 +38,17 @@ OF SUCH DAMAGE. #include "gd32f20x.h" /* TRNG definitions */ -#define TRNG TRNG_BASE +#define TRNG TRNG_BASE /*!< TRNG base address */ /* registers definitions */ -#define TRNG_CTL REG32(TRNG + 0x00U) /*!< control register */ -#define TRNG_STAT REG32(TRNG + 0x04U) /*!< status register */ -#define TRNG_DATA REG32(TRNG + 0x08U) /*!< data register */ +#define TRNG_CTL REG32(TRNG + 0x00000000U) /*!< control register */ +#define TRNG_STAT REG32(TRNG + 0x00000004U) /*!< status register */ +#define TRNG_DATA REG32(TRNG + 0x00000008U) /*!< data register */ /* bits definitions */ /* TRNG_CTL */ #define TRNG_CTL_TRNGEN BIT(2) /*!< TRNG enable bit */ -#define TRNG_CTL_IE BIT(3) /*!< interrupt enable bit */ +#define TRNG_CTL_TRNGIE BIT(3) /*!< interrupt enable bit */ /* TRNG_STAT */ #define TRNG_STAT_DRDY BIT(0) /*!< random data ready status bit */ @@ -60,46 +57,41 @@ OF SUCH DAMAGE. #define TRNG_STAT_CEIF BIT(5) /*!< clock error interrupt flag */ #define TRNG_STAT_SEIF BIT(6) /*!< seed error interrupt flag */ -/* TRNG_DATA */ -#define TRNG_DATA_TRNDATA BITS(0,31) /*!< 32-Bit Random data */ - /* constants definitions */ /* trng status flag */ -typedef enum -{ +typedef enum { TRNG_FLAG_DRDY = TRNG_STAT_DRDY, /*!< random Data ready status */ TRNG_FLAG_CECS = TRNG_STAT_CECS, /*!< clock error current status */ TRNG_FLAG_SECS = TRNG_STAT_SECS /*!< seed error current status */ -}trng_flag_enum; +} trng_flag_enum; /* trng inerrupt flag */ -typedef enum -{ - TRNG_INT_FLAG_CE = TRNG_STAT_CEIF, /*!< clock error interrupt flag */ - TRNG_INT_FLAG_SE = TRNG_STAT_SEIF /*!< seed error interrupt flag */ -}trng_int_flag_enum; +typedef enum { + TRNG_INT_FLAG_CE = TRNG_STAT_CEIF, /*!< clock error interrupt flag */ + TRNG_INT_FLAG_SE = TRNG_STAT_SEIF /*!< seed error interrupt flag */ +} trng_int_flag_enum; /* function declarations */ /* initialization functions */ -/* deinitialize the TRNG */ +/* reset TRNG */ void trng_deinit(void); -/* enable the TRNG interface */ +/* enable TRNG */ void trng_enable(void); -/* disable the TRNG interface */ +/* disable TRNG */ void trng_disable(void); /* get the true random data */ uint32_t trng_get_true_random_data(void); /* interrupt & flag functions */ -/* get the trng status flags */ +/* get TRNG status flags */ FlagStatus trng_flag_get(trng_flag_enum flag); -/* the trng interrupt enable */ +/* enable TRNG interrupt */ void trng_interrupt_enable(void); -/* the trng interrupt disable */ +/* disable TRNG interrupt */ void trng_interrupt_disable(void); -/* get the trng interrupt flags */ +/* get TRNG interrupt flag status */ FlagStatus trng_interrupt_flag_get(trng_int_flag_enum int_flag); -/* clear the trng interrupt flags */ +/* clear TRNG interrupt flag status */ void trng_interrupt_flag_clear(trng_int_flag_enum int_flag); #endif /* GD32F20X_TRNG_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_usart.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_usart.h index 01c43fc6..114eb53a 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_usart.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_usart.h @@ -2,36 +2,33 @@ \file gd32f20x_usart.h \brief definitions for the USART - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -42,108 +39,108 @@ OF SUCH DAMAGE. /* USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) definitions */ #define USART1 USART_BASE /*!< USART1 base address */ -#define USART2 (USART_BASE+0x00000400U) /*!< USART2 base address */ -#define UART3 (USART_BASE+0x00000800U) /*!< UART3 base address */ -#define UART4 (USART_BASE+0x00000C00U) /*!< UART4 base address */ -#define UART6 (USART_BASE+0x00003400U) /*!< UART6 base address */ -#define UART7 (USART_BASE+0x00003800U) /*!< UART7 base address */ -#define USART0 (USART_BASE+0x0000F400U) /*!< USART0 base address */ -#define USART5 (USART_BASE+0x00012C00U) /*!< USART5 base address */ +#define USART2 (USART_BASE + 0x00000400U) /*!< USART2 base address */ +#define UART3 (USART_BASE + 0x00000800U) /*!< UART3 base address */ +#define UART4 (USART_BASE + 0x00000C00U) /*!< UART4 base address */ +#define UART6 (USART_BASE + 0x00003400U) /*!< UART6 base address */ +#define UART7 (USART_BASE + 0x00003800U) /*!< UART7 base address */ +#define USART0 (USART_BASE + 0x0000F400U) /*!< USART0 base address */ +#define USART5 (USART_BASE + 0x00012C00U) /*!< USART5 base address */ /* registers definitions */ -#define USART_STAT0(usartx) REG32((usartx) + 0x00U) /*!< USART status register 0 */ -#define USART_DATA(usartx) REG32((usartx) + 0x04U) /*!< USART data register */ -#define USART_BAUD(usartx) REG32((usartx) + 0x08U) /*!< USART baud rate register */ -#define USART_CTL0(usartx) REG32((usartx) + 0x0CU) /*!< USART control register 0 */ -#define USART_CTL1(usartx) REG32((usartx) + 0x10U) /*!< USART control register 1 */ -#define USART_CTL2(usartx) REG32((usartx) + 0x14U) /*!< USART control register 2 */ -#define USART_GP(usartx) REG32((usartx) + 0x18U) /*!< USART guard time and prescaler register */ -#define USART_CTL3(usartx) REG32((usartx) + 0x80U) /*!< USART control register 3 */ -#define USART_RT(usartx) REG32((usartx) + 0x84U) /*!< USART receiver timeout register */ -#define USART_STAT1(usartx) REG32((usartx) + 0x88U) /*!< USART status register 1 */ +#define USART_STAT0(usartx) REG32((usartx) + 0x00000000U) /*!< USART status register 0 */ +#define USART_DATA(usartx) REG32((usartx) + 0x00000004U) /*!< USART data register */ +#define USART_BAUD(usartx) REG32((usartx) + 0x00000008U) /*!< USART baud rate register */ +#define USART_CTL0(usartx) REG32((usartx) + 0x0000000CU) /*!< USART control register 0 */ +#define USART_CTL1(usartx) REG32((usartx) + 0x00000010U) /*!< USART control register 1 */ +#define USART_CTL2(usartx) REG32((usartx) + 0x00000014U) /*!< USART control register 2 */ +#define USART_GP(usartx) REG32((usartx) + 0x00000018U) /*!< USART guard time and prescaler register */ +#define USART_CTL3(usartx) REG32((usartx) + 0x00000080U) /*!< USART control register 3 */ +#define USART_RT(usartx) REG32((usartx) + 0x00000084U) /*!< USART receiver timeout register */ +#define USART_STAT1(usartx) REG32((usartx) + 0x00000088U) /*!< USART status register 1 */ /* bits definitions */ /* USARTx_STAT0 */ -#define USART_STAT0_PERR BIT(0) /*!< parity error flag */ -#define USART_STAT0_FERR BIT(1) /*!< frame error flag */ -#define USART_STAT0_NERR BIT(2) /*!< noise error flag */ -#define USART_STAT0_ORERR BIT(3) /*!< overrun error */ -#define USART_STAT0_IDLEF BIT(4) /*!< IDLE frame detected flag */ -#define USART_STAT0_RBNE BIT(5) /*!< read data buffer not empty */ -#define USART_STAT0_TC BIT(6) /*!< transmission complete */ -#define USART_STAT0_TBE BIT(7) /*!< transmit data buffer empty */ -#define USART_STAT0_LBDF BIT(8) /*!< LIN break detected flag */ -#define USART_STAT0_CTSF BIT(9) /*!< CTS change flag */ +#define USART_STAT0_PERR BIT(0) /*!< parity error flag */ +#define USART_STAT0_FERR BIT(1) /*!< frame error flag */ +#define USART_STAT0_NERR BIT(2) /*!< noise error flag */ +#define USART_STAT0_ORERR BIT(3) /*!< overrun error */ +#define USART_STAT0_IDLEF BIT(4) /*!< IDLE frame detected flag */ +#define USART_STAT0_RBNE BIT(5) /*!< read data buffer not empty */ +#define USART_STAT0_TC BIT(6) /*!< transmission complete */ +#define USART_STAT0_TBE BIT(7) /*!< transmit data buffer empty */ +#define USART_STAT0_LBDF BIT(8) /*!< LIN break detected flag */ +#define USART_STAT0_CTSF BIT(9) /*!< CTS change flag */ /* USARTx_DATA */ -#define USART_DATA_DATA BITS(0,8) /*!< transmit or read data value */ +#define USART_DATA_DATA BITS(0,8) /*!< transmit or read data value */ /* USARTx_BAUD */ -#define USART_BAUD_FRADIV BITS(0,3) /*!< fraction part of baud-rate divider */ -#define USART_BAUD_INTDIV BITS(4,15) /*!< integer part of baud-rate divider */ +#define USART_BAUD_FRADIV BITS(0,3) /*!< fraction part of baud-rate divider */ +#define USART_BAUD_INTDIV BITS(4,15) /*!< integer part of baud-rate divider */ /* USARTx_CTL0 */ -#define USART_CTL0_SBKCMD BIT(0) /*!< send break command */ -#define USART_CTL0_RWU BIT(1) /*!< receiver wakeup from mute mode */ -#define USART_CTL0_REN BIT(2) /*!< receiver enable */ -#define USART_CTL0_TEN BIT(3) /*!< transmitter enable */ -#define USART_CTL0_IDLEIE BIT(4) /*!< idle line detected interrupt enable */ -#define USART_CTL0_RBNEIE BIT(5) /*!< read data buffer not empty interrupt and overrun error interrupt enable */ -#define USART_CTL0_TCIE BIT(6) /*!< transmission complete interrupt enable */ -#define USART_CTL0_TBEIE BIT(7) /*!< transmitter buffer empty interrupt enable */ -#define USART_CTL0_PERRIE BIT(8) /*!< parity error interrupt enable */ -#define USART_CTL0_PM BIT(9) /*!< parity mode */ -#define USART_CTL0_PCEN BIT(10) /*!< parity check function enable */ -#define USART_CTL0_WM BIT(11) /*!< wakeup method in mute mode */ -#define USART_CTL0_WL BIT(12) /*!< word length */ -#define USART_CTL0_UEN BIT(13) /*!< USART enable */ +#define USART_CTL0_SBKCMD BIT(0) /*!< send break command */ +#define USART_CTL0_RWU BIT(1) /*!< receiver wakeup from mute mode */ +#define USART_CTL0_REN BIT(2) /*!< enable receiver */ +#define USART_CTL0_TEN BIT(3) /*!< enable transmitter */ +#define USART_CTL0_IDLEIE BIT(4) /*!< enable idle line detected interrupt */ +#define USART_CTL0_RBNEIE BIT(5) /*!< enable read data buffer not empty interrupt and overrun error interrupt */ +#define USART_CTL0_TCIE BIT(6) /*!< enable transmission complete interrupt */ +#define USART_CTL0_TBEIE BIT(7) /*!< enable transmitter buffer empty interrupt */ +#define USART_CTL0_PERRIE BIT(8) /*!< enable parity error interrupt */ +#define USART_CTL0_PM BIT(9) /*!< parity mode */ +#define USART_CTL0_PCEN BIT(10) /*!< enable parity check function */ +#define USART_CTL0_WM BIT(11) /*!< wakeup method in mute mode */ +#define USART_CTL0_WL BIT(12) /*!< word length */ +#define USART_CTL0_UEN BIT(13) /*!< enable USART */ /* USARTx_CTL1 */ -#define USART_CTL1_ADDR BITS(0,3) /*!< address of USART */ -#define USART_CTL1_LBLEN BIT(5) /*!< LIN break frame length */ -#define USART_CTL1_LBDIE BIT(6) /*!< LIN break detected interrupt eanble */ -#define USART_CTL1_CLEN BIT(8) /*!< CK length */ -#define USART_CTL1_CPH BIT(9) /*!< CK phase */ -#define USART_CTL1_CPL BIT(10) /*!< CK polarity */ -#define USART_CTL1_CKEN BIT(11) /*!< CK pin enable */ -#define USART_CTL1_STB BITS(12,13) /*!< STOP bits length */ -#define USART_CTL1_LMEN BIT(14) /*!< LIN mode enable */ +#define USART_CTL1_ADDR BITS(0,3) /*!< address of USART */ +#define USART_CTL1_LBLEN BIT(5) /*!< LIN break frame length */ +#define USART_CTL1_LBDIE BIT(6) /*!< eanble LIN break detected interrupt */ +#define USART_CTL1_CLEN BIT(8) /*!< CK length */ +#define USART_CTL1_CPH BIT(9) /*!< CK phase */ +#define USART_CTL1_CPL BIT(10) /*!< CK polarity */ +#define USART_CTL1_CKEN BIT(11) /*!< enable CK pin */ +#define USART_CTL1_STB BITS(12,13) /*!< STOP bits length */ +#define USART_CTL1_LMEN BIT(14) /*!< enable LIN mode */ /* USARTx_CTL2 */ -#define USART_CTL2_ERRIE BIT(0) /*!< error interrupt enable */ -#define USART_CTL2_IREN BIT(1) /*!< IrDA mode enable */ -#define USART_CTL2_IRLP BIT(2) /*!< IrDA low-power */ -#define USART_CTL2_HDEN BIT(3) /*!< half-duplex enable */ -#define USART_CTL2_NKEN BIT(4) /*!< NACK enable in smartcard mode */ -#define USART_CTL2_SCEN BIT(5) /*!< smartcard mode enable */ -#define USART_CTL2_DENR BIT(6) /*!< DMA request enable for reception */ -#define USART_CTL2_DENT BIT(7) /*!< DMA request enable for transmission */ -#define USART_CTL2_RTSEN BIT(8) /*!< RTS enable */ -#define USART_CTL2_CTSEN BIT(9) /*!< CTS enable */ -#define USART_CTL2_CTSIE BIT(10) /*!< CTS interrupt enable */ +#define USART_CTL2_ERRIE BIT(0) /*!< enable error interrupt */ +#define USART_CTL2_IREN BIT(1) /*!< enable IrDA mode */ +#define USART_CTL2_IRLP BIT(2) /*!< IrDA low-power */ +#define USART_CTL2_HDEN BIT(3) /*!< enable half-duplex */ +#define USART_CTL2_NKEN BIT(4) /*!< mode NACK enable in smartcard */ +#define USART_CTL2_SCEN BIT(5) /*!< senable martcard mode */ +#define USART_CTL2_DENR BIT(6) /*!< enable DMA request for reception */ +#define USART_CTL2_DENT BIT(7) /*!< enable DMA request for transmission */ +#define USART_CTL2_RTSEN BIT(8) /*!< enable RTS */ +#define USART_CTL2_CTSEN BIT(9) /*!< enable CTS */ +#define USART_CTL2_CTSIE BIT(10) /*!< enable CTS interrupt */ /* USARTx_GP */ -#define USART_GP_PSC BITS(0,7) /*!< prescaler value for dividing the system clock */ -#define USART_GP_GUAT BITS(8,15) /*!< guard time value in smartcard mode */ - +#define USART_GP_PSC BITS(0,7) /*!< prescaler value for dividing the system clock */ +#define USART_GP_GUAT BITS(8,15) /*!< guard time value in smartcard mode */ + /* USARTx_CTL3 */ -#define USART_CTL3_RTEN BIT(0) /*!< receiver timeout enable */ -#define USART_CTL3_SCRTNUM BITS(1,3) /*!< smartcard auto-retry number */ -#define USART_CTL3_RTIE BIT(4) /*!< interrupt enable bit of receive timeout event */ -#define USART_CTL3_EBIE BIT(5) /*!< interrupt enable bit of end of block event */ -#define USART_CTL3_RINV BIT(8) /*!< RX pin level inversion */ -#define USART_CTL3_TINV BIT(9) /*!< TX pin level inversion */ -#define USART_CTL3_DINV BIT(10) /*!< data bit level inversion */ -#define USART_CTL3_MSBF BIT(11) /*!< most significant bit first */ +#define USART_CTL3_RTEN BIT(0) /*!< enable receiver timeout */ +#define USART_CTL3_SCRTNUM BITS(1,3) /*!< smartcard auto-retry number */ +#define USART_CTL3_RTIE BIT(4) /*!< interrupt enable bit of receive timeout event */ +#define USART_CTL3_EBIE BIT(5) /*!< interrupt enable bit of end of block event */ +#define USART_CTL3_RINV BIT(8) /*!< RX pin level inversion */ +#define USART_CTL3_TINV BIT(9) /*!< TX pin level inversion */ +#define USART_CTL3_DINV BIT(10) /*!< data bit level inversion */ +#define USART_CTL3_MSBF BIT(11) /*!< most significant bit first */ /* USARTx_RT */ -#define USART_RT_RT BITS(0,23) /*!< receiver timeout threshold */ -#define USART_RT_BL BITS(24,31) /*!< block length */ +#define USART_RT_RT BITS(0,23) /*!< receiver timeout threshold */ +#define USART_RT_BL BITS(24,31) /*!< block length */ /* USARTx_STAT1 */ -#define USART_STAT1_RTF BIT(11) /*!< receiver timeout flag */ -#define USART_STAT1_EBF BIT(12) /*!< end of block flag */ -#define USART_STAT1_BSY BIT(16) /*!< busy flag */ +#define USART_STAT1_RTF BIT(11) /*!< receiver timeout flag */ +#define USART_STAT1_EBF BIT(12) /*!< end of block flag */ +#define USART_STAT1_BSY BIT(16) /*!< busy flag */ /* constants definitions */ /* define the USART bit position and its register index offset */ @@ -156,36 +153,34 @@ OF SUCH DAMAGE. #define USART_BIT_POS2(val) (((uint32_t)(val) & 0x1F0000U) >> 16) /* register offset */ -#define USART_STAT0_REG_OFFSET 0x00U /*!< STAT0 register offset */ -#define USART_STAT1_REG_OFFSET 0x88U /*!< STAT1 register offset */ -#define USART_CTL0_REG_OFFSET 0x0CU /*!< CTL0 register offset */ -#define USART_CTL1_REG_OFFSET 0x10U /*!< CTL1 register offset */ -#define USART_CTL2_REG_OFFSET 0x14U /*!< CTL2 register offset */ -#define USART_CTL3_REG_OFFSET 0x80U /*!< CTL3 register offset */ +#define USART_STAT0_REG_OFFSET ((uint32_t)0x00000000U) /*!< STAT0 register offset */ +#define USART_STAT1_REG_OFFSET ((uint32_t)0x00000088U) /*!< STAT1 register offset */ +#define USART_CTL0_REG_OFFSET ((uint32_t)0x0000000CU) /*!< CTL0 register offset */ +#define USART_CTL1_REG_OFFSET ((uint32_t)0x00000010U) /*!< CTL1 register offset */ +#define USART_CTL2_REG_OFFSET ((uint32_t)0x00000014U) /*!< CTL2 register offset */ +#define USART_CTL3_REG_OFFSET ((uint32_t)0x00000080U) /*!< CTL3 register offset */ /* USART flags */ -typedef enum -{ +typedef enum { /* flags in STAT0 register */ - USART_FLAG_CTS = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 9U), /*!< CTS change flag */ - USART_FLAG_LBD = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 8U), /*!< LIN break detected flag */ - USART_FLAG_TBE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 7U), /*!< transmit data buffer empty */ - USART_FLAG_TC = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 6U), /*!< transmission complete */ - USART_FLAG_RBNE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 5U), /*!< read data buffer not empty */ - USART_FLAG_IDLE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 4U), /*!< IDLE frame detected flag */ - USART_FLAG_ORERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 3U), /*!< overrun error */ - USART_FLAG_NERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 2U), /*!< noise error flag */ - USART_FLAG_FERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 1U), /*!< frame error flag */ - USART_FLAG_PERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 0U), /*!< parity error flag */ + USART_FLAG_CTS = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 9U), /*!< CTS change flag */ + USART_FLAG_LBD = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 8U), /*!< LIN break detected flag */ + USART_FLAG_TBE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 7U), /*!< transmit data buffer empty */ + USART_FLAG_TC = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 6U), /*!< transmission complete */ + USART_FLAG_RBNE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 5U), /*!< read data buffer not empty */ + USART_FLAG_IDLE = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 4U), /*!< IDLE frame detected flag */ + USART_FLAG_ORERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 3U), /*!< overrun error */ + USART_FLAG_NERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 2U), /*!< noise error flag */ + USART_FLAG_FERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 1U), /*!< frame error flag */ + USART_FLAG_PERR = USART_REGIDX_BIT(USART_STAT0_REG_OFFSET, 0U), /*!< parity error flag */ /* flags in STAT1 register */ - USART_FLAG_BSY = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 16U), /*!< busy flag */ - USART_FLAG_EB = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 12U), /*!< end of block flag */ - USART_FLAG_RT = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 11U), /*!< receiver timeout flag */ -}usart_flag_enum; + USART_FLAG_BSY = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 16U), /*!< busy flag */ + USART_FLAG_EB = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 12U), /*!< end of block flag */ + USART_FLAG_RT = USART_REGIDX_BIT(USART_STAT1_REG_OFFSET, 11U) /*!< receiver timeout flag */ +} usart_flag_enum; /* USART interrupt flags */ -typedef enum -{ +typedef enum { /* interrupt flags in CTL0 register */ USART_INT_FLAG_PERR = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 8U, USART_STAT0_REG_OFFSET, 0U), /*!< parity error interrupt and flag */ USART_INT_FLAG_TBE = USART_REGIDX_BIT2(USART_CTL0_REG_OFFSET, 7U, USART_STAT0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt and flag */ @@ -202,12 +197,11 @@ typedef enum USART_INT_FLAG_ERR_FERR = USART_REGIDX_BIT2(USART_CTL2_REG_OFFSET, 0U, USART_STAT0_REG_OFFSET, 1U), /*!< error interrupt and frame error flag */ /* interrupt flags in CTL3 register */ USART_INT_FLAG_EB = USART_REGIDX_BIT2(USART_CTL3_REG_OFFSET, 5U, USART_STAT1_REG_OFFSET, 12U), /*!< interrupt enable bit of end of block event and flag */ - USART_INT_FLAG_RT = USART_REGIDX_BIT2(USART_CTL3_REG_OFFSET, 4U, USART_STAT1_REG_OFFSET, 11U), /*!< interrupt enable bit of receive timeout event and flag */ -}usart_interrupt_flag_enum; + USART_INT_FLAG_RT = USART_REGIDX_BIT2(USART_CTL3_REG_OFFSET, 4U, USART_STAT1_REG_OFFSET, 11U) /*!< interrupt enable bit of receive timeout event and flag */ +} usart_interrupt_flag_enum; /* USART interrupt enable or disable */ -typedef enum -{ +typedef enum { /* interrupt in CTL0 register */ USART_INT_PERR = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 8U), /*!< parity error interrupt */ USART_INT_TBE = USART_REGIDX_BIT(USART_CTL0_REG_OFFSET, 7U), /*!< transmitter buffer empty interrupt */ @@ -221,123 +215,115 @@ typedef enum USART_INT_ERR = USART_REGIDX_BIT(USART_CTL2_REG_OFFSET, 0U), /*!< error interrupt */ /* interrupt in CTL3 register */ USART_INT_EB = USART_REGIDX_BIT(USART_CTL3_REG_OFFSET, 5U), /*!< end of block interrupt */ - USART_INT_RT = USART_REGIDX_BIT(USART_CTL3_REG_OFFSET, 4U), /*!< receive timeout interrupt */ -}usart_interrupt_enum; + USART_INT_RT = USART_REGIDX_BIT(USART_CTL3_REG_OFFSET, 4U) /*!< receive timeout interrupt */ +} usart_interrupt_enum; -/* USART invert configure */ -typedef enum -{ +/* configure USART invert */ +typedef enum { /* data bit level inversion */ - USART_DINV_ENABLE, /*!< data bit level inversion */ - USART_DINV_DISABLE, /*!< data bit level not inversion */ + USART_DINV_ENABLE, /*!< data bit level inversion */ + USART_DINV_DISABLE, /*!< data bit level not inversion */ /* TX pin level inversion */ - USART_TXPIN_ENABLE, /*!< TX pin level inversion */ - USART_TXPIN_DISABLE, /*!< TX pin level not inversion */ + USART_TXPIN_ENABLE, /*!< TX pin level inversion */ + USART_TXPIN_DISABLE, /*!< TX pin level not inversion */ /* RX pin level inversion */ - USART_RXPIN_ENABLE, /*!< RX pin level inversion */ - USART_RXPIN_DISABLE, /*!< RX pin level not inversion */ -}usart_invert_enum; + USART_RXPIN_ENABLE, /*!< RX pin level inversion */ + USART_RXPIN_DISABLE /*!< RX pin level not inversion */ +} usart_invert_enum; -/* USART receiver configure */ +/* configure USART receiver */ #define CTL0_REN(regval) (BIT(2) & ((uint32_t)(regval) << 2)) -#define USART_RECEIVE_ENABLE CTL0_REN(1) /*!< enable receiver */ -#define USART_RECEIVE_DISABLE CTL0_REN(0) /*!< disable receiver */ +#define USART_RECEIVE_ENABLE CTL0_REN(1) /*!< enable receiver */ +#define USART_RECEIVE_DISABLE CTL0_REN(0) /*!< disable receiver */ -/* USART transmitter configure */ +/* configure USART transmitter */ #define CTL0_TEN(regval) (BIT(3) & ((uint32_t)(regval) << 3)) -#define USART_TRANSMIT_ENABLE CTL0_TEN(1) /*!< enable transmitter */ -#define USART_TRANSMIT_DISABLE CTL0_TEN(0) /*!< disable transmitter */ +#define USART_TRANSMIT_ENABLE CTL0_TEN(1) /*!< enable transmitter */ +#define USART_TRANSMIT_DISABLE CTL0_TEN(0) /*!< disable transmitter */ /* USART parity bits definitions */ #define CTL0_PM(regval) (BITS(9,10) & ((uint32_t)(regval) << 9)) -#define USART_PM_NONE CTL0_PM(0) /*!< no parity */ -#define USART_PM_EVEN CTL0_PM(2) /*!< even parity */ -#define USART_PM_ODD CTL0_PM(3) /*!< odd parity */ +#define USART_PM_NONE CTL0_PM(0) /*!< no parity */ +#define USART_PM_EVEN CTL0_PM(2) /*!< even parity */ +#define USART_PM_ODD CTL0_PM(3) /*!< odd parity */ /* USART wakeup method in mute mode */ #define CTL0_WM(regval) (BIT(11) & ((uint32_t)(regval) << 11)) -#define USART_WM_IDLE CTL0_WM(0) /*!< idle line */ -#define USART_WM_ADDR CTL0_WM(1) /*!< address match */ +#define USART_WM_IDLE CTL0_WM(0) /*!< idle line */ +#define USART_WM_ADDR CTL0_WM(1) /*!< address match */ /* USART word length definitions */ #define CTL0_WL(regval) (BIT(12) & ((uint32_t)(regval) << 12)) -#define USART_WL_8BIT CTL0_WL(0) /*!< 8 bits */ -#define USART_WL_9BIT CTL0_WL(1) /*!< 9 bits */ +#define USART_WL_8BIT CTL0_WL(0) /*!< 8 bits */ +#define USART_WL_9BIT CTL0_WL(1) /*!< 9 bits */ /* USART stop bits definitions */ #define CTL1_STB(regval) (BITS(12,13) & ((uint32_t)(regval) << 12)) -#define USART_STB_1BIT CTL1_STB(0) /*!< 1 bit */ -#define USART_STB_0_5BIT CTL1_STB(1) /*!< 0.5 bit */ -#define USART_STB_2BIT CTL1_STB(2) /*!< 2 bits */ -#define USART_STB_1_5BIT CTL1_STB(3) /*!< 1.5 bits */ +#define USART_STB_1BIT CTL1_STB(0) /*!< 1 bit */ +#define USART_STB_0_5BIT CTL1_STB(1) /*!< 0.5 bit */ +#define USART_STB_2BIT CTL1_STB(2) /*!< 2 bits */ +#define USART_STB_1_5BIT CTL1_STB(3) /*!< 1.5 bits */ /* USART LIN break frame length */ #define CTL1_LBLEN(regval) (BIT(5) & ((uint32_t)(regval) << 5)) -#define USART_LBLEN_10B CTL1_LBLEN(0) /*!< 10 bits */ -#define USART_LBLEN_11B CTL1_LBLEN(1) /*!< 11 bits */ +#define USART_LBLEN_10B CTL1_LBLEN(0) /*!< 10 bits */ +#define USART_LBLEN_11B CTL1_LBLEN(1) /*!< 11 bits */ /* USART CK length */ #define CTL1_CLEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) -#define USART_CLEN_NONE CTL1_CLEN(0) /*!< there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame */ -#define USART_CLEN_EN CTL1_CLEN(1) /*!< there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame */ +#define USART_CLEN_NONE CTL1_CLEN(0) /*!< there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame */ +#define USART_CLEN_EN CTL1_CLEN(1) /*!< there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame */ /* USART clock phase */ #define CTL1_CPH(regval) (BIT(9) & ((uint32_t)(regval) << 9)) -#define USART_CPH_1CK CTL1_CPH(0) /*!< first clock transition is the first data capture edge */ -#define USART_CPH_2CK CTL1_CPH(1) /*!< second clock transition is the first data capture edge */ +#define USART_CPH_1CK CTL1_CPH(0) /*!< first clock transition is the first data capture edge */ +#define USART_CPH_2CK CTL1_CPH(1) /*!< second clock transition is the first data capture edge */ /* USART clock polarity */ #define CTL1_CPL(regval) (BIT(10) & ((uint32_t)(regval) << 10)) -#define USART_CPL_LOW CTL1_CPL(0) /*!< steady low value on CK pin */ -#define USART_CPL_HIGH CTL1_CPL(1) /*!< steady high value on CK pin */ - -/* USART DMA request for receive configure */ -#define CLT2_DENR(regval) (BIT(6) & ((uint32_t)(regval) << 6)) -#define USART_DENR_ENABLE CLT2_DENR(1) /*!< DMA request enable for reception */ -#define USART_DENR_DISABLE CLT2_DENR(0) /*!< DMA request disable for reception */ - -/* USART DMA request for transmission configure */ -#define CLT2_DENT(regval) (BIT(7) & ((uint32_t)(regval) << 7)) -#define USART_DENT_ENABLE CLT2_DENT(1) /*!< DMA request enable for transmission */ -#define USART_DENT_DISABLE CLT2_DENT(0) /*!< DMA request disable for transmission */ - -/* USART RTS configure */ +#define USART_CPL_LOW CTL1_CPL(0) /*!< steady low value on CK pin */ +#define USART_CPL_HIGH CTL1_CPL(1) /*!< steady high value on CK pin */ + +/* configure USART DMA */ +#define CLT2_RECEIVE_DMAEN(regval) (BIT(6) & ((uint32_t)(regval) << 6)) +#define CTL2_TRANSMIT_DMAEN(regval) (BIT(7) & ((uint32_t)(regval) << 7)) +#define USART_RECEIVE_DMA_ENABLE CLT2_RECEIVE_DMAEN(1) /* enable DMA request for reception */ +#define USART_RECEIVE_DMA_DISABLE CLT2_RECEIVE_DMAEN(0) /* disable DMA request for reception */ +#define USART_TRANSMIT_DMA_ENABLE CTL2_TRANSMIT_DMAEN(1) /* enable DMA request for transmission */ +#define USART_TRANSMIT_DMA_DISABLE CTL2_TRANSMIT_DMAEN(0) /* disable DMA request for transmission */ + +/* configure USART RTS */ #define CLT2_RTSEN(regval) (BIT(8) & ((uint32_t)(regval) << 8)) -#define USART_RTS_ENABLE CLT2_RTSEN(1) /*!< RTS enable */ -#define USART_RTS_DISABLE CLT2_RTSEN(0) /*!< RTS disable */ +#define USART_RTS_ENABLE CLT2_RTSEN(1) /*!< enable RTS */ +#define USART_RTS_DISABLE CLT2_RTSEN(0) /*!< disable RTS */ -/* USART CTS configure */ +/* configure USART CTS */ #define CLT2_CTSEN(regval) (BIT(9) & ((uint32_t)(regval) << 9)) -#define USART_CTS_ENABLE CLT2_CTSEN(1) /*!< CTS enable */ -#define USART_CTS_DISABLE CLT2_CTSEN(0) /*!< CTS disable */ +#define USART_CTS_ENABLE CLT2_CTSEN(1) /*!< enable CTS */ +#define USART_CTS_DISABLE CLT2_CTSEN(0) /*!< disable CTS */ -/* USART IrDA low-power enable */ +/* enable USART IrDA low-power */ #define CTL2_IRLP(regval) (BIT(2) & ((uint32_t)(regval) << 2)) -#define USART_IRLP_LOW CTL2_IRLP(1) /*!< low-power */ -#define USART_IRLP_NORMAL CTL2_IRLP(0) /*!< normal */ +#define USART_IRLP_LOW CTL2_IRLP(1) /*!< low-power */ +#define USART_IRLP_NORMAL CTL2_IRLP(0) /*!< normal */ /* USART data is transmitted/received with the LSB/MSB first */ #define CTL3_MSBF(regval) (BIT(11) & ((uint32_t)(regval) << 11)) -#define USART_MSBF_LSB CTL3_MSBF(0) /*!< LSB first */ -#define USART_MSBF_MSB CTL3_MSBF(1) /*!< MSB first */ - - +#define USART_MSBF_LSB CTL3_MSBF(0) /*!< LSB first */ +#define USART_MSBF_MSB CTL3_MSBF(1) /*!< MSB first */ /* function declarations */ /* initialization functions */ -/* reset USART */ +/* reset USART/UART */ void usart_deinit(uint32_t usart_periph); /* configure USART baud rate value */ void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval); -/* configure USART parity function */ +/* configure USART parity */ void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg); /* configure USART word length */ void usart_word_length_set(uint32_t usart_periph, uint32_t wlen); /* configure USART stop bit length */ void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen); - -/* function configuration */ -/* USART normal mode communication */ /* enable USART */ void usart_enable(uint32_t usart_periph); /* disable USART */ @@ -346,9 +332,11 @@ void usart_disable(uint32_t usart_periph); void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig); /* configure USART receiver */ void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig); + +/* USART normal mode communication */ /* data is transmitted/received with the LSB/MSB first */ void usart_data_first_config(uint32_t usart_periph, uint32_t msbf); -/* configure USART inverted */ +/* configure USART inversion */ void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara); /* enable receiver timeout */ void usart_receiver_timeout_enable(uint32_t usart_periph); @@ -362,7 +350,7 @@ void usart_data_transmit(uint32_t usart_periph, uint16_t data); uint16_t usart_data_receive(uint32_t usart_periph); /* multi-processor communication */ -/* configure address of the USART */ +/* configure the address of the USART in wake up by address match mode */ void usart_address_config(uint32_t usart_periph, uint8_t addr); /* enable mute mode */ void usart_mute_mode_enable(uint32_t usart_periph); @@ -372,44 +360,44 @@ void usart_mute_mode_disable(uint32_t usart_periph); void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod); /* LIN mode communication */ -/* LIN mode enable */ +/* enable LIN mode */ void usart_lin_mode_enable(uint32_t usart_periph); -/* LIN mode disable */ +/* disable LIN mode */ void usart_lin_mode_disable(uint32_t usart_periph); -/* LIN break detection length */ +/* configure lin break frame length */ void usart_lin_break_detection_length_config(uint32_t usart_periph, uint32_t lblen); /* send break frame */ void usart_send_break(uint32_t usart_periph); /* half-duplex communication */ -/* half-duplex enable */ +/* enable half-duplex mode */ void usart_halfduplex_enable(uint32_t usart_periph); -/* half-duplex disable */ +/* disable half-duplex mode */ void usart_halfduplex_disable(uint32_t usart_periph); /* synchronous communication */ -/* clock enable */ +/* enable CK pin in synchronous mode */ void usart_synchronous_clock_enable(uint32_t usart_periph); -/* clock disable */ +/* disable CK pin in synchronous mode */ void usart_synchronous_clock_disable(uint32_t usart_periph); -/* configure usart synchronous mode parameters */ +/* configure USART synchronous mode parameters */ void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl); /* smartcard communication */ -/* guard time value configure in smartcard mode */ -void usart_guard_time_config(uint32_t usart_periph,uint32_t guat); -/* smartcard mode enable */ +/* configure guard time value in smartcard mode */ +void usart_guard_time_config(uint32_t usart_periph, uint8_t guat); +/* enable smartcard mode */ void usart_smartcard_mode_enable(uint32_t usart_periph); -/* smartcard mode disable */ +/* disable smartcard mode */ void usart_smartcard_mode_disable(uint32_t usart_periph); -/* NACK enable in smartcard mode */ +/* enable NACK in smartcard mode */ void usart_smartcard_mode_nack_enable(uint32_t usart_periph); -/* NACK disable in smartcard mode */ +/* disable NACK in smartcard mode */ void usart_smartcard_mode_nack_disable(uint32_t usart_periph); -/* smartcard auto-retry number configure */ -void usart_smartcard_autoretry_config(uint32_t usart_periph, uint32_t scrtnum); -/* block length configure */ -void usart_block_length_config(uint32_t usart_periph, uint32_t bl); +/* configure smartcard auto-retry number */ +void usart_smartcard_autoretry_config(uint32_t usart_periph, uint8_t scrtnum); +/* configure block length */ +void usart_block_length_config(uint32_t usart_periph, uint8_t bl); /* IrDA communication */ /* enable IrDA mode */ @@ -427,23 +415,24 @@ void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig); /* configure hardware flow control CTS */ void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig); -/* configure USART DMA for reception */ -void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd); -/* configure USART DMA for transmission */ -void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd); +/* DMA communication */ +/* configure USART DMA reception */ +void usart_dma_receive_config(uint32_t usart_periph, uint8_t dmaconfig); +/* configure USART DMA transmission */ +void usart_dma_transmit_config(uint32_t usart_periph, uint8_t dmaconfig); -/* interrupt & flag functions */ +/* flag & interrupt functions */ /* get flag in STAT0/STAT1 register */ FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag); /* clear flag in STAT0/STAT1 register */ void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag); /* enable USART interrupt */ -void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag); +void usart_interrupt_enable(uint32_t usart_periph, usart_interrupt_enum interrupt); /* disable USART interrupt */ -void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag); +void usart_interrupt_disable(uint32_t usart_periph, usart_interrupt_enum interrupt); /* get USART interrupt and flag status */ -FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag); -/* clear interrupt flag in STAT0/STAT1 register */ -void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t flag); +FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, usart_interrupt_flag_enum int_flag); +/* clear USART interrupt flag in STAT0/STAT1 register */ +void usart_interrupt_flag_clear(uint32_t usart_periph, usart_interrupt_flag_enum int_flag); -#endif /* GD32F20X_USART_H */ +#endif /* GD32F20X_USART_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_wwdgt.h b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_wwdgt.h index 84b2dd26..d483ffc5 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_wwdgt.h +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Include/gd32f20x_wwdgt.h @@ -1,37 +1,34 @@ /*! \file gd32f20x_wwdgt.h - \brief definitions for the WWDGT + \brief definitions for the WWDGT - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -68,24 +65,30 @@ OF SUCH DAMAGE. #define WWDGT_CFG_PSC_DIV4 CFG_PSC(2) /*!< the time base of WWDGT = (PCLK1/4096)/4 */ #define WWDGT_CFG_PSC_DIV8 CFG_PSC(3) /*!< the time base of WWDGT = (PCLK1/4096)/8 */ +/* write value to WWDGT_CTL_CNT bit field */ +#define CTL_CNT(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) +/* write value to WWDGT_CFG_WIN bit field */ +#define CFG_WIN(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) + /* function declarations */ /* initialization functions */ /* reset the window watchdog timer configuration */ void wwdgt_deinit(void); /* start the window watchdog timer counter */ void wwdgt_enable(void); - /* configure the window watchdog timer counter value */ void wwdgt_counter_update(uint16_t counter_value); /* configure counter value, window value, and prescaler divider value */ void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler); /* interrupt & flag functions */ -/* enable early wakeup interrupt of WWDGT */ -void wwdgt_interrupt_enable(void); -/* check early wakeup interrupt state of WWDGT */ +/* get early wakeup interrupt flag of WWDGT */ +FlagStatus wwdgt_interrupt_flag_get(void); +/* get early wakeup flag of WWDGT */ FlagStatus wwdgt_flag_get(void); /* clear early wakeup interrupt state of WWDGT */ void wwdgt_flag_clear(void); +/* enable early wakeup interrupt of WWDGT */ +void wwdgt_interrupt_enable(void); #endif /* GD32F20X_WWDGT_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_adc.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_adc.c index 3e563616..5b6b2093 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_adc.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_adc.c @@ -2,36 +2,33 @@ \file gd32f20x_adc.c \brief ADC driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -60,14 +57,14 @@ OF SUCH DAMAGE. #define ADC_OFFSET_SHIFT_LENGTH ((uint8_t)4U) /*! - \brief reset ADC + \brief reset ADC \param[in] adc_periph: ADCx, x=0,1,2 \param[out] none \retval none */ void adc_deinit(uint32_t adc_periph) { - switch(adc_periph){ + switch(adc_periph) { case ADC0: /* reset ADC0 */ rcu_periph_reset_enable(RCU_ADC0RST); @@ -125,33 +122,33 @@ void adc_mode_config(uint32_t mode) */ void adc_special_function_config(uint32_t adc_periph, uint32_t function, ControlStatus new_value) { - if(new_value){ - if(0U != (function & ADC_SCAN_MODE)){ + if(new_value) { + if(0U != (function & ADC_SCAN_MODE)) { /* enable ADC scan mode */ ADC_CTL0(adc_periph) |= ADC_SCAN_MODE; } - if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)) { /* enable ADC inserted channel group convert automatically */ ADC_CTL0(adc_periph) |= ADC_INSERTED_CHANNEL_AUTO; } - if(0U != (function & ADC_CONTINUOUS_MODE)){ + if(0U != (function & ADC_CONTINUOUS_MODE)) { /* enable ADC continuous mode */ ADC_CTL1(adc_periph) |= ADC_CONTINUOUS_MODE; - } - }else{ - if(0U != (function & ADC_SCAN_MODE)){ + } + } else { + if(0U != (function & ADC_SCAN_MODE)) { /* disable scan mode */ ADC_CTL0(adc_periph) &= ~ADC_SCAN_MODE; } - if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)){ + if(0U != (function & ADC_INSERTED_CHANNEL_AUTO)) { /* disable ADC inserted channel group convert automatically */ ADC_CTL0(adc_periph) &= ~ADC_INSERTED_CHANNEL_AUTO; } - if(0U != (function & ADC_CONTINUOUS_MODE)){ + if(0U != (function & ADC_CONTINUOUS_MODE)) { /* disable ADC continuous mode */ ADC_CTL1(adc_periph) &= ~ADC_CONTINUOUS_MODE; } @@ -159,7 +156,7 @@ void adc_special_function_config(uint32_t adc_periph, uint32_t function, Control } /*! - \brief configure ADC data alignment + \brief configure ADC data alignment \param[in] adc_periph: ADCx, x=0,1,2 \param[in] data_alignment: data alignment select only one parameter can be selected which is shown as below: @@ -170,10 +167,10 @@ void adc_special_function_config(uint32_t adc_periph, uint32_t function, Control */ void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment) { - if(ADC_DATAALIGN_RIGHT != data_alignment){ + if(ADC_DATAALIGN_RIGHT != data_alignment) { /* MSB alignment */ ADC_CTL1(adc_periph) |= ADC_CTL1_DAL; - }else{ + } else { /* LSB alignment */ ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_DAL); } @@ -187,7 +184,7 @@ void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment) */ void adc_enable(uint32_t adc_periph) { - if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)){ + if(RESET == (ADC_CTL1(adc_periph) & ADC_CTL1_ADCON)) { /* enable ADC */ ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON; } @@ -216,12 +213,12 @@ void adc_calibration_enable(uint32_t adc_periph) /* reset the selected ADC calibration registers */ ADC_CTL1(adc_periph) |= (uint32_t) ADC_CTL1_RSTCLB; /* check the RSTCLB bit state */ - while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)){ + while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_RSTCLB)) { } /* enable ADC calibration process */ ADC_CTL1(adc_periph) |= ADC_CTL1_CLB; /* check the CLB bit state */ - while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_CLB)){ + while(RESET != (ADC_CTL1(adc_periph) & ADC_CTL1_CLB)) { } } @@ -250,7 +247,7 @@ void adc_tempsensor_vrefint_disable(void) } /*! - \brief enable DMA request + \brief enable DMA request \param[in] adc_periph: ADCx, x=0,1,2 only one among these parameters can be selected \param[out] none @@ -263,7 +260,7 @@ void adc_dma_mode_enable(uint32_t adc_periph) } /*! - \brief disable DMA request + \brief disable DMA request \param[in] adc_periph: ADCx, x=0,1,2 \param[out] none \retval none @@ -275,7 +272,7 @@ void adc_dma_mode_disable(uint32_t adc_periph) } /*! - \brief configure ADC discontinuous mode + \brief configure ADC discontinuous mode \param[in] adc_periph: ADCx, x=0,1,2 \param[in] adc_channel_group: select the channel group only one parameter can be selected which is shown as below: @@ -291,7 +288,7 @@ void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_grou { /* disable discontinuous mode of regular & inserted channel */ ADC_CTL0(adc_periph) &= ~((uint32_t)(ADC_CTL0_DISRC | ADC_CTL0_DISIC)); - switch(adc_channel_group){ + switch(adc_channel_group) { case ADC_REGULAR_CHANNEL: /* configure the number of conversions in discontinuous mode */ ADC_CTL0(adc_periph) &= ~((uint32_t)ADC_CTL0_DISNUM); @@ -304,7 +301,7 @@ void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_grou ADC_CTL0(adc_periph) |= (uint32_t)ADC_CTL0_DISIC; break; case ADC_CHANNEL_DISCON_DISABLE: - /* disable discontinuous mode of regular & inserted channel */ + /* disable discontinuous mode of regular & inserted channel */ default: break; } @@ -325,7 +322,7 @@ void adc_discontinuous_mode_config(uint32_t adc_periph, uint8_t adc_channel_grou */ void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length) { - switch(adc_channel_group){ + switch(adc_channel_group) { case ADC_REGULAR_CHANNEL: /* configure the length of regular channel group */ ADC_RSQ0(adc_periph) &= ~((uint32_t)ADC_RSQ0_RL); @@ -348,7 +345,7 @@ void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, u \param[in] rank: the regular group sequence rank,this parameter must be between 0 to 15 \param[in] adc_channel: the selected ADC channel only one parameter can be selected which is shown as below: - \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx + \arg ADC_CHANNEL_x(x=0..17)(x=16 and x=17 are only for ADC0): ADC Channelx \param[in] sample_time: the sample time value only one parameter can be selected which is shown as below: \arg ADC_SAMPLETIME_1POINT5: 1.5 cycles @@ -364,56 +361,56 @@ void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, u */ void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) { - uint32_t rsq,sampt; - + uint32_t rsq, sampt; + /* configure ADC regular sequence */ - if(rank < ADC_REGULAR_CHANNEL_RANK_SIX){ + if(rank < ADC_REGULAR_CHANNEL_RANK_SIX) { /* the regular group sequence rank is smaller than six */ rsq = ADC_RSQ2(adc_periph); rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH * rank))); /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH * rank)); ADC_RSQ2(adc_periph) = rsq; - }else if(rank < ADC_REGULAR_CHANNEL_RANK_TWELVE){ + } else if(rank < ADC_REGULAR_CHANNEL_RANK_TWELVE) { /* the regular group sequence rank is smaller than twelve */ rsq = ADC_RSQ1(adc_periph); rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH * (rank - ADC_REGULAR_CHANNEL_RANK_SIX)))); /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH * (rank - ADC_REGULAR_CHANNEL_RANK_SIX))); ADC_RSQ1(adc_periph) = rsq; - }else if(rank < ADC_REGULAR_CHANNEL_RANK_SIXTEEN){ + } else if(rank < ADC_REGULAR_CHANNEL_RANK_SIXTEEN) { /* the regular group sequence rank is smaller than sixteen */ rsq = ADC_RSQ0(adc_periph); rsq &= ~((uint32_t)(ADC_RSQX_RSQN << (ADC_REGULAR_CHANNEL_RANK_LENGTH * (rank - ADC_REGULAR_CHANNEL_RANK_TWELVE)))); /* the channel number is written to these bits to select a channel as the nth conversion in the regular channel group */ rsq |= ((uint32_t)adc_channel << (ADC_REGULAR_CHANNEL_RANK_LENGTH * (rank - ADC_REGULAR_CHANNEL_RANK_TWELVE))); ADC_RSQ0(adc_periph) = rsq; - }else{ + } else { /* illegal parameters */ } - + /* configure ADC sampling time */ - if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){ + if(adc_channel < ADC_CHANNEL_SAMPLE_TEN) { /* the regular group sequence rank is smaller than ten */ sampt = ADC_SAMPT1(adc_periph); sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH * adc_channel))); /* channel sample time set*/ sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH * adc_channel)); ADC_SAMPT1(adc_periph) = sampt; - }else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){ + } else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN) { /* the regular group sequence rank is smaller than eighteen */ sampt = ADC_SAMPT0(adc_periph); sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH * (adc_channel - ADC_CHANNEL_SAMPLE_TEN)))); /* channel sample time set*/ sampt |= (uint32_t)(sample_time << (ADC_CHANNEL_SAMPLE_LENGTH * (adc_channel - ADC_CHANNEL_SAMPLE_TEN))); ADC_SAMPT0(adc_periph) = sampt; - }else{ - /* illegal parameters */ + } else { + /* illegal parameters */ } } /*! - \brief configure ADC inserted channel + \brief configure ADC inserted channel \param[in] adc_periph: ADCx,x=0,1,2 only one among these parameters can be selected \param[in] rank: the inserted group sequencer rank,this parameter must be between 0 to 3 @@ -436,7 +433,7 @@ void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_c void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) { uint8_t inserted_length; - uint32_t isq,sampt; + uint32_t isq, sampt; /* get inserted channel group length */ inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph), 20U, 21U); /* the channel number is written to these bits to select a channel as the nth conversion in the inserted channel group */ @@ -445,28 +442,28 @@ void adc_inserted_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_ isq |= ((uint32_t)adc_channel << (ADC_INSERTED_CHANNEL_SHIFT_LENGTH - (inserted_length - rank) * ADC_INSERTED_CHANNEL_RANK_LENGTH)); ADC_ISQ(adc_periph) = isq; - /* ADC sampling time config */ - if(adc_channel < ADC_CHANNEL_SAMPLE_TEN){ + /* ADC sampling time config */ + if(adc_channel < ADC_CHANNEL_SAMPLE_TEN) { /* the inserted group sequence rank is smaller than ten */ sampt = ADC_SAMPT1(adc_periph); sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH * adc_channel))); /* channel sample time set*/ sampt |= (uint32_t) sample_time << (ADC_CHANNEL_SAMPLE_LENGTH * adc_channel); ADC_SAMPT1(adc_periph) = sampt; - }else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN){ + } else if(adc_channel < ADC_CHANNEL_SAMPLE_EIGHTEEN) { /* the inserted group sequence rank is smaller than eighteen */ sampt = ADC_SAMPT0(adc_periph); sampt &= ~((uint32_t)(ADC_SAMPTX_SPTN << (ADC_CHANNEL_SAMPLE_LENGTH * (adc_channel - ADC_CHANNEL_SAMPLE_TEN)))); /* channel sample time set*/ sampt |= ((uint32_t)sample_time << (ADC_CHANNEL_SAMPLE_LENGTH * (adc_channel - ADC_CHANNEL_SAMPLE_TEN))); ADC_SAMPT0(adc_periph) = sampt; - }else{ + } else { /* illegal parameters */ } } /*! - \brief configure ADC inserted channel offset + \brief configure ADC inserted channel offset \param[in] adc_periph: ADCx,x=0,1,2 only one among these parameters can be selected \param[in] inserted_channel: insert channel select @@ -486,8 +483,8 @@ void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_ch inserted_length = (uint8_t)GET_BITS(ADC_ISQ(adc_periph), 20U, 21U); num = ((uint32_t)ADC_OFFSET_LENGTH - ((uint32_t)inserted_length - (uint32_t)inserted_channel)); - - if(num <= ADC_OFFSET_LENGTH){ + + if(num <= ADC_OFFSET_LENGTH) { /* calculate the offset of the register */ num = num * ADC_OFFSET_SHIFT_LENGTH; /* configure the offset of the selected channels */ @@ -496,7 +493,7 @@ void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_ch } /*! - \brief configure ADC external trigger source + \brief configure ADC external trigger source \param[in] adc_periph: ADCx, x=0,1,2 only one among these parameters can be selected \param[in] adc_channel_group: select the channel group @@ -518,7 +515,7 @@ void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_ch \arg ADC2_EXTTRIG_REGULAR_T1_CH2: TIMER1 CH2 event select \arg ADC2_EXTTRIG_REGULAR_T0_CH2: TIMER0 CH2 event select \arg ADC2_EXTTRIG_REGULAR_T7_CH0: TIMER7 CH0 event select - \arg ADC2_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select + \arg ADC2_EXTTRIG_REGULAR_T7_TRGO: TIMER7 TRGO event select \arg ADC2_EXTTRIG_REGULAR_T4_CH0: TIMER4 CH0 event select \arg ADC2_EXTTRIG_REGULAR_T4_CH2: TIMER4 CH2 event select \arg ADC0_1_2_EXTTRIG_REGULAR_NONE: software trigger @@ -543,8 +540,8 @@ void adc_inserted_channel_offset_config(uint32_t adc_periph, uint8_t inserted_ch \retval none */ void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source) -{ - switch(adc_channel_group){ +{ + switch(adc_channel_group) { case ADC_REGULAR_CHANNEL: /* configure ADC regular group external trigger source */ ADC_CTL1(adc_periph) &= ~((uint32_t)ADC_CTL1_ETSRC); @@ -561,7 +558,7 @@ void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel } /*! - \brief configure ADC external trigger + \brief configure ADC external trigger \param[in] adc_periph: ADCx, x=0,1,2 only one among these parameters can be selected \param[in] adc_channel_group: select the channel group @@ -574,23 +571,23 @@ void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel */ void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue) { - if(newvalue){ - if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + if(newvalue) { + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)) { /* external trigger enable for regular channel */ ADC_CTL1(adc_periph) |= ADC_CTL1_ETERC; } - if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)) { /* external trigger enable for inserted channel */ ADC_CTL1(adc_periph) |= ADC_CTL1_ETEIC; } - }else{ - if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + } else { + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)) { /* external trigger disable for regular channel */ ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETERC; } - if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)) { /* external trigger disable for inserted channel */ ADC_CTL1(adc_periph) &= ~ADC_CTL1_ETEIC; } @@ -598,7 +595,7 @@ void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, } /*! - \brief enable ADC software trigger + \brief enable ADC software trigger \param[in] adc_periph: ADCx, x=0,1,2 only one among these parameters can be selected \param[in] adc_channel_group: select the channel group @@ -610,19 +607,19 @@ void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, */ void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group) { - if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)){ + if(0U != (adc_channel_group & ADC_REGULAR_CHANNEL)) { /* enable regular group channel software trigger */ ADC_CTL1(adc_periph) |= ADC_CTL1_SWRCST; } - if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)){ + if(0U != (adc_channel_group & ADC_INSERTED_CHANNEL)) { /* enable inserted channel group software trigger */ ADC_CTL1(adc_periph) |= ADC_CTL1_SWICST; } } /*! - \brief read ADC regular group data register + \brief read ADC regular group data register \param[in] adc_periph: ADCx, x=0,1,2 only one among these parameters can be selected \param[in] none @@ -635,7 +632,7 @@ uint16_t adc_regular_data_read(uint32_t adc_periph) } /*! - \brief read ADC inserted group data register + \brief read ADC inserted group data register \param[in] adc_periph: ADCx, x=0,1,2 only one among these parameters can be selected \param[in] inserted_channel: inserted channel select @@ -651,7 +648,7 @@ uint16_t adc_inserted_data_read(uint32_t adc_periph, uint8_t inserted_channel) { uint32_t idata; /* read the data of the selected channel */ - switch(inserted_channel){ + switch(inserted_channel) { case ADC_INSERTED_CHANNEL_0: /* read the data of channel 0 */ idata = ADC_IDATA0(adc_periph); @@ -688,7 +685,7 @@ uint32_t adc_sync_mode_convert_value_read(void) } /*! - \brief configure ADC analog watchdog single channel + \brief configure ADC analog watchdog single channel \param[in] adc_periph: ADCx, x=0,1,2 only one among these parameters can be selected \param[in] adc_channel: the selected ADC channel @@ -706,11 +703,11 @@ void adc_watchdog_single_channel_enable(uint32_t adc_periph, uint8_t adc_channel } /*! - \brief configure ADC analog watchdog group channel + \brief configure ADC analog watchdog group channel \param[in] adc_periph: ADCx, x=0,1,2 only one among these parameters can be selected \param[in] adc_channel_group: the channel group use analog watchdog - only one parameter can be selected which is shown as below: + only one parameter can be selected which is shown as below: \arg ADC_REGULAR_CHANNEL: regular channel group \arg ADC_INSERTED_CHANNEL: inserted channel group \arg ADC_REGULAR_INSERTED_CHANNEL: both regular and inserted group @@ -721,7 +718,7 @@ void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_ { ADC_CTL0(adc_periph) &= (uint32_t)~(ADC_CTL0_RWDEN | ADC_CTL0_IWDEN | ADC_CTL0_WDSC); /* select the group */ - switch(adc_channel_group){ + switch(adc_channel_group) { case ADC_REGULAR_CHANNEL: /* regular channel analog watchdog enable */ ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_RWDEN; @@ -740,7 +737,7 @@ void adc_watchdog_group_channel_enable(uint32_t adc_periph, uint8_t adc_channel_ } /*! - \brief disable ADC analog watchdog + \brief disable ADC analog watchdog \param[in] adc_periph: ADCx,x=0,1,2 only one among these parameters can be selected \param[out] none @@ -752,7 +749,7 @@ void adc_watchdog_disable(uint32_t adc_periph) } /*! - \brief configure ADC analog watchdog threshold + \brief configure ADC analog watchdog threshold \param[in] adc_periph: ADCx,x=0,1,2 only one among these parameters can be selected \param[in] low_threshold: analog watchdog low threshold,0..4095 @@ -766,6 +763,95 @@ void adc_watchdog_threshold_config(uint32_t adc_periph, uint16_t low_threshold, ADC_WDHT(adc_periph) = (uint32_t)WDHT_WDHT(high_threshold); } +/*! + \brief configure ADC resolution + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[in] resolution: ADC resolution + only one among these parameters can be selected + \arg ADC_RESOLUTION_12B: 12-bit ADC resolution + \arg ADC_RESOLUTION_10B: 10-bit ADC resolution + \arg ADC_RESOLUTION_8B: 8-bit ADC resolution + \arg ADC_RESOLUTION_6B: 6-bit ADC resolution + \param[out] none + \retval none +*/ +void adc_resolution_config(uint32_t adc_periph, uint32_t resolution) +{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_DRES); + ADC_OVSAMPCTL(adc_periph) |= (uint32_t)resolution; +} + +/*! + \brief configure ADC oversample mode + \param[in] adc_periph: ADCx, x=0,1,2 + only one among these parameters can be selected + \param[in] mode: ADC oversampling mode + only oneparameter can be selected + \arg ADC_OVERSAMPLING_ALL_CONVERT: all oversampled conversions for a channel are done consecutively after a trigger + \arg ADC_OVERSAMPLING_ONE_CONVERT: each oversampled conversion for a channel needs a trigger + \param[in] shift: ADC oversampling shift + only oneparameter can be selected + \arg ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_4B: 3-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift + \arg ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift + \param[in] ratio: ADC oversampling ratio + only oneparameter can be selected + \arg ADC_OVERSAMPLING_RATIO_MUL2: oversampling ratio multiple 2 + \arg ADC_OVERSAMPLING_RATIO_MUL4: oversampling ratio multiple 4 + \arg ADC_OVERSAMPLING_RATIO_MUL8: oversampling ratio multiple 8 + \arg ADC_OVERSAMPLING_RATIO_MUL16: oversampling ratio multiple 16 + \arg ADC_OVERSAMPLING_RATIO_MUL32: oversampling ratio multiple 32 + \arg ADC_OVERSAMPLING_RATIO_MUL64: oversampling ratio multiple 64 + \arg ADC_OVERSAMPLING_RATIO_MUL128: oversampling ratio multiple 128 + \arg ADC_OVERSAMPLING_RATIO_MUL256: oversampling ratio multiple 256 + \param[out] none + \retval none +*/ +void adc_oversample_mode_config(uint32_t adc_periph, uint8_t mode, uint16_t shift, uint8_t ratio) +{ + /* configure ADC oversampling mode */ + if(ADC_OVERSAMPLING_ONE_CONVERT == mode) { + ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_TOVS; + } else { + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_TOVS); + } + + /* configure the shift and ratio */ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)(ADC_OVSAMPCTL_OVSR | ADC_OVSAMPCTL_OVSS)); + ADC_OVSAMPCTL(adc_periph) |= ((uint32_t)shift | (uint32_t)ratio); +} + +/*! + \brief enable ADC oversample mode + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_oversample_mode_enable(uint32_t adc_periph) +{ + ADC_OVSAMPCTL(adc_periph) |= ADC_OVSAMPCTL_OVSEN; +} + +/*! + \brief disable ADC oversample mode + \param[in] adc_periph: ADCx,x=0,1,2 + only one among these parameters can be selected + \param[out] none + \retval none +*/ +void adc_oversample_mode_disable(uint32_t adc_periph) +{ + ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_OVSEN); +} + /*! \brief get the ADC flag bits \param[in] adc_periph: ADCx, x=0,1,2 @@ -783,7 +869,7 @@ void adc_watchdog_threshold_config(uint32_t adc_periph, uint16_t low_threshold, FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag) { FlagStatus reval = RESET; - if(ADC_STAT(adc_periph) & adc_flag){ + if(ADC_STAT(adc_periph) & adc_flag) { reval = SET; } return reval; @@ -809,70 +895,7 @@ void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag) } /*! - \brief get the ADC interrupt flag - \param[in] adc_periph: ADCx,x=0,1,2 - only one among these parameters can be selected - \param[in] adc_interrupt: the adc interrupt bits - only one parameter can be selected which is shown as below: - \arg ADC_INT_FLAG_WDE: analog watchdog interrupt - \arg ADC_INT_FLAG_EOC: end of group conversion interrupt - \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt) -{ - FlagStatus interrupt_flag = RESET; - uint32_t state; - /* check the interrupt bits */ - switch(adc_interrupt){ - case ADC_INT_FLAG_WDE: - /* get the ADC analog watchdog interrupt bits */ - state = ADC_STAT(adc_periph) & ADC_STAT_WDE; - if((ADC_CTL0(adc_periph) & ADC_CTL0_WDEIE) && state){ - interrupt_flag = SET; - } - break; - case ADC_INT_FLAG_EOC: - /* get the ADC end of group conversion interrupt bits */ - state = ADC_STAT(adc_periph) & ADC_STAT_EOC; - if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state){ - interrupt_flag = SET; - } - break; - case ADC_INT_FLAG_EOIC: - /* get the ADC end of inserted group conversion interrupt bits */ - state = ADC_STAT(adc_periph) & ADC_STAT_EOIC; - if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state){ - interrupt_flag = SET; - } - break; - default: - break; - } - - return interrupt_flag; -} - -/*! - \brief clear the ADC interrupt flag - \param[in] adc_periph: ADCx, x=0,1,2 - only one among these parameters can be selected - \param[in] adc_interrupt: the adc status flag - one or more parameters can be selected which are shown as below: - \arg ADC_INT_FLAG_WDE: analog watchdog interrupt - \arg ADC_INT_FLAG_EOC: end of group conversion interrupt - \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt - \param[out] none - \retval none -*/ -void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt) -{ - ADC_STAT(adc_periph) &= ~((uint32_t)adc_interrupt); -} - -/*! - \brief enable ADC interrupt + \brief enable ADC interrupt \param[in] adc_periph: ADCx, x=0,1,2 only one among these parameters can be selected \param[in] adc_interrupt: the adc interrupt @@ -886,21 +909,21 @@ void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt) void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt) { /* enable ADC analog watchdog interrupt */ - if(0U != (adc_interrupt & ADC_INT_WDE)){ + if(0U != (adc_interrupt & ADC_INT_WDE)) { ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_WDEIE; - } + } /* enable ADC end of group conversion interrupt */ - if(0U != (adc_interrupt & ADC_INT_EOC)){ + if(0U != (adc_interrupt & ADC_INT_EOC)) { ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOCIE; - } + } /* enable ADC end of inserted group conversion interrupt */ - if(0U != (adc_interrupt & ADC_INT_EOIC)){ + if(0U != (adc_interrupt & ADC_INT_EOIC)) { ADC_CTL0(adc_periph) |= (uint32_t) ADC_CTL0_EOICIE; } } /*! - \brief disable ADC interrupt + \brief disable ADC interrupt \param[in] adc_periph: ADCx,x=0,1,2 only one among these parameters can be selected \param[in] adc_interrupt: the adc interrupt flag @@ -912,108 +935,81 @@ void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt) \retval none */ void adc_interrupt_disable(uint32_t adc_periph, uint32_t adc_interrupt) -{ +{ /* disable ADC analog watchdog interrupt */ - if(0U != (adc_interrupt & ADC_INT_WDE)){ + if(0U != (adc_interrupt & ADC_INT_WDE)) { ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_WDEIE; - } + } /* disable ADC end of group conversion interrupt */ - if(0U != (adc_interrupt & ADC_INT_EOC)){ + if(0U != (adc_interrupt & ADC_INT_EOC)) { ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOCIE; - } + } /* disable ADC end of inserted group conversion interrupt */ - if(0U != (adc_interrupt & ADC_INT_EOIC)){ + if(0U != (adc_interrupt & ADC_INT_EOIC)) { ADC_CTL0(adc_periph) &= ~(uint32_t) ADC_CTL0_EOICIE; } } - - /*! - \brief configure ADC resolution + \brief get the ADC interrupt flag \param[in] adc_periph: ADCx,x=0,1,2 only one among these parameters can be selected - \param[in] resolution: ADC resolution - only one among these parameters can be selected - \arg ADC_RESOLUTION_12B: 12-bit ADC resolution - \arg ADC_RESOLUTION_10B: 10-bit ADC resolution - \arg ADC_RESOLUTION_8B: 8-bit ADC resolution - \arg ADC_RESOLUTION_6B: 6-bit ADC resolution - \param[out] none - \retval none -*/ -void adc_resolution_config(uint32_t adc_periph, uint32_t resolution) -{ - ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_DRES); - ADC_OVSAMPCTL(adc_periph) |= (uint32_t)resolution; -} - -/*! - \brief configure ADC oversample mode - \param[in] adc_periph: ADCx, x=0,1,2 - only one among these parameters can be selected - \param[in] mode: ADC oversampling mode - only oneparameter can be selected - \arg ADC_OVERSAMPLING_ALL_CONVERT: all oversampled conversions for a channel are done consecutively after a trigger - \arg ADC_OVERSAMPLING_ONE_CONVERT: each oversampled conversion for a channel needs a trigger - \param[in] shift: ADC oversampling shift - only oneparameter can be selected - \arg ADC_OVERSAMPLING_SHIFT_NONE: no oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_1B: 1-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_2B: 2-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_3B: 3-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_4B: 3-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_5B: 5-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_6B: 6-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_7B: 7-bit oversampling shift - \arg ADC_OVERSAMPLING_SHIFT_8B: 8-bit oversampling shift - \param[in] ratio: ADC oversampling ratio - only oneparameter can be selected - \arg ADC_OVERSAMPLING_RATIO_MUL2: oversampling ratio multiple 2 - \arg ADC_OVERSAMPLING_RATIO_MUL4: oversampling ratio multiple 4 - \arg ADC_OVERSAMPLING_RATIO_MUL8: oversampling ratio multiple 8 - \arg ADC_OVERSAMPLING_RATIO_MUL16: oversampling ratio multiple 16 - \arg ADC_OVERSAMPLING_RATIO_MUL32: oversampling ratio multiple 32 - \arg ADC_OVERSAMPLING_RATIO_MUL64: oversampling ratio multiple 64 - \arg ADC_OVERSAMPLING_RATIO_MUL128: oversampling ratio multiple 128 - \arg ADC_OVERSAMPLING_RATIO_MUL256: oversampling ratio multiple 256 + \param[in] adc_interrupt: the adc interrupt bits + only one parameter can be selected which is shown as below: + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt \param[out] none - \retval none + \retval FlagStatus: SET or RESET */ -void adc_oversample_mode_config(uint32_t adc_periph, uint8_t mode, uint16_t shift, uint8_t ratio) +FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt) { - /* configure ADC oversampling mode */ - if(ADC_OVERSAMPLING_ONE_CONVERT == mode){ - ADC_OVSAMPCTL(adc_periph) |= (uint32_t)ADC_OVSAMPCTL_TOVS; - }else{ - ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_TOVS); + FlagStatus interrupt_flag = RESET; + uint32_t state; + /* check the interrupt bits */ + switch(adc_interrupt) { + case ADC_INT_FLAG_WDE: + /* get the ADC analog watchdog interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_WDE; + if((ADC_CTL0(adc_periph) & ADC_CTL0_WDEIE) && state) { + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOC: + /* get the ADC end of group conversion interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_EOC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOCIE) && state) { + interrupt_flag = SET; + } + break; + case ADC_INT_FLAG_EOIC: + /* get the ADC end of inserted group conversion interrupt bits */ + state = ADC_STAT(adc_periph) & ADC_STAT_EOIC; + if((ADC_CTL0(adc_periph) & ADC_CTL0_EOICIE) && state) { + interrupt_flag = SET; + } + break; + default: + break; } - - /* configure the shift and ratio */ - ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)(ADC_OVSAMPCTL_OVSR | ADC_OVSAMPCTL_OVSS)); - ADC_OVSAMPCTL(adc_periph) |= ((uint32_t)shift | (uint32_t)ratio); -} -/*! - \brief enable ADC oversample mode - \param[in] adc_periph: ADCx,x=0,1,2 - only one among these parameters can be selected - \param[out] none - \retval none -*/ -void adc_oversample_mode_enable(uint32_t adc_periph) -{ - ADC_OVSAMPCTL(adc_periph) |= ADC_OVSAMPCTL_OVSEN; + return interrupt_flag; } /*! - \brief disable ADC oversample mode - \param[in] adc_periph: ADCx,x=0,1,2 + \brief clear the ADC interrupt flag + \param[in] adc_periph: ADCx, x=0,1,2 only one among these parameters can be selected + \param[in] adc_interrupt: the adc status flag + one or more parameters can be selected which are shown as below: + \arg ADC_INT_FLAG_WDE: analog watchdog interrupt + \arg ADC_INT_FLAG_EOC: end of group conversion interrupt + \arg ADC_INT_FLAG_EOIC: end of inserted group conversion interrupt \param[out] none \retval none */ -void adc_oversample_mode_disable(uint32_t adc_periph) +void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt) { - ADC_OVSAMPCTL(adc_periph) &= ~((uint32_t)ADC_OVSAMPCTL_OVSEN); + ADC_STAT(adc_periph) &= ~((uint32_t)adc_interrupt); } + diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_bkp.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_bkp.c index c6081cc5..687d4464 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_bkp.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_bkp.c @@ -2,43 +2,41 @@ \file gd32f20x_bkp.c \brief BKP driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "gd32f20x_bkp.h" -#define TAMPER0_FLAG_SHIFT ((uint8_t)8U) -#define TAMPER1_FLAG_SHIFT ((uint8_t)9U) +#define TAMPER0_FLAG_SHIFT ((uint8_t)0x08U) +#define TAMPER1_FLAG_SHIFT ((uint8_t)0x09U) +#define TAMPER1_PIN_SHIFT ((uint8_t)0x08U) /*! \brief reset BKP registers @@ -64,11 +62,11 @@ void bkp_deinit(void) */ void bkp_data_write(bkp_data_register_enum register_number, uint16_t data) { - if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)) { BKP_DATA10_41(register_number - 1U) = data; - }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + } else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)) { BKP_DATA0_9(register_number - 1U) = data; - }else{ + } else { /* illegal parameters */ } } @@ -84,13 +82,13 @@ void bkp_data_write(bkp_data_register_enum register_number, uint16_t data) uint16_t bkp_data_read(bkp_data_register_enum register_number) { uint16_t data = 0U; - + /* get the data from the BKP data register */ - if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)){ + if((register_number >= BKP_DATA_10) && (register_number <= BKP_DATA_41)) { data = BKP_DATA10_41(register_number - 1U); - }else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)){ + } else if((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_9)) { data = BKP_DATA0_9(register_number - 1U); - }else{ + } else { /* illegal parameters */ } return data; @@ -152,7 +150,7 @@ void bkp_rtc_signal_output_disable(void) void bkp_rtc_output_select(uint16_t outputsel) { uint16_t ctl = 0U; - + ctl = BKP_OCTL; ctl &= (uint16_t)~BKP_OCTL_ROSEL; ctl |= outputsel; @@ -160,8 +158,9 @@ void bkp_rtc_output_select(uint16_t outputsel) } /*! - \brief select RTC clock output + \brief RTC clock output selection \param[in] clocksel: RTC clock output selection + only one parameter can be selected which is shown as below: \arg RTC_CLOCK_DIV64: RTC clock div 64 \arg RTC_CLOCK_DIV1: RTC clock \param[out] none @@ -170,7 +169,7 @@ void bkp_rtc_output_select(uint16_t outputsel) void bkp_rtc_clock_output_select(uint16_t clocksel) { uint16_t ctl = 0U; - + ctl = BKP_OCTL; ctl &= (uint16_t)~BKP_OCTL_CCOSEL; ctl |= clocksel; @@ -180,7 +179,8 @@ void bkp_rtc_clock_output_select(uint16_t clocksel) /*! \brief RTC clock calibration direction \param[in] direction: RTC clock calibration direction - \arg RTC_CLOCK_SLOWED_DOWN: RTC clock slow down + only one parameter can be selected which is shown as below: + \arg RTC_CLOCK_SLOW_DOWN: RTC clock slow down \arg RTC_CLOCK_SPEED_UP: RTC clock speed up \param[out] none \retval none @@ -188,7 +188,7 @@ void bkp_rtc_clock_output_select(uint16_t clocksel) void bkp_rtc_clock_calibration_direction(uint16_t direction) { uint16_t ctl = 0U; - + ctl = BKP_OCTL; ctl &= (uint16_t)~BKP_OCTL_CALDIR; ctl |= direction; @@ -196,7 +196,7 @@ void bkp_rtc_clock_calibration_direction(uint16_t direction) } /*! - \brief set RTC clock calibration value + \brief set RTC clock calibration value \param[in] value: RTC clock calibration value \arg 0x00 - 0x7F \param[out] none @@ -205,7 +205,7 @@ void bkp_rtc_clock_calibration_direction(uint16_t direction) void bkp_rtc_calibration_value_set(uint8_t value) { uint16_t ctl; - + /* configure BKP_OCTL_RCCV with value */ ctl = BKP_OCTL; ctl &= (uint16_t)OCTL_RCCV(0); @@ -214,8 +214,9 @@ void bkp_rtc_calibration_value_set(uint8_t value) } /*! - \brief enable tamper detection - \param[in] tamperx + \brief enable tamper pin detection + \param[in] tamperx: BKP tamperx + only one parameter can be selected which is shown as below: \arg TAMPER_0: BKP tamper0 \arg TAMPER_1: BKP tamper1 \param[out] none @@ -223,16 +224,17 @@ void bkp_rtc_calibration_value_set(uint8_t value) */ void bkp_tamper_detection_enable(bkp_tamper_enum tamperx) { - if(TAMPER_0 == tamperx){ + if(TAMPER_0 == tamperx) { BKP_TPCTL0 |= (uint16_t)BKP_TPCTL0_TPEN0; - }else{ + } else { BKP_TPCTL1 |= (uint16_t)BKP_TPCTL1_TPEN1; } } /*! - \brief disable tamper detection - \param[in] tamperx + \brief disable tamper pin detection + \param[in] tamperx: BKP tamperx + only one parameter can be selected which is shown as below: \arg TAMPER_0: BKP tamper0 \arg TAMPER_1: BKP tamper1 \param[out] none @@ -240,19 +242,21 @@ void bkp_tamper_detection_enable(bkp_tamper_enum tamperx) */ void bkp_tamper_detection_disable(bkp_tamper_enum tamperx) { - if(TAMPER_0 == tamperx){ + if(TAMPER_0 == tamperx) { BKP_TPCTL0 &= (uint16_t)~BKP_TPCTL0_TPEN0; - }else{ + } else { BKP_TPCTL1 &= (uint16_t)~BKP_TPCTL1_TPEN1; } } /*! \brief set tamper pin active level - \param[in] tamperx + \param[in] tamperx: BKP tamperx + only one parameter can be selected which is shown as below: \arg TAMPER_0: BKP tamper0 \arg TAMPER_1: BKP tamper1 - \param[in] level: tamper active level + \param[in] level: tamper pin active level + only one parameter can be selected which is shown as below: \arg TAMPER_PIN_ACTIVE_HIGH: the tamper pin is active high \arg TAMPER_PIN_ACTIVE_LOW: the tamper pin is active low \param[out] none @@ -262,69 +266,36 @@ void bkp_tamper_active_level_set(bkp_tamper_enum tamperx, uint16_t level) { uint16_t ctl = 0U; - if(TAMPER_0 == tamperx){ + if(TAMPER_0 == tamperx) { ctl = BKP_TPCTL0; ctl &= (uint16_t)~BKP_TPCTL0_TPAL0; ctl |= level; BKP_TPCTL0 = ctl; - }else{ + } else { ctl = BKP_TPCTL1; ctl &= (uint16_t)~BKP_TPCTL1_TPAL1; - ctl |= level; + ctl |= (uint16_t)(level << TAMPER1_PIN_SHIFT); BKP_TPCTL1 = ctl; } } -/*! - \brief enable tamper interrupt - \param[in] tamperx - \arg TAMPER_0: BKP tamper0 - \arg TAMPER_1: BKP tamper1 - \param[out] none - \retval none -*/ -void bkp_tamper_interrupt_enable(bkp_tamper_enum tamperx) -{ - if(TAMPER_0 == tamperx){ - BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE0; - }else{ - BKP_TPCS |= (uint16_t)BKP_TPCS_TPIE1; - } -} - -/*! - \brief disable tamper interrupt - \param[in] tamperx - \arg TAMPER_0: BKP tamper0 - \arg TAMPER_1: BKP tamper1 - \param[out] none - \retval none -*/ -void bkp_tamper_interrupt_disable(bkp_tamper_enum tamperx) -{ - if(TAMPER_0 == tamperx){ - BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE0; - }else{ - BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE1; - } -} - /*! \brief waveform detect configure - \param[in] waveform_detect_mode + \param[in] waveform_detect_mode: + only one parameter can be selected which is shown as below: \arg BKP_WAVEFORM_DETECT_1: the first waveform detection \arg BKP_WAVEFORM_DETECT_2: the second waveform detection \param[in] newvalue: ENABLE or DISABLE \param[out] none - \retval FlagStatus: SET or RESET + \retval none */ -void bkp_waveform_detect_enable(uint16_t waveform_detect_mode, ControlStatus newvalue) +void bkp_waveform_detect_config(uint16_t waveform_detect_mode, ControlStatus newvalue) { uint16_t tpctl0 = 0U, tpctl1 = 0U, octl = 0U; - + tpctl0 = BKP_TPCTL0; tpctl1 = BKP_TPCTL1; - + /* disable tamper0 and tamper1 */ tpctl0 &= (uint16_t)~BKP_TPCTL0_TPEN0; tpctl1 &= (uint16_t)~BKP_TPCTL1_TPEN1; @@ -339,54 +310,99 @@ void bkp_waveform_detect_enable(uint16_t waveform_detect_mode, ControlStatus new BKP_TPCTL1 = tpctl1; BKP_OCTL = octl; - if(DISABLE != newvalue){ + if(DISABLE != newvalue) { /* enable the waveform detection function */ BKP_TPCTL1 |= waveform_detect_mode; - }else{ + } else { /* disable the waveform detection function */ BKP_TPCTL1 &= (uint16_t)(~waveform_detect_mode); } } /*! - \brief get bkp flag state - \param[in] flag + \brief get BKP flag + \param[in] flag: + only one parameter can be selected which is shown as below: \arg BKP_FLAG_TAMPER0: tamper0 event flag - \arg BKP_FLAG_TAMPER1_WAVEDETECT: tamper1/wavedetect event flag + \arg BKP_FLAG_TAMPER1_WAVEDETECT: tamper1/waveform detect event flag \param[out] none \retval FlagStatus: SET or RESET */ FlagStatus bkp_flag_get(uint16_t flag) { - if(RESET != (BKP_TPCS & flag)){ + if(RESET != (BKP_TPCS & flag)) { return SET; - }else{ + } else { return RESET; } } /*! - \brief clear bkp flag state - \param[in] flag + \brief clear BKP flag + \param[in] flag: + only one parameter can be selected which is shown as below: \arg BKP_FLAG_TAMPER0: tamper0 event flag - \arg BKP_FLAG_TAMPER1_WAVEDETECT: tamper1/wavedetect event flag + \arg BKP_FLAG_TAMPER1_WAVEDETECT: tamper1/waveform detect event flag \param[out] none \retval none */ void bkp_flag_clear(uint16_t flag) { - if(BKP_FLAG_TAMPER0 == flag){ + if(BKP_FLAG_TAMPER0 == flag) { BKP_TPCS |= (uint16_t)(flag >> TAMPER0_FLAG_SHIFT); - }else if(BKP_FLAG_TAMPER1_WAVEDETECT == flag){ + } else if(BKP_FLAG_TAMPER1_WAVEDETECT == flag) { BKP_TPCS |= (uint16_t)(flag >> TAMPER1_FLAG_SHIFT); - }else{ + } else { /* illegal parameters */ } } /*! - \brief get bkp interrupt flag state - \param[in] flag + \brief enable tamper interrupt + \param[in] bkp_interrupt: the BKP interrupt + only one parameter can be selected which is shown as below: + \arg BKP_INT_TAMPER0: BKP tamper0 interrupt + \arg BKP_INT_TAMPER1_WAVEDETECT: BKP tamper1/waveform detect interrupt + \param[out] none + \retval none +*/ +void bkp_tamper_interrupt_enable(uint16_t bkp_interrupt) +{ + /* enable BKP tamper0 interrupt */ + if(0U != (bkp_interrupt & BKP_TPCS_TPIE0)) { + BKP_TPCS |= (uint16_t) BKP_TPCS_TPIE0; + } + /* enable BKP tamper1/waveform detect interrupt */ + if(0U != (bkp_interrupt & BKP_TPCS_TPIE1)) { + BKP_TPCS |= (uint16_t) BKP_TPCS_TPIE1; + } +} + +/*! + \brief disable tamper interrupt + \param[in] bkp_interrupt: the BKP interrupt + only one parameter can be selected which is shown as below: + \arg BKP_INT_TAMPER0: BKP tamper0 interrupt + \arg BKP_INT_TAMPER1_WAVEDETECT: BKP tamper1/waveform detect interrupt + \param[out] none + \retval none +*/ +void bkp_tamper_interrupt_disable(uint16_t bkp_interrupt) +{ + /* disable BKP tamper0 interrupt */ + if(0U != (bkp_interrupt & BKP_TPCS_TPIE0)) { + BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE0; + } + /* disable BKP tamper1/waveform detect interrupt */ + if(0U != (bkp_interrupt & BKP_TPCS_TPIE1)) { + BKP_TPCS &= (uint16_t)~BKP_TPCS_TPIE1; + } +} + +/*! + \brief get BKP interrupt flag + \param[in] flag: + only one parameter can be selected which is shown as below: \arg BKP_INT_FLAG_TAMPER0: tamper0 interrupt flag \arg BKP_INT_FLAG_TAMPER1_WAVEDETECT: tamper1/waveform detect interrupt flag \param[out] none @@ -394,16 +410,17 @@ void bkp_flag_clear(uint16_t flag) */ FlagStatus bkp_interrupt_flag_get(uint16_t flag) { - if(RESET != (BKP_TPCS & flag)){ + if(RESET != (BKP_TPCS & flag)) { return SET; - }else{ + } else { return RESET; } } /*! - \brief clear bkp interrupt flag state - \param[in] flag + \brief clear BKP interrupt flag + \param[in] flag: + only one parameter can be selected which is shown as below: \arg BKP_INT_FLAG_TAMPER0: tamper0 interrupt flag \arg BKP_INT_FLAG_TAMPER1_WAVEDETECT: tamper1/waveform detect interrupt flag \param[out] none @@ -411,11 +428,11 @@ FlagStatus bkp_interrupt_flag_get(uint16_t flag) */ void bkp_interrupt_flag_clear(uint16_t flag) { - if(BKP_INT_FLAG_TAMPER0 == flag){ + if(BKP_INT_FLAG_TAMPER0 == flag) { BKP_TPCS |= (uint16_t)(flag >> TAMPER0_FLAG_SHIFT); - }else if(BKP_INT_FLAG_TAMPER1_WAVEDETECT == flag){ + } else if(BKP_INT_FLAG_TAMPER1_WAVEDETECT == flag) { BKP_TPCS |= (uint16_t)(flag >> TAMPER1_FLAG_SHIFT); - }else{ + } else { /* illegal parameters */ } } diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_can.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_can.c index b1a3abee..c3fa0079 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_can.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_can.c @@ -2,61 +2,56 @@ \file gd32f20x_can.c \brief CAN driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2019-11-27, V2.1.1, firmware for GD32F20x - \version 2020-07-14, V2.1.2, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "gd32f20x_can.h" #define CAN_ERROR_HANDLE(s) do{}while(1) - -#define RFO1_CLEAR_VAL ((uint32_t)0x00000000U) /*!< RFO1 clear value */ -#define RFF1_CLEAR_VAL ((uint32_t)0x00000018U) /*!< RFF1 clear value */ + +#define RFO1_CLEAR_VAL ((uint32_t)0x00000000U) /*!< RFO1 clear value */ +#define RFF1_CLEAR_VAL ((uint32_t)0x00000018U) /*!< RFF1 clear value */ /*! - \brief deinitialize CAN + \brief deinitialize CAN \param[in] can_periph - \arg CANx(x=0,1) + \arg CANx(x=0,1) \param[out] none \retval none */ void can_deinit(uint32_t can_periph) { - if(CAN0 == can_periph){ + if(CAN0 == can_periph) { rcu_periph_reset_enable(RCU_CAN0RST); rcu_periph_reset_disable(RCU_CAN0RST); - }else{ + } else { rcu_periph_reset_enable(RCU_CAN1RST); rcu_periph_reset_disable(RCU_CAN1RST); } @@ -64,7 +59,7 @@ void can_deinit(uint32_t can_periph) /*! \brief initialize CAN parameter struct with a default value - \param[in] type: the type of CAN parameter struct + \param[in] type: the type of CAN parameter struct only one parameter can be selected which is shown as below: \arg CAN_INIT_STRUCT: the CAN initial struct \arg CAN_FILTER_STRUCT: the CAN filter struct @@ -77,67 +72,71 @@ void can_deinit(uint32_t can_periph) void can_struct_para_init(can_struct_type_enum type, void* p_struct) { uint8_t i; - + + if(NULL == p_struct){ + CAN_ERROR_HANDLE("struct parameter can not be NULL \r\n"); + } + /* get type of the struct */ - switch(type){ - /* used for can_init() */ - case CAN_INIT_STRUCT: - ((can_parameter_struct*)p_struct)->auto_bus_off_recovery = DISABLE; - ((can_parameter_struct*)p_struct)->no_auto_retrans = DISABLE; - ((can_parameter_struct*)p_struct)->auto_wake_up = DISABLE; - ((can_parameter_struct*)p_struct)->prescaler = 0x03FFU; - ((can_parameter_struct*)p_struct)->rec_fifo_overwrite = DISABLE; - ((can_parameter_struct*)p_struct)->resync_jump_width = CAN_BT_SJW_1TQ; - ((can_parameter_struct*)p_struct)->time_segment_1 = CAN_BT_BS1_3TQ; - ((can_parameter_struct*)p_struct)->time_segment_2 = CAN_BT_BS2_1TQ; - ((can_parameter_struct*)p_struct)->time_triggered = DISABLE; - ((can_parameter_struct*)p_struct)->trans_fifo_order = DISABLE; - ((can_parameter_struct*)p_struct)->working_mode = CAN_NORMAL_MODE; - - break; - /* used for can_filter_init() */ - case CAN_FILTER_STRUCT: - ((can_filter_parameter_struct*)p_struct)->filter_bits = CAN_FILTERBITS_32BIT; - ((can_filter_parameter_struct*)p_struct)->filter_enable = DISABLE; - ((can_filter_parameter_struct*)p_struct)->filter_fifo_number = CAN_FIFO0; - ((can_filter_parameter_struct*)p_struct)->filter_list_high = 0x0000U; - ((can_filter_parameter_struct*)p_struct)->filter_list_low = 0x0000U; - ((can_filter_parameter_struct*)p_struct)->filter_mask_high = 0x0000U; - ((can_filter_parameter_struct*)p_struct)->filter_mask_low = 0x0000U; - ((can_filter_parameter_struct*)p_struct)->filter_mode = CAN_FILTERMODE_MASK; - ((can_filter_parameter_struct*)p_struct)->filter_number = 0U; - - break; - /* used for can_message_transmit() */ - case CAN_TX_MESSAGE_STRUCT: - for(i = 0U; i < 8U; i++){ - ((can_trasnmit_message_struct*)p_struct)->tx_data[i] = 0U; - } - - ((can_trasnmit_message_struct*)p_struct)->tx_dlen = 0u; - ((can_trasnmit_message_struct*)p_struct)->tx_efid = 0U; - ((can_trasnmit_message_struct*)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD; - ((can_trasnmit_message_struct*)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA; - ((can_trasnmit_message_struct*)p_struct)->tx_sfid = 0U; - - break; - /* used for can_message_receive() */ - case CAN_RX_MESSAGE_STRUCT: - for(i = 0U; i < 8U; i++){ - ((can_receive_message_struct*)p_struct)->rx_data[i] = 0U; - } - - ((can_receive_message_struct*)p_struct)->rx_dlen = 0U; - ((can_receive_message_struct*)p_struct)->rx_efid = 0U; - ((can_receive_message_struct*)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD; - ((can_receive_message_struct*)p_struct)->rx_fi = 0U; - ((can_receive_message_struct*)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA; - ((can_receive_message_struct*)p_struct)->rx_sfid = 0U; - - break; - - default: - CAN_ERROR_HANDLE("parameter is invalid \r\n"); + switch(type) { + /* used for can_init() */ + case CAN_INIT_STRUCT: + ((can_parameter_struct *)p_struct)->auto_bus_off_recovery = DISABLE; + ((can_parameter_struct *)p_struct)->auto_retrans = DISABLE; + ((can_parameter_struct *)p_struct)->auto_wake_up = DISABLE; + ((can_parameter_struct *)p_struct)->prescaler = 0x03FFU; + ((can_parameter_struct *)p_struct)->rec_fifo_overwrite = DISABLE; + ((can_parameter_struct *)p_struct)->resync_jump_width = CAN_BT_SJW_1TQ; + ((can_parameter_struct *)p_struct)->time_segment_1 = CAN_BT_BS1_3TQ; + ((can_parameter_struct *)p_struct)->time_segment_2 = CAN_BT_BS2_1TQ; + ((can_parameter_struct *)p_struct)->time_triggered = DISABLE; + ((can_parameter_struct *)p_struct)->trans_fifo_order = DISABLE; + ((can_parameter_struct *)p_struct)->working_mode = CAN_NORMAL_MODE; + + break; + /* used for can_filter_init() */ + case CAN_FILTER_STRUCT: + ((can_filter_parameter_struct *)p_struct)->filter_bits = CAN_FILTERBITS_32BIT; + ((can_filter_parameter_struct *)p_struct)->filter_enable = DISABLE; + ((can_filter_parameter_struct *)p_struct)->filter_fifo_number = CAN_FIFO0; + ((can_filter_parameter_struct *)p_struct)->filter_list_high = 0x0000U; + ((can_filter_parameter_struct *)p_struct)->filter_list_low = 0x0000U; + ((can_filter_parameter_struct *)p_struct)->filter_mask_high = 0x0000U; + ((can_filter_parameter_struct *)p_struct)->filter_mask_low = 0x0000U; + ((can_filter_parameter_struct *)p_struct)->filter_mode = CAN_FILTERMODE_MASK; + ((can_filter_parameter_struct *)p_struct)->filter_number = 0U; + + break; + /* used for can_message_transmit() */ + case CAN_TX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++) { + ((can_trasnmit_message_struct *)p_struct)->tx_data[i] = 0U; + } + + ((can_trasnmit_message_struct *)p_struct)->tx_dlen = 0u; + ((can_trasnmit_message_struct *)p_struct)->tx_efid = 0U; + ((can_trasnmit_message_struct *)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_trasnmit_message_struct *)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA; + ((can_trasnmit_message_struct *)p_struct)->tx_sfid = 0U; + + break; + /* used for can_message_receive() */ + case CAN_RX_MESSAGE_STRUCT: + for(i = 0U; i < 8U; i++) { + ((can_receive_message_struct *)p_struct)->rx_data[i] = 0U; + } + + ((can_receive_message_struct *)p_struct)->rx_dlen = 0U; + ((can_receive_message_struct *)p_struct)->rx_efid = 0U; + ((can_receive_message_struct *)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD; + ((can_receive_message_struct *)p_struct)->rx_fi = 0U; + ((can_receive_message_struct *)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA; + ((can_receive_message_struct *)p_struct)->rx_sfid = 0U; + + break; + + default: + CAN_ERROR_HANDLE("parameter is invalid \r\n"); } } @@ -153,7 +152,7 @@ void can_struct_para_init(can_struct_type_enum type, void* p_struct) \arg time_triggered: ENABLE or DISABLE \arg auto_bus_off_recovery: ENABLE or DISABLE \arg auto_wake_up: ENABLE or DISABLE - \arg no_auto_retrans: ENABLE or DISABLE + \arg auto_retrans: ENABLE or DISABLE \arg rec_fifo_overwrite: ENABLE or DISABLE \arg trans_fifo_order: ENABLE or DISABLE \arg prescaler: 0x0001 - 0x0400 @@ -164,158 +163,159 @@ ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init { uint32_t timeout = CAN_TIMEOUT; ErrStatus flag = ERROR; - + /* disable sleep mode */ CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; /* enable initialize mode */ CAN_CTL(can_periph) |= CAN_CTL_IWMOD; /* wait ACK */ - while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)) { timeout--; } /* check initialize working success */ - if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ + if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) { flag = ERROR; - }else{ + } else { /* set the bit timing register */ CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \ BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \ BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \ BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \ BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U))); + /* time trigger communication mode */ - if(ENABLE == can_parameter_init->time_triggered){ + if(ENABLE == can_parameter_init->time_triggered) { CAN_CTL(can_periph) |= CAN_CTL_TTC; - }else{ + } else { CAN_CTL(can_periph) &= ~CAN_CTL_TTC; } - /* automatic bus-off managment */ - if(ENABLE == can_parameter_init->auto_bus_off_recovery){ + /* automatic bus-off management */ + if(ENABLE == can_parameter_init->auto_bus_off_recovery) { CAN_CTL(can_periph) |= CAN_CTL_ABOR; - }else{ + } else { CAN_CTL(can_periph) &= ~CAN_CTL_ABOR; } /* automatic wakeup mode */ - if(ENABLE == can_parameter_init->auto_wake_up){ + if(ENABLE == can_parameter_init->auto_wake_up) { CAN_CTL(can_periph) |= CAN_CTL_AWU; - }else{ + } else { CAN_CTL(can_periph) &= ~CAN_CTL_AWU; } - /* automatic retransmission mode disable*/ - if(ENABLE == can_parameter_init->no_auto_retrans){ - CAN_CTL(can_periph) |= CAN_CTL_ARD; - }else{ + /* automatic retransmission mode disable */ + if(ENABLE == can_parameter_init->auto_retrans) { CAN_CTL(can_periph) &= ~CAN_CTL_ARD; + } else { + CAN_CTL(can_periph) |= CAN_CTL_ARD; } - /* receive fifo overwrite mode */ - if(ENABLE == can_parameter_init->rec_fifo_overwrite){ - CAN_CTL(can_periph) |= CAN_CTL_RFOD; - }else{ + /* receive fifo overwrite mode */ + if(ENABLE == can_parameter_init->rec_fifo_overwrite) { CAN_CTL(can_periph) &= ~CAN_CTL_RFOD; - } + } else { + CAN_CTL(can_periph) |= CAN_CTL_RFOD; + } /* transmit fifo order */ - if(ENABLE == can_parameter_init->trans_fifo_order){ + if(ENABLE == can_parameter_init->trans_fifo_order) { CAN_CTL(can_periph) |= CAN_CTL_TFO; - }else{ + } else { CAN_CTL(can_periph) &= ~CAN_CTL_TFO; - } + } /* disable initialize mode */ CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD; timeout = CAN_TIMEOUT; /* wait the ACK */ - while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)) { timeout--; } /* check exit initialize mode */ - if(0U != timeout){ + if(0U != timeout) { flag = SUCCESS; } - } + } return flag; } /*! - \brief initialize CAN filter + \brief initialize CAN filter \param[in] can_filter_parameter_init: struct for CAN filter initialization \arg filter_list_high: 0x0000 - 0xFFFF \arg filter_list_low: 0x0000 - 0xFFFF \arg filter_mask_high: 0x0000 - 0xFFFF \arg filter_mask_low: 0x0000 - 0xFFFF - \arg filter_fifo_number: CAN_FIFO0, CAN_FIFO1 + \arg filter_fifo_number: CAN_FIFO0, CAN_FIFO1 \arg filter_number: 0 - 27 \arg filter_mode: CAN_FILTERMODE_MASK, CAN_FILTERMODE_LIST - \arg filter_bits: CAN_FILTERBITS_32BIT, CAN_FILTERBITS_16BIT + \arg filter_bits: CAN_FILTERBITS_32BIT, CAN_FILTERBITS_16BIT \arg filter_enable: ENABLE or DISABLE \param[out] none \retval none */ -void can_filter_init(can_filter_parameter_struct* can_filter_parameter_init) +void can_filter_init(can_filter_parameter_struct *can_filter_parameter_init) { uint32_t val = 0U; - + val = ((uint32_t)1) << (can_filter_parameter_init->filter_number); /* filter lock disable */ CAN_FCTL(CAN0) |= CAN_FCTL_FLD; /* disable filter */ CAN_FW(CAN0) &= ~(uint32_t)val; - + /* filter 16 bits */ - if(CAN_FILTERBITS_16BIT == can_filter_parameter_init->filter_bits){ + if(CAN_FILTERBITS_16BIT == can_filter_parameter_init->filter_bits) { /* set filter 16 bits */ CAN_FSCFG(CAN0) &= ~(uint32_t)val; /* first 16 bits list and first 16 bits mask or first 16 bits list and second 16 bits list */ CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \ - FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS) | \ - FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS) | \ + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); /* second 16 bits list and second 16 bits mask or third 16 bits list and fourth 16 bits list */ CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \ - FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | \ - FDATA_MASK_LOW((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS); + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | \ + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS); } /* filter 32 bits */ - if(CAN_FILTERBITS_32BIT == can_filter_parameter_init->filter_bits){ + if(CAN_FILTERBITS_32BIT == can_filter_parameter_init->filter_bits) { /* set filter 32 bits */ CAN_FSCFG(CAN0) |= (uint32_t)val; /* 32 bits list or first 32 bits list */ CAN_FDATA0(CAN0, can_filter_parameter_init->filter_number) = \ - FDATA_MASK_HIGH((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS) | - FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); + FDATA_MASK_HIGH((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS) | + FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS); /* 32 bits mask or second 32 bits list */ CAN_FDATA1(CAN0, can_filter_parameter_init->filter_number) = \ - FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | - FDATA_MASK_LOW((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS); + FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | + FDATA_MASK_LOW((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS); } - + /* filter mode */ - if(CAN_FILTERMODE_MASK == can_filter_parameter_init->filter_mode){ + if(CAN_FILTERMODE_MASK == can_filter_parameter_init->filter_mode) { /* mask mode */ CAN_FMCFG(CAN0) &= ~(uint32_t)val; - }else{ + } else { /* list mode */ CAN_FMCFG(CAN0) |= (uint32_t)val; } - + /* filter FIFO */ - if(CAN_FIFO0 == (can_filter_parameter_init->filter_fifo_number)){ + if(CAN_FIFO0 == (can_filter_parameter_init->filter_fifo_number)) { /* FIFO0 */ CAN_FAFIFO(CAN0) &= ~(uint32_t)val; - }else{ + } else { /* FIFO1 */ CAN_FAFIFO(CAN0) |= (uint32_t)val; } - + /* filter working */ - if(ENABLE == can_filter_parameter_init->filter_enable){ - + if(ENABLE == can_filter_parameter_init->filter_enable) { + CAN_FW(CAN0) |= (uint32_t)val; } - + /* filter lock enable */ CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; } /*! - \brief set CAN1 fliter start bank number + \brief set CAN1 filter start bank number \param[in] start_bank: CAN1 start bank number only one parameter can be selected which is shown as below: \arg (1..27) @@ -329,14 +329,14 @@ void can1_filter_start_bank(uint8_t start_bank) /* set CAN1 filter start number */ CAN_FCTL(CAN0) &= ~(uint32_t)CAN_FCTL_HBC1F; CAN_FCTL(CAN0) |= FCTL_HBC1F(start_bank); - /* filter lock enaable */ + /* filter lock enable */ CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD; } /*! \brief enable CAN debug freeze \param[in] can_periph - \arg CANx(x=0,1) + \arg CANx(x=0,1) \param[out] none \retval none */ @@ -345,9 +345,9 @@ void can_debug_freeze_enable(uint32_t can_periph) /* set DFZ bit */ CAN_CTL(can_periph) |= CAN_CTL_DFZ; - if(CAN0 == can_periph){ + if(CAN0 == can_periph) { dbg_periph_enable(DBG_CAN0_HOLD); - }else{ + } else { dbg_periph_enable(DBG_CAN1_HOLD); } } @@ -364,9 +364,9 @@ void can_debug_freeze_disable(uint32_t can_periph) /* set DFZ bit */ CAN_CTL(can_periph) &= ~CAN_CTL_DFZ; - if(CAN0 == can_periph){ + if(CAN0 == can_periph) { dbg_periph_disable(DBG_CAN0_HOLD); - }else{ + } else { dbg_periph_disable(DBG_CAN1_HOLD); } } @@ -381,11 +381,11 @@ void can_debug_freeze_disable(uint32_t can_periph) void can_time_trigger_mode_enable(uint32_t can_periph) { uint8_t mailbox_number; - - /* enable the tcc mode */ + + /* enable the TTC mode */ CAN_CTL(can_periph) |= CAN_CTL_TTC; /* enable time stamp */ - for(mailbox_number=0U; mailbox_number<3U; mailbox_number++){ + for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++) { CAN_TMP(can_periph, mailbox_number) |= CAN_TMP_TSEN; } } @@ -399,20 +399,20 @@ void can_time_trigger_mode_enable(uint32_t can_periph) */ void can_time_trigger_mode_disable(uint32_t can_periph) { - uint8_t mailbox_number; - - /* disable the TCC mode */ + uint8_t mailbox_number; + + /* disable the TTC mode */ CAN_CTL(can_periph) &= ~CAN_CTL_TTC; /* reset TSEN bits */ - for(mailbox_number=0U; mailbox_number<3U; mailbox_number++){ + for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++) { CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_TSEN; } } /*! - \brief transmit CAN message + \brief transmit CAN message \param[in] can_periph - \arg CANx(x=0,1) + \arg CANx(x=0,1) \param[in] transmit_message: struct for CAN transmit message \arg tx_sfid: 0x00000000 - 0x000007FF \arg tx_efid: 0x00000000 - 0x1FFFFFFF @@ -423,48 +423,48 @@ void can_time_trigger_mode_disable(uint32_t can_periph) \param[out] none \retval mailbox_number */ -uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message) +uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct *transmit_message) { uint8_t mailbox_number = CAN_MAILBOX0; /* select one empty mailbox */ - if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)){ + if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)) { mailbox_number = CAN_MAILBOX0; - }else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)){ + } else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)) { mailbox_number = CAN_MAILBOX1; - }else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)){ + } else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)) { mailbox_number = CAN_MAILBOX2; - }else{ + } else { mailbox_number = CAN_NOMAILBOX; } /* return no mailbox empty */ - if(CAN_NOMAILBOX == mailbox_number){ + if(CAN_NOMAILBOX == mailbox_number) { return CAN_NOMAILBOX; } - + CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN; - if(CAN_FF_STANDARD == transmit_message->tx_ff){ + if(CAN_FF_STANDARD == transmit_message->tx_ff) { /* set transmit mailbox standard identifier */ CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_SFID(transmit_message->tx_sfid) | \ - transmit_message->tx_ft); - }else{ + transmit_message->tx_ft); + } else { /* set transmit mailbox extended identifier */ CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_EFID(transmit_message->tx_efid) | \ - transmit_message->tx_ff | \ - transmit_message->tx_ft); + transmit_message->tx_ff | \ + transmit_message->tx_ft); } /* set the data length */ - CAN_TMP(can_periph, mailbox_number) &= ((uint32_t)~CAN_TMP_DLENC); + CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_DLENC; CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen; /* set the data */ CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \ - TMDATA0_DB2(transmit_message->tx_data[2]) | \ - TMDATA0_DB1(transmit_message->tx_data[1]) | \ - TMDATA0_DB0(transmit_message->tx_data[0]); + TMDATA0_DB2(transmit_message->tx_data[2]) | \ + TMDATA0_DB1(transmit_message->tx_data[1]) | \ + TMDATA0_DB0(transmit_message->tx_data[0]); CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \ - TMDATA1_DB6(transmit_message->tx_data[6]) | \ - TMDATA1_DB5(transmit_message->tx_data[5]) | \ - TMDATA1_DB4(transmit_message->tx_data[4]); + TMDATA1_DB6(transmit_message->tx_data[6]) | \ + TMDATA1_DB5(transmit_message->tx_data[5]) | \ + TMDATA1_DB4(transmit_message->tx_data[4]); /* enable transmission */ CAN_TMI(can_periph, mailbox_number) |= CAN_TMI_TEN; @@ -472,7 +472,7 @@ uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* t } /*! - \brief get CAN transmit state + \brief get CAN transmit state \param[in] can_periph \arg CANx(x=0,1) \param[in] mailbox_number @@ -485,9 +485,9 @@ can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox { can_transmit_state_enum state = CAN_TRANSMIT_FAILED; uint32_t val = 0U; - - /* check selected mailbox state */ - switch(mailbox_number){ + + /* check selected mailbox state */ + switch(mailbox_number) { /* mailbox0 */ case CAN_MAILBOX0: val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0); @@ -504,26 +504,26 @@ can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox val = CAN_TRANSMIT_FAILED; break; } - - switch(val){ - /* transmit pending */ - case (CAN_STATE_PENDING): + + switch(val) { + /* transmit pending */ + case(CAN_STATE_PENDING): state = CAN_TRANSMIT_PENDING; break; - /* mailbox0 transmit succeeded */ - case (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0): + /* mailbox0 transmit succeeded */ + case(CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0): state = CAN_TRANSMIT_OK; break; - /* mailbox1 transmit succeeded */ - case (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1): + /* mailbox1 transmit succeeded */ + case(CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1): state = CAN_TRANSMIT_OK; break; - /* mailbox2 transmit succeeded */ - case (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2): + /* mailbox2 transmit succeeded */ + case(CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2): state = CAN_TRANSMIT_OK; break; - /* transmit failed */ - default: + /* transmit failed */ + default: state = CAN_TRANSMIT_FAILED; break; } @@ -542,19 +542,19 @@ can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox */ void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number) { - if(CAN_MAILBOX0 == mailbox_number){ + if(CAN_MAILBOX0 == mailbox_number) { CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0; - while(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){ + while(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)) { } - }else if(CAN_MAILBOX1 == mailbox_number){ + } else if(CAN_MAILBOX1 == mailbox_number) { CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1; - while(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){ + while(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)) { } - }else if(CAN_MAILBOX2 == mailbox_number){ + } else if(CAN_MAILBOX2 == mailbox_number) { CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2; - while(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)){ + while(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)) { } - }else{ + } else { /* illegal parameters */ } } @@ -562,7 +562,7 @@ void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number) /*! \brief CAN receive message \param[in] can_periph - \arg CANx(x=0,1) + \arg CANx(x=0,1) \param[in] fifo_number \arg CAN_FIFOx(x=0,1) \param[out] receive_message: struct for CAN receive message @@ -575,24 +575,24 @@ void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number) \arg rx_fi: 0 - 27 \retval none */ -void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message) +void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct *receive_message) { /* get the frame format */ receive_message->rx_ff = (uint8_t)(CAN_RFIFOMI_FF & CAN_RFIFOMI(can_periph, fifo_number)); - if(CAN_FF_STANDARD == receive_message->rx_ff){ + if(CAN_FF_STANDARD == receive_message->rx_ff) { /* get standard identifier */ - receive_message -> rx_sfid = (uint32_t)(GET_RFIFOMI_SFID(CAN_RFIFOMI(can_periph, fifo_number))); - }else{ + receive_message->rx_sfid = (uint32_t)(GET_RFIFOMI_SFID(CAN_RFIFOMI(can_periph, fifo_number))); + } else { /* get extended identifier */ - receive_message -> rx_efid = (uint32_t)(GET_RFIFOMI_EFID(CAN_RFIFOMI(can_periph, fifo_number))); + receive_message->rx_efid = (uint32_t)(GET_RFIFOMI_EFID(CAN_RFIFOMI(can_periph, fifo_number))); } /* get frame type */ - receive_message -> rx_ft = (uint8_t)(CAN_RFIFOMI_FT & CAN_RFIFOMI(can_periph, fifo_number)); - /* get recevie data length */ - receive_message -> rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); + receive_message->rx_ft = (uint8_t)(CAN_RFIFOMI_FT & CAN_RFIFOMI(can_periph, fifo_number)); /* filtering index */ - receive_message -> rx_fi = (uint8_t)(GET_RFIFOMP_FI(CAN_RFIFOMP(can_periph, fifo_number))); + receive_message->rx_fi = (uint8_t)(GET_RFIFOMP_FI(CAN_RFIFOMP(can_periph, fifo_number))); + /* get receive data length */ + receive_message->rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number))); /* receive data */ receive_message -> rx_data[0] = (uint8_t)(GET_RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number))); @@ -605,15 +605,15 @@ void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_m receive_message -> rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number))); /* release FIFO */ - if(CAN_FIFO0 == fifo_number){ + if(CAN_FIFO0 == fifo_number) { CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; - }else{ + } else { CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; } } /*! - \brief release FIFO0 + \brief release FIFO \param[in] can_periph \arg CANx(x=0,1) \param[in] fifo_number @@ -624,11 +624,11 @@ void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_m */ void can_fifo_release(uint32_t can_periph, uint8_t fifo_number) { - if(CAN_FIFO0 == fifo_number){ + if(CAN_FIFO0 == fifo_number) { CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0; - }else if(CAN_FIFO1 == fifo_number){ + } else if(CAN_FIFO1 == fifo_number) { CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1; - }else{ + } else { /* illegal parameters */ CAN_ERROR_HANDLE("CAN FIFO NUM is invalid \r\n"); } @@ -640,21 +640,21 @@ void can_fifo_release(uint32_t can_periph, uint8_t fifo_number) \arg CANx(x=0,1) \param[in] fifo_number only one parameter can be selected which is shown as below: - \arg CAN_FIFOx(x=0,1) + \arg CAN_FIFOx(x=0,1) \param[out] none \retval message length */ uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number) { uint8_t val = 0U; - - if(CAN_FIFO0 == fifo_number){ + + if(CAN_FIFO0 == fifo_number) { /* FIFO0 */ val = (uint8_t)(CAN_RFIFO0(can_periph) & CAN_RFIF_RFL_MASK); - }else if(CAN_FIFO1 == fifo_number){ + } else if(CAN_FIFO1 == fifo_number) { /* FIFO1 */ val = (uint8_t)(CAN_RFIFO1(can_periph) & CAN_RFIF_RFL_MASK); - }else{ + } else { /* illegal parameters */ } return val; @@ -663,7 +663,7 @@ uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number) /*! \brief set CAN working mode \param[in] can_periph - \arg CANx(x=0,1) + \arg CANx(x=0,1) \param[in] can_working_mode only one parameter can be selected which is shown as below: \arg CAN_MODE_INITIALIZE @@ -676,49 +676,49 @@ ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode) { ErrStatus flag = ERROR; /* timeout for IWS or also for SLPWS bits */ - uint32_t timeout = CAN_TIMEOUT; - - if(CAN_MODE_INITIALIZE == working_mode){ + uint32_t timeout = CAN_TIMEOUT; + + if(CAN_MODE_INITIALIZE == working_mode) { /* disable sleep mode */ CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_SLPWMOD); /* set initialize mode */ CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_IWMOD; /* wait the acknowledge */ - while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){ + while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)) { timeout--; } - if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){ + if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) { flag = ERROR; - }else{ + } else { flag = SUCCESS; } - }else if(CAN_MODE_NORMAL == working_mode){ + } else if(CAN_MODE_NORMAL == working_mode) { /* enter normal mode */ CAN_CTL(can_periph) &= ~(uint32_t)(CAN_CTL_SLPWMOD | CAN_CTL_IWMOD); /* wait the acknowledge */ - while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)){ + while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)) { timeout--; } - if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))){ + if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) { flag = ERROR; - }else{ + } else { flag = SUCCESS; } - }else if(CAN_MODE_SLEEP == working_mode){ + } else if(CAN_MODE_SLEEP == working_mode) { /* disable initialize mode */ CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_IWMOD); /* set sleep mode */ CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_SLPWMOD; /* wait the acknowledge */ - while((CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0U != timeout)){ + while((CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0U != timeout)) { timeout--; } - if(CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ + if(CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) { flag = ERROR; - }else{ + } else { flag = SUCCESS; } - }else{ + } else { flag = ERROR; } return flag; @@ -727,7 +727,7 @@ ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode) /*! \brief wake up CAN \param[in] can_periph - \arg CANx(x=0,1) + \arg CANx(x=0,1) \param[out] none \retval ErrStatus: SUCCESS or ERROR */ @@ -735,17 +735,17 @@ ErrStatus can_wakeup(uint32_t can_periph) { ErrStatus flag = ERROR; uint32_t timeout = CAN_TIMEOUT; - + /* wakeup */ CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD; - - while((0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0x00U != timeout)){ + + while((0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0x00U != timeout)) { timeout--; } /* check state */ - if(0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){ + if(0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) { flag = ERROR; - }else{ + } else { flag = SUCCESS; } return flag; @@ -770,7 +770,7 @@ can_error_enum can_error_get(uint32_t can_periph) { can_error_enum error; error = CAN_ERROR_NONE; - + /* get error type */ error = (can_error_enum)(GET_ERR_ERRN(CAN_ERR(can_periph))); return error; @@ -779,14 +779,14 @@ can_error_enum can_error_get(uint32_t can_periph) /*! \brief get CAN receive error number \param[in] can_periph - \arg CANx(x=0,1) + \arg CANx(x=0,1) \param[out] none \retval error number */ uint8_t can_receive_error_number_get(uint32_t can_periph) { uint8_t val; - + /* get error count */ val = (uint8_t)(GET_ERR_RECNT(CAN_ERR(can_periph))); return val; @@ -795,74 +795,18 @@ uint8_t can_receive_error_number_get(uint32_t can_periph) /*! \brief get CAN transmit error number \param[in] can_periph - \arg CANx(x=0,1) + \arg CANx(x=0,1) \param[out] none \retval error number */ uint8_t can_transmit_error_number_get(uint32_t can_periph) { uint8_t val; - + val = (uint8_t)(GET_ERR_TECNT(CAN_ERR(can_periph))); return val; } -/*! - \brief enable CAN interrupt - \param[in] can_periph - \arg CANx(x=0,1) - \param[in] interrupt - one or more parameters can be selected which are shown as below: - \arg CAN_INT_TME: transmit mailbox empty interrupt enable - \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable - \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable - \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable - \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable - \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable - \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable - \arg CAN_INT_WERR: warning error interrupt enable - \arg CAN_INT_PERR: passive error interrupt enable - \arg CAN_INT_BO: bus-off interrupt enable - \arg CAN_INT_ERRN: error number interrupt enable - \arg CAN_INT_ERR: error interrupt enable - \arg CAN_INT_WAKEUP: wakeup interrupt enable - \arg CAN_INT_SLPW: sleep working interrupt enable - \param[out] none - \retval none -*/ -void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt) -{ - CAN_INTEN(can_periph) |= interrupt; -} - -/*! - \brief disable CAN interrupt - \param[in] can_periph - \arg CANx(x=0,1) - \param[in] interrupt - one or more parameters can be selected which are shown as below: - \arg CAN_INT_TME: transmit mailbox empty interrupt enable - \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable - \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable - \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable - \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable - \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable - \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable - \arg CAN_INT_WERR: warning error interrupt enable - \arg CAN_INT_PERR: passive error interrupt enable - \arg CAN_INT_BO: bus-off interrupt enable - \arg CAN_INT_ERRN: error number interrupt enable - \arg CAN_INT_ERR: error interrupt enable - \arg CAN_INT_WAKEUP: wakeup interrupt enable - \arg CAN_INT_SLPW: sleep working interrupt enable - \param[out] none - \retval none -*/ -void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt) -{ - CAN_INTEN(can_periph) &= ~interrupt; -} - /*! \brief get CAN flag state \param[in] can_periph @@ -878,9 +822,9 @@ void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt) \arg CAN_FLAG_ERRIF: error flag \arg CAN_FLAG_SLPWS: sleep working state \arg CAN_FLAG_IWS: initial working state - \arg CAN_FLAG_TMLS2: transmit mailbox 2 last sending in Tx FIFO - \arg CAN_FLAG_TMLS1: transmit mailbox 1 last sending in Tx FIFO - \arg CAN_FLAG_TMLS0: transmit mailbox 0 last sending in Tx FIFO + \arg CAN_FLAG_TMLS2: transmit mailbox 2 last sending in TX FIFO + \arg CAN_FLAG_TMLS1: transmit mailbox 1 last sending in TX FIFO + \arg CAN_FLAG_TMLS0: transmit mailbox 0 last sending in TX FIFO \arg CAN_FLAG_TME2: transmit mailbox 2 empty \arg CAN_FLAG_TME1: transmit mailbox 1 empty \arg CAN_FLAG_TME0: transmit mailbox 0 empty @@ -907,11 +851,11 @@ void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt) \retval FlagStatus: SET or RESET */ FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag) -{ +{ /* get flag and interrupt enable state */ - if(RESET != (CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag)))){ + if(RESET != (CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag)))) { return SET; - }else{ + } else { return RESET; } } @@ -946,15 +890,71 @@ FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag) */ void can_flag_clear(uint32_t can_periph, can_flag_enum flag) { - if (flag == CAN_FLAG_RFO1){ + if(flag == CAN_FLAG_RFO1) { CAN_REG_VAL(can_periph, flag) = RFO1_CLEAR_VAL; - } else if (flag == CAN_FLAG_RFF1){ + } else if(flag == CAN_FLAG_RFF1) { CAN_REG_VAL(can_periph, flag) = RFF1_CLEAR_VAL; } else { CAN_REG_VAL(can_periph, flag) = BIT(CAN_BIT_POS(flag)); } } +/*! + \brief enable CAN interrupt + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] interrupt + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WAKEUP: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable + \param[out] none + \retval none +*/ +void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt) +{ + CAN_INTEN(can_periph) |= interrupt; +} + +/*! + \brief disable CAN interrupt + \param[in] can_periph + \arg CANx(x=0,1) + \param[in] interrupt + one or more parameters can be selected which are shown as below: + \arg CAN_INT_TME: transmit mailbox empty interrupt enable + \arg CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable + \arg CAN_INT_RFF0: receive FIFO0 full interrupt enable + \arg CAN_INT_RFO0: receive FIFO0 overfull interrupt enable + \arg CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable + \arg CAN_INT_RFF1: receive FIFO1 full interrupt enable + \arg CAN_INT_RFO1: receive FIFO1 overfull interrupt enable + \arg CAN_INT_WERR: warning error interrupt enable + \arg CAN_INT_PERR: passive error interrupt enable + \arg CAN_INT_BO: bus-off interrupt enable + \arg CAN_INT_ERRN: error number interrupt enable + \arg CAN_INT_ERR: error interrupt enable + \arg CAN_INT_WAKEUP: wakeup interrupt enable + \arg CAN_INT_SLPW: sleep working interrupt enable + \param[out] none + \retval none +*/ +void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt) +{ + CAN_INTEN(can_periph) &= ~interrupt; +} + /*! \brief get CAN interrupt flag state \param[in] can_periph @@ -984,22 +984,22 @@ FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum f { uint32_t ret1 = RESET; uint32_t ret2 = RESET; - - /* get the staus of interrupt flag */ - if (flag == CAN_INT_FLAG_RFL0) { + + /* get the status of interrupt flag */ + if(flag == CAN_INT_FLAG_RFL0) { ret1 = can_receive_message_length_get(can_periph, CAN_FIFO0); - } else if (flag == CAN_INT_FLAG_RFL1) { + } else if(flag == CAN_INT_FLAG_RFL1) { ret1 = can_receive_message_length_get(can_periph, CAN_FIFO1); - } else if (flag == CAN_INT_FLAG_ERRN) { + } else if(flag == CAN_INT_FLAG_ERRN) { ret1 = can_error_get(can_periph); } else { ret1 = CAN_REG_VALS(can_periph, flag) & BIT(CAN_BIT_POS0(flag)); } - /* get the staus of interrupt enale bit */ + /* get the status of interrupt enable bit */ ret2 = CAN_INTEN(can_periph) & BIT(CAN_BIT_POS1(flag)); - if(ret1 && ret2){ + if(ret1 && ret2) { return SET; - }else{ + } else { return RESET; } } @@ -1025,9 +1025,9 @@ FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum f */ void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum flag) { - if (flag == CAN_INT_FLAG_RFO1){ + if(flag == CAN_INT_FLAG_RFO1) { CAN_REG_VALS(can_periph, flag) = RFO1_CLEAR_VAL; - } else if (flag == CAN_INT_FLAG_RFF1){ + } else if(flag == CAN_INT_FLAG_RFF1) { CAN_REG_VALS(can_periph, flag) = RFF1_CLEAR_VAL; } else { CAN_REG_VALS(can_periph, flag) = BIT(CAN_BIT_POS0(flag)); diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau.c index d0fd887a..2b4ee8f5 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau.c @@ -2,36 +2,33 @@ \file gd32f20x_cau.c \brief CAU driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -42,7 +39,7 @@ OF SUCH DAMAGE. /*! \brief reset the CAU peripheral - \param[in] none + \param[in] none \param[out] none \retval none */ @@ -63,8 +60,8 @@ void cau_deinit(void) void cau_enable(void) { /* enable the CAU processor */ - CAU_CTL |= CAU_CTL_CAUEN; -} + CAU_CTL |= CAU_CTL_CAUEN; +} /*! \brief disable the CAU peripheral @@ -82,7 +79,7 @@ void cau_disable(void) \brief enable the CAU DMA interface \param[in] dma_req: specify the CAU DMA transfer request to be enabled one or more parameters can be selected which are shown as below - \arg CAU_DMA_INFIFO: DMA for incoming(Rx) data transfer + \arg CAU_DMA_INFIFO: DMA for incoming(Rx) data transfer \arg CAU_DMA_OUTFIFO: DMA for outgoing(Tx) data transfer \param[out] none \retval none @@ -97,7 +94,7 @@ void cau_dma_enable(uint32_t dma_req) \brief disable the CAU DMA interface \param[in] dma_req: specify the CAU DMA transfer request to be disabled one or more parameters can be selected which are shown as below - \arg CAU_DMA_INFIFO: DMA for incoming(Rx) data transfer + \arg CAU_DMA_INFIFO: DMA for incoming(Rx) data transfer \arg CAU_DMA_OUTFIFO: DMA for outgoing(Tx) data transfer \param[out] none \retval none @@ -123,27 +120,27 @@ void cau_dma_disable(uint32_t dma_req) \arg CAU_MODE_AES_ECB: AES-ECB (AES Electronic codebook) \arg CAU_MODE_AES_CBC: AES-CBC (AES Cipher block chaining) \arg CAU_MODE_AES_CTR: AES-CTR (AES counter mode) - \arg CAU_MODE_AES_KEY: AES decryption key preparation mode + \arg CAU_MODE_AES_KEY: AES decryption key preparation mode \param[in] swapping: data swapping selection only one parameter can be selected which is shown as below \arg CAU_SWAPPING_32BIT: no swapping \arg CAU_SWAPPING_16BIT: half-word swapping \arg CAU_SWAPPING_8BIT: bytes swapping - \arg CAU_SWAPPING_1BIT: bit swapping + \arg CAU_SWAPPING_1BIT: bit swapping \param[out] none \retval none */ void cau_init(uint32_t algo_dir, uint32_t algo_mode, uint32_t swapping) -{ - /* select algorithm mode */ +{ + /* select algorithm mode */ CAU_CTL &= ~CAU_CTL_ALGM; CAU_CTL |= algo_mode; - - /* select data swapping */ + + /* select data swapping */ CAU_CTL &= ~CAU_CTL_DATAM; CAU_CTL |= swapping; - /* select algorithm direction */ + /* select algorithm direction */ CAU_CTL &= ~CAU_CTL_CAUDIR; CAU_CTL |= algo_dir; } @@ -153,16 +150,16 @@ void cau_init(uint32_t algo_dir, uint32_t algo_mode, uint32_t swapping) \param[in] key_size: key length selection when aes mode only one parameter can be selected which is shown as below \arg CAU_KEYSIZE_128BIT: 128 bit key length - \arg CAU_KEYSIZE_192BIT: 192 bit key length - \arg CAU_KEYSIZE_256BIT: 256 bit key length + \arg CAU_KEYSIZE_192BIT: 192 bit key length + \arg CAU_KEYSIZE_256BIT: 256 bit key length \param[out] none \retval none */ void cau_aes_keysize_config(uint32_t key_size) { CAU_CTL &= ~CAU_CTL_KEYM; - CAU_CTL |= key_size; -} + CAU_CTL |= key_size; +} /*! \brief initialize the key parameters @@ -178,7 +175,7 @@ void cau_aes_keysize_config(uint32_t key_size) \param[out] none \retval none */ -void cau_key_init(cau_key_parameter_struct* key_initpara) +void cau_key_init(cau_key_parameter_struct *key_initpara) { CAU_KEY0H = key_initpara->key_0_high; CAU_KEY0L = key_initpara->key_0_low; @@ -204,7 +201,7 @@ void cau_key_init(cau_key_parameter_struct* key_initpara) \param[out] none \retval none */ -void cau_key_parameter_init(cau_key_parameter_struct* key_initpara) +void cau_key_parameter_init(cau_key_parameter_struct *key_initpara) { key_initpara->key_0_high = 0U; key_initpara->key_0_low = 0U; @@ -226,7 +223,7 @@ void cau_key_parameter_init(cau_key_parameter_struct* key_initpara) \param[out] none \retval none */ -void cau_iv_init(cau_iv_parameter_struct* iv_initpara) +void cau_iv_init(cau_iv_parameter_struct *iv_initpara) { CAU_IV0H = iv_initpara->iv_0_high; CAU_IV0L = iv_initpara->iv_0_low; @@ -244,7 +241,7 @@ void cau_iv_init(cau_iv_parameter_struct* iv_initpara) \param[out] none \retval none */ -void cau_iv_parameter_init(cau_iv_parameter_struct* iv_initpara) +void cau_iv_parameter_init(cau_iv_parameter_struct *iv_initpara) { iv_initpara->iv_0_high = 0U; iv_initpara->iv_0_low = 0U; @@ -273,7 +270,7 @@ void cau_fifo_flush(void) ControlStatus cau_enable_state_get(void) { ControlStatus ret = DISABLE; - if(RESET != (CAU_CTL & CAU_CTL_CAUEN)){ + if(RESET != (CAU_CTL & CAU_CTL_CAUEN)) { ret = ENABLE; } return ret; @@ -305,13 +302,13 @@ uint32_t cau_data_read(void) \brief get the CAU flag status \param[in] flag: CAU flag status only one parameter can be selected which is shown as below - \arg CAU_FLAG_INFIFO_EMPTY: input FIFO empty + \arg CAU_FLAG_INFIFO_EMPTY: input FIFO empty \arg CAU_FLAG_INFIFO_NO_FULL: input FIFO is not full - \arg CAU_FLAG_OUTFIFO_NO_EMPTY: output FIFO not empty + \arg CAU_FLAG_OUTFIFO_NO_EMPTY: output FIFO not empty \arg CAU_FLAG_OUTFIFO_FULL: output FIFO is full - \arg CAU_FLAG_BUSY: the CAU core is busy + \arg CAU_FLAG_BUSY: the CAU core is busy \arg CAU_FLAG_INFIFO: input FIFO flag status - \arg CAU_FLAG_OUTFIFO: output FIFO flag status + \arg CAU_FLAG_OUTFIFO: output FIFO flag status \param[out] none \retval FlagStatus: SET or RESET */ @@ -321,18 +318,18 @@ FlagStatus cau_flag_get(uint32_t flag) FlagStatus ret_flag = RESET; /* check if the flag is in CAU_STAT1 register */ - if(RESET != (flag & FLAG_MASK)){ + if(RESET != (flag & FLAG_MASK)) { reg = CAU_STAT1; - }else{ + } else { /* the flag is in CAU_STAT0 register */ reg = CAU_STAT0; } /* check the status of the specified CAU flag */ - if(RESET != (reg & flag)){ + if(RESET != (reg & flag)) { ret_flag = SET; } - + return ret_flag; } @@ -340,7 +337,7 @@ FlagStatus cau_flag_get(uint32_t flag) \brief enable the CAU interrupts \param[in] interrupt: specify the CAU interrupt source to be enabled one or more parameters can be selected which are shown as below - \arg CAU_INT_INFIFO: input FIFO interrupt + \arg CAU_INT_INFIFO: input FIFO interrupt \arg CAU_INT_OUTFIFO: output FIFO interrupt \param[out] none \retval none @@ -355,7 +352,7 @@ void cau_interrupt_enable(uint32_t interrupt) \brief disable the CAU interrupts \param[in] interrupt: specify the CAU interrupt source to be disabled one or more parameters can be selected which are shown as below - \arg CAU_INT_INFIFO: input FIFO interrupt + \arg CAU_INT_INFIFO: input FIFO interrupt \arg CAU_INT_OUTFIFO: output FIFO interrupt \param[out] none \retval none @@ -370,7 +367,7 @@ void cau_interrupt_disable(uint32_t interrupt) \brief get the interrupt flag \param[in] int_flag: CAU interrupt flag only one parameter can be selected which is shown as below - \arg CAU_INT_FLAG_INFIFO: input FIFO interrupt + \arg CAU_INT_FLAG_INFIFO: input FIFO interrupt \arg CAU_INT_FLAG_OUTFIFO: output FIFO interrupt \param[out] none \retval FlagStatus: SET or RESET @@ -378,11 +375,11 @@ void cau_interrupt_disable(uint32_t interrupt) FlagStatus cau_interrupt_flag_get(uint32_t int_flag) { FlagStatus flag = RESET; - + /* check the status of the specified CAU interrupt */ - if(RESET != (CAU_INTF & int_flag)){ + if(RESET != (CAU_INTF & int_flag)) { flag = SET; } - + return flag; } diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau_aes.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau_aes.c index e9980134..f70d7adf 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau_aes.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau_aes.c @@ -2,36 +2,33 @@ \file gd32f20x_cau_aes.c \brief CAU_AES driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -40,7 +37,7 @@ OF SUCH DAMAGE. #define AESBSY_TIMEOUT ((uint32_t)0x00010000U) /* AES key structure parameter config */ -static void cau_aes_key_config(uint8_t *key, uint16_t keysize, cau_key_parameter_struct* cau_key_initpara); +static void cau_aes_key_config(uint8_t *key, uint16_t keysize, cau_key_parameter_struct *cau_key_initpara); /* AES calculate process */ static ErrStatus cau_aes_calculate(uint8_t *input, uint32_t in_length, uint8_t *output); @@ -52,7 +49,7 @@ static ErrStatus cau_aes_calculate(uint8_t *input, uint32_t in_length, uint8_t * \arg CAU_DECRYPT: decrypt \param[in] key: key used for AES algorithm \param[in] keysize: length of the key, must be a 128, 192 or 256 - \param[in] text: pointer to the text information struct + \param[in] text: pointer to the text information struct input: pointer to the input buffer in_length: length of the input buffer, must be a multiple of 16 output: pointer to the returned buffer @@ -71,32 +68,32 @@ ErrStatus cau_aes_ecb(uint32_t algo_dir, uint8_t *key, uint16_t keysize, cau_tex /* AES key structure parameter config */ cau_aes_key_config(key, keysize, &key_initpara); /* key initialization */ - cau_key_init(&key_initpara); + cau_key_init(&key_initpara); /* AES decryption */ - if(CAU_DECRYPT == algo_dir){ + if(CAU_DECRYPT == algo_dir) { /* flush the IN and OUT FIFOs */ cau_fifo_flush(); /* initialize the CAU peripheral */ - cau_init(CAU_DECRYPT, CAU_MODE_AES_KEY, CAU_SWAPPING_32BIT); + cau_init(CAU_DECRYPT, CAU_MODE_AES_KEY, CAU_SWAPPING_32BIT); /* enable the CAU peripheral */ cau_enable(); /* wait until the busy flag is RESET */ - do{ + do { busystatus = cau_flag_get(CAU_FLAG_BUSY); counter++; - }while((AESBSY_TIMEOUT != counter) && (RESET != busystatus)); + } while((AESBSY_TIMEOUT != counter) && (RESET != busystatus)); - if(RESET != busystatus){ + if(RESET != busystatus) { return ERROR; } } - + /* initialize the CAU peripheral */ cau_init(algo_dir, CAU_MODE_AES_ECB, CAU_SWAPPING_8BIT); - + /* flush the IN and OUT FIFOs */ cau_fifo_flush(); @@ -118,14 +115,14 @@ ErrStatus cau_aes_ecb(uint32_t algo_dir, uint8_t *key, uint16_t keysize, cau_tex \arg CAU_DECRYPT: decrypt \param[in] key: key used for AES algorithm \param[in] keysize: length of the key, must be a 128, 192 or 256 - \param[in] iv: initialization vectors used for TDES algorithm - \param[in] text: pointer to the text information struct + \param[in] iv: initialization vectors used for TDES algorithm + \param[in] text: pointer to the text information struct input: pointer to the input buffer in_length: length of the input buffer, must be a multiple of 16 output: pointer to the returned buffer \param[out] none \retval ErrStatus: SUCCESS or ERROR -*/ +*/ ErrStatus cau_aes_cbc(uint32_t algo_dir, uint8_t *key, uint16_t keysize, uint8_t iv[16], cau_text_struct *text) { ErrStatus ret = ERROR; @@ -133,7 +130,7 @@ ErrStatus cau_aes_cbc(uint32_t algo_dir, uint8_t *key, uint16_t keysize, uint8_t cau_iv_parameter_struct iv_initpara; __IO uint32_t counter = 0U; uint32_t busystatus = 0U; - + uint32_t ivaddr = (uint32_t)iv; /* key structure initialization */ @@ -141,41 +138,41 @@ ErrStatus cau_aes_cbc(uint32_t algo_dir, uint8_t *key, uint16_t keysize, uint8_t /* AES key structure parameter config */ cau_aes_key_config(key, keysize, &key_initpara); /* key initialization */ - cau_key_init(&key_initpara); + cau_key_init(&key_initpara); /* AES decryption */ - if(CAU_DECRYPT == algo_dir){ + if(CAU_DECRYPT == algo_dir) { /* flush the IN and OUT FIFOs */ cau_fifo_flush(); /* initialize the CAU peripheral */ - cau_init(CAU_DECRYPT, CAU_MODE_AES_KEY, CAU_SWAPPING_32BIT); + cau_init(CAU_DECRYPT, CAU_MODE_AES_KEY, CAU_SWAPPING_32BIT); /* enable the CAU peripheral */ cau_enable(); /* wait until the busy flag is RESET */ - do{ + do { busystatus = cau_flag_get(CAU_FLAG_BUSY); counter++; - }while((AESBSY_TIMEOUT != counter) && (RESET != busystatus)); + } while((AESBSY_TIMEOUT != counter) && (RESET != busystatus)); - if(RESET != busystatus){ + if(RESET != busystatus) { return ERROR; } } - + /* initialize the CAU peripheral */ cau_init(algo_dir, CAU_MODE_AES_CBC, CAU_SWAPPING_8BIT); - + /* vectors initialization */ - iv_initpara.iv_0_high = __REV(*(uint32_t*)(ivaddr)); + iv_initpara.iv_0_high = __REV(*(uint32_t *)(ivaddr)); ivaddr += 4U; - iv_initpara.iv_0_low = __REV(*(uint32_t*)(ivaddr)); + iv_initpara.iv_0_low = __REV(*(uint32_t *)(ivaddr)); ivaddr += 4U; - iv_initpara.iv_1_high = __REV(*(uint32_t*)(ivaddr)); + iv_initpara.iv_1_high = __REV(*(uint32_t *)(ivaddr)); ivaddr += 4U; - iv_initpara.iv_1_low = __REV(*(uint32_t*)(ivaddr)); - cau_iv_init(&iv_initpara); + iv_initpara.iv_1_low = __REV(*(uint32_t *)(ivaddr)); + cau_iv_init(&iv_initpara); /* flush the IN and OUT FIFOs */ cau_fifo_flush(); @@ -198,40 +195,40 @@ ErrStatus cau_aes_cbc(uint32_t algo_dir, uint8_t *key, uint16_t keysize, uint8_t \arg CAU_DECRYPT: decrypt \param[in] key: key used for AES algorithm \param[in] keysize: length of the key, must be a 128, 192 or 256 - \param[in] iv: initialization vectors used for TDES algorithm - \param[in] text: pointer to the text information struct + \param[in] iv: initialization vectors used for TDES algorithm + \param[in] text: pointer to the text information struct input: pointer to the input buffer in_length: length of the input buffer, must be a multiple of 16 output: pointer to the returned buffer \param[out] none \retval ErrStatus: SUCCESS or ERROR -*/ +*/ ErrStatus cau_aes_ctr(uint32_t algo_dir, uint8_t *key, uint16_t keysize, uint8_t iv[16], cau_text_struct *text) { ErrStatus ret = ERROR; cau_key_parameter_struct key_initpara; cau_iv_parameter_struct iv_initpara; - + uint32_t ivaddr = (uint32_t)iv; /* key structure initialization */ cau_key_parameter_init(&key_initpara); /* initialize the CAU peripheral */ - cau_init(algo_dir, CAU_MODE_AES_CTR, CAU_SWAPPING_8BIT); - + cau_init(algo_dir, CAU_MODE_AES_CTR, CAU_SWAPPING_8BIT); + /* AES key structure parameter config */ cau_aes_key_config(key, keysize, &key_initpara); /* key initialization */ cau_key_init(&key_initpara); - + /* vectors initialization */ - iv_initpara.iv_0_high = __REV(*(uint32_t*)(ivaddr)); + iv_initpara.iv_0_high = __REV(*(uint32_t *)(ivaddr)); ivaddr += 4U; - iv_initpara.iv_0_low = __REV(*(uint32_t*)(ivaddr)); + iv_initpara.iv_0_low = __REV(*(uint32_t *)(ivaddr)); ivaddr += 4U; - iv_initpara.iv_1_high = __REV(*(uint32_t*)(ivaddr)); + iv_initpara.iv_1_high = __REV(*(uint32_t *)(ivaddr)); ivaddr += 4U; - iv_initpara.iv_1_low = __REV(*(uint32_t*)(ivaddr)); + iv_initpara.iv_1_low = __REV(*(uint32_t *)(ivaddr)); cau_iv_init(&iv_initpara); /* flush the IN and OUT FIFOs */ @@ -250,7 +247,7 @@ ErrStatus cau_aes_ctr(uint32_t algo_dir, uint8_t *key, uint16_t keysize, uint8_t /*! \brief AES key structure parameter config \param[in] key: key used for AES algorithm - \param[in] keysize: length of the key, must be a 128, 192 or 256 + \param[in] keysize: length of the key, must be a 128, 192 or 256 \param[out] cau_key_initpara: key init parameter struct key_0_high: key 0 high key_0_low: key 0 low @@ -262,52 +259,52 @@ ErrStatus cau_aes_ctr(uint32_t algo_dir, uint8_t *key, uint16_t keysize, uint8_t key_3_low: key 3 low \retval none */ -static void cau_aes_key_config(uint8_t *key, uint16_t keysize, cau_key_parameter_struct* cau_key_initpara) +static void cau_aes_key_config(uint8_t *key, uint16_t keysize, cau_key_parameter_struct *cau_key_initpara) { uint32_t keyaddr = (uint32_t)key; - - switch(keysize){ - case 128: + + switch(keysize) { + case 128: cau_aes_keysize_config(CAU_KEYSIZE_128BIT); - cau_key_initpara->key_2_high = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_2_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - cau_key_initpara->key_2_low = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_2_low = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - cau_key_initpara->key_3_high = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_3_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - cau_key_initpara->key_3_low = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_3_low = __REV(*(uint32_t *)(keyaddr)); break; case 192: cau_aes_keysize_config(CAU_KEYSIZE_192BIT); - cau_key_initpara->key_1_high = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_1_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - cau_key_initpara->key_1_low = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_1_low = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - cau_key_initpara->key_2_high = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_2_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - cau_key_initpara->key_2_low = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_2_low = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - cau_key_initpara->key_3_high = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_3_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - cau_key_initpara->key_3_low = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_3_low = __REV(*(uint32_t *)(keyaddr)); break; case 256: cau_aes_keysize_config(CAU_KEYSIZE_256BIT); - cau_key_initpara->key_0_high = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_0_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - cau_key_initpara->key_0_low = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_0_low = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - cau_key_initpara->key_1_high = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_1_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - cau_key_initpara->key_1_low = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_1_low = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - cau_key_initpara->key_2_high = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_2_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - cau_key_initpara->key_2_low = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_2_low = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - cau_key_initpara->key_3_high = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_3_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - cau_key_initpara->key_3_low = __REV(*(uint32_t*)(keyaddr)); + cau_key_initpara->key_3_low = __REV(*(uint32_t *)(keyaddr)); break; default: break; @@ -316,9 +313,9 @@ static void cau_aes_key_config(uint8_t *key, uint16_t keysize, cau_key_parameter /*! \brief AES calculate process - \param[in] input: pointer to the input buffer - \param[in] in_length: length of the input buffer, must be a multiple of 16 - \param[in] output: pointer to the returned buffer + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer, must be a multiple of 16 + \param[in] output: pointer to the returned buffer \param[out] none \retval ErrStatus: SUCCESS or ERROR */ @@ -328,45 +325,45 @@ static ErrStatus cau_aes_calculate(uint8_t *input, uint32_t in_length, uint8_t * uint32_t outputaddr = (uint32_t)output; uint32_t i = 0U; __IO uint32_t counter = 0U; - uint32_t busystatus = 0U; - - /* the clock is not enabled or there is no embeded CAU peripheral */ - if(DISABLE == cau_enable_state_get()){ + uint32_t busystatus = 0U; + + /* the clock is not enabled or there is no embeded CAU peripheral */ + if(DISABLE == cau_enable_state_get()) { return ERROR; } - for(i = 0U; i < in_length; i += 16U){ + for(i = 0U; i < in_length; i += 16U) { /* write data to the IN FIFO */ - cau_data_write(*(uint32_t*)(inputaddr)); + cau_data_write(*(uint32_t *)(inputaddr)); + inputaddr += 4U; + cau_data_write(*(uint32_t *)(inputaddr)); inputaddr += 4U; - cau_data_write(*(uint32_t*)(inputaddr)); + cau_data_write(*(uint32_t *)(inputaddr)); inputaddr += 4U; - cau_data_write(*(uint32_t*)(inputaddr)); + cau_data_write(*(uint32_t *)(inputaddr)); inputaddr += 4U; - cau_data_write(*(uint32_t*)(inputaddr)); - inputaddr += 4U; /* wait until the complete message has been processed */ counter = 0U; - do{ + do { busystatus = cau_flag_get(CAU_FLAG_BUSY); counter++; - }while((AESBSY_TIMEOUT != counter) && (RESET != busystatus)); + } while((AESBSY_TIMEOUT != counter) && (RESET != busystatus)); - if(RESET != busystatus){ + if(RESET != busystatus) { return ERROR; - }else{ + } else { /* read the output block from the output FIFO */ - *(uint32_t*)(outputaddr) = cau_data_read(); + *(uint32_t *)(outputaddr) = cau_data_read(); outputaddr += 4U; - *(uint32_t*)(outputaddr) = cau_data_read(); + *(uint32_t *)(outputaddr) = cau_data_read(); outputaddr += 4U; - *(uint32_t*)(outputaddr) = cau_data_read(); + *(uint32_t *)(outputaddr) = cau_data_read(); + outputaddr += 4U; + *(uint32_t *)(outputaddr) = cau_data_read(); outputaddr += 4U; - *(uint32_t*)(outputaddr) = cau_data_read(); - outputaddr += 4U; } } - + return SUCCESS; } diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau_des.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau_des.c index 3bcc3981..82c646cd 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau_des.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau_des.c @@ -2,36 +2,33 @@ \file gd32f20x_cau_des.c \brief CAU_DES driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -48,14 +45,14 @@ static ErrStatus cau_des_calculate(uint8_t *input, uint32_t in_length, uint8_t * only one parameter can be selected which is shown as below \arg CAU_ENCRYPT: encrypt \arg CAU_DECRYPT: decrypt - \param[in] key: key used for DES algorithm - \param[in] text: pointer to the text information struct + \param[in] key: key used for DES algorithm + \param[in] text: pointer to the text information struct input: pointer to the input buffer in_length: length of the input buffer, must be a multiple of 8 output: pointer to the returned buffer \param[out] none \retval ErrStatus: SUCCESS or ERROR -*/ +*/ ErrStatus cau_des_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text) { ErrStatus ret = ERROR; @@ -66,12 +63,12 @@ ErrStatus cau_des_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text) /* key structure initialization */ cau_key_parameter_init(&key_initpara); /* initialize the CAU peripheral */ - cau_init(algo_dir, CAU_MODE_DES_ECB, CAU_SWAPPING_8BIT); - - /* key initialisation */ - key_initpara.key_1_high = __REV(*(uint32_t*)(keyaddr)); + cau_init(algo_dir, CAU_MODE_DES_ECB, CAU_SWAPPING_8BIT); + + /* key initialization */ + key_initpara.key_1_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - key_initpara.key_1_low= __REV(*(uint32_t*)(keyaddr)); + key_initpara.key_1_low = __REV(*(uint32_t *)(keyaddr)); cau_key_init(& key_initpara); /* flush the IN and OUT FIFOs */ @@ -84,7 +81,7 @@ ErrStatus cau_des_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text) /* disable the CAU peripheral */ cau_disable(); - return ret; + return ret; } /*! @@ -94,11 +91,11 @@ ErrStatus cau_des_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text) \arg CAU_ENCRYPT: encrypt \arg CAU_DECRYPT: decrypt \param[in] key: key used for DES algorithm - \param[in] iv: initialization vectors used for TDES algorithm - \param[in] text: pointer to the text information struct + \param[in] iv: initialization vectors used for TDES algorithm + \param[in] text: pointer to the text information struct input: pointer to the input buffer in_length: length of the input buffer, must be a multiple of 8 - output: pointer to the returned buffer + output: pointer to the returned buffer \param[out] none \retval ErrStatus: SUCCESS or ERROR */ @@ -115,17 +112,17 @@ ErrStatus cau_des_cbc(uint32_t algo_dir, uint8_t key[24], uint8_t iv[8], cau_tex cau_key_parameter_init(&key_initpara); /* initialize the CAU peripheral */ cau_init(algo_dir, CAU_MODE_DES_CBC, CAU_SWAPPING_8BIT); - - /* key initialisation */ - key_initpara.key_1_high = __REV(*(uint32_t*)(keyaddr)); + + /* key initialization */ + key_initpara.key_1_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - key_initpara.key_1_low= __REV(*(uint32_t*)(keyaddr)); + key_initpara.key_1_low = __REV(*(uint32_t *)(keyaddr)); cau_key_init(&key_initpara); /* vectors initialization */ - iv_initpara.iv_0_high = __REV(*(uint32_t*)(ivaddr)); + iv_initpara.iv_0_high = __REV(*(uint32_t *)(ivaddr)); ivaddr += 4U; - iv_initpara.iv_0_low= __REV(*(uint32_t*)(ivaddr)); + iv_initpara.iv_0_low = __REV(*(uint32_t *)(ivaddr)); cau_iv_init(&iv_initpara); /* flush the IN and OUT FIFOs */ @@ -138,14 +135,14 @@ ErrStatus cau_des_cbc(uint32_t algo_dir, uint8_t key[24], uint8_t iv[8], cau_tex /* disable the CAU peripheral */ cau_disable(); - return ret; + return ret; } /*! \brief DES calculate process - \param[in] input: pointer to the input buffer - \param[in] in_length: length of the input buffer, must be a multiple of 8 - \param[in] output: pointer to the returned buffer + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer, must be a multiple of 8 + \param[in] output: pointer to the returned buffer \param[out] none \retval ErrStatus: SUCCESS or ERROR */ @@ -155,37 +152,37 @@ static ErrStatus cau_des_calculate(uint8_t *input, uint32_t in_length, uint8_t * uint32_t outputaddr = (uint32_t)output; uint32_t i = 0U; __IO uint32_t counter = 0U; - uint32_t busystatus = 0U; - - /* the clock is not enabled or there is no embeded CAU peripheral */ - if(DISABLE == cau_enable_state_get()){ + uint32_t busystatus = 0U; + + /* the clock is not enabled or there is no embeded CAU peripheral */ + if(DISABLE == cau_enable_state_get()) { return ERROR; } - for(i = 0U; i < in_length; i += 8U){ + for(i = 0U; i < in_length; i += 8U) { /* write data to the IN FIFO */ - cau_data_write(*(uint32_t*)(inputaddr)); + cau_data_write(*(uint32_t *)(inputaddr)); inputaddr += 4U; - cau_data_write(*(uint32_t*)(inputaddr)); + cau_data_write(*(uint32_t *)(inputaddr)); inputaddr += 4U; /* wait until the complete message has been processed */ counter = 0U; - do{ + do { busystatus = cau_flag_get(CAU_FLAG_BUSY); counter++; - }while((DESBUSY_TIMEOUT != counter) && (RESET != busystatus)); + } while((DESBUSY_TIMEOUT != counter) && (RESET != busystatus)); - if(RESET != busystatus){ + if(RESET != busystatus) { return ERROR; - }else{ + } else { /* read the output block from the output FIFO */ - *(uint32_t*)(outputaddr) = cau_data_read(); + *(uint32_t *)(outputaddr) = cau_data_read(); outputaddr += 4U; - *(uint32_t*)(outputaddr) = cau_data_read(); + *(uint32_t *)(outputaddr) = cau_data_read(); outputaddr += 4U; } } - + return SUCCESS; } diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau_tdes.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau_tdes.c index aa698226..b555c931 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau_tdes.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_cau_tdes.c @@ -2,36 +2,33 @@ \file gd32f20x_cau_tdes.c \brief CAU_TDES driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -48,14 +45,14 @@ static ErrStatus cau_tdes_calculate(uint8_t *input, uint32_t in_length, uint8_t only one parameter can be selected which is shown as below \arg CAU_ENCRYPT: encrypt \arg CAU_DECRYPT: decrypt - \param[in] key: key used for TDES algorithm - \param[in] text: pointer to the text information struct + \param[in] key: key used for TDES algorithm + \param[in] text: pointer to the text information struct input: pointer to the input buffer in_length: length of the input buffer, must be a multiple of 8 output: pointer to the returned buffer \param[out] none \retval ErrStatus: SUCCESS or ERROR -*/ +*/ ErrStatus cau_tdes_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text) { ErrStatus ret = ERROR; @@ -69,17 +66,17 @@ ErrStatus cau_tdes_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text cau_init(algo_dir, CAU_MODE_TDES_ECB, CAU_SWAPPING_8BIT); /* key initialization */ - key_initpara.key_1_high = __REV(*(uint32_t*)(keyaddr)); + key_initpara.key_1_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - key_initpara.key_1_low= __REV(*(uint32_t*)(keyaddr)); + key_initpara.key_1_low = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - key_initpara.key_2_high = __REV(*(uint32_t*)(keyaddr)); + key_initpara.key_2_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - key_initpara.key_2_low= __REV(*(uint32_t*)(keyaddr)); + key_initpara.key_2_low = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - key_initpara.key_3_high = __REV(*(uint32_t*)(keyaddr)); + key_initpara.key_3_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - key_initpara.key_3_low= __REV(*(uint32_t*)(keyaddr)); + key_initpara.key_3_low = __REV(*(uint32_t *)(keyaddr)); cau_key_init(&key_initpara); /* flush the IN and OUT FIFOs */ @@ -92,7 +89,7 @@ ErrStatus cau_tdes_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text /* disable the CAU peripheral */ cau_disable(); - return ret; + return ret; } /*! @@ -102,20 +99,20 @@ ErrStatus cau_tdes_ecb(uint32_t algo_dir, uint8_t key[24], cau_text_struct *text \arg CAU_ENCRYPT: encrypt \arg CAU_DECRYPT: decrypt \param[in] key: key used for TDES algorithm - \param[in] iv: initialization vectors used for TDES algorithm - \param[in] text: pointer to the text information struct + \param[in] iv: initialization vectors used for TDES algorithm + \param[in] text: pointer to the text information struct input: pointer to the input buffer in_length: length of the input buffer, must be a multiple of 8 output: pointer to the returned buffer \param[out] none \retval ErrStatus: SUCCESS or ERROR -*/ +*/ ErrStatus cau_tdes_cbc(uint32_t algo_dir, uint8_t key[24], uint8_t iv[8], cau_text_struct *text) { ErrStatus ret = ERROR; cau_key_parameter_struct key_initpara; cau_iv_parameter_struct iv_initpara; - + uint32_t keyaddr = (uint32_t)key; uint32_t ivaddr = (uint32_t)iv; @@ -123,25 +120,25 @@ ErrStatus cau_tdes_cbc(uint32_t algo_dir, uint8_t key[24], uint8_t iv[8], cau_te cau_key_parameter_init(&key_initpara); /* initialize the CAU peripheral */ cau_init(algo_dir, CAU_MODE_TDES_CBC, CAU_SWAPPING_8BIT); - + /* key initialization */ - key_initpara.key_1_high = __REV(*(uint32_t*)(keyaddr)); + key_initpara.key_1_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - key_initpara.key_1_low= __REV(*(uint32_t*)(keyaddr)); + key_initpara.key_1_low = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - key_initpara.key_2_high = __REV(*(uint32_t*)(keyaddr)); + key_initpara.key_2_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - key_initpara.key_2_low= __REV(*(uint32_t*)(keyaddr)); + key_initpara.key_2_low = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - key_initpara.key_3_high = __REV(*(uint32_t*)(keyaddr)); + key_initpara.key_3_high = __REV(*(uint32_t *)(keyaddr)); keyaddr += 4U; - key_initpara.key_3_low= __REV(*(uint32_t*)(keyaddr)); + key_initpara.key_3_low = __REV(*(uint32_t *)(keyaddr)); cau_key_init(&key_initpara); /* vectors initialization */ - iv_initpara.iv_0_high = __REV(*(uint32_t*)(ivaddr)); + iv_initpara.iv_0_high = __REV(*(uint32_t *)(ivaddr)); ivaddr += 4U; - iv_initpara.iv_0_low= __REV(*(uint32_t*)(ivaddr)); + iv_initpara.iv_0_low = __REV(*(uint32_t *)(ivaddr)); cau_iv_init(&iv_initpara); /* flush the IN and OUT FIFOs */ @@ -154,14 +151,14 @@ ErrStatus cau_tdes_cbc(uint32_t algo_dir, uint8_t key[24], uint8_t iv[8], cau_te /* disable the CAU peripheral */ cau_disable(); - return ret; + return ret; } /*! \brief TDES calculate process - \param[in] input: pointer to the input buffer - \param[in] in_length: length of the input buffer, must be a multiple of 8 - \param[in] output: pointer to the returned buffer + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer, must be a multiple of 8 + \param[in] output: pointer to the returned buffer \param[out] none \retval ErrStatus: SUCCESS or ERROR */ @@ -171,37 +168,37 @@ static ErrStatus cau_tdes_calculate(uint8_t *input, uint32_t in_length, uint8_t uint32_t outputaddr = (uint32_t)output; uint32_t i = 0U; __IO uint32_t counter = 0U; - uint32_t busystatus = 0U; - - /* the clock is not enabled or there is no embeded CAU peripheral */ - if(DISABLE == cau_enable_state_get()){ + uint32_t busystatus = 0U; + + /* the clock is not enabled or there is no embedded CAU peripheral */ + if(DISABLE == cau_enable_state_get()) { return ERROR; } - for(i = 0U; i < in_length; i += 8U){ + for(i = 0U; i < in_length; i += 8U) { /* write data to the IN FIFO */ - cau_data_write(*(uint32_t*)(inputaddr)); + cau_data_write(*(uint32_t *)(inputaddr)); inputaddr += 4U; - cau_data_write(*(uint32_t*)(inputaddr)); + cau_data_write(*(uint32_t *)(inputaddr)); inputaddr += 4U; /* wait until the complete message has been processed */ counter = 0U; - do{ + do { busystatus = cau_flag_get(CAU_FLAG_BUSY); counter++; - }while((TDESBSY_TIMEOUT != counter) && (RESET != busystatus)); + } while((TDESBSY_TIMEOUT != counter) && (RESET != busystatus)); - if(RESET != busystatus){ + if(RESET != busystatus) { return ERROR; - }else{ + } else { /* read the output block from the output FIFO */ - *(uint32_t*)(outputaddr) = cau_data_read(); + *(uint32_t *)(outputaddr) = cau_data_read(); outputaddr += 4U; - *(uint32_t*)(outputaddr) = cau_data_read(); + *(uint32_t *)(outputaddr) = cau_data_read(); outputaddr += 4U; } } - + return SUCCESS; } diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_crc.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_crc.c index 418b6814..a8ca8fa5 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_crc.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_crc.c @@ -2,36 +2,33 @@ \file gd32f20x_crc.c \brief CRC driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -54,7 +51,7 @@ void crc_deinit(void) } /*! - \brief reset data register to the value of initializaiton data register + \brief reset data register to the value of initialization data register \param[in] none \param[out] none \retval none @@ -65,7 +62,7 @@ void crc_data_register_reset(void) } /*! - \brief read the value of the data register + \brief read the value of the data register \param[in] none \param[out] none \retval 32-bit value of the data register @@ -123,7 +120,7 @@ uint32_t crc_single_data_calculate(uint32_t sdata) uint32_t crc_block_data_calculate(uint32_t array[], uint32_t size) { uint32_t index; - for(index = 0U; index < size; index++){ + for(index = 0U; index < size; index++) { CRC_DATA = array[index]; } return (CRC_DATA); diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dac.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dac.c index 1677143f..a638fe96 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dac.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dac.c @@ -2,36 +2,33 @@ \file gd32f20x_dac.c \brief DAC driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -63,12 +60,12 @@ void dac_deinit(void) */ void dac_enable(uint32_t dac_periph) { - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { DAC_CTL |= DAC_CTL_DEN0; - }else{ + } else { DAC_CTL |= DAC_CTL_DEN1; } -} +} /*! \brief disable DAC @@ -79,9 +76,9 @@ void dac_enable(uint32_t dac_periph) */ void dac_disable(uint32_t dac_periph) { - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { DAC_CTL &= ~DAC_CTL_DEN0; - }else{ + } else { DAC_CTL &= ~DAC_CTL_DEN1; } } @@ -95,9 +92,9 @@ void dac_disable(uint32_t dac_periph) */ void dac_dma_enable(uint32_t dac_periph) { - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { DAC_CTL |= DAC_CTL_DDMAEN0; - }else{ + } else { DAC_CTL |= DAC_CTL_DDMAEN1; } } @@ -111,9 +108,9 @@ void dac_dma_enable(uint32_t dac_periph) */ void dac_dma_disable(uint32_t dac_periph) { - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { DAC_CTL &= ~DAC_CTL_DDMAEN0; - }else{ + } else { DAC_CTL &= ~DAC_CTL_DDMAEN1; } } @@ -127,9 +124,9 @@ void dac_dma_disable(uint32_t dac_periph) */ void dac_output_buffer_enable(uint32_t dac_periph) { - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { DAC_CTL &= ~DAC_CTL_DBOFF0; - }else{ + } else { DAC_CTL &= ~DAC_CTL_DBOFF1; } } @@ -143,9 +140,9 @@ void dac_output_buffer_enable(uint32_t dac_periph) */ void dac_output_buffer_disable(uint32_t dac_periph) { - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { DAC_CTL |= DAC_CTL_DBOFF0; - }else{ + } else { DAC_CTL |= DAC_CTL_DBOFF1; } } @@ -160,10 +157,10 @@ void dac_output_buffer_disable(uint32_t dac_periph) uint16_t dac_output_value_get(uint32_t dac_periph) { uint16_t data = 0U; - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { /* store the DAC0 output value */ data = (uint16_t)DAC0_DO; - }else{ + } else { /* store the DAC1 output value */ data = (uint16_t)DAC1_DO; } @@ -185,8 +182,8 @@ uint16_t dac_output_value_get(uint32_t dac_periph) */ void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data) { - if(DAC0 == dac_periph){ - switch(dac_align){ + if(DAC0 == dac_periph) { + switch(dac_align) { /* data right 12b alignment */ case DAC_ALIGN_12B_R: DAC0_R12DH = data; @@ -202,8 +199,8 @@ void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data) default: break; } - }else{ - switch(dac_align){ + } else { + switch(dac_align) { /* data right 12b alignment */ case DAC_ALIGN_12B_R: DAC1_R12DH = data; @@ -231,9 +228,9 @@ void dac_data_set(uint32_t dac_periph, uint32_t dac_align, uint16_t data) */ void dac_trigger_enable(uint32_t dac_periph) { - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { DAC_CTL |= DAC_CTL_DTEN0; - }else{ + } else { DAC_CTL |= DAC_CTL_DTEN1; } } @@ -247,9 +244,9 @@ void dac_trigger_enable(uint32_t dac_periph) */ void dac_trigger_disable(uint32_t dac_periph) { - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { DAC_CTL &= ~DAC_CTL_DTEN0; - }else{ + } else { DAC_CTL &= ~DAC_CTL_DTEN1; } } @@ -273,11 +270,11 @@ void dac_trigger_disable(uint32_t dac_periph) */ void dac_trigger_source_config(uint32_t dac_periph, uint32_t triggersource) { - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { /* configure DAC0 trigger source */ DAC_CTL &= ~DAC_CTL_DTSEL0; DAC_CTL |= triggersource; - }else{ + } else { /* configure DAC1 trigger source */ DAC_CTL &= ~DAC_CTL_DTSEL1; DAC_CTL |= (triggersource << DAC1_REG_OFFSET); @@ -292,9 +289,9 @@ void dac_trigger_source_config(uint32_t dac_periph, uint32_t triggersource) */ void dac_software_trigger_enable(uint32_t dac_periph) { - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { DAC_SWT |= DAC_SWT_SWTR0; - }else{ + } else { DAC_SWT |= DAC_SWT_SWTR1; } } @@ -308,9 +305,9 @@ void dac_software_trigger_enable(uint32_t dac_periph) */ void dac_software_trigger_disable(uint32_t dac_periph) { - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { DAC_SWT &= ~DAC_SWT_SWTR0; - }else{ + } else { DAC_SWT &= ~DAC_SWT_SWTR1; } } @@ -329,11 +326,11 @@ void dac_software_trigger_disable(uint32_t dac_periph) */ void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode) { - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { /* configure DAC0 wave mode */ DAC_CTL &= ~DAC_CTL_DWM0; DAC_CTL |= wave_mode; - }else{ + } else { /* configure DAC1 wave mode */ DAC_CTL &= ~DAC_CTL_DWM1; DAC_CTL |= (wave_mode << DAC1_REG_OFFSET); @@ -363,11 +360,11 @@ void dac_wave_mode_config(uint32_t dac_periph, uint32_t wave_mode) */ void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width) { - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { /* configure DAC0 wave bit width */ DAC_CTL &= ~DAC_CTL_DWBW0; DAC_CTL |= bit_width; - }else{ + } else { /* configure DAC1 wave bit width */ DAC_CTL &= ~DAC_CTL_DWBW1; DAC_CTL |= (bit_width << DAC1_REG_OFFSET); @@ -397,11 +394,11 @@ void dac_wave_bit_width_config(uint32_t dac_periph, uint32_t bit_width) */ void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits) { - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { /* configure DAC0 LFSR noise mode */ DAC_CTL &= ~DAC_CTL_DWBW0; DAC_CTL |= unmask_bits; - }else{ + } else { /* configure DAC1 LFSR noise mode */ DAC_CTL &= ~DAC_CTL_DWBW1; DAC_CTL |= (unmask_bits << DAC1_REG_OFFSET); @@ -431,11 +428,11 @@ void dac_lfsr_noise_config(uint32_t dac_periph, uint32_t unmask_bits) */ void dac_triangle_noise_config(uint32_t dac_periph, uint32_t amplitude) { - if(DAC0 == dac_periph){ + if(DAC0 == dac_periph) { /* configure DAC0 triangle noise mode */ DAC_CTL &= ~DAC_CTL_DWBW0; DAC_CTL |= amplitude; - }else{ + } else { /* configure DAC1 triangle noise mode */ DAC_CTL &= ~DAC_CTL_DWBW1; DAC_CTL |= (amplitude << DAC1_REG_OFFSET); @@ -478,7 +475,7 @@ void dac_concurrent_software_trigger_enable(void) { uint32_t swt = 0U; swt = DAC_SWT_SWTR0 | DAC_SWT_SWTR1; - DAC_SWT |= (swt); + DAC_SWT |= (swt); } /*! @@ -535,7 +532,7 @@ void dac_concurrent_output_buffer_disable(void) void dac_concurrent_data_set(uint32_t dac_align, uint16_t data0, uint16_t data1) { uint32_t data = 0U; - switch(dac_align){ + switch(dac_align) { /* data right 12b alignment */ case DAC_ALIGN_12B_R: data = ((uint32_t)data1 << DH_12BIT_OFFSET) | data0; diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dbg.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dbg.c index bbd6c9f0..8bde336c 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dbg.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dbg.c @@ -2,36 +2,33 @@ \file gd32f20x_dbg.c \brief DBG driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -67,9 +64,9 @@ void dbg_low_power_enable(uint32_t dbg_low_power) \brief disable low power behavior when the mcu is in debug mode \param[in] dbg_low_power: one or more parameters can be selected which are shown as below: - \arg DBG_LOW_POWER_SLEEP: donot keep debugger connection during sleep mode - \arg DBG_LOW_POWER_DEEPSLEEP: donot keep debugger connection during deepsleep mode - \arg DBG_LOW_POWER_STANDBY: donot keep debugger connection during standby mode + \arg DBG_LOW_POWER_SLEEP: do not keep debugger connection during sleep mode + \arg DBG_LOW_POWER_DEEPSLEEP: do not keep debugger connection during deepsleep mode + \arg DBG_LOW_POWER_STANDBY: do not keep debugger connection during standby mode \param[out] none \retval none */ @@ -82,11 +79,11 @@ void dbg_low_power_disable(uint32_t dbg_low_power) \brief enable peripheral behavior when the mcu is in debug mode \param[in] dbg_periph: refer to dbg_periph_enum one or more parameters can be selected which are shown as below: - \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted - \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted - \arg DBG_CANx_HOLD (x=0,1): hold CANx counter when core is halted - \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted - \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): hold TIMERx counter when core is halted + \arg DBG_FWDGT_HOLD: debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD: debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD(x=0,1): hold CANx counter when core is halted + \arg DBG_I2Cx_HOLD(x=0,1,2): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD(x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): hold TIMERx counter when core is halted \param[out] none \retval none */ @@ -99,11 +96,11 @@ void dbg_periph_enable(dbg_periph_enum dbg_periph) \brief disable peripheral behavior when the mcu is in debug mode \param[in] dbg_periph: refer to dbg_periph_enum one or more parameters can be selected which are shown as below: - \arg DBG_FWDGT_HOLD : debug FWDGT kept when core is halted - \arg DBG_WWDGT_HOLD : debug WWDGT kept when core is halted - \arg DBG_CANx_HOLD (x=0,1): hold CANx counter when core is halted - \arg DBG_I2Cx_HOLD (x=0,1): hold I2Cx smbus when core is halted - \arg DBG_TIMERx_HOLD (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): hold TIMERx counter when core is halted + \arg DBG_FWDGT_HOLD: debug FWDGT kept when core is halted + \arg DBG_WWDGT_HOLD: debug WWDGT kept when core is halted + \arg DBG_CANx_HOLD(x=0,1): hold CANx counter when core is halted + \arg DBG_I2Cx_HOLD(x=0,1,2): hold I2Cx smbus when core is halted + \arg DBG_TIMERx_HOLD(x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): hold TIMERx counter when core is halted \param[out] none \retval none */ @@ -135,10 +132,10 @@ void dbg_trace_pin_disable(void) } /*! - \brief trace pin mode selection + \brief trace pin mode selection \param[in] trace_mode: only one parameter can be selected which is shown as below: - \arg TRACE_MODE_ASYNC: trace pin used for async mode + \arg TRACE_MODE_ASYNC: trace pin used for async mode \arg TRACE_MODE_SYNC_DATASIZE_1: trace pin used for sync mode and data size is 1 \arg TRACE_MODE_SYNC_DATASIZE_2: trace pin used for sync mode and data size is 2 \arg TRACE_MODE_SYNC_DATASIZE_4: trace pin used for sync mode and data size is 4 diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dci.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dci.c index 33ef579d..dbfa925f 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dci.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dci.c @@ -2,36 +2,33 @@ \file gd32f20x_dci.c \brief DCI driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -63,7 +60,7 @@ void dci_deinit(void) \param[out] none \retval none */ -void dci_init(dci_parameter_struct* dci_struct) +void dci_init(dci_parameter_struct *dci_struct) { uint32_t reg = 0U; /* disable capture function and DCI */ @@ -80,18 +77,18 @@ void dci_init(dci_parameter_struct* dci_struct) } /*! - \brief enable DCI function + \brief enable DCI function \param[in] none \param[out] none \retval none */ void dci_enable(void) { - DCI_CTL |= DCI_CTL_DCIEN; + DCI_CTL |= DCI_CTL_DCIEN; } /*! - \brief disable DCI function + \brief disable DCI function \param[in] none \param[out] none \retval none @@ -102,7 +99,7 @@ void dci_disable(void) } /*! - \brief enable DCI capture + \brief enable DCI capture \param[in] none \param[out] none \retval none @@ -113,7 +110,7 @@ void dci_capture_enable(void) } /*! - \brief disable DCI capture + \brief disable DCI capture \param[in] none \param[out] none \retval none @@ -124,7 +121,7 @@ void dci_capture_disable(void) } /*! - \brief enable DCI jpeg mode + \brief enable DCI jpeg mode \param[in] none \param[out] none \retval none @@ -135,7 +132,7 @@ void dci_jpeg_enable(void) } /*! - \brief disable DCI jpeg mode + \brief disable DCI jpeg mode \param[in] none \param[out] none \retval none @@ -168,7 +165,7 @@ void dci_crop_window_disable(void) } /*! - \brief configure DCI cropping window + \brief configure DCI cropping window \param[in] start_x: window horizontal start position \param[in] start_y: window vertical start position \param[in] size_width: window horizontal size @@ -178,8 +175,8 @@ void dci_crop_window_disable(void) */ void dci_crop_window_config(uint16_t start_x, uint16_t start_y, uint16_t size_width, uint16_t size_height) { - DCI_CWSPOS = ((uint32_t)start_x | ((uint32_t)start_y<<16)); - DCI_CWSZ = ((uint32_t)size_width | ((uint32_t)size_height<<16)); + DCI_CWSPOS = ((uint32_t)start_x | ((uint32_t)start_y << 16)); + DCI_CWSZ = ((uint32_t)size_width | ((uint32_t)size_height << 16)); } /*! @@ -214,7 +211,7 @@ void dci_embedded_sync_disable(void) */ void dci_sync_codes_config(uint8_t frame_start, uint8_t line_start, uint8_t line_end, uint8_t frame_end) { - DCI_SC = ((uint32_t)frame_start | ((uint32_t)line_start<<8) | ((uint32_t)line_end<<16) | ((uint32_t)frame_end<<24)); + DCI_SC = ((uint32_t)frame_start | ((uint32_t)line_start << 8) | ((uint32_t)line_end << 16) | ((uint32_t)frame_end << 24)); } /*! @@ -228,14 +225,14 @@ void dci_sync_codes_config(uint8_t frame_start, uint8_t line_start, uint8_t line */ void dci_sync_codes_unmask_config(uint8_t frame_start, uint8_t line_start, uint8_t line_end, uint8_t frame_end) { - DCI_SCUMSK = ((uint32_t)frame_start | ((uint32_t)line_start<<8) | ((uint32_t)line_end<<16) | ((uint32_t)frame_end<<24)); + DCI_SCUMSK = ((uint32_t)frame_start | ((uint32_t)line_start << 8) | ((uint32_t)line_end << 16) | ((uint32_t)frame_end << 24)); } /*! \brief read DCI data register \param[in] none \param[out] none - \retval data + \retval data of DCI data register */ uint32_t dci_data_read(void) { @@ -259,18 +256,18 @@ uint32_t dci_data_read(void) FlagStatus dci_flag_get(uint32_t flag) { uint32_t stat = 0U; - - if(flag >> 31){ + + if(flag >> 31) { /* get flag status from DCI_STAT1 register */ stat = DCI_STAT1; - }else{ + } else { /* get flag status from DCI_STAT0 register */ stat = DCI_STAT0; } - - if(flag & stat){ + + if(flag & stat) { return SET; - }else{ + } else { return RESET; } } @@ -280,7 +277,7 @@ FlagStatus dci_flag_get(uint32_t flag) \param[in] interrupt: \arg DCI_INT_EF: end of frame interrupt \arg DCI_INT_OVR: FIFO overrun interrupt - \arg DCI_INT_ESE: embedded synchronous error interrupt + \arg DCI_INT_ESE: embedded synchronous error interrupt \arg DCI_INT_VSYNC: vsync interrupt \arg DCI_INT_EL: end of line interrupt \param[out] none @@ -296,7 +293,7 @@ void dci_interrupt_enable(uint32_t interrupt) \param[in] interrupt: \arg DCI_INT_EF: end of frame interrupt \arg DCI_INT_OVR: FIFO overrun interrupt - \arg DCI_INT_ESE: embedded synchronous error interrupt + \arg DCI_INT_ESE: embedded synchronous error interrupt \arg DCI_INT_VSYNC: vsync interrupt \arg DCI_INT_EL: end of line interrupt \param[out] none @@ -312,7 +309,7 @@ void dci_interrupt_disable(uint32_t interrupt) \param[in] int_flag: \arg DCI_INT_FLAG_EF: end of frame interrupt flag \arg DCI_INT_FLAG_OVR: FIFO overrun interrupt flag - \arg DCI_INT_FLAG_ESE: embedded synchronous error interrupt flag + \arg DCI_INT_FLAG_ESE: embedded synchronous error interrupt flag \arg DCI_INT_FLAG_VSYNC: vsync interrupt flag \arg DCI_INT_FLAG_EL: end of line interrupt flag \param[out] none @@ -320,9 +317,9 @@ void dci_interrupt_disable(uint32_t interrupt) */ FlagStatus dci_interrupt_flag_get(uint32_t int_flag) { - if(RESET == (DCI_INTF & int_flag)){ + if(RESET == (DCI_INTF & int_flag)) { return RESET; - }else{ + } else { return SET; } } @@ -332,7 +329,7 @@ FlagStatus dci_interrupt_flag_get(uint32_t int_flag) \param[in] int_flag: \arg DCI_INT_EF: end of frame interrupt \arg DCI_INT_OVR: FIFO overrun interrupt - \arg DCI_INT_ESE: embedded synchronous error interrupt + \arg DCI_INT_ESE: embedded synchronous error interrupt \arg DCI_INT_VSYNC: vsync interrupt \arg DCI_INT_EL: end of line interrupt \param[out] none diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dma.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dma.c index 7a0650e7..f41c1308 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dma.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_dma.c @@ -2,46 +2,42 @@ \file gd32f20x_dma.c \brief DMA driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "gd32f20x_dma.h" -#include "gd32f20x_rcu.h" #define DMA_WRONG_HANDLE while(1){} /*! - \brief deinitialize DMA a channel registers + \brief deinitialize a DMA channel registers \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) \param[in] channelx: specify which DMA channel is deinitialized @@ -60,23 +56,23 @@ void dma_deinit(uint32_t dma_periph, dma_channel_enum channelx) DMA_CHPADDR(dma_periph, channelx) = DMA_CHPADDR_RESET_VALUE; DMA_CHMADDR(dma_periph, channelx) = DMA_CHMADDR_RESET_VALUE; DMA_INTC(dma_periph) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, channelx); - - if((DMA1 == dma_periph) && (DMA_CH5 == channelx)){ + + if((DMA1 == dma_periph) && (DMA_CH5 == channelx)) { DMA_ACFG = DMA_ACFG_RESET_VALUE; } } /*! \brief initialize the parameters of DMA struct with the default values - \param[in] init_struct: the initialization data needed to initialize DMA channel - \param[out] none + \param[in] none + \param[out] init_struct: the initialization data needed to initialize DMA channel \retval none */ -void dma_struct_para_init(dma_parameter_struct* init_struct) +void dma_struct_para_init(dma_parameter_struct *init_struct) { /* set the DMA struct with the default values */ init_struct->periph_addr = 0U; - init_struct->periph_width = 0U; + init_struct->periph_width = 0U; init_struct->periph_inc = DMA_PERIPH_INCREASE_DISABLE; init_struct->memory_addr = 0U; init_struct->memory_width = 0U; @@ -96,12 +92,12 @@ void dma_struct_para_init(dma_parameter_struct* init_struct) \param[in] init_struct: the data needed to initialize DMA channel periph_addr: peripheral base address periph_width: DMA_PERIPHERAL_WIDTH_8BIT, DMA_PERIPHERAL_WIDTH_16BIT, DMA_PERIPHERAL_WIDTH_32BIT - periph_inc: DMA_PERIPH_INCREASE_ENABLE, DMA_PERIPH_INCREASE_DISABLE + periph_inc: DMA_PERIPH_INCREASE_ENABLE, DMA_PERIPH_INCREASE_DISABLE memory_addr: memory base address memory_width: DMA_MEMORY_WIDTH_8BIT, DMA_MEMORY_WIDTH_16BIT, DMA_MEMORY_WIDTH_32BIT memory_inc: DMA_MEMORY_INCREASE_ENABLE, DMA_MEMORY_INCREASE_DISABLE direction: DMA_PERIPHERAL_TO_MEMORY, DMA_MEMORY_TO_PERIPHERAL - number: the number of remaining data to be transferred by the DMA + number: the number of remaining data to be transferred by the DMA, 0 - 0xFFFF priority: DMA_PRIORITY_LOW, DMA_PRIORITY_MEDIUM, DMA_PRIORITY_HIGH, DMA_PRIORITY_ULTRA_HIGH \param[out] none \retval none @@ -112,13 +108,13 @@ void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_stru /* configure peripheral base address */ DMA_CHPADDR(dma_periph, channelx) = init_struct->periph_addr; - + /* configure memory base address */ DMA_CHMADDR(dma_periph, channelx) = init_struct->memory_addr; - + /* configure the number of remaining data to be transferred */ DMA_CHCNT(dma_periph, channelx) = (init_struct->number & DMA_CHANNEL_CNT_MASK); - + /* configure peripheral transfer width,memory transfer width, */ ctl = DMA_CHCTL(dma_periph, channelx); ctl &= ~(DMA_CHXCTL_PWIDTH | DMA_CHXCTL_MWIDTH | DMA_CHXCTL_PRIO); @@ -126,36 +122,36 @@ void dma_init(uint32_t dma_periph, dma_channel_enum channelx, dma_parameter_stru DMA_CHCTL(dma_periph, channelx) = ctl; /* configure peripheral increasing mode */ - if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc){ + if(DMA_PERIPH_INCREASE_ENABLE == init_struct->periph_inc) { DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_PNAGA; - }else{ + } else { DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_PNAGA; } /* configure memory increasing mode */ - if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc){ + if(DMA_MEMORY_INCREASE_ENABLE == init_struct->memory_inc) { DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_MNAGA; - }else{ + } else { DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_MNAGA; } - + /* configure the direction of data transfer */ - if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction){ + if(DMA_PERIPHERAL_TO_MEMORY == init_struct->direction) { DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; - }else{ + } else { DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; - } + } } /*! - \brief enable DMA circulation mode + \brief enable DMA circulation mode \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) \param[in] channelx: specify which DMA channel only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[out] none - \retval none + \retval none */ void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx) { @@ -163,14 +159,14 @@ void dma_circulation_enable(uint32_t dma_periph, dma_channel_enum channelx) } /*! - \brief disable DMA circulation mode + \brief disable DMA circulation mode \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[out] none - \retval none + \retval none */ void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx) { @@ -181,7 +177,7 @@ void dma_circulation_disable(uint32_t dma_periph, dma_channel_enum channelx) \brief enable memory to memory mode \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[out] none @@ -208,14 +204,14 @@ void dma_memory_to_memory_disable(uint32_t dma_periph, dma_channel_enum channelx } /*! - \brief enable DMA channel + \brief enable DMA channel \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[out] none - \retval none + \retval none */ void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx) { @@ -223,14 +219,14 @@ void dma_channel_enable(uint32_t dma_periph, dma_channel_enum channelx) } /*! - \brief disable DMA channel + \brief disable DMA channel \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[out] none - \retval none + \retval none */ void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx) { @@ -238,15 +234,15 @@ void dma_channel_disable(uint32_t dma_periph, dma_channel_enum channelx) } /*! - \brief set DMA peripheral base address + \brief set DMA peripheral base address \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel to set peripheral base address + \param[in] channelx: specify which DMA channel to set peripheral base address only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[in] address: peripheral base address \param[out] none - \retval none + \retval none */ void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) { @@ -254,15 +250,15 @@ void dma_periph_address_config(uint32_t dma_periph, dma_channel_enum channelx, u } /*! - \brief set DMA memory base address + \brief set DMA memory base address \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel to set memory base address + \param[in] channelx: specify which DMA channel to set memory base address only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[in] address: memory base address \param[out] none - \retval none + \retval none */ void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t address) { @@ -270,16 +266,16 @@ void dma_memory_address_config(uint32_t dma_periph, dma_channel_enum channelx, u } /*! - \brief set the number of remaining data to be transferred by the DMA + \brief set the number of remaining data to be transferred by the DMA \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel to set number + \param[in] channelx: specify which DMA channel to set number only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[in] number: the number of remaining data to be transferred by the DMA \arg 0x0000-0xFFFF \param[out] none - \retval none + \retval none */ void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t number) { @@ -287,14 +283,14 @@ void dma_transfer_number_config(uint32_t dma_periph, dma_channel_enum channelx, } /*! - \brief get the number of remaining data to be transferred by the DMA + \brief get the number of remaining data to be transferred by the DMA \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel to set number + \param[in] channelx: specify which DMA channel to set number only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[out] none - \retval uint32_t: the number of remaining data to be transferred by the DMA + \retval uint32_t: the number of remaining data to be transferred by the DMA */ uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx) { @@ -302,10 +298,10 @@ uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx) } /*! - \brief configure priority level of DMA channel + \brief configure priority level of DMA channel \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[in] priority: priority Level of this channel @@ -315,7 +311,7 @@ uint32_t dma_transfer_number_get(uint32_t dma_periph, dma_channel_enum channelx) \arg DMA_PRIORITY_HIGH: high priority \arg DMA_PRIORITY_ULTRA_HIGH: ultra high priority \param[out] none - \retval none + \retval none */ void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_t priority) { @@ -323,17 +319,17 @@ void dma_priority_config(uint32_t dma_periph, dma_channel_enum channelx, uint32_ /* acquire DMA_CHxCTL register */ ctl = DMA_CHCTL(dma_periph, channelx); - /* assign regiser */ + /* assign register */ ctl &= ~DMA_CHXCTL_PRIO; ctl |= priority; DMA_CHCTL(dma_periph, channelx) = ctl; } /*! - \brief configure transfer data size of memory + \brief configure transfer data size of memory \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[in] mwidth: transfer data width of memory @@ -357,10 +353,10 @@ void dma_memory_width_config(uint32_t dma_periph, dma_channel_enum channelx, uin } /*! - \brief configure transfer data size of peripheral + \brief configure transfer data size of peripheral \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[in] pwidth: transfer data width of peripheral @@ -377,17 +373,17 @@ void dma_periph_width_config(uint32_t dma_periph, dma_channel_enum channelx, uin /* acquire DMA_CHxCTL register */ ctl = DMA_CHCTL(dma_periph, channelx); - /* assign regiser */ + /* assign register */ ctl &= ~DMA_CHXCTL_PWIDTH; ctl |= pwidth; DMA_CHCTL(dma_periph, channelx) = ctl; } /*! - \brief enable next address increasement algorithm of memory + \brief enable next address increasement algorithm of memory \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[out] none @@ -399,10 +395,10 @@ void dma_memory_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) } /*! - \brief disable next address increasement algorithm of memory + \brief disable next address increasement algorithm of memory \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[out] none @@ -417,7 +413,7 @@ void dma_memory_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) \brief enable next address increasement algorithm of peripheral \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[out] none @@ -429,10 +425,10 @@ void dma_periph_increase_enable(uint32_t dma_periph, dma_channel_enum channelx) } /*! - \brief disable next address increasement algorithm of peripheral + \brief disable next address increasement algorithm of peripheral \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[out] none @@ -444,10 +440,10 @@ void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) } /*! - \brief configure the direction of data transfer on the channel + \brief configure the direction of data transfer on the channel \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[in] direction: specify the direction of data transfer @@ -459,15 +455,37 @@ void dma_periph_increase_disable(uint32_t dma_periph, dma_channel_enum channelx) */ void dma_transfer_direction_config(uint32_t dma_periph, dma_channel_enum channelx, uint8_t direction) { - if(DMA_PERIPHERAL_TO_MEMORY == direction){ + if(DMA_PERIPHERAL_TO_MEMORY == direction) { DMA_CHCTL(dma_periph, channelx) &= ~DMA_CHXCTL_DIR; - }else{ + } else { DMA_CHCTL(dma_periph, channelx) |= DMA_CHXCTL_DIR; } } /*! - \brief check DMA flag is set or not + \brief enable the DMA1 channel 5 Full_Data transfer mode + \param[in] none + \param[out] none + \retval none +*/ +void dma_1_channel_5_fulldata_transfer_enable(void) +{ + DMA_ACFG |= DMA_ACFG_FD_CH5EN; +} + +/*! + \brief disable the DMA1 channel 5 Full_Data transfer mode + \param[in] none + \param[out] none + \retval none +*/ +void dma_1_channel_5_fulldata_transfer_disable(void) +{ + DMA_ACFG &= ~DMA_ACFG_FD_CH5EN; +} + +/*! + \brief check DMA flag is set or not \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) \param[in] channelx: specify which DMA channel to get flag @@ -487,12 +505,12 @@ FlagStatus dma_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t FlagStatus reval; /* check whether the flag is set or not */ - if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))){ + if(RESET != (DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx))) { reval = SET; - }else{ + } else { reval = RESET; } - + return reval; } @@ -517,93 +535,15 @@ void dma_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t fla DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); } -/*! - \brief check DMA flag and interrupt enable bit is set or not - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel to get flag - only one parameter can be selected which is shown as below: - \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) - \param[in] flag: specify get which flag - only one parameter can be selected which is shown as below: - \arg DMA_INT_FLAG_G: global interrupt flag of channel - \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel - \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel - \arg DMA_INT_FLAG_ERR: error interrupt flag of channel - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) -{ - uint32_t interrupt_enable = 0U, interrupt_flag = 0U; - uint32_t gif_check = 0x0FU, gif_enable = 0x0EU; - - switch(flag){ - case DMA_INT_FLAG_FTF: - /* check whether the full transfer finish interrupt flag is set and enabled */ - interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); - interrupt_flag = interrupt_flag >> ((channelx) * 4U); - interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE; - break; - case DMA_INT_FLAG_HTF: - /* check whether the half transfer finish interrupt flag is set and enabled */ - interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); - interrupt_flag = interrupt_flag >> ((channelx) * 4U); - interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE; - break; - case DMA_INT_FLAG_ERR: - /* check whether the error interrupt flag is set and enabled */ - interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); - interrupt_flag = interrupt_flag >> ((channelx) * 4U); - interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE; - break; - case DMA_INT_FLAG_G: - interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(gif_check, channelx); - interrupt_flag = interrupt_flag >> ((channelx) * 4U); - interrupt_enable = DMA_CHCTL(dma_periph, channelx) & gif_enable; - break; - default: - DMA_WRONG_HANDLE - } - - /* when the interrupt flag is set and enabled, return SET */ - if(interrupt_flag && interrupt_enable){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear DMA a channel flag - \param[in] dma_periph: DMAx(x=0,1) - \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel to clear flag - only one parameter can be selected which is shown as below: - \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) - \param[in] flag: specify get which flag - only one parameter can be selected which is shown as below: - \arg DMA_INT_FLAG_G: global interrupt flag of channel - \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel - \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel - \arg DMA_INT_FLAG_ERR: error interrupt flag of channel - \param[out] none - \retval none -*/ -void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) -{ - DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); -} - /*! \brief enable DMA interrupt \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) \param[in] source: specify which interrupt to enbale - one or more parameters can be selected which are shown as below + one or more parameters can be selected which are shown as below: \arg DMA_INT_FTF: channel full transfer finish interrupt \arg DMA_INT_HTF: channel half transfer finish interrupt \arg DMA_INT_ERR: channel error interrupt @@ -619,11 +559,11 @@ void dma_interrupt_enable(uint32_t dma_periph, dma_channel_enum channelx, uint32 \brief disable DMA interrupt \param[in] dma_periph: DMAx(x=0,1) \arg DMAx(x=0,1) - \param[in] channelx: specify which DMA channel + \param[in] channelx: specify which DMA channel only one parameter can be selected which is shown as below: \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) - \param[in] source: specify which interrupt to disbale - one or more parameters can be selected which are shown as below + \param[in] source: specify which interrupt to disable + one or more parameters can be selected which are shown as below: \arg DMA_INT_FTF: channel full transfer finish interrupt \arg DMA_INT_HTF: channel half transfer finish interrupt \arg DMA_INT_ERR: channel error interrupt @@ -636,23 +576,79 @@ void dma_interrupt_disable(uint32_t dma_periph, dma_channel_enum channelx, uint3 } /*! - \brief enable the DMA1 channel 5 Full_Data transfer mode - \param[in] none + \brief check DMA flag and interrupt enable bit is set or not + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to get flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_G: global interrupt flag of channel + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel \param[out] none - \retval none + \retval FlagStatus: SET or RESET */ -void dma_1_channel_5_fulldata_transfer_enable(void) +FlagStatus dma_interrupt_flag_get(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) { - DMA_ACFG |= DMA_ACFG_FD_CH5EN; + uint32_t interrupt_enable = 0U, interrupt_flag = 0U; + uint32_t gif_check = 0x0FU, gif_enable = 0x0EU; + + switch(flag) { + case DMA_INT_FLAG_FTF: + /* check whether the full transfer finish interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE; + break; + case DMA_INT_FLAG_HTF: + /* check whether the half transfer finish interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE; + break; + case DMA_INT_FLAG_ERR: + /* check whether the error interrupt flag is set and enabled */ + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE; + break; + case DMA_INT_FLAG_G: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(gif_check, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & gif_enable; + break; + default: + DMA_WRONG_HANDLE + } + + /* when the interrupt flag is set and enabled, return SET */ + if(interrupt_flag && interrupt_enable) { + return SET; + } else { + return RESET; + } } /*! - \brief disable the DMA1 channel 5 Full_Data transfer mode - \param[in] none + \brief clear DMA a channel flag + \param[in] dma_periph: DMAx(x=0,1) + \arg DMAx(x=0,1) + \param[in] channelx: specify which DMA channel to clear flag + only one parameter can be selected which is shown as below: + \arg DMA0: DMA_CHx(x=0..6), DMA1: DMA_CHx(x=0..6) + \param[in] flag: specify get which flag + only one parameter can be selected which is shown as below: + \arg DMA_INT_FLAG_G: global interrupt flag of channel + \arg DMA_INT_FLAG_FTF: full transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_HTF: half transfer finish interrupt flag of channel + \arg DMA_INT_FLAG_ERR: error interrupt flag of channel \param[out] none \retval none */ -void dma_1_channel_5_fulldata_transfer_disable(void) +void dma_interrupt_flag_clear(uint32_t dma_periph, dma_channel_enum channelx, uint32_t flag) { - DMA_ACFG &= ~DMA_ACFG_FD_CH5EN; + DMA_INTC(dma_periph) |= DMA_FLAG_ADD(flag, channelx); } diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_enet.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_enet.c index 7748d7d9..ce05fc8f 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_enet.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_enet.c @@ -2,36 +2,33 @@ \file gd32f20x_enet.c \brief ENET driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -40,13 +37,13 @@ OF SUCH DAMAGE. #ifdef GD32F20X_CL #if defined (__CC_ARM) /*!< ARM compiler */ -__align(4) +__align(4) enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM]; /*!< ENET RxDMA descriptor */ -__align(4) +__align(4) enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; /*!< ENET TxDMA descriptor */ -__align(4) +__align(4) uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive buffer */ -__align(4) +__align(4) uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ #elif defined ( __ICCARM__ ) /*!< IAR compiler */ @@ -60,10 +57,10 @@ uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; /*!< ENET receive bu uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; /*!< ENET transmit buffer */ #elif defined (__GNUC__) /* GNU Compiler */ -enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET RxDMA descriptor */ -enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM] __attribute__ ((aligned (4))); /*!< ENET TxDMA descriptor */ -uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET receive buffer */ -uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE] __attribute__ ((aligned (4))); /*!< ENET transmit buffer */ +enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM] __attribute__((aligned(4))); /*!< ENET RxDMA descriptor */ +enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM] __attribute__((aligned(4))); /*!< ENET TxDMA descriptor */ +uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE] __attribute__((aligned(4))); /*!< ENET receive buffer */ +uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE] __attribute__((aligned(4))); /*!< ENET transmit buffer */ #endif /* __CC_ARM */ @@ -76,21 +73,22 @@ enet_descriptors_struct *dma_current_ptp_txdesc = NULL; enet_descriptors_struct *dma_current_ptp_rxdesc = NULL; /* init structure parameters for ENET initialization */ -static enet_initpara_struct enet_initpara ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +static enet_initpara_struct enet_initpara = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U}; static uint32_t enet_unknow_err = 0U; /* array of register offset for debug information get */ static const uint16_t enet_reg_tab[] = { -0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x1080, 0x001C, 0x0028, 0x002C, -0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, - -0x0100, 0x0104, 0x0108, 0x010C, 0x0110, 0x014C, 0x0150, 0x0168, 0x0194, 0x0198, 0x01C4, - -0x0700, 0x0704,0x0708, 0x070C, 0x0710, 0x0714, 0x0718, 0x071C, 0x0720, - -0x1000, 0x1004, 0x1008, 0x100C, 0x1010, 0x1014, 0x1018, 0x101C, 0x1020, 0x1048, 0x104C, -0x1050, 0x1054}; + 0x0000U, 0x0004U, 0x0008U, 0x000CU, 0x0010U, 0x0014U, 0x0018U, 0x1080U, 0x001CU, 0x0028U, 0x002CU, + + 0x0038U, 0x003CU, 0x0040U, 0x0044U, 0x0048U, 0x004CU, 0x0050U, 0x0054U, 0x0058U, 0x005CU, 0x0100U, + + 0x0104U, 0x0108U, 0x010CU, 0x0110U, 0x014CU, 0x0150U, 0x0168U, 0x0194U, 0x0198U, 0x01C4U, 0x0700U, + + 0x0704U, 0x0708U, 0x070CU, 0x0710U, 0x0714U, 0x0718U, 0x071CU, 0x0720U, 0x1000U, 0x1004U, 0x1008U, + + 0x100CU, 0x1010U, 0x1014U, 0x1018U, 0x101CU, 0x1020U, 0x1048U, 0x104CU, 0x1050U, 0x1054U +}; /*! @@ -108,16 +106,16 @@ void enet_deinit(void) /*! \brief configure the parameters which are usually less cared for initialization - note -- this function must be called before enet_init(), otherwise + note -- this function must be called before enet_init(), otherwise configuration will be no effect - \param[in] option: different function option, which is related to several parameters, + \param[in] option: different function option, which is related to several parameters, only one parameter can be selected which is shown as below, refer to enet_option_enum \arg FORWARD_OPTION: choose to configure the frame forward related parameters \arg DMABUS_OPTION: choose to configure the DMA bus mode related parameters \arg DMA_MAXBURST_OPTION: choose to configure the DMA max burst related parameters \arg DMA_ARBITRATION_OPTION: choose to configure the DMA arbitration related parameters \arg STORE_OPTION: choose to configure the store forward mode related parameters - \arg DMA_OPTION: choose to configure the DMA descriptor related parameters + \arg DMA_OPTION: choose to configure the DMA descriptor related parameters \arg VLAN_OPTION: choose to configure vlan related parameters \arg FLOWCTL_OPTION: choose to configure flow control related parameters \arg HASHH_OPTION: choose to configure hash high @@ -126,7 +124,7 @@ void enet_deinit(void) \arg HALFDUPLEX_OPTION: choose to configure halfduplex mode related parameters \arg TIMER_OPTION: choose to configure time counter related parameters \arg INTERFRAMEGAP_OPTION: choose to configure the inter frame gap related parameters - \param[in] para: the related parameters according to the option + \param[in] para: the related parameters according to the option all the related parameters should be configured which are shown as below FORWARD_OPTION related parameters: - ENET_AUTO_PADCRC_DROP_ENABLE/ ENET_AUTO_PADCRC_DROP_DISABLE ; @@ -169,7 +167,7 @@ void enet_deinit(void) FLOWCTL_OPTION related parameters: - MAC_FCTL_PTM(regval) ; - ENET_ZERO_QUANTA_PAUSE_ENABLE/ ENET_ZERO_QUANTA_PAUSE_DISABLE ; - - ENET_PAUSETIME_MINUS4/ ENET_PAUSETIME_MINUS28/ + - ENET_PAUSETIME_MINUS4/ ENET_PAUSETIME_MINUS28/ ENET_PAUSETIME_MINUS144/ENET_PAUSETIME_MINUS256 ; - ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT/ ENET_UNIQUE_PAUSEDETECT ; - ENET_RX_FLOWCONTROL_ENABLE/ ENET_RX_FLOWCONTROL_DISABLE ; @@ -187,7 +185,15 @@ void enet_deinit(void) - ENET_UNICAST_FILTER_EITHER/ ENET_UNICAST_FILTER_HASH/ ENET_UNICAST_FILTER_PERFECT ; - ENET_PCFRM_PREVENT_ALL/ ENET_PCFRM_PREVENT_PAUSEFRAME/ - ENET_PCFRM_FORWARD_ALL/ ENET_PCFRM_FORWARD_FILTERED . + ENET_PCFRM_FORWARD_ALL/ ENET_PCFRM_FORWARD_FILTERED ; + - ENET_ACTIVE_THRESHOLD_256BYTES/ ENET_ACTIVE_THRESHOLD_512BYTES ; + - ENET_ACTIVE_THRESHOLD_768BYTES/ ENET_ACTIVE_THRESHOLD_1024BYTES ; + - ENET_ACTIVE_THRESHOLD_1280BYTES/ ENET_ACTIVE_THRESHOLD_1536BYTES ; + - ENET_ACTIVE_THRESHOLD_1792BYTES ; + - ENET_DEACTIVE_THRESHOLD_256BYTES/ ENET_DEACTIVE_THRESHOLD_512BYTES ; + - ENET_DEACTIVE_THRESHOLD_768BYTES/ ENET_DEACTIVE_THRESHOLD_1024BYTES ; + - ENET_DEACTIVE_THRESHOLD_1280BYTES/ ENET_DEACTIVE_THRESHOLD_1536BYTES ; + - ENET_DEACTIVE_THRESHOLD_1792BYTES . HALFDUPLEX_OPTION related parameters: - ENET_CARRIERSENSE_ENABLE/ ENET_CARRIERSENSE_DISABLE ; - ENET_RECEIVEOWN_ENABLE/ ENET_RECEIVEOWN_DISABLE ; @@ -203,12 +209,12 @@ void enet_deinit(void) ENET_INTERFRAMEGAP_80BIT/ ENET_INTERFRAMEGAP_72BIT/ ENET_INTERFRAMEGAP_64BIT/ ENET_INTERFRAMEGAP_56BIT/ ENET_INTERFRAMEGAP_48BIT/ ENET_INTERFRAMEGAP_40BIT . - \param[out] none + \param[out] none \retval none */ void enet_initpara_config(enet_option_enum option, uint32_t para) { - switch(option){ + switch(option) { case FORWARD_OPTION: /* choose to configure forward_frame, and save the configuration parameters */ enet_initpara.option_enable |= (uint32_t)FORWARD_OPTION; @@ -272,7 +278,7 @@ void enet_initpara_config(enet_option_enum option, uint32_t para) case TIMER_OPTION: /* choose to configure timer_config, and save the configuration parameters */ enet_initpara.option_enable |= (uint32_t)TIMER_OPTION; - enet_initpara.timer_config = para; + enet_initpara.timer_config = para; break; case INTERFRAMEGAP_OPTION: /* choose to configure interframegap, and save the configuration parameters */ @@ -280,15 +286,15 @@ void enet_initpara_config(enet_option_enum option, uint32_t para) enet_initpara.interframegap = para; break; default: - break; - } -} + break; + } +} /*! - \brief initialize ENET peripheral with generally concerned parameters and the less cared + \brief initialize ENET peripheral with generally concerned parameters and the less cared parameters \param[in] mediamode: PHY mode and mac loopback configurations, only one parameter can be selected - which is shown as below, refer to enet_mediamode_enum + which is shown as below, refer to enet_mediamode_enum \arg ENET_AUTO_NEGOTIATION: PHY auto negotiation \arg ENET_100M_FULLDUPLEX: 100Mbit/s, full-duplex \arg ENET_100M_HALFDUPLEX: 100Mbit/s, half-duplex @@ -296,135 +302,136 @@ void enet_initpara_config(enet_option_enum option, uint32_t para) \arg ENET_10M_HALFDUPLEX: 10Mbit/s, half-duplex \arg ENET_LOOPBACKMODE: MAC in loopback mode at the MII \param[in] checksum: IP frame checksum offload function, only one parameter can be selected - which is shown as below, refer to enet_mediamode_enum + which is shown as below, refer to enet_mediamode_enum \arg ENET_NO_AUTOCHECKSUM: disable IP frame checksum function \arg ENET_AUTOCHECKSUM_DROP_FAILFRAMES: enable IP frame checksum function \arg ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES: enable IP frame checksum function, and the received frame with only payload error but no other errors will not be dropped \param[in] recept: frame filter function, only one parameter can be selected - which is shown as below, refer to enet_frmrecept_enum + which is shown as below, refer to enet_frmrecept_enum \arg ENET_PROMISCUOUS_MODE: promiscuous mode enabled \arg ENET_RECEIVEALL: all received frame are forwarded to application \arg ENET_BROADCAST_FRAMES_PASS: the address filters pass all received broadcast frames \arg ENET_BROADCAST_FRAMES_DROP: the address filters filter all incoming broadcast frames - \param[out] none + \param[out] none \retval ErrStatus: ERROR or SUCCESS */ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept) { - uint32_t reg_value=0U, reg_temp = 0U, temp = 0U; + uint32_t reg_value = 0U, reg_temp = 0U, temp = 0U; uint32_t media_temp = 0U; uint32_t timeout = 0U; uint16_t phy_value = 0U; - ErrStatus phy_state= ERROR, enet_state = ERROR; + ErrStatus phy_state = ERROR, enet_state = ERROR; /* PHY interface configuration, configure SMI clock and reset PHY chip */ -// if(ERROR == enet_phy_config()){ -// _ENET_DELAY_(PHY_RESETDELAY); -// if(ERROR == enet_phy_config()){ -// return enet_state; -// } -// } +/** AvV **/ +// if(ERROR == enet_phy_config()) { +// _ENET_DELAY_(PHY_RESETDELAY); +// if(ERROR == enet_phy_config()) { +// return enet_state; +// } +// } +/** AvV **/ /* initialize ENET peripheral with generally concerned parameters */ enet_default_init(); /* 1st, configure mediamode */ media_temp = (uint32_t)mediamode; /* if is PHY auto negotiation */ - if((uint32_t)ENET_AUTO_NEGOTIATION == media_temp){ + if((uint32_t)ENET_AUTO_NEGOTIATION == media_temp) { /* wait for PHY_LINKED_STATUS bit be set */ - do{ + do { enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); - phy_value &= PHY_LINKED_STATUS; + phy_value &= PHY_LINKED_STATUS; timeout++; - }while((RESET == phy_value) && (timeout < PHY_READ_TO)); + } while((RESET == phy_value) && (timeout < PHY_READ_TO)); /* return ERROR due to timeout */ - if(PHY_READ_TO == timeout){ + if(PHY_READ_TO == timeout) { return enet_state; } - /* reset timeout counter */ timeout = 0U; /* enable auto-negotiation */ phy_value = PHY_AUTONEGOTIATION; phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); - if(!phy_state){ + if(!phy_state) { /* return ERROR due to write timeout */ return enet_state; } /* wait for the PHY_AUTONEGO_COMPLETE bit be set */ - do{ + do { enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); phy_value &= PHY_AUTONEGO_COMPLETE; timeout++; - }while((RESET == phy_value) && (timeout < (uint32_t)PHY_READ_TO)); + } while((RESET == phy_value) && (timeout < (uint32_t)PHY_READ_TO)); /* return ERROR due to timeout */ - if(PHY_READ_TO == timeout){ + if(PHY_READ_TO == timeout) { return enet_state; } - /* reset timeout counter */ timeout = 0U; /* read the result of the auto-negotiation */ - enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_SR, &phy_value); + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_SR, &phy_value); /* configure the duplex mode of MAC following the auto-negotiation result */ - if((uint16_t)RESET != (phy_value & PHY_DUPLEX_STATUS)){ + if((uint16_t)RESET != (phy_value & PHY_DUPLEX_STATUS)) { media_temp = ENET_MODE_FULLDUPLEX; - }else{ + } else { media_temp = ENET_MODE_HALFDUPLEX; } - /* configure the communication speed of MAC following the auto-negotiation result */ #if(PHY_TYPE == RTL8201F) /** AvV **/ if ((uint16_t) RESET == (phy_value & PHY_SPEED_STATUS)) { #else if ((uint16_t) RESET != (phy_value & PHY_SPEED_STATUS)) { #endif - media_temp |= ENET_SPEEDMODE_10M; - } else { - media_temp |= ENET_SPEEDMODE_100M; - } - }else{ -// phy_value = (uint16_t)((media_temp & ENET_MAC_CFG_DPM) >> 3); -// phy_value |= (uint16_t)((media_temp & ENET_MAC_CFG_SPD) >> 1); -// phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); -// if(!phy_state){ -// /* return ERROR due to write timeout */ -// return enet_state; -// } -// /* PHY configuration need some time */ -// _ENET_DELAY_(PHY_CONFIGDELAY); + media_temp |= ENET_SPEEDMODE_10M; + } else { + media_temp |= ENET_SPEEDMODE_100M; + } + } else { +/** AvV **/ +// phy_value = (uint16_t)((media_temp & ENET_MAC_CFG_DPM) >> 3U); +// phy_value |= (uint16_t)((media_temp & ENET_MAC_CFG_SPD) >> 1U); +// phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value); +// if(!phy_state) { +// /* return ERROR due to write timeout */ +// return enet_state; +// } +// /* PHY configuration need some time */ +// _ENET_DELAY_(PHY_CONFIGDELAY); +/** AvV **/ } /* after configuring the PHY, use mediamode to configure registers */ reg_value = ENET_MAC_CFG; /* configure ENET_MAC_CFG register */ - reg_value &= (~(ENET_MAC_CFG_SPD |ENET_MAC_CFG_DPM |ENET_MAC_CFG_LBM)); + reg_value &= (~(ENET_MAC_CFG_SPD | ENET_MAC_CFG_DPM | ENET_MAC_CFG_LBM)); reg_value |= media_temp; ENET_MAC_CFG = reg_value; - - + + /* 2st, configure checksum */ - if(RESET != ((uint32_t)checksum & ENET_CHECKSUMOFFLOAD_ENABLE)){ + if(RESET != ((uint32_t)checksum & ENET_CHECKSUMOFFLOAD_ENABLE)) { ENET_MAC_CFG |= ENET_CHECKSUMOFFLOAD_ENABLE; - + reg_value = ENET_DMA_CTL; /* configure ENET_DMA_CTL register */ reg_value &= ~ENET_DMA_CTL_DTCERFD; reg_value |= ((uint32_t)checksum & ENET_DMA_CTL_DTCERFD); ENET_DMA_CTL = reg_value; } - - /* 3rd, configure recept */ + + /* 3rd, configure receipt */ ENET_MAC_FRMF |= (uint32_t)recept; - + /* 4th, configure different function options */ /* configure forward_frame related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)FORWARD_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)FORWARD_OPTION)) { reg_temp = enet_initpara.forward_frame; - + reg_value = ENET_MAC_CFG; temp = reg_temp; /* configure ENET_MAC_CFG register */ @@ -432,76 +439,76 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum temp &= ENET_MAC_CFG_APCD; reg_value |= temp; ENET_MAC_CFG = reg_value; - + reg_value = ENET_DMA_CTL; temp = reg_temp; /* configure ENET_DMA_CTL register */ - reg_value &= (~(ENET_DMA_CTL_FERF |ENET_DMA_CTL_FUF)); - temp &= ((ENET_DMA_CTL_FERF | ENET_DMA_CTL_FUF)<<2); + reg_value &= (~(ENET_DMA_CTL_FERF | ENET_DMA_CTL_FUF)); + temp &= ((ENET_DMA_CTL_FERF | ENET_DMA_CTL_FUF) << 2); reg_value |= (temp >> 2); ENET_DMA_CTL = reg_value; } /* configure dmabus_mode related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)DMABUS_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMABUS_OPTION)) { temp = enet_initpara.dmabus_mode; - + reg_value = ENET_DMA_BCTL; /* configure ENET_DMA_BCTL register */ reg_value &= ~(ENET_DMA_BCTL_AA | ENET_DMA_BCTL_FB \ - |ENET_DMA_BCTL_FPBL); + | ENET_DMA_BCTL_FPBL); reg_value |= temp; ENET_DMA_BCTL = reg_value; } /* configure dma_maxburst related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_MAXBURST_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_MAXBURST_OPTION)) { temp = enet_initpara.dma_maxburst; - + reg_value = ENET_DMA_BCTL; /* configure ENET_DMA_BCTL register */ - reg_value &= ~(ENET_DMA_BCTL_RXDP| ENET_DMA_BCTL_PGBL | ENET_DMA_BCTL_UIP); + reg_value &= ~(ENET_DMA_BCTL_RXDP | ENET_DMA_BCTL_PGBL | ENET_DMA_BCTL_UIP); reg_value |= temp; ENET_DMA_BCTL = reg_value; } /* configure dma_arbitration related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_ARBITRATION_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_ARBITRATION_OPTION)) { temp = enet_initpara.dma_arbitration; - + reg_value = ENET_DMA_BCTL; /* configure ENET_DMA_BCTL register */ reg_value &= ~(ENET_DMA_BCTL_RTPR | ENET_DMA_BCTL_DAB); reg_value |= temp; ENET_DMA_BCTL = reg_value; } - + /* configure store_forward_mode related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)STORE_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)STORE_OPTION)) { temp = enet_initpara.store_forward_mode; - + reg_value = ENET_DMA_CTL; /* configure ENET_DMA_CTL register */ - reg_value &= ~(ENET_DMA_CTL_RSFD | ENET_DMA_CTL_TSFD| ENET_DMA_CTL_RTHC| ENET_DMA_CTL_TTHC); + reg_value &= ~(ENET_DMA_CTL_RSFD | ENET_DMA_CTL_TSFD | ENET_DMA_CTL_RTHC | ENET_DMA_CTL_TTHC); reg_value |= temp; ENET_DMA_CTL = reg_value; } /* configure dma_function related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_OPTION)) { reg_temp = enet_initpara.dma_function; - + reg_value = ENET_DMA_CTL; /* configure ENET_DMA_CTL register */ - reg_value &= (~(ENET_DMA_CTL_DAFRF |ENET_DMA_CTL_OSF)); + reg_value &= (~(ENET_DMA_CTL_DAFRF | ENET_DMA_CTL_OSF)); reg_value |= reg_temp; ENET_DMA_CTL = reg_value; } /* configure vlan_config related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)VLAN_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)VLAN_OPTION)) { reg_temp = enet_initpara.vlan_config; - + reg_value = ENET_MAC_VLT; /* configure ENET_MAC_VLT register */ reg_value &= ~(ENET_MAC_VLT_VLTI | ENET_MAC_VLT_VLTC); @@ -510,84 +517,84 @@ ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum } /* configure flow_control related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)FLOWCTL_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)FLOWCTL_OPTION)) { reg_temp = enet_initpara.flow_control; - + reg_value = ENET_MAC_FCTL; temp = reg_temp; /* configure ENET_MAC_FCTL register */ - reg_value &= ~(ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \ - | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN); - temp &= (ENET_MAC_FCTL_PTM |ENET_MAC_FCTL_DZQP |ENET_MAC_FCTL_PLTS \ - | ENET_MAC_FCTL_UPFDT |ENET_MAC_FCTL_RFCEN |ENET_MAC_FCTL_TFCEN); + reg_value &= ~(ENET_MAC_FCTL_PTM | ENET_MAC_FCTL_DZQP | ENET_MAC_FCTL_PLTS \ + | ENET_MAC_FCTL_UPFDT | ENET_MAC_FCTL_RFCEN | ENET_MAC_FCTL_TFCEN); + temp &= (ENET_MAC_FCTL_PTM | ENET_MAC_FCTL_DZQP | ENET_MAC_FCTL_PLTS \ + | ENET_MAC_FCTL_UPFDT | ENET_MAC_FCTL_RFCEN | ENET_MAC_FCTL_TFCEN); reg_value |= temp; ENET_MAC_FCTL = reg_value; - + reg_value = ENET_MAC_FCTH; temp = reg_temp; /* configure ENET_MAC_FCTH register */ - reg_value &= ~(ENET_MAC_FCTH_RFA |ENET_MAC_FCTH_RFD); - temp &= ((ENET_MAC_FCTH_RFA | ENET_MAC_FCTH_RFD )<<8); - reg_value |= (temp >> 8); + reg_value &= ~(ENET_MAC_FCTH_RFA | ENET_MAC_FCTH_RFD); + temp &= ((ENET_MAC_FCTH_RFA | ENET_MAC_FCTH_RFD) << 8U); + reg_value |= (temp >> 8U); ENET_MAC_FCTH = reg_value; - } - + } + /* configure hashtable_high related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)HASHH_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHH_OPTION)) { ENET_MAC_HLH = enet_initpara.hashtable_high; - } + } /* configure hashtable_low related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)HASHL_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)HASHL_OPTION)) { ENET_MAC_HLL = enet_initpara.hashtable_low; - } + } /* configure framesfilter_mode related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)FILTER_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)FILTER_OPTION)) { reg_temp = enet_initpara.framesfilter_mode; - + reg_value = ENET_MAC_FRMF; /* configure ENET_MAC_FRMF register */ reg_value &= ~(ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT | ENET_MAC_FRMF_DAIFLT \ - | ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT | ENET_MAC_FRMF_MFD \ - | ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_PCFRM); + | ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT | ENET_MAC_FRMF_MFD \ + | ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_PCFRM); reg_value |= reg_temp; ENET_MAC_FRMF = reg_value; - } + } /* configure halfduplex_param related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)HALFDUPLEX_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)HALFDUPLEX_OPTION)) { reg_temp = enet_initpara.halfduplex_param; - + reg_value = ENET_MAC_CFG; /* configure ENET_MAC_CFG register */ reg_value &= ~(ENET_MAC_CFG_CSD | ENET_MAC_CFG_ROD | ENET_MAC_CFG_RTD \ - | ENET_MAC_CFG_BOL | ENET_MAC_CFG_DFC); + | ENET_MAC_CFG_BOL | ENET_MAC_CFG_DFC); reg_value |= reg_temp; ENET_MAC_CFG = reg_value; - } + } /* configure timer_config related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)TIMER_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)TIMER_OPTION)) { reg_temp = enet_initpara.timer_config; - + reg_value = ENET_MAC_CFG; /* configure ENET_MAC_CFG register */ reg_value &= ~(ENET_MAC_CFG_WDD | ENET_MAC_CFG_JBD); reg_value |= reg_temp; ENET_MAC_CFG = reg_value; - } - + } + /* configure interframegap related registers */ - if(RESET != (enet_initpara.option_enable & (uint32_t)INTERFRAMEGAP_OPTION)){ + if(RESET != (enet_initpara.option_enable & (uint32_t)INTERFRAMEGAP_OPTION)) { reg_temp = enet_initpara.interframegap; - + reg_value = ENET_MAC_CFG; /* configure ENET_MAC_CFG register */ reg_value &= ~ENET_MAC_CFG_IGBS; reg_value |= reg_temp; ENET_MAC_CFG = reg_value; - } + } enet_state = SUCCESS; return enet_state; @@ -604,21 +611,21 @@ ErrStatus enet_software_reset(void) uint32_t timeout = 0U; ErrStatus enet_state = ERROR; uint32_t dma_flag; - + /* reset all core internal registers located in CLK_TX and CLK_RX */ ENET_DMA_BCTL |= ENET_DMA_BCTL_SWR; - + /* wait for reset operation complete */ - do{ + do { dma_flag = (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR); timeout++; - }while((RESET != dma_flag) && (ENET_DELAY_TO != timeout)); + } while((RESET != dma_flag) && (ENET_DELAY_TO != timeout)); - /* reset operation complete */ - if(RESET == (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR)){ + /* reset operation complete */ + if(RESET == (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR)) { enet_state = SUCCESS; } - + return enet_state; } @@ -632,19 +639,19 @@ uint32_t enet_rxframe_size_get(void) { uint32_t size = 0U; uint32_t status; - + /* get rdes0 information of current RxDMA descriptor */ status = dma_current_rxdesc->status; - - /* if the desciptor is owned by DMA */ - if((uint32_t)RESET != (status & ENET_RDES0_DAV)){ + + /* if the descriptor is owned by DMA */ + if((uint32_t)RESET != (status & ENET_RDES0_DAV)) { return 0U; } - + /* if has any error, or the frame uses two or more descriptors */ if((((uint32_t)RESET) != (status & ENET_RDES0_ERRS)) || - (((uint32_t)RESET) == (status & ENET_RDES0_LDES)) || - (((uint32_t)RESET) == (status & ENET_RDES0_FDES))){ + (((uint32_t)RESET) == (status & ENET_RDES0_LDES)) || + (((uint32_t)RESET) == (status & ENET_RDES0_FDES))) { /* drop current receive frame */ enet_rxframe_drop(); @@ -653,30 +660,30 @@ uint32_t enet_rxframe_size_get(void) /* if is an ethernet-type frame, and IP frame payload error occurred */ if((((uint32_t)RESET) != (status & ENET_RDES0_FRMT)) && - (((uint32_t)RESET) != (status & ENET_RDES0_PCERR))){ - /* drop current receive frame */ - enet_rxframe_drop(); + (((uint32_t)RESET) != (status & ENET_RDES0_PCERR))) { + /* drop current receive frame */ + enet_rxframe_drop(); return 1U; - } + } - /* if CPU owns current descriptor, no error occured, the frame uses only one descriptor */ + /* if CPU owns current descriptor, no error occurred, the frame uses only one descriptor */ if((((uint32_t)RESET) == (status & ENET_RDES0_DAV)) && - (((uint32_t)RESET) == (status & ENET_RDES0_ERRS)) && - (((uint32_t)RESET) != (status & ENET_RDES0_LDES)) && - (((uint32_t)RESET) != (status & ENET_RDES0_FDES))){ + (((uint32_t)RESET) == (status & ENET_RDES0_ERRS)) && + (((uint32_t)RESET) != (status & ENET_RDES0_LDES)) && + (((uint32_t)RESET) != (status & ENET_RDES0_FDES))) { /* get the size of the received data including CRC */ size = GET_RDES0_FRML(status); - /* substract the CRC size */ + /* substract the CRC size */ size = size - 4U; - }else{ + } else { enet_unknow_err++; enet_rxframe_drop(); - return 1U; + return 1U; } - - /* return packet size */ + + /* return packet size */ return size; } @@ -694,62 +701,62 @@ void enet_descriptors_chain_init(enet_dmadirection_enum direction) uint32_t num = 0U, count = 0U, maxsize = 0U; uint32_t desc_status = 0U, desc_bufsize = 0U; enet_descriptors_struct *desc, *desc_tab; - uint8_t *buf; + uint8_t *buf; /* if want to initialize DMA Tx descriptors */ - if (ENET_DMA_TX == direction){ + if(ENET_DMA_TX == direction) { /* save a copy of the DMA Tx descriptors */ desc_tab = txdesc_tab; buf = &tx_buff[0][0]; count = ENET_TXBUF_NUM; maxsize = ENET_TXBUF_SIZE; - + /* select chain mode */ desc_status = ENET_TDES0_TCHM; - + /* configure DMA Tx descriptor table address register */ ENET_DMA_TDTADDR = (uint32_t)desc_tab; dma_current_txdesc = desc_tab; - }else{ + } else { /* if want to initialize DMA Rx descriptors */ /* save a copy of the DMA Rx descriptors */ desc_tab = rxdesc_tab; buf = &rx_buff[0][0]; count = ENET_RXBUF_NUM; maxsize = ENET_RXBUF_SIZE; - + /* enable receiving */ desc_status = ENET_RDES0_DAV; /* select receive chained mode and set buffer1 size */ desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; - + /* configure DMA Rx descriptor table address register */ ENET_DMA_RDTADDR = (uint32_t)desc_tab; - dma_current_rxdesc = desc_tab; + dma_current_rxdesc = desc_tab; } dma_current_ptp_rxdesc = NULL; dma_current_ptp_txdesc = NULL; - - /* configure each descriptor */ - for(num=0U; num < count; num++){ + + /* configure each descriptor */ + for(num = 0U; num < count; num++) { /* get the pointer to the next descriptor of the descriptor table */ desc = desc_tab + num; /* configure descriptors */ - desc->status = desc_status; + desc->status = desc_status; desc->control_buffer_size = desc_bufsize; desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); - + /* if is not the last descriptor */ - if(num < (count - 1U)){ + if(num < (count - 1U)) { /* configure the next descriptor address */ desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); - }else{ - /* when it is the last descriptor, the next descriptor address - equals to first descriptor address in descriptor table */ - desc->buffer2_next_desc_addr = (uint32_t) desc_tab; + } else { + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t) desc_tab; } - } + } } /*! @@ -767,64 +774,64 @@ void enet_descriptors_ring_init(enet_dmadirection_enum direction) uint32_t desc_status = 0U, desc_bufsize = 0U; enet_descriptors_struct *desc; enet_descriptors_struct *desc_tab; - uint8_t *buf; - + uint8_t *buf; + /* configure descriptor skip length */ ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); - + /* if want to initialize DMA Tx descriptors */ - if (ENET_DMA_TX == direction){ + if(ENET_DMA_TX == direction) { /* save a copy of the DMA Tx descriptors */ desc_tab = txdesc_tab; buf = &tx_buff[0][0]; count = ENET_TXBUF_NUM; - maxsize = ENET_TXBUF_SIZE; - + maxsize = ENET_TXBUF_SIZE; + /* configure DMA Tx descriptor table address register */ ENET_DMA_TDTADDR = (uint32_t)desc_tab; dma_current_txdesc = desc_tab; - }else{ + } else { /* if want to initialize DMA Rx descriptors */ /* save a copy of the DMA Rx descriptors */ desc_tab = rxdesc_tab; buf = &rx_buff[0][0]; count = ENET_RXBUF_NUM; - maxsize = ENET_RXBUF_SIZE; - + maxsize = ENET_RXBUF_SIZE; + /* enable receiving */ desc_status = ENET_RDES0_DAV; /* set buffer1 size */ desc_bufsize = ENET_RXBUF_SIZE; - - /* configure DMA Rx descriptor table address register */ + + /* configure DMA Rx descriptor table address register */ ENET_DMA_RDTADDR = (uint32_t)desc_tab; - dma_current_rxdesc = desc_tab; + dma_current_rxdesc = desc_tab; } dma_current_ptp_rxdesc = NULL; dma_current_ptp_txdesc = NULL; - - /* configure each descriptor */ - for(num=0U; num < count; num++){ + + /* configure each descriptor */ + for(num = 0U; num < count; num++) { /* get the pointer to the next descriptor of the descriptor table */ desc = desc_tab + num; /* configure descriptors */ - desc->status = desc_status; - desc->control_buffer_size = desc_bufsize; - desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); - + desc->status = desc_status; + desc->control_buffer_size = desc_bufsize; + desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); + /* when it is the last descriptor */ - if(num == (count - 1U)){ - if (ENET_DMA_TX == direction){ - /* configure transmit end of ring mode */ + if(num == (count - 1U)) { + if(ENET_DMA_TX == direction) { + /* configure transmit end of ring mode */ desc->status |= ENET_TDES0_TERM; - }else{ + } else { /* configure receive end of ring mode */ desc->control_buffer_size |= ENET_RDES1_RERM; } } - } + } } /*! @@ -837,64 +844,64 @@ void enet_descriptors_ring_init(enet_dmadirection_enum direction) ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize) { uint32_t offset = 0U, size = 0U; - + /* the descriptor is busy due to own by the DMA */ - if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ - return ERROR; + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)) { + return ERROR; } - + /* if buffer pointer is null, indicates that users has copied data in application */ - if(NULL != buffer){ + if(NULL != buffer) { /* if no error occurs, and the frame uses only one descriptor */ - if((((uint32_t)RESET) == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && - (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && - (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ + if((((uint32_t)RESET) == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_FDES))) { /* get the frame length except CRC */ size = GET_RDES0_FRML(dma_current_rxdesc->status); size = size - 4U; - + /* to avoid situation that the frame size exceeds the buffer length */ - if(size > bufsize){ + if(size > bufsize) { return ERROR; } - + /* copy data from Rx buffer to application buffer */ - for(offset = 0U; offsetbuffer1_addr) + offset)); + for(offset = 0U; offset < size; offset++) { + (*(buffer + offset)) = (*(__IO uint8_t *)(uint32_t)((dma_current_rxdesc->buffer1_addr) + offset)); } - - }else{ + + } else { /* return ERROR */ return ERROR; } } /* enable reception, descriptor is owned by DMA */ - dma_current_rxdesc->status = ENET_RDES0_DAV; - + dma_current_rxdesc->status = ENET_RDES0_DAV; + /* check Rx buffer unavailable flag status */ - if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + if((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)) { /* clear RBU flag */ ENET_DMA_STAT = ENET_DMA_STAT_RBU; /* resume DMA reception by writing to the RPEN register*/ ENET_DMA_RPEN = 0U; } - - /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + + /* update the current RxDMA descriptor pointer to the next descriptor in RxDMA descriptor table */ /* chained mode */ - if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ - dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); - }else{ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)) { + dma_current_rxdesc = (enet_descriptors_struct *)(dma_current_rxdesc->buffer2_next_desc_addr); + } else { /* ring mode */ - if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)) { /* if is the last descriptor in table, the next descriptor is the table header */ - dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); - }else{ + dma_current_rxdesc = (enet_descriptors_struct *)(ENET_DMA_RDTADDR); + } else { /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ - dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); + dma_current_rxdesc = (enet_descriptors_struct *)(uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); } } - + return SUCCESS; } @@ -910,55 +917,55 @@ ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length) { uint32_t offset = 0U; uint32_t dma_tbu_flag, dma_tu_flag; - + /* the descriptor is busy due to own by the DMA */ - if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)) { return ERROR; } - + /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ - if(length > ENET_MAX_FRAME_SIZE){ + if(length > ENET_MAX_FRAME_SIZE) { return ERROR; - } - + } + /* if buffer pointer is null, indicates that users has handled data in application */ - if(NULL != buffer){ + if(NULL != buffer) { /* copy frame data from application buffer to Tx buffer */ - for(offset = 0U; offset < length; offset++){ - (*(__IO uint8_t *) (uint32_t)((dma_current_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + for(offset = 0U; offset < length; offset++) { + (*(__IO uint8_t *)(uint32_t)((dma_current_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); } } - + /* set the frame length */ dma_current_txdesc->control_buffer_size = length; - /* set the segment of frame, frame is transmitted in one descriptor */ + /* set the segment of frame, frame is transmitted in one descriptor */ dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; /* enable the DMA transmission */ dma_current_txdesc->status |= ENET_TDES0_DAV; - + /* check Tx buffer unavailable flag status */ - dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); - - if ((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + + if((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)) { /* clear TBU and TU flag */ ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); /* resume DMA transmission by writing to the TPEN register*/ ENET_DMA_TPEN = 0U; } - - /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/ + + /* update the current TxDMA descriptor pointer to the next descriptor in TxDMA descriptor table*/ /* chained mode */ - if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ - dma_current_txdesc = (enet_descriptors_struct*) (dma_current_txdesc->buffer2_next_desc_addr); - }else{ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)) { + dma_current_txdesc = (enet_descriptors_struct *)(dma_current_txdesc->buffer2_next_desc_addr); + } else { /* ring mode */ - if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)) { /* if is the last descriptor in table, the next descriptor is the table header */ - dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); - }else{ + dma_current_txdesc = (enet_descriptors_struct *)(ENET_DMA_TDTADDR); + } else { /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ - dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); + dma_current_txdesc = (enet_descriptors_struct *)(uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL))); } } @@ -1008,18 +1015,18 @@ void enet_disable(void) } /*! - \brief configure MAC address - \param[in] mac_addr: select which MAC address will be set, - only one parameter can be selected which is shown as below + \brief configure MAC address + \param[in] mac_addr: select which MAC address will be set, + only one parameter can be selected which is shown as below \arg ENET_MAC_ADDRESS0: set MAC address 0 filter \arg ENET_MAC_ADDRESS1: set MAC address 1 filter \arg ENET_MAC_ADDRESS2: set MAC address 2 filter \arg ENET_MAC_ADDRESS3: set MAC address 3 filter \param[in] paddr: the buffer pointer which stores the MAC address - (little-ending store, such as MAC address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + (little-ending store, such as MAC address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) \param[out] none \retval none -*/ +*/ void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]) { REG32(ENET_ADDRH_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRH(paddr); @@ -1027,7 +1034,7 @@ void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]) } /*! - \brief get MAC address + \brief get MAC address \param[in] mac_addr: select which MAC address will be get, only one parameter can be selected which is shown as below \arg ENET_MAC_ADDRESS0: get MAC address 0 filter @@ -1035,9 +1042,9 @@ void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[]) \arg ENET_MAC_ADDRESS2: get MAC address 2 filter \arg ENET_MAC_ADDRESS3: get MAC address 3 filter \param[out] paddr: the buffer pointer which is stored the MAC address - (little-ending store, such as mac address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) + (little-ending store, such as mac address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa}) \retval none -*/ +*/ void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[]) { paddr[0] = ENET_GET_MACADDR(mac_addr, 0U); @@ -1049,277 +1056,41 @@ void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[]) } /*! - \brief get the ENET MAC/MSC/PTP/DMA status flag - \param[in] enet_flag: ENET status flag, refer to enet_flag_enum, - only one parameter can be selected which is shown as below - \arg ENET_MAC_FLAG_MPKR: magic packet received flag - \arg ENET_MAC_FLAG_WUFR: wakeup frame received flag - \arg ENET_MAC_FLAG_FLOWCONTROL: flow control status flag - \arg ENET_MAC_FLAG_WUM: WUM status flag - \arg ENET_MAC_FLAG_MSC: MSC status flag - \arg ENET_MAC_FLAG_MSCR: MSC receive status flag - \arg ENET_MAC_FLAG_MSCT: MSC transmit status flag - \arg ENET_MAC_FLAG_TMST: time stamp trigger status flag - \arg ENET_PTP_FLAG_TSSCO: timestamp second counter overflow flag - \arg ENET_PTP_FLAG_TTM: target time match flag - \arg ENET_MSC_FLAG_RFCE: received frames CRC error flag - \arg ENET_MSC_FLAG_RFAE: received frames alignment error flag - \arg ENET_MSC_FLAG_RGUF: received good unicast frames flag - \arg ENET_MSC_FLAG_TGFSC: transmitted good frames single collision flag - \arg ENET_MSC_FLAG_TGFMSC: transmitted good frames more single collision flag - \arg ENET_MSC_FLAG_TGF: transmitted good frames flag - \arg ENET_DMA_FLAG_TS: transmit status flag - \arg ENET_DMA_FLAG_TPS: transmit process stopped status flag - \arg ENET_DMA_FLAG_TBU: transmit buffer unavailable status flag - \arg ENET_DMA_FLAG_TJT: transmit jabber timeout status flag - \arg ENET_DMA_FLAG_RO: receive overflow status flag - \arg ENET_DMA_FLAG_TU: transmit underflow status flag - \arg ENET_DMA_FLAG_RS: receive status flag - \arg ENET_DMA_FLAG_RBU: receive buffer unavailable status flag - \arg ENET_DMA_FLAG_RPS: receive process stopped status flag - \arg ENET_DMA_FLAG_RWT: receive watchdog timeout status flag - \arg ENET_DMA_FLAG_ET: early transmit status flag - \arg ENET_DMA_FLAG_FBE: fatal bus error status flag - \arg ENET_DMA_FLAG_ER: early receive status flag - \arg ENET_DMA_FLAG_AI: abnormal interrupt summary flag - \arg ENET_DMA_FLAG_NI: normal interrupt summary flag - \arg ENET_DMA_FLAG_EB_DMA_ERROR: DMA error flag - \arg ENET_DMA_FLAG_EB_TRANSFER_ERROR: transfer error flag - \arg ENET_DMA_FLAG_EB_ACCESS_ERROR: access error flag - \arg ENET_DMA_FLAG_MSC: MSC status flag - \arg ENET_DMA_FLAG_WUM: WUM status flag - \arg ENET_DMA_FLAG_TST: timestamp trigger status flag + \brief ENET Tx function enable (include MAC and DMA module) + \param[in] none \param[out] none - \retval FlagStatus: SET or RESET + \retval none */ -FlagStatus enet_flag_get(enet_flag_enum enet_flag) +void enet_tx_enable(void) { - if(RESET != (ENET_REG_VAL(enet_flag) & BIT(ENET_BIT_POS(enet_flag)))){ - return SET; - }else{ - return RESET; - } + ENET_MAC_CFG |= ENET_MAC_CFG_TEN; + enet_txfifo_flush(); + ENET_DMA_CTL |= ENET_DMA_CTL_STE; } /*! - \brief clear the ENET DMA status flag - \param[in] enet_flag: ENET DMA flag clear, refer to enet_flag_clear_enum - only one parameter can be selected which is shown as below - \arg ENET_DMA_FLAG_TS_CLR: transmit status flag clear - \arg ENET_DMA_FLAG_TPS_CLR: transmit process stopped status flag clear - \arg ENET_DMA_FLAG_TBU_CLR: transmit buffer unavailable status flag clear - \arg ENET_DMA_FLAG_TJT_CLR: transmit jabber timeout status flag clear - \arg ENET_DMA_FLAG_RO_CLR: receive overflow status flag clear - \arg ENET_DMA_FLAG_TU_CLR: transmit underflow status flag clear - \arg ENET_DMA_FLAG_RS_CLR: receive status flag clear - \arg ENET_DMA_FLAG_RBU_CLR: receive buffer unavailable status flag clear - \arg ENET_DMA_FLAG_RPS_CLR: receive process stopped status flag clear - \arg ENET_DMA_FLAG_RWT_CLR: receive watchdog timeout status flag clear - \arg ENET_DMA_FLAG_ET_CLR: early transmit status flag clear - \arg ENET_DMA_FLAG_FBE_CLR: fatal bus error status flag clear - \arg ENET_DMA_FLAG_ER_CLR: early receive status flag clear - \arg ENET_DMA_FLAG_AI_CLR: abnormal interrupt summary flag clear - \arg ENET_DMA_FLAG_NI_CLR: normal interrupt summary flag clear + \brief ENET Tx function disable (include MAC and DMA module) + \param[in] none \param[out] none \retval none */ -void enet_flag_clear(enet_flag_clear_enum enet_flag) +void enet_tx_disable(void) { - /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ - ENET_REG_VAL(enet_flag) = BIT(ENET_BIT_POS(enet_flag)); + ENET_DMA_CTL &= ~ENET_DMA_CTL_STE; + enet_txfifo_flush(); + ENET_MAC_CFG &= ~ENET_MAC_CFG_TEN; } /*! - \brief enable ENET MAC/MSC/DMA interrupt - \param[in] enet_int: ENET interrupt, - only one parameter can be selected which is shown as below - \arg ENET_MAC_INT_WUMIM: WUM interrupt mask - \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask - \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask - \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask - \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask - \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask - \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask - \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask - \arg ENET_DMA_INT_TIE: transmit interrupt enable - \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable - \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable - \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable - \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable - \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable - \arg ENET_DMA_INT_RIE: receive interrupt enable - \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable - \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable - \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable - \arg ENET_DMA_INT_ETIE: early transmit interrupt enable - \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable - \arg ENET_DMA_INT_ERIE: early receive interrupt enable - \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable - \arg ENET_DMA_INT_NIE: normal interrupt summary enable + \brief ENET Rx function enable (include MAC and DMA module) + \param[in] none \param[out] none \retval none */ -void enet_interrupt_enable(enet_int_enum enet_int) +void enet_rx_enable(void) { - if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){ - /* ENET_DMA_INTEN register interrupt */ - ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); - }else{ - /* other INTMSK register interrupt */ - ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); - } -} - -/*! - \brief disable ENET MAC/MSC/DMA interrupt - \param[in] enet_int: ENET interrupt, - only one parameter can be selected which is shown as below - \arg ENET_MAC_INT_WUMIM: WUM interrupt mask - \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask - \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask - \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask - \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask - \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask - \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask - \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask - \arg ENET_DMA_INT_TIE: transmit interrupt enable - \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable - \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable - \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable - \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable - \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable - \arg ENET_DMA_INT_RIE: receive interrupt enable - \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable - \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable - \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable - \arg ENET_DMA_INT_ETIE: early transmit interrupt enable - \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable - \arg ENET_DMA_INT_ERIE: early receive interrupt enable - \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable - \arg ENET_DMA_INT_NIE: normal interrupt summary enable - \param[out] none - \retval none -*/ -void enet_interrupt_disable(enet_int_enum enet_int) -{ - if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)){ - /* ENET_DMA_INTEN register interrupt */ - ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); - }else{ - /* other INTMSK register interrupt */ - ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); - } -} - -/*! - \brief get ENET MAC/MSC/DMA interrupt flag - \param[in] int_flag: ENET interrupt flag, - only one parameter can be selected which is shown as below - \arg ENET_MAC_INT_FLAG_WUM: WUM status flag - \arg ENET_MAC_INT_FLAG_MSC: MSC status flag - \arg ENET_MAC_INT_FLAG_MSCR: MSC receive status flag - \arg ENET_MAC_INT_FLAG_MSCT: MSC transmit status flag - \arg ENET_MAC_INT_FLAG_TMST: time stamp trigger status flag - \arg ENET_MSC_INT_FLAG_RFCE: received frames CRC error flag - \arg ENET_MSC_INT_FLAG_RFAE: received frames alignment error flag - \arg ENET_MSC_INT_FLAG_RGUF: received good unicast frames flag - \arg ENET_MSC_INT_FLAG_TGFSC: transmitted good frames single collision flag - \arg ENET_MSC_INT_FLAG_TGFMSC: transmitted good frames more single collision flag - \arg ENET_MSC_INT_FLAG_TGF: transmitted good frames flag - \arg ENET_DMA_INT_FLAG_TS: transmit status flag - \arg ENET_DMA_INT_FLAG_TPS: transmit process stopped status flag - \arg ENET_DMA_INT_FLAG_TBU: transmit buffer unavailable status flag - \arg ENET_DMA_INT_FLAG_TJT: transmit jabber timeout status flag - \arg ENET_DMA_INT_FLAG_RO: receive overflow status flag - \arg ENET_DMA_INT_FLAG_TU: transmit underflow status flag - \arg ENET_DMA_INT_FLAG_RS: receive status flag - \arg ENET_DMA_INT_FLAG_RBU: receive buffer unavailable status flag - \arg ENET_DMA_INT_FLAG_RPS: receive process stopped status flag - \arg ENET_DMA_INT_FLAG_RWT: receive watchdog timeout status flag - \arg ENET_DMA_INT_FLAG_ET: early transmit status flag - \arg ENET_DMA_INT_FLAG_FBE: fatal bus error status flag - \arg ENET_DMA_INT_FLAG_ER: early receive status flag - \arg ENET_DMA_INT_FLAG_AI: abnormal interrupt summary flag - \arg ENET_DMA_INT_FLAG_NI: normal interrupt summary flag - \arg ENET_DMA_INT_FLAG_MSC: MSC status flag - \arg ENET_DMA_INT_FLAG_WUM: WUM status flag - \arg ENET_DMA_INT_FLAG_TST: timestamp trigger status flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag) -{ - if(RESET != (ENET_REG_VAL(int_flag) & BIT(ENET_BIT_POS(int_flag)))){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear ENET DMA interrupt flag - \param[in] int_flag_clear: clear ENET interrupt flag, - only one parameter can be selected which is shown as below - \arg ENET_DMA_INT_FLAG_TS_CLR: transmit status flag - \arg ENET_DMA_INT_FLAG_TPS_CLR: transmit process stopped status flag - \arg ENET_DMA_INT_FLAG_TBU_CLR: transmit buffer unavailable status flag - \arg ENET_DMA_INT_FLAG_TJT_CLR: transmit jabber timeout status flag - \arg ENET_DMA_INT_FLAG_RO_CLR: receive overflow status flag - \arg ENET_DMA_INT_FLAG_TU_CLR: transmit underflow status flag - \arg ENET_DMA_INT_FLAG_RS_CLR: receive status flag - \arg ENET_DMA_INT_FLAG_RBU_CLR: receive buffer unavailable status flag - \arg ENET_DMA_INT_FLAG_RPS_CLR: receive process stopped status flag - \arg ENET_DMA_INT_FLAG_RWT_CLR: receive watchdog timeout status flag - \arg ENET_DMA_INT_FLAG_ET_CLR: early transmit status flag - \arg ENET_DMA_INT_FLAG_FBE_CLR: fatal bus error status flag - \arg ENET_DMA_INT_FLAG_ER_CLR: early receive status flag - \arg ENET_DMA_INT_FLAG_AI_CLR: abnormal interrupt summary flag - \arg ENET_DMA_INT_FLAG_NI_CLR: normal interrupt summary flag - \param[out] none - \retval none -*/ -void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear) -{ - /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ - ENET_REG_VAL(int_flag_clear) = BIT(ENET_BIT_POS(int_flag_clear)); -} - -/*! - \brief ENET Tx function enable (include MAC and DMA module) - \param[in] none - \param[out] none - \retval none -*/ -void enet_tx_enable(void) -{ - ENET_MAC_CFG |= ENET_MAC_CFG_TEN; - enet_txfifo_flush(); - ENET_DMA_CTL |= ENET_DMA_CTL_STE; -} - -/*! - \brief ENET Tx function disable (include MAC and DMA module) - \param[in] none - \param[out] none - \retval none -*/ -void enet_tx_disable(void) -{ - ENET_DMA_CTL &= ~ENET_DMA_CTL_STE; - enet_txfifo_flush(); - ENET_MAC_CFG &= ~ENET_MAC_CFG_TEN; -} - -/*! - \brief ENET Rx function enable (include MAC and DMA module) - \param[in] none - \param[out] none - \retval none -*/ -void enet_rx_enable(void) -{ - ENET_MAC_CFG |= ENET_MAC_CFG_REN; - ENET_DMA_CTL |= ENET_DMA_CTL_SRE; + ENET_MAC_CFG |= ENET_MAC_CFG_REN; + ENET_DMA_CTL |= ENET_DMA_CTL_SRE; } /*! @@ -1335,10 +1106,10 @@ void enet_rx_disable(void) } /*! - \brief put registers value into the application buffer + \brief put registers value into the application buffer \param[in] type: register type which will be get, refer to enet_registers_type_enum, only one parameter can be selected which is shown as below - \arg ALL_MAC_REG: get the registers within the offset scope between ENET_MAC_CFG and ENET_MAC_FCTH + \arg ALL_MAC_REG: get the registers within the offset scope between ENET_MAC_CFG and ENET_MAC_FCTH \arg ALL_MSC_REG: get the registers within the offset scope between ENET_MSC_CTL and ENET_MSC_RGUFCNT \arg ALL_PTP_REG: get the registers within the offset scope between ENET_PTP_TSCTL and ENET_PTP_PPSCTL \arg ALL_DMA_REG: get the registers within the offset scope between ENET_DMA_BCTL and ENET_DMA_CRBADDR @@ -1349,26 +1120,26 @@ void enet_rx_disable(void) void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num) { uint32_t offset = 0U, max = 0U, limit = 0U; - + offset = (uint32_t)type; max = (uint32_t)type + num; - limit = sizeof(enet_reg_tab)/sizeof(uint16_t); - + limit = sizeof(enet_reg_tab) / sizeof(uint16_t); + /* prevent element in this array is out of range */ - if(max > limit){ + if(max > limit) { max = limit; } - - for(; offset < max; offset++){ + + for(; offset < max; offset++) { /* get value of the corresponding register */ - *preg = REG32((ENET) + enet_reg_tab[offset]); + *preg = REG32((ENET) + enet_reg_tab[offset]); preg++; } -} +} /*! - \brief enable the MAC address filter - \param[in] mac_addr: select which MAC address will be enable + \brief enable the MAC address filter + \param[in] mac_addr: select which MAC address will be enable \arg ENET_MAC_ADDRESS1: enable MAC address 1 filter \arg ENET_MAC_ADDRESS2: enable MAC address 2 filter \arg ENET_MAC_ADDRESS3: enable MAC address 3 filter @@ -1381,7 +1152,7 @@ void enet_address_filter_enable(enet_macaddress_enum mac_addr) } /*! - \brief disable the MAC address filter + \brief disable the MAC address filter \param[in] mac_addr: select which MAC address will be disable, only one parameter can be selected which is shown as below \arg ENET_MAC_ADDRESS1: disable MAC address 1 filter @@ -1396,7 +1167,7 @@ void enet_address_filter_disable(enet_macaddress_enum mac_addr) } /*! - \brief configure the MAC address filter + \brief configure the MAC address filter \param[in] mac_addr: select which MAC address will be configured, only one parameter can be selected which is shown as below \arg ENET_MAC_ADDRESS1: configure MAC address 1 filter @@ -1405,7 +1176,7 @@ void enet_address_filter_disable(enet_macaddress_enum mac_addr) \param[in] addr_mask: select which MAC address bytes will be mask, one or more parameters can be selected which are shown as below \arg ENET_ADDRESS_MASK_BYTE0: mask ENET_MAC_ADDR1L[7:0] bits - \arg ENET_ADDRESS_MASK_BYTE1: mask ENET_MAC_ADDR1L[15:8] bits + \arg ENET_ADDRESS_MASK_BYTE1: mask ENET_MAC_ADDR1L[15:8] bits \arg ENET_ADDRESS_MASK_BYTE2: mask ENET_MAC_ADDR1L[23:16] bits \arg ENET_ADDRESS_MASK_BYTE3: mask ENET_MAC_ADDR1L [31:24] bits \arg ENET_ADDRESS_MASK_BYTE4: mask ENET_MAC_ADDR1H [7:0] bits @@ -1420,7 +1191,7 @@ void enet_address_filter_disable(enet_macaddress_enum mac_addr) void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type) { uint32_t reg; - + /* get the address filter register value which is to be configured */ reg = REG32(ENET_ADDRH_BASE + mac_addr); @@ -1435,53 +1206,53 @@ void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mas \param[in] none \param[out] none \retval ErrStatus: SUCCESS or ERROR -*/ +*/ ErrStatus enet_phy_config(void) { uint32_t ahbclk; uint32_t reg; uint16_t phy_value; ErrStatus enet_state = ERROR; - + /* clear the previous MDC clock */ reg = ENET_MAC_PHY_CTL; reg &= ~ENET_MAC_PHY_CTL_CLR; /* get the HCLK frequency */ ahbclk = rcu_clock_freq_get(CK_AHB); - + /* configure MDC clock according to HCLK frequency range */ - if(ENET_RANGE(ahbclk, 20000000U, 35000000U)){ + if(ENET_RANGE(ahbclk, 20000000U, 35000000U)) { reg |= ENET_MDC_HCLK_DIV16; - }else if(ENET_RANGE(ahbclk, 35000000U, 60000000U)){ + } else if(ENET_RANGE(ahbclk, 35000000U, 60000000U)) { reg |= ENET_MDC_HCLK_DIV26; - }else if(ENET_RANGE(ahbclk, 60000000U, 100000000U)){ + } else if(ENET_RANGE(ahbclk, 60000000U, 100000000U)) { reg |= ENET_MDC_HCLK_DIV42; - }else if((ENET_RANGE(ahbclk, 100000000U, 120000000U))||(120000000U == ahbclk)){ - reg |= ENET_MDC_HCLK_DIV62; - }else{ + } else if((ENET_RANGE(ahbclk, 100000000U, 120000000U)) || (120000000U == ahbclk)) { + reg |= ENET_MDC_HCLK_DIV62; + } else { return enet_state; } ENET_MAC_PHY_CTL = reg; /* reset PHY */ phy_value = PHY_RESET; - if(ERROR == (enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ + if(ERROR == (enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value))) { return enet_state; } - /* PHY reset need some time */ + /* PHY reset need some time */ _ENET_DELAY_(ENET_DELAY_TO); - + /* check whether PHY reset is complete */ - if(ERROR == (enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value))){ + if(ERROR == (enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value))) { return enet_state; } /* PHY reset complete */ - if(RESET == (phy_value & PHY_RESET)){ + if(RESET == (phy_value & PHY_RESET)) { enet_state = SUCCESS; } - + return enet_state; } @@ -1492,7 +1263,7 @@ ErrStatus enet_phy_config(void) \arg ENET_PHY_READ: read data from phy register \param[in] phy_address: 0x0 - 0x1F \param[in] phy_reg: 0x0 - 0x1F - \param[in] pvalue: the value will be written to the PHY register in ENET_PHY_WRITE direction + \param[in] pvalue: the value will be written to the PHY register in ENET_PHY_WRITE direction \param[out] pvalue: the value will be read from the PHY register in ENET_PHY_READ direction \retval ErrStatus: SUCCESS or ERROR */ @@ -1502,34 +1273,33 @@ ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_add uint32_t timeout = 0U; ErrStatus enet_state = ERROR; - /* configure ENET_MAC_PHY_CTL with write/read operation */ + /* configure ENET_MAC_PHY_CTL with write/read operation */ reg = ENET_MAC_PHY_CTL; reg &= ~(ENET_MAC_PHY_CTL_PB | ENET_MAC_PHY_CTL_PW | ENET_MAC_PHY_CTL_PR | ENET_MAC_PHY_CTL_PA); - reg |= (direction | MAC_PHY_CTL_PR(phy_reg) | MAC_PHY_CTL_PA(phy_address) | ENET_MAC_PHY_CTL_PB); + reg |= (direction | MAC_PHY_CTL_PR(phy_reg) | MAC_PHY_CTL_PA(phy_address) | ENET_MAC_PHY_CTL_PB); /* if do the write operation, write value to the register */ - if(ENET_PHY_WRITE == direction){ - ENET_MAC_PHY_DATA = *pvalue; + if(ENET_PHY_WRITE == direction) { + ENET_MAC_PHY_DATA = *pvalue; } - + /* do PHY write/read operation, and wait the operation complete */ ENET_MAC_PHY_CTL = reg; - do{ + do { phy_flag = (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB); timeout++; - } - while((RESET != phy_flag) && (ENET_DELAY_TO != timeout)); + } while((RESET != phy_flag) && (ENET_DELAY_TO != timeout)); - /* write/read operation complete */ - if(RESET == (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB)){ + /* write/read operation complete */ + if(RESET == (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB)) { enet_state = SUCCESS; } - /* if do the read operation, get value from the register */ - if(ENET_PHY_READ == direction){ - *pvalue = (uint16_t)ENET_MAC_PHY_DATA; + /* if do the read operation, get value from the register */ + if(ENET_PHY_READ == direction) { + *pvalue = (uint16_t)ENET_MAC_PHY_DATA; } - + return enet_state; } @@ -1545,7 +1315,7 @@ ErrStatus enet_phyloopback_enable(void) ErrStatus phy_state = ERROR; /* get the PHY configuration to update it */ - enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); /* enable the PHY loopback mode */ temp_phy |= PHY_LOOPBACK; @@ -1568,7 +1338,7 @@ ErrStatus enet_phyloopback_disable(void) ErrStatus phy_state = ERROR; /* get the PHY configuration to update it */ - enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy); /* disable the PHY loopback mode */ temp_phy &= (uint16_t)~PHY_LOOPBACK; @@ -1592,10 +1362,10 @@ ErrStatus enet_phyloopback_disable(void) void enet_forward_feature_enable(uint32_t feature) { uint32_t mask; - + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); ENET_MAC_CFG |= mask; - + mask = (feature & (~(ENET_AUTO_PADCRC_DROP))); ENET_DMA_CTL |= (mask >> 2); } @@ -1604,24 +1374,24 @@ void enet_forward_feature_enable(uint32_t feature) \brief disable ENET forward feature \param[in] feature: the feature of ENET forward mode, one or more parameters can be selected which are shown as below - \arg ENET_AUTO_PADCRC_DROP: the automatic zero-quanta generation function - \arg ENET_FORWARD_ERRFRAMES: decoding function for the received pause frame and process it - \arg ENET_FORWARD_UNDERSZ_GOODFRAMES: back pressure operation in the MAC(only use in half-dulex mode) + \arg ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames + \arg ENET_FORWARD_ERRFRAMES: the function that all frame received with error except runt error are forwarded to memory + \arg ENET_FORWARD_UNDERSZ_GOODFRAMES: the function that forwarding undersized good frames \param[out] none \retval none */ void enet_forward_feature_disable(uint32_t feature) { uint32_t mask; - + mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES))); ENET_MAC_CFG &= ~mask; - + mask = (feature & (~(ENET_AUTO_PADCRC_DROP))); - ENET_DMA_CTL &= ~(mask >> 2); + ENET_DMA_CTL &= ~(mask >> 2U); } - -/*! + +/*! \brief enable ENET fliter feature \param[in] feature: the feature of ENET fliter mode, one or more parameters can be selected which are shown as below @@ -1666,18 +1436,18 @@ void enet_fliter_feature_disable(uint32_t feature) \param[out] none \retval ErrStatus: ERROR or SUCCESS */ -ErrStatus enet_pauseframe_generate(void) -{ - ErrStatus enet_state =ERROR; +ErrStatus enet_pauseframe_generate(void) +{ + ErrStatus enet_state = ERROR; uint32_t temp = 0U; /* in full-duplex mode, must make sure this bit is 0 before writing register */ temp = ENET_MAC_FCTL & ENET_MAC_FCTL_FLCBBKPA; - if(RESET == temp){ + if(RESET == temp) { ENET_MAC_FCTL |= ENET_MAC_FCTL_FLCBBKPA; enet_state = SUCCESS; } - return enet_state; + return enet_state; } /*! @@ -1686,7 +1456,7 @@ ErrStatus enet_pauseframe_generate(void) only one parameter can be selected which is shown as below \arg ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT: besides the unique multicast address, MAC can also use the MAC0 address to detecting pause frame - \arg ENET_UNIQUE_PAUSEDETECT: only the unique multicast address for pause frame which is specified + \arg ENET_UNIQUE_PAUSEDETECT: only the unique multicast address for pause frame which is specified in IEEE802.3 can be detected \param[out] none \retval none @@ -1719,7 +1489,7 @@ void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold) /*! \brief configure the threshold of the flow control(deactive and active threshold) \param[in] deactive: the threshold of the deactive flow control, this value - should always be less than active flow control value, only one + should always be less than active flow control value, only one parameter can be selected which is shown as below \arg ENET_DEACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes \arg ENET_DEACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes @@ -1742,7 +1512,7 @@ void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold) */ void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active) { - ENET_MAC_FCTH = ((deactive | active) >> 8); + ENET_MAC_FCTH = ((deactive | active) >> 8U); } /*! @@ -1758,7 +1528,7 @@ void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active) */ void enet_flowcontrol_feature_enable(uint32_t feature) { - if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){ + if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)) { ENET_MAC_FCTL &= ~ENET_ZERO_QUANTA_PAUSE; } feature &= ~ENET_ZERO_QUANTA_PAUSE; @@ -1778,7 +1548,7 @@ void enet_flowcontrol_feature_enable(uint32_t feature) */ void enet_flowcontrol_feature_disable(uint32_t feature) { - if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)){ + if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)) { ENET_MAC_FCTL |= ENET_ZERO_QUANTA_PAUSE; } feature &= ~ENET_ZERO_QUANTA_PAUSE; @@ -1787,7 +1557,7 @@ void enet_flowcontrol_feature_disable(uint32_t feature) /*! \brief get the dma transmit/receive process state - \param[in] direction: choose the direction of dma process which users want to check, + \param[in] direction: choose the direction of dma process which users want to check, refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below \arg ENET_DMA_TX: dma transmit process \arg ENET_DMA_RX: dma receive process @@ -1806,9 +1576,9 @@ uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction) } /*! - \brief poll the DMA transmission/reception enable by writing any value to the + \brief poll the DMA transmission/reception enable by writing any value to the ENET_DMA_TPEN/ENET_DMA_RPEN register, this will make the DMA to resume transmission/reception - \param[in] direction: choose the direction of DMA process which users want to resume, + \param[in] direction: choose the direction of DMA process which users want to resume, refer to enet_dmadirection_enum, only one parameter can be selected which is shown as below \arg ENET_DMA_TX: DMA transmit process \arg ENET_DMA_RX: DMA receive process @@ -1817,15 +1587,15 @@ uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction) */ void enet_dmaprocess_resume(enet_dmadirection_enum direction) { - if(ENET_DMA_TX == direction){ + if(ENET_DMA_TX == direction) { ENET_DMA_TPEN = 0U; - }else{ + } else { ENET_DMA_RPEN = 0U; } } /*! - \brief check and recover the Rx process + \brief check and recover the Rx process \param[in] none \param[out] none \retval none @@ -1834,15 +1604,15 @@ void enet_rxprocess_check_recovery(void) { uint32_t status; - /* get DAV information of current RxDMA descriptor */ + /* get DAV information of current RxDMA descriptor */ status = dma_current_rxdesc->status; status &= ENET_RDES0_DAV; - - /* if current descriptor is owned by DMA, but the descriptor address mismatches with + + /* if current descriptor is owned by DMA, but the descriptor address mismatches with receive descriptor address pointer updated by RxDMA controller */ if((ENET_DMA_CRDADDR != ((uint32_t)dma_current_rxdesc)) && - (ENET_RDES0_DAV == status)){ - dma_current_rxdesc = (enet_descriptors_struct*)ENET_DMA_CRDADDR; + (ENET_RDES0_DAV == status)) { + dma_current_rxdesc = (enet_descriptors_struct *)ENET_DMA_CRDADDR; } } @@ -1857,19 +1627,19 @@ ErrStatus enet_txfifo_flush(void) uint32_t flush_state; uint32_t timeout = 0U; ErrStatus enet_state = ERROR; - + /* set the FTF bit for flushing transmit FIFO */ - ENET_DMA_CTL |= ENET_DMA_CTL_FTF; + ENET_DMA_CTL |= ENET_DMA_CTL_FTF; /* wait until the flush operation completes */ - do{ - flush_state = ENET_DMA_CTL & ENET_DMA_CTL_FTF; + do { + flush_state = ENET_DMA_CTL & ENET_DMA_CTL_FTF; timeout++; - }while((RESET != flush_state) && (timeout < ENET_DELAY_TO)); + } while((RESET != flush_state) && (timeout < ENET_DELAY_TO)); /* return ERROR due to timeout */ - if(RESET == flush_state){ + if(RESET == flush_state) { enet_state = SUCCESS; } - + return enet_state; } @@ -1885,14 +1655,14 @@ ErrStatus enet_txfifo_flush(void) \arg ENET_TX_CURRENT_DESC: the start descriptor address of the current transmit descriptor read by the TxDMA controller \arg ENET_TX_CURRENT_BUFFER: the current transmit buffer address being read by the TxDMA controller - \param[out] none + \param[out] none \retval address value */ uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get) { uint32_t reval = 0U; - reval = REG32((ENET) +(uint32_t)addr_get); + reval = REG32((ENET) + (uint32_t)addr_get); return reval; } @@ -1914,30 +1684,30 @@ uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate { uint32_t reval = 0xFFFFFFFFU; - switch(info_get){ + switch(info_get) { case RXDESC_BUFFER_1_SIZE: reval = GET_RDES1_RB1S(desc->control_buffer_size); break; case RXDESC_BUFFER_2_SIZE: reval = GET_RDES1_RB2S(desc->control_buffer_size); - break; - case RXDESC_FRAME_LENGTH: + break; + case RXDESC_FRAME_LENGTH: reval = GET_RDES0_FRML(desc->status); - if(reval > 4U){ + if(reval > 4U) { reval = reval - 4U; - }else{ + } else { reval = 0U; } break; - case RXDESC_BUFFER_1_ADDR: - reval = desc->buffer1_addr; + case RXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; break; - case TXDESC_BUFFER_1_ADDR: - reval = desc->buffer1_addr; + case TXDESC_BUFFER_1_ADDR: + reval = desc->buffer1_addr; break; - case TXDESC_COLLISION_COUNT: + case TXDESC_COLLISION_COUNT: reval = GET_TDES0_COCNT(desc->status); - break; + break; default: break; } @@ -1954,7 +1724,7 @@ uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) { uint32_t temp_counter = 0U; - + temp_counter = ENET_DMA_MFBOCNT; *rxfifo_drop = GET_DMA_MFBOCNT_MSFA(temp_counter); *rxdma_drop = GET_DMA_MFBOCNT_MSFC(temp_counter); @@ -1965,7 +1735,7 @@ void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) \param[in] desc: the descriptor pointer which users want to get flag \param[in] desc_flag: the bit flag of ENET DMA descriptor, only one parameter can be selected which is shown as below - \arg ENET_TDES0_DB: deferred + \arg ENET_TDES0_DB: deferred \arg ENET_TDES0_UFE: underflow error \arg ENET_TDES0_EXD: excessive deferral \arg ENET_TDES0_VFRM: VLAN frame @@ -1978,18 +1748,18 @@ void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) \arg ENET_TDES0_JT: jabber timeout \arg ENET_TDES0_ES: error summary \arg ENET_TDES0_IPHE: IP header error - \arg ENET_TDES0_TTMSS: transmit timestamp status + \arg ENET_TDES0_TTMSS: transmit timestamp status \arg ENET_TDES0_TCHM: the second address chained mode \arg ENET_TDES0_TERM: transmit end of ring mode \arg ENET_TDES0_TTSEN: transmit timestamp function enable - \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DPAD: disable adding pad \arg ENET_TDES0_DCRC: disable CRC \arg ENET_TDES0_FSG: first segment \arg ENET_TDES0_LSG: last segment \arg ENET_TDES0_INTC: interrupt on completion \arg ENET_TDES0_DAV: DAV bit - - \arg ENET_RDES0_PCERR: payload checksum error + + \arg ENET_RDES0_PCERR: payload checksum error \arg ENET_RDES0_CERR: CRC error \arg ENET_RDES0_DBERR: dribble bit error \arg ENET_RDES0_RERR: receive error @@ -2000,11 +1770,11 @@ void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) \arg ENET_RDES0_LDES: last descriptor \arg ENET_RDES0_FDES: first descriptor \arg ENET_RDES0_VTAG: VLAN tag - \arg ENET_RDES0_OERR: overflow error + \arg ENET_RDES0_OERR: overflow error \arg ENET_RDES0_LERR: length error \arg ENET_RDES0_SAFF: SA filter fail \arg ENET_RDES0_DERR: descriptor error - \arg ENET_RDES0_ERRS: error summary + \arg ENET_RDES0_ERRS: error summary \arg ENET_RDES0_DAFF: destination address filter fail \arg ENET_RDES0_DAV: descriptor available \param[out] none @@ -2013,8 +1783,8 @@ void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop) FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag) { FlagStatus enet_flag = RESET; - - if ((uint32_t)RESET != (desc->status & desc_flag)){ + + if((uint32_t)RESET != (desc->status & desc_flag)) { enet_flag = SET; } @@ -2031,13 +1801,13 @@ FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag) \arg ENET_TDES0_TCHM: the second address chained mode \arg ENET_TDES0_TERM: transmit end of ring mode \arg ENET_TDES0_TTSEN: transmit timestamp function enable - \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DPAD: disable adding pad \arg ENET_TDES0_DCRC: disable CRC \arg ENET_TDES0_FSG: first segment \arg ENET_TDES0_LSG: last segment \arg ENET_TDES0_INTC: interrupt on completion \arg ENET_TDES0_DAV: DAV bit - \arg ENET_RDES0_DAV: descriptor available + \arg ENET_RDES0_DAV: descriptor available \param[out] none \retval none */ @@ -2056,13 +1826,13 @@ void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag) \arg ENET_TDES0_TCHM: the second address chained mode \arg ENET_TDES0_TERM: transmit end of ring mode \arg ENET_TDES0_TTSEN: transmit timestamp function enable - \arg ENET_TDES0_DPAD: disable adding pad + \arg ENET_TDES0_DPAD: disable adding pad \arg ENET_TDES0_DCRC: disable CRC \arg ENET_TDES0_FSG: first segment \arg ENET_TDES0_LSG: last segment \arg ENET_TDES0_INTC: interrupt on completion \arg ENET_TDES0_DAV: DAV bit - \arg ENET_RDES0_DAV: descriptor available + \arg ENET_RDES0_DAV: descriptor available \param[out] none \retval none */ @@ -2072,7 +1842,7 @@ void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag) } /*! - \brief when receiving completed, set RS bit in ENET_DMA_STAT register will set + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will set \param[in] desc: the descriptor pointer which users want to configure \param[out] none \retval none @@ -2083,7 +1853,7 @@ void enet_desc_receive_complete_bit_enable(enet_descriptors_struct *desc) } /*! - \brief when receiving completed, set RS bit in ENET_DMA_STAT register will not set + \brief when receiving completed, set RS bit in ENET_DMA_STAT register will not set \param[in] desc: the descriptor pointer which users want to configure \param[out] none \retval none @@ -2102,36 +1872,36 @@ void enet_desc_receive_complete_bit_disable(enet_descriptors_struct *desc) void enet_rxframe_drop(void) { /* enable reception, descriptor is owned by DMA */ - dma_current_rxdesc->status = ENET_RDES0_DAV; - + dma_current_rxdesc->status = ENET_RDES0_DAV; + /* chained mode */ - if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ - if(NULL != dma_current_ptp_rxdesc){ - dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)) { + if(NULL != dma_current_ptp_rxdesc) { + dma_current_rxdesc = (enet_descriptors_struct *)(dma_current_ptp_rxdesc->buffer2_next_desc_addr); /* if it is the last ptp descriptor */ - if(0U != dma_current_ptp_rxdesc->status){ + if(0U != dma_current_ptp_rxdesc->status) { /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ - dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); - }else{ - /* ponter to the next ptp descriptor */ + dma_current_ptp_rxdesc = (enet_descriptors_struct *)(dma_current_ptp_rxdesc->status); + } else { + /* pointer to the next ptp descriptor */ dma_current_ptp_rxdesc++; } - }else{ - dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_rxdesc->buffer2_next_desc_addr); + } else { + dma_current_rxdesc = (enet_descriptors_struct *)(dma_current_rxdesc->buffer2_next_desc_addr); } - - }else{ - /* ring mode */ - if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + + } else { + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)) { /* if is the last descriptor in table, the next descriptor is the table header */ - dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); - if(NULL != dma_current_ptp_rxdesc){ - dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); + dma_current_rxdesc = (enet_descriptors_struct *)(ENET_DMA_RDTADDR); + if(NULL != dma_current_ptp_rxdesc) { + dma_current_ptp_rxdesc = (enet_descriptors_struct *)(dma_current_ptp_rxdesc->status); } - }else{ + } else { /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ - dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); - if(NULL != dma_current_ptp_rxdesc){ + dma_current_rxdesc = (enet_descriptors_struct *)(uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + if(NULL != dma_current_ptp_rxdesc) { dma_current_ptp_rxdesc++; } } @@ -2149,7 +1919,7 @@ void enet_rxframe_drop(void) */ void enet_dma_feature_enable(uint32_t feature) { - ENET_DMA_CTL |= feature; + ENET_DMA_CTL |= feature; } /*! @@ -2182,67 +1952,67 @@ void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, en uint32_t desc_status = 0U, desc_bufsize = 0U; enet_descriptors_struct *desc, *desc_tab; uint8_t *buf; - + /* if want to initialize DMA Tx descriptors */ - if (ENET_DMA_TX == direction){ + if(ENET_DMA_TX == direction) { /* save a copy of the DMA Tx descriptors */ desc_tab = txdesc_tab; buf = &tx_buff[0][0]; count = ENET_TXBUF_NUM; - maxsize = ENET_TXBUF_SIZE; - + maxsize = ENET_TXBUF_SIZE; + /* select chain mode, and enable transmit timestamp function */ desc_status = ENET_TDES0_TCHM | ENET_TDES0_TTSEN; - + /* configure DMA Tx descriptor table address register */ ENET_DMA_TDTADDR = (uint32_t)desc_tab; dma_current_txdesc = desc_tab; dma_current_ptp_txdesc = desc_ptptab; - }else{ + } else { /* if want to initialize DMA Rx descriptors */ /* save a copy of the DMA Rx descriptors */ desc_tab = rxdesc_tab; buf = &rx_buff[0][0]; count = ENET_RXBUF_NUM; - maxsize = ENET_RXBUF_SIZE; - + maxsize = ENET_RXBUF_SIZE; + /* enable receiving */ desc_status = ENET_RDES0_DAV; /* select receive chained mode and set buffer1 size */ desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE; - + /* configure DMA Rx descriptor table address register */ ENET_DMA_RDTADDR = (uint32_t)desc_tab; dma_current_rxdesc = desc_tab; - dma_current_ptp_rxdesc = desc_ptptab; + dma_current_ptp_rxdesc = desc_ptptab; } - - /* configure each descriptor */ - for(num = 0U; num < count; num++){ + + /* configure each descriptor */ + for(num = 0U; num < count; num++) { /* get the pointer to the next descriptor of the descriptor table */ desc = desc_tab + num; /* configure descriptors */ - desc->status = desc_status; + desc->status = desc_status; desc->control_buffer_size = desc_bufsize; desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); - + /* if is not the last descriptor */ - if(num < (count - 1U)){ + if(num < (count - 1U)) { /* configure the next descriptor address */ desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U); - }else{ - /* when it is the last descriptor, the next descriptor address - equals to first descriptor address in descriptor table */ - desc->buffer2_next_desc_addr = (uint32_t)desc_tab; + } else { + /* when it is the last descriptor, the next descriptor address + equals to first descriptor address in descriptor table */ + desc->buffer2_next_desc_addr = (uint32_t)desc_tab; } /* set desc_ptptab equal to desc_tab */ (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; - } - /* when it is the last ptp descriptor, preserve the first descriptor + } + /* when it is the last ptp descriptor, preserve the first descriptor address of desc_ptptab in ptp descriptor status */ - (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; + (&desc_ptptab[num - 1U])->status = (uint32_t)desc_ptptab; } /*! @@ -2265,57 +2035,57 @@ void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, ene /* configure descriptor skip length */ ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL; ENET_DMA_BCTL |= DMA_BCTL_DPSL(0); - + /* if want to initialize DMA Tx descriptors */ - if (ENET_DMA_TX == direction){ + if(ENET_DMA_TX == direction) { /* save a copy of the DMA Tx descriptors */ desc_tab = txdesc_tab; buf = &tx_buff[0][0]; count = ENET_TXBUF_NUM; - maxsize = ENET_TXBUF_SIZE; - + maxsize = ENET_TXBUF_SIZE; + /* select ring mode, and enable transmit timestamp function */ desc_status = ENET_TDES0_TTSEN; - + /* configure DMA Tx descriptor table address register */ ENET_DMA_TDTADDR = (uint32_t)desc_tab; dma_current_txdesc = desc_tab; dma_current_ptp_txdesc = desc_ptptab; - }else{ + } else { /* if want to initialize DMA Rx descriptors */ /* save a copy of the DMA Rx descriptors */ desc_tab = rxdesc_tab; buf = &rx_buff[0][0]; count = ENET_RXBUF_NUM; - maxsize = ENET_RXBUF_SIZE; - + maxsize = ENET_RXBUF_SIZE; + /* enable receiving */ desc_status = ENET_RDES0_DAV; /* select receive ring mode and set buffer1 size */ desc_bufsize = (uint32_t)ENET_RXBUF_SIZE; - + /* configure DMA Rx descriptor table address register */ ENET_DMA_RDTADDR = (uint32_t)desc_tab; dma_current_rxdesc = desc_tab; - dma_current_ptp_rxdesc = desc_ptptab; + dma_current_ptp_rxdesc = desc_ptptab; } - - /* configure each descriptor */ - for(num = 0U; num < count; num++){ + + /* configure each descriptor */ + for(num = 0U; num < count; num++) { /* get the pointer to the next descriptor of the descriptor table */ desc = desc_tab + num; /* configure descriptors */ - desc->status = desc_status; + desc->status = desc_status; desc->control_buffer_size = desc_bufsize; desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]); - + /* when it is the last descriptor */ - if(num == (count - 1U)){ - if (ENET_DMA_TX == direction){ - /* configure transmit end of ring mode */ + if(num == (count - 1U)) { + if(ENET_DMA_TX == direction) { + /* configure transmit end of ring mode */ desc->status |= ENET_TDES0_TERM; - }else{ + } else { /* configure receive end of ring mode */ desc->control_buffer_size |= ENET_RDES1_RERM; } @@ -2323,14 +2093,14 @@ void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, ene /* set desc_ptptab equal to desc_tab */ (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr; (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr; - } - /* when it is the last ptp descriptor, preserve the first descriptor + } + /* when it is the last ptp descriptor, preserve the first descriptor address of desc_ptptab in ptp descriptor status */ - (&desc_ptptab[num-1U])->status = (uint32_t)desc_ptptab; + (&desc_ptptab[num - 1U])->status = (uint32_t)desc_ptptab; } /*! - \brief receive a packet data with timestamp values to application buffer, when the DMA is in normal mode + \brief receive a packet data with timestamp values to application buffer, when the DMA is in normal mode \param[in] bufsize: the size of buffer which is the parameter in function \param[out] timestamp: pointer to the table which stores the timestamp high and low \param[out] buffer: pointer to the application buffer @@ -2340,33 +2110,33 @@ void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, ene ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[]) { uint32_t offset = 0U, size = 0U; - + /* the descriptor is busy due to own by the DMA */ - if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)){ + if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)) { return ERROR; } - + /* if buffer pointer is null, indicates that users has copied data in application */ - if(NULL != buffer){ + if(NULL != buffer) { /* if no error occurs, and the frame uses only one descriptor */ if(((uint32_t)RESET == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) && - ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && - ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))){ - + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) && + ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))) { + /* get the frame length except CRC */ size = GET_RDES0_FRML(dma_current_rxdesc->status) - 4U; - + /* to avoid situation that the frame size exceeds the buffer length */ - if(size > bufsize){ + if(size > bufsize) { return ERROR; } /* copy data from Rx buffer to application buffer */ - for(offset = 0U; offset < size; offset++){ + for(offset = 0U; offset < size; offset++) { (*(buffer + offset)) = (*(__IO uint8_t *)(uint32_t)((dma_current_ptp_rxdesc->buffer1_addr) + offset)); } - - }else{ + + } else { return ERROR; } } @@ -2376,42 +2146,42 @@ ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, u dma_current_rxdesc->buffer1_addr = dma_current_ptp_rxdesc ->buffer1_addr ; dma_current_rxdesc->buffer2_next_desc_addr = dma_current_ptp_rxdesc ->buffer2_next_desc_addr; - + /* enable reception, descriptor is owned by DMA */ dma_current_rxdesc->status = ENET_RDES0_DAV; - + /* check Rx buffer unavailable flag status */ - if ((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)){ + if((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)) { /* clear RBU flag */ ENET_DMA_STAT = ENET_DMA_STAT_RBU; /* resume DMA reception by writing to the RPEN register*/ ENET_DMA_RPEN = 0U; } - - /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */ + + /* update the current RxDMA descriptor pointer to the next descriptor in RxDMA descriptor table */ /* chained mode */ - if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)){ - dma_current_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->buffer2_next_desc_addr); + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)) { + dma_current_rxdesc = (enet_descriptors_struct *)(dma_current_ptp_rxdesc->buffer2_next_desc_addr); /* if it is the last ptp descriptor */ - if(0U != dma_current_ptp_rxdesc->status){ + if(0U != dma_current_ptp_rxdesc->status) { /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ - dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); - }else{ + dma_current_ptp_rxdesc = (enet_descriptors_struct *)(dma_current_ptp_rxdesc->status); + } else { /* ponter to the next ptp descriptor */ dma_current_ptp_rxdesc++; } - }else{ - /* ring mode */ - if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)){ + } else { + /* ring mode */ + if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)) { /* if is the last descriptor in table, the next descriptor is the table header */ - dma_current_rxdesc = (enet_descriptors_struct*) (ENET_DMA_RDTADDR); + dma_current_rxdesc = (enet_descriptors_struct *)(ENET_DMA_RDTADDR); /* RDES2 and RDES3 will not be covered by buffer address, so do not need to preserve a new table, use the same table with RxDMA descriptor */ - dma_current_ptp_rxdesc = (enet_descriptors_struct*) (dma_current_ptp_rxdesc->status); - }else{ + dma_current_ptp_rxdesc = (enet_descriptors_struct *)(dma_current_ptp_rxdesc->status); + } else { /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ - dma_current_rxdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_rxdesc = (enet_descriptors_struct *)(uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); dma_current_ptp_rxdesc ++; } } @@ -2420,7 +2190,7 @@ ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, u } /*! - \brief send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode + \brief send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode \param[in] buffer: pointer on the application buffer note -- if the input is NULL, user should copy data in application by himself \param[in] length: the length of frame data to be transmitted @@ -2431,23 +2201,23 @@ ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, u ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[]) { uint32_t offset = 0U, timeout = 0U; - uint32_t dma_tbu_flag, dma_tu_flag, tdes0_ttmss_flag; - + uint32_t dma_tbu_flag, dma_tu_flag, tdes0_ttmss_flag; + /* the descriptor is busy due to own by the DMA */ - if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)) { return ERROR; } /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */ - if(length > ENET_MAX_FRAME_SIZE){ + if(length > ENET_MAX_FRAME_SIZE) { return ERROR; } - + /* if buffer pointer is null, indicates that users has handled data in application */ - if(NULL != buffer){ + if(NULL != buffer) { /* copy frame data from application buffer to Tx buffer */ - for(offset = 0U; offset < length; offset++){ - (*(__IO uint8_t *) (uint32_t)((dma_current_ptp_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); + for(offset = 0U; offset < length; offset++) { + (*(__IO uint8_t *)(uint32_t)((dma_current_ptp_txdesc->buffer1_addr) + offset)) = (*(buffer + offset)); } } /* set the frame length */ @@ -2456,31 +2226,31 @@ ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, u dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; /* enable the DMA transmission */ dma_current_txdesc->status |= ENET_TDES0_DAV; - + /* check Tx buffer unavailable flag status */ - dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); - - if((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)){ + + if((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)) { /* clear TBU and TU flag */ ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); /* resume DMA transmission by writing to the TPEN register*/ ENET_DMA_TPEN = 0U; } - + /* if timestamp pointer is null, indicates that users don't care timestamp in application */ - if(NULL != timestamp){ + if(NULL != timestamp) { /* wait for ENET_TDES0_TTMSS flag to be set, a timestamp was captured */ - do{ + do { tdes0_ttmss_flag = (dma_current_txdesc->status & ENET_TDES0_TTMSS); timeout++; - }while((RESET == tdes0_ttmss_flag) && (timeout < ENET_DELAY_TO)); - + } while((RESET == tdes0_ttmss_flag) && (timeout < ENET_DELAY_TO)); + /* return ERROR due to timeout */ - if(ENET_DELAY_TO == timeout){ + if(ENET_DELAY_TO == timeout) { return ERROR; - } - + } + /* clear the ENET_TDES0_TTMSS flag */ dma_current_txdesc->status &= ~ENET_TDES0_TTMSS; /* get the timestamp value of the transmit frame */ @@ -2490,37 +2260,37 @@ ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, u dma_current_txdesc->buffer1_addr = dma_current_ptp_txdesc ->buffer1_addr ; dma_current_txdesc->buffer2_next_desc_addr = dma_current_ptp_txdesc ->buffer2_next_desc_addr; - /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table */ + /* update the current TxDMA descriptor pointer to the next descriptor in TxDMA descriptor table */ /* chained mode */ - if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)){ - dma_current_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->buffer2_next_desc_addr); + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)) { + dma_current_txdesc = (enet_descriptors_struct *)(dma_current_ptp_txdesc->buffer2_next_desc_addr); /* if it is the last ptp descriptor */ - if(0U != dma_current_ptp_txdesc->status){ + if(0U != dma_current_ptp_txdesc->status) { /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ - dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); - }else{ - /* ponter to the next ptp descriptor */ + dma_current_ptp_txdesc = (enet_descriptors_struct *)(dma_current_ptp_txdesc->status); + } else { + /* pointer to the next ptp descriptor */ dma_current_ptp_txdesc++; } - }else{ - /* ring mode */ - if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)){ + } else { + /* ring mode */ + if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)) { /* if is the last descriptor in table, the next descriptor is the table header */ - dma_current_txdesc = (enet_descriptors_struct*) (ENET_DMA_TDTADDR); + dma_current_txdesc = (enet_descriptors_struct *)(ENET_DMA_TDTADDR); /* TDES2 and TDES3 will not be covered by buffer address, so do not need to preserve a new table, use the same table with TxDMA descriptor */ - dma_current_ptp_txdesc = (enet_descriptors_struct*) (dma_current_ptp_txdesc->status); - }else{ + dma_current_ptp_txdesc = (enet_descriptors_struct *)(dma_current_ptp_txdesc->status); + } else { /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */ - dma_current_txdesc = (enet_descriptors_struct*) (uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); - dma_current_ptp_txdesc ++; + dma_current_txdesc = (enet_descriptors_struct *)(uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)); + dma_current_ptp_txdesc ++; } } return SUCCESS; } /*! - \brief wakeup frame filter register pointer reset + \brief wakeup frame filter register pointer reset \param[in] none \param[out] none \retval none @@ -2531,7 +2301,7 @@ void enet_wum_filter_register_pointer_reset(void) } /*! - \brief set the remote wakeup frame registers + \brief set the remote wakeup frame registers \param[in] pdata: pointer to buffer data which is written to remote wakeup frame registers (8 words total) \param[out] none \retval none @@ -2539,15 +2309,15 @@ void enet_wum_filter_register_pointer_reset(void) void enet_wum_filter_config(uint32_t pdata[]) { uint32_t num = 0U; - + /* configure ENET_MAC_RWFF register */ - for(num = 0U; num < ETH_WAKEUP_REGISTER_LENGTH; num++){ + for(num = 0U; num < ETH_WAKEUP_REGISTER_LENGTH; num++) { ENET_MAC_RWFF = pdata[num]; } } /*! - \brief enable wakeup management features + \brief enable wakeup management features \param[in] feature: one or more parameters can be selected which are shown as below \arg ENET_WUM_POWER_DOWN: power down mode \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception @@ -2562,7 +2332,7 @@ void enet_wum_feature_enable(uint32_t feature) } /*! - \brief disable wakeup management features + \brief disable wakeup management features \param[in] feature: one or more parameters can be selected which are shown as below \arg ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception \arg ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception @@ -2576,8 +2346,8 @@ void enet_wum_feature_disable(uint32_t feature) } /*! - \brief reset the MAC statistics counters - \param[in] none + \brief reset the MAC statistics counters + \param[in] none \param[out] none \retval none */ @@ -2603,7 +2373,7 @@ void enet_msc_feature_enable(uint32_t feature) /*! \brief disable the MAC statistics counter features - \param[in] feature: one or more parameters can be selected which are shown as below + \param[in] feature: one or more parameters can be selected which are shown as below \arg ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover \arg ENET_MSC_RESET_ON_READ: reset on read \arg ENET_MSC_COUNTERS_FREEZE: MSC counter freeze @@ -2612,11 +2382,11 @@ void enet_msc_feature_enable(uint32_t feature) */ void enet_msc_feature_disable(uint32_t feature) { - ENET_MSC_CTL &= (~feature); + ENET_MSC_CTL &= (~feature); } /*! - \brief get MAC statistics counter + \brief get MAC statistics counter \param[in] counter: MSC counters which is selected, refer to enet_msc_counter_enum, only one parameter can be selected which is shown as below \arg ENET_MSC_TX_SCCNT: MSC transmitted good frames after a single collision counter @@ -2631,14 +2401,14 @@ void enet_msc_feature_disable(uint32_t feature) uint32_t enet_msc_counters_get(enet_msc_counter_enum counter) { uint32_t reval; - + reval = REG32((ENET + (uint32_t)counter)); - + return reval; } /*! - \brief change subsecond to nanosecond + \brief change subsecond to nanosecond \param[in] subsecond: subsecond value \param[out] none \retval the nanosecond value @@ -2646,12 +2416,12 @@ uint32_t enet_msc_counters_get(enet_msc_counter_enum counter) uint32_t enet_ptp_subsecond_2_nanosecond(uint32_t subsecond) { uint64_t val = subsecond * 1000000000Ull; - val >>= 31; + val >>= 31U; return (uint32_t)val; } /*! - \brief change nanosecond to subsecond + \brief change nanosecond to subsecond \param[in] nanosecond: nanosecond value \param[out] none \retval the subsecond value @@ -2709,54 +2479,54 @@ ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func) uint32_t timeout = 0U; ErrStatus enet_state = SUCCESS; - switch(func){ - case ENET_PTP_ADDEND_UPDATE: + switch(func) { + case ENET_PTP_ADDEND_UPDATE: /* this bit must be read as zero before application set it */ - do{ - temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSARU; + do { + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSARU; timeout++; - }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + } while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); /* return ERROR due to timeout */ - if(ENET_DELAY_TO == timeout){ + if(ENET_DELAY_TO == timeout) { enet_state = ERROR; - }else{ + } else { ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSARU; - } + } break; case ENET_PTP_SYSTIME_UPDATE: /* both the TMSSTU and TMSSTI bits must be read as zero before application set this bit */ - do{ - temp_state = ENET_PTP_TSCTL & (ENET_PTP_TSCTL_TMSSTU | ENET_PTP_TSCTL_TMSSTI); + do { + temp_state = ENET_PTP_TSCTL & (ENET_PTP_TSCTL_TMSSTU | ENET_PTP_TSCTL_TMSSTI); timeout++; - }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + } while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); /* return ERROR due to timeout */ - if(ENET_DELAY_TO == timeout){ + if(ENET_DELAY_TO == timeout) { enet_state = ERROR; - }else{ + } else { ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTU; - } - break; + } + break; case ENET_PTP_SYSTIME_INIT: /* this bit must be read as zero before application set it */ - do{ - temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSSTI; + do { + temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSSTI; timeout++; - }while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); + } while((RESET != temp_state) && (timeout < ENET_DELAY_TO)); /* return ERROR due to timeout */ - if(ENET_DELAY_TO == timeout){ + if(ENET_DELAY_TO == timeout) { enet_state = ERROR; - }else{ + } else { ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTI; - } - break; + } + break; default: - temp_config = (uint32_t)func & (~BIT(31)); - if(RESET != ((uint32_t)func & BIT(31))){ - ENET_PTP_TSCTL |= temp_config; - }else{ - ENET_PTP_TSCTL &= ~temp_config; + temp_config = (uint32_t)func & (~BIT(31)); + if(RESET != ((uint32_t)func & BIT(31))) { + ENET_PTP_TSCTL |= temp_config; + } else { + ENET_PTP_TSCTL &= ~temp_config; } - break; + break; } return enet_state; @@ -2764,7 +2534,7 @@ ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func) /*! \brief configure system time subsecond increment value - \param[in] subsecond: the value will be added to the subsecond value of system time, + \param[in] subsecond: the value will be added to the subsecond value of system time, this value must be between 0 and 0xFF \param[out] none \retval none @@ -2792,7 +2562,7 @@ void enet_ptp_timestamp_addend_config(uint32_t add) \arg ENET_PTP_ADD_TO_TIME: timestamp update value is added to system time \arg ENET_PTP_SUBSTRACT_FROM_TIME: timestamp update value is subtracted from system time \param[in] second: initializing or adding/subtracting to second of the system time - \param[in] subsecond: the current subsecond of the system time + \param[in] subsecond: the current subsecond of the system time with 0.46 ns accuracy if required accuracy is 20 ns \param[out] none \retval none @@ -2800,7 +2570,7 @@ void enet_ptp_timestamp_addend_config(uint32_t add) void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond) { ENET_PTP_TSUH = second; - ENET_PTP_TSUL = sign | PTP_TSUL_TMSUSS(subsecond); + ENET_PTP_TSUL = sign | PTP_TSUL_TMSUSS(subsecond); } /*! @@ -2819,7 +2589,7 @@ void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond) /*! \brief get the current system time \param[in] none - \param[out] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + \param[out] systime_struct: pointer to a enet_ptp_systime_struct structure which contains parameters of PTP system time members of the structure and the member values are shown as below: second: 0x0 - 0xFFFF FFFF @@ -2831,11 +2601,11 @@ void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct) { uint32_t temp_sec = 0U, temp_subs = 0U; - /* get the value of sysytem time registers */ - temp_sec = (uint32_t)ENET_PTP_TSH; + /* get the value of system time registers */ + temp_sec = (uint32_t)ENET_PTP_TSH; temp_subs = (uint32_t)ENET_PTP_TSL; - - /* get sysytem time and construct the enet_ptp_systime_struct structure */ + + /* get system time and construct the enet_ptp_systime_struct structure */ systime_struct->second = temp_sec; systime_struct->nanosecond = GET_PTP_TSL_STMSS(temp_subs); systime_struct->nanosecond = enet_ptp_subsecond_2_nanosecond(systime_struct->nanosecond); @@ -2865,12 +2635,12 @@ void enet_ptp_start(int32_t updatemethod, uint32_t init_sec, uint32_t init_subse /* configure system time subsecond increment based on the PTP clock frequency */ enet_ptp_subsecond_increment_config(accuracy_cfg); - if(ENET_PTP_FINEMODE == updatemethod){ + if(ENET_PTP_FINEMODE == updatemethod) { /* fine correction method: configure the timestamp addend, then update */ enet_ptp_timestamp_addend_config(carry_cfg); enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); /* wait until update is completed */ - while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_ADDEND_UPDATE)){ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_ADDEND_UPDATE)) { } } @@ -2897,7 +2667,7 @@ void enet_ptp_finecorrection_adjfreq(int32_t carry_cfg) /*! \brief update system time in coarse method - \param[in] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + \param[in] systime_struct: pointer to a enet_ptp_systime_struct structure which contains parameters of PTP system time members of the structure and the member values are shown as below: second: 0x0 - 0xFFFF FFFF @@ -2912,7 +2682,7 @@ void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_s uint32_t carry_cfg; subsecond_val = enet_ptp_nanosecond_2_subsecond(systime_struct->nanosecond); - + /* save the carry_cfg value */ carry_cfg = ENET_PTP_TSADDEND_TMSA; @@ -2921,9 +2691,9 @@ void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_s enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_UPDATE); /* wait until the update is completed */ - while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_UPDATE)){ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_UPDATE)) { } - + /* write back the carry_cfg value, then update */ enet_ptp_timestamp_addend_config(carry_cfg); enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); @@ -2931,7 +2701,7 @@ void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_s /*! \brief set system time in fine method - \param[in] systime_struct: pointer to a enet_ptp_systime_struct structure which contains + \param[in] systime_struct: pointer to a enet_ptp_systime_struct structure which contains parameters of PTP system time members of the structure and the member values are shown as below: second: 0x0 - 0xFFFF FFFF @@ -2940,7 +2710,7 @@ void enet_ptp_coarsecorrection_systime_update(enet_ptp_systime_struct *systime_s \param[out] none \retval none */ -void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct) +void enet_ptp_finecorrection_settime(enet_ptp_systime_struct *systime_struct) { uint32_t subsecond_val; @@ -2949,15 +2719,15 @@ void enet_ptp_finecorrection_settime(enet_ptp_systime_struct * systime_struct) /* initialize the system time */ enet_ptp_timestamp_update_config(systime_struct->sign, systime_struct->second, subsecond_val); enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT); - + /* wait until the system time initialzation finished */ - while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_INIT)){ + while(SET == enet_ptp_flag_get((uint32_t)ENET_PTP_SYSTIME_INIT)) { } } /*! \brief get the ptp flag status - \param[in] flag: ptp flag status to be checked + \param[in] flag: ptp flag status to be checked \arg ENET_PTP_ADDEND_UPDATE: addend register update \arg ENET_PTP_SYSTIME_UPDATE: timestamp update \arg ENET_PTP_SYSTIME_INIT: timestamp initialize @@ -2968,10 +2738,10 @@ FlagStatus enet_ptp_flag_get(uint32_t flag) { FlagStatus bitstatus = RESET; - if ((uint32_t)RESET != (ENET_PTP_TSCTL & flag)){ + if((uint32_t)RESET != (ENET_PTP_TSCTL & flag)) { bitstatus = SET; } - + return bitstatus; } @@ -2989,7 +2759,7 @@ void enet_initpara_reset(void) enet_initpara.dma_maxburst = 0U; enet_initpara.dma_arbitration = 0U; enet_initpara.store_forward_mode = 0U; - enet_initpara.dma_function = 0U; + enet_initpara.dma_function = 0U; enet_initpara.vlan_config = 0U; enet_initpara.flow_control = 0U; enet_initpara.hashtable_high = 0U; @@ -2998,10 +2768,10 @@ void enet_initpara_reset(void) enet_initpara.halfduplex_param = 0U; enet_initpara.timer_config = 0U; enet_initpara.interframegap = 0U; -} +} /*! - \brief initialize ENET peripheral with generally concerned parameters, call it by enet_init() + \brief initialize ENET peripheral with generally concerned parameters, call it by enet_init() \param[in] none \param[out] none \retval none @@ -3015,56 +2785,53 @@ static void enet_default_init(void) reg_value = ENET_MAC_CFG; reg_value &= MAC_CFG_MASK; reg_value |= ENET_WATCHDOG_ENABLE | ENET_JABBER_ENABLE | ENET_INTERFRAMEGAP_96BIT \ - | ENET_SPEEDMODE_10M |ENET_MODE_HALFDUPLEX | ENET_LOOPBACKMODE_DISABLE \ - | ENET_CARRIERSENSE_ENABLE | ENET_RECEIVEOWN_ENABLE \ - | ENET_RETRYTRANSMISSION_ENABLE | ENET_BACKOFFLIMIT_10 \ - | ENET_DEFERRALCHECK_DISABLE \ - | ENET_AUTO_PADCRC_DROP_DISABLE \ - | ENET_CHECKSUMOFFLOAD_DISABLE; + | ENET_SPEEDMODE_10M | ENET_MODE_HALFDUPLEX | ENET_LOOPBACKMODE_DISABLE \ + | ENET_CARRIERSENSE_ENABLE | ENET_RECEIVEOWN_ENABLE \ + | ENET_RETRYTRANSMISSION_ENABLE | ENET_BACKOFFLIMIT_10 \ + | ENET_DEFERRALCHECK_DISABLE \ + | ENET_AUTO_PADCRC_DROP_DISABLE \ + | ENET_CHECKSUMOFFLOAD_DISABLE; ENET_MAC_CFG = reg_value; - + /* configure ENET_MAC_FRMF register */ - ENET_MAC_FRMF = ENET_SRC_FILTER_DISABLE |ENET_DEST_FILTER_INVERSE_DISABLE \ - |ENET_MULTICAST_FILTER_PERFECT |ENET_UNICAST_FILTER_PERFECT \ - |ENET_PCFRM_PREVENT_ALL |ENET_BROADCASTFRAMES_ENABLE \ - |ENET_PROMISCUOUS_DISABLE |ENET_RX_FILTER_ENABLE; + ENET_MAC_FRMF = ENET_SRC_FILTER_DISABLE | ENET_DEST_FILTER_INVERSE_DISABLE \ + | ENET_MULTICAST_FILTER_PERFECT | ENET_UNICAST_FILTER_PERFECT \ + | ENET_PCFRM_PREVENT_ALL | ENET_BROADCASTFRAMES_ENABLE \ + | ENET_PROMISCUOUS_DISABLE | ENET_RX_FILTER_ENABLE; /* configure ENET_MAC_HLH, ENET_MAC_HLL register */ ENET_MAC_HLH = 0x0U; - + ENET_MAC_HLL = 0x0U; /* configure ENET_MAC_FCTL, ENET_MAC_FCTH register */ reg_value = ENET_MAC_FCTL; reg_value &= MAC_FCTL_MASK; - reg_value |= MAC_FCTL_PTM(0) |ENET_ZERO_QUANTA_PAUSE_DISABLE \ - |ENET_PAUSETIME_MINUS4 |ENET_UNIQUE_PAUSEDETECT \ - |ENET_RX_FLOWCONTROL_DISABLE |ENET_TX_FLOWCONTROL_DISABLE; - ENET_MAC_FCTL = reg_value; - - ENET_MAC_FCTH = ENET_DEACTIVE_THRESHOLD_512BYTES |ENET_ACTIVE_THRESHOLD_1536BYTES; - + reg_value |= MAC_FCTL_PTM(0) | ENET_ZERO_QUANTA_PAUSE_DISABLE \ + | ENET_PAUSETIME_MINUS4 | ENET_UNIQUE_PAUSEDETECT \ + | ENET_RX_FLOWCONTROL_DISABLE | ENET_TX_FLOWCONTROL_DISABLE; + ENET_MAC_FCTL = reg_value; + /* configure ENET_MAC_VLT register */ - ENET_MAC_VLT = ENET_VLANTAGCOMPARISON_16BIT |MAC_VLT_VLTI(0); - + ENET_MAC_VLT = ENET_VLANTAGCOMPARISON_16BIT | MAC_VLT_VLTI(0); + /* DMA */ /* configure ENET_DMA_CTL register */ reg_value = ENET_DMA_CTL; reg_value &= DMA_CTL_MASK; - reg_value |= ENET_TCPIP_CKSUMERROR_DROP |ENET_RX_MODE_STOREFORWARD \ - |ENET_FLUSH_RXFRAME_ENABLE |ENET_TX_MODE_STOREFORWARD \ - |ENET_TX_THRESHOLD_64BYTES |ENET_RX_THRESHOLD_64BYTES \ - |ENET_FORWARD_ERRFRAMES_DISABLE |ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE \ - |ENET_SECONDFRAME_OPT_DISABLE; - ENET_DMA_CTL = reg_value; + reg_value |= ENET_TCPIP_CKSUMERROR_DROP | ENET_RX_MODE_STOREFORWARD \ + | ENET_FLUSH_RXFRAME_ENABLE | ENET_TX_MODE_STOREFORWARD \ + | ENET_TX_THRESHOLD_64BYTES | ENET_RX_THRESHOLD_64BYTES \ + | ENET_SECONDFRAME_OPT_DISABLE; + ENET_DMA_CTL = reg_value; /* configure ENET_DMA_BCTL register */ reg_value = ENET_DMA_BCTL; reg_value &= DMA_BCTL_MASK; - reg_value = ENET_ADDRESS_ALIGN_ENABLE |ENET_ARBITRATION_RXTX_2_1 \ - |ENET_RXDP_32BEAT |ENET_PGBL_32BEAT |ENET_RXTX_DIFFERENT_PGBL \ - |ENET_FIXED_BURST_ENABLE; - ENET_DMA_BCTL = reg_value; + reg_value = ENET_ADDRESS_ALIGN_ENABLE | ENET_ARBITRATION_RXTX_2_1 \ + | ENET_RXDP_32BEAT | ENET_PGBL_32BEAT | ENET_RXTX_DIFFERENT_PGBL \ + | ENET_FIXED_BURST_ENABLE; + ENET_DMA_BCTL = reg_value; } #ifndef USE_DELAY @@ -3076,11 +2843,247 @@ static void enet_default_init(void) */ static void enet_delay(uint32_t ncount) { - __IO uint32_t delay_time = 0U; - - for(delay_time = ncount; delay_time != 0U; delay_time--){ + __IO uint32_t delay_time = 0U; + + for(delay_time = ncount; delay_time != 0U; delay_time--) { } } #endif /* USE_DELAY */ +/*! + \brief get the ENET MAC/MSC/PTP/DMA status flag + \param[in] enet_flag: ENET status flag, refer to enet_flag_enum, + only one parameter can be selected which is shown as below + \arg ENET_MAC_FLAG_MPKR: magic packet received flag + \arg ENET_MAC_FLAG_WUFR: wakeup frame received flag + \arg ENET_MAC_FLAG_FLOWCONTROL: flow control status flag + \arg ENET_MAC_FLAG_WUM: WUM status flag + \arg ENET_MAC_FLAG_MSC: MSC status flag + \arg ENET_MAC_FLAG_MSCR: MSC receive status flag + \arg ENET_MAC_FLAG_MSCT: MSC transmit status flag + \arg ENET_MAC_FLAG_TMST: time stamp trigger status flag + \arg ENET_PTP_FLAG_TSSCO: timestamp second counter overflow flag + \arg ENET_PTP_FLAG_TTM: target time match flag + \arg ENET_MSC_FLAG_RFCE: received frames CRC error flag + \arg ENET_MSC_FLAG_RFAE: received frames alignment error flag + \arg ENET_MSC_FLAG_RGUF: received good unicast frames flag + \arg ENET_MSC_FLAG_TGFSC: transmitted good frames single collision flag + \arg ENET_MSC_FLAG_TGFMSC: transmitted good frames more single collision flag + \arg ENET_MSC_FLAG_TGF: transmitted good frames flag + \arg ENET_DMA_FLAG_TS: transmit status flag + \arg ENET_DMA_FLAG_TPS: transmit process stopped status flag + \arg ENET_DMA_FLAG_TBU: transmit buffer unavailable status flag + \arg ENET_DMA_FLAG_TJT: transmit jabber timeout status flag + \arg ENET_DMA_FLAG_RO: receive overflow status flag + \arg ENET_DMA_FLAG_TU: transmit underflow status flag + \arg ENET_DMA_FLAG_RS: receive status flag + \arg ENET_DMA_FLAG_RBU: receive buffer unavailable status flag + \arg ENET_DMA_FLAG_RPS: receive process stopped status flag + \arg ENET_DMA_FLAG_RWT: receive watchdog timeout status flag + \arg ENET_DMA_FLAG_ET: early transmit status flag + \arg ENET_DMA_FLAG_FBE: fatal bus error status flag + \arg ENET_DMA_FLAG_ER: early receive status flag + \arg ENET_DMA_FLAG_AI: abnormal interrupt summary flag + \arg ENET_DMA_FLAG_NI: normal interrupt summary flag + \arg ENET_DMA_FLAG_EB_DMA_ERROR: DMA error flag + \arg ENET_DMA_FLAG_EB_TRANSFER_ERROR: transfer error flag + \arg ENET_DMA_FLAG_EB_ACCESS_ERROR: access error flag + \arg ENET_DMA_FLAG_MSC: MSC status flag + \arg ENET_DMA_FLAG_WUM: WUM status flag + \arg ENET_DMA_FLAG_TST: timestamp trigger status flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_flag_get(enet_flag_enum enet_flag) +{ + if(RESET != (ENET_REG_VAL(enet_flag) & BIT(ENET_BIT_POS(enet_flag)))) { + return SET; + } else { + return RESET; + } +} + +/*! + \brief clear the ENET DMA status flag + \param[in] enet_flag: ENET DMA flag clear, refer to enet_flag_clear_enum + only one parameter can be selected which is shown as below + \arg ENET_DMA_FLAG_TS_CLR: transmit status flag clear + \arg ENET_DMA_FLAG_TPS_CLR: transmit process stopped status flag clear + \arg ENET_DMA_FLAG_TBU_CLR: transmit buffer unavailable status flag clear + \arg ENET_DMA_FLAG_TJT_CLR: transmit jabber timeout status flag clear + \arg ENET_DMA_FLAG_RO_CLR: receive overflow status flag clear + \arg ENET_DMA_FLAG_TU_CLR: transmit underflow status flag clear + \arg ENET_DMA_FLAG_RS_CLR: receive status flag clear + \arg ENET_DMA_FLAG_RBU_CLR: receive buffer unavailable status flag clear + \arg ENET_DMA_FLAG_RPS_CLR: receive process stopped status flag clear + \arg ENET_DMA_FLAG_RWT_CLR: receive watchdog timeout status flag clear + \arg ENET_DMA_FLAG_ET_CLR: early transmit status flag clear + \arg ENET_DMA_FLAG_FBE_CLR: fatal bus error status flag clear + \arg ENET_DMA_FLAG_ER_CLR: early receive status flag clear + \arg ENET_DMA_FLAG_AI_CLR: abnormal interrupt summary flag clear + \arg ENET_DMA_FLAG_NI_CLR: normal interrupt summary flag clear + \param[out] none + \retval none +*/ +void enet_flag_clear(enet_flag_clear_enum enet_flag) +{ + /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ + ENET_REG_VAL(enet_flag) = BIT(ENET_BIT_POS(enet_flag)); +} + +/*! + \brief enable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_WUMIM: WUM interrupt mask + \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask + \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask + \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask + \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask + \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask + \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask + \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask + \arg ENET_DMA_INT_TIE: transmit interrupt enable + \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable + \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable + \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable + \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable + \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable + \arg ENET_DMA_INT_RIE: receive interrupt enable + \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable + \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable + \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable + \arg ENET_DMA_INT_ETIE: early transmit interrupt enable + \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable + \arg ENET_DMA_INT_ERIE: early receive interrupt enable + \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable + \arg ENET_DMA_INT_NIE: normal interrupt summary enable + \param[out] none + \retval none +*/ +void enet_interrupt_enable(enet_int_enum enet_int) +{ + if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6U)) { + /* ENET_DMA_INTEN register interrupt */ + ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); + } else { + /* other INTMSK register interrupt */ + ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); + } +} + +/*! + \brief disable ENET MAC/MSC/DMA interrupt + \param[in] enet_int: ENET interrupt, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_WUMIM: WUM interrupt mask + \arg ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask + \arg ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask + \arg ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask + \arg ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask + \arg ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask + \arg ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask + \arg ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask + \arg ENET_DMA_INT_TIE: transmit interrupt enable + \arg ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable + \arg ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable + \arg ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable + \arg ENET_DMA_INT_ROIE: receive overflow interrupt enable + \arg ENET_DMA_INT_TUIE: transmit underflow interrupt enable + \arg ENET_DMA_INT_RIE: receive interrupt enable + \arg ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable + \arg ENET_DMA_INT_RPSIE: receive process stopped interrupt enable + \arg ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable + \arg ENET_DMA_INT_ETIE: early transmit interrupt enable + \arg ENET_DMA_INT_FBEIE: fatal bus error interrupt enable + \arg ENET_DMA_INT_ERIE: early receive interrupt enable + \arg ENET_DMA_INT_AIE: abnormal interrupt summary enable + \arg ENET_DMA_INT_NIE: normal interrupt summary enable + \param[out] none + \retval none +*/ +void enet_interrupt_disable(enet_int_enum enet_int) +{ + if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6U)) { + /* ENET_DMA_INTEN register interrupt */ + ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int)); + } else { + /* other INTMSK register interrupt */ + ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int)); + } +} + +/*! + \brief get ENET MAC/MSC/DMA interrupt flag + \param[in] int_flag: ENET interrupt flag, + only one parameter can be selected which is shown as below + \arg ENET_MAC_INT_FLAG_WUM: WUM status flag + \arg ENET_MAC_INT_FLAG_MSC: MSC status flag + \arg ENET_MAC_INT_FLAG_MSCR: MSC receive status flag + \arg ENET_MAC_INT_FLAG_MSCT: MSC transmit status flag + \arg ENET_MAC_INT_FLAG_TMST: time stamp trigger status flag + \arg ENET_MSC_INT_FLAG_RFCE: received frames CRC error flag + \arg ENET_MSC_INT_FLAG_RFAE: received frames alignment error flag + \arg ENET_MSC_INT_FLAG_RGUF: received good unicast frames flag + \arg ENET_MSC_INT_FLAG_TGFSC: transmitted good frames single collision flag + \arg ENET_MSC_INT_FLAG_TGFMSC: transmitted good frames more single collision flag + \arg ENET_MSC_INT_FLAG_TGF: transmitted good frames flag + \arg ENET_DMA_INT_FLAG_TS: transmit status flag + \arg ENET_DMA_INT_FLAG_TPS: transmit process stopped status flag + \arg ENET_DMA_INT_FLAG_TBU: transmit buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_TJT: transmit jabber timeout status flag + \arg ENET_DMA_INT_FLAG_RO: receive overflow status flag + \arg ENET_DMA_INT_FLAG_TU: transmit underflow status flag + \arg ENET_DMA_INT_FLAG_RS: receive status flag + \arg ENET_DMA_INT_FLAG_RBU: receive buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_RPS: receive process stopped status flag + \arg ENET_DMA_INT_FLAG_RWT: receive watchdog timeout status flag + \arg ENET_DMA_INT_FLAG_ET: early transmit status flag + \arg ENET_DMA_INT_FLAG_FBE: fatal bus error status flag + \arg ENET_DMA_INT_FLAG_ER: early receive status flag + \arg ENET_DMA_INT_FLAG_AI: abnormal interrupt summary flag + \arg ENET_DMA_INT_FLAG_NI: normal interrupt summary flag + \arg ENET_DMA_INT_FLAG_MSC: MSC status flag + \arg ENET_DMA_INT_FLAG_WUM: WUM status flag + \arg ENET_DMA_INT_FLAG_TST: timestamp trigger status flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag) +{ + if(RESET != (ENET_REG_VAL(int_flag) & BIT(ENET_BIT_POS(int_flag)))) { + return SET; + } else { + return RESET; + } +} + +/*! + \brief clear ENET DMA interrupt flag + \param[in] int_flag_clear: clear ENET interrupt flag, + only one parameter can be selected which is shown as below + \arg ENET_DMA_INT_FLAG_TS_CLR: transmit status flag + \arg ENET_DMA_INT_FLAG_TPS_CLR: transmit process stopped status flag + \arg ENET_DMA_INT_FLAG_TBU_CLR: transmit buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_TJT_CLR: transmit jabber timeout status flag + \arg ENET_DMA_INT_FLAG_RO_CLR: receive overflow status flag + \arg ENET_DMA_INT_FLAG_TU_CLR: transmit underflow status flag + \arg ENET_DMA_INT_FLAG_RS_CLR: receive status flag + \arg ENET_DMA_INT_FLAG_RBU_CLR: receive buffer unavailable status flag + \arg ENET_DMA_INT_FLAG_RPS_CLR: receive process stopped status flag + \arg ENET_DMA_INT_FLAG_RWT_CLR: receive watchdog timeout status flag + \arg ENET_DMA_INT_FLAG_ET_CLR: early transmit status flag + \arg ENET_DMA_INT_FLAG_FBE_CLR: fatal bus error status flag + \arg ENET_DMA_INT_FLAG_ER_CLR: early receive status flag + \arg ENET_DMA_INT_FLAG_AI_CLR: abnormal interrupt summary flag + \arg ENET_DMA_INT_FLAG_NI_CLR: normal interrupt summary flag + \param[out] none + \retval none +*/ +void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear) +{ + /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */ + ENET_REG_VAL(int_flag_clear) = BIT(ENET_BIT_POS(int_flag_clear)); +} + #endif /* GD32F20X_CL */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_exmc.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_exmc.c index ce34be58..7634a973 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_exmc.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_exmc.c @@ -2,36 +2,33 @@ \file gd32f20x_exmc.c \brief EXMC driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -127,6 +124,7 @@ OF SUCH DAMAGE. /*! \brief deinitialize EXMC NOR/SRAM region \param[in] exmc_norsram_region: select the region of bank0 + only one parameter can be selected which is shown as below: \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) \param[out] none \retval none @@ -140,14 +138,14 @@ void exmc_norsram_deinit(uint32_t exmc_norsram_region) } /*! - \brief initialize the struct exmc_norsram_parameter_struct + \brief initialize exmc_norsram_parameter_struct with the default values \param[in] none \param[out] exmc_norsram_init_struct: the initialized struct exmc_norsram_parameter_struct pointer \retval none */ -void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) +void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct *exmc_norsram_init_struct) { - /* configure the structure with default value */ + /* configure the structure with default values */ exmc_norsram_init_struct->norsram_region = EXMC_BANK0_NORSRAM_REGION0; exmc_norsram_init_struct->address_data_mux = ENABLE; exmc_norsram_init_struct->memory_type = EXMC_MEMORY_TYPE_SRAM; @@ -162,7 +160,7 @@ void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_i exmc_norsram_init_struct->asyn_wait = DISABLE; exmc_norsram_init_struct->write_mode = EXMC_ASYN_WRITE; - /* read/write timing configure */ + /* configure read/write timing */ exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime = 0xFU; exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime = 0xFU; exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime = 0xFFU; @@ -171,7 +169,7 @@ void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_i exmc_norsram_init_struct->read_write_timing->syn_data_latency = EXMC_DATALAT_17_CLK; exmc_norsram_init_struct->read_write_timing->asyn_access_mode = EXMC_ACCESS_MODE_A; - /* write timing configure, when extended mode is used */ + /* configure write timing, when extended mode is used */ exmc_norsram_init_struct->write_timing->asyn_address_setuptime = 0xFU; exmc_norsram_init_struct->write_timing->asyn_address_holdtime = 0xFU; exmc_norsram_init_struct->write_timing->asyn_data_setuptime = 0xFFU; @@ -184,7 +182,7 @@ void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_i \param[in] exmc_norsram_parameter_struct: configure the EXMC NOR/SRAM parameter norsram_region: EXMC_BANK0_NORSRAM_REGIONx,x=0..3 write_mode: EXMC_ASYN_WRITE or EXMC_SYN_WRITE - extended_mode: ENABLE or DISABLE + extended_mode: ENABLE or DISABLE asyn_wait: ENABLE or DISABLE nwait_signal: ENABLE or DISABLE memory_write: ENABLE or DISABLE @@ -198,68 +196,70 @@ void exmc_norsram_struct_para_init(exmc_norsram_parameter_struct* exmc_norsram_i read_write_timing: struct exmc_norsram_timing_parameter_struct set the time asyn_access_mode: EXMC_ACCESS_MODE_A, EXMC_ACCESS_MODE_B, EXMC_ACCESS_MODE_C, EXMC_ACCESS_MODE_D syn_data_latency: EXMC_DATALAT_x_CLK, x=2..17 - syn_clk_division: EXMC_SYN_CLOCK_RATIO_x_CLK, x=2..16 - bus_latency: 0x01U~0x10U + syn_clk_division: EXMC_SYN_CLOCK_RATIO_DISABLE, EXMC_SYN_CLOCK_RATIO_x_CLK, x=2..16 + bus_latency: 0x01U~0x10U asyn_data_setuptime: 0x02U~0x100U asyn_address_holdtime: 0x02U~0x10U asyn_address_setuptime: 0x01U~0x10U write_timing: struct exmc_norsram_timing_parameter_struct set the time asyn_access_mode: EXMC_ACCESS_MODE_A, EXMC_ACCESS_MODE_B, EXMC_ACCESS_MODE_C, EXMC_ACCESS_MODE_D syn_data_latency: EXMC_DATALAT_x_CLK, x=2..17 - syn_clk_division: EXMC_SYN_CLOCK_RATIO_x_CLK, x=2..16 - bus_latency: 0x01U~0x10U + syn_clk_division: EXMC_SYN_CLOCK_RATIO_DISABLE, EXMC_SYN_CLOCK_RATIO_x_CLK, x=2..16 + bus_latency: 0x01U~0x10U asyn_data_setuptime: 0x02U~0x100U asyn_address_holdtime: 0x02U~0x10U asyn_address_setuptime: 0x01U~0x10U \param[out] none \retval none */ -void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) +void exmc_norsram_init(exmc_norsram_parameter_struct *exmc_norsram_init_struct) { uint32_t snctl = 0x00000000U, sntcfg = 0x00000000U, snwtcfg = 0x00000000U; - + /* get the register value */ snctl = EXMC_SNCTL(exmc_norsram_init_struct->norsram_region); /* clear relative bits */ - snctl &= ((uint32_t)~(EXMC_SNCTL_NREN | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN | - EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG | EXMC_SNCTL_WREN | - EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT | EXMC_SNCTL_SYNCWR | - EXMC_SNCTL_NRMUX )); + snctl &= ((uint32_t)~(EXMC_SNCTL_NREN | EXMC_SNCTL_NRTP | EXMC_SNCTL_NRW | EXMC_SNCTL_SBRSTEN | + EXMC_SNCTL_NRWTPOL | EXMC_SNCTL_WRAPEN | EXMC_SNCTL_NRWTCFG | EXMC_SNCTL_WREN | + EXMC_SNCTL_NRWTEN | EXMC_SNCTL_EXMODEN | EXMC_SNCTL_ASYNCWAIT | EXMC_SNCTL_SYNCWR | + EXMC_SNCTL_NRMUX)); + /* configure control bits */ snctl |= (uint32_t)(exmc_norsram_init_struct->address_data_mux << SNCTL_NRMUX_OFFSET) | - exmc_norsram_init_struct->memory_type | - exmc_norsram_init_struct->databus_width | - (exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) | - exmc_norsram_init_struct->nwait_polarity | - (exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) | - exmc_norsram_init_struct->nwait_config | - (exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) | - (exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) | - (exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) | - (exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) | - exmc_norsram_init_struct->write_mode; - + exmc_norsram_init_struct->memory_type | + exmc_norsram_init_struct->databus_width | + (exmc_norsram_init_struct->burst_mode << SNCTL_SBRSTEN_OFFSET) | + exmc_norsram_init_struct->nwait_polarity | + (exmc_norsram_init_struct->wrap_burst_mode << SNCTL_WRAPEN_OFFSET) | + exmc_norsram_init_struct->nwait_config | + (exmc_norsram_init_struct->memory_write << SNCTL_WREN_OFFSET) | + (exmc_norsram_init_struct->nwait_signal << SNCTL_NRWTEN_OFFSET) | + (exmc_norsram_init_struct->extended_mode << SNCTL_EXMODEN_OFFSET) | + (exmc_norsram_init_struct->asyn_wait << SNCTL_ASYNCWAIT_OFFSET) | + exmc_norsram_init_struct->write_mode; + + /* configure timing */ sntcfg = (uint32_t)((exmc_norsram_init_struct->read_write_timing->asyn_address_setuptime - 1U) & EXMC_SNTCFG_ASET) | - (((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U) << SNTCFG_AHLD_OFFSET) & EXMC_SNTCFG_AHLD) | - (((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U) << SNTCFG_DSET_OFFSET) & EXMC_SNTCFG_DSET) | - (((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U) << SNTCFG_BUSLAT_OFFSET) & EXMC_SNTCFG_BUSLAT) | - exmc_norsram_init_struct->read_write_timing->syn_clk_division | - exmc_norsram_init_struct->read_write_timing->syn_data_latency | - exmc_norsram_init_struct->read_write_timing->asyn_access_mode; - - /* nor flash access enable */ - if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type){ + (((exmc_norsram_init_struct->read_write_timing->asyn_address_holdtime - 1U) << SNTCFG_AHLD_OFFSET) & EXMC_SNTCFG_AHLD) | + (((exmc_norsram_init_struct->read_write_timing->asyn_data_setuptime - 1U) << SNTCFG_DSET_OFFSET) & EXMC_SNTCFG_DSET) | + (((exmc_norsram_init_struct->read_write_timing->bus_latency - 1U) << SNTCFG_BUSLAT_OFFSET) & EXMC_SNTCFG_BUSLAT) | + exmc_norsram_init_struct->read_write_timing->syn_clk_division | + exmc_norsram_init_struct->read_write_timing->syn_data_latency | + exmc_norsram_init_struct->read_write_timing->asyn_access_mode; + + /* enable nor flash access */ + if(EXMC_MEMORY_TYPE_NOR == exmc_norsram_init_struct->memory_type) { snctl |= (uint32_t)EXMC_SNCTL_NREN; } - /* extended mode configure */ - if(ENABLE == exmc_norsram_init_struct->extended_mode){ + /* configure extended mode */ + if(ENABLE == exmc_norsram_init_struct->extended_mode) { snwtcfg = (uint32_t)(((exmc_norsram_init_struct->write_timing->asyn_address_setuptime - 1U) & EXMC_SNWTCFG_WASET) | - (((exmc_norsram_init_struct->write_timing->asyn_address_holdtime - 1U) << SNTCFG_AHLD_OFFSET ) & EXMC_SNWTCFG_WAHLD)| + (((exmc_norsram_init_struct->write_timing->asyn_address_holdtime - 1U) << SNTCFG_AHLD_OFFSET) & EXMC_SNWTCFG_WAHLD) | (((exmc_norsram_init_struct->write_timing->asyn_data_setuptime - 1U) << SNTCFG_DSET_OFFSET) & EXMC_SNWTCFG_WDSET) | - exmc_norsram_init_struct->write_timing->asyn_access_mode); - }else{ + exmc_norsram_init_struct->write_timing->asyn_access_mode); + } else { snwtcfg = BANK0_SNWTCFG_RESET; } @@ -271,7 +271,8 @@ void exmc_norsram_init(exmc_norsram_parameter_struct* exmc_norsram_init_struct) /*! \brief enable EXMC NOR/PSRAM bank region - \param[in] exmc_norsram_region: specifie the region of NOR/PSRAM bank + \param[in] exmc_norsram_region: specify the region of NOR/PSRAM bank + only one parameter can be selected which is shown as below: \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) \param[out] none \retval none @@ -283,7 +284,8 @@ void exmc_norsram_enable(uint32_t exmc_norsram_region) /*! \brief disable EXMC NOR/PSRAM bank region - \param[in] exmc_norsram_region: specifie the region of NOR/PSRAM Bank + \param[in] exmc_norsram_region: specify the region of NOR/PSRAM Bank + only one parameter can be selected which is shown as below: \arg EXMC_BANK0_NORSRAM_REGIONx(x=0..3) \param[out] none \retval none @@ -296,7 +298,8 @@ void exmc_norsram_disable(uint32_t exmc_norsram_region) /*! \brief deinitialize EXMC NAND bank \param[in] exmc_nand_bank: select the bank of NAND - \arg EXMC_BANKx_NAND(x=1..2) + only one parameter can be selected which is shown as below: + \arg EXMC_BANKx_NAND(x=1, 2) \param[out] none \retval none */ @@ -310,14 +313,14 @@ void exmc_nand_deinit(uint32_t exmc_nand_bank) } /*! - \brief initialize the struct exmc_nand_init_struct + \brief initialize exmc_nand_parameter_struct with the default values \param[in] none - \param[out] the initialized struct exmc_nand_init_struct pointer + \param[out] the initialized struct exmc_nand_parameter_struct pointer \retval none */ -void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struct) +void exmc_nand_struct_para_init(exmc_nand_parameter_struct *exmc_nand_init_struct) { - /* configure the structure with default value */ + /* configure the structure with default values */ exmc_nand_init_struct->nand_bank = EXMC_BANK1_NAND; exmc_nand_init_struct->wait_feature = DISABLE; exmc_nand_init_struct->databus_width = EXMC_NAND_DATABUS_WIDTH_8B; @@ -358,29 +361,29 @@ void exmc_nand_struct_para_init(exmc_nand_parameter_struct* exmc_nand_init_struc \param[out] none \retval none */ -void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct) +void exmc_nand_init(exmc_nand_parameter_struct *exmc_nand_init_struct) { uint32_t npctl = 0x00000000U, npctcfg = 0x00000000U, npatcfg = 0x00000000U; - - npctl = (uint32_t)(exmc_nand_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET)| - EXMC_NPCTL_NDTP | - exmc_nand_init_struct->databus_width | - (exmc_nand_init_struct->ecc_logic << NPCTL_ECCEN_OFFSET)| - exmc_nand_init_struct->ecc_size | - exmc_nand_init_struct->ctr_latency | - exmc_nand_init_struct->atr_latency; - - npctcfg = (uint32_t)((exmc_nand_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET ) | - (((exmc_nand_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | - ((exmc_nand_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | - (((exmc_nand_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); - - npatcfg = (uint32_t)((exmc_nand_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | - (((exmc_nand_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | - ((exmc_nand_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD ) | - (((exmc_nand_init_struct->attribute_space_timing->databus_hiztime - 1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ ); - - /* EXMC_BANK1_NAND or EXMC_BANK2_NAND initialize */ + + npctl = (uint32_t)(exmc_nand_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET) | + EXMC_NPCTL_NDTP | + exmc_nand_init_struct->databus_width | + (exmc_nand_init_struct->ecc_logic << NPCTL_ECCEN_OFFSET) | + exmc_nand_init_struct->ecc_size | + exmc_nand_init_struct->ctr_latency | + exmc_nand_init_struct->atr_latency; + + npctcfg = (uint32_t)((exmc_nand_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET) | + (((exmc_nand_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT) | + ((exmc_nand_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD) | + (((exmc_nand_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ); + + npatcfg = (uint32_t)((exmc_nand_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET) | + (((exmc_nand_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT) | + ((exmc_nand_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD) | + (((exmc_nand_init_struct->attribute_space_timing->databus_hiztime - 1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ); + + /* initialize EXMC_BANK1_NAND or EXMC_BANK2_NAND */ EXMC_NPCTL(exmc_nand_init_struct->nand_bank) = npctl; EXMC_NPCTCFG(exmc_nand_init_struct->nand_bank) = npctcfg; EXMC_NPATCFG(exmc_nand_init_struct->nand_bank) = npatcfg; @@ -388,7 +391,8 @@ void exmc_nand_init(exmc_nand_parameter_struct* exmc_nand_init_struct) /*! \brief enable NAND bank - \param[in] exmc_nand_bank: specifie the NAND bank + \param[in] exmc_nand_bank: specify the NAND bank + only one parameter can be selected which is shown as below: \arg EXMC_BANKx_NAND(x=1,2) \param[out] none \retval none @@ -400,7 +404,8 @@ void exmc_nand_enable(uint32_t exmc_nand_bank) /*! \brief disable NAND bank - \param[in] exmc_nand_bank: specifie the NAND bank + \param[in] exmc_nand_bank: specify the NAND bank + only one parameter can be selected which is shown as below: \arg EXMC_BANKx_NAND(x=1,2) \param[out] none \retval none @@ -412,7 +417,8 @@ void exmc_nand_disable(uint32_t exmc_nand_bank) /*! \brief enable or disable the EXMC NAND ECC function - \param[in] exmc_nand_bank: specifie the NAND bank + \param[in] exmc_nand_bank: specify the NAND bank + only one parameter can be selected which is shown as below: \arg EXMC_BANKx_NAND(x=1,2) \param[in] newvalue: ENABLE or DISABLE \param[out] none @@ -420,10 +426,10 @@ void exmc_nand_disable(uint32_t exmc_nand_bank) */ void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue) { - if (ENABLE == newvalue){ + if(ENABLE == newvalue) { /* enable the selected NAND bank ECC function */ EXMC_NPCTL(exmc_nand_bank) |= EXMC_NPCTL_ECCEN; - }else{ + } else { /* disable the selected NAND bank ECC function */ EXMC_NPCTL(exmc_nand_bank) &= ~EXMC_NPCTL_ECCEN; } @@ -431,7 +437,8 @@ void exmc_nand_ecc_config(uint32_t exmc_nand_bank, ControlStatus newvalue) /*! \brief get the EXMC ECC value - \param[in] exmc_nand_bank: specifie the NAND bank + \param[in] exmc_nand_bank: specify the NAND bank + only one parameter can be selected which is shown as below: \arg EXMC_BANKx_NAND(x=1,2) \param[out] none \retval the error correction code(ECC) value @@ -457,6 +464,32 @@ void exmc_pccard_deinit(void) EXMC_PIOTCFG3 = BANK3_PIOTCFG3_RESET; } +/*! + \brief initialize exmc_pccard_parameter_struct with the default values + \param[in] none + \param[out] the initialized struct exmc_pccard_parameter_struct pointer + \retval none +*/ +void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct *exmc_pccard_init_struct) +{ + /* configure the structure with default value */ + exmc_pccard_init_struct->wait_feature = DISABLE; + exmc_pccard_init_struct->ctr_latency = 0x0U; + exmc_pccard_init_struct->atr_latency = 0x0U; + exmc_pccard_init_struct->common_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->common_space_timing->databus_hiztime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->attribute_space_timing->databus_hiztime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->setuptime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->waittime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->holdtime = 0xFCU; + exmc_pccard_init_struct->io_space_timing->databus_hiztime = 0xFCU; +} + /*! \brief initialize EXMC PC card bank \param[in] exmc_pccard_parameter_struct: configure the EXMC NAND parameter @@ -481,61 +514,35 @@ void exmc_pccard_deinit(void) \param[out] none \retval none */ -void exmc_pccard_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) +void exmc_pccard_init(exmc_pccard_parameter_struct *exmc_pccard_init_struct) { /* configure the EXMC bank3 PC card control register */ EXMC_NPCTL3 = (uint32_t)(exmc_pccard_init_struct->wait_feature << NPCTL_NDWTEN_OFFSET) | - EXMC_NAND_DATABUS_WIDTH_16B | - exmc_pccard_init_struct->ctr_latency | - exmc_pccard_init_struct->atr_latency ; - + EXMC_NAND_DATABUS_WIDTH_16B | + exmc_pccard_init_struct->ctr_latency | + exmc_pccard_init_struct->atr_latency ; + /* configure the EXMC bank3 PC card common space timing configuration register */ - EXMC_NPCTCFG3 = (uint32_t)((exmc_pccard_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET ) | - (((exmc_pccard_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT ) | - ((exmc_pccard_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD ) | - (((exmc_pccard_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ ); + EXMC_NPCTCFG3 = (uint32_t)((exmc_pccard_init_struct->common_space_timing->setuptime - 1U) & EXMC_NPCTCFG_COMSET) | + (((exmc_pccard_init_struct->common_space_timing->waittime - 1U) << NPCTCFG_COMWAIT_OFFSET) & EXMC_NPCTCFG_COMWAIT) | + ((exmc_pccard_init_struct->common_space_timing->holdtime << NPCTCFG_COMHLD_OFFSET) & EXMC_NPCTCFG_COMHLD) | + (((exmc_pccard_init_struct->common_space_timing->databus_hiztime - 1U) << NPCTCFG_COMHIZ_OFFSET) & EXMC_NPCTCFG_COMHIZ); /* configure the EXMC bank3 PC card attribute space timing configuration register */ - EXMC_NPATCFG3 = (uint32_t)((exmc_pccard_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET ) | - (((exmc_pccard_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT ) | - ((exmc_pccard_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD ) | - (((exmc_pccard_init_struct->attribute_space_timing->databus_hiztime - 1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ); + EXMC_NPATCFG3 = (uint32_t)((exmc_pccard_init_struct->attribute_space_timing->setuptime - 1U) & EXMC_NPATCFG_ATTSET) | + (((exmc_pccard_init_struct->attribute_space_timing->waittime - 1U) << NPATCFG_ATTWAIT_OFFSET) & EXMC_NPATCFG_ATTWAIT) | + ((exmc_pccard_init_struct->attribute_space_timing->holdtime << NPATCFG_ATTHLD_OFFSET) & EXMC_NPATCFG_ATTHLD) | + (((exmc_pccard_init_struct->attribute_space_timing->databus_hiztime - 1U) << NPATCFG_ATTHIZ_OFFSET) & EXMC_NPATCFG_ATTHIZ); /* configure the EXMC bank3 PC card io space timing configuration register */ - EXMC_PIOTCFG3 = (uint32_t)((exmc_pccard_init_struct->io_space_timing->setuptime - 1U) & EXMC_PIOTCFG3_IOSET ) | - (((exmc_pccard_init_struct->io_space_timing->waittime - 1U) << PIOTCFG_IOWAIT_OFFSET) & EXMC_PIOTCFG3_IOWAIT ) | - ((exmc_pccard_init_struct->io_space_timing->holdtime << PIOTCFG_IOHLD_OFFSET) & EXMC_PIOTCFG3_IOHLD ) | - ((exmc_pccard_init_struct->io_space_timing->databus_hiztime << PIOTCFG_IOHIZ_OFFSET) & EXMC_PIOTCFG3_IOHIZ ); + EXMC_PIOTCFG3 = (uint32_t)((exmc_pccard_init_struct->io_space_timing->setuptime - 1U) & EXMC_PIOTCFG3_IOSET) | + (((exmc_pccard_init_struct->io_space_timing->waittime - 1U) << PIOTCFG_IOWAIT_OFFSET) & EXMC_PIOTCFG3_IOWAIT) | + ((exmc_pccard_init_struct->io_space_timing->holdtime << PIOTCFG_IOHLD_OFFSET) & EXMC_PIOTCFG3_IOHLD) | + ((exmc_pccard_init_struct->io_space_timing->databus_hiztime << PIOTCFG_IOHIZ_OFFSET) & EXMC_PIOTCFG3_IOHIZ); } /*! - \brief initialize the struct exmc_pccard_parameter_struct - \param[in] none - \param[out] the initialized struct exmc_pccard_parameter_struct pointer - \retval none -*/ -void exmc_pccard_struct_para_init(exmc_pccard_parameter_struct* exmc_pccard_init_struct) -{ - /* configure the structure with default value */ - exmc_pccard_init_struct->wait_feature = DISABLE; - exmc_pccard_init_struct->ctr_latency = 0x0U; - exmc_pccard_init_struct->atr_latency = 0x0U; - exmc_pccard_init_struct->common_space_timing->setuptime = 0xFCU; - exmc_pccard_init_struct->common_space_timing->waittime = 0xFCU; - exmc_pccard_init_struct->common_space_timing->holdtime = 0xFCU; - exmc_pccard_init_struct->common_space_timing->databus_hiztime = 0xFCU; - exmc_pccard_init_struct->attribute_space_timing->setuptime = 0xFCU; - exmc_pccard_init_struct->attribute_space_timing->waittime = 0xFCU; - exmc_pccard_init_struct->attribute_space_timing->holdtime = 0xFCU; - exmc_pccard_init_struct->attribute_space_timing->databus_hiztime = 0xFCU; - exmc_pccard_init_struct->io_space_timing->setuptime = 0xFCU; - exmc_pccard_init_struct->io_space_timing->waittime = 0xFCU; - exmc_pccard_init_struct->io_space_timing->holdtime = 0xFCU; - exmc_pccard_init_struct->io_space_timing->databus_hiztime = 0xFCU; -} - -/*! - \brief enable PC Card Bank + \brief enable PC card bank \param[in] none \param[out] none \retval none @@ -546,19 +553,21 @@ void exmc_pccard_enable(void) } /*! - \brief disable PC Card Bank + \brief disable PC card bank \param[in] none \param[out] none \retval none */ void exmc_pccard_disable(void) { - EXMC_NPCTL3 &= ~EXMC_NPCTL_NDBKEN; + EXMC_NPCTL3 &= ~EXMC_NPCTL_NDBKEN; } /*! \brief deinitialize EXMC SDRAM device - \param[in] exmc_sdram_device: + \param[in] exmc_sdram_device: select the SDRAM device + only one parameter can be selected which is shown as below: + \arg EXMC_SDRAM_DEVICEx(x=0, 1) \param[out] none \retval none */ @@ -572,6 +581,35 @@ void exmc_sdram_deinit(uint32_t exmc_sdram_device) EXMC_SDRSCTL = SDRAM_DEVICE_SDRSCTL_RESET; } +/*! + \brief initialize exmc_sdram_init_struct with the default values + \param[in] none + \param[out] the initialized struct exmc_sdram_parameter_struct pointer + \retval none +*/ +void exmc_sdram_struct_para_init(exmc_sdram_parameter_struct *exmc_sdram_init_struct) +{ + /* configure the structure with default value */ + exmc_sdram_init_struct->sdram_device = EXMC_SDRAM_DEVICE0; + exmc_sdram_init_struct->column_address_width = EXMC_SDRAM_COW_ADDRESS_8; + exmc_sdram_init_struct->row_address_width = EXMC_SDRAM_ROW_ADDRESS_11; + exmc_sdram_init_struct->data_width = EXMC_SDRAM_DATABUS_WIDTH_16B; + exmc_sdram_init_struct->internal_bank_number = EXMC_SDRAM_4_INTER_BANK; + exmc_sdram_init_struct->cas_latency = EXMC_CAS_LATENCY_1_SDCLK; + exmc_sdram_init_struct->write_protection = ENABLE; + exmc_sdram_init_struct->sdclock_config = EXMC_SDCLK_DISABLE; + exmc_sdram_init_struct->burst_read_switch = DISABLE; + exmc_sdram_init_struct->pipeline_read_delay = EXMC_PIPELINE_DELAY_0_HCLK; + + exmc_sdram_init_struct->timing->load_mode_register_delay = 16U; + exmc_sdram_init_struct->timing->exit_selfrefresh_delay = 16U; + exmc_sdram_init_struct->timing->row_address_select_delay = 16U; + exmc_sdram_init_struct->timing->auto_refresh_delay = 16U; + exmc_sdram_init_struct->timing->write_recovery_delay = 16U; + exmc_sdram_init_struct->timing->row_precharge_delay = 16U; + exmc_sdram_init_struct->timing->row_to_column_delay = 16U; +} + /*! \brief initialize EXMC SDRAM device \param[in] exmc_sdram_parameter_struct: configure the EXMC SDRAM parameter @@ -596,62 +634,62 @@ void exmc_sdram_deinit(uint32_t exmc_sdram_device) \param[out] none \retval none */ -void exmc_sdram_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct) +void exmc_sdram_init(exmc_sdram_parameter_struct *exmc_sdram_init_struct) { uint32_t sdctl0, sdctl1, sdtcfg0, sdtcfg1; - /* configuration EXMC_SDCTL0 or EXMC_SDCTL1 */ - if(EXMC_SDRAM_DEVICE0 == exmc_sdram_init_struct->sdram_device){ - /* configuration EXMC_SDCTL0 */ - EXMC_SDCTL(EXMC_SDRAM_DEVICE0) = (uint32_t)exmc_sdram_init_struct->column_address_width | - exmc_sdram_init_struct->row_address_width | - exmc_sdram_init_struct->data_width | - exmc_sdram_init_struct->internal_bank_number | - exmc_sdram_init_struct->cas_latency | - (exmc_sdram_init_struct->write_protection << SDCTL_WPEN_OFFSET)| - exmc_sdram_init_struct->sdclock_config | - (exmc_sdram_init_struct->brust_read_switch << SDCTL_BRSTRD_OFFSET)| - exmc_sdram_init_struct->pipeline_read_delay; + /* configure EXMC_SDCTL0 or EXMC_SDCTL1 */ + if(EXMC_SDRAM_DEVICE0 == exmc_sdram_init_struct->sdram_device) { + /* configure EXMC_SDCTL0 */ + EXMC_SDCTL(EXMC_SDRAM_DEVICE0) = (uint32_t)(exmc_sdram_init_struct->column_address_width | + exmc_sdram_init_struct->row_address_width | + exmc_sdram_init_struct->data_width | + exmc_sdram_init_struct->internal_bank_number | + exmc_sdram_init_struct->cas_latency | + (exmc_sdram_init_struct->write_protection << SDCTL_WPEN_OFFSET) | + exmc_sdram_init_struct->sdclock_config | + (exmc_sdram_init_struct->burst_read_switch << SDCTL_BRSTRD_OFFSET) | + exmc_sdram_init_struct->pipeline_read_delay); - /* configuration EXMC_SDTCFG0 */ - EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) = (uint32_t)((exmc_sdram_init_struct->timing->load_mode_register_delay)-1U) | - (((exmc_sdram_init_struct->timing->exit_selfrefresh_delay)-1U) << SDTCFG_XSRD_OFFSET) | - (((exmc_sdram_init_struct->timing->row_address_select_delay)-1U) << SDTCFG_RASD_OFFSET) | - (((exmc_sdram_init_struct->timing->auto_refresh_delay)-1U) << SDTCFG_ARFD_OFFSET) | - (((exmc_sdram_init_struct->timing->write_recovery_delay)-1U) << SDTCFG_WRD_OFFSET) | - (((exmc_sdram_init_struct->timing->row_precharge_delay)-1U) << SDTCFG_RPD_OFFSET) | - (((exmc_sdram_init_struct->timing->row_to_column_delay)-1U) << SDTCFG_RCD_OFFSET); - }else{ - /* configuration EXMC_SDCTL0 and EXMC_SDCTL1 */ + /* configure EXMC_SDTCFG0 */ + EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) = (uint32_t)((exmc_sdram_init_struct->timing->load_mode_register_delay) - 1U) | + (((exmc_sdram_init_struct->timing->exit_selfrefresh_delay) - 1U) << SDTCFG_XSRD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_address_select_delay) - 1U) << SDTCFG_RASD_OFFSET) | + (((exmc_sdram_init_struct->timing->auto_refresh_delay) - 1U) << SDTCFG_ARFD_OFFSET) | + (((exmc_sdram_init_struct->timing->write_recovery_delay) - 1U) << SDTCFG_WRD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_precharge_delay) - 1U) << SDTCFG_RPD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_to_column_delay) - 1U) << SDTCFG_RCD_OFFSET); + } else { + /* configure EXMC_SDCTL0 and EXMC_SDCTL1 */ /* some bits in the EXMC_SDCTL1 register are reserved */ - sdctl0 = EXMC_SDCTL(EXMC_SDRAM_DEVICE0) & (~( EXMC_SDCTL_PIPED | EXMC_SDCTL_BRSTRD | EXMC_SDCTL_SDCLK )); - - sdctl0 |= (uint32_t)exmc_sdram_init_struct->sdclock_config | - exmc_sdram_init_struct->brust_read_switch | - exmc_sdram_init_struct->pipeline_read_delay; + sdctl0 = EXMC_SDCTL(EXMC_SDRAM_DEVICE0) & (~(EXMC_SDCTL_PIPED | EXMC_SDCTL_BRSTRD | EXMC_SDCTL_SDCLK)); + + sdctl0 |= (uint32_t)(exmc_sdram_init_struct->sdclock_config | + (exmc_sdram_init_struct->burst_read_switch << SDCTL_BRSTRD_OFFSET) | + exmc_sdram_init_struct->pipeline_read_delay); - sdctl1 = (uint32_t)exmc_sdram_init_struct->column_address_width | - exmc_sdram_init_struct->row_address_width | - exmc_sdram_init_struct->data_width | - exmc_sdram_init_struct->internal_bank_number | - exmc_sdram_init_struct->cas_latency | - exmc_sdram_init_struct->write_protection ; + sdctl1 = (uint32_t)(exmc_sdram_init_struct->column_address_width | + exmc_sdram_init_struct->row_address_width | + exmc_sdram_init_struct->data_width | + exmc_sdram_init_struct->internal_bank_number | + exmc_sdram_init_struct->cas_latency | + (exmc_sdram_init_struct->write_protection << SDCTL_WPEN_OFFSET)); EXMC_SDCTL(EXMC_SDRAM_DEVICE0) = sdctl0; EXMC_SDCTL(EXMC_SDRAM_DEVICE1) = sdctl1; - + /* configuration EXMC_SDTCFG0 and EXMC_SDTCFG1 */ /* some bits in the EXMC_SDTCFG1 register are reserved */ sdtcfg0 = EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) & (~(EXMC_SDTCFG_RPD | EXMC_SDTCFG_WRD | EXMC_SDTCFG_ARFD)); - sdtcfg0 |= (uint32_t)(((exmc_sdram_init_struct->timing->auto_refresh_delay)-1U) << SDTCFG_ARFD_OFFSET) | - (((exmc_sdram_init_struct->timing->row_precharge_delay)-1U) << SDTCFG_RPD_OFFSET) | - (((exmc_sdram_init_struct->timing->write_recovery_delay)-1U) << SDTCFG_WRD_OFFSET); + sdtcfg0 |= (uint32_t)(((exmc_sdram_init_struct->timing->auto_refresh_delay) - 1U) << SDTCFG_ARFD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_precharge_delay) - 1U) << SDTCFG_RPD_OFFSET) | + (((exmc_sdram_init_struct->timing->write_recovery_delay) - 1U) << SDTCFG_WRD_OFFSET); - sdtcfg1 = (uint32_t)((exmc_sdram_init_struct->timing->load_mode_register_delay)-1U) | - (((exmc_sdram_init_struct->timing->exit_selfrefresh_delay)-1U) << SDTCFG_XSRD_OFFSET) | - (((exmc_sdram_init_struct->timing->row_address_select_delay)-1U) << SDTCFG_RASD_OFFSET) | - (((exmc_sdram_init_struct->timing->row_to_column_delay)-1U) << SDTCFG_RCD_OFFSET); + sdtcfg1 = (uint32_t)((exmc_sdram_init_struct->timing->load_mode_register_delay) - 1U) | + (((exmc_sdram_init_struct->timing->exit_selfrefresh_delay) - 1U) << SDTCFG_XSRD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_address_select_delay) - 1U) << SDTCFG_RASD_OFFSET) | + (((exmc_sdram_init_struct->timing->row_to_column_delay) - 1U) << SDTCFG_RCD_OFFSET); EXMC_SDTCFG(EXMC_SDRAM_DEVICE0) = sdtcfg0; EXMC_SDTCFG(EXMC_SDRAM_DEVICE1) = sdtcfg1; @@ -659,88 +697,74 @@ void exmc_sdram_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct) } /*! - \brief initialize the struct exmc_sdram_parameter_struct + \brief initialize exmc_sdram_struct_command_para_init with the default values \param[in] none - \param[out] the initialized struct exmc_sdram_parameter_struct pointer + \param[out] the initialized struct exmc_sdram_struct_command_para_init pointer \retval none */ -void exmc_sdram_parameter_init(exmc_sdram_parameter_struct* exmc_sdram_init_struct) +void exmc_sdram_struct_command_para_init(exmc_sdram_command_parameter_struct *exmc_sdram_command_init_struct) { /* configure the structure with default value */ - exmc_sdram_init_struct->sdram_device = EXMC_SDRAM_DEVICE0; - exmc_sdram_init_struct->column_address_width = EXMC_SDRAM_COW_ADDRESS_8; - exmc_sdram_init_struct->row_address_width = EXMC_SDRAM_ROW_ADDRESS_11; - exmc_sdram_init_struct->data_width = EXMC_SDRAM_DATABUS_WIDTH_16B; - exmc_sdram_init_struct->internal_bank_number = EXMC_SDRAM_4_INTER_BANK; - exmc_sdram_init_struct->cas_latency = EXMC_CAS_LATENCY_1_SDCLK; - exmc_sdram_init_struct->write_protection = ENABLE; - exmc_sdram_init_struct->sdclock_config = EXMC_SDCLK_DISABLE; - exmc_sdram_init_struct->brust_read_switch = DISABLE; - exmc_sdram_init_struct->pipeline_read_delay = EXMC_PIPELINE_DELAY_0_HCLK; - - exmc_sdram_init_struct->timing->load_mode_register_delay = 16U; - exmc_sdram_init_struct->timing->exit_selfrefresh_delay = 16U; - exmc_sdram_init_struct->timing->row_address_select_delay = 16U; - exmc_sdram_init_struct->timing->auto_refresh_delay = 16U; - exmc_sdram_init_struct->timing->write_recovery_delay = 16U; - exmc_sdram_init_struct->timing->row_precharge_delay = 16U; - exmc_sdram_init_struct->timing->row_to_column_delay = 16U; + exmc_sdram_command_init_struct->mode_register_content = 0U; + exmc_sdram_command_init_struct->auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK; + exmc_sdram_command_init_struct->bank_select = EXMC_SDRAM_DEVICE0_SELECT; + exmc_sdram_command_init_struct->command = EXMC_SDRAM_NORMAL_OPERATION; } /*! \brief configure the SDRAM memory command - \param[in] exmc_sdram_command_init_struct: initialize EXMC SDRAM command + \param[in] exmc_sdram_command_init_struct: initialize EXMC SDRAM command mode_register_content: auto_refresh_number: EXMC_SDRAM_AUTO_REFLESH_x_SDCLK, x=1..15 - bank_select: EXMC_SDRAM_DEVICE0_SELECT, EXMC_SDRAM_DEVICE1_SELECT, EXMC_SDRAM_DEVICE0_1_SELECT - command: EXMC_SDRAM_NORMAL_OPERATION, EXMC_SDRAM_CLOCK_ENABLE, EXMC_SDRAM_PRECHARGE_ALL, - EXMC_SDRAM_AUTO_REFRESH, EXMC_SDRAM_LOAD_MODE_REGISTER, EXMC_SDRAM_SELF_REFRESH, - EXMC_SDRAM_POWERDOWN_ENTRY + bank_select: EXMC_SDRAM_DEVICE0_SELECT, EXMC_SDRAM_DEVICE1_SELECT, EXMC_SDRAM_DEVICE0_1_SELECT + command: EXMC_SDRAM_NORMAL_OPERATION, EXMC_SDRAM_CLOCK_ENABLE, EXMC_SDRAM_PRECHARGE_ALL, + EXMC_SDRAM_AUTO_REFRESH, EXMC_SDRAM_LOAD_MODE_REGISTER, EXMC_SDRAM_SELF_REFRESH, + EXMC_SDRAM_POWERDOWN_ENTRY \param[out] none \retval none */ -void exmc_sdram_command_config(exmc_sdram_command_parameter_struct* exmc_sdram_command_init_struct) +void exmc_sdram_command_config(exmc_sdram_command_parameter_struct *exmc_sdram_command_init_struct) { /* configure command register */ EXMC_SDCMD = (uint32_t)((exmc_sdram_command_init_struct->command) | - (exmc_sdram_command_init_struct->bank_select) | - ((exmc_sdram_command_init_struct->auto_refresh_number)) | - ((exmc_sdram_command_init_struct->mode_register_content)<bank_select) | + ((exmc_sdram_command_init_struct->auto_refresh_number)) | + ((exmc_sdram_command_init_struct->mode_register_content) << SDCMD_MRC_OFFSET)); } /*! \brief set auto-refresh interval - \param[in] exmc_count: the number SDRAM clock cycles unit between two successive auto-refresh commands - \arg (SDRAM refresh period / number of rows) - 20 + \param[in] exmc_count: the number SDRAM clock cycles unit between two successive auto-refresh commands, 0x0000~0x1FFF \param[out] none \retval none */ void exmc_sdram_refresh_count_set(uint32_t exmc_count) { uint32_t sdari; - + sdari = EXMC_SDARI & (~EXMC_SDARI_ARINTV); EXMC_SDARI = sdari | (uint32_t)((exmc_count << SDARI_ARINTV_OFFSET) & EXMC_SDARI_ARINTV); } /*! \brief set the number of successive auto-refresh command - \param[in] exmc_number: how many successive Auto-refresh cycles will be send when CMD = Auto-refresh command - \arg EXMC_SDRAM_AUTO_REFLESH_x_SDCLK, x=1..15 + \param[in] exmc_number: the number of successive auto-refresh cycles will be send, 1~15 + \arg EXMC_SDRAM_AUTO_REFLESH_x_SDCLK(x=1..15) \param[out] none \retval none */ void exmc_sdram_autorefresh_number_set(uint32_t exmc_number) { uint32_t sdcmd; - + sdcmd = EXMC_SDCMD & (~EXMC_SDCMD_NARF); EXMC_SDCMD = sdcmd | (uint32_t)((exmc_number << SDCMD_NARF_OFFSET) & EXMC_SDCMD_NARF) ; } /*! - \brief config the write protection function - \param[in] exmc_sdram_device: specifie the SDRAM device + \brief configure the write protection function + \param[in] exmc_sdram_device: specify the SDRAM device + only one parameter can be selected which is shown as below: \arg EXMC_SDRAM_DEVICEx(x=0,1) \param[in] newvalue: ENABLE or DISABLE \param[out] none @@ -748,9 +772,9 @@ void exmc_sdram_autorefresh_number_set(uint32_t exmc_number) */ void exmc_sdram_write_protection_config(uint32_t exmc_sdram_device, ControlStatus newvalue) { - if (ENABLE == newvalue){ + if(ENABLE == newvalue) { EXMC_SDCTL(exmc_sdram_device) |= (uint32_t)EXMC_SDCTL_WPEN; - }else{ + } else { EXMC_SDCTL(exmc_sdram_device) &= ~((uint32_t)EXMC_SDCTL_WPEN); } @@ -758,7 +782,8 @@ void exmc_sdram_write_protection_config(uint32_t exmc_sdram_device, ControlStatu /*! \brief get the status of SDRAM device0 or device1 - \param[in] exmc_sdram_device: specifie the SDRAM device + \param[in] exmc_sdram_device: specify the SDRAM device + only one parameter can be selected which is shown as below: \arg EXMC_SDRAM_DEVICEx(x=0,1) \param[out] none \retval the status of SDRAM device @@ -770,9 +795,9 @@ uint32_t exmc_sdram_bankstatus_get(uint32_t exmc_sdram_device) { uint32_t sdstat = 0U; - if(EXMC_SDRAM_DEVICE0 == exmc_sdram_device){ + if(EXMC_SDRAM_DEVICE0 == exmc_sdram_device) { sdstat = ((uint32_t)(EXMC_SDSTAT & EXMC_SDSDAT_STA0) >> SDSTAT_STA0_OFFSET); - }else{ + } else { sdstat = ((uint32_t)(EXMC_SDSTAT & EXMC_SDSDAT_STA1) >> SDSTAT_STA1_OFFSET); } @@ -782,8 +807,10 @@ uint32_t exmc_sdram_bankstatus_get(uint32_t exmc_sdram_device) /*! \brief configure the delayed sample clock of read data \param[in] delay_cell: SDRAM the delayed sample clock of read data + only one parameter can be selected which is shown as below: \arg EXMC_SDRAM_x_DELAY_CELL(x=0..15) \param[in] extra_hclk: sample cycle of read data + only one parameter can be selected which is shown as below: \arg EXMC_SDRAM_READSAMPLE_x_EXTRAHCLK(x=0,1) \param[out] none \retval none @@ -791,10 +818,10 @@ uint32_t exmc_sdram_bankstatus_get(uint32_t exmc_sdram_device) void exmc_sdram_readsample_config(uint32_t delay_cell, uint32_t extra_hclk) { uint32_t sdrsctl = 0U; - + sdrsctl = EXMC_SDRSCTL & (~(EXMC_SDRSCTL_SDSC | EXMC_SDRSCTL_SSCR)); sdrsctl |= (uint32_t)(delay_cell & EXMC_SDRSCTL_SDSC) | - ((extra_hclk << SDRSCTL_SSCR_OFFSET) & EXMC_SDRSCTL_SSCR); + ((extra_hclk << SDRSCTL_SSCR_OFFSET) & EXMC_SDRSCTL_SSCR); EXMC_SDRSCTL = sdrsctl; } @@ -822,7 +849,7 @@ void exmc_sdram_readsample_disable(void) /*! - \brief deinitialize exmc SQPIPSRAM + \brief deinitialize EXMC SQPIPSRAM \param[in] none \param[out] none \retval none @@ -837,6 +864,21 @@ void exmc_sqpipsram_deinit(void) EXMC_SIDH = BANK0_SQPI_SIDH_RESET; } +/*! + \brief initialize exmc_sqpipsram_init_struct with the default values + \param[in] the structure exmc_sqpipsram_parameter_struct pointer + \param[out] none + \retval none +*/ +void exmc_sqpipsram_struct_para_init(exmc_sqpipsram_parameter_struct *exmc_sqpipsram_init_struct) +{ + /* configure the structure with default value */ + exmc_sqpipsram_init_struct->sample_polarity = EXMC_SQPIPSRAM_SAMPLE_RISING_EDGE; + exmc_sqpipsram_init_struct->id_length = EXMC_SQPIPSRAM_ID_LENGTH_64B; + exmc_sqpipsram_init_struct->address_bits = EXMC_SQPIPSRAM_ADDR_LENGTH_24B; + exmc_sqpipsram_init_struct->command_bits = EXMC_SQPIPSRAM_COMMAND_LENGTH_8B; +} + /*! \brief initialize EXMC SQPIPSRAM \param[in] exmc_sqpipsram_parameter_struct: configure the EXMC SQPIPSRAM parameter @@ -847,33 +889,19 @@ void exmc_sqpipsram_deinit(void) \param[out] none \retval none */ -void exmc_sqpipsram_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct) +void exmc_sqpipsram_init(exmc_sqpipsram_parameter_struct *exmc_sqpipsram_init_struct) { /* initialize SQPI controller */ EXMC_SINIT = (uint32_t)exmc_sqpipsram_init_struct->sample_polarity | - exmc_sqpipsram_init_struct->id_length | - exmc_sqpipsram_init_struct->address_bits | - exmc_sqpipsram_init_struct->command_bits; -} - -/*! - \brief initialize the struct exmc_sqpipsram_parameter_struct - \param[in] the struct exmc_sqpipsram_parameter_struct pointer - \param[out] none - \retval none -*/ -void exmc_sqpipsram_parameter_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsram_init_struct) -{ - /* configure the structure with default value */ - exmc_sqpipsram_init_struct->sample_polarity = EXMC_SQPIPSRAM_SAMPLE_RISING_EDGE; - exmc_sqpipsram_init_struct->id_length = EXMC_SQPIPSRAM_ID_LENGTH_64B; - exmc_sqpipsram_init_struct->address_bits = EXMC_SQPIPSRAM_ADDR_LENGTH_24B; - exmc_sqpipsram_init_struct->command_bits = EXMC_SQPIPSRAM_COMMAND_LENGTH_8B; + exmc_sqpipsram_init_struct->id_length | + exmc_sqpipsram_init_struct->address_bits | + exmc_sqpipsram_init_struct->command_bits; } /*! \brief set the read command \param[in] read_command_mode: configure SPI PSRAM read command mode + only one parameter can be selected which is shown as below: \arg EXMC_SQPIPSRAM_READ_MODE_DISABLE: not SPI mode \arg EXMC_SQPIPSRAM_READ_MODE_SPI: SPI mode \arg EXMC_SQPIPSRAM_READ_MODE_SQPI: SQPI mode @@ -886,16 +914,17 @@ void exmc_sqpipsram_parameter_init(exmc_sqpipsram_parameter_struct* exmc_sqpipsr void exmc_sqpipsram_read_command_set(uint32_t read_command_mode, uint32_t read_wait_cycle, uint32_t read_command_code) { uint32_t srcmd; - + srcmd = (uint32_t) read_command_mode | - ((read_wait_cycle << SRCMD_RWAITCYCLE_OFFSET) & EXMC_SRCMD_RWAITCYCLE) | - ((read_command_code & EXMC_SRCMD_RCMD)); + ((read_wait_cycle << SRCMD_RWAITCYCLE_OFFSET) & EXMC_SRCMD_RWAITCYCLE) | + ((read_command_code & EXMC_SRCMD_RCMD)); EXMC_SRCMD = srcmd; } /*! \brief set the write command \param[in] write_command_mode: configure SPI PSRAM write command mode + only one parameter can be selected which is shown as below: \arg EXMC_SQPIPSRAM_WRITE_MODE_DISABLE: not SPI mode \arg EXMC_SQPIPSRAM_WRITE_MODE_SPI: SPI mode \arg EXMC_SQPIPSRAM_WRITE_MODE_SQPI: SQPI mode @@ -908,10 +937,10 @@ void exmc_sqpipsram_read_command_set(uint32_t read_command_mode, uint32_t read_w void exmc_sqpipsram_write_command_set(uint32_t write_command_mode, uint32_t write_wait_cycle, uint32_t write_command_code) { uint32_t swcmd; - + swcmd = (uint32_t) write_command_mode | - ((write_wait_cycle << SWCMD_WWAITCYCLE_OFFSET) & EXMC_SWCMD_WWAITCYCLE) | - ((write_command_code & EXMC_SWCMD_WCMD)); + ((write_wait_cycle << SWCMD_WWAITCYCLE_OFFSET) & EXMC_SWCMD_WWAITCYCLE) | + ((write_command_code & EXMC_SWCMD_WCMD)); EXMC_SWCMD = swcmd; } @@ -962,6 +991,7 @@ uint32_t exmc_sqpipsram_high_id_get(void) /*! \brief get the bit value of EXMC send write command bit or read ID command \param[in] send_command_flag: the send command flag + only one parameter can be selected which is shown as below: \arg EXMC_SEND_COMMAND_FLAG_RDID: EXMC_SRCMD_RDID flag bit \arg EXMC_SEND_COMMAND_FLAG_SC: EXMC_SWCMD_SC flag bit \param[out] none @@ -970,32 +1000,34 @@ uint32_t exmc_sqpipsram_high_id_get(void) FlagStatus exmc_sqpipsram_send_command_state_get(uint32_t send_command_flag) { uint32_t flag = 0x00000000U; - - if(EXMC_SEND_COMMAND_FLAG_RDID == send_command_flag){ + + if(EXMC_SEND_COMMAND_FLAG_RDID == send_command_flag) { flag = EXMC_SRCMD; - }else if(EXMC_SEND_COMMAND_FLAG_SC == send_command_flag){ + } else if(EXMC_SEND_COMMAND_FLAG_SC == send_command_flag) { flag = EXMC_SWCMD; - }else{ + } else { } - - if (flag & send_command_flag){ + + if(flag & send_command_flag) { /* flag is set */ return SET; - }else{ + } else { /* flag is reset */ return RESET; } } /*! - \brief check EXMC flag is set or not - \param[in] bank: specifies the NAND bank , PC card bank or SDRAM device + \brief get EXMC flag status + \param[in] exmc_bank: specify the NAND bank , PC card bank or SDRAM device + only one parameter can be selected which is shown as below: \arg EXMC_BANK1_NAND: the NAND bank1 \arg EXMC_BANK2_NAND: the NAND bank2 \arg EXMC_BANK3_PCCARD: the PC Card bank \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 - \param[in] flag: specify get which flag + \param[in] flag: EXMC status and flag + only one parameter can be selected which is shown as below: \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status @@ -1009,32 +1041,34 @@ FlagStatus exmc_flag_get(uint32_t bank, uint32_t flag) { uint32_t status = 0x00000000U; - if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)) { /* NAND bank1,bank2 or PC card bank3 */ status = EXMC_NPINTEN(bank); - }else{ - /* SDRAM device0 or device1 */ + } else { + /* SDRAM device0 or device1 */ status = EXMC_SDSTAT; } - - if((status & flag) != (uint32_t)flag){ + + if((status & flag) != (uint32_t)flag) { /* flag is reset */ return RESET; - }else{ + } else { /* flag is set */ return SET; } } /*! - \brief clear EXMC flag - \param[in] bank: specifie the NAND bank , PCCARD bank or SDRAM device + \brief clear EXMC flag status + \param[in] exmc_bank: specify the NAND bank , PCCARD bank or SDRAM device + only one parameter can be selected which is shown as below: \arg EXMC_BANK1_NAND: the NAND bank1 \arg EXMC_BANK2_NAND: the NAND bank2 \arg EXMC_BANK3_PCCARD: the PC card bank \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 - \param[in] flag: specify get which flag + \param[in] flag: EXMC status and flag + only one parameter can be selected which is shown as below: \arg EXMC_NAND_PCCARD_FLAG_RISE: interrupt rising edge status \arg EXMC_NAND_PCCARD_FLAG_LEVEL: interrupt high-level status \arg EXMC_NAND_PCCARD_FLAG_FALL: interrupt falling edge status @@ -1046,133 +1080,140 @@ FlagStatus exmc_flag_get(uint32_t bank, uint32_t flag) */ void exmc_flag_clear(uint32_t bank, uint32_t flag) { - if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)) { /* NAND bank1,bank2 or PC card bank3 */ EXMC_NPINTEN(bank) &= ~flag; - }else{ + } else { /* SDRAM device0 or device1 */ EXMC_SDSTAT &= ~flag; - } + } } /*! - \brief check EXMC interrupt flag is set or not - \param[in] bank: specifies the NAND bank , PC card bank or SDRAM device + \brief enable EXMC interrupt + \param[in] bank: specify the NAND bank,PC card bank or SDRAM device + only one parameter can be selected which is shown as below: \arg EXMC_BANK1_NAND: the NAND bank1 \arg EXMC_BANK2_NAND: the NAND bank2 \arg EXMC_BANK3_PCCARD: the PC card bank \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 - \param[in] interrupt_source: specify get which interrupt flag - \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: interrupt source of rising edge - \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: interrupt source of high-level - \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: interrupt source of falling edge - \arg EXMC_SDRAM_INT_FLAG_REFRESH: interrupt source of refresh error + \param[in] interrupt: specify get which interrupt flag + only one parameter can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge + \arg EXMC_SDRAM_INT_REFRESH: interrupt source of refresh error \param[out] none - \retval FlagStatus: SET or RESET + \retval none */ -FlagStatus exmc_interrupt_flag_get(uint32_t bank, uint32_t interrupt_source) +void exmc_interrupt_enable(uint32_t bank, uint32_t interrupt) { - uint32_t status = 0x00000000U, interrupt_enable = 0x00000000U, interrupt_state = 0x00000000U; - - if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)) { /* NAND bank1,bank2 or PC card bank3 */ - status = EXMC_NPINTEN(bank); - interrupt_state = (status & (interrupt_source >> INTEN_INTS_OFFSET)); - }else{ - /* SDRAM device0 or device1 */ - status = EXMC_SDARI; - interrupt_state = (EXMC_SDSTAT & EXMC_SDSDAT_REIF); - } - - interrupt_enable = (status & interrupt_source); - - if ((interrupt_enable) && (interrupt_state)){ - /* interrupt flag is set */ - return SET; - }else{ - /* interrupt flag is reset */ - return RESET; + EXMC_NPINTEN(bank) |= interrupt; + } else { + /* SDRAM device0 or device1 */ + EXMC_SDARI |= EXMC_SDARI_REIE; } } /*! - \brief clear EXMC interrupt flag - \param[in] bank: specifies the NAND bank , PC card bank or SDRAM device + \brief disable EXMC interrupt + \param[in] bank: specify the NAND bank , PC card bank or SDRAM device + only one parameter can be selected which is shown as below: \arg EXMC_BANK1_NAND: the NAND bank1 \arg EXMC_BANK2_NAND: the NAND bank2 \arg EXMC_BANK3_PCCARD: the PC card bank \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 - \param[in] interrupt_source: specify get which interrupt flag - \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: interrupt source of rising edge - \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: interrupt source of high-level - \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: interrupt source of falling edge - \arg EXMC_SDRAM_INT_FLAG_REFRESH: interrupt source of refresh error + \param[in] interrupt: specify get which interrupt flag + only one parameter can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge + \arg EXMC_SDRAM_INT_REFRESH: interrupt source of refresh error \param[out] none \retval none */ -void exmc_interrupt_flag_clear(uint32_t bank, uint32_t interrupt_source) +void exmc_interrupt_disable(uint32_t bank, uint32_t interrupt) { - if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)) { /* NAND bank1,bank2 or PC card bank3 */ - EXMC_NPINTEN(bank) &= ~(interrupt_source >> INTEN_INTS_OFFSET); - }else{ + EXMC_NPINTEN(bank) &= ~interrupt; + } else { /* SDRAM device0 or device1 */ - EXMC_SDARI |= EXMC_SDARI_REC; + EXMC_SDARI &= ~EXMC_SDARI_REIE; } } /*! - \brief enable EXMC interrupt - \param[in] bank: specifies the NAND bank,PC card bank or SDRAM device + \brief get EXMC interrupt flag + \param[in] bank: specify the NAND bank , PC card bank or SDRAM device + only one parameter can be selected which is shown as below: \arg EXMC_BANK1_NAND: the NAND bank1 \arg EXMC_BANK2_NAND: the NAND bank2 \arg EXMC_BANK3_PCCARD: the PC card bank \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 - \param[in] interrupt_source: specify get which interrupt flag - \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge - \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level - \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge - \arg EXMC_SDRAM_INT_REFRESH: interrupt source of refresh error + \param[in] interrupt: EXMC interrupt flag + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: interrupt source of falling edge + \arg EXMC_SDRAM_INT_FLAG_REFRESH: interrupt source of refresh error \param[out] none - \retval none + \retval FlagStatus: SET or RESET */ -void exmc_interrupt_enable(uint32_t bank, uint32_t interrupt_source) +FlagStatus exmc_interrupt_flag_get(uint32_t bank, uint32_t interrupt) { - if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + uint32_t status = 0x00000000U, interrupt_enable = 0x00000000U, interrupt_state = 0x00000000U; + + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)) { /* NAND bank1,bank2 or PC card bank3 */ - EXMC_NPINTEN(bank) |= interrupt_source; - }else{ + status = EXMC_NPINTEN(bank); + interrupt_state = (status & (interrupt >> INTEN_INTS_OFFSET)); + } else { /* SDRAM device0 or device1 */ - EXMC_SDARI |= EXMC_SDARI_REIE; + status = EXMC_SDARI; + interrupt_state = (EXMC_SDSTAT & EXMC_SDSDAT_REIF); + } + + interrupt_enable = (status & interrupt); + + if((interrupt_enable) && (interrupt_state)) { + /* interrupt flag is set */ + return SET; + } else { + /* interrupt flag is reset */ + return RESET; } } /*! - \brief disable EXMC interrupt - \param[in] bank: specifies the NAND bank , PC card bank or SDRAM device + \brief clear EXMC interrupt flag + \param[in] bank: specify the NAND bank , PC card bank or SDRAM device + only one parameter can be selected which is shown as below: \arg EXMC_BANK1_NAND: the NAND bank1 \arg EXMC_BANK2_NAND: the NAND bank2 \arg EXMC_BANK3_PCCARD: the PC card bank \arg EXMC_SDRAM_DEVICE0: the SDRAM device0 \arg EXMC_SDRAM_DEVICE1: the SDRAM device1 - \param[in] interrupt_source: specify get which interrupt flag - \arg EXMC_NAND_PCCARD_INT_RISE: interrupt source of rising edge - \arg EXMC_NAND_PCCARD_INT_LEVEL: interrupt source of high-level - \arg EXMC_NAND_PCCARD_INT_FALL: interrupt source of falling edge - \arg EXMC_SDRAM_INT_REFRESH: interrupt source of refresh error + \param[in] interrupt: specify get which interrupt flag + only one parameter can be selected which is shown as below: + \arg EXMC_NAND_PCCARD_INT_FLAG_RISE: interrupt source of rising edge + \arg EXMC_NAND_PCCARD_INT_FLAG_LEVEL: interrupt source of high-level + \arg EXMC_NAND_PCCARD_INT_FLAG_FALL: interrupt source of falling edge + \arg EXMC_SDRAM_INT_FLAG_REFRESH: interrupt source of refresh error \param[out] none \retval none */ -void exmc_interrupt_disable(uint32_t bank, uint32_t interrupt_source) +void exmc_interrupt_flag_clear(uint32_t bank, uint32_t interrupt) { - if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)){ + if((EXMC_BANK1_NAND == bank) || (EXMC_BANK2_NAND == bank) || (EXMC_BANK3_PCCARD == bank)) { /* NAND bank1,bank2 or PC card bank3 */ - EXMC_NPINTEN(bank) &= ~interrupt_source; - }else{ + EXMC_NPINTEN(bank) &= ~(interrupt >> INTEN_INTS_OFFSET); + } else { /* SDRAM device0 or device1 */ - EXMC_SDARI &= ~EXMC_SDARI_REIE; + EXMC_SDARI |= EXMC_SDARI_REC; } } diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_exti.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_exti.c index ffa56cc5..70246c2e 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_exti.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_exti.c @@ -2,36 +2,33 @@ \file gd32f20x_exti.c \brief EXTI driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -56,7 +53,7 @@ void exti_deinit(void) } /*! - \brief initialize the EXTI + \brief initialize the EXTI line x \param[in] linex: EXTI line number, refer to exti_line_enum only one parameter can be selected which is shown as below: \arg EXTI_x (x=0..19): EXTI line x @@ -67,8 +64,9 @@ void exti_deinit(void) \param[in] trig_type: interrupt trigger type, refer to exti_trig_type_enum only one parameter can be selected which is shown as below: \arg EXTI_TRIG_RISING: rising edge trigger - \arg EXTI_TRIG_FALLING: falling edge trigger - \arg EXTI_TRIG_BOTH: rising edge and falling edge trigger + \arg EXTI_TRIG_FALLING: falling trigger + \arg EXTI_TRIG_BOTH: rising and falling trigger + \arg EXTI_TRIG_NONE: without rising edge or falling edge trigger \param[out] none \retval none */ @@ -79,9 +77,9 @@ void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum tr EXTI_EVEN &= ~(uint32_t)linex; EXTI_RTEN &= ~(uint32_t)linex; EXTI_FTEN &= ~(uint32_t)linex; - + /* set the EXTI mode and enable the interrupts or events from EXTI line x */ - switch(mode){ + switch(mode) { case EXTI_INTERRUPT: EXTI_INTEN |= (uint32_t)linex; break; @@ -91,9 +89,9 @@ void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum tr default: break; } - + /* set the EXTI trigger type */ - switch(trig_type){ + switch(trig_type) { case EXTI_TRIG_RISING: EXTI_RTEN |= (uint32_t)linex; EXTI_FTEN &= ~(uint32_t)linex; @@ -106,6 +104,7 @@ void exti_init(exti_line_enum linex, exti_mode_enum mode, exti_trig_type_enum tr EXTI_RTEN |= (uint32_t)linex; EXTI_FTEN |= (uint32_t)linex; break; + case EXTI_TRIG_NONE: default: break; } @@ -125,29 +124,29 @@ void exti_interrupt_enable(exti_line_enum linex) } /*! - \brief enable the events from EXTI line x + \brief disable the interrupts from EXTI line x \param[in] linex: EXTI line number, refer to exti_line_enum only one parameter can be selected which is shown as below: \arg EXTI_x (x=0..19): EXTI line x \param[out] none \retval none */ -void exti_event_enable(exti_line_enum linex) +void exti_interrupt_disable(exti_line_enum linex) { - EXTI_EVEN |= (uint32_t)linex; + EXTI_INTEN &= ~(uint32_t)linex; } /*! - \brief disable the interrupt from EXTI line x + \brief enable the events from EXTI line x \param[in] linex: EXTI line number, refer to exti_line_enum only one parameter can be selected which is shown as below: \arg EXTI_x (x=0..19): EXTI line x \param[out] none \retval none */ -void exti_interrupt_disable(exti_line_enum linex) +void exti_event_enable(exti_line_enum linex) { - EXTI_INTEN &= ~(uint32_t)linex; + EXTI_EVEN |= (uint32_t)linex; } /*! @@ -164,92 +163,87 @@ void exti_event_disable(exti_line_enum linex) } /*! - \brief get EXTI lines flag + \brief enable the software interrupt event from EXTI line x \param[in] linex: EXTI line number, refer to exti_line_enum only one parameter can be selected which is shown as below: \arg EXTI_x (x=0..19): EXTI line x \param[out] none - \retval FlagStatus: status of flag (RESET or SET) + \retval none */ -FlagStatus exti_flag_get(exti_line_enum linex) +void exti_software_interrupt_enable(exti_line_enum linex) { - if(RESET != (EXTI_PD & (uint32_t)linex)){ - return SET; - }else{ - return RESET; - } + EXTI_SWIEV |= (uint32_t)linex; } /*! - \brief clear EXTI lines pending flag + \brief disable the software interrupt event from EXTI line x \param[in] linex: EXTI line number, refer to exti_line_enum only one parameter can be selected which is shown as below: \arg EXTI_x (x=0..19): EXTI line x \param[out] none \retval none */ -void exti_flag_clear(exti_line_enum linex) +void exti_software_interrupt_disable(exti_line_enum linex) { - EXTI_PD = (uint32_t)linex; + EXTI_SWIEV &= ~(uint32_t)linex; } /*! - \brief get EXTI lines flag when the interrupt flag is set + \brief get EXTI line x interrupt pending flag \param[in] linex: EXTI line number, refer to exti_line_enum only one parameter can be selected which is shown as below: \arg EXTI_x (x=0..19): EXTI line x \param[out] none \retval FlagStatus: status of flag (RESET or SET) */ -FlagStatus exti_interrupt_flag_get(exti_line_enum linex) +FlagStatus exti_flag_get(exti_line_enum linex) { - uint32_t flag_left, flag_right; - - flag_left = EXTI_PD & (uint32_t)linex; - flag_right = EXTI_INTEN & (uint32_t)linex; - - if((RESET != flag_left) && (RESET != flag_right)){ + if(RESET != (EXTI_PD & (uint32_t)linex)) { return SET; - }else{ + } else { return RESET; } } /*! - \brief clear EXTI lines pending flag + \brief clear EXTI line x interrupt pending flag \param[in] linex: EXTI line number, refer to exti_line_enum only one parameter can be selected which is shown as below: \arg EXTI_x (x=0..19): EXTI line x \param[out] none \retval none */ -void exti_interrupt_flag_clear(exti_line_enum linex) +void exti_flag_clear(exti_line_enum linex) { EXTI_PD = (uint32_t)linex; } /*! - \brief enable EXTI software interrupt event + \brief get EXTI line x interrupt pending flag \param[in] linex: EXTI line number, refer to exti_line_enum only one parameter can be selected which is shown as below: \arg EXTI_x (x=0..19): EXTI line x \param[out] none - \retval none + \retval FlagStatus: status of flag (RESET or SET) */ -void exti_software_interrupt_enable(exti_line_enum linex) +FlagStatus exti_interrupt_flag_get(exti_line_enum linex) { - EXTI_SWIEV |= (uint32_t)linex; + if(RESET != (EXTI_PD & (uint32_t)linex)) { + return SET; + } else { + return RESET; + } } /*! - \brief disable EXTI software interrupt event + \brief clear EXTI line x interrupt pending flag \param[in] linex: EXTI line number, refer to exti_line_enum only one parameter can be selected which is shown as below: \arg EXTI_x (x=0..19): EXTI line x \param[out] none \retval none */ -void exti_software_interrupt_disable(exti_line_enum linex) +void exti_interrupt_flag_clear(exti_line_enum linex) { - EXTI_SWIEV &= ~(uint32_t)linex; + EXTI_PD = (uint32_t)linex; } diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_fmc.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_fmc.c index f10bf34c..aee94fae 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_fmc.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_fmc.c @@ -2,44 +2,51 @@ \file gd32f20x_fmc.c \brief FMC driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "gd32f20x_fmc.h" +/* return the FMC bank0 state */ +fmc_state_enum fmc_bank0_state_get(void); /** AvV **/ +/* return the FMC bank1 state */ +fmc_state_enum fmc_bank1_state_get(void); /** AvV **/ +/* check FMC bank0 ready or not */ +static fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout); +/* check FMC bank1 ready or not */ +static fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout); + /*! \brief set the wait state counter value - \param[in] wscnt£ºwait state counter value + \param[in] wscnt��wait state counter value + only one parameter can be selected which is shown as below: \arg WS_WSCNT_0: FMC 0 wait state \arg WS_WSCNT_1: FMC 1 wait state \arg WS_WSCNT_2: FMC 2 wait state @@ -49,7 +56,7 @@ OF SUCH DAMAGE. void fmc_wscnt_set(uint32_t wscnt) { uint32_t reg; - + reg = FMC_WS; /* set the wait state counter value */ reg &= ~FMC_WS_WSCNT; @@ -64,14 +71,14 @@ void fmc_wscnt_set(uint32_t wscnt) */ void fmc_unlock(void) { - if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){ + if((RESET != (FMC_CTL0 & FMC_CTL0_LK))) { /* write the FMC unlock key */ FMC_KEY0 = UNLOCK_KEY0; FMC_KEY0 = UNLOCK_KEY1; } - if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_SIZE < FMC_SIZE) { /* write the FMC unlock key */ - if(RESET != (FMC_CTL1 & FMC_CTL1_LK)){ + if(RESET != (FMC_CTL1 & FMC_CTL1_LK)) { FMC_KEY1 = UNLOCK_KEY0; FMC_KEY1 = UNLOCK_KEY1; } @@ -79,7 +86,7 @@ void fmc_unlock(void) } /*! - \brief unlock the FMC bank0 operation + \brief unlock the FMC bank0 operation this function can be used for all GD32F20x devices. for GD32F20x with flash more than 512KB, this function unlocks bank0. for GD32F20x with flash no more than 512KB and it is equivalent to fmc_unlock function. @@ -89,7 +96,7 @@ void fmc_unlock(void) */ void fmc_bank0_unlock(void) { - if((RESET != (FMC_CTL0 & FMC_CTL0_LK))){ + if((RESET != (FMC_CTL0 & FMC_CTL0_LK))) { /* write the FMC unlock key */ FMC_KEY0 = UNLOCK_KEY0; FMC_KEY0 = UNLOCK_KEY1; @@ -97,7 +104,7 @@ void fmc_bank0_unlock(void) } /*! - \brief unlock the FMC bank1 operation + \brief unlock the FMC bank1 operation this function can be used for GD32F20x with flash more than 512KB. \param[in] none \param[out] none @@ -105,7 +112,7 @@ void fmc_bank0_unlock(void) */ void fmc_bank1_unlock(void) { - if((RESET != (FMC_CTL1 & FMC_CTL1_LK))){ + if((RESET != (FMC_CTL1 & FMC_CTL1_LK))) { /* write the FMC unlock key */ FMC_KEY1 = UNLOCK_KEY0; FMC_KEY1 = UNLOCK_KEY1; @@ -122,8 +129,8 @@ void fmc_lock(void) { /* set the LK bit */ FMC_CTL0 |= FMC_CTL0_LK; - - if(FMC_BANK0_SIZE < FMC_SIZE){ + + if(FMC_BANK0_SIZE < FMC_SIZE) { /* set the LK bit */ FMC_CTL1 |= FMC_CTL1_LK; } @@ -167,11 +174,11 @@ fmc_state_enum fmc_page_erase(uint32_t page_address) { fmc_state_enum fmc_state; /* flash size is greater than 512k */ - if(FMC_BANK0_SIZE < FMC_SIZE){ - if(FMC_BANK0_END_ADDRESS > page_address){ + if(FMC_BANK0_SIZE < FMC_SIZE) { + if(FMC_BANK0_END_ADDRESS > page_address) { fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); /* if the last operation is completed, start page erase */ - if(FMC_READY == fmc_state){ + if(FMC_READY == fmc_state) { FMC_CTL0 |= FMC_CTL0_PER; FMC_ADDR0 = page_address; FMC_CTL0 |= FMC_CTL0_START; @@ -180,14 +187,14 @@ fmc_state_enum fmc_page_erase(uint32_t page_address) /* reset the PER bit */ FMC_CTL0 &= ~FMC_CTL0_PER; } - }else{ + } else { /* wait for the FMC ready */ fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); /* if the last operation is completed, start page erase */ - if(FMC_READY == fmc_state){ + if(FMC_READY == fmc_state) { FMC_CTL1 |= FMC_CTL1_PER; FMC_ADDR1 = page_address; - if(FMC_OBSTAT & FMC_OBSTAT_SPC){ + if(FMC_OBSTAT & FMC_OBSTAT_SPC) { FMC_ADDR0 = page_address; } FMC_CTL1 |= FMC_CTL1_START; @@ -197,10 +204,10 @@ fmc_state_enum fmc_page_erase(uint32_t page_address) FMC_CTL1 &= ~FMC_CTL1_PER; } } - }else{ + } else { fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); /* if the last operation is completed, start page erase */ - if(FMC_READY == fmc_state){ + if(FMC_READY == fmc_state) { FMC_CTL0 |= FMC_CTL0_PER; FMC_ADDR0 = page_address; FMC_CTL0 |= FMC_CTL0_START; @@ -224,10 +231,10 @@ fmc_state_enum fmc_mass_erase(void) { fmc_state_enum fmc_state; /* flash size is greater than 512k */ - if(FMC_BANK0_SIZE < FMC_SIZE){ + if(FMC_BANK0_SIZE < FMC_SIZE) { /* wait for the FMC ready */ fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - if(FMC_READY == fmc_state){ + if(FMC_READY == fmc_state) { /* start whole chip erase */ FMC_CTL0 |= FMC_CTL0_MER; FMC_CTL0 |= FMC_CTL0_START; @@ -237,7 +244,7 @@ fmc_state_enum fmc_mass_erase(void) FMC_CTL0 &= ~FMC_CTL0_MER; } fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); - if(FMC_READY == fmc_state){ + if(FMC_READY == fmc_state) { /* start whole chip erase */ FMC_CTL1 |= FMC_CTL1_MER; FMC_CTL1 |= FMC_CTL1_START; @@ -246,20 +253,20 @@ fmc_state_enum fmc_mass_erase(void) /* reset the MER bit */ FMC_CTL1 &= ~FMC_CTL1_MER; } - }else{ + } else { fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_READY == fmc_state){ + + if(FMC_READY == fmc_state) { /* start whole chip erase */ FMC_CTL0 |= FMC_CTL0_MER; - FMC_CTL0 |= FMC_CTL0_START; + FMC_CTL0 |= FMC_CTL0_START; /* wait for the FMC ready */ fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); /* reset the MER bit */ FMC_CTL0 &= ~FMC_CTL0_MER; } } - /* return the FMC state */ + /* return the FMC state */ return fmc_state; } @@ -275,7 +282,7 @@ fmc_state_enum fmc_bank0_erase(void) /* wait for the FMC ready */ fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - if(FMC_READY == fmc_state){ + if(FMC_READY == fmc_state) { /* start FMC bank0 erase */ FMC_CTL0 |= FMC_CTL0_MER; FMC_CTL0 |= FMC_CTL0_START; @@ -284,7 +291,7 @@ fmc_state_enum fmc_bank0_erase(void) /* reset the MER bit */ FMC_CTL0 &= ~FMC_CTL0_MER; } - /* return the fmc state */ + /* return the FMC state */ return fmc_state; } @@ -299,8 +306,8 @@ fmc_state_enum fmc_bank1_erase(void) fmc_state_enum fmc_state = FMC_READY; /* wait for the FMC ready */ fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_READY == fmc_state){ + + if(FMC_READY == fmc_state) { /* start FMC bank1 erase */ FMC_CTL1 |= FMC_CTL1_MER; FMC_CTL1 |= FMC_CTL1_START; @@ -309,7 +316,7 @@ fmc_state_enum fmc_bank1_erase(void) /* reset the MER bit */ FMC_CTL1 &= ~FMC_CTL1_MER; } - /* return the fmc state */ + /* return the FMC state */ return fmc_state; } @@ -324,11 +331,11 @@ fmc_state_enum fmc_word_program(uint32_t address, uint32_t data) { fmc_state_enum fmc_state = FMC_READY; /* flash size is greater than 512k */ - if(FMC_BANK0_SIZE < FMC_SIZE){ - if(FMC_BANK0_END_ADDRESS > address){ - fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_READY == fmc_state){ + if(FMC_BANK0_SIZE < FMC_SIZE) { + if(FMC_BANK0_END_ADDRESS > address) { + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state) { /* set the PG bit to start program */ FMC_CTL0 |= FMC_CTL0_PG; REG32(address) = data; @@ -337,10 +344,10 @@ fmc_state_enum fmc_word_program(uint32_t address, uint32_t data) /* reset the PG bit */ FMC_CTL0 &= ~FMC_CTL0_PG; } - }else{ - fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_READY == fmc_state){ + } else { + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state) { /* set the PG bit to start program */ FMC_CTL1 |= FMC_CTL1_PG; REG32(address) = data; @@ -350,10 +357,10 @@ fmc_state_enum fmc_word_program(uint32_t address, uint32_t data) FMC_CTL1 &= ~FMC_CTL1_PG; } } - }else{ + } else { fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_READY == fmc_state){ + + if(FMC_READY == fmc_state) { /* set the PG bit to start program */ FMC_CTL0 |= FMC_CTL0_PG; REG32(address) = data; @@ -361,7 +368,7 @@ fmc_state_enum fmc_word_program(uint32_t address, uint32_t data) fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); /* reset the PG bit */ FMC_CTL0 &= ~FMC_CTL0_PG; - } + } } /* return the FMC state */ return fmc_state; @@ -378,11 +385,11 @@ fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data) { fmc_state_enum fmc_state = FMC_READY; /* flash size is greater than 512k */ - if(FMC_BANK0_SIZE < FMC_SIZE){ - if(FMC_BANK0_END_ADDRESS > address){ - fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_READY == fmc_state){ + if(FMC_BANK0_SIZE < FMC_SIZE) { + if(FMC_BANK0_END_ADDRESS > address) { + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state) { /* set the PG bit to start program */ FMC_CTL0 |= FMC_CTL0_PG; REG16(address) = data; @@ -391,10 +398,10 @@ fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data) /* reset the PG bit */ FMC_CTL0 &= ~FMC_CTL0_PG; } - }else{ - fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_READY == fmc_state){ + } else { + fmc_state = fmc_bank1_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_READY == fmc_state) { /* set the PG bit to start program */ FMC_CTL1 |= FMC_CTL1_PG; REG16(address) = data; @@ -404,10 +411,10 @@ fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data) FMC_CTL1 &= ~FMC_CTL1_PG; } } - }else{ + } else { fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_READY == fmc_state){ + + if(FMC_READY == fmc_state) { /* set the PG bit to start program */ FMC_CTL0 |= FMC_CTL0_PG; REG16(address) = data; @@ -415,7 +422,7 @@ fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data) fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); /* reset the PG bit */ FMC_CTL0 &= ~FMC_CTL0_PG; - } + } } /* return the FMC state */ return fmc_state; @@ -429,14 +436,14 @@ fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data) */ void ob_unlock(void) { - if(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){ + if(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)) { /* write the FMC key */ FMC_OBKEY = UNLOCK_KEY0; FMC_OBKEY = UNLOCK_KEY1; } /* wait until OBWEN bit is set by hardware */ - while(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)){ + while(RESET == (FMC_CTL0 & FMC_CTL0_OBWEN)) { } } @@ -466,11 +473,11 @@ fmc_state_enum ob_erase(void) fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); /* check the option byte security protection value */ - if(RESET != ob_spc_get()){ - temp_spc = FMC_USPC; + if(RESET != ob_spc_get()) { + temp_spc = FMC_USPC; } - if(FMC_READY == fmc_state){ + if(FMC_READY == fmc_state) { /* start erase the option byte */ FMC_CTL0 |= FMC_CTL0_OBER; @@ -478,22 +485,22 @@ fmc_state_enum ob_erase(void) /* wait for the FMC ready */ fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_READY == fmc_state){ + + if(FMC_READY == fmc_state) { /* reset the OBER bit */ FMC_CTL0 &= ~FMC_CTL0_OBER; /* set the OBPG bit */ FMC_CTL0 |= FMC_CTL0_OBPG; /* no security protection */ - OB_SPC = (uint16_t)temp_spc; + OB_SPC = (uint16_t)temp_spc; /* wait for the FMC ready */ - fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - if(FMC_TOERR != fmc_state){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + if(FMC_TOERR != fmc_state) { /* reset the OBPG bit */ FMC_CTL0 &= ~FMC_CTL0_OBPG; } - }else{ - if(FMC_TOERR != fmc_state){ + } else { + if(FMC_TOERR != fmc_state) { /* reset the OBPG bit */ FMC_CTL0 &= ~FMC_CTL0_OBPG; } @@ -505,10 +512,11 @@ fmc_state_enum ob_erase(void) /*! \brief enable write protection - \param[in] ob_wp: specify sector to be write protected, set the bit to 1 if - you want to protect the corresponding pages. meanwhile, sector - macro could used to set specific sector write protected. + \param[in] ob_wp: specify sector to be write protected, set the bit to 1 if + you want to protect the corresponding pages. meanwhile, sector + macro could used to set specific sector write protected. one or more parameters can be selected which are shown as below: + OB_WP_NONE: disable all erase/program protection \arg OB_WPx(x = 0..31): write protect specify sector \arg OB_WP_ALL: write protect all sector \param[out] none @@ -526,40 +534,40 @@ fmc_state_enum ob_write_protection_enable(uint32_t ob_wp) temp_wp2 = (uint16_t)((ob_wp & OB_WP2_WP2) >> 16U); temp_wp3 = (uint16_t)((ob_wp & OB_WP3_WP3) >> 24U); - if(FMC_READY == fmc_state){ - + if(FMC_READY == fmc_state) { + /* set the OBPG bit*/ FMC_CTL0 |= FMC_CTL0_OBPG; - if(0xFFU != temp_wp0){ + if(0xFFU != temp_wp0) { OB_WP0 = temp_wp0; - + /* wait for the FMC ready */ fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); } - if((FMC_READY == fmc_state) && (0xFFU != temp_wp1)){ + if((FMC_READY == fmc_state) && (0xFFU != temp_wp1)) { OB_WP1 = temp_wp1; - + /* wait for the FMC ready */ fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); } - if((FMC_READY == fmc_state) && (0xFFU != temp_wp2)){ + if((FMC_READY == fmc_state) && (0xFFU != temp_wp2)) { OB_WP2 = temp_wp2; - + /* wait for the FMC ready */ fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); } - if((FMC_READY == fmc_state) && (0xFFU != temp_wp3)){ + if((FMC_READY == fmc_state) && (0xFFU != temp_wp3)) { OB_WP3 = temp_wp3; - + /* wait for the FMC ready */ fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); } - if(FMC_TOERR != fmc_state){ + if(FMC_TOERR != fmc_state) { /* reset the OBPG bit */ FMC_CTL0 &= ~FMC_CTL0_OBPG; } - } + } /* return the FMC state */ return fmc_state; } @@ -577,31 +585,31 @@ fmc_state_enum ob_security_protection_config(uint8_t ob_spc) { fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - if(FMC_READY == fmc_state){ + if(FMC_READY == fmc_state) { FMC_CTL0 |= FMC_CTL0_OBER; FMC_CTL0 |= FMC_CTL0_START; - + /* wait for the FMC ready */ fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_READY == fmc_state){ + + if(FMC_READY == fmc_state) { /* reset the OBER bit */ FMC_CTL0 &= ~FMC_CTL0_OBER; - + /* start the option byte program */ FMC_CTL0 |= FMC_CTL0_OBPG; - + OB_SPC = (uint16_t)ob_spc; /* wait for the FMC ready */ - fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_TOERR != fmc_state){ + fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); + + if(FMC_TOERR != fmc_state) { /* reset the OBPG bit */ FMC_CTL0 &= ~FMC_CTL0_OBPG; } - }else{ - if(FMC_TOERR != fmc_state){ + } else { + if(FMC_TOERR != fmc_state) { /* reset the OBER bit */ FMC_CTL0 &= ~FMC_CTL0_OBER; } @@ -612,17 +620,21 @@ fmc_state_enum ob_security_protection_config(uint8_t ob_spc) } /*! - \brief program the FMC user option byte + \brief program option bytes user \param[in] ob_fwdgt: option byte watchdog value + only one parameter can be selected which is shown as below: \arg OB_FWDGT_SW: software free watchdog \arg OB_FWDGT_HW: hardware free watchdog \param[in] ob_deepsleep: option byte deepsleep reset value + only one parameter can be selected which is shown as below: \arg OB_DEEPSLEEP_NRST: no reset when entering deepsleep mode - \arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode + \arg OB_DEEPSLEEP_RST: generate a reset instead of entering deepsleep mode \param[in] ob_stdby:option byte standby reset value + only one parameter can be selected which is shown as below: \arg OB_STDBY_NRST: no reset when entering standby mode \arg OB_STDBY_RST: generate a reset instead of entering standby mode \param[in] ob_boot: specifies the option byte boot bank value + only one parameter can be selected which is shown as below: \arg OB_BOOT_B0: boot from bank0 \arg OB_BOOT_B1: boot from bank1 or bank0 if bank1 is void \param[out] none @@ -635,18 +647,18 @@ fmc_state_enum ob_user_write(uint8_t ob_fwdgt, uint8_t ob_deepsleep, uint8_t ob_ /* wait for the FMC ready */ fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_READY == fmc_state){ + + if(FMC_READY == fmc_state) { /* set the OBPG bit*/ - FMC_CTL0 |= FMC_CTL0_OBPG; + FMC_CTL0 |= FMC_CTL0_OBPG; temp = ((uint8_t)((uint8_t)((uint8_t)(ob_boot | ob_fwdgt) | ob_deepsleep) | ob_stdby) | OB_USER_MASK); OB_USER = (uint16_t)temp; - + /* wait for the FMC ready */ fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - if(FMC_TOERR != fmc_state){ + if(FMC_TOERR != fmc_state) { /* reset the OBPG bit */ FMC_CTL0 &= ~FMC_CTL0_OBPG; } @@ -666,15 +678,15 @@ fmc_state_enum ob_data_program(uint32_t address, uint8_t data) { fmc_state_enum fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - if(FMC_READY == fmc_state){ + if(FMC_READY == fmc_state) { /* set the OBPG bit */ - FMC_CTL0 |= FMC_CTL0_OBPG; + FMC_CTL0 |= FMC_CTL0_OBPG; REG16(address) = data; - + /* wait for the FMC ready */ fmc_state = fmc_bank0_ready_wait(FMC_TIMEOUT_COUNT); - - if(FMC_TOERR != fmc_state){ + + if(FMC_TOERR != fmc_state) { /* reset the OBPG bit */ FMC_CTL0 &= ~FMC_CTL0_OBPG; } @@ -684,7 +696,7 @@ fmc_state_enum ob_data_program(uint32_t address, uint8_t data) } /*! - \brief get the FMC user option byte + \brief get the FMC option bytes user \param[in] none \param[out] none \retval the FMC user option byte values @@ -696,7 +708,7 @@ uint8_t ob_user_get(void) } /*! - \brief get OB_DATA in register FMC_OBSTAT + \brief get the FMC option bytes data \param[in] none \param[out] none \retval ob_data @@ -728,46 +740,14 @@ FlagStatus ob_spc_get(void) { FlagStatus spc_state = RESET; - if(RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)){ + if(RESET != (FMC_OBSTAT & FMC_OBSTAT_SPC)) { spc_state = SET; - }else{ + } else { spc_state = RESET; } return spc_state; } -/*! - \brief enable FMC interrupt - \param[in] interrupt: the FMC interrupt source - only one parameter can be selected which is shown as below: - \arg FMC_INT_BANK0_END: enable FMC end of program interrupt - \arg FMC_INT_BANK0_ERR: enable FMC error interrupt - \arg FMC_INT_BANK1_END: enable FMC bank1 end of program interrupt - \arg FMC_INT_BANK1_ERR: enable FMC bank1 error interrupt - \param[out] none - \retval none -*/ -void fmc_interrupt_enable(uint32_t interrupt) -{ - FMC_REG_VAL(interrupt) |= BIT(FMC_BIT_POS(interrupt)); -} - -/*! - \brief disable FMC interrupt - \param[in] interrupt: the FMC interrupt source - only one parameter can be selected which is shown as below: - \arg FMC_INT_BANK0_END: enable FMC end of program interrupt - \arg FMC_INT_BANK0_ERR: enable FMC error interrupt - \arg FMC_INT_BANK1_END: enable FMC bank1 end of program interrupt - \arg FMC_INT_BANK1_ERR: enable FMC bank1 error interrupt - \param[out] none - \retval none -*/ -void fmc_interrupt_disable(uint32_t interrupt) -{ - FMC_REG_VAL(interrupt) &= ~BIT(FMC_BIT_POS(interrupt)); -} - /*! \brief check flag is set or not \param[in] flag: check FMC flag @@ -786,9 +766,9 @@ void fmc_interrupt_disable(uint32_t interrupt) */ FlagStatus fmc_flag_get(uint32_t flag) { - if(RESET != (FMC_REG_VAL(flag) & BIT(FMC_BIT_POS(flag)))){ + if(RESET != (FMC_REG_VAL(flag) & BIT(FMC_BIT_POS(flag)))) { return SET; - }else{ + } else { return RESET; } } @@ -811,9 +791,41 @@ void fmc_flag_clear(uint32_t flag) FMC_REG_VAL(flag) |= BIT(FMC_BIT_POS(flag)); } +/*! + \brief enable FMC interrupt + \param[in] interrupt: the FMC interrupt source + only one parameter can be selected which is shown as below: + \arg FMC_INT_BANK0_END: FMC bank0 end of program interrupt + \arg FMC_INT_BANK0_ERR: FMC bank0 error interrupt + \arg FMC_INT_BANK1_END: FMC bank1 end of program interrupt + \arg FMC_INT_BANK1_ERR: FMC bank1 error interrupt + \param[out] none + \retval none +*/ +void fmc_interrupt_enable(fmc_interrupt_enum interrupt) +{ + FMC_REG_VAL(interrupt) |= BIT(FMC_BIT_POS(interrupt)); +} + +/*! + \brief disable FMC interrupt + \param[in] interrupt: the FMC interrupt source + only one parameter can be selected which is shown as below: + \arg FMC_INT_BANK0_END: FMC bank0 end of program interrupt + \arg FMC_INT_BANK0_ERR: FMC bank0 error interrupt + \arg FMC_INT_BANK1_END: FMC bank1 end of program interrupt + \arg FMC_INT_BANK1_ERR: FMC bank1 error interrupt + \param[out] none + \retval none +*/ +void fmc_interrupt_disable(fmc_interrupt_enum interrupt) +{ + FMC_REG_VAL(interrupt) &= ~BIT(FMC_BIT_POS(interrupt)); +} + /*! \brief get FMC interrupt flag state - \param[in] flag: FMC interrupt flags, refer to fmc_interrupt_flag_enum + \param[in] int_flag: FMC interrupt flags, refer to fmc_interrupt_flag_enum only one parameter can be selected which is shown as below: \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit @@ -824,33 +836,33 @@ void fmc_flag_clear(uint32_t flag) \param[out] none \retval FlagStatus: SET or RESET */ -FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag) -{ - FlagStatus ret1 = RESET; - FlagStatus ret2 = RESET; - - if(FMC_STAT0_REG_OFFSET == FMC_REG_OFFSET_GET(flag)){ - /* get the staus of interrupt flag */ - ret1 = (FlagStatus)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag))); - /* get the staus of interrupt enale bit */ - ret2 = (FlagStatus)(FMC_CTL0 & BIT(FMC_BIT_POS1(flag))); - }else{ - /* get the staus of interrupt flag */ - ret1 = (FlagStatus)(FMC_REG_VALS(flag) & BIT(FMC_BIT_POS0(flag))); - /* get the staus of interrupt enale bit */ - ret2 = (FlagStatus)(FMC_CTL1 & BIT(FMC_BIT_POS1(flag))); +FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum int_flag) +{ + uint32_t ret1 = RESET; + uint32_t ret2 = RESET; + + if(FMC_STAT0_REG_OFFSET == FMC_REG_OFFSET_GET(int_flag)) { + /* get the status of interrupt flag */ + ret1 = (uint32_t)(FMC_REG_VALS(int_flag) & BIT(FMC_BIT_POS0(int_flag))); + /* get the status of interrupt enable bit */ + ret2 = (uint32_t)(FMC_CTL0 & BIT(FMC_BIT_POS1(int_flag))); + } else { + /* get the status of interrupt flag */ + ret1 = (uint32_t)(FMC_REG_VALS(int_flag) & BIT(FMC_BIT_POS0(int_flag))); + /* get the status of interrupt enable bit */ + ret2 = (uint32_t)(FMC_CTL1 & BIT(FMC_BIT_POS1(int_flag))); } - if(ret1 && ret2){ + if(ret1 && ret2) { return SET; - }else{ + } else { return RESET; } } /*! \brief clear FMC interrupt flag state - \param[in] flag: FMC interrupt flags, refer to can_interrupt_flag_enum + \param[in] int_flag: FMC interrupt flags, refer to can_interrupt_flag_enum only one parameter can be selected which is shown as below: \arg FMC_INT_FLAG_BANK0_PGERR: FMC bank0 operation error interrupt flag bit \arg FMC_INT_FLAG_BANK0_WPERR: FMC bank0 erase/program protection error interrupt flag bit @@ -861,9 +873,9 @@ FlagStatus fmc_interrupt_flag_get(fmc_interrupt_flag_enum flag) \param[out] none \retval none */ -void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag) +void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum int_flag) { - FMC_REG_VALS(flag) |= BIT(FMC_BIT_POS0(flag)); + FMC_REG_VALS(int_flag) |= BIT(FMC_BIT_POS0(int_flag)); } /*! @@ -872,18 +884,18 @@ void fmc_interrupt_flag_clear(fmc_interrupt_flag_enum flag) \param[out] none \retval state of FMC, refer to fmc_state_enum */ -fmc_state_enum fmc_bank0_state_get(void) +fmc_state_enum fmc_bank0_state_get(void) /** AvV **/ { fmc_state_enum fmc_state = FMC_READY; - - if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_BUSY)){ + + if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_BUSY)) { fmc_state = FMC_BUSY; - }else{ - if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_WPERR)){ + } else { + if((uint32_t)0x00U != (FMC_STAT0 & FMC_STAT0_WPERR)) { fmc_state = FMC_WPERR; - }else{ - if((uint32_t)0x00U != (FMC_STAT0 & (FMC_STAT0_PGERR))){ - fmc_state = FMC_PGERR; + } else { + if((uint32_t)0x00U != (FMC_STAT0 & (FMC_STAT0_PGERR))) { + fmc_state = FMC_PGERR; } } } @@ -897,18 +909,18 @@ fmc_state_enum fmc_bank0_state_get(void) \param[out] none \retval state of FMC, refer to fmc_state_enum */ -fmc_state_enum fmc_bank1_state_get(void) +fmc_state_enum fmc_bank1_state_get(void) /** AvV **/ { fmc_state_enum fmc_state = FMC_READY; - if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_BUSY)){ + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_BUSY)) { fmc_state = FMC_BUSY; - }else{ - if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_WPERR)){ + } else { + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_WPERR)) { fmc_state = FMC_WPERR; - }else{ - if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_PGERR)){ - fmc_state = FMC_PGERR; + } else { + if((uint32_t)0x00U != (FMC_STAT1 & FMC_STAT1_PGERR)) { + fmc_state = FMC_PGERR; } } } @@ -923,18 +935,18 @@ fmc_state_enum fmc_bank1_state_get(void) \param[out] none \retval state of FMC, refer to fmc_state_enum */ -fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout) +static fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout) { fmc_state_enum fmc_state = FMC_BUSY; - + /* wait for FMC ready */ - do{ + do { /* get FMC state */ fmc_state = fmc_bank0_state_get(); timeout--; - }while((FMC_BUSY == fmc_state) && (0x00U != timeout)); - - if(FMC_BUSY == fmc_state){ + } while((FMC_BUSY == fmc_state) && (0x00U != timeout)); + + if(FMC_BUSY == fmc_state) { fmc_state = FMC_TOERR; } /* return the FMC state */ @@ -947,18 +959,18 @@ fmc_state_enum fmc_bank0_ready_wait(uint32_t timeout) \param[out] none \retval state of FMC, refer to fmc_state_enum */ -fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout) +static fmc_state_enum fmc_bank1_ready_wait(uint32_t timeout) { fmc_state_enum fmc_state = FMC_BUSY; - + /* wait for FMC ready */ - do{ + do { /* get FMC state */ fmc_state = fmc_bank1_state_get(); timeout--; - }while((FMC_BUSY == fmc_state) && (0x00U != timeout)); - - if(FMC_BUSY == fmc_state){ + } while((FMC_BUSY == fmc_state) && (0x00U != timeout)); + + if(FMC_BUSY == fmc_state) { fmc_state = FMC_TOERR; } /* return the FMC state */ diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_fwdgt.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_fwdgt.c index 0afbec24..1c7fdd36 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_fwdgt.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_fwdgt.c @@ -2,46 +2,38 @@ \file gd32f20x_fwdgt.c \brief FWDGT driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "gd32f20x_fwdgt.h" -/* write value to FWDGT_CTL_CMD bit field */ -#define CTL_CMD(regval) (BITS(0,15) & ((uint32_t)(regval) << 0)) -/* write value to FWDGT_RLD_RLD bit field */ -#define RLD_RLD(regval) (BITS(0,11) & ((uint32_t)(regval) << 0)) - /*! \brief enable write access to FWDGT_PSC and FWDGT_RLD \param[in] none @@ -75,6 +67,71 @@ void fwdgt_enable(void) FWDGT_CTL = FWDGT_KEY_ENABLE; } +/*! + \brief configure the free watchdog timer counter prescaler value + \param[in] prescaler_value: specify prescaler value + only one parameter can be selected which is shown as below: + \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 + \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 + \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 + \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 + \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 + \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 + \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value) +{ + uint32_t timeout = FWDGT_PSC_TIMEOUT; + uint32_t flag_status = RESET; + + /* enable write access to FWDGT_PSC */ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; + + /* wait until the PUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_PUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if ((uint32_t)RESET != flag_status){ + return ERROR; + } + + /* configure FWDGT */ + FWDGT_PSC = (uint32_t)prescaler_value; + + return SUCCESS; +} + +/*! + \brief configure the free watchdog timer counter reload value + \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus fwdgt_reload_value_config(uint16_t reload_value) +{ + uint32_t timeout = FWDGT_RLD_TIMEOUT; + uint32_t flag_status = RESET; + + /* enable write access to FWDGT_RLD */ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; + + /* wait until the RUD flag to be reset */ + do{ + flag_status = FWDGT_STAT & FWDGT_STAT_RUD; + }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if ((uint32_t)RESET != flag_status){ + return ERROR; + } + + FWDGT_RLD = RLD_RLD(reload_value); + + return SUCCESS; +} + /*! \brief reload the counter of FWDGT \param[in] none @@ -105,16 +162,16 @@ ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) { uint32_t timeout = FWDGT_PSC_TIMEOUT; uint32_t flag_status = RESET; - + /* enable write access to FWDGT_PSC,and FWDGT_RLD */ FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; - + /* wait until the PUD flag to be reset */ - do{ - flag_status = FWDGT_STAT & FWDGT_STAT_PUD; - }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if ((uint32_t)RESET != flag_status){ + do { + flag_status = FWDGT_STAT & FWDGT_STAT_PUD; + } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status) { return ERROR; } @@ -123,16 +180,16 @@ ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) timeout = FWDGT_RLD_TIMEOUT; /* wait until the RUD flag to be reset */ - do{ - flag_status = FWDGT_STAT & FWDGT_STAT_RUD; - }while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); - - if ((uint32_t)RESET != flag_status){ + do { + flag_status = FWDGT_STAT & FWDGT_STAT_RUD; + } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status) { return ERROR; } - + FWDGT_RLD = RLD_RLD(reload_value); - + /* reload the counter */ FWDGT_CTL = FWDGT_KEY_RELOAD; @@ -141,7 +198,7 @@ ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) /*! \brief get flag state of FWDGT - \param[in] flag: flag to get + \param[in] flag: flag to get only one parameter can be selected which is shown as below: \arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going \arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going @@ -150,9 +207,9 @@ ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_div) */ FlagStatus fwdgt_flag_get(uint16_t flag) { - if(FWDGT_STAT & flag){ + if(FWDGT_STAT & flag) { return SET; } - + return RESET; } diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_gpio.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_gpio.c index 0acf1093..4fd2c55a 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_gpio.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_gpio.c @@ -2,46 +2,43 @@ \file gd32f20x_gpio.c \brief GPIO driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "gd32f20x_gpio.h" -#define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/ +#define AFIO_EXTI_SOURCE_MASK ((uint8_t)0x03U) /*!< AFIO exti source selection mask*/ #define AFIO_EXTI_SOURCE_FIELDS ((uint8_t)0x04U) /*!< select AFIO exti source registers */ #define LSB_16BIT_MASK ((uint16_t)0xFFFFU) /*!< LSB 16-bit mask */ #define PCF_POSITION_MASK ((uint32_t)0x000F0000U) /*!< AFIO_PCF register position mask */ -#define PCF_SWJCFG_MASK ((uint32_t)0xF0FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */ +#define PCF_SWJCFG_MASK ((uint32_t)0xF8FFFFFFU) /*!< AFIO_PCF register SWJCFG mask */ #define PCF_LOCATION1_MASK ((uint32_t)0x00200000U) /*!< AFIO_PCF register location1 mask */ #define PCF_LOCATION2_MASK ((uint32_t)0x00100000U) /*!< AFIO_PCF register location2 mask */ #define AFIO_PCF1_FIELDS ((uint32_t)0x80000000U) /*!< select AFIO_PCF1 register */ @@ -55,7 +52,7 @@ OF SUCH DAMAGE. */ void gpio_deinit(uint32_t gpio_periph) { - switch(gpio_periph){ + switch(gpio_periph) { case GPIOA: /* reset GPIOA */ rcu_periph_reset_enable(RCU_GPIOARST); @@ -120,7 +117,7 @@ void gpio_afio_deinit(void) /*! \brief GPIO parameter initialization - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) \param[in] mode: gpio pin mode only one parameter can be selected which is shown as below: \arg GPIO_MODE_AIN: analog input mode @@ -139,7 +136,6 @@ void gpio_afio_deinit(void) \param[in] pin: GPIO pin one or more parameters can be selected which are shown as below: \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL - \param[out] none \retval none */ @@ -151,30 +147,29 @@ void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin /* GPIO mode configuration */ temp_mode = (uint32_t)(mode & ((uint32_t)0x0FU)); - + /* GPIO speed configuration */ - if(((uint32_t)0x00U) != ((uint32_t)mode & ((uint32_t)0x10U))){ - /* output mode max speed:10MHz,2MHz,50MHz */ + if(((uint32_t)0x00U) != ((uint32_t)mode & ((uint32_t)0x10U))) { + /* output mode max speed: 10MHz, 2MHz, 50MHz */ temp_mode |= (uint32_t)speed; } /* configure the eight low port pins with GPIO_CTL0 */ - for(i = 0U;i < 8U;i++){ - if((1U << i) & pin){ + for(i = 0U; i < 8U; i++) { + if((1U << i) & pin) { reg = GPIO_CTL0(gpio_periph); - /* clear the specified pin mode bits */ reg &= ~GPIO_MODE_MASK(i); /* set the specified pin mode bits */ reg |= GPIO_MODE_SET(i, temp_mode); - + /* set IPD or IPU */ - if(GPIO_MODE_IPD == mode){ + if(GPIO_MODE_IPD == mode) { /* reset the corresponding OCTL bit */ GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin); - }else{ + } else { /* set the corresponding OCTL bit */ - if(GPIO_MODE_IPU == mode){ + if(GPIO_MODE_IPU == mode) { GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin); } } @@ -183,22 +178,21 @@ void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin } } /* configure the eight high port pins with GPIO_CTL1 */ - for(i = 8U;i < 16U;i++){ - if((1U << i) & pin){ + for(i = 8U; i < 16U; i++) { + if((1U << i) & pin) { reg = GPIO_CTL1(gpio_periph); - /* clear the specified pin mode bits */ reg &= ~GPIO_MODE_MASK(i - 8U); /* set the specified pin mode bits */ reg |= GPIO_MODE_SET(i - 8U, temp_mode); - + /* set IPD or IPU */ - if(GPIO_MODE_IPD == mode){ + if(GPIO_MODE_IPD == mode) { /* reset the corresponding OCTL bit */ GPIO_BC(gpio_periph) = (uint32_t)((1U << i) & pin); - }else{ + } else { /* set the corresponding OCTL bit */ - if(GPIO_MODE_IPU == mode){ + if(GPIO_MODE_IPU == mode) { GPIO_BOP(gpio_periph) = (uint32_t)((1U << i) & pin); } } @@ -210,35 +204,35 @@ void gpio_init(uint32_t gpio_periph, uint32_t mode, uint32_t speed, uint32_t pin /*! \brief set GPIO pin - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) \param[in] pin: GPIO pin one or more parameters can be selected which are shown as below: \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL \param[out] none \retval none */ -void gpio_bit_set(uint32_t gpio_periph,uint32_t pin) +void gpio_bit_set(uint32_t gpio_periph, uint32_t pin) { GPIO_BOP(gpio_periph) = (uint32_t)pin; } /*! \brief reset GPIO pin - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) \param[in] pin: GPIO pin one or more parameters can be selected which are shown as below: \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL \param[out] none \retval none */ -void gpio_bit_reset(uint32_t gpio_periph,uint32_t pin) +void gpio_bit_reset(uint32_t gpio_periph, uint32_t pin) { GPIO_BC(gpio_periph) = (uint32_t)pin; } /*! \brief write data to the specified GPIO pin - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) \param[in] pin: GPIO pin one or more parameters can be selected which are shown as below: \arg GPIO_PIN_x(x=0..15), GPIO_PIN_ALL @@ -248,23 +242,23 @@ void gpio_bit_reset(uint32_t gpio_periph,uint32_t pin) \param[out] none \retval none */ -void gpio_bit_write(uint32_t gpio_periph,uint32_t pin,bit_status bit_value) +void gpio_bit_write(uint32_t gpio_periph, uint32_t pin, bit_status bit_value) { - if(RESET != bit_value){ + if(RESET != bit_value) { GPIO_BOP(gpio_periph) = (uint32_t)pin; - }else{ + } else { GPIO_BC(gpio_periph) = (uint32_t)pin; } } /*! \brief write data to the specified GPIO port - \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) + \param[in] gpio_periph: GPIOx(x = A,B,C,D,E,F,G,H,I) \param[in] data: specify the value to be written to the port output data register \param[out] none \retval none */ -void gpio_port_write(uint32_t gpio_periph,uint16_t data) +void gpio_port_write(uint32_t gpio_periph, uint16_t data) { GPIO_OCTL(gpio_periph) = (uint32_t)data; } @@ -278,11 +272,11 @@ void gpio_port_write(uint32_t gpio_periph,uint16_t data) \param[out] none \retval input status of gpio pin: SET or RESET */ -FlagStatus gpio_input_bit_get(uint32_t gpio_periph,uint32_t pin) +FlagStatus gpio_input_bit_get(uint32_t gpio_periph, uint32_t pin) { - if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph)&(pin))){ - return SET; - }else{ + if((uint32_t)RESET != (GPIO_ISTAT(gpio_periph) & (pin))) { + return SET; + } else { return RESET; } } @@ -307,11 +301,11 @@ uint16_t gpio_input_port_get(uint32_t gpio_periph) \param[out] none \retval output status of gpio pin: SET or RESET */ -FlagStatus gpio_output_bit_get(uint32_t gpio_periph,uint32_t pin) +FlagStatus gpio_output_bit_get(uint32_t gpio_periph, uint32_t pin) { - if((uint32_t)RESET !=(GPIO_OCTL(gpio_periph)&(pin))){ + if((uint32_t)RESET != (GPIO_OCTL(gpio_periph) & (pin))) { return SET; - }else{ + } else { return RESET; } } @@ -329,14 +323,15 @@ uint16_t gpio_output_port_get(uint32_t gpio_periph) /*! \brief configure GPIO pin remap - \param[in] gpio_remap: select the pin to remap + \param[in] remap: select the pin to remap + only one parameter can be selected which are shown as below: \arg GPIO_SPI0_REMAP: SPI0 remapping \arg GPIO_I2C0_REMAP: I2C0 remapping \arg GPIO_USART0_REMAP: USART0 remapping \arg GPIO_USART1_REMAP: USART1 remapping \arg GPIO_USART2_PARTIAL_REMAP: USART2 partial remapping \arg GPIO_USART2_FULL_REMAP: USART2 full remapping - \arg GPIO_TIMER0_PARTIAL_REMAP: TIMER0 partial remapping + \arg GPIO_TIMER0_PARTIAL_REMAP: TIMER0 partial remapping \arg GPIO_TIMER0_FULL_REMAP: TIMER0 full remapping \arg GPIO_TIMER1_PARTIAL_REMAP0: TIMER1 partial remapping \arg GPIO_TIMER1_PARTIAL_REMAP1: TIMER1 partial remapping @@ -354,12 +349,12 @@ uint16_t gpio_output_port_get(uint32_t gpio_periph) \arg GPIO_ADC1_ETRGREG_REMAP: ADC1 external trigger regular conversion remapping \arg GPIO_ENET_REMAP: ENET remapping \arg GPIO_CAN1_REMAP: CAN1 remapping - \arg GPIO_SWJ_NONJTRST_REMAP: full SWJ(JTAG-DP + SW-DP),but without NJTRST + \arg GPIO_SWJ_NONJTRST_REMAP: full SWJ(JTAG-DP + SW-DP), but without NJTRST \arg GPIO_SWJ_SWDPENABLE_REMAP: JTAG-DP disabled and SW-DP enabled \arg GPIO_SWJ_DISABLE_REMAP: JTAG-DP disabled and SW-DP disabled \arg GPIO_SPI2_REMAP: SPI2 remapping \arg GPIO_TIMER1ITI1_REMAP: TIMER1 internal trigger 1 remapping - \arg GPIO_PTP_PPS_REMAP: ethernet PTP PPS remapping + \arg GPIO_PTP_PPS_REMAP: ethernet PTP PPS remapping \arg GPIO_TIMER8_REMAP: TIMER8 remapping \arg GPIO_TIMER9_REMAP: TIMER9 remapping \arg GPIO_TIMER10_REMAP: TIMER10 remapping @@ -370,51 +365,51 @@ uint16_t gpio_output_port_get(uint32_t gpio_periph) \param[out] none \retval none */ -void gpio_pin_remap_config(uint32_t gpio_remap, ControlStatus newvalue) +void gpio_pin_remap_config(uint32_t remap, ControlStatus newvalue) { uint32_t remap1 = 0U, remap2 = 0U, temp_reg = 0U, temp_mask = 0U; - if(AFIO_PCF1_FIELDS == (gpio_remap & AFIO_PCF1_FIELDS)){ + if(AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)) { /* get AFIO_PCF1 regiter value */ temp_reg = AFIO_PCF1; - }else{ + } else { /* get AFIO_PCF0 regiter value */ temp_reg = AFIO_PCF0; } - temp_mask = (gpio_remap & PCF_POSITION_MASK) >> 0x10U; - remap1 = gpio_remap & LSB_16BIT_MASK; + temp_mask = (remap & PCF_POSITION_MASK) >> 0x10U; + remap1 = remap & LSB_16BIT_MASK; /* judge pin remap type */ - if((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK) == (gpio_remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))){ + if((PCF_LOCATION1_MASK | PCF_LOCATION2_MASK) == (remap & (PCF_LOCATION1_MASK | PCF_LOCATION2_MASK))) { temp_reg &= PCF_SWJCFG_MASK; AFIO_PCF0 &= PCF_SWJCFG_MASK; - }else if(PCF_LOCATION2_MASK == (gpio_remap & PCF_LOCATION2_MASK)){ + } else if(PCF_LOCATION2_MASK == (remap & PCF_LOCATION2_MASK)) { remap2 = ((uint32_t)0x03U) << temp_mask; temp_reg &= ~remap2; temp_reg |= ~PCF_SWJCFG_MASK; - }else{ - temp_reg &= ~(remap1 << ((gpio_remap >> 0x15U)*0x10U)); + } else { + temp_reg &= ~(remap1 << ((remap >> 0x15U) * 0x10U)); temp_reg |= ~PCF_SWJCFG_MASK; } - + /* set pin remap value */ - if(DISABLE != newvalue){ - temp_reg |= (remap1 << ((gpio_remap >> 0x15U)*0x10U)); + if(DISABLE != newvalue) { + temp_reg |= (remap1 << ((remap >> 0x15U) * 0x10U)); } - - if(AFIO_PCF1_FIELDS == (gpio_remap & AFIO_PCF1_FIELDS)){ - /* set AFIO_PCF1 regiter value */ + + if(AFIO_PCF1_FIELDS == (remap & AFIO_PCF1_FIELDS)) { + /* set AFIO_PCF1 register value */ AFIO_PCF1 = temp_reg; - }else{ - /* set AFIO_PCF0 regiter value */ + } else { + /* set AFIO_PCF0 register value */ AFIO_PCF0 = temp_reg; } } /*! \brief configure GPIO pin remap1 - \param[in] remap_reg: + \param[in] remap_reg: \arg GPIO_PCF2: AFIO port configuration register 2 \arg GPIO_PCF3: AFIO port configuration register 3 \arg GPIO_PCF4: AFIO port configuration register 4 @@ -437,109 +432,109 @@ void gpio_pin_remap_config(uint32_t gpio_remap, ControlStatus newvalue) \arg GPIO_PCF2_DCI_D5_PD3_REMAP: DCI D5 remapped to PD3 \arg GPIO_PCF2_DCI_D5_PI4_REMAP: DCI D5 remapped to PI4 \arg GPIO_PCF2_DCI_D6_PE5_REMAP: DCI D6 remapped to PE5 - \arg GPIO_PCF2_DCI_D6_PI6_REMAP: DCI D6 remapped to PI6 - \arg GPIO_PCF2_DCI_D7_PE6_REMAP: DCI D7 remapped to PE6 - \arg GPIO_PCF2_DCI_D7_PI7_REMAP: DCI D7 remapped to PI7 - \arg GPIO_PCF2_DCI_D8_PH6_REMAP: DCI D8 remapped to PH6 - \arg GPIO_PCF2_DCI_D8_PI1_REMAP: DCI D8 remapped to PI1 - \arg GPIO_PCF2_DCI_D9_PH7_REMAP: DCI D9 remapped to PH7 - \arg GPIO_PCF2_DCI_D9_PI2_REMAP: DCI D9 remapped to PI2 - \arg GPIO_PCF2_DCI_D10_PD6_REMAP: DCI D10 remapped to PD6 - \arg GPIO_PCF2_DCI_D10_PI3_REMAP: DCI D10 remapped to PI3 - \arg GPIO_PCF2_DCI_D11_PF10_REMAP: DCI D11 remapped to PF10 - \arg GPIO_PCF2_DCI_D11_PH15_REMAP: DCI D11 remapped to PH15 - \arg GPIO_PCF2_DCI_D12_PG6_REMAP: DCI D12 remapped to PG6 - \arg GPIO_PCF2_DCI_D13_PG15_REMAP: DCI D12 remapped to PG15 - \arg GPIO_PCF2_DCI_D13_PI0_REMAP: DCI D13 remapped to PI0 - \arg GPIO_PCF2_DCI_HSYNC_PH8_REMAP: DCI HSYNC to PH8 - \arg GPIO_PCF2_PH01_REMAP: PH0/PH1 remapping - \arg GPIO_PCF3_TLI_B5_PA3_REMAP: TLI B5 remapped to PA3 - \arg GPIO_PCF3_TLI_VSYNC_PA4_REMAP: TLI VSYNC remapped to PA4 - \arg GPIO_PCF3_TLI_G2_PA6_REMAP: TLI G2 remapped to PA6 - \arg GPIO_PCF3_TLI_R6_PA8_REMAP: TLI R6 remapped to PA8 - \arg GPIO_PCF3_TLI_R4_PA11_REMAP: TLI R4 remapped to PA11 - \arg GPIO_PCF3_TLI_R5_PA12_REMAP: TLI R5 remapped to PA12 - \arg GPIO_PCF3_TLI_R3_PB0_REMAP: TLI R3 remapped to PB0 - \arg GPIO_PCF3_TLI_R6_PB1_REMAP: TLI R6 remapped to PB1 - \arg GPIO_PCF3_TLI_B6_PB8_REMAP: TLI B6 remapped to PB8 - \arg GPIO_PCF3_TLI_B7_PB9_REMAP: TLI B7 remapped to PB9 - \arg GPIO_PCF3_TLI_G4_PB10_REMAP: TLI G4 remapped to PB10 - \arg GPIO_PCF3_TLI_G5_PB11_REMAP: TLI G5 remapped to PB11 - \arg GPIO_PCF3_TLI_HSYNC_PC6_REMAP: TLI HSYNC remapped to PC6 - \arg GPIO_PCF3_TLI_G6_PC7_REMAP: TLI G6 remapped to PC7 - \arg GPIO_PCF3_TLI_R2_PC10_REMAP: TLI R2 remapped to PC10 - \arg GPIO_PCF3_TLI_G7_PD3_REMAP: TLI G7 remapped to PD3 - \arg GPIO_PCF3_TLI_B2_PD6_REMAP: TLI B2 remapped to PD6 - \arg GPIO_PCF3_TLI_B3_PD10_REMAP: TLI B3 remapped to PD10 - \arg GPIO_PCF3_TLI_B0_PE4_REMAP: TLI B0 remapped to PE4 - \arg GPIO_PCF3_TLI_G0_PE5_REMAP: TLI G0 remapped to PE5 - \arg GPIO_PCF3_TLI_G1_PE6_REMAP: TLI G1 remapped to PE6 - \arg GPIO_PCF3_TLI_G3_PE11_REMAP: TLI G3 remapped to PE11 - \arg GPIO_PCF3_TLI_B4_PE12_REMAP: TLI B4 remapped to PE12 - \arg GPIO_PCF3_TLI_DE_PE13_REMAP: TLI DE remapped to PE13 - \arg GPIO_PCF3_TLI_CLK_PE14_REMAP: TLI CLK remapped to PE14 - \arg GPIO_PCF3_TLI_R7_PE15_REMAP: TLI R7 remapped to PE15 - \arg GPIO_PCF3_TLI_DE_PF10_REMAP: TLI DE remapped to PF10 - \arg GPIO_PCF3_TLI_R7_PG6_REMAP: TLI R7 remapped to PG6 - \arg GPIO_PCF3_TLI_CLK_PG7_REMAP: TLI CLK remapped to PG7 - \arg GPIO_PCF3_TLI_G3_PG10_REMAP: TLI G3 remapped to PG10 - \arg GPIO_PCF3_TLI_B2_PG10_REMAP: TLI B2 remapped to PG10 - \arg GPIO_PCF3_TLI_B3_PG11_REMAP: TLI B3 remapped to PG11 - \arg GPIO_PCF4_TLI_B4_PG12_REMAP: B4 remapped to PG12 - \arg GPIO_PCF4_TLI_B1_PG12_REMAP: B1 remapped to PG12 - \arg GPIO_PCF4_TLI_R0_PH2_REMAP2: R0 remapped to PH2 - \arg GPIO_PCF4_TLI_R1_PH3_REMAP: TLI R1 remapped to PH3 - \arg GPIO_PCF4_TLI_R2_PH8_REMAP: TLI R2 remapped to PH8 - \arg GPIO_PCF4_TLI_R3_PH9_REMAP: TLI R3 remapped to PH9 - \arg GPIO_PCF4_TLI_R4_PH10_REMAP: TLI R4 remapped to PH10 - \arg GPIO_PCF4_TLI_R5_PH11_REMAP: TLI R5 remapped to PH11 - \arg GPIO_PCF4_TLI_R6_PH12_REMAP: TLI R6 remapped to PH12 - \arg GPIO_PCF4_TLI_G2_PH13_REMAP: TLI G2 remapped to PH13 - \arg GPIO_PCF4_TLI_G3_PH14_REMAP: TLI G3 remapped to PH14 - \arg GPIO_PCF4_TLI_G4_PH15_REMAP: TLI G4 remapped to PH15 - \arg GPIO_PCF4_TLI_G5_PI0_REMAP: TLI G5 remapped to PI0 - \arg GPIO_PCF4_TLI_G6_PI1_REMAP: TLI G6 remapped to PI1 - \arg GPIO_PCF4_TLI_G7_PI2_REMAP: TLI G7 remapped to PI2 - \arg GPIO_PCF4_TLI_B4_PI4_REMAP: TLI B4 remapped to PI4 - \arg GPIO_PCF4_TLI_B5_PI5_REMAP: TLI B5 remapped to PI5 - \arg GPIO_PCF4_TLI_B6_PI6_REMAP: TLI B6 remapped to PI6 - \arg GPIO_PCF4_TLI_B7_PI7_REMAP: TLI B7 remapped to PI7 - \arg GPIO_PCF4_TLI_VSYNC_PI9_REMAP: TLI VSYNC remapped to PI9 - \arg GPIO_PCF4_TLI_HSYNC_PI10_REMAP: TLI HSYNC remapped to PI10 - \arg GPIO_PCF4_TLI_R0_PH4_REMAP: TLI R0 remapped to PH4 - \arg GPIO_PCF4_TLI_R1_PI3_REMAP: TLI R1 remapped to PI3 - \arg GPIO_PCF4_SPI1_SCK_PD3_REMAP: SPI1 SCK remapped to PD3 - \arg GPIO_PCF4_SPI2_MOSI_PD6_REMAP: SPI2 MOSI remapped to PD6 - \arg GPIO_PCF5_I2C2_REMAP0: I2C2 remapping 0 - \arg GPIO_PCF5_I2C2_REMAP1: I2C2 remapping 1 - \arg GPIO_PCF5_TIMER1_CH0_REMAP: TIMER1 CH0 remapped to PA5 - \arg GPIO_PCF5_TIMER4_REMAP: TIMER4 CH0 remapping - \arg GPIO_PCF5_TIMER7_CHON_REMAP0: TIMER7 CHON remapping 0 - \arg GPIO_PCF5_TIMER7_CHON_REMAP1: TIMER7 CHON remapping 1 - \arg GPIO_PCF5_TIMER7_CH_REMAP: TIMER7 CH remapping - \arg GPIO_PCF5_I2C1_REMAP0: I2C1 remapping 0 - \arg GPIO_PCF5_I2C1_REMAP1: I2C1 remapping 1 - \arg GPIO_PCF5_SPI1_NSCK_REMAP0: SPI1 NSS/SCK remapping 0 - \arg GPIO_PCF5_SPI1_NSCK_REMAP1: SPI1 NSS/SCK remapping 1 - \arg GPIO_PCF5_SPI1_IO_REMAP0: SPI1 MISO/MOSI remapping 0 - \arg GPIO_PCF5_SPI1_IO_REMAP1: SPI1 MISO/MOSI remapping 1 - \arg GPIO_PCF5_UART3_REMAP: UART3 remapping - \arg GPIO_PCF5_TIMER11_REMAP: TIMER11 remapping - \arg GPIO_PCF5_CAN0_ADD_REMAP: CAN0 addition remapping - \arg GPIO_PCF5_ENET_TXD3_REMAP: ETH_TXD3 remapped to PE2 - \arg GPIO_PCF5_PPS_HI_REMAP: ETH_PPS_OUT remapped to PG8 - \arg GPIO_PCF5_ENET_TXD01_REMAP: ETH_TX_EN/ETH_TXD0/ETH_TXD1 remapping - \arg GPIO_PCF5_ENET_CRSCOL_REMAP: ETH_MII_CRS/ETH_MII_COL remapping - \arg GPIO_PCF5_ENET_RX_HI_REMAP: ETH_RXD2/ETH_RXD3/ETH_RX_ER remapping - \arg GPIO_PCF5_UART6_REMAP: UART6 remapping - \arg GPIO_PCF5_USART5_CK_PG7_REMAP: USART5 CK remapped to PG7 - \arg GPIO_PCF5_USART5_RTS_PG12_REMAP: USART5 RTS remapped to PG12 - \arg GPIO_PCF5_USART5_CTS_PG13_REMAP: USART5 CTS remapped to PG13 - \arg GPIO_PCF5_USART5_TX_PG14_REMAP: USART5 TX remapped to PG14 - \arg GPIO_PCF5_USART5_RX_PG9_REMAP: USART5 RX remapped to PG9 - \arg GPIO_PCF5_EXMC_SDNWE_PC0_REMAP: EXMC SDNWE remapped to PC0 - \arg GPIO_PCF5_EXMC_SDCKE0_PC3_REMAP: EXMC SDCKE0 remapped to PC3 - \arg GPIO_PCF5_EXMC_SDCKE1_PB5_REMAP: EXMC SDCKE1 remapped to PB5 + \arg GPIO_PCF2_DCI_D6_PI6_REMAP: DCI D6 remapped to PI6 + \arg GPIO_PCF2_DCI_D7_PE6_REMAP: DCI D7 remapped to PE6 + \arg GPIO_PCF2_DCI_D7_PI7_REMAP: DCI D7 remapped to PI7 + \arg GPIO_PCF2_DCI_D8_PH6_REMAP: DCI D8 remapped to PH6 + \arg GPIO_PCF2_DCI_D8_PI1_REMAP: DCI D8 remapped to PI1 + \arg GPIO_PCF2_DCI_D9_PH7_REMAP: DCI D9 remapped to PH7 + \arg GPIO_PCF2_DCI_D9_PI2_REMAP: DCI D9 remapped to PI2 + \arg GPIO_PCF2_DCI_D10_PD6_REMAP: DCI D10 remapped to PD6 + \arg GPIO_PCF2_DCI_D10_PI3_REMAP: DCI D10 remapped to PI3 + \arg GPIO_PCF2_DCI_D11_PF10_REMAP: DCI D11 remapped to PF10 + \arg GPIO_PCF2_DCI_D11_PH15_REMAP: DCI D11 remapped to PH15 + \arg GPIO_PCF2_DCI_D12_PG6_REMAP: DCI D12 remapped to PG6 + \arg GPIO_PCF2_DCI_D13_PG15_REMAP: DCI D12 remapped to PG15 + \arg GPIO_PCF2_DCI_D13_PI0_REMAP: DCI D13 remapped to PI0 + \arg GPIO_PCF2_DCI_HSYNC_PH8_REMAP: DCI HSYNC to PH8 + \arg GPIO_PCF2_PH01_REMAP: PH0/PH1 remapping + \arg GPIO_PCF3_TLI_B5_PA3_REMAP: TLI B5 remapped to PA3 + \arg GPIO_PCF3_TLI_VSYNC_PA4_REMAP: TLI VSYNC remapped to PA4 + \arg GPIO_PCF3_TLI_G2_PA6_REMAP: TLI G2 remapped to PA6 + \arg GPIO_PCF3_TLI_R6_PA8_REMAP: TLI R6 remapped to PA8 + \arg GPIO_PCF3_TLI_R4_PA11_REMAP: TLI R4 remapped to PA11 + \arg GPIO_PCF3_TLI_R5_PA12_REMAP: TLI R5 remapped to PA12 + \arg GPIO_PCF3_TLI_R3_PB0_REMAP: TLI R3 remapped to PB0 + \arg GPIO_PCF3_TLI_R6_PB1_REMAP: TLI R6 remapped to PB1 + \arg GPIO_PCF3_TLI_B6_PB8_REMAP: TLI B6 remapped to PB8 + \arg GPIO_PCF3_TLI_B7_PB9_REMAP: TLI B7 remapped to PB9 + \arg GPIO_PCF3_TLI_G4_PB10_REMAP: TLI G4 remapped to PB10 + \arg GPIO_PCF3_TLI_G5_PB11_REMAP: TLI G5 remapped to PB11 + \arg GPIO_PCF3_TLI_HSYNC_PC6_REMAP: TLI HSYNC remapped to PC6 + \arg GPIO_PCF3_TLI_G6_PC7_REMAP: TLI G6 remapped to PC7 + \arg GPIO_PCF3_TLI_R2_PC10_REMAP: TLI R2 remapped to PC10 + \arg GPIO_PCF3_TLI_G7_PD3_REMAP: TLI G7 remapped to PD3 + \arg GPIO_PCF3_TLI_B2_PD6_REMAP: TLI B2 remapped to PD6 + \arg GPIO_PCF3_TLI_B3_PD10_REMAP: TLI B3 remapped to PD10 + \arg GPIO_PCF3_TLI_B0_PE4_REMAP: TLI B0 remapped to PE4 + \arg GPIO_PCF3_TLI_G0_PE5_REMAP: TLI G0 remapped to PE5 + \arg GPIO_PCF3_TLI_G1_PE6_REMAP: TLI G1 remapped to PE6 + \arg GPIO_PCF3_TLI_G3_PE11_REMAP: TLI G3 remapped to PE11 + \arg GPIO_PCF3_TLI_B4_PE12_REMAP: TLI B4 remapped to PE12 + \arg GPIO_PCF3_TLI_DE_PE13_REMAP: TLI DE remapped to PE13 + \arg GPIO_PCF3_TLI_CLK_PE14_REMAP: TLI CLK remapped to PE14 + \arg GPIO_PCF3_TLI_R7_PE15_REMAP: TLI R7 remapped to PE15 + \arg GPIO_PCF3_TLI_DE_PF10_REMAP: TLI DE remapped to PF10 + \arg GPIO_PCF3_TLI_R7_PG6_REMAP: TLI R7 remapped to PG6 + \arg GPIO_PCF3_TLI_CLK_PG7_REMAP: TLI CLK remapped to PG7 + \arg GPIO_PCF3_TLI_G3_PG10_REMAP: TLI G3 remapped to PG10 + \arg GPIO_PCF3_TLI_B2_PG10_REMAP: TLI B2 remapped to PG10 + \arg GPIO_PCF3_TLI_B3_PG11_REMAP: TLI B3 remapped to PG11 + \arg GPIO_PCF4_TLI_B4_PG12_REMAP: B4 remapped to PG12 + \arg GPIO_PCF4_TLI_B1_PG12_REMAP: B1 remapped to PG12 + \arg GPIO_PCF4_TLI_R0_PH2_REMAP2: R0 remapped to PH2 + \arg GPIO_PCF4_TLI_R1_PH3_REMAP: TLI R1 remapped to PH3 + \arg GPIO_PCF4_TLI_R2_PH8_REMAP: TLI R2 remapped to PH8 + \arg GPIO_PCF4_TLI_R3_PH9_REMAP: TLI R3 remapped to PH9 + \arg GPIO_PCF4_TLI_R4_PH10_REMAP: TLI R4 remapped to PH10 + \arg GPIO_PCF4_TLI_R5_PH11_REMAP: TLI R5 remapped to PH11 + \arg GPIO_PCF4_TLI_R6_PH12_REMAP: TLI R6 remapped to PH12 + \arg GPIO_PCF4_TLI_G2_PH13_REMAP: TLI G2 remapped to PH13 + \arg GPIO_PCF4_TLI_G3_PH14_REMAP: TLI G3 remapped to PH14 + \arg GPIO_PCF4_TLI_G4_PH15_REMAP: TLI G4 remapped to PH15 + \arg GPIO_PCF4_TLI_G5_PI0_REMAP: TLI G5 remapped to PI0 + \arg GPIO_PCF4_TLI_G6_PI1_REMAP: TLI G6 remapped to PI1 + \arg GPIO_PCF4_TLI_G7_PI2_REMAP: TLI G7 remapped to PI2 + \arg GPIO_PCF4_TLI_B4_PI4_REMAP: TLI B4 remapped to PI4 + \arg GPIO_PCF4_TLI_B5_PI5_REMAP: TLI B5 remapped to PI5 + \arg GPIO_PCF4_TLI_B6_PI6_REMAP: TLI B6 remapped to PI6 + \arg GPIO_PCF4_TLI_B7_PI7_REMAP: TLI B7 remapped to PI7 + \arg GPIO_PCF4_TLI_VSYNC_PI9_REMAP: TLI VSYNC remapped to PI9 + \arg GPIO_PCF4_TLI_HSYNC_PI10_REMAP: TLI HSYNC remapped to PI10 + \arg GPIO_PCF4_TLI_R0_PH4_REMAP: TLI R0 remapped to PH4 + \arg GPIO_PCF4_TLI_R1_PI3_REMAP: TLI R1 remapped to PI3 + \arg GPIO_PCF4_SPI1_SCK_PD3_REMAP: SPI1 SCK remapped to PD3 + \arg GPIO_PCF4_SPI2_MOSI_PD6_REMAP: SPI2 MOSI remapped to PD6 + \arg GPIO_PCF5_I2C2_REMAP0: I2C2 remapping 0 + \arg GPIO_PCF5_I2C2_REMAP1: I2C2 remapping 1 + \arg GPIO_PCF5_TIMER1_CH0_REMAP: TIMER1 CH0 remapped to PA5 + \arg GPIO_PCF5_TIMER4_REMAP: TIMER4 CH0 remapping + \arg GPIO_PCF5_TIMER7_CHON_REMAP0: TIMER7 CHON remapping 0 + \arg GPIO_PCF5_TIMER7_CHON_REMAP1: TIMER7 CHON remapping 1 + \arg GPIO_PCF5_TIMER7_CH_REMAP: TIMER7 CH remapping + \arg GPIO_PCF5_I2C1_REMAP0: I2C1 remapping 0 + \arg GPIO_PCF5_I2C1_REMAP1: I2C1 remapping 1 + \arg GPIO_PCF5_SPI1_NSCK_REMAP0: SPI1 NSS/SCK remapping 0 + \arg GPIO_PCF5_SPI1_NSCK_REMAP1: SPI1 NSS/SCK remapping 1 + \arg GPIO_PCF5_SPI1_IO_REMAP0: SPI1 MISO/MOSI remapping 0 + \arg GPIO_PCF5_SPI1_IO_REMAP1: SPI1 MISO/MOSI remapping 1 + \arg GPIO_PCF5_UART3_REMAP: UART3 remapping + \arg GPIO_PCF5_TIMER11_REMAP: TIMER11 remapping + \arg GPIO_PCF5_CAN0_ADD_REMAP: CAN0 addition remapping + \arg GPIO_PCF5_ENET_TXD3_REMAP: ETH_TXD3 remapped to PE2 + \arg GPIO_PCF5_PPS_HI_REMAP: ETH_PPS_OUT remapped to PG8 + \arg GPIO_PCF5_ENET_TXD01_REMAP: ETH_TX_EN/ETH_TXD0/ETH_TXD1 remapping + \arg GPIO_PCF5_ENET_CRSCOL_REMAP: ETH_MII_CRS/ETH_MII_COL remapping + \arg GPIO_PCF5_ENET_RX_HI_REMAP: ETH_RXD2/ETH_RXD3/ETH_RX_ER remapping + \arg GPIO_PCF5_UART6_REMAP: UART6 remapping + \arg GPIO_PCF5_USART5_CK_PG7_REMAP: USART5 CK remapped to PG7 + \arg GPIO_PCF5_USART5_RTS_PG12_REMAP: USART5 RTS remapped to PG12 + \arg GPIO_PCF5_USART5_CTS_PG13_REMAP: USART5 CTS remapped to PG13 + \arg GPIO_PCF5_USART5_TX_PG14_REMAP: USART5 TX remapped to PG14 + \arg GPIO_PCF5_USART5_RX_PG9_REMAP: USART5 RX remapped to PG9 + \arg GPIO_PCF5_EXMC_SDNWE_PC0_REMAP: EXMC SDNWE remapped to PC0 + \arg GPIO_PCF5_EXMC_SDCKE0_PC3_REMAP: EXMC SDCKE0 remapped to PC3 + \arg GPIO_PCF5_EXMC_SDCKE1_PB5_REMAP: EXMC SDCKE1 remapped to PB5 \arg GPIO_PCF5_EXMC_SDNE0_PC2_REMAP: EXMC SDNE0 remapped to PC2 \arg GPIO_PCF5_EXMC_SDNE1_PB6_REMAP: EXMC SDNE1 remapped to PB6 \param[in] newvalue: ENABLE or DISABLE @@ -550,63 +545,83 @@ void gpio_pin_remap1_config(uint8_t remap_reg, uint32_t remap, ControlStatus new { uint32_t reg = 0U; - if(DISABLE != newvalue){ + if(DISABLE != newvalue) { /* AFIO port configuration register selection */ - if(GPIO_PCF2 == remap_reg){ + if(GPIO_PCF2 == remap_reg) { reg = AFIO_PCF2; reg |= remap; AFIO_PCF2 = reg; - }else if(GPIO_PCF3 == remap_reg){ + } else if(GPIO_PCF3 == remap_reg) { reg = AFIO_PCF3; reg |= remap; AFIO_PCF3 = reg; - }else if(GPIO_PCF4 == remap_reg){ + } else if(GPIO_PCF4 == remap_reg) { reg = AFIO_PCF4; reg |= remap; AFIO_PCF4 = reg; - }else if(GPIO_PCF5 == remap_reg){ + } else if(GPIO_PCF5 == remap_reg) { reg = AFIO_PCF5; reg |= remap; AFIO_PCF5 = reg; - }else{ + } else { /* illegal parameters */ } - }else{ - if(GPIO_PCF2 == remap_reg){ + } else { + if(GPIO_PCF2 == remap_reg) { reg = AFIO_PCF2; reg &= ~remap; AFIO_PCF2 = reg; - }else if(GPIO_PCF3 == remap_reg){ + } else if(GPIO_PCF3 == remap_reg) { reg = AFIO_PCF3; reg &= ~remap; AFIO_PCF3 = reg; - }else if(GPIO_PCF4 == remap_reg){ + } else if(GPIO_PCF4 == remap_reg) { reg = AFIO_PCF4; reg &= ~remap; AFIO_PCF4 = reg; - }else if(GPIO_PCF5 == remap_reg){ + } else if(GPIO_PCF5 == remap_reg) { reg = AFIO_PCF5; reg &= ~remap; AFIO_PCF5 = reg; - }else{ + } else { /* illegal parameters */ } } } +/*! + \brief select ethernet MII or RMII PHY + \param[in] enet_sel: ethernet MII or RMII PHY selection + \arg GPIO_ENET_PHY_MII: configure ethernet MAC for connection with an MII PHY + \arg GPIO_ENET_PHY_RMII: configure ethernet MAC for connection with an RMII PHY + \param[out] none + \retval none +*/ +void gpio_ethernet_phy_select(uint32_t enet_sel) +{ + /* clear AFIO_PCF0_ENET_PHY_SEL bit */ + AFIO_PCF0 &= (uint32_t)(~AFIO_PCF0_ENET_PHY_SEL); + + /* select MII or RMII PHY */ + AFIO_PCF0 |= (uint32_t)enet_sel; +} + /*! \brief select GPIO pin exti sources \param[in] output_port: gpio event output port + only one parameter can be selected which are shown as below: \arg GPIO_PORT_SOURCE_GPIOA: output port source A \arg GPIO_PORT_SOURCE_GPIOB: output port source B \arg GPIO_PORT_SOURCE_GPIOC: output port source C \arg GPIO_PORT_SOURCE_GPIOD: output port source D - \arg GPIO_PORT_SOURCE_GPIOE: output port source E + \arg GPIO_PORT_SOURCE_GPIOE: output port source E \arg GPIO_PORT_SOURCE_GPIOF: output port source F \arg GPIO_PORT_SOURCE_GPIOG: output port source G \arg GPIO_PORT_SOURCE_GPIOH: output port source H \arg GPIO_PORT_SOURCE_GPIOI: output port source I - \param[in] output_pin: GPIO_PIN_SOURCE_x(x=0..15) + \param[in] output_pin: GPIO output pin source + only one parameter can be selected which are shown as below: + \arg GPIO_PIN_SOURCE_x(x=0..15) \param[out] none \retval none */ @@ -616,19 +631,19 @@ void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin) source = ((uint32_t)0x0FU) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK)); /* select EXTI sources */ - if(GPIO_PIN_SOURCE_4 > output_pin){ + if(GPIO_PIN_SOURCE_4 > output_pin) { /* select EXTI0/EXTI1/EXTI2/EXTI3 */ AFIO_EXTISS0 &= ~source; AFIO_EXTISS0 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); - }else if(GPIO_PIN_SOURCE_8 > output_pin){ + } else if(GPIO_PIN_SOURCE_8 > output_pin) { /* select EXTI4/EXTI5/EXTI6/EXTI7 */ AFIO_EXTISS1 &= ~source; AFIO_EXTISS1 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); - }else if(GPIO_PIN_SOURCE_12 > output_pin){ + } else if(GPIO_PIN_SOURCE_12 > output_pin) { /* select EXTI8/EXTI9/EXTI10/EXTI11 */ AFIO_EXTISS2 &= ~source; AFIO_EXTISS2 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); - }else{ + } else { /* select EXTI12/EXTI13/EXTI14/EXTI15 */ AFIO_EXTISS3 &= ~source; AFIO_EXTISS3 |= (((uint32_t)output_port) << (AFIO_EXTI_SOURCE_FIELDS * (output_pin & AFIO_EXTI_SOURCE_MASK))); @@ -644,7 +659,7 @@ void gpio_exti_source_select(uint8_t output_port, uint8_t output_pin) \arg GPIO_EVENT_PORT_GPIOC: event output port C \arg GPIO_EVENT_PORT_GPIOD: event output port D \arg GPIO_EVENT_PORT_GPIOE: event output port E - \param[in] output_pin: + \param[in] output_pin: GPIO event output pin only one parameter can be selected which are shown as below: \arg GPIO_EVENT_PIN_x(x=0..15) \param[out] none @@ -654,13 +669,13 @@ void gpio_event_output_config(uint8_t output_port, uint8_t output_pin) { uint32_t reg = 0U; reg = AFIO_EC; - + /* clear AFIO_EC_PORT and AFIO_EC_PIN bits */ - reg &= (uint32_t)(~(AFIO_EC_PORT|AFIO_EC_PIN)); - + reg &= (uint32_t)(~(AFIO_EC_PORT | AFIO_EC_PIN)); + reg |= (uint32_t)((uint32_t)output_port << GPIO_OUTPUT_PORT_OFFSET); reg |= (uint32_t)output_pin; - + AFIO_EC = reg; } @@ -695,7 +710,7 @@ void gpio_event_output_disable(void) \param[out] none \retval none */ -void gpio_pin_lock(uint32_t gpio_periph,uint32_t pin) +void gpio_pin_lock(uint32_t gpio_periph, uint32_t pin) { uint32_t lock = 0x00010000U; lock |= pin; @@ -707,20 +722,3 @@ void gpio_pin_lock(uint32_t gpio_periph,uint32_t pin) lock = GPIO_LOCK(gpio_periph); lock = GPIO_LOCK(gpio_periph); } - -/*! - \brief select ethernet MII or RMII PHY - \param[in] enet_sel: ethernet MII or RMII PHY selection - \arg GPIO_ENET_PHY_MII: configure ethernet MAC for connection with an MII PHY - \arg GPIO_ENET_PHY_RMII: configure ethernet MAC for connection with an RMII PHY - \param[out] none - \retval none -*/ -void gpio_ethernet_phy_select(uint32_t enet_sel) -{ - /* clear AFIO_PCF0_ENET_PHY_SEL bit */ - AFIO_PCF0 &= (uint32_t)(~AFIO_PCF0_ENET_PHY_SEL); - - /* select MII or RMII PHY */ - AFIO_PCF0 |= (uint32_t)enet_sel; -} diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_hau.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_hau.c index 6b2482fb..5cc79f0c 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_hau.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_hau.c @@ -1,37 +1,34 @@ /*! - \file gd32f20x_cau.c - \brief CAU driver + \file gd32f20x_hau.c + \brief HAU driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -40,7 +37,7 @@ OF SUCH DAMAGE. /*! \brief reset the HAU peripheral - \param[in] none + \param[in] none \param[out] none \retval none */ @@ -63,20 +60,20 @@ void hau_deinit(void) \param[out] none \retval none */ -void hau_init(hau_init_parameter_struct* initpara) +void hau_init(hau_init_parameter_struct *initpara) { /* configure the algorithm, mode and the data type */ HAU_CTL &= ~(HAU_CTL_ALGM_0 | HAU_CTL_ALGM_1 | HAU_CTL_DATAM | HAU_CTL_HMS); HAU_CTL |= (initpara->algo | initpara->datatype | initpara->mode); - - /* when mode is HMAC, set the key */ - if(HAU_MODE_HMAC == initpara->mode){ + + /* when mode is HMAC, set the key */ + if(HAU_MODE_HMAC == initpara->mode) { HAU_CTL &= ~HAU_CTL_KLM; HAU_CTL |= initpara->keytype; } /* start the digest of a new message */ - HAU_CTL |= HAU_CTL_START; + HAU_CTL |= HAU_CTL_START; } /*! @@ -90,7 +87,7 @@ void hau_init(hau_init_parameter_struct* initpara) \param[out] none \retval none */ -void hau_init_parameter_init(hau_init_parameter_struct* initpara) +void hau_init_struct_para_init(hau_init_parameter_struct *initpara) { initpara->algo = HAU_ALGO_SHA1; initpara->mode = HAU_MODE_HASH; @@ -100,7 +97,7 @@ void hau_init_parameter_init(hau_init_parameter_struct* initpara) /*! \brief reset the HAU processor core - \param[in] none + \param[in] none \param[out] none \retval none */ @@ -123,7 +120,7 @@ void hau_reset(void) \retval none */ void hau_last_word_validbits_num_config(uint32_t valid_num) -{ +{ HAU_CFG &= ~(HAU_CFG_VBL); HAU_CFG |= CFG_VBL(valid_num); } @@ -146,8 +143,8 @@ void hau_data_write(uint32_t data) \retval number of words in the input FIFO */ uint32_t hau_infifo_words_num_get(void) -{ - uint32_t ret = 0U; +{ + uint32_t ret = 0U; ret = GET_CTL_NWIF(HAU_CTL); return ret; } @@ -159,7 +156,7 @@ uint32_t hau_infifo_words_num_get(void) out[7:0]: message digest result 0-7 \retval none */ -void hau_digest_read(hau_digest_parameter_struct* digestpara) +void hau_digest_read(hau_digest_parameter_struct *digestpara) { digestpara->out[0] = HAU_DO0; digestpara->out[1] = HAU_DO1; @@ -172,7 +169,7 @@ void hau_digest_read(hau_digest_parameter_struct* digestpara) } /*! - \brief enable digest calculation + \brief enable digest calculation \param[in] none \param[out] none \retval none @@ -183,7 +180,7 @@ void hau_digest_calculation_enable(void) } /*! - \brief configure single or multiple DMA is used, and digest calculation at the end of a DMA transfer or not + \brief configure single or multiple DMA is used, and digest calculation at the end of a DMA transfer or not \param[in] multi_single only one parameter can be selected which is shown as below \arg SINGLE_DMA_AUTO_DIGEST: message padding and message digest calculation at the end of a DMA transfer @@ -196,9 +193,9 @@ void hau_multiple_single_dma_config(uint32_t multi_single) HAU_CTL &= ~HAU_CTL_MDS; HAU_CTL |= multi_single; } - + /*! - \brief enable the HAU DMA interface + \brief enable the HAU DMA interface \param[in] none \param[out] none \retval none @@ -209,7 +206,7 @@ void hau_dma_enable(void) } /*! - \brief disable the HAU DMA interface + \brief disable the HAU DMA interface \param[in] none \param[out] none \retval none @@ -223,7 +220,7 @@ void hau_dma_disable(void) \brief get the HAU flag status \param[in] flag: HAU flag status only one parameter can be selected which is shown as below - \arg HAU_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO + \arg HAU_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO \arg HAU_FLAG_CALCULATION_COMPLETE: digest calculation is completed \arg HAU_FLAG_DMA: DMA is enabled (DMAE =1) or a transfer is processing \arg HAU_FLAG_BUSY: data block is in process @@ -237,13 +234,13 @@ FlagStatus hau_flag_get(uint32_t flag) FlagStatus ret_flag = RESET; /* check if the flag is in HAU_CTL register */ - if(RESET != (flag & HAU_FLAG_INFIFO_NO_EMPTY)){ + if(RESET != (flag & HAU_FLAG_INFIFO_NO_EMPTY)) { ret = HAU_CTL; - }else{ + } else { ret = HAU_STAT; } - if (RESET != (ret & flag)){ + if(RESET != (ret & flag)) { ret_flag = SET; } @@ -254,7 +251,7 @@ FlagStatus hau_flag_get(uint32_t flag) \brief clear the HAU flag status \param[in] flag: HAU flag status one or more parameters can be selected which are shown as below - \arg HAU_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO + \arg HAU_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO \arg HAU_FLAG_CALCULATION_COMPLETE: digest calculation is completed \param[out] none \retval none @@ -268,7 +265,7 @@ void hau_flag_clear(uint32_t flag) \brief enable the HAU interrupts \param[in] interrupt: specify the HAU interrupt source to be enabled one or more parameters can be selected which are shown as below - \arg HAU_INT_DATA_INPUT: a new block can be entered into the IN buffer + \arg HAU_INT_DATA_INPUT: a new block can be entered into the IN buffer \arg HAU_INT_CALCULATION_COMPLETE: calculation complete \param[out] none \retval none @@ -282,7 +279,7 @@ void hau_interrupt_enable(uint32_t interrupt) \brief disable the HAU interrupts \param[in] interrupt: specify the HAU interrupt source to be disabled one or more parameters can be selected which are shown as below - \arg HAU_INT_DATA_INPUT: a new block can be entered into the IN buffer + \arg HAU_INT_DATA_INPUT: a new block can be entered into the IN buffer \arg HAU_INT_CALCULATION_COMPLETE: calculation complete \param[out] none \retval none @@ -296,7 +293,7 @@ void hau_interrupt_disable(uint32_t interrupt) \brief get the HAU interrupt flag status \param[in] int_flag: HAU interrupt flag status only one parameter can be selected which is shown as below - \arg HAU_INT_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO + \arg HAU_INT_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO \arg HAU_INT_FLAG_CALCULATION_COMPLETE: digest calculation is completed \param[out] none \retval FlagStatus: SET or RESET @@ -309,10 +306,10 @@ FlagStatus hau_interrupt_flag_get(uint32_t int_flag) /* return the status of the interrupt */ ret = HAU_STAT; - if(RESET != ((HAU_INTEN & ret) & int_flag)){ + if(RESET != ((HAU_INTEN & ret) & int_flag)) { flag = SET; } - + return flag; } @@ -320,7 +317,7 @@ FlagStatus hau_interrupt_flag_get(uint32_t int_flag) \brief clear the HAU interrupt flag status \param[in] int_flag: HAU interrupt flag status one or more parameters can be selected which are shown as below - \arg HAU_INT_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO + \arg HAU_INT_FLAG_DATA_INPUT: there is enough space (16 bytes) in the input FIFO \arg HAU_INT_FLAG_CALCULATION_COMPLETE: digest calculation is completed \param[out] none \retval none diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_hau_sha_md5.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_hau_sha_md5.c index a486f9b6..4b456d66 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_hau_sha_md5.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_hau_sha_md5.c @@ -2,36 +2,33 @@ \file gd32f20x_hau_sha_md5.c \brief HAU_SHA_MD5 driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -42,15 +39,15 @@ OF SUCH DAMAGE. /* HAU SHA/MD5 digest read in HASH mode */ static void hau_sha_md5_digest_read(uint32_t algo, uint8_t *output); /* HAU digest calculate process in HASH mode */ -static ErrStatus hau_hash_calculate(uint32_t algo, uint8_t *input, uint32_t in_length, uint8_t *output); +static ErrStatus hau_hash_calculate(uint32_t algo, uint8_t *input, uint32_t in_length, uint8_t *output); /* HAU digest calculate process in HMAC mode */ static ErrStatus hau_hmac_calculate(uint32_t algo, uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t in_length, uint8_t *output); /*! - \brief calculate digest using SHA1 in HASH mode - \param[in] input: pointer to the input buffer - \param[in] in_length: length of the input buffer - \param[in] output: the result digest + \brief calculate digest using SHA1 in HASH mode + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest \param[out] none \retval ErrStatus: SUCCESS or ERROR */ @@ -64,10 +61,10 @@ ErrStatus hau_hash_sha_1(uint8_t *input, uint32_t in_length, uint8_t output[20]) /*! \brief calculate digest using SHA1 in HMAC mode \param[in] key: pointer to the key used for HMAC - \param[in] keysize: length of the key used for HMAC - \param[in] input: pointer to the input buffer - \param[in] in_length: length of the input buffer - \param[in] output: the result digest + \param[in] keysize: length of the key used for HMAC + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest \param[out] none \retval ErrStatus: SUCCESS or ERROR */ @@ -80,9 +77,9 @@ ErrStatus hau_hmac_sha_1(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_ /*! \brief calculate digest using SHA224 in HASH mode - \param[in] input: pointer to the input buffer - \param[in] in_length: length of the input buffer - \param[in] output: the result digest + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest \param[out] none \retval ErrStatus: SUCCESS or ERROR */ @@ -96,10 +93,10 @@ ErrStatus hau_hash_sha_224(uint8_t *input, uint32_t in_length, uint8_t output[28 /*! \brief calculate digest using SHA224 in HMAC mode \param[in] key: pointer to the key used for HMAC - \param[in] keysize: length of the key used for HMAC - \param[in] input: pointer to the input buffer - \param[in] in_length: length of the input buffer - \param[in] output: the result digest + \param[in] keysize: length of the key used for HMAC + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest \param[out] none \retval ErrStatus: SUCCESS or ERROR */ @@ -112,9 +109,9 @@ ErrStatus hau_hmac_sha_224(uint8_t *key, uint32_t keysize, uint8_t *input, uint3 /*! \brief calculate digest using SHA256 in HASH mode - \param[in] input: pointer to the input buffer - \param[in] in_length: length of the input buffer - \param[in] output: the result digest + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest \param[out] none \retval ErrStatus: SUCCESS or ERROR */ @@ -128,10 +125,10 @@ ErrStatus hau_hash_sha_256(uint8_t *input, uint32_t in_length, uint8_t output[32 /*! \brief calculate digest using SHA256 in HMAC mode \param[in] key: pointer to the key used for HMAC - \param[in] keysize: length of the key used for HMAC - \param[in] input: pointer to the input buffer - \param[in] in_length: length of the input buffer - \param[in] output: the result digest + \param[in] keysize: length of the key used for HMAC + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest \param[out] none \retval ErrStatus: SUCCESS or ERROR */ @@ -139,14 +136,14 @@ ErrStatus hau_hmac_sha_256(uint8_t *key, uint32_t keysize, uint8_t *input, uint3 { ErrStatus ret = ERROR; ret = hau_hmac_calculate(HAU_ALGO_SHA256, key, keysize, input, in_length, output); - return ret; + return ret; } /*! - \brief calculate digest using MD5 in HASH mode - \param[in] input: pointer to the input buffer - \param[in] in_length: length of the input buffer - \param[in] output: the result digest + \brief calculate digest using MD5 in HASH mode + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest \param[out] none \retval ErrStatus: SUCCESS or ERROR */ @@ -160,10 +157,10 @@ ErrStatus hau_hash_md5(uint8_t *input, uint32_t in_length, uint8_t output[16]) /*! \brief calculate digest using MD5 in HMAC mode \param[in] key: pointer to the key used for HMAC - \param[in] keysize: length of the key used for HMAC - \param[in] input: pointer to the input buffer - \param[in] in_length: length of the input buffer - \param[in] output: the result digest + \param[in] keysize: length of the key used for HMAC + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest \param[out] none \retval ErrStatus: SUCCESS or ERROR */ @@ -176,72 +173,72 @@ ErrStatus hau_hmac_md5(uint8_t *key, uint32_t keysize, uint8_t *input, uint32_t /*! \brief HAU SHA/MD5 digest read - \param[in] algo: algorithm selection + \param[in] algo: algorithm selection \param[out] output: the result digest \retval none */ static void hau_sha_md5_digest_read(uint32_t algo, uint8_t *output) { hau_digest_parameter_struct digest_para; - uint32_t outputaddr = (uint32_t)output; - - switch(algo){ - case HAU_ALGO_SHA1: + uint32_t outputaddr = (uint32_t)output; + + switch(algo) { + case HAU_ALGO_SHA1: hau_digest_read(&digest_para); - *(uint32_t*)(outputaddr) = __REV(digest_para.out[0]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[0]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[1]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[1]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[2]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[2]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[3]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[3]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[4]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[4]); break; case HAU_ALGO_SHA224: hau_digest_read(&digest_para); - *(uint32_t*)(outputaddr) = __REV(digest_para.out[0]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[0]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[1]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[1]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[2]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[2]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[3]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[3]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[4]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[4]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[5]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[5]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[6]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[6]); break; case HAU_ALGO_SHA256: hau_digest_read(&digest_para); - *(uint32_t*)(outputaddr) = __REV(digest_para.out[0]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[0]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[1]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[1]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[2]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[2]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[3]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[3]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[4]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[4]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[5]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[5]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[6]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[6]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[7]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[7]); break; case HAU_ALGO_MD5: hau_digest_read(&digest_para); - *(uint32_t*)(outputaddr) = __REV(digest_para.out[0]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[0]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[1]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[1]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[2]); + *(uint32_t *)(outputaddr) = __REV(digest_para.out[2]); outputaddr += 4U; - *(uint32_t*)(outputaddr) = __REV(digest_para.out[3]); - break; + *(uint32_t *)(outputaddr) = __REV(digest_para.out[3]); + break; default: break; } @@ -250,16 +247,16 @@ static void hau_sha_md5_digest_read(uint32_t algo, uint8_t *output) /*! \brief HAU digest calculate process in HASH mode \param[in] algo: algorithm selection - \param[in] input: pointer to the input buffer - \param[in] in_length: length of the input buffer - \param[in] output: the result digest + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest \param[out] none \retval ErrStatus: SUCCESS or ERROR */ static ErrStatus hau_hash_calculate(uint32_t algo, uint8_t *input, uint32_t in_length, uint8_t *output) { hau_init_parameter_struct init_para; - + __IO uint32_t num_last_valid = 0U; uint32_t i = 0U; __IO uint32_t counter = 0U; @@ -282,8 +279,8 @@ static ErrStatus hau_hash_calculate(uint32_t algo, uint8_t *input, uint32_t in_l hau_last_word_validbits_num_config(num_last_valid); /* write data to the IN FIFO */ - for(i = 0U; i < in_length; i += 4U){ - hau_data_write(*(uint32_t*)inputaddr); + for(i = 0U; i < in_length; i += 4U) { + hau_data_write(*(uint32_t *)inputaddr); inputaddr += 4U; } @@ -291,14 +288,14 @@ static ErrStatus hau_hash_calculate(uint32_t algo, uint8_t *input, uint32_t in_l hau_digest_calculation_enable(); /* wait until the busy flag is reset */ - do{ + do { busystatus = hau_flag_get(HAU_FLAG_BUSY); counter++; - }while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); + } while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); - if(RESET != busystatus){ + if(RESET != busystatus) { return ERROR; - }else{ + } else { /* read the message digest */ hau_sha_md5_digest_read(algo, output); } @@ -309,10 +306,10 @@ static ErrStatus hau_hash_calculate(uint32_t algo, uint8_t *input, uint32_t in_l \brief HAU digest calculate process in HMAC mode \param[in] algo: algorithm selection \param[in] key: pointer to the key used for HMAC - \param[in] keysize: length of the key used for HMAC - \param[in] input: pointer to the input buffer - \param[in] in_length: length of the input buffer - \param[in] output: the result digest + \param[in] keysize: length of the key used for HMAC + \param[in] input: pointer to the input buffer + \param[in] in_length: length of the input buffer + \param[in] output: the result digest \param[out] none \retval ErrStatus: SUCCESS or ERROR */ @@ -340,9 +337,9 @@ static ErrStatus hau_hmac_calculate(uint32_t algo, uint8_t *key, uint32_t keysiz init_para.algo = algo; init_para.mode = HAU_MODE_HMAC; init_para.datatype = HAU_SWAPPING_8BIT; - if(keysize > 64U){ + if(keysize > 64U) { init_para.keytype = HAU_KEY_LONGGER_64; - }else{ + } else { init_para.keytype = HAU_KEY_SHORTER_64; } hau_init(&init_para); @@ -351,8 +348,8 @@ static ErrStatus hau_hmac_calculate(uint32_t algo, uint8_t *key, uint32_t keysiz hau_last_word_validbits_num_config((uint32_t)num_key_valid); /* write the key */ - for(i = 0U; i < keysize; i += 4U){ - hau_data_write(*(uint32_t*)keyaddr); + for(i = 0U; i < keysize; i += 4U) { + hau_data_write(*(uint32_t *)keyaddr); keyaddr += 4U; } @@ -360,20 +357,20 @@ static ErrStatus hau_hmac_calculate(uint32_t algo, uint8_t *key, uint32_t keysiz hau_digest_calculation_enable(); /* wait until the busy flag is reset */ - do{ + do { busystatus = hau_flag_get(HAU_FLAG_BUSY); counter++; - }while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); + } while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); - if(RESET != busystatus){ + if(RESET != busystatus) { return ERROR; - }else{ + } else { /* configure the number of valid bits in last word of the message */ hau_last_word_validbits_num_config((uint32_t)num_last_valid); /* write data to the IN FIFO */ - for(i = 0U; i < in_length; i += 4U){ - hau_data_write(*(uint32_t*)inputaddr); + for(i = 0U; i < in_length; i += 4U) { + hau_data_write(*(uint32_t *)inputaddr); inputaddr += 4U; } @@ -382,21 +379,21 @@ static ErrStatus hau_hmac_calculate(uint32_t algo, uint8_t *key, uint32_t keysiz /* wait until the busy flag is reset */ counter = 0U; - do{ + do { busystatus = hau_flag_get(HAU_FLAG_BUSY); counter++; - }while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); + } while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); - if(RESET != busystatus){ + if(RESET != busystatus) { return ERROR; - }else{ + } else { /* configure the number of valid bits in last word of the key */ hau_last_word_validbits_num_config((uint32_t)num_key_valid); /* write the key */ keyaddr = (uint32_t)key; - for(i = 0U; i < keysize; i += 4U){ - hau_data_write(*(uint32_t*)keyaddr); + for(i = 0U; i < keysize; i += 4U) { + hau_data_write(*(uint32_t *)keyaddr); keyaddr += 4U; } @@ -404,19 +401,19 @@ static ErrStatus hau_hmac_calculate(uint32_t algo, uint8_t *key, uint32_t keysiz hau_digest_calculation_enable(); /* wait until the busy flag is reset */ - counter =0U; - do{ + counter = 0U; + do { busystatus = hau_flag_get(HAU_FLAG_BUSY); counter++; - }while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); + } while((SHAMD5_BSY_TIMEOUT != counter) && (RESET != busystatus)); - if(RESET != busystatus){ + if(RESET != busystatus) { return ERROR; - }else{ + } else { /* read the message digest */ hau_sha_md5_digest_read(algo, output); } - } + } } - return SUCCESS; + return SUCCESS; } diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_i2c.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_i2c.c index 1911cd73..9947df63 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_i2c.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_i2c.c @@ -2,51 +2,47 @@ \file gd32f20x_i2c.c \brief I2C driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x - \version 2019-04-16, V2.1.1, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "gd32f20x_i2c.h" /* I2C register bit mask */ -#define I2CCLK_MAX ((uint32_t)0x0000003FU) /*!< i2cclk maximum value */ +#define I2CCLK_MAX ((uint32_t)0x0000003CU) /*!< i2cclk maximum value */ #define I2CCLK_MIN ((uint32_t)0x00000002U) /*!< i2cclk minimum value */ #define I2C_FLAG_MASK ((uint32_t)0x0000FFFFU) /*!< i2c flag mask */ #define I2C_ADDRESS_MASK ((uint32_t)0x000003FFU) /*!< i2c address mask */ #define I2C_ADDRESS2_MASK ((uint32_t)0x000000FEU) /*!< the second i2c address mask */ /* I2C register bit offset */ -#define STAT1_PECV_OFFSET ((uint32_t)8U) /* bit offset of PECV in I2C_STAT1 */ +#define STAT1_PECV_OFFSET ((uint32_t)0x00000008U) /* bit offset of PECV in I2C_STAT1 */ /*! \brief reset I2C @@ -56,7 +52,7 @@ OF SUCH DAMAGE. */ void i2c_deinit(uint32_t i2c_periph) { - switch(i2c_periph){ + switch(i2c_periph) { case I2C0: /* reset I2C0 */ rcu_periph_reset_enable(RCU_I2C0RST); @@ -74,7 +70,6 @@ void i2c_deinit(uint32_t i2c_periph) break; default: break; - } } @@ -82,92 +77,92 @@ void i2c_deinit(uint32_t i2c_periph) \brief configure I2C clock \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] clkspeed: I2C clock speed, supports standard mode (up to 100 kHz), fast mode (up to 400 kHz) - and fast mode plus (up to 1MHz) - \param[in] dutycyc: duty cycle in fast mode or fast mode plus + \param[in] dutycyc: duty cycle in fast mode only one parameter can be selected which is shown as below: - \arg I2C_DTCY_2: T_low/T_high=2 - \arg I2C_DTCY_16_9: T_low/T_high=16/9 + \arg I2C_DTCY_2: T_low/T_high = 2 in fast mode + \arg I2C_DTCY_16_9: T_low/T_high = 16/9 in fast mode \param[out] none \retval none */ -void i2c_clock_config(uint32_t i2c_periph,uint32_t clkspeed,uint32_t dutycyc) +void i2c_clock_config(uint32_t i2c_periph, uint32_t clkspeed, uint32_t dutycyc) { - uint32_t pclk1,clkc,freq,risetime; + uint32_t pclk1, clkc, freq, risetime; uint32_t temp; - + pclk1 = rcu_clock_freq_get(CK_APB1); /* I2C peripheral clock frequency */ - freq = (uint32_t)(pclk1/1000000U); - if(freq >= I2CCLK_MAX){ + freq = (uint32_t)(pclk1 / 1000000U); + if(freq >= I2CCLK_MAX) { freq = I2CCLK_MAX; } temp = I2C_CTL1(i2c_periph); temp &= ~I2C_CTL1_I2CCLK; temp |= freq; - + I2C_CTL1(i2c_periph) = temp; - - if(100000U >= clkspeed){ + + if(100000U >= clkspeed) { /* the maximum SCL rise time is 1000ns in standard mode */ - risetime = (uint32_t)((pclk1/1000000U)+1U); - if(risetime >= I2CCLK_MAX){ + risetime = (uint32_t)((pclk1 / 1000000U) + 1U); + if(risetime >= I2CCLK_MAX) { I2C_RT(i2c_periph) = I2CCLK_MAX; - }else if(risetime <= I2CCLK_MIN){ + } else if(risetime <= I2CCLK_MIN) { I2C_RT(i2c_periph) = I2CCLK_MIN; - }else{ + } else { I2C_RT(i2c_periph) = risetime; } - clkc = (uint32_t)(pclk1/(clkspeed*2U)); - if(clkc < 0x04U){ - /* the CLKC in standard mode minmum value is 4 */ + clkc = (uint32_t)(pclk1 / (clkspeed * 2U)); + if(clkc < 0x04U) { + /* the CLKC in standard mode minimum value is 4 */ clkc = 0x04U; } + I2C_CKCFG(i2c_periph) |= (I2C_CKCFG_CLKC & clkc); - }else if(400000U >= clkspeed){ + } else if(400000U >= clkspeed) { /* the maximum SCL rise time is 300ns in fast mode */ - I2C_RT(i2c_periph) = (uint32_t)(((freq*(uint32_t)300U)/(uint32_t)1000U)+(uint32_t)1U); - if(I2C_DTCY_2 == dutycyc){ + I2C_RT(i2c_periph) = (uint32_t)(((freq * (uint32_t)300U) / (uint32_t)1000U) + (uint32_t)1U); + if(I2C_DTCY_2 == dutycyc) { /* I2C duty cycle is 2 */ - clkc = (uint32_t)(pclk1/(clkspeed*3U)); + clkc = (uint32_t)(pclk1 / (clkspeed * 3U)); I2C_CKCFG(i2c_periph) &= ~I2C_CKCFG_DTCY; - }else{ + } else { /* I2C duty cycle is 16/9 */ - clkc = (uint32_t)(pclk1/(clkspeed*25U)); + clkc = (uint32_t)(pclk1 / (clkspeed * 25U)); I2C_CKCFG(i2c_periph) |= I2C_CKCFG_DTCY; } - if(0U == (clkc & I2C_CKCFG_CLKC)){ - /* the CLKC in fast mode minmum value is 1 */ - clkc |= 0x0001U; + if(0U == (clkc & I2C_CKCFG_CLKC)) { + /* the CLKC in fast mode minimum value is 1 */ + clkc |= 0x0001U; } I2C_CKCFG(i2c_periph) |= I2C_CKCFG_FAST; I2C_CKCFG(i2c_periph) |= clkc; - }else{ + } else { } } /*! - \brief configure I2C address + \brief configure I2C address \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] mod: + \param[in] mode: only one parameter can be selected which is shown as below: - \arg I2C_I2CMODE_ENABLE: I2C mode + \arg I2C_I2CMODE_ENABLE: I2C mode \arg I2C_SMBUSMODE_ENABLE: SMBus mode \param[in] addformat: 7bits or 10bits only one parameter can be selected which is shown as below: - \arg I2C_ADDFORMAT_7BITS: 7bits - \arg I2C_ADDFORMAT_10BITS: 10bits + \arg I2C_ADDFORMAT_7BITS: address format is 7 bits + \arg I2C_ADDFORMAT_10BITS: address format is 10 bits \param[in] addr: I2C address \param[out] none \retval none */ -void i2c_mode_addr_config(uint32_t i2c_periph,uint32_t mode,uint32_t addformat,uint32_t addr) +void i2c_mode_addr_config(uint32_t i2c_periph, uint32_t mode, uint32_t addformat, uint32_t addr) { /* SMBus/I2C mode selected */ uint32_t ctl = 0U; - + ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_SMBEN); + ctl &= ~(I2C_CTL0_SMBEN); ctl |= mode; I2C_CTL0(i2c_periph) = ctl; /* configure address */ @@ -176,20 +171,20 @@ void i2c_mode_addr_config(uint32_t i2c_periph,uint32_t mode,uint32_t addformat,u } /*! - \brief SMBus type selection + \brief select SMBus type \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] type: only one parameter can be selected which is shown as below: - \arg I2C_SMBUS_DEVICE: device - \arg I2C_SMBUS_HOST: host + \arg I2C_SMBUS_DEVICE: SMBus mode device type + \arg I2C_SMBUS_HOST: SMBus mode host type \param[out] none \retval none */ void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type) { - if(I2C_SMBUS_HOST == type){ + if(I2C_SMBUS_HOST == type) { I2C_CTL0(i2c_periph) |= I2C_CTL0_SMBSEL; - }else{ + } else { I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_SMBSEL); } } @@ -206,11 +201,12 @@ void i2c_smbus_type_config(uint32_t i2c_periph, uint32_t type) */ void i2c_ack_config(uint32_t i2c_periph, uint32_t ack) { - if(I2C_ACK_ENABLE == ack){ - I2C_CTL0(i2c_periph) |= I2C_CTL0_ACKEN; - }else{ - I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_ACKEN); - } + uint32_t ctl = 0U; + + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_ACKEN); + ctl |= ack; + I2C_CTL0(i2c_periph) = ctl; } /*! @@ -218,38 +214,38 @@ void i2c_ack_config(uint32_t i2c_periph, uint32_t ack) \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] pos: only one parameter can be selected which is shown as below: - \arg I2C_ACKPOS_CURRENT: whether to send ACK or not for the current - \arg I2C_ACKPOS_NEXT: whether to send ACK or not for the next byte + \arg I2C_ACKPOS_CURRENT: ACKEN bit decides whether or not to send ACK or not for the current byte + \arg I2C_ACKPOS_NEXT: ACKEN bit decides whether or not to send ACK for the next byte \param[out] none \retval none */ void i2c_ackpos_config(uint32_t i2c_periph, uint32_t pos) { + uint32_t ctl = 0U; /* configure I2C POAP position */ - if(I2C_ACKPOS_NEXT == pos){ - I2C_CTL0(i2c_periph) |= I2C_CTL0_POAP; - }else{ - I2C_CTL0(i2c_periph) &= ~(I2C_CTL0_POAP); - } + ctl = I2C_CTL0(i2c_periph); + ctl &= ~(I2C_CTL0_POAP); + ctl |= pos; + I2C_CTL0(i2c_periph) = ctl; } /*! \brief master sends slave address \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] addr: slave address + \param[in] addr: slave address \param[in] trandirection: transmitter or receiver only one parameter can be selected which is shown as below: - \arg I2C_TRANSMITTER: transmitter - \arg I2C_RECEIVER: receiver + \arg I2C_TRANSMITTER: transmitter + \arg I2C_RECEIVER: receiver \param[out] none \retval none */ void i2c_master_addressing(uint32_t i2c_periph, uint32_t addr, uint32_t trandirection) { /* master is a transmitter or a receiver */ - if(I2C_TRANSMITTER == trandirection){ + if(I2C_TRANSMITTER == trandirection) { addr = addr & I2C_TRANSMITTER; - }else{ + } else { addr = addr | I2C_RECEIVER; } /* send slave address */ @@ -272,7 +268,7 @@ void i2c_dualaddr_enable(uint32_t i2c_periph, uint32_t addr) /*! \brief disable dual-address mode - \param[in] i2c_periph: I2Cx(x=0,1,2) + \param[in] i2c_periph: I2Cx(x=0,1,2) \param[out] none \retval none */ @@ -283,7 +279,7 @@ void i2c_dualaddr_disable(uint32_t i2c_periph) /*! \brief enable I2C - \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] i2c_periph: I2Cx(x=0,1,2) \param[out] none \retval none */ @@ -294,7 +290,7 @@ void i2c_enable(uint32_t i2c_periph) /*! \brief disable I2C - \param[in] i2c_periph: I2Cx(x=0,1) + \param[in] i2c_periph: I2Cx(x=0,1,2) \param[out] none \retval none */ @@ -328,7 +324,7 @@ void i2c_stop_on_bus(uint32_t i2c_periph) /*! \brief I2C transmit data function \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] data: data of transmission + \param[in] data: data of transmission \param[out] none \retval none */ @@ -349,20 +345,20 @@ uint8_t i2c_data_receive(uint32_t i2c_periph) } /*! - \brief enable I2C DMA mode + \brief configure I2C DMA mode \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] dmastate: only one parameter can be selected which is shown as below: - \arg I2C_DMA_ON: DMA mode enable - \arg I2C_DMA_OFF: DMA mode disable + \arg I2C_DMA_ON: enable DMA mode + \arg I2C_DMA_OFF: disable DMA mode \param[out] none \retval none */ -void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate) +void i2c_dma_config(uint32_t i2c_periph, uint32_t dmastate) { /* configure I2C DMA function */ uint32_t ctl = 0U; - + ctl = I2C_CTL1(i2c_periph); ctl &= ~(I2C_CTL1_DMAON); ctl |= dmastate; @@ -372,7 +368,7 @@ void i2c_dma_enable(uint32_t i2c_periph, uint32_t dmastate) /*! \brief configure whether next DMA EOT is DMA last transfer or not \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] dmalast: + \param[in] dmalast: only one parameter can be selected which is shown as below: \arg I2C_DMALST_ON: next DMA EOT is the last transfer \arg I2C_DMALST_OFF: next DMA EOT is not the last transfer @@ -383,7 +379,7 @@ void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast) { /* configure DMA last transfer */ uint32_t ctl = 0U; - + ctl = I2C_CTL1(i2c_periph); ctl &= ~(I2C_CTL1_DMALST); ctl |= dmalast; @@ -391,28 +387,28 @@ void i2c_dma_last_transfer_config(uint32_t i2c_periph, uint32_t dmalast) } /*! - \brief whether to stretch SCL low when data is not ready in slave mode + \brief whether to stretch SCL low when data is not ready in slave mode \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] stretchpara: only one parameter can be selected which is shown as below: - \arg I2C_SCLSTRETCH_ENABLE: SCL stretching is enabled - \arg I2C_SCLSTRETCH_DISABLE: SCL stretching is disabled + \arg I2C_SCLSTRETCH_ENABLE: enable SCL stretching + \arg I2C_SCLSTRETCH_DISABLE: disable SCL stretching \param[out] none \retval none */ void i2c_stretch_scl_low_config(uint32_t i2c_periph, uint32_t stretchpara) { - /* configure I2C SCL strerching enable or disable */ + /* configure I2C SCL strerching */ uint32_t ctl = 0U; - + ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_DISSTRC); + ctl &= ~(I2C_CTL0_SS); ctl |= stretchpara; I2C_CTL0(i2c_periph) = ctl; } /*! - \brief whether or not to response to a general call + \brief whether or not to response to a general call \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] gcallpara: only one parameter can be selected which is shown as below: @@ -425,15 +421,15 @@ void i2c_slave_response_to_gcall_config(uint32_t i2c_periph, uint32_t gcallpara) { /* configure slave response to a general call enable or disable */ uint32_t ctl = 0U; - + ctl = I2C_CTL0(i2c_periph); - ctl &= ~(I2C_CTL0_GCEN); + ctl &= ~(I2C_CTL0_GCEN); ctl |= gcallpara; I2C_CTL0(i2c_periph) = ctl; } /*! - \brief software reset I2C + \brief configure software reset of I2C \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] sreset: only one parameter can be selected which is shown as below: @@ -454,16 +450,16 @@ void i2c_software_reset_config(uint32_t i2c_periph, uint32_t sreset) } /*! - \brief I2C PEC calculation on or off + \brief configure I2C PEC calculation \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] pecpara: + \param[in] pecstate: only one parameter can be selected which is shown as below: - \arg I2C_PEC_ENABLE: PEC calculation on - \arg I2C_PEC_DISABLE: PEC calculation off + \arg I2C_PEC_ENABLE: PEC calculation on + \arg I2C_PEC_DISABLE: PEC calculation off \param[out] none \retval none */ -void i2c_pec_enable(uint32_t i2c_periph,uint32_t pecstate) +void i2c_pec_config(uint32_t i2c_periph, uint32_t pecstate) { /* on/off PEC calculation */ uint32_t ctl = 0U; @@ -475,19 +471,20 @@ void i2c_pec_enable(uint32_t i2c_periph,uint32_t pecstate) } /*! - \brief I2C whether to transfer PEC value + \brief configure whether to transfer PEC value \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] pecpara: only one parameter can be selected which is shown as below: - \arg I2C_PECTRANS_ENABLE: transfer PEC - \arg I2C_PECTRANS_DISABLE: not transfer PEC + \arg I2C_PECTRANS_ENABLE: transfer PEC value + \arg I2C_PECTRANS_DISABLE: not transfer PEC value \param[out] none \retval none */ -void i2c_pec_transfer_enable(uint32_t i2c_periph,uint32_t pecpara) +void i2c_pec_transfer_config(uint32_t i2c_periph, uint32_t pecpara) { /* whether to transfer PEC */ uint32_t ctl = 0U; + ctl = I2C_CTL0(i2c_periph); ctl &= ~(I2C_CTL0_PECTRANS); ctl |= pecpara; @@ -495,31 +492,31 @@ void i2c_pec_transfer_enable(uint32_t i2c_periph,uint32_t pecpara) } /*! - \brief get packet error checking value + \brief get packet error checking value \param[in] i2c_periph: I2Cx(x=0,1,2) \param[out] none \retval PEC value */ uint8_t i2c_pec_value_get(uint32_t i2c_periph) { - return (uint8_t)((I2C_STAT1(i2c_periph) &I2C_STAT1_ECV) >> STAT1_PECV_OFFSET); + return (uint8_t)((I2C_STAT1(i2c_periph) & I2C_STAT1_PECV) >> STAT1_PECV_OFFSET); } /*! - \brief I2C issue alert through SMBA pin + \brief configure I2C alert through SMBA pin \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] smbuspara: only one parameter can be selected which is shown as below: - \arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin - \arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin + \arg I2C_SALTSEND_ENABLE: issue alert through SMBA pin + \arg I2C_SALTSEND_DISABLE: not issue alert through SMBA pin \param[out] none \retval none */ -void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) +void i2c_smbus_alert_config(uint32_t i2c_periph, uint32_t smbuspara) { - /* issue alert through SMBA pin configure*/ + /* configure smbus alert through SMBA pin */ uint32_t ctl = 0U; - + ctl = I2C_CTL0(i2c_periph); ctl &= ~(I2C_CTL0_SALT); ctl |= smbuspara; @@ -527,7 +524,7 @@ void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) } /*! - \brief enable or disable I2C ARP protocol in SMBus switch + \brief configure I2C ARP protocol in SMBus \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] arpstate: only one parameter can be selected which is shown as below: @@ -536,11 +533,11 @@ void i2c_smbus_issue_alert(uint32_t i2c_periph, uint32_t smbuspara) \param[out] none \retval none */ -void i2c_smbus_arp_enable(uint32_t i2c_periph,uint32_t arpstate) +void i2c_smbus_arp_config(uint32_t i2c_periph, uint32_t arpstate) { /* enable or disable I2C ARP protocol*/ uint32_t ctl = 0U; - + ctl = I2C_CTL0(i2c_periph); ctl &= ~(I2C_CTL0_ARPEN); ctl |= arpstate; @@ -552,23 +549,23 @@ void i2c_smbus_arp_enable(uint32_t i2c_periph,uint32_t arpstate) \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] flag: I2C flags, refer to i2c_flag_enum only one parameter can be selected which is shown as below: - \arg I2C_FLAG_SBSEND: start condition send out + \arg I2C_FLAG_SBSEND: start condition sent out in master mode \arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode \arg I2C_FLAG_BTC: byte transmission finishes \arg I2C_FLAG_ADD10SEND: header of 10-bit address is sent in master mode \arg I2C_FLAG_STPDET: stop condition detected in slave mode - \arg I2C_FLAG_RBNE: I2C_DATA is not Empty during receiving + \arg I2C_FLAG_RBNE: I2C_DATA is not empty during receiving \arg I2C_FLAG_TBE: I2C_DATA is empty during transmitting \arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus \arg I2C_FLAG_LOSTARB: arbitration lost in master mode \arg I2C_FLAG_AERR: acknowledge error - \arg I2C_FLAG_OUERR: overrun or underrun situation occurs in slave mode + \arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode \arg I2C_FLAG_PECERR: PEC error when receiving data \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode \arg I2C_FLAG_SMBALT: SMBus alert status \arg I2C_FLAG_MASTER: a flag indicating whether I2C block is in master or slave mode \arg I2C_FLAG_I2CBSY: busy flag - \arg I2C_FLAG_TRS: whether the I2C is a transmitter or a receiver + \arg I2C_FLAG_TR: whether the I2C is a transmitter or a receiver \arg I2C_FLAG_RXGC: general call address (00h) received \arg I2C_FLAG_DEFSMB: default address of SMBus device \arg I2C_FLAG_HSTSMB: SMBus host header detected in slave mode @@ -578,36 +575,36 @@ void i2c_smbus_arp_enable(uint32_t i2c_periph,uint32_t arpstate) */ FlagStatus i2c_flag_get(uint32_t i2c_periph, i2c_flag_enum flag) { - if(RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))){ + if(RESET != (I2C_REG_VAL(i2c_periph, flag) & BIT(I2C_BIT_POS(flag)))) { return SET; - }else{ + } else { return RESET; } } /*! - \brief clear I2C flag + \brief clear I2C flag status \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] flag: I2C flags, refer to i2c_flag_enum only one parameter can be selected which is shown as below: - \arg I2C_FLAG_SMBALT: SMBus Alert status + \arg I2C_FLAG_SMBALT: SMBus alert status \arg I2C_FLAG_SMBTO: timeout signal in SMBus mode \arg I2C_FLAG_PECERR: PEC error when receiving data - \arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode + \arg I2C_FLAG_OUERR: over-run or under-run situation occurs in slave mode \arg I2C_FLAG_AERR: acknowledge error - \arg I2C_FLAG_LOSTARB: arbitration lost in master mode - \arg I2C_FLAG_BERR: a bus error - \arg I2C_FLAG_ADDSEND: cleared by reading I2C_STAT0 and reading I2C_STAT1 + \arg I2C_FLAG_LOSTARB: arbitration lost in master mode + \arg I2C_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus + \arg I2C_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode \param[out] none \retval none */ void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag) { - if(I2C_FLAG_ADDSEND == flag){ + if(I2C_FLAG_ADDSEND == flag) { /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ I2C_STAT0(i2c_periph); I2C_STAT1(i2c_periph); - }else{ + } else { I2C_REG_VAL(i2c_periph, flag) &= ~BIT(I2C_BIT_POS(flag)); } } @@ -617,9 +614,9 @@ void i2c_flag_clear(uint32_t i2c_periph, i2c_flag_enum flag) \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum only one parameter can be selected which is shown as below: - \arg I2C_INT_ERR: error interrupt enable - \arg I2C_INT_EV: event interrupt enable - \arg I2C_INT_BUF: buffer interrupt enable + \arg I2C_INT_ERR: error interrupt + \arg I2C_INT_EV: event interrupt + \arg I2C_INT_BUF: buffer interrupt \param[out] none \retval none */ @@ -631,11 +628,11 @@ void i2c_interrupt_enable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) /*! \brief disable I2C interrupt \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] interrupt: I2C interrupts, refer to i2c_flag_enum + \param[in] interrupt: I2C interrupts, refer to i2c_interrupt_enum only one parameter can be selected which is shown as below: - \arg I2C_INT_ERR: error interrupt enable - \arg I2C_INT_EV: event interrupt enable - \arg I2C_INT_BUF: buffer interrupt enable + \arg I2C_INT_ERR: error interrupt + \arg I2C_INT_EV: event interrupt + \arg I2C_INT_BUF: buffer interrupt \param[out] none \retval none */ @@ -645,15 +642,15 @@ void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) } /*! - \brief check I2C interrupt flag + \brief get I2C interrupt flag status \param[in] i2c_periph: I2Cx(x=0,1,2) \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum only one parameter can be selected which is shown as below: \arg I2C_INT_FLAG_SBSEND: start condition sent out in master mode interrupt flag \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag - \arg I2C_INT_FLAG_BTC: byte transmission finishes + \arg I2C_INT_FLAG_BTC: byte transmission finishes interrupt flag \arg I2C_INT_FLAG_ADD10SEND: header of 10-bit address is sent in master mode interrupt flag - \arg I2C_INT_FLAG_STPDET: etop condition detected in slave mode interrupt flag + \arg I2C_INT_FLAG_STPDET: stop condition detected in slave mode interrupt flag \arg I2C_INT_FLAG_RBNE: I2C_DATA is not Empty during receiving interrupt flag \arg I2C_INT_FLAG_TBE: I2C_DATA is empty during transmitting interrupt flag \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag @@ -662,40 +659,40 @@ void i2c_interrupt_disable(uint32_t i2c_periph, i2c_interrupt_enum interrupt) \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag - \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus alert status interrupt flag \param[out] none - \retval FlagStatus SET or RESET + \retval FlagStatus: SET or RESET */ FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) { uint32_t intenable = 0U, flagstatus = 0U, bufie; - + /* check BUFIE */ bufie = I2C_CTL1(i2c_periph)&I2C_CTL1_BUFIE; - + /* get the interrupt enable bit status */ intenable = (I2C_REG_VAL(i2c_periph, int_flag) & BIT(I2C_BIT_POS(int_flag))); /* get the corresponding flag bit status */ flagstatus = (I2C_REG_VAL2(i2c_periph, int_flag) & BIT(I2C_BIT_POS2(int_flag))); - if((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)){ - if(intenable && bufie){ + if((I2C_INT_FLAG_RBNE == int_flag) || (I2C_INT_FLAG_TBE == int_flag)) { + if(intenable && bufie) { intenable = 1U; - }else{ + } else { intenable = 0U; } } - if((0U != flagstatus) && (0U != intenable)){ + if((0U != flagstatus) && (0U != intenable)) { return SET; - }else{ + } else { return RESET; } } /*! - \brief clear I2C interrupt flag + \brief clear I2C interrupt flag status \param[in] i2c_periph: I2Cx(x=0,1,2) - \param[in] intflag: I2C interrupt flags, refer to i2c_interrupt_flag_enum + \param[in] int_flag: I2C interrupt flags, refer to i2c_interrupt_flag_enum only one parameter can be selected which is shown as below: \arg I2C_INT_FLAG_ADDSEND: address is sent in master mode or received and matches in slave mode interrupt flag \arg I2C_INT_FLAG_BERR: a bus error occurs indication a unexpected start or stop condition on I2C bus interrupt flag @@ -704,17 +701,17 @@ FlagStatus i2c_interrupt_flag_get(uint32_t i2c_periph, i2c_interrupt_flag_enum i \arg I2C_INT_FLAG_OUERR: over-run or under-run situation occurs in slave mode interrupt flag \arg I2C_INT_FLAG_PECERR: PEC error when receiving data interrupt flag \arg I2C_INT_FLAG_SMBTO: timeout signal in SMBus mode interrupt flag - \arg I2C_INT_FLAG_SMBALT: SMBus Alert status interrupt flag + \arg I2C_INT_FLAG_SMBALT: SMBus alert status interrupt flag \param[out] none \retval none */ void i2c_interrupt_flag_clear(uint32_t i2c_periph, i2c_interrupt_flag_enum int_flag) { - if(I2C_INT_FLAG_ADDSEND == int_flag){ + if(I2C_INT_FLAG_ADDSEND == int_flag) { /* read I2C_STAT0 and then read I2C_STAT1 to clear ADDSEND */ I2C_STAT0(i2c_periph); I2C_STAT1(i2c_periph); - }else{ + } else { I2C_REG_VAL2(i2c_periph, int_flag) &= ~BIT(I2C_BIT_POS2(int_flag)); } } diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_misc.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_misc.c index 4a45def6..2f0fe097 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_misc.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_misc.c @@ -2,36 +2,33 @@ \file gd32f20x_misc.c \brief MISC driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -40,11 +37,11 @@ OF SUCH DAMAGE. /*! \brief set the priority group \param[in] nvic_prigroup: the NVIC priority group - \arg NVIC_PRIGROUP_PRE0_SUB4:0 bits for pre-emption priority 4 bits for subpriority - \arg NVIC_PRIGROUP_PRE1_SUB3:1 bits for pre-emption priority 3 bits for subpriority - \arg NVIC_PRIGROUP_PRE2_SUB2:2 bits for pre-emption priority 2 bits for subpriority - \arg NVIC_PRIGROUP_PRE3_SUB1:3 bits for pre-emption priority 1 bits for subpriority - \arg NVIC_PRIGROUP_PRE4_SUB0:4 bits for pre-emption priority 0 bits for subpriority + \arg NVIC_PRIGROUP_PRE0_SUB4: 0 bits for pre-emption priority, 4 bits for subpriority + \arg NVIC_PRIGROUP_PRE1_SUB3: 1 bits for pre-emption priority, 3 bits for subpriority + \arg NVIC_PRIGROUP_PRE2_SUB2: 2 bits for pre-emption priority, 2 bits for subpriority + \arg NVIC_PRIGROUP_PRE3_SUB1: 3 bits for pre-emption priority, 1 bits for subpriority + \arg NVIC_PRIGROUP_PRE4_SUB0: 4 bits for pre-emption priority, 0 bits for subpriority \param[out] none \retval none */ @@ -55,21 +52,21 @@ void nvic_priority_group_set(uint32_t nvic_prigroup) } /*! - \brief enable NVIC request + \brief enable NVIC interrupt request \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type \param[in] nvic_irq_pre_priority: the pre-emption priority needed to set \param[in] nvic_irq_sub_priority: the subpriority needed to set \param[out] none \retval none */ -void nvic_irq_enable(uint8_t nvic_irq, - uint8_t nvic_irq_pre_priority, +void nvic_irq_enable(uint8_t nvic_irq, + uint8_t nvic_irq_pre_priority, uint8_t nvic_irq_sub_priority) { uint32_t temp_priority = 0x00U, temp_pre = 0x00U, temp_sub = 0x00U; /* use the priority group value to get the temp_pre and the temp_sub */ - switch ((SCB->AIRCR) & (uint32_t)0x700U) { + switch((SCB->AIRCR) & (uint32_t)0x700U) { case NVIC_PRIGROUP_PRE0_SUB4: temp_pre = 0U; temp_sub = 0x4U; @@ -99,7 +96,7 @@ void nvic_irq_enable(uint8_t nvic_irq, /* get the temp_priority to fill the NVIC->IP register */ temp_priority = (uint32_t)nvic_irq_pre_priority << (0x4U - temp_pre); - temp_priority |= nvic_irq_sub_priority &(0x0FU >> (0x4U - temp_sub)); + temp_priority |= nvic_irq_sub_priority & (0x0FU >> (0x4U - temp_sub)); temp_priority = temp_priority << 0x04U; NVIC->IP[nvic_irq] = (uint8_t)temp_priority; @@ -108,7 +105,7 @@ void nvic_irq_enable(uint8_t nvic_irq, } /*! - \brief disable NVIC request + \brief disable NVIC interrupt request \param[in] nvic_irq: the NVIC interrupt request, detailed in IRQn_Type \param[out] none \retval none @@ -124,22 +121,24 @@ void nvic_irq_disable(uint8_t nvic_irq) \param[in] nvic_vict_tab: the RAM or FLASH base address \arg NVIC_VECTTAB_RAM: RAM base address \are NVIC_VECTTAB_FLASH: Flash base address - \param[in] offset: Vector Table offset + \param[in] offset: vector table offset \param[out] none \retval none */ void nvic_vector_table_set(uint32_t nvic_vict_tab, uint32_t offset) { SCB->VTOR = nvic_vict_tab | (offset & NVIC_VECTTAB_OFFSET_MASK); + + __DSB(); } /*! \brief set the state of the low power mode \param[in] lowpower_mode: the low power mode state - \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system always enter low power + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system always enter low power mode by exiting from ISR \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the DEEPSLEEP mode - \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode can be woke up + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the low power mode can be woke up by all the enable and disable interrupts \param[out] none \retval none @@ -152,10 +151,10 @@ void system_lowpower_set(uint8_t lowpower_mode) /*! \brief reset the state of the low power mode \param[in] lowpower_mode: the low power mode state - \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system will exit low power + \arg SCB_LPM_SLEEP_EXIT_ISR: if chose this para, the system will exit low power mode by exiting from ISR \arg SCB_LPM_DEEPSLEEP: if chose this para, the system will enter the SLEEP mode - \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the lowpower mode only can be + \arg SCB_LPM_WAKE_BY_ALL_INT: if chose this para, the low power mode only can be woke up by the enable interrupts \param[out] none \retval none @@ -176,10 +175,10 @@ void system_lowpower_reset(uint8_t lowpower_mode) void systick_clksource_set(uint32_t systick_clksource) { - if(SYSTICK_CLKSOURCE_HCLK == systick_clksource ){ + if(SYSTICK_CLKSOURCE_HCLK == systick_clksource) { /* set the systick clock source from HCLK */ SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK; - }else{ + } else { /* set the systick clock source from HCLK/8 */ SysTick->CTRL &= SYSTICK_CLKSOURCE_HCLK_DIV8; } diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_pmu.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_pmu.c index f66e5fc5..e284d06a 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_pmu.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_pmu.c @@ -2,36 +2,33 @@ \file gd32f20x_pmu.c \brief PMU driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -90,7 +87,7 @@ void pmu_lvd_disable(void) } /*! - \brief PMU work at sleep mode + \brief PMU work in sleep mode \param[in] sleepmodecmd: only one parameter can be selected which is shown as below: \arg WFI_CMD: use WFI command @@ -102,98 +99,96 @@ void pmu_to_sleepmode(uint8_t sleepmodecmd) { /* clear sleepdeep bit of Cortex-M3 system control register */ SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); - + /* select WFI or WFE command to enter sleep mode */ - if(WFI_CMD == sleepmodecmd){ + if(WFI_CMD == sleepmodecmd) { __WFI(); - }else{ + } else { __WFE(); } } /*! - \brief PMU work at deepsleep mode + \brief PMU work in deepsleep mode \param[in] ldo: only one parameter can be selected which is shown as below: \arg PMU_LDO_NORMAL: LDO work at normal power mode when pmu enter deepsleep mode \arg PMU_LDO_LOWPOWER: LDO work at low power mode when pmu enter deepsleep mode \param[in] deepsleepmodecmd: - only one parameter can be selected which is shown as below: + only one parameter can be selected which is shown as below: \arg WFI_CMD: use WFI command \arg WFE_CMD: use WFE command \param[out] none \retval none */ -void pmu_to_deepsleepmode(uint32_t ldo,uint8_t deepsleepmodecmd) +void pmu_to_deepsleepmode(uint32_t ldo, uint8_t deepsleepmodecmd) { - static uint32_t reg_snap[ 4 ]; + static uint32_t reg_snap[4]; /* clear stbmod and ldolp bits */ PMU_CTL &= ~((uint32_t)(PMU_CTL_STBMOD | PMU_CTL_LDOLP)); - + /* set ldolp bit according to pmu_ldo */ PMU_CTL |= ldo; - + /* set sleepdeep bit of Cortex-M3 system control register */ SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; - reg_snap[ 0 ] = REG32( 0xE000E010U ); - reg_snap[ 1 ] = REG32( 0xE000E100U ); - reg_snap[ 2 ] = REG32( 0xE000E104U ); - reg_snap[ 3 ] = REG32( 0xE000E108U ); - - REG32( 0xE000E010U ) &= 0x00010004U; - REG32( 0xE000E180U ) = 0XFF7FF83DU; - REG32( 0xE000E184U ) = 0XBFFFF8FFU; - REG32( 0xE000E188U ) = 0xFFFFFFFFU; - + reg_snap[0] = REG32(0xE000E010U); + reg_snap[1] = REG32(0xE000E100U); + reg_snap[2] = REG32(0xE000E104U); + reg_snap[3] = REG32(0xE000E108U); + + REG32(0xE000E010U) &= 0x00010004U; + REG32(0xE000E180U) = 0XFF7FF83DU; + REG32(0xE000E184U) = 0XBFFFF8FFU; + REG32(0xE000E188U) = 0xFFFFFFFFU; + /* select WFI or WFE command to enter deepsleep mode */ - if(WFI_CMD == deepsleepmodecmd){ + if(WFI_CMD == deepsleepmodecmd) { __WFI(); - }else{ + } else { __SEV(); __WFE(); __WFE(); } - - REG32( 0xE000E010U ) = reg_snap[ 0 ] ; - REG32( 0xE000E100U ) = reg_snap[ 1 ] ; - REG32( 0xE000E104U ) = reg_snap[ 2 ] ; - REG32( 0xE000E108U ) = reg_snap[ 3 ] ; - + + REG32(0xE000E010U) = reg_snap[0] ; + REG32(0xE000E100U) = reg_snap[1] ; + REG32(0xE000E104U) = reg_snap[2] ; + REG32(0xE000E108U) = reg_snap[3] ; + /* reset sleepdeep bit of Cortex-M3 system control register */ SCB->SCR &= ~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); } /*! - \brief pmu work at standby mode - \param[in] standbymodecmd: - only one parameter can be selected which is shown as below: - \arg WFI_CMD: use WFI command - \arg WFE_CMD: use WFE command + \brief pmu work in standby mode + \param[in] none \param[out] none \retval none */ -void pmu_to_standbymode(uint8_t standbymodecmd) +void pmu_to_standbymode(void) { - /* set sleepdeep bit of Cortex-M3 system control register */ - SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; - /* set stbmod bit */ PMU_CTL |= PMU_CTL_STBMOD; - + /* reset wakeup flag */ PMU_CTL |= PMU_CTL_WURST; - + + /* set sleepdeep bit of Cortex-M3 system control register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; + + REG32(0xE000E010U) &= 0x00010004U; + REG32(0xE000E180U) = 0XFFFFFFF7U; + REG32(0xE000E184U) = 0XFFFFFDFFU; + REG32(0xE000E188U) = 0xFFFFFFFFU; + /* select WFI or WFE command to enter standby mode */ - if(WFI_CMD == standbymodecmd){ - __WFI(); - }else{ - __WFE(); - } + __WFI(); } /*! - \brief enable wakeup pin + \brief enable PMU wakeup pin \param[in] none \param[out] none \retval none @@ -204,7 +199,7 @@ void pmu_wakeup_pin_enable(void) } /*! - \brief disable wakeup pin + \brief disable PMU wakeup pin \param[in] none \param[out] none \retval none @@ -248,25 +243,25 @@ void pmu_backup_write_disable(void) */ FlagStatus pmu_flag_get(uint32_t flag) { - if(PMU_CS & flag){ + if(PMU_CS & flag) { return SET; - }else{ + } else { return RESET; } } /*! \brief clear flag bit - \param[in] flag_reset: + \param[in] flag: only one parameter can be selected which is shown as below: \arg PMU_FLAG_RESET_WAKEUP: reset wakeup flag \arg PMU_FLAG_RESET_STANDBY: reset standby flag \param[out] none \retval none */ -void pmu_flag_clear(uint32_t flag_reset) +void pmu_flag_clear(uint32_t flag) { - switch(flag_reset){ + switch(flag) { case PMU_FLAG_RESET_WAKEUP: /* reset wakeup flag */ PMU_CTL |= PMU_CTL_WURST; diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_rcu.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_rcu.c index 69e3341c..3f7bc64e 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_rcu.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_rcu.c @@ -2,36 +2,33 @@ \file gd32f20x_rcu.c \brief RCU driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -58,16 +55,20 @@ void rcu_deinit(void) RCU_CTL |= RCU_CTL_IRC8MEN; rcu_osci_stab_wait(RCU_IRC8M); + RCU_CFG0 &= ~RCU_CFG0_SCS; + /* reset HXTALEN, CKMEN, PLLEN bits */ + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); + /* reset SCS, AHBPSC, APB1PSC, APB2PSC, ADCPSC, CKOUT0SEL bits */ RCU_CFG0 &= ~(RCU_CFG0_SCS | RCU_CFG0_AHBPSC | RCU_CFG0_APB1PSC | RCU_CFG0_APB2PSC | RCU_CFG0_ADCPSC | RCU_CFG0_ADCPSC_2 | RCU_CFG0_CKOUT0SEL); /* reset HXTALEN, CKMEN, PLLEN bits */ - RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN ); + RCU_CTL &= ~(RCU_CTL_HXTALEN | RCU_CTL_CKMEN | RCU_CTL_PLLEN); /* Reset HXTALBPS bit */ RCU_CTL &= ~(RCU_CTL_HXTALBPS); - + /* reset PLLSEL, PREDV0_LSB, PLLMF, USBFSPSC bits */ RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0_LSB | RCU_CFG0_PLLMF | RCU_CFG0_USBFSPSC | RCU_CFG0_PLLMF_4); @@ -77,16 +78,16 @@ void rcu_deinit(void) /* reset CFG1 register */ RCU_CFG1 = 0x00000000U; - + /* reset INT register */ RCU_INT = 0x00FF0000U; - + /* reset CFG2 register */ RCU_CFG2 = 0x00000000U; - + /* reset PLLTCTL register */ - RCU_PLLTCTL &= (~RCU_PLLTCTL_PLLTEN); - + RCU_PLLTCTL &= (~RCU_PLLTCTL_PLLTEN); + /* reset PLLTINT register */ RCU_PLLTINT = 0x00400000U; @@ -217,7 +218,7 @@ void rcu_periph_clock_sleep_disable(rcu_periph_sleep_enum periph) \arg RCU_CANxRST (x=0,1): reset CAN \arg RCU_PMURST: reset PMU \arg RCU_DACRST: reset DAC - \arg RCU_ADCRST (x=0,1,2): reset ADC + \arg RCU_ADCxRST (x=0,1,2): reset ADC \arg RCU_BKPIRST: reset BKPI \arg RCU_TLIRST: reset TLI \arg RCU_DCIRST: reset DCI @@ -249,7 +250,7 @@ void rcu_periph_reset_enable(rcu_periph_reset_enum periph_reset) \arg RCU_CANxRST (x=0,1): reset CAN \arg RCU_PMURST: reset PMU \arg RCU_DACRST: reset DAC - \arg RCU_ADCRST (x=0,1,2): reset ADC + \arg RCU_ADCxRST (x=0,1,2): reset ADC \arg RCU_BKPIRST: reset BKPI \arg RCU_TLIRST: reset TLI \arg RCU_DCIRST: reset DCI @@ -299,7 +300,7 @@ void rcu_bkp_reset_disable(void) void rcu_system_clock_source_config(uint32_t ck_sys) { uint32_t reg; - + reg = RCU_CFG0; /* reset the SCS bits and set according to ck_sys */ reg &= ~RCU_CFG0_SCS; @@ -324,14 +325,14 @@ uint32_t rcu_system_clock_source_get(void) \brief configure the AHB clock prescaler selection \param[in] ck_ahb: AHB clock prescaler selection only one parameter can be selected which is shown as below: - \arg RCU_AHB_CKSYS_DIVx, x=1, 2, 4, 8, 16, 64, 128, 256, 512 +\arg RCU_AHB_CKSYS_DIVx (x=1, 2, 4, 8, 16, 64, 128, 256, 512): select CK_SYS / x as CK_AHB \param[out] none \retval none */ void rcu_ahb_clock_config(uint32_t ck_ahb) { uint32_t reg; - + reg = RCU_CFG0; /* reset the AHBPSC bits and set according to ck_ahb */ @@ -354,7 +355,7 @@ void rcu_ahb_clock_config(uint32_t ck_ahb) void rcu_apb1_clock_config(uint32_t ck_apb1) { uint32_t reg; - + reg = RCU_CFG0; /* reset the APB1PSC and set according to ck_apb1 */ @@ -377,7 +378,7 @@ void rcu_apb1_clock_config(uint32_t ck_apb1) void rcu_apb2_clock_config(uint32_t ck_apb2) { uint32_t reg; - + reg = RCU_CFG0; /* reset the APB2PSC and set according to ck_apb2 */ @@ -398,7 +399,7 @@ void rcu_apb2_clock_config(uint32_t ck_apb2) \arg RCU_CKOUT0SRC_CKPLL2_DIV2: CK_PLL2/2 selected \arg RCU_CKOUT0SRC_EXT1: EXT1 selected \arg RCU_CKOUT0SRC_CKPLL2: PLL selected - \param[in] ckout0_div: CK_OUT0 divider + \param[in] ckout0_div: CK_OUT0 divider \arg RCU_CKOUT0_DIVx(x=1..64): CK_OUT0 is divided by x \param[out] none \retval none @@ -406,15 +407,15 @@ void rcu_apb2_clock_config(uint32_t ck_apb2) void rcu_ckout0_config(uint32_t ckout0_src, uint32_t ckout0_div) { uint32_t reg; - + reg = RCU_CFG0; - + /* set the CKOUT0SEL according to ckout0_src */ reg &= ~RCU_CFG0_CKOUT0SEL; RCU_CFG0 = (reg | ckout0_src); - + reg = RCU_CFG2; - + /* set the CKOUT0DIV according to ckout0_div */ reg &= ~RCU_CFG2_CKOUT0DIV; RCU_CFG2 = (reg | ckout0_div); @@ -433,7 +434,7 @@ void rcu_ckout0_config(uint32_t ckout0_src, uint32_t ckout0_div) \arg RCU_CKOUT1SRC_CKPLL2_DIV2: CK_PLL2/2 selected \arg RCU_CKOUT1SRC_EXT1: EXT1 selected \arg RCU_CKOUT1SRC_CKPLL2: PLL selected - \param[in] ckout1_div: CK_OUT1 divider + \param[in] ckout1_div: CK_OUT1 divider \arg RCU_CKOUT1_DIVx(x=1..64): CK_OUT1 is divided by x \param[out] none \retval none @@ -441,7 +442,7 @@ void rcu_ckout0_config(uint32_t ckout0_src, uint32_t ckout0_div) void rcu_ckout1_config(uint32_t ckout1_src, uint32_t ckout1_div) { uint32_t reg; - + reg = RCU_CFG2; /* set the CKOUT1SEL and CKOUT1DIV according to ckout1_src and ckout1_div */ reg &= ~(RCU_CFG2_CKOUT1SEL | RCU_CFG2_CKOUT1DIV); @@ -450,12 +451,12 @@ void rcu_ckout1_config(uint32_t ckout1_src, uint32_t ckout1_div) } /*! - \brief configure the main PLL clock + \brief configure the main PLL clock \param[in] pll_src: PLL clock source selection \arg RCU_PLLSRC_IRC8M_DIV2: IRC8M/2 clock selected as source clock of PLL \arg RCU_PLLSRC_HXTAL: HXTAL selected as source clock of PLL \param[in] pll_mul: PLL clock multiplication factor - \arg RCU_PLL_MULx (x = 2..14,16..32,6.5) + \arg RCU_PLL_MULx (x = 2..14,16..32,6.5): PLL clock * x \param[out] none \retval none */ @@ -480,14 +481,14 @@ void rcu_pll_config(uint32_t pll_src, uint32_t pll_mul) \arg RCU_PREDV0SRC_CKPLL1: CK_PLL1 selected as PREDV0 input source clock \param[in] predv0_div: PREDV0 division factor only one parameter can be selected which is shown as below: - \arg RCU_PREDV0_DIVx, x = 1..16 + \arg RCU_PREDV0_DIVx (x= 1..16): PREDV0 input source clock is divided x \param[out] none \retval none */ void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div) { uint32_t reg = 0U; - + reg = RCU_CFG1; /* reset PREDV0SEL and PREDV0 bits */ reg &= ~(RCU_CFG1_PREDV0SEL | RCU_CFG1_PREDV0); @@ -501,14 +502,14 @@ void rcu_predv0_config(uint32_t predv0_source, uint32_t predv0_div) \brief configure the PREDV1 division factor \param[in] predv1_div: PREDV1 division factor only one parameter can be selected which is shown as below: - \arg RCU_PREDV1_DIVx, x = 1..16 + \arg RCU_PREDV1_DIVx (x = 1..16): PREDV1 input source clock is divided x \param[out] none \retval none */ void rcu_predv1_config(uint32_t predv1_div) { uint32_t reg = 0U; - + reg = RCU_CFG1; /* reset the PREDV1 bits */ reg &= ~RCU_CFG1_PREDV1; @@ -519,10 +520,10 @@ void rcu_predv1_config(uint32_t predv1_div) } /*! - \brief configure the PLL1 clock + \brief configure the PLL1 clock \param[in] pll_mul: PLL clock multiplication factor only one parameter can be selected which is shown as below: - \arg RCU_PLL1_MULx (x = 8..16, 20) + \arg RCU_PLL1_MULx (x = 8..16, 20): PLL1 clock * x \param[out] none \retval none */ @@ -533,17 +534,17 @@ void rcu_pll1_config(uint32_t pll_mul) } /*! - \brief configure the PLL2 clock + \brief configure the PLL2 clock \param[in] pll_mul: PLL clock multiplication factor only one parameter can be selected which is shown as below: - \arg RCU_PLL2_MULx (x = 8..16, 20) + \arg RCU_PLL2_MULx (x = 8..16, 20): PLL2 clock * x \param[out] none \retval none */ void rcu_pll2_config(uint32_t pll_mul) { RCU_CFG1 &= ~RCU_CFG1_PLL2MF; - RCU_CFG1 |= pll_mul; + RCU_CFG1 |= pll_mul; } /*! @@ -568,22 +569,22 @@ void rcu_adc_clock_config(uint32_t adc_psc) reg0 &= ~(RCU_CFG0_ADCPSC_2 | RCU_CFG0_ADCPSC); /* set the ADC prescaler factor */ - switch(adc_psc){ - case RCU_CKADC_CKAPB2_DIV2: - case RCU_CKADC_CKAPB2_DIV4: - case RCU_CKADC_CKAPB2_DIV6: - case RCU_CKADC_CKAPB2_DIV8: - reg0 |= (adc_psc << 14); - break; - - case RCU_CKADC_CKAPB2_DIV12: - case RCU_CKADC_CKAPB2_DIV16: - adc_psc &= ~BIT(2); - reg0 |= (adc_psc << 14 | RCU_CFG0_ADCPSC_2); - break; - - default: - break; + switch(adc_psc) { + case RCU_CKADC_CKAPB2_DIV2: + case RCU_CKADC_CKAPB2_DIV4: + case RCU_CKADC_CKAPB2_DIV6: + case RCU_CKADC_CKAPB2_DIV8: + reg0 |= (adc_psc << 14); + break; + + case RCU_CKADC_CKAPB2_DIV12: + case RCU_CKADC_CKAPB2_DIV16: + adc_psc &= ~BIT(2); + reg0 |= (adc_psc << 14 | RCU_CFG0_ADCPSC_2); + break; + + default: + break; } /* set the register */ @@ -603,7 +604,7 @@ void rcu_adc_clock_config(uint32_t adc_psc) void rcu_usbfs_trng_clock_config(uint32_t usbfs_trng_psc) { uint32_t reg = 0U; - + reg = RCU_CFG0; /* configure the USBFS/TRNG prescaler factor */ @@ -611,7 +612,6 @@ void rcu_usbfs_trng_clock_config(uint32_t usbfs_trng_psc) RCU_CFG0 = (reg | usbfs_trng_psc); } - /*! \brief configure the RTC clock source selection \param[in] rtc_clock_source: RTC clock source selection @@ -626,8 +626,8 @@ void rcu_usbfs_trng_clock_config(uint32_t usbfs_trng_psc) void rcu_rtc_clock_config(uint32_t rtc_clock_source) { uint32_t reg; - - reg = RCU_BDCTL; + + reg = RCU_BDCTL; /* reset the RTCSRC bits and set according to rtc_clock_source */ reg &= ~RCU_BDCTL_RTCSRC; RCU_BDCTL = (reg | rtc_clock_source); @@ -645,8 +645,8 @@ void rcu_rtc_clock_config(uint32_t rtc_clock_source) void rcu_i2s1_clock_config(uint32_t i2s_clock_source) { uint32_t reg; - - reg = RCU_CFG1; + + reg = RCU_CFG1; /* reset the I2S1SEL bit and set according to i2s_clock_source */ reg &= ~RCU_CFG1_I2S1SEL; RCU_CFG1 = (reg | i2s_clock_source); @@ -664,140 +664,98 @@ void rcu_i2s1_clock_config(uint32_t i2s_clock_source) void rcu_i2s2_clock_config(uint32_t i2s_clock_source) { uint32_t reg; - - reg = RCU_CFG1; + + reg = RCU_CFG1; /* reset the I2S2SEL bit and set according to i2s_clock_source */ reg &= ~RCU_CFG1_I2S2SEL; RCU_CFG1 = (reg | i2s_clock_source); } /*! - \brief get the clock stabilization and periphral reset flags - \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum - only one parameter can be selected which is shown as below: - \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag - \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag - \arg RCU_FLAG_PLLSTB: PLL stabilization flag - \arg RCU_FLAG_PLL1STB: PLL1 stabilization flag - \arg RCU_FLAG_PLL2STB: PLL2 stabilization flag - \arg RCU_FLAG_PLLTSTB: PLLT stabilization flag - \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag - \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag - \arg RCU_FLAG_EPRST: external PIN reset flag - \arg RCU_FLAG_PORRST: power reset flag - \arg RCU_FLAG_SWRST: software reset flag - \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag - \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag - \arg RCU_FLAG_LPRST: low-power reset flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus rcu_flag_get(rcu_flag_enum flag) -{ - /* get the rcu flag */ - if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear all the reset flag - \param[in] none + \brief configure the PLLT clock selection + \param[in] pllt_src: PLLT clock source selection + \arg RCU_PLLTSRC_IRC8M: IRC8M selected as source clock of PLLT + \arg RCU_PLLTSRC_HXTAL: HXTAL selected as source clock of PLLT \param[out] none \retval none */ -void rcu_all_reset_flag_clear(void) +void rcu_pllt_config(uint32_t pllt_src) { - RCU_RSTSCK |= RCU_RSTSCK_RSTFC; + uint32_t reg = 0U; + + reg = RCU_PLLTCFG; + + /* reset the PLLT clock source bit PLLTSEL */ + reg &= ~RCU_PLLTCFG_PLLTSEL; + + RCU_PLLTCFG = (reg | pllt_src); } /*! - \brief get the clock stabilization and ckm interrupt flags - \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum - only one parameter can be selected which is shown as below: - \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag - \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag - \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag - \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag - \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag - \arg RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag - \arg RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag - \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag - \arg RCU_INT_FLAG_PLLTSTB: PLLT stabilization interrupt flag + \brief configure the PLLT clock multiplication and division factors + \param[in] pllt_psc: the PLLT VCO input clock division factor + \arg this parameter should be selected between 2 and 63. And this parameter should + be selected correctly to ensure that the VCO input frequency ranges from 1 to 2 MHz + \param[in] pllt_mul: he PLLT VCO output clock multiplication factor + \arg this parameter should be selected between 49 and 432 + \param[in] ppltr_psc: the PLLTR division factor + \arg this parameter should be selected between 2 and 7 \param[out] none - \retval FlagStatus: SET or RESET + \retval ErrStatus: SUCCESS or ERROR */ -FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag) +ErrStatus rcu_pllt_vco_config(uint32_t pllt_psc, uint32_t pllt_mul, uint32_t ppltr_psc) { - /* get the rcu interrupt flag */ - if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))){ - return SET; - }else{ - return RESET; + uint32_t reg = 0U; + + /* check the function parameter */ + if((pllt_psc < 2U) || (pllt_psc > 63U)) { + return ERROR; + } else { } -} -/*! - \brief clear the interrupt flags - \param[in] int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum - only one parameter can be selected which is shown as below: - \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear - \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear - \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear - \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear - \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear - \arg RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear - \arg RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear - \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear - \arg RCU_INT_FLAG_PLLTSTB_CLR: PLLT stabilization interrupt flag clear - \param[out] none - \retval none -*/ -void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear) -{ - RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear)); -} + if((pllt_mul < 49U) || (pllt_mul > 432U)) { + return ERROR; + } else { + } -/*! - \brief enable the stabilization interrupt - \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum - Only one parameter can be selected which is shown as below: - \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable - \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable - \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable - \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable - \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable - \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable - \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable - \arg RCU_INT_PLLTSTB: PLLT stabilization interrupt enable - \param[out] none - \retval none -*/ -void rcu_interrupt_enable(rcu_int_enum stab_int) -{ - RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int)); + if((ppltr_psc < 2U) || (ppltr_psc > 7U)) { + return ERROR; + } else { + } + + reg = RCU_PLLTCFG; + + /* reset the PLLTRPSC bits, PLLTMF bits and PLLTPSC bits */ + reg &= ~(RCU_PLLTCFG_PLLTRPSC | RCU_PLLTCFG_PLLTMF | RCU_PLLTCFG_PLLTPSC); + + reg |= (PLLTCFG_PLLTPSC(pllt_psc) | PLLTCFG_PLLTMF(pllt_mul) | PLLTCFG_PLLTRPSC(ppltr_psc)); + + RCU_PLLTCFG = reg; + + return SUCCESS; } /*! - \brief disable the stabilization interrupt - \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum + \brief configure the TLI prescaler factor from PLLTR clock + \param[in] tli_psc: TLI prescaler factor only one parameter can be selected which is shown as below: - \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable - \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable - \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable - \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable - \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable - \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable - \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable - \arg RCU_INT_PLLTSTB: PLLT stabilization interrupt enable + \arg RCU_CKTLI_CKPLLTR_DIV2: TLI prescaler select CK_PLLTR/2 + \arg RCU_CKTLI_CKPLLTR_DIV4: TLI prescaler select CK_PLLTR/4 + \arg RCU_CKTLI_CKPLLTR_DIV8: TLI prescaler select CK_PLLTR/8 + \arg RCU_CKTLI_CKPLLTR_DIV16: TLI prescaler select CK_PLLTR/16 \param[out] none \retval none */ -void rcu_interrupt_disable(rcu_int_enum stab_int) +void rcu_tli_clock_config(uint32_t tli_psc) { - RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int)); + uint32_t reg = 0U; + + reg = RCU_PLLTCFG; + + /* reset the TLIPSC bits */ + reg &= ~RCU_PLLTCFG_TLIPSC; + + RCU_PLLTCFG = (reg | tli_psc); } /*! @@ -814,9 +772,9 @@ void rcu_interrupt_disable(rcu_int_enum stab_int) void rcu_lxtal_drive_capability_config(uint32_t lxtal_dricap) { uint32_t reg; - + reg = RCU_BDCTL; - + /* reset the LXTALDRI bits and set according to lxtal_dricap */ reg &= ~RCU_BDCTL_LXTALDRI; RCU_BDCTL = (reg | lxtal_dricap); @@ -842,112 +800,112 @@ ErrStatus rcu_osci_stab_wait(rcu_osci_type_enum osci) uint32_t stb_cnt = 0U; ErrStatus reval = ERROR; FlagStatus osci_stat = RESET; - - switch(osci){ + + switch(osci) { /* wait HXTAL stable */ case RCU_HXTAL: - while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)){ + while((RESET == osci_stat) && (HXTAL_STARTUP_TIMEOUT != stb_cnt)) { osci_stat = rcu_flag_get(RCU_FLAG_HXTALSTB); stb_cnt++; } /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)){ + if(RESET != rcu_flag_get(RCU_FLAG_HXTALSTB)) { reval = SUCCESS; } break; /* wait LXTAL stable */ case RCU_LXTAL: - while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)){ + while((RESET == osci_stat) && (LXTAL_STARTUP_TIMEOUT != stb_cnt)) { osci_stat = rcu_flag_get(RCU_FLAG_LXTALSTB); stb_cnt++; } /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)){ + if(RESET != rcu_flag_get(RCU_FLAG_LXTALSTB)) { reval = SUCCESS; } break; /* wait IRC8M stable */ case RCU_IRC8M: - while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)){ + while((RESET == osci_stat) && (IRC8M_STARTUP_TIMEOUT != stb_cnt)) { osci_stat = rcu_flag_get(RCU_FLAG_IRC8MSTB); stb_cnt++; } /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)){ + if(RESET != rcu_flag_get(RCU_FLAG_IRC8MSTB)) { reval = SUCCESS; } break; /* wait IRC40K stable */ case RCU_IRC40K: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) { osci_stat = rcu_flag_get(RCU_FLAG_IRC40KSTB); stb_cnt++; } /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)){ + if(RESET != rcu_flag_get(RCU_FLAG_IRC40KSTB)) { reval = SUCCESS; } break; /* wait PLL stable */ case RCU_PLL_CK: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) { osci_stat = rcu_flag_get(RCU_FLAG_PLLSTB); stb_cnt++; } /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)){ + if(RESET != rcu_flag_get(RCU_FLAG_PLLSTB)) { reval = SUCCESS; } break; /* wait PLL1 stable */ case RCU_PLL1_CK: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) { osci_stat = rcu_flag_get(RCU_FLAG_PLL1STB); stb_cnt++; } /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)){ + if(RESET != rcu_flag_get(RCU_FLAG_PLL1STB)) { reval = SUCCESS; } break; - + /* wait PLL2 stable */ case RCU_PLL2_CK: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) { osci_stat = rcu_flag_get(RCU_FLAG_PLL2STB); stb_cnt++; } /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)){ + if(RESET != rcu_flag_get(RCU_FLAG_PLL2STB)) { reval = SUCCESS; } break; /* wait PLLT stable */ case RCU_PLLT_CK: - while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)){ + while((RESET == osci_stat) && (OSC_STARTUP_TIMEOUT != stb_cnt)) { osci_stat = rcu_flag_get(RCU_FLAG_PLLTSTB); stb_cnt++; } /* check whether flag is set or not */ - if(RESET != rcu_flag_get(RCU_FLAG_PLLTSTB)){ + if(RESET != rcu_flag_get(RCU_FLAG_PLLTSTB)) { reval = SUCCESS; } break; - + default: break; } @@ -1009,7 +967,7 @@ void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci) { uint32_t reg; - switch(osci){ + switch(osci) { /* enable HXTAL to bypass mode */ case RCU_HXTAL: reg = RCU_CTL; @@ -1046,8 +1004,8 @@ void rcu_osci_bypass_mode_enable(rcu_osci_type_enum osci) void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci) { uint32_t reg; - - switch(osci){ + + switch(osci) { /* disable HXTAL to bypass mode */ case RCU_HXTAL: reg = RCU_CTL; @@ -1078,7 +1036,6 @@ void rcu_osci_bypass_mode_disable(rcu_osci_type_enum osci) \param[out] none \retval none */ - void rcu_hxtal_clock_monitor_enable(void) { RCU_CTL |= RCU_CTL_CKMEN; @@ -1104,7 +1061,7 @@ void rcu_hxtal_clock_monitor_disable(void) void rcu_irc8m_adjust_value_set(uint8_t irc8m_adjval) { uint32_t reg; - + reg = RCU_CTL; /* reset the IRC8MADJ bits and set according to irc8m_adjval */ reg &= ~RCU_CTL_IRC8MADJ; @@ -1123,7 +1080,7 @@ void rcu_irc8m_adjust_value_set(uint8_t irc8m_adjval) \retval none */ void rcu_deepsleep_voltage_set(uint32_t dsvol) -{ +{ dsvol &= RCU_DSV_DSLPVS; RCU_DSV = dsvol; } @@ -1143,7 +1100,7 @@ uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) { uint32_t sws, ck_freq = 0U; uint32_t cksys_freq, ahb_freq, apb1_freq, apb2_freq; - uint32_t pllsel, predv0sel, pllmf,ck_src, idx, clk_exp; + uint32_t pllsel, predv0sel, pllmf, ck_src, idx, clk_exp; uint32_t predv0, predv1, pll1mf; /* exponent of AHB, APB1 and APB2 clock divider */ @@ -1152,7 +1109,7 @@ uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) uint8_t apb2_exp[8] = {0, 0, 0, 0, 1, 2, 3, 4}; sws = GET_BITS(RCU_CFG0, 2, 3); - switch(sws){ + switch(sws) { /* IRC8M is selected as CK_SYS */ case SEL_IRC8M: cksys_freq = IRC8M_VALUE; @@ -1169,41 +1126,41 @@ uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) if(RCU_PLLSRC_HXTAL == pllsel) { /* PLL clock source is HXTAL */ ck_src = HXTAL_VALUE; - + predv0sel = (RCU_CFG1 & RCU_CFG1_PREDV0SEL); /* source clock use PLL1 */ - if(RCU_PREDV0SRC_CKPLL1 == predv0sel){ + if(RCU_PREDV0SRC_CKPLL1 == predv0sel) { predv1 = (uint32_t)((RCU_CFG1 & RCU_CFG1_PREDV1) >> 4) + 1U; pll1mf = (uint32_t)((RCU_CFG1 & RCU_CFG1_PLL1MF) >> 8) + 2U; - if(17U == pll1mf){ + if(17U == pll1mf) { pll1mf = 20U; } - ck_src = (ck_src/predv1)*pll1mf; + ck_src = (ck_src / predv1) * pll1mf; } predv0 = (RCU_CFG1 & RCU_CFG1_PREDV0) + 1U; ck_src /= predv0; - }else{ + } else { /* PLL clock source is IRC8M/2 */ - ck_src = IRC8M_VALUE/2U; + ck_src = IRC8M_VALUE / 2U; } /* PLL multiplication factor */ pllmf = GET_BITS(RCU_CFG0, 18, 21); - if((RCU_CFG0 & RCU_CFG0_PLLMF_4)){ + if((RCU_CFG0 & RCU_CFG0_PLLMF_4)) { pllmf |= 0x10U; } - if(13U == pllmf){ + if(13U == pllmf) { /* PLL source clock multiply by 6.5 */ - cksys_freq = ck_src*6U + ck_src/2U; - }else{ - if(pllmf < 15U){ + cksys_freq = ck_src * 6U + ck_src / 2U; + } else { + if(pllmf < 15U) { pllmf += 2U; - }else{ + } else { pllmf += 1U; } - cksys_freq = ck_src*pllmf; + cksys_freq = ck_src * pllmf; } break; /* IRC8M is selected as CK_SYS */ @@ -1216,19 +1173,19 @@ uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) idx = GET_BITS(RCU_CFG0, 4, 7); clk_exp = ahb_exp[idx]; ahb_freq = cksys_freq >> clk_exp; - + /* calculate APB1 clock frequency */ idx = GET_BITS(RCU_CFG0, 8, 10); clk_exp = apb1_exp[idx]; apb1_freq = ahb_freq >> clk_exp; - + /* calculate APB2 clock frequency */ idx = GET_BITS(RCU_CFG0, 11, 13); clk_exp = apb2_exp[idx]; apb2_freq = ahb_freq >> clk_exp; - + /* return the clocks frequency */ - switch(clock){ + switch(clock) { case CK_SYS: ck_freq = cksys_freq; break; @@ -1248,89 +1205,130 @@ uint32_t rcu_clock_freq_get(rcu_clock_freq_enum clock) } /*! - \brief configure the PLLT clock selection - \param[in] pllt_src: PLLT clock source selection - \arg RCU_PLLTSRC_IRC8M: IRC8M selected as source clock of PLLT - \arg RCU_PLLTSRC_HXTAL: HXTAL selected as source clock of PLLT + \brief get the clock stabilization and periphral reset flags + \param[in] flag: the clock stabilization and periphral reset flags, refer to rcu_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_FLAG_IRC8MSTB: IRC8M stabilization flag + \arg RCU_FLAG_HXTALSTB: HXTAL stabilization flag + \arg RCU_FLAG_PLLSTB: PLL stabilization flag + \arg RCU_FLAG_PLL1STB: PLL1 stabilization flag + \arg RCU_FLAG_PLL2STB: PLL2 stabilization flag + \arg RCU_FLAG_PLLTSTB: PLLT stabilization flag + \arg RCU_FLAG_LXTALSTB: LXTAL stabilization flag + \arg RCU_FLAG_IRC40KSTB: IRC40K stabilization flag + \arg RCU_FLAG_EPRST: external PIN reset flag + \arg RCU_FLAG_PORRST: power reset flag + \arg RCU_FLAG_SWRST: software reset flag + \arg RCU_FLAG_FWDGTRST: free watchdog timer reset flag + \arg RCU_FLAG_WWDGTRST: window watchdog timer reset flag + \arg RCU_FLAG_LPRST: low-power reset flag \param[out] none - \retval none + \retval FlagStatus: SET or RESET */ -void rcu_pllt_config(uint32_t pllt_src) +FlagStatus rcu_flag_get(rcu_flag_enum flag) { - uint32_t reg = 0U; + /* get the rcu flag */ + if(RESET != (RCU_REG_VAL(flag) & BIT(RCU_BIT_POS(flag)))) { + return SET; + } else { + return RESET; + } +} - reg = RCU_PLLTCFG; +/*! + \brief clear all the reset flag + \param[in] none + \param[out] none + \retval none +*/ +void rcu_all_reset_flag_clear(void) +{ + RCU_RSTSCK |= RCU_RSTSCK_RSTFC; +} - /* reset the PLLT clock source bit PLLTSEL */ - reg &= ~RCU_PLLTCFG_PLLTSEL; +/*! + \brief enable the stabilization interrupt + \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum + Only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable + \arg RCU_INT_PLLTSTB: PLLT stabilization interrupt enable + \param[out] none + \retval none +*/ +void rcu_interrupt_enable(rcu_int_enum stab_int) +{ + RCU_REG_VAL(stab_int) |= BIT(RCU_BIT_POS(stab_int)); +} - RCU_PLLTCFG = (reg | pllt_src); +/*! + \brief disable the stabilization interrupt + \param[in] stab_int: clock stabilization interrupt, refer to rcu_int_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_IRC40KSTB: IRC40K stabilization interrupt enable + \arg RCU_INT_LXTALSTB: LXTAL stabilization interrupt enable + \arg RCU_INT_IRC8MSTB: IRC8M stabilization interrupt enable + \arg RCU_INT_HXTALSTB: HXTAL stabilization interrupt enable + \arg RCU_INT_PLLSTB: PLL stabilization interrupt enable + \arg RCU_INT_PLL1STB: PLL1 stabilization interrupt enable + \arg RCU_INT_PLL2STB: PLL2 stabilization interrupt enable + \arg RCU_INT_PLLTSTB: PLLT stabilization interrupt enable + \param[out] none + \retval none +*/ +void rcu_interrupt_disable(rcu_int_enum stab_int) +{ + RCU_REG_VAL(stab_int) &= ~BIT(RCU_BIT_POS(stab_int)); } /*! - \brief configure the PLLT clock multiplication and division factors - \param[in] pllt_psc: the PLLT VCO input clock division factor - \arg this parameter should be selected between 2 and 63. And this parameter should - be selected correctly to ensure that the VCO input frequency ranges from 1 to 2 MHz - \param[in] pllt_mul: he PLLT VCO output clock multiplication factor - \arg this parameter should be selected between 49 and 432 - \param[in] ppltr_psc: the PLLTR division factor - \arg this parameter should be selected between 2 and 7 + \brief get the clock stabilization and ckm interrupt flags + \param[in] int_flag: interrupt and ckm flags, refer to rcu_int_flag_enum + only one parameter can be selected which is shown as below: + \arg RCU_INT_FLAG_IRC40KSTB: IRC40K stabilization interrupt flag + \arg RCU_INT_FLAG_LXTALSTB: LXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_IRC8MSTB: IRC8M stabilization interrupt flag + \arg RCU_INT_FLAG_HXTALSTB: HXTAL stabilization interrupt flag + \arg RCU_INT_FLAG_PLLSTB: PLL stabilization interrupt flag + \arg RCU_INT_FLAG_PLL1STB: PLL1 stabilization interrupt flag + \arg RCU_INT_FLAG_PLL2STB: PLL2 stabilization interrupt flag + \arg RCU_INT_FLAG_CKM: HXTAL clock stuck interrupt flag + \arg RCU_INT_FLAG_PLLTSTB: PLLT stabilization interrupt flag \param[out] none - \retval ErrStatus: SUCCESS or ERROR + \retval FlagStatus: SET or RESET */ -ErrStatus rcu_pllt_vco_config(uint32_t pllt_psc, uint32_t pllt_mul, uint32_t ppltr_psc) +FlagStatus rcu_interrupt_flag_get(rcu_int_flag_enum int_flag) { - uint32_t reg = 0U; - - /* check the function parameter */ - if((pllt_psc < 2U) || (pllt_psc > 63U)){ - return ERROR; - }else{ - } - - if((pllt_mul < 49U) || (pllt_mul > 432U)){ - return ERROR; - }else{ - } - - if((ppltr_psc < 2U) || (ppltr_psc > 7U)){ - return ERROR; - }else{ + /* get the rcu interrupt flag */ + if(RESET != (RCU_REG_VAL(int_flag) & BIT(RCU_BIT_POS(int_flag)))) { + return SET; + } else { + return RESET; } - - reg = RCU_PLLTCFG; - - /* reset the PLLTRPSC bits, PLLTMF bits and PLLTPSC bits */ - reg &= ~(RCU_PLLTCFG_PLLTRPSC | RCU_PLLTCFG_PLLTMF | RCU_PLLTCFG_PLLTPSC); - - reg |= (PLLTCFG_PLLTPSC(pllt_psc) | PLLTCFG_PLLTMF(pllt_mul) | PLLTCFG_PLLTRPSC(ppltr_psc)); - - RCU_PLLTCFG = reg; - - return SUCCESS; } /*! - \brief configure the TLI prescaler factor from PLLTR clock - \param[in] tli_psc: TLI prescaler factor + \brief clear the interrupt flags + \param[in] int_flag_clear: clock stabilization and stuck interrupt flags clear, refer to rcu_int_flag_clear_enum only one parameter can be selected which is shown as below: - \arg RCU_CKTLI_CKPLLTR_DIV2: TLI prescaler select CK_PLLTR/2 - \arg RCU_CKTLI_CKPLLTR_DIV4: TLI prescaler select CK_PLLTR/4 - \arg RCU_CKTLI_CKPLLTR_DIV8: TLI prescaler select CK_PLLTR/8 - \arg RCU_CKTLI_CKPLLTR_DIV16: TLI prescaler select CK_PLLTR/16 + \arg RCU_INT_FLAG_IRC40KSTB_CLR: IRC40K stabilization interrupt flag clear + \arg RCU_INT_FLAG_LXTALSTB_CLR: LXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_IRC8MSTB_CLR: IRC8M stabilization interrupt flag clear + \arg RCU_INT_FLAG_HXTALSTB_CLR: HXTAL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLLSTB_CLR: PLL stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLL1STB_CLR: PLL1 stabilization interrupt flag clear + \arg RCU_INT_FLAG_PLL2STB_CLR: PLL2 stabilization interrupt flag clear + \arg RCU_INT_FLAG_CKM_CLR: clock stuck interrupt flag clear + \arg RCU_INT_FLAG_PLLTSTB_CLR: PLLT stabilization interrupt flag clear \param[out] none \retval none */ -void rcu_tli_clock_config(uint32_t tli_psc) +void rcu_interrupt_flag_clear(rcu_int_flag_clear_enum int_flag_clear) { - uint32_t reg = 0U; - - reg = RCU_PLLTCFG; - - /* reset the TLIPSC bits */ - reg &= ~RCU_PLLTCFG_TLIPSC; - - RCU_PLLTCFG = (reg | tli_psc); + RCU_REG_VAL(int_flag_clear) |= BIT(RCU_BIT_POS(int_flag_clear)); } - diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_rtc.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_rtc.c index 2f2b1004..b6c5b923 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_rtc.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_rtc.c @@ -2,36 +2,33 @@ \file gd32f20x_rtc.c \brief RTC driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -56,7 +53,7 @@ void rtc_configuration_mode_enter(void) } /*! - \brief exit RTC configuration mode + \brief exit RTC configuration mode \param[in] none \param[out] none \retval none @@ -66,6 +63,49 @@ void rtc_configuration_mode_exit(void) RTC_CTL &= ~RTC_CTL_CMF; } +/*! + \brief wait RTC last write operation finished flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_lwoff_wait(void) +{ + /* loop until LWOFF flag is set */ + while(RESET == (RTC_CTL & RTC_CTL_LWOFF)) { + } +} + +/*! + \brief wait RTC registers synchronized flag set + \param[in] none + \param[out] none + \retval none +*/ +void rtc_register_sync_wait(void) +{ + /* clear RSYNF flag */ + RTC_CTL &= ~RTC_CTL_RSYNF; + /* loop until RSYNF flag is set */ + while(RESET == (RTC_CTL & RTC_CTL_RSYNF)) { + } +} + +/*! + \brief get RTC counter value + \param[in] none + \param[out] none + \retval RTC counter value +*/ +uint32_t rtc_counter_get(void) +{ + uint32_t temp = 0x0U; + + temp = RTC_CNTL; + temp |= (RTC_CNTH << RTC_HIGH_BITS_OFFSET); + return temp; +} + /*! \brief set RTC counter value \param[in] cnt: RTC counter value @@ -98,33 +138,6 @@ void rtc_prescaler_set(uint32_t psc) rtc_configuration_mode_exit(); } -/*! - \brief wait RTC last write operation finished flag set - \param[in] none - \param[out] none - \retval none -*/ -void rtc_lwoff_wait(void) -{ - /* loop until LWOFF flag is set */ - while(RESET == (RTC_CTL & RTC_CTL_LWOFF)){ - } -} - -/*! - \brief wait RTC registers synchronized flag set - \param[in] none - \param[out] none - \retval none -*/ -void rtc_register_sync_wait(void) -{ - /* clear RSYNF flag */ - RTC_CTL &= ~RTC_CTL_RSYNF; - /* loop until RSYNF flag is set */ - while(RESET == (RTC_CTL & RTC_CTL_RSYNF)){ - } -} /*! \brief set RTC alarm value @@ -142,20 +155,6 @@ void rtc_alarm_config(uint32_t alarm) rtc_configuration_mode_exit(); } -/*! - \brief get RTC counter value - \param[in] none - \param[out] none - \retval RTC counter value -*/ -uint32_t rtc_counter_get(void) -{ - uint32_t temp = 0x0U; - - temp = RTC_CNTL; - temp |= (RTC_CNTH << RTC_HIGH_BITS_OFFSET); - return temp; -} /*! \brief get RTC divider value @@ -166,111 +165,76 @@ uint32_t rtc_counter_get(void) uint32_t rtc_divider_get(void) { uint32_t temp = 0x00U; - + temp = ((RTC_DIVH & RTC_DIVH_DIV) << RTC_HIGH_BITS_OFFSET); temp |= RTC_DIVL; return temp; } /*! - \brief get RTC flag status - \param[in] flag: specify which flag status to get - only one parameter can be selected which is shown as below: - \arg RTC_FLAG_SECOND: second interrupt flag - \arg RTC_FLAG_ALARM: alarm interrupt flag - \arg RTC_FLAG_OVERFLOW: overflow interrupt flag - \arg RTC_FLAG_RSYN: registers synchronized flag - \arg RTC_FLAG_LWOF: last write operation finished flag + \brief enable RTC interrupt + \param[in] interrupt: specify which interrupt to enbale + one or more parameters can be selected which are shown as below: + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt \param[out] none - \retval SET or RESET + \retval none */ -FlagStatus rtc_flag_get(uint32_t flag) +void rtc_interrupt_enable(uint32_t interrupt) { - if(RESET != (RTC_CTL & flag)){ - return SET; - }else{ - return RESET; - } + RTC_INTEN |= interrupt; } /*! - \brief clear RTC flag status - \param[in] flag: specify which flag status to clear + \brief disable RTC interrupt + \param[in] interrupt: specify which interrupt to disable one or more parameters can be selected which are shown as below: - \arg RTC_FLAG_SECOND: second interrupt flag - \arg RTC_FLAG_ALARM: alarm interrupt flag - \arg RTC_FLAG_OVERFLOW: overflow interrupt flag - \arg RTC_FLAG_RSYN: registers synchronized flag + \arg RTC_INT_SECOND: second interrupt + \arg RTC_INT_ALARM: alarm interrupt + \arg RTC_INT_OVERFLOW: overflow interrupt \param[out] none \retval none */ -void rtc_flag_clear(uint32_t flag) +void rtc_interrupt_disable(uint32_t interrupt) { - /* clear RTC flag */ - RTC_CTL &= ~flag; + RTC_INTEN &= ~interrupt; } /*! - \brief get RTC interrupt flag status + \brief get RTC flag status \param[in] flag: specify which flag status to get only one parameter can be selected which is shown as below: - \arg RTC_INT_FLAG_SECOND: second interrupt flag - \arg RTC_INT_FLAG_ALARM: alarm interrupt flag - \arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag + \arg RTC_FLAG_LWOF: last write operation finished flag \param[out] none \retval SET or RESET */ -FlagStatus rtc_interrupt_flag_get(uint32_t flag) +FlagStatus rtc_flag_get(uint32_t flag) { - if(RESET != (RTC_CTL & flag)){ + if(RESET != (RTC_CTL & flag)) { return SET; - }else{ + } else { return RESET; } } /*! - \brief clear RTC interrupt flag status + \brief clear RTC flag status \param[in] flag: specify which flag status to clear one or more parameters can be selected which are shown as below: - \arg RTC_INT_FLAG_SECOND: second interrupt flag - \arg RTC_INT_FLAG_ALARM: alarm interrupt flag - \arg RTC_INT_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_SECOND: second interrupt flag + \arg RTC_FLAG_ALARM: alarm interrupt flag + \arg RTC_FLAG_OVERFLOW: overflow interrupt flag + \arg RTC_FLAG_RSYN: registers synchronized flag \param[out] none \retval none */ -void rtc_interrupt_flag_clear(uint32_t flag) +void rtc_flag_clear(uint32_t flag) { - /* clear RTC interrupt flag */ + /* clear RTC flag */ RTC_CTL &= ~flag; } - -/*! - \brief enable RTC interrupt - \param[in] interrupt: specify which interrupt to enbale - one or more parameters can be selected which are shown as below: - \arg RTC_INT_SECOND: second interrupt - \arg RTC_INT_ALARM: alarm interrupt - \arg RTC_INT_OVERFLOW: overflow interrupt - \param[out] none - \retval none -*/ -void rtc_interrupt_enable(uint32_t interrupt) -{ - RTC_INTEN |= interrupt; -} - -/*! - \brief disable RTC interrupt - \param[in] interrupt: specify which interrupt to disbale - one or more parameters can be selected which are shown as below: - \arg RTC_INT_SECOND: second interrupt - \arg RTC_INT_ALARM: alarm interrupt - \arg RTC_INT_OVERFLOW: overflow interrupt - \param[out] none - \retval none -*/ -void rtc_interrupt_disable(uint32_t interrupt) -{ - RTC_INTEN &= ~interrupt; -} diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_sdio.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_sdio.c index 84b0d733..ba7505bf 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_sdio.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_sdio.c @@ -2,36 +2,33 @@ \file gd32f20x_sdio.c \brief SDIO driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -83,7 +80,7 @@ void sdio_clock_config(uint32_t clock_edge, uint32_t clock_bypass, uint32_t cloc /* reset the CLKEDGE, CLKBYP, CLKPWRSAV, DIV */ clock_config &= ~(SDIO_CLKCTL_CLKEDGE | SDIO_CLKCTL_CLKBYP | SDIO_CLKCTL_CLKPWRSAV | SDIO_CLKCTL_DIV8 | SDIO_CLKCTL_DIV); /* if the clock division is greater or equal to 256, set the DIV[8] */ - if(clock_division >= 256U){ + if(clock_division >= 256U) { clock_config |= SDIO_CLKCTL_DIV8; clock_division -= 256U; } @@ -271,7 +268,7 @@ uint8_t sdio_command_index_get(void) uint32_t sdio_response_get(uint32_t responsex) { uint32_t resp_content = 0U; - switch(responsex){ + switch(responsex) { case SDIO_RESPONSE0: resp_content = SDIO_RESP0; break; @@ -492,9 +489,9 @@ void sdio_stop_readwait_disable(void) */ void sdio_readwait_type_set(uint32_t readwait_type) { - if(SDIO_READWAITTYPE_CLK == readwait_type){ + if(SDIO_READWAITTYPE_CLK == readwait_type) { SDIO_DATACTL |= SDIO_DATACTL_RWTYPE; - }else{ + } else { SDIO_DATACTL &= ~SDIO_DATACTL_RWTYPE; } } @@ -643,7 +640,7 @@ void sdio_ceata_command_completion_disable(void) FlagStatus sdio_flag_get(uint32_t flag) { FlagStatus temp_flag = RESET; - if(RESET != (SDIO_STAT & flag)){ + if(RESET != (SDIO_STAT & flag)) { temp_flag = SET; } return temp_flag; @@ -781,10 +778,10 @@ FlagStatus sdio_interrupt_flag_get(uint32_t int_flag) { uint32_t state = 0U; state = SDIO_STAT; - if(state & int_flag){ + if(state & int_flag) { state = SDIO_INTEN; /* check whether the corresponding bit in SDIO_INTEN is set or not */ - if(state & int_flag){ + if(state & int_flag) { return SET; } } diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_spi.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_spi.c index d491db22..ef61dad4 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_spi.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_spi.c @@ -2,36 +2,33 @@ \file gd32f20x_spi.c \brief SPI driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -53,14 +50,14 @@ OF SUCH DAMAGE. #define RCU_CFG1_PLL2MF_OFFSET 12U /* PLL2MF offset in RCU_CFG1 */ /*! - \brief reset SPI and I2S + \brief reset SPI and I2S \param[in] spi_periph: SPIx(x=0,1,2) \param[out] none \retval none */ void spi_i2s_deinit(uint32_t spi_periph) { - switch(spi_periph){ + switch(spi_periph) { case SPI0: /* reset SPI0 */ rcu_periph_reset_enable(RCU_SPI0RST); @@ -76,32 +73,33 @@ void spi_i2s_deinit(uint32_t spi_periph) rcu_periph_reset_enable(RCU_SPI2RST); rcu_periph_reset_disable(RCU_SPI2RST); break; - default : + default: break; } } /*! - \brief initialize the parameters of SPI struct with the default values - \param[in] spi_struct: SPI parameter stuct - \param[out] none + \brief initialize the parameters of SPI structure with the default values + \param[in] none + \param[out] spi_struct: the initialized structure spi_parameter_struct pointer \retval none */ -void spi_struct_para_init(spi_parameter_struct* spi_struct) +void spi_struct_para_init(spi_parameter_struct *spi_struct) { - /* set the SPI struct with the default values */ - spi_struct->device_mode = SPI_SLAVE; - spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX; - spi_struct->frame_size = SPI_FRAMESIZE_8BIT; - spi_struct->nss = SPI_NSS_HARD; + /* configure the SPI structure with the default values */ + spi_struct->device_mode = SPI_SLAVE; + spi_struct->trans_mode = SPI_TRANSMODE_FULLDUPLEX; + spi_struct->frame_size = SPI_FRAMESIZE_8BIT; + spi_struct->nss = SPI_NSS_HARD; + spi_struct->endian = SPI_ENDIAN_MSB; spi_struct->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; - spi_struct->prescale = SPI_PSC_2; + spi_struct->prescale = SPI_PSC_2; } /*! \brief initialize SPI parameter \param[in] spi_periph: SPIx(x=0,1,2) - \param[in] spi_struct: SPI parameter initialization stuct members of the structure + \param[in] spi_struct: SPI parameter initialization struct members of the structure and the member values are shown as below: device_mode: SPI_MASTER, SPI_SLAVE trans_mode: SPI_TRANSMODE_FULLDUPLEX, SPI_TRANSMODE_RECEIVEONLY, @@ -115,8 +113,8 @@ void spi_struct_para_init(spi_parameter_struct* spi_struct) \param[out] none \retval none */ -void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct) -{ +void spi_init(uint32_t spi_periph, spi_parameter_struct *spi_struct) +{ uint32_t reg = 0U; reg = SPI_CTL0(spi_periph); reg &= SPI_INIT_MASK; @@ -133,7 +131,7 @@ void spi_init(uint32_t spi_periph, spi_parameter_struct* spi_struct) reg |= spi_struct->endian; /* select SPI polarity and phase */ reg |= spi_struct->clock_polarity_phase; - /* select SPI prescale to adjust transmit speed */ + /* select SPI prescaler to adjust transmit speed */ reg |= spi_struct->prescale; /* write to SPI_CTL0 register */ @@ -154,7 +152,7 @@ void spi_enable(uint32_t spi_periph) } /*! - \brief disable SPI + \brief disable SPI \param[in] spi_periph: SPIx(x=0,1,2) \param[out] none \retval none @@ -165,7 +163,7 @@ void spi_disable(uint32_t spi_periph) } /*! - \brief initialize I2S parameter + \brief initialize I2S parameters \param[in] spi_periph: SPIx(x=1,2) \param[in] mode: I2S operation mode only one parameter can be selected which is shown as below: @@ -194,7 +192,7 @@ void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ck reg &= I2S_INIT_MASK; /* enable I2S mode */ - reg |= (uint32_t)SPI_I2SCTL_I2SSEL; + reg |= (uint32_t)SPI_I2SCTL_I2SSEL; /* select I2S mode */ reg |= (uint32_t)mode; /* select I2S standard */ @@ -207,7 +205,7 @@ void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ck } /*! - \brief configure I2S prescaler + \brief configure I2S prescaler \param[in] spi_periph: SPIx(x=1,2) \param[in] audiosample: I2S audio sample rate only one parameter can be selected which is shown as below: @@ -228,8 +226,8 @@ void i2s_init(uint32_t spi_periph, uint32_t mode, uint32_t standard, uint32_t ck \arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit \param[in] mckout: I2S master clock output only one parameter can be selected which is shown as below: - \arg I2S_MCKOUT_ENABLE: I2S master clock output enable - \arg I2S_MCKOUT_DISABLE: I2S master clock output disable + \arg I2S_MCKOUT_ENABLE: enable I2S master clock output + \arg I2S_MCKOUT_DISABLE: disable I2S master clock output \param[out] none \retval none */ @@ -239,52 +237,52 @@ void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t framefor uint32_t clks = 0U; uint32_t i2sclock = 0U; - /* deinit SPI_I2SPSC register */ + /* deinitialize SPI_I2SPSC register */ SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE; /* get the I2S clock source */ - if(SPI1 == ((uint32_t)spi_periph)){ + if(SPI1 == ((uint32_t)spi_periph)) { /* I2S1 clock source selection */ clks = I2S1_CLOCK_SEL; - }else{ + } else { /* I2S2 clock source selection */ clks = I2S2_CLOCK_SEL; } - - if(0U != (RCU_CFG1 & clks)){ + + if(0U != (RCU_CFG1 & clks)) { /* get RCU PLL2 clock multiplication factor */ clks = (uint32_t)((RCU_CFG1 & I2S_CLOCK_MUL_MASK) >> RCU_CFG1_PLL2MF_OFFSET); - - if((clks > 5U) && (clks < 15U)){ + + if((clks > 5U) && (clks < 15U)) { /* multiplier is between 8 and 14 */ clks += 2U; - }else{ - if(15U == clks){ + } else { + if(15U == clks) { /* multiplier is 20 */ clks = 20U; } } - + /* get the PREDV1 value */ - i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> RCU_CFG1_PREDV1_OFFSET) + 1U); + i2sclock = (uint32_t)(((RCU_CFG1 & I2S_CLOCK_DIV_MASK) >> RCU_CFG1_PREDV1_OFFSET) + 1U); /* calculate I2S clock based on PLL2 and PREDV1 */ - i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U); - }else{ + i2sclock = (uint32_t)((HXTAL_VALUE / i2sclock) * clks * 2U); + } else { /* get system clock */ i2sclock = rcu_clock_freq_get(CK_SYS); } - - /* config the prescaler depending on the mclk output state, the frame format and audio sample rate */ - if(I2S_MCKOUT_ENABLE == mckout){ + + /* configure the prescaler depending on the mclk output state, the frame format and audio sample rate */ + if(I2S_MCKOUT_ENABLE == mckout) { clks = (uint32_t)(((i2sclock / 256U) * 10U) / audiosample); - }else{ - if(I2S_FRAMEFORMAT_DT16B_CH16B == frameformat){ - clks = (uint32_t)(((i2sclock / 32U) *10U ) / audiosample); - }else{ - clks = (uint32_t)(((i2sclock / 64U) *10U ) / audiosample); + } else { + if(I2S_FRAMEFORMAT_DT16B_CH16B == frameformat) { + clks = (uint32_t)(((i2sclock / 32U) * 10U) / audiosample); + } else { + clks = (uint32_t)(((i2sclock / 64U) * 10U) / audiosample); } } - + /* remove the floating point */ clks = (clks + 5U) / 10U; i2sof = (clks & 0x00000001U); @@ -292,7 +290,7 @@ void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t framefor i2sof = (i2sof << 8U); /* set the default values */ - if((i2sdiv < 2U) || (i2sdiv > 255U)){ + if((i2sdiv < 2U) || (i2sdiv > 255U)) { i2sdiv = 2U; i2sof = 0U; } @@ -302,12 +300,13 @@ void i2s_psc_config(uint32_t spi_periph, uint32_t audiosample, uint32_t framefor /* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */ SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN)); + /* configure data frame format */ SPI_I2SCTL(spi_periph) |= (uint32_t)frameformat; } /*! - \brief enable I2S + \brief enable I2S \param[in] spi_periph: SPIx(x=1,2) \param[out] none \retval none @@ -318,7 +317,7 @@ void i2s_enable(uint32_t spi_periph) } /*! - \brief disable I2S + \brief disable I2S \param[in] spi_periph: SPIx(x=1,2) \param[out] none \retval none @@ -329,7 +328,7 @@ void i2s_disable(uint32_t spi_periph) } /*! - \brief enable SPI NSS output + \brief enable SPI NSS output \param[in] spi_periph: SPIx(x=0,1,2) \param[out] none \retval none @@ -340,7 +339,7 @@ void spi_nss_output_enable(uint32_t spi_periph) } /*! - \brief disable SPI NSS output + \brief disable SPI NSS output \param[in] spi_periph: SPIx(x=0,1,2) \param[out] none \retval none @@ -373,7 +372,7 @@ void spi_nss_internal_low(uint32_t spi_periph) } /*! - \brief enable SPI DMA send or receive + \brief enable SPI DMA send or receive \param[in] spi_periph: SPIx(x=0,1,2) \param[in] dma: SPI DMA mode only one parameter can be selected which is shown as below: @@ -384,15 +383,15 @@ void spi_nss_internal_low(uint32_t spi_periph) */ void spi_dma_enable(uint32_t spi_periph, uint8_t dma) { - if(SPI_DMA_TRANSMIT == dma){ + if(SPI_DMA_TRANSMIT == dma) { SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMATEN; - }else{ + } else { SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_DMAREN; } } /*! - \brief disable SPI DMA send or receive + \brief disable SPI DMA send or receive \param[in] spi_periph: SPIx(x=0,1,2) \param[in] dma: SPI DMA mode only one parameter can be selected which is shown as below: @@ -403,15 +402,15 @@ void spi_dma_enable(uint32_t spi_periph, uint8_t dma) */ void spi_dma_disable(uint32_t spi_periph, uint8_t dma) { - if(SPI_DMA_TRANSMIT == dma){ + if(SPI_DMA_TRANSMIT == dma) { SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMATEN); - }else{ + } else { SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_DMAREN); } } /*! - \brief configure SPI/I2S data frame format + \brief configure SPI data frame format \param[in] spi_periph: SPIx(x=0,1,2) \param[in] frame_format: SPI frame size only one parameter can be selected which is shown as below: @@ -428,6 +427,27 @@ void spi_i2s_data_frame_format_config(uint32_t spi_periph, uint16_t frame_format SPI_CTL0(spi_periph) |= (uint32_t)frame_format; } +/*! + \brief configure SPI bidirectional transfer direction + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] transfer_direction: SPI transfer direction + only one parameter can be selected which is shown as below: + \arg SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode + \arg SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode + \param[out] none + \retval none +*/ +void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction) +{ + if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction) { + /* set the transmit only mode */ + SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT; + } else { + /* set the receive only mode */ + SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE; + } +} + /*! \brief SPI transmit data \param[in] spi_periph: SPIx(x=0,1,2) @@ -452,28 +472,7 @@ uint16_t spi_i2s_data_receive(uint32_t spi_periph) } /*! - \brief configure SPI bidirectional transfer direction - \param[in] spi_periph: SPIx(x=0,1,2) - \param[in] transfer_direction: SPI transfer direction - only one parameter can be selected which is shown as below: - \arg SPI_BIDIRECTIONAL_TRANSMIT: SPI work in transmit-only mode - \arg SPI_BIDIRECTIONAL_RECEIVE: SPI work in receive-only mode - \param[out] none - \retval none -*/ -void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_direction) -{ - if(SPI_BIDIRECTIONAL_TRANSMIT == transfer_direction){ - /* set the transmit only mode */ - SPI_CTL0(spi_periph) |= (uint32_t)SPI_BIDIRECTIONAL_TRANSMIT; - }else{ - /* set the receive only mode */ - SPI_CTL0(spi_periph) &= SPI_BIDIRECTIONAL_RECEIVE; - } -} - -/*! - \brief set CRC polynomial + \brief set CRC polynomial \param[in] spi_periph: SPIx(x=0,1,2) \param[in] crc_poly: CRC polynomial value \param[out] none @@ -481,14 +480,12 @@ void spi_bidirectional_transfer_config(uint32_t spi_periph, uint32_t transfer_di */ void spi_crc_polynomial_set(uint32_t spi_periph, uint16_t crc_poly) { - /* enable SPI CRC */ - SPI_CTL0(spi_periph) |= (uint32_t)SPI_CTL0_CRCEN; /* set SPI CRC polynomial */ SPI_CRCPOLY(spi_periph) = (uint32_t)crc_poly; } /*! - \brief get SPI CRC polynomial + \brief get SPI CRC polynomial \param[in] spi_periph: SPIx(x=0,1,2) \param[out] none \retval 16-bit CRC polynomial @@ -499,7 +496,7 @@ uint16_t spi_crc_polynomial_get(uint32_t spi_periph) } /*! - \brief turn on CRC function + \brief turn on CRC function \param[in] spi_periph: SPIx(x=0,1,2) \param[out] none \retval none @@ -510,7 +507,7 @@ void spi_crc_on(uint32_t spi_periph) } /*! - \brief turn off CRC function + \brief turn off CRC function \param[in] spi_periph: SPIx(x=0,1,2) \param[out] none \retval none @@ -543,75 +540,151 @@ void spi_crc_next(uint32_t spi_periph) */ uint16_t spi_crc_get(uint32_t spi_periph, uint8_t crc) { - if(SPI_CRC_TX == crc){ + if(SPI_CRC_TX == crc) { return ((uint16_t)(SPI_TCRC(spi_periph))); - }else{ + } else { return ((uint16_t)(SPI_RCRC(spi_periph))); } } /*! - \brief enable SPI and I2S interrupt + \brief clear SPI CRC error flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[out] none + \retval none +*/ +void spi_crc_error_clear(uint32_t spi_periph) +{ + SPI_STAT(spi_periph) = (uint32_t)(~SPI_FLAG_CRCERR); +} + +/*! + \brief enable quad wire SPI + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void spi_quad_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QMOD; +} + +/*! + \brief disable quad wire SPI + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void spi_quad_disable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QMOD); +} + +/*! + \brief enable quad wire SPI write + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void spi_quad_write_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QRD); +} + +/*! + \brief enable quad wire SPI read + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void spi_quad_read_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QRD; +} + +/*! + \brief enable SPI_IO2 and SPI_IO3 pin output + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void spi_quad_io23_output_enable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_IO23_DRV; +} + +/*! + \brief disable SPI_IO2 and SPI_IO3 pin output + \param[in] spi_periph: SPIx(only x=0) + \param[out] none + \retval none +*/ +void spi_quad_io23_output_disable(uint32_t spi_periph) +{ + SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_IO23_DRV); +} + +/*! + \brief get SPI and I2S flag status + \param[in] spi_periph: SPIx(x=0,1,2) + \param[in] flag: SPI/I2S flag status + only one parameter can be selected which is shown as below: + \arg SPI_FLAG_TBE: transmit buffer empty flag + \arg SPI_FLAG_RBNE: receive buffer not empty flag + \arg SPI_FLAG_TRANS: transmit on-going flag + \arg SPI_FLAG_RXORERR: receive overrun error flag + \arg SPI_FLAG_CONFERR: mode config error flag + \arg SPI_FLAG_CRCERR: CRC error flag + \arg I2S_FLAG_TBE: transmit buffer empty flag + \arg I2S_FLAG_RBNE: receive buffer not empty flag + \arg I2S_FLAG_TRANS: transmit on-going flag + \arg I2S_FLAG_RXORERR: overrun error flag + \arg I2S_FLAG_TXURERR: underrun error flag + \arg I2S_FLAG_CH: channel side flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag) +{ + if(RESET != (SPI_STAT(spi_periph) & flag)) { + return SET; + } else { + return RESET; + } +} + +/*! + \brief enable SPI and I2S interrupt \param[in] spi_periph: SPIx(x=0,1,2) \param[in] interrupt: SPI/I2S interrupt only one parameter can be selected which is shown as below: \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt - \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + \arg SPI_I2S_INT_ERR: CRC error, configuration error, reception overrun error, transmission underrun error and format error interrupt \param[out] none \retval none */ void spi_i2s_interrupt_enable(uint32_t spi_periph, uint8_t interrupt) { - switch(interrupt){ - /* SPI/I2S transmit buffer empty interrupt */ - case SPI_I2S_INT_TBE: - SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_TBEIE; - break; - /* SPI/I2S receive buffer not empty interrupt */ - case SPI_I2S_INT_RBNE: - SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_RBNEIE; - break; - /* SPI/I2S error */ - case SPI_I2S_INT_ERR: - SPI_CTL1(spi_periph) |= (uint32_t)SPI_CTL1_ERRIE; - break; - default: - break; - } + SPI_CTL1(spi_periph) |= (uint32_t)interrupt; } /*! - \brief disable SPI and I2S interrupt + \brief disable SPI and I2S interrupt \param[in] spi_periph: SPIx(x=0,1,2) \param[in] interrupt: SPI/I2S interrupt only one parameter can be selected which is shown as below: \arg SPI_I2S_INT_TBE: transmit buffer empty interrupt \arg SPI_I2S_INT_RBNE: receive buffer not empty interrupt - \arg SPI_I2S_INT_ERR: CRC error,configuration error,reception overrun error, + \arg SPI_I2S_INT_ERR: CRC error, configuration error, reception overrun error, transmission underrun error and format error interrupt \param[out] none \retval none */ void spi_i2s_interrupt_disable(uint32_t spi_periph, uint8_t interrupt) { - switch(interrupt){ - /* SPI/I2S transmit buffer empty interrupt */ - case SPI_I2S_INT_TBE: - SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_TBEIE); - break; - /* SPI/I2S receive buffer not empty interrupt */ - case SPI_I2S_INT_RBNE: - SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_RBNEIE); - break; - /* SPI/I2S error */ - case SPI_I2S_INT_ERR: - SPI_CTL1(spi_periph) &= (uint32_t)(~SPI_CTL1_ERRIE); - break; - default : - break; - } + SPI_CTL1(spi_periph) &= ~(uint32_t)interrupt; } /*! @@ -633,7 +706,7 @@ FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt) uint32_t reg1 = SPI_STAT(spi_periph); uint32_t reg2 = SPI_CTL1(spi_periph); - switch(interrupt){ + switch(interrupt) { /* SPI/I2S transmit buffer empty interrupt */ case SPI_I2S_INT_FLAG_TBE: reg1 = reg1 & SPI_STAT_TBE; @@ -664,119 +737,13 @@ FlagStatus spi_i2s_interrupt_flag_get(uint32_t spi_periph, uint8_t interrupt) reg1 = reg1 & SPI_STAT_TXURERR; reg2 = reg2 & SPI_CTL1_ERRIE; break; - default : + default: break; } /*get SPI/I2S interrupt flag status */ - if((0U != reg1) && (0U != reg2)){ + if((0U != reg1) && (0U != reg2)) { return SET; - }else{ + } else { return RESET; } } - -/*! - \brief get SPI and I2S flag status - \param[in] spi_periph: SPIx(x=0,1,2) - \param[in] flag: SPI/I2S flag status - only one parameter can be selected which is shown as below: - \arg SPI_FLAG_TBE: transmit buffer empty flag - \arg SPI_FLAG_RBNE: receive buffer not empty flag - \arg SPI_FLAG_TRANS: transmit on-going flag - \arg SPI_FLAG_RXORERR: receive overrun error flag - \arg SPI_FLAG_CONFERR: mode config error flag - \arg SPI_FLAG_CRCERR: CRC error flag - \arg I2S_FLAG_TBE: transmit buffer empty flag - \arg I2S_FLAG_RBNE: receive buffer not empty flag - \arg I2S_FLAG_TRANS: transmit on-going flag - \arg I2S_FLAG_RXORERR: overrun error flag - \arg I2S_FLAG_TXURERR: underrun error flag - \arg I2S_FLAG_CH: channel side flag - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus spi_i2s_flag_get(uint32_t spi_periph, uint32_t flag) -{ - if(RESET != (SPI_STAT(spi_periph) & flag)){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear SPI CRC error flag status - \param[in] spi_periph: SPIx(x=0,1,2) - \param[out] none - \retval none -*/ -void spi_crc_error_clear(uint32_t spi_periph) -{ - SPI_STAT(spi_periph) &= (uint32_t)(~SPI_FLAG_CRCERR); -} - -/*! - \brief enable quad wire SPI - \param[in] spi_periph: SPIx(only x=0) - \param[out] none - \retval none -*/ -void qspi_enable(uint32_t spi_periph) -{ - SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QMOD; -} - -/*! - \brief disable quad wire SPI - \param[in] spi_periph: SPIx(only x=0) - \param[out] none - \retval none -*/ -void qspi_disable(uint32_t spi_periph) -{ - SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QMOD); -} - -/*! - \brief enable quad wire SPI write - \param[in] spi_periph: SPIx(only x=0) - \param[out] none - \retval none -*/ -void qspi_write_enable(uint32_t spi_periph) -{ - SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_QRD); -} - -/*! - \brief enable quad wire SPI read - \param[in] spi_periph: SPIx(only x=0) - \param[out] none - \retval none -*/ -void qspi_read_enable(uint32_t spi_periph) -{ - SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_QRD; -} - -/*! - \brief enable SPI_IO2 and SPI_IO3 pin output - \param[in] spi_periph: SPIx(only x=0) - \param[out] none - \retval none -*/ -void qspi_io23_output_enable(uint32_t spi_periph) -{ - SPI_QCTL(spi_periph) |= (uint32_t)SPI_QCTL_IO23_DRV; -} - - /*! - \brief disable SPI_IO2 and SPI_IO3 pin output - \param[in] spi_periph: SPIx(only x=0) - \param[out] none - \retval none -*/ -void qspi_io23_output_disable(uint32_t spi_periph) -{ - SPI_QCTL(spi_periph) &= (uint32_t)(~SPI_QCTL_IO23_DRV); -} diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_timer.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_timer.c index 2b893913..8318da69 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_timer.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_timer.c @@ -2,40 +2,38 @@ \file gd32f20x_timer.c \brief TIMER driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "gd32f20x_timer.h" + /* TIMER init parameter mask */ #define ALIGNEDMODE_MASK ((uint32_t)0x00000060U) /*!< TIMER init parameter aligne dmode mask */ #define COUNTERDIRECTION_MASK ((uint32_t)0x00000010U) /*!< TIMER init parameter counter direction mask */ @@ -49,7 +47,7 @@ OF SUCH DAMAGE. */ void timer_deinit(uint32_t timer_periph) { - switch(timer_periph){ + switch(timer_periph) { case TIMER0: /* reset TIMER0 */ rcu_periph_reset_enable(RCU_TIMER0RST); @@ -127,11 +125,11 @@ void timer_deinit(uint32_t timer_periph) /*! \brief initialize TIMER init parameter struct with a default value - \param[in] initpara: init parameter struct - \param[out] none + \param[in] none + \param[out] initpara: init parameter struct \retval none */ -void timer_struct_para_init(timer_parameter_struct* initpara) +void timer_struct_para_init(timer_parameter_struct *initpara) { /* initialize the init parameter struct member with the default value */ initpara->prescaler = 0U; @@ -146,24 +144,24 @@ void timer_struct_para_init(timer_parameter_struct* initpara) \brief initialize TIMER counter \param[in] timer_periph: TIMERx(x=0..13) \param[in] initpara: init parameter struct - prescaler: prescaler value of the counter clock,0~65535 - alignedmode: TIMER_COUNTER_EDGE,TIMER_COUNTER_CENTER_DOWN,TIMER_COUNTER_CENTER_UP,TIMER_COUNTER_CENTER_BOTH - counterdirection: TIMER_COUNTER_UP,TIMER_COUNTER_DOWN - period: counter auto reload value,0~65535 - clockdivision: TIMER_CKDIV_DIV1,TIMER_CKDIV_DIV2,TIMER_CKDIV_DIV4 - repetitioncounter: counter repetition value,0~255 + prescaler: prescaler value of the counter clock,0~65535 + alignedmode: TIMER_COUNTER_EDGE,TIMER_COUNTER_CENTER_DOWN,TIMER_COUNTER_CENTER_UP,TIMER_COUNTER_CENTER_BOTH + counterdirection: TIMER_COUNTER_UP,TIMER_COUNTER_DOWN + period: counter auto reload value,0~65535 + clockdivision: TIMER_CKDIV_DIV1,TIMER_CKDIV_DIV2,TIMER_CKDIV_DIV4 + repetitioncounter: counter repetition value,0~255 \param[out] none \retval none */ -void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara) +void timer_init(uint32_t timer_periph, timer_parameter_struct *initpara) { /* configure the counter prescaler value */ TIMER_PSC(timer_periph) = (uint16_t)initpara->prescaler; /* configure the counter direction and aligned mode */ if((TIMER0 == timer_periph) || (TIMER1 == timer_periph) || (TIMER2 == timer_periph) || (TIMER3 == timer_periph) || - (TIMER4 == timer_periph) || (TIMER7 == timer_periph) || (TIMER8 == timer_periph) || (TIMER9 == timer_periph) || - (TIMER10 == timer_periph) || (TIMER11 == timer_periph) || (TIMER12 == timer_periph) || (TIMER13 == timer_periph)){ + (TIMER4 == timer_periph) || (TIMER7 == timer_periph) || (TIMER8 == timer_periph) || (TIMER9 == timer_periph) || + (TIMER10 == timer_periph) || (TIMER11 == timer_periph) || (TIMER12 == timer_periph) || (TIMER13 == timer_periph)) { TIMER_CTL0(timer_periph) &= (~(uint32_t)(TIMER_CTL0_DIR | TIMER_CTL0_CAM)); TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->alignedmode & ALIGNEDMODE_MASK); TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->counterdirection & COUNTERDIRECTION_MASK); @@ -172,13 +170,13 @@ void timer_init(uint32_t timer_periph, timer_parameter_struct* initpara) /* configure the autoreload value */ TIMER_CAR(timer_periph) = (uint32_t)initpara->period; - if((TIMER5 != timer_periph) && (TIMER6 != timer_periph)){ + if((TIMER5 != timer_periph) && (TIMER6 != timer_periph)) { /* reset the CKDIV bit */ TIMER_CTL0(timer_periph) &= (~(uint32_t)TIMER_CTL0_CKDIV); TIMER_CTL0(timer_periph) |= (uint32_t)(initpara->clockdivision & CLOCKDIVISION_MASK); } - if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)) { /* configure the repetition counter value */ TIMER_CREP(timer_periph) = (uint32_t)initpara->repetitioncounter; } @@ -267,7 +265,7 @@ void timer_update_event_disable(uint32_t timer_periph) */ void timer_counter_alignment(uint32_t timer_periph, uint16_t aligned) { - TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_CAM; + TIMER_CTL0(timer_periph) &= (uint32_t)(~TIMER_CTL0_CAM); TIMER_CTL0(timer_periph) |= (uint32_t)aligned; } @@ -296,7 +294,7 @@ void timer_counter_down_direction(uint32_t timer_periph) /*! \brief configure TIMER prescaler \param[in] timer_periph: TIMERx(x=0..13) - \param[in] prescaler: prescaler value + \param[in] prescaler: prescaler value, 0~65535 \param[in] pscreload: prescaler reload mode only one parameter can be selected which is shown as below: \arg TIMER_PSC_RELOAD_NOW: the prescaler is loaded right now @@ -307,8 +305,8 @@ void timer_counter_down_direction(uint32_t timer_periph) void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t pscreload) { TIMER_PSC(timer_periph) = (uint32_t)prescaler; - - if(TIMER_PSC_RELOAD_NOW == pscreload){ + + if(TIMER_PSC_RELOAD_NOW == pscreload) { TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; } } @@ -316,22 +314,22 @@ void timer_prescaler_config(uint32_t timer_periph, uint16_t prescaler, uint32_t /*! \brief configure TIMER repetition register value \param[in] timer_periph: TIMERx(x=0,7) - \param[in] repetition: the counter repetition value,0~255 + \param[in] repetition: the counter repetition value, 0~255 \param[out] none \retval none */ -void timer_repetition_value_config(uint32_t timer_periph, uint8_t repetition) +void timer_repetition_value_config(uint32_t timer_periph, uint16_t repetition) { TIMER_CREP(timer_periph) = (uint32_t)repetition; -} - +} + /*! \brief configure TIMER autoreload register value \param[in] timer_periph: TIMERx(x=0..13) - \param[in] autoreload: the counter auto-reload value + \param[in] autoreload: the counter auto-reload value, 0~65535 \param[out] none \retval none -*/ +*/ void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload) { TIMER_CAR(timer_periph) = (uint32_t)autoreload; @@ -340,10 +338,10 @@ void timer_autoreload_value_config(uint32_t timer_periph, uint32_t autoreload) /*! \brief configure TIMER counter register value \param[in] timer_periph: TIMERx(x=0..13) - \param[in] counter: the counter value + \param[in] counter: the counter value, 0~65535 \param[out] none \retval none -*/ +*/ void timer_counter_value_config(uint32_t timer_periph, uint32_t counter) { TIMER_CNT(timer_periph) = (uint32_t)counter; @@ -353,8 +351,8 @@ void timer_counter_value_config(uint32_t timer_periph, uint32_t counter) \brief read TIMER counter value \param[in] timer_periph: TIMERx(x=0..13) \param[out] none - \retval counter value -*/ + \retval counter value, 0~65535 +*/ uint32_t timer_counter_read(uint32_t timer_periph) { uint32_t count_value = 0U; @@ -366,8 +364,8 @@ uint32_t timer_counter_read(uint32_t timer_periph) \brief read TIMER prescaler value \param[in] timer_periph: TIMERx(x=0..13) \param[out] none - \retval prescaler register value -*/ + \retval prescaler register value, 0~65535 +*/ uint16_t timer_prescaler_read(uint32_t timer_periph) { uint16_t prescaler_value = 0U; @@ -387,17 +385,17 @@ uint16_t timer_prescaler_read(uint32_t timer_periph) */ void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode) { - if(TIMER_SP_MODE_SINGLE == spmode){ + if(TIMER_SP_MODE_SINGLE == spmode) { TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_SPM; - }else if(TIMER_SP_MODE_REPETITIVE == spmode){ + } else if(TIMER_SP_MODE_REPETITIVE == spmode) { TIMER_CTL0(timer_periph) &= ~((uint32_t)TIMER_CTL0_SPM); - }else{ - /* illegal parameters */ + } else { + /* illegal parameters */ } } /*! - \brief configure TIMER update source + \brief configure TIMER update source \param[in] timer_periph: TIMERx(x=0..13) \param[in] update: only one parameter can be selected which is shown as below: @@ -409,19 +407,19 @@ void timer_single_pulse_mode_config(uint32_t timer_periph, uint32_t spmode) */ void timer_update_source_config(uint32_t timer_periph, uint32_t update) { - if(TIMER_UPDATE_SRC_REGULAR == update){ + if(TIMER_UPDATE_SRC_REGULAR == update) { TIMER_CTL0(timer_periph) |= (uint32_t)TIMER_CTL0_UPS; - }else if(TIMER_UPDATE_SRC_GLOBAL == update){ + } else if(TIMER_UPDATE_SRC_GLOBAL == update) { TIMER_CTL0(timer_periph) &= ~(uint32_t)TIMER_CTL0_UPS; - }else{ + } else { /* illegal parameters */ } } /*! \brief enable the TIMER DMA - \param[in] timer_periph: TIMERx(x=0,1,2,5,14,15,16) - \param[in] dma: timer DMA source enable + \param[in] timer_periph: TIMERx(x=0..7) + \param[in] dma: timer DMA source enable only one parameter can be selected which is shown as below: \arg TIMER_DMA_UPD: update DMA enable,TIMERx(x=0..7) \arg TIMER_DMA_CH0D: channel 0 DMA enable,TIMERx(x=0..4,7) @@ -435,12 +433,12 @@ void timer_update_source_config(uint32_t timer_periph, uint32_t update) */ void timer_dma_enable(uint32_t timer_periph, uint16_t dma) { - TIMER_DMAINTEN(timer_periph) |= (uint32_t) dma; + TIMER_DMAINTEN(timer_periph) |= (uint32_t) dma; } /*! \brief disable the TIMER DMA - \param[in] timer_periph: please refer to the following parameters + \param[in] timer_periph: TIMERx(x=0..7) \param[in] dma: timer DMA source disable only one parameter can be selected which is shown as below: \arg TIMER_DMA_UPD: update DMA disable,TIMERx(x=0..7) @@ -448,14 +446,14 @@ void timer_dma_enable(uint32_t timer_periph, uint16_t dma) \arg TIMER_DMA_CH1D: channel 1 DMA disable,TIMERx(x=0..4,7) \arg TIMER_DMA_CH2D: channel 2 DMA disable,TIMERx(x=0..4,7) \arg TIMER_DMA_CH3D: channel 3 DMA disable,TIMERx(x=0..4,7) - \arg TIMER_DMA_CMTD: commutation DMA request disable,TIMERx(x=0,7) + \arg TIMER_DMA_CMTD: commutation DMA request disable, TIMERx(x=0,7) \arg TIMER_DMA_TRGD: trigger DMA disable,TIMERx(x=0..4,7) \param[out] none \retval none */ void timer_dma_disable(uint32_t timer_periph, uint16_t dma) { - TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)(dma)); + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)(dma)); } /*! @@ -464,18 +462,18 @@ void timer_dma_disable(uint32_t timer_periph, uint16_t dma) \param[in] dma_request: channel DMA request source selection only one parameter can be selected which is shown as below: \arg TIMER_DMAREQUEST_CHANNELEVENT: DMA request of channel y is sent when channel y event occurs - \arg TIMER_DMAREQUEST_UPDATEEVENT: DMA request of channel y is sent when update event occurs + \arg TIMER_DMAREQUEST_UPDATEEVENT: DMA request of channel y is sent when update event occurs \param[out] none \retval none */ void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma_request) { - if(TIMER_DMAREQUEST_UPDATEEVENT == dma_request){ + if(TIMER_DMAREQUEST_UPDATEEVENT == dma_request) { TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_DMAS; - }else if(TIMER_DMAREQUEST_CHANNELEVENT == dma_request){ + } else if(TIMER_DMAREQUEST_CHANNELEVENT == dma_request) { TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_DMAS; - }else{ - /* illegal parameters */ + } else { + /* illegal parameters */ } } @@ -512,21 +510,24 @@ void timer_channel_dma_request_source_select(uint32_t timer_periph, uint32_t dma */ void timer_dma_transfer_config(uint32_t timer_periph, uint32_t dma_baseaddr, uint32_t dma_lenth) { - TIMER_DMACFG(timer_periph) &= (~(uint32_t)(TIMER_DMACFG_DMATA | TIMER_DMACFG_DMATC)); - TIMER_DMACFG(timer_periph) |= (uint32_t)(dma_baseaddr | dma_lenth); + uint32_t reg = 0U; + reg = TIMER_DMACFG(timer_periph); + reg &= (~(uint32_t)(TIMER_DMACFG_DMATA | TIMER_DMACFG_DMATC)); + reg |= (uint32_t)(dma_baseaddr | dma_lenth); + TIMER_DMACFG(timer_periph) = (uint32_t)reg; } /*! - \brief software generate events + \brief software generate events \param[in] timer_periph: please refer to the following parameters \param[in] event: the timer software event generation sources one or more parameters can be selected which are shown as below: \arg TIMER_EVENT_SRC_UPG: update event generation, TIMERx(x=0..13) - \arg TIMER_EVENT_SRC_CH0G: channel 0 capture or compare event generation, TIMERx(x=0..4,7..13) + \arg TIMER_EVENT_SRC_CH0G: channel 0 capture or compare event generation, TIMERx(x=0..4,7..13) \arg TIMER_EVENT_SRC_CH1G: channel 1 capture or compare event generation, TIMERx(x=0..4,7,8,11) - \arg TIMER_EVENT_SRC_CH2G: channel 2 capture or compare event generation, TIMERx(x=0..4,7) - \arg TIMER_EVENT_SRC_CH3G: channel 3 capture or compare event generation, TIMERx(x=0..4,7) - \arg TIMER_EVENT_SRC_CMTG: channel commutation event generation, TIMERx(x=0,7) + \arg TIMER_EVENT_SRC_CH2G: channel 2 capture or compare event generation, TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CH3G: channel 3 capture or compare event generation, TIMERx(x=0..4,7) + \arg TIMER_EVENT_SRC_CMTG: channel commutation event generation, TIMERx(x=0,7) \arg TIMER_EVENT_SRC_TRGG: trigger event generation, TIMERx(x=0..4,7,8,11) \arg TIMER_EVENT_SRC_BRKG: break event generation, TIMERx(x=0,7) \param[out] none @@ -539,11 +540,11 @@ void timer_event_software_generate(uint32_t timer_periph, uint16_t event) /*! \brief initialize TIMER break parameter struct with a default value - \param[in] breakpara: TIMER break parameter struct - \param[out] none + \param[in] none + \param[out] breakpara: TIMER break parameter struct \retval none */ -void timer_break_struct_para_init(timer_break_parameter_struct* breakpara) +void timer_break_struct_para_init(timer_break_parameter_struct *breakpara) { /* initialize the break parameter struct member with the default value */ breakpara->runoffstate = TIMER_ROS_STATE_DISABLE; @@ -556,20 +557,20 @@ void timer_break_struct_para_init(timer_break_parameter_struct* breakpara) } /*! - \brief configure TIMER break function + \brief configure TIMER break function \param[in] timer_periph: TIMERx(x=0,7) \param[in] breakpara: TIMER break parameter struct - runoffstate: TIMER_ROS_STATE_ENABLE,TIMER_ROS_STATE_DISABLE - ideloffstate: TIMER_IOS_STATE_ENABLE,TIMER_IOS_STATE_DISABLE + runoffstate: TIMER_ROS_STATE_ENABLE, TIMER_ROS_STATE_DISABLE + ideloffstate: TIMER_IOS_STATE_ENABLE, TIMER_IOS_STATE_DISABLE deadtime: 0~255 - breakpolarity: TIMER_BREAK_POLARITY_LOW,TIMER_BREAK_POLARITY_HIGH - outputautostate: TIMER_OUTAUTO_ENABLE,TIMER_OUTAUTO_DISABLE - protectmode: TIMER_CCHP_PROT_OFF,TIMER_CCHP_PROT_0,TIMER_CCHP_PROT_1,TIMER_CCHP_PROT_2 + breakpolarity: TIMER_BREAK_POLARITY_LOW, TIMER_BREAK_POLARITY_HIGH + outputautostate: TIMER_OUTAUTO_ENABLE ,TIMER_OUTAUTO_DISABLE + protectmode: TIMER_CCHP_PROT_OFF,TIMER_CCHP_PROT_0, TIMER_CCHP_PROT_1, TIMER_CCHP_PROT_2 breakstate: TIMER_BREAK_ENABLE,TIMER_BREAK_DISABLE \param[out] none \retval none */ -void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct* breakpara) +void timer_break_config(uint32_t timer_periph, timer_break_parameter_struct *breakpara) { TIMER_CCHP(timer_periph) = (uint32_t)(((uint32_t)(breakpara->runoffstate)) | ((uint32_t)(breakpara->ideloffstate)) | @@ -625,7 +626,7 @@ void timer_automatic_output_disable(uint32_t timer_periph) } /*! - \brief enable or disable TIMER primary output function + \brief configure TIMER primary output function \param[in] timer_periph: TIMERx(x=0,7) \param[in] newvalue: ENABLE or DISABLE \param[out] none @@ -633,25 +634,25 @@ void timer_automatic_output_disable(uint32_t timer_periph) */ void timer_primary_output_config(uint32_t timer_periph, ControlStatus newvalue) { - if(ENABLE == newvalue){ + if(ENABLE == newvalue) { TIMER_CCHP(timer_periph) |= (uint32_t)TIMER_CCHP_POEN; - }else{ + } else { TIMER_CCHP(timer_periph) &= (~(uint32_t)TIMER_CCHP_POEN); } } /*! - \brief enable or disable channel capture/compare control shadow register + \brief enable or disable channel capture/compare control shadow register \param[in] timer_periph: TIMERx(x=0,7) - \param[in] newvalue: ENABLE or DISABLE + \param[in] newvalue: ENABLE or DISABLE \param[out] none \retval none */ void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus newvalue) { - if(ENABLE == newvalue){ + if(ENABLE == newvalue) { TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCSE; - }else{ + } else { TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCSE); } } @@ -662,28 +663,28 @@ void timer_channel_control_shadow_config(uint32_t timer_periph, ControlStatus ne \param[in] ccuctl: channel control shadow register update control only one parameter can be selected which is shown as below: \arg TIMER_UPDATECTL_CCU: the shadow registers update by when CMTG bit is set - \arg TIMER_UPDATECTL_CCUTRI: the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs + \arg TIMER_UPDATECTL_CCUTRI: the shadow registers update by when CMTG bit is set or an rising edge of TRGI occurs \param[out] none \retval none -*/ +*/ void timer_channel_control_shadow_update_config(uint32_t timer_periph, uint32_t ccuctl) { - if(TIMER_UPDATECTL_CCU == ccuctl){ + if(TIMER_UPDATECTL_CCU == ccuctl) { TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_CCUC); - }else if(TIMER_UPDATECTL_CCUTRI == ccuctl){ + } else if(TIMER_UPDATECTL_CCUTRI == ccuctl) { TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_CCUC; - }else{ - /* illegal parameters */ + } else { + /* illegal parameters */ } } /*! \brief initialize TIMER channel output parameter struct with a default value - \param[in] ocpara: TIMER channel n output parameter struct - \param[out] none + \param[in] none + \param[out] ocpara: TIMER channel n output parameter struct \retval none */ -void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara) +void timer_channel_output_struct_para_init(timer_oc_parameter_struct *ocpara) { /* initialize the channel output parameter struct member with the default value */ ocpara->outputstate = TIMER_CCX_DISABLE; @@ -704,18 +705,18 @@ void timer_channel_output_struct_para_init(timer_oc_parameter_struct* ocpara) \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7)) \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7)) \param[in] ocpara: TIMER channeln output parameter struct - outputstate: TIMER_CCX_ENABLE,TIMER_CCX_DISABLE - outputnstate: TIMER_CCXN_ENABLE,TIMER_CCXN_DISABLE - ocpolarity: TIMER_OC_POLARITY_HIGH,TIMER_OC_POLARITY_LOW - ocnpolarity: TIMER_OCN_POLARITY_HIGH,TIMER_OCN_POLARITY_LOW - ocidlestate: TIMER_OC_IDLE_STATE_LOW,TIMER_OC_IDLE_STATE_HIGH - ocnidlestate: TIMER_OCN_IDLE_STATE_LOW,TIMER_OCN_IDLE_STATE_HIGH + outputstate: TIMER_CCX_ENABLE, TIMER_CCX_DISABLE + outputnstate: TIMER_CCXN_ENABLE, TIMER_CCXN_DISABLE + ocpolarity: TIMER_OC_POLARITY_HIGH, TIMER_OC_POLARITY_LOW + ocnpolarity: TIMER_OCN_POLARITY_HIGH, TIMER_OCN_POLARITY_LOW + ocidlestate: TIMER_OC_IDLE_STATE_LOW, TIMER_OC_IDLE_STATE_HIGH + ocnidlestate: TIMER_OCN_IDLE_STATE_LOW, TIMER_OCN_IDLE_STATE_HIGH \param[out] none \retval none */ -void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct* ocpara) +void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_oc_parameter_struct *ocpara) { - switch(channel){ + switch(channel) { /* configure TIMER_CH_0 */ case TIMER_CH_0: /* reset the CH0EN bit */ @@ -728,7 +729,7 @@ void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_ /* set the CH0P bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)ocpara->ocpolarity; - if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)) { /* reset the CH0NEN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); /* set the CH0NEN bit */ @@ -757,25 +758,25 @@ void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_ /* reset the CH1P bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1P); /* set the CH1P bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 4U); - if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)) { /* reset the CH1NEN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NEN); /* set the CH1NEN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate)<< 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate) << 4U); /* reset the CH1NP bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1NP); /* set the CH1NP bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity)<< 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity) << 4U); /* reset the ISO1 bit */ TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1); /* set the ISO1 bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 2U); + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 2U); /* reset the ISO1N bit */ TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO1N); /* set the ISO1N bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate)<< 2U); + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate) << 2U); } break; /* configure TIMER_CH_2 */ @@ -788,44 +789,44 @@ void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_ /* reset the CH2P bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2P); /* set the CH2P bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 8U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 8U); - if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)) { /* reset the CH2NEN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NEN); /* set the CH2NEN bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate)<< 8U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputnstate) << 8U); /* reset the CH2NP bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH2NP); /* set the CH2NP bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity)<< 8U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnpolarity) << 8U); /* reset the ISO2 bit */ TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2); /* set the ISO2 bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 4U); + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 4U); /* reset the ISO2N bit */ TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO2N); /* set the ISO2N bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate)<< 4U); + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocnidlestate) << 4U); } break; /* configure TIMER_CH_3 */ case TIMER_CH_3: /* reset the CH3EN bit */ - TIMER_CHCTL2(timer_periph) &=(~(uint32_t)TIMER_CHCTL2_CH3EN); + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3EN); TIMER_CHCTL1(timer_periph) &= ~(uint32_t)TIMER_CHCTL1_CH3MS; /* set the CH3EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->outputstate) << 12U); /* reset the CH3P bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH3P); /* set the CH3P bit */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity)<< 12U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocpolarity) << 12U); - if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)){ + if((TIMER0 == timer_periph) || (TIMER7 == timer_periph)) { /* reset the ISO3 bit */ TIMER_CTL1(timer_periph) &= (~(uint32_t)TIMER_CTL1_ISO3); /* set the ISO3 bit */ - TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate)<< 6U); + TIMER_CTL1(timer_periph) |= (uint32_t)((uint32_t)(ocpara->ocidlestate) << 6U); } break; default: @@ -850,14 +851,14 @@ void timer_channel_output_config(uint32_t timer_periph, uint16_t channel, timer_ \arg TIMER_OC_MODE_TOGGLE: toggle mode \arg TIMER_OC_MODE_LOW: force low mode \arg TIMER_OC_MODE_HIGH: force high mode - \arg TIMER_OC_MODE_PWM0: PWM0 mode - \arg TIMER_OC_MODE_PWM1: PWM1 mode + \arg TIMER_OC_MODE_PWM0: PWM mode 0 + \arg TIMER_OC_MODE_PWM1: PWM mode 1 \param[out] none \retval none */ void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, uint16_t ocmode) { - switch(channel){ + switch(channel) { /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCTL); @@ -866,7 +867,7 @@ void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, u /* configure TIMER_CH_1 */ case TIMER_CH_1: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1COMCTL); - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocmode)<< 8U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(ocmode) << 8U); break; /* configure TIMER_CH_2 */ case TIMER_CH_2: @@ -876,7 +877,7 @@ void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, u /* configure TIMER_CH_3 */ case TIMER_CH_3: TIMER_CHCTL1(timer_periph) &= (~(uint32_t)TIMER_CHCTL1_CH3COMCTL); - TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocmode)<< 8U); + TIMER_CHCTL1(timer_periph) |= (uint32_t)((uint32_t)(ocmode) << 8U); break; default: break; @@ -892,13 +893,13 @@ void timer_channel_output_mode_config(uint32_t timer_periph, uint16_t channel, u \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) - \param[in] pulse: channel output pulse value + \param[in] pulse: channel output pulse value, 0~65535 \param[out] none \retval none */ -void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint16_t pulse) +void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t channel, uint32_t pulse) { - switch(channel){ + switch(channel) { /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CH0CV(timer_periph) = (uint32_t)pulse; @@ -913,7 +914,7 @@ void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t cha break; /* configure TIMER_CH_3 */ case TIMER_CH_3: - TIMER_CH3CV(timer_periph) = (uint32_t)pulse; + TIMER_CH3CV(timer_periph) = (uint32_t)pulse; break; default: break; @@ -938,7 +939,7 @@ void timer_channel_output_pulse_value_config(uint32_t timer_periph, uint16_t cha */ void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, uint16_t ocshadow) { - switch(channel){ + switch(channel) { /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMSEN); @@ -982,7 +983,7 @@ void timer_channel_output_shadow_config(uint32_t timer_periph, uint16_t channel, */ void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, uint16_t ocfast) { - switch(channel){ + switch(channel) { /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMFEN); @@ -1026,7 +1027,7 @@ void timer_channel_output_fast_config(uint32_t timer_periph, uint16_t channel, u */ void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, uint16_t occlear) { - switch(channel){ + switch(channel) { /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0COMCEN); @@ -1053,7 +1054,7 @@ void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, } /*! - \brief configure TIMER channel output polarity + \brief configure TIMER channel output polarity \param[in] timer_periph: please refer to the following parameters \param[in] channel: only one parameter can be selected which is shown as below: @@ -1070,7 +1071,7 @@ void timer_channel_output_clear_config(uint32_t timer_periph, uint16_t channel, */ void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocpolarity) { - switch(channel){ + switch(channel) { /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0P); @@ -1097,14 +1098,14 @@ void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channe } /*! - \brief configure TIMER channel complementary output polarity + \brief configure TIMER channel complementary output polarity \param[in] timer_periph: TIMERx(x=0,7) - \param[in] channel: + \param[in] channel: only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel0(TIMERx(x=0..4,7..13)) \arg TIMER_CH_1: TIMER channel1(TIMERx(x=0..4,7,8,11)) \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) - \param[in] ocnpolarity: channel complementary output polarity + \param[in] ocnpolarity: channel complementary output polarity only one parameter can be selected which is shown as below: \arg TIMER_OCN_POLARITY_HIGH: channel complementary output polarity is high \arg TIMER_OCN_POLARITY_LOW: channel complementary output polarity is low @@ -1113,7 +1114,7 @@ void timer_channel_output_polarity_config(uint32_t timer_periph, uint16_t channe */ void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnpolarity) { - switch(channel){ + switch(channel) { /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NP); @@ -1145,14 +1146,14 @@ void timer_channel_complementary_output_polarity_config(uint32_t timer_periph, u \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) \param[in] state: TIMER channel enable state only one parameter can be selected which is shown as below: - \arg TIMER_CCX_ENABLE: channel enable - \arg TIMER_CCX_DISABLE: channel disable + \arg TIMER_CCX_ENABLE: channel enable + \arg TIMER_CCX_DISABLE: channel disable \param[out] none \retval none */ void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, uint32_t state) { - switch(channel){ + switch(channel) { /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); @@ -1188,14 +1189,14 @@ void timer_channel_output_state_config(uint32_t timer_periph, uint16_t channel, \arg TIMER_CH_2: TIMER channel2 \param[in] ocnstate: TIMER channel complementary output enable state only one parameter can be selected which is shown as below: - \arg TIMER_CCXN_ENABLE: channel complementary enable - \arg TIMER_CCXN_DISABLE: channel complementary disable + \arg TIMER_CCXN_ENABLE: channel complementary enable + \arg TIMER_CCXN_DISABLE: channel complementary disable \param[out] none \retval none */ void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint16_t channel, uint16_t ocnstate) { - switch(channel){ + switch(channel) { /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0NEN); @@ -1218,11 +1219,11 @@ void timer_channel_complementary_output_state_config(uint32_t timer_periph, uint /*! \brief initialize TIMER channel input parameter struct with a default value - \param[in] icpara: TIMER channel intput parameter struct - \param[out] none + \param[in] none + \param[out] icpara: TIMER channel intput parameter struct \retval none */ -void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara) +void timer_channel_input_struct_para_init(timer_ic_parameter_struct *icpara) { /* initialize the channel input parameter struct member with the default value */ icpara->icpolarity = TIMER_IC_POLARITY_RISING; @@ -1232,17 +1233,17 @@ void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara) } /*! - \brief configure TIMER input capture parameter + \brief configure TIMER input capture parameter \param[in] timer_periph: please refer to the following parameters \param[in] channel: - only one parameter can be selected which is shown as below: + only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel 0(TIMERx(x=0..4,7..13)) \arg TIMER_CH_1: TIMER channel 1(TIMERx(x=0..4,7,8,11)) \arg TIMER_CH_2: TIMER channel 2(TIMERx(x=0..4,7)) \arg TIMER_CH_3: TIMER channel 3(TIMERx(x=0..4,7)) \param[in] icpara: TIMER channel intput parameter struct icpolarity: TIMER_IC_POLARITY_RISING, TIMER_IC_POLARITY_FALLING, - TIMER_IC_POLARITY_BOTH_EDGE(only for TIMER1~TIMER8) + TIMER_IC_POLARITY_BOTH_EDGE(only for TIMERx(x=0, 7..13)) icselection: TIMER_IC_SELECTION_DIRECTTI, TIMER_IC_SELECTION_INDIRECTTI, TIMER_IC_SELECTION_ITS icprescaler: TIMER_IC_PSC_DIV1, TIMER_IC_PSC_DIV2, TIMER_IC_PSC_DIV4, @@ -1251,9 +1252,9 @@ void timer_channel_input_struct_para_init(timer_ic_parameter_struct* icpara) \param[out] none \retval none */ -void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpara) +void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct *icpara) { - switch(channel){ + switch(channel) { /* configure TIMER_CH_0 */ case TIMER_CH_0: /* reset the CH0EN bit */ @@ -1272,7 +1273,7 @@ void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_i /* set the CH0EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; break; - + /* configure TIMER_CH_1 */ case TIMER_CH_1: /* reset the CH1EN bit */ @@ -1335,7 +1336,7 @@ void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_i break; } /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph,channel,(uint16_t)(icpara->icprescaler)); + timer_channel_input_capture_prescaler_config(timer_periph, channel, (uint16_t)(icpara->icprescaler)); } /*! @@ -1358,7 +1359,7 @@ void timer_input_capture_config(uint32_t timer_periph, uint16_t channel, timer_i */ void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_t channel, uint16_t prescaler) { - switch(channel){ + switch(channel) { /* configure TIMER_CH_0 */ case TIMER_CH_0: TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH0CAPPSC); @@ -1394,13 +1395,13 @@ void timer_channel_input_capture_prescaler_config(uint32_t timer_periph, uint16_ \arg TIMER_CH_2: TIMER channel2(TIMERx(x=0..4,7)) \arg TIMER_CH_3: TIMER channel3(TIMERx(x=0..4,7)) \param[out] none - \retval channel capture compare register value + \retval channel capture compare register value, 0~65535 */ uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16_t channel) { uint32_t count_value = 0U; - switch(channel){ + switch(channel) { case TIMER_CH_0: /* read TIMER channel 0 capture compare register value */ count_value = TIMER_CH0CV(timer_periph); @@ -1424,39 +1425,39 @@ uint32_t timer_channel_capture_value_register_read(uint32_t timer_periph, uint16 } /*! - \brief configure TIMER input pwm capture function + \brief configure TIMER input pwm capture function \param[in] timer_periph: TIMERx(x=0..4,7,8,11) \param[in] channel: only one parameter can be selected which is shown as below: \arg TIMER_CH_0: TIMER channel0 \arg TIMER_CH_1: TIMER channel1 \param[in] icpwm:TIMER channel intput pwm parameter struct - icpolarity: TIMER_IC_POLARITY_RISING,TIMER_IC_POLARITY_FALLING - icselection: TIMER_IC_SELECTION_DIRECTTI,TIMER_IC_SELECTION_INDIRECTTI - icprescaler: TIMER_IC_PSC_DIV1,TIMER_IC_PSC_DIV2,TIMER_IC_PSC_DIV4,TIMER_IC_PSC_DIV8 + icpolarity: TIMER_IC_POLARITY_RISING, TIMER_IC_POLARITY_FALLING + icselection: TIMER_IC_SELECTION_DIRECTTI, TIMER_IC_SELECTION_INDIRECTTI + icprescaler: TIMER_IC_PSC_DIV1, TIMER_IC_PSC_DIV2, TIMER_IC_PSC_DIV4, TIMER_IC_PSC_DIV8 icfilter: 0~15 \param[out] none \retval none */ -void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct* icpwm) +void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, timer_ic_parameter_struct *icpwm) { uint16_t icpolarity = 0x0U; uint16_t icselection = 0x0U; /* Set channel input polarity */ - if(TIMER_IC_POLARITY_RISING == icpwm->icpolarity){ + if(TIMER_IC_POLARITY_RISING == icpwm->icpolarity) { icpolarity = TIMER_IC_POLARITY_FALLING; - }else{ + } else { icpolarity = TIMER_IC_POLARITY_RISING; } /* Set channel input mode selection */ - if(TIMER_IC_SELECTION_DIRECTTI == icpwm->icselection){ + if(TIMER_IC_SELECTION_DIRECTTI == icpwm->icselection) { icselection = TIMER_IC_SELECTION_INDIRECTTI; - }else{ + } else { icselection = TIMER_IC_SELECTION_DIRECTTI; } - if(TIMER_CH_0 == channel){ + if(TIMER_CH_0 == channel) { /* reset the CH0EN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); /* reset the CH0P and CH0NP bits */ @@ -1474,50 +1475,50 @@ void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, tim /* set the CH0EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(icpwm->icprescaler)); + timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_0, (uint16_t)(icpwm->icprescaler)); /* reset the CH1EN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); /* reset the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); /* set the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)icpolarity<< 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)icpolarity << 4U); /* reset the CH1MS bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); /* set the CH1MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)icselection<< 8U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)icselection << 8U); /* reset the CH1CAPFLT bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); /* set the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter)<< 12U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter) << 12U); /* set the CH1EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(icpwm->icprescaler)); - }else{ + timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_1, (uint16_t)(icpwm->icprescaler)); + } else { /* reset the CH1EN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); /* reset the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); /* set the CH1P and CH1NP bits */ - TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icpolarity)<< 4U); + TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icpolarity) << 4U); /* reset the CH1MS bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); /* set the CH1MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icselection)<< 8U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icselection) << 8U); /* reset the CH1CAPFLT bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); /* set the CH1CAPFLT bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter)<< 12U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)(icpwm->icfilter) << 12U); /* set the CH1EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_1,(uint16_t)(icpwm->icprescaler)); + timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_1, (uint16_t)(icpwm->icprescaler)); /* reset the CH0EN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); /* reset the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); /* set the CH0P and CH0NP bits */ TIMER_CHCTL2(timer_periph) |= (uint32_t)icpolarity; /* reset the CH0MS bit */ @@ -1531,7 +1532,7 @@ void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, tim /* set the CH0EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH0EN; /* configure TIMER channel input capture prescaler value */ - timer_channel_input_capture_prescaler_config(timer_periph,TIMER_CH_0,(uint16_t)(icpwm->icprescaler)); + timer_channel_input_capture_prescaler_config(timer_periph, TIMER_CH_0, (uint16_t)(icpwm->icprescaler)); } } @@ -1545,44 +1546,48 @@ void timer_input_pwm_capture_config(uint32_t timer_periph, uint16_t channel, tim \param[out] none \retval none */ -void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode) +void timer_hall_mode_config(uint32_t timer_periph, uint32_t hallmode) { - if(TIMER_HALLINTERFACE_ENABLE == hallmode){ + if(TIMER_HALLINTERFACE_ENABLE == hallmode) { TIMER_CTL1(timer_periph) |= (uint32_t)TIMER_CTL1_TI0S; - }else if(TIMER_HALLINTERFACE_DISABLE == hallmode){ + } else if(TIMER_HALLINTERFACE_DISABLE == hallmode) { TIMER_CTL1(timer_periph) &= ~(uint32_t)TIMER_CTL1_TI0S; - }else{ - /* illegal parameters */ + } else { + /* illegal parameters */ } } /*! - \brief select TIMER input trigger source + \brief select TIMER input trigger source \param[in] timer_periph: please refer to the following parameters \param[in] intrigger: only one parameter can be selected which is shown as below: - \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0,TIMERx(x=0..4,7,8,11) - \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1,TIMERx(x=0..4,7,8,11) - \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2,TIMERx(x=0..4,7,8,11) - \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3,TIMERx(x=0..4,7,8,11) - \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector,TIMERx(x=0..4,7,8,11) - \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0,TIMERx(x=0..4,7,8,11) - \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1,TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0, TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1, TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI2: internal trigger 2, TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_ITI3: internal trigger 3, TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector, TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0, TIMERx(x=0..4,7,8,11) + \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1, TIMERx(x=0..4,7,8,11) \arg TIMER_SMCFG_TRGSEL_ETIFP: external trigger,TIMERx(x=0..4,7) \param[out] none \retval none */ void timer_input_trigger_source_select(uint32_t timer_periph, uint32_t intrigger) { - TIMER_SMCFG(timer_periph) &= (~(uint32_t)TIMER_SMCFG_TRGS); - TIMER_SMCFG(timer_periph) |= (uint32_t)intrigger; + uint32_t reg; + + reg = TIMER_SMCFG(timer_periph); + reg &= (~(uint32_t)TIMER_SMCFG_TRGS); + reg |= (uint32_t)intrigger; + TIMER_SMCFG(timer_periph) = reg; } /*! - \brief select TIMER master mode output trigger source + \brief select TIMER master mode output trigger source \param[in] timer_periph: TIMERx(x=0..7) \param[in] outrigger: - only one parameter can be selected which is shown as below: + only one parameter can be selected which is shown as below: \arg TIMER_TRI_OUT_SRC_RESET: the UPG bit as trigger output(TIMERx(x=0..7)) \arg TIMER_TRI_OUT_SRC_ENABLE: the counter enable signal TIMER_CTL0_CEN as trigger output(TIMERx(x=0..7)) \arg TIMER_TRI_OUT_SRC_UPDATE: update event as trigger output(TIMERx(x=0..7)) @@ -1601,14 +1606,14 @@ void timer_master_output_trigger_source_select(uint32_t timer_periph, uint32_t o } /*! - \brief select TIMER slave mode + \brief select TIMER slave mode \param[in] timer_periph: TIMERx(x=0..4,7,8,11) \param[in] slavemode: only one parameter can be selected which is shown as below: \arg TIMER_SLAVE_MODE_DISABLE: slave mode disable - \arg TIMER_ENCODER_MODE0: encoder mode 0 - \arg TIMER_ENCODER_MODE1: encoder mode 1 - \arg TIMER_ENCODER_MODE2: encoder mode 2 + \arg TIMER_QUAD_DECODER_MODE0: quadrature decoder mode 0 + \arg TIMER_QUAD_DECODER_MODE1: quadrature decoder mode 1 + \arg TIMER_QUAD_DECODER_MODE2: quadrature decoder mode 2 \arg TIMER_SLAVE_MODE_RESTART: restart mode \arg TIMER_SLAVE_MODE_PAUSE: pause mode \arg TIMER_SLAVE_MODE_EVENT: event mode @@ -1625,7 +1630,7 @@ void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode) } /*! - \brief configure TIMER master slave mode + \brief configure TIMER master slave mode \param[in] timer_periph: TIMERx(x=0..4,7,8,11) \param[in] masterslave: only one parameter can be selected which is shown as below: @@ -1633,15 +1638,15 @@ void timer_slave_mode_select(uint32_t timer_periph, uint32_t slavemode) \arg TIMER_MASTER_SLAVE_MODE_DISABLE: master slave mode disable \param[out] none \retval none -*/ +*/ void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave) { - if(TIMER_MASTER_SLAVE_MODE_ENABLE == masterslave){ + if(TIMER_MASTER_SLAVE_MODE_ENABLE == masterslave) { TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SMCFG_MSM; - }else if(TIMER_MASTER_SLAVE_MODE_DISABLE == masterslave){ + } else if(TIMER_MASTER_SLAVE_MODE_DISABLE == masterslave) { TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_MSM; - }else{ - /* illegal parameters */ + } else { + /* illegal parameters */ } } @@ -1662,7 +1667,7 @@ void timer_master_slave_mode_config(uint32_t timer_periph, uint32_t masterslave) \param[out] none \retval none */ -void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter) +void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter) { TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_ETP | TIMER_SMCFG_ETPSC | TIMER_SMCFG_ETFC)); TIMER_SMCFG(timer_periph) |= (uint32_t)(extprescaler | extpolarity); @@ -1671,12 +1676,12 @@ void timer_external_trigger_config(uint32_t timer_periph, uint32_t extprescaler, /*! \brief configure TIMER quadrature decoder mode - \param[in] timer_periph: TIMERx(x=0..4,7,8,11) + \param[in] timer_periph: TIMERx(x=0..4,7) \param[in] decomode: only one parameter can be selected which is shown as below: - \arg TIMER_ENCODER_MODE0: counter counts on CI0FE0 edge depending on CI1FE1 level - \arg TIMER_ENCODER_MODE1: counter counts on CI1FE1 edge depending on CI0FE0 level - \arg TIMER_ENCODER_MODE2: counter counts on both CI0FE0 and CI1FE1 edges depending on the level of the other input + \arg TIMER_QUAD_DECODER_MODE0: counter counts on CI0FE0 edge depending on CI1FE1 level + \arg TIMER_QUAD_DECODER_MODE1: counter counts on CI1FE1 edge depending on CI0FE0 level + \arg TIMER_QUAD_DECODER_MODE2: counter counts on both CI0FE0 and CI1FE1 edges depending on the level of the other input \param[in] ic0polarity: only one parameter can be selected which is shown as below: \arg TIMER_IC_POLARITY_RISING: capture rising edge @@ -1716,7 +1721,7 @@ void timer_internal_clock_config(uint32_t timer_periph) /*! \brief configure TIMER the internal trigger as external clock input \param[in] timer_periph: TIMERx(x=0..4,7,8,11) - \param[in] intrigger: + \param[in] intrigger: only one parameter can be selected which is shown as below: \arg TIMER_SMCFG_TRGSEL_ITI0: internal trigger 0 \arg TIMER_SMCFG_TRGSEL_ITI1: internal trigger 1 @@ -1727,7 +1732,7 @@ void timer_internal_clock_config(uint32_t timer_periph) */ void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t intrigger) { - timer_input_trigger_source_select(timer_periph,intrigger); + timer_input_trigger_source_select(timer_periph, intrigger); TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC; TIMER_SMCFG(timer_periph) |= (uint32_t)TIMER_SLAVE_MODE_EXTERNAL0; } @@ -1740,7 +1745,7 @@ void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint \arg TIMER_SMCFG_TRGSEL_CI0F_ED: TI0 edge detector \arg TIMER_SMCFG_TRGSEL_CI0FE0: filtered TIMER input 0 \arg TIMER_SMCFG_TRGSEL_CI1FE1: filtered TIMER input 1 - \param[in] expolarity: + \param[in] extpolarity: only one parameter can be selected which is shown as below: \arg TIMER_IC_POLARITY_RISING: active high or rising edge active \arg TIMER_IC_POLARITY_FALLING: active low or falling edge active @@ -1748,30 +1753,30 @@ void timer_internal_trigger_as_external_clock_config(uint32_t timer_periph, uint \param[out] none \retval none */ -void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint8_t extfilter) +void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint32_t extrigger, uint16_t extpolarity, uint32_t extfilter) { - if(TIMER_SMCFG_TRGSEL_CI1FE1 == extrigger){ + if(TIMER_SMCFG_TRGSEL_CI1FE1 == extrigger) { /* reset the CH1EN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH1EN); /* reset the CH1NP bit */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P|TIMER_CHCTL2_CH1NP)); + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH1P | TIMER_CHCTL2_CH1NP)); /* set the CH1NP bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)((uint32_t)extpolarity << 4U); /* reset the CH1MS bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1MS); /* set the CH1MS bit */ - TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)TIMER_IC_SELECTION_DIRECTTI<< 8U); + TIMER_CHCTL0(timer_periph) |= (uint32_t)((uint32_t)TIMER_IC_SELECTION_DIRECTTI << 8U); /* reset the CH1CAPFLT bit */ TIMER_CHCTL0(timer_periph) &= (~(uint32_t)TIMER_CHCTL0_CH1CAPFLT); /* set the CH1CAPFLT bit */ TIMER_CHCTL0(timer_periph) |= (uint32_t)(extfilter << 12U); /* set the CH1EN bit */ TIMER_CHCTL2(timer_periph) |= (uint32_t)TIMER_CHCTL2_CH1EN; - }else{ + } else { /* reset the CH0EN bit */ TIMER_CHCTL2(timer_periph) &= (~(uint32_t)TIMER_CHCTL2_CH0EN); /* reset the CH0P and CH0NP bits */ - TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P|TIMER_CHCTL2_CH0NP)); + TIMER_CHCTL2(timer_periph) &= (~(uint32_t)(TIMER_CHCTL2_CH0P | TIMER_CHCTL2_CH0NP)); /* set the CH0P and CH0NP bits */ TIMER_CHCTL2(timer_periph) |= (uint32_t)extpolarity; /* reset the CH0MS bit */ @@ -1802,7 +1807,7 @@ void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint \arg TIMER_EXT_TRI_PSC_DIV2: divided by 2 \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 - \param[in] expolarity: + \param[in] extpolarity: only one parameter can be selected which is shown as below: \arg TIMER_ETP_FALLING: active low or falling edge active \arg TIMER_ETP_RISING: active high or rising edge active @@ -1810,14 +1815,17 @@ void timer_external_trigger_as_external_clock_config(uint32_t timer_periph, uint \param[out] none \retval none */ -void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter) +void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter) { + uint32_t reg = 0U; + reg = TIMER_SMCFG(timer_periph); + /* configure TIMER external trigger input */ timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); - /* reset the SMC bit,TRGS bit */ - TIMER_SMCFG(timer_periph) &= (~(uint32_t)(TIMER_SMCFG_SMC | TIMER_SMCFG_TRGS)); - /* set the SMC bit,TRGS bit */ - TIMER_SMCFG(timer_periph) |= (uint32_t)(TIMER_SLAVE_MODE_EXTERNAL0 | TIMER_SMCFG_TRGSEL_ETIFP); + /* set the SMC bit, TRGS bit */ + reg &= (~(uint32_t)(TIMER_SMCFG_SMC | TIMER_SMCFG_TRGS)); + reg |= (uint32_t)(TIMER_SLAVE_MODE_EXTERNAL0 | TIMER_SMCFG_TRGSEL_ETIFP); + TIMER_SMCFG(timer_periph) = reg; } /*! @@ -1830,14 +1838,14 @@ void timer_external_clock_mode0_config(uint32_t timer_periph, uint32_t extpresca \arg TIMER_EXT_TRI_PSC_DIV4: divided by 4 \arg TIMER_EXT_TRI_PSC_DIV8: divided by 8 \param[in] extpolarity: - only one parameter can be selected which is shown as below: + only one parameter can be selected which is shown as below: \arg TIMER_ETP_FALLING: active low or falling edge active \arg TIMER_ETP_RISING: active high or rising edge active \param[in] extfilter: a value between 0 and 15 \param[out] none \retval none */ -void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint8_t extfilter) +void timer_external_clock_mode1_config(uint32_t timer_periph, uint32_t extprescaler, uint32_t extpolarity, uint32_t extfilter) { /* configure TIMER external trigger input */ timer_external_trigger_config(timer_periph, extprescaler, extpolarity, extfilter); @@ -1855,9 +1863,64 @@ void timer_external_clock_mode1_disable(uint32_t timer_periph) TIMER_SMCFG(timer_periph) &= ~(uint32_t)TIMER_SMCFG_SMC1; } + +/*! + \brief get TIMER flags + \param[in] timer_periph: please refer to the following parameters + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: + \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) + \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) + \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CMT: channel commutation flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag) +{ + if(RESET != (TIMER_INTF(timer_periph) & flag)) { + return SET; + } else { + return RESET; + } +} + +/*! + \brief clear TIMER flags + \param[in] timer_periph: please refer to the following parameters + \param[in] flag: the timer interrupt flags + only one parameter can be selected which is shown as below: + \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) + \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) + \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) + \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) + \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) + \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) + \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) + \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) + \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) + \param[out] none + \retval none +*/ +void timer_flag_clear(uint32_t timer_periph, uint32_t flag) +{ + TIMER_INTF(timer_periph) = (~(uint32_t)flag); +} + /*! \brief enable the TIMER interrupt - \param[in] timer_periph: please refer to the following parameters + \param[in] timer_periph: please refer to the following parameters \param[in] interrupt: timer interrupt enable source only one parameter can be selected which is shown as below: \arg TIMER_INT_UP: update interrupt enable, TIMERx(x=0..13) @@ -1873,7 +1936,7 @@ void timer_external_clock_mode1_disable(uint32_t timer_periph) */ void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt) { - TIMER_DMAINTEN(timer_periph) |= (uint32_t) interrupt; + TIMER_DMAINTEN(timer_periph) |= (uint32_t) interrupt; } /*! @@ -1894,32 +1957,32 @@ void timer_interrupt_enable(uint32_t timer_periph, uint32_t interrupt) */ void timer_interrupt_disable(uint32_t timer_periph, uint32_t interrupt) { - TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)interrupt); + TIMER_DMAINTEN(timer_periph) &= (~(uint32_t)interrupt); } /*! \brief get timer interrupt flag \param[in] timer_periph: please refer to the following parameters - \param[in] interrupt: the timer interrupt bits + \param[in] int_flag: the timer interrupt flag only one parameter can be selected which is shown as below: \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) - \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) \param[out] none \retval FlagStatus: SET or RESET */ -FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt) +FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t int_flag) { uint32_t val; - val = (TIMER_DMAINTEN(timer_periph) & interrupt); - if((RESET != (TIMER_INTF(timer_periph) & interrupt) ) && (RESET != val)){ + val = (TIMER_DMAINTEN(timer_periph) & int_flag); + if((RESET != (TIMER_INTF(timer_periph) & int_flag)) && (RESET != val)) { return SET; - }else{ + } else { return RESET; } } @@ -1927,74 +1990,20 @@ FlagStatus timer_interrupt_flag_get(uint32_t timer_periph, uint32_t interrupt) /*! \brief clear TIMER interrupt flag \param[in] timer_periph: please refer to the following parameters - \param[in] interrupt: the timer interrupt bits + \param[in] int_flag: the timer interrupt flag only one parameter can be selected which is shown as below: \arg TIMER_INT_FLAG_UP: update interrupt flag,TIMERx(x=0..13) \arg TIMER_INT_FLAG_CH0: channel 0 interrupt flag,TIMERx(x=0..4,7..13) \arg TIMER_INT_FLAG_CH1: channel 1 interrupt flag,TIMERx(x=0..4,7,8,11) \arg TIMER_INT_FLAG_CH2: channel 2 interrupt flag,TIMERx(x=0..4,7) \arg TIMER_INT_FLAG_CH3: channel 3 interrupt flag,TIMERx(x=0..4,7) - \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) + \arg TIMER_INT_FLAG_CMT: channel commutation interrupt flag,TIMERx(x=0,7) \arg TIMER_INT_FLAG_TRG: trigger interrupt flag,TIMERx(x=0,7,8,11) \arg TIMER_INT_FLAG_BRK: break interrupt flag,TIMERx(x=0,7) \param[out] none \retval none */ -void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt) +void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t int_flag) { - TIMER_INTF(timer_periph) = (~(uint32_t)interrupt); -} - -/*! - \brief get TIMER flags - \param[in] timer_periph: please refer to the following parameters - \param[in] flag: the timer interrupt flags - only one parameter can be selected which is shown as below: - \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) - \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) - \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CMT: channel commutation flag,TIMERx(x=0,7) - \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) - \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) - \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) - \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) - \param[out] none - \retval FlagStatus: SET or RESET -*/ -FlagStatus timer_flag_get(uint32_t timer_periph, uint32_t flag) -{ - if(RESET != (TIMER_INTF(timer_periph) & flag)){ - return SET; - }else{ - return RESET; - } -} - -/*! - \brief clear TIMER flags - \param[in] timer_periph: please refer to the following parameters - \param[in] flag: the timer interrupt flags - only one parameter can be selected which is shown as below: - \arg TIMER_FLAG_UP: update flag,TIMERx(x=0..13) - \arg TIMER_FLAG_CH0: channel 0 flag,TIMERx(x=0..4,7..13) - \arg TIMER_FLAG_CH1: channel 1 flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_FLAG_CH2: channel 2 flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CH3: channel 3 flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CMT: channel control update flag,TIMERx(x=0,7) - \arg TIMER_FLAG_TRG: trigger flag,TIMERx(x=0,7,8,11) - \arg TIMER_FLAG_BRK: break flag,TIMERx(x=0,7) - \arg TIMER_FLAG_CH0O: channel 0 overcapture flag,TIMERx(x=0..4,7..11) - \arg TIMER_FLAG_CH1O: channel 1 overcapture flag,TIMERx(x=0..4,7,8,11) - \arg TIMER_FLAG_CH2O: channel 2 overcapture flag,TIMERx(x=0..4,7) - \arg TIMER_FLAG_CH3O: channel 3 overcapture flag,TIMERx(x=0..4,7) - \param[out] none - \retval none -*/ -void timer_flag_clear(uint32_t timer_periph, uint32_t flag) -{ - TIMER_INTF(timer_periph) = (~(uint32_t)flag); + TIMER_INTF(timer_periph) = (~(uint32_t)int_flag); } diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_tli.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_tli.c index 9b1362ea..26dc3f0d 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_tli.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_tli.c @@ -2,43 +2,43 @@ \file gd32f20x_tli.c \brief TLI driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "gd32f20x_tli.h" +#define TLI_DEFAULT_VALUE 0x00000000U +#define TLI_OPAQUE_VALUE 0x000000FFU + /*! - \brief deinitialize TLI registers + \brief deinitialize TLI registers \param[in] none \param[out] none \retval none @@ -50,22 +50,64 @@ void tli_deinit(void) } /*! - \brief initialize TLI display timing parameters - \param[in] tli_struct: the data needed to initialize tli + \brief initialize the parameters of TLI parameter structure with the default values, it is suggested + that call this function after a tli_parameter_struct structure is defined + \param[in] none + \param[out] tli_struct: the data needed to initialize TLI synpsz_vpsz: size of the vertical synchronous pulse synpsz_hpsz: size of the horizontal synchronous pulse - backpsz_vbpsz: size of the vertical back porch plus synchronous pulse + backpsz_vbpsz: size of the vertical back porch plus synchronous pulse backpsz_hbpsz: size of the horizontal back porch plus synchronous pulse activesz_vasz: size of the vertical active area width plus back porch and synchronous pulse activesz_hasz: size of the horizontal active area width plus back porch and synchronous pulse - totalsz_vtsz: vertical total size of the display, including active area, back porch, synchronous + totalsz_vtsz: vertical total size of the display, including active area, back porch, synchronous totalsz_htsz: vorizontal total size of the display, including active area, back porch, synchronous backcolor_red: background value red backcolor_green: background value green backcolor_blue: background value blue - signalpolarity_hs: TLI_HSYN_ACTLIVE_LOW,TLI_HSYN_ACTLIVE_HIGHT - signalpolarity_vs: TLI_VSYN_ACTLIVE_LOW,TLI_VSYN_ACTLIVE_HIGHT - signalpolarity_de: TLI_DE_ACTLIVE_LOW,TLI_DE_ACTLIVE_HIGHT + signalpolarity_hs: TLI_HSYN_ACTLIVE_LOW,TLI_HSYN_ACTLIVE_HIGH + signalpolarity_vs: TLI_VSYN_ACTLIVE_LOW,TLI_VSYN_ACTLIVE_HIGH + signalpolarity_de: TLI_DE_ACTLIVE_LOW,TLI_DE_ACTLIVE_HIGH + signalpolarity_pixelck: TLI_PIXEL_CLOCK_TLI,TLI_PIXEL_CLOCK_INVERTEDTLI + \retval none +*/ +void tli_struct_para_init(tli_parameter_struct *tli_struct) +{ + /* initialize the struct parameters with default values */ + tli_struct->synpsz_vpsz = TLI_DEFAULT_VALUE; + tli_struct->synpsz_hpsz = TLI_DEFAULT_VALUE; + tli_struct->backpsz_vbpsz = TLI_DEFAULT_VALUE; + tli_struct->backpsz_hbpsz = TLI_DEFAULT_VALUE; + tli_struct->activesz_vasz = TLI_DEFAULT_VALUE; + tli_struct->activesz_hasz = TLI_DEFAULT_VALUE; + tli_struct->totalsz_vtsz = TLI_DEFAULT_VALUE; + tli_struct->totalsz_htsz = TLI_DEFAULT_VALUE; + tli_struct->backcolor_red = TLI_DEFAULT_VALUE; + tli_struct->backcolor_green = TLI_DEFAULT_VALUE; + tli_struct->backcolor_blue = TLI_DEFAULT_VALUE; + tli_struct->signalpolarity_hs = TLI_HSYN_ACTLIVE_LOW; + tli_struct->signalpolarity_vs = TLI_VSYN_ACTLIVE_LOW; + tli_struct->signalpolarity_de = TLI_DE_ACTLIVE_LOW; + tli_struct->signalpolarity_pixelck = TLI_PIXEL_CLOCK_TLI; +} + +/*! + \brief initialize TLI display timing parameters + \param[in] tli_struct: the data needed to initialize TLI + synpsz_vpsz: size of the vertical synchronous pulse + synpsz_hpsz: size of the horizontal synchronous pulse + backpsz_vbpsz: size of the vertical back porch plus synchronous pulse + backpsz_hbpsz: size of the horizontal back porch plus synchronous pulse + activesz_vasz: size of the vertical active area width plus back porch and synchronous pulse + activesz_hasz: size of the horizontal active area width plus back porch and synchronous pulse + totalsz_vtsz: vertical total size of the display, including active area, back porch, synchronous + totalsz_htsz: horizontal total size of the display, including active area, back porch, synchronous + backcolor_red: background value red + backcolor_green: background value green + backcolor_blue: background value blue + signalpolarity_hs: TLI_HSYN_ACTLIVE_LOW,TLI_HSYN_ACTLIVE_HIGH + signalpolarity_vs: TLI_VSYN_ACTLIVE_LOW,TLI_VSYN_ACTLIVE_HIGH + signalpolarity_de: TLI_DE_ACTLIVE_LOW,TLI_DE_ACTLIVE_HIGH signalpolarity_pixelck: TLI_PIXEL_CLOCK_TLI,TLI_PIXEL_CLOCK_INVERTEDTLI \param[out] none \retval none @@ -73,44 +115,45 @@ void tli_deinit(void) void tli_init(tli_parameter_struct *tli_struct) { /* synchronous pulse size configuration */ - TLI_SPSZ &= ~(TLI_SPSZ_VPSZ|TLI_SPSZ_HPSZ); - TLI_SPSZ = (tli_struct->synpsz_vpsz|(tli_struct->synpsz_hpsz<<16U)); + TLI_SPSZ &= ~(TLI_SPSZ_VPSZ | TLI_SPSZ_HPSZ); + TLI_SPSZ = (uint32_t)((uint32_t)tli_struct->synpsz_vpsz | ((uint32_t)tli_struct->synpsz_hpsz << 16U)); /* back-porch size configuration */ - TLI_BPSZ &= ~(TLI_BPSZ_VBPSZ|TLI_BPSZ_HBPSZ); - TLI_BPSZ = (tli_struct->backpsz_vbpsz|(tli_struct->backpsz_hbpsz<<16U)); - /* active size configuration */ - TLI_ASZ &= ~(TLI_ASZ_VASZ|TLI_ASZ_HASZ); - TLI_ASZ = (tli_struct->activesz_vasz|(tli_struct->activesz_hasz<<16U)); - /* total size configuration */ - TLI_TSZ &= ~(TLI_TSZ_VTSZ|TLI_TSZ_HTSZ); - TLI_TSZ = (tli_struct->totalsz_vtsz|(tli_struct->totalsz_htsz<<16U)); - /* background color configuration */ - TLI_BGC &= ~(TLI_BGC_BVB|(TLI_BGC_BVG)|(TLI_BGC_BVR)); - TLI_BGC = (tli_struct->backcolor_blue|(tli_struct->backcolor_green<<8U)|(tli_struct->backcolor_red<<16U)); - TLI_CTL &= ~(TLI_CTL_HPPS|TLI_CTL_VPPS|TLI_CTL_DEPS|TLI_CTL_CLKPS); - TLI_CTL |= (tli_struct->signalpolarity_hs|tli_struct->signalpolarity_vs|\ - tli_struct->signalpolarity_de|tli_struct->signalpolarity_pixelck); + TLI_BPSZ &= ~(TLI_BPSZ_VBPSZ | TLI_BPSZ_HBPSZ); + TLI_BPSZ = (uint32_t)((uint32_t)tli_struct->backpsz_vbpsz | ((uint32_t)tli_struct->backpsz_hbpsz << 16U)); + /* active size configuration */ + TLI_ASZ &= ~(TLI_ASZ_VASZ | TLI_ASZ_HASZ); + TLI_ASZ = (tli_struct->activesz_vasz | (tli_struct->activesz_hasz << 16U)); + /* total size configuration */ + TLI_TSZ &= ~(TLI_TSZ_VTSZ | TLI_TSZ_HTSZ); + TLI_TSZ = (tli_struct->totalsz_vtsz | (tli_struct->totalsz_htsz << 16U)); + /* background color configuration */ + TLI_BGC &= ~(TLI_BGC_BVB | (TLI_BGC_BVG) | (TLI_BGC_BVR)); + TLI_BGC = (tli_struct->backcolor_blue | (tli_struct->backcolor_green << 8U) | (tli_struct->backcolor_red << 16U)); + TLI_CTL &= ~(TLI_CTL_HPPS | TLI_CTL_VPPS | TLI_CTL_DEPS | TLI_CTL_CLKPS); + TLI_CTL |= (tli_struct->signalpolarity_hs | tli_struct->signalpolarity_vs | \ + tli_struct->signalpolarity_de | tli_struct->signalpolarity_pixelck); } /*! - \brief configure TLI dither function - \param[in] ditherstat + \brief configure TLI dither function + \param[in] dither_stat + only one parameter can be selected which is shown as below: \arg TLI_DITHER_ENABLE \arg TLI_DITHER_DISABLE \param[out] none \retval none */ -void tli_dither_config(uint8_t ditherstat) +void tli_dither_config(uint8_t dither_stat) { - if(TLI_DITHER_ENABLE == ditherstat){ + if(TLI_DITHER_ENABLE == dither_stat) { TLI_CTL |= TLI_CTL_DFEN; - }else{ + } else { TLI_CTL &= ~(TLI_CTL_DFEN); } } /*! - \brief TLI enable + \brief enable TLI \param[in] none \param[out] none \retval none @@ -121,7 +164,7 @@ void tli_enable(void) } /*! - \brief TLI disable + \brief disable TLI \param[in] none \param[out] none \retval none @@ -132,118 +175,78 @@ void tli_disable(void) } /*! - \brief configure TLI reload mode - \param[in] reloadmode + \brief configure TLI reload mode + \param[in] reload_mod + only one parameter can be selected which is shown as below: \arg TLI_FRAME_BLANK_RELOAD_EN \arg TLI_REQUEST_RELOAD_EN \param[out] none \retval none */ -void tli_reload_config(uint8_t reloadmode) +void tli_reload_config(uint8_t reload_mod) { - if(TLI_FRAME_BLANK_RELOAD_EN == reloadmode){ + if(TLI_FRAME_BLANK_RELOAD_EN == reload_mod) { + /* the layer configuration will be reloaded at frame blank */ TLI_RL |= TLI_RL_FBR; - }else{ + } else { + /* the layer configuration will be reloaded after this bit sets */ TLI_RL |= TLI_RL_RQR; } } /*! - \brief set line mark value - \param[in] linenum: line number - \param[out] none - \retval none -*/ -void tli_line_mark_set(uint32_t linenum) -{ - TLI_LM &= ~(TLI_LM_LM); - TLI_LM = linenum; -} - -/*! - \brief get current displayed position - \param[in] none - \param[out] none - \retval none -*/ -uint32_t tli_current_pos_get(void) -{ - return TLI_CPPOS; -} - -/*! - \brief TLI layer enable - \param[in] layerx: LAYERx(x=0,1) - \param[out] none - \retval none -*/ -void tli_layer_enable(uint32_t layerx) -{ - TLI_LxCTL(layerx) |= TLI_LxCTL_LEN; -} - -/*! - \brief TLI layer disable - \param[in] layerx: LAYERx(x=0,1) - \param[out] none - \retval none -*/ -void tli_layer_disable(uint32_t layerx) -{ - TLI_LxCTL(layerx) &= ~(TLI_LxCTL_LEN); -} - -/*! - \brief TLI layer color keying enable - \param[in] layerx: LAYERx(x=0,1) - \param[out] none - \retval none -*/ -void tli_color_key_enable(uint32_t layerx) -{ - TLI_LxCTL(layerx) |= TLI_LxCTL_CKEYEN; -} - -/*! - \brief TLI layer color keying disable - \param[in] layerx: LAYERx(x=0,1) - \param[out] none - \retval none -*/ -void tli_color_key_disable(uint32_t layerx) -{ - TLI_LxCTL(layerx) &= ~(TLI_LxCTL_CKEYEN); -} - -/*! - \brief TLI layer LUT enable - \param[in] layerx: LAYERx(x=0,1) - \param[out] none - \retval none -*/ -void tli_lut_enable(uint32_t layerx) -{ - TLI_LxCTL(layerx) |= TLI_LxCTL_LUTEN; -} - -/*! - \brief TLI layer LUT disable - \param[in] layerx: LAYERx(x=0,1) - \param[out] none + \brief initialize the parameters of TLI layer structure with the default values, it is suggested + that call this function after a tli_layer_parameter_struct structure is defined + \param[in] none + \param[out] layer_struct: TLI Layer parameter struct + layer_window_rightpos: window right position + layer_window_leftpos: window left position + layer_window_bottompos: window bottom position + layer_window_toppos: window top position + layer_ppf: LAYER_PPF_ARGB8888,LAYER_PPF_RGB888,LAYER_PPF_RGB565, + LAYER_PPF_ARG1555,LAYER_PPF_ARGB4444,LAYER_PPF_L8, + LAYER_PPF_AL44,LAYER_PPF_AL88 + layer_sa: specified alpha + layer_default_alpha: the default color alpha + layer_default_red: the default color red + layer_default_green: the default color green + layer_default_blue: the default color blue + layer_acf1: LAYER_ACF1_SA,LAYER_ACF1_PASA + layer_acf2: LAYER_ACF2_SA,LAYER_ACF2_PASA + layer_frame_bufaddr: frame buffer base address + layer_frame_buf_stride_offset: frame buffer stride offset + layer_frame_line_length: frame line length + layer_frame_total_line_number: frame total line number \retval none */ -void tli_lut_disable(uint32_t layerx) +void tli_layer_struct_para_init(tli_layer_parameter_struct *layer_struct) { - TLI_LxCTL(layerx) &= ~(TLI_LxCTL_LUTEN); + /* initialize the struct parameters with default values */ + layer_struct->layer_window_rightpos = TLI_DEFAULT_VALUE; + layer_struct->layer_window_leftpos = TLI_DEFAULT_VALUE; + layer_struct->layer_window_bottompos = TLI_DEFAULT_VALUE; + layer_struct->layer_window_toppos = TLI_DEFAULT_VALUE; + layer_struct->layer_ppf = LAYER_PPF_ARGB8888; + layer_struct->layer_sa = TLI_OPAQUE_VALUE; + layer_struct->layer_default_alpha = TLI_DEFAULT_VALUE; + layer_struct->layer_default_red = TLI_DEFAULT_VALUE; + layer_struct->layer_default_green = TLI_DEFAULT_VALUE; + layer_struct->layer_default_blue = TLI_DEFAULT_VALUE; + layer_struct->layer_acf1 = LAYER_ACF1_PASA; + layer_struct->layer_acf2 = LAYER_ACF2_PASA; + layer_struct->layer_frame_bufaddr = TLI_DEFAULT_VALUE; + layer_struct->layer_frame_buf_stride_offset = TLI_DEFAULT_VALUE; + layer_struct->layer_frame_line_length = TLI_DEFAULT_VALUE; + layer_struct->layer_frame_total_line_number = TLI_DEFAULT_VALUE; } /*! - \brief TLI layer initialize + \brief initialize TLI layer \param[in] layerx: LAYERx(x=0,1) \param[in] layer_struct: TLI Layer parameter struct layer_window_rightpos: window right position layer_window_leftpos: window left position - layer_window_bottompos: window bottom position + layer_window_bottompos: window bottom position layer_window_toppos: window top position layer_ppf: LAYER_PPF_ARGB8888,LAYER_PPF_RGB888,LAYER_PPF_RGB565, LAYER_PPF_ARG1555,LAYER_PPF_ARGB4444,LAYER_PPF_L8, @@ -262,14 +265,14 @@ void tli_lut_disable(uint32_t layerx) \param[out] none \retval none */ -void tli_layer_init(uint32_t layerx,tli_layer_parameter_struct *layer_struct) +void tli_layer_init(uint32_t layerx, tli_layer_parameter_struct *layer_struct) { /* configure layer window horizontal position */ - TLI_LxHPOS(layerx) &= ~(TLI_LxHPOS_WLP|(TLI_LxHPOS_WRP)); - TLI_LxHPOS(layerx) = (layer_struct->layer_window_leftpos | (layer_struct->layer_window_rightpos<<16U)); + TLI_LxHPOS(layerx) &= ~(TLI_LxHPOS_WLP | (TLI_LxHPOS_WRP)); + TLI_LxHPOS(layerx) = (uint32_t)((uint32_t)layer_struct->layer_window_leftpos | ((uint32_t)layer_struct->layer_window_rightpos << 16U)); /* configure layer window vertical position */ - TLI_LxVPOS(layerx) &= ~(TLI_LxVPOS_WTP|(TLI_LxVPOS_WBP)); - TLI_LxVPOS(layerx) = (layer_struct->layer_window_toppos |(layer_struct->layer_window_bottompos<<16U)); + TLI_LxVPOS(layerx) &= ~(TLI_LxVPOS_WTP | (TLI_LxVPOS_WBP)); + TLI_LxVPOS(layerx) = (uint32_t)((uint32_t)layer_struct->layer_window_toppos | ((uint32_t)layer_struct->layer_window_bottompos << 16U)); /* configure layer packeted pixel format */ TLI_LxPPF(layerx) &= ~(TLI_LxPPF_PPF); TLI_LxPPF(layerx) = layer_struct->layer_ppf; @@ -277,173 +280,252 @@ void tli_layer_init(uint32_t layerx,tli_layer_parameter_struct *layer_struct) TLI_LxSA(layerx) &= ~(TLI_LxSA_SA); TLI_LxSA(layerx) = layer_struct->layer_sa; /* configure layer default color */ - TLI_LxDC(layerx) &= ~(TLI_LxDC_DCB|(TLI_LxDC_DCG)|(TLI_LxDC_DCR)|(TLI_LxDC_DCA)); - TLI_LxDC(layerx) = (layer_struct->layer_default_blue |(layer_struct->layer_default_green<<8U) - |(layer_struct->layer_default_red<<16U) - |(layer_struct->layer_default_alpha<<24U)); + TLI_LxDC(layerx) &= ~(TLI_LxDC_DCB | (TLI_LxDC_DCG) | (TLI_LxDC_DCR) | (TLI_LxDC_DCA)); + TLI_LxDC(layerx) = (uint32_t)((uint32_t)layer_struct->layer_default_blue | ((uint32_t)layer_struct->layer_default_green << 8U) + | ((uint32_t)layer_struct->layer_default_red << 16U) + | ((uint32_t)layer_struct->layer_default_alpha << 24U)); /* configure layer alpha calculation factors */ - TLI_LxBLEND(layerx) &= ~(TLI_LxBLEND_ACF2|(TLI_LxBLEND_ACF1)); - TLI_LxBLEND(layerx) = ((layer_struct->layer_acf2)|(layer_struct->layer_acf1)); + TLI_LxBLEND(layerx) &= ~(TLI_LxBLEND_ACF2 | (TLI_LxBLEND_ACF1)); + TLI_LxBLEND(layerx) = ((layer_struct->layer_acf2) | (layer_struct->layer_acf1)); /* configure layer frame buffer base address */ TLI_LxFBADDR(layerx) &= ~(TLI_LxFBADDR_FBADD); TLI_LxFBADDR(layerx) = (layer_struct->layer_frame_bufaddr); /* configure layer frame line length */ - TLI_LxFLLEN(layerx) &= ~(TLI_LxFLLEN_FLL|(TLI_LxFLLEN_STDOFF)); - TLI_LxFLLEN(layerx) = (layer_struct->layer_frame_line_length|(layer_struct->layer_frame_buf_stride_offset<<16U)); - /* configure layer frame buffer base address */ - TLI_LxFBADDR(layerx) &= ~(TLI_LxFBADDR_FBADD); - TLI_LxFBADDR(layerx) = (layer_struct->layer_frame_bufaddr); + TLI_LxFLLEN(layerx) &= ~(TLI_LxFLLEN_FLL | (TLI_LxFLLEN_STDOFF)); + TLI_LxFLLEN(layerx) = (uint32_t)((uint32_t)layer_struct->layer_frame_line_length | ((uint32_t)layer_struct->layer_frame_buf_stride_offset << 16U)); /* configure layer frame total line number */ - TLI_LxFTLN(layerx) &= ~(TLI_LxFTLN_FTLN); - TLI_LxFTLN(layerx) = (layer_struct->layer_frame_total_line_number); + TLI_LxFTLN(layerx) &= ~(TLI_LxFTLN_FTLN); + TLI_LxFTLN(layerx) = (uint32_t)(layer_struct->layer_frame_total_line_number); + } /*! - \brief reconfigure window position - \param[in] layerx: LAYERx(x=0,1) - \param[in] offset_x: new horizontal offset - \param[in] offset_y: new vertical offset + \brief reconfigure window position + \param[in] layerx: LAYERx(x=0,1) + \param[in] offset_x: new horizontal offset + \param[in] offset_y: new vertical offset \param[out] none \retval none */ -void tli_layer_window_offset_modify(uint32_t layerx,uint32_t offset_x,uint32_t offset_y) +void tli_layer_window_offset_modify(uint32_t layerx, uint16_t offset_x, uint16_t offset_y) { /* configure window start position */ - uint32_t layer_ppf,line_length,line_num,hstart,vstart; - TLI_LxHPOS(layerx) &= ~(TLI_LxHPOS_WLP|(TLI_LxHPOS_WRP)); - TLI_LxVPOS(layerx) &= ~(TLI_LxVPOS_WTP|(TLI_LxVPOS_WBP)); - hstart = offset_x+(((TLI_BPSZ & TLI_BPSZ_HBPSZ)>>16U)+1U); - vstart = offset_y+((TLI_BPSZ & TLI_BPSZ_VBPSZ)+1U); + uint32_t layer_ppf, line_num, hstart, vstart; + uint32_t line_length = 0U; + TLI_LxHPOS(layerx) &= ~(TLI_LxHPOS_WLP | (TLI_LxHPOS_WRP)); + TLI_LxVPOS(layerx) &= ~(TLI_LxVPOS_WTP | (TLI_LxVPOS_WBP)); + hstart = (uint32_t)offset_x + (((TLI_BPSZ & TLI_BPSZ_HBPSZ) >> 16U) + 1U); + vstart = (uint32_t)offset_y + ((TLI_BPSZ & TLI_BPSZ_VBPSZ) + 1U); line_num = (TLI_LxFTLN(layerx) & TLI_LxFTLN_FTLN); layer_ppf = (TLI_LxPPF(layerx) & TLI_LxPPF_PPF); /* the bytes of a line equal TLI_LxFLLEN_FLL bits value minus 3 */ - switch(layer_ppf){ + switch(layer_ppf) { case LAYER_PPF_ARGB8888: /* each pixel includes 4bytes,when pixel format is ARGB8888 */ - line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)/4U); + line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL) - 3U) / 4U); break; case LAYER_PPF_RGB888: /* each pixel includes 3bytes,when pixel format is RGB888 */ - line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)/3U); + line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL) - 3U) / 3U); break; case LAYER_PPF_RGB565: case LAYER_PPF_ARGB1555: case LAYER_PPF_ARGB4444: case LAYER_PPF_AL88: /* each pixel includes 2bytes,when pixel format is RGB565,ARG1555,ARGB4444 or AL88 */ - line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)/2U); + line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL) - 3U) / 2U); break; case LAYER_PPF_L8: case LAYER_PPF_AL44: /* each pixel includes 1byte,when pixel format is L8 or AL44 */ - line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL)-3U)); + line_length = (((TLI_LxFLLEN(layerx) & TLI_LxFLLEN_FLL) - 3U)); break; default: break; } /* reconfigure window position */ - TLI_LxHPOS(layerx) = (hstart|((hstart+line_length-1U)<<16U)); - TLI_LxVPOS(layerx) = (vstart|((vstart+line_num-1U)<<16U)); + TLI_LxHPOS(layerx) = (hstart | ((hstart + line_length - 1U) << 16U)); + TLI_LxVPOS(layerx) = (vstart | ((vstart + line_num - 1U) << 16U)); } /*! - \brief TLI layer LUT initialize + \brief initialize the parameters of TLI layer LUT structure with the default values, it is suggested + that call this function after a tli_layer_lut_parameter_struct structure is defined + \param[in] none + \param[out] lut_struct: TLI layer LUT parameter struct + layer_table_addr: look up table write address + layer_lut_channel_red: red channel of a LUT entry + layer_lut_channel_green: green channel of a LUT entry + layer_lut_channel_blue: blue channel of a LUT entry + \retval none +*/ +void tli_lut_struct_para_init(tli_layer_lut_parameter_struct *lut_struct) +{ + /* initialize the struct parameters with default values */ + lut_struct->layer_table_addr = TLI_DEFAULT_VALUE; + lut_struct->layer_lut_channel_red = TLI_DEFAULT_VALUE; + lut_struct->layer_lut_channel_green = TLI_DEFAULT_VALUE; + lut_struct->layer_lut_channel_blue = TLI_DEFAULT_VALUE; +} + +/*! + \brief initialize TLI layer LUT \param[in] layerx: LAYERx(x=0,1) \param[in] lut_struct: TLI layer LUT parameter struct layer_table_addr: window right position layer_lut_channel_red: window left position - layer_window_bottompos: window bottom position + layer_window_bottompos: window bottom position layer_window_toppos: window top position \param[out] none \retval none */ -void tli_lut_init(uint32_t layerx,tli_layer_lut_parameter_struct *lut_struct) +void tli_lut_init(uint32_t layerx, tli_layer_lut_parameter_struct *lut_struct) { - TLI_LxLUT(layerx) &= ~(TLI_LxLUT_TB|TLI_LxLUT_TG|TLI_LxLUT_TR|TLI_LxLUT_TADD); - TLI_LxLUT(layerx) = ((lut_struct->layer_lut_channel_blue)|(lut_struct->layer_lut_channel_green<<8) - |(lut_struct->layer_lut_channel_red<<16 - |(lut_struct->layer_table_addr<<24))); + TLI_LxLUT(layerx) = (uint32_t)(((uint32_t)lut_struct->layer_lut_channel_blue) | ((uint32_t)lut_struct->layer_lut_channel_green << 8U) + | ((uint32_t)lut_struct->layer_lut_channel_red << 16U + | ((uint32_t)lut_struct->layer_table_addr << 24U))); } /*! - \brief TLI layer key initialize - \param[in] layerx: LAYERx(x=0,1) - \param[in] redkey: color key red - \param[in] greenkey: color key green - \param[in] bluekey: color key blue + \brief initialize TLI layer color key + \param[in] layerx: LAYERx(x=0,1) + \param[in] redkey: color key red + \param[in] greenkey: color key green + \param[in] bluekey: color key blue \param[out] none \retval none */ -void tli_ckey_init(uint32_t layerx,uint32_t redkey,uint32_t greenkey,uint32_t bluekey) +void tli_color_key_init(uint32_t layerx, uint8_t redkey, uint8_t greenkey, uint8_t bluekey) { - TLI_LxCKEY(layerx) = ((bluekey)|(greenkey<<8U)|(redkey<<16U)); + TLI_LxCKEY(layerx) = (((uint32_t)bluekey) | ((uint32_t)greenkey << 8U) | ((uint32_t)redkey << 16U)); } /*! - \brief get TLI flag or state - \param[in] flag: TLI flags or states - \arg TLI_FLAG_VDE: current VDE state - \arg TLI_FLAG_HDE: current HDE state - \arg TLI_FLAG_VS: current vs state - \arg TLI_FLAG_HS: current hs state - \arg TLI_FLAG_LM: line mark interrupt flag - \arg TLI_FLAG_FE: FIFO error interrupt flag - \arg TLI_FLAG_TE: transaction error interrupt flag - \arg TLI_FLAG_LCR: layer configuration reloaded interrupt flag + \brief enable TLI layer + \param[in] layerx: LAYERx(x=0,1) \param[out] none - \retval FlagStatus: SET or RESET + \retval none */ -FlagStatus tli_flag_get(uint32_t flag) +void tli_layer_enable(uint32_t layerx) { - uint32_t stat; - if(flag >> 31){ - /* get flag status from TLI_INTF register */ - stat = TLI_INTF; - }else{ - /* get flag status from TLI_STAT register */ - stat = TLI_STAT; - } - if(flag & stat){ - return SET; - }else{ - return RESET; - } + TLI_LxCTL(layerx) |= TLI_LxCTL_LEN; } /*! - \brief enable TLI interrupt - \param[in] interrupt: TLI interrupt flags - \arg TLI_INT_LM: line mark interrupt - \arg TLI_INT_FE: FIFO error interrupt - \arg TLI_INT_TE: transaction error interrupt - \arg TLI_INT_LCR: layer configuration reloaded interrupt + \brief disable TLI layer + \param[in] layerx: LAYERx(x=0,1) \param[out] none \retval none */ -void tli_interrupt_enable(uint32_t interrupt) +void tli_layer_disable(uint32_t layerx) { - TLI_INTEN |= (interrupt); + TLI_LxCTL(layerx) &= ~(TLI_LxCTL_LEN); } /*! - \brief disable TLI interrupt - \param[in] interrupt: TLI interrupt flags - \arg TLI_INT_LM: line mark interrupt - \arg TLI_INT_FE: FIFO error interrupt - \arg TLI_INT_TE: transaction error interrupt - \arg TLI_INT_LCR: layer configuration reloaded interrupt + \brief enable TLI layer color keying + \param[in] layerx: LAYERx(x=0,1) \param[out] none \retval none */ -void tli_interrupt_disable(uint32_t interrupt) +void tli_color_key_enable(uint32_t layerx) { - TLI_INTEN &= ~(interrupt); + TLI_LxCTL(layerx) |= TLI_LxCTL_CKEYEN; } /*! - \brief get TLI interrupt flag + \brief disable TLI layer color keying + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_color_key_disable(uint32_t layerx) +{ + TLI_LxCTL(layerx) &= ~(TLI_LxCTL_CKEYEN); +} + +/*! + \brief enable TLI layer LUT + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_lut_enable(uint32_t layerx) +{ + TLI_LxCTL(layerx) |= TLI_LxCTL_LUTEN; +} + +/*! + \brief disable TLI layer LUT + \param[in] layerx: LAYERx(x=0,1) + \param[out] none + \retval none +*/ +void tli_lut_disable(uint32_t layerx) +{ + TLI_LxCTL(layerx) &= ~(TLI_LxCTL_LUTEN); +} + +/*! + \brief set line mark value + \param[in] line_num: line number + \param[out] none + \retval none +*/ +void tli_line_mark_set(uint16_t line_num) +{ + TLI_LM &= ~(TLI_LM_LM); + TLI_LM = (uint32_t)line_num; +} + +/*! + \brief get current displayed position + \param[in] none + \param[out] none + \retval position of current pixel +*/ +uint32_t tli_current_pos_get(void) +{ + return TLI_CPPOS; +} + +/*! + \brief enable TLI interrupt + \param[in] int_flag: TLI interrupt flags + one or more parameters can be selected which are shown as below: + \arg TLI_INT_LM: line mark interrupt + \arg TLI_INT_FE: FIFO error interrupt + \arg TLI_INT_TE: transaction error interrupt + \arg TLI_INT_LCR: layer configuration reloaded interrupt + \param[out] none + \retval none +*/ +void tli_interrupt_enable(uint32_t int_flag) +{ + TLI_INTEN |= (int_flag); +} + +/*! + \brief disable TLI interrupt \param[in] int_flag: TLI interrupt flags + one or more parameters can be selected which are shown as below: + \arg TLI_INT_LM: line mark interrupt + \arg TLI_INT_FE: FIFO error interrupt + \arg TLI_INT_TE: transaction error interrupt + \arg TLI_INT_LCR: layer configuration reloaded interrupt + \param[out] none + \retval none +*/ +void tli_interrupt_disable(uint32_t int_flag) +{ + TLI_INTEN &= ~(int_flag); +} + +/*! + \brief get TLI interrupt flag + \param[in] int_flag: TLI interrupt flags + one or more parameters can be selected which are shown as below: \arg TLI_INT_FLAG_LM: line mark interrupt flag \arg TLI_INT_FLAG_FE: FIFO error interrupt flag \arg TLI_INT_FLAG_TE: transaction error interrupt flag @@ -455,10 +537,10 @@ FlagStatus tli_interrupt_flag_get(uint32_t int_flag) { uint32_t state; state = TLI_INTF; - if(state & int_flag){ + if(state & int_flag) { state = TLI_INTEN; /* check whether the corresponding bit in TLI_INTEN is set or not */ - if(state & int_flag){ + if(state & int_flag) { return SET; } } @@ -466,8 +548,9 @@ FlagStatus tli_interrupt_flag_get(uint32_t int_flag) } /*! - \brief clear TLI interrupt flag + \brief clear TLI interrupt flag \param[in] int_flag: TLI interrupt flags + one or more parameters can be selected which are shown as below: \arg TLI_INT_FLAG_LM: line mark interrupt flag \arg TLI_INT_FLAG_FE: FIFO error interrupt flag \arg TLI_INT_FLAG_TE: transaction error interrupt flag @@ -479,3 +562,34 @@ void tli_interrupt_flag_clear(uint32_t int_flag) { TLI_INTC |= (int_flag); } + +/*! + \brief get TLI flag or state in TLI_INTF register or TLI_STAT register + \param[in] flag: TLI flags or states + only one parameter can be selected which is shown as below: + \arg TLI_FLAG_VDE: current VDE state + \arg TLI_FLAG_HDE: current HDE state + \arg TLI_FLAG_VS: current VS status of the TLI + \arg TLI_FLAG_HS: current HS status of the TLI + \arg TLI_FLAG_LM: line mark interrupt flag + \arg TLI_FLAG_FE: FIFO error interrupt flag + \arg TLI_FLAG_TE: transaction error interrupt flag + \arg TLI_FLAG_LCR: layer configuration reloaded interrupt flag + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus tli_flag_get(uint32_t flag) +{ + uint32_t stat; + /* choose which register to get flag or state */ + if(flag >> 31U) { + stat = TLI_INTF; + } else { + stat = TLI_STAT; + } + if(flag & stat) { + return SET; + } else { + return RESET; + } +} diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_trng.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_trng.c index 0e098a56..35f5bb1c 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_trng.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_trng.c @@ -2,43 +2,40 @@ \file gd32f20x_trng.c \brief TRNG driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "gd32f20x_trng.h" /*! - \brief deinitialize the TRNG + \brief reset TRNG \param[in] none \param[out] none \retval none @@ -50,7 +47,7 @@ void trng_deinit(void) } /*! - \brief enable the TRNG interface + \brief enable TRNG \param[in] none \param[out] none \retval none @@ -61,7 +58,7 @@ void trng_enable(void) } /*! - \brief disable the TRNG interface + \brief disable TRNG \param[in] none \param[out] none \retval none @@ -75,7 +72,7 @@ void trng_disable(void) \brief get the true random data \param[in] none \param[out] none - \retval the generated random data + \retval the generated random data: 0 - 0xFFFFFFFF */ uint32_t trng_get_true_random_data(void) { @@ -83,7 +80,7 @@ uint32_t trng_get_true_random_data(void) } /*! - \brief get the trng status flags + \brief get TRNG flag status \param[in] flag: trng status flag, refer to trng_flag_enum only one parameter can be selected which is shown as below: \arg TRNG_FLAG_DRDY: Random Data ready status @@ -94,37 +91,37 @@ uint32_t trng_get_true_random_data(void) */ FlagStatus trng_flag_get(trng_flag_enum flag) { - if(RESET != (TRNG_STAT & flag)){ + if(RESET != (TRNG_STAT & flag)) { return SET; - }else{ + } else { return RESET; } } /*! - \brief enable the TRNG interrupt + \brief enable TRNG interrupt \param[in] none \param[out] none \retval none */ -void trng_interrupt_enable(void) +void trng_interrupt_enable(void) { - TRNG_CTL |= TRNG_CTL_IE; + TRNG_CTL |= TRNG_CTL_TRNGIE; } /*! - \brief disable the TRNG interrupt + \brief disable TRNG interrupt \param[in] none \param[out] none \retval none */ void trng_interrupt_disable(void) { - TRNG_CTL &= ~TRNG_CTL_IE; + TRNG_CTL &= ~TRNG_CTL_TRNGIE; } /*! - \brief get the trng interrupt flags + \brief get TRNG interrupt flag status \param[in] int_flag: trng interrupt flag, refer to trng_int_flag_enum only one parameter can be selected which is shown as below: \arg TRNG_INT_FLAG_CE: clock error interrupt flag @@ -134,15 +131,15 @@ void trng_interrupt_disable(void) */ FlagStatus trng_interrupt_flag_get(trng_int_flag_enum int_flag) { - if(RESET != (TRNG_STAT & int_flag)){ + if(RESET != (TRNG_STAT & int_flag)) { return SET; - }else{ + } else { return RESET; } } /*! - \brief clear the trng interrupt flags + \brief clear TRNG interrupt flag status \param[in] int_flag: trng interrupt flag, refer to trng_int_flag_enum only one parameter can be selected which is shown as below: \arg TRNG_INT_FLAG_CE: clock error interrupt flag diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_usart.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_usart.c index 1674afa9..2c829132 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_usart.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_usart.c @@ -2,51 +2,52 @@ \file gd32f20x_usart.c \brief USART driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x - \version 2019-04-11, V2.1.1, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "gd32f20x_usart.h" +/* USART register bit offset */ +#define GP_GUAT_OFFSET ((uint32_t)8U) /* bit offset of GUAT in USART_GP */ +#define CTL3_SCRTNUM_OFFSET ((uint32_t)1U) /* bit offset of SCRTNUM in USART_CTL3 */ +#define RT_BL_OFFSET ((uint32_t)24U) /* bit offset of BL in USART_RT */ + /*! - \brief reset USART/UART + \brief reset USART/UART \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[out] none \retval none */ void usart_deinit(uint32_t usart_periph) { - switch(usart_periph){ + switch(usart_periph) { case USART0: /* reset USART0 */ rcu_periph_reset_enable(RCU_USART0RST); @@ -98,80 +99,80 @@ void usart_deinit(uint32_t usart_periph) \param[in] baudval: baud rate value \param[out] none \retval none -*/ +*/ void usart_baudrate_set(uint32_t usart_periph, uint32_t baudval) { - uint32_t uclk=0U, intdiv=0U, fradiv=0U, udiv=0U; - switch(usart_periph){ - /* get clock frequency */ + uint32_t uclk = 0U, intdiv = 0U, fradiv = 0U, udiv = 0U; + switch(usart_periph) { + /* get clock frequency */ case USART0: - /* get USART0 clock */ - uclk=rcu_clock_freq_get(CK_APB2); - break; + /* get USART0 clock */ + uclk = rcu_clock_freq_get(CK_APB2); + break; case USART5: - /* get USART5 clock */ - uclk=rcu_clock_freq_get(CK_APB2); - break; + /* get USART5 clock */ + uclk = rcu_clock_freq_get(CK_APB2); + break; case USART1: - /* get USART1 clock */ - uclk=rcu_clock_freq_get(CK_APB1); - break; + /* get USART1 clock */ + uclk = rcu_clock_freq_get(CK_APB1); + break; case USART2: - /* get USART2 clock */ - uclk=rcu_clock_freq_get(CK_APB1); - break; + /* get USART2 clock */ + uclk = rcu_clock_freq_get(CK_APB1); + break; case UART3: - /* get UART3 clock */ - uclk=rcu_clock_freq_get(CK_APB1); - break; + /* get UART3 clock */ + uclk = rcu_clock_freq_get(CK_APB1); + break; case UART4: - /* get UART4 clock */ - uclk=rcu_clock_freq_get(CK_APB1); - break; + /* get UART4 clock */ + uclk = rcu_clock_freq_get(CK_APB1); + break; case UART6: - /* get UART6 clock */ - uclk=rcu_clock_freq_get(CK_APB1); - break; + /* get UART6 clock */ + uclk = rcu_clock_freq_get(CK_APB1); + break; case UART7: - /* get UART7 clock */ - uclk=rcu_clock_freq_get(CK_APB1); - break; + /* get UART7 clock */ + uclk = rcu_clock_freq_get(CK_APB1); + break; default: - break; + break; } - /* when oversampling by 16, configure the value of USART_BAUD */ - udiv = (uclk+baudval/2U)/baudval; + /* oversampling by 16, configure the value of USART_BAUD */ + udiv = (uclk + baudval / 2U) / baudval; intdiv = udiv & 0xfff0U; fradiv = udiv & 0xfU; USART_BAUD(usart_periph) = ((USART_BAUD_FRADIV | USART_BAUD_INTDIV) & (intdiv | fradiv)); } /*! - \brief configure USART parity - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) - \param[in] paritycfg: configure USART parity - only one parameter can be selected which is shown as below: - \arg USART_PM_NONE: no parity - \arg USART_PM_ODD: odd parity - \arg USART_PM_EVEN: even parity + \brief configure USART parity + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] paritycfg: configure USART parity + only one parameter can be selected which is shown as below: + \arg USART_PM_NONE: no parity + \arg USART_PM_ODD: odd parity + \arg USART_PM_EVEN: even parity \param[out] none \retval none */ void usart_parity_config(uint32_t usart_periph, uint32_t paritycfg) { - /* clear USART_CTL0 PM,PCEN Bits */ + /* clear USART_CTL0 PM,PCEN bits */ USART_CTL0(usart_periph) &= ~(USART_CTL0_PM | USART_CTL0_PCEN); /* configure USART parity mode */ USART_CTL0(usart_periph) |= paritycfg; } /*! - \brief configure USART word length - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) - \param[in] wlen: USART word length configure - only one parameter can be selected which is shown as below: - \arg USART_WL_8BIT: 8 bits - \arg USART_WL_9BIT: 9 bits + \brief configure USART word length + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] wlen: USART word length configure + only one parameter can be selected which is shown as below: + \arg USART_WL_8BIT: 8 bits + \arg USART_WL_9BIT: 9 bits \param[out] none \retval none */ @@ -184,11 +185,11 @@ void usart_word_length_set(uint32_t usart_periph, uint32_t wlen) } /*! - \brief configure USART stop bit length - \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) - \param[in] stblen: USART stop bit configure - only one parameter can be selected which is shown as below: - \arg USART_STB_1BIT: 1 bit + \brief configure USART stop bit length + \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) + \param[in] stblen: USART stop bit configure + only one parameter can be selected which is shown as below: + \arg USART_STB_1BIT: 1 bit \arg USART_STB_0_5BIT: 0.5 bit(not available for UARTx(x=3,4,6,7)) \arg USART_STB_2BIT: 2 bits \arg USART_STB_1_5BIT: 1.5 bits(not available for UARTx(x=3,4,6,7)) @@ -198,10 +199,11 @@ void usart_word_length_set(uint32_t usart_periph, uint32_t wlen) void usart_stop_bit_set(uint32_t usart_periph, uint32_t stblen) { /* clear USART_CTL1 STB bits */ - USART_CTL1(usart_periph) &= ~USART_CTL1_STB; + USART_CTL1(usart_periph) &= ~USART_CTL1_STB; /* configure USART stop bits */ USART_CTL1(usart_periph) |= stblen; } + /*! \brief enable USART \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) @@ -230,19 +232,14 @@ void usart_disable(uint32_t usart_periph) \param[in] txconfig: enable or disable USART transmitter only one parameter can be selected which is shown as below: \arg USART_TRANSMIT_ENABLE: enable USART transmission - \arg USART_TRANSMIT_DISABLE: enable USART transmission + \arg USART_TRANSMIT_DISABLE: disable USART transmission \param[out] none \retval none */ void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig) { - uint32_t ctl = 0U; - - ctl = USART_CTL0(usart_periph); - ctl &= ~USART_CTL0_TEN; - ctl |= txconfig; - /* configure transfer mode */ - USART_CTL0(usart_periph) = ctl; + USART_CTL0(usart_periph) &= ~(USART_CTL0_TEN); + USART_CTL0(usart_periph) |= (USART_CTL0_TEN & txconfig); } /*! @@ -257,19 +254,15 @@ void usart_transmit_config(uint32_t usart_periph, uint32_t txconfig) */ void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig) { - uint32_t ctl = 0U; - - ctl = USART_CTL0(usart_periph); - ctl &= ~USART_CTL0_REN; - ctl |= rxconfig; - /* configure receiver mode */ - USART_CTL0(usart_periph) = ctl; + USART_CTL0(usart_periph) &= ~(USART_CTL0_REN); + USART_CTL0(usart_periph) |= (USART_CTL0_REN & rxconfig); } /*! \brief data is transmitted/received with the LSB/MSB first \param[in] usart_periph: USARTx(x=0,1,2,5) \param[in] msbf: LSB/MSB + only one parameter can be selected which is shown as below: \arg USART_MSBF_LSB: LSB first \arg USART_MSBF_MSB: MSB first \param[out] none @@ -277,14 +270,15 @@ void usart_receive_config(uint32_t usart_periph, uint32_t rxconfig) */ void usart_data_first_config(uint32_t usart_periph, uint32_t msbf) { - USART_CTL3(usart_periph) &= ~(USART_CTL3_MSBF); + USART_CTL3(usart_periph) &= ~(USART_CTL3_MSBF); USART_CTL3(usart_periph) |= msbf; } /*! \brief configure USART inversion \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[in] invertpara: refer to enum USART_INVERT_CONFIG + \param[in] invertpara: refer to enum usart_invert_enum + only one parameter can be selected which is shown as below: \arg USART_DINV_ENABLE: data bit level inversion \arg USART_DINV_DISABLE: data bit level not inversion \arg USART_TXPIN_ENABLE: TX pin level inversion @@ -296,24 +290,30 @@ void usart_data_first_config(uint32_t usart_periph, uint32_t msbf) */ void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara) { - /* inverted or not the specified siginal */ - switch(invertpara){ + /* inverted or not the specified siginal */ + switch(invertpara) { case USART_DINV_ENABLE: + /* data bit level inversion */ USART_CTL3(usart_periph) |= USART_CTL3_DINV; break; case USART_TXPIN_ENABLE: + /* TX pin level inversion */ USART_CTL3(usart_periph) |= USART_CTL3_TINV; break; case USART_RXPIN_ENABLE: + /* RX pin level inversion */ USART_CTL3(usart_periph) |= USART_CTL3_RINV; break; case USART_DINV_DISABLE: + /* data bit level not inversion */ USART_CTL3(usart_periph) &= ~(USART_CTL3_DINV); break; case USART_TXPIN_DISABLE: + /* TX pin level not inversion */ USART_CTL3(usart_periph) &= ~(USART_CTL3_TINV); break; case USART_RXPIN_DISABLE: + /* RX pin level not inversion */ USART_CTL3(usart_periph) &= ~(USART_CTL3_RINV); break; default: @@ -322,7 +322,7 @@ void usart_invert_config(uint32_t usart_periph, usart_invert_enum invertpara) } /*! - \brief enable receiver timeout of USART + \brief enable receiver timeout \param[in] usart_periph: USARTx(x=0,1,2,5) \param[out] none \retval none @@ -333,7 +333,7 @@ void usart_receiver_timeout_enable(uint32_t usart_periph) } /*! - \brief disable receiver timeout of USART + \brief disable receiver timeout \param[in] usart_periph: USARTx(x=0,1,2,5) \param[out] none \retval none @@ -344,7 +344,7 @@ void usart_receiver_timeout_disable(uint32_t usart_periph) } /*! - \brief set the receiver timeout threshold of USART + \brief configure receiver timeout threshold \param[in] usart_periph: USARTx(x=0,1,2,5) \param[in] rtimeout: 0-0xFFFFFF \param[out] none @@ -359,13 +359,13 @@ void usart_receiver_timeout_threshold_config(uint32_t usart_periph, uint32_t rti /*! \brief USART transmit data function \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) - \param[in] data: data of transmission + \param[in] data: data to be transmitted \param[out] none \retval none */ void usart_data_transmit(uint32_t usart_periph, uint16_t data) { - USART_DATA(usart_periph) = ((uint16_t)USART_DATA_DATA & data); + USART_DATA(usart_periph) = USART_DATA_DATA & (uint32_t)data; } /*! @@ -389,11 +389,11 @@ uint16_t usart_data_receive(uint32_t usart_periph) void usart_address_config(uint32_t usart_periph, uint8_t addr) { USART_CTL1(usart_periph) &= ~(USART_CTL1_ADDR); - USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & addr); + USART_CTL1(usart_periph) |= (USART_CTL1_ADDR & (uint32_t)addr); } /*! - \brief receiver in mute mode + \brief enable mute mode \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[out] none \retval none @@ -404,7 +404,7 @@ void usart_mute_mode_enable(uint32_t usart_periph) } /*! - \brief receiver in active mode + \brief disable mute mode \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[out] none \retval none @@ -437,7 +437,7 @@ void usart_mute_mode_wakeup_config(uint32_t usart_periph, uint32_t wmethod) \retval none */ void usart_lin_mode_enable(uint32_t usart_periph) -{ +{ USART_CTL1(usart_periph) |= USART_CTL1_LMEN; } @@ -448,7 +448,7 @@ void usart_lin_mode_enable(uint32_t usart_periph) \retval none */ void usart_lin_mode_disable(uint32_t usart_periph) -{ +{ USART_CTL1(usart_periph) &= ~(USART_CTL1_LMEN); } @@ -480,18 +480,18 @@ void usart_send_break(uint32_t usart_periph) } /*! - \brief enable half duplex mode + \brief enable half-duplex mode \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[out] none \retval none */ void usart_halfduplex_enable(uint32_t usart_periph) -{ +{ USART_CTL2(usart_periph) |= USART_CTL2_HDEN; } /*! - \brief disable half duplex mode + \brief disable half-duplex mode \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[out] none \retval none @@ -528,43 +528,36 @@ void usart_synchronous_clock_disable(uint32_t usart_periph) \param[in] usart_periph: USARTx(x=0,1,2,5) \param[in] clen: CK length only one parameter can be selected which is shown as below: - \arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame + \arg USART_CLEN_NONE: there are 7 CK pulses for an 8 bit frame and 8 CK pulses for a 9 bit frame \arg USART_CLEN_EN: there are 8 CK pulses for an 8 bit frame and 9 CK pulses for a 9 bit frame \param[in] cph: clock phase only one parameter can be selected which is shown as below: - \arg USART_CPH_1CK: first clock transition is the first data capture edge + \arg USART_CPH_1CK: first clock transition is the first data capture edge \arg USART_CPH_2CK: second clock transition is the first data capture edge \param[in] cpl: clock polarity only one parameter can be selected which is shown as below: - \arg USART_CPL_LOW: steady low value on CK pin + \arg USART_CPL_LOW: steady low value on CK pin \arg USART_CPL_HIGH: steady high value on CK pin \param[out] none \retval none */ void usart_synchronous_clock_config(uint32_t usart_periph, uint32_t clen, uint32_t cph, uint32_t cpl) { - uint32_t ctl = 0U; - - /* read USART_CTL1 register */ - ctl = USART_CTL1(usart_periph); - ctl &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL); - /* set CK length, CK phase, CK polarity */ - ctl |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl); - - USART_CTL1(usart_periph) = ctl; + USART_CTL1(usart_periph) &= ~(USART_CTL1_CLEN | USART_CTL1_CPH | USART_CTL1_CPL); + USART_CTL1(usart_periph) |= (USART_CTL1_CLEN & clen) | (USART_CTL1_CPH & cph) | (USART_CTL1_CPL & cpl); } /*! \brief configure guard time value in smartcard mode \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[in] guat: guard time value + \param[in] guat: guard time value, 0-0xFF \param[out] none \retval none */ -void usart_guard_time_config(uint32_t usart_periph,uint32_t guat) +void usart_guard_time_config(uint32_t usart_periph, uint8_t guat) { USART_GP(usart_periph) &= ~(USART_GP_GUAT); - USART_GP(usart_periph) |= (USART_GP_GUAT & ((guat)<<8)); + USART_GP(usart_periph) |= (USART_GP_GUAT & ((uint32_t)guat << GP_GUAT_OFFSET)); } /*! @@ -618,23 +611,23 @@ void usart_smartcard_mode_nack_disable(uint32_t usart_periph) \param[out] none \retval none */ -void usart_smartcard_autoretry_config(uint32_t usart_periph, uint32_t scrtnum) +void usart_smartcard_autoretry_config(uint32_t usart_periph, uint8_t scrtnum) { USART_CTL3(usart_periph) &= ~(USART_CTL3_SCRTNUM); - USART_CTL3(usart_periph) |= (USART_CTL3_SCRTNUM & ((scrtnum)<<1)); + USART_CTL3(usart_periph) |= (USART_CTL3_SCRTNUM & ((uint32_t)scrtnum << CTL3_SCRTNUM_OFFSET)); } /*! - \brief configure block length in Smartcard T=1 reception + \brief configure block length \param[in] usart_periph: USARTx(x=0,1,2,5) \param[in] bl: block length \param[out] none \retval none */ -void usart_block_length_config(uint32_t usart_periph, uint32_t bl) +void usart_block_length_config(uint32_t usart_periph, uint8_t bl) { USART_RT(usart_periph) &= ~(USART_RT_BL); - USART_RT(usart_periph) |= (USART_RT_BL & ((bl)<<24)); + USART_RT(usart_periph) |= (USART_RT_BL & ((uint32_t)bl << RT_BL_OFFSET)); } /*! @@ -660,7 +653,7 @@ void usart_irda_mode_disable(uint32_t usart_periph) } /*! - \brief configure the peripheral clock prescaler in USART IrDA low-power mode + \brief configure the peripheral clock prescaler \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[in] psc: 0x00-0xFF \param[out] none @@ -669,7 +662,7 @@ void usart_irda_mode_disable(uint32_t usart_periph) void usart_prescaler_config(uint32_t usart_periph, uint8_t psc) { USART_GP(usart_periph) &= ~(USART_GP_PSC); - USART_GP(usart_periph) |= psc; + USART_GP(usart_periph) |= (uint32_t)psc; } /*! @@ -691,7 +684,7 @@ void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp) /*! \brief configure hardware flow control RTS \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[in] hardwareflow: enable or disable RTS + \param[in] rtsconfig: enable or disable RTS only one parameter can be selected which is shown as below: \arg USART_RTS_ENABLE: enable RTS \arg USART_RTS_DISABLE: disable RTS @@ -700,19 +693,14 @@ void usart_irda_lowpower_config(uint32_t usart_periph, uint32_t irlp) */ void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig) { - uint32_t ctl = 0U; - - ctl = USART_CTL2(usart_periph); - ctl &= ~USART_CTL2_RTSEN; - ctl |= rtsconfig; - /* configure RTS */ - USART_CTL2(usart_periph) = ctl; + USART_CTL2(usart_periph) &= ~(USART_CTL2_RTSEN); + USART_CTL2(usart_periph) |= (USART_CTL2_RTSEN & rtsconfig); } /*! \brief configure hardware flow control CTS \param[in] usart_periph: USARTx(x=0,1,2,5) - \param[in] hardwareflow: enable or disable CTS + \param[in] ctsconfig: enable or disable CTS only one parameter can be selected which is shown as below: \arg USART_CTS_ENABLE: enable CTS \arg USART_CTS_DISABLE: disable CTS @@ -721,55 +709,40 @@ void usart_hardware_flow_rts_config(uint32_t usart_periph, uint32_t rtsconfig) */ void usart_hardware_flow_cts_config(uint32_t usart_periph, uint32_t ctsconfig) { - uint32_t ctl = 0U; - - ctl = USART_CTL2(usart_periph); - ctl &= ~USART_CTL2_CTSEN; - ctl |= ctsconfig; - /* configure CTS */ - USART_CTL2(usart_periph) = ctl; + USART_CTL2(usart_periph) &= ~(USART_CTL2_CTSEN); + USART_CTL2(usart_periph) |= (USART_CTL2_CTSEN & ctsconfig); } /*! \brief configure USART DMA reception \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) - \param[in] dmacmd: enable or disable DMA for reception + \param[in] dmaconfig: USART DMA mode only one parameter can be selected which is shown as below: - \arg USART_DENR_ENABLE: DMA enable for reception - \arg USART_DENR_DISABLE: DMA disable for reception + \arg USART_RECEIVE_DMA_ENABLE: enable USART DMA for reception + \arg USART_RECEIVE_DMA_DISABLE: disable USART DMA for reception \param[out] none \retval none */ -void usart_dma_receive_config(uint32_t usart_periph, uint32_t dmacmd) +void usart_dma_receive_config(uint32_t usart_periph, uint8_t dmaconfig) { - uint32_t ctl = 0U; - - ctl = USART_CTL2(usart_periph); - ctl &= ~USART_CTL2_DENR; - ctl |= dmacmd; - /* configure DMA reception */ - USART_CTL2(usart_periph) = ctl; + USART_CTL2(usart_periph) &= ~(USART_CTL2_DENR); + USART_CTL2(usart_periph) |= (USART_CTL2_DENR & dmaconfig); } /*! \brief configure USART DMA transmission \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) - \param[in] dmacmd: enable or disable DMA for transmission + \param[in] dmaconfig: USART DMA mode only one parameter can be selected which is shown as below: - \arg USART_DENT_ENABLE: DMA enable for transmission - \arg USART_DENT_DISABLE: DMA disable for transmission + \arg USART_TRANSMIT_DMA_ENABLE: enable USART DMA for transmission + \arg USART_TRANSMIT_DMA_DISABLE: disable USART DMA for transmission \param[out] none \retval none */ -void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd) +void usart_dma_transmit_config(uint32_t usart_periph, uint8_t dmaconfig) { - uint32_t ctl = 0U; - - ctl = USART_CTL2(usart_periph); - ctl &= ~USART_CTL2_DENT; - ctl |= dmacmd; - /* configure DMA transmission */ - USART_CTL2(usart_periph) = ctl; + USART_CTL2(usart_periph) &= ~(USART_CTL2_DENT); + USART_CTL2(usart_periph) |= (USART_CTL2_DENT & dmaconfig); } /*! @@ -795,9 +768,9 @@ void usart_dma_transmit_config(uint32_t usart_periph, uint32_t dmacmd) */ FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag) { - if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))){ + if(RESET != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))) { return SET; - }else{ + } else { return RESET; } } @@ -807,8 +780,8 @@ FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag) \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) \param[in] flag: USART flags, refer to usart_flag_enum only one parameter can be selected which is shown as below: - \arg USART_FLAG_CTS: CTS change flag - \arg USART_FLAG_LBD: LIN break detected flag + \arg USART_FLAG_CTSF: CTS change flag + \arg USART_FLAG_LBDF: LIN break detected flag \arg USART_FLAG_TC: transmission complete \arg USART_FLAG_RBNE: read data buffer not empty \arg USART_FLAG_EB: end of block flag @@ -818,13 +791,13 @@ FlagStatus usart_flag_get(uint32_t usart_periph, usart_flag_enum flag) */ void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag) { - USART_REG_VAL(usart_periph, flag) &= ~BIT(USART_BIT_POS(flag)); + USART_REG_VAL(usart_periph, flag) = ~BIT(USART_BIT_POS(flag)); } /*! \brief enable USART interrupt \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) - \param[in] int_flag + \param[in] interrupt: USART interrupts, refer to usart_interrupt_enum only one parameter can be selected which is shown as below: \arg USART_INT_PERR: parity error interrupt \arg USART_INT_TBE: transmitter buffer empty interrupt @@ -839,15 +812,15 @@ void usart_flag_clear(uint32_t usart_periph, usart_flag_enum flag) \param[out] none \retval none */ -void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag) +void usart_interrupt_enable(uint32_t usart_periph, usart_interrupt_enum interrupt) { - USART_REG_VAL(usart_periph, int_flag) |= BIT(USART_BIT_POS(int_flag)); + USART_REG_VAL(usart_periph, interrupt) |= BIT(USART_BIT_POS(interrupt)); } /*! \brief disable USART interrupt \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) - \param[in] int_flag + \param[in] interrupt: USART interrupts, refer to usart_interrupt_enum only one parameter can be selected which is shown as below: \arg USART_INT_PERR: parity error interrupt \arg USART_INT_TBE: transmitter buffer empty interrupt @@ -862,9 +835,9 @@ void usart_interrupt_enable(uint32_t usart_periph, uint32_t int_flag) \param[out] none \retval none */ -void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag) +void usart_interrupt_disable(uint32_t usart_periph, usart_interrupt_enum interrupt) { - USART_REG_VAL(usart_periph, int_flag) &= ~BIT(USART_BIT_POS(int_flag)); + USART_REG_VAL(usart_periph, interrupt) &= ~BIT(USART_BIT_POS(interrupt)); } /*! @@ -886,9 +859,9 @@ void usart_interrupt_disable(uint32_t usart_periph, uint32_t int_flag) \arg USART_INT_FLAG_EB: interrupt enable bit of end of block event and flag \arg USART_INT_FLAG_RT: interrupt enable bit of receive timeout event and flag \param[out] none - \retval FlagStatus + \retval FlagStatus: SET or RESET */ -FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag) +FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, usart_interrupt_flag_enum int_flag) { uint32_t intenable = 0U, flagstatus = 0U; /* get the interrupt enable bit status */ @@ -896,28 +869,28 @@ FlagStatus usart_interrupt_flag_get(uint32_t usart_periph, uint32_t int_flag) /* get the corresponding flag bit status */ flagstatus = (USART_REG_VAL2(usart_periph, int_flag) & BIT(USART_BIT_POS2(int_flag))); - if(flagstatus && intenable){ + if((0U != flagstatus) && (0U != intenable)) { return SET; - }else{ - return RESET; + } else { + return RESET; } } /*! \brief clear USART interrupt flag in STAT0/STAT1 register \param[in] usart_periph: USARTx(x=0,1,2,5)/UARTx(x=3,4,6,7) - \param[in] flag: USART interrupt flag + \param[in] int_flag: USART interrupt flags, refer to usart_interrupt_flag_enum only one parameter can be selected which is shown as below: - \arg USART_INT_FLAG_CTS: CTS interrupt and flag - \arg USART_INT_FLAG_LBD: LIN break detected interrupt and flag - \arg USART_INT_FLAG_TC: transmission complete interrupt and flag - \arg USART_INT_FLAG_RBNE: read data buffer not empty interrupt and flag - \arg USART_INT_FLAG_EB: interrupt enable bit of end of block event and flag - \arg USART_INT_FLAG_RT: interrupt enable bit of receive timeout event and flag + \arg USART_INT_FLAG_CTS: CTS change flag + \arg USART_INT_FLAG_LBD: LIN break detected flag + \arg USART_INT_FLAG_TC: transmission complete + \arg USART_INT_FLAG_RBNE: read data buffer not empty + \arg USART_INT_FLAG_EB: end of block flag + \arg USART_INT_FLAG_RT: receiver timeout flag \param[out] none \retval none */ -void usart_interrupt_flag_clear(uint32_t usart_periph, uint32_t flag) +void usart_interrupt_flag_clear(uint32_t usart_periph, usart_interrupt_flag_enum int_flag) { - USART_REG_VAL2(usart_periph, flag) &= ~BIT(USART_BIT_POS2(flag)); + USART_REG_VAL2(usart_periph, int_flag) = ~BIT(USART_BIT_POS2(int_flag)); } diff --git a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_wwdgt.c b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_wwdgt.c index f205b0c2..7c3f7a27 100644 --- a/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_wwdgt.c +++ b/lib-gd32/gd32f20x/GD32F20x_standard_peripheral/Source/gd32f20x_wwdgt.c @@ -2,46 +2,38 @@ \file gd32f20x_wwdgt.c \brief WWDGT driver - \version 2015-07-15, V1.0.0, firmware for GD32F20x - \version 2017-06-05, V2.0.0, firmware for GD32F20x - \version 2018-10-31, V2.1.0, firmware for GD32F20x - \version 2020-09-30, V2.2.0, firmware for GD32F20x + \version 2023-06-30, V2.5.0, firmware for GD32F20x */ /* - Copyright (c) 2020, GigaDevice Semiconductor Inc. + Copyright (c) 2023, GigaDevice Semiconductor Inc. - Redistribution and use in source and binary forms, with or without modification, + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright notice, this + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "gd32f20x_wwdgt.h" -/* write value to WWDGT_CTL_CNT bit field */ -#define CTL_CNT(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) -/* write value to WWDGT_CFG_WIN bit field */ -#define CFG_WIN(regval) (BITS(0,6) & ((uint32_t)(regval) << 0)) - /*! \brief reset the window watchdog timer configuration \param[in] none @@ -73,17 +65,12 @@ void wwdgt_enable(void) */ void wwdgt_counter_update(uint16_t counter_value) { - uint32_t reg = 0U; - - reg = (WWDGT_CTL & (~WWDGT_CTL_CNT)); - reg |= CTL_CNT(counter_value); - - WWDGT_CTL = reg; + WWDGT_CTL = (uint32_t)(CTL_CNT(counter_value)); } /*! - \brief configure counter value, window value, and prescaler divider value - \param[in] counter: 0x00 - 0x7F + \brief configure counter value, window value, and prescaler divider value + \param[in] counter: 0x00 - 0x7F \param[in] window: 0x00 - 0x7F \param[in] prescaler: wwdgt prescaler value only one parameter can be selected which is shown as below: @@ -96,41 +83,36 @@ void wwdgt_counter_update(uint16_t counter_value) */ void wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler) { - uint32_t reg_cfg = 0U, reg_ctl = 0U; - - /* clear WIN and PSC bits, clear CNT bit */ - reg_cfg = (WWDGT_CFG &(~(WWDGT_CFG_WIN|WWDGT_CFG_PSC))); - reg_ctl = (WWDGT_CTL &(~WWDGT_CTL_CNT)); - - /* configure WIN and PSC bits, configure CNT bit */ - reg_cfg |= CFG_WIN(window); - reg_cfg |= prescaler; - reg_ctl |= CTL_CNT(counter); - - WWDGT_CTL = reg_ctl; - WWDGT_CFG = reg_cfg; + WWDGT_CTL = (uint32_t)(CTL_CNT(counter)); + WWDGT_CFG = (uint32_t)(CFG_WIN(window) | prescaler); } /*! - \brief enable early wakeup interrupt of WWDGT + \brief get early wakeup interrupt flag of WWDGT \param[in] none \param[out] none - \retval none + \retval FlagStatus: SET or RESET */ -void wwdgt_interrupt_enable(void) +FlagStatus wwdgt_interrupt_flag_get(void) { - WWDGT_CFG |= WWDGT_CFG_EWIE; + uint32_t state; + state = WWDGT_STAT & WWDGT_STAT_EWIF; + if((WWDGT_CFG & WWDGT_CFG_EWIE) & state) { + return SET; + } + + return RESET; } /*! - \brief check early wakeup interrupt state of WWDGT + \brief get early wakeup flag of WWDGT \param[in] none \param[out] none \retval FlagStatus: SET or RESET */ FlagStatus wwdgt_flag_get(void) { - if(WWDGT_STAT & WWDGT_STAT_EWIF){ + if(WWDGT_STAT & WWDGT_STAT_EWIF) { return SET; } @@ -145,5 +127,16 @@ FlagStatus wwdgt_flag_get(void) */ void wwdgt_flag_clear(void) { - WWDGT_STAT &= (~WWDGT_STAT_EWIF); + WWDGT_STAT = (uint32_t)(RESET); +} + +/*! + \brief enable early wakeup interrupt of WWDGT + \param[in] none + \param[out] none + \retval none +*/ +void wwdgt_interrupt_enable(void) +{ + WWDGT_CFG |= WWDGT_CFG_EWIE; } diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Include/audio_core.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Include/audio_core.h new file mode 100644 index 00000000..d7b914d6 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Include/audio_core.h @@ -0,0 +1,320 @@ +/*! + \file audio_core.h + \brief the header file of USB audio device class core functions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_CORE_H +#define __AUDIO_CORE_H + +#include "usbd_enum.h" + +#define FORMAT_24BIT(x) (uint8_t)(x);(uint8_t)((x) >> 8U);(uint8_t)((x) >> 16U) + +/* number of sub-packets in the audio transfer buffer. you can modify this value but always make sure + that it is an even number and higher than 3 */ +#define OUT_PACKET_NUM 200U + +/* total size of the audio transfer buffer */ +#define OUT_BUF_MARGIN 0U +#define TOTAL_OUT_BUF_SIZE ((uint32_t)((SPEAKER_OUT_PACKET + OUT_BUF_MARGIN) * OUT_PACKET_NUM)) + +#define AD_CONFIG_DESC_SET_LEN (sizeof(usb_desc_config_set)) +#define AD_INTERFACE_DESC_SIZE 9U + +#define USB_AD_DESC_SIZ 0x09U +#define AD_STANDARD_EP_DESC_SIZE 0x09U +#define AD_STREAMING_EP_DESC_SIZE 0x07U + +/* audio interface class code */ +#define USB_CLASS_AUDIO 0x01U + +/* audio interface subclass codes */ +#define AD_SUBCLASS_CONTROL 0x01U +#define AD_SUBCLASS_AUDIOSTREAMING 0x02U +#define AD_SUBCLASS_MIDISTREAMING 0x03U + +/* audio interface protocol codes */ +#define AD_PROTOCOL_UNDEFINED 0x00U +#define AD_STREAMING_GENERAL 0x01U +#define AD_STREAMING_FORMAT_TYPE 0x02U + +/* audio class-specific descriptor types */ +#define AD_DESCTYPE_UNDEFINED 0x20U +#define AD_DESCTYPE_DEVICE 0x21U +#define AD_DESCTYPE_CONFIGURATION 0x22U +#define AD_DESCTYPE_STRING 0x23U +#define AD_DESCTYPE_INTERFACE 0x24U +#define AD_DESCTYPE_ENDPOINT 0x25U + +/* audio control interface descriptor subtypes */ +#define AD_CONTROL_HEADER 0x01U +#define AD_CONTROL_INPUT_TERMINAL 0x02U +#define AD_CONTROL_OUTPUT_TERMINAL 0x03U +#define AD_CONTROL_MIXER_UNIT 0x04U +#define AD_CONTROL_SELECTOR_UNIT 0x05U +#define AD_CONTROL_FEATURE_UNIT 0x06U +#define AD_CONTROL_PROCESSING_UNIT 0x07U +#define AD_CONTROL_EXTENSION_UNIT 0x08U + +#define AD_INPUT_TERMINAL_DESC_SIZE 0x0CU +#define AD_OUTPUT_TERMINAL_DESC_SIZE 0x09U +#define AD_STREAMING_INTERFACE_DESC_SIZE 0x07U + +#define AD_CONTROL_MUTE 0x01U +#define AD_CONTROL_VOLUME 0x02U + +#define AD_FORMAT_TYPE_I 0x01U +#define AD_FORMAT_TYPE_III 0x03U + +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01U +#define AD_ENDPOINT_GENERAL 0x01U + +#define AD_REQ_UNDEFINED 0x00U +#define AD_REQ_SET_CUR 0x01U +#define AD_REQ_GET_CUR 0x81U +#define AD_REQ_SET_MIN 0x02U +#define AD_REQ_GET_MIN 0x82U +#define AD_REQ_SET_MAX 0x03U +#define AD_REQ_GET_MAX 0x83U +#define AD_REQ_SET_RES 0x04U +#define AD_REQ_GET_RES 0x84U +#define AD_REQ_SET_MEM 0x05U +#define AD_REQ_GET_MEM 0x85U +#define AD_REQ_GET_STAT 0xFFU + +#define AD_OUT_STREAMING_CTRL 0x05U +#define AD_IN_STREAMING_CTRL 0x02U + +/* audio stream interface number */ +enum +{ +#ifdef USE_USB_AD_MICPHONE + MIC_INTERFACE_COUNT, +#endif /* USE_USB_AD_MICPHONE */ + +#ifdef USE_USB_AD_SPEAKER + SPEAK_INTERFACE_COUNT, +#endif /* USE_USB_AD_SPEAKER */ + CONFIG_DESC_AS_ITF_COUNT, +}; + +#define AC_ITF_TOTAL_LEN (sizeof(usb_desc_AC_itf) + CONFIG_DESC_AS_ITF_COUNT*(sizeof(usb_desc_input_terminal) + \ + sizeof(usb_desc_mono_feature_unit) + sizeof(usb_desc_output_terminal))) + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< header descriptor subtype */ + uint16_t bcdADC; /*!< audio device class specification release number in binary-coded decimal */ + uint16_t wTotalLength; /*!< total number of bytes */ + uint8_t bInCollection; /*!< the number of the streaming interfaces */ +#ifdef USE_USB_AD_MICPHONE + uint8_t baInterfaceNr0; /*!< interface number of the streaming interfaces */ +#endif /* USE_USB_AD_MICPHONE */ + +#ifdef USE_USB_AD_SPEAKER + uint8_t baInterfaceNr1; /*!< interface number of the streaming interfaces */ +#endif /* USE_USB_AD_SPEAKER */ +} usb_desc_AC_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< AS_GENERAL descriptor subtype */ + uint8_t bTerminalLink; /*!< the terminal ID */ + uint8_t bDelay; /*!< delay introduced by the data path */ + uint16_t wFormatTag; /*!< the audio data format */ +} usb_desc_AS_itf; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< INPUT_TERMINAL descriptor subtype. */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< ID of the output terminal */ + uint8_t bNrChannels; /*!< number of logical output channels */ + uint16_t wChannelConfig; /*!< describes the spatial location of the logical channels */ + uint8_t iChannelNames; /*!< index of a string descriptor */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_input_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< OUTPUT_TERMINAL descriptor subtype */ + uint8_t bTerminalID; /*!< constant uniquely identifying the terminal within the audio function */ + uint16_t wTerminalType; /*!< constant characterizing the type of terminal */ + uint8_t bAssocTerminal; /*!< constant, identifying the input terminal to which this output terminal is associated */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t iTerminal; /*!< index of a string descriptor */ +} usb_desc_output_terminal; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint8_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint8_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_mono_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FEATURE_UNIT descriptor subtype */ + uint8_t bUnitID; /*!< constant uniquely identifying the unit within the audio function */ + uint8_t bSourceID; /*!< ID of the unit or terminal */ + uint8_t bControlSize; /*!< size in bytes of an element of the bmaControls() array */ + uint16_t bmaControls0; /*!< a bit set to 1 indicates that the mentioned control is supported for master channel 0 */ + uint16_t bmaControls1; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 1 */ + uint16_t bmaControls2; /*!< a bit set to 1 indicates that the mentioned control is supported for logical channel 2 */ + uint8_t iFeature; /*!< index of a string descriptor */ +} usb_desc_stereo_feature_unit; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< FORMAT_TYPE descriptor subtype */ + uint8_t bFormatType; /*!< constant identifying the format type */ + uint8_t bNrChannels; /*!< indicates the number of physical channels in the audio data stream */ + uint8_t bSubFrameSize; /*!< the number of bytes occupied by one audio subframe */ + uint8_t bBitResolution; /*!< the number of effectively used bits from the available bits in an audio subframe */ + uint8_t bSamFreqType; /*!< indicates how the sampling frequency can be programmed */ + uint8_t bSamFreq[3]; /*!< sampling frequency ns in Hz for this isochronous data endpoint */ +} usb_desc_format_type; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< the address of the endpoint */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint16_t wMaxPacketSize; /*!< maximum packet size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /*!< left to the designer's discretion */ + uint8_t bRefresh; /*!< reset to 0 */ + uint8_t bSynchAddress; /*!< reset to 0 */ +} usb_desc_std_ep; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bDescriptorSubtype; /*!< EP_GENERAL descriptor subtype */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint8_t bLockDelayUnits; /*!< indicates the units used for the wLockDelay field */ + uint16_t wLockDelay; /*!< indicates the time it takes this endpoint to reliably lock its internal clock recovery circuitry */ +} usb_desc_AS_ep; + +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bEndpointAddress; /*!< EP_GENERAL descriptor subtype */ + uint8_t bmAttributes; /*!< transfer type and synchronization type */ + uint16_t wMaxPacketSize; /*!< maximum packet size this endpoint is capable of sending or receiving */ + uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */ + uint8_t Refresh; /*!< bRefresh 1~9, power of 2 */ + uint8_t bSynchAddress; /* bSynchAddress */ +} usb_desc_FeedBack_ep; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf std_itf; + usb_desc_AC_itf ac_itf; + +#ifdef USE_USB_AD_MICPHONE + usb_desc_input_terminal mic_in_terminal; + usb_desc_mono_feature_unit mic_feature_unit; + usb_desc_output_terminal mic_out_terminal; +#endif + +#ifdef USE_USB_AD_SPEAKER + usb_desc_input_terminal speak_in_terminal; + usb_desc_mono_feature_unit speak_feature_unit; + usb_desc_output_terminal speak_out_terminal; +#endif /* USE_USB_AD_SPEAKER */ + +#ifdef USE_USB_AD_MICPHONE + usb_desc_itf mic_std_as_itf_zeroband; + usb_desc_itf mic_std_as_itf_opera; + usb_desc_AS_itf mic_as_itf; + usb_desc_format_type mic_format_typeI; + usb_desc_std_ep mic_std_endpoint; + usb_desc_AS_ep mic_as_endpoint; +#endif /* USE_USB_AD_MICPHONE */ + +#ifdef USE_USB_AD_SPEAKER + usb_desc_itf speak_std_as_itf_zeroband; + usb_desc_itf speak_std_as_itf_opera; + usb_desc_AS_itf speak_as_itf; + usb_desc_format_type speak_format_typeI; + usb_desc_std_ep speak_std_endpoint; + usb_desc_AS_ep speak_as_endpoint; + usb_desc_FeedBack_ep speak_feedback_endpoint; +#endif /* USE_USB_AD_SPEAKER */ +} usb_desc_config_set; + +typedef struct +{ + /* main buffer for audio data out transfers and its relative pointers */ + uint8_t isoc_out_buff[TOTAL_OUT_BUF_SIZE]; + uint8_t* isoc_out_wrptr; + uint8_t* isoc_out_rdptr; + uint16_t buf_free_size; + uint16_t dam_tx_len; + + __IO uint32_t actual_freq; + __IO uint8_t play_flag; + uint8_t feedback_freq[3]; + uint32_t cur_sam_freq; + + /* usb receive buffer */ + uint8_t usb_rx_buffer[SPEAKER_OUT_MAX_PACKET]; + + /* main buffer for audio control requests transfers and its relative variables */ + uint8_t audioctl[64]; + uint8_t audioctl_unit; + uint32_t audioctl_len; +} usbd_audio_handler; + +extern usb_desc audio_desc; +extern usb_class_core usbd_audio_cb; +extern usbd_audio_handler audio_handler; + +#endif /* __AUDIO_CORE_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Include/audio_out_itf.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Include/audio_out_itf.h new file mode 100644 index 00000000..0ed8b58c --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Include/audio_out_itf.h @@ -0,0 +1,49 @@ +/*! + \file audio_out_itf.h + \brief audio OUT (playback) interface header file + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __AUDIO_OUT_ITF_H +#define __AUDIO_OUT_ITF_H + +#include "usbd_conf.h" +#include "string.h" + +typedef struct { + uint8_t (*audio_init) (uint32_t audio_freq, uint32_t volume); + uint8_t (*audio_deinit) (void); + uint8_t (*audio_cmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); +} audio_fops_struct; + +extern audio_fops_struct audio_out_fops; + +#endif /* __AUDIO_OUT_ITF_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Source/audio_core.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Source/audio_core.c new file mode 100644 index 00000000..05ad7d17 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Source/audio_core.c @@ -0,0 +1,959 @@ +/*! + \file audio_core.c + \brief USB audio device class core functions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_out_itf.h" +#include "audio_core.h" +#include +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x9574U + +#define VOL_MIN 0U /* volume Minimum Value */ +#define VOL_MAX 100U /* volume Maximum Value */ +#define VOL_RES 1U /* volume Resolution */ +#define VOL_0dB 70U /* 0dB is in the middle of VOL_MIN and VOL_MAX */ + +#ifdef USE_USB_AD_MICPHONE +extern volatile uint32_t count_data; +extern const char wavetestdata[]; +#define LENGTH_DATA (1747 * 32) +#endif /* USE_USB_AD_MICPHONE */ + +usbd_audio_handler audio_handler; + +/* local function prototypes ('static') */ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index); +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req); +static uint8_t audio_set_intf (usb_dev *udev, usb_req *req); +static uint8_t audio_ctlx_out (usb_dev *udev); +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num); +static uint8_t audio_sof (usb_dev *udev); +static uint8_t audio_iso_in_incomplete (usb_dev *udev); +static uint8_t audio_iso_out_incomplete (usb_dev *udev); +static uint32_t usbd_audio_spk_get_feedback(usb_dev *udev); +static void get_feedback_fs_rate(uint32_t rate, uint8_t *buf); + +usb_class_core usbd_audio_cb = { + .init = audio_init, + .deinit = audio_deinit, + .req_proc = audio_req_handler, + .set_intf = audio_set_intf, + .ctlx_out = audio_ctlx_out, + .data_in = audio_data_in, + .data_out = audio_data_out, + .SOF = audio_sof, + .incomplete_isoc_in = audio_iso_in_incomplete, + .incomplete_isoc_out = audio_iso_out_incomplete +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev audio_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_desc_config_set audio_config_set = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = AD_CONFIG_DESC_SET_LEN, + .bNumInterfaces = 0x01U + CONFIG_DESC_AS_ITF_COUNT, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .std_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AD_SUBCLASS_CONTROL, + .bInterfaceProtocol = AD_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .ac_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AC_itf), + .bDescriptorType = AD_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bcdADC = 0x0100U, + .wTotalLength = AC_ITF_TOTAL_LEN, + .bInCollection = CONFIG_DESC_AS_ITF_COUNT, +#ifdef USE_USB_AD_MICPHONE + .baInterfaceNr0 = 0x01U, +#endif /* USE_USB_AD_MICPHONE */ + +#ifdef USE_USB_AD_SPEAKER + .baInterfaceNr1 = 0x02U +#endif /* USE_USB_AD_SPEAKER */ + }, + +#ifdef USE_USB_AD_MICPHONE + .mic_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AD_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bTerminalID = 0x01U, + .wTerminalType = 0x0201U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .mic_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AD_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AD_CONTROL_FEATURE_UNIT, + .bUnitID = AD_IN_STREAMING_CTRL, + .bSourceID = 0x01U, + .bControlSize = 0x01U, + .bmaControls0 = AD_CONTROL_MUTE | AD_CONTROL_VOLUME, + .bmaControls1 = 0x00U, + .iFeature = 0x00U + }, + + .mic_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AD_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AD_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x03U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x02U, + .iTerminal = 0x00U + }, +#endif /* USE_USB_AD_MICPHONE */ + +#ifdef USE_USB_AD_SPEAKER + .speak_in_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_input_terminal), + .bDescriptorType = AD_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AD_CONTROL_INPUT_TERMINAL, + .bTerminalID = 0x04U, + .wTerminalType = 0x0101U, + .bAssocTerminal = 0x00U, + .bNrChannels = 0x02U, + .wChannelConfig = 0x0003U, + .iChannelNames = 0x00U, + .iTerminal = 0x00U + }, + + .speak_feature_unit = + { + .header = + { + .bLength = sizeof(usb_desc_mono_feature_unit), + .bDescriptorType = AD_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AD_CONTROL_FEATURE_UNIT, + .bUnitID = AD_OUT_STREAMING_CTRL, + .bSourceID = 0x04U, + .bControlSize = 0x01U, + .bmaControls0 = AD_CONTROL_MUTE | AD_CONTROL_VOLUME, + .bmaControls1 = 0x00U, + .iFeature = 0x00U + }, + + .speak_out_terminal = + { + .header = + { + .bLength = sizeof(usb_desc_output_terminal), + .bDescriptorType = AD_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AD_CONTROL_OUTPUT_TERMINAL, + .bTerminalID = 0x06U, + .wTerminalType = 0x0301U, + .bAssocTerminal = 0x00U, + .bSourceID = 0x05U, + .iTerminal = 0x00U + }, +#endif /* USE_USB_AD_SPEAKER */ + +#ifdef USE_USB_AD_MICPHONE + .mic_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AD_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AD_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AD_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AD_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .mic_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AD_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AD_STREAMING_GENERAL, + .bTerminalLink = 0x03U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .mic_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AD_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AD_STREAMING_FORMAT_TYPE, + .bFormatType = AD_FORMAT_TYPE_I, + .bNrChannels = MIC_IN_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = MIC_IN_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_MIC_FREQ, + .bSamFreq[1] = USBD_MIC_FREQ >> 8U, + .bSamFreq[2] = USBD_MIC_FREQ >> 16U + }, + + .mic_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AD_IN_EP, + .bmAttributes = USB_ENDPOINT_TYPE_ISOCHRONOUS, + .wMaxPacketSize = MIC_IN_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = 0x00U + }, + + .mic_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AD_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AD_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + }, +#endif /* USE_USB_AD_MICPHONE */ + +#ifdef USE_USB_AD_SPEAKER + .speak_std_as_itf_zeroband = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AD_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AD_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_std_as_itf_opera = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x02U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = AD_SUBCLASS_AUDIOSTREAMING, + .bInterfaceProtocol = AD_PROTOCOL_UNDEFINED, + .iInterface = 0x00U + }, + + .speak_as_itf = + { + .header = + { + .bLength = sizeof(usb_desc_AS_itf), + .bDescriptorType = AD_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AD_STREAMING_GENERAL, + .bTerminalLink = 0x04U, + .bDelay = 0x01U, + .wFormatTag = 0x0001U, + }, + + .speak_format_typeI = + { + .header = + { + .bLength = sizeof(usb_desc_format_type), + .bDescriptorType = AD_DESCTYPE_INTERFACE + }, + .bDescriptorSubtype = AD_STREAMING_FORMAT_TYPE, + .bFormatType = AD_FORMAT_TYPE_I, + .bNrChannels = SPEAKER_OUT_CHANNEL_NBR, + .bSubFrameSize = 0x02U, + .bBitResolution = SPEAKER_OUT_BIT_RESOLUTION, + .bSamFreqType = 0x01U, + .bSamFreq[0] = (uint8_t)USBD_SPEAKER_FREQ, + .bSamFreq[1] = USBD_SPEAKER_FREQ >> 8U, + .bSamFreq[2] = USBD_SPEAKER_FREQ >> 16U + }, + + .speak_std_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_std_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AD_OUT_EP, + .bmAttributes = USB_EP_ATTR_ISO | USB_EP_ATTR_ASYNC, + .wMaxPacketSize = SPEAKER_OUT_PACKET, + .bInterval = 0x01U, + .bRefresh = 0x00U, + .bSynchAddress = AD_FEEDBACK_IN_EP, + }, + + .speak_as_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_AS_ep), + .bDescriptorType = AD_DESCTYPE_ENDPOINT + }, + .bDescriptorSubtype = AD_ENDPOINT_GENERAL, + .bmAttributes = 0x00U, + .bLockDelayUnits = 0x00U, + .wLockDelay = 0x0000U, + }, + + .speak_feedback_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_FeedBack_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = AD_FEEDBACK_IN_EP, + .bmAttributes = USB_EP_ATTR_ISO | USB_EP_ATTR_ASYNC | USB_EP_ATTR_FEEDBACK, + .wMaxPacketSize = FEEDBACK_IN_PACKET, + .bInterval = 0x01U, + .Refresh = FEEDBACK_IN_INTERVAL, /* refresh every 32(2^5) ms */ + .bSynchAddress = 0x00U, + }, +#endif /* USE_USB_AD_SPEAKER */ +}; + +/* USB language ID descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'A', 'u', 'd', 'i', 'o'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +void *const usbd_audio_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +/* USB descriptor configure */ +usb_desc audio_desc = { + .dev_desc = (uint8_t *)&audio_dev_desc, + .config_desc = (uint8_t *)&audio_config_set, + .strings = usbd_audio_strings +}; + +/*! + \brief initialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_init (usb_dev *udev, uint8_t config_index) +{ + memset((void *)&audio_handler, 0, sizeof(usbd_audio_handler)); + +#ifdef USE_USB_AD_MICPHONE +{ + usb_desc_std_ep std_ep = audio_config_set.mic_std_endpoint; + + usb_desc_ep ep = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = std_ep.wMaxPacketSize, + .bInterval = std_ep.bInterval + }; + + /* initialize TX endpoint */ + usbd_ep_setup (udev, &ep); +} +#endif /* USE_USB_AD_MICPHONE */ + +#ifdef USE_USB_AD_SPEAKER +{ + audio_handler.isoc_out_rdptr = audio_handler.isoc_out_buff; + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + usb_desc_std_ep std_ep = audio_config_set.speak_std_endpoint; + + usb_desc_ep ep1 = { + .header = std_ep.header, + .bEndpointAddress = std_ep.bEndpointAddress, + .bmAttributes = std_ep.bmAttributes, + .wMaxPacketSize = SPEAKER_OUT_MAX_PACKET, + .bInterval = std_ep.bInterval + }; + + /* initialize RX endpoint */ + usbd_ep_setup (udev, &ep1); + + /* prepare out endpoint to receive next audio packet */ + usbd_ep_recev (udev, AD_OUT_EP, audio_handler.usb_rx_buffer, SPEAKER_OUT_MAX_PACKET); + + /* initialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_init(USBD_SPEAKER_FREQ, DEFAULT_VOLUME)) { + return USBD_FAIL; + } + + usb_desc_FeedBack_ep feedback_ep = audio_config_set.speak_feedback_endpoint; + + usb_desc_ep ep2 = { + .header = feedback_ep.header, + .bEndpointAddress = feedback_ep.bEndpointAddress, + .bmAttributes = feedback_ep.bmAttributes, + .wMaxPacketSize = feedback_ep.wMaxPacketSize, + .bInterval = feedback_ep.bInterval + }; + + /* initialize Tx endpoint */ + usbd_ep_setup (udev, &ep2); +} +#endif /* USE_USB_AD_SPEAKER */ + + return USBD_OK; +} + +/*! + \brief de-initialize the AUDIO device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_deinit (usb_dev *udev, uint8_t config_index) +{ +#ifdef USE_USB_AD_MICPHONE + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AD_IN_EP); +#endif /* USE_USB_AD_MICPHONE */ + +#ifdef USE_USB_AD_SPEAKER + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AD_OUT_EP); + + /* deinitialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_deinit()) { + return USBD_FAIL; + } + + /* deinitialize AUDIO endpoints */ + usbd_ep_clear(udev, AD_FEEDBACK_IN_EP); +#endif /* USE_USB_AD_SPEAKER */ + + return USBD_OK; +} + +/*! + \brief handle the AUDIO class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_req_handler (usb_dev *udev, usb_req *req) +{ + uint8_t status = REQ_NOTSUPP; + + usb_transc *transc_in = &udev->dev.transc_in[0]; + usb_transc *transc_out = &udev->dev.transc_out[0]; + + switch (req->bRequest) { + case AD_REQ_GET_CUR: + transc_in->xfer_buf = audio_handler.audioctl; + transc_in->remain_len = req->wLength; + + status = REQ_SUPP; + break; + + case AD_REQ_SET_CUR: + if (req->wLength) { + transc_out->xfer_buf = audio_handler.audioctl; + transc_out->remain_len = req->wLength; + + udev->dev.class_core->command = AD_REQ_SET_CUR; + + audio_handler.audioctl_len = req->wLength; + audio_handler.audioctl_unit = BYTE_HIGH(req->wIndex); + + status = REQ_SUPP; + } + break; + + case AD_REQ_GET_MIN: + *((uint16_t *)audio_handler.audioctl) = VOL_MIN; + transc_in->xfer_buf = audio_handler.audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AD_REQ_GET_MAX: + *((uint16_t *)audio_handler.audioctl) = VOL_MAX; + transc_in->xfer_buf = audio_handler.audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + case AD_REQ_GET_RES: + *((uint16_t *)audio_handler.audioctl) = VOL_RES; + transc_in->xfer_buf = audio_handler.audioctl; + transc_in->remain_len = req->wLength; + status = REQ_SUPP; + break; + + default: + break; + } + + return status; +} + +/*! + \brief handle the AUDIO set interface requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_set_intf(usb_dev *udev, usb_req *req) +{ + udev->dev.class_core->alter_set = req->wValue; + + if(0xFF != req->wValue){ + if (req->wValue != 0){ + /* deinit audio handler */ + memset((void *)&audio_handler, 0, sizeof(usbd_audio_handler)); + + audio_handler.play_flag = 0; + audio_handler.isoc_out_rdptr = audio_handler.isoc_out_buff; + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + /* feedback calculate sample freq */ + audio_handler.actual_freq = I2S_ACTUAL_SAM_FREQ(USBD_SPEAKER_FREQ); + get_feedback_fs_rate(audio_handler.actual_freq, audio_handler.feedback_freq); + + /* send feedback data of estimated frequence*/ + usbd_ep_send(udev, AD_FEEDBACK_IN_EP, audio_handler.feedback_freq, FEEDBACK_IN_PACKET); + } else { + /* stop audio output */ + audio_out_fops.audio_cmd(audio_handler.isoc_out_rdptr, SPEAKER_OUT_PACKET/2, AD_CMD_STOP); + + audio_handler.play_flag = 0; + audio_handler.isoc_out_rdptr = audio_handler.isoc_out_buff; + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + usbd_fifo_flush (udev, AD_IN_EP); + usbd_fifo_flush (udev, AD_FEEDBACK_IN_EP); + usbd_fifo_flush (udev, AD_OUT_EP); + } + } + + return 0; +} + +/*! + \brief handles the control transfer OUT callback + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_ctlx_out (usb_dev *udev) +{ +#ifdef USE_USB_AD_SPEAKER + /* handles audio control requests data */ + /* check if an audio_control request has been issued */ + if (AD_REQ_SET_CUR == udev->dev.class_core->command) { + /* in this driver, to simplify code, only SET_CUR request is managed */ + + /* check for which addressed unit the audio_control request has been issued */ + if (AD_OUT_STREAMING_CTRL == audio_handler.audioctl_unit) { + /* in this driver, to simplify code, only one unit is manage */ + + /* reset the audioctl_cmd variable to prevent re-entering this function */ + udev->dev.class_core->command = 0U; + + audio_handler.audioctl_len = 0U; + } + } +#endif /* USE_USB_AD_SPEAKER */ + + return USBD_OK; +} + +/*! + \brief handles the audio IN data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_in (usb_dev *udev, uint8_t ep_num) +{ +#ifdef USE_USB_AD_MICPHONE + if(ep_num == EP_ID(AD_IN_EP)){ + if(count_data < LENGTH_DATA){ + /* Prepare next buffer to be sent: dummy data */ + usbd_ep_send(udev, AD_IN_EP,(uint8_t*)&wavetestdata[count_data],MIC_IN_PACKET); + count_data += MIC_IN_PACKET; + } else { + usbd_ep_send(udev, AD_IN_EP,(uint8_t*)wavetestdata,MIC_IN_PACKET); + count_data = MIC_IN_PACKET; + } + } +#endif /* USE_USB_AD_MICPHONE */ + +#ifdef USE_USB_AD_SPEAKER + if(ep_num == EP_ID(AD_FEEDBACK_IN_EP)){ + /* calculate feedback actual freq */ + audio_handler.actual_freq = usbd_audio_spk_get_feedback(udev); + get_feedback_fs_rate(audio_handler.actual_freq, audio_handler.feedback_freq); + + usbd_ep_send(udev, AD_FEEDBACK_IN_EP, audio_handler.feedback_freq, FEEDBACK_IN_PACKET); + } +#endif /* USE_USB_AD_SPEAKER */ + + return USBD_OK; +} + +/*! + \brief handles the audio OUT data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_data_out (usb_dev *udev, uint8_t ep_num) +{ + uint16_t usb_rx_length, tail_len; + + /* get receive length */ + usb_rx_length = ((usb_core_driver *)udev)->dev.transc_out[ep_num].xfer_count; + + if(audio_handler.isoc_out_wrptr >= audio_handler.isoc_out_rdptr){ + audio_handler.buf_free_size = TOTAL_OUT_BUF_SIZE + audio_handler.isoc_out_rdptr - audio_handler.isoc_out_wrptr; + }else{ + audio_handler.buf_free_size = audio_handler.isoc_out_rdptr - audio_handler.isoc_out_wrptr; + } + + /* free buffer enough to save rx data */ + if(audio_handler.buf_free_size > usb_rx_length){ + if(audio_handler.isoc_out_wrptr >= audio_handler.isoc_out_rdptr){ + tail_len = audio_handler.isoc_out_buff + TOTAL_OUT_BUF_SIZE - audio_handler.isoc_out_wrptr; + + if(tail_len >= usb_rx_length){ + memcpy(audio_handler.isoc_out_wrptr, audio_handler.usb_rx_buffer, usb_rx_length); + + /* increment the buffer pointer */ + audio_handler.isoc_out_wrptr += usb_rx_length; + + /* increment the Buffer pointer or roll it back when all buffers are full */ + if(audio_handler.isoc_out_wrptr >= (audio_handler.isoc_out_buff + TOTAL_OUT_BUF_SIZE)){ + /* all buffers are full: roll back */ + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + } + }else{ + memcpy(audio_handler.isoc_out_wrptr, audio_handler.usb_rx_buffer, tail_len); + /* adjust write pointer */ + audio_handler.isoc_out_wrptr = audio_handler.isoc_out_buff; + + memcpy(audio_handler.isoc_out_wrptr, &audio_handler.usb_rx_buffer[tail_len], usb_rx_length - tail_len); + /* adjust write pointer */ + audio_handler.isoc_out_wrptr += usb_rx_length - tail_len; + } + }else{ + memcpy(audio_handler.isoc_out_wrptr, audio_handler.usb_rx_buffer, usb_rx_length); + + /* increment the buffer pointer */ + audio_handler.isoc_out_wrptr += usb_rx_length; + } + } + + /* Toggle the frame index */ + udev->dev.transc_out[ep_num].frame_num = (udev->dev.transc_out[ep_num].frame_num)? 0U:1U; + + /* prepare out endpoint to receive next audio packet */ + usbd_ep_recev (udev, AD_OUT_EP, audio_handler.usb_rx_buffer, SPEAKER_OUT_MAX_PACKET); + + if(audio_handler.isoc_out_wrptr >= audio_handler.isoc_out_rdptr){ + audio_handler.buf_free_size = TOTAL_OUT_BUF_SIZE + audio_handler.isoc_out_rdptr - audio_handler.isoc_out_wrptr; + }else{ + audio_handler.buf_free_size = audio_handler.isoc_out_rdptr - audio_handler.isoc_out_wrptr; + } + + if ((0U == audio_handler.play_flag) && (audio_handler.buf_free_size < TOTAL_OUT_BUF_SIZE/2)) { + /* enable start of streaming */ + audio_handler.play_flag = 1U; + + /* initialize the audio output hardware layer */ + if (USBD_OK != audio_out_fops.audio_cmd(audio_handler.isoc_out_rdptr, SPEAKER_OUT_MAX_PACKET/2, AD_CMD_PLAY)) { + return USBD_FAIL; + } + + audio_handler.dam_tx_len = SPEAKER_OUT_MAX_PACKET; + } + + return USBD_OK; +} + +/*! + \brief handles the SOF event (data buffer update and synchronization) + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_sof (usb_dev *udev) +{ + return USBD_OK; +} + +/*! + \brief handles the audio ISO IN Incomplete event + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_iso_in_incomplete (usb_dev *udev) +{ + (void)usb_txfifo_flush (&udev->regs, EP_ID(AD_FEEDBACK_IN_EP)); + + audio_handler.actual_freq = usbd_audio_spk_get_feedback(udev); + get_feedback_fs_rate(audio_handler.actual_freq, audio_handler.feedback_freq); + + /* send feedback data of estimated frequence*/ + usbd_ep_send(udev, AD_FEEDBACK_IN_EP, audio_handler.feedback_freq, FEEDBACK_IN_PACKET); + + return USBD_OK; +} + +/*! + \brief handles the audio ISO OUT Incomplete event + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t audio_iso_out_incomplete (usb_dev *udev) +{ + return USBD_OK; +} + +/*! + \brief calculate feedback sample frequency + \param[in] udev: pointer to USB device instance + \param[out] none + \retval feedback frequency value +*/ +static uint32_t usbd_audio_spk_get_feedback(usb_dev *udev) +{ + static uint32_t fb_freq; + + /* calculate buffer free size */ + if(audio_handler.isoc_out_wrptr >= audio_handler.isoc_out_rdptr){ + audio_handler.buf_free_size = TOTAL_OUT_BUF_SIZE + audio_handler.isoc_out_rdptr - audio_handler.isoc_out_wrptr; + }else{ + audio_handler.buf_free_size = audio_handler.isoc_out_rdptr - audio_handler.isoc_out_wrptr; + } + + /* calculate feedback frequency */ + if(audio_handler.buf_free_size <= (TOTAL_OUT_BUF_SIZE/4)){ + fb_freq = I2S_ACTUAL_SAM_FREQ(USBD_SPEAKER_FREQ) - FEEDBACK_FREQ_OFFSET; + }else if(audio_handler.buf_free_size >= (TOTAL_OUT_BUF_SIZE*3/4)){ + fb_freq = I2S_ACTUAL_SAM_FREQ(USBD_SPEAKER_FREQ) + FEEDBACK_FREQ_OFFSET; + }else{ + fb_freq = I2S_ACTUAL_SAM_FREQ(USBD_SPEAKER_FREQ); + } + + return fb_freq; +} + +/*! + \brief get feedback value from rate in USB full speed + \param[in] rate: sample frequence + \param[in] buf: pointer to result buffer + \param[out] none + \retval USB device operation status +*/ +static void get_feedback_fs_rate(uint32_t rate, uint8_t *buf) +{ + rate = ((rate / 1000) << 14) | ((rate % 1000) << 4); + + buf[0] = rate; + buf[1] = rate >> 8; + buf[2] = rate >> 16; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Source/audio_out_itf.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Source/audio_out_itf.c new file mode 100644 index 00000000..68d8842b --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/audio/Source/audio_out_itf.c @@ -0,0 +1,168 @@ +/*! + \file audio_out_itf.c + \brief audio OUT (playback) interface functions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "audio_core.h" +#include "audio_out_itf.h" + +/* local function prototypes ('static') */ +static uint8_t init (uint32_t audio_freq, uint32_t volume); +static uint8_t deinit (void); +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd); + +/* local variable defines */ +static uint8_t audio_state = AD_STATE_INACTIVE; + +audio_fops_struct audio_out_fops = +{ + .audio_init = init, + .audio_deinit = deinit, + .audio_cmd = audio_cmd, +}; + +/*! + \brief initialize and configures all required resources + \param[in] audio_freq: statrt_up audio frequency + \param[in] volume: start_up volume to be set + \param[out] none + \retval AD_OK if all operations succeed, otherwise, AD_FAIL. +*/ +static uint8_t init (uint32_t audio_freq, uint32_t volume) +{ + static uint32_t initialized = 0U; + + /* check if the low layer has already been initialized */ + if (0U == initialized) { + /* initialize GPIO */ + codec_gpio_init(); + + /* initialize i2s */ + codec_audio_interface_init(audio_freq); + + /* initialize DMA */ + codec_i2s_dma_init(); + + /* prevent reinitializing the interface again */ + initialized = 1U; + } + + /* update the audio state machine */ + audio_state = AD_STATE_ACTIVE; + + return AD_OK; +} + +/*! + \brief free all resources used by low layer and stops audio-play function + \param[in] none + \param[out] none + \retval AD_OK if all operations succeed, otherwise, AD_FAIL. +*/ +static uint8_t deinit (void) +{ + /* update the audio state machine */ + audio_state = AD_STATE_INACTIVE; + + return AD_OK; +} + +/*! + \brief play, stop, pause or resume current file + \param[in] pbuf: address from which file should be played + \param[in] size: size of the current buffer/file + \param[in] cmd: command to be executed, can be: + \arg AD_CMD_PLAY + \arg AD_CMD_PAUSE + \arg AD_CMD_RESUME + \arg AD_CMD_STOP + \param[out] none + \retval AD_OK if all operations succeed, otherwise, AD_FAIL. +*/ +static uint8_t audio_cmd (uint8_t* pbuf, uint32_t size, uint8_t cmd) +{ + /* check the current state */ + if ((AD_STATE_INACTIVE == audio_state) || (AD_STATE_ERROR == audio_state)) { + audio_state = AD_STATE_ERROR; + + return AD_FAIL; + } + + switch (cmd) { + /* process the play command */ + case AD_CMD_PLAY: + /* if current state is active or stopped */ + if ((AD_STATE_ACTIVE == audio_state) || \ + (AD_STATE_STOPPED == audio_state) || \ + (AD_STATE_PLAYING == audio_state)) { + audio_play((uint32_t)pbuf, size); + audio_state = AD_STATE_PLAYING; + + return AD_OK; + } else if (AD_STATE_PAUSED == audio_state) { + audio_pause_resume(AD_RESUME, (uint32_t)pbuf, (size/2)); + audio_state = AD_STATE_PLAYING; + + return AD_OK; + } else { + return AD_FAIL; + } + + /* process the stop command */ + case AD_CMD_STOP: + if (AD_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AD_FAIL; + } else { + audio_stop(); + audio_state = AD_STATE_STOPPED; + + return AD_OK; + } + + /* process the pause command */ + case AD_CMD_PAUSE: + if (AD_STATE_PLAYING != audio_state) { + /* unsupported command */ + return AD_FAIL; + } else { + audio_pause_resume(AD_PAUSE, (uint32_t)pbuf, (size/2)); + audio_state = AD_STATE_PAUSED; + + return AD_OK; + } + + /* unsupported command */ + default: + return AD_FAIL; + } +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h new file mode 100644 index 00000000..493eb669 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/cdc/Include/cdc_acm_core.h @@ -0,0 +1,66 @@ +/*! + \file cdc_acm_core.h + \brief the header file of CDC ACM driver + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CDC_ACM_CORE_H +#define __CDC_ACM_CORE_H + +#include "usbd_enum.h" +#include "usb_cdc.h" + +#define USB_CDC_RX_LEN USB_CDC_DATA_PACKET_SIZE + +typedef struct { + uint8_t packet_sent; + uint8_t packet_receive; + + uint8_t data[USB_CDC_RX_LEN]; + uint8_t cmd[USB_CDC_CMD_PACKET_SIZE]; + + uint32_t receive_length; + + acm_line line_coding; +} usb_cdc_handler; + +extern usb_desc cdc_desc; +extern usb_class_core cdc_class; + +/* function declarations */ +/* check CDC ACM is ready for data transfer */ +uint8_t cdc_acm_check_ready(usb_dev *udev); +/* send CDC ACM data */ +void cdc_acm_data_send(usb_dev *udev); +/* receive CDC ACM data */ +void cdc_acm_data_receive(usb_dev *udev); + +#endif /* __CDC_ACM_CORE_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c new file mode 100644 index 00000000..6904c850 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/cdc/Source/cdc_acm_core.c @@ -0,0 +1,529 @@ +/*! + \file cdc_acm_core.c + \brief CDC ACM driver + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "cdc_acm_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x018AU + +/* note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev cdc_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = USB_CLASS_CDC, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_cdc_desc_config_set cdc_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG, + }, + .wTotalLength = USB_CDC_ACM_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x02U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .cmd_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 0x00U + }, + + .cdc_header = + { + .header = + { + .bLength = sizeof(usb_desc_header_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x00U, + .bcdCDC = 0x0110U + }, + + .cdc_call_managment = + { + .header = + { + .bLength = sizeof(usb_desc_call_managment_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x01U, + .bmCapabilities = 0x00U, + .bDataInterface = 0x01U + }, + + .cdc_acm = + { + .header = + { + .bLength = sizeof(usb_desc_acm_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x02U, + .bmCapabilities = 0x02U, + }, + + .cdc_union = + { + .header = + { + .bLength = sizeof(usb_desc_union_func), + .bDescriptorType = USB_DESCTYPE_CS_INTERFACE + }, + .bDescriptorSubtype = 0x06U, + .bMasterInterface = 0x00U, + .bSlaveInterface0 = 0x01U, + }, + + .cdc_cmd_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_CMD_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = USB_CDC_CMD_PACKET_SIZE, + .bInterval = 0x0AU + }, + + .cdc_data_interface = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF, + }, + .bInterfaceNumber = 0x01U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = USB_CDC_PROTOCOL_NONE, + .iInterface = 0x00U + }, + + .cdc_out_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP, + }, + .bEndpointAddress = CDC_DATA_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + }, + + .cdc_in_endpoint = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CDC_DATA_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = USB_CDC_DATA_PACKET_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'D', 'C', '_', 'A', 'C', 'M'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_cdc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *) &usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *) &manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *) &product_string, + [STR_IDX_SERIAL] = (uint8_t *) &serial_string +}; + +usb_desc cdc_desc = +{ + .dev_desc = (uint8_t *) &cdc_dev_desc, + .config_desc = (uint8_t *) &cdc_config_desc, + .strings = usbd_cdc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req); +static uint8_t cdc_acm_ctlx_out (usb_dev *udev); +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num); +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num); + +/* USB CDC device class callbacks structure */ +usb_class_core cdc_class = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = cdc_acm_init, + .deinit = cdc_acm_deinit, + .req_proc = cdc_acm_req, + .ctlx_out = cdc_acm_ctlx_out, + .data_in = cdc_acm_in, + .data_out = cdc_acm_out +}; + +/*! + \brief check CDC ACM is ready for data transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval 0 if CDC is ready, 5 else +*/ +uint8_t cdc_acm_check_ready(usb_dev *udev) +{ + if (udev->dev.class_data[CDC_COM_INTERFACE] != NULL) { + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((1U == cdc->packet_receive) && (1U == cdc->packet_sent)) { + return 0U; + } + } + + return 1U; +} + +/*! + \brief send CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_send (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (0U != cdc->receive_length) { + cdc->packet_sent = 0U; + + usbd_ep_send (udev, CDC_DATA_IN_EP, (uint8_t*)(cdc->data), cdc->receive_length); + + cdc->receive_length = 0U; + } +} + +/*! + \brief receive CDC ACM data + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +void cdc_acm_data_receive (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 0U; + cdc->packet_sent = 0U; + + usbd_ep_recev (udev, CDC_DATA_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_DATA_PACKET_SIZE); +} + +/*! + \brief initialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index) +{ + static usb_cdc_handler cdc_handler; + + /* initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_in_endpoint)); + + /* initialize the data Rx endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_out_endpoint)); + + /* initialize the command Tx endpoint */ + usbd_ep_setup (udev, &(cdc_config_desc.cdc_cmd_endpoint)); + + /* initialize CDC handler structure */ + cdc_handler.packet_receive = 1U; + cdc_handler.packet_sent = 1U; + cdc_handler.receive_length = 0U; + + cdc_handler.line_coding = (acm_line){ + .dwDTERate = 115200U, + .bCharFormat = 0U, + .bParityType = 0U, + .bDataBits = 0x08U + }; + + udev->dev.class_data[CDC_COM_INTERFACE] = (void *)&cdc_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the CDC ACM device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data Tx/Rx endpoint */ + usbd_ep_clear (udev, CDC_DATA_IN_EP); + usbd_ep_clear (udev, CDC_DATA_OUT_EP); + + /* deinitialize the command Tx endpoint */ + usbd_ep_clear (udev, CDC_CMD_EP); + + return USBD_OK; +} + +/*! + \brief handle the CDC ACM class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + usb_transc *transc = NULL; + + switch (req->bRequest) { + case SEND_ENCAPSULATED_COMMAND: + /* no operation for this driver */ + break; + + case GET_ENCAPSULATED_RESPONSE: + /* no operation for this driver */ + break; + + case SET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case GET_COMM_FEATURE: + /* no operation for this driver */ + break; + + case CLEAR_COMM_FEATURE: + /* no operation for this driver */ + break; + + case SET_LINE_CODING: + transc = &udev->dev.transc_out[0]; + + /* set the value of the current command to be processed */ + udev->dev.class_core->alter_set = req->bRequest; + + /* enable EP0 prepare to receive command data packet */ + transc->remain_len = req->wLength; + transc->xfer_buf = cdc->cmd; + break; + + case GET_LINE_CODING: + transc = &udev->dev.transc_in[0]; + + cdc->cmd[0] = (uint8_t)(cdc->line_coding.dwDTERate); + cdc->cmd[1] = (uint8_t)(cdc->line_coding.dwDTERate >> 8); + cdc->cmd[2] = (uint8_t)(cdc->line_coding.dwDTERate >> 16); + cdc->cmd[3] = (uint8_t)(cdc->line_coding.dwDTERate >> 24); + cdc->cmd[4] = cdc->line_coding.bCharFormat; + cdc->cmd[5] = cdc->line_coding.bParityType; + cdc->cmd[6] = cdc->line_coding.bDataBits; + + transc->xfer_buf = cdc->cmd; + transc->remain_len = 7U; + break; + + case SET_CONTROL_LINE_STATE: + /* no operation for this driver */ + break; + + case SEND_BREAK: + /* no operation for this driver */ + break; + + default: + break; + } + + return USBD_OK; +} + +/*! + \brief command data received on control endpoint + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_ctlx_out (usb_dev *udev) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if (udev->dev.class_core->alter_set != NO_CMD) { + /* process the command data */ + cdc->line_coding.dwDTERate = (uint32_t)((uint32_t)cdc->cmd[0] | + ((uint32_t)cdc->cmd[1] << 8U) | + ((uint32_t)cdc->cmd[2] << 16U) | + ((uint32_t)cdc->cmd[3] << 24U)); + + cdc->line_coding.bCharFormat = cdc->cmd[4]; + cdc->line_coding.bParityType = cdc->cmd[5]; + cdc->line_coding.bDataBits = cdc->cmd[6]; + + udev->dev.class_core->alter_set = NO_CMD; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data in + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_num)]; + + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + if ((0U == transc->xfer_len % transc->max_len) && (0U != transc->xfer_len)) { + usbd_ep_send (udev, ep_num, NULL, 0U); + } else { + cdc->packet_sent = 1U; + } + + return USBD_OK; +} + +/*! + \brief handle CDC ACM data out + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num) +{ + usb_cdc_handler *cdc = (usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE]; + + cdc->packet_receive = 1U; + cdc->receive_length = ((usb_core_driver *)udev)->dev.transc_out[ep_num].xfer_count; + + return USBD_OK; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_core.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_core.h new file mode 100644 index 00000000..469e1e1d --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_core.h @@ -0,0 +1,175 @@ +/*! + \file dfu_core.h + \brief the header file of USB DFU device class core functions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_CORE_H +#define __DFU_CORE_H + +#include "usbd_enum.h" + +/* DFU class code */ +#define USB_DFU_CLASS 0xFEU + +/* DFU subclass code */ +#define USB_DFU_SUBCLASS_UPGRADE 0x01U + +/* DFU protocol code */ +#define USB_DFU_PROTOCL_RUNTIME 0x01U +#define USB_DFU_PROTOCL_DFU 0x02U + +/* manifestation state */ +#define MANIFEST_COMPLETE 0x00U +#define MANIFEST_IN_PROGRESS 0x01U + +/* DFU attributes code */ +#define USB_DFU_CAN_DOWNLOAD 0x01U +#define USB_DFU_CAN_UPLOAD 0x02U +#define USB_DFU_MANIFEST_TOLERANT 0x04U +#define USB_DFU_WILL_DETACH 0x08U + +/* special commands with download request */ +#define GET_COMMANDS 0x00U +#define SET_ADDRESS_POINTER 0x21U +#define ERASE 0x41U + +/* memory operation command */ +#define CMD_ERASE 0U +#define CMD_WRITE 1U + +#define _BYTE1(x) (uint8_t)((x) & 0xFFU) /*!< addressing cycle 1st byte */ +#define _BYTE2(x) (uint8_t)(((x) & 0xFF00U) >> 8U) /*!< addressing cycle 2nd byte */ +#define _BYTE3(x) (uint8_t)(((x) & 0xFF0000U) >> 16U) /*!< addressing cycle 3rd byte */ + +#define FLASH_ERASE_TIMEOUT 60U +#define FLASH_WRITE_TIMEOUT 80U + +/* bit detach capable = bit 3 in bmAttributes field */ +#define DFU_DETACH_MASK (uint8_t)(0x10U) + +#define DFU_DESC_TYPE 0x21U + +/* DFU device state defines */ +typedef enum { + STATE_APP_IDLE = 0x00U, + STATE_APP_DETACH, + STATE_DFU_IDLE, + STATE_DFU_DNLOAD_SYNC, + STATE_DFU_DNBUSY, + STATE_DFU_DNLOAD_IDLE, + STATE_DFU_MANIFEST_SYNC, + STATE_DFU_MANIFEST, + STATE_DFU_MANIFEST_WAIT_RESET, + STATE_DFU_UPLOAD_IDLE, + STATE_DFU_ERROR +} dfu_state; + +/* DFU device status defines */ +typedef enum { + STATUS_OK = 0x00U, + STATUS_ERR_TARGET, + STATUS_ERR_FILE, + STATUS_ERR_WRITE, + STATUS_ERR_ERASE, + STATUS_ERR_CHECK_ERASED, + STATUS_ERR_PROG, + STATUS_ERR_VERIFY, + STATUS_ERR_ADDRESS, + STATUS_ERR_NOTDONE, + STATUS_ERR_FIRMWARE, + STATUS_ERR_VENDOR, + STATUS_ERR_USBR, + STATUS_ERR_POR, + STATUS_ERR_UNKNOWN, + STATUS_ERR_STALLEDPKT +} dfu_status; + +/* DFU class-specific requests */ +typedef enum { + DFU_DETACH = 0U, + DFU_DNLOAD, + DFU_UPLOAD, + DFU_GETSTATUS, + DFU_CLRSTATUS, + DFU_GETSTATE, + DFU_ABORT, + DFU_REQ_MAX +} dfu_requests; + +#pragma pack(1) + +/* USB DFU function descriptor structure */ +typedef struct +{ + usb_desc_header header; /*!< descriptor header, including type and size */ + uint8_t bmAttributes; /*!< DFU attributes */ + uint16_t wDetachTimeOut; /*!< time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request. If */ + uint16_t wTransferSize; /*!< maximum number of bytes that the device can accept per control-write transaction */ + uint16_t bcdDFUVersion; /*!< numeric expression identifying the version of the DFU specification release. */ +} usb_desc_dfu_func; + +#pragma pack() + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf dfu_itf0; + usb_desc_itf dfu_itf1; + usb_desc_itf dfu_itf2; + usb_desc_dfu_func dfu_func; +} usb_dfu_desc_config_set; + +/* USB DFU handler structure */ +typedef struct +{ + uint8_t bStatus; + uint8_t bwPollTimeout0; + uint8_t bwPollTimeout1; + uint8_t bwPollTimeout2; + uint8_t bState; + uint8_t iString; + + uint8_t manifest_state; + uint32_t data_len; + uint16_t block_num; + uint32_t base_addr; + + uint8_t buf[TRANSFER_SIZE]; +} usbd_dfu_handler; + +typedef void (*app_func) (void); + +extern usb_desc dfu_desc; +extern usb_class_core dfu_class; + +#endif /* DFU_CORE_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_mem.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_mem.h new file mode 100644 index 00000000..39e46d5a --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Include/dfu_mem.h @@ -0,0 +1,83 @@ +/*! + \file dfu_mem.h + \brief USB DFU device media access layer header file + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DFU_MEM_H +#define __DFU_MEM_H + +#include "usb_conf.h" + +typedef struct _dfu_mem_prop +{ + const uint8_t* pstr_desc; + + uint8_t (*mem_init)(void); + uint8_t (*mem_deinit)(void); + uint8_t (*mem_erase)(uint32_t addr); + uint8_t (*mem_write)(uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t *(*mem_read)(uint8_t *buf, uint32_t addr, uint32_t len); + uint8_t (*mem_checkaddr)(uint32_t addr); + + const uint32_t erase_timeout; + const uint32_t write_timeout; +} dfu_mem_prop; + +typedef enum +{ + MEM_OK = 0, + MEM_FAIL +} mem_status; + +#define _1ST_BYTE(x) (uint8_t)((x) & 0xFF) /*!< addressing cycle 1st byte */ +#define _2ND_BYTE(x) (uint8_t)(((x) & 0xFF00) >> 8) /*!< addressing cycle 2nd byte */ +#define _3RD_BYTE(x) (uint8_t)(((x) & 0xFF0000) >> 16) /*!< addressing cycle 3rd byte */ + +#define POLLING_TIMEOUT_SET(x) buffer[0] = _1ST_BYTE(x);\ + buffer[1] = _2ND_BYTE(x);\ + buffer[2] = _3RD_BYTE(x); + +/* function declarations */ +/* initialize the memory media on the GD32 */ +uint8_t dfu_mem_init(void); +/* deinitialize the memory media on the GD32 */ +uint8_t dfu_mem_deinit(void); +/* erase a memory sector */ +uint8_t dfu_mem_erase(uint32_t addr); +/* write data to sectors of memory */ +uint8_t dfu_mem_write(uint8_t *buf, uint32_t addr, uint32_t len); +/* read data from sectors of memory */ +uint8_t* dfu_mem_read(uint8_t *buf, uint32_t addr, uint32_t len); +/* get the status of a given memory and store in buffer */ +uint8_t dfu_mem_getstatus(uint32_t addr, uint8_t cmd, uint8_t *buffer); + +#endif /* __DFU_MEM_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_core.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_core.c new file mode 100644 index 00000000..44b73a13 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_core.c @@ -0,0 +1,733 @@ +/*! + \file dfu_core.c + \brief USB DFU device class core functions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_core.h" +#include "dfu_mem.h" +#include "drv_usb_hw.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0189U + +/* local function prototypes ('static') */ +static uint8_t dfu_init(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_deinit(usb_dev *udev, uint8_t config_index); +static uint8_t dfu_req_handler(usb_dev *udev, usb_req *req); +static uint8_t dfu_ctlx_in(usb_dev *udev); + +static void dfu_mode_leave(usb_dev *udev); +static uint8_t dfu_getstatus_complete (usb_dev *udev); + +/* DFU requests management functions */ +static void dfu_detach(usb_dev *udev, usb_req *req); +static void dfu_dnload(usb_dev *udev, usb_req *req); +static void dfu_upload(usb_dev *udev, usb_req *req); +static void dfu_getstatus(usb_dev *udev, usb_req *req); +static void dfu_clrstatus(usb_dev *udev, usb_req *req); +static void dfu_getstate(usb_dev *udev, usb_req *req); +static void dfu_abort(usb_dev *udev, usb_req *req); + +static void string_to_unicode (uint8_t *str, uint16_t *pbuf); + +static void (*dfu_request_process[])(usb_dev *udev, usb_req *req) = +{ + [DFU_DETACH] = dfu_detach, + [DFU_DNLOAD] = dfu_dnload, + [DFU_UPLOAD] = dfu_upload, + [DFU_GETSTATUS] = dfu_getstatus, + [DFU_CLRSTATUS] = dfu_clrstatus, + [DFU_GETSTATE] = dfu_getstate, + [DFU_ABORT] = dfu_abort +}; + +/* note:it should use the c99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev dfu_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +const usb_dfu_desc_config_set dfu_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = sizeof(usb_dfu_desc_config_set), + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .dfu_itf0 = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCL_DFU, + .iInterface = STR_IDX_ALT_ITF0 + }, + + .dfu_itf1 = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x01U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCL_DFU, + .iInterface = STR_IDX_ALT_ITF1 + }, + + .dfu_itf2 = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x02U, + .bNumEndpoints = 0x00U, + .bInterfaceClass = USB_DFU_CLASS, + .bInterfaceSubClass = USB_DFU_SUBCLASS_UPGRADE, + .bInterfaceProtocol = USB_DFU_PROTOCL_DFU, + .iInterface = STR_IDX_ALT_ITF2 + }, + + .dfu_func= + { + .header = + { + .bLength = sizeof(usb_desc_dfu_func), + .bDescriptorType = DFU_DESC_TYPE + }, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeOut = 0x00FFU, + .wTransferSize = TRANSFER_SIZE, + .bcdDFUVersion = 0x0110U, + }, +}; + +/* USB language ID descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'D', 'F', 'U'} +}; + +/* USB serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB configure string */ +static const usb_desc_str config_string = +{ + .header = + { + .bLength = USB_STRING_LEN(15U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', ' ', 'U', 'S', 'B', ' ', 'C', 'O', 'N', 'F', 'I', 'G'} +}; + +/* alternate interface 0 string */ +static usb_desc_str interface_string0 = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + }, +}; + +/* alternate interface 1 string */ +static usb_desc_str interface_string1 = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + }, +}; + +/* alternate interface 2 string */ +static usb_desc_str interface_string2 = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + }, +}; + +void *const usbd_dfu_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string, + [STR_IDX_CONFIG] = (uint8_t *)&config_string, + [STR_IDX_ALT_ITF0] = (uint8_t *)&interface_string0, + [STR_IDX_ALT_ITF1] = (uint8_t *)&interface_string1, + [STR_IDX_ALT_ITF2] = (uint8_t *)&interface_string2, +}; + +usb_desc dfu_desc = { + .dev_desc = (uint8_t *)&dfu_dev_desc, + .config_desc = (uint8_t *)&dfu_config_desc, + .strings = usbd_dfu_strings +}; + +usb_class_core dfu_class = { + .init = dfu_init, + .deinit = dfu_deinit, + .req_proc = dfu_req_handler, + .ctlx_in = dfu_ctlx_in +}; + +/*! + \brief initialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_init (usb_dev *udev, uint8_t config_index) +{ + static usbd_dfu_handler dfu_handler; + + /* unlock the internal flash */ + dfu_mem_init(); + + memset((void *)&dfu_handler, 0, sizeof(usbd_dfu_handler)); + + dfu_handler.manifest_state = MANIFEST_COMPLETE; + dfu_handler.bState = STATE_DFU_IDLE; + dfu_handler.bStatus = STATUS_OK; + + udev->dev.class_data[USBD_DFU_INTERFACE] = (void *)&dfu_handler; + + /* create interface string */ + string_to_unicode((uint8_t *)dfu_inter_flash_cb.pstr_desc, udev->dev.desc->strings[STR_IDX_ALT_ITF0]); + string_to_unicode((uint8_t *)dfu_nor_flash_cb.pstr_desc, udev->dev.desc->strings[STR_IDX_ALT_ITF1]); + string_to_unicode((uint8_t *)dfu_nand_flash_cb.pstr_desc, udev->dev.desc->strings[STR_IDX_ALT_ITF2]); + + return USBD_OK; +} + +/*! + \brief deinitialize the DFU device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_deinit (usb_dev *udev, uint8_t config_index) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + /* restore device default state */ + memset(udev->dev.class_data[USBD_DFU_INTERFACE], 0, sizeof(usbd_dfu_handler)); + + dfu->bState = STATE_DFU_IDLE; + dfu->bStatus = STATUS_OK; + + /* deinit the memory */ + dfu_mem_deinit(); + + return USBD_OK; +} + +/*! + \brief handle the DFU class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_req_handler (usb_dev *udev, usb_req *req) +{ + if (req->bRequest < DFU_REQ_MAX) { + dfu_request_process[req->bRequest](udev, req); + } else { + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data stage + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status +*/ +static uint8_t dfu_ctlx_in (usb_dev *udev) +{ + dfu_getstatus_complete(udev); + + return USBD_OK; +} + +/*! + \brief leave DFU mode and reset device to jump to user loaded code + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void dfu_mode_leave (usb_dev *udev) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + dfu->manifest_state = MANIFEST_COMPLETE; + + if (dfu_config_desc.dfu_func.bmAttributes & 0x04U) { + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } else { + dfu->bState = STATE_DFU_MANIFEST_WAIT_RESET; + + /* deinit the memory */ + dfu_mem_deinit(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); + } +} + +/*! + \brief handle data IN stage in control endpoint 0 + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation status + */ +static uint8_t dfu_getstatus_complete (usb_dev *udev) +{ + uint32_t addr; + + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_DNBUSY == dfu->bState) { + /* decode the special command */ + if (0U == dfu->block_num) { + if (1U == dfu->data_len){ + if (GET_COMMANDS == dfu->buf[0]) { + /* no operation */ + } + } else if (5U == dfu->data_len) { + if (SET_ADDRESS_POINTER == dfu->buf[0]) { + /* set flash operation address */ + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + } else if (ERASE == dfu->buf[0]) { + dfu->base_addr = *(uint32_t *)(dfu->buf + 1U); + + dfu_mem_erase(dfu->base_addr); + } else { + /* no operation */ + } + } else { + /* no operation */ + } + } else if (dfu->block_num > 1U) { /* regular download command */ + /* decode the required address */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + dfu_mem_write (dfu->buf, addr, dfu->data_len); + + dfu->block_num = 0U; + } else { + /* no operation */ + } + + dfu->data_len = 0U; + + /* update the device state and poll timeout */ + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + return USBD_OK; + } else if (dfu->bState == STATE_DFU_MANIFEST) { /* manifestation in progress */ + /* start leaving DFU mode */ + dfu_mode_leave(udev); + } else { + /* no operation */ + } + + return USBD_OK; +} + +/*! + \brief handle the DFU_DETACH request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none. +*/ +static void dfu_detach(usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } + + /* check the detach capability in the DFU functional descriptor */ + if (dfu_config_desc.dfu_func.wDetachTimeOut & DFU_DETACH_MASK) { + usbd_disconnect (udev); + + usbd_connect (udev); + } else { + /* wait for the period of time specified in detach request */ + usb_mdelay (4U); + } +} + +/*! + \brief handle the DFU_DNLOAD request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_dnload(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_IDLE: + if (req->wLength > 0U) { + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + dfu->bState = STATE_DFU_DNLOAD_SYNC; + + transc->remain_len = dfu->data_len; + transc->xfer_buf = dfu->buf; + } else { + dfu->manifest_state = MANIFEST_IN_PROGRESS; + dfu->bState = STATE_DFU_MANIFEST_SYNC; + } + break; + + default: + break; + } +} + +/*! + \brief handles the DFU UPLOAD request. + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_upload (usb_dev *udev, usb_req *req) +{ + uint8_t *phy_addr = NULL; + uint32_t addr = 0U; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + usb_transc *transc = &udev->dev.transc_in[0]; + + if(req->wLength <= 0U) { + dfu->bState = STATE_DFU_IDLE; + return; + } + + switch (dfu->bState) { + case STATE_DFU_IDLE: + case STATE_DFU_UPLOAD_IDLE: + /* update the global length and block number */ + dfu->block_num = req->wValue; + dfu->data_len = req->wLength; + + /* DFU get command */ + if (0U == dfu->block_num) { + /* update the state machine */ + dfu->bState = (dfu->data_len > 3U) ? STATE_DFU_IDLE : STATE_DFU_UPLOAD_IDLE; + + /* store the values of all supported commands */ + dfu->buf[0] = GET_COMMANDS; + dfu->buf[1] = SET_ADDRESS_POINTER; + dfu->buf[2] = ERASE; + + /* send the status data over EP0 */ + transc->xfer_buf = &(dfu->buf[0]); + transc->remain_len = 3U; + } else if (dfu->block_num > 1U) { + dfu->bState = STATE_DFU_UPLOAD_IDLE; + + /* change is accelerated */ + addr = (dfu->block_num - 2U) * TRANSFER_SIZE + dfu->base_addr; + + /* return the physical address where data are stored */ + phy_addr = dfu_mem_read (dfu->buf, addr, dfu->data_len); + + /* send the status data over EP0 */ + transc->xfer_buf = phy_addr; + transc->remain_len = dfu->data_len; + } else { + dfu->bState = STATUS_ERR_STALLEDPKT; + } + break; + + default: + dfu->data_len = 0U; + dfu->block_num = 0U; + break; + } +} + +/*! + \brief handle the DFU_GETSTATUS request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstatus (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState) { + case STATE_DFU_DNLOAD_SYNC: + if (0U != dfu->data_len) { + dfu->bState = STATE_DFU_DNBUSY; + + if (0U == dfu->block_num) { + if (ERASE == dfu->buf[0]) { + dfu_mem_getstatus (dfu->base_addr, CMD_ERASE, (uint8_t *)&dfu->bwPollTimeout0); + } else { + dfu_mem_getstatus (dfu->base_addr, CMD_WRITE, (uint8_t *)&dfu->bwPollTimeout0); + } + } + } else { + dfu->bState = STATE_DFU_DNLOAD_IDLE; + } + break; + + case STATE_DFU_MANIFEST_SYNC: + if (MANIFEST_IN_PROGRESS == dfu->manifest_state) { + dfu->bState = STATE_DFU_MANIFEST; + dfu->bwPollTimeout0 = 1U; + } else if ((MANIFEST_COMPLETE == dfu->manifest_state) && \ + (dfu_config_desc.dfu_func.bmAttributes & 0x04U)){ + dfu->bState = STATE_DFU_IDLE; + dfu->bwPollTimeout0 = 0U; + } else { + /* no operation */ + } + break; + + default: + break; + } + + /* send the status data of DFU interface to host over EP0 */ + transc->xfer_buf = (uint8_t *)&(dfu->bStatus); + transc->remain_len = 6U; +} + +/*! + \brief handle the DFU_CLRSTATUS request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_clrstatus (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + if (STATE_DFU_ERROR == dfu->bState) { + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + } else { + /* state error */ + dfu->bStatus = STATUS_ERR_UNKNOWN; + dfu->bState = STATE_DFU_ERROR; + } + + dfu->iString = 0U; /* iString: index = 0 */ +} + +/*! + \brief handle the DFU_GETSTATE request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_getstate (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + /* send the current state of the DFU interface to host */ + transc->xfer_buf = &(dfu->bState); + transc->remain_len = 1U; +} + +/*! + \brief handle the DFU_ABORT request + \param[in] udev: pointer to USB device instance + \param[in] req: DFU class request + \param[out] none + \retval none +*/ +static void dfu_abort (usb_dev *udev, usb_req *req) +{ + usbd_dfu_handler *dfu = (usbd_dfu_handler *)udev->dev.class_data[USBD_DFU_INTERFACE]; + + switch (dfu->bState){ + case STATE_DFU_IDLE: + case STATE_DFU_DNLOAD_SYNC: + case STATE_DFU_DNLOAD_IDLE: + case STATE_DFU_MANIFEST_SYNC: + case STATE_DFU_UPLOAD_IDLE: + dfu->bStatus = STATUS_OK; + dfu->bState = STATE_DFU_IDLE; + dfu->iString = 0U; /* iString: index = 0 */ + + dfu->block_num = 0U; + dfu->data_len = 0U; + break; + + default: + break; + } +} + +/*! + \brief convert string value into unicode char + \param[in] str: pointer to plain string + \param[in] pbuf: buffer pointer to store unicode char + \param[out] none + \retval none +*/ +static void string_to_unicode (uint8_t *str, uint16_t *pbuf) +{ + uint8_t index = 0; + + if (str != NULL) { + pbuf[index++] = ((strlen((const char *)str) * 2U + 2U) & 0x00FFU) | ((USB_DESCTYPE_STR << 8U) & 0xFF00); + + while (*str != '\0') { + pbuf[index++] = *str++; + } + } +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_mem.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_mem.c new file mode 100644 index 00000000..7a1a3cec --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/dfu/Source/dfu_mem.c @@ -0,0 +1,243 @@ +/*! + \file dfu_mem.c + \brief USB DFU device media access layer functions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "dfu_mem.h" +#include "drv_usb_hw.h" +#include "usbd_transc.h" + +extern usb_core_driver usb_dfu_dev; + +extern struct { + uint8_t buf[TRANSFER_SIZE]; + uint16_t data_len; + uint16_t block_num; + uint32_t base_addr; +} prog; + +dfu_mem_prop* mem_tab[MAX_USED_MEMORY_MEDIA] = { + &dfu_inter_flash_cb, + &dfu_nor_flash_cb, + &dfu_nand_flash_cb, +}; + +/* The list of memory interface string descriptor pointers. This list + can be updated whenever a memory has to be added or removed */ +const uint8_t* USBD_DFU_StringDesc[MAX_USED_MEMORY_MEDIA] = +{ + (const uint8_t *)INTER_FLASH_IF_STR, + (const uint8_t *)NOR_FLASH_IF_STR, + (const uint8_t *)NAND_FLASH_IF_STR +}; + +static uint8_t dfu_mem_checkaddr (uint32_t addr); + +/*! + \brief initialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MEM_OK +*/ +uint8_t dfu_mem_init (void) +{ + uint32_t mem_index = 0U; + + /* initialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != mem_tab[mem_index]->mem_init) { + mem_tab[mem_index]->mem_init(); + } + } + + return MEM_OK; +} + +/*! + \brief deinitialize the memory media on the GD32 + \param[in] none + \param[out] none + \retval MEM_OK +*/ +uint8_t dfu_mem_deinit (void) +{ + uint32_t mem_index = 0U; + + /* deinitialize all supported memory medias */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* check if the memory media exists */ + if (NULL != mem_tab[mem_index]->mem_deinit) { + mem_tab[mem_index]->mem_deinit(); + } + } + + return MEM_OK; +} + +/*! + \brief erase a memory sector + \param[in] addr: memory sector address/code + \param[out] none + \retval MEM_OK +*/ +uint8_t dfu_mem_erase (uint32_t addr) +{ + uint32_t mem_index = dfu_mem_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MEM_FAIL; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != mem_tab[mem_index]->mem_erase) { + return mem_tab[mem_index]->mem_erase(addr); + } else { + return MEM_FAIL; + } + } else { + return MEM_FAIL; + } +} + +/*! + \brief write data to sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval MEM_OK +*/ +uint8_t dfu_mem_write (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = dfu_mem_checkaddr(addr); + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(addr)) { + return MEM_FAIL; + } + + if ((addr & MAL_MASK_OB) == OB_RDPT) { + option_byte_write(addr, buf); + NVIC_SystemReset(); + + return MEM_OK; + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != mem_tab[mem_index]->mem_write) { + return mem_tab[mem_index]->mem_write(buf, addr, len); + } else { + return MEM_FAIL; + } + } else { + return MEM_FAIL; + } +} + +/*! + \brief read data from sectors of memory + \param[in] buf: the data buffer to be write + \param[in] addr: memory sector address/code + \param[in] len: data length + \param[out] none + \retval pointer to buffer +*/ +uint8_t* dfu_mem_read (uint8_t *buf, uint32_t addr, uint32_t len) +{ + uint32_t mem_index = 0U; + + if (OB_RDPT != addr) { + mem_index = dfu_mem_checkaddr(addr); + } + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + /* check if the operation is supported */ + if (NULL != mem_tab[mem_index]->mem_read) { + return mem_tab[mem_index]->mem_read(buf, addr, len); + } else { + return buf; + } + } else { + return buf; + } +} + +/*! + \brief get the status of a given memory and store in buffer + \param[in] addr: memory sector address/code + \param[in] cmd: 0 for erase and 1 for write + \param[in] buffer: pointer to the buffer where the status data will be stored + \param[out] none + \retval MEM_OK if all operations are OK, MEM_FAIL else +*/ +uint8_t dfu_mem_getstatus (uint32_t addr, uint8_t cmd, uint8_t *buffer) +{ + uint32_t mem_index = dfu_mem_checkaddr(addr); + + if (mem_index < MAX_USED_MEMORY_MEDIA) { + if (cmd & 0x01U) { + POLLING_TIMEOUT_SET(mem_tab[mem_index]->write_timeout); + } else { + POLLING_TIMEOUT_SET(mem_tab[mem_index]->erase_timeout); + } + + return MEM_OK; + } else { + return MEM_FAIL; + } +} + +/*! + \brief check the address is supported + \param[in] addr: memory sector address/code + \param[out] none + \retval index of the addressed memory +*/ +static uint8_t dfu_mem_checkaddr (uint32_t addr) +{ + uint8_t mem_index = 0U; + + /* check with all supported memories */ + for (mem_index = 0U; mem_index < MAX_USED_MEMORY_MEDIA; mem_index++) { + /* if the check address is supported, return the memory index */ + if (MEM_OK == mem_tab[mem_index]->mem_checkaddr(addr)) { + return mem_index; + } + } + + /* if there is no memory found, return MAX_USED_MEMORY_MEDIA */ + return (MAX_USED_MEMORY_MEDIA); +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Include/custom_hid_core.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Include/custom_hid_core.h new file mode 100644 index 00000000..6c86f1ee --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Include/custom_hid_core.h @@ -0,0 +1,69 @@ +/*! + \file custom_hid_core.h + \brief definitions for HID core + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __CUSTOM_HID_CORE_H +#define __CUSTOM_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define DESC_LEN_REPORT 96U +#define DESC_LEN_CONFIG 41U + +#define NO_CMD 0xFFU + +#define MAX_PERIPH_NUM 4U + +typedef struct { + uint8_t data[2]; + + uint8_t reportID; + uint8_t idlestate; + uint8_t protocol; +} custom_hid_handler; + +typedef struct { + void (*periph_config[MAX_PERIPH_NUM])(void); +} hid_fop_handler; + +extern usb_desc custom_hid_desc; +extern usb_class_core usbd_custom_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send custom HID report */ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __CUSTOM_HID_CORE_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Include/standard_hid_core.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Include/standard_hid_core.h new file mode 100644 index 00000000..1af49d32 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Include/standard_hid_core.h @@ -0,0 +1,68 @@ +/*! + \file standard_hid_core.h + \brief definitions for HID core + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __STANDARD_HID_CORE_H +#define __STANDARD_HID_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_HID_CONFIG_DESC_LEN 0x22U +#define USB_HID_REPORT_DESC_LEN 0x2EU + +#define NO_CMD 0xFFU + +typedef struct { + uint32_t protocol; + uint32_t idle_state; + + uint8_t data[HID_IN_PACKET]; + __IO uint8_t prev_transfer_complete; +} standard_hid_handler; + +typedef struct { + void (*hid_itf_config) (void); + void (*hid_itf_data_process) (usb_dev *udev); +} hid_fop_handler; + +extern usb_desc hid_desc; +extern usb_class_core usbd_hid_cb; + +/* function declarations */ +/* register HID interface operation functions */ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop); +/* send keyboard report */ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __STANDARD_HID_CORE_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Source/custom_hid_core.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Source/custom_hid_core.c new file mode 100644 index 00000000..ef8bef6e --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Source/custom_hid_core.c @@ -0,0 +1,488 @@ +/*! + \file custom_hid_core.c + \brief custom HID class driver + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "custom_hid_core.h" +#include "usbd_enum.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028AU + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev custom_hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_hid_desc_config_set custom_hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = DESC_LEN_CONFIG, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = DESC_LEN_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_IN_PACKET, + .bInterval = 0x20U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = CUSTOMHID_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = CUSTOMHID_OUT_PACKET, + .bInterval = 0x20U + } +}; + +/* USB language ID descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(14U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'C', 'u', 's', 't', 'o', 'm', 'H', 'I', 'D'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor set */ +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc custom_hid_desc = { + .dev_desc = (uint8_t *)&custom_hid_dev_desc, + .config_desc = (uint8_t *)&custom_hid_config_desc, + .strings = usbd_hid_strings +}; + +const uint8_t customhid_report_descriptor[DESC_LEN_REPORT] = +{ + 0x06, 0x00, 0xFF, /* USAGE_PAGE (Vendor Defined: 0xFF00) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* led 1 */ + 0x85, 0x11, /* REPORT_ID (0x11) */ + 0x09, 0x01, /* USAGE (LED 1) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 2 */ + 0x85, 0x12, /* REPORT_ID (0x12) */ + 0x09, 0x02, /* USAGE (LED 2) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 3 */ + 0x85, 0x13, /* REPORT_ID (0x13) */ + 0x09, 0x03, /* USAGE (LED 3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* led 4 */ + 0x85, 0x14, /* REPORT_ID (0x14) */ + 0x09, 0x04, /* USAGE (LED 4) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* wakeup key */ + 0x85, 0x15, /* REPORT_ID (0x15) */ + 0x09, 0x05, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + /* tamper key */ + 0x85, 0x16, /* REPORT_ID (0x16) */ + 0x09, 0x06, /* USAGE (Push Button) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs,Vol) */ + + 0x75, 0x07, /* REPORT_SIZE (7) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req); + +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num); +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_custom_hid_cb = +{ + .command = NO_CMD, + .alter_set = 0U, + + .init = custom_hid_init, + .deinit = custom_hid_deinit, + + .req_proc = custom_hid_req_handler, + + .data_in = custom_hid_data_in, + .data_out = custom_hid_data_out +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation functions structure + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send custom HID report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t custom_hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, CUSTOMHID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_init (usb_dev *udev, uint8_t config_index) +{ + static custom_hid_handler hid_handler; + + memset((void *)&hid_handler, 0U, sizeof(custom_hid_handler)); + + /* initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epin)); + + /* initialize the data Rx endpoint */ + usbd_ep_setup (udev, &(custom_hid_config_desc.hid_epout)); + + /* prepare receive data */ + usbd_ep_recev (udev, CUSTOMHID_OUT_EP, hid_handler.data, 2U); + + udev->dev.class_data[CUSTOM_HID_INTERFACE] = (void *)&hid_handler; + + if (udev->dev.user_data != NULL) { + for (uint8_t i = 0U; i < MAX_PERIPH_NUM; i++) { + if (((hid_fop_handler *)udev->dev.user_data)->periph_config[i] != NULL) { + ((hid_fop_handler *)udev->dev.user_data)->periph_config[i](); + } + } + } + + return USBD_OK; +} + +/*! + \brief deinitialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, CUSTOMHID_IN_EP); + usbd_ep_clear(udev, CUSTOMHID_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + hid->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + hid->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(DESC_LEN_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)customhid_report_descriptor; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle custom HID data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t custom_hid_data_out (usb_dev *udev, uint8_t ep_num) +{ + custom_hid_handler *hid = (custom_hid_handler *)udev->dev.class_data[CUSTOM_HID_INTERFACE]; + + /* light the LED */ + switch (hid->data[0]){ + case 0x11U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED1); + } else { + gd_eval_led_off(LED1); + } + break; + + case 0x12U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED2); + } else { + gd_eval_led_off(LED2); + } + break; + + case 0x13U: + if (RESET != hid->data[1]) { + gd_eval_led_on(LED3); + } else { + gd_eval_led_off(LED3); + } + break; + + case 0x14U: + if(RESET != hid->data[1]) { + gd_eval_led_on(LED4); + } else { + gd_eval_led_off(LED4); + } + break; + + default: + break; + } + + usbd_ep_recev (udev, CUSTOMHID_OUT_EP, hid->data, 2U); + + return USBD_OK; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Source/standard_hid_core.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Source/standard_hid_core.c new file mode 100644 index 00000000..d05bd9e7 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/hid/Source/standard_hid_core.c @@ -0,0 +1,389 @@ +/*! + \file standard_hid_core.c + \brief HID class driver + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "standard_hid_core.h" +#include + +#define USBD_VID 0x28e9U +#define USBD_PID 0x0380U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +const usb_desc_dev hid_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +const usb_hid_desc_config_set hid_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_HID_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x01U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = USB_HID_SUBCLASS_BOOT_ITF, + .bInterfaceProtocol = USB_HID_PROTOCOL_KEYBOARD, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_HID_REPORT_DESC_LEN, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = HID_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = HID_IN_PACKET, + .bInterval = 0x10U + } +}; + +/* USB language ID Descriptor */ +const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(17U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_hid_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc hid_desc = { + .dev_desc = (uint8_t *)&hid_dev_desc, + .config_desc = (uint8_t *)&hid_config_desc, + .strings = usbd_hid_strings +}; + +const uint8_t hid_report_desc[USB_HID_REPORT_DESC_LEN] = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x06, /* USAGE (Keyboard) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ + 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + + 0x95, 0x06, /* REPORT_COUNT (6) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x26, 0xFF, 0x00, /* LOGICAL_MAXIMUM (255) */ + 0x05, 0x07, /* USAGE_PAGE (Keyboard/Keypad) */ + 0x19, 0x00, /* USAGE_MINIMUM (Reserved (no event indicated)) */ + 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */ + 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + + 0xc0 /* END_COLLECTION */ +}; + +/* local function prototypes ('static') */ +static uint8_t hid_init (usb_dev *udev, uint8_t config_index); +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t hid_req (usb_dev *udev, usb_req *req); +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_hid_cb = { + .command = NO_CMD, + .alter_set = 0U, + + .init = hid_init, + .deinit = hid_deinit, + .req_proc = hid_req, + .data_in = hid_data_in +}; + +/*! + \brief register HID interface operation functions + \param[in] udev: pointer to USB device instance + \param[in] hid_fop: HID operation function structure + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_itfop_register (usb_dev *udev, hid_fop_handler *hid_fop) +{ + if (NULL != hid_fop) { + udev->dev.user_data = (void *)hid_fop; + + return USBD_OK; + } + + return USBD_FAIL; +} + +/*! + \brief send keyboard report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t hid_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + hid->prev_transfer_complete = 0U; + + usbd_ep_send(udev, HID_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_init(usb_dev *udev, uint8_t config_index) +{ + static standard_hid_handler hid_handler; + + memset((void *)&hid_handler, 0U, sizeof(standard_hid_handler)); + + /* initialize the data TX endpoint */ + usbd_ep_setup (udev, &(hid_config_desc.hid_epin)); + + hid_handler.prev_transfer_complete = 1U; + + udev->dev.class_data[USBD_HID_INTERFACE] = (void *)&hid_handler; + + if (NULL != udev->dev.user_data) { + ((hid_fop_handler *)udev->dev.user_data)->hid_itf_config(); + } + + return USBD_OK; +} + +/*! + \brief deinitialize the HID device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize HID endpoints */ + usbd_ep_clear(udev, HID_IN_EP); + + return USBD_OK; +} + +/*! + \brief handle the HID class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&hid->idle_state; + + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&hid->protocol; + + transc->remain_len = 1U; + break; + + case SET_REPORT: + /* no use for this driver */ + break; + + case SET_IDLE: + hid->idle_state = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + hid->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_HID_REPORT_DESC_LEN, req->wLength); + transc->xfer_buf = (uint8_t *)hid_report_desc; + + return REQ_SUPP; + } else if (USB_DESCTYPE_HID == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(9U, req->wLength); + transc->xfer_buf = (uint8_t *)(&(hid_config_desc.hid_vendor)); + } + break; + + default: + break; + } + + return USBD_OK; +} + +/*! + \brief handle data stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval USB device operation status +*/ +static uint8_t hid_data_in (usb_dev *udev, uint8_t ep_num) +{ + standard_hid_handler *hid = (standard_hid_handler *)udev->dev.class_data[USBD_HID_INTERFACE]; + + if (0U != hid->data[2]) { + hid->data[2] = 0x00U; + + usbd_ep_send(udev, HID_IN_EP, hid->data, HID_IN_PACKET); + } else { + hid->prev_transfer_complete = 1U; + } + + return USBD_OK; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/iap/Include/usb_iap_core.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/iap/Include/usb_iap_core.h new file mode 100644 index 00000000..17668ac7 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/iap/Include/usb_iap_core.h @@ -0,0 +1,89 @@ +/*! + \file usb_iap_core.h + \brief the header file of IAP driver + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_IAP_CORE_H +#define __USB_IAP_CORE_H + +#include "usbd_enum.h" +#include "usb_hid.h" + +#define USB_SERIAL_STRING_SIZE 0x06U + +#ifdef USE_USB_FS + #define USB_DESC_LEN_IAP_REPORT 35U +#endif /* USE_USB_FS */ + +#define USB_DESC_LEN_IAP_CONFIG_SET 41U + +/* special commands with download request */ +#define IAP_OPTION_BYTE1 0x01U +#define IAP_ERASE 0x02U +#define IAP_DNLOAD 0x03U +#define IAP_LEAVE 0x04U +#define IAP_GETBIN_ADDRESS 0x05U +#define IAP_OPTION_BYTE2 0x06U + +typedef struct +{ + uint8_t option_byte[IAP_IN_PACKET]; + + /* state machine variables */ + uint8_t dev_status[IAP_IN_PACKET]; + uint8_t bin_addr[IAP_IN_PACKET]; + + uint8_t report_buf[IAP_OUT_PACKET + 1U]; + + uint8_t reportID; + uint8_t flag; + + uint32_t protocol; + uint32_t idlestate; + + uint16_t transfer_times; + uint16_t page_count; + uint16_t lps; /* last packet size */ + uint32_t file_length; + uint32_t base_address; +} usbd_iap_handler; + +typedef void (*app_func)(void); + +extern usb_desc iap_desc; +extern usb_class_core iap_class; + +/* function declarations */ +/* send IAP report */ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len); + +#endif /* __USB_IAP_CORE_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/iap/Source/usb_iap_core.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/iap/Source/usb_iap_core.c new file mode 100644 index 00000000..3e125d81 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/iap/Source/usb_iap_core.c @@ -0,0 +1,561 @@ +/*! + \file usb_iap_core.c + \brief IAP driver + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_iap_core.h" +#include "flash_operation.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0228U + +/* Note:it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev iap_dev_desc __ALIGN_END = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +__ALIGN_BEGIN const usb_hid_desc_config_set iap_config_desc __ALIGN_END = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_DESC_LEN_IAP_CONFIG_SET, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0x80U, + .bMaxPower = 0x32U + }, + + .hid_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_HID_CLASS, + .bInterfaceSubClass = 0x00U, + .bInterfaceProtocol = 0x00U, + .iInterface = 0x00U + }, + + .hid_vendor = + { + .header = + { + .bLength = sizeof(usb_desc_hid), + .bDescriptorType = USB_DESCTYPE_HID + }, + .bcdHID = 0x0111U, + .bCountryCode = 0x00U, + .bNumDescriptors = 0x01U, + .bDescriptorType = USB_DESCTYPE_REPORT, + .wDescriptorLength = USB_DESC_LEN_IAP_REPORT, + }, + + .hid_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_IN_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_IN_PACKET, + .bInterval = 0x01U + }, + + .hid_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = IAP_OUT_EP, + .bmAttributes = USB_EP_ATTR_INT, + .wMaxPacketSize = IAP_OUT_PACKET, + .bInterval = 0x01U + } +}; + +/* USB language ID Descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'I', 'A', 'P'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(2U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +void *const usbd_iap_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc iap_desc = { + .dev_desc = (uint8_t *)&iap_dev_desc, + .config_desc = (uint8_t *)&iap_config_desc, + .strings = usbd_iap_strings +}; + +/* local function prototypes ('static') */ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index); +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req); +static uint8_t iap_data_out (usb_dev *udev, uint8_t ep_num); + +/* IAP requests management functions */ +static void iap_req_erase (usb_dev *udev); +static void iap_req_dnload (usb_dev *udev); +static void iap_req_optionbyte (usb_dev *udev, uint8_t option_num); +static void iap_req_leave (usb_dev *udev); +static void iap_address_send (usb_dev *udev); + +usb_class_core iap_class = { + .init = iap_init, + .deinit = iap_deinit, + .req_proc = iap_req_handler, + .data_out = iap_data_out +}; + +/* USB custom HID device report descriptor */ +__ALIGN_BEGIN const uint8_t iap_report_desc[USB_DESC_LEN_IAP_REPORT] __ALIGN_END = +{ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x00, /* USAGE (Custom Device) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + + /* IAP command and data */ + 0x85, 0x01, /* REPORT_ID (0x01) */ + 0x09, 0x01, /* USAGE (IAP command) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_OUT_COUNT, + 0x91, 0x82, /* OUTPUT (Data,Var,Abs,Vol) */ + + /* device status and option byte */ + 0x85, 0x02, /* REPORT_ID (0x02) */ + 0x09, 0x02, /* USAGE (Status and option byte) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x95, REPORT_IN_COUNT, /* REPORT_COUNT (23) */ + 0x81, 0x82, /* INPUT (Data,Var,Abs,Vol) */ + + 0xc0 /* END_COLLECTION */ +}; + +/*! + \brief send IAP report + \param[in] udev: pointer to USB device instance + \param[in] report: pointer to HID report + \param[in] len: data length + \param[out] none + \retval USB device operation status +*/ +uint8_t iap_report_send (usb_dev *udev, uint8_t *report, uint32_t len) +{ + usbd_ep_send (udev, IAP_IN_EP, report, len); + + return USBD_OK; +} + +/*! + \brief initialize the IAP device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_iap_handler iap_handler __ALIGN_END; + + /* initialize Tx endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epin)); + + /* initialize Rx endpoint */ + usbd_ep_setup(udev, &(iap_config_desc.hid_epout)); + + /* unlock the internal flash */ + fmc_unlock(); + + memset((void *)&iap_handler, 0U, sizeof(usbd_iap_handler)); + + /* prepare receive data */ + usbd_ep_recev(udev, IAP_OUT_EP, iap_handler.report_buf, IAP_OUT_PACKET); + + iap_handler.base_address = APP_LOADED_ADDR; + + udev->dev.class_data[USBD_IAP_INTERFACE] = (void *)&iap_handler; + + return USBD_OK; +} + +/*! + \brief deinitialize the IAP device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize IAP endpoints */ + usbd_ep_clear (udev, IAP_IN_EP); + usbd_ep_clear (udev, IAP_OUT_EP); + + /* lock the internal flash */ + fmc_lock(); + + return USBD_OK; +} + +/*! + \brief handle the IAP class-specific requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t iap_req_handler (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + switch (req->bRequest) { + case GET_REPORT: + /* no use for this driver */ + break; + + case GET_IDLE: + transc->xfer_buf = (uint8_t *)&iap->idlestate; + transc->remain_len = 1U; + break; + + case GET_PROTOCOL: + transc->xfer_buf = (uint8_t *)&iap->protocol; + transc->remain_len = 1U; + break; + + case SET_REPORT: + iap->reportID = (uint8_t)(req->wValue); + break; + + case SET_IDLE: + iap->idlestate = (uint8_t)(req->wValue >> 8U); + break; + + case SET_PROTOCOL: + iap->protocol = (uint8_t)(req->wValue); + break; + + case USB_GET_DESCRIPTOR: + if (USB_DESCTYPE_REPORT == (req->wValue >> 8U)) { + transc->remain_len = USB_MIN(USB_DESC_LEN_IAP_REPORT, req->wLength); + transc->xfer_buf = (uint8_t *)iap_report_desc; + } + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier + \param[out] none + \retval none +*/ +static uint8_t iap_data_out (usb_dev *udev ,uint8_t ep_num) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0x01U == iap->report_buf[0]) { + switch (iap->report_buf[1]) { + case IAP_DNLOAD: + iap_req_dnload(udev); + break; + + case IAP_ERASE: + iap_req_erase(udev); + break; + + case IAP_OPTION_BYTE1: + iap_req_optionbyte(udev, 0x01U); + break; + + case IAP_LEAVE: + iap_req_leave(udev); + break; + + case IAP_GETBIN_ADDRESS: + iap_address_send(udev); + break; + + case IAP_OPTION_BYTE2: + iap_req_optionbyte(udev, 0x02U); + break; + + default: + break; + } + } + + usbd_ep_recev(udev, IAP_OUT_EP, iap->report_buf, IAP_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief handle the IAP_DNLOAD request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_req_dnload(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + if (0U != iap->transfer_times) { + if (1U == iap->transfer_times) { + if (0U == iap->lps) { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, iap->file_length % TRANSFER_SIZE); + iap->lps = 0U; + } + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x02U; + iap_report_send (udev, iap->dev_status, IAP_IN_PACKET); + } else { + iap_data_write(&iap->report_buf[2], iap->base_address, TRANSFER_SIZE); + + iap->base_address += TRANSFER_SIZE; + } + + iap->transfer_times--; + } +} + +/*! + \brief handle the IAP_ERASE request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_req_erase(usb_dev *udev) +{ + uint32_t addr = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + /* get base address to erase */ + iap->base_address = iap->report_buf[2]; + iap->base_address |= iap->report_buf[3] << 8U; + iap->base_address |= iap->report_buf[4] << 16U; + iap->base_address |= iap->report_buf[5] << 24U; + + /* get file length */ + iap->file_length = iap->report_buf[7]; + iap->file_length |= iap->report_buf[8] << 8U; + iap->file_length |= iap->report_buf[9] << 16U; + iap->file_length |= iap->report_buf[10] << 24U; + + iap->lps = iap->file_length % TRANSFER_SIZE; + if (0U == iap->lps) { + iap->transfer_times = iap->file_length / TRANSFER_SIZE; + } else { + iap->transfer_times = iap->file_length / TRANSFER_SIZE + 1U; + } + + /* check if the address is in protected area */ + if (IS_PROTECTED_AREA(iap->base_address)) { + return; + } + + addr = iap->base_address; + + /* unlock the flash program erase controller */ + fmc_unlock(); + + flash_erase(addr, iap->file_length, iap->report_buf); + + fmc_lock(); + + iap->dev_status[0] = 0x02U; + iap->dev_status[1] = 0x01U; + + usbd_ep_send(udev, IAP_IN_EP, iap->dev_status, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_OPTION_BYTE request + \param[in] udev: pointer to USB device instance + \param[in] option_num: number of option byte + \param[out] none + \retval none +*/ +static void iap_req_optionbyte(usb_dev *udev, uint8_t option_num) +{ + uint8_t i = 0U; + uint32_t address = 0U; + + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->option_byte[0] = 0x02U; + + if (0x01U == option_num) { + address = OPT_BYTE_ADDR1; +#ifdef OPT_BYTE_ADDR2 + } else if (0x02U == option_num) { + address = OPT_BYTE_ADDR2; +#endif + } else { + return; + } + + for (i = 1U; i < 17U; i++) { + iap->option_byte[i] = *(uint8_t *)address; + address++; + } + + iap_report_send (udev, iap->option_byte, IAP_IN_PACKET); +} + +/*! + \brief handle the IAP_LEAVE request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_req_leave(usb_dev *udev) +{ + /* lock the internal flash */ + fmc_lock(); + + /* generate system reset to allow jumping to the user code */ + NVIC_SystemReset(); +} + +/*! + \brief handle the IAP_SEND_ADDRESS request + \param[in] udev: pointer to usb device instance + \param[out] none + \retval none +*/ +static void iap_address_send(usb_dev *udev) +{ + usbd_iap_handler *iap = (usbd_iap_handler *)udev->dev.class_data[USBD_IAP_INTERFACE]; + + iap->bin_addr[0] = 0x02U; + + iap->bin_addr[1] = (uint8_t)(APP_LOADED_ADDR); + iap->bin_addr[2] = (uint8_t)(APP_LOADED_ADDR >> 8U); + iap->bin_addr[3] = (uint8_t)(APP_LOADED_ADDR >> 16U); + iap->bin_addr[4] = (uint8_t)(APP_LOADED_ADDR >> 24U); + + iap_report_send (udev, iap->bin_addr, IAP_IN_PACKET); +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h new file mode 100644 index 00000000..f5457744 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_bbb.h @@ -0,0 +1,101 @@ +/*! + \file usbd_msc_bbb.h + \brief the header file of the usbd_msc_bbb.c file + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_BBB_H +#define __USBD_MSC_BBB_H + +#include "usbd_core.h" +#include "msc_bbb.h" +#include "usbd_msc_mem.h" +#include "usbd_msc_scsi.h" + +/* MSC BBB state */ +enum msc_bbb_state { + BBB_IDLE = 0U, /*!< idle state */ + BBB_DATA_OUT, /*!< data OUT state */ + BBB_DATA_IN, /*!< data IN state */ + BBB_LAST_DATA_IN, /*!< last data IN state */ + BBB_SEND_DATA /*!< send immediate data state */ +}; + +/* MSC BBB status */ +enum msc_bbb_status { + BBB_STATUS_NORMAL = 0U, /*!< normal status */ + BBB_STATUS_RECOVERY, /*!< recovery status*/ + BBB_STATUS_ERROR /*!< error status */ +}; + +typedef struct +{ + uint8_t bbb_data[MSC_MEDIA_PACKET_SIZE]; + + uint8_t max_lun; + uint8_t bbb_state; + uint8_t bbb_status; + + uint32_t bbb_datalen; + + msc_bbb_cbw bbb_cbw; + msc_bbb_csw bbb_csw; + + uint8_t scsi_sense_head; + uint8_t scsi_sense_tail; + + uint32_t scsi_blk_size[MEM_LUN_NUM]; + uint32_t scsi_blk_nbr[MEM_LUN_NUM]; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; + uint32_t scsi_disk_pop; + + msc_scsi_sense scsi_sense[SENSE_LIST_DEEPTH]; +} usbd_msc_handler; + +/* function declarations */ +/* initialize the bbb process */ +void msc_bbb_init (usb_core_driver *udev); +/* reset the BBB machine */ +void msc_bbb_reset (usb_core_driver *udev); +/* deinitialize the BBB machine */ +void msc_bbb_deinit (usb_core_driver *udev); +/* handle BBB data IN stage */ +void msc_bbb_data_in (usb_core_driver *udev, uint8_t ep_num); +/* handle BBB data OUT stage */ +void msc_bbb_data_out (usb_core_driver *udev, uint8_t ep_num); +/* send the CSW(command status wrapper) */ +void msc_bbb_csw_send (usb_core_driver *udev, uint8_t csw_status); +/* complete the clear feature request */ +void msc_bbb_clrfeature (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_MSC_BBB_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_core.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_core.h new file mode 100644 index 00000000..730465d2 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_core.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_core.h + \brief the header file of USB MSC device class core functions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_CORE_H +#define __USBD_MSC_CORE_H + +#include "usbd_core.h" +#include "usb_msc.h" + +#define USB_MSC_CONFIG_DESC_SIZE 32U + +#define MSC_EPIN_SIZE MSC_DATA_PACKET_SIZE +#define MSC_EPOUT_SIZE MSC_DATA_PACKET_SIZE + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + + usb_desc_itf msc_itf; + usb_desc_ep msc_epin; + usb_desc_ep msc_epout; +} usb_desc_config_set; + +extern usb_desc msc_desc; +extern usb_class_core msc_class; + +#endif /* __USBD_MSC_CORE_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h new file mode 100644 index 00000000..eec6a256 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_mem.h @@ -0,0 +1,59 @@ +/*! + \file usbd_msc_mem.h + \brief header file for storage memory + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_MEM_H +#define __USBD_MSC_MEM_H + +#include "usbd_conf.h" + +#define USBD_STD_INQUIRY_LENGTH 36U + +typedef struct +{ + int8_t (*mem_init) (uint8_t lun); + int8_t (*mem_ready) (uint8_t lun); + int8_t (*mem_protected) (uint8_t lun); + int8_t (*mem_read) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_write) (uint8_t lun, uint8_t *buf, uint32_t block_addr, uint16_t block_len); + int8_t (*mem_maxlun) (void); + + uint8_t *mem_toc_data; + uint8_t *mem_inquiry_data[MEM_LUN_NUM]; + uint32_t mem_block_size[MEM_LUN_NUM]; + uint32_t mem_block_len[MEM_LUN_NUM]; +} usbd_mem_cb; + +extern usbd_mem_cb *usbd_mem_fops; + +#endif /* __USBD_MSC_MEM_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h new file mode 100644 index 00000000..889a2551 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Include/usbd_msc_scsi.h @@ -0,0 +1,58 @@ +/*! + \file usbd_msc_scsi.h + \brief the header file of the usbd_msc_scsi.c file + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_MSC_SCSI_H +#define __USBD_MSC_SCSI_H + +#include "usbd_msc_bbb.h" +#include "msc_scsi.h" + +#define SENSE_LIST_DEEPTH 4U + +#define MODE_SENSE6_LENGTH 8U +#define MODE_SENSE10_LENGTH 8U +#define INQUIRY_PAGE00_LENGTH 96U +#define FORMAT_CAPACITIES_LENGTH 20U + +extern const uint8_t msc_page00_inquiry_data[]; +extern const uint8_t msc_mode_sense6_data[]; +extern const uint8_t msc_mode_sense10_data[]; + +/* function declarations */ +/* process SCSI commands */ +int8_t scsi_process_cmd (usb_core_driver *udev, uint8_t lun, uint8_t *cmd); +/* load the last error code in the error list */ +void scsi_sense_code (usb_core_driver *udev, uint8_t lun, uint8_t skey, uint8_t asc); + +#endif /* __USBD_MSC_SCSI_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c new file mode 100644 index 00000000..b2bfbaaf --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_bbb.c @@ -0,0 +1,287 @@ +/*! + \file usbd_msc_bbb.c + \brief USB BBB(Bulk/Bulk/Bulk) protocol core functions + \note BBB means Bulk-only transport protocol for USB MSC + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" + +/* local function prototypes ('static') */ +static void msc_bbb_cbw_decode (usb_core_driver *udev); +static void msc_bbb_data_send (usb_core_driver *udev, uint8_t *pbuf, uint32_t Len); +static void msc_bbb_abort (usb_core_driver *udev); + +/*! + \brief initialize the bbb process + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_init (usb_core_driver *udev) +{ + uint8_t lun_num; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_NORMAL; + + /* initializes the storage logic unit */ + for(lun_num = 0U; lun_num < MEM_LUN_NUM; lun_num++) { + usbd_mem_fops->mem_init(lun_num); + } + + /* flush the Rx FIFO */ + usbd_fifo_flush (udev, MSC_OUT_EP); + + /* flush the Tx FIFO */ + usbd_fifo_flush (udev, MSC_IN_EP); + + /* prepare endpoint to receive the first BBB CBW */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief reset the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_reset (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; + msc->bbb_status = BBB_STATUS_RECOVERY; + + /* prepare endpoint to receive the first BBB command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief deinitialize the BBB machine + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void msc_bbb_deinit (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_state = BBB_IDLE; +} + +/*! + \brief handle BBB data IN stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_in (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_DATA_IN: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + case BBB_SEND_DATA: + case BBB_LAST_DATA_IN: + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + break; + + default: + break; + } +} + +/*! + \brief handle BBB data OUT stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_data_out (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + switch (msc->bbb_state) { + case BBB_IDLE: + msc_bbb_cbw_decode (udev); + break; + + case BBB_DATA_OUT: + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } + break; + + default: + break; + } +} + +/*! + \brief send the CSW(command status wrapper) + \param[in] udev: pointer to USB device instance + \param[in] csw_status: CSW status + \param[out] none + \retval none +*/ +void msc_bbb_csw_send (usb_core_driver *udev, uint8_t csw_status) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWSignature = BBB_CSW_SIGNATURE; + msc->bbb_csw.bCSWStatus = csw_status; + msc->bbb_state = BBB_IDLE; + + usbd_ep_send (udev, MSC_IN_EP, (uint8_t *)&msc->bbb_csw, BBB_CSW_LENGTH); + + /* prepare endpoint to receive next command */ + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); +} + +/*! + \brief complete the clear feature request + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval none +*/ +void msc_bbb_clrfeature (usb_core_driver *udev, uint8_t ep_num) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_status == BBB_STATUS_ERROR){ /* bad CBW signature */ + usbd_ep_stall(udev, MSC_IN_EP); + + msc->bbb_status = BBB_STATUS_NORMAL; + } else if(((ep_num & 0x80U) == 0x80U) && (msc->bbb_status != BBB_STATUS_RECOVERY)) { + msc_bbb_csw_send (udev, CSW_CMD_FAILED); + } else { + + } +} + +/*! + \brief decode the CBW command and set the BBB state machine accordingly + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_cbw_decode (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_csw.dCSWTag = msc->bbb_cbw.dCBWTag; + msc->bbb_csw.dCSWDataResidue = msc->bbb_cbw.dCBWDataTransferLength; + + if((BBB_CBW_LENGTH != usbd_rxcount_get(udev, MSC_OUT_EP)) || + (BBB_CBW_SIGNATURE != msc->bbb_cbw.dCBWSignature) || + (msc->bbb_cbw.bCBWLUN > 1U) || + (msc->bbb_cbw.bCBWCBLength < 1U) || + (msc->bbb_cbw.bCBWCBLength > 16U)) { + /* illegal command handler */ + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + msc->bbb_status = BBB_STATUS_ERROR; + + msc_bbb_abort (udev); + } else { + if (scsi_process_cmd (udev, msc->bbb_cbw.bCBWLUN, &msc->bbb_cbw.CBWCB[0]) < 0) { + msc_bbb_abort (udev); + } else if ((BBB_DATA_IN != msc->bbb_state) && + (BBB_DATA_OUT != msc->bbb_state) && + (BBB_LAST_DATA_IN != msc->bbb_state)) { /* burst xfer handled internally */ + if (msc->bbb_datalen > 0U) { + msc_bbb_data_send (udev, msc->bbb_data, msc->bbb_datalen); + } else if (0U == msc->bbb_datalen) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + + } + } else { + + } + } +} + +/*! + \brief send the requested data + \param[in] udev: pointer to USB device instance + \param[in] buf: pointer to data buffer + \param[in] len: data length + \param[out] none + \retval none +*/ +static void msc_bbb_data_send (usb_core_driver *udev, uint8_t *buf, uint32_t len) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + len = USB_MIN (msc->bbb_cbw.dCBWDataTransferLength, len); + + msc->bbb_csw.dCSWDataResidue -= len; + msc->bbb_csw.bCSWStatus = CSW_CMD_PASSED; + msc->bbb_state = BBB_SEND_DATA; + + usbd_ep_send (udev, MSC_IN_EP, buf, len); +} + +/*! + \brief abort the current transfer + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +static void msc_bbb_abort (usb_core_driver *udev) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((0U == msc->bbb_cbw.bmCBWFlags) && + (0U != msc->bbb_cbw.dCBWDataTransferLength) && + (BBB_STATUS_NORMAL == msc->bbb_status)) { + usbd_ep_stall(udev, MSC_OUT_EP); + } + + usbd_ep_stall(udev, MSC_IN_EP); + + if (msc->bbb_status == BBB_STATUS_ERROR) { + usbd_ep_recev (udev, MSC_OUT_EP, (uint8_t *)&msc->bbb_cbw, BBB_CBW_LENGTH); + } +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_core.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_core.c new file mode 100644 index 00000000..8bfdf77a --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_core.c @@ -0,0 +1,318 @@ +/*! + \file usbd_msc_core.c + \brief USB MSC device class core functions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_core.h" +#include + +#define USBD_VID 0x28E9U +#define USBD_PID 0x028FU + +/* local function prototypes ('static') */ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t msc_core_req (usb_dev *udev, usb_req *req); +static uint8_t msc_core_in (usb_dev *udev, uint8_t ep_num); +static uint8_t msc_core_out (usb_dev *udev, uint8_t ep_num); + +static __ALIGN_BEGIN uint8_t usbd_msc_maxlun = 0U __ALIGN_END; + +usb_class_core msc_class = +{ + .init = msc_core_init, + .deinit = msc_core_deinit, + + .req_proc = msc_core_req, + + .data_in = msc_core_in, + .data_out = msc_core_out +}; + +/* note: it should use the C99 standard when compiling the below codes */ +/* USB standard device descriptor */ +__ALIGN_BEGIN const usb_desc_dev msc_dev_desc __ALIGN_END = +{ + .header = { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM +}; + +/* USB device configuration descriptor */ +__ALIGN_BEGIN const usb_desc_config_set msc_config_desc __ALIGN_END = +{ + .config = + { + .header = { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_MSC_CONFIG_DESC_SIZE, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xC0U, + .bMaxPower = 0x32U + }, + + .msc_itf = + { + .header = { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_MSC, + .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI, + .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB, + .iInterface = 0x00U + }, + + .msc_epin = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPIN_SIZE, + .bInterval = 0x00U + }, + + .msc_epout = + { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = MSC_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = MSC_EPOUT_SIZE, + .bInterval = 0x00U + } +}; + +/* USB language ID descriptor */ +static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'M', 'S', 'C'} +}; + +/* USBD serial string */ +static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc msc_desc = { + .dev_desc = (uint8_t *)&msc_dev_desc, + .config_desc = (uint8_t *)&msc_config_desc, + .strings = usbd_msc_strings +}; + +/*! + \brief initialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_init (usb_dev *udev, uint8_t config_index) +{ + static __ALIGN_BEGIN usbd_msc_handler msc_handler __ALIGN_END; + + memset((void *)&msc_handler, 0U, sizeof(usbd_msc_handler)); + + udev->dev.class_data[USBD_MSC_INTERFACE] = (void *)&msc_handler; + + /* configure MSC Tx endpoint */ + usbd_ep_setup (udev, &(msc_config_desc.msc_epin)); + + /* configure MSC Rx endpoint */ + usbd_ep_setup (udev, &(msc_config_desc.msc_epout)); + + /* initialize the BBB layer */ + msc_bbb_init(udev); + + return USBD_OK; +} + +/*! + \brief deinitialize the MSC device + \param[in] udev: pointer to USB device instance + \param[in] config_index: configuration index + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_deinit (usb_dev *udev, uint8_t config_index) +{ + /* clear MSC endpoints */ + usbd_ep_clear (udev, MSC_IN_EP); + usbd_ep_clear (udev, MSC_OUT_EP); + + /* deinitialize the BBB layer */ + msc_bbb_deinit(udev); + + return USBD_OK; +} + +/*! + \brief handle the MSC class-specific and standard requests + \param[in] udev: pointer to USB device instance + \param[in] req: device class-specific request + \param[out] none + \retval USB device operation status +*/ +static uint8_t msc_core_req (usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case BBB_GET_MAX_LUN : + if((0U == req->wValue) && + (1U == req->wLength) && + (0x80U == (req->bmRequestType & 0x80U))) { + usbd_msc_maxlun = (uint8_t)usbd_mem_fops->mem_maxlun(); + + transc->xfer_buf = &usbd_msc_maxlun; + transc->remain_len = 1U; + } else { + return USBD_FAIL; + } + break; + + case BBB_RESET : + if((0U == req->wValue) && + (0U == req->wLength) && + (0x80U != (req->bmRequestType & 0x80U))) { + msc_bbb_reset(udev); + } else { + return USBD_FAIL; + } + break; + + case USB_CLEAR_FEATURE: + msc_bbb_clrfeature (udev, (uint8_t)req->wIndex); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle data in stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_in (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_in (udev, ep_num); + + return USBD_OK; +} + +/*! + \brief handle data out stage + \param[in] udev: pointer to USB device instance + \param[in] ep_num: the endpoint number + \param[out] none + \retval none +*/ +static uint8_t msc_core_out (usb_dev *udev, uint8_t ep_num) +{ + msc_bbb_data_out (udev, ep_num); + + return USBD_OK; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c new file mode 100644 index 00000000..66283cad --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/msc/Source/usbd_msc_scsi.c @@ -0,0 +1,761 @@ +/*! + \file usbd_msc_scsi.c + \brief USB SCSI layer functions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_msc_bbb.h" +#include "usbd_msc_scsi.h" + +/* USB mass storage page 0 inquiry data */ +const uint8_t msc_page00_inquiry_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + (INQUIRY_PAGE00_LENGTH - 4U), + 0x80U, + 0x83U, +}; + +/* USB mass storage sense 6 data */ +const uint8_t msc_mode_sense6_data[] = +{ + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; + +/* USB mass storage sense 10 data */ +const uint8_t msc_mode_sense10_data[] = +{ + 0x00U, + 0x06U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U, + 0x00U +}; + +/* local function prototypes ('static') */ +static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select6 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_select10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params); + +static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun); +static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun); + +static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr); +static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun); +static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params); +static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params); + +/*! + \brief process SCSI commands + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +int8_t scsi_process_cmd(usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + switch (params[0]) { + case SCSI_TEST_UNIT_READY: + return scsi_test_unit_ready (udev, lun, params); + + case SCSI_REQUEST_SENSE: + return scsi_request_sense (udev, lun, params); + + case SCSI_INQUIRY: + return scsi_inquiry (udev, lun, params); + + case SCSI_START_STOP_UNIT: + return scsi_start_stop_unit (udev, lun, params); + + case SCSI_ALLOW_MEDIUM_REMOVAL: + return scsi_allow_medium_removal (udev, lun, params); + + case SCSI_MODE_SENSE6: + return scsi_mode_sense6 (udev, lun, params); + + case SCSI_MODE_SENSE10: + return scsi_mode_sense10 (udev, lun, params); + + case SCSI_READ_FORMAT_CAPACITIES: + return scsi_read_format_capacity (udev, lun, params); + + case SCSI_READ_CAPACITY10: + return scsi_read_capacity10 (udev, lun, params); + + case SCSI_READ10: + return scsi_read10 (udev, lun, params); + + case SCSI_WRITE10: + return scsi_write10 (udev, lun, params); + + case SCSI_VERIFY10: + return scsi_verify10 (udev, lun, params); + + case SCSI_FORMAT_UNIT: + return scsi_format_cmd (udev, lun); + + case SCSI_READ_TOC_DATA: + return scsi_toc_cmd_read (udev, lun, params); + + case SCSI_MODE_SELECT6: + return scsi_mode_select6 (udev, lun, params); + + case SCSI_MODE_SELECT10: + return scsi_mode_select10 (udev, lun, params); + + default: + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } +} + +/*! + \brief load the last error code in the error list + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] skey: sense key + \param[in] asc: additional sense key + \param[out] none + \retval none +*/ +void scsi_sense_code (usb_core_driver *udev, uint8_t lun, uint8_t skey, uint8_t asc) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_sense[msc->scsi_sense_tail].SenseKey = skey; + msc->scsi_sense[msc->scsi_sense_tail].ASC = asc; + msc->scsi_sense_tail++; + + if (SENSE_LIST_DEEPTH == msc->scsi_sense_tail) { + msc->scsi_sense_tail = 0U; + } +} + +/*! + \brief process SCSI Test Unit Ready command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_test_unit_ready (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + /* case 9 : Hi > D0 */ + if (0U != msc->bbb_cbw.dCBWDataTransferLength) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code(udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select6 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_select10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Inquiry command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_inquiry (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t *page = NULL; + uint16_t len = 0U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (params[1] & 0x01U) { + page = (uint8_t *)msc_page00_inquiry_data; + + len = INQUIRY_PAGE00_LENGTH; + } else { + page = (uint8_t *)usbd_mem_fops->mem_inquiry_data[lun]; + + len = (uint16_t)(page[4] + 5U); + + if (params[4] <= len) { + len = params[4]; + } + } + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = page[len]; + } + + return 0; +} + +/*! + \brief process Read Capacity 10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_capacity10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun] - 1U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->scsi_blk_nbr[lun] = usbd_mem_fops->mem_block_len[lun]; + msc->scsi_blk_size[lun] = usbd_mem_fops->mem_block_size[lun]; + + msc->bbb_data[0] = (uint8_t)(blk_num >> 24U); + msc->bbb_data[1] = (uint8_t)(blk_num >> 16U); + msc->bbb_data[2] = (uint8_t)(blk_num >> 8U); + msc->bbb_data[3] = (uint8_t)(blk_num); + + msc->bbb_data[4] = (uint8_t)(msc->scsi_blk_size[lun] >> 24U); + msc->bbb_data[5] = (uint8_t)(msc->scsi_blk_size[lun] >> 16U); + msc->bbb_data[6] = (uint8_t)(msc->scsi_blk_size[lun] >> 8U); + msc->bbb_data[7] = (uint8_t)(msc->scsi_blk_size[lun]); + + msc->bbb_datalen = 8U; + + return 0; +} + +/*! + \brief process Read Format Capacity command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read_format_capacity (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t i = 0U; + uint32_t blk_size = usbd_mem_fops->mem_block_size[lun]; + uint32_t blk_num = usbd_mem_fops->mem_block_len[lun]; + uint32_t blk_nbr = blk_num - 1U; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < 12U; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[3] = 0x08U; + msc->bbb_data[4] = (uint8_t)(blk_nbr >> 24U); + msc->bbb_data[5] = (uint8_t)(blk_nbr >> 16U); + msc->bbb_data[6] = (uint8_t)(blk_nbr >> 8U); + msc->bbb_data[7] = (uint8_t)(blk_nbr); + + msc->bbb_data[8] = 0x02U; + msc->bbb_data[9] = (uint8_t)(blk_size >> 16U); + msc->bbb_data[10] = (uint8_t)(blk_size >> 8U); + msc->bbb_data[11] = (uint8_t)(blk_size); + + msc->bbb_datalen = 12U; + + return 0; +} + +/*! + \brief process Mode Sense6 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense6 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense6_data[len]; + } + + return 0; +} + +/*! + \brief process Mode Sense10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_mode_sense10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = msc_mode_sense10_data[len]; + } + + return 0; +} + +/*! + \brief process Request Sense command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_request_sense (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t i = 0U; + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + for (i = 0U; i < REQUEST_SENSE_DATA_LEN; i++) { + msc->bbb_data[i] = 0U; + } + + msc->bbb_data[0] = 0x70U; + msc->bbb_data[7] = REQUEST_SENSE_DATA_LEN - 6U; + + if ((msc->scsi_sense_head != msc->scsi_sense_tail)) { + msc->bbb_data[2] = msc->scsi_sense[msc->scsi_sense_head].SenseKey; + msc->bbb_data[12] = msc->scsi_sense[msc->scsi_sense_head].ASC; + msc->bbb_data[13] = msc->scsi_sense[msc->scsi_sense_head].ASCQ; + msc->scsi_sense_head++; + + if (msc->scsi_sense_head == SENSE_LIST_DEEPTH) { + msc->scsi_sense_head = 0U; + } + } + + msc->bbb_datalen = USB_MIN(REQUEST_SENSE_DATA_LEN, params[4]); + + return 0; +} + +/*! + \brief process Start Stop Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_start_stop_unit (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + msc->scsi_disk_pop = 1U; + + return 0; +} + +/*! + \brief process Allow Medium Removal command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static inline int8_t scsi_allow_medium_removal (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief process Read10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_read10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (msc->bbb_state == BBB_IDLE) { + /* direction is from device to host */ + if (0x80U != (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_state = BBB_DATA_IN; + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 4,5 : Hi <> Dn */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + } + + msc->bbb_datalen = MSC_MEDIA_PACKET_SIZE; + + return scsi_process_read (udev, lun); +} + +/*! + \brief process Write10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_write10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (BBB_IDLE == msc->bbb_state) { + /* case 8 : Hi <> Do */ + if (0x80U == (msc->bbb_cbw.bmCBWFlags & 0x80U)) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* check whether media is ready */ + if (0 != usbd_mem_fops->mem_ready(lun)) { + scsi_sense_code (udev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + + return -1; + } + + /* check if media is write-protected */ + if (0 != usbd_mem_fops->mem_protected(lun)) { + scsi_sense_code (udev, lun, NOT_READY, WRITE_PROTECTED); + + return -1; + } + + msc->scsi_blk_addr = (params[2] << 24U) | (params[3] << 16U) | \ + (params[4] << 8U) | params[5]; + + msc->scsi_blk_len = (params[7] << 8U) | params[8]; + + /* check if LBA address is in the right range */ + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->scsi_blk_addr *= msc->scsi_blk_size[lun]; + msc->scsi_blk_len *= msc->scsi_blk_size[lun]; + + /* cases 3,11,13 : Hn,Ho <> D0 */ + if (msc->bbb_cbw.dCBWDataTransferLength != msc->scsi_blk_len) { + scsi_sense_code (udev, msc->bbb_cbw.bCBWLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + /* prepare endpoint to receive first data packet */ + msc->bbb_state = BBB_DATA_OUT; + + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } else { /* write process ongoing */ + return scsi_process_write (udev, lun); + } + + return 0; +} + +/*! + \brief process Verify10 command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_verify10 (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if (0x02U == (params[1] & 0x02U)) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + + return -1; /* error, verify mode not supported*/ + } + + if (scsi_check_address_range (udev, lun, msc->scsi_blk_addr, (uint16_t)msc->scsi_blk_len) < 0) { + return -1; /* error */ + } + + msc->bbb_datalen = 0U; + + return 0; +} + +/*! + \brief check address range + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] blk_offset: block offset + \param[in] blk_nbr: number of block to be processed + \param[out] none + \retval status +*/ +static inline int8_t scsi_check_address_range (usb_core_driver *udev, uint8_t lun, uint32_t blk_offset, uint16_t blk_nbr) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + if ((blk_offset + blk_nbr) > msc->scsi_blk_nbr[lun]) { + scsi_sense_code (udev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + + return -1; + } + + return 0; +} + +/*! + \brief handle read process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_read (usb_core_driver *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_read(lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + + return -1; + } + + usbd_ep_send (udev, MSC_IN_EP, msc->bbb_data, len); + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 6 : Hi = Di */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc->bbb_state = BBB_LAST_DATA_IN; + } + + return 0; +} + +/*! + \brief handle write process + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static int8_t scsi_process_write (usb_core_driver *udev, uint8_t lun) +{ + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + uint32_t len = USB_MIN(msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE); + + if (usbd_mem_fops->mem_write (lun, + msc->bbb_data, + msc->scsi_blk_addr, + (uint16_t)(len / msc->scsi_blk_size[lun])) < 0) { + scsi_sense_code(udev, lun, HARDWARE_ERROR, WRITE_FAULT); + + return -1; + } + + msc->scsi_blk_addr += len; + msc->scsi_blk_len -= len; + + /* case 12 : Ho = Do */ + msc->bbb_csw.dCSWDataResidue -= len; + + if (0U == msc->scsi_blk_len) { + msc_bbb_csw_send (udev, CSW_CMD_PASSED); + } else { + /* prepare endpoint to receive next packet */ + usbd_ep_recev (udev, + MSC_OUT_EP, + msc->bbb_data, + USB_MIN (msc->scsi_blk_len, MSC_MEDIA_PACKET_SIZE)); + } + + return 0; +} + +/*! + \brief process Format Unit command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[out] none + \retval status +*/ +static inline int8_t scsi_format_cmd (usb_core_driver *udev, uint8_t lun) +{ + return 0; +} + +/*! + \brief process Read_Toc command + \param[in] udev: pointer to USB device instance + \param[in] lun: logical unit number + \param[in] params: command parameters + \param[out] none + \retval status +*/ +static int8_t scsi_toc_cmd_read (usb_core_driver *udev, uint8_t lun, uint8_t *params) +{ + uint8_t* pPage; + uint16_t len; + + usbd_msc_handler *msc = (usbd_msc_handler *)udev->dev.class_data[USBD_MSC_INTERFACE]; + + pPage = (uint8_t *)&usbd_mem_fops->mem_toc_data[lun * READ_TOC_CMD_LEN]; + len = (uint16_t)pPage[1] + 2U; + + msc->bbb_datalen = len; + + while (len) { + len--; + msc->bbb_data[len] = pPage[len]; + } + + return 0; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/printer/Include/printer_core.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/printer/Include/printer_core.h new file mode 100644 index 00000000..bb1f66f9 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/printer/Include/printer_core.h @@ -0,0 +1,78 @@ +/*! + \file printer_core.h + \brief the header file of USB printer device class core functions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __PRINTER_CORE_H +#define __PRINTER_CORE_H + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +/* USB printing device class code */ +#define USB_CLASS_PRINTER 0x07U + +/* printing device subclass code */ +#define USB_SUBCLASS_PRINTER 0x01U + +/* printing device protocol code */ +#define PROTOCOL_UNIDIRECTIONAL_ITF 0x01U +#define PROTOCOL_BI_DIRECTIONAL_ITF 0x02U +#define PROTOCOL_1284_4_ITF 0x03U +#define PROTOCOL_VENDOR 0xFFU + +#define DEVICE_ID_LEN 103U + +#define USB_PRINTER_CONFIG_DESC_LEN 32U + +/* printing device specific-class request */ +#define GET_DEVICE_ID 0x00U +#define GET_PORT_STATUS 0x01U +#define SOFT_RESET 0x02U + +#pragma pack(1) + +/* USB configuration descriptor structure */ +typedef struct +{ + usb_desc_config config; + usb_desc_itf printer_itf; + usb_desc_ep printer_epin; + usb_desc_ep printer_epout; +} usb_printer_desc_config_set; + +#pragma pack() + +extern usb_desc printer_desc; +extern usb_class_core usbd_printer_cb; + +#endif /* __PRINTER_CORE_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/printer/Source/printer_core.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/printer/Source/printer_core.c new file mode 100644 index 00000000..6bccaf4c --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/class/printer/Source/printer_core.c @@ -0,0 +1,310 @@ +/*! + \file printer_core.c + \brief USB printer device class core functions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "printer_core.h" + +#define USBD_VID 0x28E9U +#define USBD_PID 0x0003U + +/* printer port status: paper not empty/selected/no error */ +static uint8_t g_port_status = 0x18U; + +uint8_t g_printer_data_buf[PRINTER_OUT_PACKET]; + +uint8_t PRINTER_DEVICE_ID[DEVICE_ID_LEN] = +{ + 0x00, 0x67, + 'M', 'A', 'N', 'U', 'F', 'A', 'C', 'T', 'U', 'R', 'E', 'R', ':', + 'G', 'I', 'G', 'A', ' ', 'D', 'E', 'V', 'I', 'C', 'E', '-', ';', + 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ',', 'M', 'P', 'L', ';', + 'M', 'O', 'D', 'E', 'L', ':', + 'L', 'a', 's', 'e', 'r', 'B', 'e', 'a', 'm', '?', ';', + 'C', 'O', 'M', 'M', 'E', 'N', 'T', ':', + 'G', 'o', 'o', 'd', ' ', '!', ';', + 'A', 'C', 'T', 'I', 'V', 'E', ' ', 'C', 'O', 'M', 'M', 'A', 'N', 'D', ' ', 'S', 'E', 'T', ':', + 'P', 'C', 'L', ';' +}; + +/* USB standard device descriptor */ +const usb_desc_dev printer_dev_desc = +{ + .header = + { + .bLength = USB_DEV_DESC_LEN, + .bDescriptorType = USB_DESCTYPE_DEV, + }, + .bcdUSB = 0x0200U, + .bDeviceClass = 0x00U, + .bDeviceSubClass = 0x00U, + .bDeviceProtocol = 0x00U, + .bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, + .idVendor = USBD_VID, + .idProduct = USBD_PID, + .bcdDevice = 0x0100U, + .iManufacturer = STR_IDX_MFC, + .iProduct = STR_IDX_PRODUCT, + .iSerialNumber = STR_IDX_SERIAL, + .bNumberConfigurations = USBD_CFG_MAX_NUM, +}; + +/* USB device configuration descriptor */ +const usb_printer_desc_config_set printer_config_desc = +{ + .config = + { + .header = + { + .bLength = sizeof(usb_desc_config), + .bDescriptorType = USB_DESCTYPE_CONFIG + }, + .wTotalLength = USB_PRINTER_CONFIG_DESC_LEN, + .bNumInterfaces = 0x01U, + .bConfigurationValue = 0x01U, + .iConfiguration = 0x00U, + .bmAttributes = 0xA0U, + .bMaxPower = 0x32U + }, + + .printer_itf = + { + .header = + { + .bLength = sizeof(usb_desc_itf), + .bDescriptorType = USB_DESCTYPE_ITF + }, + .bInterfaceNumber = 0x00U, + .bAlternateSetting = 0x00U, + .bNumEndpoints = 0x02U, + .bInterfaceClass = USB_CLASS_PRINTER, + .bInterfaceSubClass = USB_SUBCLASS_PRINTER, + .bInterfaceProtocol = PROTOCOL_BI_DIRECTIONAL_ITF, + .iInterface = 0x00U + }, + + .printer_epin = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_IN_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_IN_PACKET, + .bInterval = 0x00U + }, + + .printer_epout = + { + .header = + { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = PRINTER_OUT_EP, + .bmAttributes = USB_EP_ATTR_BULK, + .wMaxPacketSize = PRINTER_OUT_PACKET, + .bInterval = 0x00U + }, +}; + +/* USB language ID Descriptor */ +static const usb_desc_LANGID usbd_language_id_desc = +{ + .header = + { + .bLength = sizeof(usb_desc_LANGID), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .wLANGID = ENG_LANGID +}; + +/* USB manufacture string */ +static const usb_desc_str manufacturer_string = +{ + .header = + { + .bLength = USB_STRING_LEN(10U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'} +}; + +/* USB product string */ +static const usb_desc_str product_string = +{ + .header = + { + .bLength = USB_STRING_LEN(16U), + .bDescriptorType = USB_DESCTYPE_STR, + }, + .unicode_string = {'G', 'D', '3', '2', '-', 'U', 'S', 'B', '_', 'P', 'r', 'i', 'n', 't', 'e', 'r'} +}; + +/* USBD serial string */ +static usb_desc_str serial_string = +{ + .header = + { + .bLength = USB_STRING_LEN(12U), + .bDescriptorType = USB_DESCTYPE_STR, + } +}; + +/* USB string descriptor */ +static void *const usbd_msc_strings[] = +{ + [STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc, + [STR_IDX_MFC] = (uint8_t *)&manufacturer_string, + [STR_IDX_PRODUCT] = (uint8_t *)&product_string, + [STR_IDX_SERIAL] = (uint8_t *)&serial_string +}; + +usb_desc printer_desc = { + .dev_desc = (uint8_t *)&printer_dev_desc, + .config_desc = (uint8_t *)&printer_config_desc, + .strings = usbd_msc_strings +}; + +/* local function prototypes ('static') */ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index); +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index); +static uint8_t printer_req (usb_dev *udev, usb_req *req); +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num); +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num); + +usb_class_core usbd_printer_cb = { + .init = printer_init, + .deinit = printer_deinit, + + .req_proc = printer_req, + + .data_in = printer_in, + .data_out = printer_out +}; + +/*! + \brief initialize the printer device + \param[in] udev: pointer to usb device instance + \param[in] config_index: configuration index + \param[out] none + \retval usb device operation status +*/ +static uint8_t printer_init (usb_dev *udev, uint8_t config_index) +{ + /* initialize the data Tx endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epin)); + + /* initialize the data Rx endpoint */ + usbd_ep_setup (udev, &(printer_config_desc.printer_epout)); + + /* prepare to receive data */ + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + + return USBD_OK; +} + +/*! + \brief deinitialize the printer device + \param[in] udev: pointer to usb device instance + \param[in] config_index: configuration index + \param[out] none + \retval usb device operation status +*/ +static uint8_t printer_deinit (usb_dev *udev, uint8_t config_index) +{ + /* deinitialize the data Tx/Rx endpoint */ + usbd_ep_clear (udev, PRINTER_IN_EP); + usbd_ep_clear (udev, PRINTER_OUT_EP); + + return USBD_OK; +} + +/*! + \brief handle the printer class-specific requests + \param[in] udev: pointer to usb device instance + \param[in] req: device class-specific request + \param[out] none + \retval usb device operation status +*/ +static uint8_t printer_req(usb_dev *udev, usb_req *req) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (req->bRequest) { + case GET_DEVICE_ID: + transc->xfer_buf = (uint8_t *)PRINTER_DEVICE_ID; + transc->remain_len = DEVICE_ID_LEN; + break; + + case GET_PORT_STATUS: + transc->xfer_buf = (uint8_t *)&g_port_status; + transc->remain_len = 1U; + break; + + case SOFT_RESET: + usbd_ep_recev(udev, PRINTER_OUT_EP, g_printer_data_buf, PRINTER_OUT_PACKET); + break; + + default: + return USBD_FAIL; + } + + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_in (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} + +/*! + \brief handle printer data + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation status +*/ +static uint8_t printer_out (usb_dev *udev, uint8_t ep_num) +{ + return USBD_OK; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Include/usbd_core.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Include/usbd_core.h new file mode 100644 index 00000000..2ee25bd2 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Include/usbd_core.h @@ -0,0 +1,103 @@ +/*! + \file usbd_core.h + \brief USB device mode core functions prototype + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_CORE_H +#define __USBD_CORE_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +typedef enum +{ + USBD_OK = 0U, /*!< status OK */ + USBD_BUSY, /*!< status busy */ + USBD_FAIL /*!< status fail */ +} usbd_status; + +enum _usbd_status { + USBD_DEFAULT = 1U, /*!< default status */ + USBD_ADDRESSED = 2U, /*!< address send status */ + USBD_CONFIGURED = 3U, /*!< configured status */ + USBD_SUSPENDED = 4U /*!< suspended status */ +}; + +/* static inline function definitions */ + +/*! + \brief set USB device address + \param[in] udev: pointer to USB core instance + \param[in] addr: device address to set + \param[out] none + \retval none +*/ +__STATIC_INLINE void usbd_addr_set (usb_core_driver *udev, uint8_t addr) +{ + usb_devaddr_set(udev, addr); +} + +/*! + \brief get the received data length + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint number + \param[out] none + \retval USB device operation cur_status +*/ +__STATIC_INLINE uint16_t usbd_rxcount_get (usb_core_driver *udev, uint8_t ep_num) +{ + return (uint16_t)udev->dev.transc_out[ep_num].xfer_count; +} + +/* function declarations */ +/* initializes the USB device-mode stack and load the class driver */ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core); +/* endpoint initialization */ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc); +/* configure the endpoint when it is disabled */ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr); +/* endpoint prepare to receive data */ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* endpoint prepare to transmit data */ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len); +/* set an endpoint to STALL status */ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr); +/* clear endpoint STALLed status */ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr); +/* flush the endpoint FIFOs */ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr); +/* device connect */ +void usbd_connect (usb_core_driver *udev); +/* device disconnect */ +void usbd_disconnect (usb_core_driver *udev); + +#endif /* __USBD_CORE_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Include/usbd_enum.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Include/usbd_enum.h new file mode 100644 index 00000000..baccdef1 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Include/usbd_enum.h @@ -0,0 +1,106 @@ +/*! + \file usbd_enum.h + \brief USB enumeration definitions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_ENUM_H +#define __USBD_ENUM_H + +#include "usbd_core.h" +#include "usbd_conf.h" +#include + +#ifndef NULL + #define NULL 0U +#endif + +typedef enum _usb_reqsta +{ + REQ_SUPP = 0x0U, /* request support */ + REQ_NOTSUPP = 0x1U, /* request not support */ +} usb_reqsta; + +/* string descriptor index */ +enum _str_index +{ + STR_IDX_LANGID = 0x00U, /* language ID string index */ + STR_IDX_MFC = 0x01U, /* manufacturer string index */ + STR_IDX_PRODUCT = 0x02U, /* product string index */ + STR_IDX_SERIAL = 0x03U, /* serial string index */ + STR_IDX_CONFIG = 0x04U, /* configuration string index */ + STR_IDX_ITF = 0x05U, /* interface string index */ +#ifndef WINUSB_EXEMPT_DRIVER + STR_IDX_MAX = 0x0AU, /* string maximum index */ +#else + STR_IDX_MAX = 0xEFU, /* string maximum index */ +#endif /* WINUSB_EXEMPT_DRIVER */ +}; + +typedef enum _usb_pwrsta { + USB_PWRSTA_SELF_POWERED = 0x1U, /* USB is in self powered status */ + USB_PWRSTA_REMOTE_WAKEUP = 0x2U, /* USB is in remote wakeup status */ +} usb_pwrsta; + +typedef enum _usb_feature +{ + USB_FEATURE_EP_HALT = 0x0U, /* USB has endpoint halt feature */ + USB_FEATURE_REMOTE_WAKEUP = 0x1U, /* USB has endpoint remote wakeup feature */ + USB_FEATURE_TEST_MODE = 0x2U, /* USB has endpoint test mode feature */ +} usb_feature; + +#define ENG_LANGID 0x0409U /* english language ID */ +#define CHN_LANGID 0x0804U /* chinese language ID */ + +/* USB device exported macros */ +#define CTL_EP(ep) (((ep) == 0x00U) || ((ep) == 0x80U)) + +#define DEVICE_ID1 (0x1FFFF7E8U) /* device ID1 */ +#define DEVICE_ID2 (0x1FFFF7ECU) /* device ID2 */ +#define DEVICE_ID3 (0x1FFFF7F0U) /* device ID3 */ + +#define DEVICE_ID (0x40022100U) + +/* function declarations */ +/* handle USB standard device request */ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req); +/* handle USB device class request */ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req); +/* handle USB vendor request */ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req); +/* handle USB enumeration error */ +void usbd_enum_error (usb_core_driver *udev, usb_req *req); +/* convert hex 32bits value into unicode char */ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len); +/* get serial string */ +void serial_string_get (uint16_t *unicode_str); + +#endif /* __USBD_ENUM_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Include/usbd_transc.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Include/usbd_transc.h new file mode 100644 index 00000000..0271f9f1 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Include/usbd_transc.h @@ -0,0 +1,56 @@ +/*! + \file usbd_transc.h + \brief USB transaction core functions prototype + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBD_TRANSC_H +#define __USBD_TRANSC_H + +#include "usbd_core.h" + +/* function declarations */ +/* USB send data in the control transaction */ +usbd_status usbd_ctl_send (usb_core_driver *udev); +/* USB receive data in control transaction */ +usbd_status usbd_ctl_recev (usb_core_driver *udev); +/* USB send control transaction status */ +usbd_status usbd_ctl_status_send (usb_core_driver *udev); +/* USB control receive status */ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev); +/* USB setup stage processing */ +uint8_t usbd_setup_transc (usb_core_driver *udev); +/* data out stage processing */ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num); +/* data in stage processing */ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num); + +#endif /* __USBD_TRANSC_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Source/usbd_core.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Source/usbd_core.c new file mode 100644 index 00000000..0c11e42a --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Source/usbd_core.c @@ -0,0 +1,312 @@ +/*! + \file usbd_core.c + \brief USB device mode core functions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_core.h" +#include "usbd_enum.h" +#include "drv_usb_hw.h" + +/* endpoint type */ +const uint32_t ep_type[] = { + [USB_EP_ATTR_CTL] = (uint32_t)USB_EPTYPE_CTRL, + [USB_EP_ATTR_BULK] = (uint32_t)USB_EPTYPE_BULK, + [USB_EP_ATTR_INT] = (uint32_t)USB_EPTYPE_INTR, + [USB_EP_ATTR_ISO] = (uint32_t)USB_EPTYPE_ISOC +}; + +/*! + \brief initializes the USB device-mode stack and load the class driver + \param[in] udev: pointer to USB core instance + \param[in] core: USB core type + \param[in] desc: pointer to USB descriptor + \param[in] class_core: class driver + \param[out] none + \retval none +*/ +void usbd_init (usb_core_driver *udev, usb_core_enum core, usb_desc *desc, usb_class_core *class_core) +{ + udev->dev.desc = desc; + + /* class callbacks */ + udev->dev.class_core = class_core; + + /* create serial string */ + serial_string_get(udev->dev.desc->strings[STR_IDX_SERIAL]); + + /* configure USB capabilities */ + (void)usb_basic_init (&udev->bp, &udev->regs, core); + + usb_globalint_disable(&udev->regs); + + /* initializes the USB core*/ + (void)usb_core_init (udev->bp, &udev->regs); + + /* set device disconnect */ + usbd_disconnect (udev); + +#ifndef USE_OTG_MODE + usb_curmode_set(&udev->regs, DEVICE_MODE); +#endif /* USE_OTG_MODE */ + + /* initializes device mode */ + (void)usb_devcore_init (udev); + + usb_globalint_enable(&udev->regs); + + /* set device connect */ + usbd_connect (udev); + + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; +} + +/*! + \brief endpoint initialization + \param[in] udev: pointer to USB core instance + \param[in] ep_desc: pointer to endpoint descriptor + \param[out] none + \retval none +*/ +uint32_t usbd_ep_setup (usb_core_driver *udev, const usb_desc_ep *ep_desc) +{ + usb_transc *transc; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint16_t max_len = ep_desc->wMaxPacketSize; + + /* set endpoint direction */ + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + transc->ep_addr.dir = 1U; + } else { + transc = &udev->dev.transc_out[ep_addr]; + + transc->ep_addr.dir = 0U; + } + + transc->ep_addr.num = EP_ID(ep_addr); + transc->max_len = max_len; + transc->ep_type = (uint8_t)ep_type[ep_desc->bmAttributes & (uint8_t)USB_EPTYPE_MASK]; + + /* active USB endpoint function */ + (void)usb_transc_active (udev, transc); + + return 0U; +} + +/*! + \brief configure the endpoint when it is disabled + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + /* deactivate USB endpoint function */ + (void)usb_transc_deactivate (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to receive data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: user buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_recev (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_out[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + /* start the transfer */ + (void)usb_transc_outxfer (udev, transc); + + return 0U; +} + +/*! + \brief endpoint prepare to transmit data + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[in] pbuf: transmit buffer address pointer + \param[in] len: buffer length + \param[out] none + \retval none +*/ +uint32_t usbd_ep_send (usb_core_driver *udev, uint8_t ep_addr, uint8_t *pbuf, uint32_t len) +{ + usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + + /* setup the transfer */ + transc->xfer_buf = pbuf; + transc->xfer_len = len; + transc->xfer_count = 0U; + + /* start the transfer */ + (void)usb_transc_inxfer (udev, transc); + + return 0U; +} + +/*! + \brief set an endpoint to STALL status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 1U; + + (void)usb_transc_stall (udev, transc); + + return (0U); +} + +/*! + \brief clear endpoint STALLed status + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_ep_stall_clear (usb_core_driver *udev, uint8_t ep_addr) +{ + usb_transc *transc = NULL; + + if (EP_DIR(ep_addr)) { + transc = &udev->dev.transc_in[EP_ID(ep_addr)]; + } else { + transc = &udev->dev.transc_out[ep_addr]; + } + + transc->ep_stall = 0U; + + (void)usb_transc_clrstall (udev, transc); + + return (0U); +} + +/*! + \brief flush the endpoint FIFOs + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + in this parameter: + bit0..bit6: endpoint number (0..7) + bit7: endpoint direction which can be IN(1) or OUT(0) + \param[out] none + \retval none +*/ +uint32_t usbd_fifo_flush (usb_core_driver *udev, uint8_t ep_addr) +{ + if (EP_DIR(ep_addr)) { + (void)usb_txfifo_flush (&udev->regs, EP_ID(ep_addr)); + } else { + (void)usb_rxfifo_flush (&udev->regs); + } + + return (0U); +} + +/*! + \brief device connect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_connect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* connect device */ + usb_dev_connect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} + +/*! + \brief device disconnect + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_disconnect (usb_core_driver *udev) +{ +#ifndef USE_OTG_MODE + /* disconnect device for 3ms */ + usb_dev_disconnect (udev); + + usb_mdelay(3U); +#endif /* USE_OTG_MODE */ +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Source/usbd_enum.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Source/usbd_enum.c new file mode 100644 index 00000000..5fa9f3ab --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Source/usbd_enum.c @@ -0,0 +1,764 @@ +/*! + \file usbd_enum.c + \brief USB enumeration function + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usb_ch9_std.h" + +#ifdef WINUSB_EXEMPT_DRIVER + +extern usbd_status usbd_OEM_req(usb_dev *udev, usb_req *req); + +#endif /* WINUSB_EXEMPT_DRIVER */ + +/* local function prototypes ('static') */ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req); +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len); +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req); +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req); + +static usb_reqsta (*_std_dev_req[])(usb_core_driver *udev, usb_req *req) = +{ + [USB_GET_STATUS] = _usb_std_getstatus, + [USB_CLEAR_FEATURE] = _usb_std_clearfeature, + [USB_RESERVED2] = _usb_std_reserved, + [USB_SET_FEATURE] = _usb_std_setfeature, + [USB_RESERVED4] = _usb_std_reserved, + [USB_SET_ADDRESS] = _usb_std_setaddress, + [USB_GET_DESCRIPTOR] = _usb_std_getdescriptor, + [USB_SET_DESCRIPTOR] = _usb_std_setdescriptor, + [USB_GET_CONFIGURATION] = _usb_std_getconfiguration, + [USB_SET_CONFIGURATION] = _usb_std_setconfiguration, + [USB_GET_INTERFACE] = _usb_std_getinterface, + [USB_SET_INTERFACE] = _usb_std_setinterface, + [USB_SYNCH_FRAME] = _usb_std_synchframe, +}; + +/* get standard descriptor handler */ +static uint8_t* (*std_desc_get[])(usb_core_driver *udev, uint8_t index, uint16_t *len) = { + [(uint8_t)USB_DESCTYPE_DEV - 1U] = _usb_dev_desc_get, + [(uint8_t)USB_DESCTYPE_CONFIG - 1U] = _usb_config_desc_get, + [(uint8_t)USB_DESCTYPE_STR - 1U] = _usb_str_desc_get, +}; + +/*! + \brief handle USB standard device request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_standard_request (usb_core_driver *udev, usb_req *req) +{ + return (*_std_dev_req[req->bRequest])(udev, req); +} + +/*! + \brief handle USB device class request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device class request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_class_request (usb_core_driver *udev, usb_req *req) +{ + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + /* call device class handle function */ + return (usb_reqsta)udev->dev.class_core->req_proc(udev, req); + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB vendor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +usb_reqsta usbd_vendor_request (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* added by user... */ +#ifdef WINUSB_EXEMPT_DRIVER + usbd_OEM_req(udev, req); +#endif + + return REQ_SUPP; +} + +/*! + \brief handle USB enumeration error + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval none +*/ +void usbd_enum_error (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + (void)usbd_ep_stall (udev, 0x80U); + (void)usbd_ep_stall (udev, 0x00U); + + usb_ctlep_startout(udev); +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] value: hex 32bits value + \param[in] pbuf: buffer pointer to store unicode char + \param[in] len: value length + \param[out] none + \retval none +*/ +void int_to_unicode (uint32_t value, uint8_t *pbuf, uint8_t len) +{ + uint8_t index; + + for (index = 0U; index < len; index++) { + if ((value >> 28U) < 0x0AU) { + pbuf[2U * index] = (uint8_t)((value >> 28U) + '0'); + } else { + pbuf[2U * index] = (uint8_t)((value >> 28U) + 'A' - 10U); + } + + value = value << 4U; + + pbuf[2U * index + 1U] = 0U; + } +} + +/*! + \brief convert hex 32bits value into unicode char + \param[in] unicode_str: pointer to unicode string + \param[out] none + \retval none +*/ +void serial_string_get (uint16_t *unicode_str) +{ + if ((unicode_str[0] & 0x00FFU) != 6U) { + uint32_t DeviceSerial0, DeviceSerial1, DeviceSerial2; + + DeviceSerial0 = *(uint32_t*)DEVICE_ID1; + DeviceSerial1 = *(uint32_t*)DEVICE_ID2; + DeviceSerial2 = *(uint32_t*)DEVICE_ID3; + + DeviceSerial0 += DeviceSerial2; + + if (0U != DeviceSerial0) { + int_to_unicode(DeviceSerial0, (uint8_t*)&(unicode_str[1]), 8U); + int_to_unicode(DeviceSerial1, (uint8_t*)&(unicode_str[9]), 4U); + } + } else { + uint32_t device_serial = *(uint32_t*)DEVICE_ID; + + if(0U != device_serial) { + unicode_str[1] = (uint16_t)(device_serial & 0x0000FFFFU); + unicode_str[2] = (uint16_t)((device_serial & 0xFFFF0000U) >> 16U); + + } + } +} + +/*! + \brief no operation, just for reserved + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB vendor request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_reserved (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no operation... */ + + return REQ_NOTSUPP; +} + +/*! + \brief get the device descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_dev_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->dev_desc[0]; + + return udev->dev.desc->dev_desc; +} + +/*! + \brief get the configuration descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_config_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->config_desc[2] | (udev->dev.desc->config_desc[3]<< 8U); + + return udev->dev.desc->config_desc; +} + +/*! + \brief get the BOS descriptor + \brief[in] udev: pointer to USB device instance + \brief[in] index: no use + \param[out] len: data length pointer + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_bos_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + (void)index; + + *len = udev->dev.desc->bos_desc[2]; + + return udev->dev.desc->bos_desc; +} + +/*! + \brief get string descriptor + \param[in] udev: pointer to USB device instance + \param[in] index: string descriptor index + \param[out] len: pointer to string length + \retval descriptor buffer pointer +*/ +static uint8_t* _usb_str_desc_get (usb_core_driver *udev, uint8_t index, uint16_t *len) +{ + uint8_t *desc = udev->dev.desc->strings[index]; + + *len = desc[0]; + + return desc; +} + +/*! + \brief handle Get_Status request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getstatus (usb_core_driver *udev, usb_req *req) +{ + uint8_t recp = BYTE_LOW(req->wIndex); + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + static uint8_t status[2] = {0}; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + if (udev->dev.pm.power_mode) { + status[0] = USB_STATUS_SELF_POWERED; + } else { + status[0] = 0U; + } + + if (udev->dev.pm.dev_remote_wakeup) { + status[0] |= USB_STATUS_REMOTE_WAKEUP; + } else { + status[0] = 0U; + } + + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + if (((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) && (recp <= USBD_ITF_MAX_NUM)) { + req_status = REQ_SUPP; + } + break; + + case USB_RECPTYPE_EP: + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + if (0x80U == (recp & 0x80U)) { + status[0] = udev->dev.transc_in[EP_ID(recp)].ep_stall; + } else { + status[0] = udev->dev.transc_out[recp].ep_stall; + } + + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = status; + transc->remain_len = 2U; + } + + return req_status; +} + +/*! + \brief handle USB Clear_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_clearfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch(req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + + /* clear device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 0U; + + return REQ_SUPP; + } + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* clear endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall_clear (udev, ep); + + (void)udev->dev.class_core->req_proc (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Feature request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setfeature (usb_core_driver *udev, usb_req *req) +{ + uint8_t ep = 0U; + + switch (req->bmRequestType & (uint8_t)USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + if (((uint8_t)USBD_ADDRESSED == udev->dev.cur_status) || \ + ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status)) { + /* set device remote wakeup feature */ + if ((uint16_t)USB_FEATURE_REMOTE_WAKEUP == req->wValue) { + udev->dev.pm.dev_remote_wakeup = 1U; + } + + return REQ_SUPP; + } + break; + + case USB_RECPTYPE_ITF: + break; + + case USB_RECPTYPE_EP: + /* get endpoint address */ + ep = BYTE_LOW(req->wIndex); + + if ((uint8_t)USBD_CONFIGURED == udev->dev.cur_status) { + /* set endpoint halt feature */ + if (((uint16_t)USB_FEATURE_EP_HALT == req->wValue) && (!CTL_EP(ep))) { + (void)usbd_ep_stall (udev, ep); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Address request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setaddress (usb_core_driver *udev, usb_req *req) +{ + if ((0U == req->wIndex) && (0U == req->wLength)) { + udev->dev.dev_addr = (uint8_t)(req->wValue) & 0x7FU; + + if (udev->dev.cur_status != (uint8_t)USBD_CONFIGURED) { + usbd_addr_set (udev, udev->dev.dev_addr); + + if (udev->dev.dev_addr) { + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else { + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + } + + return REQ_SUPP; + } + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Get_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getdescriptor (usb_core_driver *udev, usb_req *req) +{ + uint8_t desc_type = 0U; + uint8_t desc_index = 0U; + + usb_reqsta status = REQ_NOTSUPP; + + usb_transc *transc = &udev->dev.transc_in[0]; + + /* get device standard descriptor */ + switch (req->bmRequestType & USB_RECPTYPE_MASK) { + case USB_RECPTYPE_DEV: + desc_type = BYTE_HIGH(req->wValue); + desc_index = BYTE_LOW(req->wValue); + + switch (desc_type) { + case USB_DESCTYPE_DEV: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + + if (64U == req->wLength) { + transc->remain_len = 8U; + } + break; + + case USB_DESCTYPE_CONFIG: + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + case USB_DESCTYPE_STR: + if (desc_index < (uint8_t)STR_IDX_MAX) { + transc->xfer_buf = std_desc_get[desc_type - 1U](udev, desc_index, (uint16_t *)&(transc->remain_len)); + } + break; + + case USB_DESCTYPE_ITF: + case USB_DESCTYPE_EP: + case USB_DESCTYPE_DEV_QUALIFIER: + case USB_DESCTYPE_OTHER_SPD_CONFIG: + case USB_DESCTYPE_ITF_POWER: + break; + + case USB_DESCTYPE_BOS: + transc->xfer_buf = _usb_bos_desc_get(udev, desc_index, (uint16_t *)&(transc->remain_len)); + break; + + default: + break; + } + break; + + case USB_RECPTYPE_ITF: + /* get device class special descriptor */ + status = (usb_reqsta)(udev->dev.class_core->req_proc(udev, req)); + break; + + case USB_RECPTYPE_EP: + break; + + default: + break; + } + + if ((0U != transc->remain_len) && (0U != req->wLength)) { + if (transc->remain_len < req->wLength) { + if ((transc->remain_len >= transc->max_len) && (0U == (transc->remain_len % transc->max_len))) { + udev->dev.control.ctl_zlp = 1U; + } + } else { + transc->remain_len = req->wLength; + } + + status = REQ_SUPP; + } + + return status; +} + +/*! + \brief handle USB Set_Descriptor request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setdescriptor (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle... */ + return REQ_SUPP; +} + +/*! + \brief handle USB Get_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getconfiguration (usb_core_driver *udev, usb_req *req) +{ + (void)req; + + usb_reqsta req_status = REQ_NOTSUPP; + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (USB_DEFAULT_CONFIG == udev->dev.config) { + req_status = REQ_SUPP; + } + break; + + case USBD_CONFIGURED: + if (udev->dev.config != USB_DEFAULT_CONFIG) { + req_status = REQ_SUPP; + } + break; + + default: + break; + } + + if (REQ_SUPP == req_status) { + transc->xfer_buf = &(udev->dev.config); + transc->remain_len = 1U; + } + + return req_status; +} + +/*! + \brief handle USB Set_Configuration request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setconfiguration (usb_core_driver *udev, usb_req *req) +{ + static uint8_t config; + usb_reqsta status = REQ_NOTSUPP; + + config = (uint8_t)(req->wValue); + + if (config <= USBD_CFG_MAX_NUM) { + switch (udev->dev.cur_status) { + case USBD_ADDRESSED: + if (config){ + (void)udev->dev.class_core->init(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_CONFIGURED; + } + + status = REQ_SUPP; + break; + + case USBD_CONFIGURED: + if (USB_DEFAULT_CONFIG == config) { + (void)udev->dev.class_core->deinit(udev, config); + + udev->dev.config = config; + udev->dev.cur_status = (uint8_t)USBD_ADDRESSED; + } else if (config != udev->dev.config) { + /* clear old configuration */ + (void)udev->dev.class_core->deinit(udev, config); + + /* set new configuration */ + udev->dev.config = config; + + (void)udev->dev.class_core->init(udev, config); + } else { + /* no operation */ + } + + status = REQ_SUPP; + break; + + case USBD_DEFAULT: + break; + + default: + break; + } + } + + return status; +} + +/*! + \brief handle USB Get_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_getinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + usb_transc *transc = &udev->dev.transc_in[0]; + + transc->xfer_buf = &(udev->dev.class_core->alter_set); + transc->remain_len = 1U; + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB Set_Interface request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_setinterface (usb_core_driver *udev, usb_req *req) +{ + switch (udev->dev.cur_status) { + case USBD_DEFAULT: + break; + + case USBD_ADDRESSED: + break; + + case USBD_CONFIGURED: + if (BYTE_LOW(req->wIndex) <= USBD_ITF_MAX_NUM) { + if (NULL != udev->dev.class_core->set_intf) { + (void)udev->dev.class_core->set_intf (udev, req); + } + + return REQ_SUPP; + } + break; + + default: + break; + } + + return REQ_NOTSUPP; +} + +/*! + \brief handle USB SynchFrame request + \param[in] udev: pointer to USB device instance + \param[in] req: pointer to USB device request + \param[out] none + \retval USB device request status +*/ +static usb_reqsta _usb_std_synchframe (usb_core_driver *udev, usb_req *req) +{ + (void)udev; + (void)req; + + /* no handle */ + return REQ_SUPP; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Source/usbd_transc.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Source/usbd_transc.c new file mode 100644 index 00000000..04a77b81 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/device/core/Source/usbd_transc.c @@ -0,0 +1,256 @@ +/*! + \file usbd_transc.c + \brief USB transaction core functions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_enum.h" +#include "usbd_transc.h" + +/*! + \brief USB send data in the control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_send (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_in[0]; + + (void)usbd_ep_send(udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_IN; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_IN; + } + + return USBD_OK; +} + +/*! + \brief USB receive data in control transaction + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_recev (usb_core_driver *udev) +{ + usb_transc *transc = &udev->dev.transc_out[0]; + + (void)usbd_ep_recev (udev, 0U, transc->xfer_buf, transc->remain_len); + + if (transc->remain_len > transc->max_len) { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_DATA_OUT; + } else { + udev->dev.control.ctl_state = (uint8_t)USB_CTL_LAST_DATA_OUT; + } + + return USBD_OK; +} + +/*! + \brief USB send control transaction status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_send (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_IN; + + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB control receive status + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +usbd_status usbd_ctl_status_recev (usb_core_driver *udev) +{ + udev->dev.control.ctl_state = (uint8_t)USB_CTL_STATUS_OUT; + + (void)usbd_ep_recev (udev, 0U, NULL, 0U); + + usb_ctlep_startout(udev); + + return USBD_OK; +} + +/*! + \brief USB setup stage processing + \param[in] udev: pointer to USB device instance + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_setup_transc (usb_core_driver *udev) +{ + usb_reqsta reqstat = REQ_NOTSUPP; + + usb_req req = udev->dev.control.req; + + switch (req.bmRequestType & USB_REQTYPE_MASK) { + /* standard device request */ + case USB_REQTYPE_STRD: + reqstat = usbd_standard_request (udev, &req); + break; + + /* device class request */ + case USB_REQTYPE_CLASS: + reqstat = usbd_class_request (udev, &req); + break; + + /* vendor defined request */ + case USB_REQTYPE_VENDOR: + reqstat = usbd_vendor_request (udev, &req); + break; + + default: + break; + } + + if (REQ_SUPP == reqstat) { + if (0U == req.wLength) { + (void)usbd_ctl_status_send (udev); + } else { + if (req.bmRequestType & 0x80U) { + (void)usbd_ctl_send (udev); + } else { + (void)usbd_ctl_recev (udev); + } + } + } else { + usbd_enum_error (udev, &req); + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data out stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_out_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_out[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_OUT: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + (void)usbd_ctl_recev (udev); + break; + + case USB_CTL_LAST_DATA_OUT: + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->ctlx_out != NULL) { + (void)udev->dev.class_core->ctlx_out (udev); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_send (udev); + break; + + default: + break; + } + } else if ((udev->dev.class_core->data_out != NULL) && (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED)) { + (void)udev->dev.class_core->data_out (udev, ep_num); + } else { + /* no operation */ + } + + return (uint8_t)USBD_OK; +} + +/*! + \brief data in stage processing + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier(0..7) + \param[out] none + \retval USB device operation cur_status +*/ +uint8_t usbd_in_transc (usb_core_driver *udev, uint8_t ep_num) +{ + if (0U == ep_num) { + usb_transc *transc = &udev->dev.transc_in[0]; + + switch (udev->dev.control.ctl_state) { + case USB_CTL_DATA_IN: + /* update transfer length */ + transc->remain_len -= transc->max_len; + + (void)usbd_ctl_send (udev); + break; + + case USB_CTL_LAST_DATA_IN: + /* last packet is MPS multiple, so send ZLP packet */ + if (udev->dev.control.ctl_zlp) { + (void)usbd_ep_send (udev, 0U, NULL, 0U); + + udev->dev.control.ctl_zlp = 0U; + } else { + if (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) { + if (udev->dev.class_core->ctlx_in != NULL) { + (void)udev->dev.class_core->ctlx_in (udev); + } + } + + transc->remain_len = 0U; + + (void)usbd_ctl_status_recev (udev); + } + break; + + default: + break; + } + } else { + if ((udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) && (udev->dev.class_core->data_in != NULL)) { + (void)udev->dev.class_core->data_in (udev, ep_num); + } + } + + return (uint8_t)USBD_OK; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_core.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_core.h new file mode 100644 index 00000000..8ac36500 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_core.h @@ -0,0 +1,347 @@ +/*! + \file drv_usb_core.h + \brief USB core low level driver header file + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_CORE_H +#define __DRV_USB_CORE_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" + +#ifdef USE_DEVICE_MODE + #include "usbd_conf.h" +#endif /* USE_DEVICE_MODE */ + +#define USB_FS_EP0_MAX_LEN 64U /*!< maximum packet size of endpoint 0 */ +#define HC_MAX_PACKET_COUNT 140U /*!< maximum packet count */ + +#define EP_ID(x) ((uint8_t)((x) & 0x7FU)) /*!< endpoint number */ +#define EP_DIR(x) ((uint8_t)((x) >> 7)) /*!< endpoint direction */ + +enum _usb_mode { + DEVICE_MODE = 0U, /*!< device mode */ + HOST_MODE, /*!< host mode */ + OTG_MODE /*!< OTG mode */ +}; + +enum _usb_eptype { + USB_EPTYPE_CTRL = 0U, /*!< control endpoint type */ + USB_EPTYPE_ISOC = 1U, /*!< isochronous endpoint type */ + USB_EPTYPE_BULK = 2U, /*!< bulk endpoint type */ + USB_EPTYPE_INTR = 3U, /*!< interrupt endpoint type */ + USB_EPTYPE_MASK = 3U /*!< endpoint type mask */ +}; + +typedef enum +{ + USB_OTG_OK = 0U, /*!< USB OTG status OK*/ + USB_OTG_FAIL /*!< USB OTG status fail*/ +} usb_otg_status; + +typedef enum +{ + USB_OK = 0U, /*!< USB status OK*/ + USB_FAIL /*!< USB status fail*/ +} usb_status; + +typedef enum +{ + USB_USE_FIFO, /*!< USB use FIFO transfer mode */ +} usb_transfer_mode; + +typedef struct +{ + uint8_t core_enum; /*!< USB core type */ + uint8_t core_speed; /*!< USB core speed */ + uint8_t num_pipe; /*!< USB host channel numbers */ + uint8_t num_ep; /*!< USB device endpoint numbers */ + uint8_t transfer_mode; /*!< USB transfer mode */ + uint8_t phy_itf; /*!< USB core PHY interface */ + uint8_t sof_enable; /*!< USB SOF output */ + uint8_t low_power; /*!< USB low power */ + uint8_t lpm_enable; /*!< USB link power mode(LPM) */ + uint8_t vbus_sensing_enable; /*!< USB VBUS sensing feature */ + uint8_t use_dedicated_ep1; /*!< USB dedicated endpoint1 interrupt */ + uint8_t use_external_vbus; /*!< enable or disable the use of the external VBUS */ + uint32_t base_reg; /*!< base register address */ +} usb_core_basic; + +#ifdef USE_DEVICE_MODE + +/* USB descriptor */ +typedef struct _usb_desc { + uint8_t *dev_desc; /*!< device descriptor */ + uint8_t *config_desc; /*!< configure descriptor */ + uint8_t *bos_desc; /*!< BOS descriptor */ + void* const *strings; /*!< string descriptor */ +} usb_desc; + +/* USB power management */ +typedef struct _usb_pm { + uint8_t power_mode; /*!< power mode */ + uint8_t power_low; /*!< power low */ + uint8_t dev_remote_wakeup; /*!< remote wakeup */ + uint8_t remote_wakeup_on; /*!< remote wakeup on */ +} usb_pm; + +/* USB control information */ +typedef struct _usb_control { + usb_req req; /*!< USB standard device request */ + + uint8_t ctl_state; /*!< USB control transfer state */ + uint8_t ctl_zlp; /*!< zero length package */ +} usb_control; + +typedef struct +{ + struct { + uint8_t num: 4; /*!< the endpoint number.it can be from 0 to 6 */ + uint8_t pad: 3; /*!< padding between number and direction */ + uint8_t dir: 1; /*!< the endpoint direction */ + } ep_addr; + + uint8_t ep_type; /*!< USB endpoint type */ + uint8_t ep_stall; /*!< USB endpoint stall status */ + + uint8_t frame_num; /*!< number of frame */ + uint16_t max_len; /*!< Maximum packet length */ + + /* transaction level variables */ + uint8_t *xfer_buf; /*!< transmit buffer */ + uint32_t xfer_len; /*!< transmit buffer length */ + uint32_t xfer_count; /*!< transmit buffer count */ + + uint32_t remain_len; /*!< remain packet length */ +} usb_transc; + +typedef struct _usb_core_driver usb_dev; + +typedef struct _usb_class_core +{ + uint8_t command; /*!< device class request command */ + uint8_t alter_set; /*!< alternative set */ + + uint8_t (*init) (usb_dev *udev, uint8_t config_index); /*!< initialize handler */ + uint8_t (*deinit) (usb_dev *udev, uint8_t config_index); /*!< de-initialize handler */ + + uint8_t (*req_proc) (usb_dev *udev, usb_req *req); /*!< device request handler */ + + uint8_t (*set_intf) (usb_dev *udev, usb_req *req); /*!< device set interface callback */ + + uint8_t (*ctlx_in) (usb_dev *udev); /*!< device contrl in callback */ + uint8_t (*ctlx_out) (usb_dev *udev); + + uint8_t (*data_in) (usb_dev *udev, uint8_t ep_num); /*!< device data in handler */ + uint8_t (*data_out) (usb_dev *udev, uint8_t ep_num); /*!< device data out handler */ + + uint8_t (*SOF) (usb_dev *udev); /*!< Start of frame handler */ + + uint8_t (*incomplete_isoc_in) (usb_dev *udev); /*!< Incomplete synchronization IN transfer handler */ + uint8_t (*incomplete_isoc_out) (usb_dev *udev); /*!< Incomplete synchronization OUT transfer handler */ +} usb_class_core; + +typedef struct _usb_perp_dev +{ + uint8_t config; /*!< configuration */ + uint8_t dev_addr; /*!< device address */ + + __IO uint8_t cur_status; /*!< current status */ + __IO uint8_t backup_status; /*!< backup status */ + + usb_transc transc_in[USBFS_MAX_TX_FIFOS]; /*!< endpoint IN transaction */ + usb_transc transc_out[USBFS_MAX_TX_FIFOS]; /*!< endpoint OUT transaction */ + + usb_pm pm; /*!< power management */ + usb_control control; /*!< USB control information */ + usb_desc *desc; /*!< USB descriptors pointer */ + usb_class_core *class_core; /*!< class driver */ + void *class_data[USBD_ITF_MAX_NUM]; /*!< class data pointer */ + void *user_data; /*!< user data pointer */ + void *pdata; /*!< reserved data pointer */ +} usb_perp_dev; + +#endif /* USE_DEVICE_MODE */ + +#ifdef USE_HOST_MODE + +typedef enum _usb_pipe_status +{ + PIPE_IDLE = 0U, + PIPE_XF, + PIPE_HALTED, + PIPE_NAK, + PIPE_NYET, + PIPE_STALL, + PIPE_TRACERR, + PIPE_BBERR, + PIPE_REQOVR, + PIPE_DTGERR, +} usb_pipe_staus; + +typedef enum _usb_urb_state +{ + URB_IDLE = 0U, + URB_DONE, + URB_NOTREADY, + URB_ERROR, + URB_STALL, + URB_PING +} usb_urb_state; + +typedef struct _usb_pipe +{ + uint8_t in_used; + uint8_t dev_addr; + uint32_t dev_speed; + + struct { + uint8_t num; + uint8_t dir; + uint8_t type; + uint16_t mps; + } ep; + + __IO uint8_t supp_ping; + __IO uint8_t do_ping; + __IO uint32_t DPID; + + uint8_t *xfer_buf; + uint32_t xfer_len; + uint32_t xfer_count; + + uint8_t data_toggle_in; + uint8_t data_toggle_out; + + __IO uint32_t err_count; + __IO usb_pipe_staus pp_status; + __IO usb_urb_state urb_state; +} usb_pipe; + +typedef struct _usb_host_drv +{ + __IO uint32_t connect_status; + __IO uint32_t port_enabled; + __IO uint32_t backup_xfercount[USBFS_MAX_TX_FIFOS]; + + usb_pipe pipe[USBFS_MAX_TX_FIFOS]; + void *data; +} usb_host_drv; + +#endif /* USE_HOST_MODE */ + +typedef struct _usb_core_driver +{ + usb_core_basic bp; /*!< USB basic parameters */ + usb_core_regs regs; /*!< USB registers */ + +#ifdef USE_DEVICE_MODE + usb_perp_dev dev; /*!< USB peripheral device */ +#endif /* USE_DEVICE_MODE */ + +#ifdef USE_HOST_MODE + usb_host_drv host; +#endif /* USE_HOST_MODE */ +} usb_core_driver; + +/* static inline function definitions */ + +/*! + \brief get the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_coreintr_get(usb_core_regs *usb_regs) +{ + uint32_t reg_data = usb_regs->gr->GINTEN; + + reg_data &= usb_regs->gr->GINTF; + + return reg_data; +} + +/*! + \brief set USB RX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] size: assigned FIFO size + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_set_rxfifo(usb_core_regs *usb_regs, uint16_t size) +{ + usb_regs->gr->GRFLEN = size; +} + +/*! + \brief enable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_enable(usb_core_regs *usb_regs) +{ + /* enable USB global interrupt */ + usb_regs->gr->GAHBCS |= GAHBCS_GINTEN; +} + +/*! + \brief disable the global interrupts + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_globalint_disable(usb_core_regs *usb_regs) +{ + /* disable USB global interrupt */ + usb_regs->gr->GAHBCS &= ~GAHBCS_GINTEN; +} + +/* function declarations */ +/* configure core capabilities */ +usb_status usb_basic_init (usb_core_basic *usb_basic, usb_core_regs *usb_regs, usb_core_enum usb_core); +/* initializes the USB controller registers and prepares the core device mode or host mode operation */ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs); +/* write a packet into the Tx FIFO associated with the endpoint */ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, uint8_t *src_buf, uint8_t fifo_num, uint16_t byte_count); +/* read a packet from the Rx FIFO associated with the endpoint */ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count); +/* flush a Tx FIFO or all Tx FIFOs */ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num); +/* flush the entire Rx FIFO */ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs); +/* set endpoint or channel TX FIFO size */ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size); +/* set USB current mode */ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode); + +#endif /* __DRV_USB_CORE_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_dev.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_dev.h new file mode 100644 index 00000000..655ed160 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_dev.h @@ -0,0 +1,197 @@ +/*! + \file drv_usb_dev.h + \brief USB device low level driver header file + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_DEV_H +#define __DRV_USB_DEV_H + +#include "usbd_conf.h" +#include "drv_usb_core.h" + +#define EP_IN(x) ((uint8_t)(0x80U | (x))) /*!< device IN endpoint */ +#define EP_OUT(x) ((uint8_t)(x)) /*!< device OUT endpoint */ + +enum usb_ctl_status { + USB_CTL_IDLE = 0U, /*!< USB control transfer idle state */ + USB_CTL_DATA_IN, /*!< USB control transfer data in state */ + USB_CTL_LAST_DATA_IN, /*!< USB control transfer last data in state */ + USB_CTL_DATA_OUT, /*!< USB control transfer data out state */ + USB_CTL_LAST_DATA_OUT, /*!< USB control transfer last data out state */ + USB_CTL_STATUS_IN, /*!< USB control transfer status in state*/ + USB_CTL_STATUS_OUT /*!< USB control transfer status out state */ +}; + +/* static inline function definitions */ + +/*! + \brief configure the USB device to be disconnected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_disconnect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL |= DCTL_SD; +} + +/*! + \brief configure the USB device to be connected + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_dev_connect (usb_core_driver *udev) +{ + udev->regs.dr->DCTL &= ~DCTL_SD; +} + +/*! + \brief set the USB device address + \param[in] udev: pointer to USB device + \param[in] dev_addr: device address for setting + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usb_devaddr_set (usb_core_driver *udev, uint8_t dev_addr) +{ + udev->regs.dr->DCFG &= ~DCFG_DAR; + udev->regs.dr->DCFG |= (uint32_t)dev_addr << 4U; +} + +/*! + \brief read device all OUT endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return (value & DAEPINT_OEPITB) >> 16U; +} + +/*! + \brief read device OUT endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_oepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = udev->regs.er_out[ep_num]->DOEPINTF; + + value &= udev->regs.dr->DOEPINTEN; + + return value; +} + +/*! + \brief read device all IN endpoint interrupt register + \param[in] udev: pointer to USB device + \param[out] none + \retval interrupt status +*/ +__STATIC_INLINE uint32_t usb_iepintnum_read (usb_core_driver *udev) +{ + uint32_t value = udev->regs.dr->DAEPINT; + + value &= udev->regs.dr->DAEPINTEN; + + return value & DAEPINT_IEPITB; +} + +/*! + \brief set remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_set (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* enable remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + } +} + +/*! + \brief reset remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_rwkup_reset (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + /* disable remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } +} + +/* function declarations */ +/* initialize USB core registers for device mode */ +usb_status usb_devcore_init (usb_core_driver *udev); +/* enable the USB device mode interrupts */ +usb_status usb_devint_enable (usb_core_driver *udev); +/* active the USB endpoint 0 transaction */ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc); +/* active the USB transaction */ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc); +/* deactivate the USB transaction */ +usb_status usb_transc_deactivate (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start IN transfer */ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc); +/* configure USB transaction to start OUT transfer */ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc); +/* set the USB transaction STALL status */ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc); +/* clear the USB transaction STALL status */ +usb_status usb_transc_clrstall (usb_core_driver *udev, usb_transc *transc); +/* read device IN endpoint interrupt flag register */ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num); +/* configures OUT endpoint 0 to receive SETUP packets */ +void usb_ctlep_startout (usb_core_driver *udev); +/* active remote wakeup signaling */ +void usb_rwkup_active (usb_core_driver *udev); +/* active USB core clock */ +void usb_clock_active (usb_core_driver *udev); +/* USB device suspend */ +void usb_dev_suspend (usb_core_driver *udev); +/* stop the device and clean up FIFOs */ +void usb_dev_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_DEV_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_host.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_host.h new file mode 100644 index 00000000..9d612d04 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_host.h @@ -0,0 +1,123 @@ +/*! + \file drv_usb_host.h + \brief USB host mode low level driver header file + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HOST_H +#define __DRV_USB_HOST_H + +#include "drv_usb_regs.h" +#include "usb_ch9_std.h" +#include "drv_usb_core.h" + +typedef enum _usb_pipe_mode +{ + PIPE_PERIOD = 0U, + PIPE_NON_PERIOD = 1U +} usb_pipe_mode; + +/*! + \brief get USB even frame + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +__STATIC_INLINE uint8_t usb_frame_even (usb_core_driver *udev) +{ + return (uint8_t)!(udev->regs.hr->HFINFR & 0x01U); +} + +/*! + \brief configure USB clock of PHY + \param[in] udev: pointer to USB device + \param[in] clock: PHY clock + \param[out] none + \retval none +*/ +__STATIC_INLINE void usb_phyclock_config (usb_core_driver *udev, uint8_t clock) +{ + udev->regs.hr->HCTL &= ~HCTL_CLKSEL; + udev->regs.hr->HCTL |= clock; +} + +/*! + \brief read USB port + \param[in] udev: pointer to USB device + \param[out] none + \retval port status +*/ +__STATIC_INLINE uint32_t usb_port_read (usb_core_driver *udev) +{ + return *udev->regs.HPCS & ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); +} + +/*! + \brief get USB current speed + \param[in] udev: pointer to USB device + \param[out] none + \retval USB current speed +*/ +__STATIC_INLINE uint32_t usb_curspeed_get (usb_core_driver *udev) +{ + return *udev->regs.HPCS & HPCS_PS; +} + +/*! + \brief get USB current frame + \param[in] udev: pointer to USB device + \param[out] none + \retval USB current frame +*/ +__STATIC_INLINE uint32_t usb_curframe_get (usb_core_driver *udev) +{ + return (udev->regs.hr->HFINFR & 0xFFFFU); +} + +/* function declarations */ +/* initializes USB core for host mode */ +usb_status usb_host_init (usb_core_driver *udev); +/* control the VBUS to power */ +void usb_portvbus_switch (usb_core_driver *udev, uint8_t state); +/* reset host port */ +uint32_t usb_port_reset (usb_core_driver *udev); +/* initialize host pipe */ +usb_status usb_pipe_init (usb_core_driver *udev, uint8_t pipe_num); +/* prepare host pipe for transferring packets */ +usb_status usb_pipe_xfer (usb_core_driver *udev, uint8_t pipe_num); +/* halt host pipe */ +usb_status usb_pipe_halt (usb_core_driver *udev, uint8_t pipe_num); +/* configure host pipe to do ping operation */ +usb_status usb_pipe_ping (usb_core_driver *udev, uint8_t pipe_num); +/* stop the USB host and clean up FIFO */ +void usb_host_stop (usb_core_driver *udev); + +#endif /* __DRV_USB_HOST_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_hw.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_hw.h new file mode 100644 index 00000000..2eb6e7c9 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_hw.h @@ -0,0 +1,63 @@ +/*! + \file drv_usb_hw.h + \brief usb hardware configuration header file + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_HW_H +#define __DRV_USB_HW_H + +#include "usb_conf.h" + +/* function declarations */ +/* configure USB clock */ +void usb_rcu_config (void); +/* configure USB interrupt */ +void usb_intr_config (void); +/* initializes delay unit using Timer2 */ +void usb_timer_init (void); +/* delay in micro seconds */ +void usb_udelay (const uint32_t usec); +/* delay in milliseconds */ +void usb_mdelay (const uint32_t msec); +/* configures system clock after wakeup from STOP mode */ +void system_clk_config_stop(void); + +#ifdef USE_HOST_MODE +/* configure systick */ +void systick_config(void); +/* configure USB VBus */ +void usb_vbus_config (void); +/* drive USB VBus */ +void usb_vbus_drive (uint8_t State); +#endif /* USE_HOST_MODE */ + +#endif /* __DRV_USB_HW_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_regs.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_regs.h new file mode 100644 index 00000000..91297049 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usb_regs.h @@ -0,0 +1,628 @@ +/*! + \file drv_usb_regs.h + \brief USB cell registers definition and handle macros + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USB_REGS_H +#define __DRV_USB_REGS_H + +#include "usb_conf.h" + +#define USBFS_REG_BASE 0x50000000L /*!< base address of USBFS registers */ + +#define USBFS_MAX_TX_FIFOS 15U /*!< FIFO number */ + +#define USBFS_MAX_PACKET_SIZE 64U /*!< USBFS max packet size */ +#define USBFS_MAX_CHANNEL_COUNT 8U /*!< USBFS host channel count */ +#define USBFS_MAX_EP_COUNT 4U /*!< USBFS device endpoint count */ +#define USBFS_MAX_FIFO_WORDLEN 320U /*!< USBFS max fifo size in words */ + +#define USB_DATA_FIFO_OFFSET 0x1000U /*!< USB data fifo offset */ +#define USB_DATA_FIFO_SIZE 0x1000U /*!< USB data fifo size */ + +typedef enum +{ + USB_CORE_ENUM_HS = 0, /*!< USB core type is HS */ + USB_CORE_ENUM_FS = 1 /*!< USB core type is FS */ +} usb_core_enum; + +enum USB_SPEED { + USB_SPEED_UNKNOWN = 0, /*!< USB speed unknown */ + USB_SPEED_LOW, /*!< USB speed low */ + USB_SPEED_FULL, /*!< USB speed full */ + USB_SPEED_HIGH /*!< USB speed high */ +}; + +enum usb_reg_offset { + USB_REG_OFFSET_CORE = 0x0000U, /*!< global OTG control and status register */ + USB_REG_OFFSET_DEV = 0x0800U, /*!< device mode control and status registers */ + USB_REG_OFFSET_EP = 0x0020U, + USB_REG_OFFSET_EP_IN = 0x0900U, /*!< device IN endpoint 0 control register */ + USB_REG_OFFSET_EP_OUT = 0x0B00U, /*!< device OUT endpoint 0 control register */ + USB_REG_OFFSET_HOST = 0x0400U, /*!< host control register */ + USB_REG_OFFSET_CH = 0x0020U, + USB_REG_OFFSET_PORT = 0x0440U, /*!< host port control and status register */ + USB_REG_OFFSET_CH_INOUT = 0x0500U, /*!< Host channel-x control registers */ + USB_REG_OFFSET_PWRCLKCTL = 0x0E00U, /*!< power and clock register */ +}; + +typedef struct +{ + __IO uint32_t GOTGCS; /*!< USB global OTG control and status register 000h */ + __IO uint32_t GOTGINTF; /*!< USB global OTG interrupt flag register 004h */ + __IO uint32_t GAHBCS; /*!< USB global AHB control and status register 008h */ + __IO uint32_t GUSBCS; /*!< USB global USB control and status register 00Ch */ + __IO uint32_t GRSTCTL; /*!< USB global reset control register 010h */ + __IO uint32_t GINTF; /*!< USB global interrupt flag register 014h */ + __IO uint32_t GINTEN; /*!< USB global interrupt enable register 018h */ + __IO uint32_t GRSTATR; /*!< USB receive status debug read register 01Ch */ + __IO uint32_t GRSTATP; /*!< USB receive status and pop register 020h */ + __IO uint32_t GRFLEN; /*!< USB global receive FIFO length register 024h */ + __IO uint32_t DIEP0TFLEN_HNPTFLEN; /*!< USB device IN endpoint 0/host non-periodic transmit FIFO length register 028h */ + __IO uint32_t HNPTFQSTAT; /*!< USB host non-periodic FIFO/queue status register 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h */ + __IO uint32_t GCCFG; /*!< USB global core configuration register 038h */ + __IO uint32_t CID; /*!< USB core ID register 03Ch */ + uint32_t Reserved40[48]; /*!< Reserved 040h-0FFh */ + __IO uint32_t HPTFLEN; /*!< USB host periodic transmit FIFO length register 100h */ + __IO uint32_t DIEPTFLEN[15]; /*!< USB device IN endpoint transmit FIFO length register 104h */ +} usb_gr; + +typedef struct +{ + __IO uint32_t HCTL; /*!< USB host control register 400h */ + __IO uint32_t HFT; /*!< USB host frame interval register 404h */ + __IO uint32_t HFINFR; /*!< USB host frame information remaining register 408h */ + uint32_t Reserved40C; /*!< Reserved 40Ch */ + __IO uint32_t HPTFQSTAT; /*!< USB host periodic transmit FIFO/queue status register 410h */ + __IO uint32_t HACHINT; /*!< USB host all channels interrupt register 414h */ + __IO uint32_t HACHINTEN; /*!< USB host all channels interrupt enable register 418h */ +} usb_hr; + +typedef struct +{ + __IO uint32_t HCHCTL; /*!< USB host channel control register 500h */ + __IO uint32_t HCHSTCTL; /*!< Reserved 504h */ + __IO uint32_t HCHINTF; /*!< USB host channel interrupt flag register 508h */ + __IO uint32_t HCHINTEN; /*!< USB host channel interrupt enable register 50Ch */ + __IO uint32_t HCHLEN; /*!< USB host channel transfer length register 510h */ + uint32_t Reserved514; /*!< Reserved 514h*/ + uint32_t Reserved[2]; +} usb_pr; + +typedef struct +{ + __IO uint32_t DCFG; /*!< USB device configuration register 800h */ + __IO uint32_t DCTL; /*!< USB device control register 804h */ + __IO uint32_t DSTAT; /*!< USB device status register 808h */ + uint32_t Reserved0C; /*!< Reserved 80Ch */ + __IO uint32_t DIEPINTEN; /*!< USB device IN endpoint common interrupt enable register 810h */ + __IO uint32_t DOEPINTEN; /*!< USB device OUT endpoint common interrupt enable register 814h */ + __IO uint32_t DAEPINT; /*!< USB device all endpoints interrupt register 818h */ + __IO uint32_t DAEPINTEN; /*!< USB device all endpoints interrupt enable register 81Ch */ + uint32_t Reserved20; /*!< Reserved 820h */ + uint32_t Reserved24; /*!< Reserved 824h */ + __IO uint32_t DVBUSDT; /*!< USB device VBUS discharge time register 828h */ + __IO uint32_t DVBUSPT; /*!< USB device VBUS pulsing time register 82Ch */ + __IO uint32_t DTHRCTL; /*!< device threshold control 830h */ + __IO uint32_t DIEPFEINTEN; /*!< USB Device IN endpoint FIFO empty interrupt enable register 834h */ + __IO uint32_t DEP1INT; /*!< USB device endpoint 1 interrupt register 838h */ + __IO uint32_t DEP1INTEN; /*!< USB device endpoint 1 interrupt enable register 83Ch */ + uint32_t Reserved40; /*!< Reserved 840h */ + __IO uint32_t DIEP1INTEN; /*!< USB device IN endpoint-1 interrupt enable register 844h */ + uint32_t Reserved48[15]; /*!< Reserved 848-880h */ + __IO uint32_t DOEP1INTEN; /*!< USB device OUT endpoint-1 interrupt enable register 884h */ +} usb_dr; + +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< USB device IN endpoint control register 900h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved 900h + (EpNum * 20h) + 04h */ + __IO uint32_t DIEPINTF; /*!< USB device IN endpoint interrupt flag register 900h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved 900h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DIEPLEN; /*!< USB device IN endpoint transfer length register 900h + (EpNum * 20h) + 10h */ + uint32_t Reserved14; /*!< Reserved 900h + (EpNum * 20h) + 14h */ + __IO uint32_t DIEPTFSTAT; /*!< USB device IN endpoint transmit FIFO status register 900h + (EpNum * 20h) + 18h */ +} usb_erin; + +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< USB device IN endpoint control register B00h + (EpNum * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved B00h + (EpNum * 20h) + 04h */ + __IO uint32_t DOEPINTF; /*!< USB device IN endpoint interrupt flag register B00h + (EpNum * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved B00h + (EpNum * 20h) + 0Ch */ + __IO uint32_t DOEPLEN; /*!< USB device IN endpoint transfer length register B00h + (EpNum * 20h) + 10h */ + uint32_t Reserved14; /*!< Reserved B00h + (EpNum * 20h) + 14h */ +} usb_erout; + +typedef struct _usb_regs +{ + usb_gr *gr; /*!< USBFS global registers */ + usb_dr *dr; /*!< Device control and status registers */ + usb_hr *hr; /*!< Host control and status registers */ + usb_erin *er_in[6]; /*!< USB device IN endpoint register */ + usb_erout *er_out[6]; /*!< USB device OUT endpoint register */ + usb_pr *pr[15]; /*!< USB Host channel-x control register */ + + __IO uint32_t *HPCS; /*!< USB host port control and status register */ + __IO uint32_t *DFIFO[USBFS_MAX_TX_FIFOS]; + __IO uint32_t *PWRCLKCTL; /*!< USB power and clock control register */ +} usb_core_regs; + +/* global OTG control and status register bits definitions */ +#define GOTGCS_BSV BIT(19) /*!< B-Session Valid */ +#define GOTGCS_ASV BIT(18) /*!< A-session valid */ +#define GOTGCS_DI BIT(17) /*!< debounce interval */ +#define GOTGCS_CIDPS BIT(16) /*!< id pin status */ +#define GOTGCS_DHNPEN BIT(11) /*!< device HNP enable */ +#define GOTGCS_HHNPEN BIT(10) /*!< host HNP enable */ +#define GOTGCS_HNPREQ BIT(9) /*!< HNP request */ +#define GOTGCS_HNPS BIT(8) /*!< HNP successes */ +#define GOTGCS_SRPREQ BIT(1) /*!< SRP request */ +#define GOTGCS_SRPS BIT(0) /*!< SRP successes */ + +/* global OTG interrupt flag register bits definitions */ +#define GOTGINTF_DF BIT(19) /*!< debounce finish */ +#define GOTGINTF_ADTO BIT(18) /*!< A-device timeout */ +#define GOTGINTF_HNPDET BIT(17) /*!< host negotiation request detected */ +#define GOTGINTF_HNPEND BIT(9) /*!< HNP end */ +#define GOTGINTF_SRPEND BIT(8) /*!< SRP end */ +#define GOTGINTF_SESEND BIT(2) /*!< session end */ + +/* global AHB control and status register bits definitions */ +#define GAHBCS_PTXFTH BIT(8) /*!< periodic Tx FIFO threshold */ +#define GAHBCS_TXFTH BIT(7) /*!< tx FIFO threshold */ +#define GAHBCS_GINTEN BIT(0) /*!< global interrupt enable */ + +/* global USB control and status register bits definitions */ +#define GUSBCS_FDM BIT(30) /*!< force device mode */ +#define GUSBCS_FHM BIT(29) /*!< force host mode */ +#define GUSBCS_ULPIEOI BIT(21) /*!< ULPI external over-current indicator */ +#define GUSBCS_ULPIEVD BIT(20) /*!< ULPI external VBUS driver */ +#define GUSBCS_UTT BITS(10, 13) /*!< USB turnaround time */ +#define GUSBCS_HNPCEN BIT(9) /*!< HNP capability enable */ +#define GUSBCS_SRPCEN BIT(8) /*!< SRP capability enable */ +#define GUSBCS_EMBPHY BIT(6) /*!< embedded PHY selected */ +#define GUSBCS_TOC BITS(0, 2) /*!< timeout calibration */ + +/* global reset control register bits definitions */ +#define GRSTCTL_TXFNUM BITS(6, 10) /*!< tx FIFO number */ +#define GRSTCTL_TXFF BIT(5) /*!< tx FIFO flush */ +#define GRSTCTL_RXFF BIT(4) /*!< rx FIFO flush */ +#define GRSTCTL_HFCRST BIT(2) /*!< host frame counter reset */ +#define GRSTCTL_HCSRST BIT(1) /*!< HCLK soft reset */ +#define GRSTCTL_CSRST BIT(0) /*!< core soft reset */ + +/* global interrupt flag register bits definitions */ +#define GINTF_WKUPIF BIT(31) /*!< wakeup interrupt flag */ +#define GINTF_SESIF BIT(30) /*!< session interrupt flag */ +#define GINTF_DISCIF BIT(29) /*!< disconnect interrupt flag */ +#define GINTF_IDPSC BIT(28) /*!< id pin status change */ +#define GINTF_PTXFEIF BIT(26) /*!< periodic tx FIFO empty interrupt flag */ +#define GINTF_HCIF BIT(25) /*!< host channels interrupt flag */ +#define GINTF_HPIF BIT(24) /*!< host port interrupt flag */ +#define GINTF_PXNCIF BIT(21) /*!< periodic transfer not complete interrupt flag */ +#define GINTF_ISOONCIF BIT(21) /*!< isochronous OUT transfer not complete interrupt flag */ +#define GINTF_ISOINCIF BIT(20) /*!< isochronous IN transfer not complete interrupt flag */ +#define GINTF_OEPIF BIT(19) /*!< OUT endpoint interrupt flag */ +#define GINTF_IEPIF BIT(18) /*!< IN endpoint interrupt flag */ +#define GINTF_EOPFIF BIT(15) /*!< end of periodic frame interrupt flag */ +#define GINTF_ISOOPDIF BIT(14) /*!< isochronous OUT packet dropped interrupt flag */ +#define GINTF_ENUMFIF BIT(13) /*!< enumeration finished */ +#define GINTF_RST BIT(12) /*!< USB reset */ +#define GINTF_SP BIT(11) /*!< USB suspend */ +#define GINTF_ESP BIT(10) /*!< early suspend */ +#define GINTF_GONAK BIT(7) /*!< global OUT NAK effective */ +#define GINTF_GNPINAK BIT(6) /*!< global IN non-periodic NAK effective */ +#define GINTF_NPTXFEIF BIT(5) /*!< non-periodic tx FIFO empty interrupt flag */ +#define GINTF_RXFNEIF BIT(4) /*!< rx FIFO non-empty interrupt flag */ +#define GINTF_SOF BIT(3) /*!< start of frame */ +#define GINTF_OTGIF BIT(2) /*!< OTG interrupt flag */ +#define GINTF_MFIF BIT(1) /*!< mode fault interrupt flag */ +#define GINTF_COPM BIT(0) /*!< current operation mode */ + +/* global interrupt enable register bits definitions */ +#define GINTEN_WKUPIE BIT(31) /*!< wakeup interrupt enable */ +#define GINTEN_SESIE BIT(30) /*!< session interrupt enable */ +#define GINTEN_DISCIE BIT(29) /*!< disconnect interrupt enable */ +#define GINTEN_IDPSCIE BIT(28) /*!< id pin status change interrupt enable */ +#define GINTEN_PTXFEIE BIT(26) /*!< periodic tx FIFO empty interrupt enable */ +#define GINTEN_HCIE BIT(25) /*!< host channels interrupt enable */ +#define GINTEN_HPIE BIT(24) /*!< host port interrupt enable */ +#define GINTEN_IPXIE BIT(21) /*!< periodic transfer not complete interrupt enable */ +#define GINTEN_ISOONCIE BIT(21) /*!< isochronous OUT transfer not complete interrupt enable */ +#define GINTEN_ISOINCIE BIT(20) /*!< isochronous IN transfer not complete interrupt enable */ +#define GINTEN_OEPIE BIT(19) /*!< OUT endpoints interrupt enable */ +#define GINTEN_IEPIE BIT(18) /*!< IN endpoints interrupt enable */ +#define GINTEN_EOPFIE BIT(15) /*!< end of periodic frame interrupt enable */ +#define GINTEN_ISOOPDIE BIT(14) /*!< isochronous OUT packet dropped interrupt enable */ +#define GINTEN_ENUMFIE BIT(13) /*!< enumeration finish enable */ +#define GINTEN_RSTIE BIT(12) /*!< USB reset interrupt enable */ +#define GINTEN_SPIE BIT(11) /*!< USB suspend interrupt enable */ +#define GINTEN_ESPIE BIT(10) /*!< early suspend interrupt enable */ +#define GINTEN_GONAKIE BIT(7) /*!< global OUT NAK effective interrupt enable */ +#define GINTEN_GNPINAKIE BIT(6) /*!< global non-periodic IN NAK effective interrupt enable */ +#define GINTEN_NPTXFEIE BIT(5) /*!< non-periodic Tx FIFO empty interrupt enable */ +#define GINTEN_RXFNEIE BIT(4) /*!< receive FIFO non-empty interrupt enable */ +#define GINTEN_SOFIE BIT(3) /*!< start of frame interrupt enable */ +#define GINTEN_OTGIE BIT(2) /*!< OTG interrupt enable */ +#define GINTEN_MFIE BIT(1) /*!< mode fault interrupt enable */ + +/* global receive status read and pop register bits definitions */ +#define GRSTATRP_RPCKST BITS(17, 20) /*!< received packet status */ +#define GRSTATRP_DPID BITS(15, 16) /*!< data PID */ +#define GRSTATRP_BCOUNT BITS(4, 14) /*!< byte count */ +#define GRSTATRP_CNUM BITS(0, 3) /*!< channel number */ +#define GRSTATRP_EPNUM BITS(0, 3) /*!< endpoint number */ + +/* global receive FIFO length register bits definitions */ +#define GRFLEN_RXFD BITS(0, 15) /*!< rx FIFO depth */ + +/* host non-periodic transmit FIFO length register bits definitions */ +#define HNPTFLEN_HNPTXFD BITS(16, 31) /*!< non-periodic Tx FIFO depth */ +#define HNPTFLEN_HNPTXRSAR BITS(0, 15) /*!< non-periodic Tx RAM start address */ + +/* USB IN endpoint 0 transmit FIFO length register bits definitions */ +#define DIEP0TFLEN_IEP0TXFD BITS(16, 31) /*!< IN Endpoint 0 Tx FIFO depth */ +#define DIEP0TFLEN_IEP0TXRSAR BITS(0, 15) /*!< IN Endpoint 0 TX RAM start address */ + +/* host non-periodic transmit FIFO/queue status register bits definitions */ +#define HNPTFQSTAT_NPTXRQTOP BITS(24, 30) /*!< top entry of the non-periodic Tx request queue */ +#define HNPTFQSTAT_NPTXRQS BITS(16, 23) /*!< non-periodic Tx request queue space */ +#define HNPTFQSTAT_NPTXFS BITS(0, 15) /*!< non-periodic Tx FIFO space */ +#define HNPTFQSTAT_CNUM BITS(27, 30) /*!< channel number*/ +#define HNPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HNPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HNPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + +/* global core configuration register bits definitions */ +#define GCCFG_VBUSIG BIT(21) /*!< vbus ignored */ +#define GCCFG_SOFOEN BIT(20) /*!< SOF output enable */ +#define GCCFG_VBUSBCEN BIT(19) /*!< the VBUS B-device comparer enable */ +#define GCCFG_VBUSACEN BIT(18) /*!< the VBUS A-device comparer enable */ +#define GCCFG_PWRON BIT(16) /*!< power on */ + +/* core ID register bits definitions */ +#define CID_CID BITS(0, 31) /*!< core ID */ + +/* host periodic transmit FIFO length register bits definitions */ +#define HPTFLEN_HPTXFD BITS(16, 31) /*!< host periodic Tx FIFO depth */ +#define HPTFLEN_HPTXFSAR BITS(0, 15) /*!< host periodic Tx RAM start address */ + +/* device IN endpoint transmit FIFO length register bits definitions */ +#define DIEPTFLEN_IEPTXFD BITS(16, 31) /*!< IN endpoint Tx FIFO x depth */ +#define DIEPTFLEN_IEPTXRSAR BITS(0, 15) /*!< IN endpoint FIFOx Tx x RAM start address */ + +/* host control register bits definitions */ +#define HCTL_SPDFSLS BIT(2) /*!< speed limited to FS and LS */ +#define HCTL_CLKSEL BITS(0, 1) /*!< clock select for USB clock */ + +/* host frame interval register bits definitions */ +#define HFT_FRI BITS(0, 15) /*!< frame interval */ + +/* host frame information remaining register bits definitions */ +#define HFINFR_FRT BITS(16, 31) /*!< frame remaining time */ +#define HFINFR_FRNUM BITS(0, 15) /*!< frame number */ + +/* host periodic transmit FIFO/queue status register bits definitions */ +#define HPTFQSTAT_PTXREQT BITS(24, 31) /*!< top entry of the periodic Tx request queue */ +#define HPTFQSTAT_PTXREQS BITS(16, 23) /*!< periodic Tx request queue space */ +#define HPTFQSTAT_PTXFS BITS(0, 15) /*!< periodic Tx FIFO space */ +#define HPTFQSTAT_OEFRM BIT(31) /*!< odd/eveb frame */ +#define HPTFQSTAT_CNUM BITS(27, 30) /*!< channel number */ +#define HPTFQSTAT_EPNUM BITS(27, 30) /*!< endpoint number */ +#define HPTFQSTAT_TYPE BITS(25, 26) /*!< token type */ +#define HPTFQSTAT_TMF BIT(24) /*!< terminate flag */ + +#define TFQSTAT_TXFS BITS(0, 15) +#define TFQSTAT_CNUM BITS(27, 30) + +/* host all channels interrupt register bits definitions */ +#define HACHINT_HACHINT BITS(0, 11) /*!< host all channel interrupts */ + +/* host all channels interrupt enable register bits definitions */ +#define HACHINTEN_CINTEN BITS(0, 11) /*!< channel interrupt enable */ + +/* host port control and status register bits definitions */ +#define HPCS_PS BITS(17, 18) /*!< port speed */ +#define HPCS_PP BIT(12) /*!< port power */ +#define HPCS_PLST BITS(10, 11) /*!< port line status */ +#define HPCS_PRST BIT(8) /*!< port reset */ +#define HPCS_PSP BIT(7) /*!< port suspend */ +#define HPCS_PREM BIT(6) /*!< port resume */ +#define HPCS_PEDC BIT(3) /*!< port enable/disable change */ +#define HPCS_PE BIT(2) /*!< port enable */ +#define HPCS_PCD BIT(1) /*!< port connect detected */ +#define HPCS_PCST BIT(0) /*!< port connect status */ + +/* host channel-x control register bits definitions */ +#define HCHCTL_CEN BIT(31) /*!< channel enable */ +#define HCHCTL_CDIS BIT(30) /*!< channel disable */ +#define HCHCTL_ODDFRM BIT(29) /*!< odd frame */ +#define HCHCTL_DAR BITS(22, 28) /*!< device address */ +#define HCHCTL_MPC BITS(20, 21) /*!< multiple packet count */ +#define HCHCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define HCHCTL_LSD BIT(17) /*!< low-speed device */ +#define HCHCTL_EPDIR BIT(15) /*!< endpoint direction */ +#define HCHCTL_EPNUM BITS(11, 14) /*!< endpoint number */ +#define HCHCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* host channel-x split transaction register bits definitions */ +#define HCHSTCTL_SPLEN BIT(31) /*!< enable high-speed split transaction */ +#define HCHSTCTL_CSPLT BIT(16) /*!< complete-split enable */ +#define HCHSTCTL_ISOPCE BITS(14, 15) /*!< isochronous OUT payload continuation encoding */ +#define HCHSTCTL_HADDR BITS(7, 13) /*!< HUB address */ +#define HCHSTCTL_PADDR BITS(0, 6) /*!< port address */ + +/* host channel-x interrupt flag register bits definitions */ +#define HCHINTF_DTER BIT(10) /*!< data toggle error */ +#define HCHINTF_REQOVR BIT(9) /*!< request queue overrun */ +#define HCHINTF_BBER BIT(8) /*!< babble error */ +#define HCHINTF_USBER BIT(7) /*!< USB bus Error */ +#define HCHINTF_NYET BIT(6) /*!< NYET */ +#define HCHINTF_ACK BIT(5) /*!< ACK */ +#define HCHINTF_NAK BIT(4) /*!< NAK */ +#define HCHINTF_STALL BIT(3) /*!< STALL */ +#define HCHINTF_CH BIT(1) /*!< channel halted */ +#define HCHINTF_TF BIT(0) /*!< transfer finished */ + +/* host channel-x interrupt enable register bits definitions */ +#define HCHINTEN_DTERIE BIT(10) /*!< data toggle error interrupt enable */ +#define HCHINTEN_REQOVRIE BIT(9) /*!< request queue overrun interrupt enable */ +#define HCHINTEN_BBERIE BIT(8) /*!< babble error interrupt enable */ +#define HCHINTEN_USBERIE BIT(7) /*!< USB bus error interrupt enable */ +#define HCHINTEN_NYETIE BIT(6) /*!< NYET interrupt enable */ +#define HCHINTEN_ACKIE BIT(5) /*!< ACK interrupt enable */ +#define HCHINTEN_NAKIE BIT(4) /*!< NAK interrupt enable */ +#define HCHINTEN_STALLIE BIT(3) /*!< STALL interrupt enable */ +#define HCHINTEN_CHIE BIT(1) /*!< channel halted interrupt enable */ +#define HCHINTEN_TFIE BIT(0) /*!< transfer finished interrupt enable */ + +/* host channel-x transfer length register bits definitions */ +#define HCHLEN_PING BIT(31) /*!< PING token request */ +#define HCHLEN_DPID BITS(29, 30) /*!< data PID */ +#define HCHLEN_PCNT BITS(19, 28) /*!< packet count */ +#define HCHLEN_TLEN BITS(0, 18) /*!< transfer length */ + +#define PORT_SPEED(x) (((uint32_t)(x) << 17) & HPCS_PS) /*!< Port speed */ + +#define PORT_SPEED_HIGH PORT_SPEED(0U) /*!< high speed */ +#define PORT_SPEED_FULL PORT_SPEED(1U) /*!< full speed */ +#define PORT_SPEED_LOW PORT_SPEED(2U) /*!< low speed */ + +#define PIPE_CTL_DAR(x) (((uint32_t)(x) << 22) & HCHCTL_DAR) /*!< device address */ +#define PIPE_CTL_EPTYPE(x) (((uint32_t)(x) << 18) & HCHCTL_EPTYPE) /*!< endpoint type */ +#define PIPE_CTL_EPNUM(x) (((uint32_t)(x) << 11) & HCHCTL_EPNUM) /*!< endpoint number */ +#define PIPE_CTL_EPDIR(x) (((uint32_t)(x) << 15) & HCHCTL_EPDIR) /*!< endpoint direction */ +#define PIPE_CTL_EPMPL(x) (((uint32_t)(x) << 0) & HCHCTL_MPL) /*!< maximum packet length */ +#define PIPE_CTL_LSD(x) (((uint32_t)(x) << 17) & HCHCTL_LSD) /*!< low-Speed device */ + +#define PIPE_XFER_PCNT(x) (((uint32_t)(x) << 19) & HCHLEN_PCNT) /*!< packet count */ +#define PIPE_XFER_DPID(x) (((uint32_t)(x) << 29) & HCHLEN_DPID) /*!< data PID */ + +#define PIPE_DPID_DATA0 PIPE_XFER_DPID(0) /*!< DATA0 */ +#define PIPE_DPID_DATA1 PIPE_XFER_DPID(2) /*!< DATA1 */ +#define PIPE_DPID_DATA2 PIPE_XFER_DPID(1) /*!< DATA2 */ +#define PIPE_DPID_SETUP PIPE_XFER_DPID(3) /*!< MDATA (non-control)/SETUP (control) */ + +extern const uint32_t PIPE_DPID[2]; + +/* device configuration registers bits definitions */ +#define DCFG_EOPFT BITS(11, 12) /*!< end of periodic frame time */ +#define DCFG_DAR BITS(4, 10) /*!< device address */ +#define DCFG_NZLSOH BIT(2) /*!< non-zero-length status OUT handshake */ +#define DCFG_DS BITS(0, 1) /*!< device speed */ + +/* device control registers bits definitions */ +#define DCTL_POIF BIT(11) /*!< power-on initialization finished */ +#define DCTL_CGONAK BIT(10) /*!< clear global OUT NAK */ +#define DCTL_SGONAK BIT(9) /*!< set global OUT NAK */ +#define DCTL_CGINAK BIT(8) /*!< clear global IN NAK */ +#define DCTL_SGINAK BIT(7) /*!< set global IN NAK */ +#define DCTL_GONS BIT(3) /*!< global OUT NAK status */ +#define DCTL_GINS BIT(2) /*!< global IN NAK status */ +#define DCTL_SD BIT(1) /*!< soft disconnect */ +#define DCTL_RWKUP BIT(0) /*!< remote wakeup */ + +/* device status registers bits definitions */ +#define DSTAT_FNRSOF BITS(8, 21) /*!< the frame number of the received SOF. */ +#define DSTAT_ES BITS(1, 2) /*!< enumerated speed */ +#define DSTAT_SPST BIT(0) /*!< suspend status */ + +/* device IN endpoint common interrupt enable registers bits definitions */ +#define DIEPINTEN_NAKEN BIT(13) /*!< NAK handshake sent by USBFS interrupt enable bit */ +#define DIEPINTEN_TXFEEN BIT(7) /*!< transmit FIFO empty interrupt enable bit */ +#define DIEPINTEN_IEPNEEN BIT(6) /*!< IN endpoint NAK effective interrupt enable bit */ +#define DIEPINTEN_EPTXFUDEN BIT(4) /*!< endpoint Tx FIFO underrun interrupt enable bit */ +#define DIEPINTEN_CITOEN BIT(3) /*!< control In Timeout interrupt enable bit */ +#define DIEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DIEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device OUT endpoint common interrupt enable registers bits definitions */ +#define DOEPINTEN_NYETEN BIT(14) /*!< NYET handshake is sent interrupt enable bit */ +#define DOEPINTEN_BTBSTPEN BIT(6) /*!< back-to-back SETUP packets interrupt enable bit */ +#define DOEPINTEN_EPRXFOVREN BIT(4) /*!< endpoint Rx FIFO overrun interrupt enable bit */ +#define DOEPINTEN_STPFEN BIT(3) /*!< SETUP phase finished interrupt enable bit */ +#define DOEPINTEN_EPDISEN BIT(1) /*!< endpoint disabled interrupt enable bit */ +#define DOEPINTEN_TFEN BIT(0) /*!< transfer finished interrupt enable bit */ + +/* device all endpoints interrupt registers bits definitions */ +#define DAEPINT_OEPITB BITS(16, 21) /*!< device all OUT endpoint interrupt bits */ +#define DAEPINT_IEPITB BITS(0, 5) /*!< device all IN endpoint interrupt bits */ + +/* device all endpoints interrupt enable registers bits definitions */ +#define DAEPINTEN_OEPIE BITS(16, 21) /*!< OUT endpoint interrupt enable */ +#define DAEPINTEN_IEPIE BITS(0, 3) /*!< IN endpoint interrupt enable */ + +/* device Vbus discharge time registers bits definitions */ +#define DVBUSDT_DVBUSDT BITS(0, 15) /*!< device VBUS discharge time */ + +/* device Vbus pulsing time registers bits definitions */ +#define DVBUSPT_DVBUSPT BITS(0, 11) /*!< device VBUS pulsing time */ + +/* device IN endpoint FIFO empty interrupt enable register bits definitions */ +#define DIEPFEINTEN_IEPTXFEIE BITS(0, 5) /*!< IN endpoint Tx FIFO empty interrupt enable bits */ + +/* device endpoint 0 control register bits definitions */ +#define DEP0CTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEP0CTL_EPD BIT(30) /*!< endpoint disable */ +#define DEP0CTL_SNAK BIT(27) /*!< set NAK */ +#define DEP0CTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEP0CTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEP0CTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEP0CTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEP0CTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEP0CTL_NAKS BIT(17) /*!< NAK status */ +#define DEP0CTL_EPACT BIT(15) /*!< endpoint active */ +#define DEP0CTL_MPL BITS(0, 1) /*!< maximum packet length */ + +/* device endpoint x control register bits definitions */ +#define DEPCTL_EPEN BIT(31) /*!< endpoint enable */ +#define DEPCTL_EPD BIT(30) /*!< endpoint disable */ +#define DEPCTL_SODDFRM BIT(29) /*!< set odd frame */ +#define DEPCTL_SD1PID BIT(29) /*!< set DATA1 PID */ +#define DEPCTL_SEVNFRM BIT(28) /*!< set even frame */ +#define DEPCTL_SD0PID BIT(28) /*!< set DATA0 PID */ +#define DEPCTL_SNAK BIT(27) /*!< set NAK */ +#define DEPCTL_CNAK BIT(26) /*!< clear NAK */ +#define DIEPCTL_TXFNUM BITS(22, 25) /*!< tx FIFO number */ +#define DEPCTL_STALL BIT(21) /*!< STALL handshake */ +#define DOEPCTL_SNOOP BIT(20) /*!< snoop mode */ +#define DEPCTL_EPTYPE BITS(18, 19) /*!< endpoint type */ +#define DEPCTL_NAKS BIT(17) /*!< NAK status */ +#define DEPCTL_EOFRM BIT(16) /*!< even/odd frame */ +#define DEPCTL_DPID BIT(16) /*!< endpoint data PID */ +#define DEPCTL_EPACT BIT(15) /*!< endpoint active */ +#define DEPCTL_MPL BITS(0, 10) /*!< maximum packet length */ + +/* device IN endpoint-x interrupt flag register bits definitions */ +#define DIEPINTF_NAK BIT(13) /*!< NAK handshake sent by USBFS */ +#define DIEPINTF_TXFE BIT(7) /*!< transmit FIFO empty */ +#define DIEPINTF_IEPNE BIT(6) /*!< IN endpoint NAK effective */ +#define DIEPINTF_EPTXFUD BIT(4) /*!< endpoint Tx FIFO underrun */ +#define DIEPINTF_CITO BIT(3) /*!< control In Timeout interrupt */ +#define DIEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DIEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device OUT endpoint-x interrupt flag register bits definitions */ +#define DOEPINTF_NYET BIT(14) /*!< NYET handshake is sent */ +#define DOEPINTF_BTBSTP BIT(6) /*!< back-to-back SETUP packets */ +#define DOEPINTF_EPRXFOVR BIT(4) /*!< endpoint Rx FIFO overrun */ +#define DOEPINTF_STPF BIT(3) /*!< SETUP phase finished */ +#define DOEPINTF_EPDIS BIT(1) /*!< endpoint disabled */ +#define DOEPINTF_TF BIT(0) /*!< transfer finished */ + +/* device IN endpoint 0 transfer length register bits definitions */ +#define DIEP0LEN_PCNT BITS(19, 20) /*!< packet count */ +#define DIEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint 0 transfer length register bits definitions */ +#define DOEP0LEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DOEP0LEN_PCNT BIT(19) /*!< packet count */ +#define DOEP0LEN_TLEN BITS(0, 6) /*!< transfer length */ + +/* device OUT endpoint-x transfer length register bits definitions */ +#define DOEPLEN_RXDPID BITS(29, 30) /*!< received data PID */ +#define DOEPLEN_STPCNT BITS(29, 30) /*!< SETUP packet count */ +#define DIEPLEN_MCNT BITS(29, 30) /*!< multi count */ +#define DEPLEN_PCNT BITS(19, 28) /*!< packet count */ +#define DEPLEN_TLEN BITS(0, 18) /*!< transfer length */ + +/* device IN endpoint-x transmit FIFO status register bits definitions */ +#define DIEPTFSTAT_IEPTFS BITS(0, 15) /*!< IN endpoint Tx FIFO space remaining */ + +/* USB power and clock registers bits definition */ +#define PWRCLKCTL_SHCLK BIT(1) /*!< stop HCLK */ +#define PWRCLKCTL_SUCLK BIT(0) /*!< stop the USB clock */ + +#define RSTAT_GOUT_NAK 1U /*!< global OUT NAK (triggers an interrupt) */ +#define RSTAT_DATA_UPDT 2U /*!< OUT data packet received */ +#define RSTAT_XFER_COMP 3U /*!< OUT transfer completed (triggers an interrupt) */ +#define RSTAT_SETUP_COMP 4U /*!< SETUP transaction completed (triggers an interrupt) */ +#define RSTAT_SETUP_UPDT 6U /*!< SETUP data packet received */ + +#define DSTAT_EM_HS_PHY_30MHZ_60MHZ 0U /*!< USB enumerate speed use high-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_FS_PHY_30MHZ_60MHZ 1U /*!< USB enumerate speed use full-speed PHY clock in 30MHz or 60MHz */ +#define DSTAT_EM_LS_PHY_6MHZ 2U /*!< USB enumerate speed use low-speed PHY clock in 6MHz */ +#define DSTAT_EM_FS_PHY_48MHZ 3U /*!< USB enumerate speed use full-speed PHY clock in 48MHz */ + +#define DPID_DATA0 0U /*!< device endpoint data PID is DATA0 */ +#define DPID_DATA1 2U /*!< device endpoint data PID is DATA1 */ +#define DPID_DATA2 1U /*!< device endpoint data PID is DATA2 */ +#define DPID_MDATA 3U /*!< device endpoint data PID is MDATA */ + +#define DCFG_PFRI(regval) (DCFG_EOPFT & ((regval) << 11)) /*!< end of periodic frame time configuration */ + +#define FRAME_INTERVAL_80 DCFG_PFRI(0U) /*!< 80% of the frame time */ +#define FRAME_INTERVAL_85 DCFG_PFRI(1U) /*!< 85% of the frame time */ +#define FRAME_INTERVAL_90 DCFG_PFRI(2U) /*!< 90% of the frame time */ +#define FRAME_INTERVAL_95 DCFG_PFRI(3U) /*!< 95% of the frame time */ + +#define DCFG_DEVSPEED(regval) (DCFG_DS & ((regval) << 0)) /*!< device speed configuration */ + +#define USB_SPEED_EXP_HIGH DCFG_DEVSPEED(0U) /*!< device external PHY high speed */ +#define USB_SPEED_EXP_FULL DCFG_DEVSPEED(1U) /*!< device external PHY full speed */ +#define USB_SPEED_INP_FULL DCFG_DEVSPEED(3U) /*!< device internal PHY full speed */ + +#define DEP0_MPL(regval) (DEP0CTL_MPL & ((regval) << 0)) /*!< maximum packet length configuration */ + +#define EP0MPL_64 DEP0_MPL(0U) /*!< maximum packet length 64 bytes */ +#define EP0MPL_32 DEP0_MPL(1U) /*!< maximum packet length 32 bytes */ +#define EP0MPL_16 DEP0_MPL(2U) /*!< maximum packet length 16 bytes */ +#define EP0MPL_8 DEP0_MPL(3U) /*!< maximum packet length 8 bytes */ + +#define DOEP0_TLEN(regval) (DOEP0LEN_TLEN & ((regval) << 0)) /*!< transfer length */ +#define DOEP0_PCNT(regval) (DOEP0LEN_PCNT & ((regval) << 19)) /*!< packet count */ +#define DOEP0_STPCNT(regval) (DOEP0LEN_STPCNT & ((regval) << 29)) /*!< SETUP packet count */ + +#define USB_ULPI_PHY 1U /*!< ULPI interface external PHY */ +#define USB_EMBEDDED_PHY 2U /*!< embedded PHY */ + +#define GRXSTS_PKTSTS_IN 2U +#define GRXSTS_PKTSTS_IN_XFER_COMP 3U +#define GRXSTS_PKTSTS_DATA_TOGGLE_ERR 5U +#define GRXSTS_PKTSTS_CH_HALTED 7U + +#define HCTL_30_60MHZ 0U /*!< USB clock 30-60MHZ */ +#define HCTL_48MHZ 1U /*!< USB clock 48MHZ */ +#define HCTL_6MHZ 2U /*!< USB clock 6MHZ */ + +#define EP0_OUT ((uint8_t)0x00) /*!< endpoint out 0 */ +#define EP0_IN ((uint8_t)0x80) /*!< endpoint in 0 */ +#define EP1_OUT ((uint8_t)0x01) /*!< endpoint out 1 */ +#define EP1_IN ((uint8_t)0x81) /*!< endpoint in 1 */ +#define EP2_OUT ((uint8_t)0x02) /*!< endpoint out 2 */ +#define EP2_IN ((uint8_t)0x82) /*!< endpoint in 2 */ +#define EP3_OUT ((uint8_t)0x03) /*!< endpoint out 3 */ +#define EP3_IN ((uint8_t)0x83) /*!< endpoint in 3 */ + +#endif /* __DRV_USB_REGS_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usbd_int.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usbd_int.h new file mode 100644 index 00000000..f1935212 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usbd_int.h @@ -0,0 +1,45 @@ +/*! + \file drv_usbd_int.h + \brief USB device mode interrupt header file + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBD_INT_H +#define __DRV_USBD_INT_H + +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* function declarations */ +/* USB device-mode interrupts global service routine handler */ +void usbd_isr (usb_core_driver *udev); + +#endif /* __DRV_USBD_INT_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usbh_int.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usbh_int.h new file mode 100644 index 00000000..54f47d16 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Include/drv_usbh_int.h @@ -0,0 +1,54 @@ +/*! + \file drv_usbh_int.h.h + \brief USB host mode interrupt management header file + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __DRV_USBH_INT_H +#define __DRV_USBH_INT_H + +#include "drv_usb_host.h" +#include "usbh_core.h" + +typedef struct _usbh_ev_cb +{ + uint8_t (*connect) (usbh_host *uhost); + uint8_t (*disconnect) (usbh_host *uhost); + uint8_t (*SOF) (usbh_host *uhost); +} usbh_ev_cb; + +extern usbh_ev_cb *usbh_int_fop; + +/* function declarations */ +/* handle global host interrupt */ +uint32_t usbh_isr (usb_core_driver *udev); + +#endif /* __DRV_USBH_INT_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_core.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_core.c new file mode 100644 index 00000000..8e86d210 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_core.c @@ -0,0 +1,330 @@ +/*! + \file drv_usb_core.c + \brief USB core driver which can operate in host and device mode + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_core.h" +#include "drv_usb_hw.h" + +/* local function prototypes ('static') */ +static void usb_core_reset(usb_core_regs *usb_regs); + +/*! + \brief configure USB core basic + \param[in] usb_basic: pointer to USB capabilities + \param[in] usb_regs: USB core registers + \param[in] usb_core: USB core + \param[out] none + \retval operation status +*/ +usb_status usb_basic_init(usb_core_basic *usb_basic, + usb_core_regs *usb_regs, + usb_core_enum usb_core) +{ + /* configure USB default transfer mode as FIFO mode */ + usb_basic->transfer_mode = (uint8_t)USB_USE_FIFO; + + /* USB default speed is full-speed */ + usb_basic->core_speed = (uint8_t)USB_SPEED_FULL; + + usb_basic->core_enum = (uint8_t)usb_core; + + switch(usb_core) { + case USB_CORE_ENUM_FS: + usb_basic->base_reg = (uint32_t)USBFS_REG_BASE; + + /* set the host channel numbers */ + usb_basic->num_pipe = USBFS_MAX_CHANNEL_COUNT; + + /* set the device endpoint numbers */ + usb_basic->num_ep = USBFS_MAX_EP_COUNT; + + /* USBFS core use embedded physical layer */ + usb_basic->phy_itf = USB_EMBEDDED_PHY; + break; + + default: + return USB_FAIL; + } + + usb_basic->sof_enable = USB_SOF_OUTPUT; + usb_basic->low_power = USB_LOW_POWER; + + /* assign main registers address */ + *usb_regs = (usb_core_regs) { + .gr = (usb_gr*) (usb_basic->base_reg + USB_REG_OFFSET_CORE), + .hr = (usb_hr*) (usb_basic->base_reg + USB_REG_OFFSET_HOST), + .dr = (usb_dr*) (usb_basic->base_reg + USB_REG_OFFSET_DEV), + + .HPCS = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PORT), + .PWRCLKCTL = (uint32_t*) (usb_basic->base_reg + USB_REG_OFFSET_PWRCLKCTL) + }; + + /* assign device endpoint registers address */ + for (uint8_t i = 0U; i < usb_basic->num_ep; i++) { + usb_regs->er_in[i] = (usb_erin *) \ + (usb_basic->base_reg + USB_REG_OFFSET_EP_IN + (i * USB_REG_OFFSET_EP)); + + usb_regs->er_out[i] = (usb_erout *)\ + (usb_basic->base_reg + USB_REG_OFFSET_EP_OUT + (i * USB_REG_OFFSET_EP)); + } + + /* assign host pipe registers address */ + for (uint8_t i = 0U; i < usb_basic->num_pipe; i++) { + usb_regs->pr[i] = (usb_pr *) \ + (usb_basic->base_reg + USB_REG_OFFSET_CH_INOUT + (i * USB_REG_OFFSET_CH)); + + usb_regs->DFIFO[i] = (uint32_t *) \ + (usb_basic->base_reg + USB_DATA_FIFO_OFFSET + (i * USB_DATA_FIFO_SIZE)); + } + + return USB_OK; +} + +/*! + \brief initializes the USB controller registers and + prepares the core device mode or host mode operation + \param[in] usb_basic: pointer to USB capabilities + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval operation status +*/ +usb_status usb_core_init (usb_core_basic usb_basic, usb_core_regs *usb_regs) +{ + if (USB_ULPI_PHY == usb_basic.phy_itf) { + usb_regs->gr->GCCFG &= ~GCCFG_PWRON; + + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + /* initialize the ULPI interface */ + usb_regs->gr->GUSBCS &= ~(GUSBCS_EMBPHY | GUSBCS_ULPIEOI); + + /* soft reset the core */ + usb_core_reset (usb_regs); + } else { + usb_regs->gr->GUSBCS |= GUSBCS_EMBPHY; + + /* soft reset the core */ + usb_core_reset (usb_regs); + + /* active the transceiver and enable VBUS sensing */ + usb_regs->gr->GCCFG |= GCCFG_PWRON | GCCFG_VBUSACEN | GCCFG_VBUSBCEN; + +#ifndef VBUS_SENSING_ENABLED + usb_regs->gr->GCCFG |= GCCFG_VBUSIG; +#endif /* VBUS_SENSING_ENABLED */ + + /* enable SOF output */ + if (usb_basic.sof_enable) { + usb_regs->gr->GCCFG |= GCCFG_SOFOEN; + } + + usb_mdelay(20U); + } + +#ifdef USE_OTG_MODE + + /* enable USB OTG features */ + usb_regs->gr->GUSBCS |= GUSBCS_HNPCEN | GUSBCS_SRPCEN; + + /* enable the USB wakeup and suspend interrupts */ + usb_regs->gr->GINTF = 0xBFFFFFFFU; + + usb_regs->gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE | \ + GINTEN_OTGIE | GINTEN_SESIE | GINTEN_CIDPSCIE; + +#endif /* USE_OTG_MODE */ + + return USB_OK; +} + +/*! + \brief write a packet into the Tx FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] src_buf: pointer to source buffer + \param[in] fifo_num: FIFO number which is in (0..3) + \param[in] byte_count: packet byte count + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_write (usb_core_regs *usb_regs, + uint8_t *src_buf, + uint8_t fifo_num, + uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[fifo_num]; + + while (word_count-- > 0U) { + *fifo = *((__packed uint32_t *)src_buf); + + src_buf += 4U; + } + + return USB_OK; +} + +/*! + \brief read a packet from the Rx FIFO associated with the endpoint + \param[in] usb_regs: pointer to USB core registers + \param[in] dest_buf: pointer to destination buffer + \param[in] byte_count: packet byte count + \param[out] none + \retval void type pointer +*/ +void *usb_rxfifo_read (usb_core_regs *usb_regs, uint8_t *dest_buf, uint16_t byte_count) +{ + uint32_t word_count = (byte_count + 3U) / 4U; + + __IO uint32_t *fifo = usb_regs->DFIFO[0]; + + while (word_count-- > 0U) { + *(__packed uint32_t *)dest_buf = *fifo; + + dest_buf += 4U; + } + + return ((void *)dest_buf); +} + +/*! + \brief flush a Tx FIFO or all Tx FIFOs + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo_num: FIFO number which is in (0..3) + \param[out] none + \retval operation status +*/ +usb_status usb_txfifo_flush (usb_core_regs *usb_regs, uint8_t fifo_num) +{ + usb_regs->gr->GRSTCTL = ((uint32_t)fifo_num << 6U) | GRSTCTL_TXFF; + + /* wait for Tx FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_TXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks*/ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief flush the entire Rx FIFO + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval operation status +*/ +usb_status usb_rxfifo_flush (usb_core_regs *usb_regs) +{ + usb_regs->gr->GRSTCTL = GRSTCTL_RXFF; + + /* wait for Rx FIFO flush bit is set */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_RXFF) { + /* no operation */ + } + + /* wait for 3 PHY clocks */ + usb_udelay(3U); + + return USB_OK; +} + +/*! + \brief set endpoint or channel TX FIFO size + \param[in] usb_regs: pointer to USB core registers + \param[in] fifo: TX FIFO number + \param[in] size: assigned TX FIFO size + \param[out] none + \retval none +*/ +void usb_set_txfifo(usb_core_regs *usb_regs, uint8_t fifo, uint16_t size) +{ + uint32_t tx_offset; + + tx_offset = usb_regs->gr->GRFLEN; + + if(0U == fifo) { + usb_regs->gr->DIEP0TFLEN_HNPTFLEN = ((uint32_t)size << 16) | tx_offset; + } else { + tx_offset += (usb_regs->gr->DIEP0TFLEN_HNPTFLEN) >> 16; + + for (uint8_t i = 0U; i < (fifo - 1U); i++) { + tx_offset += (usb_regs->gr->DIEPTFLEN[i] >> 16); + } + + /* multiply Tx_Size by 2 to get higher performance */ + usb_regs->gr->DIEPTFLEN[fifo - 1U] = ((uint32_t)size << 16) | tx_offset; + } +} + +/*! + \brief set USB current mode + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +void usb_curmode_set(usb_core_regs *usb_regs, uint8_t mode) +{ + usb_regs->gr->GUSBCS &= ~(GUSBCS_FDM | GUSBCS_FHM); + + if (DEVICE_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FDM; + } else if (HOST_MODE == mode) { + usb_regs->gr->GUSBCS |= GUSBCS_FHM; + } else { + /* OTG mode and other mode can not be here! */ + } +} + +/*! + \brief configure USB core to soft reset + \param[in] usb_regs: pointer to USB core registers + \param[out] none + \retval none +*/ +static void usb_core_reset (usb_core_regs *usb_regs) +{ + /* enable core soft reset */ + usb_regs->gr->GRSTCTL |= GRSTCTL_CSRST; + + /* wait for the core to be soft reset */ + while (usb_regs->gr->GRSTCTL & GRSTCTL_CSRST) { + /* no operation */ + } + + /* wait for additional 3 PHY clocks */ + usb_udelay(3U); +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_dev.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_dev.c new file mode 100644 index 00000000..39d4b9b5 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_dev.c @@ -0,0 +1,595 @@ +/*! + \file drv_usb_dev.c + \brief USB device mode low level driver + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_dev.h" + +/* endpoint 0 max packet length */ +static const uint8_t EP0_MAXLEN[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = EP0MPL_64, + [DSTAT_EM_FS_PHY_48MHZ] = EP0MPL_64, + [DSTAT_EM_LS_PHY_6MHZ] = EP0MPL_8 +}; + +#ifdef USB_FS_CORE + +/* USB endpoint Tx FIFO size */ +static uint16_t USBFS_TX_FIFO_SIZE[USBFS_MAX_EP_COUNT] = +{ + (uint16_t)TX0_FIFO_FS_SIZE, + (uint16_t)TX1_FIFO_FS_SIZE, + (uint16_t)TX2_FIFO_FS_SIZE, + (uint16_t)TX3_FIFO_FS_SIZE +}; + +#endif /* USBFS_CORE */ + +/*! + \brief initialize USB core registers for device mode + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devcore_init (usb_core_driver *udev) +{ + uint8_t i; + + /* restart the PHY clock (maybe don't need to...) */ + *udev->regs.PWRCLKCTL = 0U; + + /* configure periodic frame interval to default value */ + udev->regs.dr->DCFG &= ~DCFG_EOPFT; + udev->regs.dr->DCFG |= FRAME_INTERVAL_80; + + udev->regs.dr->DCFG &= ~DCFG_DS; + +#ifdef USB_FS_CORE + if (udev->bp.core_enum == (uint8_t)USB_CORE_ENUM_FS) { + /* set full-speed PHY */ + udev->regs.dr->DCFG |= USB_SPEED_INP_FULL; + + /* set Rx FIFO size */ + usb_set_rxfifo(&udev->regs, RX_FIFO_FS_SIZE); + + /* set endpoint 0 to 3's Tx FIFO length and RAM address */ + for(i = 0U; i < USBFS_MAX_EP_COUNT; i++) { + usb_set_txfifo(&udev->regs, i, USBFS_TX_FIFO_SIZE[i]); + } + } +#endif /* USB_FS_CORE */ + + /* make sure all FIFOs are flushed */ + + /* flush all Tx FIFOs */ + (void)usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush entire Rx FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + + /* clear all pending device interrupts */ + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + udev->regs.dr->DAEPINTEN = 0U; + + /* configure all IN/OUT endpoints */ + for (i = 0U; i < udev->bp.num_ep; i++) { + if (udev->regs.er_in[i]->DIEPCTL & DEPCTL_EPEN) { + udev->regs.er_in[i]->DIEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_in[i]->DIEPCTL = 0U; + } + + /* set IN endpoint transfer length to 0 */ + udev->regs.er_in[i]->DIEPLEN = 0U; + + /* clear all pending IN endpoint interrupts */ + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + + if (udev->regs.er_out[i]->DOEPCTL & DEPCTL_EPEN) { + udev->regs.er_out[i]->DOEPCTL |= DEPCTL_EPD | DEPCTL_SNAK; + } else { + udev->regs.er_out[i]->DOEPCTL = 0U; + } + + /* set OUT endpoint transfer length to 0 */ + udev->regs.er_out[i]->DOEPLEN = 0U; + + /* clear all pending OUT endpoint interrupts */ + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN |= DIEPINTEN_EPTXFUDEN; + + (void)usb_devint_enable (udev); + + return USB_OK; +} + +/*! + \brief enable the USB device mode interrupts + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +usb_status usb_devint_enable (usb_core_driver *udev) +{ + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* clear any pending interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable device_mode-related interrupts */ + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + } + + udev->regs.gr->GINTEN |= GINTEN_RSTIE | GINTEN_ENUMFIE | GINTEN_IEPIE | \ + GINTEN_OEPIE | GINTEN_SOFIE | GINTEN_ISOONCIE | GINTEN_ISOINCIE; + +#ifdef VBUS_SENSING_ENABLED + udev->regs.gr->GINTEN |= GINTEN_SESIE | GINTEN_OTGIE; +#endif /* VBUS_SENSING_ENABLED */ + + return USB_OK; +} + +/*! + \brief active the USB endpoint0 transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB endpoint0 transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc0_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint32_t enum_speed = udev->regs.dr->DSTAT & DSTAT_ES; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + if (ep_num) { + /* not endpoint 0 */ + return USB_FAIL; + } + + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[0]->DIEPCTL; + } else { + reg_addr = &udev->regs.er_out[0]->DOEPCTL; + } + + /* endpoint 0 is activated after USB clock is enabled */ + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint 0 maximum packet length */ + *reg_addr |= EP0_MAXLEN[enum_speed]; + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + + return USB_OK; +} + +/*! + \brief active the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_active (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + uint32_t epinten = 0U; + uint32_t enum_speed = udev->regs.dr->DSTAT & DSTAT_ES; + + /* get the endpoint number */ + uint8_t ep_num = transc->ep_addr.num; + + /* enable endpoint interrupt number */ + if (transc->ep_addr.dir) { + reg_addr = &udev->regs.er_in[ep_num]->DIEPCTL; + + epinten = 1U << ep_num; + } else { + reg_addr = &udev->regs.er_out[ep_num]->DOEPCTL; + + epinten = 1U << (16U + ep_num); + } + + /* if the endpoint is not active, need change the endpoint control register */ + if (!(*reg_addr & DEPCTL_EPACT)) { + *reg_addr &= ~(DEPCTL_MPL | DEPCTL_EPTYPE | DIEPCTL_TXFNUM); + + /* set endpoint maximum packet length */ + if (0U == ep_num) { + *reg_addr |= EP0_MAXLEN[enum_speed]; + } else { + *reg_addr |= transc->max_len; + } + + /* activate endpoint */ + *reg_addr |= ((uint32_t)transc->ep_type << 18U) | ((uint32_t)ep_num << 22U) | DEPCTL_SD0PID | DEPCTL_EPACT; + } + + /* enable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN |= epinten; + + return USB_OK; +} + +/*! + \brief deactivate the USB transaction + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_deactivate(usb_core_driver *udev, usb_transc *transc) +{ + uint32_t epinten = 0U; + + uint8_t ep_num = transc->ep_addr.num; + + /* disable endpoint interrupt number */ + if (transc->ep_addr.dir) { + epinten = 1U << ep_num; + + udev->regs.er_in[ep_num]->DIEPCTL &= ~DEPCTL_EPACT; + } else { + epinten = 1U << (ep_num + 16U); + + udev->regs.er_out[ep_num]->DOEPCTL &= ~DEPCTL_EPACT; + } + + /* disable the interrupts for this endpoint */ + udev->regs.dr->DAEPINTEN &= ~epinten; + + return USB_OK; +} + +/*! + \brief configure USB transaction to start IN transfer + \param[in] udev: pointer to USB device + \param[in] transc: the USB IN transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_inxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + __IO uint32_t epctl = udev->regs.er_in[ep_num]->DIEPCTL; + __IO uint32_t eplen = udev->regs.er_in[ep_num]->DIEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if (0U == transc->xfer_len) { + /* set transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* set transfer packet count */ + if (0U == ep_num) { + transc->xfer_len = USB_MIN(transc->xfer_len, transc->max_len); + + eplen |= 1U << 19U; + } else { + eplen |= (((transc->xfer_len - 1U) + transc->max_len) / transc->max_len) << 19U; + } + + /* set endpoint transfer length */ + eplen |= transc->xfer_len; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + eplen |= DIEPLEN_MCNT & (1U << 29U); + } + } + + udev->regs.er_in[ep_num]->DIEPLEN = eplen; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (((udev->regs.dr->DSTAT & DSTAT_FNRSOF) >> 8U) & 0x01U) { + epctl |= DEPCTL_SEVNFRM; + } else { + epctl |= DEPCTL_SODDFRM; + } + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_CNAK | DEPCTL_EPEN; + + udev->regs.er_in[ep_num]->DIEPCTL = epctl; + + if ((uint8_t)USB_USE_FIFO == udev->bp.transfer_mode) { + if (transc->ep_type != (uint8_t)USB_EPTYPE_ISOC) { + /* enable the Tx FIFO empty interrupt for this endpoint */ + if (transc->xfer_len > 0U) { + udev->regs.dr->DIEPFEINTEN |= 1U << ep_num; + } + } else { + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, ep_num, (uint16_t)transc->xfer_len); + } + } + + return status; +} + +/*! + \brief configure USB transaction to start OUT transfer + \param[in] udev: pointer to USB device + \param[in] transc: the USB OUT transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_outxfer (usb_core_driver *udev, usb_transc *transc) +{ + usb_status status = USB_OK; + + uint8_t ep_num = transc->ep_addr.num; + + uint32_t epctl = udev->regs.er_out[ep_num]->DOEPCTL; + uint32_t eplen = udev->regs.er_out[ep_num]->DOEPLEN; + + eplen &= ~(DEPLEN_TLEN | DEPLEN_PCNT); + + /* zero length packet or endpoint 0 */ + if ((0U == transc->xfer_len) || (0U == ep_num)) { + /* set the transfer length to max packet size */ + eplen |= transc->max_len; + + /* set the transfer packet count to 1 */ + eplen |= 1U << 19U; + } else { + /* configure the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + uint32_t packet_count = (transc->xfer_len + transc->max_len - 1U) / transc->max_len; + + eplen |= packet_count << 19U; + eplen |= packet_count * transc->max_len; + } + + udev->regs.er_out[ep_num]->DOEPLEN = eplen; + + if (transc->ep_type == (uint8_t)USB_EPTYPE_ISOC) { + if (transc->frame_num) { + epctl |= DEPCTL_SD1PID; + } else { + epctl |= DEPCTL_SD0PID; + } + } + + /* enable the endpoint and clear the NAK */ + epctl |= DEPCTL_EPEN | DEPCTL_CNAK; + + udev->regs.er_out[ep_num]->DOEPCTL = epctl; + + return status; +} + +/*! + \brief set the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval status +*/ +usb_status usb_transc_stall (usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + + /* set the endpoint disable bit */ + if (*reg_addr & DEPCTL_EPEN) { + *reg_addr |= DEPCTL_EPD; + } + } else { + /* set the endpoint stall bit */ + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* set the endpoint stall bit */ + *reg_addr |= DEPCTL_STALL; + + return USB_OK; +} + +/*! + \brief clear the USB transaction STALL status + \param[in] udev: pointer to USB device + \param[in] transc: the USB transaction + \param[out] none + \retval operation status +*/ +usb_status usb_transc_clrstall(usb_core_driver *udev, usb_transc *transc) +{ + __IO uint32_t *reg_addr = NULL; + + uint8_t ep_num = transc->ep_addr.num; + + if (transc->ep_addr.dir) { + reg_addr = &(udev->regs.er_in[ep_num]->DIEPCTL); + } else { + reg_addr = &(udev->regs.er_out[ep_num]->DOEPCTL); + } + + /* clear the endpoint stall bits */ + *reg_addr &= ~DEPCTL_STALL; + + /* reset data PID of the periodic endpoints */ + if ((transc->ep_type == (uint8_t)USB_EPTYPE_INTR) || (transc->ep_type == (uint8_t)USB_EPTYPE_BULK)) { + *reg_addr |= DEPCTL_SD0PID; + } + + return USB_OK; +} + +/*! + \brief read device IN endpoint interrupt flag register + \param[in] udev: pointer to USB device + \param[in] ep_num: endpoint number + \param[out] none + \retval interrupt value +*/ +uint32_t usb_iepintr_read (usb_core_driver *udev, uint8_t ep_num) +{ + uint32_t value = 0U, fifoemptymask, commonintmask; + + commonintmask = udev->regs.dr->DIEPINTEN; + fifoemptymask = udev->regs.dr->DIEPFEINTEN; + + /* check FIFO empty interrupt enable bit */ + commonintmask |= ((fifoemptymask >> ep_num) & 0x1U) << 7; + + value = udev->regs.er_in[ep_num]->DIEPINTF & commonintmask; + + return value; +} + +/*! + \brief configures OUT endpoint 0 to receive SETUP packets + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_ctlep_startout (usb_core_driver *udev) +{ + /* set OUT endpoint 0 receive length to 24 bytes, 1 packet and 3 setup packets */ + udev->regs.er_out[0]->DOEPLEN = DOEP0_TLEN(8U * 3U) | DOEP0_PCNT(1U) | DOEP0_STPCNT(3U); +} + +/*! + \brief active remote wakeup signaling + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_rwkup_active (usb_core_driver *udev) +{ + if (udev->dev.pm.dev_remote_wakeup) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + if (udev->bp.low_power) { + /* ungate USB core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + + /* active remote wakeup signaling */ + udev->regs.dr->DCTL |= DCTL_RWKUP; + + usb_mdelay(5U); + + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + } + } +} + +/*! + \brief active USB core clock + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_clock_active (usb_core_driver *udev) +{ + if (udev->bp.low_power) { + if (udev->regs.dr->DSTAT & DSTAT_SPST) { + /* ungate USB Core clock */ + *udev->regs.PWRCLKCTL &= ~(PWRCLKCTL_SHCLK | PWRCLKCTL_SUCLK); + } + } +} + +/*! + \brief USB device suspend + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_suspend (usb_core_driver *udev) +{ + __IO uint32_t devstat = udev->regs.dr->DSTAT; + + if ((udev->bp.low_power) && (devstat & DSTAT_SPST)) { + /* switch-off the USB clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode (PMU_LDO_LOWPOWER, WFI_CMD); + } +} + +/*! + \brief stop the device and clean up FIFOs + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_dev_stop (usb_core_driver *udev) +{ + uint32_t i; + + udev->dev.cur_status = 1U; + + /* clear all interrupt flag and enable bits */ + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + udev->regs.dr->DIEPINTEN = 0U; + udev->regs.dr->DOEPINTEN = 0U; + udev->regs.dr->DAEPINTEN = 0U; + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* flush the FIFO */ + (void)usb_rxfifo_flush (&udev->regs); + (void)usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_host.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_host.c new file mode 100644 index 00000000..30333532 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usb_host.c @@ -0,0 +1,446 @@ +/*! + \file drv_usb_host.c + \brief USB host mode low level driver + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usb_host.h" + +const uint32_t PIPE_DPID[2] = { + PIPE_DPID_DATA0, + PIPE_DPID_DATA1 +}; + +/*! + \brief initializes USB core for host mode + \param[in] udev: pointer to selected USB host + \param[out] none + \retval operation status +*/ +usb_status usb_host_init (usb_core_driver *udev) +{ + uint32_t i = 0U, inten = 0U; + + uint32_t nptxfifolen = 0U; + uint32_t ptxfifolen = 0U; + + /* restart the PHY Clock */ + *udev->regs.PWRCLKCTL = 0U; + + /* configure USB clock of PHY */ + usb_phyclock_config (udev, HCTL_48MHZ); + + /* support FS/LS only */ + udev->regs.hr->HCTL &= ~HCTL_SPDFSLS; + + /* configure data FIFOs size */ +#ifdef USB_FS_CORE + if (USB_CORE_ENUM_FS == udev->bp.core_enum) { + /* set Rx FIFO size */ + udev->regs.gr->GRFLEN = USB_RX_FIFO_FS_SIZE; + + /* set non-periodic Tx FIFO size and address */ + nptxfifolen |= USB_RX_FIFO_FS_SIZE; + nptxfifolen |= USB_HTX_NPFIFO_FS_SIZE << 16U; + udev->regs.gr->DIEP0TFLEN_HNPTFLEN = nptxfifolen; + + /* set periodic Tx FIFO size and address */ + ptxfifolen |= USB_RX_FIFO_FS_SIZE + USB_HTX_NPFIFO_FS_SIZE; + ptxfifolen |= USB_HTX_PFIFO_FS_SIZE << 16U; + udev->regs.gr->HPTFLEN = ptxfifolen; + } +#endif /* USB_FS_CORE */ + +#ifdef USE_OTG_MODE + + /* clear host set HNP enable in the usb_otg control register */ + udev->regs.gr->GOTGCS &= ~GOTGCS_HHNPEN; + +#endif /* USE_OTG_MODE */ + + /* make sure the FIFOs are flushed */ + + /* flush all Tx FIFOs in device or host mode */ + usb_txfifo_flush (&udev->regs, 0x10U); + + /* flush the entire Rx FIFO */ + usb_rxfifo_flush (&udev->regs); + + /* disable all interrupts */ + udev->regs.gr->GINTEN = 0U; + + /* clear any pending USB OTG interrupts */ + udev->regs.gr->GOTGINTF = 0xFFFFFFFFU; + + /* enable the USB wakeup and suspend interrupts */ + udev->regs.gr->GINTF = 0xBFFFFFFFU; + + /* clear all pending host channel interrupts */ + for (i = 0U; i < udev->bp.num_pipe; i++) { + udev->regs.pr[i]->HCHINTF = 0xFFFFFFFFU; + udev->regs.pr[i]->HCHINTEN = 0U; + } + +#ifndef USE_OTG_MODE + usb_portvbus_switch (udev, 1U); +#endif /* USE_OTG_MODE */ + + udev->regs.gr->GINTEN = GINTEN_WKUPIE | GINTEN_SPIE; + + /* enable host_mode-related interrupts */ + if (USB_USE_FIFO == udev->bp.transfer_mode) { + inten = GINTEN_RXFNEIE; + } + + inten |= GINTEN_SESIE | GINTEN_HPIE | GINTEN_HCIE | GINTEN_ISOINCIE; + + udev->regs.gr->GINTEN |= inten; + + inten = GINTEN_DISCIE | GINTEN_SOFIE; + + udev->regs.gr->GINTEN &= ~inten; + + return USB_OK; +} + +/*! + \brief control the VBUS to power + \param[in] udev: pointer to selected usb host + \param[in] state: VBUS state + \param[out] none + \retval none +*/ +void usb_portvbus_switch (usb_core_driver *udev, uint8_t state) +{ + uint32_t port = 0U; + + /* enable or disable the external charge pump */ + usb_vbus_drive (state); + + /* turn on the host port power. */ + port = usb_port_read (udev); + + if (!(port & HPCS_PP) && (1U == state)) { + port |= HPCS_PP; + } + + if ((port & HPCS_PP) && (0U == state)) { + port &= ~HPCS_PP; + } + + *udev->regs.HPCS = port; + + usb_mdelay (200U); +} + +/*! + \brief reset host port + \param[in] udev: pointer to USB device + \param[out] none + \retval operation status +*/ +uint32_t usb_port_reset (usb_core_driver *udev) +{ + __IO uint32_t port = usb_port_read (udev); + + *udev->regs.HPCS = port | HPCS_PRST; + + usb_mdelay(20U); /* see note */ + + *udev->regs.HPCS = port & ~HPCS_PRST; + + usb_mdelay(20U); + + return 1U; +} + +/*! + \brief initialize host pipe + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_init (usb_core_driver *udev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + __IO uint32_t pp_ctl = 0U; + __IO uint32_t pp_inten = HCHINTEN_TFIE; + + usb_pipe *pp = &udev->host.pipe[pipe_num]; + + /* clear old interrupt conditions for this host channel */ + udev->regs.pr[pipe_num]->HCHINTF = 0xFFFFFFFFU; + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_BBERIE; + } + + /* enable channel interrupts required for this transfer */ + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE \ + | HCHINTEN_DTERIE | HCHINTEN_NAKIE; + + if (!pp->ep.dir) { + if (PORT_SPEED_HIGH == pp->dev_speed) { + pp_inten |= HCHINTEN_NYETIE; + pp_inten |= HCHINTEN_ACKIE; + } + } + break; + + case USB_EPTYPE_INTR: + pp_inten |= HCHINTEN_STALLIE | HCHINTEN_USBERIE | HCHINTEN_DTERIE \ + | HCHINTEN_NAKIE | HCHINTEN_REQOVRIE; + break; + + case USB_EPTYPE_ISOC: + pp_inten |= HCHINTEN_REQOVRIE | HCHINTEN_ACKIE; + + if (pp->ep.dir) { + pp_inten |= HCHINTEN_USBERIE; + } + break; + + default: + break; + } + + udev->regs.pr[pipe_num]->HCHINTEN = pp_inten; + + /* enable the top level host channel interrupt */ + udev->regs.hr->HACHINTEN |= 1U << pipe_num; + + /* make sure host channel interrupts are enabled */ + udev->regs.gr->GINTEN |= GINTEN_HCIE; + + /* program the host channel control register */ + pp_ctl |= PIPE_CTL_DAR(pp->dev_addr); + pp_ctl |= PIPE_CTL_EPNUM(pp->ep.num); + pp_ctl |= PIPE_CTL_EPDIR(pp->ep.dir); + pp_ctl |= PIPE_CTL_EPTYPE(pp->ep.type); + pp_ctl |= PIPE_CTL_LSD(pp->dev_speed == PORT_SPEED_LOW); + + pp_ctl |= pp->ep.mps; + pp_ctl |= ((uint32_t)(pp->ep.type == USB_EPTYPE_INTR) << 29U) & HCHCTL_ODDFRM; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return status; +} + +/*! + \brief prepare host channel for transferring packets + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_xfer (usb_core_driver *udev, uint8_t pipe_num) +{ + usb_status status = USB_OK; + + uint16_t dword_len = 0U; + uint16_t packet_count = 0U; + + __IO uint32_t pp_ctl = 0U; + + usb_pipe *pp = &udev->host.pipe[pipe_num]; + + uint16_t max_packet_len = pp->ep.mps; + + /* compute the expected number of packets associated to the transfer */ + if (pp->xfer_len > 0U) { + packet_count = (uint16_t)((pp->xfer_len + max_packet_len - 1U) / max_packet_len); + + if (packet_count > HC_MAX_PACKET_COUNT) { + packet_count = HC_MAX_PACKET_COUNT; + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + } else { + packet_count = 1U; + } + + if (pp->ep.dir) { + pp->xfer_len = (uint16_t)(packet_count * max_packet_len); + } + + /* initialize the host channel transfer information */ + udev->regs.pr[pipe_num]->HCHLEN = pp->xfer_len | pp->DPID | PIPE_XFER_PCNT(packet_count); + + pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + if (usb_frame_even(udev)) { + pp_ctl |= HCHCTL_ODDFRM; + } else { + pp_ctl &= ~HCHCTL_ODDFRM; + } + + /* set host channel enabled */ + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + if (USB_USE_FIFO == udev->bp.transfer_mode) { + if ((0U == pp->ep.dir) && (pp->xfer_len > 0U)) { + switch (pp->ep.type) { + /* non-periodic transfer */ + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in FIFO space */ + if (dword_len > (udev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + /* need to process data in nptxfempty interrupt */ + udev->regs.gr->GINTEN |= GINTEN_NPTXFEIE; + } + break; + + /* periodic transfer */ + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + dword_len = (uint16_t)((pp->xfer_len + 3U) / 4U); + + /* check if there is enough space in fifo space */ + if (dword_len > (udev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + /* need to process data in ptxfempty interrupt */ + udev->regs.gr->GINTEN |= GINTEN_PTXFEIE; + } + break; + + default: + break; + } + + /* write packet into the Tx fifo. */ + usb_txfifo_write (&udev->regs, pp->xfer_buf, pipe_num, (uint16_t)pp->xfer_len); + } + } + + return status; +} + +/*! + \brief halt pipe + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_halt (usb_core_driver *udev, uint8_t pipe_num) +{ + __IO uint32_t pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + uint8_t ep_type = (uint8_t)((pp_ctl & HCHCTL_EPTYPE) >> 18U); + + pp_ctl |= HCHCTL_CEN | HCHCTL_CDIS; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + if (0U == (udev->regs.gr->HNPTFQSTAT & HNPTFQSTAT_NPTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + if (0U == (udev->regs.hr->HPTFQSTAT & HPTFQSTAT_PTXFS)) { + pp_ctl &= ~HCHCTL_CEN; + } + break; + + default: + break; + } + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief configure host pipe to do ping operation + \param[in] udev: pointer to USB device + \param[in] pipe_num: host pipe number which is in (0..7) + \param[out] none + \retval operation status +*/ +usb_status usb_pipe_ping (usb_core_driver *udev, uint8_t pipe_num) +{ + uint32_t pp_ctl = 0U; + + udev->regs.pr[pipe_num]->HCHLEN = HCHLEN_PING | (HCHLEN_PCNT & (1U << 19U)); + + pp_ctl = udev->regs.pr[pipe_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pipe_num]->HCHCTL = pp_ctl; + + return USB_OK; +} + +/*! + \brief stop the USB host and clean up FIFO + \param[in] udev: pointer to USB device + \param[out] none + \retval none +*/ +void usb_host_stop (usb_core_driver *udev) +{ + uint32_t i; + __IO uint32_t pp_ctl = 0U; + + udev->regs.hr->HACHINTEN = 0x0U; + udev->regs.hr->HACHINT = 0xFFFFFFFFU; + + /* flush out any leftover queued requests. */ + for (i = 0U; i < udev->bp.num_pipe; i++) { + pp_ctl = udev->regs.pr[i]->HCHCTL; + + pp_ctl &= ~(HCHCTL_CEN | HCHCTL_EPDIR); + pp_ctl |= HCHCTL_CDIS; + + udev->regs.pr[i]->HCHCTL = pp_ctl; + } + + /* flush the FIFO */ + usb_rxfifo_flush (&udev->regs); + usb_txfifo_flush (&udev->regs, 0x10U); +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usbd_int.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usbd_int.c new file mode 100644 index 00000000..08498d97 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usbd_int.c @@ -0,0 +1,494 @@ +/*! + \file drv_usbd_int.c + \brief USB device mode interrupt routines + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbd_conf.h" +#include "drv_usbd_int.h" +#include "usbd_transc.h" + +/* local function prototypes ('static') */ +static uint32_t usbd_int_epout (usb_core_driver *udev); +static uint32_t usbd_int_epin (usb_core_driver *udev); +static uint32_t usbd_int_rxfifo (usb_core_driver *udev); +static uint32_t usbd_int_reset (usb_core_driver *udev); +static uint32_t usbd_int_enumfinish (usb_core_driver *udev); +static uint32_t usbd_int_suspend (usb_core_driver *udev); +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num); + +static const uint8_t USB_SPEED[4] = { + [DSTAT_EM_HS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_HIGH, + [DSTAT_EM_FS_PHY_30MHZ_60MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_FS_PHY_48MHZ] = (uint8_t)USB_SPEED_FULL, + [DSTAT_EM_LS_PHY_6MHZ] = (uint8_t)USB_SPEED_LOW +}; + +__IO uint8_t setupc_flag = 0U; + +/*! + \brief USB device-mode interrupts global service routine handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval none +*/ +void usbd_isr (usb_core_driver *udev) +{ + if (HOST_MODE != (udev->regs.gr->GINTF & GINTF_COPM)) { + uint32_t intr = udev->regs.gr->GINTF; + intr &= udev->regs.gr->GINTEN; + + /* there are no interrupts, avoid spurious interrupt */ + if (!intr) { + return; + } + + /* OUT endpoints interrupts */ + if (intr & GINTF_OEPIF) { + (void)usbd_int_epout (udev); + } + + /* IN endpoints interrupts */ + if (intr & GINTF_IEPIF) { + (void)usbd_int_epin (udev); + } + + /* suspend interrupt */ + if (intr & GINTF_SP) { + (void)usbd_int_suspend (udev); + } + + /* wakeup interrupt */ + if (intr & GINTF_WKUPIF) { + if(USBD_SUSPENDED == udev->dev.cur_status){ + /* inform upper layer by the resume event */ + udev->dev.cur_status = udev->dev.backup_status; + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + + /* start of frame interrupt */ + if (intr & GINTF_SOF) { + if (udev->dev.class_core->SOF) { + (void)udev->dev.class_core->SOF(udev); + } + + if (0U != setupc_flag) { + setupc_flag++; + + if (setupc_flag >= 3U) { + usbd_setup_transc (udev); + + setupc_flag = 0U; + } + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + /* receive FIFO not empty interrupt */ + if (intr & GINTF_RXFNEIF) { + (void)usbd_int_rxfifo (udev); + } + + /* USB reset interrupt */ + if (intr & GINTF_RST) { + (void)usbd_int_reset (udev); + } + + /* enumeration has been done interrupt */ + if (intr & GINTF_ENUMFIF) { + (void)usbd_int_enumfinish (udev); + } + + /* incomplete synchronization IN transfer interrupt*/ + if (intr & GINTF_ISOINCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_in) { + (void)udev->dev.class_core->incomplete_isoc_in(udev); + } + + /* Clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOINCIF; + } + + /* incomplete synchronization OUT transfer interrupt*/ + if (intr & GINTF_ISOONCIF) { + if (NULL != udev->dev.class_core->incomplete_isoc_out) { + (void)udev->dev.class_core->incomplete_isoc_out(udev); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + +#ifdef VBUS_SENSING_ENABLED + + /* session request interrupt */ + if (intr & GINTF_SESIF) { + udev->regs.gr->GINTF = GINTF_SESIF; + } + + /* OTG mode interrupt */ + if (intr & GINTF_OTGIF) { + if(udev->regs.gr->GOTGINTF & GOTGINTF_SESEND) { + + } + + /* clear OTG interrupt */ + udev->regs.gr->GINTF = GINTF_OTGIF; + } +#endif /* VBUS_SENSING_ENABLED */ + } +} + +/*! + \brief indicates that an OUT endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epout (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_oepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x01U) { + __IO uint32_t oepintr = usb_oepintr_read (udev, ep_num); + + /* transfer complete interrupt */ + if (oepintr & DOEPINTF_TF) { + /* clear the bit in DOEPINTF for this interrupt */ + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_TF; + + /* inform upper layer: data ready */ + (void)usbd_out_transc (udev, ep_num); + } + + /* setup phase finished interrupt (control endpoints) */ + if (oepintr & DOEPINTF_STPF) { + if((0U == ep_num) && (0U != setupc_flag)) { + /* inform the upper layer that a setup packet is available */ + (void)usbd_setup_transc (udev); + + udev->regs.er_out[ep_num]->DOEPINTF = DOEPINTF_STPF; + + setupc_flag = 0U; + } + } + } + } + + return 1U; +} + +/*! + \brief indicates that an IN endpoint has a pending interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_epin (usb_core_driver *udev) +{ + uint32_t epintnum = 0U; + uint8_t ep_num = 0U; + + for (epintnum = usb_iepintnum_read (udev); epintnum; epintnum >>= 1, ep_num++) { + if (epintnum & 0x1U) { + __IO uint32_t iepintr = usb_iepintr_read (udev, ep_num); + + if (iepintr & DIEPINTF_TF) { + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TF; + + /* data transmission is completed */ + (void)usbd_in_transc (udev, ep_num); + } + + if (iepintr & DIEPINTF_TXFE) { + usbd_emptytxfifo_write (udev, (uint32_t)ep_num); + + udev->regs.er_in[ep_num]->DIEPINTF = DIEPINTF_TXFE; + } + } + } + + return 1U; +} + +/*! + \brief handle the RX status queue level interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_rxfifo (usb_core_driver *udev) +{ + usb_transc *transc = NULL; + + uint8_t data_PID = 0U; + uint32_t bcount = 0U; + + __IO uint32_t devrxstat = 0U; + + /* disable the Rx status queue non-empty interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + /* get the status from the top of the FIFO */ + devrxstat = udev->regs.gr->GRSTATP; + + uint8_t ep_num = (uint8_t)(devrxstat & GRSTATRP_EPNUM); + + transc = &udev->dev.transc_out[ep_num]; + + bcount = (devrxstat & GRSTATRP_BCOUNT) >> 4U; + data_PID = (uint8_t)((devrxstat & GRSTATRP_DPID) >> 15U); + + switch((devrxstat & GRSTATRP_RPCKST) >> 17U) { + case RSTAT_GOUT_NAK: + break; + + case RSTAT_DATA_UPDT: + if (bcount > 0U) { + (void)usb_rxfifo_read (&udev->regs, transc->xfer_buf, (uint16_t)bcount); + + transc->xfer_buf += bcount; + transc->xfer_count += bcount; + } + break; + + case RSTAT_XFER_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_COMP: + /* trigger the OUT endpoint interrupt */ + break; + + case RSTAT_SETUP_UPDT: + if ((0U == transc->ep_addr.num) && (8U == bcount) && (DPID_DATA0 == data_PID)) { + /* copy the setup packet received in FIFO into the setup buffer in RAM */ + (void)usb_rxfifo_read (&udev->regs, (uint8_t *)&udev->dev.control.req, (uint16_t)bcount); + + transc->xfer_count += bcount; + + /* set the flag */ + setupc_flag = 1; + } + break; + + default: + break; + } + + /* enable the Rx status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle USB reset interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_reset (usb_core_driver *udev) +{ + uint32_t i; + + /* clear the remote wakeup signaling */ + udev->regs.dr->DCTL &= ~DCTL_RWKUP; + + /* flush the Tx FIFO */ + (void)usb_txfifo_flush (&udev->regs, 0U); + + for (i = 0U; i < udev->bp.num_ep; i++) { + udev->regs.er_in[i]->DIEPINTF = 0xFFU; + udev->regs.er_out[i]->DOEPINTF = 0xFFU; + } + + /* clear all pending device endpoint interrupts */ + udev->regs.dr->DAEPINT = 0xFFFFFFFFU; + + /* enable endpoint 0 interrupts */ + udev->regs.dr->DAEPINTEN = 1U | (1U << 16U); + + /* enable OUT endpoint interrupts */ + udev->regs.dr->DOEPINTEN = DOEPINTEN_STPFEN | DOEPINTEN_TFEN; + + /* enable IN endpoint interrupts */ + udev->regs.dr->DIEPINTEN = DIEPINTEN_TFEN; + + /* reset device address */ + udev->regs.dr->DCFG &= ~DCFG_DAR; + + /* configure endpoint 0 to receive SETUP packets */ + usb_ctlep_startout (udev); + + /* clear USB reset interrupt */ + udev->regs.gr->GINTF = GINTF_RST; + + udev->dev.transc_out[0] = (usb_transc) { + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_out[0]); + + udev->dev.transc_in[0] = (usb_transc) { + .ep_addr = { + .dir = 1U + }, + + .ep_type = USB_EPTYPE_CTRL, + .max_len = USB_FS_EP0_MAX_LEN + }; + + (void)usb_transc_active (udev, &udev->dev.transc_in[0]); + + /* upon reset call user call back */ + udev->dev.cur_status = (uint8_t)USBD_DEFAULT; + + return 1U; +} + +/*! + \brief handle USB speed enumeration finish interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval status +*/ +static uint32_t usbd_int_enumfinish (usb_core_driver *udev) +{ + uint8_t enum_speed = (uint8_t)((udev->regs.dr->DSTAT & DSTAT_ES) >> 1U); + + udev->regs.dr->DCTL &= ~DCTL_CGINAK; + udev->regs.dr->DCTL |= DCTL_CGINAK; + + udev->regs.gr->GUSBCS &= ~GUSBCS_UTT; + + /* set USB turn-around time based on device speed and PHY interface */ + if (USB_SPEED[enum_speed] == (uint8_t)USB_SPEED_HIGH) { + udev->bp.core_speed = (uint8_t)USB_SPEED_HIGH; + + udev->regs.gr->GUSBCS |= 0x09U << 10U; + } else { + udev->bp.core_speed = (uint8_t)USB_SPEED_FULL; + + udev->regs.gr->GUSBCS |= 0x05U << 10U; + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ENUMFIF; + + return 1U; +} + +/*! + \brief USB suspend interrupt handler + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbd_int_suspend (usb_core_driver *udev) +{ + __IO uint8_t low_power = udev->bp.low_power; + __IO uint8_t suspend = (uint8_t)(udev->regs.dr->DSTAT & DSTAT_SPST); + __IO uint8_t is_configured = (udev->dev.cur_status == (uint8_t)USBD_CONFIGURED) ? 1U : 0U; + + udev->dev.backup_status = udev->dev.cur_status; + udev->dev.cur_status = (uint8_t)USBD_SUSPENDED; + + if (low_power && suspend && is_configured) { + /* switch-off the USB clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK | PWRCLKCTL_SHCLK; + + /* enter DEEP_SLEEP mode with LDO in low power mode */ + pmu_to_deepsleepmode (PMU_LDO_LOWPOWER, WFI_CMD); + } + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SP; + + return 1U; +} + +/*! + \brief check FIFO for the next packet to be loaded + \param[in] udev: pointer to USB device instance + \param[in] ep_num: endpoint identifier which is in (0..3) + \param[out] none + \retval status +*/ +static uint32_t usbd_emptytxfifo_write (usb_core_driver *udev, uint32_t ep_num) +{ + uint32_t len; + uint32_t word_count; + + usb_transc *transc = &udev->dev.transc_in[ep_num]; + + len = transc->xfer_len - transc->xfer_count; + + /* get the data length to write */ + if (len > transc->max_len) { + len = transc->max_len; + } + + word_count = (len + 3U) / 4U; + + while (((udev->regs.er_in[ep_num]->DIEPTFSTAT & DIEPTFSTAT_IEPTFS) >= word_count) && \ + (transc->xfer_count < transc->xfer_len)) { + len = transc->xfer_len - transc->xfer_count; + + if (len > transc->max_len) { + len = transc->max_len; + } + + /* write FIFO in word(4bytes) */ + word_count = (len + 3U) / 4U; + + /* write the FIFO */ + (void)usb_txfifo_write (&udev->regs, transc->xfer_buf, (uint8_t)ep_num, (uint16_t)len); + + transc->xfer_buf += len; + transc->xfer_count += len; + + if (transc->xfer_count == transc->xfer_len) { + /* disable the device endpoint FIFO empty interrupt */ + udev->regs.dr->DIEPFEINTEN &= ~(0x01U << ep_num); + } + } + + return 1U; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usbh_int.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usbh_int.c new file mode 100644 index 00000000..b096f31e --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/driver/Source/drv_usbh_int.c @@ -0,0 +1,598 @@ +/*! + \file drv_usbh_int.c + \brief USB host mode interrupt handler file + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usbh_int.h" + +#if defined (__CC_ARM) /*!< ARM compiler */ +#pragma O0 +#elif defined (__GNUC__) /*!< GNU compiler */ +#pragma GCC optimize ("O0") +#elif defined (__TASKING__) /*!< TASKING compiler */ +#pragma optimize=0 +#endif /* __CC_ARM */ + +/* local function prototypes ('static') */ +static uint32_t usbh_int_port (usb_core_driver *udev); +static uint32_t usbh_int_pipe (usb_core_driver *udev); +static uint32_t usbh_int_pipe_in (usb_core_driver *udev, uint32_t pp_num); +static uint32_t usbh_int_pipe_out (usb_core_driver *udev, uint32_t pp_num); +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *udev); +static uint32_t usbh_int_txfifoempty (usb_core_driver *udev, usb_pipe_mode pp_mode); + +/*! + \brief handle global host interrupt + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +uint32_t usbh_isr (usb_core_driver *udev) +{ + uint32_t retval = 0U; + + __IO uint32_t intr = 0U; + + /* check if host mode */ + if (HOST_MODE == (udev->regs.gr->GINTF & GINTF_COPM)) { + intr = usb_coreintr_get(&udev->regs); + + if (!intr) { + return 0U; + } + + if (intr & GINTF_SOF) { + usbh_int_fop->SOF(udev->host.data); + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_SOF; + } + + if (intr & GINTF_RXFNEIF) { + retval |= usbh_int_rxfifonoempty (udev); + } + + if (intr & GINTF_NPTXFEIF) { + retval |= usbh_int_txfifoempty (udev, PIPE_NON_PERIOD); + } + + if (intr & GINTF_PTXFEIF) { + retval |= usbh_int_txfifoempty (udev, PIPE_PERIOD); + } + + if (intr & GINTF_HCIF) { + retval |= usbh_int_pipe (udev); + } + + if (intr & GINTF_HPIF) { + retval |= usbh_int_port (udev); + } + + if (intr & GINTF_DISCIF) { + usbh_int_fop->disconnect(udev->host.data); + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_DISCIF; + } + + if (intr & GINTF_ISOONCIF) { + udev->regs.pr[0]->HCHCTL |= HCHCTL_CEN | HCHCTL_CDIS; + + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_ISOONCIF; + } + + if (intr & GINTF_SESIF) { + usb_portvbus_switch (udev, 1U); + + udev->regs.gr->GINTF = GINTF_SESIF; + } + + if (intr & GINTF_WKUPIF) { + /* clear interrupt */ + udev->regs.gr->GINTF = GINTF_WKUPIF; + } + } + + return retval; +} + +/*! + \brief handle USB pipe halt + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pp_num: host channel number which is in (0..7) + \param[in] pp_int: pipe interrupt + \param[in] pp_status: pipe status + \param[out] none + \retval none +*/ +static inline void usb_pp_halt (usb_core_driver *udev, + uint8_t pp_num, + uint32_t pp_int, + usb_pipe_staus pp_status) +{ + udev->regs.pr[pp_num]->HCHINTEN |= HCHINTEN_CHIE; + + usb_pipe_halt(udev, pp_num); + + udev->regs.pr[pp_num]->HCHINTF = pp_int; + + udev->host.pipe[pp_num].pp_status = pp_status; +} + +/*! + \brief handle the host port interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_port (usb_core_driver *udev) +{ + uint32_t retval = 0U; + uint8_t port_reset = 0U; + __IO uint32_t port_state = *udev->regs.HPCS; + + /* clear the interrupt bits in GINTSTS */ + port_state &= ~(HPCS_PE | HPCS_PCD | HPCS_PEDC); + + /* port connect detected */ + if (*udev->regs.HPCS & HPCS_PCD) { + port_state |= HPCS_PCD; + + usbh_int_fop->connect(udev->host.data); + + retval |= 1U; + } + + /* port enable changed */ + if (*udev->regs.HPCS & HPCS_PEDC) { + port_state |= HPCS_PEDC; + + if (*udev->regs.HPCS & HPCS_PE) { + uint32_t port_speed = usb_curspeed_get(udev); + uint32_t clock_type = udev->regs.hr->HCTL & HCTL_CLKSEL; + + udev->host.connect_status = 1U; + + if (PORT_SPEED_LOW == port_speed) { + udev->regs.hr->HFT = 6000U; + + if (HCTL_6MHZ != clock_type) { + if (USB_EMBEDDED_PHY == udev->bp.phy_itf) { + usb_phyclock_config (udev, HCTL_6MHZ); + } + + port_reset = 1U; + } + } else if (PORT_SPEED_FULL == port_speed) { + udev->regs.hr->HFT = 48000U; + + if (HCTL_48MHZ != clock_type) { + usb_phyclock_config (udev, HCTL_48MHZ); + } + + port_reset = 1U; + } else { + /* for high speed device and others */ + port_reset = 1U; + } + + udev->host.port_enabled = 1; + + udev->regs.gr->GINTEN |= GINTEN_DISCIE | GINTEN_SOFIE; + } else { + udev->host.port_enabled = 0; + } + } + + if (port_reset) { + usb_port_reset(udev); + } + + /* clear port interrupts */ + *udev->regs.HPCS = port_state; + + return retval; +} + +/*! + \brief handle all host channels interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +static uint32_t usbh_int_pipe (usb_core_driver *udev) +{ + uint32_t pp_num = 0U; + uint32_t retval = 0U; + + for (pp_num = 0U; pp_num < udev->bp.num_pipe; pp_num++) { + if ((udev->regs.hr->HACHINT & HACHINT_HACHINT) & (1UL << pp_num)) { + if (udev->regs.pr[pp_num]->HCHCTL & HCHCTL_EPDIR) { + retval |= usbh_int_pipe_in (udev, pp_num); + } else { + retval |= usbh_int_pipe_out (udev, pp_num); + } + } + } + + return retval; +} + +/*! + \brief handle the IN channel interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_in (usb_core_driver *udev, uint32_t pp_num) +{ + usb_pr *pp_reg = udev->regs.pr[pp_num]; + + usb_pipe *pp = &udev->host.pipe[pp_num]; + + uint32_t intr_pp = pp_reg->HCHINTF; + intr_pp &= pp_reg->HCHINTEN; + + uint8_t ep_type = (uint8_t)((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U); + + if (intr_pp & HCHINTF_ACK) { + pp_reg->HCHINTF = HCHINTF_ACK; + } else if (intr_pp & HCHINTF_STALL) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + pp_reg->HCHINTF = HCHINTF_NAK; + + /* note: When there is a 'STALL', reset also NAK, + else, the udev->host.pp_status = HC_STALL + will be overwritten by 'NAK' in code below */ + intr_pp &= ~HCHINTF_NAK; + } else if (intr_pp & HCHINTF_DTER) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + if (intr_pp & HCHINTF_REQOVR) { + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if (intr_pp & HCHINTF_TF) { + pp->pp_status = PIPE_XF; + pp->err_count = 0U; + + pp_reg->HCHINTF = HCHINTF_TF; + + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_XF); + + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_INTR: + case USB_EPTYPE_ISOC: + pp_reg->HCHCTL |= HCHCTL_ODDFRM; + pp->urb_state = URB_DONE; + break; + + default: + break; + } + } else if (intr_pp & HCHINTF_CH) { + pp_reg->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + case PIPE_DTGERR: + pp->err_count = 0U; + pp->urb_state = URB_ERROR; + + pp->data_toggle_in ^= 1U; + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_NAK: + case PIPE_NYET: + case PIPE_BBERR: + case PIPE_REQOVR: + default: + if((uint8_t)USB_EPTYPE_INTR == ep_type) { + pp->data_toggle_in ^= 1U; + } + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if (intr_pp & HCHINTF_NAK) { + switch (ep_type) { + case USB_EPTYPE_CTRL: + case USB_EPTYPE_BULK: + /* re-activate the channel */ + pp_reg->HCHCTL = (pp_reg->HCHCTL | HCHCTL_CEN) & ~HCHCTL_CDIS; + break; + + case USB_EPTYPE_INTR: + pp_reg->HCHINTEN |= HCHINTEN_CHIE; + + (void)usb_pipe_halt(udev, (uint8_t)pp_num); + break; + + default: + break; + } + + pp->pp_status = PIPE_NAK; + + pp_reg->HCHINTF = HCHINTF_NAK; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the OUT channel interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_num: host channel number which is in (0..7) + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_pipe_out (usb_core_driver *udev, uint32_t pp_num) +{ + usb_pr *pp_reg = udev->regs.pr[pp_num]; + + usb_pipe *pp = &udev->host.pipe[pp_num]; + + uint32_t intr_pp = pp_reg->HCHINTF; + intr_pp &= pp_reg->HCHINTEN; + + if(intr_pp & HCHINTF_ACK) { + + pp_reg->HCHINTF = HCHINTF_ACK; + } else if(intr_pp & HCHINTF_STALL) { + usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_STALL, PIPE_STALL); + } else if(intr_pp & HCHINTF_DTER) { + usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_DTER, PIPE_DTGERR); + pp_reg->HCHINTF = HCHINTF_NAK; + } else if(intr_pp & HCHINTF_REQOVR) { + usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_REQOVR, PIPE_REQOVR); + } else if(intr_pp & HCHINTF_TF) { + pp->err_count = 0U; + usb_pp_halt(udev, (uint8_t)pp_num, HCHINTF_TF, PIPE_XF); + } else if(intr_pp & HCHINTF_NAK) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NAK, PIPE_NAK); + } else if (intr_pp & HCHINTF_USBER) { + pp->err_count++; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_USBER, PIPE_TRACERR); + } else if(intr_pp & HCHINTF_NYET) { + pp->err_count = 0U; + usb_pp_halt (udev, (uint8_t)pp_num, HCHINTF_NYET, PIPE_NYET); + } else if (intr_pp & HCHINTF_CH) { + udev->regs.pr[pp_num]->HCHINTEN &= ~HCHINTEN_CHIE; + + switch (pp->pp_status) { + case PIPE_XF: + pp->urb_state = URB_DONE; + + if ((uint8_t)USB_EPTYPE_BULK == ((pp_reg->HCHCTL & HCHCTL_EPTYPE) >> 18U)) { + pp->data_toggle_out ^= 1U; + } + break; + + case PIPE_NAK: + case PIPE_NYET: + pp->urb_state = URB_NOTREADY; + break; + + case PIPE_STALL: + pp->urb_state = URB_STALL; + break; + + case PIPE_TRACERR: + if (3U == pp->err_count) { + pp->urb_state = URB_ERROR; + pp->err_count = 0U; + } + break; + + case PIPE_IDLE: + case PIPE_HALTED: + case PIPE_BBERR: + case PIPE_REQOVR: + case PIPE_DTGERR: + default: + break; + } + + pp_reg->HCHINTF = HCHINTF_CH; + } else { + /* no operation */ + } + + return 1U; +} + +/*! + \brief handle the RX FIFO non-empty interrupt + \param[in] udev: pointer to USB device instance + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_rxfifonoempty (usb_core_driver *udev) +{ + uint32_t count = 0U, xfer_count = 0U; + + __IO uint8_t pp_num = 0U; + __IO uint32_t rx_stat = 0U; + + /* disable the RX status queue level interrupt */ + udev->regs.gr->GINTEN &= ~GINTEN_RXFNEIE; + + rx_stat = udev->regs.gr->GRSTATP; + pp_num = (uint8_t)(rx_stat & GRSTATRP_CNUM); + + switch ((rx_stat & GRSTATRP_RPCKST) >> 17U) { + case GRXSTS_PKTSTS_IN: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + /* read the data into the host buffer. */ + if ((count > 0U) && (NULL != udev->host.pipe[pp_num].xfer_buf)) { + (void)usb_rxfifo_read (&udev->regs, udev->host.pipe[pp_num].xfer_buf, (uint16_t)count); + + /* manage multiple transfer packet */ + udev->host.pipe[pp_num].xfer_buf += count; + udev->host.pipe[pp_num].xfer_count += count; + + xfer_count = udev->host.pipe[pp_num].xfer_count; + + udev->host.backup_xfercount[pp_num] = xfer_count; + + if (udev->regs.pr[pp_num]->HCHLEN & HCHLEN_PCNT) { + /* re-activate the channel when more packets are expected */ + uint32_t pp_ctl = udev->regs.pr[pp_num]->HCHCTL; + + pp_ctl |= HCHCTL_CEN; + pp_ctl &= ~HCHCTL_CDIS; + + udev->regs.pr[pp_num]->HCHCTL = pp_ctl; + } + } + break; + + case GRXSTS_PKTSTS_IN_XFER_COMP: + break; + + case GRXSTS_PKTSTS_DATA_TOGGLE_ERR: + count = (rx_stat & GRSTATRP_BCOUNT) >> 4U; + + while (count > 0U) { + rx_stat = udev->regs.gr->GRSTATP; + count--; + } + break; + + case GRXSTS_PKTSTS_CH_HALTED: + break; + + default: + break; + } + + /* enable the RX status queue level interrupt */ + udev->regs.gr->GINTEN |= GINTEN_RXFNEIE; + + return 1U; +} + +/*! + \brief handle the TX FIFO empty interrupt + \param[in] udev: pointer to USB device instance + \param[in] pp_mode: pipe mode + \param[out] none + \retval operation status +*/ +#if defined (__ICCARM__) /*!< IAR compiler */ + #pragma optimize = none +#endif /* __ICCARM */ +static uint32_t usbh_int_txfifoempty (usb_core_driver *udev, usb_pipe_mode pp_mode) +{ + uint8_t pp_num = 0U; + uint16_t word_count = 0U, len = 0U; + __IO uint32_t *txfiforeg = 0U, txfifostate = 0U; + + if (PIPE_NON_PERIOD == pp_mode) { + txfiforeg = &udev->regs.gr->HNPTFQSTAT; + } else if (PIPE_PERIOD == pp_mode) { + txfiforeg = &udev->regs.hr->HPTFQSTAT; + } else { + return 0U; + } + + txfifostate = *txfiforeg; + + pp_num = (uint8_t)((txfifostate & TFQSTAT_CNUM) >> 27U); + + word_count = (uint16_t)(udev->host.pipe[pp_num].xfer_len + 3U) / 4U; + + while (((txfifostate & TFQSTAT_TXFS) >= word_count) && (0U != udev->host.pipe[pp_num].xfer_len)) { + len = (uint16_t)(txfifostate & TFQSTAT_TXFS) * 4U; + + if (len > udev->host.pipe[pp_num].xfer_len) { + /* last packet */ + len = (uint16_t)udev->host.pipe[pp_num].xfer_len; + + if (PIPE_NON_PERIOD == pp_mode) { + udev->regs.gr->GINTEN &= ~GINTEN_NPTXFEIE; + } else { + udev->regs.gr->GINTEN &= ~GINTEN_PTXFEIE; + } + } + + word_count = (uint16_t)((udev->host.pipe[pp_num].xfer_len + 3U) / 4U); + usb_txfifo_write (&udev->regs, udev->host.pipe[pp_num].xfer_buf, pp_num, len); + + udev->host.pipe[pp_num].xfer_buf += len; + udev->host.pipe[pp_num].xfer_len -= len; + udev->host.pipe[pp_num].xfer_count += len; + + txfifostate = *txfiforeg; + } + + return 1U; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_core.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_core.h new file mode 100644 index 00000000..69931d44 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Include/usbh_hid_core.h @@ -0,0 +1,120 @@ +/*! + \file usbh_hid_core.h + \brief header file for the usbh_hid_core.c + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_HID_CORE_H +#define __USBH_HID_CORE_H + +#include "usb_hid.h" +#include "usbh_enum.h" +#include "usbh_transc.h" + +#define HID_MIN_POLL 10U +#define HID_REPORT_SIZE 16U +#define HID_QUEUE_SIZE 10U + +#define USB_HID_DESC_SIZE 9U + +/* states for HID state machine */ +typedef enum { + HID_INIT = 0U, + HID_IDLE, + HID_SEND_DATA, + HID_BUSY, + HID_GET_DATA, + HID_SYNC, + HID_POLL, + HID_ERROR, +} hid_state; + +typedef enum { + HID_REQ_INIT = 0U, + HID_REQ_IDLE, + HID_REQ_GET_REPORT_DESC, + HID_REQ_GET_HID_DESC, + HID_REQ_SET_IDLE, + HID_REQ_SET_PROTOCOL, + HID_REQ_SET_REPORT, +} hid_ctlstate; + +typedef enum +{ + HID_MOUSE = 0x01U, + HID_KEYBOARD = 0x02U, + HID_UNKNOWN = 0xFFU, +} hid_type; + +typedef struct +{ + uint8_t *buf; + uint16_t head; + uint16_t tail; + uint16_t size; + uint8_t lock; +} data_fifo; + +/* structure for HID process */ +typedef struct _hid_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_addr; + uint8_t ep_in; + uint8_t ep_out; + uint8_t *pdata; + __IO uint8_t data_ready; + uint16_t len; + uint16_t poll; + + __IO uint32_t timer; + usb_desc_hid hid_desc; + + hid_state state; + hid_ctlstate ctl_state; + + usbh_status (*init)(usb_core_driver *udev, usbh_host *uhost); + usbh_status (*decode)(uint8_t *data); +} usbh_hid_handler; + +extern usbh_class usbh_hid; + +/* function declarations */ +/* set HID report */ +usbh_status usbh_set_report (usb_core_driver *udev, + usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf); + +#endif /* __USBH_HID_CORE_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Include/usbh_standard_hid.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Include/usbh_standard_hid.h new file mode 100644 index 00000000..2b8161b9 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Include/usbh_standard_hid.h @@ -0,0 +1,99 @@ +/*! + \file usbh_standard_hid.h + \brief header file for usbh_standard_hid.c + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_STANDARD_HID_H +#define __USBH_STANDARD_HID_H + +#include "usb_conf.h" +#include "usbh_hid_core.h" + +//#define AZERTY_KEYBOARD +#define QWERTY_KEYBOARD + +#define MOUSE_BUTTON_1 0x01U +#define MOUSE_BUTTON_2 0x02U +#define MOUSE_BUTTON_3 0x04U + +#define KBD_LEFT_CTRL 0x01U +#define KBD_LEFT_SHIFT 0x02U +#define KBD_LEFT_ALT 0x04U +#define KBD_LEFT_GUI 0x08U +#define KBD_RIGHT_CTRL 0x10U +#define KBD_RIGHT_SHIFT 0x20U +#define KBD_RIGHT_ALT 0x40U +#define KBD_RIGHT_GUI 0x80U + +#define KBD_PRESSED_MAX_NUM 6U + +typedef struct _hid_mouse_info +{ + uint8_t x; + uint8_t y; + uint8_t buttons[3]; +} hid_mouse_info; + +typedef struct +{ + uint8_t state; + uint8_t lctrl; + uint8_t lshift; + uint8_t lalt; + uint8_t lgui; + uint8_t rctrl; + uint8_t rshift; + uint8_t ralt; + uint8_t rgui; + uint8_t keys[6]; +} hid_keybd_info; + +/* function declarations */ +/* initialize mouse */ +void usr_mouse_init (void); +/* process mouse data */ +void usr_mouse_process_data (hid_mouse_info *data); +/* initialize mouse function */ +usbh_status usbh_hid_mouse_init (usb_core_driver *udev, usbh_host *uhost); +/* decode mouse information */ +usbh_status usbh_hid_mouse_decode(uint8_t *data); + +/* initialize keyboard */ +void usr_keybrd_init (void); +/* process keyboard data */ +void usr_keybrd_process_data (uint8_t pbuf); +/* initialize the keyboard function */ +usbh_status usbh_hid_keybrd_init (usb_core_driver *udev, usbh_host *uhost); +/* decode keyboard information */ +usbh_status usbh_hid_keybrd_decode (uint8_t *data); + +#endif /* __USBH_STANDARD_HID_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_core.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_core.c new file mode 100644 index 00000000..e93d5fb1 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Source/usbh_hid_core.c @@ -0,0 +1,581 @@ +/*! + \file usbh_hid_core.c + \brief USB host HID class driver + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include +#include "usbh_pipe.h" +#include "usbh_hid_core.h" +#include "usbh_standard_hid.h" + +/* local function prototypes ('static') */ +static void usbh_hiddesc_parse(usb_desc_hid *hid_desc, uint8_t *buf); +static void usbh_hid_itf_deinit(usbh_host *uhost); +static usbh_status usbh_hid_itf_init(usbh_host *uhost); +static usbh_status usbh_hid_class_req(usbh_host *uhost); +static usbh_status usbh_hid_handle(usbh_host *uhost); +static usbh_status usbh_hid_reportdesc_get(usbh_host *uhost, uint16_t len); +static usbh_status usbh_hid_sof(usbh_host *uhost); +static usbh_status usbh_hid_desc_get(usbh_host *uhost, uint16_t len); +static usbh_status usbh_set_idle(usbh_host *uhost, uint8_t duration, uint8_t report_ID); +static usbh_status usbh_set_protocol(usbh_host *uhost, uint8_t protocol); + +usbh_class usbh_hid = +{ + USB_HID_CLASS, + usbh_hid_itf_init, + usbh_hid_itf_deinit, + usbh_hid_class_req, + usbh_hid_handle, + usbh_hid_sof +}; + +/*! + \brief get report + \param[in] uhost: pointer to USB host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_get_report (usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = GET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (uhost, report_buf, report_len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set report + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[in] report_type: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[in] report_len: length of data report to be send + \param[in] report_buf: report buffer + \param[out] none + \retval operation status +*/ +usbh_status usbh_set_report (usb_core_driver *udev, + usbh_host *uhost, + uint8_t report_type, + uint8_t report_ID, + uint8_t report_len, + uint8_t *report_buf) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_REPORT, + .wValue = (report_type << 8U) | report_ID, + .wIndex = 0U, + .wLength = report_len + }; + + usbh_ctlstate_config (uhost, report_buf, report_len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief deinitialize the host pipes used for the HID class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +void usbh_hid_itf_deinit (usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (0x00U != hid->pipe_in) { + usb_pipe_halt (uhost->data, hid->pipe_in); + + usbh_pipe_free (uhost->data, hid->pipe_in); + + hid->pipe_in = 0U; /* reset the pipe as free */ + } + + if (0x00U != hid->pipe_out) { + usb_pipe_halt (uhost->data, hid->pipe_out); + + usbh_pipe_free (uhost->data, hid->pipe_out); + + hid->pipe_out = 0U; /* reset the channel as free */ + } +} + +/*! + \brief return device type + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval hid_type +*/ +hid_type usbh_hid_device_type_get(usb_core_driver *udev, usbh_host *uhost) +{ + hid_type type = HID_UNKNOWN; + uint8_t interface_protocol; + + if (HOST_CLASS_HANDLER == uhost->cur_state) { + interface_protocol = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + + if (USB_HID_PROTOCOL_KEYBOARD == interface_protocol) { + type = HID_KEYBOARD; + } else { + if (USB_HID_PROTOCOL_MOUSE == interface_protocol) { + type = HID_MOUSE; + } + } + } + + return type; +} + +/*! + \brief return HID device poll time + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval poll time (ms) +*/ +uint8_t usbh_hid_poll_interval_get (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if ((HOST_CLASS_ENUM == uhost->cur_state) || + (HOST_USER_INPUT == uhost->cur_state) || + (HOST_CLASS_CHECK == uhost->cur_state) || + (HOST_CLASS_HANDLER == uhost->cur_state)) { + return (uint8_t)(hid->poll); + } else { + return 0U; + } +} + +/*! + \brief initialize the hid class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_itf_init (usbh_host *uhost) +{ + uint8_t num = 0U, ep_num = 0U, interface = 0U; + usbh_status status = USBH_BUSY; + + interface = usbh_interface_find(&uhost->dev_prop, USB_HID_CLASS, USB_HID_SUBCLASS_BOOT_ITF, 0xFFU); + + if (0xFFU == interface) { + uhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + usbh_interface_select(&uhost->dev_prop, interface); + + static usbh_hid_handler hid_handler; + + memset((void*)&hid_handler, 0, sizeof(usbh_hid_handler)); + + hid_handler.state = HID_ERROR; + + uint8_t itf_protocol = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bInterfaceProtocol; + if (USB_HID_PROTOCOL_KEYBOARD == itf_protocol) { + hid_handler.init = usbh_hid_keybrd_init; + hid_handler.decode = usbh_hid_keybrd_decode; + } else if (USB_HID_PROTOCOL_MOUSE == itf_protocol) { + hid_handler.init = usbh_hid_mouse_init; + hid_handler.decode = usbh_hid_mouse_decode; + } else { + status = USBH_FAIL; + } + + hid_handler.state = HID_INIT; + hid_handler.ctl_state = HID_REQ_INIT; + hid_handler.ep_addr = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].bEndpointAddress; + hid_handler.len = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].wMaxPacketSize; + hid_handler.poll = uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[0].bInterval; + + if (hid_handler.poll < HID_MIN_POLL) { + hid_handler.poll = HID_MIN_POLL; + } + + /* check for available number of endpoints */ + /* find the number of endpoints in the interface descriptor */ + /* choose the lower number in order not to overrun the buffer allocated */ + ep_num = USB_MIN(uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].itf_desc.bNumEndpoints, USBH_MAX_EP_NUM); + + /* decode endpoint IN and OUT address from interface descriptor */ + for (num = 0U; num < ep_num; num++) { + usb_desc_ep *ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[uhost->dev_prop.cur_itf][0].ep_desc[num]; + + uint8_t ep_addr = ep_desc->bEndpointAddress; + + if (ep_addr & 0x80U) { + hid_handler.ep_in = ep_addr; + hid_handler.pipe_in = usbh_pipe_allocate (uhost->data, ep_addr); + + /* open channel for IN endpoint */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + hid_handler.pipe_in, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(uhost->data, hid_handler.pipe_in, 0U); + } else { + hid_handler.ep_out = ep_addr; + hid_handler.pipe_out = usbh_pipe_allocate (uhost->data, ep_addr); + + /* open channel for OUT endpoint */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + hid_handler.pipe_out, + USB_EPTYPE_INTR, + hid_handler.len); + + usbh_pipe_toggle_set(uhost->data, hid_handler.pipe_out, 0U); + } + } + + uhost->active_class->class_data = (void *)&hid_handler; + + status = USBH_OK; + } + + return status; +} + +/*! + \brief handle HID class requests for HID class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_class_req (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + usbh_status class_req_status = USBH_BUSY; + + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + /* handle HID control state machine */ + switch (hid->ctl_state) { + case HID_REQ_INIT: + case HID_REQ_GET_HID_DESC: + /* get HID descriptor */ + if (USBH_OK == usbh_hid_desc_get (uhost, USB_HID_DESC_SIZE)) { + usbh_hiddesc_parse(&hid->hid_desc, uhost->dev_prop.data); + + hid->ctl_state = HID_REQ_GET_REPORT_DESC; + } + break; + + case HID_REQ_GET_REPORT_DESC: + /* get report descriptor */ + if (USBH_OK == usbh_hid_reportdesc_get(uhost, hid->hid_desc.wDescriptorLength)) { + hid->ctl_state = HID_REQ_SET_IDLE; + } + break; + + case HID_REQ_SET_IDLE: + class_req_status = usbh_set_idle (uhost, 0U, 0U); + + /* set idle */ + if (USBH_OK == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } else { + if(USBH_NOT_SUPPORTED == class_req_status) { + hid->ctl_state = HID_REQ_SET_PROTOCOL; + } + } + break; + + case HID_REQ_SET_PROTOCOL: + /* set protocol */ + if (USBH_OK == usbh_set_protocol (uhost, 0U)) { + hid->ctl_state = HID_REQ_IDLE; + + /* all requests performed */ + status = USBH_OK; + } + break; + + case HID_REQ_IDLE: + default: + break; + } + + return status; +} + +/*! + \brief manage state machine for HID data transfers + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_handle (usbh_host *uhost) +{ + usbh_status status = USBH_OK; + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + switch (hid->state) { + case HID_INIT: + hid->init(uhost->data, uhost); + hid->state = HID_IDLE; + break; + + case HID_IDLE: + hid->state = HID_SYNC; + status = USBH_OK; + break; + + case HID_SYNC: + /* sync with start of even frame */ + if (TRUE == usb_frame_even(uhost->data)) { + hid->state = HID_GET_DATA; + } + break; + + case HID_GET_DATA: + usbh_data_recev (uhost->data, hid->pdata, hid->pipe_in, hid->len); + + hid->state = HID_POLL; + hid->timer = usb_curframe_get (uhost->data); + hid->data_ready = 0U; + break; + + case HID_POLL: + if (URB_DONE == usbh_urbstate_get (uhost->data, hid->pipe_in)) { + if (0U == hid->data_ready) { + hid->data_ready = 1U; + + hid->decode(hid->pdata); + } + } else { + /* check IN endpoint stall status */ + if (URB_STALL == usbh_urbstate_get (uhost->data, hid->pipe_in)) { + /* issue clear feature on interrupt in endpoint */ + if (USBH_OK == (usbh_clrfeature (uhost, hid->ep_addr, hid->pipe_in))) { + /* change state to issue next in token */ + hid->state = HID_GET_DATA; + } + } + } + break; + + default: + break; + } + return status; +} + +/*! + \brief send get report descriptor command to the device + \param[in] uhost: pointer to USB host + \param[in] len: HID report descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_reportdesc_get (usbh_host *uhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_REPORT), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief managing the SOF process + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_sof(usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + if (HID_POLL == hid->state) { + uint32_t frame_count = usb_curframe_get (uhost->data); + + if ((frame_count > hid->timer) && ((frame_count - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else if ((frame_count < hid->timer) && ((frame_count + 0x3FFFU - hid->timer) >= hid->poll)) { + hid->state = HID_GET_DATA; + } else { + /* no operation */ + } + } + + return USBH_OK; +} + +/*! + \brief send the command of get HID descriptor to the device + \param[in] uhost: pointer to USB host + \param[in] len: HID descriptor length + \param[out] none + \retval operation status +*/ +static usbh_status usbh_hid_desc_get (usbh_host *uhost, uint16_t len) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_HID), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set idle state + \param[in] uhost: pointer to USB host + \param[in] duration: duration for HID set idle request + \param[in] report_ID: targeted report ID for HID set idle request + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_idle (usbh_host *uhost, uint8_t duration, uint8_t report_ID) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_IDLE, + .wValue = (duration << 8U) | report_ID, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set protocol state + \param[in] uhost: pointer to USB host + \param[in] protocol: boot/report protocol + \param[out] none + \retval operation status +*/ +static usbh_status usbh_set_protocol (usbh_host *uhost, uint8_t protocol) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_CLASS, + .bRequest = SET_PROTOCOL, + .wValue = !protocol, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief parse the HID descriptor + \param[in] hid_desc: pointer to HID descriptor + \param[in] buf: pointer to buffer where the source descriptor is available + \param[out] none + \retval none +*/ +static void usbh_hiddesc_parse (usb_desc_hid *hid_desc, uint8_t *buf) +{ + hid_desc->header.bLength = *(uint8_t *)(buf + 0U); + hid_desc->header.bDescriptorType = *(uint8_t *)(buf + 1U); + hid_desc->bcdHID = BYTE_SWAP(buf + 2U); + hid_desc->bCountryCode = *(uint8_t *)(buf + 4U); + hid_desc->bNumDescriptors = *(uint8_t *)(buf + 5U); + hid_desc->bDescriptorType = *(uint8_t *)(buf + 6U); + hid_desc->wDescriptorLength = BYTE_SWAP(buf + 7U); +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Source/usbh_standard_hid.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Source/usbh_standard_hid.c new file mode 100644 index 00000000..8d5c8ece --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/hid/Source/usbh_standard_hid.c @@ -0,0 +1,274 @@ +/*! + \file usbh_standard_hid.c + \brief USB host HID mouse and keyboard driver + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_standard_hid.h" +#include + +hid_mouse_info mouse_info; +hid_keybd_info keybd_info; + +uint8_t mouse_report_data[8] = {0U}; +uint32_t keybd_report_data[2]; + +/* local constants */ +static const uint8_t kbd_codes[] = +{ + 0, 0, 0, 0, 31, 50, 48, 33, + 19, 34, 35, 36, 24, 37, 38, 39, /* 0x00 - 0x0F */ + 52, 51, 25, 26, 17, 20, 32, 21, + 23, 49, 18, 47, 22, 46, 2, 3, /* 0x10 - 0x1F */ + 4, 5, 6, 7, 8, 9, 10, 11, + 43, 110, 15, 16, 61, 12, 13, 27, /* 0x20 - 0x2F */ + 28, 29, 42, 40, 41, 1, 53, 54, + 55, 30, 112, 113, 114, 115, 116, 117, /* 0x30 - 0x3F */ + 118, 119, 120, 121, 122, 123, 124, 125, + 126, 75, 80, 85, 76, 81, 86, 89, /* 0x40 - 0x4F */ + 79, 84, 83, 90, 95, 100, 105, 106, + 108, 93, 98, 103, 92, 97, 102, 91, /* 0x50 - 0x5F */ + 96, 101, 99, 104, 45, 129, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7F */ + 0, 0, 0, 0, 0, 107, 0, 56, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9F */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 - 0xAF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 - 0xBF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xCF */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xDF */ + 58, 44, 60, 127, 64, 57, 62, 128 /* 0xE0 - 0xE7 */ +}; + +#ifdef QWERTY_KEYBOARD + +static const int8_t kbd_key[] = +{ + '\0', '`', '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '\0', '\r', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', + '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', + 'k', 'l', ';', '\'', '\0', '\n', + '\0', '\0', 'z', 'x', 'c', 'v', 'b', 'n', + 'm', ',', '.', '/', '\0', '\0', + '\0', '\0', '\0', ' ', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '7', '4', '1', + '\0', '/', '8', '5', '2', + '0', '*', '9', '6', '3', + '.', '-', '+', '\0', '\n', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0' +}; + +static const int8_t kbd_key_shift[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', + '_', '+', '\0', '\0', '\0', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', + 'I', 'O', 'P', '{', '}', '|', '\0', 'A', 'S', 'D', 'F', 'G', + 'H', 'J', 'K', 'L', ':', '"', '\0', '\n', '\0', '\0', 'Z', 'X', + 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#else + +static const int8_t kbd_key[] = { + '\0', '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + '-', '=', '\0', '\r', '\t', 'a', 'z', 'e', 'r', 't', 'y', 'u', + 'i', 'o', 'p', '[', ']', '\\', '\0', 'q', 's', 'd', 'f', 'g', + 'h', 'j', 'k', 'l', 'm', '\0', '\0', '\n', '\0', '\0', 'w', 'x', + 'c', 'v', 'b', 'n', ',', ';', ':', '!', '\0', '\0', '\0', '\0', + '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\r', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '4', '1', '\0', '/', + '8', '5', '2', '0', '*', '9', '6', '3', '.', '-', '+', '\0', + '\n', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +static const int8_t kbd_key_shift[] = { + '\0', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', + '+', '\0', '\0', '\0', 'A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', + 'P', '{', '}', '*', '\0', 'Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K', + 'L', 'M', '%', '\0', '\n', '\0', '\0', 'W', 'X', 'C', 'V', 'B', 'N', + '?', '.', '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' +}; + +#endif /* QWERTY_KEYBOARD */ + +/*! + \brief initialize the mouse function + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +usbh_status usbh_hid_mouse_init (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + mouse_info.x = 0U; + mouse_info.y = 0U; + mouse_info.buttons[0] = 0U; + mouse_info.buttons[1] = 0U; + mouse_info.buttons[2] = 0U; + + if(hid->len > sizeof(mouse_report_data)) { + hid->len = sizeof(mouse_report_data); + } + + hid->pdata = (uint8_t *)(void *)mouse_report_data; + + usr_mouse_init(); + + return USBH_OK; +} + +/*! + \brief decode mouse information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_hid_mouse_decode(uint8_t *data) +{ + mouse_info.buttons[0] = data[0] & MOUSE_BUTTON_1; + mouse_info.buttons[1] = data[0] & MOUSE_BUTTON_2; + mouse_info.buttons[2] = data[0] & MOUSE_BUTTON_3; + + mouse_info.x = data[1]; + mouse_info.y = data[2]; + + /* handle mouse data position */ + usr_mouse_process_data(&mouse_info); + + return USBH_FAIL; +} + +/*! + \brief initialize the keyboard function + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_hid_keybrd_init (usb_core_driver *udev, usbh_host *uhost) +{ + usbh_hid_handler *hid = (usbh_hid_handler *)uhost->active_class->class_data; + + keybd_info.lctrl = keybd_info.lshift = 0U; + keybd_info.lalt = keybd_info.lgui = 0U; + keybd_info.rctrl = keybd_info.rshift = 0U; + keybd_info.ralt = keybd_info.rgui = 0U; + + for (uint32_t x = 0U; x < (sizeof(keybd_report_data) / sizeof(uint32_t)); x++) { + keybd_report_data[x] = 0U; + } + + if (hid->len > (sizeof(keybd_report_data) / sizeof(uint32_t))) { + hid->len = (sizeof(keybd_report_data) / sizeof(uint32_t)); + } + + hid->pdata = (uint8_t*)(void *)keybd_report_data; + + /* call user initialization*/ + usr_keybrd_init(); + + return USBH_OK; +} + +/*! + \brief get ascii code + \param[in] info: keyboard information + \param[out] none + \retval output +*/ +uint8_t usbh_hid_ascii_code_get (hid_keybd_info *info) +{ + uint8_t output; + if ((1U == info->lshift) || (info->rshift)) { + output = kbd_key_shift[kbd_codes[info->keys[0]]]; + } else { + output = kbd_key[kbd_codes[info->keys[0]]]; + } + + return output; +} + +/*! + \brief decode keyboard information + \param[in] udev: pointer to USB core instance + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_hid_keybrd_decode (uint8_t *data) +{ + uint8_t output; + + keybd_info.lshift = data[0] & KBD_LEFT_SHIFT; + keybd_info.rshift = data[0] & KBD_RIGHT_SHIFT; + + keybd_info.keys[0] = data[2]; + + if (keybd_info.lshift || keybd_info.rshift) { + output = kbd_key_shift[kbd_codes[keybd_info.keys[0]]]; + } else { + output = kbd_key[kbd_codes[keybd_info.keys[0]]]; + } + + if (0U != output) { + usr_keybrd_process_data(output); + } + + return USBH_OK; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h new file mode 100644 index 00000000..4c82de85 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_bbb.h @@ -0,0 +1,150 @@ +/*! + \file usbh_msc_bbb.h + \brief header file for usbh_msc_bbb.c + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_BBB_H +#define __USBH_MSC_BBB_H + +#include "usbh_enum.h" +#include "msc_bbb.h" + +typedef union { + msc_bbb_cbw field; + + uint8_t CBWArray[31]; +} usbh_cbw_pkt; + +typedef union { + msc_bbb_csw field; + + uint8_t CSWArray[13]; +} usbh_csw_pkt; + +enum usbh_msc_state { + USBH_MSC_BBB_INIT_STATE = 0U, + USBH_MSC_BBB_RESET, + USBH_MSC_GET_MAX_LUN, + USBH_MSC_TEST_UNIT_READY, + USBH_MSC_READ_CAPACITY10, + USBH_MSC_MODE_SENSE6, + USBH_MSC_REQUEST_SENSE, + USBH_MSC_BBB_USB_TRANSFERS, + USBH_MSC_DEFAULT_APPLI_STATE, + USBH_MSC_CTRL_ERROR_STATE, + USBH_MSC_UNRECOVERED_STATE +}; + +typedef enum +{ + BBB_OK = 0U, + BBB_FAIL, + BBB_PHASE_ERROR, + BBB_BUSY +} bbb_status; + +typedef enum +{ + BBB_CMD_IDLE = 0U, + BBB_CMD_SEND, + BBB_CMD_WAIT +} bbb_cmd_state; + +/* csw status definitions */ +typedef enum +{ + BBB_CSW_CMD_PASSED = 0U, + BBB_CSW_CMD_FAILED, + BBB_CSW_PHASE_ERROR +} bbb_csw_status; + +typedef enum +{ + BBB_SEND_CBW = 1U, + BBB_SEND_CBW_WAIT, + BBB_DATA_IN, + BBB_DATA_IN_WAIT, + BBB_DATA_OUT, + BBB_DATA_OUT_WAIT, + BBB_RECEIVE_CSW, + BBB_RECEIVE_CSW_WAIT, + BBB_ERROR_IN, + BBB_ERROR_OUT, + BBB_UNRECOVERED_ERROR +} bbb_state; + +typedef struct +{ + uint8_t *pbuf; + uint32_t data[16]; + bbb_state state; + bbb_state prev_state; + bbb_cmd_state cmd_state; + usbh_cbw_pkt cbw; + usbh_csw_pkt csw; +} bbb_handle; + +#define USBH_MSC_BBB_CBW_TAG 0x20304050U + +#define USBH_MSC_CSW_MAX_LENGTH 63U + +#define USBH_MSC_SEND_CSW_DISABLE 0U +#define USBH_MSC_SEND_CSW_ENABLE 1U + +#define USBH_MSC_DIR_IN 0U +#define USBH_MSC_DIR_OUT 1U +#define USBH_MSC_BOTH_DIR 2U + +#define USBH_MSC_PAGE_LENGTH 512U + +#define CBW_CB_LENGTH 16U +#define CBW_LENGTH 10U +#define CBW_LENGTH_TEST_UNIT_READY 0U + +#define MAX_BULK_STALL_COUNT_LIMIT 0x04U /*!< If STALL is seen on Bulk + Endpoint continously, this means + that device and Host has phase error + Hence a Reset is needed */ + +/* function declarations */ +/* initialize the mass storage parameters */ +void usbh_msc_bbb_init (usbh_host *uhost); +/* manage the different states of BBB transfer and updates the status to upper layer */ +usbh_status usbh_msc_bbb_process (usbh_host *uhost, uint8_t lun); +/* manages the different error handling for stall */ +usbh_status usbh_msc_bbb_abort (usbh_host *uhost, uint8_t direction); +/* reset MSC bbb request structure */ +usbh_status usbh_msc_bbb_reset (usbh_host *uhost); +/* decode the CSW received by the device and updates the same to upper layer */ +bbb_csw_status usbh_msc_csw_decode (usbh_host *uhost); + +#endif /* __USBH_MSC_BBB_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_core.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_core.h new file mode 100644 index 00000000..5a5f92b1 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_core.h @@ -0,0 +1,124 @@ +/*! + \file usbh_core.h + \brief header file for the usbh_core.c + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_CORE_H +#define __USBH_MSC_CORE_H + +#include "usb_msc.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#define MSC_MAX_SUPPORTED_LUN 2U + +typedef enum +{ + MSC_INIT = 0U, + MSC_IDLE, + MSC_TEST_UNIT_READY, + MSC_READ_CAPACITY10, + MSC_READ_INQUIRY, + MSC_REQUEST_SENSE, + MSC_READ, + MSC_WRITE, + MSC_UNRECOVERED_ERROR, + MSC_PERIODIC_CHECK, +} msc_state; + +typedef enum +{ + MSC_OK, + MSC_NOT_READY, + MSC_ERROR, +} msc_error; + +typedef enum +{ + MSC_REQ_IDLE = 0U, + MSC_REQ_RESET, + MSC_REQ_GET_MAX_LUN, + MSC_REQ_ERROR, +} msc_req_state; + +/* structure for LUN */ +typedef struct +{ + msc_state state; + msc_error error; + msc_scsi_sense sense; + scsi_capacity capacity; + scsi_std_inquiry_data inquiry; + usbh_status prev_ready_state; + uint8_t state_changed; +} msc_lun; + +/* structure for msc process */ +typedef struct _msc_process +{ + uint8_t pipe_in; + uint8_t pipe_out; + uint8_t ep_in; + uint8_t ep_out; + uint16_t ep_size_in; + uint16_t ep_size_out; + uint8_t cur_lun; + uint16_t rw_lun; + uint32_t max_lun; + msc_state state; + msc_error error; + msc_req_state req_state; + msc_req_state prev_req_state; + bbb_handle bbb; + msc_lun unit[MSC_MAX_SUPPORTED_LUN]; + uint32_t timer; +} usbh_msc_handler; + +extern usbh_class usbh_msc; + +/* function declarations */ +/* get msc logic unit information */ +usbh_status usbh_msc_lun_info_get (usbh_host *uhost, uint8_t lun, msc_lun *info); +/* msc read interface */ +usbh_status usbh_msc_read (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); +/* msc write interface */ +usbh_status usbh_msc_write (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length); + +#endif /* __USBH_MSC_CORE_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h new file mode 100644 index 00000000..34aeab6e --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Include/usbh_msc_scsi.h @@ -0,0 +1,100 @@ +/*! + \file usbh_msc_scsi.h + \brief header file for usbh_msc_scsi.c + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_MSC_SCSI_H +#define __USBH_MSC_SCSI_H + +#include "msc_scsi.h" +#include "usbh_enum.h" + +/* capacity data */ +typedef struct +{ + uint32_t block_nbr; + uint16_t block_size; +} scsi_capacity; + +/* inquiry data */ +typedef struct +{ + uint8_t peripheral_qualifier; + uint8_t device_type; + uint8_t removable_media; + uint8_t vendor_id[9]; + uint8_t product_id[17]; + uint8_t revision_id[5]; +} scsi_std_inquiry_data; + +typedef struct +{ + uint32_t msc_capacity; + uint32_t msc_sense_key; + uint16_t msc_page_len; + uint8_t msc_write_protect; +} usbh_msc_parameter; + +#define DESC_REQUEST_SENSE 0x00U +#define ALLOCATION_LENGTH_REQUEST_SENSE 63U +#define XFER_LEN_MODE_SENSE6 63U + +#define MASK_MODE_SENSE_WRITE_PROTECT 0x80U +#define MODE_SENSE_PAGE_CONTROL_FIELD 0x00U +#define MODE_SENSE_PAGE_CODE 0x3FU +#define DISK_WRITE_PROTECTED 0x01U + +/* function declarations */ +/* send 'Inquiry' command to the device */ +usbh_status usbh_msc_scsi_inquiry (usbh_host *uhost, uint8_t lun, scsi_std_inquiry_data *inquiry); +/* send 'Test unit ready' command to the device */ +usbh_status usbh_msc_test_unitready (usbh_host *uhost, uint8_t lun); +/* send the read capacity command to the device */ +usbh_status usbh_msc_read_capacity10 (usbh_host *uhost, uint8_t lun, scsi_capacity *capacity); +/* send the mode sense6 command to the device */ +usbh_status usbh_msc_mode_sense6 (usbh_host *uhost, uint8_t lun); +/* send the Request Sense command to the device */ +usbh_status usbh_msc_request_sense (usbh_host *uhost, uint8_t lun, msc_scsi_sense *sense_data); +/* send the write10 command to the device */ +usbh_status usbh_msc_write10 (usbh_host *uhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); +/* send the read10 command to the device */ +usbh_status usbh_msc_read10 (usbh_host *uhost, + uint8_t lun, + uint8_t *data_buf, + uint32_t addr, + uint32_t byte_num); + +#endif /* __USBH_MSC_SCSI_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c new file mode 100644 index 00000000..f8155b18 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_bbb.c @@ -0,0 +1,362 @@ +/*! + \file usbh_msc_bbb.c + \brief USB MSC BBB protocol related functions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_transc.h" +#include "drv_usbh_int.h" + +/*! + \brief initialize the mass storage parameters + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval none +*/ +void usbh_msc_bbb_init (usbh_host *uhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + msc->bbb.cbw.field.dCBWSignature = BBB_CBW_SIGNATURE; + msc->bbb.cbw.field.dCBWTag = USBH_MSC_BBB_CBW_TAG; + msc->bbb.state = BBB_SEND_CBW; + msc->bbb.cmd_state = BBB_CMD_SEND; +} + +/*! + \brief manage the different states of BBB transfer and updates the status to upper layer + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bbb_process (usbh_host *uhost, uint8_t lun) +{ + bbb_csw_status csw_status = BBB_CSW_CMD_FAILED; + usbh_status status = USBH_BUSY; + usbh_status error = USBH_BUSY; + usb_urb_state urb_status = URB_IDLE; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bbb.state) { + case BBB_SEND_CBW: + msc->bbb.cbw.field.bCBWLUN = lun; + msc->bbb.state = BBB_SEND_CBW_WAIT; + /* send CBW */ + usbh_data_send (uhost->data, + msc->bbb.cbw.CBWArray, + msc->pipe_out, + BBB_CBW_LENGTH); + break; + + case BBB_SEND_CBW_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_out); + + if (URB_DONE == urb_status) { + if (0U != msc->bbb.cbw.field.dCBWDataTransferLength) { + if (USB_TRX_IN == (msc->bbb.cbw.field.bmCBWFlags & USB_TRX_MASK)) { + msc->bbb.state = BBB_DATA_IN; + } else { + msc->bbb.state = BBB_DATA_OUT; + } + } else { + msc->bbb.state = BBB_RECEIVE_CSW; + } + + } else if (URB_NOTREADY == urb_status) { + msc->bbb.state = BBB_SEND_CBW; + } else { + if (URB_STALL == urb_status) { + msc->bbb.state = BBB_ERROR_OUT; + } + } + break; + + case BBB_DATA_IN: + usbh_data_recev (uhost->data, + msc->bbb.pbuf, + msc->pipe_in, + msc->ep_size_in); + + msc->bbb.state = BBB_DATA_IN_WAIT; + break; + + case BBB_DATA_IN_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_in); + + /* BBB DATA IN stage */ + if (URB_DONE == urb_status) { + if (msc->bbb.cbw.field.dCBWDataTransferLength > msc->ep_size_in) { + msc->bbb.pbuf += msc->ep_size_in; + msc->bbb.cbw.field.dCBWDataTransferLength -= msc->ep_size_in; + } else { + msc->bbb.cbw.field.dCBWDataTransferLength = 0U; + } + + if (msc->bbb.cbw.field.dCBWDataTransferLength > 0U) { + usbh_data_recev (uhost->data, + msc->bbb.pbuf, + msc->pipe_in, + msc->ep_size_in); + } else { + msc->bbb.state = BBB_RECEIVE_CSW; + } + } else if(URB_STALL == urb_status) { + /* this is data stage stall condition */ + msc->bbb.state = BBB_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BBB_DATA_OUT: + usbh_data_send (uhost->data, + msc->bbb.pbuf, + msc->pipe_out, + msc->ep_size_out); + + msc->bbb.state = BBB_DATA_OUT_WAIT; + break; + + case BBB_DATA_OUT_WAIT: + /* BBB DATA OUT stage */ + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_out); + if (URB_DONE == urb_status) { + if (msc->bbb.cbw.field.dCBWDataTransferLength > msc->ep_size_out) { + msc->bbb.pbuf += msc->ep_size_out; + msc->bbb.cbw.field.dCBWDataTransferLength -= msc->ep_size_out; + } else { + msc->bbb.cbw.field.dCBWDataTransferLength = 0; /* reset this value and keep in same state */ + } + + if (msc->bbb.cbw.field.dCBWDataTransferLength > 0) { + usbh_data_send (uhost->data, + msc->bbb.pbuf, + msc->pipe_out, + msc->ep_size_out); + } else { + msc->bbb.state = BBB_RECEIVE_CSW; + } + } else if (URB_NOTREADY == urb_status) { + msc->bbb.state = BBB_DATA_OUT; + } else if (URB_STALL == urb_status) { + msc->bbb.state = BBB_ERROR_OUT; + } else { + /* no operation */ + } + break; + + case BBB_RECEIVE_CSW: + /* BBB CSW stage */ + usbh_data_recev (uhost->data, + msc->bbb.csw.CSWArray, + msc->pipe_in, + BBB_CSW_LENGTH); + + msc->bbb.state = BBB_RECEIVE_CSW_WAIT; + break; + + case BBB_RECEIVE_CSW_WAIT: + urb_status = usbh_urbstate_get(uhost->data, msc->pipe_in); + + /* decode CSW */ + if (URB_DONE == urb_status) { + msc->bbb.state = BBB_SEND_CBW; + msc->bbb.cmd_state = BBB_CMD_SEND; + + csw_status = usbh_msc_csw_decode(uhost); + if (BBB_CSW_CMD_PASSED == csw_status) { + status = USBH_OK; + } else { + status = USBH_FAIL; + } + } else if (URB_STALL == urb_status) { + msc->bbb.state = BBB_ERROR_IN; + } else { + /* no operation */ + } + break; + + case BBB_ERROR_IN: + error = usbh_msc_bbb_abort(uhost, USBH_MSC_DIR_IN); + + if (USBH_OK == error) { + msc->bbb.state = BBB_RECEIVE_CSW; + } else if (USBH_UNRECOVERED_ERROR == status) { + /* this means that there is a stall error limit, do reset recovery */ + msc->bbb.state = BBB_UNRECOVERED_ERROR; + } else { + /* no operation */ + } + break; + + case BBB_ERROR_OUT: + status = usbh_msc_bbb_abort (uhost, USBH_MSC_DIR_OUT); + + if (USBH_OK == status) { + uint8_t toggle = usbh_pipe_toggle_get(uhost->data, msc->pipe_out); + usbh_pipe_toggle_set(uhost->data, msc->pipe_out, 1U - toggle); + usbh_pipe_toggle_set(uhost->data, msc->pipe_in, 0U); + msc->bbb.state = BBB_ERROR_IN; + } else { + if (USBH_UNRECOVERED_ERROR == status) { + msc->bbb.state = BBB_UNRECOVERED_ERROR; + } + } + break; + + case BBB_UNRECOVERED_ERROR: + status = usbh_msc_bbb_reset(uhost); + if (USBH_OK == status) { + msc->bbb.state = BBB_SEND_CBW; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief manages the different error handling for stall + \param[in] uhost: pointer to USB host handler + \param[in] direction: data IN or OUT + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bbb_abort (usbh_host *uhost, uint8_t direction) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (direction) { + case USBH_MSC_DIR_IN : + /* send clrfeature command on bulk IN endpoint */ + status = usbh_clrfeature(uhost, + msc->ep_in, + msc->pipe_in); + break; + + case USBH_MSC_DIR_OUT : + /*send clrfeature command on bulk OUT endpoint */ + status = usbh_clrfeature(uhost, + msc->ep_out, + msc->pipe_out); + break; + + default: + break; + } + + return status; +} + +/*! + \brief reset msc bbb transfer + \param[in] uhost: pointer to USB host handler + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_bbb_reset (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + + if (CTL_IDLE == uhost->control.ctl_state) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_RESET, + .wValue = 0U, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief decode the CSW received by the device and updates the same to upper layer + \param[in] uhost: pointer to USB host + \param[out] none + \retval on success USBH_MSC_OK, on failure USBH_MSC_FAIL + \notes + Refer to USB Mass-Storage Class: BBB (www.usb.org) + 6.3.1 Valid CSW Conditions : + The host shall consider the CSW valid when: + 1. dCSWSignature is equal to 53425355h + 2. the CSW is 13 (Dh) bytes in length, + 3. dCSWTag matches the dCBWTag from the corresponding CBW. +*/ +bbb_csw_status usbh_msc_csw_decode (usbh_host *uhost) +{ + bbb_csw_status status = BBB_CSW_CMD_FAILED; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + /* checking if the transfer length is different than 13 */ + if (BBB_CSW_LENGTH != usbh_xfercount_get (uhost->data, msc->pipe_in)) { + status = BBB_CSW_PHASE_ERROR; + } else { + /* CSW length is correct */ + + /* check validity of the CSW Signature and CSWStatus */ + if (BBB_CSW_SIGNATURE == msc->bbb.csw.field.dCSWSignature) { + /* check condition 1. dCSWSignature is equal to 53425355h */ + if (msc->bbb.csw.field.dCSWTag == msc->bbb.cbw.field.dCBWTag) { + /* check condition 3. dCSWTag matches the dCBWTag from the corresponding CBW */ + if (0U == msc->bbb.csw.field.bCSWStatus) { + status = BBB_CSW_CMD_PASSED; + } else if (1U == msc->bbb.csw.field.bCSWStatus) { + status = BBB_CSW_CMD_FAILED; + } else if (2U == msc->bbb.csw.field.bCSWStatus) { + status = BBB_CSW_PHASE_ERROR; + } else { + /* no operation */ + } + } + } else { + /* If the CSW signature is not valid, we shall return the phase error to + upper layers for reset recovery */ + status = BBB_CSW_PHASE_ERROR; + } + } + + return status; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_core.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_core.c new file mode 100644 index 00000000..7c7354d0 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_core.c @@ -0,0 +1,563 @@ +/*! + \file usbh_core.c + \brief USB MSC(mass storage device) class driver + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include +#include + +/* local function prototypes ('static') */ +static void usbh_msc_itf_deinit (usbh_host *uhost); +static usbh_status usbh_msc_itf_init (usbh_host *uhost); +static usbh_status usbh_msc_req (usbh_host *uhost); +static usbh_status usbh_msc_handle (usbh_host *uhost); +static usbh_status usbh_msc_maxlun_get (usbh_host *uhost, uint8_t *maxlun); +static usbh_status usbh_msc_rdwr_process(usbh_host *uhost, uint8_t lun); + +usbh_class usbh_msc = +{ + USB_CLASS_MSC, + usbh_msc_itf_init, + usbh_msc_itf_deinit, + usbh_msc_req, + usbh_msc_handle, + NULL, + NULL +}; + +/*! + \brief interface initialization for MSC class + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_itf_init (usbh_host *uhost) +{ + usbh_status status = USBH_OK; + + uint8_t interface = usbh_interface_find(&uhost->dev_prop, MSC_CLASS, USB_MSC_SUBCLASS_SCSI, MSC_PROTOCOL); + + if (0xFFU == interface) { + uhost->usr_cb->dev_not_supported(); + + status = USBH_FAIL; + } else { + static usbh_msc_handler msc_handler; + + memset((void*)&msc_handler, 0U, sizeof(usbh_msc_handler)); + + uhost->active_class->class_data = (void *)&msc_handler; + + usbh_interface_select(&uhost->dev_prop, interface); + + usb_desc_ep *ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[0]; + + if (ep_desc->bEndpointAddress & 0x80U) { + msc_handler.ep_in = ep_desc->bEndpointAddress; + msc_handler.ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc_handler.ep_out = ep_desc->bEndpointAddress; + msc_handler.ep_size_out = ep_desc->wMaxPacketSize; + } + + ep_desc = &uhost->dev_prop.cfg_desc_set.itf_desc_set[interface][0].ep_desc[1]; + + if(ep_desc->bEndpointAddress & 0x80U) { + msc_handler.ep_in = ep_desc->bEndpointAddress; + msc_handler.ep_size_in = ep_desc->wMaxPacketSize; + } else { + msc_handler.ep_out = ep_desc->bEndpointAddress; + msc_handler.ep_size_out = ep_desc->wMaxPacketSize; + } + + msc_handler.state = MSC_INIT; + msc_handler.error = MSC_OK; + msc_handler.req_state = MSC_REQ_IDLE; + msc_handler.pipe_out = usbh_pipe_allocate(uhost->data, msc_handler.ep_out); + msc_handler.pipe_in = usbh_pipe_allocate(uhost->data, msc_handler.ep_in); + + usbh_msc_bbb_init(uhost); + + /* open the new channels */ + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + msc_handler.pipe_out, + USB_EPTYPE_BULK, + msc_handler.ep_size_out); + + usbh_pipe_create (uhost->data, + &uhost->dev_prop, + msc_handler.pipe_in, + USB_EPTYPE_BULK, + msc_handler.ep_size_in); + + usbh_pipe_toggle_set (uhost->data, msc_handler.pipe_out, 0U); + usbh_pipe_toggle_set (uhost->data, msc_handler.pipe_in, 0U); + } + + return status; +} + +/*! + \brief deinitialize interface by freeing host channels allocated to interface + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +void usbh_msc_itf_deinit (usbh_host *uhost) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if (msc->pipe_out) { + usb_pipe_halt (uhost->data, msc->pipe_out); + usbh_pipe_free (uhost->data, msc->pipe_out); + + msc->pipe_out = 0U; + } + + if (msc->pipe_in) { + usb_pipe_halt (uhost->data, msc->pipe_in); + usbh_pipe_free (uhost->data, msc->pipe_in); + + msc->pipe_in = 0U; + } +} + +/*! + \brief initialize the MSC state machine + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_req (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->req_state) { + case MSC_REQ_IDLE: + case MSC_REQ_GET_MAX_LUN: + /* issue Get_MaxLun request */ + status = usbh_msc_maxlun_get (uhost, (uint8_t *)&msc->max_lun); + + if (USBH_OK == status) { + msc->max_lun = ((uint8_t)msc->max_lun > MSC_MAX_SUPPORTED_LUN) ? MSC_MAX_SUPPORTED_LUN : (uint8_t)msc->max_lun + 1U; + + for (uint8_t i = 0U; i < msc->max_lun; i++) { + msc->unit[i].prev_ready_state = USBH_FAIL; + msc->unit[i].state_changed = 0U; + } + } else { + if (USBH_NOT_SUPPORTED == status) { + msc->max_lun = 0U; + status = USBH_OK; + } + } + break; + + case MSC_REQ_ERROR: + /* issue clear feature request */ + if (USBH_OK == usbh_clrfeature(uhost, 0x00U, uhost->control.pipe_out_num)) { + msc->req_state = msc->prev_req_state; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief MSC state machine handler + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_handle (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + uint8_t scsi_status = USBH_BUSY; + uint8_t ready_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->state) { + case MSC_INIT: + if (msc->cur_lun < msc->max_lun) { + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + + switch (msc->unit[msc->cur_lun].state) { + case MSC_INIT: + msc->unit[msc->cur_lun].state = MSC_READ_INQUIRY; + msc->timer = uhost->control.timer; + break; + + case MSC_READ_INQUIRY: + scsi_status = usbh_msc_scsi_inquiry (uhost, msc->cur_lun, &msc->unit[msc->cur_lun].inquiry); + + if (USBH_OK == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + } else if(scsi_status == USBH_FAIL) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if(scsi_status == USBH_UNRECOVERED_ERROR) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_TEST_UNIT_READY: + /* issue SCSI command TestUnitReady */ + ready_status = usbh_msc_test_unitready (uhost, msc->cur_lun); + + if (USBH_OK == ready_status) { + if (USBH_OK != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_READ_CAPACITY10; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->unit[msc->cur_lun].prev_ready_state = USBH_OK; + } else if(USBH_FAIL == ready_status) { + if(USBH_FAIL != msc->unit[msc->cur_lun].prev_ready_state) { + msc->unit[msc->cur_lun].state_changed = 1U; + } else { + msc->unit[msc->cur_lun].state_changed = 0U; + } + + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + msc->unit[msc->cur_lun].error = MSC_NOT_READY; + msc->unit[msc->cur_lun].prev_ready_state = USBH_FAIL; + } else { + if(USBH_UNRECOVERED_ERROR == ready_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_READ_CAPACITY10: + /* issue READ_CAPACITY10 SCSI command */ + scsi_status = usbh_msc_read_capacity10 (uhost, msc->cur_lun, &msc->unit[msc->cur_lun].capacity); + + if (USBH_OK == scsi_status) { + if (1U == msc->unit[msc->cur_lun].state_changed) { + } + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_OK; + msc->cur_lun ++; + } else if(USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_REQUEST_SENSE; + } else { + if(USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_REQUEST_SENSE: + /* issue RequestSense SCSI command for retrieving error code */ + scsi_status = usbh_msc_request_sense (uhost, msc->cur_lun, &msc->unit[msc->cur_lun].sense); + if (USBH_OK == scsi_status) { + if ((msc->unit[msc->cur_lun].sense.SenseKey == UNIT_ATTENTION) || (msc->unit[msc->cur_lun].sense.SenseKey == NOT_READY)) { + if (((uhost->control.timer > msc->timer) && ((uhost->control.timer - msc->timer) < 10000U)) \ + || ((uhost->control.timer < msc->timer) && ((uhost->control.timer + 0x3FFFU - msc->timer) < 10000U))) { + msc->unit[msc->cur_lun].state = MSC_TEST_UNIT_READY; + break; + } + } + + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->cur_lun++; + } else if (USBH_FAIL == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_UNRECOVERED_ERROR; + } else { + if (MSC_UNRECOVERED_ERROR == scsi_status) { + msc->unit[msc->cur_lun].state = MSC_IDLE; + msc->unit[msc->cur_lun].error = MSC_ERROR; + } + } + break; + + case MSC_UNRECOVERED_ERROR: + msc->cur_lun++; + break; + + default: + break; + } + } else { + msc->cur_lun = 0U; + msc->state = MSC_IDLE; + } + break; + + case MSC_IDLE: + uhost->usr_cb->dev_user_app(); + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] uhost: pointer to USB host + \param[in] maxlun: pointer to max lun + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_maxlun_get (usbh_host *uhost, uint8_t *maxlun) +{ + usbh_status status = USBH_BUSY; + + if (uhost->control.ctl_state == CTL_IDLE) { + uhost->control.setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_REQTYPE_CLASS | USB_RECPTYPE_ITF, + .bRequest = BBB_GET_MAX_LUN, + .wValue = 0U, + .wIndex = 0U, + .wLength = 1U + }; + + usbh_ctlstate_config (uhost, maxlun, 1U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief get max lun of the mass storage device + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +static usbh_status usbh_msc_rdwr_process(usbh_host *uhost, uint8_t lun) +{ + usbh_status error = USBH_BUSY; + usbh_status scsi_status = USBH_BUSY; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + /* switch msc req state machine */ + switch (msc->unit[lun].state) { + case MSC_READ: + scsi_status = usbh_msc_read10(uhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if (USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_WRITE: + scsi_status = usbh_msc_write10(uhost, lun, NULL, 0U, 0U); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + error = USBH_OK; + } else if (USBH_FAIL == scsi_status) { + msc->unit[lun].state = MSC_REQUEST_SENSE; + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + case MSC_REQUEST_SENSE: + scsi_status = usbh_msc_request_sense (uhost, lun, &msc->unit[lun].sense); + + if (USBH_OK == scsi_status) { + msc->unit[lun].state = MSC_IDLE; + msc->unit[lun].error = MSC_ERROR; + + error = USBH_FAIL; + } + + if (USBH_FAIL == scsi_status) { + } else { + if (USBH_UNRECOVERED_ERROR == scsi_status) { + msc->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; + } + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief get lun information + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] info: pointer to lun information + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_lun_info_get (usbh_host *uhost, uint8_t lun, msc_lun *info) +{ + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if (HOST_CLASS_HANDLER == uhost->cur_state) { + memcpy(info, &msc->unit[lun], sizeof(msc_lun)); + + return USBH_OK; + } else { + return USBH_FAIL; + } +} + +/*! + \brief handle msc read operation + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + if ((0U == udev->host.connect_status) || + (HOST_CLASS_HANDLER != uhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_READ; + msc->unit[lun].state = MSC_READ; + msc->rw_lun = lun; + + usbh_msc_read10(uhost, lun, pbuf, address, length); + + timeout = uhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(uhost, lun)) { + if (((uhost->control.timer > timeout) && ((uhost->control.timer - timeout) > (1000U * length))) \ + || ((uhost->control.timer < timeout) && ((uhost->control.timer + 0x3FFFU - timeout) > (1000U * length))) \ + || (0U == udev->host.connect_status)){ + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} + +/*! + \brief handle msc write operation + \param[in] uhost: pointer to USB host + \param[in] lun: logic unit number + \param[in] address: data address + \param[in] pbuf: pointer to data buffer + \param[in] length: buffer length + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write (usbh_host *uhost, + uint8_t lun, + uint32_t address, + uint8_t *pbuf, + uint32_t length) +{ + uint32_t timeout = 0U; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + if ((0U == udev->host.connect_status) || + (HOST_CLASS_HANDLER != uhost->cur_state) || + (MSC_IDLE != msc->unit[lun].state)) { + return USBH_FAIL; + } + + msc->state = MSC_WRITE; + msc->unit[lun].state = MSC_WRITE; + msc->rw_lun = lun; + + usbh_msc_write10(uhost, lun, pbuf, address, length); + + timeout = uhost->control.timer; + + while (USBH_BUSY == usbh_msc_rdwr_process(uhost, lun)) { + if (((uhost->control.timer > timeout) && ((uhost->control.timer - timeout) > (1000U * length))) \ + || ((uhost->control.timer < timeout) && ((uhost->control.timer + 0x3FFFU - timeout) > (1000U * length))) \ + || (0U == udev->host.connect_status)) { + msc->state = MSC_IDLE; + return USBH_FAIL; + } + } + + msc->state = MSC_IDLE; + + return USBH_OK; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c new file mode 100644 index 00000000..74c30c13 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_fatfs.c @@ -0,0 +1,235 @@ +/*! + \file usbh_msc_fatfs.c + \brief USB MSC host FATFS related functions + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usb_conf.h" +#include "usbh_msc_core.h" + +#include "ff.h" +#include "diskio.h" + +static volatile DSTATUS state = STA_NOINIT; /* disk status */ + +extern usbh_host usb_host; + +/*! + \brief initialize the disk drive + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_initialize (BYTE drv) +{ + usb_core_driver *udev = (usb_core_driver *)usb_host.data; + + if (udev->host.connect_status) { + state &= ~STA_NOINIT; + } + + return state; +} + +/*! + \brief get disk status + \param[in] drv: physical drive number (0) + \param[out] none + \retval operation status +*/ +DSTATUS disk_status (BYTE drv) +{ + if (drv) { + return STA_NOINIT; /* supports only single drive */ + } + + return state; +} + +/*! + \brief read sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_read (BYTE drv, BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *udev = (usb_core_driver *)usb_host.data; + + if (drv || (!count)) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (udev->host.connect_status) { + do { + status = usbh_msc_read (&usb_host, drv, sector, buff, count); + + if (!udev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#if _READONLY == 0U + +/*! + \brief write sectors + \param[in] drv: physical drive number (0) + \param[in] buff: pointer to the data buffer to store read data + \param[in] sector: start sector number (LBA) + \param[in] count: sector count (1..255) + \param[out] none + \retval operation status +*/ +DRESULT disk_write (BYTE drv, const BYTE *buff, DWORD sector, UINT count) +{ + BYTE status = USBH_OK; + usb_core_driver *udev = (usb_core_driver *)usb_host.data; + + if ((!count) || drv) { + return RES_PARERR; + } + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + if (state & STA_PROTECT) { + return RES_WRPRT; + } + + if (udev->host.connect_status) { + do { + status = usbh_msc_write (&usb_host, drv, sector, (BYTE*)buff, count); + + if (!udev->host.connect_status) { + return RES_ERROR; + } + } while(status == USBH_BUSY); + } + + if (status == USBH_OK) { + return RES_OK; + } + + return RES_ERROR; +} + +#endif /* _READONLY == 0 */ + +/*! + \brief I/O control function + \param[in] drv: physical drive number (0) + \param[in] ctrl: control code + \param[in] buff: pointer to the data buffer to store read data + \param[out] none + \retval operation status +*/ +DRESULT disk_ioctl (BYTE drv, BYTE ctrl, void *buff) +{ + DRESULT res = RES_OK; + msc_lun info; + + if (drv) { + return RES_PARERR; + } + + res = RES_ERROR; + + if (state & STA_NOINIT) { + return RES_NOTRDY; + } + + switch (ctrl) { + /* make sure that no pending write process */ + case CTRL_SYNC: + res = RES_OK; + break; + + /* get number of sectors on the disk (dword) */ + case GET_SECTOR_COUNT: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host, drv, &info)) { + *(DWORD*)buff = (DWORD)info.capacity.block_nbr; + res = RES_OK; + } + break; + + /* get r/w sector size (word) */ + case GET_SECTOR_SIZE: + if (USBH_OK == usbh_msc_lun_info_get(&usb_host, drv, &info)) { + *(WORD*)buff = (DWORD)info.capacity.block_size; + res = RES_OK; + } + break; + + /* get erase block size in unit of sector (dword) */ + case GET_BLOCK_SIZE: + *(DWORD *)buff = 512U; + break; + + default: + res = RES_PARERR; + break; + } + + return res; +} + +/*! + \brief get fat time + \param[in] none + \param[out] none + \retval time value +*/ +DWORD get_fattime (void) +{ + return ((DWORD)(2019U - 1980U) << 25U) /* year 2019 */ + | ((DWORD)1U << 21U) /* month 1 */ + | ((DWORD)1U << 16U) /* day 1 */ + | ((DWORD)0U << 11U) /* hour 0 */ + | ((DWORD)0U << 5U) /* min 0 */ + | ((DWORD)0U >> 1U); /* sec 0 */ +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c new file mode 100644 index 00000000..40702cc0 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/class/msc/Source/usbh_msc_scsi.c @@ -0,0 +1,400 @@ +/*! + \file usbh_msc_scsi.c + \brief USB MSC SCSI commands implementing + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bbb.h" + +#include + +/*! + \brief send 'Inquiry' command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] inquiry: pointer to the inquiry structure + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_scsi_inquiry (usbh_host *uhost, uint8_t lun, scsi_std_inquiry_data *inquiry) +{ + usbh_status error = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bbb.cmd_state) { + case BBB_CMD_SEND: + /* prepare the cbw and relevant field*/ + msc->bbb.cbw.field.dCBWDataTransferLength = STANDARD_INQUIRY_DATA_LEN; + msc->bbb.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bbb.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bbb.cbw.field.CBWCB, 0U, CBW_LENGTH); + + msc->bbb.cbw.field.CBWCB[0] = SCSI_INQUIRY; + msc->bbb.cbw.field.CBWCB[1] = (lun << 5U); + msc->bbb.cbw.field.CBWCB[4] = 0x24U; + + msc->bbb.state = BBB_SEND_CBW; + msc->bbb.cmd_state = BBB_CMD_WAIT; + msc->bbb.pbuf = (uint8_t *)(void *)msc->bbb.data; + error = USBH_BUSY; + break; + + case BBB_CMD_WAIT: + error = usbh_msc_bbb_process(uhost, lun); + + if (USBH_OK == error) { + memset(inquiry, 0U, sizeof(scsi_std_inquiry_data)); + + /* assign inquiry data */ + inquiry->device_type = msc->bbb.pbuf[0] & 0x1FU; + inquiry->peripheral_qualifier = msc->bbb.pbuf[0] >> 5U; + + if (0x80U == ((uint32_t)msc->bbb.pbuf[1] & 0x80U)) { + inquiry->removable_media = 1U; + } else { + inquiry->removable_media = 0U; + } + + memcpy (inquiry->vendor_id, &msc->bbb.pbuf[8], 8U); + memcpy (inquiry->product_id, &msc->bbb.pbuf[16], 16U); + memcpy (inquiry->revision_id, &msc->bbb.pbuf[32], 4U); + } + break; + + default: + break; + } + + return error; +} + +/*! + \brief send 'Test unit ready' command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_test_unitready (usbh_host *uhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->bbb.cmd_state) { + case BBB_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bbb.cbw.field.dCBWDataTransferLength = CBW_LENGTH_TEST_UNIT_READY; + msc->bbb.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bbb.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bbb.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bbb.cbw.field.CBWCB[0] = SCSI_TEST_UNIT_READY; + msc->bbb.state = BBB_SEND_CBW; + msc->bbb.cmd_state = BBB_CMD_WAIT; + + status = USBH_BUSY; + break; + + case BBB_CMD_WAIT: + status = usbh_msc_bbb_process(uhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read capacity command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] capacity: pointer to SCSI capacity + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read_capacity10 (usbh_host *uhost, uint8_t lun, scsi_capacity *capacity) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bbb.cmd_state) { + case BBB_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bbb.cbw.field.dCBWDataTransferLength = READ_CAPACITY10_DATA_LEN; + msc->bbb.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bbb.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bbb.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bbb.cbw.field.CBWCB[0] = SCSI_READ_CAPACITY10; + msc->bbb.state = BBB_SEND_CBW; + msc->bbb.cmd_state = BBB_CMD_WAIT; + msc->bbb.pbuf = (uint8_t *)(void *)msc->bbb.data; + + status = USBH_BUSY; + break; + + case BBB_CMD_WAIT: + status = usbh_msc_bbb_process(uhost, lun); + + if (USBH_OK == status) { + capacity->block_nbr = msc->bbb.pbuf[3] | \ + ((uint32_t)msc->bbb.pbuf[2] << 8U) | \ + ((uint32_t)msc->bbb.pbuf[1] << 16U) | \ + ((uint32_t)msc->bbb.pbuf[0] << 24U); + + capacity->block_size = (uint16_t)(msc->bbb.pbuf[7] | ((uint32_t)msc->bbb.pbuf[6] << 8U)); + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the mode sense6 command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_mode_sense6 (usbh_host *uhost, uint8_t lun) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + + switch (msc->bbb.cmd_state) { + case BBB_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bbb.cbw.field.dCBWDataTransferLength = XFER_LEN_MODE_SENSE6; + msc->bbb.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bbb.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bbb.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bbb.cbw.field.CBWCB[0] = SCSI_MODE_SENSE6; + msc->bbb.cbw.field.CBWCB[2] = MODE_SENSE_PAGE_CONTROL_FIELD | MODE_SENSE_PAGE_CODE; + msc->bbb.cbw.field.CBWCB[4] = XFER_LEN_MODE_SENSE6; + msc->bbb.state = BBB_SEND_CBW; + msc->bbb.cmd_state = BBB_CMD_WAIT; + msc->bbb.pbuf = (uint8_t *)(void *)msc->bbb.data; + + status = USBH_BUSY; + break; + + case BBB_CMD_WAIT: + status = usbh_msc_bbb_process(uhost, lun); + + if (USBH_OK == status) { + if (msc->bbb.data[2] & MASK_MODE_SENSE_WRITE_PROTECT) { + + } else { + + } + } + break; + + default: + break; + } + + + return status; +} + +/*! + \brief send the Request Sense command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] sense_data: pointer to sense data + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_request_sense (usbh_host *uhost, uint8_t lun, msc_scsi_sense *sense_data) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bbb.cmd_state) { + case BBB_CMD_SEND: + /* prepare the cbw and relevant field */ + msc->bbb.cbw.field.dCBWDataTransferLength = ALLOCATION_LENGTH_REQUEST_SENSE; + msc->bbb.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bbb.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bbb.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bbb.cbw.field.CBWCB[0] = SCSI_REQUEST_SENSE; + msc->bbb.cbw.field.CBWCB[1] = (lun << 5U); + msc->bbb.cbw.field.CBWCB[4] = ALLOCATION_LENGTH_REQUEST_SENSE; + + msc->bbb.state = BBB_SEND_CBW; + msc->bbb.cmd_state = BBB_CMD_WAIT; + msc->bbb.pbuf = (uint8_t *)(void *)msc->bbb.data; + + status = USBH_BUSY; + break; + + case BBB_CMD_WAIT: + status = usbh_msc_bbb_process(uhost, lun); + + if (status == USBH_OK) { + /* get sense data */ + sense_data->SenseKey = msc->bbb.pbuf[2] & 0x0FU; + sense_data->ASC = msc->bbb.pbuf[12]; + sense_data->ASCQ = msc->bbb.pbuf[13]; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the write10 command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be written + \param[in] sector_num: number of sector to be written + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_write10 (usbh_host *uhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bbb.cmd_state) { + case BBB_CMD_SEND: + msc->bbb.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bbb.cbw.field.bmCBWFlags = USB_TRX_OUT; + msc->bbb.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bbb.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bbb.cbw.field.CBWCB[0] = SCSI_WRITE10; + + /* logical block address */ + msc->bbb.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bbb.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bbb.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bbb.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bbb.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bbb.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bbb.state = BBB_SEND_CBW; + msc->bbb.cmd_state = BBB_CMD_WAIT; + msc->bbb.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BBB_CMD_WAIT: + status = usbh_msc_bbb_process(uhost, lun); + break; + + default: + break; + } + + return status; +} + +/*! + \brief send the read10 command to the device + \param[in] uhost: pointer to USB host handler + \param[in] lun: logic unit number + \param[in] data_buf: data buffer contains the data to write + \param[in] addr: address to which the data will be read + \param[in] sector_num: number of sector to be read + \param[out] none + \retval operation status +*/ +usbh_status usbh_msc_read10 (usbh_host *uhost, uint8_t lun, uint8_t *data_buf, uint32_t addr, uint32_t sector_num) +{ + usbh_status status = USBH_FAIL; + usbh_msc_handler *msc = (usbh_msc_handler *)uhost->active_class->class_data; + + switch (msc->bbb.cmd_state) { + case BBB_CMD_SEND: + /* prepare the CBW and relevant field */ + msc->bbb.cbw.field.dCBWDataTransferLength = sector_num * msc->unit[lun].capacity.block_size; + msc->bbb.cbw.field.bmCBWFlags = USB_TRX_IN; + msc->bbb.cbw.field.bCBWCBLength = CBW_LENGTH; + + memset(msc->bbb.cbw.field.CBWCB, 0U, CBW_CB_LENGTH); + + msc->bbb.cbw.field.CBWCB[0] = SCSI_READ10; + + /* logical block address */ + msc->bbb.cbw.field.CBWCB[2] = (((uint8_t*)&addr)[3]); + msc->bbb.cbw.field.CBWCB[3] = (((uint8_t*)&addr)[2]); + msc->bbb.cbw.field.CBWCB[4] = (((uint8_t*)&addr)[1]); + msc->bbb.cbw.field.CBWCB[5] = (((uint8_t*)&addr)[0]); + + /* transfer length */ + msc->bbb.cbw.field.CBWCB[7] = (((uint8_t *)§or_num)[1]); + msc->bbb.cbw.field.CBWCB[8] = (((uint8_t *)§or_num)[0]); + + msc->bbb.state = BBB_SEND_CBW; + msc->bbb.cmd_state = BBB_CMD_WAIT; + msc->bbb.pbuf = data_buf; + + status = USBH_BUSY; + break; + + case BBB_CMD_WAIT: + status = usbh_msc_bbb_process(uhost, lun); + break; + + default: + break; + } + + return status; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_core.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_core.h new file mode 100644 index 00000000..873b22eb --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_core.h @@ -0,0 +1,279 @@ +/*! + \file usbh_core.h + \brief USB host core state machine header file + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_CORE_H +#define __USBH_CORE_H + +#include "usbh_conf.h" +#include "drv_usb_host.h" + +#define MSC_CLASS 0x08U +#define HID_CLASS 0x03U +#define MSC_PROTOCOL 0x50U +#define CBI_PROTOCOL 0x01U + +#define USBH_MAX_ERROR_COUNT 3U + +#define USBH_DEV_ADDR_DEFAULT 0U +#define USBH_DEV_ADDR 1U + +typedef enum +{ + USBH_OK = 0U, + USBH_BUSY, + USBH_FAIL, + USBH_NOT_SUPPORTED, + USBH_UNRECOVERED_ERROR, + USBH_SPEED_UNKNOWN_ERROR, + USBH_APPLY_DEINIT +} usbh_status; + +/* USB host global operation state */ +typedef enum +{ + HOST_DEFAULT = 0U, + HOST_DETECT_DEV_SPEED, + HOST_DEV_CONNECT, + HOST_DEV_DETACHED, + HOST_DEV_ENUM, + HOST_PWR_FEATURE_SET, + HOST_CLASS_CHECK, + HOST_CLASS_ENUM, + HOST_CLASS_HANDLER, + HOST_USER_INPUT, + HOST_SUSPEND, + HOST_WAKEUP, + HOST_ERROR +} usb_host_state; + +/* USB host enumeration state */ +typedef enum +{ + ENUM_DEFAULT = 0U, + ENUM_GET_DEV_DESC, + ENUM_SET_ADDR, + ENUM_GET_CFG_DESC, + ENUM_GET_CFG_DESC_SET, + ENUM_GET_STR_DESC, +#ifdef USB_MTP + ENUM_GET_MTP_STR, +#endif + ENUM_SET_CONFIGURATION, + ENUM_DEV_CONFIGURED +} usbh_enum_state; + +/* USB host control transfer state */ +typedef enum +{ + CTL_IDLE = 0U, + CTL_SETUP, + CTL_SETUP_WAIT, + CTL_DATA_IN, + CTL_DATA_IN_WAIT, + CTL_DATA_OUT, + CTL_DATA_OUT_WAIT, + CTL_STATUS_IN, + CTL_STATUS_IN_WAIT, + CTL_STATUS_OUT, + CTL_STATUS_OUT_WAIT, + CTL_ERROR, + CTL_FINISH +} usbh_ctl_state; + +/* user action state */ +typedef enum +{ + USR_IN_NO_RESP = 0U, + USR_IN_RESP_OK = 1U, +} usbh_user_status; + +/* USB host wakeup mode */ +typedef enum +{ + NORMAL_WORK = 0U, + GENERAL_WAKEUP = 1U, + REMOTE_WAKEUP = 2, +} usbh_wakeup_mode; + +/* control transfer information */ +typedef struct _usbh_control +{ + uint8_t pipe_in_num; + uint8_t pipe_out_num; + uint8_t max_len; + uint8_t error_count; + + uint8_t *buf; + uint16_t ctl_len; + uint16_t timer; + + usb_setup setup; + usbh_ctl_state ctl_state; +} usbh_control; + +/* USB interface descriptor set */ +typedef struct _usb_desc_itf_set +{ + usb_desc_itf itf_desc; + usb_desc_ep ep_desc[USBH_MAX_EP_NUM]; +} usb_desc_itf_set; + +/* USB configure descriptor set */ +typedef struct _usb_desc_cfg_set +{ + usb_desc_config cfg_desc; + usb_desc_itf_set itf_desc_set[USBH_MAX_INTERFACES_NUM][USBH_MAX_ALT_SETTING]; +} usb_desc_cfg_set; + +/* USB device property */ +typedef struct +{ + uint8_t data[USBH_DATA_BUF_MAX_LEN]; + uint8_t cur_itf; + uint8_t addr; + + uint32_t speed; + + usb_desc_dev dev_desc; + usb_desc_cfg_set cfg_desc_set; + +#if (USBH_CFG_DESC_KEEP == 1U) + uint8_t cfgdesc_rawdata[USBH_CFGSET_MAX_LEN]; +#endif /* (USBH_CFG_DESC_KEEP == 1U) */ +} usb_dev_prop; + +struct _usbh_host; + +/* device class callbacks */ +typedef struct +{ + uint8_t class_code; /*!< USB class type */ + + usbh_status (*class_init) (struct _usbh_host *phost); + void (*class_deinit) (struct _usbh_host *phost); + usbh_status (*class_requests) (struct _usbh_host *phost); + usbh_status (*class_machine) (struct _usbh_host *phost); + usbh_status (*class_sof) (struct _usbh_host *uhost); + + void *class_data; +} usbh_class; + +/* user callbacks */ +typedef struct +{ + void (*dev_init) (void); + void (*dev_deinit) (void); + void (*dev_attach) (void); + void (*dev_reset) (void); + void (*dev_detach) (void); + void (*dev_over_currented) (void); + void (*dev_speed_detected) (uint32_t dev_speed); + void (*dev_devdesc_assigned) (void *dev_desc); + void (*dev_address_set) (void); + + void (*dev_cfgdesc_assigned) (usb_desc_config *cfg_desc, + usb_desc_itf *itf_desc, + usb_desc_ep *ep_desc); + + void (*dev_mfc_str) (void *mfc_str); + void (*dev_prod_str) (void *prod_str); + void (*dev_seral_str) (void *serial_str); + void (*dev_enumerated) (void); + usbh_user_status (*dev_user_input) (void); + int (*dev_user_app) (void); + void (*dev_not_supported) (void); + void (*dev_error) (void); +} usbh_user_cb; + +/* host information */ +typedef struct _usbh_host +{ + usb_host_state cur_state; /*!< host state machine value */ + usb_host_state backup_state; /*!< backup of previous state machine value */ + usbh_enum_state enum_state; /*!< enumeration state machine */ + usbh_control control; /*!< USB host control state machine */ + usb_dev_prop dev_prop; /*!< USB device property */ + + usbh_class *uclass[USBH_MAX_SUPPORTED_CLASS]; /*!< USB host supported class */ + usbh_class *active_class; /*!< USB active class */ + usbh_user_cb *usr_cb; /*!< USB user callback */ + + uint8_t class_num; /*!< USB class number */ + + void *data; /*!< used for... */ + +#if USB_LOW_POWER + uint8_t suspend_flag; /*!< host suspend flag */ + uint8_t dev_supp_remote_wkup; /*!< record device remote wakeup function */ + usbh_wakeup_mode wakeup_mode; /*!< record wakeup mode */ +#endif /* USB_LOW_POWER*/ +} usbh_host; + +/*! + \brief get USB URB state + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline usb_urb_state usbh_urbstate_get (usb_core_driver *udev, uint8_t pp_num) +{ + return udev->host.pipe[pp_num].urb_state; +} + +/*! + \brief get USB transfer data count + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval none +*/ +static inline uint32_t usbh_xfercount_get (usb_core_driver *udev, uint8_t pp_num) +{ + return udev->host.backup_xfercount[pp_num]; +} + +/* function declarations */ +/* USB host stack initializations */ +void usbh_init (usbh_host *uhost, usbh_user_cb *user_cb); +/* USB host register device class */ +usbh_status usbh_class_register (usbh_host *uhost, usbh_class *puclass); +/* de-initialize USB host */ +usbh_status usbh_deinit (usbh_host *uhost); +/* USB host core main state machine process */ +void usbh_core_task (usbh_host *uhost); +/* handle the error on USB host side */ +void usbh_error_handler (usbh_host *uhost, usbh_status err_type); + +#endif /* __USBH_CORE_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_enum.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_enum.h new file mode 100644 index 00000000..e5e5c6fb --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_enum.h @@ -0,0 +1,70 @@ +/*! + \file usbh_enum.h + \brief USB host mode USB enumeration header file + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_ENUM_H +#define __USBH_ENUM_H + +#include "usbh_core.h" + +/* function declarations */ +/* configure USB control status parameters */ +void usbh_ctlstate_config (usbh_host *uhost, uint8_t *buf, uint16_t len); +/* get device descriptor from the USB device */ +usbh_status usbh_devdesc_get (usbh_host *uhost, uint8_t len); +/* get configuration descriptor from the USB device */ +usbh_status usbh_cfgdesc_get (usbh_host *uhost, uint16_t len); +/* get string descriptor from the USB device */ +usbh_status usbh_strdesc_get (usbh_host *uhost,uint8_t str_index, uint8_t *buf, uint16_t len); +/* set the address to the connected device */ +usbh_status usbh_setaddress (usbh_host *uhost, uint8_t dev_addr); +/* set the configuration value to the connected device */ +usbh_status usbh_setcfg (usbh_host *uhost, uint16_t config); +/* set the interface value to the connected device */ +usbh_status usbh_setinterface (usbh_host *uhost, uint8_t itf_num, uint8_t alter_setting); +/* set or enable a specific device feature */ +usbh_status usbh_setdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific device feature */ +usbh_status usbh_clrdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex); +/* clear or disable a specific feature */ +usbh_status usbh_clrfeature (usbh_host *uhost, uint8_t ep_addr, uint8_t pp_num); +/* get the next descriptor header */ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr); +/* select an interface */ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface); +/* find the interface index for a specific class */ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol); +/* find the interface index for a specific class interface and alternate setting number */ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings); + +#endif /* __USBH_ENUM_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_pipe.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_pipe.h new file mode 100644 index 00000000..a6f694c5 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_pipe.h @@ -0,0 +1,102 @@ +/*! + \file usbh_pipe.h + \brief USB host mode pipe header file + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_PIPE_H +#define __USBH_PIPE_H + +#include "usbh_core.h" + +/* host pipe maximum */ +#define HP_MAX 8U + +/* host pipe status */ +#define HP_OK 0x0000U +#define HP_USED 0x8000U +#define HP_ERROR 0xFFFFU +#define HP_USED_MASK 0x7FFFU + +/*! + \brief set toggle for a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[in] toggle: toggle (0/1) + \param[out] none + \retval operation status +*/ +__STATIC_INLINE void usbh_pipe_toggle_set (usb_core_driver *udev, uint8_t pp_num, uint8_t toggle) +{ + if (udev->host.pipe[pp_num].ep.dir) { + udev->host.pipe[pp_num].data_toggle_in = toggle; + } else { + udev->host.pipe[pp_num].data_toggle_out = toggle; + } +} + +/*! + \brief get toggle flag of pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +__STATIC_INLINE uint8_t usbh_pipe_toggle_get (usb_core_driver *udev, uint8_t pp_num) +{ + if (udev->host.pipe[pp_num].ep.dir) { + return udev->host.pipe[pp_num].data_toggle_in; + } else { + return udev->host.pipe[pp_num].data_toggle_out; + } +} + +/* function declarations */ +/* create a pipe */ +uint8_t usbh_pipe_create (usb_core_driver *udev, + usb_dev_prop *dev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl); +/* modify a pipe */ +uint8_t usbh_pipe_update (usb_core_driver *udev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl); +/* allocate a new pipe */ +uint8_t usbh_pipe_allocate (usb_core_driver *udev, uint8_t ep_addr); +/* free a pipe */ +uint8_t usbh_pipe_free (usb_core_driver *udev, uint8_t pp_num); +/* delete all USB host pipe */ +uint8_t usbh_pipe_delete (usb_core_driver *udev); + +#endif /* __USBH_PIPE_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_transc.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_transc.h new file mode 100644 index 00000000..4bae775e --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Include/usbh_transc.h @@ -0,0 +1,50 @@ +/*! + \file usbh_transc.h + \brief USB host mode transactions header file + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USBH_TRANSC_H +#define __USBH_TRANSC_H + +#include "usbh_core.h" + +/* function declarations */ +/* send the setup packet to the USB device */ +usbh_status usbh_ctlsetup_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num); +/* send a data packet to the USB device */ +usbh_status usbh_data_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* receive a data packet from the USB device */ +usbh_status usbh_data_recev (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len); +/* USB control transfer handler */ +usbh_status usbh_ctl_handler (usbh_host *uhost); + +#endif /* __USBH_TRANSC_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_core.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_core.c new file mode 100644 index 00000000..4c2492f5 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_core.c @@ -0,0 +1,653 @@ +/*! + \file usbh_core.c + \brief USB host core state machine driver + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "drv_usbh_int.h" +#include "usbh_pipe.h" +#include "usbh_enum.h" + +#include + +usb_core_driver usbh_core; + +/* local function prototypes ('static') */ +static uint8_t usb_ev_sof (usbh_host *uhost); +static uint8_t usb_ev_connect (usbh_host *uhost); +static uint8_t usb_ev_disconnect (usbh_host *uhost); +static usbh_status usbh_enum_task (usbh_host *uhost); + +#if USB_LOW_POWER +static void usb_hwp_suspend (usb_core_driver *udev); +static void usb_hwp_resume (usb_core_driver *udev); +#endif /* USB_LOW_POWER */ + +usbh_ev_cb usbh_int_op = +{ + usb_ev_connect, + usb_ev_disconnect, + usb_ev_sof, +}; + +usbh_ev_cb *usbh_int_fop = &usbh_int_op; + +/*! + \brief USB host stack initializations + \param[in] uhost: pointer to USB host + \param[in] user_cb: pointer to user callback + \param[out] none + \retval none +*/ +void usbh_init (usbh_host *uhost, usbh_user_cb *user_cb) +{ + /* host deinitialization */ + usbh_deinit(uhost); + + uhost->usr_cb = user_cb; + + usbh_core.host.connect_status = 0U; + + for (uint8_t i = 0U; i < USBFS_MAX_TX_FIFOS; i++) { + usbh_core.host.pipe[i].err_count = 0U; + usbh_core.host.pipe[i].pp_status = PIPE_IDLE; + usbh_core.host.backup_xfercount[i] = 0U; + } + + usbh_core.host.pipe[0].ep.mps = 8U; + +#ifdef USE_USB_FS + usb_basic_init (&usbh_core.bp, &usbh_core.regs, USB_CORE_ENUM_FS); +#endif /* USE_USB_FS */ + +#ifndef DUAL_ROLE_MODE_ENABLED + usb_globalint_disable(&usbh_core.regs); + + usb_core_init (usbh_core.bp, &usbh_core.regs); + +#ifndef USE_OTG_MODE + usb_curmode_set (&usbh_core.regs, HOST_MODE); +#endif /* USE_OTG_MODE */ + + usb_host_init (&usbh_core); + + usb_globalint_enable(&usbh_core.regs); +#endif /* DUAL_ROLE_MODE_ENABLED */ + + /* link driver to the stack */ + usbh_core.host.data = (void *)uhost; + uhost->data = (void *)&usbh_core; + + /* upon initialize call usr call back */ + uhost->usr_cb->dev_init(); +} + +/*! + \brief USB host register device class + \param[in] uhost: pointer to USB host instance + \param[in] puclass: pointer to USB device class + \param[out] none + \retval operation status +*/ +usbh_status usbh_class_register (usbh_host *uhost, usbh_class *puclass) +{ + usbh_status status = USBH_OK; + + if (NULL != puclass) { + if (uhost->class_num < USBH_MAX_SUPPORTED_CLASS) { + uhost->uclass[uhost->class_num++] = puclass; + } else { + status = USBH_FAIL; + } + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief deinitialize USB host + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_deinit(usbh_host *uhost) +{ + /* software initialize */ + uhost->cur_state = HOST_DEFAULT; + uhost->backup_state = HOST_DEFAULT; + uhost->enum_state = ENUM_DEFAULT; + + uhost->control.ctl_state = CTL_IDLE; + uhost->control.max_len = USB_FS_EP0_MAX_LEN; + + uhost->dev_prop.addr = USBH_DEV_ADDR_DEFAULT; + uhost->dev_prop.speed = PORT_SPEED_FULL; + uhost->dev_prop.cur_itf = 0xFFU; + + usbh_pipe_free(&usbh_core, uhost->control.pipe_in_num); + usbh_pipe_free(&usbh_core, uhost->control.pipe_out_num); + + return USBH_OK; +} + +/*! + \brief USB host core main state machine process + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +void usbh_core_task (usbh_host *uhost) +{ + volatile usbh_status status = USBH_FAIL; + + /* check for host port events */ + if (((0U == usbh_core.host.connect_status) || (0U == usbh_core.host.port_enabled)) && (HOST_DEFAULT != uhost->cur_state)) { + if (uhost->cur_state != HOST_DEV_DETACHED) { + uhost->cur_state = HOST_DEV_DETACHED; + } + } + + switch (uhost->cur_state) { + case HOST_DEFAULT: + if (usbh_core.host.connect_status) { + uhost->cur_state = HOST_DETECT_DEV_SPEED; + + usb_mdelay (100U); + + usb_port_reset (&usbh_core); + + uhost->usr_cb->dev_reset(); + } + break; + + case HOST_DETECT_DEV_SPEED: + if (usbh_core.host.port_enabled) { + uhost->cur_state = HOST_DEV_CONNECT; + + uhost->dev_prop.speed = usb_curspeed_get (&usbh_core); + + uhost->usr_cb->dev_speed_detected(uhost->dev_prop.speed); + + usb_mdelay (50U); + } + break; + + case HOST_DEV_CONNECT: + uhost->usr_cb->dev_attach(); + uhost->control.pipe_out_num = usbh_pipe_allocate(&usbh_core, 0x00U); + uhost->control.pipe_in_num = usbh_pipe_allocate(&usbh_core, 0x80U); + + /* open IN control pipe */ + usbh_pipe_create (&usbh_core, + &uhost->dev_prop, + uhost->control.pipe_in_num, + USB_EPTYPE_CTRL, + (uint16_t)uhost->control.max_len); + + /* open OUT control pipe */ + usbh_pipe_create (&usbh_core, + &uhost->dev_prop, + uhost->control.pipe_out_num, + USB_EPTYPE_CTRL, + (uint16_t)uhost->control.max_len); + + uhost->cur_state = HOST_DEV_ENUM; + break; + + case HOST_DEV_ENUM: + /* check for enumeration status */ + if (USBH_OK == usbh_enum_task (uhost)) { + /* the function shall return USBH_OK when full enumeration is complete */ + + /* user callback for end of device basic enumeration */ + uhost->usr_cb->dev_enumerated(); + +#if USB_LOW_POWER + uhost->cur_state = HOST_SUSPEND; + + /* judge device remote wakeup function */ + if ((uhost->dev_prop.cfg_desc_set.cfg_desc.bmAttributes) & (1U << 5)) { + uhost->dev_supp_remote_wkup = 1; + }else{ + uhost->dev_supp_remote_wkup = 0; + } +#else + uhost->cur_state = HOST_PWR_FEATURE_SET; +#endif /* USB_LOW_POWER */ + } + break; + + case HOST_PWR_FEATURE_SET: + if ((uhost->dev_prop.cfg_desc_set.cfg_desc.bmAttributes) & (1U << 5)) { + if (usbh_setdevfeature(uhost, FEATURE_SELECTOR_REMOTEWAKEUP, 0U) == USBH_OK) { + uhost->cur_state = HOST_CLASS_CHECK; + } + } else { + uhost->cur_state = HOST_CLASS_CHECK; + } + break; + + case HOST_CLASS_CHECK: + if (0U == uhost->class_num) { + uhost->cur_state = HOST_ERROR; + } else { + uhost->active_class = NULL; + + uint8_t itf_class = uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc.bInterfaceClass; + + for (uint8_t index = 0U; index < uhost->class_num; index++) { + if ((uhost->uclass[index]->class_code == itf_class) || (0xFFU == itf_class)) { + uhost->active_class = uhost->uclass[index]; + } + } + + if (uhost->active_class != NULL) { + uhost->cur_state = HOST_USER_INPUT; + } else { + uhost->cur_state = HOST_ERROR; + } + } + break; + + case HOST_USER_INPUT: + /* the function should return user response true to move to class state */ + if (USR_IN_RESP_OK == uhost->usr_cb->dev_user_input()) { + if ((USBH_OK == uhost->active_class->class_init(uhost))) { + uhost->cur_state = HOST_CLASS_ENUM; + } + } + break; + +#if USB_LOW_POWER + case HOST_SUSPEND: + if(uhost->dev_supp_remote_wkup){ + /* send set feature command*/ + if (USBH_OK == usbh_setdevfeature (uhost, FEATURE_SELECTOR_REMOTEWAKEUP, 0U)) { + + usb_hwp_suspend(&usbh_core); + + usb_mdelay (20U); + uhost->suspend_flag = 1; + uhost->usr_cb->dev_user_input(); + + /* MCU enter deep-sleep*/ + pmu_to_deepsleepmode (PMU_LDO_LOWPOWER, WFI_CMD); + uhost->cur_state = HOST_WAKEUP; + } + } else { + /* host suspend */ + usb_hwp_suspend(&usbh_core); + + usb_mdelay(20U); + uhost->suspend_flag = 1U; + uhost->usr_cb->dev_user_input(); + + /* MCU enter deep-sleep */ + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD); + uhost->cur_state = HOST_WAKEUP; + } + break; + + case HOST_WAKEUP: + /* judge suspend status */ + if (0U == uhost->suspend_flag) { + usb_hwp_resume(&usbh_core); + usb_mdelay(500U); + + if (uhost->dev_supp_remote_wkup) { + if (USBH_OK == usbh_clrdevfeature (uhost, FEATURE_SELECTOR_DEV, 0U)) { + /* user callback for initialization */ + uhost->usr_cb->dev_init(); + uhost->cur_state = HOST_CLASS_CHECK; + } + } else { + uhost->cur_state = HOST_CLASS_CHECK; + } + } + break; +#endif /* USB_LOW_POWER */ + + case HOST_CLASS_ENUM: + /* process class standard control requests state machine */ + status = uhost->active_class->class_requests(uhost); + + if (USBH_OK == status) { + uhost->cur_state = HOST_CLASS_HANDLER; + } else { + usbh_error_handler (uhost, status); + } + break; + + case HOST_CLASS_HANDLER: + /* process class state machine */ + status = uhost->active_class->class_machine(uhost); + + usbh_error_handler (uhost, status); + break; + + case HOST_ERROR: + /* deinitialize host for new enumeration */ + usbh_deinit (uhost); + uhost->usr_cb->dev_deinit(); + uhost->active_class->class_deinit(uhost); + break; + + case HOST_DEV_DETACHED: + /* manage user disconnect operations*/ + uhost->usr_cb->dev_detach(); + + /* re-initialize host for new enumeration */ + usbh_deinit (uhost); + uhost->usr_cb->dev_deinit(); + uhost->active_class->class_deinit(uhost); + usbh_pipe_delete(&usbh_core); + uhost->cur_state = HOST_DEFAULT; + break; + + default: + break; + } +} + +/*! + \brief handle the error on USB host side + \param[in] uhost: pointer to USB host + \param[in] err_type: type of error or busy/OK state + \param[out] none + \retval none +*/ +void usbh_error_handler (usbh_host *uhost, usbh_status err_type) +{ + /* error unrecovered or not supported device speed */ + if ((USBH_SPEED_UNKNOWN_ERROR == err_type) || (USBH_UNRECOVERED_ERROR == err_type)) { + uhost->usr_cb->dev_error(); + + uhost->cur_state = HOST_ERROR; + } else if (USBH_APPLY_DEINIT == err_type) { + uhost->cur_state = HOST_ERROR; + + /* user callback for initialization */ + uhost->usr_cb->dev_init(); + } else { + /* no operation */ + } +} + +/*! + \brief USB SOF event function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usb_ev_sof (usbh_host *uhost) +{ + /* this callback could be used to implement a scheduler process */ + uhost->control.timer = (uint16_t)usb_curframe_get(&usbh_core); + + if (uhost->active_class != NULL) { + if (uhost->active_class->class_sof != NULL) { + uhost->active_class->class_sof(uhost); + } + } + + return 0U; +} + +/*! + \brief USB connect event function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usb_ev_connect (usbh_host *uhost) +{ + usbh_core.host.connect_status = 1U; + + return 0U; +} + +/*! + \brief USB disconnect event function from the interrupt + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +static uint8_t usb_ev_disconnect (usbh_host *uhost) +{ + usbh_core.host.connect_status = 0U; + + return 0U; +} + +/*! + \brief handle the USB enumeration task + \param[in] uhost: pointer to host + \param[out] none + \retval none +*/ +static usbh_status usbh_enum_task (usbh_host *uhost) +{ + uint8_t str_buf[512]; + usbh_status status = USBH_BUSY; + + static uint8_t index_mfc_str = 0U, index_prod_str = 0U, index_serial_str = 0U; + + switch (uhost->enum_state) { + case ENUM_DEFAULT: + /* get device descriptor for only 1st 8 bytes : to get ep0 max packet size */ + if (USBH_OK == usbh_devdesc_get (uhost, 8U)) { + uhost->control.max_len = uhost->dev_prop.dev_desc.bMaxPacketSize0; + + /* modify control channels configuration for maximum packet size */ + usbh_pipe_update (&usbh_core, + uhost->control.pipe_out_num, + 0U, 0U, + (uint16_t)uhost->control.max_len); + + usbh_pipe_update (&usbh_core, + uhost->control.pipe_in_num, + 0U, 0U, + (uint16_t)uhost->control.max_len); + + uhost->enum_state = ENUM_GET_DEV_DESC; + } + break; + + case ENUM_GET_DEV_DESC: + /* get full device descriptor */ + if (USBH_OK == usbh_devdesc_get (uhost, USB_DEV_DESC_LEN)) { + uhost->usr_cb->dev_devdesc_assigned(&uhost->dev_prop.dev_desc); + + index_mfc_str = uhost->dev_prop.dev_desc.iManufacturer; + index_prod_str = uhost->dev_prop.dev_desc.iProduct; + index_serial_str = uhost->dev_prop.dev_desc.iSerialNumber; + + uhost->enum_state = ENUM_SET_ADDR; + } + break; + + case ENUM_SET_ADDR: + /* set address */ + if (USBH_OK == usbh_setaddress (uhost, USBH_DEV_ADDR)) { + usb_mdelay (2U); + + uhost->dev_prop.addr = USBH_DEV_ADDR; + + /* user callback for device address assigned */ + uhost->usr_cb->dev_address_set(); + + /* modify control channels to update device address */ + usbh_pipe_update (&usbh_core, + uhost->control.pipe_in_num, + uhost->dev_prop.addr, + 0U, 0U); + + usbh_pipe_update (&usbh_core, + uhost->control.pipe_out_num, + uhost->dev_prop.addr, + 0U, 0U); + + uhost->enum_state = ENUM_GET_CFG_DESC; + } + break; + + case ENUM_GET_CFG_DESC: + /* get standard configuration descriptor */ + if (USBH_OK == usbh_cfgdesc_get (uhost, USB_CFG_DESC_LEN)) { + uhost->enum_state = ENUM_GET_CFG_DESC_SET; + } + break; + + case ENUM_GET_CFG_DESC_SET: + /* get full configure descriptor (config, interface, endpoints) */ + if (USBH_OK == usbh_cfgdesc_get (uhost, uhost->dev_prop.cfg_desc_set.cfg_desc.wTotalLength)) { + /* user callback for configuration descriptors available */ + uhost->usr_cb->dev_cfgdesc_assigned (&uhost->dev_prop.cfg_desc_set.cfg_desc, + &uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].itf_desc, + &uhost->dev_prop.cfg_desc_set.itf_desc_set[0][0].ep_desc[0]); + + uhost->enum_state = ENUM_GET_STR_DESC; + } + break; + + case ENUM_GET_STR_DESC: + if (index_mfc_str) { + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iManufacturer, + str_buf, + 0xFFU)) { + /* user callback for manufacturing string */ + uhost->usr_cb->dev_mfc_str(str_buf); + + index_mfc_str = 0U; + } + } else { + if (index_prod_str) { + /* check that product string is available */ + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iProduct, + str_buf, + 0xFFU)) { + uhost->usr_cb->dev_prod_str(str_buf); + + index_prod_str = 0U; + } + } else { + if (index_serial_str) { + if (USBH_OK == usbh_strdesc_get (uhost, + uhost->dev_prop.dev_desc.iSerialNumber, + str_buf, + 0xFFU)) { + uhost->usr_cb->dev_seral_str(str_buf); + uhost->enum_state = ENUM_SET_CONFIGURATION; + index_serial_str = 0U; + } + } else { + uhost->enum_state = ENUM_SET_CONFIGURATION; + } + } + } + break; + + case ENUM_SET_CONFIGURATION: + if (USBH_OK == usbh_setcfg (uhost, (uint16_t)uhost->dev_prop.cfg_desc_set.cfg_desc.bConfigurationValue)) { + uhost->enum_state = ENUM_DEV_CONFIGURED; + } + break; + + case ENUM_DEV_CONFIGURED: + status = USBH_OK; + break; + + default: + break; + } + + return status; +} + +#if USB_LOW_POWER + +/*! + \brief handles the USB resume from suspend mode + \param[in] udev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_resume(usb_core_driver *udev) +{ + __IO uint32_t hprt = 0U; + + /* switch-on the clocks */ + *udev->regs.PWRCLKCTL &= ~PWRCLKCTL_SUCLK; + + *udev->regs.PWRCLKCTL &= ~PWRCLKCTL_SHCLK; + + hprt = usb_port_read(udev); + + hprt &= ~HPCS_PSP; + hprt |= HPCS_PREM; + + *udev->regs.HPCS = hprt; + + usb_mdelay (20U); + + hprt &= ~HPCS_PREM; + + *udev->regs.HPCS = hprt; +} + +/*! + \brief handles the USB enter to suspend mode + \param[in] udev: pointer to selected USB device + \param[out] none + \retval none +*/ +static void usb_hwp_suspend(usb_core_driver *udev) +{ + __IO uint32_t hprt = 0U; + + hprt = usb_port_read(udev); + + hprt |= HPCS_PSP; + + *udev->regs.HPCS = hprt; + + /* switch-off the clocks */ + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SUCLK; + + *udev->regs.PWRCLKCTL |= PWRCLKCTL_SHCLK; +} + +#endif /* USB_LOW_POWER */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_enum.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_enum.c new file mode 100644 index 00000000..a5c81014 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_enum.c @@ -0,0 +1,693 @@ +/*! + \file usbh_enum.c + \brief USB host mode enumeration driver + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" +#include "usbh_transc.h" +#include "usbh_enum.h" + +/* local function prototypes ('static') */ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len); +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf); +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf); +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf); +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf); +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len); + +/*! + \brief configure USB control status parameters + \param[in] uhost: pointer to USB host + \param[in] buf: control transfer data buffer pointer + \param[in] len: length of the data buffer + \param[out] none + \retval none +*/ +void usbh_ctlstate_config (usbh_host *uhost, uint8_t *buf, uint16_t len) +{ + /* prepare the transactions */ + uhost->control.buf = buf; + uhost->control.ctl_len = len; + + uhost->control.ctl_state = CTL_SETUP; +} + +/*! + \brief get device descriptor from the USB device + \param[in] uhost: pointer to USB host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_devdesc_get (usbh_host *uhost, uint8_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_DEV), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, (uint16_t)len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_devdesc_parse (&uhost->dev_prop.dev_desc, uhost->dev_prop.data, (uint16_t)len); + } + + return status; +} + +/*! + \brief get configuration descriptor from the USB device + \param[in] uhost: pointer to USB host + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_cfgdesc_get (usbh_host *uhost, uint16_t len) +{ + uint8_t *pdata = NULL; + + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + +#if (USBH_CFG_DESC_KEEP == 1U) + pdata = uhost->dev_prop.cfgdesc_rawdata; +#else + pdata = uhost->dev_prop.data; +#endif /* (USBH_CFG_DESC_KEEP == 1U) */ + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_CONFIG), + .wIndex = 0U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, pdata, len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + if (len <= USB_CFG_DESC_LEN) { + usbh_cfgdesc_parse (&uhost->dev_prop.cfg_desc_set.cfg_desc, pdata); + } else { + usbh_cfgset_parse (&uhost->dev_prop, pdata); + } + } + + return status; +} + +/*! + \brief get string descriptor from the USB device + \param[in] uhost: pointer to USB host + \param[in] str_index: index for the string descriptor + \param[in] buf: buffer pointer to the string descriptor + \param[in] len: length of the descriptor + \param[out] none + \retval operation status +*/ +usbh_status usbh_strdesc_get (usbh_host *uhost, + uint8_t str_index, + uint8_t *buf, + uint16_t len) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_IN | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_GET_DESCRIPTOR, + .wValue = USBH_DESC(USB_DESCTYPE_STR) | str_index, + .wIndex = 0x0409U, + .wLength = len + }; + + usbh_ctlstate_config (uhost, uhost->dev_prop.data, len); + } + + status = usbh_ctl_handler (uhost); + + if (USBH_OK == status) { + /* commands successfully sent and response received */ + usbh_strdesc_parse (uhost->dev_prop.data, buf, len); + } + + return status; +} + +/*! + \brief set the address to the connected device + \param[in] uhost: pointer to USB host + \param[in] dev_addr: device address to assign + \param[out] none + \retval operation status +*/ +usbh_status usbh_setaddress (usbh_host *uhost, uint8_t dev_addr) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_ADDRESS, + .wValue = (uint16_t)dev_addr, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the configuration value to the connected device + \param[in] uhost: pointer to USB host + \param[in] config_index: configuration value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setcfg (usbh_host *uhost, uint16_t config_index) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_CONFIGURATION, + .wValue = config_index, + .wIndex = 0U, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] uhost: pointer to USB host + \param[in] itf_num: interface number + \param[in] set: alternated setting value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setinterface (usbh_host *uhost, uint8_t itf_num, uint8_t set) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_ITF | USB_REQTYPE_STRD, + .bRequest = USB_SET_INTERFACE, + .wValue = set, + .wIndex = itf_num, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief set the interface value to the connected device + \param[in] uhost: pointer to USB host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_setdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_SET_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief clear the interface value to the connected device + \param[in] uhost: pointer to USB host + \param[in] feature_selector: feature selector + \param[in] windex: index value + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrdevfeature (usbh_host *uhost, uint8_t feature_selector, uint16_t windex) +{ + usbh_status status = USBH_BUSY; + + usbh_control *usb_ctl = &uhost->control; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_DEV | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = feature_selector, + .wIndex = windex, + .wLength = 0U + }; + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief clear or disable a specific feature + \param[in] uhost: pointer to USB host + \param[in] ep_addr: endpoint address + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_clrfeature (usbh_host *uhost, uint8_t ep_addr, uint8_t pp_num) +{ + usbh_status status = USBH_BUSY; + usbh_control *usb_ctl = &uhost->control; + usb_core_driver *udev = (usb_core_driver *)uhost->data; + + if (CTL_IDLE == usb_ctl->ctl_state) { + usb_ctl->setup.req = (usb_req) { + .bmRequestType = USB_TRX_OUT | USB_RECPTYPE_EP | USB_REQTYPE_STRD, + .bRequest = USB_CLEAR_FEATURE, + .wValue = FEATURE_SELECTOR_EP, + .wIndex = ep_addr, + .wLength = 0U + }; + + if (EP_ID(ep_addr) == udev->host.pipe[pp_num].ep.num) { + usbh_pipe_toggle_set(udev, pp_num, 0U); + } else { + return USBH_FAIL; + } + + usbh_ctlstate_config (uhost, NULL, 0U); + } + + status = usbh_ctl_handler (uhost); + + return status; +} + +/*! + \brief get the next descriptor header + \param[in] pbuf: pointer to buffer where the configuration descriptor set is available + \param[in] ptr: data pointer inside the configuration descriptor set + \param[out] none + \retval return descriptor header +*/ +usb_desc_header *usbh_nextdesc_get (uint8_t *pbuf, uint16_t *ptr) +{ + usb_desc_header *pnext; + + *ptr += ((usb_desc_header *)pbuf)->bLength; + + pnext = (usb_desc_header *)((uint8_t *)pbuf + ((usb_desc_header *)pbuf)->bLength); + + return (pnext); +} + +/*! + \brief get the next descriptor header + \param[in] udev: pointer to device property + \param[in] interface: interface number + \param[out] none + \retval operation status +*/ +usbh_status usbh_interface_select (usb_dev_prop *udev, uint8_t interface) +{ + usbh_status status = USBH_OK; + + if (interface < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + udev->cur_itf = interface; + } else { + status = USBH_FAIL; + } + + return status; +} + +/*! + \brief find the interface index for a specific class + \param[in] udev: pointer to device property + \param[in] main_class: class code + \param[in] sub_class: subclass code + \param[in] protocol: Protocol code + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interface_find (usb_dev_prop *udev, uint8_t main_class, uint8_t sub_class, uint8_t protocol) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < udev->cfg_desc_set.cfg_desc.bNumInterfaces) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][0].itf_desc; + + if (((pif->bInterfaceClass == main_class) || (main_class == 0xFFU))&& + ((pif->bInterfaceSubClass == sub_class) || (sub_class == 0xFFU))&& + ((pif->bInterfaceProtocol == protocol) || (protocol == 0xFFU))) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief find the interface index for a specific class interface and alternate setting number + \param[in] udev: pointer to device property + \param[in] interface_number: interface number + \param[in] alt_settings: alternate setting number + \param[out] none + \retval interface index in the configuration structure + \note interface index 0xFF means interface index not found +*/ +uint8_t usbh_interfaceindex_find (usb_dev_prop *udev, uint8_t interface_number, uint8_t alt_settings) +{ + usb_desc_itf *pif; + + uint8_t if_ix = 0U; + + pif = (usb_desc_itf *)0; + + while (if_ix < USBH_MAX_INTERFACES_NUM) { + pif = &udev->cfg_desc_set.itf_desc_set[if_ix][alt_settings].itf_desc; + + if ((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings)) { + return if_ix; + } + + if_ix++; + } + + return 0xFFU; +} + +/*! + \brief parse the device descriptor + \param[in] dev_desc: pointer to USB device descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_devdesc_parse (usb_desc_dev *dev_desc, uint8_t *buf, uint16_t len) +{ + *dev_desc = (usb_desc_dev) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bcdUSB = BYTE_SWAP(buf + 2U), + .bDeviceClass = *(uint8_t *)(buf + 4U), + .bDeviceSubClass = *(uint8_t *)(buf + 5U), + .bDeviceProtocol = *(uint8_t *)(buf + 6U), + .bMaxPacketSize0 = *(uint8_t *)(buf + 7U) + }; + + if (len > 8U) { + /* for 1st time after device connection, host may issue only 8 bytes for device descriptor length */ + dev_desc->idVendor = BYTE_SWAP(buf + 8U); + dev_desc->idProduct = BYTE_SWAP(buf + 10U); + dev_desc->bcdDevice = BYTE_SWAP(buf + 12U); + dev_desc->iManufacturer = *(uint8_t *)(buf + 14U); + dev_desc->iProduct = *(uint8_t *)(buf + 15U); + dev_desc->iSerialNumber = *(uint8_t *)(buf + 16U); + dev_desc->bNumberConfigurations = *(uint8_t *)(buf + 17U); + } +} + +/*! + \brief parse the configuration descriptor + \param[in] cfg_desc: pointer to USB configuration descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgdesc_parse (usb_desc_config *cfg_desc, uint8_t *buf) +{ + /* parse configuration descriptor */ + *cfg_desc = (usb_desc_config) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .wTotalLength = BYTE_SWAP(buf + 2U), + .bNumInterfaces = *(uint8_t *)(buf + 4U), + .bConfigurationValue = *(uint8_t *)(buf + 5U), + .iConfiguration = *(uint8_t *)(buf + 6U), + .bmAttributes = *(uint8_t *)(buf + 7U), + .bMaxPower = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the configuration descriptor set + \param[in] udev: pointer to device property + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_cfgset_parse (usb_dev_prop *udev, uint8_t *buf) +{ + usb_desc_ep *ep = NULL; + usb_desc_itf_set *itf = NULL; + usb_desc_itf itf_value; + usb_desc_config *cfg = NULL; + + usb_desc_header *pdesc = (usb_desc_header *)buf; + + uint8_t itf_index = 0U, ep_index = 0U, alt_setting = 0U; + uint8_t pre_itf_index = 0U; + uint16_t ptr; + + /* parse configuration descriptor */ + usbh_cfgdesc_parse (&udev->cfg_desc_set.cfg_desc, buf); + cfg = &udev->cfg_desc_set.cfg_desc; + ptr = USB_CFG_DESC_LEN; + + if (cfg->bNumInterfaces > USBH_MAX_INTERFACES_NUM) { + return; + } + + while (ptr < cfg->wTotalLength) { + pdesc = usbh_nextdesc_get ((uint8_t *)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_ITF) { + itf_index = *(((uint8_t *)pdesc) + 2U); + + if (pre_itf_index != itf_index) { + alt_setting = 0U; + } + + itf = &udev->cfg_desc_set.itf_desc_set[itf_index][alt_setting]; + + alt_setting++; + + if ((*((uint8_t *)pdesc + 3U)) < 3U) { + usbh_itfdesc_parse (&itf_value, (uint8_t *)pdesc); + + /* parse endpoint descriptors relative to the current interface */ + if (itf_value.bNumEndpoints > USBH_MAX_EP_NUM) { + return; + } + + usbh_itfdesc_parse (&itf->itf_desc, (uint8_t *)&itf_value); + + /* store the previous interface index */ + pre_itf_index = itf_index; + + if (0U == itf_value.bNumEndpoints) { + continue; + } + + for (ep_index = 0U; ep_index < itf_value.bNumEndpoints; ) { + pdesc = usbh_nextdesc_get ((void*)pdesc, &ptr); + + if (pdesc->bDescriptorType == USB_DESCTYPE_EP) { + ep = &itf->ep_desc[ep_index]; + + usbh_epdesc_parse (ep, (uint8_t *)pdesc); + + ep_index++; + } + } + } + } + } +} + +/*! + \brief parse the interface descriptor + \param[in] itf_desc: pointer to USB interface descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_itfdesc_parse (usb_desc_itf *itf_desc, uint8_t *buf) +{ + *itf_desc = (usb_desc_itf) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U), + }, + + .bInterfaceNumber = *(uint8_t *)(buf + 2U), + .bAlternateSetting = *(uint8_t *)(buf + 3U), + .bNumEndpoints = *(uint8_t *)(buf + 4U), + .bInterfaceClass = *(uint8_t *)(buf + 5U), + .bInterfaceSubClass = *(uint8_t *)(buf + 6U), + .bInterfaceProtocol = *(uint8_t *)(buf + 7U), + .iInterface = *(uint8_t *)(buf + 8U) + }; +} + +/*! + \brief parse the endpoint descriptor + \param[in] ep_desc: pointer to USB endpoint descriptor buffer + \param[in] buf: pointer to the source descriptor buffer + \param[out] none + \retval none +*/ +static void usbh_epdesc_parse (usb_desc_ep *ep_desc, uint8_t *buf) +{ + *ep_desc = (usb_desc_ep) { + .header = { + .bLength = *(uint8_t *)(buf + 0U), + .bDescriptorType = *(uint8_t *)(buf + 1U) + }, + + .bEndpointAddress = *(uint8_t *)(buf + 2U), + .bmAttributes = *(uint8_t *)(buf + 3U), + .wMaxPacketSize = BYTE_SWAP(buf + 4U), + .bInterval = *(uint8_t *)(buf + 6U) + }; +} + +/*! + \brief parse the string descriptor + \param[in] psrc: source pointer containing the descriptor data + \param[in] pdest: destination address pointer + \param[in] len: length of the descriptor + \param[out] none + \retval none +*/ +static void usbh_strdesc_parse (uint8_t *psrc, uint8_t *pdest, uint16_t len) +{ + uint16_t str_len = 0U, index = 0U; + + /* the unicode string descriptor is not NULL-terminated. The string length is + * computed by substracting two from the value of the first byte of the descriptor. + */ + + /* check which is lower size, the size of string or the length of bytes read from the device */ + if (USB_DESCTYPE_STR == psrc[1]) { + /* make sure the descriptor is string type */ + + /* psrc[0] contains size of descriptor, subtract 2 to get the length of string */ + str_len = USB_MIN((uint16_t)psrc[0] - 2U, len); + + psrc += 2U; /* adjust the offset ignoring the string length and descriptor type */ + + for(index = 0U; index < str_len; index += 2U) { + /* copy only the string and ignore the unicode id, hence add the source */ + *pdest = psrc[index]; + + pdest++; + } + + *pdest = 0U; /* mark end of string */ + } +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_pipe.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_pipe.c new file mode 100644 index 00000000..933bf806 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_pipe.c @@ -0,0 +1,181 @@ +/*! + \file usbh_pipe.c + \brief USB host mode pipe operation driver + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "usbh_pipe.h" + +/* local function prototypes ('static') */ +static uint16_t usbh_freepipe_get (usb_core_driver *udev); + +/*! + \brief create a pipe + \param[in] udev: pointer to USB core instance + \param[in] dev: USB device + \param[in] pp_num: pipe number + \param[in] ep_type: endpoint type + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_create (usb_core_driver *udev, + usb_dev_prop *dev, + uint8_t pp_num, + uint8_t ep_type, + uint16_t ep_mpl) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->dev_addr = dev->addr; + pp->dev_speed = dev->speed; + pp->ep.type = ep_type; + pp->ep.mps = ep_mpl; + + if ((USB_EPTYPE_BULK == pp->ep.type) || (USB_EPTYPE_CTRL == pp->ep.type)) { + pp->supp_ping = (uint8_t)(pp->dev_speed == PORT_SPEED_HIGH); + } + + usb_pipe_init (udev, pp_num); + + return HP_OK; +} + +/*! + \brief modify a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[in] dev_addr: device address + \param[in] dev_speed: device speed + \param[in] ep_mpl: endpoint max packet length + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_update (usb_core_driver *udev, + uint8_t pp_num, + uint8_t dev_addr, + uint32_t dev_speed, + uint16_t ep_mpl) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + if ((pp->dev_addr != dev_addr) && (dev_addr)) { + pp->dev_addr = dev_addr; + } + + if ((pp->dev_speed != dev_speed) && (dev_speed)) { + pp->dev_speed = dev_speed; + + if ((USB_EPTYPE_BULK == pp->ep.type) || (USB_EPTYPE_CTRL == pp->ep.type)) { + pp->supp_ping = (uint8_t)(pp->dev_speed == PORT_SPEED_HIGH); + } + } + + if ((pp->ep.mps != ep_mpl) && (ep_mpl)) { + pp->ep.mps = ep_mpl; + } + + usb_pipe_init (udev, pp_num); + + return HP_OK; +} + +/*! + \brief allocate a new pipe + \param[in] udev: pointer to USB core instance + \param[in] ep_addr: endpoint address + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_allocate (usb_core_driver *udev, uint8_t ep_addr) +{ + uint16_t pp_num = usbh_freepipe_get (udev); + + if (HP_ERROR != pp_num) { + udev->host.pipe[pp_num].in_used = 1U; + udev->host.pipe[pp_num].ep.dir = EP_DIR(ep_addr); + udev->host.pipe[pp_num].ep.num = EP_ID(ep_addr); + } + + return (uint8_t)pp_num; +} + +/*! + \brief free a pipe + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_free (usb_core_driver *udev, uint8_t pp_num) +{ + if (pp_num < HP_MAX) { + udev->host.pipe[pp_num].in_used = 0U; + } + + return USBH_OK; +} + +/*! + \brief delete all USB host pipe + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +uint8_t usbh_pipe_delete (usb_core_driver *udev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 2U; pp_num < HP_MAX; pp_num++) { + udev->host.pipe[pp_num] = (usb_pipe) {0}; + } + + return USBH_OK; +} + +/*! + \brief get a free pipe number for allocation + \param[in] udev: pointer to USB core instance + \param[out] none + \retval operation status +*/ +static uint16_t usbh_freepipe_get (usb_core_driver *udev) +{ + uint8_t pp_num = 0U; + + for (pp_num = 0U; pp_num < HP_MAX; pp_num++) { + if (0U == udev->host.pipe[pp_num].in_used) { + return (uint16_t)pp_num; + } + } + + return HP_ERROR; +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_transc.c b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_transc.c new file mode 100644 index 00000000..053e6ac6 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/host/core/Source/usbh_transc.c @@ -0,0 +1,370 @@ +/*! + \file usbh_transc.c + \brief USB host mode transactions driver + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#include "drv_usb_hw.h" +#include "usbh_pipe.h" +#include "usbh_transc.h" + +/* local function prototypes ('static') */ +static usb_urb_state usbh_urb_wait (usbh_host *uhost, uint8_t pp_num, uint32_t wait_time); +static void usbh_setup_transc (usbh_host *uhost); +static void usbh_data_in_transc (usbh_host *uhost); +static void usbh_data_out_transc (usbh_host *uhost); +static void usbh_status_in_transc (usbh_host *uhost); +static void usbh_status_out_transc (usbh_host *uhost); +static uint32_t usbh_request_submit (usb_core_driver *udev, uint8_t pp_num); + +/*! + \brief send the setup packet to the USB device + \param[in] udev: pointer to USB core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctlsetup_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->DPID = PIPE_DPID_SETUP; + pp->xfer_buf = buf; + pp->xfer_len = USB_SETUP_PACKET_LEN; + + return (usbh_status)usbh_request_submit (udev, pp_num); +} + +/*! + \brief send a data packet to the USB device + \param[in] udev: pointer to USB core instance + \param[in] buf: data buffer which will be sent to USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be sent + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_send (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + if (0U == len) { + pp->data_toggle_out = 1U; + } + + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + + pp->data_toggle_out ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_out]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (udev, pp_num); + + return USBH_OK; +} + +/*! + \brief receive a data packet from the USB device + \param[in] udev: pointer to USB core instance + \param[in] buf: data buffer which will be received from USB device + \param[in] pp_num: pipe number + \param[in] len: length of the data to be received + \param[out] none + \retval operation status +*/ +usbh_status usbh_data_recev (usb_core_driver *udev, uint8_t *buf, uint8_t pp_num, uint16_t len) +{ + usb_pipe *pp = &udev->host.pipe[pp_num]; + + pp->xfer_buf = buf; + pp->xfer_len = len; + + switch (pp->ep.type) { + case USB_EPTYPE_CTRL: + pp->DPID = PIPE_DPID[1]; + break; + + case USB_EPTYPE_INTR: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + + /* toggle DATA PID */ + pp->data_toggle_in ^= 1U; + break; + + case USB_EPTYPE_BULK: + pp->DPID = PIPE_DPID[pp->data_toggle_in]; + break; + + case USB_EPTYPE_ISOC: + pp->DPID = PIPE_DPID[0]; + break; + + default: + break; + } + + usbh_request_submit (udev, pp_num); + + return USBH_OK; +} + +/*! + \brief USB control transfer handler + \param[in] uhost: pointer to USB host + \param[out] none + \retval operation status +*/ +usbh_status usbh_ctl_handler (usbh_host *uhost) +{ + usbh_status status = USBH_BUSY; + + switch (uhost->control.ctl_state) { + case CTL_SETUP: + usbh_setup_transc (uhost); + break; + + case CTL_DATA_IN: + usbh_data_in_transc (uhost); + break; + + case CTL_DATA_OUT: + usbh_data_out_transc (uhost); + break; + + case CTL_STATUS_IN: + usbh_status_in_transc (uhost); + break; + + case CTL_STATUS_OUT: + usbh_status_out_transc (uhost); + break; + + case CTL_FINISH: + uhost->control.ctl_state = CTL_IDLE; + + status = USBH_OK; + break; + + case CTL_ERROR: + if (++uhost->control.error_count <= USBH_MAX_ERROR_COUNT) { + /* do the transmission again, starting from SETUP packet */ + uhost->control.ctl_state = CTL_SETUP; + } else { + status = USBH_FAIL; + } + break; + + default: + break; + } + + return status; +} + +/*! + \brief wait for USB URB(USB request block) state + \param[in] uhost: pointer to USB host + \param[in] pp_num: pipe number + \param[in] wait_time: wait time + \param[out] none + \retval USB URB state +*/ +static usb_urb_state usbh_urb_wait (usbh_host *uhost, uint8_t pp_num, uint32_t wait_time) +{ + uint32_t timeout = 0U; + usb_urb_state urb_status = URB_IDLE; + timeout = uhost->control.timer; + + while (URB_DONE != (urb_status = usbh_urbstate_get(uhost->data, pp_num))) { + if (URB_NOTREADY == urb_status) { + break; + } else if (URB_STALL == urb_status) { + uhost->control.ctl_state = CTL_SETUP; + break; + } else if (URB_ERROR == urb_status) { + uhost->control.ctl_state = CTL_ERROR; + break; + } else if ((wait_time > 0U) && (((usb_curframe_get(uhost->data) > timeout) && ((usb_curframe_get(uhost->data) - timeout) > wait_time)) \ + || ((usb_curframe_get(uhost->data) < timeout) && ((usb_curframe_get(uhost->data) + 0x3FFFU - timeout) > wait_time)))){ + /* timeout for in transfer */ + uhost->control.ctl_state = CTL_ERROR; + break; + } else { + /* no operation, just wait */ + } + } + + return urb_status; +} + +/*! + \brief USB setup transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_setup_transc (usbh_host *uhost) +{ + /* send a SETUP packet */ + usbh_ctlsetup_send (uhost->data, + uhost->control.setup.data, + uhost->control.pipe_out_num); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_out_num, 0U)) { + uint8_t dir = (uhost->control.setup.req.bmRequestType & USB_TRX_MASK); + + if (uhost->control.setup.req.wLength) { + if (USB_TRX_IN == dir) { + uhost->control.ctl_state = CTL_DATA_IN; + } else { + uhost->control.ctl_state = CTL_DATA_OUT; + } + } else { + if (USB_TRX_IN == dir) { + uhost->control.ctl_state = CTL_STATUS_OUT; + } else { + uhost->control.ctl_state = CTL_STATUS_IN; + } + } + + /* set the delay timer to enable timeout for data stage completion */ + uhost->control.timer = (uint16_t)usb_curframe_get(uhost->data); + } +} + +/*! + \brief USB data IN transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_in_transc (usbh_host *uhost) +{ + usbh_data_recev (uhost->data, + uhost->control.buf, + uhost->control.pipe_in_num, + uhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_in_num, DATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_STATUS_OUT; + + } +} + +/*! + \brief USB data OUT transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_data_out_transc (usbh_host *uhost) +{ + usbh_pipe_toggle_set(uhost->data, uhost->control.pipe_out_num, 1U); + + usbh_data_send (uhost->data, + uhost->control.buf, + uhost->control.pipe_out_num, + uhost->control.ctl_len); + + if (URB_DONE == usbh_urb_wait (uhost, uhost->control.pipe_out_num, DATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_STATUS_IN; + } +} + +/*! + \brief USB status IN transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_in_transc (usbh_host *uhost) +{ + uint8_t pp_num = uhost->control.pipe_in_num; + + usbh_data_recev (uhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (uhost, pp_num, NODATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief USB status OUT transaction + \param[in] uhost: pointer to USB host + \param[out] none + \retval none +*/ +static void usbh_status_out_transc (usbh_host *uhost) +{ + uint8_t pp_num = uhost->control.pipe_out_num; + + usbh_data_send (uhost->data, NULL, pp_num, 0U); + + if (URB_DONE == usbh_urb_wait (uhost, pp_num, NODATA_STAGE_TIMEOUT)) { + uhost->control.ctl_state = CTL_FINISH; + } +} + +/*! + \brief prepare a pipe and start a transfer + \param[in] udev: pointer to USB core instance + \param[in] pp_num: pipe number + \param[out] none + \retval operation status +*/ +static uint32_t usbh_request_submit (usb_core_driver *udev, uint8_t pp_num) +{ + udev->host.pipe[pp_num].urb_state = URB_IDLE; + udev->host.pipe[pp_num].xfer_count = 0U; + + return (uint32_t)usb_pipe_xfer (udev, pp_num); +} diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/cdc/usb_cdc.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/cdc/usb_cdc.h new file mode 100644 index 00000000..c586cace --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/cdc/usb_cdc.h @@ -0,0 +1,180 @@ +/*! + \file usb_cdc.h + \brief the header file of communication device class standard + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CDC_H +#define __USB_CDC_H + +#include "usb_ch9_std.h" + +/* communications device class code */ +#define USB_CLASS_CDC 0x02U + +/* communications interface class control protocol codes */ +#define USB_CDC_PROTOCOL_NONE 0x00U +#define USB_CDC_PROTOCOL_AT 0x01U +#define USB_CDC_PROTOCOL_VENDOR 0xFFU + +/* data interface class code */ +#define USB_CLASS_DATA 0x0AU + +#define USB_DESCTYPE_CDC_ACM 0x21U +#define USB_DESCTYPE_CS_INTERFACE 0x24U + +#define USB_CDC_ACM_CONFIG_DESC_SIZE 0x43U + +/* class-specific notification codes for pstn subclasses */ +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20U + +/* class-specific request codes */ +#define SEND_ENCAPSULATED_COMMAND 0x00U +#define GET_ENCAPSULATED_RESPONSE 0x01U +#define SET_COMM_FEATURE 0x02U +#define GET_COMM_FEATURE 0x03U +#define CLEAR_COMM_FEATURE 0x04U + +#define SET_AUX_LINE_STATE 0x10U +#define SET_HOOK_STATE 0x11U +#define PULSE_SETUP 0x12U +#define SEND_PULSE 0x13U +#define SET_PULSE_TIME 0x14U +#define RING_AUX_JACK 0x15U + +#define SET_LINE_CODING 0x20U +#define GET_LINE_CODING 0x21U +#define SET_CONTROL_LINE_STATE 0x22U +#define SEND_BREAK 0x23U +#define NO_CMD 0xFFU + +#define SET_RINGER_PARMS 0x30U +#define GET_RINGER_PARMS 0x31U +#define SET_OPERATION_PARMS 0x32U +#define GET_OPERATION_PARMS 0x33U +#define SET_LINE_PARMS 0x34U +#define GET_LINE_PARMS 0x35U +#define DIAL_DIGITS 0x36U +#define SET_UNIT_PARAMETER 0x37U +#define GET_UNIT_PARAMETER 0x38U +#define CLEAR_UNIT_PARAMETER 0x39U +#define GET_PROFILE 0x3AU + +#define SET_ETHERNET_MULTICAST_FILTERS 0x40U +#define SET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x41U +#define GET_ETHERNET_POWER_MANAGEMENT_PATTERN FILTER 0x42U +#define SET_ETHERNET_PACKET_FILTER 0x43U +#define GET_ETHERNET_STATISTIC 0x44U + +#define SET_ATM_DATA_FORMAT 0x50U +#define GET_ATM_DEVICE_STATISTICS 0x51U +#define SET_ATM_DEFAULT_VC 0x52U +#define GET_ATM_VC_STATISTICS 0x53U + +/* wValue for set control line state */ +#define CDC_ACTIVATE_CARRIER_SIGNAL_RTS 0x0002U +#define CDC_DEACTIVATE_CARRIER_SIGNAL_RTS 0x0000U +#define CDC_ACTIVATE_SIGNAL_DTR 0x0001U +#define CDC_DEACTIVATE_SIGNAL_DTR 0x0000U + +/* CDC subclass code */ +enum usb_cdc_subclass { + USB_CDC_SUBCLASS_RESERVED = 0U, /*!< reserved */ + USB_CDC_SUBCLASS_DLCM, /*!< direct line control mode */ + USB_CDC_SUBCLASS_ACM, /*!< abstract control mode */ + USB_CDC_SUBCLASS_TCM, /*!< telephone control mode */ + USB_CDC_SUBCLASS_MCM, /*!< multichannel control model */ + USB_CDC_SUBCLASS_CCM, /*!< CAPI control model */ + USB_CDC_SUBCLASS_ENCM, /*!< ethernet networking control model */ + USB_CDC_SUBCLASS_ANCM /*!< ATM networking control model */ +}; + +#pragma pack(1) + +/* cdc acm line coding structure */ +typedef struct { + uint32_t dwDTERate; /*!< data terminal rate */ + uint8_t bCharFormat; /*!< stop bits */ + uint8_t bParityType; /*!< parity */ + uint8_t bDataBits; /*!< data bits */ +} acm_line; + +/* notification structure */ +typedef struct { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bNotification; /*!< communication interface class notifications */ + uint16_t wValue; /*!< value of notification */ + uint16_t wIndex; /*!< index of interface */ + uint16_t wLength; /*!< length of notification data */ +} acm_notification; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: header function descriptor */ + uint16_t bcdCDC; /*!< bcdCDC: low byte of spec release number (CDC1.10) */ +} usb_desc_header_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: call management function descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D0 is reset, D1 is ignored */ + uint8_t bDataInterface; /*!< bDataInterface: 1 interface used for call management */ +} usb_desc_call_managment_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: abstract control management descriptor */ + uint8_t bmCapabilities; /*!< bmCapabilities: D1 */ +} usb_desc_acm_func; + +typedef struct { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint8_t bDescriptorSubtype; /*!< bDescriptorSubtype: union function descriptor */ + uint8_t bMasterInterface; /*!< bMasterInterface: communication class interface */ + uint8_t bSlaveInterface0; /*!< bSlaveInterface0: data class interface */ +} usb_desc_union_func; + +#pragma pack() + +typedef struct { + usb_desc_config config; + usb_desc_itf cmd_itf; + usb_desc_header_func cdc_header; + usb_desc_call_managment_func cdc_call_managment; + usb_desc_acm_func cdc_acm; + usb_desc_union_func cdc_union; + usb_desc_ep cdc_cmd_endpoint; + usb_desc_itf cdc_data_interface; + usb_desc_ep cdc_out_endpoint; + usb_desc_ep cdc_in_endpoint; +} usb_cdc_desc_config_set; + +#endif /* __USB_CDC_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/hid/usb_hid.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/hid/usb_hid.h new file mode 100644 index 00000000..3c8adf89 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/hid/usb_hid.h @@ -0,0 +1,83 @@ +/*! + \file usb_hid.h + \brief definitions for the USB HID class + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_HID_H +#define __USB_HID_H + +#include "usb_ch9_std.h" + +#define USB_HID_CLASS 0x03U + +#define USB_DESCTYPE_HID 0x21U +#define USB_DESCTYPE_REPORT 0x22U + +/* HID subclass code */ +#define USB_HID_SUBCLASS_BOOT_ITF 0x01U + +/* HID protocol codes */ +#define USB_HID_PROTOCOL_KEYBOARD 0x01U +#define USB_HID_PROTOCOL_MOUSE 0x02U + +#define GET_REPORT 0x01U +#define GET_IDLE 0x02U +#define GET_PROTOCOL 0x03U +#define SET_REPORT 0x09U +#define SET_IDLE 0x0AU +#define SET_PROTOCOL 0x0BU + +#pragma pack(1) + +typedef struct +{ + usb_desc_header header; /*!< regular descriptor header containing the descriptor's type and length */ + + uint16_t bcdHID; /*!< BCD encoded version that the HID descriptor and device complies to */ + uint8_t bCountryCode; /*!< country code of the localized device, or zero if universal */ + uint8_t bNumDescriptors; /*!< total number of HID report descriptors for the interface */ + uint8_t bDescriptorType; /*!< type of HID report */ + uint16_t wDescriptorLength; /*!< length of the associated HID report descriptor, in bytes */ +} usb_desc_hid; + +#pragma pack() + +typedef struct +{ + usb_desc_config config; + usb_desc_itf hid_itf; + usb_desc_hid hid_vendor; + usb_desc_ep hid_epin; + usb_desc_ep hid_epout; +} usb_hid_desc_config_set; + +#endif /* __USB_HID_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/msc/msc_bbb.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/msc/msc_bbb.h new file mode 100644 index 00000000..630d908e --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/msc/msc_bbb.h @@ -0,0 +1,69 @@ +/*! + \file msc_bbb.h + \brief definitions for the USB MSC BBB(bulk/bulk/bulk) protocol + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_BBB_H +#define __MSC_BBB_H + +#include "usb_ch9_std.h" + +#define BBB_CBW_SIGNATURE 0x43425355U +#define BBB_CSW_SIGNATURE 0x53425355U +#define BBB_CBW_LENGTH 31U +#define BBB_CSW_LENGTH 13U + +typedef struct { + uint32_t dCBWSignature; + uint32_t dCBWTag; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; + uint8_t CBWCB[16]; +} msc_bbb_cbw; + +typedef struct { + uint32_t dCSWSignature; + uint32_t dCSWTag; + uint32_t dCSWDataResidue; + uint8_t bCSWStatus; +} msc_bbb_csw; + +/* CSW command status */ +enum msc_csw_status { + CSW_CMD_PASSED = 0, + CSW_CMD_FAILED, + CSW_PHASE_ERROR +}; + +#endif /* __MSC_BBB_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/msc/msc_scsi.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/msc/msc_scsi.h new file mode 100644 index 00000000..8a178c7d --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/msc/msc_scsi.h @@ -0,0 +1,117 @@ +/*! + \file msc_scsi.h + \brief definitions for the USB MSC SCSI commands + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __MSC_SCSI_H +#define __MSC_SCSI_H + +#include "usb_ch9_std.h" + +/* SCSI commands */ +#define SCSI_FORMAT_UNIT 0x04U +#define SCSI_INQUIRY 0x12U +#define SCSI_MODE_SELECT6 0x15U +#define SCSI_MODE_SELECT10 0x55U +#define SCSI_MODE_SENSE6 0x1AU +#define SCSI_READ_TOC_DATA 0x43U +#define SCSI_MODE_SENSE10 0x5AU +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1EU +#define SCSI_READ6 0x08U +#define SCSI_READ10 0x28U +#define SCSI_READ12 0xA8U +#define SCSI_READ16 0x88U + +#define SCSI_READ_CAPACITY10 0x25U +#define SCSI_READ_CAPACITY16 0x9EU + +#define SCSI_REQUEST_SENSE 0x03U +#define SCSI_START_STOP_UNIT 0x1BU +#define SCSI_TEST_UNIT_READY 0x00U +#define SCSI_WRITE6 0x0AU +#define SCSI_WRITE10 0x2AU +#define SCSI_WRITE12 0xAAU +#define SCSI_WRITE16 0x8AU + +#define SCSI_VERIFY10 0x2FU +#define SCSI_VERIFY12 0xAFU +#define SCSI_VERIFY16 0x8FU + +#define SCSI_SEND_DIAGNOSTIC 0x1DU +#define SCSI_READ_FORMAT_CAPACITIES 0x23U + +#define INVALID_CDB 0x20U +#define INVALID_FIELED_IN_COMMAND 0x24U +#define PARAMETER_LIST_LENGTH_ERROR 0x1AU +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26U +#define ADDRESS_OUT_OF_RANGE 0x21U +#define MEDIUM_NOT_PRESENT 0x3AU +#define MEDIUM_HAVE_CHANGED 0x28U +#define WRITE_PROTECTED 0x27U +#define UNRECOVERED_READ_ERROR 0x11U +#define WRITE_FAULT 0x03U + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0CU +#define READ_CAPACITY10_DATA_LEN 0x08U +#define MODE_SENSE10_DATA_LEN 0x08U +#define MODE_SENSE6_DATA_LEN 0x04U +#define READ_TOC_CMD_LEN 0x14U +#define REQUEST_SENSE_DATA_LEN 0x12U +#define STANDARD_INQUIRY_DATA_LEN 0x24U +#define BLKVFY 0x04U + +enum sense_state { + NO_SENSE = 0U, + RECOVERED_ERROR, + NOT_READY, + MEDIUM_ERROR, + HARDWARE_ERROR, + ILLEGAL_REQUEST, + UNIT_ATTENTION, + DATA_PROTECT, + BLANK_CHECK, + VENDOR_SPECIFIC, + COPY_ABORTED, + ABORTED_COMMAND, + RESERVED, + VOLUME_OVERFLOW, + MISCOMPARE +}; + +typedef struct { + uint8_t SenseKey; + uint32_t Information; + uint8_t ASC; + uint8_t ASCQ; +} msc_scsi_sense; + +#endif /* __MSC_SCSI_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/msc/usb_msc.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/msc/usb_msc.h new file mode 100644 index 00000000..4bdb2418 --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/class/msc/usb_msc.h @@ -0,0 +1,68 @@ +/*! + \file usb_msc.h + \brief definitions for the USB MSC class + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_MSC_H +#define __USB_MSC_H + +#include "usb_ch9_std.h" + +/* mass storage device class code */ +#define USB_CLASS_MSC 0x08U + +/* mass storage subclass code */ +#define USB_MSC_SUBCLASS_RBC 0x01U +#define USB_MSC_SUBCLASS_ATAPI 0x02U +#define USB_MSC_SUBCLASS_UFI 0x04U +#define USB_MSC_SUBCLASS_SCSI 0x06U +#define USB_MSC_SUBCLASS_LOCKABLE 0x07U +#define USB_MSC_SUBCLASS_IEEE1667 0x08U + +/* mass storage interface class control protocol codes */ +#define USB_MSC_PROTOCOL_CBI 0x00U +#define USB_MSC_PROTOCOL_CBI_ALT 0x01U +#define USB_MSC_PROTOCOL_BBB 0x50U + +/* mass storage request codes */ +#define USB_MSC_REQ_CODES_ADSC 0x00U +#define USB_MSC_REQ_CODES_GET 0xFCU +#define USB_MSC_REQ_CODES_PUT 0xFDU +#define USB_MSC_REQ_CODES_GML 0xFEU +#define USB_MSC_REQ_CODES_BOMSR 0xFFU + +#define BBB_GET_MAX_LUN 0xFEU +#define BBB_RESET 0xFFU + +#define SCSI_CMD_LENGTH 16U + +#endif /* __USB_MSC_H */ diff --git a/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/common/usb_ch9_std.h b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/common/usb_ch9_std.h new file mode 100644 index 00000000..ab8d275e --- /dev/null +++ b/lib-gd32/gd32f20x/GD32F20x_usbfs_library/ustd/common/usb_ch9_std.h @@ -0,0 +1,248 @@ +/*! + \file usb_ch9_std.h + \brief USB 2.0 standard defines + + \version 2023-06-30, V2.5.0, firmware for GD32F20x +*/ + +/* + Copyright (c) 2023, GigaDevice Semiconductor Inc. + + Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef __USB_CH9_STD_H +#define __USB_CH9_STD_H + +#include "usb_conf.h" + +#define USB_DEV_QUALIFIER_DESC_LEN 0x0AU /*!< USB device qualifier descriptor length */ +#define USB_DEV_DESC_LEN 0x12U /*!< USB device descriptor length */ +#define USB_CFG_DESC_LEN 0x09U /*!< USB configuration descriptor length */ +#define USB_ITF_DESC_LEN 0x09U /*!< USB interface descriptor length */ +#define USB_EP_DESC_LEN 0x07U /*!< USB endpoint descriptor length */ +#define USB_IAD_DESC_LEN 0x08U /*!< USB IAD descriptor length */ +#define USB_OTG_DESC_LEN 0x03U /*!< USB device OTG descriptor length */ + +#define USB_SETUP_PACKET_LEN 0x08U /*!< USB setup packet length */ + +/* bit 7 of bmRequestType: data phase transfer direction */ +#define USB_TRX_MASK 0x80U /*!< USB transfer direction mask */ +#define USB_TRX_OUT 0x00U /*!< USB transfer OUT direction */ +#define USB_TRX_IN 0x80U /*!< USB transfer IN direction */ + +/* bit 6..5 of bmRequestType: request type */ +#define USB_REQTYPE_STRD 0x00U /*!< USB standard request */ +#define USB_REQTYPE_CLASS 0x20U /*!< USB class request */ +#define USB_REQTYPE_VENDOR 0x40U /*!< USB vendor request */ +#define USB_REQTYPE_MASK 0x60U /*!< USB request mask */ + +#define USBD_BUS_POWERED 0x00U /*!< USB bus power supply */ +#define USBD_SELF_POWERED 0x01U /*!< USB self power supply */ + +#define USB_STATUS_REMOTE_WAKEUP 2U /*!< USB is in remote wakeup status */ +#define USB_STATUS_SELF_POWERED 1U /*!< USB is in self powered status */ + +/* bit 4..0 of bmRequestType: recipient type */ +enum _usb_recp_type { + USB_RECPTYPE_DEV = 0x0U, /*!< USB device request type */ + USB_RECPTYPE_ITF = 0x1U, /*!< USB interface request type */ + USB_RECPTYPE_EP = 0x2U, /*!< USB endpoint request type */ + USB_RECPTYPE_MASK = 0x3U /*!< USB request type mask */ +}; + +/* bRequest value */ +enum _usb_request { + USB_GET_STATUS = 0x0U, /*!< USB get status request */ + USB_CLEAR_FEATURE = 0x1U, /*!< USB clear feature request */ + USB_RESERVED2 = 0x2U, + USB_SET_FEATURE = 0x3U, /*!< USB set feature request */ + USB_RESERVED4 = 0x4U, + USB_SET_ADDRESS = 0x5U, /*!< USB set address request */ + USB_GET_DESCRIPTOR = 0x6U, /*!< USB get descriptor request */ + USB_SET_DESCRIPTOR = 0x7U, /*!< USB set descriptor request */ + USB_GET_CONFIGURATION = 0x8U, /*!< USB get configuration request */ + USB_SET_CONFIGURATION = 0x9U, /*!< USB set configuration request */ + USB_GET_INTERFACE = 0xAU, /*!< USB get interface request */ + USB_SET_INTERFACE = 0xBU, /*!< USB set interface request */ + USB_SYNCH_FRAME = 0xCU /*!< USB synchronize frame request */ +}; + +/* descriptor types of USB specifications */ +enum _usb_desctype { + USB_DESCTYPE_DEV = 0x1U, /*!< USB device descriptor type */ + USB_DESCTYPE_CONFIG = 0x2U, /*!< USB configuration descriptor type */ + USB_DESCTYPE_STR = 0x3U, /*!< USB string descriptor type */ + USB_DESCTYPE_ITF = 0x4U, /*!< USB interface descriptor type */ + USB_DESCTYPE_EP = 0x5U, /*!< USB endpoint descriptor type */ + USB_DESCTYPE_DEV_QUALIFIER = 0x6U, /*!< USB device qualifier descriptor type */ + USB_DESCTYPE_OTHER_SPD_CONFIG = 0x7U, /*!< USB other speed configuration descriptor type */ + USB_DESCTYPE_ITF_POWER = 0x8U, /*!< USB interface power descriptor type */ + USB_DESCTYPE_IAD = 0xBU, /*!< USB interface association descriptor type */ + USB_DESCTYPE_BOS = 0xFU /*!< USB BOS descriptor type */ +}; + +/* USB Endpoint Descriptor bmAttributes bit definitions */ +/* bits 1..0 : transfer type */ +enum _usbx_type { + USB_EP_ATTR_CTL = 0x0U, /*!< USB control transfer type */ + USB_EP_ATTR_ISO = 0x1U, /*!< USB Isochronous transfer type */ + USB_EP_ATTR_BULK = 0x2U, /*!< USB Bulk transfer type */ + USB_EP_ATTR_INT = 0x3U /*!< USB Interrupt transfer type */ +}; + +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_NOSYNC 0x00U /*!< No Synchronization */ +#define USB_EP_ATTR_ASYNC 0x04U /*!< Asynchronous */ +#define USB_EP_ATTR_ADAPTIVE 0x08U /*!< Adaptive */ +#define USB_EP_ATTR_SYNC 0x0CU /*!< Synchronous */ +#define USB_EP_ATTR_SYNCTYPE 0x0CU /*!< Synchronous type */ + +/* bits 5..4 : usage type (only if ISOCHRONOUS) */ +#define USB_EP_ATTR_DATA 0x00U /*!< Data endpoint */ +#define USB_EP_ATTR_FEEDBACK 0x10U /*!< Feedback endpoint */ +#define USB_EP_ATTR_IMPLICIT_FEEDBACK_DATA 0x20U /*!< Implicit feedback Data endpoint */ +#define USB_EP_ATTR_USAGETYPE 0x30U /*!< Usage type */ + +/* endpoint max packet size bits12..11 */ +#define USB_EP_MPS_ADD_0 (0x00 << 11) /*!< None(1 transaction per microframe */ +#define USB_EP_MPS_ADD_1 (0x01 << 11) /*!< 1 additional(2 transaction per microframe */ +#define USB_EP_MPS_ADD_2 (0x02 << 11) /*!< 2 additional(3 transaction per microframe */ + +#define FEATURE_SELECTOR_EP 0x00U /*!< USB endpoint feature selector */ +#define FEATURE_SELECTOR_DEV 0x01U /*!< USB device feature selector */ +#define FEATURE_SELECTOR_REMOTEWAKEUP 0x01U /*!< USB feature selector remote wakeup */ + +#define BYTE_SWAP(addr) (((uint16_t)(*((uint8_t *)(addr)))) + \ + (uint16_t)(((uint16_t)(*(((uint8_t *)(addr)) + 1U))) << 8U)) + +#define BYTE_LOW(x) ((uint8_t)((x) & 0x00FFU)) +#define BYTE_HIGH(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) + +#define USB_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define USB_DEFAULT_CONFIG 0U + +/* USB classes */ +#define USB_CLASS_HID 0x03U /*!< USB HID class */ +#define USB_CLASS_MSC 0x08U /*!< USB MSC class */ + +/* use the following values when USB host need to get descriptor */ +#define USBH_DESC(x) (((x)<< 8U) & 0xFF00U) + +/* as per USB specs 9.2.6.4 :standard request with data request timeout: 5sec + standard request with no data stage timeout : 50ms */ +#define DATA_STAGE_TIMEOUT 5000U /*!< USB data stage timeout*/ +#define NODATA_STAGE_TIMEOUT 50U /*!< USB no data stage timeout*/ + +#pragma pack(1) + +/* USB standard device request structure */ +typedef struct _usb_req { + uint8_t bmRequestType; /*!< type of request */ + uint8_t bRequest; /*!< request of setup packet */ + uint16_t wValue; /*!< value of setup packet */ + uint16_t wIndex; /*!< index of setup packet */ + uint16_t wLength; /*!< length of setup packet */ +} usb_req; + +/* USB setup packet define */ +typedef union _usb_setup { + uint8_t data[8]; + + usb_req req; +} usb_setup; + +/* USB descriptor defines */ + +typedef struct _usb_desc_header { + uint8_t bLength; /*!< size of the descriptor */ + uint8_t bDescriptorType; /*!< type of the descriptor */ +} usb_desc_header; + +typedef struct _usb_desc_dev { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t bcdUSB; /*!< BCD of the supported USB specification */ + uint8_t bDeviceClass; /*!< USB device class */ + uint8_t bDeviceSubClass; /*!< USB device subclass */ + uint8_t bDeviceProtocol; /*!< USB device protocol */ + uint8_t bMaxPacketSize0; /*!< size of the control (address 0) endpoint's bank in bytes */ + uint16_t idVendor; /*!< vendor ID for the USB product */ + uint16_t idProduct; /*!< unique product ID for the USB product */ + uint16_t bcdDevice; /*!< product release (version) number */ + uint8_t iManufacturer; /*!< string index for the manufacturer's name */ + uint8_t iProduct; /*!< string index for the product name/details */ + uint8_t iSerialNumber; /*!< string index for the product's globally unique hexadecimal serial number */ + uint8_t bNumberConfigurations; /*!< total number of configurations supported by the device */ +} usb_desc_dev; + +typedef struct _usb_desc_config { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint16_t wTotalLength; /*!< size of the configuration descriptor header,and all sub descriptors inside the configuration */ + uint8_t bNumInterfaces; /*!< total number of interfaces in the configuration */ + uint8_t bConfigurationValue; /*!< configuration index of the current configuration */ + uint8_t iConfiguration; /*!< index of a string descriptor describing the configuration */ + uint8_t bmAttributes; /*!< configuration attributes */ + uint8_t bMaxPower; /*!< maximum power consumption of the device while in the current configuration */ +} usb_desc_config; + +typedef struct _usb_desc_itf { + usb_desc_header header; /*!< descriptor header, including type and size */ + + uint8_t bInterfaceNumber; /*!< index of the interface in the current configuration */ + uint8_t bAlternateSetting; /*!< alternate setting for the interface number */ + uint8_t bNumEndpoints; /*!< total number of endpoints in the interface */ + uint8_t bInterfaceClass; /*!< interface class ID */ + uint8_t bInterfaceSubClass; /*!< interface subclass ID */ + uint8_t bInterfaceProtocol; /*!< interface protocol ID */ + uint8_t iInterface; /*!< index of the string descriptor describing the interface */ +} usb_desc_itf; + +typedef struct _usb_desc_ep { + usb_desc_header header; /*!< descriptor header, including type and size. */ + + uint8_t bEndpointAddress; /*!< logical address of the endpoint */ + uint8_t bmAttributes; /*!< endpoint attributes */ + uint16_t wMaxPacketSize; /*!< size of the endpoint bank, in bytes */ + uint8_t bInterval; /*!< polling interval in milliseconds for the endpoint if it is an INTERRUPT or ISOCHRONOUS type */ +} usb_desc_ep; + +typedef struct _usb_desc_LANGID { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t wLANGID; /*!< LANGID code */ +} usb_desc_LANGID; + +typedef struct _usb_desc_str { + usb_desc_header header; /*!< descriptor header, including type and size. */ + uint16_t unicode_string[128]; /*!< unicode string data */ +} usb_desc_str; + +#pragma pack() + +/* compute string descriptor length */ +#define USB_STRING_LEN(unicode_chars) (sizeof(usb_desc_header) + ((unicode_chars) << 1U)) + +#endif /* __USB_CH9_STD_H */ diff --git a/lib-gd32/include/FreeRTOSConfig.h b/lib-gd32/include/FreeRTOSConfig.h new file mode 100644 index 00000000..28b79c84 --- /dev/null +++ b/lib-gd32/include/FreeRTOSConfig.h @@ -0,0 +1,164 @@ +/* + FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS 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. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__TASKING__) || defined(__GNUC__) +#include +extern uint32_t SystemCoreClock; +#endif + + +#define configUSE_PREEMPTION 1 +#define configCPU_CLOCK_HZ ( SystemCoreClock ) +#define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) +#define configMAX_PRIORITIES ( 8 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 30 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 16 ) +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configUSE_APPLICATION_TASK_TAG 0 + + +/* hook function related definitions */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_MALLOC_FAILED_HOOK 0 + +/* run time and task stats gathering related definitions */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TRACE_FACILITY 1 + + +/* co-routine definitions */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* software timer definitions */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( 2 ) +#define configTIMER_QUEUE_LENGTH 10 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +/* set to 1 to include the API function, or 0 to exclude the API function */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 + + + + +/* Cortex-M specific definitions */ +#ifdef __NVIC_PRIO_BITS + /* __NVIC_PRIO_BITS will be specified when CMSIS is being used. */ + #define configPRIO_BITS __NVIC_PRIO_BITS +#else + #define configPRIO_BITS 4 /* 15 priority levels */ +#endif + +/* the lowest interrupt priority that can be used in a call to a "set priority" function */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. Do not call +interrupt safe freertos api functions from any interrupt that has a higher +priority than this! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2 + +/* interrupt priorities used by the kernel port layer itself */ +#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) +/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) + + + + +/* normal assert() semantics without relying on the provision of an assert.h header file */ +#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); } + +/* map the FreeRTOS port interrupt handlers to CMSIS standard names */ +#define vPortSVCHandler SVC_Handler +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler + + + +#endif /* FREERTOS_CONFIG_H */ diff --git a/lib-gd32/include/board/bw_opidmx4.h b/lib-gd32/include/board/bw_opidmx4.h index 2d93a0dd..999a89cc 100644 --- a/lib-gd32/include/board/bw_opidmx4.h +++ b/lib-gd32/include/board/bw_opidmx4.h @@ -2,7 +2,7 @@ * @file bw_opidmx4.h * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,6 +38,8 @@ # error USART0 is used for console #endif +#include + /** * LEDs */ @@ -75,30 +77,32 @@ */ #define I2C0_REMAP -#define I2C_REMAP GPIO_I2C0_REMAP -#define I2C_PERIPH I2C0_PERIPH -#define I2C_RCU_CLK I2C0_RCU_CLK -#define I2C_GPIO_SCL_PORT I2C0_SCL_GPIOx -#define I2C_GPIO_SCL_CLK I2C0_SCL_RCU_GPIOx -#define I2C_GPIO_SDA_PORT I2C0_SDA_GPIOx -#define I2C_GPIO_SDA_CLK I2C0_SDA_RCU_GPIOx -#define I2C_SCL_PIN I2C0_SCL_GPIO_PINx -#define I2C_SDA_PIN I2C0_SDA_GPIO_PINx +#define I2C_REMAP GPIO_I2C0_REMAP +#define I2C_PERIPH I2C0_PERIPH +#define I2C_RCU_I2Cx I2C0_RCU_I2C0 +#define I2C_GPIO_AFx I2C0_GPIO_AFx +#define I2C_SCL_RCU_GPIOx I2C0_SCL_RCU_GPIOx +#define I2C_SCL_GPIOx I2C0_SCL_GPIOx +#define I2C_SCL_GPIO_PINx I2C0_SCL_GPIO_PINx +#define I2C_SDA_RCU_GPIOx I2C0_SDA_RCU_GPIOx +#define I2C_SDA_GPIOx I2C0_SDA_GPIOx +#define I2C_SDA_GPIO_PINx I2C0_SDA_GPIO_PINx /** * SPI */ #define SPI_PERIPH SPI2_PERIPH +#define SPI_RCU_SPIx SPI2_RCU_SPI2 +#define SPI_RCU_GPIOx SPI2_RCU_GPIOx +#define SPI_GPIO_AFx SPI2_GPIO_AFx +#define SPI_GPIOx SPI2_GPIOx +#define SPI_SCK_GPIO_PINx SPI2_SCK_GPIO_PINx +#define SPI_MISO_GPIO_PINx SPI2_MISO_GPIO_PINx +#define SPI_MOSI_GPIO_PINx SPI2_MOSI_GPIO_PINx #define SPI_NSS_GPIOx SPI2_NSS_GPIOx #define SPI_NSS_RCU_GPIOx SPI2_NSS_RCU_GPIOx #define SPI_NSS_GPIO_PINx SPI2_NSS_GPIO_PINx -#define SPI_RCU_CLK SPI2_RCU_CLK -#define SPI_GPIOx SPI2_GPIOx -#define SPI_RCU_GPIOx SPI2_RCU_GPIOx -#define SPI_SCK_PIN SPI2_SCK_GPIO_PINx -#define SPI_MISO_PIN SPI2_MISO_GPIO_PINx -#define SPI_MOSI_PIN SPI2_MOSI_GPIO_PINx #define SPI_DMAx SPI2_DMAx #define SPI_DMA_CHx SPI2_TX_DMA_CHx #define SPI_DMA_SUBPERIx SPI2_TX_DMA_SUBPERIx @@ -113,6 +117,7 @@ /** * Panel LEDs */ + #ifdef __cplusplus namespace hal { namespace panelled { @@ -138,9 +143,9 @@ static constexpr uint32_t PORT_A_TX = 0; * SPI flash */ -#define SPI_FLASH_CS_GPIOx GPIOB -#define SPI_FLASH_CS_RCU_GPIOx RCU_GPIOB -#define SPI_FLASH_CS_GPIO_PINx GPIO_PIN_1 +#define SPI_FLASH_CS_RCU_GPIOx RCU_GPIOB +#define SPI_FLASH_CS_GPIOx GPIOB +#define SPI_FLASH_CS_GPIO_PINx GPIO_PIN_1 /** * EXT PHY @@ -171,7 +176,7 @@ static constexpr uint32_t PORT_A_TX = 0; */ #if defined (GD32F20X_CL) -# include "mcu/gd32f20x_mcu.h" +# include "mcu/gd32f207_mcu.h" # define GD32_MCU_NAME "GD32F207RG" #elif defined (GD32F407) # include "mcu/gd32f407_mcu.h" @@ -189,15 +194,21 @@ static constexpr uint32_t PORT_A_TX = 0; #define GD32_BOARD_LED3 GD32_PORT_TO_GPIO(GD32_GPIO_PORTC, 3) #define GD32_BOARD_STATUS_LED GD32_BOARD_LED1 +/** + * LCD + */ + +#define DISPLAYTIMEOUT_GPIO GD32_PORT_TO_GPIO(GD32_GPIO_PORTA, 14) // KEY2 + /** * SPI LCD */ -#define SPI_LCD_RST_PIN GPIO_EXT_7 -#define SPI_LCD_DC_PIN GPIO_EXT_26 -#define SPI_LCD_BL_PIN GPIO_EXT_22 -#if defined(SPI_LCD_HAVE_CS_PIN) -# define SPI_LCD_CS_PIN GPIO_EXT_24 +#define SPI_LCD_RST_PIN GPIO_EXT_7 +#define SPI_LCD_DC_GPIO GPIO_EXT_26 +#define SPI_LCD_BL_GPIO GPIO_EXT_22 +#if defined(SPI_LCD_HAVE_CS_GPIO) +# define SPI_LCD_CS_GPIO GPIO_EXT_24 #endif #include "gpio_header.h" diff --git a/lib-gd32/include/board/dmx3.h b/lib-gd32/include/board/dmx3.h index fe73db40..594e39a9 100644 --- a/lib-gd32/include/board/dmx3.h +++ b/lib-gd32/include/board/dmx3.h @@ -2,7 +2,7 @@ * @file dmx3.h * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,6 +34,8 @@ # error This file should be included later #endif +#include + /** * LEDs */ @@ -71,30 +73,32 @@ */ #define I2C0_REMAP -#define I2C_REMAP GPIO_I2C0_REMAP -#define I2C_PERIPH I2C0_PERIPH -#define I2C_RCU_CLK I2C0_RCU_CLK -#define I2C_GPIO_SCL_PORT I2C0_SCL_GPIOx -#define I2C_GPIO_SCL_CLK I2C0_SCL_RCU_GPIOx -#define I2C_GPIO_SDA_PORT I2C0_SDA_GPIOx -#define I2C_GPIO_SDA_CLK I2C0_SDA_RCU_GPIOx -#define I2C_SCL_PIN I2C0_SCL_GPIO_PINx -#define I2C_SDA_PIN I2C0_SDA_GPIO_PINx +#define I2C_REMAP GPIO_I2C0_REMAP +#define I2C_PERIPH I2C0_PERIPH +#define I2C_RCU_I2Cx I2C0_RCU_I2C0 +#define I2C_GPIO_AFx I2C0_GPIO_AFx +#define I2C_SCL_RCU_GPIOx I2C0_SCL_RCU_GPIOx +#define I2C_SCL_GPIOx I2C0_SCL_GPIOx +#define I2C_SCL_GPIO_PINx I2C0_SCL_GPIO_PINx +#define I2C_SDA_RCU_GPIOx I2C0_SDA_RCU_GPIOx +#define I2C_SDA_GPIOx I2C0_SDA_GPIOx +#define I2C_SDA_GPIO_PINx I2C0_SDA_GPIO_PINx /** * SPI */ #define SPI_PERIPH SPI2_PERIPH +#define SPI_RCU_SPIx SPI2_RCU_SPI2 +#define SPI_RCU_GPIOx SPI2_RCU_GPIOx +#define SPI_GPIO_AFx SPI2_GPIO_AFx +#define SPI_GPIOx SPI2_GPIOx +#define SPI_SCK_GPIO_PINx SPI2_SCK_GPIO_PINx +#define SPI_MISO_GPIO_PINx SPI2_MISO_GPIO_PINx +#define SPI_MOSI_GPIO_PINx SPI2_MOSI_GPIO_PINx #define SPI_NSS_GPIOx SPI2_NSS_GPIOx #define SPI_NSS_RCU_GPIOx SPI2_NSS_RCU_GPIOx #define SPI_NSS_GPIO_PINx SPI2_NSS_GPIO_PINx -#define SPI_RCU_CLK SPI2_RCU_CLK -#define SPI_GPIOx SPI2_GPIOx -#define SPI_RCU_GPIOx SPI2_RCU_GPIOx -#define SPI_SCK_PIN SPI2_SCK_GPIO_PINx -#define SPI_MISO_PIN SPI2_MISO_GPIO_PINx -#define SPI_MOSI_PIN SPI2_MOSI_GPIO_PINx #define SPI_DMAx SPI2_DMAx #define SPI_DMA_CHx SPI2_TX_DMA_CHx #define SPI_DMA_SUBPERIx SPI2_TX_DMA_SUBPERIx @@ -109,6 +113,7 @@ /** * Panel LEDs */ + #ifdef __cplusplus namespace hal { namespace panelled { @@ -124,19 +129,26 @@ static constexpr uint32_t OSC_IN = 0; static constexpr uint32_t OSC_OUT = 0; static constexpr uint32_t TCNET = 0; // DMX -static constexpr uint32_t PORT_A_RX = 0; -static constexpr uint32_t PORT_A_TX = 0; +static constexpr uint32_t PORT_A_TX = (1U << 0); +static constexpr uint32_t PORT_A_RX = (1U << 8); +#define CONFIG_PANELLED_RDM_PORT +static constexpr uint32_t PORT_A_RDM = (1U << 16); } // namespace panelled } // namespace hal #endif +#define PANELLED_595_COUNT 2 +#define PANELLED_595_CS_GPIOx GPIOA +#define PANELLED_595_CS_RCU_GPIOx RCU_GPIOA +#define PANELLED_595_CS_GPIO_PINx GPIO_PIN_15 + /** * SPI flash */ -#define SPI_FLASH_CS_GPIOx GPIOB -#define SPI_FLASH_CS_RCU_GPIOx RCU_GPIOB -#define SPI_FLASH_CS_GPIO_PINx GPIO_PIN_1 +#define SPI_FLASH_CS_RCU_GPIOx RCU_GPIOB +#define SPI_FLASH_CS_GPIOx GPIOB +#define SPI_FLASH_CS_GPIO_PINx GPIO_PIN_1 /** * EXT PHY @@ -167,7 +179,7 @@ static constexpr uint32_t PORT_A_TX = 0; */ #if defined (GD32F20X_CL) -# include "mcu/gd32f20x_mcu.h" +# include "mcu/gd32f207_mcu.h" # define GD32_MCU_NAME "GD32F207RG" #elif defined (GD32F407) # include "mcu/gd32f407_mcu.h" @@ -185,15 +197,21 @@ static constexpr uint32_t PORT_A_TX = 0; #define GD32_BOARD_LED3 GD32_PORT_TO_GPIO(GD32_GPIO_PORTC, 3) #define GD32_BOARD_STATUS_LED GD32_BOARD_LED1 +/** + * LCD + */ + +#define DISPLAYTIMEOUT_GPIO GD32_PORT_TO_GPIO(GD32_GPIO_PORTA, 14) // KEY2 + /** * SPI LCD */ -#define SPI_LCD_RST_PIN GPIO_EXT_7 -#define SPI_LCD_DC_PIN GPIO_EXT_26 -#define SPI_LCD_BL_PIN GPIO_EXT_22 -#if defined(SPI_LCD_HAVE_CS_PIN) -# define SPI_LCD_CS_PIN GPIO_EXT_24 +#define SPI_LCD_RST_PIN GPIO_EXT_7 +#define SPI_LCD_DC_GPIO GPIO_EXT_26 +#define SPI_LCD_BL_GPIO GPIO_EXT_22 +#if defined(SPI_LCD_HAVE_CS_GPIO) +# define SPI_LCD_CS_GPIO GPIO_EXT_24 #endif #include "gpio_header.h" diff --git a/lib-gd32/include/board/dmx4.h b/lib-gd32/include/board/dmx4.h index 9826e5f3..8f1bdf32 100644 --- a/lib-gd32/include/board/dmx4.h +++ b/lib-gd32/include/board/dmx4.h @@ -2,7 +2,7 @@ * @file dmx4.h * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,6 +38,8 @@ # error USART0 is used for console #endif +#include + /** * LEDs */ @@ -75,30 +77,32 @@ */ #define I2C0_REMAP -#define I2C_REMAP GPIO_I2C0_REMAP -#define I2C_PERIPH I2C0_PERIPH -#define I2C_RCU_CLK I2C0_RCU_CLK -#define I2C_GPIO_SCL_PORT I2C0_SCL_GPIOx -#define I2C_GPIO_SCL_CLK I2C0_SCL_RCU_GPIOx -#define I2C_GPIO_SDA_PORT I2C0_SDA_GPIOx -#define I2C_GPIO_SDA_CLK I2C0_SDA_RCU_GPIOx -#define I2C_SCL_PIN I2C0_SCL_GPIO_PINx -#define I2C_SDA_PIN I2C0_SDA_GPIO_PINx +#define I2C_REMAP GPIO_I2C0_REMAP +#define I2C_PERIPH I2C0_PERIPH +#define I2C_RCU_I2Cx I2C0_RCU_I2C0 +#define I2C_GPIO_AFx I2C0_GPIO_AFx +#define I2C_SCL_RCU_GPIOx I2C0_SCL_RCU_GPIOx +#define I2C_SCL_GPIOx I2C0_SCL_GPIOx +#define I2C_SCL_GPIO_PINx I2C0_SCL_GPIO_PINx +#define I2C_SDA_RCU_GPIOx I2C0_SDA_RCU_GPIOx +#define I2C_SDA_GPIOx I2C0_SDA_GPIOx +#define I2C_SDA_GPIO_PINx I2C0_SDA_GPIO_PINx /** * SPI */ #define SPI_PERIPH SPI2_PERIPH +#define SPI_RCU_SPIx SPI2_RCU_SPI2 +#define SPI_RCU_GPIOx SPI2_RCU_GPIOx +#define SPI_GPIO_AFx SPI2_GPIO_AFx +#define SPI_GPIOx SPI2_GPIOx +#define SPI_SCK_GPIO_PINx SPI2_SCK_GPIO_PINx +#define SPI_MISO_GPIO_PINx SPI2_MISO_GPIO_PINx +#define SPI_MOSI_GPIO_PINx SPI2_MOSI_GPIO_PINx #define SPI_NSS_GPIOx SPI2_NSS_GPIOx #define SPI_NSS_RCU_GPIOx SPI2_NSS_RCU_GPIOx #define SPI_NSS_GPIO_PINx SPI2_NSS_GPIO_PINx -#define SPI_RCU_CLK SPI2_RCU_CLK -#define SPI_GPIOx SPI2_GPIOx -#define SPI_RCU_GPIOx SPI2_RCU_GPIOx -#define SPI_SCK_PIN SPI2_SCK_GPIO_PINx -#define SPI_MISO_PIN SPI2_MISO_GPIO_PINx -#define SPI_MOSI_PIN SPI2_MOSI_GPIO_PINx #define SPI_DMAx SPI2_DMAx #define SPI_DMA_CHx SPI2_TX_DMA_CHx #define SPI_DMA_SUBPERIx SPI2_TX_DMA_SUBPERIx @@ -113,6 +117,7 @@ /** * Panel LEDs */ + #ifdef __cplusplus namespace hal { namespace panelled { @@ -128,24 +133,26 @@ static constexpr uint32_t OSC_IN = 0; static constexpr uint32_t OSC_OUT = 0; static constexpr uint32_t TCNET = 0; // DMX -static constexpr uint32_t PORT_A_TX = (1U << 0); -static constexpr uint32_t PORT_A_RX = (1U << 8); +static constexpr uint32_t PORT_A_TX = (1U << 0); +static constexpr uint32_t PORT_A_RX = (1U << 8); +#define CONFIG_PANELLED_RDM_PORT +static constexpr uint32_t PORT_A_RDM = (1U << 16); } // namespace panelled } // namespace hal #endif -#define LEDPANEL_595_COUNT 2 -#define LEDPANEL_595_CS_GPIOx GPIOA -#define LEDPANEL_595_CS_RCU_GPIOx RCU_GPIOA -#define LEDPANEL_595_CS_GPIO_PINx GPIO_PIN_15 +#define PANELLED_595_COUNT 2 +#define PANELLED_595_CS_GPIOx GPIOA +#define PANELLED_595_CS_RCU_GPIOx RCU_GPIOA +#define PANELLED_595_CS_GPIO_PINx GPIO_PIN_15 /** * SPI flash */ -#define SPI_FLASH_CS_GPIOx GPIOB -#define SPI_FLASH_CS_RCU_GPIOx RCU_GPIOB -#define SPI_FLASH_CS_GPIO_PINx GPIO_PIN_1 +#define SPI_FLASH_CS_RCU_GPIOx RCU_GPIOB +#define SPI_FLASH_CS_GPIOx GPIOB +#define SPI_FLASH_CS_GPIO_PINx GPIO_PIN_1 /** * EXT PHY @@ -176,7 +183,7 @@ static constexpr uint32_t PORT_A_RX = (1U << 8); */ #if defined (GD32F20X_CL) -# include "mcu/gd32f20x_mcu.h" +# include "mcu/gd32f207_mcu.h" # define GD32_MCU_NAME "GD32F207RG" #elif defined (GD32F407) # include "mcu/gd32f407_mcu.h" @@ -194,15 +201,21 @@ static constexpr uint32_t PORT_A_RX = (1U << 8); #define GD32_BOARD_LED3 GD32_PORT_TO_GPIO(GD32_GPIO_PORTC, 3) #define GD32_BOARD_STATUS_LED GD32_BOARD_LED1 +/** + * LCD + */ + +#define DISPLAYTIMEOUT_GPIO GD32_PORT_TO_GPIO(GD32_GPIO_PORTA, 14) // KEY2 + /** * SPI LCD */ -#define SPI_LCD_RST_PIN GPIO_EXT_7 -#define SPI_LCD_DC_PIN GPIO_EXT_26 -#define SPI_LCD_BL_PIN GPIO_EXT_22 -#if defined(SPI_LCD_HAVE_CS_PIN) -# define SPI_LCD_CS_PIN GPIO_EXT_24 +#define SPI_LCD_RST_PIN GPIO_EXT_7 +#define SPI_LCD_DC_GPIO GPIO_EXT_26 +#define SPI_LCD_BL_GPIO GPIO_EXT_22 +#if defined(SPI_LCD_HAVE_CS_GPIO) +# define SPI_LCD_CS_GPIO GPIO_EXT_24 #endif #include "gpio_header.h" diff --git a/lib-gd32/include/board/gd32f207rg.h b/lib-gd32/include/board/gd32f207rg.h index 0bdb16f7..142622ed 100644 --- a/lib-gd32/include/board/gd32f207rg.h +++ b/lib-gd32/include/board/gd32f207rg.h @@ -2,7 +2,7 @@ * @file gd32f207rg.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,6 +34,15 @@ # error This file should be included later #endif +#include + +/** + * U(S)ART + */ + +#define USART0_REMAP +#define USART2_PARTIAL_REMAP + /** * LEDs */ @@ -77,41 +86,103 @@ #define I2C0_REMAP #define I2C_REMAP GPIO_I2C0_REMAP #define I2C_PERIPH I2C0_PERIPH -#define I2C_RCU_CLK I2C0_RCU_CLK -#define I2C_GPIO_SCL_PORT I2C0_SCL_GPIOx -#define I2C_GPIO_SCL_CLK I2C0_SCL_RCU_GPIOx -#define I2C_GPIO_SDA_PORT I2C0_SDA_GPIOx -#define I2C_GPIO_SDA_CLK I2C0_SDA_RCU_GPIOx -#define I2C_SCL_PIN I2C0_SCL_GPIO_PINx -#define I2C_SDA_PIN I2C0_SDA_GPIO_PINx +#define I2C_RCU_I2Cx I2C0_RCU_I2C0 +#define I2C_SCL_RCU_GPIOx I2C0_SCL_RCU_GPIOx +#define I2C_SCL_GPIOx I2C0_SCL_GPIOx +#define I2C_SCL_GPIO_PINx I2C0_SCL_GPIO_PINx +#define I2C_SDA_RCU_GPIOx I2C0_SDA_RCU_GPIOx +#define I2C_SDA_GPIOx I2C0_SDA_GPIOx +#define I2C_SDA_GPIO_PINx I2C0_SDA_GPIO_PINx /** * SPI */ -#define SPI_PERIPH SPI2_PERIPH -#define SPI_NSS_GPIOx SPI2_NSS_GPIOx -#define SPI_NSS_RCU_GPIOx SPI2_NSS_RCU_GPIOx -#define SPI_NSS_GPIO_PINx SPI2_NSS_GPIO_PINx -#define SPI_RCU_CLK SPI2_RCU_CLK -#define SPI_GPIOx SPI2_GPIOx -#define SPI_RCU_GPIOx SPI2_RCU_GPIOx -#define SPI_SCK_PIN SPI2_SCK_GPIO_PINx -#define SPI_MISO_PIN SPI2_MISO_GPIO_PINx -#define SPI_MOSI_PIN SPI2_MOSI_GPIO_PINx -#define SPI_DMAx SPI2_DMAx -#define SPI_DMA_CHx SPI2_TX_DMA_CHx +#if defined (CONFIG_SPI_USE_SPI2) +# define SPI2_REMAP +# define SPI_REMAP_GPIO SPI2_REMAP_GPIO +# define SPI_PERIPH SPI2_PERIPH +# define SPI_RCU_SPIx SPI2_RCU_SPI2 +# define SPI_RCU_GPIOx SPI2_RCU_GPIOx +# define SPI_GPIOx SPI2_GPIOx +# define SPI_SCK_GPIO_PINx SPI2_SCK_GPIO_PINx +# define SPI_MISO_GPIO_PINx SPI2_MISO_GPIO_PINx +# define SPI_MOSI_GPIO_PINx SPI2_MOSI_GPIO_PINx +# define SPI_NSS_RCU_GPIOx RCU_GPIOC +# define SPI_NSS_GPIOx GPIOC +# define SPI_NSS_GPIO_PINx GPIO_PIN_13 +# define SPI_DMAx SPI2_DMAx +# define SPI_DMA_CHx SPI2_TX_DMA_CHx +#else +# define SPI0_REMAP +# if defined (SPI0_REMAP) +# define SPI_REMAP_GPIO SPI0_REMAP_GPIO +# endif +# define SPI_PERIPH SPI0_PERIPH +# define SPI_RCU_SPIx SPI0_RCU_SPI0 +# define SPI_RCU_GPIOx SPI0_RCU_GPIOx +# define SPI_GPIOx SPI0_GPIOx +# define SPI_SCK_GPIO_PINx SPI0_SCK_GPIO_PINx +# define SPI_MISO_GPIO_PINx SPI0_MISO_GPIO_PINx +# define SPI_MOSI_GPIO_PINx SPI0_MOSI_GPIO_PINx +# define SPI_NSS_RCU_GPIOx SPI0_NSS_RCU_GPIOx +# define SPI_NSS_GPIOx SPI0_NSS_GPIOx +# define SPI_NSS_GPIO_PINx SPI0_NSS_GPIO_PINx +# define SPI_DMAx SPI0_DMAx +# define SPI_DMA_CHx SPI0_TX_DMA_CHx +#endif /** - * U(S)ART + * I2S */ -#define USART0_REMAP -#define USART2_PARTIAL_REMAP +#define SPI2_REMAP +#if defined (SPI2_REMAP) +# define I2S_REMAP_GPIO SPI2_REMAP_GPIO +#endif +#define I2S_PERIPH SPI2_PERIPH +#define I2S_RCU_SPIx SPI2_RCU_SPI2 +#define I2S_RCU_GPIOx SPI2_RCU_GPIOx +#define I2S_GPIOx SPI2_GPIOx +#define I2S_CK_GPIO_PINx SPI2_SCK_GPIO_PINx +#define I2S_SD_GPIO_PINx SPI2_MOSI_GPIO_PINx +#define I2S_WS_RCU_GPIOx SPI2_NSS_RCU_GPIOx +#define I2S_WS_GPIOx SPI2_NSS_GPIOx +#define I2S_WS_GPIO_PINx SPI2_NSS_GPIO_PINx +#define I2S_DMAx SPI2_DMAx +#define I2S_DMA_CHx SPI2_TX_DMA_CHx + +/** + * PWM + */ + +#define PWM_TIMERx TIMER2 +#define PWM_RCU_TIMERx RCU_TIMER2 + +#define TIMER2_FULL_REMAP +#define PWM_TIMER_REMAP TIMER2_REMAP +#define PWM_GPIO_AFx TIMER2_GPIO_AFx + +#define PWM_CH0_RCU_GPIOx TIMER2_CH0_RCU_GPIOx +#define PWM_CH0_GPIOx TIMER2_CH0_GPIOx +#define PWM_CH0_GPIO_PINx TIMER2_CH0_GPIO_PINx + +#define PWM_CH1_RCU_GPIOx TIMER2_CH1_RCU_GPIOx +#define PWM_CH1_GPIOx TIMER2_CH1_GPIOx +#define PWM_CH1_GPIO_PINx TIMER2_CH1_GPIO_PINx + +#define PWM_CH2_RCU_GPIOx TIMER2_CH2_RCU_GPIOx +#define PWM_CH2_GPIOx TIMER2_CH2_GPIOx +#define PWM_CH2_GPIO_PINx TIMER2_CH2_GPIO_PINx + +#define PWM_CH3_RCU_GPIOx TIMER2_CH3_RCU_GPIOx +#define PWM_CH3_GPIOx TIMER2_CH3_GPIOx +#define PWM_CH3_GPIO_PINx TIMER2_CH3_GPIO_PINx /** * Panel LEDs */ + #ifdef __cplusplus namespace hal { namespace panelled { @@ -137,9 +208,9 @@ static constexpr uint32_t PORT_A_TX = 0; * SPI flash */ -#define SPI_FLASH_CS_GPIOx GPIOB -#define SPI_FLASH_CS_RCU_GPIOx RCU_GPIOB -#define SPI_FLASH_CS_GPIO_PINx GPIO_PIN_1 +#define SPI_FLASH_CS_RCU_GPIOx RCU_GPIOB +#define SPI_FLASH_CS_GPIOx GPIOB +#define SPI_FLASH_CS_GPIO_PINx GPIO_PIN_1 /** * EXT PHY @@ -165,7 +236,7 @@ static constexpr uint32_t PORT_A_TX = 0; #define GD32_MCU_NAME "GD32F207RG" #define GD32_BOARD_NAME "GD32F207RG" -#include "mcu/gd32f20x_mcu.h" +#include "mcu/gd32f207_mcu.h" #include "gd32_gpio.h" #define GD32_BOARD_LED1 GD32_PORT_TO_GPIO(GD32_GPIO_PORTC, 0) @@ -173,17 +244,37 @@ static constexpr uint32_t PORT_A_TX = 0; #define GD32_BOARD_LED3 GD32_PORT_TO_GPIO(GD32_GPIO_PORTC, 3) #define GD32_BOARD_STATUS_LED GD32_BOARD_LED1 +/** + * LCD + */ + +#define DISPLAYTIMEOUT_GPIO GD32_PORT_TO_GPIO(GD32_GPIO_PORTB, 14) // KEY2 + +/** + * Pixel DMX + */ + +#define PIXELDMXSTARTSTOP_GPIO GD32_BOARD_LED2 + /** * SPI LCD */ #define SPI_LCD_RST_PIN GPIO_EXT_7 -#define SPI_LCD_DC_PIN GPIO_EXT_26 -#define SPI_LCD_BL_PIN GPIO_EXT_22 -#if defined(SPI_LCD_HAVE_CS_PIN) -# define SPI_LCD_CS_PIN GPIO_EXT_24 +#define SPI_LCD_DC_GPIO GPIO_EXT_26 +#define SPI_LCD_BL_GPIO GPIO_EXT_22 +#if defined(SPI_LCD_HAVE_CS_GPIO) +# define SPI_LCD_CS_GPIO GPIO_EXT_24 #endif +/** + * FT8xx LCD + */ + +#define FT8XX_LCD_DC_GPIO GPIO_EXT_26 +#define FT8XX_LCD_CS_GPIO GPIO_EXT_22 +#define FT8XX_LCD_INT_GPIO GPIO_EXT_12 + #include "gpio_header.h" #endif /* BOARD_GD32F207R_H_ */ diff --git a/lib-gd32/include/board/logic_analyzer.h b/lib-gd32/include/board/logic_analyzer.h index e3bc5fa1..9c2ab503 100644 --- a/lib-gd32/include/board/logic_analyzer.h +++ b/lib-gd32/include/board/logic_analyzer.h @@ -2,7 +2,7 @@ * @file logic_analyzer.h * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,60 +26,31 @@ #ifndef BOARD_LOGIC_ANALYZER_H_ #define BOARD_LOGIC_ANALYZER_H_ -#if defined (BOARD_GD32F207C_EVAL) -# define LOGIC_ANALYZER_CH0_GPIO_PINx GPIO_PIN_0 -# define LOGIC_ANALYZER_CH1_GPIO_PINx GPIO_PIN_1 -# define LOGIC_ANALYZER_CH2_GPIO_PINx GPIO_PIN_7 -//#define LOGIC_ANALYZER_CH3_GPIO_PINx -//#define LOGIC_ANALYZER_CH4_GPIO_PINx -//#define LOGIC_ANALYZER_CH5_GPIO_PINx -//#define LOGIC_ANALYZER_CH6_GPIO_PINx -//#define LOGIC_ANALYZER_CH7_GPIO_PINx - -# define LOGIC_ANALYZER_CH0_GPIOx GPIOE -# define LOGIC_ANALYZER_CH1_GPIOx GPIOE -# define LOGIC_ANALYZER_CH2_GPIOx GPIOD -# define LOGIC_ANALYZER_CH3_GPIOx -# define LOGIC_ANALYZER_CH4_GPIOx -# define LOGIC_ANALYZER_CH5_GPIOx -# define LOGIC_ANALYZER_CH6_GPIOx -# define LOGIC_ANALYZER_CH7_GPIOx - -# define LOGIC_ANALYZER_CH0_RCU_GPIOx RCU_GPIOE -# define LOGIC_ANALYZER_CH1_RCU_GPIOx RCU_GPIOE -# define LOGIC_ANALYZER_CH2_RCU_GPIOx RCU_GPIOD -# define LOGIC_ANALYZER_CH3_RCU_GPIOx -# define LOGIC_ANALYZER_CH4_RCU_GPIOx -# define LOGIC_ANALYZER_CH5_RCU_GPIOx -# define LOGIC_ANALYZER_CH6_RCU_GPIOx -# define LOGIC_ANALYZER_CH7_RCU_GPIOx -#else -# define LOGIC_ANALYZER_CH0_GPIO_PINx GPIO_PIN_8 // PC8 -# define LOGIC_ANALYZER_CH1_GPIO_PINx GPIO_PIN_9 // PC9 -# define LOGIC_ANALYZER_CH2_GPIO_PINx GPIO_PIN_13 // PC13 -# define LOGIC_ANALYZER_CH3_GPIO_PINx GPIO_PIN_4 // PA4 -# define LOGIC_ANALYZER_CH4_GPIO_PINx GPIO_PIN_5 // PA5 -# define LOGIC_ANALYZER_CH5_GPIO_PINx GPIO_PIN_13 // PA13 -//# define LOGIC_ANALYZER_CH6_GPIO_PINx GPIO_PIN_ -//# define LOGIC_ANALYZER_CH7_GPIO_PINx GPIO_PIN_ - -# define LOGIC_ANALYZER_CH0_GPIOx GPIOC -# define LOGIC_ANALYZER_CH1_GPIOx GPIOC -# define LOGIC_ANALYZER_CH2_GPIOx GPIOC -# define LOGIC_ANALYZER_CH3_GPIOx GPIOA -# define LOGIC_ANALYZER_CH4_GPIOx GPIOA -# define LOGIC_ANALYZER_CH5_GPIOx GPIOA -# define LOGIC_ANALYZER_CH6_GPIOx GPIO -# define LOGIC_ANALYZER_CH7_GPIOx GPIO - -# define LOGIC_ANALYZER_CH0_RCU_GPIOx RCU_GPIOC -# define LOGIC_ANALYZER_CH1_RCU_GPIOx RCU_GPIOC -# define LOGIC_ANALYZER_CH2_RCU_GPIOx RCU_GPIOC -# define LOGIC_ANALYZER_CH3_RCU_GPIOx RCU_GPIOA -# define LOGIC_ANALYZER_CH4_RCU_GPIOx RCU_GPIOA -# define LOGIC_ANALYZER_CH5_RCU_GPIOx RCU_GPIOA -# define LOGIC_ANALYZER_CH6_RCU_GPIOx RCU_GPIO -# define LOGIC_ANALYZER_CH7_RCU_GPIOx RCU_GPIO -#endif +#define LOGIC_ANALYZER_CH0_GPIO_PINx GPIO_PIN_3 +#define LOGIC_ANALYZER_CH1_GPIO_PINx GPIO_PIN_4 +#define LOGIC_ANALYZER_CH2_GPIO_PINx GPIO_PIN_5 +#define LOGIC_ANALYZER_CH3_GPIO_PINx GPIO_PIN_8 +#define LOGIC_ANALYZER_CH4_GPIO_PINx GPIO_PIN_9 +#define LOGIC_ANALYZER_CH5_GPIO_PINx GPIO_PIN_13 +#define LOGIC_ANALYZER_CH6_GPIO_PINx GPIO_PIN_11 +#define LOGIC_ANALYZER_CH7_GPIO_PINx GPIO_PIN_15 + +#define LOGIC_ANALYZER_CH0_GPIOx GPIOB +#define LOGIC_ANALYZER_CH1_GPIOx GPIOB +#define LOGIC_ANALYZER_CH2_GPIOx GPIOB +#define LOGIC_ANALYZER_CH3_GPIOx GPIOC +#define LOGIC_ANALYZER_CH4_GPIOx GPIOC +#define LOGIC_ANALYZER_CH5_GPIOx GPIOC +#define LOGIC_ANALYZER_CH6_GPIOx GPIOA +#define LOGIC_ANALYZER_CH7_GPIOx GPIOA + +#define LOGIC_ANALYZER_CH0_RCU_GPIOx RCU_GPIOB +#define LOGIC_ANALYZER_CH1_RCU_GPIOx RCU_GPIOB +#define LOGIC_ANALYZER_CH2_RCU_GPIOx RCU_GPIOB +#define LOGIC_ANALYZER_CH3_RCU_GPIOx RCU_GPIOC +#define LOGIC_ANALYZER_CH4_RCU_GPIOx RCU_GPIOC +#define LOGIC_ANALYZER_CH5_RCU_GPIOx RCU_GPIOC +#define LOGIC_ANALYZER_CH6_RCU_GPIOx RCU_GPIOA +#define LOGIC_ANALYZER_CH7_RCU_GPIOx RCU_GPIOA #endif /* BOARD_LOGIC_ANALYZER_H_ */ diff --git a/lib-gd32/include/gd32.h b/lib-gd32/include/gd32.h index b13f5dc1..c138dad6 100644 --- a/lib-gd32/include/gd32.h +++ b/lib-gd32/include/gd32.h @@ -2,7 +2,7 @@ * @file gd32.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,17 +26,22 @@ #ifndef GD32_H_ #define GD32_H_ -#include +# include -#if !defined __cplusplus - void udelay(uint32_t us); -#else -# if !defined(GD32_UDELAY) -# define GD32_UDELAY +#ifdef __cplusplus +# if !defined(UDELAY) +# define UDELAY void udelay(uint32_t us, uint32_t offset = 0); # endif #endif +struct HwTimersSeconds { +#if !defined (CONFIG_ENET_ENABLE_PTP) + volatile uint32_t nTimeval; +#endif + volatile uint32_t nUptime; +}; + /* * Needed for GD32 Firmware and CMSIS */ @@ -45,25 +50,23 @@ #ifdef __cplusplus # pragma GCC diagnostic ignored "-Wold-style-cast" # pragma GCC diagnostic ignored "-Wuseless-cast" +# if __cplusplus > 201402 +// error: compound assignment with 'volatile'-qualified left operand is deprecated +# pragma GCC diagnostic ignored "-Wvolatile" +# endif extern "C" { #endif -#if defined (GD32F10X_HD) || defined (GD32F10X_CL) -# define GD32F10X +#if defined (GD32F10X_HD) || defined (GD32F10X_CL) # include "gd32f10x.h" -# include "gd32f10x_libopt.h" #elif defined (GD32F20X_CL) -# define GD32F20X # include "gd32f20x.h" -# include "gd32f20x_libopt.h" #elif defined (GD32F30X_HD) -# define GD32F30X # include "gd32f30x.h" -# include "gd32f30x_libopt.h" -#elif defined (GD32F407) || defined (GD32F450) -# define GD32F4XX +#elif defined (GD32F407) || defined (GD32F450) || defined (GD32F470) # include "gd32f4xx.h" -# include "gd32f4xx_libopt.h" +#elif defined (GD32H759) +# include "gd32h7xx.h" #else # error MCU is not supported #endif @@ -77,7 +80,7 @@ extern "C" { # define bkp_data_read bkp_read_data #endif -#if defined(GD32F4XX) && defined(__cplusplus) +#if (defined(GD32F4XX) || defined (GD32H7XX)) && defined(__cplusplus) typedef enum { BKP_DATA_0, @@ -87,6 +90,34 @@ void bkp_data_write(bkp_data_register_enum register_number, uint16_t data); uint16_t bkp_data_read(bkp_data_register_enum register_number); #endif +#if !(defined (GD32F4XX) || defined (GD32H7XX)) +#define GPIO_INIT +#endif + +#if defined (GD32H7XX) +# define GPIO_OSPEED GPIO_OSPEED_60MHZ +#else +# define GPIO_OSPEED GPIO_OSPEED_50MHZ +#endif + +#define GD32_PORT_TO_GPIO(p,n) ((p * 16) + n) +#define GD32_GPIO_TO_PORT(g) (uint8_t)(g / 16) +#define GD32_GPIO_TO_NUMBER(g) (uint8_t)(g - (16 * GD32_GPIO_TO_PORT(g))) + +typedef enum T_GD32_Port { + GD32_GPIO_PORTA = 0, + GD32_GPIO_PORTB, + GD32_GPIO_PORTC, + GD32_GPIO_PORTD, + GD32_GPIO_PORTE, + GD32_GPIO_PORTF, + GD32_GPIO_PORTG, + GD32_GPIO_PORTH, + GD32_GPIO_PORTI, + GD32_GPIO_PORTJ, + GD32_GPIO_PORTK +} GD32_Port_TypeDef; + #include "gd32_board.h" #endif /* GD32_H_ */ diff --git a/lib-gd32/include/gd32_adc.h b/lib-gd32/include/gd32_adc.h index d637dc6f..fc66537d 100644 --- a/lib-gd32/include/gd32_adc.h +++ b/lib-gd32/include/gd32_adc.h @@ -26,10 +26,10 @@ #ifndef GD32_ADC_H_ #define GD32_ADC_H_ -float gd32_adc_gettemp(void); -float gd32_adc_getvref(void); +float gd32_adc_gettemp(); +float gd32_adc_getvref(); #if defined (GD32F4XX) -float gd32_adc_getvbat(void); +float gd32_adc_getvbat(); #endif #ifdef __cplusplus diff --git a/lib-gd32/include/gd32_board.h b/lib-gd32/include/gd32_board.h index bb1ec557..f07b59ef 100644 --- a/lib-gd32/include/gd32_board.h +++ b/lib-gd32/include/gd32_board.h @@ -2,7 +2,7 @@ * @file gd32_board.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -46,8 +46,14 @@ # include "board/gd32f450vi.h" #elif defined (BOARD_16X4U_PIXEL) # include "board/16x4u-pixel.h" +#elif defined (BOARD_GD32F470VG) +# include "board/gd32f470vg.h" #elif defined (BOARD_GD32F207C_EVAL) # include "board/gd32f207c_eval.h" +#elif defined (BOARD_GD32F470Z_EVAL) +# include "board/gd32f470z_eval.h" +#elif defined (BOARD_GD32H759I_EVAL) +# include "board/gd32h759i_eval.h" #elif defined (BOARD_BW_OPIDMX4) # include "board/bw_opidmx4.h" #elif defined (BOARD_DMX3) @@ -64,4 +70,22 @@ # error Configuration error #endif +#if defined (GD32H7XX) +# ifdef USE_ENET0 +# define ENETx ENET0 +# define RCU_ENET RCU_ENET0 +# define RCU_ENETTX RCU_ENET0TX +# define RCU_ENETRX RCU_ENET0RX +# elif USE_ENET1 +# define ENETx ENET1 +# define RCU_ENET RCU_ENET1 +# define RCU_ENETTX RCU_ENET1TX +# define RCU_ENETRX RCU_ENET1RX +# else +# error +# endif +#else +# define ENETx +#endif + #endif /* GD32_BOARD_H_ */ diff --git a/lib-gd32/include/gd32_dma.h b/lib-gd32/include/gd32_dma.h new file mode 100644 index 00000000..fbad893f --- /dev/null +++ b/lib-gd32/include/gd32_dma.h @@ -0,0 +1,225 @@ +/** + * @file gd32_dma.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef GD32_DMA_H_ +#define GD32_DMA_H_ + +#include +#include + +#include "gd32.h" + +#if defined (GD32F4XX) || defined (GD32H7XX) +# define DMA_PARAMETER_STRUCT dma_single_data_parameter_struct +# define DMA_CHMADDR DMA_CHM0ADDR +# define DMA_MEMORY_TO_PERIPHERAL DMA_MEMORY_TO_PERIPH +# define DMA_PERIPHERAL_WIDTH_8BIT DMA_PERIPH_WIDTH_8BIT +# define dma_init dma_single_data_mode_init +# define dma_memory_to_memory_disable(x,y) +#else +# define DMA_PARAMETER_STRUCT dma_parameter_struct +#endif + +#if defined (GD32F10X) || defined (GD32F30X) +template +bool gd32_dma_interrupt_flag_get() { + uint32_t interrupt_enable = 0, interrupt_flag = 0; + + switch (flag) { + case DMA_INT_FLAG_FTF: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE; + break; + case DMA_INT_FLAG_HTF: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE; + break; + case DMA_INT_FLAG_ERR: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE; + break; + default: + assert(0); + } + + return interrupt_flag && interrupt_enable; +} +#elif defined (GD32F20X) +template +bool gd32_dma_interrupt_flag_get() { + uint32_t interrupt_enable = 0U, interrupt_flag = 0U; + uint32_t gif_check = 0x0FU, gif_enable = 0x0EU; + + switch (flag) { + case DMA_INT_FLAG_FTF: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE; + break; + case DMA_INT_FLAG_HTF: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE; + break; + case DMA_INT_FLAG_ERR: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_ERRIE; + break; + case DMA_INT_FLAG_G: + interrupt_flag = DMA_INTF(dma_periph) & DMA_FLAG_ADD(gif_check, channelx); + interrupt_flag = interrupt_flag >> ((channelx) * 4U); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & gif_enable; + break; + default: + assert(0); + } + + return (interrupt_flag && interrupt_enable); +} +#elif defined (GD32F4XX) || defined (GD32H7XX) +template +bool gd32_dma_interrupt_flag_get() { + uint32_t interrupt_enable = 0U, interrupt_flag = 0U; + + if constexpr (channelx < DMA_CH4) { + switch (flag) { + case DMA_INTF_FEEIF: + interrupt_flag = DMA_INTF0(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHFCTL(dma_periph, channelx) & DMA_CHXFCTL_FEEIE; + break; + case DMA_INTF_SDEIF: + interrupt_flag = DMA_INTF0(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_SDEIE; + break; + case DMA_INTF_TAEIF: + interrupt_flag = DMA_INTF0( dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_TAEIE; + break; + case DMA_INTF_HTFIF: + interrupt_flag = DMA_INTF0(dma_periph) & DMA_FLAG_ADD(flag, channelx); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE; + break; + case DMA_INTF_FTFIF: + interrupt_flag = (DMA_INTF0(dma_periph) & DMA_FLAG_ADD(flag, channelx)); + interrupt_enable = (DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE); + break; + default: + assert(0); + break; + } + } else if constexpr (channelx <= DMA_CH7) { + constexpr uint32_t channel_flag_offset = static_cast(channelx) - 4; + switch (flag) { + case DMA_INTF_FEEIF: + interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(flag, channel_flag_offset); + interrupt_enable = DMA_CHFCTL(dma_periph, channelx) & DMA_CHXFCTL_FEEIE; + break; + case DMA_INTF_SDEIF: + interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(flag, channel_flag_offset); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_SDEIE; + break; + case DMA_INTF_TAEIF: + interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(flag, channel_flag_offset); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_TAEIE; + break; + case DMA_INTF_HTFIF: + interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(flag, channel_flag_offset); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_HTFIE; + break; + case DMA_INTF_FTFIF: + interrupt_flag = DMA_INTF1(dma_periph) & DMA_FLAG_ADD(flag, channel_flag_offset); + interrupt_enable = DMA_CHCTL(dma_periph, channelx) & DMA_CHXCTL_FTFIE; + break; + default: + assert(0); + break; + } + } else { + assert(0); + } + + return (interrupt_flag && interrupt_enable); +} +#else +# error +#endif + +#if defined (GD32F10X) || defined (GD32F30X) || defined (GD32F20X) +template +void gd32_dma_interrupt_flag_clear() { + DMA_INTC(peripheral) |= DMA_FLAG_ADD(nFlag, channel); +} +#elif defined (GD32F4XX) || defined (GD32H7XX) +template +inline void gd32_dma_interrupt_flag_clear() { + if constexpr (channel < DMA_CH4) { + DMA_INTC0(peripheral) |= DMA_FLAG_ADD(nFlag, channel); + } else { + DMA_INTC1(peripheral) |= DMA_FLAG_ADD(nFlag, static_cast(channel) - 4U); + } +} +#else +# error +#endif + +#if defined (GD32F10X) || defined (GD32F30X) +template +void gd32_dma_interrupt_disable() { + if constexpr (DMA1 == peripheral) { + static_assert(channel <= DMA_CH4, "for DMA1, the channel is from DMA_CH0 to DMA_CH4"); + } + + DMA_CHCTL(peripheral, channel) &= static_cast(~nSource); +} +#elif defined (GD32F20X) +template +void gd32_dma_interrupt_disable() { + DMA_CHCTL(peripheral, channel) &= static_cast(~nSource); +} +#elif defined (GD32F4XX) +template +void gd32_dma_interrupt_disable() { + if constexpr (DMA_CHXFCTL_FEEIE != nSource) { + DMA_CHCTL(peripheral, channel) &= static_cast(~nSource); + } else { + DMA_CHFCTL(peripheral, channel) &= static_cast(~nSource); + } +} +#elif defined (GD32H7XX) +template +void gd32_dma_interrupt_disable() { + if constexpr (DMA_CHXFCTL_FEEIE != (DMA_CHXFCTL_FEEIE & nSource)) { + DMA_CHCTL(peripheral, channel) &= static_cast(~nSource); + } else { + DMA_CHFCTL(peripheral, channel) &= static_cast(~DMA_CHXFCTL_FEEIE); + DMA_CHCTL(peripheral, channel) &= static_cast(~(nSource & (~DMA_CHXFCTL_FEEIE))); + } +} +#else +# error +#endif + +#endif /* GD32_DMA_H_ */ diff --git a/lib-gd32/include/gd32_dma_memcpy32.h b/lib-gd32/include/gd32_dma_memcpy32.h new file mode 100644 index 00000000..c7936c14 --- /dev/null +++ b/lib-gd32/include/gd32_dma_memcpy32.h @@ -0,0 +1,56 @@ +/* + * gd32_dma_memcpy32.h + */ + +#ifndef GD32_DMA_MEMCPY32_H_ +#define GD32_DMA_MEMCPY32_H_ + +#include +#include + +#include "gd32.h" + +namespace dma { +void memcpy32_init() ; + +inline void memcpy32(const void *pDestination, const void *pSource, const uint32_t nLength) { + assert((reinterpret_cast(pSource) & 0x3) == 0); + assert((reinterpret_cast(pDestination) & 0x3) == 0); + +#if !defined (GD32F4XX) + uint32_t dmaCHCTL = DMA_CHCTL(DMA0, DMA_CH3); + dmaCHCTL &= ~DMA_CHXCTL_CHEN; + DMA_CHCTL(DMA0, DMA_CH3) = dmaCHCTL; + + DMA_CHPADDR(DMA0, DMA_CH3) = reinterpret_cast(pSource); + DMA_CHMADDR(DMA0, DMA_CH3) = reinterpret_cast(pDestination); + DMA_CHCNT(DMA0, DMA_CH3) = (nLength & DMA_CHXCNT_CNT); + + dmaCHCTL |= DMA_CHXCTL_CHEN; + DMA_CHCTL(DMA0, DMA_CH3) = dmaCHCTL; +#else + uint32_t dmaCHCTL = DMA_CHCTL(DMA1, DMA_CH0); + dmaCHCTL &= ~DMA_CHXCTL_CHEN; + DMA_CHCTL(DMA1, DMA_CH0) = dmaCHCTL; + + DMA_INTC0(DMA1) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, DMA_CH0); + + DMA_CHM0ADDR(DMA1, DMA_CH0) = reinterpret_cast(pDestination); + DMA_CHPADDR(DMA1, DMA_CH0) = reinterpret_cast(pSource); + DMA_CHCNT(DMA1, DMA_CH0) = nLength; + + dmaCHCTL |= DMA_CHXCTL_CHEN; + DMA_CHCTL(DMA1, DMA_CH0) = dmaCHCTL; +#endif +} + +inline bool memcpy32_is_active() { +#if !defined (GD32F4XX) + return DMA_CHCNT(DMA0, DMA_CH3) != 0; +#else + return DMA_CHCNT(DMA1, DMA_CH0) != 0; +#endif +} +} // namespace dma + +#endif /* GD32_DMA_MEMCPY32_H_ */ diff --git a/lib-gd32/include/gd32_gpio.h b/lib-gd32/include/gd32_gpio.h index 7591f93a..71ec42c7 100644 --- a/lib-gd32/include/gd32_gpio.h +++ b/lib-gd32/include/gd32_gpio.h @@ -2,7 +2,7 @@ * @file gd32_gpio.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,20 +27,7 @@ #define GD32_GPIO_H_ #include - -#define GD32_PORT_TO_GPIO(p,n) ((p * 16) + n) -#define GD32_GPIO_TO_PORT(g) (uint8_t)(g / 16) -#define GD32_GPIO_TO_NUMBER(g) (uint8_t)(g - (16 * GD32_GPIO_TO_PORT(g))) - -typedef enum T_GD32_Port { - GD32_GPIO_PORTA = 0, - GD32_GPIO_PORTB, - GD32_GPIO_PORTC, - GD32_GPIO_PORTD, - GD32_GPIO_PORTE, - GD32_GPIO_PORTF, - GD32_GPIO_PORTG, -} GD32_Port_TypeDef; +#include #include "gd32.h" @@ -52,7 +39,7 @@ typedef enum T_GD32_Port { # define GPIO_PULL_DISABLE GPIO_MODE_IN_FLOATING # define GPIO_INT_CFG_NEG_EDGE EXTI_TRIG_FALLING # define GPIO_INT_CFG_BOTH EXTI_TRIG_BOTH -#elif defined (GD32F407) || defined (GD32F450) +#elif defined (GD32F407) || defined (GD32F450) || defined (GD32F470) || defined (GD32F470) || defined (GD32H759) # define GPIO_FSEL_OUTPUT GPIO_MODE_OUTPUT # define GPIO_FSEL_INPUT GPIO_MODE_INPUT # define GPIO_PULL_UP GPIO_PUPD_PULLUP @@ -60,7 +47,8 @@ typedef enum T_GD32_Port { # define GPIO_PULL_DISABLE GPIO_PUPD_NONE #endif -inline static void gpio_fsel(const uint32_t gpio_periph, const uint32_t pin, const uint32_t fsel) { +#ifdef __cplusplus +inline void gpio_fsel(const uint32_t gpio_periph, const uint32_t pin, const uint32_t fsel) { switch (gpio_periph) { case GPIOA: rcu_periph_clock_enable(RCU_GPIOA); @@ -80,11 +68,32 @@ inline static void gpio_fsel(const uint32_t gpio_periph, const uint32_t pin, con case GPIOF: rcu_periph_clock_enable(RCU_GPIOF); break; + case GPIOG: + rcu_periph_clock_enable(RCU_GPIOG); + break; +#if !(defined (GD32F10X) || defined (GD32F30X)) + case GPIOH: + rcu_periph_clock_enable(RCU_GPIOH); + break; +# if !defined (GD32H7XX) + case GPIOI: + rcu_periph_clock_enable(RCU_GPIOI); + break; +# endif +#endif +#if defined (GD32H7XX) + case GPIOJ: + rcu_periph_clock_enable(RCU_GPIOJ); + break; + case GPIOK: + rcu_periph_clock_enable(RCU_GPIOK); + break; +#endif default: break; } -#if defined (GD32F10X) || defined (GD32F20X) || defined (GD32F30X) +#if defined (GD32F10X) || defined (GD32F20X) || defined (GD32F30X) if (gpio_periph == GPIOA) { if ((pin == GPIO_PIN_13) || (pin == GPIO_PIN_14)) { rcu_periph_clock_enable(RCU_AF); @@ -93,10 +102,10 @@ inline static void gpio_fsel(const uint32_t gpio_periph, const uint32_t pin, con } gpio_init(gpio_periph, fsel, GPIO_OSPEED_50MHZ, pin); -#elif defined (GD32F4XX) +#elif defined (GD32F4XX) || defined (GD32H7XX) if (fsel == GPIO_FSEL_OUTPUT) { gpio_mode_set(gpio_periph, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, pin); - gpio_output_options_set(gpio_periph, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, pin); + gpio_output_options_set(gpio_periph, GPIO_OTYPE_PP, GPIO_OSPEED, pin); } else { gpio_mode_set(gpio_periph, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, pin); } @@ -105,31 +114,8 @@ inline static void gpio_fsel(const uint32_t gpio_periph, const uint32_t pin, con #endif } -inline static void gd32_gpio_fsel(const uint32_t gpio, const uint32_t fsel) { - const uint32_t gpio_periph = GPIOA + (GD32_GPIO_TO_PORT(gpio) * 0x400); - const uint32_t pin = BIT(GD32_GPIO_TO_NUMBER(gpio)); - - gpio_fsel(gpio_periph, pin, fsel); -} - -inline static void gd32_gpio_pud(const uint32_t gpio, const uint32_t pud) { - const uint32_t gpio_periph = GPIOA + (GD32_GPIO_TO_PORT(gpio) * 0x400); - const uint32_t pin = BIT(GD32_GPIO_TO_NUMBER(gpio)); - -#if defined (GD32F10X) || defined (GD32F20X) || defined (GD32F30X) - gpio_init(gpio_periph, pud, GPIO_OSPEED_50MHZ, pin); -#elif defined (GD32F4XX) - if (pud == GPIO_PULL_UP) { - gpio_mode_set(gpio_periph, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, pin); - } else if (pud == GPIO_PULL_DOWN) { - gpio_mode_set(gpio_periph, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, pin); - } else { - gpio_mode_set(gpio_periph, GPIO_MODE_INPUT, GPIO_PUPD_NONE, pin); - } -#endif -} - -inline static void gd32_gpio_int_cfg(const uint32_t gpio, const uint32_t trig_type) { +#if !defined (GD32H7XX) +inline void gd32_gpio_int_cfg(const uint32_t gpio, const uint32_t trig_type) { const uint32_t linex = BIT(GD32_GPIO_TO_NUMBER(gpio)); switch(trig_type){ @@ -158,22 +144,66 @@ inline static void gd32_gpio_int_cfg(const uint32_t gpio, const uint32_t trig_ty syscfg_exti_line_config(output_port, output_pin); #endif } +#endif -inline static void gd32_gpio_clr(const uint32_t gpio) { - const uint32_t gpio_periph = GPIOA + (GD32_GPIO_TO_PORT(gpio) * 0x400); +inline uint32_t gd32_gpio_to_periph(const uint32_t gpio) { + switch ((GD32_Port_TypeDef) GD32_GPIO_TO_PORT(gpio)) { + case GD32_GPIO_PORTA: + case GD32_GPIO_PORTB: + case GD32_GPIO_PORTC: + case GD32_GPIO_PORTD: + case GD32_GPIO_PORTE: + case GD32_GPIO_PORTF: + case GD32_GPIO_PORTG: + return GPIOA + (GD32_GPIO_TO_PORT(gpio) * 0x400); + break; +#if !(defined (GD32F10X) || defined (GD32F30X)) + case GD32_GPIO_PORTH: + return GPIOH; + break; +# if !defined (GD32H7XX) + case GD32_GPIO_PORTI: + return GPIOI; + break; +# endif +#endif +#if defined (GD32H7XX) + case GD32_GPIO_PORTJ: + return GPIOJ; + break; + case GD32_GPIO_PORTK: + return GPIOK; + break; +#endif + default: + assert(0); + return 0; + break; + } +} + +inline void gd32_gpio_fsel(const uint32_t gpio, const uint32_t fsel) { + const uint32_t gpio_periph = gd32_gpio_to_periph(gpio); const uint32_t pin = BIT(GD32_GPIO_TO_NUMBER(gpio)); - GPIO_BC(gpio_periph) = (uint32_t) pin; + gpio_fsel(gpio_periph, pin, fsel); } -inline static void gd32_gpio_set(const uint32_t gpio) { - const uint32_t gpio_periph = GPIOA + (GD32_GPIO_TO_PORT(gpio) * 0x400); +inline void gd32_gpio_clr(const uint32_t gpio) { + const uint32_t gpio_periph = gd32_gpio_to_periph(gpio); const uint32_t pin = BIT(GD32_GPIO_TO_NUMBER(gpio)); - GPIO_BOP(gpio_periph) = (uint32_t) pin; + GPIO_BC(gpio_periph) = pin; } -inline static void gd32_gpio_write(const uint32_t gpio, const uint32_t level) { +inline void gd32_gpio_set(const uint32_t gpio) { + const uint32_t gpio_periph = gd32_gpio_to_periph(gpio); + const uint32_t pin = BIT(GD32_GPIO_TO_NUMBER(gpio)); + + GPIO_BOP(gpio_periph) = pin; +} + +inline void gd32_gpio_write(const uint32_t gpio, const uint32_t level) { if (level == 0) { gd32_gpio_clr(gpio); } else { @@ -181,10 +211,135 @@ inline static void gd32_gpio_write(const uint32_t gpio, const uint32_t level) { } } -inline static uint32_t gd32_gpio_lev(const uint32_t gpio) { - const uint32_t gpio_periph = GPIOA + (GD32_GPIO_TO_PORT(gpio) * 0x400); +inline uint32_t gd32_gpio_lev(const uint32_t gpio) { + const uint32_t gpio_periph = gd32_gpio_to_periph(gpio); const uint32_t pin = BIT(GD32_GPIO_TO_NUMBER(gpio)); - return (uint32_t) ((uint32_t) 0 != (GPIO_ISTAT(gpio_periph) & pin)); + + return (uint32_t)(0 != (GPIO_ISTAT(gpio_periph) & pin)); } +inline void gd32_gpio_set_pud(const uint32_t gpio, const uint32_t pud) { + const uint32_t gpio_periph = gd32_gpio_to_periph(gpio); + const uint32_t pin = BIT(GD32_GPIO_TO_NUMBER(gpio)); + +#if defined (GD32F10X) || defined (GD32F20X) || defined (GD32F30X) + gpio_init(gpio_periph, pud, GPIO_OSPEED_50MHZ, pin); +#elif defined (GD32F4XX) || defined (GD32H7XX) + if (pud == GPIO_PULL_UP) { + gpio_mode_set(gpio_periph, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, pin); + } else if (pud == GPIO_PULL_DOWN) { + gpio_mode_set(gpio_periph, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, pin); + } else { + gpio_mode_set(gpio_periph, GPIO_MODE_INPUT, GPIO_PUPD_NONE, pin); + } +#endif +} + +#if defined (GD32F4XX) || defined (GD32H7XX) +template +inline void gd32_gpio_mode_set() { + static_assert(pin != 0, "pin cannot be zero"); + static_assert(pin == (1U << __builtin_ctz(pin)), "Only single pin values are allowed"); + + uint32_t ctl = GPIO_CTL(gpio_periph); + uint32_t pupd = GPIO_PUD(gpio_periph); + + constexpr auto i = 31U - __builtin_clz(pin); + + /* clear the specified pin mode bits */ + ctl &= ~GPIO_MODE_MASK(i); + /* set the specified pin mode bits */ + ctl |= GPIO_MODE_SET(i, mode); + + /* clear the specified pin pupd bits */ + pupd &= ~GPIO_PUPD_MASK(i); + /* set the specified pin pupd bits */ + pupd |= GPIO_PUPD_SET(i, pull_up_down); + + GPIO_CTL(gpio_periph) = ctl; + GPIO_PUD(gpio_periph) = pupd; +} + +template +inline void gd32_gpio_af_set() { + static_assert(pin != 0, "pin cannot be zero"); + static_assert(pin == (1U << __builtin_ctz(pin)), "Only single pin values are allowed"); + + constexpr uint32_t i = 31U - __builtin_clz(pin); + + auto afrl = GPIO_AFSEL0(gpio_periph); + auto afrh = GPIO_AFSEL1(gpio_periph); + + if constexpr(i < 8U) { + /* clear the specified pin alternate function bits */ + afrl &= ~GPIO_AFR_MASK(i); + afrl |= GPIO_AFR_SET(i, alt_func_num); + } else if constexpr(i < 16U) { + /* clear the specified pin alternate function bits */ + afrh &= ~GPIO_AFR_MASK(i - 8U); + afrh |= GPIO_AFR_SET(i - 8U, alt_func_num); + } + + GPIO_AFSEL0(gpio_periph) = afrl; + GPIO_AFSEL1(gpio_periph) = afrh; +} +#else +template +inline void gd32_gpio_init() { + /* GPIO mode configuration */ + auto temp_mode = (mode & 0x0F); + + /* GPIO speed configuration */ + if constexpr ((0x00U) != (mode & (0x10U))) { + /* output mode max speed: 10MHz, 2MHz, 50MHz */ + temp_mode |= speed; + } + + constexpr uint32_t pin_pos = 31U - __builtin_clz(pin); + + if constexpr (pin_pos < 8U) { + uint32_t reg = GPIO_CTL0(gpio_periph); + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(pin_pos); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(pin_pos, temp_mode); + + /* set IPD or IPU */ + if constexpr (GPIO_MODE_IPD == mode) { + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (1U << pin_pos); + } else { + /* set the corresponding OCTL bit */ + if constexpr (GPIO_MODE_IPU == mode) { + GPIO_BOP(gpio_periph) = (1U << pin_pos); + } + } + /* set GPIO_CTL0 register */ + GPIO_CTL0(gpio_periph) = reg; + } else { + /* configure the eight high port pins with GPIO_CTL1 */ + constexpr uint32_t high_pin_pos = pin_pos - 8U; + uint32_t reg = GPIO_CTL1(gpio_periph); + /* clear the specified pin mode bits */ + reg &= ~GPIO_MODE_MASK(high_pin_pos); + /* set the specified pin mode bits */ + reg |= GPIO_MODE_SET(high_pin_pos, temp_mode); + + /* set IPD or IPU */ + if constexpr (GPIO_MODE_IPD == mode) { + /* reset the corresponding OCTL bit */ + GPIO_BC(gpio_periph) = (1U << pin_pos); + } else { + /* set the corresponding OCTL bit */ + if (GPIO_MODE_IPU == mode) { + GPIO_BOP(gpio_periph) = (1U << pin_pos); + } + } + /* set GPIO_CTL1 register */ + GPIO_CTL1(gpio_periph) = reg; + } +} +#endif +#endif + #endif /* GD32_GPIO_H_ */ diff --git a/lib-gd32/include/gd32_ptp.h b/lib-gd32/include/gd32_ptp.h new file mode 100644 index 00000000..c1eb623e --- /dev/null +++ b/lib-gd32/include/gd32_ptp.h @@ -0,0 +1,98 @@ +/** + * @file gd32_ptp.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef GD32_PTP_H_ +#define GD32_PTP_H_ + +#include + +#include "gd32.h" + +namespace gd32 { +namespace ptp { +#if !defined(MCU_CLOCK_FREQ) +# error MCU_CLOCK_FREQ is not defined +#endif +#if !defined(PTP_ACCARACY_NS) + static constexpr uint8_t PTP_TICK = 20; +#else + static constexpr uint8_t PTP_TICK = PTP_ACCARACY_NS; +#endif +static constexpr uint8_t ADJ_FREQ_BASE_INCREMENT = static_cast((PTP_TICK * static_cast(1ULL << 31) / 1E9) + 0.5f); +static constexpr uint32_t ADJ_FREQ_BASE_ADDEND = (static_cast(1ULL << 63) / AHB_CLOCK_FREQ) / ADJ_FREQ_BASE_INCREMENT; +static constexpr int32_t ADJ_FREQ_MAX = 5120000; + +struct time_t { + int32_t tv_sec; + int32_t tv_nsec; +}; + +struct ptptime { + uint32_t tv_sec; + uint32_t tv_nsec; +}; +} // namespace ptp + +inline uint32_t ptp_nanosecond_2_subsecond(const uint32_t nanosecond) { + uint64_t val = nanosecond * 0x80000000Ull; + val /= 1000000000U; + return static_cast(val); +} + +inline uint32_t ptp_subsecond_2_nanosecond(const uint32_t subsecond) { + uint64_t val = subsecond * 1000000000Ull; + val >>= 31U; + return (uint32_t) val; +} + +inline void normalize_time(ptp::time_t *r) { + r->tv_sec += r->tv_nsec / 1000000000; + r->tv_nsec -= r->tv_nsec / 1000000000 * 1000000000; + + if (r->tv_sec > 0 && r->tv_nsec < 0) { + r->tv_sec -= 1; + r->tv_nsec += 1000000000; + } else if (r->tv_sec < 0 && r->tv_nsec > 0) { + r->tv_sec += 1; + r->tv_nsec -= 1000000000; + } +} + +inline void sub_time(struct ptp::time_t *r, const struct ptp::time_t *x, const struct ptp::time_t *y) { + r->tv_sec = x->tv_sec - y->tv_sec; + r->tv_nsec = x->tv_nsec - y->tv_nsec; + + normalize_time(r); +} + +} // namespace gd32 + +void gd32_ptp_start(); +void gd32_ptp_get_time(gd32::ptp::ptptime *ptp_time); +void gd32_ptp_set_time(const gd32::ptp::ptptime *ptp_time); +void gd32_ptp_update_time(const gd32::ptp::time_t *ptp_time); +bool gd32_adj_frequency(const int32_t adjust_pbb); + +#endif /* GD32_PTP_H_ */ diff --git a/lib-gd32/include/gd32_pwm.h b/lib-gd32/include/gd32_pwm.h new file mode 100644 index 00000000..5e3cf8c8 --- /dev/null +++ b/lib-gd32/include/gd32_pwm.h @@ -0,0 +1,43 @@ +/** + * @file gd32_pwm.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef GD32_PWM_H_ +#define GD32_PWM_H_ + +#include + +namespace pwm { +enum class Channel { + PWM_CHANNEL_0, + PWM_CHANNEL_1, + PWM_CHANNEL_2, + PWM_CHANNEL_3 +}; +} // namespace pwm + +void gd32_pwm_begin(); +void gd32_pwm_set_duty_cycle(const pwm::Channel channel, const uint32_t nDutyCycle); + +#endif /* GD32_PWM_H_ */ diff --git a/lib-gd32/include/gd32_spi.h b/lib-gd32/include/gd32_spi.h index 9b1f8ad5..10d410f0 100644 --- a/lib-gd32/include/gd32_spi.h +++ b/lib-gd32/include/gd32_spi.h @@ -2,7 +2,7 @@ * @file gd32_spi.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -62,10 +62,21 @@ void gd32_spi_writenb(const char *pTxBuffer, uint32_t nDataLength); * DMA support */ +const uint8_t *gd32_spi_dma_tx_prepare(uint32_t& nLength); +void gd32_spi_dma_tx_start(const uint8_t *pTxBuffer, uint32_t nLength); +bool gd32_spi_dma_tx_is_active(); + +/** + * SPI DMA implementation using I2S. + * Limitation SPI is that you cannot set the speed exactly. + * Exact speed is needed for pixels (WS2812B, etc). + */ +namespace i2s { void gd32_spi_dma_begin(); -void gd32_spi_dma_set_speed_hz(uint32_t speed_hz); -const uint8_t *gd32_spi_dma_tx_prepare(uint32_t *data_length); -void gd32_spi_dma_tx_start(const uint8_t *tx_buffer, uint32_t length); +void gd32_spi_dma_set_speed_hz(uint32_t nSpeedHz); +const uint8_t *gd32_spi_dma_tx_prepare(uint32_t *pLength); +void gd32_spi_dma_tx_start(const uint8_t *pTxBuffer, uint32_t nLength); bool gd32_spi_dma_tx_is_active(); +} // namespace i2s #endif /* GD32_SPI_H_ */ diff --git a/lib-gd32/include/gd32_uart.h b/lib-gd32/include/gd32_uart.h index 5f3c7595..f562f6c3 100644 --- a/lib-gd32/include/gd32_uart.h +++ b/lib-gd32/include/gd32_uart.h @@ -2,7 +2,7 @@ * @file gd32_uart.h * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,13 @@ #ifndef GD32_UART_H_ #define GD32_UART_H_ +#if !defined (GD32H7XX) +# define USART_TDATA USART_DATA +# define USART_RDATA USART_DATA +# define USART_TDATA_TDATA USART_DATA_DATA +# define USART_RDATA_TDATA USART_DATA_DATA +#endif + typedef enum GD32_UART_BITS { GD32_UART_BITS_8 = 8, GD32_UART_BITS_9 = 9 @@ -42,27 +49,75 @@ typedef enum GD32_UART_STOPBITS { GD32_UART_STOP_2BITS = 2 } gd32_uart_stopbits_t; -#include +#include #include "gd32.h" -#ifdef __cplusplus -extern "C" { -#endif - -extern void gd32_uart_begin(const uint32_t usart_periph, uint32_t baudrate, uint32_t bits, uint32_t parity, uint32_t stop_bits); -extern void gd32_uart_set_baudrate(const uint32_t usart_periph, uint32_t baudrate); -extern void gd32_uart_transmit(const uint32_t usart_periph, const uint8_t *data, uint32_t length); -extern void gd32_uart_transmit_string(const uint32_t uart_base, const char *data); +void gd32_uart_begin(const uint32_t usart_periph, uint32_t baudrate, uint32_t bits, uint32_t parity, uint32_t stop_bits); +void gd32_uart_set_baudrate(const uint32_t usart_periph, uint32_t baudrate); +void gd32_uart_transmit(const uint32_t usart_periph, const uint8_t *data, uint32_t length); +void gd32_uart_transmit_string(const uint32_t usart_periph, const char *data); -static inline uint32_t gd32_uart_get_rx_fifo_level(__attribute__((unused)) const uint32_t usart_periph) { +inline uint32_t gd32_uart_get_rx_fifo_level(__attribute__((unused)) const uint32_t usart_periph) { return 1; } -static inline uint8_t gd32_uart_get_rx_data(const uint32_t uart_base) { - return (uint8_t)(GET_BITS(USART_DATA(uart_base), 0U, 8U)); +inline uint8_t gd32_uart_get_rx_data(const uint32_t usart_periph) { + return static_cast(GET_BITS(USART_RDATA(usart_periph), 0U, 8U)); +} + +template +bool gd32_usart_flag_get(const uint32_t usart_periph) { + return (0 != (USART_REG_VAL(usart_periph, flag) & BIT(USART_BIT_POS(flag)))); +} + +template +void gd32_usart_flag_clear(const uint32_t usart_periph) { +#if defined (GD32F10X) || defined (GD32F30X) || defined (GD32F20X) + USART_REG_VAL(usart_periph, flag) = ~BIT(USART_BIT_POS(flag)); +#elif defined (GD32F4XX) + USART_REG_VAL(usart_periph, flag) &= ~BIT(USART_BIT_POS(flag)); +#elif defined (GD32H7XX) + if constexpr (USART_FLAG_AM1 == flag) { + USART_INTC(usart_periph) |= USART_INTC_AMC1; + } else if constexpr (USART_FLAG_EPERR == flag) { + USART_CHC(usart_periph) &= (uint32_t) (~USART_CHC_EPERR); + } else if constexpr (USART_FLAG_TFE == flag) { + USART_FCS(usart_periph) |= USART_FCS_TFEC; + } else { + USART_INTC(usart_periph) |= BIT(USART_BIT_POS(flag)); + } +#else +# error +#endif +} + +template +void gd32_usart_interrupt_enable(const uint32_t usart_periph) { + USART_REG_VAL(usart_periph, interrupt) |= BIT(USART_BIT_POS(interrupt)); } -#ifdef __cplusplus +template +void gd32_usart_interrupt_disable(const uint32_t usart_periph) { + USART_REG_VAL(usart_periph, interrupt) &= ~BIT(USART_BIT_POS(interrupt)); } + +template +void gd32_usart_interrupt_flag_clear(const uint32_t usart_periph) { +#if defined (GD32F10X) || defined (GD32F30X) || defined (GD32F20X) + USART_REG_VAL2(usart_periph, flag) = ~BIT(USART_BIT_POS2(flag)); +#elif defined (GD32F4XX) + USART_REG_VAL2(usart_periph, flag) &= ~BIT(USART_BIT_POS2(flag)); +#elif defined (GD32H7XX) + if constexpr (USART_INT_FLAG_TFE == flag) { + USART_FCS(usart_periph) |= USART_FCS_TFEC; + } else if constexpr (USART_INT_FLAG_RFF == flag) { + USART_FCS(usart_periph) &= (~USART_FCS_RFFIF); + } else { + USART_INTC(usart_periph) |= BIT(USART_BIT_POS2(flag)); + } +#else +# error #endif +} + #endif /* GD32_UART_H_ */ diff --git a/lib-gd32/include/logic_analyzer.h b/lib-gd32/include/logic_analyzer.h index ff116a02..c70ef0b4 100644 --- a/lib-gd32/include/logic_analyzer.h +++ b/lib-gd32/include/logic_analyzer.h @@ -2,7 +2,7 @@ * @file logic_analyzer.h * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,96 +26,96 @@ #ifndef LOGIC_ANALYZER_H_ #define LOGIC_ANALYZER_H_ +#include "board/logic_analyzer.h" #include "gd32.h" namespace logic_analyzer { - -static void init() { +inline void init() { #if defined (LOGIC_ANALYZER) # if defined (LOGIC_ANALYZER_CH0_GPIO_PINx) rcu_periph_clock_enable(LOGIC_ANALYZER_CH0_RCU_GPIOx); -# if !defined (GD32F4XX) +# if defined (GPIO_INIT) gpio_init(LOGIC_ANALYZER_CH0_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH0_GPIO_PINx); # else gpio_mode_set(LOGIC_ANALYZER_CH0_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH0_GPIO_PINx); - gpio_output_options_set(LOGIC_ANALYZER_CH0_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH0_GPIO_PINx); + gpio_output_options_set(LOGIC_ANALYZER_CH0_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, LOGIC_ANALYZER_CH0_GPIO_PINx); # endif GPIO_BC(LOGIC_ANALYZER_CH0_GPIOx) = LOGIC_ANALYZER_CH0_GPIO_PINx; # endif # if defined (LOGIC_ANALYZER_CH1_GPIO_PINx) rcu_periph_clock_enable(LOGIC_ANALYZER_CH1_RCU_GPIOx); -# if !defined (GD32F4XX) +# if defined (GPIO_INIT) gpio_init(LOGIC_ANALYZER_CH1_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH1_GPIO_PINx); # else gpio_mode_set(LOGIC_ANALYZER_CH1_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH1_GPIO_PINx); - gpio_output_options_set(LOGIC_ANALYZER_CH1_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH1_GPIO_PINx); + gpio_output_options_set(LOGIC_ANALYZER_CH1_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, LOGIC_ANALYZER_CH1_GPIO_PINx); # endif GPIO_BC(LOGIC_ANALYZER_CH1_GPIOx) = LOGIC_ANALYZER_CH1_GPIO_PINx; # endif # if defined (LOGIC_ANALYZER_CH2_GPIO_PINx) rcu_periph_clock_enable(LOGIC_ANALYZER_CH2_RCU_GPIOx); -# if !defined (GD32F4XX) +# if defined (GPIO_INIT) gpio_init(LOGIC_ANALYZER_CH2_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH2_GPIO_PINx); # else gpio_mode_set(LOGIC_ANALYZER_CH2_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH2_GPIO_PINx); - gpio_output_options_set(LOGIC_ANALYZER_CH2_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH2_GPIO_PINx); + gpio_output_options_set(LOGIC_ANALYZER_CH2_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, LOGIC_ANALYZER_CH2_GPIO_PINx); # endif GPIO_BC(LOGIC_ANALYZER_CH2_GPIOx) = LOGIC_ANALYZER_CH2_GPIO_PINx; # endif # if defined (LOGIC_ANALYZER_CH3_GPIO_PINx) rcu_periph_clock_enable(LOGIC_ANALYZER_CH3_RCU_GPIOx); -# if !defined (GD32F4XX) +# if defined (GPIO_INIT) gpio_init(LOGIC_ANALYZER_CH3_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH3_GPIO_PINx); # else gpio_mode_set(LOGIC_ANALYZER_CH3_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH3_GPIO_PINx); - gpio_output_options_set(LOGIC_ANALYZER_CH3_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH3_GPIO_PINx); + gpio_output_options_set(LOGIC_ANALYZER_CH3_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, LOGIC_ANALYZER_CH3_GPIO_PINx); # endif GPIO_BC(LOGIC_ANALYZER_CH3_GPIOx) = LOGIC_ANALYZER_CH3_GPIO_PINx; # endif # if defined (LOGIC_ANALYZER_CH4_GPIO_PINx) rcu_periph_clock_enable(LOGIC_ANALYZER_CH4_RCU_GPIOx); -# if !defined (GD32F4XX) +# if defined (GPIO_INIT) gpio_init(LOGIC_ANALYZER_CH4_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH4_GPIO_PINx); # else gpio_mode_set(LOGIC_ANALYZER_CH4_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH4_GPIO_PINx); - gpio_output_options_set(LOGIC_ANALYZER_CH4_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH4_GPIO_PINx); + gpio_output_options_set(LOGIC_ANALYZER_CH4_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, LOGIC_ANALYZER_CH4_GPIO_PINx); # endif GPIO_BC(LOGIC_ANALYZER_CH4_GPIOx) = LOGIC_ANALYZER_CH4_GPIO_PINx; # endif # if defined (LOGIC_ANALYZER_CH5_GPIO_PINx) rcu_periph_clock_enable(LOGIC_ANALYZER_CH5_RCU_GPIOx); -# if !defined (GD32F4XX) +# if defined (GPIO_INIT) gpio_init(LOGIC_ANALYZER_CH5_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH5_GPIO_PINx); # else gpio_mode_set(LOGIC_ANALYZER_CH5_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH5_GPIO_PINx); - gpio_output_options_set(LOGIC_ANALYZER_CH5_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH5_GPIO_PINx); + gpio_output_options_set(LOGIC_ANALYZER_CH5_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, LOGIC_ANALYZER_CH5_GPIO_PINx); # endif GPIO_BC(LOGIC_ANALYZER_CH5_GPIOx) = LOGIC_ANALYZER_CH5_GPIO_PINx; # endif # if defined (LOGIC_ANALYZER_CH6_GPIO_PINx) rcu_periph_clock_enable(LOGIC_ANALYZER_CH6_RCU_GPIOx); -# if !defined (GD32F4XX) +# if defined (GPIO_INIT) gpio_init(LOGIC_ANALYZER_CH6_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH6_GPIO_PINx); # else gpio_mode_set(LOGIC_ANALYZER_CH6_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH6_GPIO_PINx); - gpio_output_options_set(LOGIC_ANALYZER_CH6_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH6_GPIO_PINx); + gpio_output_options_set(LOGIC_ANALYZER_CH6_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, LOGIC_ANALYZER_CH6_GPIO_PINx); # endif GPIO_BC(LOGIC_ANALYZER_CH6_GPIOx) = LOGIC_ANALYZER_CH6_GPIO_PINx; # endif # if defined (LOGIC_ANALYZER_CH7_GPIO_PINx) rcu_periph_clock_enable(LOGIC_ANALYZER_CH7_RCU_GPIOx); -# if !defined (GD32F4XX) +# if defined (GPIO_INIT) gpio_init(LOGIC_ANALYZER_CH7_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH7_GPIO_PINx); # else gpio_mode_set(LOGIC_ANALYZER_CH7_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LOGIC_ANALYZER_CH7_GPIO_PINx); - gpio_output_options_set(LOGIC_ANALYZER_CH7_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LOGIC_ANALYZER_CH7_GPIO_PINx); + gpio_output_options_set(LOGIC_ANALYZER_CH7_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, LOGIC_ANALYZER_CH7_GPIO_PINx); # endif GPIO_BC(LOGIC_ANALYZER_CH7_GPIOx) = LOGIC_ANALYZER_CH7_GPIO_PINx; # endif @@ -123,103 +123,101 @@ static void init() { #endif } -static void ch0_clear() { -#if defined (LOGIC_ANALYZER_CH0_GPIO_PINx) +inline void ch0_clear() { +#if defined (LOGIC_ANALYZER_CH0_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BC(LOGIC_ANALYZER_CH0_GPIOx) = LOGIC_ANALYZER_CH0_GPIO_PINx; #endif } -static void ch0_set() { -#if defined (LOGIC_ANALYZER_CH0_GPIO_PINx) +inline void ch0_set() { +#if defined (LOGIC_ANALYZER_CH0_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BOP(LOGIC_ANALYZER_CH0_GPIOx) = LOGIC_ANALYZER_CH0_GPIO_PINx; #endif } -static void ch1_clear() { -#if defined (LOGIC_ANALYZER_CH1_GPIO_PINx) +inline void ch1_clear() { +#if defined (LOGIC_ANALYZER_CH1_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BC(LOGIC_ANALYZER_CH1_GPIOx) = LOGIC_ANALYZER_CH1_GPIO_PINx; #endif } -static void ch1_set() { -#if defined (LOGIC_ANALYZER_CH1_GPIO_PINx) +inline void ch1_set() { +#if defined (LOGIC_ANALYZER_CH1_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BOP(LOGIC_ANALYZER_CH1_GPIOx) = LOGIC_ANALYZER_CH1_GPIO_PINx; #endif } -static void ch2_clear() { -#if defined (LOGIC_ANALYZER_CH2_GPIO_PINx) +inline void ch2_clear() { +#if defined (LOGIC_ANALYZER_CH2_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BC(LOGIC_ANALYZER_CH2_GPIOx) = LOGIC_ANALYZER_CH2_GPIO_PINx; #endif } -static void ch2_set() { -#if defined (LOGIC_ANALYZER_CH2_GPIO_PINx) +inline void ch2_set() { +#if defined (LOGIC_ANALYZER_CH2_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BOP(LOGIC_ANALYZER_CH2_GPIOx) = LOGIC_ANALYZER_CH2_GPIO_PINx; #endif } -static void ch3_clear() { -#if defined (LOGIC_ANALYZER_CH3_GPIO_PINx) +inline void ch3_clear() { +#if defined (LOGIC_ANALYZER_CH3_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BC(LOGIC_ANALYZER_CH3_GPIOx) = LOGIC_ANALYZER_CH3_GPIO_PINx; #endif } -static void ch3_set() { -#if defined (LOGIC_ANALYZER_CH3_GPIO_PINx) +inline void ch3_set() { +#if defined (LOGIC_ANALYZER_CH3_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BOP(LOGIC_ANALYZER_CH3_GPIOx) = LOGIC_ANALYZER_CH3_GPIO_PINx; #endif } -// -static void ch4_clear() { -#if defined (LOGIC_ANALYZER_CH4_GPIO_PINx) +inline void ch4_clear() { +#if defined (LOGIC_ANALYZER_CH4_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BC(LOGIC_ANALYZER_CH4_GPIOx) = LOGIC_ANALYZER_CH4_GPIO_PINx; #endif } -static void ch4_set() { -#if defined (LOGIC_ANALYZER_CH4_GPIO_PINx) +inline void ch4_set() { +#if defined (LOGIC_ANALYZER_CH4_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BOP(LOGIC_ANALYZER_CH4_GPIOx) = LOGIC_ANALYZER_CH4_GPIO_PINx; #endif } -static void ch5_clear() { -#if defined (LOGIC_ANALYZER_CH5_GPIO_PINx) +inline void ch5_clear() { +#if defined (LOGIC_ANALYZER_CH5_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BC(LOGIC_ANALYZER_CH5_GPIOx) = LOGIC_ANALYZER_CH5_GPIO_PINx; #endif } -static void ch5_set() { -#if defined (LOGIC_ANALYZER_CH5_GPIO_PINx) +inline void ch5_set() { +#if defined (LOGIC_ANALYZER_CH5_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BOP(LOGIC_ANALYZER_CH5_GPIOx) = LOGIC_ANALYZER_CH5_GPIO_PINx; #endif } -static void ch6_clear() { -#if defined (LOGIC_ANALYZER_CH6_GPIO_PINx) +inline void ch6_clear() { +#if defined (LOGIC_ANALYZER_CH6_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BC(LOGIC_ANALYZER_CH6_GPIOx) = LOGIC_ANALYZER_CH6_GPIO_PINx; #endif } -static void ch6_set() { -#if defined (LOGIC_ANALYZER_CH6_GPIO_PINx) +inline void ch6_set() { +#if defined (LOGIC_ANALYZER_CH6_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BOP(LOGIC_ANALYZER_CH6_GPIOx) = LOGIC_ANALYZER_CH6_GPIO_PINx; #endif } -static void ch7_clear() { -#if defined (LOGIC_ANALYZER_CH7_GPIO_PINx) +inline void ch7_clear() { +#if defined (LOGIC_ANALYZER_CH7_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BC(LOGIC_ANALYZER_CH7_GPIOx) = LOGIC_ANALYZER_CH7_GPIO_PINx; #endif } -static void ch7_set() { -#if defined (LOGIC_ANALYZER_CH7_GPIO_PINx) +inline void ch7_set() { +#if defined (LOGIC_ANALYZER_CH7_GPIO_PINx) && defined (LOGIC_ANALYZER) GPIO_BOP(LOGIC_ANALYZER_CH7_GPIOx) = LOGIC_ANALYZER_CH7_GPIO_PINx; #endif } - } // namespace logic_analyzer #endif /* LOGIC_ANALYZER_H_ */ diff --git a/lib-gd32/include/mcu/gd32f207_mcu.h b/lib-gd32/include/mcu/gd32f207_mcu.h new file mode 100644 index 00000000..ae856918 --- /dev/null +++ b/lib-gd32/include/mcu/gd32f207_mcu.h @@ -0,0 +1,44 @@ +/** + * @file gd32f207_mcu.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MCU_GD32F207_MCU_H_ +#define MCU_GD32F207_MCU_H_ + +#if !defined(GD32F20X_CL) +# error This file should not be included +#endif + +#include + +#define MCU_CLOCK_FREQ (uint32_t)(120000000) +#define AHB_CLOCK_FREQ (uint32_t)(120000000) +#define APB1_CLOCK_FREQ (uint32_t)(60000000) +#define APB2_CLOCK_FREQ (uint32_t)(120000000) +#define TIMER_PSC_1MHZ (uint16_t)(119) +#define TIMER_PSC_10KHZ (uint16_t)(11999) + +#include "gd32f20x_mcu.h" + +#endif /* MCU_GD32F207_MCU_H_ */ diff --git a/lib-gd32/include/mcu/gd32f20x_mcu.h b/lib-gd32/include/mcu/gd32f20x_mcu.h index ce26b135..1ab03b73 100644 --- a/lib-gd32/include/mcu/gd32f20x_mcu.h +++ b/lib-gd32/include/mcu/gd32f20x_mcu.h @@ -2,7 +2,7 @@ * @file gd32f20x_mcu.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,14 +32,6 @@ #include -#define MCU_CLOCK_FREQ (uint32_t)(120000000) -#define APB1_CLOCK_FREQ (uint32_t)(60000000) -#define APB2_CLOCK_FREQ (uint32_t)(120000000) -#define TIMER_PSC_1MHZ (uint16_t)(119) -#define TIMER_PSC_10KHZ (uint16_t)(11999) - -#include "gd32f20x_libopt.h" - /** * */ @@ -50,113 +42,113 @@ * U(S)ART */ -#define USART0_RCU_CLK RCU_USART0 +#define USART0_RCU_USART0 RCU_USART0 #if defined (USART0_REMAP) -# define USART0_GPIO_PORT GPIOB -# define USART0_GPIO_CLK RCU_GPIOB -# define USART0_TX_PIN GPIO_PIN_6 -# define USART0_RX_PIN GPIO_PIN_7 +# define USART0_RCU_GPIOx RCU_GPIOB +# define USART0_GPIOx GPIOB +# define USART0_TX_GPIO_PINx GPIO_PIN_6 +# define USART0_RX_GPIO_PINx GPIO_PIN_7 #else -# define USART0_GPIO_PORT GPIOA -# define USART0_GPIO_CLK RCU_GPIOA -# define USART0_TX_PIN GPIO_PIN_9 -# define USART0_RX_PIN GPIO_PIN_10 +# define USART0_RCU_GPIOx RCU_GPIOA +# define USART0_GPIOx GPIOA +# define USART0_TX_GPIO_PINx GPIO_PIN_9 +# define USART0_RX_GPIO_PINx GPIO_PIN_10 #endif -#define USART1_RCU_CLK RCU_USART1 +#define USART1_RCU_USART1 RCU_USART1 #if defined (USART1_REMAP) -# define USART1_GPIO_PORT GPIOD -# define USART1_GPIO_CLK RCU_GPIOD -# define USART1_TX_PIN GPIO_PIN_5 -# define USART1_RX_PIN GPIO_PIN_6 +# define USART1_RCU_GPIOx RCU_GPIOD +# define USART1_GPIOx GPIOD +# define USART1_TX_GPIO_PINx GPIO_PIN_5 +# define USART1_RX_GPIO_PINx GPIO_PIN_6 #else -# define USART1_GPIO_PORT GPIOA -# define USART1_GPIO_CLK RCU_GPIOA -# define USART1_TX_PIN GPIO_PIN_2 -# define USART1_RX_PIN GPIO_PIN_3 +# define USART1_RCU_GPIOx RCU_GPIOA +# define USART1_GPIOx GPIOA +# define USART1_TX_GPIO_PINx GPIO_PIN_2 +# define USART1_RX_GPIO_PINx GPIO_PIN_3 #endif -#define USART2_RCU_CLK RCU_USART2 +#define USART2_RCU_USART2 RCU_USART2 #if defined (USART2_FULL_REMAP) -# define USART2_GPIO_PORT GPIOD -# define USART2_GPIO_CLK RCU_GPIOD -# define USART2_TX_PIN GPIO_PIN_8 -# define USART2_RX_PIN GPIO_PIN_9 +# define USART2_RCU_GPIOx RCU_GPIOD +# define USART2_GPIOx GPIOD +# define USART2_TX_GPIO_PINx GPIO_PIN_8 +# define USART2_RX_GPIO_PINx GPIO_PIN_9 #elif defined (USART2_PARTIAL_REMAP) -# define USART2_GPIO_PORT GPIOC -# define USART2_GPIO_CLK RCU_GPIOC -# define USART2_TX_PIN GPIO_PIN_10 -# define USART2_RX_PIN GPIO_PIN_11 +# define USART2_RCU_GPIOx RCU_GPIOC +# define USART2_GPIOx GPIOC +# define USART2_TX_GPIO_PINx GPIO_PIN_10 +# define USART2_RX_GPIO_PINx GPIO_PIN_11 #else -# define USART2_GPIO_PORT GPIOB -# define USART2_GPIO_CLK RCU_GPIOB -# define USART2_TX_PIN GPIO_PIN_10 -# define USART2_RX_PIN GPIO_PIN_11 +# define USART2_RCU_GPIOx RCU_GPIOB +# define USART2_GPIOx GPIOB +# define USART2_TX_GPIO_PINx GPIO_PIN_10 +# define USART2_RX_GPIO_PINx GPIO_PIN_11 #endif -#define UART3_RCU_CLK RCU_UART3 +#define UART3_RCU_UART3 RCU_UART3 #if defined (UART3_REMAP) -# define UART3_GPIO_PORT GPIOA -# define UART3_GPIO_CLK RCU_GPIOA -# define UART3_TX_PIN GPIO_PIN_0 -# define UART3_RX_PIN GPIO_PIN_1 +# define UART3_RCU_GPIOx RCU_GPIOA +# define UART3_GPIOx GPIOA +# define UART3_TX_GPIO_PINx GPIO_PIN_0 +# define UART3_RX_GPIO_PINx GPIO_PIN_1 #else -# define UART3_GPIO_PORT GPIOC -# define UART3_GPIO_CLK RCU_GPIOC -# define UART3_TX_PIN GPIO_PIN_10 -# define UART3_RX_PIN GPIO_PIN_11 +# define UART3_RCU_GPIOx RCU_GPIOC +# define UART3_GPIOx GPIOC +# define UART3_TX_GPIO_PINx GPIO_PIN_10 +# define UART3_RX_GPIO_PINx GPIO_PIN_11 #endif -#define UART4_RCU_CLK RCU_UART4 -#define UART4_GPIO_TX_PORT GPIOC -#define UART4_GPIO_TX_CLK RCU_GPIOC -#define UART4_GPIO_RX_PORT GPIOD -#define UART4_GPIO_RX_CLK RCU_GPIOD -#define UART4_TX_PIN GPIO_PIN_12 -#define UART4_RX_PIN GPIO_PIN_2 +#define UART4_RCU_UART4 RCU_UART4 +#define UART4_TX_RCU_GPIOx RCU_GPIOC +#define UART4_TX_GPIOx GPIOC +#define UART4_TX_GPIO_PINx GPIO_PIN_12 +#define UART4_RX_RCU_GPIOx RCU_GPIOD +#define UART4_RX_GPIOx GPIOD +#define UART4_RX_GPIO_PINx GPIO_PIN_2 -#define USART5_RCU_CLK RCU_USART5 +#define USART5_RCU_USART5 RCU_USART5 #if defined (USART5_REMAP) -# define USART5_GPIO_PORT GPIOG -# define USART5_GPIO_CLK RCU_GPIOG -# define USART5_TX_PIN GPIO_PIN_14 -# define USART5_RX_PIN GPIO_PIN_9 +# define USART5_RCU_GPIOx RCU_GPIOG +# define USART5_GPIOx GPIOG +# define USART5_TX_GPIO_PINx GPIO_PIN_14 +# define USART5_RX_GPIO_PINx GPIO_PIN_9 #else -# define USART5_GPIO_PORT GPIOC -# define USART5_GPIO_CLK RCU_GPIOC -# define USART5_TX_PIN GPIO_PIN_6 -# define USART5_RX_PIN GPIO_PIN_7 +# define USART5_RCU_GPIOx RCU_GPIOC +# define USART5_GPIOx GPIOC +# define USART5_TX_GPIO_PINx GPIO_PIN_6 +# define USART5_RX_GPIO_PINx GPIO_PIN_7 #endif -#define UART6_RCU_CLK RCU_UART6 +#define UART6_RCU_UART6 RCU_UART6 #if defined (UART6_REMAP) -# define UART6_GPIO_PORT GPIOF -# define UART6_GPIO_CLK RCU_GPIOF -# define UART6_TX_PIN GPIO_PIN_7 -# define UART6_RX_PIN GPIO_PIN_6 +# define UART6_RCU_GPIOx RCU_GPIOF +# define UART6_GPIOx GPIOF +# define UART6_TX_GPIO_PINx GPIO_PIN_7 +# define UART6_RX_GPIO_PINx GPIO_PIN_6 #else -# define UART6_GPIO_PORT GPIOE -# define UART6_GPIO_CLK RCU_GPIOE -# define UART6_TX_PIN GPIO_PIN_8 -# define UART6_RX_PIN GPIO_PIN_7 +# define UART6_RCU_GPIOx RCU_GPIOE +# define UART6_GPIOx GPIOE +# define UART6_TX_GPIO_PINx GPIO_PIN_8 +# define UART6_RX_GPIO_PINx GPIO_PIN_7 #endif -#define UART7_RCU_CLK RCU_UART7 -#define UART7_GPIO_PORT GPIOE -#define UART7_GPIO_CLK RCU_GPIOE -#define UART7_TX_PIN GPIO_PIN_1 -#define UART7_RX_PIN GPIO_PIN_0 +#define UART7_RCU_UART7 RCU_UART7 +#define UART7_RCU_GPIOx RCU_GPIOE +#define UART7_GPIOx GPIOE +#define UART7_TX_GPIO_PINx GPIO_PIN_1 +#define UART7_RX_GPIO_PINx GPIO_PIN_0 /** * I2C */ #define I2C0_PERIPH I2C0 -#define I2C0_RCU_CLK RCU_I2C0 -#define I2C0_SCL_GPIOx GPIOB +#define I2C0_RCU_I2C0 RCU_I2C0 #define I2C0_SCL_RCU_GPIOx RCU_GPIOB -#define I2C0_SDA_GPIOx GPIOB +#define I2C0_SCL_GPIOx GPIOB #define I2C0_SDA_RCU_GPIOx RCU_GPIOB +#define I2C0_SDA_GPIOx GPIOB #if defined (I2C0_REMAP) # define I2C0_SCL_GPIO_PINx GPIO_PIN_8 # define I2C0_SDA_GPIO_PINx GPIO_PIN_9 @@ -166,186 +158,239 @@ #endif #define I2C1_PERIPH I2C1 -#define I2C1_RCU_CLK RCU_I2C1 +#define I2C1_RCU_I2C1 RCU_I2C1 #if defined (I2C1_REMAP10) -# define I2C1_SCL_GPIOx GPIOH # define I2C1_SCL_RCU_GPIOx RCU_GPIOH -# define I2C1_SDA_GPIOx GPIOH -# define I2C1_SDA_RCU_GPIOx RCU_GPIOH +# define I2C1_SCL_GPIOx GPIOH # define I2C1_SCL_GPIO_PINx GPIO_PIN_4 +# define I2C1_SDA_RCU_GPIOx RCU_GPIOH +# define I2C1_SDA_GPIOx GPIOH # define I2C1_SDA_GPIO_PINx GPIO_PIN_5 #elif defined (I2C1_REMAP11) -# define I2C1_SCL_GPIOx GPIOF # define I2C1_SCL_RCU_GPIOx RCU_GPIOF -# define I2C1_SDA_GPIOx GPIOF -# define I2C1_SDA_RCU_GPIOx RCU_GPIOF +# define I2C1_SCL_GPIOx GPIOF # define I2C1_SCL_GPIO_PINx GPIO_PIN_0 +# define I2C1_SDA_RCU_GPIOx RCU_GPIOF +# define I2C1_SDA_GPIOx GPIOF # define I2C1_SDA_GPIO_PINx GPIO_PIN_1 #else -# define I2C1_SCL_GPIOx GPIOB # define I2C1_SCL_RCU_GPIOx RCU_GPIOB -# define I2C1_SDA_GPIOx GPIOB -# define I2C1_SDA_RCU_GPIOx RCU_GPIOB +# define I2C1_SCL_GPIOx GPIOB # define I2C1_SCL_GPIO_PINx GPIO_PIN_10 +# define I2C1_SDA_RCU_GPIOx RCU_GPIOB +# define I2C1_SDA_GPIOx GPIOB # define I2C1_SDA_GPIO_PINx GPIO_PIN_11 #endif #define I2C2_PERIPH I2C2 -#define I2C2_RCU_CLK RCU_I2C2 +#define I2C2_RCU_I2C2 RCU_I2C2 #if defined (I2C2_REMAP) -# define I2C2_GPIO_SCL_PORT GPIOH -# define I2C2_GPIO_SCL_CLK RCU_GPIOH -# define I2C2_SCL_PIN GPIO_PIN_7 -# define I2C2_GPIO_SDA_PORT GPIOH -# define I2C2_GPIO_SDA_CLK RCU_GPIOH -# define I2C2_SDA_PIN GPIO_PIN_8 +# define I2C2_SCL_GPIOx GPIOH +# define I2C2_SCL_RCU_GPIOx RCU_GPIOH +# define I2C2_SCL_GPIO_PINx GPIO_PIN_7 +# define I2C2_SDA_GPIOx GPIOH +# define I2C2_SDA_RCU_GPIOx RCU_GPIOH +# define I2C2_SDA_GPIO_PINx GPIO_PIN_8 #else -# define I2C2_GPIO_SCL_PORT GPIOA -# define I2C2_GPIO_SCL_CLK RCU_GPIOA -# define I2C2_SCL_PIN GPIO_PIN_8 -# define I2C2_GPIO_SDA_PORT GPIOC -# define I2C2_GPIO_SDA_CLK RCU_GPIOC -# define I2C2_SDA_PIN GPIO_PIN_9 +# define I2C2_SCL_GPIOx GPIOA +# define I2C2_SCL_RCU_GPIOx RCU_GPIOA +# define I2C2_SCL_GPIO_PINx GPIO_PIN_8 +# define I2C2_SDA_GPIOx GPIOC +# define I2C2_SDA_RCU_GPIOx RCU_GPIOC +# define I2C2_SDA_GPIO_PINx GPIO_PIN_9 #endif /** * SPI */ -#define SPI0_PERiPH SPI0 -#define SPI0_RCU_CLK RCU_SPI0 +#define SPI0_PERIPH SPI0 +#define SPI0_RCU_SPI0 RCU_SPI0 #if defined (SPI0_REMAP) # define SPI0_REMAP_GPIO GPIO_SPI0_REMAP -# define SPI0_NSS_GPIOx GPIOA -# define SPI0_NSS_RCU_GPIOx RCU_GPIOA -# define SPI0_NSS_GPIO_PINx GPIO_PIN_15 # define SPI0_GPIOx GPIOB # define SPI0_RCU_GPIOx RCU_GPIOB # define SPI0_SCK_GPIO_PINx GPIO_PIN_3 # define SPI0_MISO_GPIO_PINx GPIO_PIN_4 # define SPI0_MOSI_GPIO_PINx GPIO_PIN_5 -#else -# define SPI0_NSS_GPIOx GPIOA # define SPI0_NSS_RCU_GPIOx RCU_GPIOA -# define SPI0_NSS_GPIO_PINx GPIO_PIN_4 +# define SPI0_NSS_GPIOx GPIOA +# define SPI0_NSS_GPIO_PINx GPIO_PIN_15 +#else # define SPI0_GPIOx GPIOA # define SPI0_RCU_GPIOx RCU_GPIOA # define SPI0_SCK_GPIO_PINx GPIO_PIN_5 # define SPI0_MISO_GPIO_PINx GPIO_PIN_6 # define SPI0_MOSI_GPIO_PINx GPIO_PIN_7 +# define SPI0_IO3_GPIO_PINx GPIO_PIN_2 +# define SPI0_IO4_GPIO_PINx GPIO_PIN_3 +# define SPI0_NSS_RCU_GPIOx RCU_GPIOA +# define SPI0_NSS_GPIOx GPIOA +# define SPI0_NSS_GPIO_PINx GPIO_PIN_4 #endif #define SPI1_PERIPH SPI1 -#define SPI1_RCU_CLK RCU_SPI1 +#define SPI1_RCU_SPI1 RCU_SPI1 #if defined (SPI1_REMAP10) -# define SPI1_NSS_GPIOx GPIOI -# define SPI1_NSS_RCU_GPIOx RCU_GPIOI -# define SPI1_NSS_GPIO_PINx GPIO_PIN_0 -# define SPI1_GPIOx GPIOI # define SPI1_RCU_GPIOx RCU_GPIOI +# define SPI1_GPIOx GPIOI # define SPI1_SCK_GPIO_PINx GPIO_PIN_1 # define SPI1_MISO_GPIO_PINx GPIO_PIN_2 # define SPI1_MOSI_GPIO_PINx GPIO_PIN_3 +# define SPI1_NSS_RCU_GPIOx RCU_GPIOI +# define SPI1_NSS_GPIOx GPIOI +# define SPI1_NSS_GPIO_PINx GPIO_PIN_0 #elif defined (SPI1_REMAP11) # error SPI1_REMAP11 is not defined #else -# define SPI1_NSS_GPIOx GPIOB -# define SPI1_NSS_RCU_GPIOx RCU_GPIOB -# define SPI1_NSS_GPIO_PINx GPIO_PIN_12 -# define SPI1_GPIOx GPIOB # define SPI1_RCU_GPIOx RCU_GPIOB +# define SPI1_GPIOx GPIOB # define SPI1_SCK_GPIO_PINx GPIO_PIN_13 # define SPI1_MISO_GPIO_PINx GPIO_PIN_14 # define SPI1_MOSI_GPIO_PINx GPIO_PIN_15 +# define SPI1_NSS_RCU_GPIOx RCU_GPIOB +# define SPI1_NSS_GPIOx GPIOB +# define SPI1_NSS_GPIO_PINx GPIO_PIN_12 #endif #define SPI2_PERIPH SPI2 -#define SPI2_RCU_CLK RCU_SPI2 +#define SPI2_RCU_SPI2 RCU_SPI2 #if defined (SPI2_REMAP) # define SPI2_REMAP_GPIO GPIO_SPI2_REMAP -# define SPI2_NSS_GPIOx GPIOA -# define SPI2_NSS_RCU_GPIOx RCU_GPIOA -# define SPI2_NSS_GPIO_PINx GPIO_PIN_4 -# define SPI2_GPIOx GPIOC # define SPI2_RCU_GPIOx RCU_GPIOC +# define SPI2_GPIOx GPIOC # define SPI2_SCK_GPIO_PINx GPIO_PIN_10 # define SPI2_MISO_GPIO_PINx GPIO_PIN_11 # define SPI2_MOSI_GPIO_PINx GPIO_PIN_12 -#else -# define SPI2_NSS_GPIOx GPIOA # define SPI2_NSS_RCU_GPIOx RCU_GPIOA -# define SPI2_NSS_GPIO_PINx GPIO_PIN_15 -# define SPI2_GPIOx GPIOB +# define SPI2_NSS_GPIOx GPIOA +# define SPI2_NSS_GPIO_PINx GPIO_PIN_4 +#else # define SPI2_RCU_GPIOx RCU_GPIOB +# define SPI2_GPIOx GPIOB # define SPI2_SCK_GPIO_PINx GPIO_PIN_3 # define SPI2_MISO_GPIO_PINx GPIO_PIN_4 # define SPI2_MOSI_GPIO_PINx GPIO_PIN_5 +# define SPI2_NSS_RCU_GPIOx RCU_GPIOA +# define SPI2_NSS_GPIOx GPIOA +# define SPI2_NSS_GPIO_PINx GPIO_PIN_15 #endif /** * TIMER GPIO */ -#define TIMER2CH0_RCU_GPIOx RCU_GPIOA -#define TIMER2CH0_GPIOx GPIOA -#define TIMER2CH0_GPIO_PINx GPIO_PIN_6 +#define TIMER2CH0_RCU_GPIOx RCU_GPIOA +#define TIMER2CH0_GPIOx GPIOA +#define TIMER2CH0_GPIO_PINx GPIO_PIN_6 + +#if defined(TIMER2_FULL_REMAP) +# define TIMER2_REMAP GPIO_TIMER2_FULL_REMAP +# define TIMER2_CH0_RCU_GPIOx RCU_GPIOC +# define TIMER2_CH0_GPIOx GPIOC +# define TIMER2_CH0_GPIO_PINx GPIO_PIN_6 + +# define TIMER2_CH1_RCU_GPIOx RCU_GPIOC +# define TIMER2_CH1_GPIOx GPIOC +# define TIMER2_CH1_GPIO_PINx GPIO_PIN_7 + +# define TIMER2_CH2_RCU_GPIOx RCU_GPIOC +# define TIMER2_CH2_GPIOx GPIOC +# define TIMER2_CH2_GPIO_PINx GPIO_PIN_8 + +# define TIMER2_CH3_RCU_GPIOx RCU_GPIOC +# define TIMER2_CH3_GPIOx GPIOC +# define TIMER2_CH3_GPIO_PINx GPIO_PIN_9 +#elif defined(TIMER2_PARTIAL_REMAP) +# define TIMER2_REMAP GPIO_TIMER2_PARTIAL_REMAP +# define TIMER2_CH0_RCU_GPIOx RCU_GPIOB +# define TIMER2_CH0_GPIOx GPIOB +# define TIMER2_CH0_GPIO_PINx GPIO_PIN_4 + +# define TIMER2_CH1_RCU_GPIOx RCU_GPIOB +# define TIMER2_CH1_GPIOx GPIOB +# define TIMER2_CH1_GPIO_PINx GPIO_PIN_5 + +# define TIMER2_CH2_RCU_GPIOx RCU_GPIOB +# define TIMER2_CH2_GPIOx GPIOB +# define TIMER2_CH2_GPIO_PINx GPIO_PIN_0 + +# define TIMER2_CH3_RCU_GPIOx RCU_GPIOB +# define TIMER2_CH3_GPIOx GPIOB +# define TIMER2_CH3_GPIO_PINx GPIO_PIN_1 +#else +# define TIMER2_CH0_RCU_GPIOx RCU_GPIOA +# define TIMER2_CH0_GPIOx GPIOA +# define TIMER2_CH0_GPIO_PINx GPIO_PIN_6 + +# define TIMER2_CH1_RCU_GPIOx RCU_GPIOA +# define TIMER2_CH1_GPIOx GPIOA +# define TIMER2_CH1_GPIO_PINx GPIO_PIN_7 + +# define TIMER2_CH2_RCU_GPIOx RCU_GPIOB +# define TIMER2_CH2_GPIOx GPIOB +# define TIMER2_CH2_GPIO_PINx GPIO_PIN_0 + +# define TIMER2_CH3_RCU_GPIOx RCU_GPIOB +# define TIMER2_CH3_GPIOx GPIOB +# define TIMER2_CH3_GPIO_PINx GPIO_PIN_1 +#endif /** * DMA */ -#define SPI0_DMAx DMA0 -#define SPI0_TX_DMA_CHx DMA_CH2 +#define SPI0_DMAx DMA0 +#define SPI0_TX_DMA_CHx DMA_CH2 -#define SPI1_DMAx DMA0 -#define SPI1_TX_DMA_CHx DMA_CH4 +#define SPI1_DMAx DMA0 +#define SPI1_TX_DMA_CHx DMA_CH4 -#define SPI2_DMAx DMA1 -#define SPI2_TX_DMA_CHx DMA_CH1 +#define SPI2_DMAx DMA1 +#define SPI2_TX_DMA_CHx DMA_CH1 -#define TIMER2_RCU_DMAx RCU_DMA0 -#define TIMER2_DMAx DMA0 -#define TIMER2_CH0_DMA_CHx DMA_CH5 -// #define TIMER2_CH1_DMA_CHx -#define TIMER2_CH2_DMA_CHx DMA_CH1 -#define TIMER2_CH3_DMA_CHx DMA_CH2 +#define TIMER2_RCU_DMAx RCU_DMA0 +#define TIMER2_DMAx DMA0 +#define TIMER2_CH0_DMA_CHx DMA_CH5 +#define TIMER2_CH2_DMA_CHx DMA_CH1 +#define TIMER2_CH3_DMA_CHx DMA_CH2 -#define TIMER7_RCU_DMAx RCU_DMA1 -#define TIMER7_DMAx DMA1 -#define TIMER7_CH0_DMA_CHx DMA_CH2 -#define TIMER7_CH1_DMA_CHx DMA_CH4 -#define TIMER7_CH2_DMA_CHx DMA_CH0 +#define TIMER7_RCU_DMAx RCU_DMA1 +#define TIMER7_DMAx DMA1 +#define TIMER7_CH0_DMA_CHx DMA_CH2 +#define TIMER7_CH1_DMA_CHx DMA_CH4 +#define TIMER7_CH2_DMA_CHx DMA_CH0 -#define USART0_DMA DMA0 -#define USART0_TX_DMA_CH DMA_CH3 -#define USART0_RX_DMA_CH DMA_CH4 +#define USART0_DMAx DMA0 +#define USART0_TX_DMA_CHx DMA_CH3 +#define USART0_RX_DMA_CHx DMA_CH4 -#define USART1_DMA DMA0 -#define USART1_TX_DMA_CH DMA_CH6 -#define USART1_RX_DMA_CH DMA_CH5 +#define USART1_DMAx DMA0 +#define USART1_TX_DMA_CHx DMA_CH6 +#define USART1_RX_DMA_CHx DMA_CH5 -#define USART2_DMA DMA0 -#define USART2_TX_DMA_CH DMA_CH1 -#define USART2_RX_DMA_CH DMA_CH2 +#define USART2_DMAx DMA0 +#define USART2_TX_DMA_CHx DMA_CH1 +#define USART2_RX_DMA_CHx DMA_CH2 -#define UART3_DMA DMA1 -#define UART3_TX_DMA_CH DMA_CH4 -#define UART3_RX_DMA_CH DMA_CH2 +#define UART3_DMAx DMA1 +#define UART3_TX_DMA_CHx DMA_CH4 +#define UART3_RX_DMA_CHx DMA_CH2 -#define UART4_DMA DMA1 -#define UART4_TX_DMA_CH DMA_CH3 -#define UART4_RX_DMA_CH DMA_CH1 +#define UART4_DMAx DMA1 +#define UART4_TX_DMA_CHx DMA_CH3 +#define UART4_RX_DMA_CHx DMA_CH1 -#define USART5_DMA DMA1 -#define USART5_TX_DMA_CH DMA_CH6 -#define USART5_RX_DMA_CH DMA_CH5 +#define USART5_DMAx DMA1 +#define USART5_TX_DMA_CHx DMA_CH6 +#define USART5_RX_DMA_CHx DMA_CH5 -#define UART6_DMA DMA1 -#define UART6_TX_DMA_CH DMA_CH4 -#define UART6_RX_DMA_CH DMA_CH2 +#define UART6_DMAx DMA1 +#define UART6_TX_DMA_CHx DMA_CH4 +#define UART6_RX_DMA_CHx DMA_CH2 -#define UART7_DMA DMA1 -#define UART7_TX_DMA_CH DMA_CH3 -#define UART7_RX_DMA_CH DMA_CH1 +#define UART7_DMAx DMA1 +#define UART7_TX_DMA_CHx DMA_CH3 +#define UART7_RX_DMA_CHx DMA_CH1 #endif /* MCU_GD32F20X_MCU_H_ */ diff --git a/lib-gd32/src/bkp.cpp b/lib-gd32/src/bkp.cpp index 74349c53..bd4d57d8 100644 --- a/lib-gd32/src/bkp.cpp +++ b/lib-gd32/src/bkp.cpp @@ -2,7 +2,7 @@ * @file bkp.cpp * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,18 +23,39 @@ * THE SOFTWARE. */ +#include + #include "gd32.h" -#if defined (GD32F4XX) +#if defined (GD32F4XX) || defined (GD32H7XX) void bkp_data_write(bkp_data_register_enum register_number, uint16_t data) { - if ((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_1)) { - REG16((BKPSRAM_BASE) + 16 + (register_number) * 2) = data; + switch (register_number) { + case BKP_DATA_0: + RTC_BKP0 = (uint32_t) data; + break; + case BKP_DATA_1: + RTC_BKP1 = (uint32_t) data; + break; + default: + assert(0); + break; } } + uint16_t bkp_data_read(bkp_data_register_enum register_number) { - if ((register_number >= BKP_DATA_0) && (register_number <= BKP_DATA_1)) { - return REG16((BKPSRAM_BASE) + 16 + (register_number) * 2); + switch (register_number) { + case BKP_DATA_0: + return RTC_BKP0; + break; + case BKP_DATA_1: + return RTC_BKP1; + break; + default: + assert(0); + break; } + + assert(0); return 0; } #endif diff --git a/lib-gd32/src/gd32_adc.cpp b/lib-gd32/src/f/gd32_adc.cpp similarity index 96% rename from lib-gd32/src/gd32_adc.cpp rename to lib-gd32/src/f/gd32_adc.cpp index 43479213..294b2951 100644 --- a/lib-gd32/src/gd32_adc.cpp +++ b/lib-gd32/src/f/gd32_adc.cpp @@ -27,7 +27,7 @@ #include "gd32.h" -void gd32_adc_init(void) { +void gd32_adc_init() { rcu_periph_clock_enable(RCU_ADC0); #if !defined (GD32F4XX) rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV12); @@ -86,21 +86,20 @@ void gd32_adc_init(void) { adc_software_trigger_enable(ADC0, ADC_INSERTED_CHANNEL); } -float gd32_adc_gettemp(void) { - /* value convert */ +float gd32_adc_gettemp() { const float temperature = (1.43f - ADC_IDATA0(ADC0) * 3.3f / 4096) * 1000 / 4.3f + 25; adc_software_trigger_enable(ADC0, ADC_INSERTED_CHANNEL); return temperature; } -float gd32_adc_getvref(void) { +float gd32_adc_getvref() { const float vref_value = (ADC_IDATA1(ADC0) * 3.3f / 4096); adc_software_trigger_enable(ADC0, ADC_INSERTED_CHANNEL); return vref_value; } #if defined (GD32F4XX) -float gd32_adc_getvbat(void) { +float gd32_adc_getvbat() { const float vref_value = (ADC_IDATA2(ADC0) * 3.3f / 4096) * 4; adc_software_trigger_enable(ADC0, ADC_INSERTED_CHANNEL); return vref_value; diff --git a/lib-gd32/src/f/gd32_dma_memcpy32.cpp b/lib-gd32/src/f/gd32_dma_memcpy32.cpp new file mode 100644 index 00000000..55625b32 --- /dev/null +++ b/lib-gd32/src/f/gd32_dma_memcpy32.cpp @@ -0,0 +1,55 @@ +/* + * gd32_dma_memcpy32.cpp + */ + +#include +#include + +#include "gd32.h" + +namespace dma { +void memcpy32_init() { +#if !defined (GD32F4XX) + rcu_periph_clock_enable(RCU_DMA0); + dma_deinit(DMA0, DMA_CH3); + + dma_parameter_struct dma_init_struct; + dma_struct_para_init(&dma_init_struct); + + dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; +// dma_init_struct.memory_addr = destination; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_32BIT; + dma_init_struct.number = 0; // BUFFER_SIZE; +// dma_init_struct.periph_addr = source + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_ENABLE; + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_32BIT; + dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; + + dma_init(DMA0, DMA_CH3, &dma_init_struct); + dma_circulation_disable(DMA0, DMA_CH3); + dma_memory_to_memory_enable(DMA0, DMA_CH3); +#else + rcu_periph_clock_enable(RCU_DMA1); + dma_deinit(DMA1, DMA_CH0); + + dma_multi_data_parameter_struct dma_init_parameter; + +// dma_init_parameter.periph_addr = source; + dma_init_parameter.periph_width = DMA_PERIPH_WIDTH_32BIT; + dma_init_parameter.periph_inc = DMA_PERIPH_INCREASE_ENABLE; +// dma_init_parameter.memory0_addr = destination; + dma_init_parameter.memory_width = DMA_MEMORY_WIDTH_32BIT; + dma_init_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE; + dma_init_parameter.memory_burst_width = DMA_MEMORY_BURST_4_BEAT; + dma_init_parameter.periph_burst_width = DMA_PERIPH_BURST_4_BEAT; + dma_init_parameter.critical_value = DMA_FIFO_4_WORD; + dma_init_parameter.circular_mode = DMA_CIRCULAR_MODE_DISABLE; + dma_init_parameter.direction = DMA_MEMORY_TO_MEMORY; + dma_init_parameter.number = 0; // BUFFER_SIZE; + dma_init_parameter.priority = DMA_PRIORITY_ULTRA_HIGH; + + dma_multi_data_mode_init(DMA1, DMA_CH0, &dma_init_parameter); +#endif +} +} // namespace dma diff --git a/lib-gd32/src/gd32_i2c.cpp b/lib-gd32/src/f/gd32_i2c.cpp similarity index 67% rename from lib-gd32/src/gd32_i2c.cpp rename to lib-gd32/src/f/gd32_i2c.cpp index 2a233991..880f1146 100644 --- a/lib-gd32/src/gd32_i2c.cpp +++ b/lib-gd32/src/f/gd32_i2c.cpp @@ -2,7 +2,7 @@ * @file gd32_i2c.cpp * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,6 +24,7 @@ */ #include +#include #include "gd32_i2c.h" #include "gd32.h" @@ -32,21 +33,18 @@ static constexpr int32_t TIMEOUT = 0xfff; static uint8_t s_nAddress; -static int32_t _sendstart(void) { +static int32_t send_start() { auto nTimeout = TIMEOUT; - /* wait until I2C bus is idle */ while (i2c_flag_get(I2C_PERIPH, I2C_FLAG_I2CBSY)) { if (--nTimeout <= 0) { return -GD32_I2C_NOK_TOUT; } } - nTimeout = TIMEOUT; - - /* send a start condition to I2C bus */ i2c_start_on_bus(I2C_PERIPH); + nTimeout = TIMEOUT; /* wait until SBSEND bit is set */ while (!i2c_flag_get(I2C_PERIPH, I2C_FLAG_SBSEND)) { if (--nTimeout <= 0) { @@ -57,25 +55,22 @@ static int32_t _sendstart(void) { return GD32_I2C_OK; } -static int32_t _sendslaveaddr(void) { - auto nTimeout = TIMEOUT; - - /* send slave address to I2C bus */ +static int32_t send_slaveaddr() { i2c_master_addressing(I2C_PERIPH, s_nAddress, I2C_TRANSMITTER); - /* wait until ADDSEND bit is set */ + auto nTimeout = TIMEOUT; + while (!i2c_flag_get(I2C_PERIPH, I2C_FLAG_ADDSEND)) { if (--nTimeout <= 0) { return -GD32_I2C_NOK_TOUT; } } - /* clear the ADDSEND bit */ + i2c_flag_clear(I2C_PERIPH, I2C_FLAG_ADDSEND); nTimeout = TIMEOUT; - /* wait until the transmit data buffer is empty */ while (SET != i2c_flag_get(I2C_PERIPH, I2C_FLAG_TBE)) { if (--nTimeout <= 0) { return -GD32_I2C_NOK_TOUT; @@ -85,10 +80,9 @@ static int32_t _sendslaveaddr(void) { return GD32_I2C_OK; } -static int32_t _stop(void) { +static int32_t send_stop() { auto nTimeout = TIMEOUT; - /* send a stop condition to I2C bus */ i2c_stop_on_bus(I2C_PERIPH); /* wait until the stop condition is finished */ @@ -101,18 +95,12 @@ static int32_t _stop(void) { return GD32_I2C_OK; } -static int32_t _senddata(uint8_t *pData, uint32_t nCount) { - int32_t nTimeout; - +static int32_t send_data(const uint8_t *pData, const uint32_t nCount) { for (uint32_t i = 0; i < nCount; i++) { i2c_data_transmit(I2C_PERIPH, *pData); - - /* point to the next byte to be written */ pData++; + auto nTimeout = TIMEOUT; - nTimeout = TIMEOUT; - - /* wait until BTC bit is set */ while (!i2c_flag_get(I2C_PERIPH, I2C_FLAG_BTC)) { if (--nTimeout <= 0) { return -GD32_I2C_NOK_TOUT; @@ -123,60 +111,72 @@ static int32_t _senddata(uint8_t *pData, uint32_t nCount) { return GD32_I2C_OK; } -static int _write(char *pBuffer, int nLength) { - if (_sendstart() != GD32_I2C_OK) { - _stop(); +static int32_t write(const char *pBuffer, const int nLength) { + if (send_start() != GD32_I2C_OK) { + send_stop(); return -1; } - if (_sendslaveaddr() != GD32_I2C_OK) { - _stop(); + if (send_slaveaddr() != GD32_I2C_OK) { + send_stop(); return -1; } - if (_senddata((uint8_t*) pBuffer, (uint32_t) nLength) != GD32_I2C_OK) { - _stop(); + if (send_data((uint8_t*) pBuffer, (uint32_t) nLength) != GD32_I2C_OK) { + send_stop(); return -1; } - _stop(); + send_stop(); return 0; } -/* - * Public API's - */ - -void gd32_i2c_begin(void) { - rcu_periph_clock_enable(I2C_RCU_CLK); - rcu_periph_clock_enable(I2C_GPIO_SCL_CLK); - rcu_periph_clock_enable(I2C_GPIO_SDA_CLK); +static void rcu_config() { + rcu_periph_clock_enable(I2C_RCU_I2Cx); + rcu_periph_clock_enable(I2C_SCL_RCU_GPIOx); + rcu_periph_clock_enable(I2C_SDA_RCU_GPIOx); +} -#if !defined (GD32F4XX) - gpio_init(I2C_GPIO_SCL_PORT, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, I2C_SCL_PIN); - gpio_init(I2C_GPIO_SDA_PORT, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, I2C_SDA_PIN); +static void gpio_config() { +#if defined (GPIO_INIT) + gpio_init(I2C_SCL_GPIOx, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, I2C_SCL_GPIO_PINx); + gpio_init(I2C_SDA_GPIOx, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, I2C_SDA_GPIO_PINx); # if defined (I2C_REMAP) if (I2C_REMAP == GPIO_I2C0_REMAP) { gpio_pin_remap_config(GPIO_I2C0_REMAP, ENABLE); + } else { + assert(0); } # endif #else - gpio_af_set(I2C_GPIO_SCL_PORT, GPIO_AF_4, I2C_SCL_PIN); - gpio_af_set(I2C_GPIO_SCL_PORT, GPIO_AF_4, I2C_SDA_PIN); + gpio_af_set(I2C_SCL_GPIOx, I2C_GPIO_AFx, I2C_SCL_GPIO_PINx); + gpio_mode_set(I2C_SCL_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SCL_GPIO_PINx); + gpio_output_options_set(I2C_SCL_GPIOx, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SCL_GPIO_PINx); - gpio_mode_set(I2C_GPIO_SCL_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SCL_PIN); - gpio_output_options_set(I2C_GPIO_SCL_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SCL_PIN); - gpio_mode_set(I2C_GPIO_SDA_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SDA_PIN); - gpio_output_options_set(I2C_GPIO_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SDA_PIN); + gpio_af_set(I2C_SDA_GPIOx, I2C_GPIO_AFx, I2C_SDA_GPIO_PINx); + gpio_mode_set(I2C_SDA_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SDA_GPIO_PINx); + gpio_output_options_set(I2C_SDA_GPIOx, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SDA_GPIO_PINx); #endif +} +static void i2c_config() { i2c_clock_config(I2C_PERIPH, GD32_I2C_FULL_SPEED, I2C_DTCY_2); i2c_enable(I2C_PERIPH); i2c_ack_config(I2C_PERIPH, I2C_ACK_ENABLE); } +/* + * Public API's + */ + +void gd32_i2c_begin() { + rcu_config(); + gpio_config(); + i2c_config(); +} + void gd32_i2c_set_baudrate(uint32_t nBaudrate) { i2c_clock_config(I2C_PERIPH, nBaudrate, I2C_DTCY_2); } @@ -186,18 +186,16 @@ void gd32_i2c_set_address(uint8_t nAddress) { } uint8_t gd32_i2c_write(const char *pBuffer, uint32_t nLength) { - const auto ret = _write((char *)pBuffer, (int) nLength); - + const auto ret = write((char *)pBuffer, (int) nLength); return (uint8_t)-ret; } uint8_t gd32_i2c_read(char *pBuffer, uint32_t nLength) { auto nTimeout = TIMEOUT; - /* wait until I2C bus is idle */ while (i2c_flag_get(I2C_PERIPH, I2C_FLAG_I2CBSY)) { if (--nTimeout <= 0) { - _stop(); + send_stop(); return GD32_I2C_NOK_TOUT; } } @@ -206,79 +204,67 @@ uint8_t gd32_i2c_read(char *pBuffer, uint32_t nLength) { i2c_ackpos_config(I2C_PERIPH, I2C_ACKPOS_NEXT); } - /* send a start condition to I2C bus */ i2c_start_on_bus(I2C_PERIPH); nTimeout = TIMEOUT; - /* wait until SBSEND bit is set */ while (!i2c_flag_get(I2C_PERIPH, I2C_FLAG_SBSEND)) { if (--nTimeout <= 0) { - _stop(); + send_stop(); return GD32_I2C_NOK_TOUT; } } - /* send slave address to I2C bus */ i2c_master_addressing(I2C_PERIPH, s_nAddress, I2C_RECEIVER); if (nLength < 3) { - /* disable acknowledge */ i2c_ack_config(I2C_PERIPH, I2C_ACK_DISABLE); } nTimeout = TIMEOUT; - /* wait until ADDSEND bit is set */ while (!i2c_flag_get(I2C_PERIPH, I2C_FLAG_ADDSEND)) { if (--nTimeout <= 0) { - _stop(); + send_stop(); return GD32_I2C_NOK_TOUT; } } - /* clear the ADDSEND bit */ i2c_flag_clear(I2C_PERIPH, I2C_FLAG_ADDSEND); if (1 == nLength) { - /* send a stop condition to I2C bus */ i2c_stop_on_bus(I2C_PERIPH); } auto nTimeoutLoop = TIMEOUT; - /* while there is data to be read */ while (nLength) { if (3 == nLength) { nTimeout = TIMEOUT; - /* wait until BTC bit is set */ + while (!i2c_flag_get(I2C_PERIPH, I2C_FLAG_BTC)) { if (--nTimeout <= 0) { - _stop(); + send_stop(); return GD32_I2C_NOK_TOUT; } } - /* disable acknowledge */ i2c_ack_config(I2C_PERIPH, I2C_ACK_DISABLE); } if (2 == nLength) { nTimeout = TIMEOUT; - /* wait until BTC bit is set */ while (!i2c_flag_get(I2C_PERIPH, I2C_FLAG_BTC)) { if (--nTimeout <= 0) { - _stop(); + send_stop(); return GD32_I2C_NOK_TOUT; } } - /* send a stop condition to I2C bus */ i2c_stop_on_bus(I2C_PERIPH); } - /* wait until the RBNE bit is set and clear it */ if (i2c_flag_get(I2C_PERIPH, I2C_FLAG_RBNE)) { *pBuffer = i2c_data_receive(I2C_PERIPH); pBuffer++; @@ -287,23 +273,20 @@ uint8_t gd32_i2c_read(char *pBuffer, uint32_t nLength) { } if (--nTimeoutLoop <= 0) { - _stop(); + send_stop(); return GD32_I2C_NOK_TOUT; } } nTimeout = TIMEOUT; - /* wait until the stop condition is finished */ while (I2C_CTL0(I2C_PERIPH) & 0x0200) { if (--nTimeout <= 0) { return GD32_I2C_NOK_TOUT; } } - /* enable acknowledge */ i2c_ack_config(I2C_PERIPH, I2C_ACK_ENABLE); - i2c_ackpos_config(I2C_PERIPH, I2C_ACKPOS_CURRENT); return GD32_I2C_OK; diff --git a/lib-gd32/src/gd32_spi.cpp b/lib-gd32/src/f/gd32_spi.cpp similarity index 70% rename from lib-gd32/src/gd32_spi.cpp rename to lib-gd32/src/f/gd32_spi.cpp index 74a9828c..5e16577f 100644 --- a/lib-gd32/src/gd32_spi.cpp +++ b/lib-gd32/src/f/gd32_spi.cpp @@ -2,7 +2,7 @@ * @file gd32_spi.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,19 +32,19 @@ static uint8_t s_nChipSelect = GD32_SPI_CS0; -static inline void _cs_high() { +static void cs_high() { if (s_nChipSelect == GD32_SPI_CS0) { - GPIO_BOP(SPI_NSS_GPIOx) = static_cast(SPI_NSS_GPIO_PINx); + GPIO_BOP(SPI_NSS_GPIOx) = SPI_NSS_GPIO_PINx; } } -static inline void _cs_low() { +static void cs_low() { if (s_nChipSelect == GD32_SPI_CS0) { - GPIO_BC(SPI_NSS_GPIOx) = static_cast(SPI_NSS_GPIO_PINx); + GPIO_BC(SPI_NSS_GPIOx) = SPI_NSS_GPIO_PINx; } } -static uint8_t _send_byte(uint8_t byte) { +static uint8_t send_byte(uint8_t byte) { while (RESET == (SPI_STAT(SPI_PERIPH) & SPI_FLAG_TBE)) ; @@ -56,37 +56,44 @@ static uint8_t _send_byte(uint8_t byte) { return static_cast(static_cast(SPI_DATA(SPI_PERIPH))); } -void gd32_spi_begin() { +static void rcu_config() { + rcu_periph_clock_enable(SPI_RCU_SPIx); rcu_periph_clock_enable(SPI_RCU_GPIOx); - rcu_periph_clock_enable(SPI_RCU_CLK); + rcu_periph_clock_enable(SPI_NSS_RCU_GPIOx); -#if !defined (GD32F4XX) +#if defined (GPIO_INIT) rcu_periph_clock_enable(RCU_AF); +#endif +} - gpio_init(SPI_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, SPI_SCK_PIN | SPI_MISO_PIN | SPI_MOSI_PIN); - -# if defined (SPI_REMAP) - gpio_pin_remap_config(SPI_REMAP, ENABLE); +static void gpio_config() { +#if defined (GPIO_INIT) +# if defined (SPI_REMAP_GPIO) + gpio_pin_remap_config(SPI_REMAP_GPIO, ENABLE); + if (SPI_PERIPH == SPI0) { + gpio_pin_remap_config(GPIO_SWJ_DISABLE_REMAP, ENABLE); + } # else if (SPI_PERIPH == SPI2) { gpio_pin_remap_config(GPIO_SWJ_DISABLE_REMAP, ENABLE); } # endif + gpio_init(SPI_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, SPI_SCK_GPIO_PINx | SPI_MOSI_GPIO_PINx); + gpio_init(SPI_GPIOx, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, SPI_MISO_GPIO_PINx); + gpio_init(SPI_NSS_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SPI_NSS_GPIO_PINx); #else - if (SPI_PERIPH == SPI2) { - gpio_af_set(SPI_GPIOx, GPIO_AF_6, SPI_SCK_PIN | SPI_MISO_PIN | SPI_MOSI_PIN); - } else { - gpio_af_set(SPI_GPIOx, GPIO_AF_5, SPI_SCK_PIN | SPI_MISO_PIN | SPI_MOSI_PIN); - } + gpio_af_set(SPI_GPIOx, SPI_GPIO_AFx, SPI_SCK_GPIO_PINx | SPI_MISO_GPIO_PINx | SPI_MOSI_GPIO_PINx); + gpio_mode_set(SPI_GPIOx, GPIO_MODE_AF, GPIO_PUPD_NONE, SPI_SCK_GPIO_PINx | SPI_MISO_GPIO_PINx | SPI_MOSI_GPIO_PINx); + gpio_output_options_set(SPI_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI_SCK_GPIO_PINx | SPI_MOSI_GPIO_PINx); - gpio_mode_set(SPI_GPIOx, GPIO_MODE_AF, GPIO_PUPD_NONE, SPI_SCK_PIN | SPI_MISO_PIN | SPI_MOSI_PIN); - gpio_output_options_set(SPI_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI_SCK_PIN | SPI_MISO_PIN | SPI_MOSI_PIN); + gpio_mode_set(SPI_NSS_GPIOx, GPIO_MODE_OUTPUT,GPIO_PUPD_NONE, SPI_NSS_GPIO_PINx); + gpio_output_options_set(SPI_NSS_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, SPI_NSS_GPIO_PINx); #endif - gpio_fsel(SPI_NSS_GPIOx, SPI_NSS_GPIO_PINx, GPIO_FSEL_OUTPUT); - - _cs_high(); + cs_high(); +} +static void spi_config() { spi_disable(SPI_PERIPH); spi_i2s_deinit(SPI_PERIPH); @@ -103,15 +110,23 @@ void gd32_spi_begin() { spi_enable(SPI_PERIPH); } +/* + * Public API's + */ + +void gd32_spi_begin() { + rcu_config(); + gpio_config(); + spi_config(); +} + void gd32_spi_end() { - spi_i2s_deinit(SPI_PERIPH); -#if !defined (GD32F4XX) - gpio_init(SPI_GPIOx, GPIO_MODE_IPD, GPIO_OSPEED_50MHZ, SPI_SCK_PIN | SPI_MISO_PIN | SPI_MOSI_PIN); + spi_disable(SPI_PERIPH); +#if defined (GPIO_INIT) + gpio_init(SPI_GPIOx, GPIO_MODE_IPD, GPIO_OSPEED_50MHZ, SPI_SCK_GPIO_PINx | SPI_MISO_GPIO_PINx | SPI_MOSI_GPIO_PINx); gpio_init(SPI_NSS_GPIOx, GPIO_MODE_IPD, GPIO_OSPEED_50MHZ, SPI_NSS_GPIO_PINx); #else - gpio_af_set(SPI_GPIOx, GPIO_AF_0, SPI_SCK_PIN | SPI_MISO_PIN | SPI_MOSI_PIN); - gpio_mode_set(SPI_GPIOx, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SPI_SCK_PIN | SPI_MISO_PIN | SPI_MOSI_PIN); - + gpio_mode_set(SPI_GPIOx, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SPI_SCK_GPIO_PINx | SPI_MISO_GPIO_PINx | SPI_MOSI_GPIO_PINx); gpio_mode_set(SPI_NSS_GPIOx, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SPI_NSS_GPIO_PINx); #endif } @@ -165,21 +180,27 @@ void gd32_spi_setDataMode(uint8_t nMode) { void gd32_spi_chipSelect(uint8_t nChipSelect) { s_nChipSelect = nChipSelect; + + if (nChipSelect == GD32_SPI_CS0) { + spi_nss_output_enable(SPI_PERIPH); + } else { + spi_nss_output_disable(SPI_PERIPH); + } } void gd32_spi_transfernb(const char *pTxBuffer, char *pRxBuffer, uint32_t nDataLength) { assert(pTxBuffer != nullptr); assert(pRxBuffer != nullptr); - _cs_low(); + cs_low(); while (nDataLength-- > 0) { - *pRxBuffer = _send_byte(static_cast(*pTxBuffer)); + *pRxBuffer = send_byte(static_cast(*pTxBuffer)); pRxBuffer++; pTxBuffer++; } - _cs_high(); + cs_high(); } void gd32_spi_transfern(char *pTxBuffer, uint32_t nDataLength) { @@ -187,23 +208,23 @@ void gd32_spi_transfern(char *pTxBuffer, uint32_t nDataLength) { } void gd32_spi_write(const uint16_t nData) { - _cs_low(); + cs_low(); - _send_byte(static_cast(nData >> 8)); - _send_byte(static_cast(nData & 0xFF)); + send_byte(static_cast(nData >> 8)); + send_byte(static_cast(nData & 0xFF)); - _cs_high(); + cs_high(); } void gd32_spi_writenb(const char *pTxBuffer, uint32_t nDataLength) { assert(pTxBuffer != nullptr); - _cs_low(); + cs_low(); while (nDataLength-- > 0) { - _send_byte(static_cast(*pTxBuffer)); + send_byte(static_cast(*pTxBuffer)); pTxBuffer++; } - _cs_high(); + cs_high(); } diff --git a/lib-gd32/src/i2s_psc_config_dump.cpp b/lib-gd32/src/f/i2s_psc_config_dump.cpp similarity index 96% rename from lib-gd32/src/i2s_psc_config_dump.cpp rename to lib-gd32/src/f/i2s_psc_config_dump.cpp index e364ec22..e8d72356 100644 --- a/lib-gd32/src/i2s_psc_config_dump.cpp +++ b/lib-gd32/src/f/i2s_psc_config_dump.cpp @@ -45,7 +45,7 @@ #define RCU_CFG1_PREDV1_OFFSET 4U /* PREDV1 offset in RCU_CFG1 */ #define RCU_CFG1_PLL2MF_OFFSET 12U /* PLL2MF offset in RCU_CFG1 */ -void i2s_psc_config_dump(__attribute__((unused)) uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout) { +void i2s_psc_config_dump([[maybe_unused]] uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout) { uint32_t i2sdiv = 2U, i2sof = 0U; uint32_t clks = 0U; uint32_t i2sclock = 0U; diff --git a/lib-gd32/src/gd32_gpio_mode_set.cpp b/lib-gd32/src/gd32_gpio_mode_set.cpp new file mode 100644 index 00000000..bf8f4807 --- /dev/null +++ b/lib-gd32/src/gd32_gpio_mode_set.cpp @@ -0,0 +1,75 @@ +#if defined (GD32F4XX) || defined (GD32H7XX) +/** + * @file gd32_gpio_mode_set.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "gd32.h" + +void gd32_gpio_mode_set_output(const uint32_t gpio_periph, const uint32_t pin) { + assert(pin != 0); + assert(__builtin_popcount(static_cast(pin)) == 1); + + auto ctl = GPIO_CTL(gpio_periph); + auto pupd = GPIO_PUD(gpio_periph); + + const auto i = 31 - __builtin_clz(pin); + + /* clear the specified pin mode bits */ + ctl &= ~GPIO_MODE_MASK(i); + /* set the specified pin mode bits */ + ctl |= GPIO_MODE_SET(i, GPIO_MODE_OUTPUT); + /* clear the specified pin pupd bits */ + pupd &= ~GPIO_PUPD_MASK(i); + /* set the specified pin pupd bits */ + pupd |= GPIO_PUPD_SET(i, GPIO_PUPD_NONE); + + GPIO_CTL(gpio_periph) = ctl; + GPIO_PUD(gpio_periph) = pupd; +} + +void gd32_gpio_mode_set_af(const uint32_t gpio_periph, const uint32_t pin) { + assert(pin != 0); + assert(__builtin_popcount(static_cast(pin)) == 1); + + auto ctl = GPIO_CTL(gpio_periph); + auto pupd = GPIO_PUD(gpio_periph); + + const auto i = 31 - __builtin_clz(pin); + + /* clear the specified pin mode bits */ + ctl &= ~GPIO_MODE_MASK(i); + /* set the specified pin mode bits */ + ctl |= GPIO_MODE_SET(i, GPIO_MODE_AF); + /* clear the specified pin pupd bits */ + pupd &= ~GPIO_PUPD_MASK(i); + /* set the specified pin pupd bits */ + pupd |= GPIO_PUPD_SET(i, GPIO_PUPD_PULLUP); + + GPIO_CTL(gpio_periph) = ctl; + GPIO_PUD(gpio_periph) = pupd; +} +#endif diff --git a/lib-gd32/src/gd32_pwm.cpp b/lib-gd32/src/gd32_pwm.cpp new file mode 100644 index 00000000..44c8da36 --- /dev/null +++ b/lib-gd32/src/gd32_pwm.cpp @@ -0,0 +1,300 @@ +/** + * @file gd32_pwm.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if 0 +#undef NDEBUG + +#define PWM_TIMERx TIMER2 +#define PWM_RCU_TIMERx RCU_TIMER2 + +#define TIMER2_FULL_REMAP +#define PWM_TIMER_REMAP TIMER2_REMAP +#define PWM_GPIO_AFx TIMER2_GPIO_AFx + +#define PWM_CH0_RCU_GPIOx TIMER2_CH0_RCU_GPIOx +#define PWM_CH0_GPIOx TIMER2_CH0_GPIOx +#define PWM_CH0_GPIO_PINx TIMER2_CH0_GPIO_PINx + +#define PWM_CH1_RCU_GPIOx TIMER2_CH1_RCU_GPIOx +#define PWM_CH1_GPIOx TIMER2_CH1_GPIOx +#define PWM_CH1_GPIO_PINx TIMER2_CH1_GPIO_PINx + +#define PWM_CH2_RCU_GPIOx TIMER2_CH2_RCU_GPIOx +#define PWM_CH2_GPIOx TIMER2_CH2_GPIOx +#define PWM_CH2_GPIO_PINx TIMER2_CH2_GPIO_PINx + +#define PWM_CH3_RCU_GPIOx TIMER2_CH3_RCU_GPIOx +#define PWM_CH3_GPIOx TIMER2_CH3_GPIOx +#define PWM_CH3_GPIO_PINx TIMER2_CH3_GPIO_PINx +#endif + +#include +#ifndef NDEBUG +# include +#endif + +#include "gd32_pwm.h" +#include "gd32.h" + +#include "debug.h" + +namespace pwm { +#if !defined(PWM_CHANNEL_0_DUTYCYCLE) +# define PWM_CHANNEL_0_DUTYCYCLE 50 +#endif +#if !defined(PWM_CHANNEL_1_DUTYCYCLE) +# define PWM_CHANNEL_1_DUTYCYCLE 50 +#endif +#if !defined(PWM_CHANNEL_2_DUTYCYCLE) +# define PWM_CHANNEL_2_DUTYCYCLE 50 +#endif +#if !defined(PWM_CHANNEL_3_DUTYCYCLE) +# define PWM_CHANNEL_3_DUTYCYCLE 50 +#endif +#if defined (PWM_CH0_RCU_GPIOx) +static constexpr uint32_t DEFAUL_CHANNEL_0_DUTYCYCLE = PWM_CHANNEL_0_DUTYCYCLE; +#endif +#if defined (PWM_CH1_RCU_GPIOx) +static constexpr uint32_t DEFAUL_CHANNEL_1_DUTYCYCLE = PWM_CHANNEL_1_DUTYCYCLE; +#endif +#if defined (PWM_CH2_RCU_GPIOx) +static constexpr uint32_t DEFAUL_CHANNEL_2_DUTYCYCLE = PWM_CHANNEL_2_DUTYCYCLE; +#endif +#if defined (PWM_CH3_RCU_GPIOx) +static constexpr uint32_t DEFAUL_CHANNEL_3_DUTYCYCLE = PWM_CHANNEL_3_DUTYCYCLE; +#endif +#if defined (PWM_RCU_TIMERx) && defined (PWM_TIMERx) +static constexpr uint32_t TIMER_PERIOD = 19999; // 50KHz +#endif +} // namespace pwm + +#if defined (PWM_RCU_TIMERx) && defined (PWM_TIMERx) + +static void dump() { +#if 1 + DEBUG_ENTRY +#ifndef NDEBUG + printf("PWM_TIMERx=0x%.8X\n", PWM_TIMERx - TIMER_BASE); + printf("PWM_RCU_TIMERx=0x%.8X\n", PWM_RCU_TIMERx); +# if defined (GPIO_INIT) + printf("PWM_TIMER_REMAP=0x%.8X\n", PWM_TIMER_REMAP); +# endif + puts("--------------------------------"); +# if defined (PWM_CH0_RCU_GPIOx) + printf("PWM_CH0_RCU_GPIOx=0x%.8X\n", PWM_CH0_RCU_GPIOx); + printf("PWM_CH0_GPIOx=0x%.8X\n", PWM_CH0_GPIOx); + printf("PWM_CH0_GPIO_PINx=0x%.4X\n", PWM_CH0_GPIO_PINx); + puts("--------------------------------"); +# endif +# if defined (PWM_CH1_RCU_GPIOx) + printf("PWM_CH1_RCU_GPIOx=0x%.8X\n", PWM_CH1_RCU_GPIOx); + printf("PWM_CH1_GPIOx=0x%.8X\n", PWM_CH1_GPIOx); + printf("PWM_CH1_GPIO_PINx=0x%.4X\n", PWM_CH1_GPIO_PINx); + puts("--------------------------------"); +# endif +# if defined (PWM_CH2_RCU_GPIOx) + printf("PWM_CH2_RCU_GPIOx=0x%.8X\n", PWM_CH2_RCU_GPIOx); + printf("PWM_CH2_GPIOx=0x%.8X\n", PWM_CH2_GPIOx); + printf("PWM_CH2_GPIO_PINx=0x%.4X\n", PWM_CH2_GPIO_PINx); + puts("--------------------------------"); +# endif +# if defined (PWM_CH3_RCU_GPIOx) + printf("PWM_CH3_RCU_GPIOx=0x%.8X\n", PWM_CH3_RCU_GPIOx); + printf("PWM_CH3_GPIOx=0x%.8X\n", PWM_CH3_GPIOx); + printf("PWM_CH3_GPIO_PINx=0x%.4X\n", PWM_CH3_GPIO_PINx); +# endif +#endif + DEBUG_EXIT +#endif +} + +static void gpio_config() { +#if defined (PWM_CH0_RCU_GPIOx) + rcu_periph_clock_enable(PWM_CH0_RCU_GPIOx); +#endif +#if defined (PWM_CH1_RCU_GPIOx) + rcu_periph_clock_enable(PWM_CH1_RCU_GPIOx); +#endif +#if defined (PWM_CH2_RCU_GPIOx) + rcu_periph_clock_enable(PWM_CH2_RCU_GPIOx); +#endif +#if defined (PWM_CH3_RCU_GPIOx) + rcu_periph_clock_enable(PWM_CH3_RCU_GPIOx); +#endif + +#if defined (GPIO_INIT) + rcu_periph_clock_enable(RCU_AF); +# if defined(PWM_TIMER_REMAP) + gpio_pin_remap_config(PWM_TIMER_REMAP, ENABLE); +# endif +# if defined (PWM_CH0_GPIOx) && defined (PWM_CH0_GPIO_PINx) + gpio_init(PWM_CH0_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PWM_CH0_GPIO_PINx); +# endif +# if defined (PWM_CH1_GPIOx) && defined (PWM_CH1_GPIO_PINx) + gpio_init(PWM_CH1_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PWM_CH1_GPIO_PINx); +# endif +# if defined (PWM_CH2_GPIOx) && defined (PWM_CH2_GPIO_PINx) + gpio_init(PWM_CH2_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PWM_CH2_GPIO_PINx); +# endif +# if defined (PWM_CH3_GPIOx) && defined (PWM_CH3_GPIO_PINx) + gpio_init(PWM_CH3_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PWM_CH3_GPIO_PINx); +# endif +#else +# if defined (PWM_CH0_GPIOx) && defined (PWM_CH0_GPIO_PINx) + gpio_af_set(PWM_CH0_GPIOx, PWM_GPIO_AFx, PWM_CH0_GPIO_PINx); + gpio_mode_set(PWM_CH0_GPIOx, GPIO_MODE_AF, GPIO_PUPD_NONE, PWM_CH0_GPIO_PINx); + gpio_output_options_set(PWM_CH0_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, PWM_CH0_GPIO_PINx); +# endif +# if defined (PWM_CH1_GPIOx) && defined (PWM_CH1_GPIO_PINx) + gpio_af_set(PWM_CH1_GPIOx, PWM_GPIO_AFx, PWM_CH1_GPIO_PINx); + gpio_mode_set(PWM_CH1_GPIOx, GPIO_MODE_AF, GPIO_PUPD_NONE, PWM_CH1_GPIO_PINx); + gpio_output_options_set(PWM_CH1_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, PWM_CH1_GPIO_PINx); +# endif +# if defined (PWM_CH2_GPIOx) && defined (PWM_CH2_GPIO_PINx) + gpio_af_set(PWM_CH2_GPIOx, PWM_GPIO_AFx, PWM_CH2_GPIO_PINx); + gpio_mode_set(PWM_CH2_GPIOx, GPIO_MODE_AF, GPIO_PUPD_NONE, PWM_CH2_GPIO_PINx); + gpio_output_options_set(PWM_CH2_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, PWM_CH2_GPIO_PINx); +# endif +# if defined (PWM_CH3_GPIOx) && defined (PWM_CH3_GPIO_PINx) + gpio_af_set(PWM_CH3_GPIOx, PWM_GPIO_AFx, PWM_CH3_GPIO_PINx); + gpio_mode_set(PWM_CH3_GPIOx, GPIO_MODE_AF, GPIO_PUPD_NONE, PWM_CH3_GPIO_PINx); + gpio_output_options_set(PWM_CH3_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, PWM_CH3_GPIO_PINx); +# endif +#endif +} + +static void timer_config() { +#if defined (PWM_RCU_TIMERx) && defined (PWM_TIMERx) + rcu_periph_clock_enable(PWM_RCU_TIMERx); + + timer_deinit(PWM_TIMERx); + + timer_parameter_struct timer_initpara; + timer_initpara.prescaler = TIMER_PSC_1MHZ; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = pwm::TIMER_PERIOD; + timer_initpara.clockdivision = TIMER_CKDIV_DIV1; + timer_initpara.repetitioncounter = 0; + timer_init(PWM_TIMERx, &timer_initpara); + +# if defined (PWM_CH0_RCU_GPIOx) || defined (PWM_CH1_RCU_GPIOx) || defined (PWM_CH2_RCU_GPIOx) || defined (PWM_CH3_RCU_GPIOx) + timer_oc_parameter_struct timer_ocintpara; + timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocintpara.outputstate = TIMER_CCX_ENABLE; + timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; + timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE; + timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; + timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; +# endif +# if defined (PWM_CH0_RCU_GPIOx) + timer_channel_output_config(PWM_TIMERx, TIMER_CH_0, &timer_ocintpara); + timer_channel_output_pulse_value_config(PWM_TIMERx, TIMER_CH_0, 1999); + timer_channel_output_mode_config(PWM_TIMERx, TIMER_CH_0, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(PWM_TIMERx, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE); +# endif +# if defined (PWM_CH1_RCU_GPIOx) + timer_channel_output_config(PWM_TIMERx, TIMER_CH_1, &timer_ocintpara); + timer_channel_output_pulse_value_config(PWM_TIMERx, TIMER_CH_1, 3999); + timer_channel_output_mode_config(PWM_TIMERx, TIMER_CH_1, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(PWM_TIMERx, TIMER_CH_1, TIMER_OC_SHADOW_DISABLE); +# endif +# if defined (PWM_CH2_RCU_GPIOx) + timer_channel_output_config(PWM_TIMERx, TIMER_CH_2, &timer_ocintpara); + timer_channel_output_pulse_value_config(PWM_TIMERx, TIMER_CH_2, 7999); + timer_channel_output_mode_config(PWM_TIMERx, TIMER_CH_2, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(PWM_TIMERx, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE); +# endif +# if defined (PWM_CH3_RCU_GPIOx) + timer_channel_output_config(PWM_TIMERx, TIMER_CH_3, &timer_ocintpara); + timer_channel_output_pulse_value_config(PWM_TIMERx, TIMER_CH_3, 11999); + timer_channel_output_mode_config(PWM_TIMERx, TIMER_CH_3, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(PWM_TIMERx, TIMER_CH_3, TIMER_OC_SHADOW_DISABLE); +# endif + + timer_auto_reload_shadow_enable(PWM_TIMERx); + timer_enable(PWM_TIMERx); +#endif +} + +void gd32_pwm_begin() { + DEBUG_ENTRY + + dump(); + + gpio_config(); + timer_config(); + +#if defined (PWM_CH0_RCU_GPIOx) + gd32_pwm_set_duty_cycle(pwm::Channel::PWM_CHANNEL_0, pwm::DEFAUL_CHANNEL_0_DUTYCYCLE); +#endif +#if defined (PWM_CH1_RCU_GPIOx) + gd32_pwm_set_duty_cycle(pwm::Channel::PWM_CHANNEL_1, pwm::DEFAUL_CHANNEL_1_DUTYCYCLE); +#endif +#if defined (PWM_CH2_RCU_GPIOx) + gd32_pwm_set_duty_cycle(pwm::Channel::PWM_CHANNEL_2, pwm::DEFAUL_CHANNEL_2_DUTYCYCLE); +#endif +#if defined (PWM_CH3_RCU_GPIOx) + gd32_pwm_set_duty_cycle(pwm::Channel::PWM_CHANNEL_3, pwm::DEFAUL_CHANNEL_3_DUTYCYCLE); +#endif + + DEBUG_EXIT +} + +void gd32_pwm_set_duty_cycle(const pwm::Channel channel, const uint32_t nDutyCycle) { + DEBUG_ENTRY + + const uint32_t nPulse = (nDutyCycle > 100 ? 100 : nDutyCycle) * (pwm::TIMER_PERIOD / 100U); + + DEBUG_PRINTF("Channel=%u, nDutyCycle=%u, nPulse=%u", static_cast(channel), nDutyCycle, static_cast(nPulse)); + + switch (channel) { +#if defined (PWM_CH0_RCU_GPIOx) + case pwm::Channel::PWM_CHANNEL_0: + timer_channel_output_pulse_value_config(PWM_TIMERx, TIMER_CH_0, nPulse); + break; +#endif +#if defined (PWM_CH1_RCU_GPIOx) + case pwm::Channel::PWM_CHANNEL_1: + timer_channel_output_pulse_value_config(PWM_TIMERx, TIMER_CH_1, nPulse); + break; +#endif +#if defined (PWM_CH2_RCU_GPIOx) + case pwm::Channel::PWM_CHANNEL_2: + timer_channel_output_pulse_value_config(PWM_TIMERx, TIMER_CH_2, nPulse); + break; +#endif +#if defined (PWM_CH3_RCU_GPIOx) + case pwm::Channel::PWM_CHANNEL_3: + timer_channel_output_pulse_value_config(PWM_TIMERx, TIMER_CH_3, nPulse); + break; +#endif + default: + break; + } + + DEBUG_EXIT +} +#endif diff --git a/lib-gd32/src/gd32_spi_dma_i2s.cpp b/lib-gd32/src/gd32_spi_dma_i2s.cpp index e25fedae..6ddfbd5e 100644 --- a/lib-gd32/src/gd32_spi_dma_i2s.cpp +++ b/lib-gd32/src/gd32_spi_dma_i2s.cpp @@ -2,7 +2,7 @@ * @file gd32_spi_dma_i2s.cpp * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,143 +28,156 @@ #include "gd32.h" -#if defined (GD32F4XX) -# define DMA_PARAMETER_STRUCT dma_single_data_parameter_struct -# define DMA_CHMADDR DMA_CHM0ADDR -# define DMA_MEMORY_TO_PERIPHERAL DMA_MEMORY_TO_PERIPH -# define DMA_PERIPHERAL_WIDTH_16BIT DMA_PERIPH_WIDTH_16BIT -# define dma_init dma_single_data_mode_init -# define dma_struct_para_init dma_single_data_para_struct_init -# define dma_memory_to_memory_disable(x,y) +#if defined (I2S_PERIPH) + +# if defined (GD32H7XX) + static_assert(I2S_PERIPH != SPI3); + static_assert(I2S_PERIPH != SPI4); +# else + static_assert(I2S_PERIPH != SPI0); +# endif + +# if defined (GD32F4XX) || defined (GD32H7XX) +# define DMA_PARAMETER_STRUCT dma_single_data_parameter_struct +# define DMA_CHMADDR DMA_CHM0ADDR +# define DMA_MEMORY_TO_PERIPHERAL DMA_MEMORY_TO_PERIPH +# define DMA_PERIPHERAL_WIDTH_16BIT DMA_PERIPH_WIDTH_16BIT +# define dma_init dma_single_data_mode_init +# define dma_struct_para_init dma_single_data_para_struct_init +# define dma_memory_to_memory_disable(x,y) +# else +# define DMA_PARAMETER_STRUCT dma_parameter_struct +# endif + +# ifndef NDEBUG +# if !defined (GD32H7XX) + void i2s_psc_config_dump(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout); +# endif +# endif + +# if !defined(SPI_BUFFER_SIZE) +# define SPI_BUFFER_SIZE ((24 * 1024) / 2) +# endif + +static uint16_t s_TxBuffer[SPI_BUFFER_SIZE] __attribute__ ((aligned (4))); + +static void rcu_config() { + rcu_periph_clock_enable(I2S_WS_RCU_GPIOx); + +#if defined (GPIO_INIT) + rcu_periph_clock_enable(RCU_AF); + rcu_periph_clock_enable(I2S_RCU_SPIx); + rcu_periph_clock_enable(I2S_RCU_GPIOx); #else -# define DMA_PARAMETER_STRUCT dma_parameter_struct + rcu_periph_clock_enable(I2S_CK_RCU_GPIOx); + rcu_periph_clock_enable(I2S_SD_RCU_GPIOx); #endif -#ifndef NDEBUG -void i2s_psc_config_dump(uint32_t spi_periph, uint32_t audiosample, uint32_t frameformat, uint32_t mckout); -#endif + if (I2S_DMAx == DMA0) { + rcu_periph_clock_enable(RCU_DMA0); + } else { + rcu_periph_clock_enable(RCU_DMA1); + } -#if !defined(SPI_BUFFER_SIZE) -# define SPI_BUFFER_SIZE ((24 * 1024) / 2) +#if defined (GD32H7XX) + rcu_periph_clock_enable(RCU_DMAMUX); #endif +} -static uint16_t s_TxBuffer[SPI_BUFFER_SIZE] __attribute__ ((aligned (4))); +static void gpio_config() { +#if defined (GPIO_INIT) +# if defined (I2S_REMAP_GPIO) + gpio_pin_remap_config(I2S_REMAP_GPIO, ENABLE); + if (I2S_PERIPH == SPI0) { + gpio_pin_remap_config(GPIO_SWJ_DISABLE_REMAP, ENABLE); + } +# else + if (I2S_PERIPH == SPI2) { + gpio_pin_remap_config(GPIO_SWJ_DISABLE_REMAP, ENABLE); + } +# endif + gpio_init(I2S_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, I2S_CK_GPIO_PINx | I2S_SD_GPIO_PINx); + gpio_init(I2S_WS_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, I2S_WS_GPIO_PINx); +#else + gpio_af_set(I2S_CK_GPIOx, I2S_GPIO_AFx, I2S_CK_GPIO_PINx); + gpio_mode_set(I2S_CK_GPIOx, GPIO_MODE_AF, GPIO_PUPD_NONE, I2S_CK_GPIO_PINx); + gpio_output_options_set(I2S_CK_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, I2S_CK_GPIO_PINx); + + gpio_af_set(I2S_SD_GPIOx, I2S_GPIO_AFx, I2S_SD_GPIO_PINx); + gpio_mode_set(I2S_SD_GPIOx, GPIO_MODE_AF, GPIO_PUPD_NONE, I2S_SD_GPIO_PINx); + gpio_output_options_set(I2S_SD_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, I2S_SD_GPIO_PINx); -static void _spi_i2s_dma_config() { - rcu_periph_clock_enable(RCU_DMA1); + gpio_af_set(I2S_WS_GPIOx, I2S_GPIO_AFx, I2S_WS_GPIO_PINx); + gpio_mode_set(I2S_WS_GPIOx, GPIO_MODE_OUTPUT,GPIO_PUPD_NONE, I2S_WS_GPIO_PINx); + gpio_output_options_set(I2S_WS_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, I2S_WS_GPIO_PINx); +#endif +} - dma_deinit(SPI_DMAx, SPI_DMA_CHx); +static void spi_i2s_dma_config() { + dma_deinit(I2S_DMAx, I2S_DMA_CHx); DMA_PARAMETER_STRUCT dma_init_struct; dma_struct_para_init(&dma_init_struct); + +#if defined (GD32H7XX) + dma_init_struct.request = I2S_DMA_REQUEST_I2S_TX; +#endif dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; -#if !defined (GD32F4XX) +# if defined (GD32F4XX) || defined (GD32H7XX) +# else dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT; #endif - dma_init_struct.periph_addr = SPI_PERIPH + 0x0CU; - dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; -#if !defined (GD32F4XX) - dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT; +#if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t)&SPI_TDATA(I2S_PERIPH); #else + dma_init_struct.periph_addr = I2S_PERIPH + 0x0CU; +#endif + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; +#if defined (GD32F4XX) || defined (GD32H7XX) dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_16BIT; +#else + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT; #endif dma_init_struct.priority = DMA_PRIORITY_HIGH; - dma_init(SPI_DMAx, SPI_DMA_CHx, &dma_init_struct); - /* configure DMA mode */ - dma_circulation_disable(SPI_DMAx, SPI_DMA_CHx); - dma_memory_to_memory_disable(SPI_DMAx, SPI_DMA_CHx); + dma_init(I2S_DMAx, I2S_DMA_CHx, &dma_init_struct); + + dma_circulation_disable(I2S_DMAx, I2S_DMA_CHx); + dma_memory_to_memory_disable(I2S_DMAx, I2S_DMA_CHx); #if defined (GD32F4XX) - dma_channel_subperipheral_select(SPI_DMAx, SPI_DMA_CHx, SPI_DMA_SUBPERIx); + dma_channel_subperipheral_select(I2S_DMAx, I2S_DMA_CHx, I2S_DMA_SUBPERIx); #endif - DMA_CHCNT(SPI_DMAx, SPI_DMA_CHx) = 0; + DMA_CHCNT(I2S_DMAx, I2S_DMA_CHx) = 0; } - +namespace i2s { void gd32_spi_dma_begin() { - assert(SPI_PERIPH != SPI0); - - rcu_periph_clock_enable(SPI_NSS_RCU_GPIOx); - rcu_periph_clock_enable(SPI_RCU_GPIOx); - rcu_periph_clock_enable(SPI_RCU_CLK); - -#if !defined (GD32F4XX) - rcu_periph_clock_enable(RCU_AF); - - gpio_init(SPI_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, SPI_SCK_PIN | SPI_MISO_PIN | SPI_MOSI_PIN); - gpio_init(SPI_NSS_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, SPI_NSS_GPIO_PINx); - -# if defined (SPI2_REMAP) - gpio_pin_remap_config(GPIO_SPI2_REMAP, ENABLE); -# else - if (SPI_PERIPH == SPI2) { - gpio_pin_remap_config(GPIO_SWJ_DISABLE_REMAP, ENABLE); - } -# endif -#else - if (SPI_PERIPH == SPI2) { - gpio_af_set(SPI_GPIOx, GPIO_AF_6, SPI_SCK_PIN | SPI_MISO_PIN | SPI_MOSI_PIN); - } else { - gpio_af_set(SPI_GPIOx, GPIO_AF_5, SPI_SCK_PIN | SPI_MISO_PIN | SPI_MOSI_PIN); - } - gpio_mode_set(SPI_GPIOx, GPIO_MODE_AF, GPIO_PUPD_NONE, SPI_SCK_PIN | SPI_MISO_PIN | SPI_MOSI_PIN); - gpio_output_options_set(SPI_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI_SCK_PIN | SPI_MISO_PIN | SPI_MOSI_PIN); - - gpio_mode_set(SPI_NSS_GPIOx, GPIO_MODE_OUTPUT,GPIO_PUPD_NONE, SPI_NSS_GPIO_PINx); - gpio_output_options_set(SPI_NSS_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI_NSS_GPIO_PINx); -#endif - -#if defined (GD32F10X_CL) || defined (GD32F20X_CL) - /** - * Setup PLL2 - * - * i2sclock=160000000 - * i2sdiv=12, i2sof=256 - */ - - RCU_CTL &= ~RCU_CTL_PLL2EN; - - rcu_pll2_config(RCU_PLL2_MUL16); + rcu_config(); + gpio_config(); - RCU_CTL |= RCU_CTL_PLL2EN; + i2s_disable(I2S_PERIPH); + i2s_psc_config(I2S_PERIPH, 200000, I2S_FRAMEFORMAT_DT16B_CH16B, I2S_MCKOUT_DISABLE); + i2s_init(I2S_PERIPH, I2S_MODE_MASTERTX, I2S_STD_MSB, I2S_CKPL_LOW); + i2s_enable(I2S_PERIPH); - while ((RCU_CTL & RCU_CTL_PLL2STB) == 0U) { - } - - if (SPI_PERIPH == SPI2) { - rcu_i2s2_clock_config(RCU_I2S2SRC_CKPLL2_MUL2); - } else { - rcu_i2s1_clock_config(RCU_I2S1SRC_CKPLL2_MUL2); - } -#endif - - i2s_disable(SPI_PERIPH); - i2s_psc_config(SPI_PERIPH, 200000, I2S_FRAMEFORMAT_DT16B_CH16B, I2S_MCKOUT_DISABLE); - i2s_init(SPI_PERIPH, I2S_MODE_MASTERTX, I2S_STD_MSB, I2S_CKPL_LOW); - i2s_enable(SPI_PERIPH); - - _spi_i2s_dma_config(); + spi_i2s_dma_config(); #ifndef NDEBUG - i2s_psc_config_dump(SPI_PERIPH, 200000, I2S_FRAMEFORMAT_DT16B_CH16B, I2S_MCKOUT_DISABLE); + i2s_psc_config_dump(I2S_PERIPH, 200000, I2S_FRAMEFORMAT_DT16B_CH16B, I2S_MCKOUT_DISABLE); #endif } void gd32_spi_dma_set_speed_hz(uint32_t nSpeedHz) { - const auto audiosample = nSpeedHz / 16 / 2 ; + const auto audiosample = nSpeedHz / 16U / 2U ; - i2s_disable(SPI_PERIPH); - i2s_psc_config(SPI2, audiosample, I2S_FRAMEFORMAT_DT16B_CH16B, I2S_MCKOUT_DISABLE); - i2s_enable(SPI_PERIPH); + i2s_disable(I2S_PERIPH); + i2s_psc_config(I2S_PERIPH, audiosample, I2S_FRAMEFORMAT_DT16B_CH16B, I2S_MCKOUT_DISABLE); + i2s_enable(I2S_PERIPH); } -/** - * DMA - */ - const uint8_t *gd32_spi_dma_tx_prepare(uint32_t *nLength) { *nLength = (sizeof(s_TxBuffer) / sizeof(s_TxBuffer[0])) * 2; - return (const uint8_t*) s_TxBuffer; + return (const uint8_t *) s_TxBuffer; } void gd32_spi_dma_tx_start(const uint8_t *pTxBuffer, uint32_t nLength) { @@ -172,24 +185,27 @@ void gd32_spi_dma_tx_start(const uint8_t *pTxBuffer, uint32_t nLength) { assert((uint32_t )pTxBuffer >= (uint32_t )s_TxBuffer); assert(nLength != 0); +#if defined (GD32F4XX) || defined (GD32H7XX) + dma_flag_clear(I2S_DMAx, I2S_DMA_CHx, DMA_FLAG_FTF); +#endif + const auto dma_chcnt = (((nLength + 1) / 2) & DMA_CHXCNT_CNT); - auto nDmaChCTL = DMA_CHCTL(SPI_DMAx, SPI_DMA_CHx); + auto nDmaChCTL = DMA_CHCTL(I2S_DMAx, I2S_DMA_CHx); nDmaChCTL &= ~DMA_CHXCTL_CHEN; - DMA_CHCTL(SPI_DMAx, SPI_DMA_CHx) = nDmaChCTL; - DMA_CHMADDR(SPI_DMAx, SPI_DMA_CHx) = (uint32_t)pTxBuffer; - DMA_CHCNT(SPI_DMAx, SPI_DMA_CHx) = dma_chcnt; + DMA_CHCTL(I2S_DMAx, I2S_DMA_CHx) = nDmaChCTL; + + DMA_CHMADDR(I2S_DMAx, I2S_DMA_CHx) = (uint32_t)pTxBuffer; + DMA_CHCNT(I2S_DMAx, I2S_DMA_CHx) = dma_chcnt; + nDmaChCTL |= DMA_CHXCTL_CHEN; - DMA_CHCTL(SPI_DMAx, SPI_DMA_CHx) = nDmaChCTL; - spi_dma_enable(SPI_PERIPH, SPI_DMA_TRANSMIT); -} + DMA_CHCTL(I2S_DMAx, I2S_DMA_CHx) = nDmaChCTL; -bool gd32_spi_dma_tx_is_active(void) { - return (uint32_t) DMA_CHCNT(SPI_DMAx, SPI_DMA_CHx) != 0; + spi_dma_enable(I2S_PERIPH, SPI_DMA_TRANSMIT); } -/** - * /CS - */ - -//TODO Implement /CS +bool gd32_spi_dma_tx_is_active() { + return DMA_CHCNT(I2S_DMAx, I2S_DMA_CHx) != 0; +} +} // namespace i2s +#endif diff --git a/lib-gd32/src/gd32_uart.cpp b/lib-gd32/src/gd32_uart.cpp index 7620cddc..41ef6a83 100644 --- a/lib-gd32/src/gd32_uart.cpp +++ b/lib-gd32/src/gd32_uart.cpp @@ -2,7 +2,7 @@ * @file gd32_uart.cpp * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,51 +29,51 @@ #include "gd32_uart.h" #include "gd32.h" -static void _rcu_periph_clock_enable(const uint32_t usart_periph) { +static void rcu_config(const uint32_t usart_periph) { #ifndef NDEBUG bool isSet = false; #endif switch (usart_periph) { case USART0: - rcu_periph_clock_enable(USART0_RCU_CLK); - rcu_periph_clock_enable(USART0_GPIO_CLK); + rcu_periph_clock_enable(USART0_RCU_USART0); + rcu_periph_clock_enable(USART0_RCU_GPIOx); #ifndef NDEBUG isSet = true; #endif break; case USART1: - rcu_periph_clock_enable(USART1_RCU_CLK); - rcu_periph_clock_enable(USART1_GPIO_CLK); + rcu_periph_clock_enable(USART1_RCU_USART1); + rcu_periph_clock_enable(USART1_RCU_GPIOx); #ifndef NDEBUG isSet = true; #endif break; case USART2: - rcu_periph_clock_enable(USART2_RCU_CLK); - rcu_periph_clock_enable(USART2_GPIO_CLK); + rcu_periph_clock_enable(USART2_RCU_USART2); + rcu_periph_clock_enable(USART2_RCU_GPIOx); #ifndef NDEBUG isSet = true; #endif break; case UART3: - rcu_periph_clock_enable(UART3_RCU_CLK); - rcu_periph_clock_enable(UART3_GPIO_CLK); + rcu_periph_clock_enable(UART3_RCU_UART3); + rcu_periph_clock_enable(UART3_RCU_GPIOx); #ifndef NDEBUG isSet = true; #endif break; case UART4: - rcu_periph_clock_enable(UART4_RCU_CLK); - rcu_periph_clock_enable(UART4_GPIO_TX_CLK); - rcu_periph_clock_enable(UART4_GPIO_RX_CLK); + rcu_periph_clock_enable(UART4_RCU_UART4); + rcu_periph_clock_enable(UART4_TX_RCU_GPIOx); + rcu_periph_clock_enable(UART4_RX_RCU_GPIOx); #ifndef NDEBUG isSet = true; #endif break; #if defined (USART5) case USART5: - rcu_periph_clock_enable(USART5_RCU_CLK); - rcu_periph_clock_enable(USART5_GPIO_CLK); + rcu_periph_clock_enable(USART5_RCU_USART5); + rcu_periph_clock_enable(USART5_RCU_GPIOx); # ifndef NDEBUG isSet = true; # endif @@ -81,8 +81,8 @@ static void _rcu_periph_clock_enable(const uint32_t usart_periph) { #endif #if defined (UART6) case UART6: - rcu_periph_clock_enable(UART6_RCU_CLK); - rcu_periph_clock_enable(UART6_GPIO_CLK); + rcu_periph_clock_enable(UART6_RCU_UART6); + rcu_periph_clock_enable(UART6_RCU_GPIOx); # ifndef NDEBUG isSet = true; # endif @@ -90,8 +90,8 @@ static void _rcu_periph_clock_enable(const uint32_t usart_periph) { #endif #if defined (UART7) case UART7: - rcu_periph_clock_enable(UART7_RCU_CLK); - rcu_periph_clock_enable(UART7_GPIO_CLK); + rcu_periph_clock_enable(UART7_RCU_UART7); + rcu_periph_clock_enable(UART7_RCU_GPIOx); # ifndef NDEBUG isSet = true; # endif @@ -106,28 +106,28 @@ static void _rcu_periph_clock_enable(const uint32_t usart_periph) { assert(isSet); } -#if !defined (GD32F4XX) -static void _gpio_init(const uint32_t usart_periph) { +#if !(defined (GD32F4XX) || defined (GD32H7XX)) +static void gpio_config(const uint32_t usart_periph) { rcu_periph_clock_enable(RCU_AF); switch (usart_periph) { case USART0: - gpio_init(USART0_GPIO_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, USART0_TX_PIN); - gpio_init(USART0_GPIO_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, USART0_RX_PIN); + gpio_init(USART0_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, USART0_TX_GPIO_PINx); + gpio_init(USART0_GPIOx, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, USART0_RX_GPIO_PINx); #if defined (USART0_REMAP) gpio_pin_remap_config(GPIO_USART0_REMAP, ENABLE); #endif break; case USART1: - gpio_init(USART1_GPIO_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, USART1_TX_PIN); - gpio_init(USART1_GPIO_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, USART1_RX_PIN); + gpio_init(USART1_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, USART1_TX_GPIO_PINx); + gpio_init(USART1_GPIOx, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, USART1_RX_GPIO_PINx); #if defined (USART1_REMAP) gpio_pin_remap_config(GPIO_USART1_REMAP, ENABLE); #endif break; case USART2: - gpio_init(USART2_GPIO_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, USART2_TX_PIN); - gpio_init(USART2_GPIO_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, USART2_RX_PIN); + gpio_init(USART2_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, USART2_TX_GPIO_PINx); + gpio_init(USART2_GPIOx, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, USART2_RX_GPIO_PINx); #if defined (USART2_FULL_REMAP) gpio_pin_remap_config(GPIO_USART2_FULL_REMAP, ENABLE); #elif defined (USART2_PARTIAL_REMAP) @@ -135,20 +135,20 @@ static void _gpio_init(const uint32_t usart_periph) { #endif break; case UART3: - gpio_init(UART3_GPIO_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, UART3_TX_PIN); - gpio_init(UART3_GPIO_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, UART3_RX_PIN); + gpio_init(UART3_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, UART3_TX_GPIO_PINx); + gpio_init(UART3_GPIOx, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, UART3_RX_GPIO_PINx); #if defined (UART3_REMAP) gpio_pin_remap_config(GPIO_PCF5_UART3_REMAP, ENABLE); #endif break; case UART4: - gpio_init(UART4_GPIO_TX_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, UART4_TX_PIN); - gpio_init(UART4_GPIO_RX_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, UART4_RX_PIN); + gpio_init(UART4_TX_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, UART4_TX_GPIO_PINx); + gpio_init(UART4_RX_GPIOx, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, UART4_RX_GPIO_PINx); break; #if defined (USART5) case USART5: - gpio_init(USART5_GPIO_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, USART5_TX_PIN); - gpio_init(USART5_GPIO_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, USART5_RX_PIN); + gpio_init(USART5_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, USART5_TX_GPIO_PINx); + gpio_init(USART5_GPIOx, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, USART5_RX_GPIO_PINx); # if defined (USART5_REMAP) gpio_pin_remap_config(GPIO_PCF5_USART5_TX_PG14_REMAP, ENABLE); gpio_pin_remap_config(GPIO_PCF5_USART5_RX_PG9_REMAP, ENABLE); @@ -157,8 +157,8 @@ static void _gpio_init(const uint32_t usart_periph) { #endif #if defined (UART6) case UART6: - gpio_init(UART6_GPIO_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, UART6_TX_PIN); - gpio_init(UART6_GPIO_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, UART6_RX_PIN); + gpio_init(UART6_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, UART6_TX_GPIO_PINx); + gpio_init(UART6_GPIOx, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, UART6_RX_GPIO_PINx); # if defined (UART6_REMAP) gpio_pin_remap_config(GPIO_PCF5_UART6_REMAP, ENABLE); # endif @@ -166,8 +166,8 @@ static void _gpio_init(const uint32_t usart_periph) { #endif #if defined (UART7) case UART7: - gpio_init(UART7_GPIO_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, UART7_TX_PIN); - gpio_init(UART7_GPIO_PORT, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, UART7_RX_PIN); + gpio_init(UART7_GPIOx, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, UART7_TX_GPIO_PINx); + gpio_init(UART7_GPIOx, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, UART7_RX_GPIO_PINx); break; #endif default: @@ -177,77 +177,77 @@ static void _gpio_init(const uint32_t usart_periph) { } } #else -void _gpio_init(const uint32_t usart_periph) { +static void gpio_config(const uint32_t usart_periph) { switch (usart_periph) { case USART0: - gpio_af_set(USART0_GPIO_PORT, GPIO_AF_7, USART0_TX_PIN); - gpio_mode_set(USART0_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART0_TX_PIN); - gpio_output_options_set(USART0_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, USART0_TX_PIN); - gpio_af_set(USART0_GPIO_PORT, GPIO_AF_7, USART0_RX_PIN); - gpio_mode_set(USART0_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART0_RX_PIN); - gpio_output_options_set(USART0_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, USART0_RX_PIN); + gpio_af_set(USART0_GPIOx, USART0_GPIO_AFx, USART0_TX_GPIO_PINx); + gpio_mode_set(USART0_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART0_TX_GPIO_PINx); + gpio_output_options_set(USART0_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, USART0_TX_GPIO_PINx); + gpio_af_set(USART0_GPIOx, USART0_GPIO_AFx, USART0_RX_GPIO_PINx); + gpio_mode_set(USART0_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART0_RX_GPIO_PINx); + gpio_output_options_set(USART0_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, USART0_RX_GPIO_PINx); break; case USART1: - gpio_af_set(USART1_GPIO_PORT, GPIO_AF_7, USART1_TX_PIN); - gpio_mode_set(USART1_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART1_TX_PIN); - gpio_output_options_set(USART1_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, USART1_TX_PIN); - gpio_af_set(USART1_GPIO_PORT, GPIO_AF_7, USART1_RX_PIN); - gpio_mode_set(USART1_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART1_RX_PIN); - gpio_output_options_set(USART1_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, USART1_RX_PIN); + gpio_af_set(USART1_GPIOx, USART1_GPIO_AFx, USART1_TX_GPIO_PINx); + gpio_mode_set(USART1_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART1_TX_GPIO_PINx); + gpio_output_options_set(USART1_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, USART1_TX_GPIO_PINx); + gpio_af_set(USART1_GPIOx, USART1_GPIO_AFx, USART1_RX_GPIO_PINx); + gpio_mode_set(USART1_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART1_RX_GPIO_PINx); + gpio_output_options_set(USART1_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, USART1_RX_GPIO_PINx); break; case USART2: - gpio_af_set(USART2_GPIO_PORT, GPIO_AF_7, USART2_TX_PIN); - gpio_mode_set(USART2_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART2_TX_PIN); - gpio_output_options_set(USART2_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, USART2_TX_PIN); - gpio_af_set(USART2_GPIO_PORT, GPIO_AF_7, USART2_RX_PIN); - gpio_mode_set(USART2_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART2_RX_PIN); - gpio_output_options_set(USART2_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, USART2_RX_PIN); + gpio_af_set(USART2_GPIOx, USART2_GPIO_AFx, USART2_TX_GPIO_PINx); + gpio_mode_set(USART2_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART2_TX_GPIO_PINx); + gpio_output_options_set(USART2_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, USART2_TX_GPIO_PINx); + gpio_af_set(USART2_GPIOx, USART2_GPIO_AFx, USART2_RX_GPIO_PINx); + gpio_mode_set(USART2_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART2_RX_GPIO_PINx); + gpio_output_options_set(USART2_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, USART2_RX_GPIO_PINx); break; case UART3: - gpio_af_set(UART3_GPIO_PORT, GPIO_AF_8, UART3_TX_PIN); - gpio_mode_set(UART3_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART3_TX_PIN); - gpio_output_options_set(UART3_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, UART3_TX_PIN); - gpio_af_set(UART3_GPIO_PORT, GPIO_AF_8, UART3_RX_PIN); - gpio_mode_set(UART3_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART3_RX_PIN); - gpio_output_options_set(UART3_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, UART3_RX_PIN); + gpio_af_set(UART3_GPIOx, UART3_GPIO_AFx, UART3_TX_GPIO_PINx); + gpio_mode_set(UART3_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART3_TX_GPIO_PINx); + gpio_output_options_set(UART3_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, UART3_TX_GPIO_PINx); + gpio_af_set(UART3_GPIOx, UART3_GPIO_AFx, UART3_RX_GPIO_PINx); + gpio_mode_set(UART3_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART3_RX_GPIO_PINx); + gpio_output_options_set(UART3_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, UART3_RX_GPIO_PINx); break; case UART4: - gpio_af_set(UART4_GPIO_TX_PORT, GPIO_AF_8, UART4_TX_PIN); - gpio_mode_set(UART4_GPIO_TX_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART4_TX_PIN); - gpio_output_options_set(UART4_GPIO_TX_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, UART4_TX_PIN); - gpio_af_set(UART4_GPIO_RX_PORT, GPIO_AF_8, UART4_RX_PIN); - gpio_mode_set(UART4_GPIO_RX_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART4_RX_PIN); - gpio_output_options_set(UART4_GPIO_RX_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, UART4_RX_PIN); + gpio_af_set(UART4_TX_GPIOx, UART4_GPIO_AFx, UART4_TX_GPIO_PINx); + gpio_mode_set(UART4_TX_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART4_TX_GPIO_PINx); + gpio_output_options_set(UART4_TX_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, UART4_TX_GPIO_PINx); + gpio_af_set(UART4_RX_GPIOx, UART4_GPIO_AFx, UART4_RX_GPIO_PINx); + gpio_mode_set(UART4_RX_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART4_RX_GPIO_PINx); + gpio_output_options_set(UART4_RX_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, UART4_RX_GPIO_PINx); break; #if defined (USART5) case USART5: - gpio_af_set(USART5_GPIO_PORT, GPIO_AF_8, USART5_TX_PIN); - gpio_mode_set(USART5_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART5_TX_PIN); - gpio_output_options_set(USART5_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, USART5_TX_PIN); - gpio_af_set(USART5_GPIO_PORT, GPIO_AF_8, USART5_RX_PIN); - gpio_mode_set(USART5_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART5_RX_PIN); - gpio_output_options_set(USART5_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, USART5_RX_PIN); + gpio_af_set(USART5_GPIOx, USART5_GPIO_AFx, USART5_TX_GPIO_PINx); + gpio_mode_set(USART5_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART5_TX_GPIO_PINx); + gpio_output_options_set(USART5_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, USART5_TX_GPIO_PINx); + gpio_af_set(USART5_GPIOx, USART5_GPIO_AFx, USART5_RX_GPIO_PINx); + gpio_mode_set(USART5_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, USART5_RX_GPIO_PINx); + gpio_output_options_set(USART5_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, USART5_RX_GPIO_PINx); break; #endif #if defined (UART6) case UART6: - gpio_af_set(UART6_GPIO_PORT, GPIO_AF_8, UART6_TX_PIN); - gpio_mode_set(UART6_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART6_TX_PIN); - gpio_output_options_set(UART6_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, UART6_TX_PIN); - gpio_af_set(UART6_GPIO_PORT, GPIO_AF_8, UART6_RX_PIN); - gpio_mode_set(UART6_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART6_RX_PIN); - gpio_output_options_set(UART6_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, UART6_RX_PIN); + gpio_af_set(UART6_GPIOx, UART6_GPIO_AFx, UART6_TX_GPIO_PINx); + gpio_mode_set(UART6_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART6_TX_GPIO_PINx); + gpio_output_options_set(UART6_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, UART6_TX_GPIO_PINx); + gpio_af_set(UART6_GPIOx, UART6_GPIO_AFx, UART6_RX_GPIO_PINx); + gpio_mode_set(UART6_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART6_RX_GPIO_PINx); + gpio_output_options_set(UART6_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, UART6_RX_GPIO_PINx); break; #endif #if defined (UART7) case UART7: - gpio_af_set(UART7_GPIO_PORT, GPIO_AF_8, UART7_TX_PIN); - gpio_mode_set(UART7_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART7_TX_PIN); - gpio_output_options_set(UART7_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, UART7_TX_PIN); - gpio_af_set(UART7_GPIO_PORT, GPIO_AF_8, UART7_RX_PIN); - gpio_mode_set(UART7_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART7_RX_PIN); - gpio_output_options_set(UART7_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, UART7_RX_PIN); + gpio_af_set(UART7_GPIOx, UART7_GPIO_AFx, UART7_TX_GPIO_PINx); + gpio_mode_set(UART7_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART7_TX_GPIO_PINx); + gpio_output_options_set(UART7_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, UART7_TX_GPIO_PINx); + gpio_af_set(UART7_GPIOx, UART7_GPIO_AFx, UART7_RX_GPIO_PINx); + gpio_mode_set(UART7_GPIOx, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UART7_RX_GPIO_PINx); + gpio_output_options_set(UART7_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, UART7_RX_GPIO_PINx); break; #endif default: @@ -259,8 +259,8 @@ void _gpio_init(const uint32_t usart_periph) { #endif void gd32_uart_begin(const uint32_t usart_periph, uint32_t baudrate, uint32_t bits, uint32_t parity, uint32_t stop_bits) { - _rcu_periph_clock_enable(usart_periph); - _gpio_init(usart_periph); + rcu_config(usart_periph); + gpio_config(usart_periph); usart_deinit(usart_periph); @@ -307,7 +307,11 @@ void gd32_uart_transmit(const uint32_t usart_periph, const uint8_t *data, uint32 while (length-- != 0) { while (RESET == usart_flag_get(usart_periph, USART_FLAG_TBE)) ; - USART_DATA(usart_periph) = ((uint16_t) USART_DATA_DATA & *data++); +#if defined (GD32H7XX) + USART_TDATA(usart_periph) = USART_TDATA_TDATA & (uint32_t)*data++; +#else + USART_DATA(usart_periph) = (USART_DATA_DATA & *data++); +#endif } } @@ -318,6 +322,10 @@ void gd32_uart_transmit_string(const uint32_t usart_periph, const char *data) { while (*data != '\0') { while (RESET == usart_flag_get(USART0, USART_FLAG_TBE)) ; - USART_DATA(usart_periph) = ((uint16_t) USART_DATA_DATA & *data++); +#if defined (GD32H7XX) + USART_TDATA(usart_periph) = USART_TDATA_TDATA & (uint32_t)*data++; +#else + USART_DATA(usart_periph) = (USART_DATA_DATA & *data++); +#endif } } diff --git a/lib-gd32/src/mac_address.cpp b/lib-gd32/src/mac_address.cpp index fe9b2d40..0306485c 100644 --- a/lib-gd32/src/mac_address.cpp +++ b/lib-gd32/src/mac_address.cpp @@ -2,7 +2,7 @@ * @file mac_address.cpp * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,12 +29,15 @@ #include "debug.h" void mac_address_get(uint8_t paddr[]) { -#if !defined (GD32F4XX) - const auto mac_hi = *(volatile uint32_t *) (0x1FFFF7E8); - const auto mac_lo = *(volatile uint32_t *) (0x1FFFF7EC); -#else +#if defined (GD32H7XX) + const auto mac_hi = *(volatile uint32_t *) (0x1FF0F7E8); + const auto mac_lo = *(volatile uint32_t *) (0x1FF0F7EC); +#elif defined (GD32F4XX) const auto mac_hi = *(volatile uint32_t *) (0x1FFF7A10); const auto mac_lo = *(volatile uint32_t *) (0x1FFF7A14); +#else + const auto mac_hi = *(volatile uint32_t *) (0x1FFFF7E8); + const auto mac_lo = *(volatile uint32_t *) (0x1FFFF7EC); #endif paddr[0] = 2; diff --git a/lib-gd32/src/ptp/gd32_ptp.cpp b/lib-gd32/src/ptp/gd32_ptp.cpp new file mode 100644 index 00000000..a027d5c0 --- /dev/null +++ b/lib-gd32/src/ptp/gd32_ptp.cpp @@ -0,0 +1,183 @@ +/** + * @file gd32_ptp.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include "gd32_ptp.h" +#include "gd32.h" + +#include "debug.h" + +extern "C" void console_error(const char *); + +#if defined (GD32H7XX) +# define enet_interrupt_disable(x) enet_interrupt_disable(ENETx, x) +# define enet_ptp_feature_enable(x) enet_ptp_feature_enable(ENETx, x) +# define enet_ptp_subsecond_increment_config(x) enet_ptp_subsecond_increment_config(ENETx, x) +# define enet_ptp_timestamp_function_config(x) enet_ptp_timestamp_function_config(ENETx, x) +# define enet_ptp_timestamp_addend_config(x) enet_ptp_timestamp_addend_config(ENETx, x) +# define enet_ptp_timestamp_update_config(x,y,z) enet_ptp_timestamp_update_config(ENETx, x, y, z) +# define enet_ptp_system_time_get(x) enet_ptp_system_time_get(ENETx, x) +static FlagStatus enet_ptpflagstatus_get(const uint32_t flag) { + FlagStatus bitstatus = RESET; + + if (0 != (ENET_PTP_TSCTL(ENETx) & flag)) { + bitstatus = SET; + } + + return bitstatus; +} +#else +static FlagStatus enet_ptpflagstatus_get(const uint32_t flag) { + FlagStatus bitstatus = RESET; + + if (0 != (ENET_PTP_TSCTL & flag)) { + bitstatus = SET; + } + + return bitstatus; +} +#endif + +static void ptp_start(const uint32_t init_sec, const uint32_t init_subsec, [[maybe_unused]] const uint32_t carry_cfg, const uint32_t accuracy_cfg) { + DEBUG_ENTRY + + enet_interrupt_disable(ENET_MAC_INT_TMSTIM); + +#if defined(GD32F4XX) || defined (GD32H7XX) + enet_ptp_feature_enable(ENET_ALL_RX_TIMESTAMP | ENET_RXTX_TIMESTAMP); +#else + enet_ptp_feature_enable(ENET_RXTX_TIMESTAMP); +#endif + enet_ptp_subsecond_increment_config(accuracy_cfg); + + enet_ptp_timestamp_addend_config(carry_cfg); + + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); + while(enet_ptpflagstatus_get(ENET_PTP_ADDEND_UPDATE) == SET); + + enet_ptp_timestamp_function_config(ENET_PTP_FINEMODE); + + enet_ptp_timestamp_update_config(ENET_PTP_ADD_TO_TIME, init_sec, init_subsec); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT); + while(enet_ptpflagstatus_get(ENET_PTP_SYSTIME_INIT) == SET); + + DEBUG_EXIT +} + +void gd32_ptp_start() { + DEBUG_ENTRY + DEBUG_PRINTF("PTP_TICK=%u", gd32::ptp::PTP_TICK); + DEBUG_PRINTF("ADJ_FREQ_BASE_INCREMENT=%u", gd32::ptp::ADJ_FREQ_BASE_INCREMENT); + DEBUG_PRINTF("ADJ_FREQ_BASE_ADDEND=x%X", gd32::ptp::ADJ_FREQ_BASE_ADDEND); + + struct tm tmbuf; + memset(&tmbuf, 0, sizeof(struct tm)); + tmbuf.tm_mday = _TIME_STAMP_DAY_; // The day of the month, in the range 1 to 31. + tmbuf.tm_mon = _TIME_STAMP_MONTH_ - 1; // The number of months since January, in the range 0 to 11. + tmbuf.tm_year = _TIME_STAMP_YEAR_ - 1900; // The number of years since 1900. + + ptp_start(mktime(&tmbuf), 0, gd32::ptp::ADJ_FREQ_BASE_ADDEND, gd32::ptp::ADJ_FREQ_BASE_INCREMENT); + +#ifndef NDEBUG + struct timeval tv; + gettimeofday(&tv, nullptr); + auto *tm = localtime(&tv.tv_sec); + + DEBUG_PRINTF("%.2d-%.2d-%.4d %.2d:%.2d:%.2d.%.6d", tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec, static_cast(tv.tv_usec)); +#endif + DEBUG_EXIT +} + +void gd32_ptp_get_time(gd32::ptp::ptptime *ptp_time) { + enet_ptp_systime_struct systime; + + enet_ptp_system_time_get(&systime); + + ptp_time->tv_sec = systime.second; +#if !defined (GD32F4XX) + ptp_time->tv_nsec = systime.nanosecond; +#else + ptp_time->tv_nsec = gd32::ptp_subsecond_2_nanosecond(systime.subsecond); +#endif +} + +void gd32_ptp_set_time(const gd32::ptp::ptptime *ptp_time) { + const auto nSign = ENET_PTP_ADD_TO_TIME; + const auto nSecond = ptp_time->tv_sec; + const auto nNanoSecond = ptp_time->tv_nsec; + const auto nSubSecond = gd32::ptp_nanosecond_2_subsecond(nNanoSecond); + + enet_ptp_timestamp_update_config(nSign, nSecond, nSubSecond); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_INIT); + while(enet_ptpflagstatus_get(ENET_PTP_SYSTIME_INIT) == SET); +} + +void gd32_ptp_update_time(const gd32::ptp::time_t *pTime) { + uint32_t nSign; + uint32_t nSecond; + uint32_t nNanoSecond; + + if (pTime->tv_sec < 0 || (pTime->tv_sec == 0 && pTime->tv_nsec < 0)) { + nSign = ENET_PTP_SUBSTRACT_FROM_TIME; + nSecond = -pTime->tv_sec; + nNanoSecond = -pTime->tv_nsec; + } else { + nSign = ENET_PTP_ADD_TO_TIME; + nSecond = pTime->tv_sec; + nNanoSecond = pTime->tv_nsec; + } + + const auto nSubSecond = gd32::ptp_nanosecond_2_subsecond(nNanoSecond); +#if defined (GD32H7XX) + const auto nAddend = ENET_PTP_TSADDEND(ENETx); +#else + const auto nAddend = ENET_PTP_TSADDEND; +#endif + + enet_ptp_timestamp_update_config(nSign, nSecond, nSubSecond); + enet_ptp_timestamp_function_config(ENET_PTP_SYSTIME_UPDATE); + while(enet_ptpflagstatus_get(ENET_PTP_SYSTIME_UPDATE) == SET); + + enet_ptp_timestamp_addend_config(nAddend); + enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); +} + +bool gd32_adj_frequency(const int32_t adjust_ppb) { + const uint32_t addend = gd32::ptp::ADJ_FREQ_BASE_ADDEND + static_cast((((static_cast(gd32::ptp::ADJ_FREQ_BASE_ADDEND)) * adjust_ppb) / 1000000000ULL)); + + enet_ptp_timestamp_addend_config(addend); + + const auto reval = enet_ptp_timestamp_function_config(ENET_PTP_ADDEND_UPDATE); + + if (reval == ERROR) { + console_error("enet_ptp_timestamp_addend_config\n"); + } + + return reval != ERROR; +} diff --git a/lib-gd32/src/softuart0/gd32_uart0.c b/lib-gd32/src/softuart0/gd32_uart0.c deleted file mode 100644 index 7f8dee8c..00000000 --- a/lib-gd32/src/softuart0/gd32_uart0.c +++ /dev/null @@ -1,189 +0,0 @@ -/** - * @file gd32_uart0.c - * - */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#if defined (NDEBUG) -# undef NDEBUG -#endif - -#include -#include -#include - -#include "gd32.h" - -#if !defined (SOFTUART_TX_PINx) -# define SOFTUART_TX_PINx GPIO_PIN_9 -# define SOFTUART_TX_GPIOx GPIOA -# define SOFTUART_TX_RCU_GPIOx RCU_GPIOA -#endif - -#if defined (GD32F4XX) -# define TIMER_CLOCK (APB2_CLOCK_FREQ * 2) -#else -# define TIMER_CLOCK (APB2_CLOCK_FREQ) -#endif - -#define BAUD_RATE (115200U) -#define TIMER_PERIOD ((TIMER_CLOCK / BAUD_RATE) - 1U) -#define BUFFER_SIZE (128U) - -typedef enum { - SOFTUART_IDLE, - SOFTUART_START_BIT, - SOFTUART_DATA, - SOFTUART_STOP_BIT, -} softuart_state; - -struct circular_buffer { - uint8_t buffer[BUFFER_SIZE]; - uint32_t head; - uint32_t tail; - bool full; -}; - -static volatile softuart_state s_state; -static volatile struct circular_buffer s_circular_buffer; -static volatile uint8_t s_data; -static volatile uint8_t s_shift; - -static bool is_circular_buffer_empty() { - return (!s_circular_buffer.full && (s_circular_buffer.head == s_circular_buffer.tail)); -} - -void TIMER0_UP_TIMER9_IRQHandler() { - GPIO_BOP(LED3_GPIOx) = LED3_GPIO_PINx; - - switch (s_state) { - case SOFTUART_IDLE: - break; - case SOFTUART_START_BIT: - GPIO_BC(SOFTUART_TX_GPIOx) = SOFTUART_TX_PINx; - - s_state = SOFTUART_DATA; - s_data = s_circular_buffer.buffer[s_circular_buffer.tail]; - s_circular_buffer.tail = (s_circular_buffer.tail + 1) & (BUFFER_SIZE - 1); - s_circular_buffer.full = false; - s_shift = 0; - break; - case SOFTUART_DATA: - if (s_data & (1U << s_shift)) { - GPIO_BOP(SOFTUART_TX_GPIOx) = SOFTUART_TX_PINx; - } else { - GPIO_BC(SOFTUART_TX_GPIOx) = SOFTUART_TX_PINx; - } - - s_shift++; - - if (s_shift == 8) { - s_state = SOFTUART_STOP_BIT; - } - break; - case SOFTUART_STOP_BIT: - GPIO_BOP(SOFTUART_TX_GPIOx) = SOFTUART_TX_PINx; - - if (is_circular_buffer_empty()) { - s_state = SOFTUART_IDLE; - timer_disable(TIMER9); - } else { - s_state = SOFTUART_START_BIT; - } - break; - default: - break; - } - - timer_interrupt_flag_clear(TIMER9, TIMER_INT_FLAG_UP); - - GPIO_BC(LED3_GPIOx) = LED3_GPIO_PINx; -} - -void uart0_init() { - rcu_periph_clock_enable (LED3_RCU_GPIOx); -#if !defined (GD32F4XX) - gpio_init(LED3_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LED3_GPIO_PINx); -#else - gpio_mode_set(LED3_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, LED3_GPIO_PINx); - gpio_output_options_set(LED3_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED3_GPIO_PINx); - gpio_af_set(LED3_GPIOx, GPIO_AF_0, LED3_GPIO_PINx); -#endif - - GPIO_BC(LED3_GPIOx) = LED3_GPIO_PINx; - - rcu_periph_clock_enable (SOFTUART_TX_RCU_GPIOx); - -#if !defined (GD32F4XX) - gpio_init(SOFTUART_TX_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SOFTUART_TX_PINx); -#else - gpio_mode_set(SOFTUART_TX_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, SOFTUART_TX_PINx); - gpio_output_options_set(SOFTUART_TX_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SOFTUART_TX_PINx); - gpio_af_set(SOFTUART_TX_GPIOx, GPIO_AF_0, SOFTUART_TX_PINx); -#endif - - GPIO_BOP(SOFTUART_TX_GPIOx) = SOFTUART_TX_PINx; - - rcu_periph_clock_enable(RCU_TIMER9); - - timer_deinit(TIMER9); - - timer_parameter_struct timer_initpara; - timer_initpara.prescaler = 0; - timer_initpara.alignedmode = TIMER_COUNTER_EDGE; - timer_initpara.counterdirection = TIMER_COUNTER_UP; - timer_initpara.period = TIMER_PERIOD; - timer_initpara.clockdivision = TIMER_CKDIV_DIV1; - - timer_init(TIMER9, &timer_initpara); - - timer_flag_clear(TIMER9, ~0); - timer_interrupt_flag_clear(TIMER9, ~0); - - timer_interrupt_enable(TIMER9, TIMER_INT_UP); - - NVIC_SetPriority(TIMER0_UP_TIMER9_IRQn, 2); - NVIC_EnableIRQ(TIMER0_UP_TIMER9_IRQn); -} - -static void _putc(int c) { - while (s_circular_buffer.full) - ; - - s_circular_buffer.buffer[s_circular_buffer.head] = (uint8_t) c; - s_circular_buffer.head = (s_circular_buffer.head + 1) & (BUFFER_SIZE - 1); - s_circular_buffer.full = s_circular_buffer.head == s_circular_buffer.tail; - - if (s_state == SOFTUART_IDLE) { - timer_counter_value_config(TIMER9, 0); - timer_enable(TIMER9); - s_state = SOFTUART_START_BIT; - } -} - -void uart0_putc(int c) { - if (c == '\n') { - _putc('\r'); - } - - _putc(c); -} diff --git a/lib-gd32/src/softuart0/uart0.cpp b/lib-gd32/src/softuart0/uart0.cpp new file mode 100644 index 00000000..14027731 --- /dev/null +++ b/lib-gd32/src/softuart0/uart0.cpp @@ -0,0 +1,234 @@ +/** + * @file uart0.c + * + */ +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# pragma GCC push_options +# pragma GCC optimize ("O2") +#endif + +#include +#include + +#include "gd32.h" + +#include "debug.h" + +#if defined (GD32H7XX) +# define TIMERx TIMER15 +# define RCU_TIMERx RCU_TIMER15 +# define TIMERx_IRQHandler TIMER15_IRQHandler +# define TIMERx_IRQn TIMER15_IRQn +#else +# define TIMERx TIMER9 +# define RCU_TIMERx RCU_TIMER9 +# define TIMERx_IRQHandler TIMER0_UP_TIMER9_IRQHandler +# define TIMERx_IRQn TIMER0_UP_TIMER9_IRQn +#endif + +#if defined (GD32H7XX) +# define TIMER_CLOCK_FREQ (AHB_CLOCK_FREQ) +#elif defined (GD32F4XX) +# define TIMER_CLOCK_FREQ (APB2_CLOCK_FREQ * 2) +#else +# define TIMER_CLOCK_FREQ (APB2_CLOCK_FREQ) +#endif + +#if !defined (SOFTUART_TX_PINx) +# define SOFTUART_TX_PINx GPIO_PIN_9 +# define SOFTUART_TX_GPIOx GPIOA +# define SOFTUART_TX_RCU_GPIOx RCU_GPIOA +#endif + +#define BAUD_RATE (115200U) +#define TIMER_PERIOD ((TIMER_CLOCK_FREQ / BAUD_RATE) - 1U) +#define BUFFER_SIZE (128U) + +typedef enum { + SOFTUART_IDLE, SOFTUART_START_BIT, SOFTUART_DATA, SOFTUART_STOP_BIT, +} softuart_state; + +struct circular_buffer { + uint8_t buffer[BUFFER_SIZE]; + uint32_t head; + uint32_t tail; + bool full; +}; + +static volatile softuart_state s_state; +static volatile struct circular_buffer s_circular_buffer; +static volatile uint8_t s_data; +static volatile uint8_t s_shift; + +static bool is_circular_buffer_empty() { + return (!s_circular_buffer.full && (s_circular_buffer.head == s_circular_buffer.tail)); +} + +extern "C" { +void TIMERx_IRQHandler() { + const auto nIntFlag = TIMER_INTF(TIMERx); + + if ((nIntFlag & TIMER_INT_FLAG_UP) == TIMER_INT_FLAG_UP) { +#if defined (LED3_GPIO_PINx) + GPIO_BOP(LED3_GPIOx) = LED3_GPIO_PINx; +#endif + + switch (s_state) { + case SOFTUART_IDLE: + break; + case SOFTUART_START_BIT: + GPIO_BC(SOFTUART_TX_GPIOx) = SOFTUART_TX_PINx; + + s_state = SOFTUART_DATA; + s_data = s_circular_buffer.buffer[s_circular_buffer.tail]; + s_circular_buffer.tail = (s_circular_buffer.tail + 1) & (BUFFER_SIZE - 1); + s_circular_buffer.full = false; + s_shift = 0; + break; + case SOFTUART_DATA: + if (s_data & (1U << s_shift)) { + GPIO_BOP(SOFTUART_TX_GPIOx) = SOFTUART_TX_PINx; + } else { + GPIO_BC(SOFTUART_TX_GPIOx) = SOFTUART_TX_PINx; + } + + s_shift++; + + if (s_shift == 8) { + s_state = SOFTUART_STOP_BIT; + } + break; + case SOFTUART_STOP_BIT: + GPIO_BOP(SOFTUART_TX_GPIOx) = SOFTUART_TX_PINx; + + if (is_circular_buffer_empty()) { + s_state = SOFTUART_IDLE; + timer_disable(TIMERx); + } else { + s_state = SOFTUART_START_BIT; + } + break; + default: + break; + } + +#if defined (LED3_GPIO_PINx) + GPIO_BC(LED3_GPIOx) = LED3_GPIO_PINx; +#endif + } + + TIMER_INTF(TIMERx) = static_cast(~nIntFlag); +} + +void uart0_init() { + s_state = SOFTUART_IDLE; + s_circular_buffer.head = 0; + s_circular_buffer.tail = 0; + s_circular_buffer.full = false; + +#if defined (LED3_GPIO_PINx) + rcu_periph_clock_enable (LED3_RCU_GPIOx); +# if defined (GPIO_INIT) + gpio_init(LED3_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LED3_GPIO_PINx); +# else + gpio_mode_set(LED3_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, LED3_GPIO_PINx); + gpio_output_options_set(LED3_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, LED3_GPIO_PINx); +# endif + + GPIO_BC(LED3_GPIOx) = LED3_GPIO_PINx; +#endif + + rcu_periph_clock_enable (SOFTUART_TX_RCU_GPIOx); + +#if defined (GPIO_INIT) + gpio_init(SOFTUART_TX_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SOFTUART_TX_PINx); +#else + gpio_mode_set(SOFTUART_TX_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, SOFTUART_TX_PINx); + gpio_output_options_set(SOFTUART_TX_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, SOFTUART_TX_PINx); +#endif + + GPIO_BOP(SOFTUART_TX_GPIOx) = SOFTUART_TX_PINx; + + rcu_periph_clock_enable(RCU_TIMERx); + + timer_deinit(TIMERx); + + timer_parameter_struct timer_initpara; + timer_struct_para_init(&timer_initpara); + + timer_initpara.prescaler = 0; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = TIMER_PERIOD; + timer_initpara.clockdivision = TIMER_CKDIV_DIV1; + timer_initpara.repetitioncounter = 0; + + timer_init(TIMERx, &timer_initpara); + + timer_flag_clear(TIMERx, ~0); + timer_interrupt_flag_clear(TIMERx, ~0); + + timer_interrupt_enable(TIMERx, TIMER_INT_UP); + + NVIC_SetPriority(TIMERx_IRQn, 2); + NVIC_EnableIRQ(TIMERx_IRQn); +} + +static void _putc(const int c) { + //FIXME deadlock when timer is not running + while (s_circular_buffer.full) + ; + + s_circular_buffer.buffer[s_circular_buffer.head] = (uint8_t) c; + s_circular_buffer.head = (s_circular_buffer.head + 1) & (BUFFER_SIZE - 1); + s_circular_buffer.full = s_circular_buffer.head == s_circular_buffer.tail; + + if (s_state == SOFTUART_IDLE) { + timer_counter_value_config(TIMERx, 0); + timer_enable(TIMERx); + s_state = SOFTUART_START_BIT; + } +} + +void uart0_putc(int c) { + if (c == '\n') { + _putc('\r'); + } + + _putc(c); +} + +void uart0_puts(const char *s) { + while (*s != '\0') { + if (*s == '\n') { + uart0_putc('\r'); + } + uart0_putc(*s++); + } + + do { + __DMB(); + } while (!is_circular_buffer_empty()); +} +} diff --git a/lib-gd32/src/systick.c b/lib-gd32/src/systick/systick.cpp similarity index 77% rename from lib-gd32/src/systick.c rename to lib-gd32/src/systick/systick.cpp index 2e9e6722..f269c586 100644 --- a/lib-gd32/src/systick.c +++ b/lib-gd32/src/systick/systick.cpp @@ -2,7 +2,7 @@ * @file systick.c * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,23 +23,24 @@ * THE SOFTWARE. */ -#include +#include #include "gd32.h" -volatile uint32_t s_nSysTickMillis; +volatile uint32_t gv_nSysTickMillis; -void systick_config(void) { - /* setup systick timer for 1000Hz interrupts */ +extern "C" { +void systick_config() { + /* Setup systick timer for 1000Hz interrupts */ if (SysTick_Config(SystemCoreClock / 1000U)) { - /* capture error */ while (1) { } } - /* configure the systick handler priority */ - NVIC_SetPriority(SysTick_IRQn, 0x00U); + + NVIC_SetPriority(SysTick_IRQn, (1UL<<__NVIC_PRIO_BITS)-1UL); // Lowest priority } -void SysTick_Handler(void) { - s_nSysTickMillis++; +void SysTick_Handler() { + gv_nSysTickMillis++; +} } diff --git a/lib-gd32/src/timer6.cpp b/lib-gd32/src/timer6.cpp new file mode 100644 index 00000000..0cbf908b --- /dev/null +++ b/lib-gd32/src/timer6.cpp @@ -0,0 +1,86 @@ +/** + * @file timer6.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma GCC push_options +#pragma GCC optimize ("O2") + +#include "gd32.h" + +struct HwTimersSeconds g_Seconds; + +extern "C" { +#if defined (CONFIG_TIMER6_HAVE_NO_IRQ_HANDLER) +void TIMER6_IRQHandler() { + const auto nIntFlag = TIMER_INTF(TIMER6); + + if ((nIntFlag & TIMER_INT_FLAG_UP) == TIMER_INT_FLAG_UP) { + g_Seconds.nUptime++; + } + + TIMER_INTF(TIMER6) = static_cast(~nIntFlag); +} +#endif +} + +void timer6_config() { + g_Seconds.nUptime = 0; + + rcu_periph_clock_enable(RCU_TIMER6); + timer_deinit(TIMER6); + + timer_parameter_struct timer_initpara; + timer_struct_para_init(&timer_initpara); + + timer_initpara.prescaler = TIMER_PSC_10KHZ; + timer_initpara.period = (10000 - 1); // 1 second + timer_init(TIMER6, &timer_initpara); + + timer_counter_value_config(TIMER6, 0); + + timer_interrupt_flag_clear(TIMER6, ~0); + + timer_interrupt_enable(TIMER6, TIMER_INT_UP); + + NVIC_SetPriority(TIMER6_IRQn, (1UL<<__NVIC_PRIO_BITS)-1UL); // Lowest priority + NVIC_EnableIRQ(TIMER6_IRQn); + + timer_enable(TIMER6); +} + +uint32_t timer6_get_elapsed_milliseconds() { + const auto nUptimeFirst = g_Seconds.nUptime; + auto nTimerCount = TIMER_CNT(TIMER6); + const auto nUptimeSecond = g_Seconds.nUptime; + + // Check for consistency + if (__builtin_expect((nUptimeFirst == nUptimeSecond), 1)) { + // No overflow detected, return the calculated time + return (nUptimeFirst * 1000U) + (nTimerCount / 10U); + } + + // Potential overflow detected, re-read the timer count + nTimerCount = TIMER_CNT(TIMER6); + return (nUptimeSecond * 1000U) + (nTimerCount / 10U); +} diff --git a/lib-gd32/src/gd32_uart0.c b/lib-gd32/src/uart0.cpp similarity index 81% rename from lib-gd32/src/gd32_uart0.c rename to lib-gd32/src/uart0.cpp index 17335bda..7562f3b3 100644 --- a/lib-gd32/src/gd32_uart0.c +++ b/lib-gd32/src/uart0.cpp @@ -1,8 +1,8 @@ /** - * @file gd32_uart0.c + * @file uart0.cpp * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,23 +23,13 @@ * THE SOFTWARE. */ -#include -#include - -extern void uart0_putc(int); +#include +#include static char s_buffer[128]; -void uart0_puts(const char *s) { - while (*s != '\0') { - if (*s == '\n') { - uart0_putc('\r'); - } - uart0_putc(*s++); - } - -// uart0_putc('\n'); //TODO Add '\n' -} +extern "C" { +void uart0_putc(int); int uart0_printf(const char *fmt, ...) { va_list arp; @@ -61,3 +51,4 @@ int uart0_printf(const char *fmt, ...) { return i; } +} diff --git a/lib-gd32/src/uart0/gd32_uart0.c b/lib-gd32/src/uart0/uart0.cpp similarity index 66% rename from lib-gd32/src/uart0/gd32_uart0.c rename to lib-gd32/src/uart0/uart0.cpp index e7c531fa..4adcc136 100644 --- a/lib-gd32/src/uart0/gd32_uart0.c +++ b/lib-gd32/src/uart0/uart0.cpp @@ -1,8 +1,8 @@ /** - * @file gd32_uart0.c + * @file uart0.cpp * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,12 +23,13 @@ * THE SOFTWARE. */ -#include -#include +#include +#include #include "gd32.h" #include "gd32_uart.h" +extern "C" { void uart0_init(void) { gd32_uart_begin(USART0, 115200U, GD32_UART_BITS_8, GD32_UART_PARITY_NONE, GD32_UART_STOP_1BIT); } @@ -37,11 +38,46 @@ void uart0_putc(int c) { if (c == '\n') { while (RESET == usart_flag_get(USART0, USART_FLAG_TBE)) ; +#if defined (GD32H7XX) + USART_TDATA(USART0) = USART_TDATA_TDATA & (uint32_t)'\r'; +#else USART_DATA(USART0) = ((uint16_t) USART_DATA_DATA & (uint8_t) '\r'); +#endif } while (RESET == usart_flag_get(USART0, USART_FLAG_TBE)) ; - +#if defined (GD32H7XX) + USART_TDATA(USART0) = USART_TDATA_TDATA & (uint32_t) c; +#else USART_DATA(USART0) = ((uint16_t) USART_DATA_DATA & (uint8_t) c); +#endif +} + +void uart0_puts(const char *s) { + while (*s != '\0') { + if (*s == '\n') { + uart0_putc('\r'); + } + uart0_putc(*s++); + } +} + +int uart0_getc(void) { + if (__builtin_expect((!gd32_usart_flag_get(USART0)), 1)) { + return EOF; + } + +#if defined (GD32H7XX) + const auto c = static_cast(USART_RDATA(USART0)); +#else + const auto c = static_cast(USART_DATA(USART0)); +#endif + +#if defined (UART0_ECHO) + uart0_putc(c); +#endif + + return c; +} } diff --git a/lib-gd32/src/udelay.cpp b/lib-gd32/src/udelay.cpp index 81cb713e..737780d3 100644 --- a/lib-gd32/src/udelay.cpp +++ b/lib-gd32/src/udelay.cpp @@ -2,7 +2,7 @@ * @file udelay.cpp * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,9 +28,9 @@ #include "gd32.h" -static constexpr auto TICKS_PER_US = (MCU_CLOCK_FREQ / 1000000U); +static constexpr uint32_t TICKS_PER_US = (MCU_CLOCK_FREQ / 1000000U); -void udelay_init(void) { +void udelay_init() { assert(MCU_CLOCK_FREQ == SystemCoreClock); CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; @@ -38,21 +38,20 @@ void udelay_init(void) { DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; } -void udelay(uint32_t nUs, uint32_t nOffsetCYCCNT) { - const auto nTicks = nUs * TICKS_PER_US; +void udelay(uint32_t nMicros, uint32_t nOffsetMicros) { + const auto nTicks = nMicros * TICKS_PER_US; uint32_t nTicksCount = 0; - uint32_t nTicksNow; uint32_t nTicksPrevious; - if (nOffsetCYCCNT == 0) { + if (nOffsetMicros == 0) { nTicksPrevious = DWT->CYCCNT; } else { - nTicksPrevious = nOffsetCYCCNT; + nTicksPrevious = nOffsetMicros; } while (1) { - nTicksNow = DWT->CYCCNT; + const auto nTicksNow = DWT->CYCCNT; if (nTicksNow != nTicksPrevious) { if (nTicksNow > nTicksPrevious) { diff --git a/lib-hal/.cproject b/lib-hal/.cproject index 707bf5ad..8f1d9807 100644 --- a/lib-hal/.cproject +++ b/lib-hal/.cproject @@ -30,11 +30,9 @@ - diff --git a/lib-hal/.settings/language.settings.xml b/lib-hal/.settings/language.settings.xml index e0cd2023..f2f25c89 100644 --- a/lib-hal/.settings/language.settings.xml +++ b/lib-hal/.settings/language.settings.xml @@ -2,7 +2,10 @@ - + + + + diff --git a/lib-hal/.settings/org.eclipse.ltk.core.refactoring.prefs b/lib-hal/.settings/org.eclipse.ltk.core.refactoring.prefs new file mode 100644 index 00000000..b196c64a --- /dev/null +++ b/lib-hal/.settings/org.eclipse.ltk.core.refactoring.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/lib-hal/Makefile.GD32 b/lib-hal/Makefile.GD32 index a03d2caa..449d03ef 100644 --- a/lib-hal/Makefile.GD32 +++ b/lib-hal/Makefile.GD32 @@ -1,26 +1,39 @@ DEFINES=NDEBUG -ifneq ($(MAKE_FLAGS),) - ifeq ($(findstring USE_LEDBLINK_BITBANGING595,$(MAKE_FLAGS)), USE_LEDBLINK_BITBANGING595) - EXTRA_SRCDIR=src/gd32/bitbanging +EXTRA_SRCDIR= + +ifneq ($(MAKE_FLAGS),) + ifeq (,$(findstring DISABLE_RTC,$(MAKE_FLAGS))) + ifeq (,$(findstring DISABLE_INTERNAL_RTC,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=rtc/gd32 + endif + endif + + ifeq ($(findstring ENABLE_USB_HOST,$(MAKE_FLAGS)), ENABLE_USB_HOST) + ifeq ($(findstring gd32h7xx,$(FAMILY)), gd32h7xx) + EXTRA_SRCDIR+=device/usb/host/gd32/h + EXTRA_INCLUDES+=device/usb/host/gd32/h + else + EXTRA_SRCDIR+=device/usb/host/gd32/f + EXTRA_INCLUDES+=device/usb/host/gd32/f + endif + EXTRA_SRCDIR+=device/usb/host/gd32 + EXTRA_INCLUDES+=device/usb/host/gd32 endif - - ifneq (,$(findstring DEBUG_EMAC,$(MAKE_FLAGS))) + + ifneq (,$(findstring DEBUG_EMAC,$(MAKE_FLAGS))) EXTRA_SRCDIR+=debug/emac/gd32 endif - - ifeq ($(findstring ENABLE_USB_HOST,$(MAKE_FLAGS)), ENABLE_USB_HOST) - EXTRA_SRCDIR+=device/usb/host/gd32 - EXTRA_INCLUDES+=device/usb/host/gd32 - endif else - EXTRA_SRCDIR+=debug/emac/gd32 - EXTRA_SRCDIR+=ff12c ff12c/option - - EXTRA_SRCDIR+=device/usb/host/gd32 - EXTRA_INCLUDES+=device/usb/host/gd32 + ifneq (, $(shell test -d '../lib-network/src/noemac' && echo -n yes)) + else + EXTRA_SRCDIR+=debug/emac/gd32 + endif + EXTRA_SRCDIR+=rtc/gd32 +# EXTRA_SRCDIR+=device/usb/host/gd32 +# EXTRA_INCLUDES+=device/usb/host/gd32 - DEFINES=ENABLE_USB_HOST CONFIG_USB_HOST_MSC +# DEFINES=ENABLE_USB_HOST CONFIG_USB_HOST_MSC endif include Rules.mk diff --git a/lib-hal/Rules.mk b/lib-hal/Rules.mk old mode 100644 new mode 100755 index cea16ff8..0ae3fcec --- a/lib-hal/Rules.mk +++ b/lib-hal/Rules.mk @@ -1,5 +1,7 @@ $(info $$MAKE_FLAGS [${MAKE_FLAGS}]) +EXTRA_SRCDIR+=debug + ifneq ($(MAKE_FLAGS),) ifneq (,$(findstring CONSOLE_I2C,$(MAKE_FLAGS))) EXTRA_SRCDIR+=console/i2c @@ -14,23 +16,43 @@ ifneq ($(MAKE_FLAGS),) endif endif endif - ifneq ($(findstring DISABLE_RTC,$(MAKE_FLAGS)), DISABLE_RTC) + + FATFS= + ifeq ($(findstring CONFIG_USB_HOST_MSC,$(MAKE_FLAGS)), CONFIG_USB_HOST_MSC) + FATFS=1 + endif + + ifeq (,$(findstring DISABLE_FS,$(MAKE_FLAGS))) + FATFS=1 + endif + + ifdef FATFS + EXTRA_SRCDIR+=ff14b/source + EXTRA_SRCDIR+=posix + endif + + ifeq (,$(findstring DISABLE_RTC,$(MAKE_FLAGS))) EXTRA_SRCDIR+=rtc - ifeq ($(findstring DISABLE_INTERNAL_RTC,$(MAKE_FLAGS)), DISABLE_INTERNAL_RTC) + ifneq (,$(findstring DISABLE_INTERNAL_RTC,$(MAKE_FLAGS))) EXTRA_SRCDIR+=rtc/i2c - else - EXTRA_SRCDIR+=rtc/gd32 endif + EXTRA_INCLUDES+=../lib-properties/include endif + ifneq (,$(findstring DEBUG_I2C,$(MAKE_FLAGS))) EXTRA_SRCDIR+=debug/i2c EXTRA_INCLUDES+=debug/i2c endif + ifneq (,$(findstring DEBUG_STACK,$(MAKE_FLAGS))) EXTRA_SRCDIR+=debug/stack endif else - DEFINES+=DEBUG_I2C DEBUG_STACK - EXTRA_INCLUDES+=debug/i2c - EXTRA_SRCDIR+=console/i2c console/null console/uart0 rtc debug/stack debug/i2c + DEFINES+=DEBUG_I2C DEBUG_STACK DEBUG_POSIX + DEFINES+=LOGIC_ANALYZER + EXTRA_INCLUDES+=debug/i2c debug/stack + EXTRA_SRCDIR+=console/i2c console/null console/uart0 + EXTRA_SRCDIR+=posix + EXTRA_SRCDIR+=rtc rtc/i2c + EXTRA_INCLUDES+=../lib-properties/include endif diff --git a/lib-hal/console/h3/console.c b/lib-hal/console/h3/console.c deleted file mode 100644 index 809a5bef..00000000 --- a/lib-hal/console/h3/console.c +++ /dev/null @@ -1,381 +0,0 @@ -/** - * @file console.c - * - */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "console.h" - -#include "device/fb.h" - -#include "arm/arm.h" - -extern unsigned char FONT[] __attribute__((aligned(4))); - -static const uint32_t FB_CHAR_W = 8; -static const uint32_t FB_CHAR_H = 16; - -static uint32_t current_x = 0; -static uint32_t current_y = 0; -static uint32_t saved_x = 0; -static uint32_t saved_y = 0; - -static uint32_t top_row = 0; - -static uint32_t cur_fore = CONSOLE_WHITE; -static uint32_t cur_back = CONSOLE_BLACK; -static uint32_t saved_fore = CONSOLE_WHITE; -static uint32_t saved_back = CONSOLE_BLACK; - -#if defined(USE_UBOOT_HDMI) -#undef FB_WIDTH -#define FB_WIDTH fb_width - -#undef FB_HEIGHT -#define FB_HEIGHT fb_height - -#undef FB_PITCH -#define FB_PITCH fb_pitch - -#undef FB_ADDRESS -#define FB_ADDRESS fb_addr -#endif - -void __attribute__((cold)) console_init(void) { - const int r = fb_init(); - - if (r == FB_OK) { - console_clear(); - } -} - -uint32_t console_get_line_width(void) { - return FB_WIDTH / FB_CHAR_W; -} - -void console_set_top_row(uint32_t row) { - if (row > FB_HEIGHT / FB_CHAR_H) { - top_row = 0; - } else { - top_row = row; - } - - current_x = 0; - current_y = row; -} - -inline static void clear_row(uint32_t *address) { - uint32_t i; - - for (i = 0 ; i < (FB_CHAR_H * FB_WIDTH) ; i++) { - *address++ = cur_back; - } -} - -inline static void newline(void) { - uint32_t i; - uint32_t *address; - uint32_t *to; - uint32_t *from; - - current_y++; - current_x = 0; - - if (current_y == FB_HEIGHT / FB_CHAR_H) { - if (top_row == 0) { - /* Pointer to row = 0 */ - to = (uint32_t *) (FB_ADDRESS); - /* Pointer to row = 1 */ - from = to + (FB_CHAR_H * FB_WIDTH); - /* Copy block from {row = 1, rows} to {row = 0, rows - 1} */ - i = ((FB_HEIGHT - FB_CHAR_H) * FB_WIDTH); - } else { - to = (uint32_t *) (FB_ADDRESS) + ((FB_CHAR_H * FB_WIDTH) * top_row); - from = to + (FB_CHAR_H * FB_WIDTH); - i = ((FB_HEIGHT - FB_CHAR_H) * FB_WIDTH - ((FB_CHAR_H * FB_WIDTH) * top_row)); - } - - memcpy_blk(to, from, i/8); - - /* Clear last row */ - address = (uint32_t *)(FB_ADDRESS) + ((FB_HEIGHT - FB_CHAR_H) * FB_WIDTH); - clear_row(address); - - current_y--; - } -} - -inline static void draw_pixel(uint32_t x, uint32_t y, uint32_t color) { - volatile uint32_t *address = (volatile uint32_t *)(FB_ADDRESS + (x * FB_BYTES_PER_PIXEL) + (y * FB_WIDTH * FB_BYTES_PER_PIXEL)); - *address = (uint32_t) color; -} - -inline static void draw_char(int c, uint32_t x, uint32_t y, uint32_t fore, uint32_t back) { - uint32_t i, j; - uint8_t line; - unsigned char *p = FONT + (c * (int) FB_CHAR_H); - - for (i = 0; i < FB_CHAR_H; i++) { - line = (uint8_t) *p++; - for (j = x; j < (FB_CHAR_W + x); j++) { - if ((line & 0x1) != 0) { - draw_pixel(j, y, fore); - } else { - draw_pixel(j, y, back); - } - line >>= 1; - } - y++; - } -} - -int console_draw_char(int ch, uint16_t x, uint16_t y, uint32_t fore, uint32_t back) { - draw_char(ch, x * FB_CHAR_W, y * FB_CHAR_H, fore, back); - return (int)ch; -} - -void console_putc(int ch) { - if (ch == (int)'\n') { - newline(); - } else if (ch == (int)'\r') { - current_x = 0; - } else if (ch == (int)'\t') { - current_x += 4; - } else { - draw_char(ch, current_x * FB_CHAR_W, current_y * FB_CHAR_H, cur_fore, cur_back); - current_x++; - if (current_x == FB_WIDTH / FB_CHAR_W) { - newline(); - } - } -} - -void console_puts(const char *s) { - char c; - while ((c = *s++) != (char) 0) { - console_putc((int) c); - } -} - -void console_write(const char *s, unsigned int n) { - char c; - - while (((c = *s++) != (char) 0) && (n-- != 0)) { - console_putc((int) c); - } -} - -void console_error(const char *s) { - uint32_t fore_current = cur_fore; - uint32_t back_current = cur_back; - - cur_fore = CONSOLE_RED; - cur_back = CONSOLE_BLACK; - - console_puts("Error <"); - console_puts((char *) s); - console_puts(">\n"); - - cur_fore = fore_current; - cur_back = back_current; -} - -void console_status(uint32_t color, const char *s) { - const uint32_t fore_current = cur_fore; - const uint32_t back_current = cur_back; - - const uint32_t s_y = current_y; - const uint32_t s_x = current_x; - - console_clear_line(29); - - cur_fore = color; - cur_back = CONSOLE_BLACK; - - console_puts((char *)s); - - current_y = s_y; - current_x = s_x; - - cur_fore = fore_current; - cur_back = back_current; -} - -#define TO_HEX(i) ((i) < 10) ? (uint8_t)'0' + (i) : (uint8_t)'A' + ((i) - (uint8_t)10) - -void console_puthex(uint8_t data) { - console_putc((int) (TO_HEX(((data & 0xF0) >> 4)))); - console_putc((int) (TO_HEX(data & 0x0F))); -} - -void console_puthex_fg_bg(uint8_t data, uint32_t fore, uint32_t back) { - uint32_t fore_current = cur_fore; - uint32_t back_current = cur_back; - - cur_fore = fore; - cur_back = back; - - (void) console_putc((int) (TO_HEX(((data & 0xF0) >> 4)))); - (void) console_putc((int) (TO_HEX(data & 0x0F))); - - cur_fore = fore_current; - cur_back = back_current; -} - -void console_putpct_fg_bg(uint8_t data, uint32_t fore, uint32_t back) { - uint32_t fore_current = cur_fore; - uint32_t back_current = cur_back; - - cur_fore = fore; - cur_back = back; - - if (data < 100) { - console_putc((int) ((char) '0' + (char) (data / 10))); - console_putc((int) ((char) '0' + (char) (data % 10))); - } else { - console_puts("%%"); - } - - cur_fore = fore_current; - cur_back = back_current; -} - -void console_put3dec_fg_bg(uint8_t data, uint32_t fore, uint32_t back) { - uint32_t fore_current = cur_fore; - uint32_t back_current = cur_back; - - cur_fore = fore; - cur_back = back; - - const uint8_t i = data / 100; - - (void) console_putc((int) ((char) '0' + (char) i)); - - data = (uint8_t)(data - (i * 100)); - - console_putc((int) ((char) '0' + (char) (data / 10))); - console_putc((int) ((char) '0' + (char) (data % 10))); - - cur_fore = fore_current; - cur_back = back_current; -} - -void console_newline(void){ - newline(); -} - -void console_clear(void) { - uint32_t *address = (uint32_t *)(fb_addr); - uint32_t i; - - for (i = 0; i < (FB_HEIGHT * FB_WIDTH); i++) { - *address++ = (uint32_t) cur_back; - } - - current_x = 0; - current_y = 0; -} - -void console_set_cursor(uint32_t x, uint32_t y) { - if (x > FB_WIDTH / FB_CHAR_W) - current_x = 0; - else - current_x = x; - - if (y > FB_HEIGHT / FB_CHAR_H) - current_y = 0; - else - current_y = y; -} - -void console_save_cursor(void) { - saved_y = current_y; - saved_x = current_x; - saved_back = cur_back; - saved_fore = cur_fore; -} - -void console_restore_cursor(void) { - current_y = saved_y; - current_x = saved_x; - cur_back = saved_back; - cur_fore = saved_fore; -} - -void console_save_color(void) { - saved_back = cur_back; - saved_fore = cur_fore; -} - -void console_restore_color(void) { - cur_back = saved_back; - cur_fore = saved_fore; -} - -void console_set_fg_color(uint32_t fore) { - cur_fore = fore; -} - -void console_set_bg_color(uint32_t back) { - cur_back = back; -} - -void console_set_fg_bg_color(uint32_t fore, uint32_t back) { - cur_fore = fore; - cur_back = back; -} - -void console_clear_line(uint32_t line) { - uint32_t *address; - - if (line > FB_HEIGHT / FB_CHAR_H) { - return; - } else { - current_y = line; - } - - current_x = 0; - - address = (uint32_t *)(fb_addr) + (line * FB_CHAR_H * FB_WIDTH); - clear_row(address); -} - -void console_clear_top_row(void) { - uint32_t line; - uint32_t *address; - - for (line = top_row; line < (FB_HEIGHT / FB_CHAR_H) - 1; line++) { - address = (uint32_t*) (fb_addr) + (line * FB_CHAR_H * FB_WIDTH); - clear_row(address); - } - - current_x = 0; - current_y = top_row; -} - -void console_putpixel(uint32_t x, uint32_t y, uint32_t color) { - draw_pixel(x, y, color); -} - diff --git a/lib-hal/console/i2c/console.c b/lib-hal/console/i2c/console.cpp similarity index 77% rename from lib-hal/console/i2c/console.c rename to lib-hal/console/i2c/console.cpp index d33e8a75..37be38bf 100644 --- a/lib-hal/console/i2c/console.c +++ b/lib-hal/console/i2c/console.cpp @@ -1,8 +1,8 @@ /** - * @file console.c + * @file console.cpp * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,9 +23,8 @@ * THE SOFTWARE. */ -#include -#include -#include +#include +#include #include "console.h" @@ -34,57 +33,57 @@ static bool s_isConnected; #if !defined (CONSOLE_I2C_ADDRESS) -# define CONSOLE_I2C_ADDRESS ((uint8_t)0x4D) +# define CONSOLE_I2C_ADDRESS (0x4D) #endif #if !defined (CONSOLE_I2C_ONBOARD_CRYSTAL) -# define CONSOLE_I2C_ONBOARD_CRYSTAL 14745600UL +# define CONSOLE_I2C_ONBOARD_CRYSTAL (14745600UL) #endif #if !defined (CONSOLE_I2C_BAUDRATE) -# define CONSOLE_I2C_BAUDRATE 115200U +# define CONSOLE_I2C_BAUDRATE (115200U) #endif #define SC16IS7X0_REG_SHIFT 3 -#define SC16IS7X0_THR ((uint8_t)(0x00 << SC16IS7X0_REG_SHIFT)) -#define SC16IS7X0_FCR ((uint8_t)(0x02 << SC16IS7X0_REG_SHIFT)) -#define SC16IS7X0_LCR ((uint8_t)(0x03 << SC16IS7X0_REG_SHIFT)) -#define SC16IS7X0_MCR ((uint8_t)(0x04 << SC16IS7X0_REG_SHIFT)) -#define SC16IS7X0_SPR ((uint8_t)(0x07 << SC16IS7X0_REG_SHIFT)) -#define SC16IS7X0_TLR ((uint8_t)(0x07 << SC16IS7X0_REG_SHIFT)) -#define SC16IS7X0_TXLVL ((uint8_t)(0x08 << SC16IS7X0_REG_SHIFT)) +#define SC16IS7X0_THR (0x00 << SC16IS7X0_REG_SHIFT) +#define SC16IS7X0_FCR (0x02 << SC16IS7X0_REG_SHIFT) +#define SC16IS7X0_LCR (0x03 << SC16IS7X0_REG_SHIFT) +#define SC16IS7X0_MCR (0x04 << SC16IS7X0_REG_SHIFT) +#define SC16IS7X0_SPR (0x07 << SC16IS7X0_REG_SHIFT) +#define SC16IS7X0_TLR (0x07 << SC16IS7X0_REG_SHIFT) +#define SC16IS7X0_TXLVL (0x08 << SC16IS7X0_REG_SHIFT) -#define SC16IS7X0_DLL ((uint8_t)(0x00 << SC16IS7X0_REG_SHIFT)) -#define SC16IS7X0_DLH ((uint8_t)(0x01 << SC16IS7X0_REG_SHIFT)) -#define SC16IS7X0_EFR ((uint8_t)(0x02 << SC16IS7X0_REG_SHIFT)) +#define SC16IS7X0_DLL (0x00 << SC16IS7X0_REG_SHIFT) +#define SC16IS7X0_DLH (0x01 << SC16IS7X0_REG_SHIFT) +#define SC16IS7X0_EFR (0x02 << SC16IS7X0_REG_SHIFT) /** See section 8.3 of the datasheet for definitions * of bits in the FIFO Control Register (FCR) */ -#define FCR_TX_FIFO_RST ((uint8_t)(1U << 2)) -#define FCR_ENABLE_FIFO ((uint8_t)(1U << 0)) +#define FCR_TX_FIFO_RST (1U << 2) +#define FCR_ENABLE_FIFO (1U << 0) /** See section 8.4 of the datasheet for definitions * of bits in the Line Control Register (LCR) */ -#define LCR_BITS8 ((uint8_t)0x03) -#define LCR_BITS1 ((uint8_t)0x00) -#define LCR_NONE ((uint8_t)0x00) -#define LCR_ENABLE_DIV ((uint8_t)0x80) +#define LCR_BITS8 (0x03) +#define LCR_BITS1 (0x00) +#define LCR_NONE (0x00) +#define LCR_ENABLE_DIV (0x80) /** * 8.6 Modem Control Register (MCR) */ //MCR[2] only accessible when EFR[4] is set -#define MCR_ENABLE_TCR_TLR ((uint8_t)(1U << 2)) -#define MCR_PRESCALE_4 ((uint8_t)(1U << 7)) +#define MCR_ENABLE_TCR_TLR (1U << 2) +#define MCR_PRESCALE_4 (1U << 7) /** * 8.11 Enhanced Features Register (EFR) */ -#define EFR_ENABLE_ENHANCED_FUNCTIONS ((uint8_t)(1U << 4)) +#define EFR_ENABLE_ENHANCED_FUNCTIONS (1U << 4) static bool is_connected(const uint8_t address, const uint32_t baudrate) { char buf; @@ -97,7 +96,7 @@ static bool is_connected(const uint8_t address, const uint32_t baudrate) { } /* This is known to corrupt the Atmel AT24RF08 EEPROM */ - return FUNC_PREFIX(i2c_write(NULL, 0)) == 0; + return FUNC_PREFIX(i2c_write(nullptr, 0)) == 0; } static void setup() { @@ -108,8 +107,8 @@ static void setup() { static void write_register(uint8_t nRegister, uint8_t nValue) { char buffer[2]; - buffer[0] = (char)(nRegister); - buffer[1] = (char)(nValue); + buffer[0] = static_cast(nRegister); + buffer[1] = static_cast(nValue); setup(); FUNC_PREFIX(i2c_write(buffer, 2)); @@ -121,13 +120,13 @@ static uint8_t read_byte() { setup(); FUNC_PREFIX(i2c_read(buffer, 1)); - return (uint8_t) (buffer[0]); + return static_cast(buffer[0]); } static uint8_t read_register(uint8_t nRegister) { char buffer[1]; - buffer[0] = (char) (nRegister); + buffer[0] = static_cast(nRegister); setup(); FUNC_PREFIX(i2c_write(buffer, 1)); @@ -135,7 +134,7 @@ static uint8_t read_register(uint8_t nRegister) { return read_byte(); } -inline static bool is_writable() { +static bool is_writable() { return (read_register(SC16IS7X0_TXLVL) != 0); } @@ -157,7 +156,7 @@ static void set_baud(uint32_t nBaud) { write_register(SC16IS7X0_LCR, nRegisterLCR); } -void __attribute__((cold)) console_init(void) { +void __attribute__((cold)) console_init() { FUNC_PREFIX(i2c_begin()); s_isConnected = is_connected(CONSOLE_I2C_ADDRESS, 100000); @@ -198,6 +197,7 @@ void __attribute__((cold)) console_init(void) { write_register(SC16IS7X0_FCR, FCR_ENABLE_FIFO); } +extern "C" { void console_putc(int c) { if (!s_isConnected) { return; @@ -303,14 +303,15 @@ void console_set_bg_color(uint16_t bg) { } } -void console_status(uint32_t color, const char *s) { +void console_status(uint32_t nColour, const char *s) { if (!s_isConnected) { return; } - console_set_fg_color((uint16_t) color); + console_set_fg_color(static_cast(nColour)); console_set_bg_color(CONSOLE_BLACK); console_puts(s); console_putc('\n'); console_set_fg_color(CONSOLE_WHITE); } +} diff --git a/lib-hal/console/null/console.cpp b/lib-hal/console/null/console.cpp new file mode 100755 index 00000000..c0cf5ec3 --- /dev/null +++ b/lib-hal/console/null/console.cpp @@ -0,0 +1,36 @@ +/** + * @file console.cpp + * + */ +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +void console_init() {} + +extern "C" { +void console_puts([[maybe_unused]] const char *p) {} +void console_write([[maybe_unused]] const char *p, [[maybe_unused]] unsigned int i) {} +void console_status([[maybe_unused]] uint32_t i, [[maybe_unused]] const char *p) {} +void console_error([[maybe_unused]] const char *p) {} +void console_putc([[maybe_unused]] int i) {} +} diff --git a/lib-hal/console/uart0/console.c b/lib-hal/console/uart0/console.cpp similarity index 83% rename from lib-hal/console/uart0/console.c rename to lib-hal/console/uart0/console.cpp index 9fca1a3f..cbb2cdf8 100644 --- a/lib-hal/console/uart0/console.c +++ b/lib-hal/console/uart0/console.cpp @@ -1,8 +1,8 @@ /** - * @file console.c + * @file console.cpp * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,20 +23,14 @@ * THE SOFTWARE. */ -#include +#include #include "console.h" -extern void uart0_init(void); -extern void uart0_putc(int); -extern void uart0_puts(const char *); - -void __attribute__((cold)) console_init(void) { - uart0_init(); - - console_set_fg_color(CONSOLE_WHITE); - console_set_bg_color(CONSOLE_BLACK); -} +extern "C" { +void uart0_init(); +void uart0_putc(int); +void uart0_puts(const char *); void console_putc(int c) { uart0_putc(c); @@ -46,6 +40,12 @@ void console_puts(const char *s) { uart0_puts(s); } +void console_error(const char *s) { + uart0_puts("\x1b[31m"); + uart0_puts(s); + uart0_puts("\x1b[37m"); +} + void console_set_fg_color(uint16_t fg) { switch (fg) { case CONSOLE_BLACK: @@ -89,19 +89,13 @@ void console_set_bg_color(uint16_t bg) { void console_write(const char *s, unsigned int n) { char c; - while (((c = *s++) != (char) 0) && (n-- != 0)) { - console_putc((int) c); + while (((c = *s++) != 0) && (n-- != 0)) { + console_putc(static_cast(c)); } } -void console_error(const char *s) { - uart0_puts("\x1b[31m"); - uart0_puts(s); - uart0_puts("\x1b[37m"); -} - -void console_status(uint32_t color, const char *s) { - console_set_fg_color((uint16_t) color); +void console_status(uint32_t nColour, const char *s) { + console_set_fg_color(static_cast(nColour)); console_set_bg_color(CONSOLE_BLACK); uart0_puts(s); @@ -109,3 +103,11 @@ void console_status(uint32_t color, const char *s) { console_set_fg_color(CONSOLE_WHITE); } +} + +void __attribute__((cold)) console_init() { + uart0_init(); + + console_set_fg_color(CONSOLE_WHITE); + console_set_bg_color(CONSOLE_BLACK); +} diff --git a/lib-debug/src/debug_dump.c b/lib-hal/debug/debug_dump.cpp old mode 100644 new mode 100755 similarity index 74% rename from lib-debug/src/debug_dump.c rename to lib-hal/debug/debug_dump.cpp index e2383f82..b69df49f --- a/lib-debug/src/debug_dump.c +++ b/lib-hal/debug/debug_dump.cpp @@ -1,8 +1,8 @@ /** - * @file debug_dump.c + * @file debug_dump.cpp * */ -/* Copyright (C) 2018-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,32 +23,31 @@ * THE SOFTWARE. */ +#include +#include #include -#include -#include #if defined (H3) -extern int uart0_printf(const char* fmt, ...); +extern "C" int uart0_printf(const char* fmt, ...); # define printf uart0_printf #endif -#define CHARS_PER_LINE 16 +static constexpr uint32_t CHARS_PER_LINE = 16; -void debug_dump(const void *packet, uint16_t len) { - uint16_t chars = 0; - uint16_t chars_this_line = 0; - const uint8_t *p = (const uint8_t *) packet; +void debug_dump(const void *pData, uint32_t nSize) { + uint32_t chars = 0; + const auto *p = reinterpret_cast(pData); - printf("%p:%d\n", packet, len); + printf("%p:%d\n", pData, nSize); do { - chars_this_line = 0; + uint32_t chars_this_line = 0; printf("%04x ", chars); - const uint8_t *q = p; + const auto *q = p; - while ((chars_this_line < CHARS_PER_LINE) && (chars < len)) { + while ((chars_this_line < CHARS_PER_LINE) && (chars < nSize)) { if (chars_this_line % 8 == 0) { printf(" "); } @@ -60,7 +59,7 @@ void debug_dump(const void *packet, uint16_t len) { p++; } - uint16_t chars_dot_line = chars_this_line; + auto chars_dot_line = chars_this_line; for (; chars_this_line < CHARS_PER_LINE; chars_this_line++) { if (chars_this_line % 8 == 0) { @@ -88,8 +87,8 @@ void debug_dump(const void *packet, uint16_t len) { q++; } - printf("\n"); + puts(""); - } while (chars < len); + } while (chars < nSize); } diff --git a/lib-debug/src/debug_print_bits.c b/lib-hal/debug/debug_print_bits.cpp old mode 100644 new mode 100755 similarity index 89% rename from lib-debug/src/debug_print_bits.c rename to lib-hal/debug/debug_print_bits.cpp index 48747959..07a758ab --- a/lib-debug/src/debug_print_bits.c +++ b/lib-hal/debug/debug_print_bits.cpp @@ -1,8 +1,8 @@ /** - * @file debug_print_bits.c + * @file debug_print_bits.cpp * */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,7 +27,7 @@ #include #if defined (H3) -extern int uart0_printf(const char* fmt, ...); +extern "C" int uart0_printf(const char* fmt, ...); # define printf uart0_printf #endif @@ -44,5 +44,5 @@ void debug_print_bits(uint32_t u) { b = b >> 1; } - printf("\n"); + puts(""); } diff --git a/lib-hal/debug/emac/gd32/emac_debug.cpp b/lib-hal/debug/emac/gd32/emac_debug.cpp old mode 100644 new mode 100755 index b42aa6c4..ef37b876 --- a/lib-hal/debug/emac/gd32/emac_debug.cpp +++ b/lib-hal/debug/emac/gd32/emac_debug.cpp @@ -2,7 +2,7 @@ * @file emac_debug.cpp * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,7 +32,11 @@ static uint32_t s_nCounter; void emac_debug_run() { uint32_t rxfifo_drop; uint32_t rxdma_drop; +#if defined (GD32H7XX) + enet_missed_frame_counter_get(ENETx, &rxfifo_drop, &rxdma_drop); +#else enet_missed_frame_counter_get(&rxfifo_drop, &rxdma_drop); +#endif if ((rxfifo_drop != 0) || (rxdma_drop != 0)) { printf("%u: RxFIFO: %u RxDMA: %u\n", ++s_nCounter, rxfifo_drop, rxdma_drop); diff --git a/lib-hal/debug/i2c/i2cdetect.cpp b/lib-hal/debug/i2c/i2cdetect.cpp old mode 100644 new mode 100755 index 90c0e243..90c647d7 --- a/lib-hal/debug/i2c/i2cdetect.cpp +++ b/lib-hal/debug/i2c/i2cdetect.cpp @@ -2,7 +2,7 @@ * @file i2cdetect.cpp * */ -/* Copyright (C) 2020-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,12 +23,16 @@ * THE SOFTWARE. */ +#undef NDEBUG + #include #include "i2cdetect.h" #include "hal_i2c.h" +#include "debug.h" + inline static bool i2c_is_connected(uint8_t nAddress) { uint8_t nResult; char buffer; diff --git a/lib-hal/debug/i2c/i2cdetect.h b/lib-hal/debug/i2c/i2cdetect.h old mode 100644 new mode 100755 index 68bf63e7..f7f44491 --- a/lib-hal/debug/i2c/i2cdetect.h +++ b/lib-hal/debug/i2c/i2cdetect.h @@ -2,7 +2,7 @@ * @file i2cdetect.h * */ -/* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-hal/debug/stack/stack_debug.cpp b/lib-hal/debug/stack/stack_debug.cpp old mode 100644 new mode 100755 index 45eac749..b106c334 --- a/lib-hal/debug/stack/stack_debug.cpp +++ b/lib-hal/debug/stack/stack_debug.cpp @@ -2,7 +2,7 @@ * @file stack_debug.cpp * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -66,6 +66,7 @@ void stack_debug_print() { if (s_nUsedBytesPrevious != nUsedBytes) { s_nUsedBytesPrevious = nUsedBytes; + if (nFreePct == 0) { printf("\x1b[31m"); } else if (nFreePct == 1) { diff --git a/lib-hal/device/usb/host/gd32/usb_host.cpp b/lib-hal/device/usb/host/gd32/f/usb_host.cpp similarity index 76% rename from lib-hal/device/usb/host/gd32/usb_host.cpp rename to lib-hal/device/usb/host/gd32/f/usb_host.cpp index c0b2ff50..254e2aac 100644 --- a/lib-hal/device/usb/host/gd32/usb_host.cpp +++ b/lib-hal/device/usb/host/gd32/f/usb_host.cpp @@ -2,7 +2,7 @@ * usb_host.cpp * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,23 +27,28 @@ #include "gd32.h" +/** + * Needed for older GD32F firmware + */ +#if !defined(GPIO_OSPEED_MAX) +# define GPIO_OSPEED_MAX GPIO_OSPEED_200MHZ +#endif + extern "C" { #include "usbh_core.h" #include "usbh_msc_core.h" - #include "drv_usbh_int.h" +void usb_mdelay(uint32_t); } static void usb_gpio_config() { #if !defined (GD32F4XX) #else rcu_periph_clock_enable(RCU_SYSCFG); - rcu_periph_clock_enable(RCU_GPIOA); - /* USBFS_DM(PA11) and USBFS_DP(PA12) GPIO pin configuration */ gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11 | GPIO_PIN_12); - gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_11 | GPIO_PIN_12); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_11 | GPIO_PIN_12); gpio_af_set(GPIOA, GPIO_AF_10, GPIO_PIN_11 | GPIO_PIN_12); #endif @@ -94,23 +99,41 @@ static void usb_intr_config() { #endif } -usbh_host usb_host_msc; +void usb_vbus_config () { +#if defined (USB_HOST_VBUS_GPIOx) + rcu_periph_clock_enable(USB_HOST_VBUS_RCU_GPIOx); + +# if defined (GPIO_INIT) + gpio_init(USB_HOST_VBUS_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, USB_HOST_VBUS_GPIO_PINx); +# else + gpio_mode_set(USB_HOST_VBUS_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, USB_HOST_VBUS_GPIO_PINx); + gpio_output_options_set(USB_HOST_VBUS_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, USB_HOST_VBUS_GPIO_PINx); +# endif + + gpio_bit_set(USB_HOST_VBUS_GPIOx, USB_HOST_VBUS_GPIO_PINx); + + usb_mdelay (200); +#endif +} + #if !defined (GD32F4XX) extern usb_core_driver usbh_core; +usbh_host usb_host; #else usb_core_driver usbh_core; +usbh_host usb_host_msc; #endif extern usbh_user_cb usr_cb; void usb_init() { usb_gpio_config(); usb_rcu_config(); - - usbh_class_register(&usb_host_msc, &usbh_msc); - + usb_vbus_config(); #if !defined (GD32F4XX) - usbh_init (&usb_host_msc, &usr_cb); + usbh_class_register(&usb_host, &usbh_msc); + usbh_init (&usb_host, &usr_cb); #else + usbh_class_register(&usb_host_msc, &usbh_msc); usbh_init(&usb_host_msc, &usbh_core, USB_CORE_ENUM_FS, diff --git a/lib-hal/device/usb/host/gd32/usb_host_msc.cpp b/lib-hal/device/usb/host/gd32/usb_host_msc.cpp index 227d0b10..585a9e81 100644 --- a/lib-hal/device/usb/host/gd32/usb_host_msc.cpp +++ b/lib-hal/device/usb/host/gd32/usb_host_msc.cpp @@ -2,7 +2,7 @@ * usb_host_msc.cpp * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#ifndef NDEBUG +# undef NDEBUG +#endif + #include #include @@ -31,8 +35,20 @@ extern "C" { #include "usb_host_msc.h" #include "usbh_core.h" +void console_error(const char *); } +#include "../lib-hal/ff14b/source/ff.h" +#include "device/usb/host.h" + +#if (FF_DEFINED == 86631) // R0.14b + static FATFS fat_fs; +#else +# error Not a recognized/tested FatFs version +#endif + +#include "device/usb/host.h" + usbh_user_cb usr_cb = { usbh_user_init, usbh_user_deinit, @@ -54,51 +70,90 @@ usbh_user_cb usr_cb = { usbh_user_unrecovered_error }; -#define USBH_USR_FS_INIT 0 -#define USBH_USR_FS_READLIST 1 -#define USBH_USR_FS_WRITEFILE 2 -#define USBH_USR_FS_DRAW 3 -#define USBH_USR_FS_DEMOEND 4 +#if defined NODE_SHOWFILE +namespace showfile { + void usb_ready(); + void usb_disconnected(); +} // namespace showfile +#endif -static uint32_t usbh_usr_application_state = USBH_USR_FS_INIT; +/* state machine for the USBH_USR_ApplicationState */ +#define USBH_USR_FS_MOUNT 0 +#define USBH_USR_FS_READY 1 -void usbh_user_init() { - static uint32_t startup = 0U; +static uint8_t usbh_usr_application_state = USBH_USR_FS_MOUNT; + +static usb::host::Status s_status; +static usb::host::Speed s_speed; +static usb::host::Class s_class; + +namespace usb { +namespace host { +Status get_status() { + return s_status; +} +Speed get_speed() { + return s_speed; +} +Class get_class() { + return s_class; +} +} // namespace host +} // namespace usb - if (0U == startup) { - startup = 1U; +void usbh_user_init() { + if (s_status == usb::host::Status::NOT_AVAILABLE) { + s_status = usb::host::Status::DISCONNECTED; +#ifndef NDEBUG puts("USB host library started."); +#endif } } void usbh_user_deinit() { - usbh_usr_application_state = USBH_USR_FS_INIT; + s_status = usb::host::Status::NOT_AVAILABLE; } void usbh_user_device_connected() { + s_status = usb::host::Status::ATTACHED; puts("> Device Attached."); } void usbh_user_unrecovered_error() { + s_status = usb::host::Status::UNRECOVERABLE_ERROR; puts("> Unrecovered error state."); } void usbh_user_device_disconnected() { + s_status = usb::host::Status::DISCONNECTED; puts("> Device Disconnected."); + usbh_usr_application_state = USBH_USR_FS_MOUNT; +#if defined NODE_SHOWFILE + showfile::usb_disconnected(); +#endif } void usbh_user_device_reset() { + s_status = usb::host::Status::RESET; puts("> Reset the USB device."); } void usbh_user_device_speed_detected(uint32_t device_speed) { if (PORT_SPEED_HIGH == device_speed) { + s_speed = usb::host::Speed::HIGH; puts("> High speed device detected."); } else if (PORT_SPEED_FULL == device_speed) { + s_speed = usb::host::Speed::FULL; +#ifndef NDEBUG puts("> Full speed device detected."); +#endif } else if (PORT_SPEED_LOW == device_speed) { + s_speed = usb::host::Speed::LOW; +#ifndef NDEBUG puts("> Low speed device detected."); +#endif } else { + s_speed = usb::host::Speed::FAULT; puts("> Device Fault."); } } @@ -137,16 +192,17 @@ void usbh_user_serialnum_string(void *serial_num_string) { } void usbh_user_enumeration_finish() { + s_status = usb::host::Status::ENUMERATION_COMPLETED; puts("> Enumeration completed."); } void usbh_user_device_not_supported() { + s_status = usb::host::Status::DEVICE_NOT_SUPPORTED; puts("> Device not supported."); } usbh_user_status usbh_user_userinput() { puts("usbh_user_userinput"); - return static_cast(1); } @@ -155,5 +211,22 @@ void usbh_user_over_current_detected() { } int usbh_usr_msc_application() { + if (usbh_usr_application_state == USBH_USR_FS_MOUNT) { + const auto result = f_mount(&fat_fs, (const TCHAR *) "0:/", (BYTE) 0); + + if (result == FR_OK) { + s_status = usb::host::Status::READY; + usbh_usr_application_state = USBH_USR_FS_READY; +#if defined NODE_SHOWFILE + showfile::usb_ready(); +#endif + } else { + char buffer[32]; + snprintf(buffer, sizeof(buffer) - 1, "f_mount failed! %d\n", (int) result); + console_error(buffer); + return -1; + } + } + return 0; } diff --git a/lib-hal/ff14b/LICENSE.txt b/lib-hal/ff14b/LICENSE.txt new file mode 100755 index 00000000..25379e46 --- /dev/null +++ b/lib-hal/ff14b/LICENSE.txt @@ -0,0 +1,24 @@ +FatFs License + +FatFs has being developped as a personal project of the author, ChaN. It is free from the code anyone else wrote at current release. Following code block shows a copy of the FatFs license document that heading the source files. + +/*----------------------------------------------------------------------------/ +/ FatFs - Generic FAT Filesystem Module Rx.xx / +/-----------------------------------------------------------------------------/ +/ +/ Copyright (C) 20xx, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: +/ +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +/----------------------------------------------------------------------------*/ + +Therefore FatFs license is one of the BSD-style licenses, but there is a significant feature. FatFs is mainly intended for embedded systems. In order to extend the usability for commercial products, the redistributions of FatFs in binary form, such as embedded code, binary library and any forms without source code, do not need to include about FatFs in the documentations. This is equivalent to the 1-clause BSD license. Of course FatFs is compatible with the most of open source software licenses include GNU GPL. When you redistribute the FatFs source code with changes or create a fork, the license can also be changed to GNU GPL, BSD-style license or any open source software license that not conflict with FatFs license. diff --git a/lib-hal/ff14b/source/00history.txt b/lib-hal/ff14b/source/00history.txt new file mode 100755 index 00000000..d3c910c1 --- /dev/null +++ b/lib-hal/ff14b/source/00history.txt @@ -0,0 +1,359 @@ +---------------------------------------------------------------------------- + Revision history of FatFs module +---------------------------------------------------------------------------- + +R0.00 (February 26, 2006) + + Prototype. + + + +R0.01 (April 29, 2006) + + The first release. + + + +R0.02 (June 01, 2006) + + Added FAT12 support. + Removed unbuffered mode. + Fixed a problem on small (<32M) partition. + + + +R0.02a (June 10, 2006) + + Added a configuration option (_FS_MINIMUM). + + + +R0.03 (September 22, 2006) + + Added f_rename(). + Changed option _FS_MINIMUM to _FS_MINIMIZE. + + + +R0.03a (December 11, 2006) + + Improved cluster scan algorithm to write files fast. + Fixed f_mkdir() creates incorrect directory on FAT32. + + + +R0.04 (February 04, 2007) + + Added f_mkfs(). + Supported multiple drive system. + Changed some interfaces for multiple drive system. + Changed f_mountdrv() to f_mount(). + + + +R0.04a (April 01, 2007) + + Supported multiple partitions on a physical drive. + Added a capability of extending file size to f_lseek(). + Added minimization level 3. + Fixed an endian sensitive code in f_mkfs(). + + + +R0.04b (May 05, 2007) + + Added a configuration option _USE_NTFLAG. + Added FSINFO support. + Fixed DBCS name can result FR_INVALID_NAME. + Fixed short seek (<= csize) collapses the file object. + + + +R0.05 (August 25, 2007) + + Changed arguments of f_read(), f_write() and f_mkfs(). + Fixed f_mkfs() on FAT32 creates incorrect FSINFO. + Fixed f_mkdir() on FAT32 creates incorrect directory. + + + +R0.05a (February 03, 2008) + + Added f_truncate() and f_utime(). + Fixed off by one error at FAT sub-type determination. + Fixed btr in f_read() can be mistruncated. + Fixed cached sector is not flushed when create and close without write. + + + +R0.06 (April 01, 2008) + + Added fputc(), fputs(), fprintf() and fgets(). + Improved performance of f_lseek() on moving to the same or following cluster. + + + +R0.07 (April 01, 2009) + + Merged Tiny-FatFs as a configuration option. (_FS_TINY) + Added long file name feature. (_USE_LFN) + Added multiple code page feature. (_CODE_PAGE) + Added re-entrancy for multitask operation. (_FS_REENTRANT) + Added auto cluster size selection to f_mkfs(). + Added rewind option to f_readdir(). + Changed result code of critical errors. + Renamed string functions to avoid name collision. + + + +R0.07a (April 14, 2009) + + Septemberarated out OS dependent code on reentrant cfg. + Added multiple sector size feature. + + + +R0.07c (June 21, 2009) + + Fixed f_unlink() can return FR_OK on error. + Fixed wrong cache control in f_lseek(). + Added relative path feature. + Added f_chdir() and f_chdrive(). + Added proper case conversion to extended character. + + + +R0.07e (November 03, 2009) + + Septemberarated out configuration options from ff.h to ffconf.h. + Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH. + Fixed name matching error on the 13 character boundary. + Added a configuration option, _LFN_UNICODE. + Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. + + + +R0.08 (May 15, 2010) + + Added a memory configuration option. (_USE_LFN = 3) + Added file lock feature. (_FS_SHARE) + Added fast seek feature. (_USE_FASTSEEK) + Changed some types on the API, XCHAR->TCHAR. + Changed .fname in the FILINFO structure on Unicode cfg. + String functions support UTF-8 encoding files on Unicode cfg. + + + +R0.08a (August 16, 2010) + + Added f_getcwd(). (_FS_RPATH = 2) + Added sector erase feature. (_USE_ERASE) + Moved file lock semaphore table from fs object to the bss. + Fixed f_mkfs() creates wrong FAT32 volume. + + + +R0.08b (January 15, 2011) + + Fast seek feature is also applied to f_read() and f_write(). + f_lseek() reports required table size on creating CLMP. + Extended format syntax of f_printf(). + Ignores duplicated directory separators in given path name. + + + +R0.09 (September 06, 2011) + + f_mkfs() supports multiple partition to complete the multiple partition feature. + Added f_fdisk(). + + + +R0.09a (August 27, 2012) + + Changed f_open() and f_opendir() reject null object pointer to avoid crash. + Changed option name _FS_SHARE to _FS_LOCK. + Fixed assertion failure due to OS/2 EA on FAT12/16 volume. + + + +R0.09b (January 24, 2013) + + Added f_setlabel() and f_getlabel(). + + + +R0.10 (October 02, 2013) + + Added selection of character encoding on the file. (_STRF_ENCODE) + Added f_closedir(). + Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO) + Added forced mount feature with changes of f_mount(). + Improved behavior of volume auto detection. + Improved write throughput of f_puts() and f_printf(). + Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write(). + Fixed f_write() can be truncated when the file size is close to 4GB. + Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect value on error. + + + +R0.10a (January 15, 2014) + + Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID) + Added a configuration option of minimum sector size. (_MIN_SS) + 2nd argument of f_rename() can have a drive number and it will be ignored. + Fixed f_mount() with forced mount fails when drive number is >= 1. (appeared at R0.10) + Fixed f_close() invalidates the file object without volume lock. + Fixed f_closedir() returns but the volume lock is left acquired. (appeared at R0.10) + Fixed creation of an entry with LFN fails on too many SFN collisions. (appeared at R0.07) + + + +R0.10b (May 19, 2014) + + Fixed a hard error in the disk I/O layer can collapse the directory entry. + Fixed LFN entry is not deleted when delete/rename an object with lossy converted SFN. (appeared at R0.07) + + + +R0.10c (November 09, 2014) + + Added a configuration option for the platforms without RTC. (_FS_NORTC) + Changed option name _USE_ERASE to _USE_TRIM. + Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b) + Fixed a potential problem of FAT access that can appear on disk error. + Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08) + + + +R0.11 (February 09, 2015) + + Added f_findfirst(), f_findnext() and f_findclose(). (_USE_FIND) + Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c) + Fixed _FS_NORTC option does not work properly. (appeared at R0.10c) + + + +R0.11a (September 05, 2015) + + Fixed wrong media change can lead a deadlock at thread-safe configuration. + Added code page 771, 860, 861, 863, 864, 865 and 869. (_CODE_PAGE) + Removed some code pages actually not exist on the standard systems. (_CODE_PAGE) + Fixed errors in the case conversion teble of code page 437 and 850 (ff.c). + Fixed errors in the case conversion teble of Unicode (cc*.c). + + + +R0.12 (April 12, 2016) + + Added support for exFAT file system. (_FS_EXFAT) + Added f_expand(). (_USE_EXPAND) + Changed some members in FINFO structure and behavior of f_readdir(). + Added an option _USE_CHMOD. + Removed an option _WORD_ACCESS. + Fixed errors in the case conversion table of Unicode (cc*.c). + + + +R0.12a (July 10, 2016) + + Added support for creating exFAT volume with some changes of f_mkfs(). + Added a file open method FA_OPEN_APPEND. An f_lseek() following f_open() is no longer needed. + f_forward() is available regardless of _FS_TINY. + Fixed f_mkfs() creates wrong volume. (appeared at R0.12) + Fixed wrong memory read in create_name(). (appeared at R0.12) + Fixed compilation fails at some configurations, _USE_FASTSEEK and _USE_FORWARD. + + + +R0.12b (September 04, 2016) + + Made f_rename() be able to rename objects with the same name but case. + Fixed an error in the case conversion teble of code page 866. (ff.c) + Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12) + Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12) + Fixed f_mkfs() creating exFAT volume with too small cluster size can collapse unallocated memory. (appeared at R0.12) + Fixed wrong object name can be returned when read directory at Unicode cfg. (appeared at R0.12) + Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12) + Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12) + + + +R0.12c (March 04, 2017) + + Improved write throughput at the fragmented file on the exFAT volume. + Made memory usage for exFAT be able to be reduced as decreasing _MAX_LFN. + Fixed successive f_getfree() can return wrong count on the FAT12/16 volume. (appeared at R0.12) + Fixed configuration option _VOLUMES cannot be set 10. (appeared at R0.10c) + + + +R0.13 (May 21, 2017) + + Changed heading character of configuration keywords "_" to "FF_". + Removed ASCII-only configuration, FF_CODE_PAGE = 1. Use FF_CODE_PAGE = 437 instead. + Added f_setcp(), run-time code page configuration. (FF_CODE_PAGE = 0) + Improved cluster allocation time on stretch a deep buried cluster chain. + Improved processing time of f_mkdir() with large cluster size by using FF_USE_LFN = 3. + Improved NoFatChain flag of the fragmented file to be set after it is truncated and got contiguous. + Fixed archive attribute is left not set when a file on the exFAT volume is renamed. (appeared at R0.12) + Fixed exFAT FAT entry can be collapsed when write or lseek operation to the existing file is done. (appeared at R0.12c) + Fixed creating a file can fail when a new cluster allocation to the exFAT directory occures. (appeared at R0.12c) + + + +R0.13a (October 14, 2017) + + Added support for UTF-8 encoding on the API. (FF_LFN_UNICODE = 2) + Added options for file name output buffer. (FF_LFN_BUF, FF_SFN_BUF). + Added dynamic memory allocation option for working buffer of f_mkfs() and f_fdisk(). + Fixed f_fdisk() and f_mkfs() create the partition table with wrong CHS parameters. (appeared at R0.09) + Fixed f_unlink() can cause lost clusters at fragmented file on the exFAT volume. (appeared at R0.12c) + Fixed f_setlabel() rejects some valid characters for exFAT volume. (appeared at R0.12) + + + +R0.13b (April 07, 2018) + + Added support for UTF-32 encoding on the API. (FF_LFN_UNICODE = 3) + Added support for Unix style volume ID. (FF_STR_VOLUME_ID = 2) + Fixed accesing any object on the exFAT root directory beyond the cluster boundary can fail. (appeared at R0.12c) + Fixed f_setlabel() does not reject some invalid characters. (appeared at R0.09b) + + + +R0.13c (October 14, 2018) + Supported stdint.h for C99 and later. (integer.h was included in ff.h) + Fixed reading a directory gets infinite loop when the last directory entry is not empty. (appeared at R0.12) + Fixed creating a sub-directory in the fragmented sub-directory on the exFAT volume collapses FAT chain of the parent directory. (appeared at R0.12) + Fixed f_getcwd() cause output buffer overrun when the buffer has a valid drive number. (appeared at R0.13b) + + + +R0.14 (October 14, 2019) + Added support for 64-bit LBA and GUID partition table (FF_LBA64 = 1) + Changed some API functions, f_mkfs() and f_fdisk(). + Fixed f_open() function cannot find the file with file name in length of FF_MAX_LFN characters. + Fixed f_readdir() function cannot retrieve long file names in length of FF_MAX_LFN - 1 characters. + Fixed f_readdir() function returns file names with wrong case conversion. (appeared at R0.12) + Fixed f_mkfs() function can fail to create exFAT volume in the second partition. (appeared at R0.12) + + +R0.14a (December 5, 2020) + Limited number of recursive calls in f_findnext(). + Fixed old floppy disks formatted with MS-DOS 2.x and 3.x cannot be mounted. + Fixed some compiler warnings. + + + +R0.14b (April 17, 2021) + Made FatFs uses standard library for copy, compare and search instead of built-in string functions. + Added support for long long integer and floating point to f_printf(). (FF_STRF_LLI and FF_STRF_FP) + Made path name parser ignore the terminating separator to allow "dir/". + Improved the compatibility in Unix style path name feature. + Fixed the file gets dead-locked when f_open() failed with some conditions. (appeared at R0.12a) + Fixed f_mkfs() can create wrong exFAT volume due to a timing dependent error. (appeared at R0.12) + Fixed code page 855 cannot be set by f_setcp(). + Fixed some compiler warnings. + + diff --git a/lib-hal/ff14b/source/00readme.txt b/lib-hal/ff14b/source/00readme.txt new file mode 100755 index 00000000..53e035f6 --- /dev/null +++ b/lib-hal/ff14b/source/00readme.txt @@ -0,0 +1,21 @@ +FatFs Module Source Files R0.14b + + +FILES + + 00readme.txt This file. + 00history.txt Revision history. + ff.c FatFs module. + ffconf.h Configuration file of FatFs module. + ff.h Common include file for FatFs and application module. + diskio.h Common include file for FatFs and disk I/O module. + diskio.c An example of glue function to attach existing disk I/O module to FatFs. + ffunicode.c Optional Unicode utility functions. + ffsystem.c An example of optional O/S related functions. + + + Low level disk I/O module is not included in this archive because the FatFs + module is only a generic file system layer and it does not depend on any specific + storage device. You need to provide a low level disk I/O module written to + control the storage device that attached to the target system. + diff --git a/lib-hal/ff14b/source/diskio.h b/lib-hal/ff14b/source/diskio.h new file mode 100755 index 00000000..554398e4 --- /dev/null +++ b/lib-hal/ff14b/source/diskio.h @@ -0,0 +1,79 @@ +/*-----------------------------------------------------------------------/ +/ Low level disk interface modlue include file (C)ChaN, 2019 / +/-----------------------------------------------------------------------*/ + +#ifndef _DISKIO_DEFINED +#define _DISKIO_DEFINED + +#include "ff.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Status of Disk Functions */ +typedef BYTE DSTATUS; + +/* Results of Disk Functions */ +typedef enum { + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ +} DRESULT; + + +/*---------------------------------------*/ +/* Prototypes for disk control functions */ + + +DSTATUS disk_initialize (BYTE pdrv); +DSTATUS disk_status (BYTE pdrv); +DRESULT disk_read (BYTE pdrv, BYTE* buff, LBA_t sector, UINT count); +DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count); +DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); + + +/* Disk Status Bits (DSTATUS) */ + +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ + + +/* Command code for disk_ioctrl fucntion */ + +/* Generic command (Used by FatFs) */ +#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */ +#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */ +#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ +#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */ +#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ + +/* Generic command (Not used by FatFs) */ +#define CTRL_POWER 5 /* Get/Set power status */ +#define CTRL_LOCK 6 /* Lock/Unlock media removal */ +#define CTRL_EJECT 7 /* Eject media */ +#define CTRL_FORMAT 8 /* Create physical format on the media */ + +/* MMC/SDC specific ioctl command */ +#define MMC_GET_TYPE 10 /* Get card type */ +#define MMC_GET_CSD 11 /* Get CSD */ +#define MMC_GET_CID 12 /* Get CID */ +#define MMC_GET_OCR 13 /* Get OCR */ +#define MMC_GET_SDSTAT 14 /* Get SD status */ +#define ISDIO_READ 55 /* Read data form SD iSDIO register */ +#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ +#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ + +/* ATA/CF specific ioctl command */ +#define ATA_GET_REV 20 /* Get F/W revision */ +#define ATA_GET_MODEL 21 /* Get model name */ +#define ATA_GET_SN 22 /* Get serial number */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib-hal/ff14b/source/ff.c b/lib-hal/ff14b/source/ff.c new file mode 100755 index 00000000..da05196d --- /dev/null +++ b/lib-hal/ff14b/source/ff.c @@ -0,0 +1,6987 @@ +#pragma GCC push_options +#pragma GCC optimize ("Os") +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wsign-conversion" +/*----------------------------------------------------------------------------/ +/ FatFs - Generic FAT Filesystem Module R0.14b / +/-----------------------------------------------------------------------------/ +/ +/ Copyright (C) 2021, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: +/ +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +/ +/----------------------------------------------------------------------------*/ + + +#include +#include "ff.h" /* Declarations of FatFs API */ +#include "diskio.h" /* Declarations of device I/O functions */ + + +/*-------------------------------------------------------------------------- + + Module Private Definitions + +---------------------------------------------------------------------------*/ + +#if FF_DEFINED != 86631 /* Revision ID */ +#error Wrong include file (ff.h). +#endif + + +/* Limits and boundaries */ +#define MAX_DIR 0x200000 /* Max size of FAT directory */ +#define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */ +#define MAX_FAT12 0xFF5 /* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */ +#define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */ +#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */ +#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */ + + +/* Character code support macros */ +#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z') +#define IsLower(c) ((c) >= 'a' && (c) <= 'z') +#define IsDigit(c) ((c) >= '0' && (c) <= '9') +#define IsSeparator(c) ((c) == '/' || (c) == '\\') +#define IsTerminator(c) ((UINT)(c) < (FF_USE_LFN ? ' ' : '!')) +#define IsSurrogate(c) ((c) >= 0xD800 && (c) <= 0xDFFF) +#define IsSurrogateH(c) ((c) >= 0xD800 && (c) <= 0xDBFF) +#define IsSurrogateL(c) ((c) >= 0xDC00 && (c) <= 0xDFFF) + + +/* Additional file access control and file status flags for internal use */ +#define FA_SEEKEND 0x20 /* Seek to end of the file on file open */ +#define FA_MODIFIED 0x40 /* File has been modified */ +#define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */ + + +/* Additional file attribute bits for internal use */ +#define AM_VOL 0x08 /* Volume label */ +#define AM_LFN 0x0F /* LFN entry */ +#define AM_MASK 0x3F /* Mask of defined bits in FAT */ +#define AM_MASKX 0x37 /* Mask of defined bits in exFAT */ + + +/* Name status flags in fn[11] */ +#define NSFLAG 11 /* Index of the name status byte */ +#define NS_LOSS 0x01 /* Out of 8.3 format */ +#define NS_LFN 0x02 /* Force to create LFN entry */ +#define NS_LAST 0x04 /* Last segment */ +#define NS_BODY 0x08 /* Lower case flag (body) */ +#define NS_EXT 0x10 /* Lower case flag (ext) */ +#define NS_DOT 0x20 /* Dot entry */ +#define NS_NOLFN 0x40 /* Do not find LFN */ +#define NS_NONAME 0x80 /* Not followed */ + + +/* exFAT directory entry types */ +#define ET_BITMAP 0x81 /* Allocation bitmap */ +#define ET_UPCASE 0x82 /* Up-case table */ +#define ET_VLABEL 0x83 /* Volume label */ +#define ET_FILEDIR 0x85 /* File and directory */ +#define ET_STREAM 0xC0 /* Stream extension */ +#define ET_FILENAME 0xC1 /* Name extension */ + + +/* FatFs refers the FAT structure as simple byte array instead of structure member +/ because the C structure is not binary compatible between different platforms */ + +#define BS_JmpBoot 0 /* x86 jump instruction (3-byte) */ +#define BS_OEMName 3 /* OEM name (8-byte) */ +#define BPB_BytsPerSec 11 /* Sector size [byte] (WORD) */ +#define BPB_SecPerClus 13 /* Cluster size [sector] (BYTE) */ +#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (WORD) */ +#define BPB_NumFATs 16 /* Number of FATs (BYTE) */ +#define BPB_RootEntCnt 17 /* Size of root directory area for FAT [entry] (WORD) */ +#define BPB_TotSec16 19 /* Volume size (16-bit) [sector] (WORD) */ +#define BPB_Media 21 /* Media descriptor byte (BYTE) */ +#define BPB_FATSz16 22 /* FAT size (16-bit) [sector] (WORD) */ +#define BPB_SecPerTrk 24 /* Number of sectors per track for int13h [sector] (WORD) */ +#define BPB_NumHeads 26 /* Number of heads for int13h (WORD) */ +#define BPB_HiddSec 28 /* Volume offset from top of the drive (DWORD) */ +#define BPB_TotSec32 32 /* Volume size (32-bit) [sector] (DWORD) */ +#define BS_DrvNum 36 /* Physical drive number for int13h (BYTE) */ +#define BS_NTres 37 /* WindowsNT error flag (BYTE) */ +#define BS_BootSig 38 /* Extended boot signature (BYTE) */ +#define BS_VolID 39 /* Volume serial number (DWORD) */ +#define BS_VolLab 43 /* Volume label string (8-byte) */ +#define BS_FilSysType 54 /* Filesystem type string (8-byte) */ +#define BS_BootCode 62 /* Boot code (448-byte) */ +#define BS_55AA 510 /* Signature word (WORD) */ + +#define BPB_FATSz32 36 /* FAT32: FAT size [sector] (DWORD) */ +#define BPB_ExtFlags32 40 /* FAT32: Extended flags (WORD) */ +#define BPB_FSVer32 42 /* FAT32: Filesystem version (WORD) */ +#define BPB_RootClus32 44 /* FAT32: Root directory cluster (DWORD) */ +#define BPB_FSInfo32 48 /* FAT32: Offset of FSINFO sector (WORD) */ +#define BPB_BkBootSec32 50 /* FAT32: Offset of backup boot sector (WORD) */ +#define BS_DrvNum32 64 /* FAT32: Physical drive number for int13h (BYTE) */ +#define BS_NTres32 65 /* FAT32: Error flag (BYTE) */ +#define BS_BootSig32 66 /* FAT32: Extended boot signature (BYTE) */ +#define BS_VolID32 67 /* FAT32: Volume serial number (DWORD) */ +#define BS_VolLab32 71 /* FAT32: Volume label string (8-byte) */ +#define BS_FilSysType32 82 /* FAT32: Filesystem type string (8-byte) */ +#define BS_BootCode32 90 /* FAT32: Boot code (420-byte) */ + +#define BPB_ZeroedEx 11 /* exFAT: MBZ field (53-byte) */ +#define BPB_VolOfsEx 64 /* exFAT: Volume offset from top of the drive [sector] (QWORD) */ +#define BPB_TotSecEx 72 /* exFAT: Volume size [sector] (QWORD) */ +#define BPB_FatOfsEx 80 /* exFAT: FAT offset from top of the volume [sector] (DWORD) */ +#define BPB_FatSzEx 84 /* exFAT: FAT size [sector] (DWORD) */ +#define BPB_DataOfsEx 88 /* exFAT: Data offset from top of the volume [sector] (DWORD) */ +#define BPB_NumClusEx 92 /* exFAT: Number of clusters (DWORD) */ +#define BPB_RootClusEx 96 /* exFAT: Root directory start cluster (DWORD) */ +#define BPB_VolIDEx 100 /* exFAT: Volume serial number (DWORD) */ +#define BPB_FSVerEx 104 /* exFAT: Filesystem version (WORD) */ +#define BPB_VolFlagEx 106 /* exFAT: Volume flags (WORD) */ +#define BPB_BytsPerSecEx 108 /* exFAT: Log2 of sector size in unit of byte (BYTE) */ +#define BPB_SecPerClusEx 109 /* exFAT: Log2 of cluster size in unit of sector (BYTE) */ +#define BPB_NumFATsEx 110 /* exFAT: Number of FATs (BYTE) */ +#define BPB_DrvNumEx 111 /* exFAT: Physical drive number for int13h (BYTE) */ +#define BPB_PercInUseEx 112 /* exFAT: Percent in use (BYTE) */ +#define BPB_RsvdEx 113 /* exFAT: Reserved (7-byte) */ +#define BS_BootCodeEx 120 /* exFAT: Boot code (390-byte) */ + +#define DIR_Name 0 /* Short file name (11-byte) */ +#define DIR_Attr 11 /* Attribute (BYTE) */ +#define DIR_NTres 12 /* Lower case flag (BYTE) */ +#define DIR_CrtTime10 13 /* Created time sub-second (BYTE) */ +#define DIR_CrtTime 14 /* Created time (DWORD) */ +#define DIR_LstAccDate 18 /* Last accessed date (WORD) */ +#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (WORD) */ +#define DIR_ModTime 22 /* Modified time (DWORD) */ +#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (WORD) */ +#define DIR_FileSize 28 /* File size (DWORD) */ +#define LDIR_Ord 0 /* LFN: LFN order and LLE flag (BYTE) */ +#define LDIR_Attr 11 /* LFN: LFN attribute (BYTE) */ +#define LDIR_Type 12 /* LFN: Entry type (BYTE) */ +#define LDIR_Chksum 13 /* LFN: Checksum of the SFN (BYTE) */ +#define LDIR_FstClusLO 26 /* LFN: MBZ field (WORD) */ +#define XDIR_Type 0 /* exFAT: Type of exFAT directory entry (BYTE) */ +#define XDIR_NumLabel 1 /* exFAT: Number of volume label characters (BYTE) */ +#define XDIR_Label 2 /* exFAT: Volume label (11-WORD) */ +#define XDIR_CaseSum 4 /* exFAT: Sum of case conversion table (DWORD) */ +#define XDIR_NumSec 1 /* exFAT: Number of secondary entries (BYTE) */ +#define XDIR_SetSum 2 /* exFAT: Sum of the set of directory entries (WORD) */ +#define XDIR_Attr 4 /* exFAT: File attribute (WORD) */ +#define XDIR_CrtTime 8 /* exFAT: Created time (DWORD) */ +#define XDIR_ModTime 12 /* exFAT: Modified time (DWORD) */ +#define XDIR_AccTime 16 /* exFAT: Last accessed time (DWORD) */ +#define XDIR_CrtTime10 20 /* exFAT: Created time subsecond (BYTE) */ +#define XDIR_ModTime10 21 /* exFAT: Modified time subsecond (BYTE) */ +#define XDIR_CrtTZ 22 /* exFAT: Created timezone (BYTE) */ +#define XDIR_ModTZ 23 /* exFAT: Modified timezone (BYTE) */ +#define XDIR_AccTZ 24 /* exFAT: Last accessed timezone (BYTE) */ +#define XDIR_GenFlags 33 /* exFAT: General secondary flags (BYTE) */ +#define XDIR_NumName 35 /* exFAT: Number of file name characters (BYTE) */ +#define XDIR_NameHash 36 /* exFAT: Hash of file name (WORD) */ +#define XDIR_ValidFileSize 40 /* exFAT: Valid file size (QWORD) */ +#define XDIR_FstClus 52 /* exFAT: First cluster of the file data (DWORD) */ +#define XDIR_FileSize 56 /* exFAT: File/Directory size (QWORD) */ + +#define SZDIRE 32 /* Size of a directory entry */ +#define DDEM 0xE5 /* Deleted directory entry mark set to DIR_Name[0] */ +#define RDDEM 0x05 /* Replacement of the character collides with DDEM */ +#define LLEF 0x40 /* Last long entry flag in LDIR_Ord */ + +#define FSI_LeadSig 0 /* FAT32 FSI: Leading signature (DWORD) */ +#define FSI_StrucSig 484 /* FAT32 FSI: Structure signature (DWORD) */ +#define FSI_Free_Count 488 /* FAT32 FSI: Number of free clusters (DWORD) */ +#define FSI_Nxt_Free 492 /* FAT32 FSI: Last allocated cluster (DWORD) */ + +#define MBR_Table 446 /* MBR: Offset of partition table in the MBR */ +#define SZ_PTE 16 /* MBR: Size of a partition table entry */ +#define PTE_Boot 0 /* MBR PTE: Boot indicator */ +#define PTE_StHead 1 /* MBR PTE: Start head */ +#define PTE_StSec 2 /* MBR PTE: Start sector */ +#define PTE_StCyl 3 /* MBR PTE: Start cylinder */ +#define PTE_System 4 /* MBR PTE: System ID */ +#define PTE_EdHead 5 /* MBR PTE: End head */ +#define PTE_EdSec 6 /* MBR PTE: End sector */ +#define PTE_EdCyl 7 /* MBR PTE: End cylinder */ +#define PTE_StLba 8 /* MBR PTE: Start in LBA */ +#define PTE_SizLba 12 /* MBR PTE: Size in LBA */ + +#define GPTH_Sign 0 /* GPT: Header signature (8-byte) */ +#define GPTH_Rev 8 /* GPT: Revision (DWORD) */ +#define GPTH_Size 12 /* GPT: Header size (DWORD) */ +#define GPTH_Bcc 16 /* GPT: Header BCC (DWORD) */ +#define GPTH_CurLba 24 /* GPT: Main header LBA (QWORD) */ +#define GPTH_BakLba 32 /* GPT: Backup header LBA (QWORD) */ +#define GPTH_FstLba 40 /* GPT: First LBA for partitions (QWORD) */ +#define GPTH_LstLba 48 /* GPT: Last LBA for partitions (QWORD) */ +#define GPTH_DskGuid 56 /* GPT: Disk GUID (16-byte) */ +#define GPTH_PtOfs 72 /* GPT: Partation table LBA (QWORD) */ +#define GPTH_PtNum 80 /* GPT: Number of table entries (DWORD) */ +#define GPTH_PteSize 84 /* GPT: Size of table entry (DWORD) */ +#define GPTH_PtBcc 88 /* GPT: Partation table BCC (DWORD) */ +#define SZ_GPTE 128 /* GPT: Size of partition table entry */ +#define GPTE_PtGuid 0 /* GPT PTE: Partition type GUID (16-byte) */ +#define GPTE_UpGuid 16 /* GPT PTE: Partition unique GUID (16-byte) */ +#define GPTE_FstLba 32 /* GPT PTE: First LBA (QWORD) */ +#define GPTE_LstLba 40 /* GPT PTE: Last LBA inclusive (QWORD) */ +#define GPTE_Flags 48 /* GPT PTE: Flags (QWORD) */ +#define GPTE_Name 56 /* GPT PTE: Name */ + + +/* Post process on fatal error in the file operations */ +#define ABORT(fs, res) { fp->err = (BYTE)(res); LEAVE_FF(fs, res); } + + +/* Re-entrancy related */ +#if FF_FS_REENTRANT +#if FF_USE_LFN == 1 +#error Static LFN work area cannot be used in thread-safe configuration +#endif +#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } +#else +#define LEAVE_FF(fs, res) return res +#endif + + +/* Definitions of logical drive - physical location conversion */ +#if FF_MULTI_PARTITION +#define LD2PD(vol) VolToPart[vol].pd /* Get physical drive number */ +#define LD2PT(vol) VolToPart[vol].pt /* Get partition number (0:auto search, 1..:forced partition number) */ +#else +#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is associated with the same physical drive number */ +#define LD2PT(vol) 0 /* Auto partition search */ +#endif + + +/* Definitions of sector size */ +#if (FF_MAX_SS < FF_MIN_SS) || (FF_MAX_SS != 512 && FF_MAX_SS != 1024 && FF_MAX_SS != 2048 && FF_MAX_SS != 4096) || (FF_MIN_SS != 512 && FF_MIN_SS != 1024 && FF_MIN_SS != 2048 && FF_MIN_SS != 4096) +#error Wrong sector size configuration +#endif +#if FF_MAX_SS == FF_MIN_SS +#define SS(fs) ((UINT)FF_MAX_SS) /* Fixed sector size */ +#else +#define SS(fs) ((fs)->ssize) /* Variable sector size */ +#endif + + +/* Timestamp */ +#if FF_FS_NORTC == 1 +#if FF_NORTC_YEAR < 1980 || FF_NORTC_YEAR > 2107 || FF_NORTC_MON < 1 || FF_NORTC_MON > 12 || FF_NORTC_MDAY < 1 || FF_NORTC_MDAY > 31 +#error Invalid FF_FS_NORTC settings +#endif +#define GET_FATTIME() ((DWORD)(FF_NORTC_YEAR - 1980) << 25 | (DWORD)FF_NORTC_MON << 21 | (DWORD)FF_NORTC_MDAY << 16) +#else +#define GET_FATTIME() get_fattime() +#endif + + +/* File lock controls */ +#if FF_FS_LOCK != 0 +#if FF_FS_READONLY +#error FF_FS_LOCK must be 0 at read-only configuration +#endif +typedef struct { + FATFS *fs; /* Object ID 1, volume (NULL:blank entry) */ + DWORD clu; /* Object ID 2, containing directory (0:root) */ + DWORD ofs; /* Object ID 3, offset in the directory */ + WORD ctr; /* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */ +} FILESEM; +#endif + + +/* SBCS up-case tables (\x80-\xFF) */ +#define TBL_CT437 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT720 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT737 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ + 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xEF,0xF5,0xF0,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT771 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDC,0xDE,0xDE, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFE,0xFF} +#define TBL_CT775 {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F, \ + 0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT850 {0x43,0x55,0x45,0x41,0x41,0x41,0x41,0x43,0x45,0x45,0x45,0x49,0x49,0x49,0x41,0x41, \ + 0x45,0x92,0x92,0x4F,0x4F,0x4F,0x55,0x55,0x59,0x4F,0x55,0x4F,0x9C,0x4F,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0x41,0x41,0x41,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0x41,0x41,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD1,0xD1,0x45,0x45,0x45,0x49,0x49,0x49,0x49,0xD9,0xDA,0xDB,0xDC,0xDD,0x49,0xDF, \ + 0x4F,0xE1,0x4F,0x4F,0x4F,0x4F,0xE6,0xE8,0xE8,0x55,0x55,0x55,0x59,0x59,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT852 {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0xAC, \ + 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} +#define TBL_CT855 {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F, \ + 0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ + 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ + 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF, \ + 0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT857 {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0x49,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT860 {0x80,0x9A,0x90,0x8F,0x8E,0x91,0x86,0x80,0x89,0x89,0x92,0x8B,0x8C,0x98,0x8E,0x8F, \ + 0x90,0x91,0x92,0x8C,0x99,0xA9,0x96,0x9D,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x86,0x8B,0x9F,0x96,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT861 {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x8B,0x8B,0x8D,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x8D,0x55,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA4,0xA5,0xA6,0xA7,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT862 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT863 {0x43,0x55,0x45,0x41,0x41,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x41,0x8F, \ + 0x45,0x45,0x45,0x4F,0x45,0x49,0x55,0x55,0x98,0x4F,0x55,0x9B,0x9C,0x55,0x55,0x9F, \ + 0xA0,0xA1,0x4F,0x55,0xA4,0xA5,0xA6,0xA7,0x49,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT864 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT865 {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT866 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT869 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x86,0x9C,0x8D,0x8F,0x90, \ + 0x91,0x90,0x92,0x95,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xA4,0xA5,0xA6,0xD9,0xDA,0xDB,0xDC,0xA7,0xA8,0xDF, \ + 0xA9,0xAA,0xAC,0xAD,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xCF,0xCF,0xD0,0xEF, \ + 0xF0,0xF1,0xD1,0xD2,0xD3,0xF5,0xD4,0xF7,0xF8,0xF9,0xD5,0x96,0x95,0x98,0xFE,0xFF} + + +/* DBCS code range |----- 1st byte -----| |----------- 2nd byte -----------| */ +/* <------> <------> <------> <------> <------> */ +#define TBL_DC932 {0x81, 0x9F, 0xE0, 0xFC, 0x40, 0x7E, 0x80, 0xFC, 0x00, 0x00} +#define TBL_DC936 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0x80, 0xFE, 0x00, 0x00} +#define TBL_DC949 {0x81, 0xFE, 0x00, 0x00, 0x41, 0x5A, 0x61, 0x7A, 0x81, 0xFE} +#define TBL_DC950 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0xA1, 0xFE, 0x00, 0x00} + + +/* Macros for table definitions */ +#define MERGE_2STR(a, b) a ## b +#define MKCVTBL(hd, cp) MERGE_2STR(hd, cp) + + + + +/*-------------------------------------------------------------------------- + + Module Private Work Area + +---------------------------------------------------------------------------*/ +/* Remark: Variables defined here without initial value shall be guaranteed +/ zero/null at start-up. If not, the linker option or start-up routine is +/ not compliance with C standard. */ + +/*--------------------------------*/ +/* File/Volume controls */ +/*--------------------------------*/ + +#if FF_VOLUMES < 1 || FF_VOLUMES > 10 +#error Wrong FF_VOLUMES setting +#endif +static FATFS* FatFs[FF_VOLUMES]; /* Pointer to the filesystem objects (logical drives) */ +static WORD Fsid; /* Filesystem mount ID */ + +#if FF_FS_RPATH != 0 +static BYTE CurrVol; /* Current drive */ +#endif + +#if FF_FS_LOCK != 0 +static FILESEM Files[FF_FS_LOCK]; /* Open object lock semaphores */ +#endif + +#if FF_STR_VOLUME_ID +#ifdef FF_VOLUME_STRS +static const char* const VolumeStr[FF_VOLUMES] = {FF_VOLUME_STRS}; /* Pre-defined volume ID */ +#endif +#endif + +#if FF_LBA64 +#if FF_MIN_GPT > 0x100000000 +#error Wrong FF_MIN_GPT setting +#endif +static const BYTE GUID_MS_Basic[16] = {0xA2,0xA0,0xD0,0xEB,0xE5,0xB9,0x33,0x44,0x87,0xC0,0x68,0xB6,0xB7,0x26,0x99,0xC7}; +#endif + + + +/*--------------------------------*/ +/* LFN/Directory working buffer */ +/*--------------------------------*/ + +#if FF_USE_LFN == 0 /* Non-LFN configuration */ +#if FF_FS_EXFAT +#error LFN must be enabled when enable exFAT +#endif +#define DEF_NAMBUF +#define INIT_NAMBUF(fs) +#define FREE_NAMBUF() +#define LEAVE_MKFS(res) return res + +#else /* LFN configurations */ +#if FF_MAX_LFN < 12 || FF_MAX_LFN > 255 +#error Wrong setting of FF_MAX_LFN +#endif +#if FF_LFN_BUF < FF_SFN_BUF || FF_SFN_BUF < 12 +#error Wrong setting of FF_LFN_BUF or FF_SFN_BUF +#endif +#if FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3 +#error Wrong setting of FF_LFN_UNICODE +#endif +static const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* FAT: Offset of LFN characters in the directory entry */ +#define MAXDIRB(nc) ((nc + 44U) / 15 * SZDIRE) /* exFAT: Size of directory entry block scratchpad buffer needed for the name length */ + +#if FF_USE_LFN == 1 /* LFN enabled with static working buffer */ +#if FF_FS_EXFAT +static BYTE DirBuf[MAXDIRB(FF_MAX_LFN)]; /* Directory entry block scratchpad buffer */ +#endif +static WCHAR LfnBuf[FF_MAX_LFN + 1]; /* LFN working buffer */ +#define DEF_NAMBUF +#define INIT_NAMBUF(fs) +#define FREE_NAMBUF() +#define LEAVE_MKFS(res) return res + +#elif FF_USE_LFN == 2 /* LFN enabled with dynamic working buffer on the stack */ +#if FF_FS_EXFAT +#define DEF_NAMBUF WCHAR lbuf[FF_MAX_LFN+1]; BYTE dbuf[MAXDIRB(FF_MAX_LFN)]; /* LFN working buffer and directory entry block scratchpad buffer */ +#define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; (fs)->dirbuf = dbuf; } +#define FREE_NAMBUF() +#else +#define DEF_NAMBUF WCHAR lbuf[FF_MAX_LFN+1]; /* LFN working buffer */ +#define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; } +#define FREE_NAMBUF() +#endif +#define LEAVE_MKFS(res) return res + +#elif FF_USE_LFN == 3 /* LFN enabled with dynamic working buffer on the heap */ +#if FF_FS_EXFAT +#define DEF_NAMBUF WCHAR *lfn; /* Pointer to LFN working buffer and directory entry block scratchpad buffer */ +#define INIT_NAMBUF(fs) { lfn = ff_memalloc((FF_MAX_LFN+1)*2 + MAXDIRB(FF_MAX_LFN)); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; (fs)->dirbuf = (BYTE*)(lfn+FF_MAX_LFN+1); } +#define FREE_NAMBUF() ff_memfree(lfn) +#else +#define DEF_NAMBUF WCHAR *lfn; /* Pointer to LFN working buffer */ +#define INIT_NAMBUF(fs) { lfn = ff_memalloc((FF_MAX_LFN+1)*2); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; } +#define FREE_NAMBUF() ff_memfree(lfn) +#endif +#define LEAVE_MKFS(res) { if (!work) ff_memfree(buf); return res; } +#define MAX_MALLOC 0x8000 /* Must be >=FF_MAX_SS */ + +#else +#error Wrong setting of FF_USE_LFN + +#endif /* FF_USE_LFN == 1 */ +#endif /* FF_USE_LFN == 0 */ + + + +/*--------------------------------*/ +/* Code conversion tables */ +/*--------------------------------*/ + +#if FF_CODE_PAGE == 0 /* Run-time code page configuration */ +#define CODEPAGE CodePage +static WORD CodePage; /* Current code page */ +static const BYTE *ExCvt, *DbcTbl; /* Pointer to current SBCS up-case table and DBCS code range table below */ + +static const BYTE Ct437[] = TBL_CT437; +static const BYTE Ct720[] = TBL_CT720; +static const BYTE Ct737[] = TBL_CT737; +static const BYTE Ct771[] = TBL_CT771; +static const BYTE Ct775[] = TBL_CT775; +static const BYTE Ct850[] = TBL_CT850; +static const BYTE Ct852[] = TBL_CT852; +static const BYTE Ct855[] = TBL_CT855; +static const BYTE Ct857[] = TBL_CT857; +static const BYTE Ct860[] = TBL_CT860; +static const BYTE Ct861[] = TBL_CT861; +static const BYTE Ct862[] = TBL_CT862; +static const BYTE Ct863[] = TBL_CT863; +static const BYTE Ct864[] = TBL_CT864; +static const BYTE Ct865[] = TBL_CT865; +static const BYTE Ct866[] = TBL_CT866; +static const BYTE Ct869[] = TBL_CT869; +static const BYTE Dc932[] = TBL_DC932; +static const BYTE Dc936[] = TBL_DC936; +static const BYTE Dc949[] = TBL_DC949; +static const BYTE Dc950[] = TBL_DC950; + +#elif FF_CODE_PAGE < 900 /* Static code page configuration (SBCS) */ +#define CODEPAGE FF_CODE_PAGE +static const BYTE ExCvt[] = MKCVTBL(TBL_CT, FF_CODE_PAGE); + +#else /* Static code page configuration (DBCS) */ +#define CODEPAGE FF_CODE_PAGE +static const BYTE DbcTbl[] = MKCVTBL(TBL_DC, FF_CODE_PAGE); + +#endif + + + + +/*-------------------------------------------------------------------------- + + Module Private Functions + +---------------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* Load/Store multi-byte word in the FAT structure */ +/*-----------------------------------------------------------------------*/ + +static WORD ld_word (const BYTE* ptr) /* Load a 2-byte little-endian word */ +{ + WORD rv; + + rv = ptr[1]; + rv = rv << 8 | ptr[0]; + return rv; +} + +static DWORD ld_dword (const BYTE* ptr) /* Load a 4-byte little-endian word */ +{ + DWORD rv; + + rv = ptr[3]; + rv = rv << 8 | ptr[2]; + rv = rv << 8 | ptr[1]; + rv = rv << 8 | ptr[0]; + return rv; +} + +#if FF_FS_EXFAT +static QWORD ld_qword (const BYTE* ptr) /* Load an 8-byte little-endian word */ +{ + QWORD rv; + + rv = ptr[7]; + rv = rv << 8 | ptr[6]; + rv = rv << 8 | ptr[5]; + rv = rv << 8 | ptr[4]; + rv = rv << 8 | ptr[3]; + rv = rv << 8 | ptr[2]; + rv = rv << 8 | ptr[1]; + rv = rv << 8 | ptr[0]; + return rv; +} +#endif + +#if !FF_FS_READONLY +static void st_word (BYTE* ptr, WORD val) /* Store a 2-byte word in little-endian */ +{ + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; +} + +static void st_dword (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-endian */ +{ + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; +} + +#if FF_FS_EXFAT +static void st_qword (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-endian */ +{ + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; +} +#endif +#endif /* !FF_FS_READONLY */ + + + +/*-----------------------------------------------------------------------*/ +/* String functions */ +/*-----------------------------------------------------------------------*/ + +/* Test if the byte is DBC 1st byte */ +static int dbc_1st (BYTE c) +{ +#if FF_CODE_PAGE == 0 /* Variable code page */ + if (DbcTbl && c >= DbcTbl[0]) { + if (c <= DbcTbl[1]) return 1; /* 1st byte range 1 */ + if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1; /* 1st byte range 2 */ + } +#elif FF_CODE_PAGE >= 900 /* DBCS fixed code page */ + if (c >= DbcTbl[0]) { + if (c <= DbcTbl[1]) return 1; + if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1; + } +#else /* SBCS fixed code page */ + if (c != 0) return 0; /* Always false */ +#endif + return 0; +} + + +/* Test if the byte is DBC 2nd byte */ +static int dbc_2nd (BYTE c) +{ +#if FF_CODE_PAGE == 0 /* Variable code page */ + if (DbcTbl && c >= DbcTbl[4]) { + if (c <= DbcTbl[5]) return 1; /* 2nd byte range 1 */ + if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1; /* 2nd byte range 2 */ + if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1; /* 2nd byte range 3 */ + } +#elif FF_CODE_PAGE >= 900 /* DBCS fixed code page */ + if (c >= DbcTbl[4]) { + if (c <= DbcTbl[5]) return 1; + if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1; + if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1; + } +#else /* SBCS fixed code page */ + if (c != 0) return 0; /* Always false */ +#endif + return 0; +} + + +#if FF_USE_LFN + +/* Get a Unicode code point from the TCHAR string in defined API encodeing */ +static DWORD tchar2uni ( /* Returns a character in UTF-16 encoding (>=0x10000 on surrogate pair, 0xFFFFFFFF on decode error) */ + const TCHAR** str /* Pointer to pointer to TCHAR string in configured encoding */ +) +{ + DWORD uc; + const TCHAR *p = *str; + +#if FF_LFN_UNICODE == 1 /* UTF-16 input */ + WCHAR wc; + + uc = *p++; /* Get a unit */ + if (IsSurrogate(uc)) { /* Surrogate? */ + wc = *p++; /* Get low surrogate */ + if (!IsSurrogateH(uc) || !IsSurrogateL(wc)) return 0xFFFFFFFF; /* Wrong surrogate? */ + uc = uc << 16 | wc; + } + +#elif FF_LFN_UNICODE == 2 /* UTF-8 input */ + BYTE b; + int nf; + + uc = (BYTE)*p++; /* Get an encoding unit */ + if (uc & 0x80) { /* Multiple byte code? */ + if ((uc & 0xE0) == 0xC0) { /* 2-byte sequence? */ + uc &= 0x1F; nf = 1; + } else if ((uc & 0xF0) == 0xE0) { /* 3-byte sequence? */ + uc &= 0x0F; nf = 2; + } else if ((uc & 0xF8) == 0xF0) { /* 4-byte sequence? */ + uc &= 0x07; nf = 3; + } else { /* Wrong sequence */ + return 0xFFFFFFFF; + } + do { /* Get trailing bytes */ + b = (BYTE)*p++; + if ((b & 0xC0) != 0x80) return 0xFFFFFFFF; /* Wrong sequence? */ + uc = uc << 6 | (b & 0x3F); + } while (--nf != 0); + if (uc < 0x80 || IsSurrogate(uc) || uc >= 0x110000) return 0xFFFFFFFF; /* Wrong code? */ + if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ + } + +#elif FF_LFN_UNICODE == 3 /* UTF-32 input */ + uc = (TCHAR)*p++; /* Get a unit */ + if (uc >= 0x110000 || IsSurrogate(uc)) return 0xFFFFFFFF; /* Wrong code? */ + if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ + +#else /* ANSI/OEM input */ + BYTE b; + WCHAR wc; + + wc = (BYTE)*p++; /* Get a byte */ + if (dbc_1st((BYTE)wc)) { /* Is it a DBC 1st byte? */ + b = (BYTE)*p++; /* Get 2nd byte */ + if (!dbc_2nd(b)) return 0xFFFFFFFF; /* Invalid code? */ + wc = (wc << 8) + b; /* Make a DBC */ + } + if (wc != 0) { + wc = ff_oem2uni(wc, CODEPAGE); /* ANSI/OEM ==> Unicode */ + if (wc == 0) return 0xFFFFFFFF; /* Invalid code? */ + } + uc = wc; + +#endif + *str = p; /* Next read pointer */ + return uc; +} + + +/* Store a Unicode char in defined API encoding */ +static UINT put_utf ( /* Returns number of encoding units written (0:buffer overflow or wrong encoding) */ + DWORD chr, /* UTF-16 encoded character (Surrogate pair if >=0x10000) */ + TCHAR* buf, /* Output buffer */ + UINT szb /* Size of the buffer */ +) +{ +#if FF_LFN_UNICODE == 1 /* UTF-16 output */ + WCHAR hs, wc; + + hs = (WCHAR)(chr >> 16); + wc = (WCHAR)chr; + if (hs == 0) { /* Single encoding unit? */ + if (szb < 1 || IsSurrogate(wc)) return 0; /* Buffer overflow or wrong code? */ + *buf = wc; + return 1; + } + if (szb < 2 || !IsSurrogateH(hs) || !IsSurrogateL(wc)) return 0; /* Buffer overflow or wrong surrogate? */ + *buf++ = hs; + *buf++ = wc; + return 2; + +#elif FF_LFN_UNICODE == 2 /* UTF-8 output */ + DWORD hc; + + if (chr < 0x80) { /* Single byte code? */ + if (szb < 1) return 0; /* Buffer overflow? */ + *buf = (TCHAR)chr; + return 1; + } + if (chr < 0x800) { /* 2-byte sequence? */ + if (szb < 2) return 0; /* Buffer overflow? */ + *buf++ = (TCHAR)(0xC0 | (chr >> 6 & 0x1F)); + *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); + return 2; + } + if (chr < 0x10000) { /* 3-byte sequence? */ + if (szb < 3 || IsSurrogate(chr)) return 0; /* Buffer overflow or wrong code? */ + *buf++ = (TCHAR)(0xE0 | (chr >> 12 & 0x0F)); + *buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F)); + *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); + return 3; + } + /* 4-byte sequence */ + if (szb < 4) return 0; /* Buffer overflow? */ + hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6; /* Get high 10 bits */ + chr = (chr & 0xFFFF) - 0xDC00; /* Get low 10 bits */ + if (hc >= 0x100000 || chr >= 0x400) return 0; /* Wrong surrogate? */ + chr = (hc | chr) + 0x10000; + *buf++ = (TCHAR)(0xF0 | (chr >> 18 & 0x07)); + *buf++ = (TCHAR)(0x80 | (chr >> 12 & 0x3F)); + *buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F)); + *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); + return 4; + +#elif FF_LFN_UNICODE == 3 /* UTF-32 output */ + DWORD hc; + + if (szb < 1) return 0; /* Buffer overflow? */ + if (chr >= 0x10000) { /* Out of BMP? */ + hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6; /* Get high 10 bits */ + chr = (chr & 0xFFFF) - 0xDC00; /* Get low 10 bits */ + if (hc >= 0x100000 || chr >= 0x400) return 0; /* Wrong surrogate? */ + chr = (hc | chr) + 0x10000; + } + *buf++ = (TCHAR)chr; + return 1; + +#else /* ANSI/OEM output */ + WCHAR wc; + + wc = ff_uni2oem(chr, CODEPAGE); + if (wc >= 0x100) { /* Is this a DBC? */ + if (szb < 2) return 0; + *buf++ = (char)(wc >> 8); /* Store DBC 1st byte */ + *buf++ = (TCHAR)wc; /* Store DBC 2nd byte */ + return 2; + } + if (wc == 0 || szb < 1) return 0; /* Invalid char or buffer overflow? */ + *buf++ = (TCHAR)wc; /* Store the character */ + return 1; +#endif +} +#endif /* FF_USE_LFN */ + + +#if FF_FS_REENTRANT +/*-----------------------------------------------------------------------*/ +/* Request/Release grant to access the volume */ +/*-----------------------------------------------------------------------*/ +static int lock_fs ( /* 1:Ok, 0:timeout */ + FATFS* fs /* Filesystem object */ +) +{ + return ff_req_grant(fs->sobj); +} + + +static void unlock_fs ( + FATFS* fs, /* Filesystem object */ + FRESULT res /* Result code to be returned */ +) +{ + if (fs && res != FR_NOT_ENABLED && res != FR_INVALID_DRIVE && res != FR_TIMEOUT) { + ff_rel_grant(fs->sobj); + } +} + +#endif + + + +#if FF_FS_LOCK != 0 +/*-----------------------------------------------------------------------*/ +/* File lock control functions */ +/*-----------------------------------------------------------------------*/ + +static FRESULT chk_lock ( /* Check if the file can be accessed */ + DIR* dp, /* Directory object pointing the file to be checked */ + int acc /* Desired access type (0:Read mode open, 1:Write mode open, 2:Delete or rename) */ +) +{ + UINT i, be; + + /* Search open object table for the object */ + be = 0; + for (i = 0; i < FF_FS_LOCK; i++) { + if (Files[i].fs) { /* Existing entry */ + if (Files[i].fs == dp->obj.fs && /* Check if the object matches with an open object */ + Files[i].clu == dp->obj.sclust && + Files[i].ofs == dp->dptr) break; + } else { /* Blank entry */ + be = 1; + } + } + if (i == FF_FS_LOCK) { /* The object has not been opened */ + return (!be && acc != 2) ? FR_TOO_MANY_OPEN_FILES : FR_OK; /* Is there a blank entry for new object? */ + } + + /* The object was opened. Reject any open against writing file and all write mode open */ + return (acc != 0 || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; +} + + +static int enq_lock (void) /* Check if an entry is available for a new object */ +{ + UINT i; + + for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; + return (i == FF_FS_LOCK) ? 0 : 1; +} + + +static UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */ + DIR* dp, /* Directory object pointing the file to register or increment */ + int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ +) +{ + UINT i; + + + for (i = 0; i < FF_FS_LOCK; i++) { /* Find the object */ + if (Files[i].fs == dp->obj.fs + && Files[i].clu == dp->obj.sclust + && Files[i].ofs == dp->dptr) break; + } + + if (i == FF_FS_LOCK) { /* Not opened. Register it as new. */ + for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; + if (i == FF_FS_LOCK) return 0; /* No free entry to register (int err) */ + Files[i].fs = dp->obj.fs; + Files[i].clu = dp->obj.sclust; + Files[i].ofs = dp->dptr; + Files[i].ctr = 0; + } + + if (acc >= 1 && Files[i].ctr) return 0; /* Access violation (int err) */ + + Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ + + return i + 1; /* Index number origin from 1 */ +} + + +static FRESULT dec_lock ( /* Decrement object open counter */ + UINT i /* Semaphore index (1..) */ +) +{ + WORD n; + FRESULT res; + + + if (--i < FF_FS_LOCK) { /* Index number origin from 0 */ + n = Files[i].ctr; + if (n == 0x100) n = 0; /* If write mode open, delete the entry */ + if (n > 0) n--; /* Decrement read mode open count */ + Files[i].ctr = n; + if (n == 0) Files[i].fs = 0; /* Delete the entry if open count gets zero */ + res = FR_OK; + } else { + res = FR_INT_ERR; /* Invalid index nunber */ + } + return res; +} + + +static void clear_lock ( /* Clear lock entries of the volume */ + FATFS *fs +) +{ + UINT i; + + for (i = 0; i < FF_FS_LOCK; i++) { + if (Files[i].fs == fs) Files[i].fs = 0; + } +} + +#endif /* FF_FS_LOCK != 0 */ + + + +/*-----------------------------------------------------------------------*/ +/* Move/Flush disk access window in the filesystem object */ +/*-----------------------------------------------------------------------*/ +#if !FF_FS_READONLY +static FRESULT sync_window ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS* fs /* Filesystem object */ +) +{ + FRESULT res = FR_OK; + + + if (fs->wflag) { /* Is the disk access window dirty? */ + if (disk_write(fs->pdrv, fs->win, fs->winsect, 1) == RES_OK) { /* Write it back into the volume */ + fs->wflag = 0; /* Clear window dirty flag */ + if (fs->winsect - fs->fatbase < fs->fsize) { /* Is it in the 1st FAT? */ + if (fs->n_fats == 2) disk_write(fs->pdrv, fs->win, fs->winsect + fs->fsize, 1); /* Reflect it to 2nd FAT if needed */ + } + } else { + res = FR_DISK_ERR; + } + } + return res; +} +#endif + + +static FRESULT move_window ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS* fs, /* Filesystem object */ + LBA_t sect /* Sector LBA to make appearance in the fs->win[] */ +) +{ + FRESULT res = FR_OK; + + + if (sect != fs->winsect) { /* Window offset changed? */ +#if !FF_FS_READONLY + res = sync_window(fs); /* Flush the window */ +#endif + if (res == FR_OK) { /* Fill sector window with new data */ + if (disk_read(fs->pdrv, fs->win, sect, 1) != RES_OK) { + sect = (LBA_t)0 - 1; /* Invalidate window if read data is not valid */ + res = FR_DISK_ERR; + } + fs->winsect = sect; + } + } + return res; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Synchronize filesystem and data on the storage */ +/*-----------------------------------------------------------------------*/ + +static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS* fs /* Filesystem object */ +) +{ + FRESULT res; + + + res = sync_window(fs); + if (res == FR_OK) { + if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */ + /* Create FSInfo structure */ + memset(fs->win, 0, sizeof fs->win); + st_word(fs->win + BS_55AA, 0xAA55); /* Boot signature */ + st_dword(fs->win + FSI_LeadSig, 0x41615252); /* Leading signature */ + st_dword(fs->win + FSI_StrucSig, 0x61417272); /* Structure signature */ + st_dword(fs->win + FSI_Free_Count, fs->free_clst); /* Number of free clusters */ + st_dword(fs->win + FSI_Nxt_Free, fs->last_clst); /* Last allocated culuster */ + fs->winsect = fs->volbase + 1; /* Write it into the FSInfo sector (Next to VBR) */ + disk_write(fs->pdrv, fs->win, fs->winsect, 1); + fs->fsi_flag = 0; + } + /* Make sure that no pending write process in the lower layer */ + if (disk_ioctl(fs->pdrv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR; + } + + return res; +} + +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Get physical sector number from cluster number */ +/*-----------------------------------------------------------------------*/ + +static LBA_t clst2sect ( /* !=0:Sector number, 0:Failed (invalid cluster#) */ + FATFS* fs, /* Filesystem object */ + DWORD clst /* Cluster# to be converted */ +) +{ + clst -= 2; /* Cluster number is origin from 2 */ + if (clst >= fs->n_fatent - 2) return 0; /* Is it invalid cluster number? */ + return fs->database + (LBA_t)fs->csize * clst; /* Start sector number of the cluster */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT access - Read value of an FAT entry */ +/*-----------------------------------------------------------------------*/ + +static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluster status */ + FFOBJID* obj, /* Corresponding object */ + DWORD clst /* Cluster number to get the value */ +) +{ + UINT wc, bc; + DWORD val; + FATFS *fs = obj->fs; + + + if (clst < 2 || clst >= fs->n_fatent) { /* Check if in valid range */ + val = 1; /* Internal error */ + + } else { + val = 0xFFFFFFFF; /* Default value falls on disk error */ + + switch (fs->fs_type) { + case FS_FAT12 : + bc = (UINT)clst; bc += bc / 2; + if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; + wc = fs->win[bc++ % SS(fs)]; /* Get 1st byte of the entry */ + if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; + wc |= fs->win[bc % SS(fs)] << 8; /* Merge 2nd byte of the entry */ + val = (clst & 1) ? (wc >> 4) : (wc & 0xFFF); /* Adjust bit position */ + break; + + case FS_FAT16 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break; + val = ld_word(fs->win + clst * 2 % SS(fs)); /* Simple WORD array */ + break; + + case FS_FAT32 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; + val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x0FFFFFFF; /* Simple DWORD array but mask out upper 4 bits */ + break; +#if FF_FS_EXFAT + case FS_EXFAT : + if ((obj->objsize != 0 && obj->sclust != 0) || obj->stat == 0) { /* Object except root dir must have valid data length */ + DWORD cofs = clst - obj->sclust; /* Offset from start cluster */ + DWORD clen = (DWORD)((LBA_t)((obj->objsize - 1) / SS(fs)) / fs->csize); /* Number of clusters - 1 */ + + if (obj->stat == 2 && cofs <= clen) { /* Is it a contiguous chain? */ + val = (cofs == clen) ? 0x7FFFFFFF : clst + 1; /* No data on the FAT, generate the value */ + break; + } + if (obj->stat == 3 && cofs < obj->n_cont) { /* Is it in the 1st fragment? */ + val = clst + 1; /* Generate the value */ + break; + } + if (obj->stat != 2) { /* Get value from FAT if FAT chain is valid */ + if (obj->n_frag != 0) { /* Is it on the growing edge? */ + val = 0x7FFFFFFF; /* Generate EOC */ + } else { + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; + val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF; + } + break; + } + } + val = 1; /* Internal error */ + break; +#endif + default: + val = 1; /* Internal error */ + } + } + + return val; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* FAT access - Change value of an FAT entry */ +/*-----------------------------------------------------------------------*/ + +static FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */ + FATFS* fs, /* Corresponding filesystem object */ + DWORD clst, /* FAT index number (cluster number) to be changed */ + DWORD val /* New value to be set to the entry */ +) +{ + UINT bc; + BYTE *p; + FRESULT res = FR_INT_ERR; + + + if (clst >= 2 && clst < fs->n_fatent) { /* Check if in valid range */ + switch (fs->fs_type) { + case FS_FAT12: + bc = (UINT)clst; bc += bc / 2; /* bc: byte offset of the entry */ + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = fs->win + bc++ % SS(fs); + *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; /* Update 1st byte */ + fs->wflag = 1; + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = fs->win + bc % SS(fs); + *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); /* Update 2nd byte */ + fs->wflag = 1; + break; + + case FS_FAT16: + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); + if (res != FR_OK) break; + st_word(fs->win + clst * 2 % SS(fs), (WORD)val); /* Simple WORD array */ + fs->wflag = 1; + break; + + case FS_FAT32: +#if FF_FS_EXFAT + case FS_EXFAT: +#endif + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); + if (res != FR_OK) break; + if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { + val = (val & 0x0FFFFFFF) | (ld_dword(fs->win + clst * 4 % SS(fs)) & 0xF0000000); + } + st_dword(fs->win + clst * 4 % SS(fs), val); + fs->wflag = 1; + break; + } + } + return res; +} + +#endif /* !FF_FS_READONLY */ + + + + +#if FF_FS_EXFAT && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* exFAT: Accessing FAT and Allocation Bitmap */ +/*-----------------------------------------------------------------------*/ + +/*--------------------------------------*/ +/* Find a contiguous free cluster block */ +/*--------------------------------------*/ + +static DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk error */ + FATFS* fs, /* Filesystem object */ + DWORD clst, /* Cluster number to scan from */ + DWORD ncl /* Number of contiguous clusters to find (1..) */ +) +{ + BYTE bm, bv; + UINT i; + DWORD val, scl, ctr; + + + clst -= 2; /* The first bit in the bitmap corresponds to cluster #2 */ + if (clst >= fs->n_fatent - 2) clst = 0; + scl = val = clst; ctr = 0; + for (;;) { + if (move_window(fs, fs->bitbase + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; + i = val / 8 % SS(fs); bm = 1 << (val % 8); + do { + do { + bv = fs->win[i] & bm; bm <<= 1; /* Get bit value */ + if (++val >= fs->n_fatent - 2) { /* Next cluster (with wrap-around) */ + val = 0; bm = 0; i = SS(fs); + } + if (bv == 0) { /* Is it a free cluster? */ + if (++ctr == ncl) return scl + 2; /* Check if run length is sufficient for required */ + } else { + scl = val; ctr = 0; /* Encountered a cluster in-use, restart to scan */ + } + if (val == clst) return 0; /* All cluster scanned? */ + } while (bm != 0); + bm = 1; + } while (++i < SS(fs)); + } +} + + +/*----------------------------------------*/ +/* Set/Clear a block of allocation bitmap */ +/*----------------------------------------*/ + +static FRESULT change_bitmap ( + FATFS* fs, /* Filesystem object */ + DWORD clst, /* Cluster number to change from */ + DWORD ncl, /* Number of clusters to be changed */ + int bv /* bit value to be set (0 or 1) */ +) +{ + BYTE bm; + UINT i; + LBA_t sect; + + + clst -= 2; /* The first bit corresponds to cluster #2 */ + sect = fs->bitbase + clst / 8 / SS(fs); /* Sector address */ + i = clst / 8 % SS(fs); /* Byte offset in the sector */ + bm = 1 << (clst % 8); /* Bit mask in the byte */ + for (;;) { + if (move_window(fs, sect++) != FR_OK) return FR_DISK_ERR; + do { + do { + if (bv == (int)((fs->win[i] & bm) != 0)) return FR_INT_ERR; /* Is the bit expected value? */ + fs->win[i] ^= bm; /* Flip the bit */ + fs->wflag = 1; + if (--ncl == 0) return FR_OK; /* All bits processed? */ + } while (bm <<= 1); /* Next bit */ + bm = 1; + } while (++i < SS(fs)); /* Next byte */ + i = 0; + } +} + + +/*---------------------------------------------*/ +/* Fill the first fragment of the FAT chain */ +/*---------------------------------------------*/ + +static FRESULT fill_first_frag ( + FFOBJID* obj /* Pointer to the corresponding object */ +) +{ + FRESULT res; + DWORD cl, n; + + + if (obj->stat == 3) { /* Has the object been changed 'fragmented' in this session? */ + for (cl = obj->sclust, n = obj->n_cont; n; cl++, n--) { /* Create cluster chain on the FAT */ + res = put_fat(obj->fs, cl, cl + 1); + if (res != FR_OK) return res; + } + obj->stat = 0; /* Change status 'FAT chain is valid' */ + } + return FR_OK; +} + + +/*---------------------------------------------*/ +/* Fill the last fragment of the FAT chain */ +/*---------------------------------------------*/ + +static FRESULT fill_last_frag ( + FFOBJID* obj, /* Pointer to the corresponding object */ + DWORD lcl, /* Last cluster of the fragment */ + DWORD term /* Value to set the last FAT entry */ +) +{ + FRESULT res; + + + while (obj->n_frag > 0) { /* Create the chain of last fragment */ + res = put_fat(obj->fs, lcl - obj->n_frag + 1, (obj->n_frag > 1) ? lcl - obj->n_frag + 2 : term); + if (res != FR_OK) return res; + obj->n_frag--; + } + return FR_OK; +} + +#endif /* FF_FS_EXFAT && !FF_FS_READONLY */ + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* FAT handling - Remove a cluster chain */ +/*-----------------------------------------------------------------------*/ + +static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */ + FFOBJID* obj, /* Corresponding object */ + DWORD clst, /* Cluster to remove a chain from */ + DWORD pclst /* Previous cluster of clst (0 if entire chain) */ +) +{ + FRESULT res = FR_OK; + DWORD nxt; + FATFS *fs = obj->fs; +#if FF_FS_EXFAT || FF_USE_TRIM + DWORD scl = clst, ecl = clst; +#endif +#if FF_USE_TRIM + LBA_t rt[2]; +#endif + + if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Check if in valid range */ + + /* Mark the previous cluster 'EOC' on the FAT if it exists */ + if (pclst != 0 && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT || obj->stat != 2)) { + res = put_fat(fs, pclst, 0xFFFFFFFF); + if (res != FR_OK) return res; + } + + /* Remove the chain */ + do { + nxt = get_fat(obj, clst); /* Get cluster status */ + if (nxt == 0) break; /* Empty cluster? */ + if (nxt == 1) return FR_INT_ERR; /* Internal error? */ + if (nxt == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error? */ + if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { + res = put_fat(fs, clst, 0); /* Mark the cluster 'free' on the FAT */ + if (res != FR_OK) return res; + } + if (fs->free_clst < fs->n_fatent - 2) { /* Update FSINFO */ + fs->free_clst++; + fs->fsi_flag |= 1; + } +#if FF_FS_EXFAT || FF_USE_TRIM + if (ecl + 1 == nxt) { /* Is next cluster contiguous? */ + ecl = nxt; + } else { /* End of contiguous cluster block */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + res = change_bitmap(fs, scl, ecl - scl + 1, 0); /* Mark the cluster block 'free' on the bitmap */ + if (res != FR_OK) return res; + } +#endif +#if FF_USE_TRIM + rt[0] = clst2sect(fs, scl); /* Start of data area to be freed */ + rt[1] = clst2sect(fs, ecl) + fs->csize - 1; /* End of data area to be freed */ + disk_ioctl(fs->pdrv, CTRL_TRIM, rt); /* Inform storage device that the data in the block may be erased */ +#endif + scl = ecl = nxt; + } +#endif + clst = nxt; /* Next cluster */ + } while (clst < fs->n_fatent); /* Repeat while not the last link */ + +#if FF_FS_EXFAT + /* Some post processes for chain status */ + if (fs->fs_type == FS_EXFAT) { + if (pclst == 0) { /* Has the entire chain been removed? */ + obj->stat = 0; /* Change the chain status 'initial' */ + } else { + if (obj->stat == 0) { /* Is it a fragmented chain from the beginning of this session? */ + clst = obj->sclust; /* Follow the chain to check if it gets contiguous */ + while (clst != pclst) { + nxt = get_fat(obj, clst); + if (nxt < 2) return FR_INT_ERR; + if (nxt == 0xFFFFFFFF) return FR_DISK_ERR; + if (nxt != clst + 1) break; /* Not contiguous? */ + clst++; + } + if (clst == pclst) { /* Has the chain got contiguous again? */ + obj->stat = 2; /* Change the chain status 'contiguous' */ + } + } else { + if (obj->stat == 3 && pclst >= obj->sclust && pclst <= obj->sclust + obj->n_cont) { /* Was the chain fragmented in this session and got contiguous again? */ + obj->stat = 2; /* Change the chain status 'contiguous' */ + } + } + } + } +#endif + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Stretch a chain or Create a new chain */ +/*-----------------------------------------------------------------------*/ + +static DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ + FFOBJID* obj, /* Corresponding object */ + DWORD clst /* Cluster# to stretch, 0:Create a new chain */ +) +{ + DWORD cs, ncl, scl; + FRESULT res; + FATFS *fs = obj->fs; + + + if (clst == 0) { /* Create a new chain */ + scl = fs->last_clst; /* Suggested cluster to start to find */ + if (scl == 0 || scl >= fs->n_fatent) scl = 1; + } + else { /* Stretch a chain */ + cs = get_fat(obj, clst); /* Check the cluster status */ + if (cs < 2) return 1; /* Test for insanity */ + if (cs == 0xFFFFFFFF) return cs; /* Test for disk error */ + if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ + scl = clst; /* Cluster to start to find */ + } + if (fs->free_clst == 0) return 0; /* No free cluster */ + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + ncl = find_bitmap(fs, scl, 1); /* Find a free cluster */ + if (ncl == 0 || ncl == 0xFFFFFFFF) return ncl; /* No free cluster or hard error? */ + res = change_bitmap(fs, ncl, 1, 1); /* Mark the cluster 'in use' */ + if (res == FR_INT_ERR) return 1; + if (res == FR_DISK_ERR) return 0xFFFFFFFF; + if (clst == 0) { /* Is it a new chain? */ + obj->stat = 2; /* Set status 'contiguous' */ + } else { /* It is a stretched chain */ + if (obj->stat == 2 && ncl != scl + 1) { /* Is the chain got fragmented? */ + obj->n_cont = scl - obj->sclust; /* Set size of the contiguous part */ + obj->stat = 3; /* Change status 'just fragmented' */ + } + } + if (obj->stat != 2) { /* Is the file non-contiguous? */ + if (ncl == clst + 1) { /* Is the cluster next to previous one? */ + obj->n_frag = obj->n_frag ? obj->n_frag + 1 : 2; /* Increment size of last framgent */ + } else { /* New fragment */ + if (obj->n_frag == 0) obj->n_frag = 1; + res = fill_last_frag(obj, clst, ncl); /* Fill last fragment on the FAT and link it to new one */ + if (res == FR_OK) obj->n_frag = 1; + } + } + } else +#endif + { /* On the FAT/FAT32 volume */ + ncl = 0; + if (scl == clst) { /* Stretching an existing chain? */ + ncl = scl + 1; /* Test if next cluster is free */ + if (ncl >= fs->n_fatent) ncl = 2; + cs = get_fat(obj, ncl); /* Get next cluster status */ + if (cs == 1 || cs == 0xFFFFFFFF) return cs; /* Test for error */ + if (cs != 0) { /* Not free? */ + cs = fs->last_clst; /* Start at suggested cluster if it is valid */ + if (cs >= 2 && cs < fs->n_fatent) scl = cs; + ncl = 0; + } + } + if (ncl == 0) { /* The new cluster cannot be contiguous and find another fragment */ + ncl = scl; /* Start cluster */ + for (;;) { + ncl++; /* Next cluster */ + if (ncl >= fs->n_fatent) { /* Check wrap-around */ + ncl = 2; + if (ncl > scl) return 0; /* No free cluster found? */ + } + cs = get_fat(obj, ncl); /* Get the cluster status */ + if (cs == 0) break; /* Found a free cluster? */ + if (cs == 1 || cs == 0xFFFFFFFF) return cs; /* Test for error */ + if (ncl == scl) return 0; /* No free cluster found? */ + } + } + res = put_fat(fs, ncl, 0xFFFFFFFF); /* Mark the new cluster 'EOC' */ + if (res == FR_OK && clst != 0) { + res = put_fat(fs, clst, ncl); /* Link it from the previous one if needed */ + } + } + + if (res == FR_OK) { /* Update FSINFO if function succeeded. */ + fs->last_clst = ncl; + if (fs->free_clst <= fs->n_fatent - 2) fs->free_clst--; + fs->fsi_flag |= 1; + } else { + ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; /* Failed. Generate error status */ + } + + return ncl; /* Return new cluster number or error status */ +} + +#endif /* !FF_FS_READONLY */ + + + + +#if FF_USE_FASTSEEK +/*-----------------------------------------------------------------------*/ +/* FAT handling - Convert offset into cluster with link map table */ +/*-----------------------------------------------------------------------*/ + +static DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ + FIL* fp, /* Pointer to the file object */ + FSIZE_t ofs /* File offset to be converted to cluster# */ +) +{ + DWORD cl, ncl, *tbl; + FATFS *fs = fp->obj.fs; + + + tbl = fp->cltbl + 1; /* Top of CLMT */ + cl = (DWORD)(ofs / SS(fs) / fs->csize); /* Cluster order from top of the file */ + for (;;) { + ncl = *tbl++; /* Number of cluters in the fragment */ + if (ncl == 0) return 0; /* End of table? (error) */ + if (cl < ncl) break; /* In this fragment? */ + cl -= ncl; tbl++; /* Next fragment */ + } + return cl + *tbl; /* Return the cluster number */ +} + +#endif /* FF_USE_FASTSEEK */ + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Fill a cluster with zeros */ +/*-----------------------------------------------------------------------*/ + +#if !FF_FS_READONLY +static FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS *fs, /* Filesystem object */ + DWORD clst /* Directory table to clear */ +) +{ + LBA_t sect; + UINT n, szb; + BYTE *ibuf; + + + if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */ + sect = clst2sect(fs, clst); /* Top of the cluster */ + fs->winsect = sect; /* Set window to top of the cluster */ + memset(fs->win, 0, sizeof fs->win); /* Clear window buffer */ +#if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */ + /* Allocate a temporary buffer */ + for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ; + if (szb > SS(fs)) { /* Buffer allocated? */ + memset(ibuf, 0, szb); + szb /= SS(fs); /* Bytes -> Sectors */ + for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ + ff_memfree(ibuf); + } else +#endif + { + ibuf = fs->win; szb = 1; /* Use window buffer (many single-sector writes may take a time) */ + for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ + } + return (n == fs->csize) ? FR_OK : FR_DISK_ERR; +} +#endif /* !FF_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Set directory index */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_sdi ( /* FR_OK(0):succeeded, !=0:error */ + DIR* dp, /* Pointer to directory object */ + DWORD ofs /* Offset of directory table */ +) +{ + DWORD csz, clst; + FATFS *fs = dp->obj.fs; + + + if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR) || ofs % SZDIRE) { /* Check range of offset and alignment */ + return FR_INT_ERR; + } + dp->dptr = ofs; /* Set current offset */ + clst = dp->obj.sclust; /* Table start cluster (0:root) */ + if (clst == 0 && fs->fs_type >= FS_FAT32) { /* Replace cluster# 0 with root cluster# */ + clst = (DWORD)fs->dirbase; + if (FF_FS_EXFAT) dp->obj.stat = 0; /* exFAT: Root dir has an FAT chain */ + } + + if (clst == 0) { /* Static table (root-directory on the FAT volume) */ + if (ofs / SZDIRE >= fs->n_rootdir) return FR_INT_ERR; /* Is index out of range? */ + dp->sect = fs->dirbase; + + } else { /* Dynamic table (sub-directory or root-directory on the FAT32/exFAT volume) */ + csz = (DWORD)fs->csize * SS(fs); /* Bytes per cluster */ + while (ofs >= csz) { /* Follow cluster chain */ + clst = get_fat(&dp->obj, clst); /* Get next cluster */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Reached to end of table or internal error */ + ofs -= csz; + } + dp->sect = clst2sect(fs, clst); + } + dp->clust = clst; /* Current cluster# */ + if (dp->sect == 0) return FR_INT_ERR; + dp->sect += ofs / SS(fs); /* Sector# of the directory entry */ + dp->dir = fs->win + (ofs % SS(fs)); /* Pointer to the entry in the win[] */ + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Move directory table index next */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ + DIR* dp, /* Pointer to the directory object */ + int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ +) +{ + DWORD ofs, clst; + FATFS *fs = dp->obj.fs; + + + ofs = dp->dptr + SZDIRE; /* Next entry */ + if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) dp->sect = 0; /* Disable it if the offset reached the max value */ + if (dp->sect == 0) return FR_NO_FILE; /* Report EOT if it has been disabled */ + + if (ofs % SS(fs) == 0) { /* Sector changed? */ + dp->sect++; /* Next sector */ + + if (dp->clust == 0) { /* Static table */ + if (ofs / SZDIRE >= fs->n_rootdir) { /* Report EOT if it reached end of static table */ + dp->sect = 0; return FR_NO_FILE; + } + } + else { /* Dynamic table */ + if ((ofs / SS(fs) & (fs->csize - 1)) == 0) { /* Cluster changed? */ + clst = get_fat(&dp->obj, dp->clust); /* Get next cluster */ + if (clst <= 1) return FR_INT_ERR; /* Internal error */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (clst >= fs->n_fatent) { /* It reached end of dynamic table */ +#if !FF_FS_READONLY + if (!stretch) { /* If no stretch, report EOT */ + dp->sect = 0; return FR_NO_FILE; + } + clst = create_chain(&dp->obj, dp->clust); /* Allocate a cluster */ + if (clst == 0) return FR_DENIED; /* No free cluster */ + if (clst == 1) return FR_INT_ERR; /* Internal error */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (dir_clear(fs, clst) != FR_OK) return FR_DISK_ERR; /* Clean up the stretched table */ + if (FF_FS_EXFAT) dp->obj.stat |= 4; /* exFAT: The directory has been stretched */ +#else + if (!stretch) dp->sect = 0; /* (this line is to suppress compiler warning) */ + dp->sect = 0; return FR_NO_FILE; /* Report EOT */ +#endif + } + dp->clust = clst; /* Initialize data for new cluster */ + dp->sect = clst2sect(fs, clst); + } + } + } + dp->dptr = ofs; /* Current entry */ + dp->dir = fs->win + ofs % SS(fs); /* Pointer to the entry in the win[] */ + + return FR_OK; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Directory handling - Reserve a block of directory entries */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */ + DIR* dp, /* Pointer to the directory object */ + UINT n_ent /* Number of contiguous entries to allocate */ +) +{ + FRESULT res; + UINT n; + FATFS *fs = dp->obj.fs; + + + res = dir_sdi(dp, 0); + if (res == FR_OK) { + n = 0; + do { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; +#if FF_FS_EXFAT + if ((fs->fs_type == FS_EXFAT) ? (int)((dp->dir[XDIR_Type] & 0x80) == 0) : (int)(dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0)) { /* Is the entry free? */ +#else + if (dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0) { /* Is the entry free? */ +#endif + if (++n == n_ent) break; /* Is a block of contiguous free entries found? */ + } else { + n = 0; /* Not a free entry, restart to search */ + } + res = dir_next(dp, 1); /* Next entry with table stretch enabled */ + } while (res == FR_OK); + } + + if (res == FR_NO_FILE) res = FR_DENIED; /* No directory entry to allocate */ + return res; +} + +#endif /* !FF_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* FAT: Directory handling - Load/Store start cluster number */ +/*-----------------------------------------------------------------------*/ + +static DWORD ld_clust ( /* Returns the top cluster value of the SFN entry */ + FATFS* fs, /* Pointer to the fs object */ + const BYTE* dir /* Pointer to the key entry */ +) +{ + DWORD cl; + + cl = ld_word(dir + DIR_FstClusLO); + if (fs->fs_type == FS_FAT32) { + cl |= (DWORD)ld_word(dir + DIR_FstClusHI) << 16; + } + + return cl; +} + + +#if !FF_FS_READONLY +static void st_clust ( + FATFS* fs, /* Pointer to the fs object */ + BYTE* dir, /* Pointer to the key entry */ + DWORD cl /* Value to be set */ +) +{ + st_word(dir + DIR_FstClusLO, (WORD)cl); + if (fs->fs_type == FS_FAT32) { + st_word(dir + DIR_FstClusHI, (WORD)(cl >> 16)); + } +} +#endif + + + +#if FF_USE_LFN +/*--------------------------------------------------------*/ +/* FAT-LFN: Compare a part of file name with an LFN entry */ +/*--------------------------------------------------------*/ + +static int cmp_lfn ( /* 1:matched, 0:not matched */ + const WCHAR* lfnbuf, /* Pointer to the LFN working buffer to be compared */ + BYTE* dir /* Pointer to the directory entry containing the part of LFN */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO */ + + i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ + + for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */ + uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */ + if (wc != 0) { + if (i >= FF_MAX_LFN + 1 || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) { /* Compare it */ + return 0; /* Not matched */ + } + wc = uc; + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } + + if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i]) return 0; /* Last segment matched but different length */ + + return 1; /* The part of LFN matched */ +} + + +#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT +/*-----------------------------------------------------*/ +/* FAT-LFN: Pick a part of file name from an LFN entry */ +/*-----------------------------------------------------*/ + +static int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */ + WCHAR* lfnbuf, /* Pointer to the LFN working buffer */ + BYTE* dir /* Pointer to the LFN entry */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO is 0 */ + + i = ((dir[LDIR_Ord] & ~LLEF) - 1) * 13; /* Offset in the LFN buffer */ + + for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */ + uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */ + if (wc != 0) { + if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */ + lfnbuf[i++] = wc = uc; /* Store it */ + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } + + if (dir[LDIR_Ord] & LLEF && wc != 0) { /* Put terminator if it is the last LFN part and not terminated */ + if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */ + lfnbuf[i] = 0; + } + + return 1; /* The part of LFN is valid */ +} +#endif + + +#if !FF_FS_READONLY +/*-----------------------------------------*/ +/* FAT-LFN: Create an entry of LFN entries */ +/*-----------------------------------------*/ + +static void put_lfn ( + const WCHAR* lfn, /* Pointer to the LFN */ + BYTE* dir, /* Pointer to the LFN entry to be created */ + BYTE ord, /* LFN order (1-20) */ + BYTE sum /* Checksum of the corresponding SFN */ +) +{ + UINT i, s; + WCHAR wc; + + + dir[LDIR_Chksum] = sum; /* Set checksum */ + dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ + dir[LDIR_Type] = 0; + st_word(dir + LDIR_FstClusLO, 0); + + i = (ord - 1) * 13; /* Get offset in the LFN working buffer */ + s = wc = 0; + do { + if (wc != 0xFFFF) wc = lfn[i++]; /* Get an effective character */ + st_word(dir + LfnOfs[s], wc); /* Put it */ + if (wc == 0) wc = 0xFFFF; /* Padding characters for following items */ + } while (++s < 13); + if (wc == 0xFFFF || !lfn[i]) ord |= LLEF; /* Last LFN part is the start of LFN sequence */ + dir[LDIR_Ord] = ord; /* Set the LFN order */ +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_USE_LFN */ + + + +#if FF_USE_LFN && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* FAT-LFN: Create a Numbered SFN */ +/*-----------------------------------------------------------------------*/ + +static void gen_numname ( + BYTE* dst, /* Pointer to the buffer to store numbered SFN */ + const BYTE* src, /* Pointer to SFN in directory form */ + const WCHAR* lfn, /* Pointer to LFN */ + UINT seq /* Sequence number */ +) +{ + BYTE ns[8], c; + UINT i, j; + WCHAR wc; + DWORD sreg; + + + memcpy(dst, src, 11); /* Prepare the SFN to be modified */ + + if (seq > 5) { /* In case of many collisions, generate a hash number instead of sequential number */ + sreg = seq; + while (*lfn) { /* Create a CRC as hash value */ + wc = *lfn++; + for (i = 0; i < 16; i++) { + sreg = (sreg << 1) + (wc & 1); + wc >>= 1; + if (sreg & 0x10000) sreg ^= 0x11021; + } + } + seq = (UINT)sreg; + } + + /* Make suffix (~ + hexdecimal) */ + i = 7; + do { + c = (BYTE)((seq % 16) + '0'); seq /= 16; + if (c > '9') c += 7; + ns[i--] = c; + } while (i && seq); + ns[i] = '~'; + + /* Append the suffix to the SFN body */ + for (j = 0; j < i && dst[j] != ' '; j++) { /* Find the offset to append */ + if (dbc_1st(dst[j])) { /* To avoid DBC break up */ + if (j == i - 1) break; + j++; + } + } + do { /* Append the suffix */ + dst[j++] = (i < 8) ? ns[i++] : ' '; + } while (j < 8); +} +#endif /* FF_USE_LFN && !FF_FS_READONLY */ + + + +#if FF_USE_LFN +/*-----------------------------------------------------------------------*/ +/* FAT-LFN: Calculate checksum of an SFN entry */ +/*-----------------------------------------------------------------------*/ + +static BYTE sum_sfn ( + const BYTE* dir /* Pointer to the SFN entry */ +) +{ + BYTE sum = 0; + UINT n = 11; + + do { + sum = (sum >> 1) + (sum << 7) + *dir++; + } while (--n); + return sum; +} + +#endif /* FF_USE_LFN */ + + + +#if FF_FS_EXFAT +/*-----------------------------------------------------------------------*/ +/* exFAT: Checksum */ +/*-----------------------------------------------------------------------*/ + +static WORD xdir_sum ( /* Get checksum of the directoly entry block */ + const BYTE* dir /* Directory entry block to be calculated */ +) +{ + UINT i, szblk; + WORD sum; + + + szblk = (dir[XDIR_NumSec] + 1) * SZDIRE; /* Number of bytes of the entry block */ + for (i = sum = 0; i < szblk; i++) { + if (i == XDIR_SetSum) { /* Skip 2-byte sum field */ + i++; + } else { + sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + dir[i]; + } + } + return sum; +} + + + +static WORD xname_sum ( /* Get check sum (to be used as hash) of the file name */ + const WCHAR* name /* File name to be calculated */ +) +{ + WCHAR chr; + WORD sum = 0; + + + while ((chr = *name++) != 0) { + chr = (WCHAR)ff_wtoupper(chr); /* File name needs to be up-case converted */ + sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr & 0xFF); + sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr >> 8); + } + return sum; +} + + +#if !FF_FS_READONLY && FF_USE_MKFS +static DWORD xsum32 ( /* Returns 32-bit checksum */ + BYTE dat, /* Byte to be calculated (byte-by-byte processing) */ + DWORD sum /* Previous sum value */ +) +{ + sum = ((sum & 1) ? 0x80000000 : 0) + (sum >> 1) + dat; + return sum; +} +#endif + + + +/*-----------------------------------*/ +/* exFAT: Get a directry entry block */ +/*-----------------------------------*/ + +static FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */ + DIR* dp /* Reading direcotry object pointing top of the entry block to load */ +) +{ + FRESULT res; + UINT i, sz_ent; + BYTE *dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */ + + + /* Load file directory entry */ + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) return res; + if (dp->dir[XDIR_Type] != ET_FILEDIR) return FR_INT_ERR; /* Invalid order */ + memcpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE); + sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE; + if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR; + + /* Load stream extension entry */ + res = dir_next(dp, 0); + if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */ + if (res != FR_OK) return res; + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) return res; + if (dp->dir[XDIR_Type] != ET_STREAM) return FR_INT_ERR; /* Invalid order */ + memcpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE); + if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR; + + /* Load file name entries */ + i = 2 * SZDIRE; /* Name offset to load */ + do { + res = dir_next(dp, 0); + if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */ + if (res != FR_OK) return res; + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) return res; + if (dp->dir[XDIR_Type] != ET_FILENAME) return FR_INT_ERR; /* Invalid order */ + if (i < MAXDIRB(FF_MAX_LFN)) memcpy(dirb + i, dp->dir, SZDIRE); + } while ((i += SZDIRE) < sz_ent); + + /* Sanity check (do it for only accessible object) */ + if (i <= MAXDIRB(FF_MAX_LFN)) { + if (xdir_sum(dirb) != ld_word(dirb + XDIR_SetSum)) return FR_INT_ERR; + } + return FR_OK; +} + + +/*------------------------------------------------------------------*/ +/* exFAT: Initialize object allocation info with loaded entry block */ +/*------------------------------------------------------------------*/ + +static void init_alloc_info ( + FATFS* fs, /* Filesystem object */ + FFOBJID* obj /* Object allocation information to be initialized */ +) +{ + obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus); /* Start cluster */ + obj->objsize = ld_qword(fs->dirbuf + XDIR_FileSize); /* Size */ + obj->stat = fs->dirbuf[XDIR_GenFlags] & 2; /* Allocation status */ + obj->n_frag = 0; /* No last fragment info */ +} + + + +#if !FF_FS_READONLY || FF_FS_RPATH != 0 +/*------------------------------------------------*/ +/* exFAT: Load the object's directory entry block */ +/*------------------------------------------------*/ + +static FRESULT load_obj_xdir ( + DIR* dp, /* Blank directory object to be used to access containing direcotry */ + const FFOBJID* obj /* Object with its containing directory information */ +) +{ + FRESULT res; + + /* Open object containing directory */ + dp->obj.fs = obj->fs; + dp->obj.sclust = obj->c_scl; + dp->obj.stat = (BYTE)obj->c_size; + dp->obj.objsize = obj->c_size & 0xFFFFFF00; + dp->obj.n_frag = 0; + dp->blk_ofs = obj->c_ofs; + + res = dir_sdi(dp, dp->blk_ofs); /* Goto object's entry block */ + if (res == FR_OK) { + res = load_xdir(dp); /* Load the object's entry block */ + } + return res; +} +#endif + + +#if !FF_FS_READONLY +/*----------------------------------------*/ +/* exFAT: Store the directory entry block */ +/*----------------------------------------*/ + +static FRESULT store_xdir ( + DIR* dp /* Pointer to the direcotry object */ +) +{ + FRESULT res; + UINT nent; + BYTE *dirb = dp->obj.fs->dirbuf; /* Pointer to the direcotry entry block 85+C0+C1s */ + + /* Create set sum */ + st_word(dirb + XDIR_SetSum, xdir_sum(dirb)); + nent = dirb[XDIR_NumSec] + 1; + + /* Store the direcotry entry block to the directory */ + res = dir_sdi(dp, dp->blk_ofs); + while (res == FR_OK) { + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) break; + memcpy(dp->dir, dirb, SZDIRE); + dp->obj.fs->wflag = 1; + if (--nent == 0) break; + dirb += SZDIRE; + res = dir_next(dp, 0); + } + return (res == FR_OK || res == FR_DISK_ERR) ? res : FR_INT_ERR; +} + + + +/*-------------------------------------------*/ +/* exFAT: Create a new directory enrty block */ +/*-------------------------------------------*/ + +static void create_xdir ( + BYTE* dirb, /* Pointer to the direcotry entry block buffer */ + const WCHAR* lfn /* Pointer to the object name */ +) +{ + UINT i; + BYTE nc1, nlen; + WCHAR wc; + + + /* Create file-directory and stream-extension entry */ + memset(dirb, 0, 2 * SZDIRE); + dirb[0 * SZDIRE + XDIR_Type] = ET_FILEDIR; + dirb[1 * SZDIRE + XDIR_Type] = ET_STREAM; + + /* Create file-name entries */ + i = SZDIRE * 2; /* Top of file_name entries */ + nlen = nc1 = 0; wc = 1; + do { + dirb[i++] = ET_FILENAME; dirb[i++] = 0; + do { /* Fill name field */ + if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++; /* Get a character if exist */ + st_word(dirb + i, wc); /* Store it */ + i += 2; + } while (i % SZDIRE != 0); + nc1++; + } while (lfn[nlen]); /* Fill next entry if any char follows */ + + dirb[XDIR_NumName] = nlen; /* Set name length */ + dirb[XDIR_NumSec] = 1 + nc1; /* Set secondary count (C0 + C1s) */ + st_word(dirb + XDIR_NameHash, xname_sum(lfn)); /* Set name hash */ +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_FS_EXFAT */ + + + +#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT +/*-----------------------------------------------------------------------*/ +/* Read an object from the directory */ +/*-----------------------------------------------------------------------*/ + +#define DIR_READ_FILE(dp) dir_read(dp, 0) +#define DIR_READ_LABEL(dp) dir_read(dp, 1) + +static FRESULT dir_read ( + DIR* dp, /* Pointer to the directory object */ + int vol /* Filtered by 0:file/directory or 1:volume label */ +) +{ + FRESULT res = FR_NO_FILE; + FATFS *fs = dp->obj.fs; + BYTE attr, b; +#if FF_USE_LFN + BYTE ord = 0xFF, sum = 0xFF; +#endif + + while (dp->sect) { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + b = dp->dir[DIR_Name]; /* Test for the entry type */ + if (b == 0) { + res = FR_NO_FILE; break; /* Reached to end of the directory */ + } +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + if (FF_USE_LABEL && vol) { + if (b == ET_VLABEL) break; /* Volume label entry? */ + } else { + if (b == ET_FILEDIR) { /* Start of the file entry block? */ + dp->blk_ofs = dp->dptr; /* Get location of the block */ + res = load_xdir(dp); /* Load the entry block */ + if (res == FR_OK) { + dp->obj.attr = fs->dirbuf[XDIR_Attr] & AM_MASK; /* Get attribute */ + } + break; + } + } + } else +#endif + { /* On the FAT/FAT32 volume */ + dp->obj.attr = attr = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */ +#if FF_USE_LFN /* LFN configuration */ + if (b == DDEM || b == '.' || (int)((attr & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */ + ord = 0xFF; + } else { + if (attr == AM_LFN) { /* An LFN entry is found */ + if (b & LLEF) { /* Is it start of an LFN sequence? */ + sum = dp->dir[LDIR_Chksum]; + b &= (BYTE)~LLEF; ord = b; + dp->blk_ofs = dp->dptr; + } + /* Check LFN validity and capture it */ + ord = (b == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF; + } else { /* An SFN entry is found */ + if (ord != 0 || sum != sum_sfn(dp->dir)) { /* Is there a valid LFN? */ + dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */ + } + break; + } + } +#else /* Non LFN configuration */ + if (b != DDEM && b != '.' && attr != AM_LFN && (int)((attr & ~AM_ARC) == AM_VOL) == vol) { /* Is it a valid entry? */ + break; + } +#endif + } + res = dir_next(dp, 0); /* Next entry */ + if (res != FR_OK) break; + } + + if (res != FR_OK) dp->sect = 0; /* Terminate the read operation on error or EOT */ + return res; +} + +#endif /* FF_FS_MINIMIZE <= 1 || FF_USE_LABEL || FF_FS_RPATH >= 2 */ + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Find an object in the directory */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ + DIR* dp /* Pointer to the directory object with the file name */ +) +{ + FRESULT res; + FATFS *fs = dp->obj.fs; + BYTE c; +#if FF_USE_LFN + BYTE a, ord, sum; +#endif + + res = dir_sdi(dp, 0); /* Rewind directory object */ + if (res != FR_OK) return res; +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + BYTE nc; + UINT di, ni; + WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */ + + while ((res = DIR_READ_FILE(dp)) == FR_OK) { /* Read an item */ +#if FF_MAX_LFN < 255 + if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue; /* Skip comparison if inaccessible object name */ +#endif + if (ld_word(fs->dirbuf + XDIR_NameHash) != hash) continue; /* Skip comparison if hash mismatched */ + for (nc = fs->dirbuf[XDIR_NumName], di = SZDIRE * 2, ni = 0; nc; nc--, di += 2, ni++) { /* Compare the name */ + if ((di % SZDIRE) == 0) di += 2; + if (ff_wtoupper(ld_word(fs->dirbuf + di)) != ff_wtoupper(fs->lfnbuf[ni])) break; + } + if (nc == 0 && !fs->lfnbuf[ni]) break; /* Name matched? */ + } + return res; + } +#endif + /* On the FAT/FAT32 volume */ +#if FF_USE_LFN + ord = sum = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ +#endif + do { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + c = dp->dir[DIR_Name]; + if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ +#if FF_USE_LFN /* LFN configuration */ + dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; + if (c == DDEM || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ + ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ + } else { + if (a == AM_LFN) { /* An LFN entry is found */ + if (!(dp->fn[NSFLAG] & NS_NOLFN)) { + if (c & LLEF) { /* Is it start of LFN sequence? */ + sum = dp->dir[LDIR_Chksum]; + c &= (BYTE)~LLEF; ord = c; /* LFN start order */ + dp->blk_ofs = dp->dptr; /* Start offset of LFN */ + } + /* Check validity of the LFN entry and compare it with given name */ + ord = (c == ord && sum == dp->dir[LDIR_Chksum] && cmp_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF; + } + } else { /* An SFN entry is found */ + if (ord == 0 && sum == sum_sfn(dp->dir)) break; /* LFN matched? */ + if (!(dp->fn[NSFLAG] & NS_LOSS) && !memcmp(dp->dir, dp->fn, 11)) break; /* SFN matched? */ + ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ + } + } +#else /* Non LFN configuration */ + dp->obj.attr = dp->dir[DIR_Attr] & AM_MASK; + if (!(dp->dir[DIR_Attr] & AM_VOL) && !memcmp(dp->dir, dp->fn, 11)) break; /* Is it a valid entry? */ +#endif + res = dir_next(dp, 0); /* Next entry */ + } while (res == FR_OK); + + return res; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Register an object to the directory */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many SFN collision, FR_DISK_ERR:disk error */ + DIR* dp /* Target directory with object name to be created */ +) +{ + FRESULT res; + FATFS *fs = dp->obj.fs; +#if FF_USE_LFN /* LFN configuration */ + UINT n, len, n_ent; + BYTE sn[12], sum; + + + if (dp->fn[NSFLAG] & (NS_DOT | NS_NONAME)) return FR_INVALID_NAME; /* Check name validity */ + for (len = 0; fs->lfnbuf[len]; len++) ; /* Get lfn length */ + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + n_ent = (len + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */ + res = dir_alloc(dp, n_ent); /* Allocate directory entries */ + if (res != FR_OK) return res; + dp->blk_ofs = dp->dptr - SZDIRE * (n_ent - 1); /* Set the allocated entry block offset */ + + if (dp->obj.stat & 4) { /* Has the directory been stretched by new allocation? */ + dp->obj.stat &= ~4; + res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */ + if (res != FR_OK) return res; + res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */ + if (res != FR_OK) return res; + if (dp->obj.sclust != 0) { /* Is it a sub-directory? */ + DIR dj; + + res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */ + if (res != FR_OK) return res; + dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */ + st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); + st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize); + fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1; /* Update the allocation status */ + res = store_xdir(&dj); /* Store the object status */ + if (res != FR_OK) return res; + } + } + + create_xdir(fs->dirbuf, fs->lfnbuf); /* Create on-memory directory block to be written later */ + return FR_OK; + } +#endif + /* On the FAT/FAT32 volume */ + memcpy(sn, dp->fn, 12); + if (sn[NSFLAG] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ + dp->fn[NSFLAG] = NS_NOLFN; /* Find only SFN */ + for (n = 1; n < 100; n++) { + gen_numname(dp->fn, sn, fs->lfnbuf, n); /* Generate a numbered name */ + res = dir_find(dp); /* Check if the name collides with existing SFN */ + if (res != FR_OK) break; + } + if (n == 100) return FR_DENIED; /* Abort if too many collisions */ + if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ + dp->fn[NSFLAG] = sn[NSFLAG]; + } + + /* Create an SFN with/without LFNs. */ + n_ent = (sn[NSFLAG] & NS_LFN) ? (len + 12) / 13 + 1 : 1; /* Number of entries to allocate */ + res = dir_alloc(dp, n_ent); /* Allocate entries */ + if (res == FR_OK && --n_ent) { /* Set LFN entry if needed */ + res = dir_sdi(dp, dp->dptr - n_ent * SZDIRE); + if (res == FR_OK) { + sum = sum_sfn(dp->fn); /* Checksum value of the SFN tied to the LFN */ + do { /* Store LFN entries in bottom first */ + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + put_lfn(fs->lfnbuf, dp->dir, (BYTE)n_ent, sum); + fs->wflag = 1; + res = dir_next(dp, 0); /* Next entry */ + } while (res == FR_OK && --n_ent); + } + } + +#else /* Non LFN configuration */ + res = dir_alloc(dp, 1); /* Allocate an entry for SFN */ + +#endif + + /* Set SFN entry */ + if (res == FR_OK) { + res = move_window(fs, dp->sect); + if (res == FR_OK) { + memset(dp->dir, 0, SZDIRE); /* Clean the entry */ + memcpy(dp->dir + DIR_Name, dp->fn, 11); /* Put SFN */ +#if FF_USE_LFN + dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT); /* Put NT flag */ +#endif + fs->wflag = 1; + } + } + + return res; +} + +#endif /* !FF_FS_READONLY */ + + + +#if !FF_FS_READONLY && FF_FS_MINIMIZE == 0 +/*-----------------------------------------------------------------------*/ +/* Remove an object from the directory */ +/*-----------------------------------------------------------------------*/ + +static FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */ + DIR* dp /* Directory object pointing the entry to be removed */ +) +{ + FRESULT res; + FATFS *fs = dp->obj.fs; +#if FF_USE_LFN /* LFN configuration */ + DWORD last = dp->dptr; + + res = (dp->blk_ofs == 0xFFFFFFFF) ? FR_OK : dir_sdi(dp, dp->blk_ofs); /* Goto top of the entry block if LFN is exist */ + if (res == FR_OK) { + do { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + dp->dir[XDIR_Type] &= 0x7F; /* Clear the entry InUse flag. */ + } else { /* On the FAT/FAT32 volume */ + dp->dir[DIR_Name] = DDEM; /* Mark the entry 'deleted'. */ + } + fs->wflag = 1; + if (dp->dptr >= last) break; /* If reached last entry then all entries of the object has been deleted. */ + res = dir_next(dp, 0); /* Next entry */ + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR; + } +#else /* Non LFN configuration */ + + res = move_window(fs, dp->sect); + if (res == FR_OK) { + dp->dir[DIR_Name] = DDEM; /* Mark the entry 'deleted'.*/ + fs->wflag = 1; + } +#endif + + return res; +} + +#endif /* !FF_FS_READONLY && FF_FS_MINIMIZE == 0 */ + + + +#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 +/*-----------------------------------------------------------------------*/ +/* Get file information from directory entry */ +/*-----------------------------------------------------------------------*/ + +static void get_fileinfo ( + DIR* dp, /* Pointer to the directory object */ + FILINFO* fno /* Pointer to the file information to be filled */ +) +{ + UINT si, di; +#if FF_USE_LFN + BYTE lcf; + WCHAR wc, hs; + FATFS *fs = dp->obj.fs; + UINT nw; +#else + TCHAR c; +#endif + + + fno->fname[0] = 0; /* Invaidate file info */ + if (dp->sect == 0) return; /* Exit if read pointer has reached end of directory */ + +#if FF_USE_LFN /* LFN configuration */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* exFAT volume */ + UINT nc = 0; + + si = SZDIRE * 2; di = 0; /* 1st C1 entry in the entry block */ + hs = 0; + while (nc < fs->dirbuf[XDIR_NumName]) { + if (si >= MAXDIRB(FF_MAX_LFN)) { di = 0; break; } /* Truncated directory block? */ + if ((si % SZDIRE) == 0) si += 2; /* Skip entry type field */ + wc = ld_word(fs->dirbuf + si); si += 2; nc++; /* Get a character */ + if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */ + hs = wc; continue; /* Get low surrogate */ + } + nw = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in API encoding */ + if (nw == 0) { di = 0; break; } /* Buffer overflow or wrong char? */ + di += nw; + hs = 0; + } + if (hs != 0) di = 0; /* Broken surrogate pair? */ + if (di == 0) fno->fname[di++] = '?'; /* Inaccessible object name? */ + fno->fname[di] = 0; /* Terminate the name */ + fno->altname[0] = 0; /* exFAT does not support SFN */ + + fno->fattrib = fs->dirbuf[XDIR_Attr] & AM_MASKX; /* Attribute */ + fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(fs->dirbuf + XDIR_FileSize); /* Size */ + fno->ftime = ld_word(fs->dirbuf + XDIR_ModTime + 0); /* Time */ + fno->fdate = ld_word(fs->dirbuf + XDIR_ModTime + 2); /* Date */ + return; + } else +#endif + { /* FAT/FAT32 volume */ + if (dp->blk_ofs != 0xFFFFFFFF) { /* Get LFN if available */ + si = di = 0; + hs = 0; + while (fs->lfnbuf[si] != 0) { + wc = fs->lfnbuf[si++]; /* Get an LFN character (UTF-16) */ + if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */ + hs = wc; continue; /* Get low surrogate */ + } + nw = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in API encoding */ + if (nw == 0) { di = 0; break; } /* Buffer overflow or wrong char? */ + di += nw; + hs = 0; + } + if (hs != 0) di = 0; /* Broken surrogate pair? */ + fno->fname[di] = 0; /* Terminate the LFN (null string means LFN is invalid) */ + } + } + + si = di = 0; + while (si < 11) { /* Get SFN from SFN entry */ + wc = dp->dir[si++]; /* Get a char */ + if (wc == ' ') continue; /* Skip padding spaces */ + if (wc == RDDEM) wc = DDEM; /* Restore replaced DDEM character */ + if (si == 9 && di < FF_SFN_BUF) fno->altname[di++] = '.'; /* Insert a . if extension is exist */ +#if FF_LFN_UNICODE >= 1 /* Unicode output */ + if (dbc_1st((BYTE)wc) && si != 8 && si != 11 && dbc_2nd(dp->dir[si])) { /* Make a DBC if needed */ + wc = wc << 8 | dp->dir[si++]; + } + wc = ff_oem2uni(wc, CODEPAGE); /* ANSI/OEM -> Unicode */ + if (wc == 0) { di = 0; break; } /* Wrong char in the current code page? */ + nw = put_utf(wc, &fno->altname[di], FF_SFN_BUF - di); /* Store it in API encoding */ + if (nw == 0) { di = 0; break; } /* Buffer overflow? */ + di += nw; +#else /* ANSI/OEM output */ + fno->altname[di++] = (TCHAR)wc; /* Store it without any conversion */ +#endif + } + fno->altname[di] = 0; /* Terminate the SFN (null string means SFN is invalid) */ + + if (fno->fname[0] == 0) { /* If LFN is invalid, altname[] needs to be copied to fname[] */ + if (di == 0) { /* If LFN and SFN both are invalid, this object is inaccesible */ + fno->fname[di++] = '?'; + } else { + for (si = di = 0, lcf = NS_BODY; fno->altname[si]; si++, di++) { /* Copy altname[] to fname[] with case information */ + wc = (WCHAR)fno->altname[si]; + if (wc == '.') lcf = NS_EXT; + if (IsUpper(wc) && (dp->dir[DIR_NTres] & lcf)) wc += 0x20; + fno->fname[di] = (TCHAR)wc; + } + } + fno->fname[di] = 0; /* Terminate the LFN */ + if (!dp->dir[DIR_NTres]) fno->altname[0] = 0; /* Altname is not needed if neither LFN nor case info is exist. */ + } + +#else /* Non-LFN configuration */ + si = di = 0; + while (si < 11) { /* Copy name body and extension */ + c = (TCHAR)dp->dir[si++]; + if (c == ' ') continue; /* Skip padding spaces */ + if (c == RDDEM) c = DDEM; /* Restore replaced DDEM character */ + if (si == 9) fno->fname[di++] = '.';/* Insert a . if extension is exist */ + fno->fname[di++] = c; + } + fno->fname[di] = 0; /* Terminate the SFN */ +#endif + + fno->fattrib = dp->dir[DIR_Attr] & AM_MASK; /* Attribute */ + fno->fsize = ld_dword(dp->dir + DIR_FileSize); /* Size */ + fno->ftime = ld_word(dp->dir + DIR_ModTime + 0); /* Time */ + fno->fdate = ld_word(dp->dir + DIR_ModTime + 2); /* Date */ +} + +#endif /* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */ + + + +#if FF_USE_FIND && FF_FS_MINIMIZE <= 1 +/*-----------------------------------------------------------------------*/ +/* Pattern matching */ +/*-----------------------------------------------------------------------*/ + +#define FIND_RECURS 4 /* Maximum number of wildcard terms in the pattern to limit recursion */ + + +static DWORD get_achar ( /* Get a character and advance ptr */ + const TCHAR** ptr /* Pointer to pointer to the ANSI/OEM or Unicode string */ +) +{ + DWORD chr; + + +#if FF_USE_LFN && FF_LFN_UNICODE >= 1 /* Unicode input */ + chr = tchar2uni(ptr); + if (chr == 0xFFFFFFFF) chr = 0; /* Wrong UTF encoding is recognized as end of the string */ + chr = ff_wtoupper(chr); + +#else /* ANSI/OEM input */ + chr = (BYTE)*(*ptr)++; /* Get a byte */ + if (IsLower(chr)) chr -= 0x20; /* To upper ASCII char */ +#if FF_CODE_PAGE == 0 + if (ExCvt && chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */ +#elif FF_CODE_PAGE < 900 + if (chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */ +#endif +#if FF_CODE_PAGE == 0 || FF_CODE_PAGE >= 900 + if (dbc_1st((BYTE)chr)) { /* Get DBC 2nd byte if needed */ + chr = dbc_2nd((BYTE)**ptr) ? chr << 8 | (BYTE)*(*ptr)++ : 0; + } +#endif + +#endif + return chr; +} + + +static int pattern_match ( /* 0:mismatched, 1:matched */ + const TCHAR* pat, /* Matching pattern */ + const TCHAR* nam, /* String to be tested */ + UINT skip, /* Number of pre-skip chars (number of ?s, b8:infinite (* specified)) */ + UINT recur /* Recursion count */ +) +{ + const TCHAR *pptr, *nptr; + DWORD pchr, nchr; + UINT sk; + + + while ((skip & 0xFF) != 0) { /* Pre-skip name chars */ + if (!get_achar(&nam)) return 0; /* Branch mismatched if less name chars */ + skip--; + } + if (*pat == 0 && skip) return 1; /* Matched? (short circuit) */ + + do { + pptr = pat; nptr = nam; /* Top of pattern and name to match */ + for (;;) { + if (*pptr == '?' || *pptr == '*') { /* Wildcard term? */ + if (recur == 0) return 0; /* Too many wildcard terms? */ + sk = 0; + do { /* Analyze the wildcard term */ + if (*pptr++ == '?') sk++; else sk |= 0x100; + } while (*pptr == '?' || *pptr == '*'); + if (pattern_match(pptr, nptr, sk, recur - 1)) return 1; /* Test new branch (recursive call) */ + nchr = *nptr; break; /* Branch mismatched */ + } + pchr = get_achar(&pptr); /* Get a pattern char */ + nchr = get_achar(&nptr); /* Get a name char */ + if (pchr != nchr) break; /* Branch mismatched? */ + if (pchr == 0) return 1; /* Branch matched? (matched at end of both strings) */ + } + get_achar(&nam); /* nam++ */ + } while (skip && nchr); /* Retry until end of name if infinite search is specified */ + + return 0; +} + +#endif /* FF_USE_FIND && FF_FS_MINIMIZE <= 1 */ + + + +/*-----------------------------------------------------------------------*/ +/* Pick a top segment and create the object name in directory form */ +/*-----------------------------------------------------------------------*/ + +static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */ + DIR* dp, /* Pointer to the directory object */ + const TCHAR** path /* Pointer to pointer to the segment in the path string */ +) +{ +#if FF_USE_LFN /* LFN configuration */ + BYTE b, cf; + WCHAR wc, *lfn; + DWORD uc; + UINT i, ni, si, di; + const TCHAR *p; + + + /* Create LFN into LFN working buffer */ + p = *path; lfn = dp->obj.fs->lfnbuf; di = 0; + for (;;) { + uc = tchar2uni(&p); /* Get a character */ + if (uc == 0xFFFFFFFF) return FR_INVALID_NAME; /* Invalid code or UTF decode error */ + if (uc >= 0x10000) lfn[di++] = (WCHAR)(uc >> 16); /* Store high surrogate if needed */ + wc = (WCHAR)uc; + if (wc < ' ' || IsSeparator(wc)) break; /* Break if end of the path or a separator is found */ + if (wc < 0x80 && strchr("*:<>|\"\?\x7F", (int)wc)) return FR_INVALID_NAME; /* Reject illegal characters for LFN */ + if (di >= FF_MAX_LFN) return FR_INVALID_NAME; /* Reject too long name */ + lfn[di++] = wc; /* Store the Unicode character */ + } + if (wc < ' ') { /* Stopped at end of the path? */ + cf = NS_LAST; /* Last segment */ + } else { /* Stopped at a separator */ + while (IsSeparator(*p)) p++; /* Skip duplicated separators if exist */ + cf = 0; /* Next segment may follow */ + if (IsTerminator(*p)) cf = NS_LAST; /* Ignore terminating separator */ + } + *path = p; /* Return pointer to the next segment */ + +#if FF_FS_RPATH != 0 + if ((di == 1 && lfn[di - 1] == '.') || + (di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) { /* Is this segment a dot name? */ + lfn[di] = 0; + for (i = 0; i < 11; i++) { /* Create dot name for SFN entry */ + dp->fn[i] = (i < di) ? '.' : ' '; + } + dp->fn[i] = cf | NS_DOT; /* This is a dot entry */ + return FR_OK; + } +#endif + while (di) { /* Snip off trailing spaces and dots if exist */ + wc = lfn[di - 1]; + if (wc != ' ' && wc != '.') break; + di--; + } + lfn[di] = 0; /* LFN is created into the working buffer */ + if (di == 0) return FR_INVALID_NAME; /* Reject null name */ + + /* Create SFN in directory form */ + for (si = 0; lfn[si] == ' '; si++) ; /* Remove leading spaces */ + if (si > 0 || lfn[si] == '.') cf |= NS_LOSS | NS_LFN; /* Is there any leading space or dot? */ + while (di > 0 && lfn[di - 1] != '.') di--; /* Find last dot (di<=si: no extension) */ + + memset(dp->fn, ' ', 11); + i = b = 0; ni = 8; + for (;;) { + wc = lfn[si++]; /* Get an LFN character */ + if (wc == 0) break; /* Break on end of the LFN */ + if (wc == ' ' || (wc == '.' && si != di)) { /* Remove embedded spaces and dots */ + cf |= NS_LOSS | NS_LFN; + continue; + } + + if (i >= ni || si == di) { /* End of field? */ + if (ni == 11) { /* Name extension overflow? */ + cf |= NS_LOSS | NS_LFN; + break; + } + if (si != di) cf |= NS_LOSS | NS_LFN; /* Name body overflow? */ + if (si > di) break; /* No name extension? */ + si = di; i = 8; ni = 11; b <<= 2; /* Enter name extension */ + continue; + } + + if (wc >= 0x80) { /* Is this an extended character? */ + cf |= NS_LFN; /* LFN entry needs to be created */ +#if FF_CODE_PAGE == 0 + if (ExCvt) { /* In SBCS cfg */ + wc = ff_uni2oem(wc, CODEPAGE); /* Unicode ==> ANSI/OEM code */ + if (wc & 0x80) wc = ExCvt[wc & 0x7F]; /* Convert extended character to upper (SBCS) */ + } else { /* In DBCS cfg */ + wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE); /* Unicode ==> Up-convert ==> ANSI/OEM code */ + } +#elif FF_CODE_PAGE < 900 /* In SBCS cfg */ + wc = ff_uni2oem(wc, CODEPAGE); /* Unicode ==> ANSI/OEM code */ + if (wc & 0x80) wc = ExCvt[wc & 0x7F]; /* Convert extended character to upper (SBCS) */ +#else /* In DBCS cfg */ + wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE); /* Unicode ==> Up-convert ==> ANSI/OEM code */ +#endif + } + + if (wc >= 0x100) { /* Is this a DBC? */ + if (i >= ni - 1) { /* Field overflow? */ + cf |= NS_LOSS | NS_LFN; + i = ni; continue; /* Next field */ + } + dp->fn[i++] = (BYTE)(wc >> 8); /* Put 1st byte */ + } else { /* SBC */ + if (wc == 0 || strchr("+,;=[]", (int)wc)) { /* Replace illegal characters for SFN */ + wc = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ + } else { + if (IsUpper(wc)) { /* ASCII upper case? */ + b |= 2; + } + if (IsLower(wc)) { /* ASCII lower case? */ + b |= 1; wc -= 0x20; + } + } + } + dp->fn[i++] = (BYTE)wc; + } + + if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */ + + if (ni == 8) b <<= 2; /* Shift capital flags if no extension */ + if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) cf |= NS_LFN; /* LFN entry needs to be created if composite capitals */ + if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended character, NT flags are created */ + if (b & 0x01) cf |= NS_EXT; /* NT flag (Extension has small capital letters only) */ + if (b & 0x04) cf |= NS_BODY; /* NT flag (Body has small capital letters only) */ + } + + dp->fn[NSFLAG] = cf; /* SFN is created into dp->fn[] */ + + return FR_OK; + + +#else /* FF_USE_LFN : Non-LFN configuration */ + BYTE c, d, *sfn; + UINT ni, si, i; + const char *p; + + /* Create file name in directory form */ + p = *path; sfn = dp->fn; + memset(sfn, ' ', 11); + si = i = 0; ni = 8; +#if FF_FS_RPATH != 0 + if (p[si] == '.') { /* Is this a dot entry? */ + for (;;) { + c = (BYTE)p[si++]; + if (c != '.' || si >= 3) break; + sfn[i++] = c; + } + if (!IsSeparator(c) && c > ' ') return FR_INVALID_NAME; + *path = p + si; /* Return pointer to the next segment */ + sfn[NSFLAG] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of the path */ + return FR_OK; + } +#endif + for (;;) { + c = (BYTE)p[si++]; /* Get a byte */ + if (c <= ' ') break; /* Break if end of the path name */ + if (IsSeparator(c)) { /* Break if a separator is found */ + while (IsSeparator(p[si])) si++; /* Skip duplicated separator if exist */ + break; + } + if (c == '.' || i >= ni) { /* End of body or field overflow? */ + if (ni == 11 || c != '.') return FR_INVALID_NAME; /* Field overflow or invalid dot? */ + i = 8; ni = 11; /* Enter file extension field */ + continue; + } +#if FF_CODE_PAGE == 0 + if (ExCvt && c >= 0x80) { /* Is SBC extended character? */ + c = ExCvt[c & 0x7F]; /* To upper SBC extended character */ + } +#elif FF_CODE_PAGE < 900 + if (c >= 0x80) { /* Is SBC extended character? */ + c = ExCvt[c & 0x7F]; /* To upper SBC extended character */ + } +#endif + if (dbc_1st(c)) { /* Check if it is a DBC 1st byte */ + d = (BYTE)p[si++]; /* Get 2nd byte */ + if (!dbc_2nd(d) || i >= ni - 1) return FR_INVALID_NAME; /* Reject invalid DBC */ + sfn[i++] = c; + sfn[i++] = d; + } else { /* SBC */ + if (strchr("*+,:;<=>[]|\"\?\x7F", (int)c)) return FR_INVALID_NAME; /* Reject illegal chrs for SFN */ + if (IsLower(c)) c -= 0x20; /* To upper */ + sfn[i++] = c; + } + } + *path = &p[si]; /* Return pointer to the next segment */ + if (i == 0) return FR_INVALID_NAME; /* Reject nul string */ + + if (sfn[0] == DDEM) sfn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */ + sfn[NSFLAG] = (c <= ' ' || p[si] <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */ + + return FR_OK; +#endif /* FF_USE_LFN */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Follow a file path */ +/*-----------------------------------------------------------------------*/ + +static FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ + DIR* dp, /* Directory object to return last directory and found object */ + const TCHAR* path /* Full-path string to find a file or directory */ +) +{ + FRESULT res; + BYTE ns; + FATFS *fs = dp->obj.fs; + + +#if FF_FS_RPATH != 0 + if (!IsSeparator(*path) && (FF_STR_VOLUME_ID != 2 || !IsTerminator(*path))) { /* Without heading separator */ + dp->obj.sclust = fs->cdir; /* Start at the current directory */ + } else +#endif + { /* With heading separator */ + while (IsSeparator(*path)) path++; /* Strip separators */ + dp->obj.sclust = 0; /* Start from the root directory */ + } +#if FF_FS_EXFAT + dp->obj.n_frag = 0; /* Invalidate last fragment counter of the object */ +#if FF_FS_RPATH != 0 + if (fs->fs_type == FS_EXFAT && dp->obj.sclust) { /* exFAT: Retrieve the sub-directory's status */ + DIR dj; + + dp->obj.c_scl = fs->cdc_scl; + dp->obj.c_size = fs->cdc_size; + dp->obj.c_ofs = fs->cdc_ofs; + res = load_obj_xdir(&dj, &dp->obj); + if (res != FR_OK) return res; + dp->obj.objsize = ld_dword(fs->dirbuf + XDIR_FileSize); + dp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2; + } +#endif +#endif + + if ((UINT)*path < ' ') { /* Null path name is the origin directory itself */ + dp->fn[NSFLAG] = NS_NONAME; + res = dir_sdi(dp, 0); + + } else { /* Follow path */ + for (;;) { + res = create_name(dp, &path); /* Get a segment name of the path */ + if (res != FR_OK) break; + res = dir_find(dp); /* Find an object with the segment name */ + ns = dp->fn[NSFLAG]; + if (res != FR_OK) { /* Failed to find the object */ + if (res == FR_NO_FILE) { /* Object is not found */ + if (FF_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exist, stay there */ + if (!(ns & NS_LAST)) continue; /* Continue to follow if not last segment */ + dp->fn[NSFLAG] = NS_NONAME; + res = FR_OK; + } else { /* Could not find the object */ + if (!(ns & NS_LAST)) res = FR_NO_PATH; /* Adjust error code if not last segment */ + } + } + break; + } + if (ns & NS_LAST) break; /* Last segment matched. Function completed. */ + /* Get into the sub-directory */ + if (!(dp->obj.attr & AM_DIR)) { /* It is not a sub-directory and cannot follow */ + res = FR_NO_PATH; break; + } +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* Save containing directory information for next dir */ + dp->obj.c_scl = dp->obj.sclust; + dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat; + dp->obj.c_ofs = dp->blk_ofs; + init_alloc_info(fs, &dp->obj); /* Open next directory */ + } else +#endif + { + dp->obj.sclust = ld_clust(fs, fs->win + dp->dptr % SS(fs)); /* Open next directory */ + } + } + } + + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Get logical drive number from path name */ +/*-----------------------------------------------------------------------*/ + +static int get_ldnumber ( /* Returns logical drive number (-1:invalid drive number or null pointer) */ + const TCHAR** path /* Pointer to pointer to the path name */ +) +{ + const TCHAR *tp, *tt; + TCHAR tc; + int i; + int vol = -1; +#if FF_STR_VOLUME_ID /* Find string volume ID */ + const char *sp; + char c; +#endif + + tt = tp = *path; + if (!tp) return vol; /* Invalid path name? */ + do tc = *tt++; while (!IsTerminator(tc) && tc != ':'); /* Find a colon in the path */ + + if (tc == ':') { /* DOS/Windows style volume ID? */ + i = FF_VOLUMES; + if (IsDigit(*tp) && tp + 2 == tt) { /* Is there a numeric volume ID + colon? */ + i = (int)*tp - '0'; /* Get the LD number */ + } +#if FF_STR_VOLUME_ID == 1 /* Arbitrary string is enabled */ + else { + i = 0; + do { + sp = VolumeStr[i]; tp = *path; /* This string volume ID and path name */ + do { /* Compare the volume ID with path name */ + c = *sp++; tc = *tp++; + if (IsLower(c)) c -= 0x20; + if (IsLower(tc)) tc -= 0x20; + } while (c && (TCHAR)c == tc); + } while ((c || tp != tt) && ++i < FF_VOLUMES); /* Repeat for each id until pattern match */ + } +#endif + if (i < FF_VOLUMES) { /* If a volume ID is found, get the drive number and strip it */ + vol = i; /* Drive number */ + *path = tt; /* Snip the drive prefix off */ + } + return vol; + } +#if FF_STR_VOLUME_ID == 2 /* Unix style volume ID is enabled */ + if (*tp == '/') { /* Is there a volume ID? */ + while (*(tp + 1) == '/') tp++; /* Skip duplicated separator */ + i = 0; + do { + tt = tp; sp = VolumeStr[i]; /* Path name and this string volume ID */ + do { /* Compare the volume ID with path name */ + c = *sp++; tc = *(++tt); + if (IsLower(c)) c -= 0x20; + if (IsLower(tc)) tc -= 0x20; + } while (c && (TCHAR)c == tc); + } while ((c || (tc != '/' && !IsTerminator(tc))) && ++i < FF_VOLUMES); /* Repeat for each ID until pattern match */ + if (i < FF_VOLUMES) { /* If a volume ID is found, get the drive number and strip it */ + vol = i; /* Drive number */ + *path = tt; /* Snip the drive prefix off */ + } + return vol; + } +#endif + /* No drive prefix is found */ +#if FF_FS_RPATH != 0 + vol = CurrVol; /* Default drive is current drive */ +#else + vol = 0; /* Default drive is 0 */ +#endif + return vol; /* Return the default drive */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* GPT support functions */ +/*-----------------------------------------------------------------------*/ + +#if FF_LBA64 + +/* Calculate CRC32 in byte-by-byte */ + +static DWORD crc32 ( /* Returns next CRC value */ + DWORD crc, /* Current CRC value */ + BYTE d /* A byte to be processed */ +) +{ + BYTE b; + + + for (b = 1; b; b <<= 1) { + crc ^= (d & b) ? 1 : 0; + crc = (crc & 1) ? crc >> 1 ^ 0xEDB88320 : crc >> 1; + } + return crc; +} + + +/* Check validity of GPT header */ + +static int test_gpt_header ( /* 0:Invalid, 1:Valid */ + const BYTE* gpth /* Pointer to the GPT header */ +) +{ + UINT i; + DWORD bcc; + + + if (memcmp(gpth + GPTH_Sign, "EFI PART" "\0\0\1\0" "\x5C\0\0", 16)) return 0; /* Check sign, version (1.0) and length (92) */ + for (i = 0, bcc = 0xFFFFFFFF; i < 92; i++) { /* Check header BCC */ + bcc = crc32(bcc, i - GPTH_Bcc < 4 ? 0 : gpth[i]); + } + if (~bcc != ld_dword(gpth + GPTH_Bcc)) return 0; + if (ld_dword(gpth + GPTH_PteSize) != SZ_GPTE) return 0; /* Table entry size (must be SZ_GPTE bytes) */ + if (ld_dword(gpth + GPTH_PtNum) > 128) return 0; /* Table size (must be 128 entries or less) */ + + return 1; +} + +#if !FF_FS_READONLY && FF_USE_MKFS + +/* Generate random value */ +static DWORD make_rand ( + DWORD seed, /* Seed value */ + BYTE* buff, /* Output buffer */ + UINT n /* Data length */ +) +{ + UINT r; + + + if (seed == 0) seed = 1; + do { + for (r = 0; r < 8; r++) seed = seed & 1 ? seed >> 1 ^ 0xA3000000 : seed >> 1; /* Shift 8 bits the 32-bit LFSR */ + *buff++ = (BYTE)seed; + } while (--n); + return seed; +} + +#endif +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Load a sector and check if it is an FAT VBR */ +/*-----------------------------------------------------------------------*/ + +/* Check what the sector is */ + +static UINT check_fs ( /* 0:FAT/FAT32 VBR, 1:exFAT VBR, 2:Not FAT and valid BS, 3:Not FAT and invalid BS, 4:Disk error */ + FATFS* fs, /* Filesystem object */ + LBA_t sect /* Sector to load and check if it is an FAT-VBR or not */ +) +{ + WORD w, sign; + BYTE b; + + + fs->wflag = 0; fs->winsect = (LBA_t)0 - 1; /* Invaidate window */ + if (move_window(fs, sect) != FR_OK) return 4; /* Load the boot sector */ + sign = ld_word(fs->win + BS_55AA); +#if FF_FS_EXFAT + if (sign == 0xAA55 && !memcmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1; /* It is an exFAT VBR */ +#endif + b = fs->win[BS_JmpBoot]; + if (b == 0xEB || b == 0xE9 || b == 0xE8) { /* Valid JumpBoot code? (short jump, near jump or near call) */ + if (sign == 0xAA55 && !memcmp(fs->win + BS_FilSysType32, "FAT32 ", 8)) { + return 0; /* It is an FAT32 VBR */ + } + /* FAT volumes formatted with early MS-DOS lack BS_55AA and BS_FilSysType, so FAT VBR needs to be identified without them. */ + w = ld_word(fs->win + BPB_BytsPerSec); + b = fs->win[BPB_SecPerClus]; + if ((w & (w - 1)) == 0 && w >= FF_MIN_SS && w <= FF_MAX_SS /* Properness of sector size (512-4096 and 2^n) */ + && b != 0 && (b & (b - 1)) == 0 /* Properness of cluster size (2^n) */ + && ld_word(fs->win + BPB_RsvdSecCnt) != 0 /* Properness of reserved sectors (MNBZ) */ + && (UINT)fs->win[BPB_NumFATs] - 1 <= 1 /* Properness of FATs (1 or 2) */ + && ld_word(fs->win + BPB_RootEntCnt) != 0 /* Properness of root dir entries (MNBZ) */ + && (ld_word(fs->win + BPB_TotSec16) >= 128 || ld_dword(fs->win + BPB_TotSec32) >= 0x10000) /* Properness of volume sectors (>=128) */ + && ld_word(fs->win + BPB_FATSz16) != 0) { /* Properness of FAT size (MNBZ) */ + return 0; /* It can be presumed an FAT VBR */ + } + } + return sign == 0xAA55 ? 2 : 3; /* Not an FAT VBR (valid or invalid BS) */ +} + + +/* Find an FAT volume */ +/* (It supports only generic partitioning rules, MBR, GPT and SFD) */ + +static UINT find_volume ( /* Returns BS status found in the hosting drive */ + FATFS* fs, /* Filesystem object */ + UINT part /* Partition to fined = 0:auto, 1..:forced */ +) +{ + UINT fmt, i; + DWORD mbr_pt[4]; + + + fmt = check_fs(fs, 0); /* Load sector 0 and check if it is an FAT VBR as SFD format */ + if (fmt != 2 && (fmt >= 3 || part == 0)) return fmt; /* Returns if it is an FAT VBR as auto scan, not a BS or disk error */ + + /* Sector 0 is not an FAT VBR or forced partition number wants a partition */ + +#if FF_LBA64 + if (fs->win[MBR_Table + PTE_System] == 0xEE) { /* GPT protective MBR? */ + DWORD n_ent, v_ent, ofs; + QWORD pt_lba; + + if (move_window(fs, 1) != FR_OK) return 4; /* Load GPT header sector (next to MBR) */ + if (!test_gpt_header(fs->win)) return 3; /* Check if GPT header is valid */ + n_ent = ld_dword(fs->win + GPTH_PtNum); /* Number of entries */ + pt_lba = ld_qword(fs->win + GPTH_PtOfs); /* Table location */ + for (v_ent = i = 0; i < n_ent; i++) { /* Find FAT partition */ + if (move_window(fs, pt_lba + i * SZ_GPTE / SS(fs)) != FR_OK) return 4; /* PT sector */ + ofs = i * SZ_GPTE % SS(fs); /* Offset in the sector */ + if (!memcmp(fs->win + ofs + GPTE_PtGuid, GUID_MS_Basic, 16)) { /* MS basic data partition? */ + v_ent++; + fmt = check_fs(fs, ld_qword(fs->win + ofs + GPTE_FstLba)); /* Load VBR and check status */ + if (part == 0 && fmt <= 1) return fmt; /* Auto search (valid FAT volume found first) */ + if (part != 0 && v_ent == part) return fmt; /* Forced partition order (regardless of it is valid or not) */ + } + } + return 3; /* Not found */ + } +#endif + if (FF_MULTI_PARTITION && part > 4) return 3; /* MBR has 4 partitions max */ + for (i = 0; i < 4; i++) { /* Load partition offset in the MBR */ + mbr_pt[i] = ld_dword(fs->win + MBR_Table + i * SZ_PTE + PTE_StLba); + } + i = part ? part - 1 : 0; /* Table index to find first */ + do { /* Find an FAT volume */ + fmt = mbr_pt[i] ? check_fs(fs, mbr_pt[i]) : 3; /* Check if the partition is FAT */ + } while (part == 0 && fmt >= 2 && ++i < 4); + return fmt; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Determine logical drive number and mount the volume if needed */ +/*-----------------------------------------------------------------------*/ + +static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ + const TCHAR** path, /* Pointer to pointer to the path name (drive number) */ + FATFS** rfs, /* Pointer to pointer to the found filesystem object */ + BYTE mode /* !=0: Check write protection for write access */ +) +{ + int vol; + DSTATUS stat; + LBA_t bsect; + DWORD tsect, sysect, fasize, nclst, szbfat; + WORD nrsv; + FATFS *fs; + UINT fmt; + + + /* Get logical drive number */ + *rfs = 0; + vol = get_ldnumber(path); + if (vol < 0) return FR_INVALID_DRIVE; + + /* Check if the filesystem object is valid or not */ + fs = FatFs[vol]; /* Get pointer to the filesystem object */ + if (!fs) return FR_NOT_ENABLED; /* Is the filesystem object available? */ +#if FF_FS_REENTRANT + if (!lock_fs(fs)) return FR_TIMEOUT; /* Lock the volume */ +#endif + *rfs = fs; /* Return pointer to the filesystem object */ + + mode &= (BYTE)~FA_READ; /* Desired access mode, write access or not */ + if (fs->fs_type != 0) { /* If the volume has been mounted */ + stat = disk_status(fs->pdrv); + if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ + if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */ + return FR_WRITE_PROTECTED; + } + return FR_OK; /* The filesystem object is already valid */ + } + } + + /* The filesystem object is not valid. */ + /* Following code attempts to mount the volume. (find an FAT volume, analyze the BPB and initialize the filesystem object) */ + + fs->fs_type = 0; /* Clear the filesystem object */ + fs->pdrv = LD2PD(vol); /* Volume hosting physical drive */ + stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */ + if (stat & STA_NOINIT) { /* Check if the initialization succeeded */ + return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ + } + if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */ + return FR_WRITE_PROTECTED; + } +#if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */ + if (disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR; + if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR; +#endif + + /* Find an FAT volume on the drive */ + fmt = find_volume(fs, LD2PT(vol)); + if (fmt == 4) return FR_DISK_ERR; /* An error occured in the disk I/O layer */ + if (fmt >= 2) return FR_NO_FILESYSTEM; /* No FAT volume is found */ + bsect = fs->winsect; /* Volume offset */ + + /* An FAT volume is found (bsect). Following code initializes the filesystem object */ + +#if FF_FS_EXFAT + if (fmt == 1) { + QWORD maxlba; + DWORD so, cv, bcl, i; + + for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */ + if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM; + + if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */ + + if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */ + return FR_NO_FILESYSTEM; + } + + maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA of the volume + 1 */ + if (!FF_LBA64 && maxlba >= 0x100000000) return FR_NO_FILESYSTEM; /* (It cannot be accessed in 32-bit LBA) */ + + fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */ + + fs->n_fats = fs->win[BPB_NumFATsEx]; /* Number of FATs */ + if (fs->n_fats != 1) return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */ + + fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */ + if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768 sectors) */ + + nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */ + if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM; /* (Too many clusters) */ + fs->n_fatent = nclst + 2; + + /* Boundaries and Limits */ + fs->volbase = bsect; + fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx); + fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx); + if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */ + fs->dirbase = ld_dword(fs->win + BPB_RootClusEx); + + /* Get bitmap location and check if it is contiguous (implementation assumption) */ + so = i = 0; + for (;;) { /* Find the bitmap entry in the root directory (in only first cluster) */ + if (i == 0) { + if (so >= fs->csize) return FR_NO_FILESYSTEM; /* Not found? */ + if (move_window(fs, clst2sect(fs, (DWORD)fs->dirbase) + so) != FR_OK) return FR_DISK_ERR; + so++; + } + if (fs->win[i] == ET_BITMAP) break; /* Is it a bitmap entry? */ + i = (i + SZDIRE) % SS(fs); /* Next entry */ + } + bcl = ld_dword(fs->win + i + 20); /* Bitmap cluster */ + if (bcl < 2 || bcl >= fs->n_fatent) return FR_NO_FILESYSTEM; /* (Wrong cluster#) */ + fs->bitbase = fs->database + fs->csize * (bcl - 2); /* Bitmap sector */ + for (;;) { /* Check if bitmap is contiguous */ + if (move_window(fs, fs->fatbase + bcl / (SS(fs) / 4)) != FR_OK) return FR_DISK_ERR; + cv = ld_dword(fs->win + bcl % (SS(fs) / 4) * 4); + if (cv == 0xFFFFFFFF) break; /* Last link? */ + if (cv != ++bcl) return FR_NO_FILESYSTEM; /* Fragmented? */ + } + +#if !FF_FS_READONLY + fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */ +#endif + fmt = FS_EXFAT; /* FAT sub-type */ + } else +#endif /* FF_FS_EXFAT */ + { + if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */ + + fasize = ld_word(fs->win + BPB_FATSz16); /* Number of sectors per FAT */ + if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32); + fs->fsize = fasize; + + fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */ + if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ + fasize *= fs->n_fats; /* Number of sectors for FAT area */ + + fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */ + if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ + + fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */ + if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM; /* (Must be sector aligned) */ + + tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */ + if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32); + + nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */ + if (nrsv == 0) return FR_NO_FILESYSTEM; /* (Must not be 0) */ + + /* Determine the FAT sub type */ + sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + DIR */ + if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ + if (nclst == 0) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + fmt = 0; + if (nclst <= MAX_FAT32) fmt = FS_FAT32; + if (nclst <= MAX_FAT16) fmt = FS_FAT16; + if (nclst <= MAX_FAT12) fmt = FS_FAT12; + if (fmt == 0) return FR_NO_FILESYSTEM; + + /* Boundaries and Limits */ + fs->n_fatent = nclst + 2; /* Number of FAT entries */ + fs->volbase = bsect; /* Volume start sector */ + fs->fatbase = bsect + nrsv; /* FAT start sector */ + fs->database = bsect + sysect; /* Data start sector */ + if (fmt == FS_FAT32) { + if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */ + if (fs->n_rootdir != 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ + fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */ + szbfat = fs->n_fatent * 4; /* (Needed FAT size) */ + } else { + if (fs->n_rootdir == 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ + fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ + szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */ + fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); + } + if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */ + +#if !FF_FS_READONLY + /* Get FSInfo if available */ + fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */ + fs->fsi_flag = 0x80; +#if (FF_FS_NOFSINFO & 3) != 3 + if (fmt == FS_FAT32 /* Allow to update FSInfo only if BPB_FSInfo32 == 1 */ + && ld_word(fs->win + BPB_FSInfo32) == 1 + && move_window(fs, bsect + 1) == FR_OK) + { + fs->fsi_flag = 0; + if (ld_word(fs->win + BS_55AA) == 0xAA55 /* Load FSInfo data if available */ + && ld_dword(fs->win + FSI_LeadSig) == 0x41615252 + && ld_dword(fs->win + FSI_StrucSig) == 0x61417272) + { +#if (FF_FS_NOFSINFO & 1) == 0 + fs->free_clst = ld_dword(fs->win + FSI_Free_Count); +#endif +#if (FF_FS_NOFSINFO & 2) == 0 + fs->last_clst = ld_dword(fs->win + FSI_Nxt_Free); +#endif + } + } +#endif /* (FF_FS_NOFSINFO & 3) != 3 */ +#endif /* !FF_FS_READONLY */ + } + + fs->fs_type = (BYTE)fmt;/* FAT sub-type */ + fs->id = ++Fsid; /* Volume mount ID */ +#if FF_USE_LFN == 1 + fs->lfnbuf = LfnBuf; /* Static LFN working buffer */ +#if FF_FS_EXFAT + fs->dirbuf = DirBuf; /* Static directory block scratchpad buuffer */ +#endif +#endif +#if FF_FS_RPATH != 0 + fs->cdir = 0; /* Initialize current directory */ +#endif +#if FF_FS_LOCK != 0 /* Clear file lock semaphores */ + clear_lock(fs); +#endif + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Check if the file/directory object is valid or not */ +/*-----------------------------------------------------------------------*/ + +static FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ + FFOBJID* obj, /* Pointer to the FFOBJID, the 1st member in the FIL/DIR object, to check validity */ + FATFS** rfs /* Pointer to pointer to the owner filesystem object to return */ +) +{ + FRESULT res = FR_INVALID_OBJECT; + + + if (obj && obj->fs && obj->fs->fs_type && obj->id == obj->fs->id) { /* Test if the object is valid */ +#if FF_FS_REENTRANT + if (lock_fs(obj->fs)) { /* Obtain the filesystem object */ + if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ + res = FR_OK; + } else { + unlock_fs(obj->fs, FR_OK); + } + } else { + res = FR_TIMEOUT; + } +#else + if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ + res = FR_OK; + } +#endif + } + *rfs = (res == FR_OK) ? obj->fs : 0; /* Corresponding filesystem object */ + return res; +} + + + + +/*--------------------------------------------------------------------------- + + Public Functions (FatFs API) + +----------------------------------------------------------------------------*/ + + + +/*-----------------------------------------------------------------------*/ +/* Mount/Unmount a Logical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mount ( + FATFS* fs, /* Pointer to the filesystem object to be registered (NULL:unmount)*/ + const TCHAR* path, /* Logical drive number to be mounted/unmounted */ + BYTE opt /* Mount option: 0=Do not mount (delayed mount), 1=Mount immediately */ +) +{ + FATFS *cfs; + int vol; + FRESULT res; + const TCHAR *rp = path; + + + /* Get logical drive number */ + vol = get_ldnumber(&rp); + if (vol < 0) return FR_INVALID_DRIVE; + cfs = FatFs[vol]; /* Pointer to fs object */ + + if (cfs) { +#if FF_FS_LOCK != 0 + clear_lock(cfs); +#endif +#if FF_FS_REENTRANT /* Discard sync object of the current volume */ + if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR; +#endif + cfs->fs_type = 0; /* Clear old fs object */ + } + + if (fs) { + fs->fs_type = 0; /* Clear new fs object */ +#if FF_FS_REENTRANT /* Create sync object for the new volume */ + if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR; +#endif + } + FatFs[vol] = fs; /* Register new fs object */ + + if (opt == 0) return FR_OK; /* Do not mount now, it will be mounted later */ + + res = mount_volume(&path, &fs, 0); /* Force mounted the volume */ + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Open or Create a File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_open ( + FIL* fp, /* Pointer to the blank file object */ + const TCHAR* path, /* Pointer to the file name */ + BYTE mode /* Access mode and open mode flags */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; +#if !FF_FS_READONLY + DWORD cl, bcs, clst, tm; + LBA_t sc; + FSIZE_t ofs; +#endif + DEF_NAMBUF + + + if (!fp) return FR_INVALID_OBJECT; + + /* Get logical drive number */ + mode &= FF_FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND; + res = mount_volume(&path, &fs, mode); + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ +#if !FF_FS_READONLY /* Read/Write configuration */ + if (res == FR_OK) { + if (dj.fn[NSFLAG] & NS_NONAME) { /* Origin directory itself? */ + res = FR_INVALID_NAME; + } +#if FF_FS_LOCK != 0 + else { + res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Check if the file can be used */ + } +#endif + } + /* Create or Open a file */ + if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { + if (res != FR_OK) { /* No file, create new */ + if (res == FR_NO_FILE) { /* There is no file to open, create a new entry */ +#if FF_FS_LOCK != 0 + res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; +#else + res = dir_register(&dj); +#endif + } + mode |= FA_CREATE_ALWAYS; /* File is created */ + } + else { /* Any object with the same name is already existing */ + if (dj.obj.attr & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ + res = FR_DENIED; + } else { + if (mode & FA_CREATE_NEW) res = FR_EXIST; /* Cannot create as new file */ + } + } + if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate the file if overwrite mode */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + /* Get current allocation info */ + fp->obj.fs = fs; + init_alloc_info(fs, &fp->obj); + /* Set directory entry block initial state */ + memset(fs->dirbuf + 2, 0, 30); /* Clear 85 entry except for NumSec */ + memset(fs->dirbuf + 38, 0, 26); /* Clear C0 entry except for NumName and NameHash */ + fs->dirbuf[XDIR_Attr] = AM_ARC; + st_dword(fs->dirbuf + XDIR_CrtTime, GET_FATTIME()); + fs->dirbuf[XDIR_GenFlags] = 1; + res = store_xdir(&dj); + if (res == FR_OK && fp->obj.sclust != 0) { /* Remove the cluster chain if exist */ + res = remove_chain(&fp->obj, fp->obj.sclust, 0); + fs->last_clst = fp->obj.sclust - 1; /* Reuse the cluster hole */ + } + } else +#endif + { + /* Set directory entry initial state */ + tm = GET_FATTIME(); /* Set created time */ + st_dword(dj.dir + DIR_CrtTime, tm); + st_dword(dj.dir + DIR_ModTime, tm); + cl = ld_clust(fs, dj.dir); /* Get current cluster chain */ + dj.dir[DIR_Attr] = AM_ARC; /* Reset attribute */ + st_clust(fs, dj.dir, 0); /* Reset file allocation info */ + st_dword(dj.dir + DIR_FileSize, 0); + fs->wflag = 1; + if (cl != 0) { /* Remove the cluster chain if exist */ + sc = fs->winsect; + res = remove_chain(&dj.obj, cl, 0); + if (res == FR_OK) { + res = move_window(fs, sc); + fs->last_clst = cl - 1; /* Reuse the cluster hole */ + } + } + } + } + } + else { /* Open an existing file */ + if (res == FR_OK) { /* Is the object exsiting? */ + if (dj.obj.attr & AM_DIR) { /* File open against a directory */ + res = FR_NO_FILE; + } else { + if ((mode & FA_WRITE) && (dj.obj.attr & AM_RDO)) { /* Write mode open against R/O file */ + res = FR_DENIED; + } + } + } + } + if (res == FR_OK) { + if (mode & FA_CREATE_ALWAYS) mode |= FA_MODIFIED; /* Set file change flag if created or overwritten */ + fp->dir_sect = fs->winsect; /* Pointer to the directory entry */ + fp->dir_ptr = dj.dir; +#if FF_FS_LOCK != 0 + fp->obj.lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Lock the file for this session */ + if (fp->obj.lockid == 0) res = FR_INT_ERR; +#endif + } +#else /* R/O configuration */ + if (res == FR_OK) { + if (dj.fn[NSFLAG] & NS_NONAME) { /* Is it origin directory itself? */ + res = FR_INVALID_NAME; + } else { + if (dj.obj.attr & AM_DIR) { /* Is it a directory? */ + res = FR_NO_FILE; + } + } + } +#endif + + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fp->obj.c_scl = dj.obj.sclust; /* Get containing directory info */ + fp->obj.c_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat; + fp->obj.c_ofs = dj.blk_ofs; + init_alloc_info(fs, &fp->obj); + } else +#endif + { + fp->obj.sclust = ld_clust(fs, dj.dir); /* Get object allocation info */ + fp->obj.objsize = ld_dword(dj.dir + DIR_FileSize); + } +#if FF_USE_FASTSEEK + fp->cltbl = 0; /* Disable fast seek mode */ +#endif + fp->obj.fs = fs; /* Validate the file object */ + fp->obj.id = fs->id; + fp->flag = mode; /* Set file access mode */ + fp->err = 0; /* Clear error flag */ + fp->sect = 0; /* Invalidate current data sector */ + fp->fptr = 0; /* Set file pointer top of the file */ +#if !FF_FS_READONLY +#if !FF_FS_TINY + memset(fp->buf, 0, sizeof fp->buf); /* Clear sector buffer */ +#endif + if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */ + fp->fptr = fp->obj.objsize; /* Offset to seek */ + bcs = (DWORD)fs->csize * SS(fs); /* Cluster size in byte */ + clst = fp->obj.sclust; /* Follow the cluster chain */ + for (ofs = fp->obj.objsize; res == FR_OK && ofs > bcs; ofs -= bcs) { + clst = get_fat(&fp->obj, clst); + if (clst <= 1) res = FR_INT_ERR; + if (clst == 0xFFFFFFFF) res = FR_DISK_ERR; + } + fp->clust = clst; + if (res == FR_OK && ofs % SS(fs)) { /* Fill sector buffer if not on the sector boundary */ + sc = clst2sect(fs, clst); + if (sc == 0) { + res = FR_INT_ERR; + } else { + fp->sect = sc + (DWORD)(ofs / SS(fs)); +#if !FF_FS_TINY + if (disk_read(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR; +#endif + } + } +#if FF_FS_LOCK != 0 + if (res != FR_OK) dec_lock(fp->obj.lockid); /* Decrement file open counter if seek failed */ +#endif + } +#endif + } + + FREE_NAMBUF(); + } + + if (res != FR_OK) fp->obj.fs = 0; /* Invalidate file object on error */ + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_read ( + FIL* fp, /* Open file to be read */ + void* buff, /* Data buffer to store the read data */ + UINT btr, /* Number of bytes to read */ + UINT* br /* Number of bytes read */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst; + LBA_t sect; + FSIZE_t remain; + UINT rcnt, cc, csect; + BYTE *rbuff = (BYTE*)buff; + + + *br = 0; /* Clear read byte counter */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ + if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + remain = fp->obj.objsize - fp->fptr; + if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + + for ( ; btr > 0; btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) { /* Repeat until btr bytes read */ + if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ + csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ + if (csect == 0) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->obj.sclust; /* Follow cluster chain from the origin */ + } else { /* Middle or end of the file */ +#if FF_USE_FASTSEEK + if (fp->cltbl) { + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + } else +#endif + { + clst = get_fat(&fp->obj, fp->clust); /* Follow cluster chain on the FAT */ + } + } + if (clst < 2) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + sect = clst2sect(fs, fp->clust); /* Get current sector */ + if (sect == 0) ABORT(fs, FR_INT_ERR); + sect += csect; + cc = btr / SS(fs); /* When remaining bytes >= sector size, */ + if (cc > 0) { /* Read maximum contiguous sectors directly */ + if (csect + cc > fs->csize) { /* Clip at cluster boundary */ + cc = fs->csize - csect; + } + if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); +#if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ +#if FF_FS_TINY + if (fs->wflag && fs->winsect - sect < cc) { + memcpy(rbuff + ((fs->winsect - sect) * SS(fs)), fs->win, SS(fs)); + } +#else + if ((fp->flag & FA_DIRTY) && fp->sect - sect < cc) { + memcpy(rbuff + ((fp->sect - sect) * SS(fs)), fp->buf, SS(fs)); + } +#endif +#endif + rcnt = SS(fs) * cc; /* Number of bytes transferred */ + continue; + } +#if !FF_FS_TINY + if (fp->sect != sect) { /* Load data sector if not in cache */ +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ + } +#endif + fp->sect = sect; + } + rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes remains in the sector */ + if (rcnt > btr) rcnt = btr; /* Clip it by btr if needed */ +#if FF_FS_TINY + if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */ + memcpy(rbuff, fs->win + fp->fptr % SS(fs), rcnt); /* Extract partial sector */ +#else + memcpy(rbuff, fp->buf + fp->fptr % SS(fs), rcnt); /* Extract partial sector */ +#endif + } + + LEAVE_FF(fs, FR_OK); +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Write File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_write ( + FIL* fp, /* Open file to be written */ + const void* buff, /* Data to be written */ + UINT btw, /* Number of bytes to write */ + UINT* bw /* Number of bytes written */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst; + LBA_t sect; + UINT wcnt, cc, csect; + const BYTE *wbuff = (const BYTE*)buff; + + + *bw = 0; /* Clear write byte counter */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ + if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + + /* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */ + if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) { + btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr); + } + + for ( ; btw > 0; btw -= wcnt, *bw += wcnt, wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize) { /* Repeat until all data written */ + if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ + csect = (UINT)(fp->fptr / SS(fs)) & (fs->csize - 1); /* Sector offset in the cluster */ + if (csect == 0) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->obj.sclust; /* Follow from the origin */ + if (clst == 0) { /* If no cluster is allocated, */ + clst = create_chain(&fp->obj, 0); /* create a new cluster chain */ + } + } else { /* On the middle or end of the file */ +#if FF_USE_FASTSEEK + if (fp->cltbl) { + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + } else +#endif + { + clst = create_chain(&fp->obj, fp->clust); /* Follow or stretch cluster chain on the FAT */ + } + } + if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ + if (clst == 1) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + if (fp->obj.sclust == 0) fp->obj.sclust = clst; /* Set start cluster if the first write */ + } +#if FF_FS_TINY + if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */ +#else + if (fp->flag & FA_DIRTY) { /* Write-back sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + sect = clst2sect(fs, fp->clust); /* Get current sector */ + if (sect == 0) ABORT(fs, FR_INT_ERR); + sect += csect; + cc = btw / SS(fs); /* When remaining bytes >= sector size, */ + if (cc > 0) { /* Write maximum contiguous sectors directly */ + if (csect + cc > fs->csize) { /* Clip at cluster boundary */ + cc = fs->csize - csect; + } + if (disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); +#if FF_FS_MINIMIZE <= 2 +#if FF_FS_TINY + if (fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + memcpy(fs->win, wbuff + ((fs->winsect - sect) * SS(fs)), SS(fs)); + fs->wflag = 0; + } +#else + if (fp->sect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + memcpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs)); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif +#endif + wcnt = SS(fs) * cc; /* Number of bytes transferred */ + continue; + } +#if FF_FS_TINY + if (fp->fptr >= fp->obj.objsize) { /* Avoid silly cache filling on the growing edge */ + if (sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); + fs->winsect = sect; + } +#else + if (fp->sect != sect && /* Fill sector cache with file data */ + fp->fptr < fp->obj.objsize && + disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) { + ABORT(fs, FR_DISK_ERR); + } +#endif + fp->sect = sect; + } + wcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes remains in the sector */ + if (wcnt > btw) wcnt = btw; /* Clip it by btw if needed */ +#if FF_FS_TINY + if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */ + memcpy(fs->win + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */ + fs->wflag = 1; +#else + memcpy(fp->buf + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */ + fp->flag |= FA_DIRTY; +#endif + } + + fp->flag |= FA_MODIFIED; /* Set file change flag */ + + LEAVE_FF(fs, FR_OK); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Synchronize the File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_sync ( + FIL* fp /* Open file to be synced */ +) +{ + FRESULT res; + FATFS *fs; + DWORD tm; + BYTE *dir; + + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res == FR_OK) { + if (fp->flag & FA_MODIFIED) { /* Is there any change to the file? */ +#if !FF_FS_TINY + if (fp->flag & FA_DIRTY) { /* Write-back cached data if needed */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + /* Update the directory entry */ + tm = GET_FATTIME(); /* Modified time */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + res = fill_first_frag(&fp->obj); /* Fill first fragment on the FAT if needed */ + if (res == FR_OK) { + res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ + } + if (res == FR_OK) { + DIR dj; + DEF_NAMBUF + + INIT_NAMBUF(fs); + res = load_obj_xdir(&dj, &fp->obj); /* Load directory entry block */ + if (res == FR_OK) { + fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ + fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1; /* Update file allocation information */ + st_dword(fs->dirbuf + XDIR_FstClus, fp->obj.sclust); /* Update start cluster */ + st_qword(fs->dirbuf + XDIR_FileSize, fp->obj.objsize); /* Update file size */ + st_qword(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize); /* (FatFs does not support Valid File Size feature) */ + st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Update modified time */ + fs->dirbuf[XDIR_ModTime10] = 0; + st_dword(fs->dirbuf + XDIR_AccTime, 0); + res = store_xdir(&dj); /* Restore it to the directory */ + if (res == FR_OK) { + res = sync_fs(fs); + fp->flag &= (BYTE)~FA_MODIFIED; + } + } + FREE_NAMBUF(); + } + } else +#endif + { + res = move_window(fs, fp->dir_sect); + if (res == FR_OK) { + dir = fp->dir_ptr; + dir[DIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ + st_clust(fp->obj.fs, dir, fp->obj.sclust); /* Update file allocation information */ + st_dword(dir + DIR_FileSize, (DWORD)fp->obj.objsize); /* Update file size */ + st_dword(dir + DIR_ModTime, tm); /* Update modified time */ + st_word(dir + DIR_LstAccDate, 0); + fs->wflag = 1; + res = sync_fs(fs); /* Restore it to the directory */ + fp->flag &= (BYTE)~FA_MODIFIED; + } + } + } + } + + LEAVE_FF(fs, res); +} + +#endif /* !FF_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Close File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_close ( + FIL* fp /* Open file to be closed */ +) +{ + FRESULT res; + FATFS *fs; + +#if !FF_FS_READONLY + res = f_sync(fp); /* Flush cached data */ + if (res == FR_OK) +#endif + { + res = validate(&fp->obj, &fs); /* Lock volume */ + if (res == FR_OK) { +#if FF_FS_LOCK != 0 + res = dec_lock(fp->obj.lockid); /* Decrement file open counter */ + if (res == FR_OK) fp->obj.fs = 0; /* Invalidate file object */ +#else + fp->obj.fs = 0; /* Invalidate file object */ +#endif +#if FF_FS_REENTRANT + unlock_fs(fs, FR_OK); /* Unlock volume */ +#endif + } + } + return res; +} + + + + +#if FF_FS_RPATH >= 1 +/*-----------------------------------------------------------------------*/ +/* Change Current Directory or Current Drive, Get Current Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_chdrive ( + const TCHAR* path /* Drive number to set */ +) +{ + int vol; + + + /* Get logical drive number */ + vol = get_ldnumber(&path); + if (vol < 0) return FR_INVALID_DRIVE; + CurrVol = (BYTE)vol; /* Set it as current volume */ + + return FR_OK; +} + + + +FRESULT f_chdir ( + const TCHAR* path /* Pointer to the directory path */ +) +{ +#if FF_STR_VOLUME_ID == 2 + UINT i; +#endif + FRESULT res; + DIR dj; + FATFS *fs; + DEF_NAMBUF + + + /* Get logical drive */ + res = mount_volume(&path, &fs, 0); + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the path */ + if (res == FR_OK) { /* Follow completed */ + if (dj.fn[NSFLAG] & NS_NONAME) { /* Is it the start directory itself? */ + fs->cdir = dj.obj.sclust; +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fs->cdc_scl = dj.obj.c_scl; + fs->cdc_size = dj.obj.c_size; + fs->cdc_ofs = dj.obj.c_ofs; + } +#endif + } else { + if (dj.obj.attr & AM_DIR) { /* It is a sub-directory */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fs->cdir = ld_dword(fs->dirbuf + XDIR_FstClus); /* Sub-directory cluster */ + fs->cdc_scl = dj.obj.sclust; /* Save containing directory information */ + fs->cdc_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat; + fs->cdc_ofs = dj.blk_ofs; + } else +#endif + { + fs->cdir = ld_clust(fs, dj.dir); /* Sub-directory cluster */ + } + } else { + res = FR_NO_PATH; /* Reached but a file */ + } + } + } + FREE_NAMBUF(); + if (res == FR_NO_FILE) res = FR_NO_PATH; +#if FF_STR_VOLUME_ID == 2 /* Also current drive is changed if in Unix style volume ID */ + if (res == FR_OK) { + for (i = FF_VOLUMES - 1; i && fs != FatFs[i]; i--) ; /* Set current drive */ + CurrVol = (BYTE)i; + } +#endif + } + + LEAVE_FF(fs, res); +} + + +#if FF_FS_RPATH >= 2 +FRESULT f_getcwd ( + TCHAR* buff, /* Pointer to the directory path */ + UINT len /* Size of buff in unit of TCHAR */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + UINT i, n; + DWORD ccl; + TCHAR *tp = buff; +#if FF_VOLUMES >= 2 + UINT vl; +#if FF_STR_VOLUME_ID + const char *vp; +#endif +#endif + FILINFO fno; + DEF_NAMBUF + + + /* Get logical drive */ + buff[0] = 0; /* Set null string to get current volume */ + res = mount_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */ + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + + /* Follow parent directories and create the path */ + i = len; /* Bottom of buffer (directory stack base) */ + if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* (Cannot do getcwd on exFAT and returns root path) */ + dj.obj.sclust = fs->cdir; /* Start to follow upper directory from current directory */ + while ((ccl = dj.obj.sclust) != 0) { /* Repeat while current directory is a sub-directory */ + res = dir_sdi(&dj, 1 * SZDIRE); /* Get parent directory */ + if (res != FR_OK) break; + res = move_window(fs, dj.sect); + if (res != FR_OK) break; + dj.obj.sclust = ld_clust(fs, dj.dir); /* Goto parent directory */ + res = dir_sdi(&dj, 0); + if (res != FR_OK) break; + do { /* Find the entry links to the child directory */ + res = DIR_READ_FILE(&dj); + if (res != FR_OK) break; + if (ccl == ld_clust(fs, dj.dir)) break; /* Found the entry */ + res = dir_next(&dj, 0); + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ + if (res != FR_OK) break; + get_fileinfo(&dj, &fno); /* Get the directory name and push it to the buffer */ + for (n = 0; fno.fname[n]; n++) ; /* Name length */ + if (i < n + 1) { /* Insufficient space to store the path name? */ + res = FR_NOT_ENOUGH_CORE; break; + } + while (n) buff[--i] = fno.fname[--n]; /* Stack the name */ + buff[--i] = '/'; + } + } + if (res == FR_OK) { + if (i == len) buff[--i] = '/'; /* Is it the root-directory? */ +#if FF_VOLUMES >= 2 /* Put drive prefix */ + vl = 0; +#if FF_STR_VOLUME_ID >= 1 /* String volume ID */ + for (n = 0, vp = (const char*)VolumeStr[CurrVol]; vp[n]; n++) ; + if (i >= n + 2) { + if (FF_STR_VOLUME_ID == 2) *tp++ = (TCHAR)'/'; + for (vl = 0; vl < n; *tp++ = (TCHAR)vp[vl], vl++) ; + if (FF_STR_VOLUME_ID == 1) *tp++ = (TCHAR)':'; + vl++; + } +#else /* Numeric volume ID */ + if (i >= 3) { + *tp++ = (TCHAR)'0' + CurrVol; + *tp++ = (TCHAR)':'; + vl = 2; + } +#endif + if (vl == 0) res = FR_NOT_ENOUGH_CORE; +#endif + /* Add current directory path */ + if (res == FR_OK) { + do *tp++ = buff[i++]; while (i < len); /* Copy stacked path string */ + } + } + FREE_NAMBUF(); + } + + *tp = 0; + LEAVE_FF(fs, res); +} + +#endif /* FF_FS_RPATH >= 2 */ +#endif /* FF_FS_RPATH >= 1 */ + + + +#if FF_FS_MINIMIZE <= 2 +/*-----------------------------------------------------------------------*/ +/* Seek File Read/Write Pointer */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_lseek ( + FIL* fp, /* Pointer to the file object */ + FSIZE_t ofs /* File pointer from top of file */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, bcs; + LBA_t nsect; + FSIZE_t ifptr; +#if FF_USE_FASTSEEK + DWORD cl, pcl, ncl, tcl, tlen, ulen; + DWORD *tbl; + LBA_t dsc; +#endif + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res == FR_OK) res = (FRESULT)fp->err; +#if FF_FS_EXFAT && !FF_FS_READONLY + if (res == FR_OK && fs->fs_type == FS_EXFAT) { + res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ + } +#endif + if (res != FR_OK) LEAVE_FF(fs, res); + +#if FF_USE_FASTSEEK + if (fp->cltbl) { /* Fast seek */ + if (ofs == CREATE_LINKMAP) { /* Create CLMT */ + tbl = fp->cltbl; + tlen = *tbl++; ulen = 2; /* Given table size and required table size */ + cl = fp->obj.sclust; /* Origin of the chain */ + if (cl != 0) { + do { + /* Get a fragment */ + tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */ + do { + pcl = cl; ncl++; + cl = get_fat(&fp->obj, cl); + if (cl <= 1) ABORT(fs, FR_INT_ERR); + if (cl == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + } while (cl == pcl + 1); + if (ulen <= tlen) { /* Store the length and top of the fragment */ + *tbl++ = ncl; *tbl++ = tcl; + } + } while (cl < fs->n_fatent); /* Repeat until end of chain */ + } + *fp->cltbl = ulen; /* Number of items used */ + if (ulen <= tlen) { + *tbl = 0; /* Terminate table */ + } else { + res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */ + } + } else { /* Fast seek */ + if (ofs > fp->obj.objsize) ofs = fp->obj.objsize; /* Clip offset at the file size */ + fp->fptr = ofs; /* Set file pointer */ + if (ofs > 0) { + fp->clust = clmt_clust(fp, ofs - 1); + dsc = clst2sect(fs, fp->clust); + if (dsc == 0) ABORT(fs, FR_INT_ERR); + dsc += (DWORD)((ofs - 1) / SS(fs)) & (fs->csize - 1); + if (fp->fptr % SS(fs) && dsc != fp->sect) { /* Refill sector cache if needed */ +#if !FF_FS_TINY +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Load current sector */ +#endif + fp->sect = dsc; + } + } + } + } else +#endif + + /* Normal Seek */ + { +#if FF_FS_EXFAT + if (fs->fs_type != FS_EXFAT && ofs >= 0x100000000) ofs = 0xFFFFFFFF; /* Clip at 4 GiB - 1 if at FATxx */ +#endif + if (ofs > fp->obj.objsize && (FF_FS_READONLY || !(fp->flag & FA_WRITE))) { /* In read-only mode, clip offset with the file size */ + ofs = fp->obj.objsize; + } + ifptr = fp->fptr; + fp->fptr = nsect = 0; + if (ofs > 0) { + bcs = (DWORD)fs->csize * SS(fs); /* Cluster size (byte) */ + if (ifptr > 0 && + (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ + fp->fptr = (ifptr - 1) & ~(FSIZE_t)(bcs - 1); /* start from the current cluster */ + ofs -= fp->fptr; + clst = fp->clust; + } else { /* When seek to back cluster, */ + clst = fp->obj.sclust; /* start from the first cluster */ +#if !FF_FS_READONLY + if (clst == 0) { /* If no cluster chain, create a new chain */ + clst = create_chain(&fp->obj, 0); + if (clst == 1) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->obj.sclust = clst; + } +#endif + fp->clust = clst; + } + if (clst != 0) { + while (ofs > bcs) { /* Cluster following loop */ + ofs -= bcs; fp->fptr += bcs; +#if !FF_FS_READONLY + if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ + if (FF_FS_EXFAT && fp->fptr > fp->obj.objsize) { /* No FAT chain object needs correct objsize to generate FAT value */ + fp->obj.objsize = fp->fptr; + fp->flag |= FA_MODIFIED; + } + clst = create_chain(&fp->obj, clst); /* Follow chain with forceed stretch */ + if (clst == 0) { /* Clip file size in case of disk full */ + ofs = 0; break; + } + } else +#endif + { + clst = get_fat(&fp->obj, clst); /* Follow cluster chain if not in write mode */ + } + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR); + fp->clust = clst; + } + fp->fptr += ofs; + if (ofs % SS(fs)) { + nsect = clst2sect(fs, clst); /* Current sector */ + if (nsect == 0) ABORT(fs, FR_INT_ERR); + nsect += (DWORD)(ofs / SS(fs)); + } + } + } + if (!FF_FS_READONLY && fp->fptr > fp->obj.objsize) { /* Set file change flag if the file size is extended */ + fp->obj.objsize = fp->fptr; + fp->flag |= FA_MODIFIED; + } + if (fp->fptr % SS(fs) && nsect != fp->sect) { /* Fill sector cache if needed */ +#if !FF_FS_TINY +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ +#endif + fp->sect = nsect; + } + } + + LEAVE_FF(fs, res); +} + + + +#if FF_FS_MINIMIZE <= 1 +/*-----------------------------------------------------------------------*/ +/* Create a Directory Object */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_opendir ( + DIR* dp, /* Pointer to directory object to create */ + const TCHAR* path /* Pointer to the directory path */ +) +{ + FRESULT res; + FATFS *fs; + DEF_NAMBUF + + + if (!dp) return FR_INVALID_OBJECT; + + /* Get logical drive */ + res = mount_volume(&path, &fs, 0); + if (res == FR_OK) { + dp->obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(dp, path); /* Follow the path to the directory */ + if (res == FR_OK) { /* Follow completed */ + if (!(dp->fn[NSFLAG] & NS_NONAME)) { /* It is not the origin directory itself */ + if (dp->obj.attr & AM_DIR) { /* This object is a sub-directory */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + dp->obj.c_scl = dp->obj.sclust; /* Get containing directory inforamation */ + dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat; + dp->obj.c_ofs = dp->blk_ofs; + init_alloc_info(fs, &dp->obj); /* Get object allocation info */ + } else +#endif + { + dp->obj.sclust = ld_clust(fs, dp->dir); /* Get object allocation info */ + } + } else { /* This object is a file */ + res = FR_NO_PATH; + } + } + if (res == FR_OK) { + dp->obj.id = fs->id; + res = dir_sdi(dp, 0); /* Rewind directory */ +#if FF_FS_LOCK != 0 + if (res == FR_OK) { + if (dp->obj.sclust != 0) { + dp->obj.lockid = inc_lock(dp, 0); /* Lock the sub directory */ + if (!dp->obj.lockid) res = FR_TOO_MANY_OPEN_FILES; + } else { + dp->obj.lockid = 0; /* Root directory need not to be locked */ + } + } +#endif + } + } + FREE_NAMBUF(); + if (res == FR_NO_FILE) res = FR_NO_PATH; + } + if (res != FR_OK) dp->obj.fs = 0; /* Invalidate the directory object if function faild */ + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Close Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_closedir ( + DIR *dp /* Pointer to the directory object to be closed */ +) +{ + FRESULT res; + FATFS *fs; + + + res = validate(&dp->obj, &fs); /* Check validity of the file object */ + if (res == FR_OK) { +#if FF_FS_LOCK != 0 + if (dp->obj.lockid) res = dec_lock(dp->obj.lockid); /* Decrement sub-directory open counter */ + if (res == FR_OK) dp->obj.fs = 0; /* Invalidate directory object */ +#else + dp->obj.fs = 0; /* Invalidate directory object */ +#endif +#if FF_FS_REENTRANT + unlock_fs(fs, FR_OK); /* Unlock volume */ +#endif + } + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read Directory Entries in Sequence */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_readdir ( + DIR* dp, /* Pointer to the open directory object */ + FILINFO* fno /* Pointer to file information to return */ +) +{ + FRESULT res; + FATFS *fs; + DEF_NAMBUF + + + res = validate(&dp->obj, &fs); /* Check validity of the directory object */ + if (res == FR_OK) { + if (!fno) { + res = dir_sdi(dp, 0); /* Rewind the directory object */ + } else { + INIT_NAMBUF(fs); + res = DIR_READ_FILE(dp); /* Read an item */ + if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */ + if (res == FR_OK) { /* A valid entry is found */ + get_fileinfo(dp, fno); /* Get the object information */ + res = dir_next(dp, 0); /* Increment index for next */ + if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory now */ + } + FREE_NAMBUF(); + } + } + LEAVE_FF(fs, res); +} + + + +#if FF_USE_FIND +/*-----------------------------------------------------------------------*/ +/* Find Next File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_findnext ( + DIR* dp, /* Pointer to the open directory object */ + FILINFO* fno /* Pointer to the file information structure */ +) +{ + FRESULT res; + + + for (;;) { + res = f_readdir(dp, fno); /* Get a directory item */ + if (res != FR_OK || !fno || !fno->fname[0]) break; /* Terminate if any error or end of directory */ + if (pattern_match(dp->pat, fno->fname, 0, FIND_RECURS)) break; /* Test for the file name */ +#if FF_USE_LFN && FF_USE_FIND == 2 + if (pattern_match(dp->pat, fno->altname, 0, FIND_RECURS)) break; /* Test for alternative name if exist */ +#endif + } + return res; +} + + + +/*-----------------------------------------------------------------------*/ +/* Find First File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_findfirst ( + DIR* dp, /* Pointer to the blank directory object */ + FILINFO* fno, /* Pointer to the file information structure */ + const TCHAR* path, /* Pointer to the directory to open */ + const TCHAR* pattern /* Pointer to the matching pattern */ +) +{ + FRESULT res; + + + dp->pat = pattern; /* Save pointer to pattern string */ + res = f_opendir(dp, path); /* Open the target directory */ + if (res == FR_OK) { + res = f_findnext(dp, fno); /* Find the first item */ + } + return res; +} + +#endif /* FF_USE_FIND */ + + + +#if FF_FS_MINIMIZE == 0 +/*-----------------------------------------------------------------------*/ +/* Get File Status */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_stat ( + const TCHAR* path, /* Pointer to the file path */ + FILINFO* fno /* Pointer to file information to return */ +) +{ + FRESULT res; + DIR dj; + DEF_NAMBUF + + + /* Get logical drive */ + res = mount_volume(&path, &dj.obj.fs, 0); + if (res == FR_OK) { + INIT_NAMBUF(dj.obj.fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) { /* Follow completed */ + if (dj.fn[NSFLAG] & NS_NONAME) { /* It is origin directory */ + res = FR_INVALID_NAME; + } else { /* Found an object */ + if (fno) get_fileinfo(&dj, fno); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(dj.obj.fs, res); +} + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Get Number of Free Clusters */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getfree ( + const TCHAR* path, /* Logical drive number */ + DWORD* nclst, /* Pointer to a variable to return number of free clusters */ + FATFS** fatfs /* Pointer to return pointer to corresponding filesystem object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD nfree, clst, stat; + LBA_t sect; + UINT i; + FFOBJID obj; + + + /* Get logical drive */ + res = mount_volume(&path, &fs, 0); + if (res == FR_OK) { + *fatfs = fs; /* Return ptr to the fs object */ + /* If free_clst is valid, return it without full FAT scan */ + if (fs->free_clst <= fs->n_fatent - 2) { + *nclst = fs->free_clst; + } else { + /* Scan FAT to obtain number of free clusters */ + nfree = 0; + if (fs->fs_type == FS_FAT12) { /* FAT12: Scan bit field FAT entries */ + clst = 2; obj.fs = fs; + do { + stat = get_fat(&obj, clst); + if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } + if (stat == 1) { res = FR_INT_ERR; break; } + if (stat == 0) nfree++; + } while (++clst < fs->n_fatent); + } else { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* exFAT: Scan allocation bitmap */ + BYTE bm; + UINT b; + + clst = fs->n_fatent - 2; /* Number of clusters */ + sect = fs->bitbase; /* Bitmap sector */ + i = 0; /* Offset in the sector */ + do { /* Counts numbuer of bits with zero in the bitmap */ + if (i == 0) { + res = move_window(fs, sect++); + if (res != FR_OK) break; + } + for (b = 8, bm = fs->win[i]; b && clst; b--, clst--) { + if (!(bm & 1)) nfree++; + bm >>= 1; + } + i = (i + 1) % SS(fs); + } while (clst); + } else +#endif + { /* FAT16/32: Scan WORD/DWORD FAT entries */ + clst = fs->n_fatent; /* Number of entries */ + sect = fs->fatbase; /* Top of the FAT */ + i = 0; /* Offset in the sector */ + do { /* Counts numbuer of entries with zero in the FAT */ + if (i == 0) { + res = move_window(fs, sect++); + if (res != FR_OK) break; + } + if (fs->fs_type == FS_FAT16) { + if (ld_word(fs->win + i) == 0) nfree++; + i += 2; + } else { + if ((ld_dword(fs->win + i) & 0x0FFFFFFF) == 0) nfree++; + i += 4; + } + i %= SS(fs); + } while (--clst); + } + } + if (res == FR_OK) { /* Update parameters if succeeded */ + *nclst = nfree; /* Return the free clusters */ + fs->free_clst = nfree; /* Now free_clst is valid */ + fs->fsi_flag |= 1; /* FAT32: FSInfo is to be updated */ + } + } + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Truncate File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_truncate ( + FIL* fp /* Pointer to the file object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD ncl; + + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); + if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + + if (fp->fptr < fp->obj.objsize) { /* Process when fptr is not on the eof */ + if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ + res = remove_chain(&fp->obj, fp->obj.sclust, 0); + fp->obj.sclust = 0; + } else { /* When truncate a part of the file, remove remaining clusters */ + ncl = get_fat(&fp->obj, fp->clust); + res = FR_OK; + if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (ncl == 1) res = FR_INT_ERR; + if (res == FR_OK && ncl < fs->n_fatent) { + res = remove_chain(&fp->obj, ncl, fp->clust); + } + } + fp->obj.objsize = fp->fptr; /* Set file size to current read/write point */ + fp->flag |= FA_MODIFIED; +#if !FF_FS_TINY + if (res == FR_OK && (fp->flag & FA_DIRTY)) { + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) { + res = FR_DISK_ERR; + } else { + fp->flag &= (BYTE)~FA_DIRTY; + } + } +#endif + if (res != FR_OK) ABORT(fs, res); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Delete a File/Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_unlink ( + const TCHAR* path /* Pointer to the file or directory path */ +) +{ + FRESULT res; + DIR dj, sdj; + DWORD dclst = 0; + FATFS *fs; +#if FF_FS_EXFAT + FFOBJID obj; +#endif + DEF_NAMBUF + + + /* Get logical drive */ + res = mount_volume(&path, &fs, FA_WRITE); + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (FF_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) { + res = FR_INVALID_NAME; /* Cannot remove dot entry */ + } +#if FF_FS_LOCK != 0 + if (res == FR_OK) res = chk_lock(&dj, 2); /* Check if it is an open object */ +#endif + if (res == FR_OK) { /* The object is accessible */ + if (dj.fn[NSFLAG] & NS_NONAME) { + res = FR_INVALID_NAME; /* Cannot remove the origin directory */ + } else { + if (dj.obj.attr & AM_RDO) { + res = FR_DENIED; /* Cannot remove R/O object */ + } + } + if (res == FR_OK) { +#if FF_FS_EXFAT + obj.fs = fs; + if (fs->fs_type == FS_EXFAT) { + init_alloc_info(fs, &obj); + dclst = obj.sclust; + } else +#endif + { + dclst = ld_clust(fs, dj.dir); + } + if (dj.obj.attr & AM_DIR) { /* Is it a sub-directory? */ +#if FF_FS_RPATH != 0 + if (dclst == fs->cdir) { /* Is it the current directory? */ + res = FR_DENIED; + } else +#endif + { + sdj.obj.fs = fs; /* Open the sub-directory */ + sdj.obj.sclust = dclst; +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + sdj.obj.objsize = obj.objsize; + sdj.obj.stat = obj.stat; + } +#endif + res = dir_sdi(&sdj, 0); + if (res == FR_OK) { + res = DIR_READ_FILE(&sdj); /* Test if the directory is empty */ + if (res == FR_OK) res = FR_DENIED; /* Not empty? */ + if (res == FR_NO_FILE) res = FR_OK; /* Empty? */ + } + } + } + } + if (res == FR_OK) { + res = dir_remove(&dj); /* Remove the directory entry */ + if (res == FR_OK && dclst != 0) { /* Remove the cluster chain if exist */ +#if FF_FS_EXFAT + res = remove_chain(&obj, dclst, 0); +#else + res = remove_chain(&dj.obj, dclst, 0); +#endif + } + if (res == FR_OK) res = sync_fs(fs); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Create a Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mkdir ( + const TCHAR* path /* Pointer to the directory path */ +) +{ + FRESULT res; + DIR dj; + FFOBJID sobj; + FATFS *fs; + DWORD dcl, pcl, tm; + DEF_NAMBUF + + + res = mount_volume(&path, &fs, FA_WRITE); /* Get logical drive */ + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) res = FR_EXIST; /* Name collision? */ + if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) { /* Invalid name? */ + res = FR_INVALID_NAME; + } + if (res == FR_NO_FILE) { /* It is clear to create a new directory */ + sobj.fs = fs; /* New object id to create a new chain */ + dcl = create_chain(&sobj, 0); /* Allocate a cluster for the new directory */ + res = FR_OK; + if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster? */ + if (dcl == 1) res = FR_INT_ERR; /* Any insanity? */ + if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; /* Disk error? */ + tm = GET_FATTIME(); + if (res == FR_OK) { + res = dir_clear(fs, dcl); /* Clean up the new table */ + if (res == FR_OK) { + if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* Create dot entries (FAT only) */ + memset(fs->win + DIR_Name, ' ', 11); /* Create "." entry */ + fs->win[DIR_Name] = '.'; + fs->win[DIR_Attr] = AM_DIR; + st_dword(fs->win + DIR_ModTime, tm); + st_clust(fs, fs->win, dcl); + memcpy(fs->win + SZDIRE, fs->win, SZDIRE); /* Create ".." entry */ + fs->win[SZDIRE + 1] = '.'; pcl = dj.obj.sclust; + st_clust(fs, fs->win + SZDIRE, pcl); + fs->wflag = 1; + } + res = dir_register(&dj); /* Register the object to the parent directoy */ + } + } + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* Initialize directory entry block */ + st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Created time */ + st_dword(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */ + st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)fs->csize * SS(fs)); /* Directory size needs to be valid */ + st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)fs->csize * SS(fs)); + fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag */ + fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */ + res = store_xdir(&dj); + } else +#endif + { + st_dword(dj.dir + DIR_ModTime, tm); /* Created time */ + st_clust(fs, dj.dir, dcl); /* Table start cluster */ + dj.dir[DIR_Attr] = AM_DIR; /* Attribute */ + fs->wflag = 1; + } + if (res == FR_OK) { + res = sync_fs(fs); + } + } else { + remove_chain(&sobj, dcl, 0); /* Could not register, remove the allocated cluster */ + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Rename a File/Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_rename ( + const TCHAR* path_old, /* Pointer to the object name to be renamed */ + const TCHAR* path_new /* Pointer to the new name */ +) +{ + FRESULT res; + DIR djo, djn; + FATFS *fs; + BYTE buf[FF_FS_EXFAT ? SZDIRE * 2 : SZDIRE], *dir; + LBA_t sect; + DEF_NAMBUF + + + get_ldnumber(&path_new); /* Snip the drive number of new name off */ + res = mount_volume(&path_old, &fs, FA_WRITE); /* Get logical drive of the old object */ + if (res == FR_OK) { + djo.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&djo, path_old); /* Check old object */ + if (res == FR_OK && (djo.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check validity of name */ +#if FF_FS_LOCK != 0 + if (res == FR_OK) { + res = chk_lock(&djo, 2); + } +#endif + if (res == FR_OK) { /* Object to be renamed is found */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* At exFAT volume */ + BYTE nf, nn; + WORD nh; + + memcpy(buf, fs->dirbuf, SZDIRE * 2); /* Save 85+C0 entry of old object */ + memcpy(&djn, &djo, sizeof djo); + res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ + if (res == FR_OK) { /* Is new name already in use by any other object? */ + res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; + } + if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ + res = dir_register(&djn); /* Register the new entry */ + if (res == FR_OK) { + nf = fs->dirbuf[XDIR_NumSec]; nn = fs->dirbuf[XDIR_NumName]; + nh = ld_word(fs->dirbuf + XDIR_NameHash); + memcpy(fs->dirbuf, buf, SZDIRE * 2); /* Restore 85+C0 entry */ + fs->dirbuf[XDIR_NumSec] = nf; fs->dirbuf[XDIR_NumName] = nn; + st_word(fs->dirbuf + XDIR_NameHash, nh); + if (!(fs->dirbuf[XDIR_Attr] & AM_DIR)) fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */ +/* Start of critical section where an interruption can cause a cross-link */ + res = store_xdir(&djn); + } + } + } else +#endif + { /* At FAT/FAT32 volume */ + memcpy(buf, djo.dir, SZDIRE); /* Save directory entry of the object */ + memcpy(&djn, &djo, sizeof (DIR)); /* Duplicate the directory object */ + res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ + if (res == FR_OK) { /* Is new name already in use by any other object? */ + res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; + } + if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ + res = dir_register(&djn); /* Register the new entry */ + if (res == FR_OK) { + dir = djn.dir; /* Copy directory entry of the object except name */ + memcpy(dir + 13, buf + 13, SZDIRE - 13); + dir[DIR_Attr] = buf[DIR_Attr]; + if (!(dir[DIR_Attr] & AM_DIR)) dir[DIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */ + fs->wflag = 1; + if ((dir[DIR_Attr] & AM_DIR) && djo.obj.sclust != djn.obj.sclust) { /* Update .. entry in the sub-directory if needed */ + sect = clst2sect(fs, ld_clust(fs, dir)); + if (sect == 0) { + res = FR_INT_ERR; + } else { +/* Start of critical section where an interruption can cause a cross-link */ + res = move_window(fs, sect); + dir = fs->win + SZDIRE * 1; /* Ptr to .. entry */ + if (res == FR_OK && dir[1] == '.') { + st_clust(fs, dir, djn.obj.sclust); + fs->wflag = 1; + } + } + } + } + } + } + if (res == FR_OK) { + res = dir_remove(&djo); /* Remove old entry */ + if (res == FR_OK) { + res = sync_fs(fs); + } + } +/* End of the critical section */ + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_FS_MINIMIZE == 0 */ +#endif /* FF_FS_MINIMIZE <= 1 */ +#endif /* FF_FS_MINIMIZE <= 2 */ + + + +#if FF_USE_CHMOD && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Change Attribute */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_chmod ( + const TCHAR* path, /* Pointer to the file path */ + BYTE attr, /* Attribute bits */ + BYTE mask /* Attribute mask to change */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + DEF_NAMBUF + + + res = mount_volume(&path, &fs, FA_WRITE); /* Get logical drive */ + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check object validity */ + if (res == FR_OK) { + mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fs->dirbuf[XDIR_Attr] = (attr & mask) | (fs->dirbuf[XDIR_Attr] & (BYTE)~mask); /* Apply attribute change */ + res = store_xdir(&dj); + } else +#endif + { + dj.dir[DIR_Attr] = (attr & mask) | (dj.dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ + fs->wflag = 1; + } + if (res == FR_OK) { + res = sync_fs(fs); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Change Timestamp */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_utime ( + const TCHAR* path, /* Pointer to the file/directory name */ + const FILINFO* fno /* Pointer to the timestamp to be set */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + DEF_NAMBUF + + + res = mount_volume(&path, &fs, FA_WRITE); /* Get logical drive */ + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check object validity */ + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + st_dword(fs->dirbuf + XDIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); + res = store_xdir(&dj); + } else +#endif + { + st_dword(dj.dir + DIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); + fs->wflag = 1; + } + if (res == FR_OK) { + res = sync_fs(fs); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + +#endif /* FF_USE_CHMOD && !FF_FS_READONLY */ + + + +#if FF_USE_LABEL +/*-----------------------------------------------------------------------*/ +/* Get Volume Label */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getlabel ( + const TCHAR* path, /* Logical drive number */ + TCHAR* label, /* Buffer to store the volume label */ + DWORD* vsn /* Variable to store the volume serial number */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + UINT si, di; + WCHAR wc; + + /* Get logical drive */ + res = mount_volume(&path, &fs, 0); + + /* Get volume label */ + if (res == FR_OK && label) { + dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */ + res = dir_sdi(&dj, 0); + if (res == FR_OK) { + res = DIR_READ_LABEL(&dj); /* Find a volume label entry */ + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + WCHAR hs; + UINT nw; + + for (si = di = hs = 0; si < dj.dir[XDIR_NumLabel]; si++) { /* Extract volume label from 83 entry */ + wc = ld_word(dj.dir + XDIR_Label + si * 2); + if (hs == 0 && IsSurrogate(wc)) { /* Is the code a surrogate? */ + hs = wc; continue; + } + nw = put_utf((DWORD)hs << 16 | wc, &label[di], 4); /* Store it in API encoding */ + if (nw == 0) { di = 0; break; } /* Encode error? */ + di += nw; + hs = 0; + } + if (hs != 0) di = 0; /* Broken surrogate pair? */ + label[di] = 0; + } else +#endif + { + si = di = 0; /* Extract volume label from AM_VOL entry */ + while (si < 11) { + wc = dj.dir[si++]; +#if FF_USE_LFN && FF_LFN_UNICODE >= 1 /* Unicode output */ + if (dbc_1st((BYTE)wc) && si < 11) wc = wc << 8 | dj.dir[si++]; /* Is it a DBC? */ + wc = ff_oem2uni(wc, CODEPAGE); /* Convert it into Unicode */ + if (wc == 0) { di = 0; break; } /* Invalid char in current code page? */ + di += put_utf(wc, &label[di], 4); /* Store it in Unicode */ +#else /* ANSI/OEM output */ + label[di++] = (TCHAR)wc; +#endif + } + do { /* Truncate trailing spaces */ + label[di] = 0; + if (di == 0) break; + } while (label[--di] == ' '); + } + } + } + if (res == FR_NO_FILE) { /* No label entry and return nul string */ + label[0] = 0; + res = FR_OK; + } + } + + /* Get volume serial number */ + if (res == FR_OK && vsn) { + res = move_window(fs, fs->volbase); + if (res == FR_OK) { + switch (fs->fs_type) { + case FS_EXFAT: + di = BPB_VolIDEx; + break; + + case FS_FAT32: + di = BS_VolID32; + break; + + default: + di = BS_VolID; + } + *vsn = ld_dword(fs->win + di); + } + } + + LEAVE_FF(fs, res); +} + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Set Volume Label */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_setlabel ( + const TCHAR* label /* Volume label to set with heading logical drive number */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + BYTE dirvn[22]; + UINT di; + WCHAR wc; + static const char badchr[18] = "+.,;=[]" "/*:<>|\\\"\?\x7F"; /* [0..16] for FAT, [7..16] for exFAT */ +#if FF_USE_LFN + DWORD dc; +#endif + + /* Get logical drive */ + res = mount_volume(&label, &fs, FA_WRITE); + if (res != FR_OK) LEAVE_FF(fs, res); + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + memset(dirvn, 0, 22); + di = 0; + while ((UINT)*label >= ' ') { /* Create volume label */ + dc = tchar2uni(&label); /* Get a Unicode character */ + if (dc >= 0x10000) { + if (dc == 0xFFFFFFFF || di >= 10) { /* Wrong surrogate or buffer overflow */ + dc = 0; + } else { + st_word(dirvn + di * 2, (WCHAR)(dc >> 16)); di++; + } + } + if (dc == 0 || strchr(&badchr[7], (int)dc) || di >= 11) { /* Check validity of the volume label */ + LEAVE_FF(fs, FR_INVALID_NAME); + } + st_word(dirvn + di * 2, (WCHAR)dc); di++; + } + } else +#endif + { /* On the FAT/FAT32 volume */ + memset(dirvn, ' ', 11); + di = 0; + while ((UINT)*label >= ' ') { /* Create volume label */ +#if FF_USE_LFN + dc = tchar2uni(&label); + wc = (dc < 0x10000) ? ff_uni2oem(ff_wtoupper(dc), CODEPAGE) : 0; +#else /* ANSI/OEM input */ + wc = (BYTE)*label++; + if (dbc_1st((BYTE)wc)) wc = dbc_2nd((BYTE)*label) ? wc << 8 | (BYTE)*label++ : 0; + if (IsLower(wc)) wc -= 0x20; /* To upper ASCII characters */ +#if FF_CODE_PAGE == 0 + if (ExCvt && wc >= 0x80) wc = ExCvt[wc - 0x80]; /* To upper extended characters (SBCS cfg) */ +#elif FF_CODE_PAGE < 900 + if (wc >= 0x80) wc = ExCvt[wc - 0x80]; /* To upper extended characters (SBCS cfg) */ +#endif +#endif + if (wc == 0 || strchr(&badchr[0], (int)wc) || di >= (UINT)((wc >= 0x100) ? 10 : 11)) { /* Reject invalid characters for volume label */ + LEAVE_FF(fs, FR_INVALID_NAME); + } + if (wc >= 0x100) dirvn[di++] = (BYTE)(wc >> 8); + dirvn[di++] = (BYTE)wc; + } + if (dirvn[0] == DDEM) LEAVE_FF(fs, FR_INVALID_NAME); /* Reject illegal name (heading DDEM) */ + while (di && dirvn[di - 1] == ' ') di--; /* Snip trailing spaces */ + } + + /* Set volume label */ + dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */ + res = dir_sdi(&dj, 0); + if (res == FR_OK) { + res = DIR_READ_LABEL(&dj); /* Get volume label entry */ + if (res == FR_OK) { + if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { + dj.dir[XDIR_NumLabel] = (BYTE)di; /* Change the volume label */ + memcpy(dj.dir + XDIR_Label, dirvn, 22); + } else { + if (di != 0) { + memcpy(dj.dir, dirvn, 11); /* Change the volume label */ + } else { + dj.dir[DIR_Name] = DDEM; /* Remove the volume label */ + } + } + fs->wflag = 1; + res = sync_fs(fs); + } else { /* No volume label entry or an error */ + if (res == FR_NO_FILE) { + res = FR_OK; + if (di != 0) { /* Create a volume label entry */ + res = dir_alloc(&dj, 1); /* Allocate an entry */ + if (res == FR_OK) { + memset(dj.dir, 0, SZDIRE); /* Clean the entry */ + if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { + dj.dir[XDIR_Type] = ET_VLABEL; /* Create volume label entry */ + dj.dir[XDIR_NumLabel] = (BYTE)di; + memcpy(dj.dir + XDIR_Label, dirvn, 22); + } else { + dj.dir[DIR_Attr] = AM_VOL; /* Create volume label entry */ + memcpy(dj.dir, dirvn, 11); + } + fs->wflag = 1; + res = sync_fs(fs); + } + } + } + } + } + + LEAVE_FF(fs, res); +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_USE_LABEL */ + + + +#if FF_USE_EXPAND && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Allocate a Contiguous Blocks to the File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_expand ( + FIL* fp, /* Pointer to the file object */ + FSIZE_t fsz, /* File size to be expanded to */ + BYTE opt /* Operation mode 0:Find and prepare or 1:Find and allocate */ +) +{ + FRESULT res; + FATFS *fs; + DWORD n, clst, stcl, scl, ncl, tcl, lclst; + + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); + if (fsz == 0 || fp->obj.objsize != 0 || !(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); +#if FF_FS_EXFAT + if (fs->fs_type != FS_EXFAT && fsz >= 0x100000000) LEAVE_FF(fs, FR_DENIED); /* Check if in size limit */ +#endif + n = (DWORD)fs->csize * SS(fs); /* Cluster size */ + tcl = (DWORD)(fsz / n) + ((fsz & (n - 1)) ? 1 : 0); /* Number of clusters required */ + stcl = fs->last_clst; lclst = 0; + if (stcl < 2 || stcl >= fs->n_fatent) stcl = 2; + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + scl = find_bitmap(fs, stcl, tcl); /* Find a contiguous cluster block */ + if (scl == 0) res = FR_DENIED; /* No contiguous cluster block was found */ + if (scl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (res == FR_OK) { /* A contiguous free area is found */ + if (opt) { /* Allocate it now */ + res = change_bitmap(fs, scl, tcl, 1); /* Mark the cluster block 'in use' */ + lclst = scl + tcl - 1; + } else { /* Set it as suggested point for next allocation */ + lclst = scl - 1; + } + } + } else +#endif + { + scl = clst = stcl; ncl = 0; + for (;;) { /* Find a contiguous cluster block */ + n = get_fat(&fp->obj, clst); + if (++clst >= fs->n_fatent) clst = 2; + if (n == 1) { res = FR_INT_ERR; break; } + if (n == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } + if (n == 0) { /* Is it a free cluster? */ + if (++ncl == tcl) break; /* Break if a contiguous cluster block is found */ + } else { + scl = clst; ncl = 0; /* Not a free cluster */ + } + if (clst == stcl) { res = FR_DENIED; break; } /* No contiguous cluster? */ + } + if (res == FR_OK) { /* A contiguous free area is found */ + if (opt) { /* Allocate it now */ + for (clst = scl, n = tcl; n; clst++, n--) { /* Create a cluster chain on the FAT */ + res = put_fat(fs, clst, (n == 1) ? 0xFFFFFFFF : clst + 1); + if (res != FR_OK) break; + lclst = clst; + } + } else { /* Set it as suggested point for next allocation */ + lclst = scl - 1; + } + } + } + + if (res == FR_OK) { + fs->last_clst = lclst; /* Set suggested start cluster to start next */ + if (opt) { /* Is it allocated now? */ + fp->obj.sclust = scl; /* Update object allocation information */ + fp->obj.objsize = fsz; + if (FF_FS_EXFAT) fp->obj.stat = 2; /* Set status 'contiguous chain' */ + fp->flag |= FA_MODIFIED; + if (fs->free_clst <= fs->n_fatent - 2) { /* Update FSINFO */ + fs->free_clst -= tcl; + fs->fsi_flag |= 1; + } + } + } + + LEAVE_FF(fs, res); +} + +#endif /* FF_USE_EXPAND && !FF_FS_READONLY */ + + + +#if FF_USE_FORWARD +/*-----------------------------------------------------------------------*/ +/* Forward Data to the Stream Directly */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_forward ( + FIL* fp, /* Pointer to the file object */ + UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ + UINT btf, /* Number of bytes to forward */ + UINT* bf /* Pointer to number of bytes forwarded */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst; + LBA_t sect; + FSIZE_t remain; + UINT rcnt, csect; + BYTE *dbuf; + + + *bf = 0; /* Clear transfer byte counter */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); + if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + + remain = fp->obj.objsize - fp->fptr; + if (btf > remain) btf = (UINT)remain; /* Truncate btf by remaining bytes */ + + for ( ; btf > 0 && (*func)(0, 0); fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) { /* Repeat until all data transferred or stream goes busy */ + csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ + if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ + if (csect == 0) { /* On the cluster boundary? */ + clst = (fp->fptr == 0) ? /* On the top of the file? */ + fp->obj.sclust : get_fat(&fp->obj, fp->clust); + if (clst <= 1) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + } + sect = clst2sect(fs, fp->clust); /* Get current data sector */ + if (sect == 0) ABORT(fs, FR_INT_ERR); + sect += csect; +#if FF_FS_TINY + if (move_window(fs, sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window to the file data */ + dbuf = fs->win; +#else + if (fp->sect != sect) { /* Fill sector cache with file data */ +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + } + dbuf = fp->buf; +#endif + fp->sect = sect; + rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes remains in the sector */ + if (rcnt > btf) rcnt = btf; /* Clip it by btr if needed */ + rcnt = (*func)(dbuf + ((UINT)fp->fptr % SS(fs)), rcnt); /* Forward the file data */ + if (rcnt == 0) ABORT(fs, FR_INT_ERR); + } + + LEAVE_FF(fs, FR_OK); +} +#endif /* FF_USE_FORWARD */ + + + +#if !FF_FS_READONLY && FF_USE_MKFS +/*-----------------------------------------------------------------------*/ +/* Create FAT/exFAT volume (with sub-functions) */ +/*-----------------------------------------------------------------------*/ + +#define N_SEC_TRACK 63 /* Sectors per track for determination of drive CHS */ +#define GPT_ALIGN 0x100000 /* Alignment of partitions in GPT [byte] (>=128KB) */ +#define GPT_ITEMS 128 /* Number of GPT table size (>=128, sector aligned) */ + + +/* Create partitions on the physical drive in format of MBR or GPT */ + +static FRESULT create_partition ( + BYTE drv, /* Physical drive number */ + const LBA_t plst[], /* Partition list */ + BYTE sys, /* System ID (for only MBR, temp setting) */ + BYTE* buf /* Working buffer for a sector */ +) +{ + UINT i, cy; + LBA_t sz_drv; + DWORD sz_drv32, nxt_alloc32, sz_part32; + BYTE *pte; + BYTE hd, n_hd, sc, n_sc; + + /* Get physical drive size */ + if (disk_ioctl(drv, GET_SECTOR_COUNT, &sz_drv) != RES_OK) return FR_DISK_ERR; + +#if FF_LBA64 + if (sz_drv >= FF_MIN_GPT) { /* Create partitions in GPT format */ + WORD ss; + UINT sz_ptbl, pi, si, ofs; + DWORD bcc, rnd, align; + QWORD nxt_alloc, sz_part, sz_pool, top_bpt; + static const BYTE gpt_mbr[16] = {0x00, 0x00, 0x02, 0x00, 0xEE, 0xFE, 0xFF, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; + +#if FF_MAX_SS != FF_MIN_SS + if (disk_ioctl(drv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; /* Get sector size */ + if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR; +#else + ss = FF_MAX_SS; +#endif + rnd = (DWORD)sz_drv + GET_FATTIME(); /* Random seed */ + align = GPT_ALIGN / ss; /* Partition alignment for GPT [sector] */ + sz_ptbl = GPT_ITEMS * SZ_GPTE / ss; /* Size of partition table [sector] */ + top_bpt = sz_drv - sz_ptbl - 1; /* Backup partiiton table start sector */ + nxt_alloc = 2 + sz_ptbl; /* First allocatable sector */ + sz_pool = top_bpt - nxt_alloc; /* Size of allocatable area */ + bcc = 0xFFFFFFFF; sz_part = 1; + pi = si = 0; /* partition table index, size table index */ + do { + if (pi * SZ_GPTE % ss == 0) memset(buf, 0, ss); /* Clean the buffer if needed */ + if (sz_part != 0) { /* Is the size table not termintated? */ + nxt_alloc = (nxt_alloc + align - 1) & ((QWORD)0 - align); /* Align partition start */ + sz_part = plst[si++]; /* Get a partition size */ + if (sz_part <= 100) { /* Is the size in percentage? */ + sz_part = sz_pool * sz_part / 100; + sz_part = (sz_part + align - 1) & ((QWORD)0 - align); /* Align partition end (only if in percentage) */ + } + if (nxt_alloc + sz_part > top_bpt) { /* Clip the size at end of the pool */ + sz_part = (nxt_alloc < top_bpt) ? top_bpt - nxt_alloc : 0; + } + } + if (sz_part != 0) { /* Add a partition? */ + ofs = pi * SZ_GPTE % ss; + memcpy(buf + ofs + GPTE_PtGuid, GUID_MS_Basic, 16); /* Set partition GUID (Microsoft Basic Data) */ + rnd = make_rand(rnd, buf + ofs + GPTE_UpGuid, 16); /* Set unique partition GUID */ + st_qword(buf + ofs + GPTE_FstLba, nxt_alloc); /* Set partition start sector */ + st_qword(buf + ofs + GPTE_LstLba, nxt_alloc + sz_part - 1); /* Set partition end sector */ + nxt_alloc += sz_part; /* Next allocatable sector */ + } + if ((pi + 1) * SZ_GPTE % ss == 0) { /* Write the buffer if it is filled up */ + for (i = 0; i < ss; bcc = crc32(bcc, buf[i++])) ; /* Calculate table check sum */ + if (disk_write(drv, buf, 2 + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR; /* Write to primary table */ + if (disk_write(drv, buf, top_bpt + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR; /* Write to secondary table */ + } + } while (++pi < GPT_ITEMS); + + /* Create primary GPT header */ + memset(buf, 0, ss); + memcpy(buf + GPTH_Sign, "EFI PART" "\0\0\1\0" "\x5C\0\0", 16); /* Signature, version (1.0) and size (92) */ + st_dword(buf + GPTH_PtBcc, ~bcc); /* Table check sum */ + st_qword(buf + GPTH_CurLba, 1); /* LBA of this header */ + st_qword(buf + GPTH_BakLba, sz_drv - 1); /* LBA of secondary header */ + st_qword(buf + GPTH_FstLba, 2 + sz_ptbl); /* LBA of first allocatable sector */ + st_qword(buf + GPTH_LstLba, top_bpt - 1); /* LBA of last allocatable sector */ + st_dword(buf + GPTH_PteSize, SZ_GPTE); /* Size of a table entry */ + st_dword(buf + GPTH_PtNum, GPT_ITEMS); /* Number of table entries */ + st_dword(buf + GPTH_PtOfs, 2); /* LBA of this table */ + rnd = make_rand(rnd, buf + GPTH_DskGuid, 16); /* Disk GUID */ + for (i = 0, bcc= 0xFFFFFFFF; i < 92; bcc = crc32(bcc, buf[i++])) ; /* Calculate header check sum */ + st_dword(buf + GPTH_Bcc, ~bcc); /* Header check sum */ + if (disk_write(drv, buf, 1, 1) != RES_OK) return FR_DISK_ERR; + + /* Create secondary GPT header */ + st_qword(buf + GPTH_CurLba, sz_drv - 1); /* LBA of this header */ + st_qword(buf + GPTH_BakLba, 1); /* LBA of primary header */ + st_qword(buf + GPTH_PtOfs, top_bpt); /* LBA of this table */ + st_dword(buf + GPTH_Bcc, 0); + for (i = 0, bcc= 0xFFFFFFFF; i < 92; bcc = crc32(bcc, buf[i++])) ; /* Calculate header check sum */ + st_dword(buf + GPTH_Bcc, ~bcc); /* Header check sum */ + if (disk_write(drv, buf, sz_drv - 1, 1) != RES_OK) return FR_DISK_ERR; + + /* Create protective MBR */ + memset(buf, 0, ss); + memcpy(buf + MBR_Table, gpt_mbr, 16); /* Create a GPT partition */ + st_word(buf + BS_55AA, 0xAA55); + if (disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; + + } else +#endif + { /* Create partitions in MBR format */ + sz_drv32 = (DWORD)sz_drv; + n_sc = N_SEC_TRACK; /* Determine drive CHS without any consideration of the drive geometry */ + for (n_hd = 8; n_hd != 0 && sz_drv32 / n_hd / n_sc > 1024; n_hd *= 2) ; + if (n_hd == 0) n_hd = 255; /* Number of heads needs to be <256 */ + + memset(buf, 0, FF_MAX_SS); /* Clear MBR */ + pte = buf + MBR_Table; /* Partition table in the MBR */ + for (i = 0, nxt_alloc32 = n_sc; i < 4 && nxt_alloc32 != 0 && nxt_alloc32 < sz_drv32; i++, nxt_alloc32 += sz_part32) { + sz_part32 = (DWORD)plst[i]; /* Get partition size */ + if (sz_part32 <= 100) sz_part32 = (sz_part32 == 100) ? sz_drv32 : sz_drv32 / 100 * sz_part32; /* Size in percentage? */ + if (nxt_alloc32 + sz_part32 > sz_drv32 || nxt_alloc32 + sz_part32 < nxt_alloc32) sz_part32 = sz_drv32 - nxt_alloc32; /* Clip at drive size */ + if (sz_part32 == 0) break; /* End of table or no sector to allocate? */ + + st_dword(pte + PTE_StLba, nxt_alloc32); /* Start LBA */ + st_dword(pte + PTE_SizLba, sz_part32); /* Number of sectors */ + pte[PTE_System] = sys; /* System type */ + + cy = (UINT)(nxt_alloc32 / n_sc / n_hd); /* Start cylinder */ + hd = (BYTE)(nxt_alloc32 / n_sc % n_hd); /* Start head */ + sc = (BYTE)(nxt_alloc32 % n_sc + 1); /* Start sector */ + pte[PTE_StHead] = hd; + pte[PTE_StSec] = (BYTE)((cy >> 2 & 0xC0) | sc); + pte[PTE_StCyl] = (BYTE)cy; + + cy = (UINT)((nxt_alloc32 + sz_part32 - 1) / n_sc / n_hd); /* End cylinder */ + hd = (BYTE)((nxt_alloc32 + sz_part32 - 1) / n_sc % n_hd); /* End head */ + sc = (BYTE)((nxt_alloc32 + sz_part32 - 1) % n_sc + 1); /* End sector */ + pte[PTE_EdHead] = hd; + pte[PTE_EdSec] = (BYTE)((cy >> 2 & 0xC0) | sc); + pte[PTE_EdCyl] = (BYTE)cy; + + pte += SZ_PTE; /* Next entry */ + } + + st_word(buf + BS_55AA, 0xAA55); /* MBR signature */ + if (disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Write it to the MBR */ + } + + return FR_OK; +} + + + +FRESULT f_mkfs ( + const TCHAR* path, /* Logical drive number */ + const MKFS_PARM* opt, /* Format options */ + void* work, /* Pointer to working buffer (null: use heap memory) */ + UINT len /* Size of working buffer [byte] */ +) +{ + static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT volume (4Ks unit) */ + static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128Ks unit) */ + static const MKFS_PARM defopt = {FM_ANY, 0, 0, 0, 0}; /* Default parameter */ + BYTE fsopt, fsty, sys, *buf, *pte, pdrv, ipart; + WORD ss; /* Sector size */ + DWORD sz_buf, sz_blk, n_clst, pau, nsect, n, vsn; + LBA_t sz_vol, b_vol, b_fat, b_data; /* Size of volume, Base LBA of volume, fat, data */ + LBA_t sect, lba[2]; + DWORD sz_rsv, sz_fat, sz_dir, sz_au; /* Size of reserved, fat, dir, data, cluster */ + UINT n_fat, n_root, i; /* Index, Number of FATs and Number of roor dir entries */ + int vol; + DSTATUS ds; + FRESULT fr; + + + /* Check mounted drive and clear work area */ + vol = get_ldnumber(&path); /* Get target logical drive */ + if (vol < 0) return FR_INVALID_DRIVE; + if (FatFs[vol]) FatFs[vol]->fs_type = 0; /* Clear the fs object if mounted */ + pdrv = LD2PD(vol); /* Physical drive */ + ipart = LD2PT(vol); /* Partition (0:create as new, 1..:get from partition table) */ + if (!opt) opt = &defopt; /* Use default parameter if it is not given */ + + /* Get physical drive status (sz_drv, sz_blk, ss) */ + ds = disk_initialize(pdrv); + if (ds & STA_NOINIT) return FR_NOT_READY; + if (ds & STA_PROTECT) return FR_WRITE_PROTECTED; + sz_blk = opt->align; + if (sz_blk == 0 && disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK) sz_blk = 1; + if (sz_blk == 0 || sz_blk > 0x8000 || (sz_blk & (sz_blk - 1))) sz_blk = 1; +#if FF_MAX_SS != FF_MIN_SS + if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; + if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR; +#else + ss = FF_MAX_SS; +#endif + /* Options for FAT sub-type and FAT parameters */ + fsopt = opt->fmt & (FM_ANY | FM_SFD); + n_fat = (opt->n_fat >= 1 && opt->n_fat <= 2) ? opt->n_fat : 1; + n_root = (opt->n_root >= 1 && opt->n_root <= 32768 && (opt->n_root % (ss / SZDIRE)) == 0) ? opt->n_root : 512; + sz_au = (opt->au_size <= 0x1000000 && (opt->au_size & (opt->au_size - 1)) == 0) ? opt->au_size : 0; + sz_au /= ss; /* Byte --> Sector */ + + /* Get working buffer */ + sz_buf = len / ss; /* Size of working buffer [sector] */ + if (sz_buf == 0) return FR_NOT_ENOUGH_CORE; + buf = (BYTE*)work; /* Working buffer */ +#if FF_USE_LFN == 3 + if (!buf) buf = ff_memalloc(sz_buf * ss); /* Use heap memory for working buffer */ +#endif + if (!buf) return FR_NOT_ENOUGH_CORE; + + /* Determine where the volume to be located (b_vol, sz_vol) */ + b_vol = sz_vol = 0; + if (FF_MULTI_PARTITION && ipart != 0) { /* Is the volume associated with any specific partition? */ + /* Get partition location from the existing partition table */ + if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load MBR */ + if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if MBR is valid */ +#if FF_LBA64 + if (buf[MBR_Table + PTE_System] == 0xEE) { /* GPT protective MBR? */ + DWORD n_ent, ofs; + QWORD pt_lba; + + /* Get the partition location from GPT */ + if (disk_read(pdrv, buf, 1, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load GPT header sector (next to MBR) */ + if (!test_gpt_header(buf)) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if GPT header is valid */ + n_ent = ld_dword(buf + GPTH_PtNum); /* Number of entries */ + pt_lba = ld_qword(buf + GPTH_PtOfs); /* Table start sector */ + ofs = i = 0; + while (n_ent) { /* Find MS Basic partition with order of ipart */ + if (ofs == 0 && disk_read(pdrv, buf, pt_lba++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Get PT sector */ + if (!memcmp(buf + ofs + GPTE_PtGuid, GUID_MS_Basic, 16) && ++i == ipart) { /* MS basic data partition? */ + b_vol = ld_qword(buf + ofs + GPTE_FstLba); + sz_vol = ld_qword(buf + ofs + GPTE_LstLba) - b_vol + 1; + break; + } + n_ent--; ofs = (ofs + SZ_GPTE) % ss; /* Next entry */ + } + if (n_ent == 0) LEAVE_MKFS(FR_MKFS_ABORTED); /* Partition not found */ + fsopt |= 0x80; /* Partitioning is in GPT */ + } else +#endif + { /* Get the partition location from MBR partition table */ + pte = buf + (MBR_Table + (ipart - 1) * SZ_PTE); + if (ipart > 4 || pte[PTE_System] == 0) LEAVE_MKFS(FR_MKFS_ABORTED); /* No partition? */ + b_vol = ld_dword(pte + PTE_StLba); /* Get volume start sector */ + sz_vol = ld_dword(pte + PTE_SizLba); /* Get volume size */ + } + } else { /* The volume is associated with a physical drive */ + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + if (!(fsopt & FM_SFD)) { /* To be partitioned? */ + /* Create a single-partition on the drive in this function */ +#if FF_LBA64 + if (sz_vol >= FF_MIN_GPT) { /* Which partition type to create, MBR or GPT? */ + fsopt |= 0x80; /* Partitioning is in GPT */ + b_vol = GPT_ALIGN / ss; sz_vol -= b_vol + GPT_ITEMS * SZ_GPTE / ss + 1; /* Estimated partition offset and size */ + } else +#endif + { /* Partitioning is in MBR */ + if (sz_vol > N_SEC_TRACK) { + b_vol = N_SEC_TRACK; sz_vol -= b_vol; /* Estimated partition offset and size */ + } + } + } + } + if (sz_vol < 128) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >=128s */ + + /* Now start to create an FAT volume at b_vol and sz_vol */ + + do { /* Pre-determine the FAT type */ + if (FF_FS_EXFAT && (fsopt & FM_EXFAT)) { /* exFAT possible? */ + if ((fsopt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || sz_au > 128) { /* exFAT only, vol >= 64MS or sz_au > 128S ? */ + fsty = FS_EXFAT; break; + } + } +#if FF_LBA64 + if (sz_vol >= 0x100000000) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too large volume for FAT/FAT32 */ +#endif + if (sz_au > 128) sz_au = 128; /* Invalid AU for FAT/FAT32? */ + if (fsopt & FM_FAT32) { /* FAT32 possible? */ + if (!(fsopt & FM_FAT)) { /* no-FAT? */ + fsty = FS_FAT32; break; + } + } + if (!(fsopt & FM_FAT)) LEAVE_MKFS(FR_INVALID_PARAMETER); /* no-FAT? */ + fsty = FS_FAT16; + } while (0); + + vsn = (DWORD)sz_vol + GET_FATTIME(); /* VSN generated from current time and partitiion size */ + +#if FF_FS_EXFAT + if (fsty == FS_EXFAT) { /* Create an exFAT volume */ + DWORD szb_bit, szb_case, sum, nbit, clu, clen[3]; + WCHAR ch, si; + UINT j, st; + + if (sz_vol < 0x1000) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume for exFAT? */ +#if FF_USE_TRIM + lba[0] = b_vol; lba[1] = b_vol + sz_vol - 1; /* Inform storage device that the volume area may be erased */ + disk_ioctl(pdrv, CTRL_TRIM, lba); +#endif + /* Determine FAT location, data location and number of clusters */ + if (sz_au == 0) { /* AU auto-selection */ + sz_au = 8; + if (sz_vol >= 0x80000) sz_au = 64; /* >= 512Ks */ + if (sz_vol >= 0x4000000) sz_au = 256; /* >= 64Ms */ + } + b_fat = b_vol + 32; /* FAT start at offset 32 */ + sz_fat = (DWORD)((sz_vol / sz_au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */ + b_data = (b_fat + sz_fat + sz_blk - 1) & ~((LBA_t)sz_blk - 1); /* Align data area to the erase block boundary */ + if (b_data - b_vol >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ + n_clst = (DWORD)(sz_vol - (b_data - b_vol)) / sz_au; /* Number of clusters */ + if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too few clusters? */ + if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters? */ + + szb_bit = (n_clst + 7) / 8; /* Size of allocation bitmap */ + clen[0] = (szb_bit + sz_au * ss - 1) / (sz_au * ss); /* Number of allocation bitmap clusters */ + + /* Create a compressed up-case table */ + sect = b_data + sz_au * clen[0]; /* Table start sector */ + sum = 0; /* Table checksum to be stored in the 82 entry */ + st = 0; si = 0; i = 0; j = 0; szb_case = 0; + do { + switch (st) { + case 0: + ch = (WCHAR)ff_wtoupper(si); /* Get an up-case char */ + if (ch != si) { + si++; break; /* Store the up-case char if exist */ + } + for (j = 1; (WCHAR)(si + j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) ; /* Get run length of no-case block */ + if (j >= 128) { + ch = 0xFFFF; st = 2; break; /* Compress the no-case block if run is >= 128 chars */ + } + st = 1; /* Do not compress short run */ + /* FALLTHROUGH */ + case 1: + ch = si++; /* Fill the short run */ + if (--j == 0) st = 0; + break; + + default: + ch = (WCHAR)j; si += (WCHAR)j; /* Number of chars to skip */ + st = 0; + } + sum = xsum32(buf[i + 0] = (BYTE)ch, sum); /* Put it into the write buffer */ + sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum); + i += 2; szb_case += 2; + if (si == 0 || i == sz_buf * ss) { /* Write buffered data when buffer full or end of process */ + n = (i + ss - 1) / ss; + if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + sect += n; i = 0; + } + } while (si); + clen[1] = (szb_case + sz_au * ss - 1) / (sz_au * ss); /* Number of up-case table clusters */ + clen[2] = 1; /* Number of root dir clusters */ + + /* Initialize the allocation bitmap */ + sect = b_data; nsect = (szb_bit + ss - 1) / ss; /* Start of bitmap and number of bitmap sectors */ + nbit = clen[0] + clen[1] + clen[2]; /* Number of clusters in-use by system (bitmap, up-case and root-dir) */ + do { + memset(buf, 0, sz_buf * ss); /* Initialize bitmap buffer */ + for (i = 0; nbit != 0 && i / 8 < sz_buf * ss; buf[i / 8] |= 1 << (i % 8), i++, nbit--) ; /* Mark used clusters */ + n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ + if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + sect += n; nsect -= n; + } while (nsect); + + /* Initialize the FAT */ + sect = b_fat; nsect = sz_fat; /* Start of FAT and number of FAT sectors */ + j = nbit = clu = 0; + do { + memset(buf, 0, sz_buf * ss); i = 0; /* Clear work area and reset write offset */ + if (clu == 0) { /* Initialize FAT [0] and FAT[1] */ + st_dword(buf + i, 0xFFFFFFF8); i += 4; clu++; + st_dword(buf + i, 0xFFFFFFFF); i += 4; clu++; + } + do { /* Create chains of bitmap, up-case and root dir */ + while (nbit != 0 && i < sz_buf * ss) { /* Create a chain */ + st_dword(buf + i, (nbit > 1) ? clu + 1 : 0xFFFFFFFF); + i += 4; clu++; nbit--; + } + if (nbit == 0 && j < 3) nbit = clen[j++]; /* Get next chain length */ + } while (nbit != 0 && i < sz_buf * ss); + n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ + if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + sect += n; nsect -= n; + } while (nsect); + + /* Initialize the root directory */ + memset(buf, 0, sz_buf * ss); + buf[SZDIRE * 0 + 0] = ET_VLABEL; /* Volume label entry (no label) */ + buf[SZDIRE * 1 + 0] = ET_BITMAP; /* Bitmap entry */ + st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */ + st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */ + buf[SZDIRE * 2 + 0] = ET_UPCASE; /* Up-case table entry */ + st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */ + st_dword(buf + SZDIRE * 2 + 20, 2 + clen[0]); /* cluster */ + st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */ + sect = b_data + sz_au * (clen[0] + clen[1]); nsect = sz_au; /* Start of the root directory and number of sectors */ + do { /* Fill root directory sectors */ + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + memset(buf, 0, ss); /* Rest of entries are filled with zero */ + sect += n; nsect -= n; + } while (nsect); + + /* Create two set of the exFAT VBR blocks */ + sect = b_vol; + for (n = 0; n < 2; n++) { + /* Main record (+0) */ + memset(buf, 0, ss); + memcpy(buf + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11); /* Boot jump code (x86), OEM name */ + st_qword(buf + BPB_VolOfsEx, b_vol); /* Volume offset in the physical drive [sector] */ + st_qword(buf + BPB_TotSecEx, sz_vol); /* Volume size [sector] */ + st_dword(buf + BPB_FatOfsEx, (DWORD)(b_fat - b_vol)); /* FAT offset [sector] */ + st_dword(buf + BPB_FatSzEx, sz_fat); /* FAT size [sector] */ + st_dword(buf + BPB_DataOfsEx, (DWORD)(b_data - b_vol)); /* Data offset [sector] */ + st_dword(buf + BPB_NumClusEx, n_clst); /* Number of clusters */ + st_dword(buf + BPB_RootClusEx, 2 + clen[0] + clen[1]); /* Root dir cluster # */ + st_dword(buf + BPB_VolIDEx, vsn); /* VSN */ + st_word(buf + BPB_FSVerEx, 0x100); /* Filesystem version (1.00) */ + for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ; /* Log2 of sector size [byte] */ + for (buf[BPB_SecPerClusEx] = 0, i = sz_au; i >>= 1; buf[BPB_SecPerClusEx]++) ; /* Log2 of cluster size [sector] */ + buf[BPB_NumFATsEx] = 1; /* Number of FATs */ + buf[BPB_DrvNumEx] = 0x80; /* Drive number (for int13) */ + st_word(buf + BS_BootCodeEx, 0xFEEB); /* Boot code (x86) */ + st_word(buf + BS_55AA, 0xAA55); /* Signature (placed here regardless of sector size) */ + for (i = sum = 0; i < ss; i++) { /* VBR checksum */ + if (i != BPB_VolFlagEx && i != BPB_VolFlagEx + 1 && i != BPB_PercInUseEx) sum = xsum32(buf[i], sum); + } + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + /* Extended bootstrap record (+1..+8) */ + memset(buf, 0, ss); + st_word(buf + ss - 2, 0xAA55); /* Signature (placed at end of sector) */ + for (j = 1; j < 9; j++) { + for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + } + /* OEM/Reserved record (+9..+10) */ + memset(buf, 0, ss); + for ( ; j < 11; j++) { + for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + } + /* Sum record (+11) */ + for (i = 0; i < ss; i += 4) st_dword(buf + i, sum); /* Fill with checksum value */ + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + } + + } else +#endif /* FF_FS_EXFAT */ + { /* Create an FAT/FAT32 volume */ + do { + pau = sz_au; + /* Pre-determine number of clusters and FAT sub-type */ + if (fsty == FS_FAT32) { /* FAT32 volume */ + if (pau == 0) { /* AU auto-selection */ + n = (DWORD)sz_vol / 0x20000; /* Volume size in unit of 128KS */ + for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) ; /* Get from table */ + } + n_clst = (DWORD)sz_vol / pau; /* Number of clusters */ + sz_fat = (n_clst * 4 + 8 + ss - 1) / ss; /* FAT size [sector] */ + sz_rsv = 32; /* Number of reserved sectors */ + sz_dir = 0; /* No static directory */ + if (n_clst <= MAX_FAT16 || n_clst > MAX_FAT32) LEAVE_MKFS(FR_MKFS_ABORTED); + } else { /* FAT volume */ + if (pau == 0) { /* au auto-selection */ + n = (DWORD)sz_vol / 0x1000; /* Volume size in unit of 4KS */ + for (i = 0, pau = 1; cst[i] && cst[i] <= n; i++, pau <<= 1) ; /* Get from table */ + } + n_clst = (DWORD)sz_vol / pau; + if (n_clst > MAX_FAT12) { + n = n_clst * 2 + 4; /* FAT size [byte] */ + } else { + fsty = FS_FAT12; + n = (n_clst * 3 + 1) / 2 + 3; /* FAT size [byte] */ + } + sz_fat = (n + ss - 1) / ss; /* FAT size [sector] */ + sz_rsv = 1; /* Number of reserved sectors */ + sz_dir = (DWORD)n_root * SZDIRE / ss; /* Root dir size [sector] */ + } + b_fat = b_vol + sz_rsv; /* FAT base */ + b_data = b_fat + sz_fat * n_fat + sz_dir; /* Data base */ + + /* Align data area to erase block boundary (for flash memory media) */ + n = (DWORD)(((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data); /* Sectors to next nearest from current data base */ + if (fsty == FS_FAT32) { /* FAT32: Move FAT */ + sz_rsv += n; b_fat += n; + } else { /* FAT: Expand FAT */ + if (n % n_fat) { /* Adjust fractional error if needed */ + n--; sz_rsv++; b_fat++; + } + sz_fat += n / n_fat; + } + + /* Determine number of clusters and final check of validity of the FAT sub-type */ + if (sz_vol < b_data + pau * 16 - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ + n_clst = ((DWORD)sz_vol - sz_rsv - sz_fat * n_fat - sz_dir) / pau; + if (fsty == FS_FAT32) { + if (n_clst <= MAX_FAT16) { /* Too few clusters for FAT32? */ + if (sz_au == 0 && (sz_au = pau / 2) != 0) continue; /* Adjust cluster size and retry */ + LEAVE_MKFS(FR_MKFS_ABORTED); + } + } + if (fsty == FS_FAT16) { + if (n_clst > MAX_FAT16) { /* Too many clusters for FAT16 */ + if (sz_au == 0 && (pau * 2) <= 64) { + sz_au = pau * 2; continue; /* Adjust cluster size and retry */ + } + if ((fsopt & FM_FAT32)) { + fsty = FS_FAT32; continue; /* Switch type to FAT32 and retry */ + } + if (sz_au == 0 && (sz_au = pau * 2) <= 128) continue; /* Adjust cluster size and retry */ + LEAVE_MKFS(FR_MKFS_ABORTED); + } + if (n_clst <= MAX_FAT12) { /* Too few clusters for FAT16 */ + if (sz_au == 0 && (sz_au = pau * 2) <= 128) continue; /* Adjust cluster size and retry */ + LEAVE_MKFS(FR_MKFS_ABORTED); + } + } + if (fsty == FS_FAT12 && n_clst > MAX_FAT12) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters for FAT12 */ + + /* Ok, it is the valid cluster configuration */ + break; + } while (1); + +#if FF_USE_TRIM + lba[0] = b_vol; lba[1] = b_vol + sz_vol - 1; /* Inform storage device that the volume area may be erased */ + disk_ioctl(pdrv, CTRL_TRIM, lba); +#endif + /* Create FAT VBR */ + memset(buf, 0, ss); + memcpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11); /* Boot jump code (x86), OEM name */ + st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */ + buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */ + st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */ + buf[BPB_NumFATs] = (BYTE)n_fat; /* Number of FATs */ + st_word(buf + BPB_RootEntCnt, (WORD)((fsty == FS_FAT32) ? 0 : n_root)); /* Number of root directory entries */ + if (sz_vol < 0x10000) { + st_word(buf + BPB_TotSec16, (WORD)sz_vol); /* Volume size in 16-bit LBA */ + } else { + st_dword(buf + BPB_TotSec32, (DWORD)sz_vol); /* Volume size in 32-bit LBA */ + } + buf[BPB_Media] = 0xF8; /* Media descriptor byte */ + st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */ + st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */ + st_dword(buf + BPB_HiddSec, (DWORD)b_vol); /* Volume offset in the physical drive [sector] */ + if (fsty == FS_FAT32) { + st_dword(buf + BS_VolID32, vsn); /* VSN */ + st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */ + st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */ + st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */ + st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */ + buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */ + buf[BS_BootSig32] = 0x29; /* Extended boot signature */ + memcpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ + } else { + st_dword(buf + BS_VolID, vsn); /* VSN */ + st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */ + buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */ + buf[BS_BootSig] = 0x29; /* Extended boot signature */ + memcpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ + } + st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */ + if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */ + + /* Create FSINFO record if needed */ + if (fsty == FS_FAT32) { + disk_write(pdrv, buf, b_vol + 6, 1); /* Write backup VBR (VBR + 6) */ + memset(buf, 0, ss); + st_dword(buf + FSI_LeadSig, 0x41615252); + st_dword(buf + FSI_StrucSig, 0x61417272); + st_dword(buf + FSI_Free_Count, n_clst - 1); /* Number of free clusters */ + st_dword(buf + FSI_Nxt_Free, 2); /* Last allocated cluster# */ + st_word(buf + BS_55AA, 0xAA55); + disk_write(pdrv, buf, b_vol + 7, 1); /* Write backup FSINFO (VBR + 7) */ + disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */ + } + + /* Initialize FAT area */ + memset(buf, 0, sz_buf * ss); + sect = b_fat; /* FAT start sector */ + for (i = 0; i < n_fat; i++) { /* Initialize FATs each */ + if (fsty == FS_FAT32) { + st_dword(buf + 0, 0xFFFFFFF8); /* FAT[0] */ + st_dword(buf + 4, 0xFFFFFFFF); /* FAT[1] */ + st_dword(buf + 8, 0x0FFFFFFF); /* FAT[2] (root directory) */ + } else { + st_dword(buf + 0, (fsty == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8); /* FAT[0] and FAT[1] */ + } + nsect = sz_fat; /* Number of FAT sectors */ + do { /* Fill FAT sectors */ + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + memset(buf, 0, ss); /* Rest of FAT all are cleared */ + sect += n; nsect -= n; + } while (nsect); + } + + /* Initialize root directory (fill with zero) */ + nsect = (fsty == FS_FAT32) ? pau : sz_dir; /* Number of root directory sectors */ + do { + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + sect += n; nsect -= n; + } while (nsect); + } + + /* A FAT volume has been created here */ + + /* Determine system ID in the MBR partition table */ + if (FF_FS_EXFAT && fsty == FS_EXFAT) { + sys = 0x07; /* exFAT */ + } else { + if (fsty == FS_FAT32) { + sys = 0x0C; /* FAT32X */ + } else { + if (sz_vol >= 0x10000) { + sys = 0x06; /* FAT12/16 (large) */ + } else { + sys = (fsty == FS_FAT16) ? 0x04 : 0x01; /* FAT16 : FAT12 */ + } + } + } + + /* Update partition information */ + if (FF_MULTI_PARTITION && ipart != 0) { /* Volume is in the existing partition */ + if (!FF_LBA64 || !(fsopt & 0x80)) { + /* Update system ID in the partition table */ + if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Read the MBR */ + buf[MBR_Table + (ipart - 1) * SZ_PTE + PTE_System] = sys; /* Set system ID */ + if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it back to the MBR */ + } + } else { /* Volume as a new single partition */ + if (!(fsopt & FM_SFD)) { /* Create partition table if not in SFD */ + lba[0] = sz_vol; lba[1] = 0; + fr = create_partition(pdrv, lba, sys, buf); + if (fr != FR_OK) LEAVE_MKFS(fr); + } + } + + if (disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); + + LEAVE_MKFS(FR_OK); +} + + + + +#if FF_MULTI_PARTITION +/*-----------------------------------------------------------------------*/ +/* Create Partition Table on the Physical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_fdisk ( + BYTE pdrv, /* Physical drive number */ + const LBA_t ptbl[], /* Pointer to the size table for each partitions */ + void* work /* Pointer to the working buffer (null: use heap memory) */ +) +{ + BYTE *buf = (BYTE*)work; + DSTATUS stat; + + + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; +#if FF_USE_LFN == 3 + if (!buf) buf = ff_memalloc(FF_MAX_SS); /* Use heap memory for working buffer */ +#endif + if (!buf) return FR_NOT_ENOUGH_CORE; + + LEAVE_MKFS(create_partition(pdrv, ptbl, 0x07, buf)); +} + +#endif /* FF_MULTI_PARTITION */ +#endif /* !FF_FS_READONLY && FF_USE_MKFS */ + + + + +#if FF_USE_STRFUNC +#if FF_USE_LFN && FF_LFN_UNICODE && (FF_STRF_ENCODE < 0 || FF_STRF_ENCODE > 3) +#error Wrong FF_STRF_ENCODE setting +#endif +/*-----------------------------------------------------------------------*/ +/* Get a String from the File */ +/*-----------------------------------------------------------------------*/ + +TCHAR* f_gets ( + TCHAR* buff, /* Pointer to the buffer to store read string */ + int len, /* Size of string buffer (items) */ + FIL* fp /* Pointer to the file object */ +) +{ + int nc = 0; + TCHAR *p = buff; + BYTE s[4]; + UINT rc; + DWORD dc; +#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE <= 2 + WCHAR wc; +#endif +#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE == 3 + UINT ct; +#endif + +#if FF_USE_LFN && FF_LFN_UNICODE /* With code conversion (Unicode API) */ + /* Make a room for the character and terminator */ + if (FF_LFN_UNICODE == 1) len -= (FF_STRF_ENCODE == 0) ? 1 : 2; + if (FF_LFN_UNICODE == 2) len -= (FF_STRF_ENCODE == 0) ? 3 : 4; + if (FF_LFN_UNICODE == 3) len -= 1; + while (nc < len) { +#if FF_STRF_ENCODE == 0 /* Read a character in ANSI/OEM */ + f_read(fp, s, 1, &rc); /* Get a code unit */ + if (rc != 1) break; /* EOF? */ + wc = s[0]; + if (dbc_1st((BYTE)wc)) { /* DBC 1st byte? */ + f_read(fp, s, 1, &rc); /* Get 2nd byte */ + if (rc != 1 || !dbc_2nd(s[0])) continue; /* Wrong code? */ + wc = wc << 8 | s[0]; + } + dc = ff_oem2uni(wc, CODEPAGE); /* Convert ANSI/OEM into Unicode */ + if (dc == 0) continue; /* Conversion error? */ +#elif FF_STRF_ENCODE == 1 || FF_STRF_ENCODE == 2 /* Read a character in UTF-16LE/BE */ + f_read(fp, s, 2, &rc); /* Get a code unit */ + if (rc != 2) break; /* EOF? */ + dc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1]; + if (IsSurrogateL(dc)) continue; /* Broken surrogate pair? */ + if (IsSurrogateH(dc)) { /* High surrogate? */ + f_read(fp, s, 2, &rc); /* Get low surrogate */ + if (rc != 2) break; /* EOF? */ + wc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1]; + if (!IsSurrogateL(wc)) continue; /* Broken surrogate pair? */ + dc = ((dc & 0x3FF) + 0x40) << 10 | (wc & 0x3FF); /* Merge surrogate pair */ + } +#else /* Read a character in UTF-8 */ + f_read(fp, s, 1, &rc); /* Get a code unit */ + if (rc != 1) break; /* EOF? */ + dc = s[0]; + if (dc >= 0x80) { /* Multi-byte sequence? */ + ct = 0; + if ((dc & 0xE0) == 0xC0) { dc &= 0x1F; ct = 1; } /* 2-byte sequence? */ + if ((dc & 0xF0) == 0xE0) { dc &= 0x0F; ct = 2; } /* 3-byte sequence? */ + if ((dc & 0xF8) == 0xF0) { dc &= 0x07; ct = 3; } /* 4-byte sequence? */ + if (ct == 0) continue; + f_read(fp, s, ct, &rc); /* Get trailing bytes */ + if (rc != ct) break; + rc = 0; + do { /* Merge the byte sequence */ + if ((s[rc] & 0xC0) != 0x80) break; + dc = dc << 6 | (s[rc] & 0x3F); + } while (++rc < ct); + if (rc != ct || dc < 0x80 || IsSurrogate(dc) || dc >= 0x110000) continue; /* Wrong encoding? */ + } +#endif + /* A code point is avaialble in dc to be output */ + + if (FF_USE_STRFUNC == 2 && dc == '\r') continue; /* Strip \r off if needed */ +#if FF_LFN_UNICODE == 1 || FF_LFN_UNICODE == 3 /* Output it in UTF-16/32 encoding */ + if (FF_LFN_UNICODE == 1 && dc >= 0x10000) { /* Out of BMP at UTF-16? */ + *p++ = (TCHAR)(0xD800 | ((dc >> 10) - 0x40)); nc++; /* Make and output high surrogate */ + dc = 0xDC00 | (dc & 0x3FF); /* Make low surrogate */ + } + *p++ = (TCHAR)dc; nc++; + if (dc == '\n') break; /* End of line? */ +#elif FF_LFN_UNICODE == 2 /* Output it in UTF-8 encoding */ + if (dc < 0x80) { /* Single byte? */ + *p++ = (TCHAR)dc; + nc++; + if (dc == '\n') break; /* End of line? */ + } else { + if (dc < 0x800) { /* 2-byte sequence? */ + *p++ = (TCHAR)(0xC0 | (dc >> 6 & 0x1F)); + *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); + nc += 2; + } else { + if (dc < 0x10000) { /* 3-byte sequence? */ + *p++ = (TCHAR)(0xE0 | (dc >> 12 & 0x0F)); + *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F)); + *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); + nc += 3; + } else { /* 4-byte sequence? */ + *p++ = (TCHAR)(0xF0 | (dc >> 18 & 0x07)); + *p++ = (TCHAR)(0x80 | (dc >> 12 & 0x3F)); + *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F)); + *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); + nc += 4; + } + } + } +#endif + } + +#else /* Byte-by-byte read without any conversion (ANSI/OEM API) */ + len -= 1; /* Make a room for the terminator */ + while (nc < len) { + f_read(fp, s, 1, &rc); /* Get a byte */ + if (rc != 1) break; /* EOF? */ + dc = s[0]; + if (FF_USE_STRFUNC == 2 && dc == '\r') continue; + *p++ = (TCHAR)dc; nc++; + if (dc == '\n') break; + } +#endif + + *p = 0; /* Terminate the string */ + return nc ? buff : 0; /* When no data read due to EOF or error, return with error. */ +} + + + + +#if !FF_FS_READONLY +#include +#define SZ_PUTC_BUF 64 +#define SZ_NUM_BUF 32 + +/*-----------------------------------------------------------------------*/ +/* Put a Character to the File (with sub-functions) */ +/*-----------------------------------------------------------------------*/ + +/* Output buffer and work area */ + +typedef struct { + FIL *fp; /* Ptr to the writing file */ + int idx, nchr; /* Write index of buf[] (-1:error), number of encoding units written */ +#if FF_USE_LFN && FF_LFN_UNICODE == 1 + WCHAR hs; +#elif FF_USE_LFN && FF_LFN_UNICODE == 2 + BYTE bs[4]; + UINT wi, ct; +#endif + BYTE buf[SZ_PUTC_BUF]; /* Write buffer */ +} putbuff; + + +/* Buffered file write with code conversion */ + +static void putc_bfd (putbuff* pb, TCHAR c) +{ + UINT n; + int i, nc; +#if FF_USE_LFN && FF_LFN_UNICODE + WCHAR hs, wc; +#if FF_LFN_UNICODE == 2 + DWORD dc; + const TCHAR *tp; +#endif +#endif + + if (FF_USE_STRFUNC == 2 && c == '\n') { /* LF -> CRLF conversion */ + putc_bfd(pb, '\r'); + } + + i = pb->idx; /* Write index of pb->buf[] */ + if (i < 0) return; /* In write error? */ + nc = pb->nchr; /* Write unit counter */ + +#if FF_USE_LFN && FF_LFN_UNICODE +#if FF_LFN_UNICODE == 1 /* UTF-16 input */ + if (IsSurrogateH(c)) { /* High surrogate? */ + pb->hs = c; return; /* Save it for next */ + } + hs = pb->hs; pb->hs = 0; + if (hs != 0) { /* There is a leading high surrogate */ + if (!IsSurrogateL(c)) hs = 0; /* Discard high surrogate if not a surrogate pair */ + } else { + if (IsSurrogateL(c)) return; /* Discard stray low surrogate */ + } + wc = c; +#elif FF_LFN_UNICODE == 2 /* UTF-8 input */ + for (;;) { + if (pb->ct == 0) { /* Out of multi-byte sequence? */ + pb->bs[pb->wi = 0] = (BYTE)c; /* Save 1st byte */ + if ((BYTE)c < 0x80) break; /* Single byte? */ + if (((BYTE)c & 0xE0) == 0xC0) pb->ct = 1; /* 2-byte sequence? */ + if (((BYTE)c & 0xF0) == 0xE0) pb->ct = 2; /* 3-byte sequence? */ + if (((BYTE)c & 0xF1) == 0xF0) pb->ct = 3; /* 4-byte sequence? */ + return; + } else { /* In the multi-byte sequence */ + if (((BYTE)c & 0xC0) != 0x80) { /* Broken sequence? */ + pb->ct = 0; continue; + } + pb->bs[++pb->wi] = (BYTE)c; /* Save the trailing byte */ + if (--pb->ct == 0) break; /* End of multi-byte sequence? */ + return; + } + } + tp = (const TCHAR*)pb->bs; + dc = tchar2uni(&tp); /* UTF-8 ==> UTF-16 */ + if (dc == 0xFFFFFFFF) return; /* Wrong code? */ + wc = (WCHAR)dc; + hs = (WCHAR)(dc >> 16); +#elif FF_LFN_UNICODE == 3 /* UTF-32 input */ + if (IsSurrogate(c) || c >= 0x110000) return; /* Discard invalid code */ + if (c >= 0x10000) { /* Out of BMP? */ + hs = (WCHAR)(0xD800 | ((c >> 10) - 0x40)); /* Make high surrogate */ + wc = 0xDC00 | (c & 0x3FF); /* Make low surrogate */ + } else { + hs = 0; + wc = (WCHAR)c; + } +#endif + /* A code point in UTF-16 is available in hs and wc */ + +#if FF_STRF_ENCODE == 1 /* Write a code point in UTF-16LE */ + if (hs != 0) { /* Surrogate pair? */ + st_word(&pb->buf[i], hs); + i += 2; + nc++; + } + st_word(&pb->buf[i], wc); + i += 2; +#elif FF_STRF_ENCODE == 2 /* Write a code point in UTF-16BE */ + if (hs != 0) { /* Surrogate pair? */ + pb->buf[i++] = (BYTE)(hs >> 8); + pb->buf[i++] = (BYTE)hs; + nc++; + } + pb->buf[i++] = (BYTE)(wc >> 8); + pb->buf[i++] = (BYTE)wc; +#elif FF_STRF_ENCODE == 3 /* Write a code point in UTF-8 */ + if (hs != 0) { /* 4-byte sequence? */ + nc += 3; + hs = (hs & 0x3FF) + 0x40; + pb->buf[i++] = (BYTE)(0xF0 | hs >> 8); + pb->buf[i++] = (BYTE)(0x80 | (hs >> 2 & 0x3F)); + pb->buf[i++] = (BYTE)(0x80 | (hs & 3) << 4 | (wc >> 6 & 0x0F)); + pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); + } else { + if (wc < 0x80) { /* Single byte? */ + pb->buf[i++] = (BYTE)wc; + } else { + if (wc < 0x800) { /* 2-byte sequence? */ + nc += 1; + pb->buf[i++] = (BYTE)(0xC0 | wc >> 6); + } else { /* 3-byte sequence */ + nc += 2; + pb->buf[i++] = (BYTE)(0xE0 | wc >> 12); + pb->buf[i++] = (BYTE)(0x80 | (wc >> 6 & 0x3F)); + } + pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); + } + } +#else /* Write a code point in ANSI/OEM */ + if (hs != 0) return; + wc = ff_uni2oem(wc, CODEPAGE); /* UTF-16 ==> ANSI/OEM */ + if (wc == 0) return; + if (wc >= 0x100) { + pb->buf[i++] = (BYTE)(wc >> 8); nc++; + } + pb->buf[i++] = (BYTE)wc; +#endif + +#else /* ANSI/OEM input (without re-encoding) */ + pb->buf[i++] = (BYTE)c; +#endif + + if (i >= (int)(sizeof pb->buf) - 4) { /* Write buffered characters to the file */ + f_write(pb->fp, pb->buf, (UINT)i, &n); + i = (n == (UINT)i) ? 0 : -1; + } + pb->idx = i; + pb->nchr = nc + 1; +} + + +/* Flush remaining characters in the buffer */ + +static int putc_flush (putbuff* pb) +{ + UINT nw; + + if ( pb->idx >= 0 /* Flush buffered characters to the file */ + && f_write(pb->fp, pb->buf, (UINT)pb->idx, &nw) == FR_OK + && (UINT)pb->idx == nw) return pb->nchr; + return -1; +} + + +/* Initialize write buffer */ + +static void putc_init (putbuff* pb, FIL* fp) +{ + memset(pb, 0, sizeof (putbuff)); + pb->fp = fp; +} + + + +int f_putc ( + TCHAR c, /* A character to be output */ + FIL* fp /* Pointer to the file object */ +) +{ + putbuff pb; + + + putc_init(&pb, fp); + putc_bfd(&pb, c); /* Put the character */ + return putc_flush(&pb); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a String to the File */ +/*-----------------------------------------------------------------------*/ + +int f_puts ( + const TCHAR* str, /* Pointer to the string to be output */ + FIL* fp /* Pointer to the file object */ +) +{ + putbuff pb; + + + putc_init(&pb, fp); + while (*str) putc_bfd(&pb, *str++); /* Put the string */ + return putc_flush(&pb); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a Formatted String to the File (with sub-functions) */ +/*-----------------------------------------------------------------------*/ +#if FF_PRINT_FLOAT && FF_INTDEF == 2 +#include + +static int ilog10 (double n) /* Calculate log10(n) in integer output */ +{ + int rv = 0; + + while (n >= 10) { /* Decimate digit in right shift */ + if (n >= 100000) { + n /= 100000; rv += 5; + } else { + n /= 10; rv++; + } + } + while (n < 1) { /* Decimate digit in left shift */ + if (n < 0.00001) { + n *= 100000; rv -= 5; + } else { + n *= 10; rv--; + } + } + return rv; +} + + +static double i10x (int n) /* Calculate 10^n in integer input */ +{ + double rv = 1; + + while (n > 0) { /* Left shift */ + if (n >= 5) { + rv *= 100000; n -= 5; + } else { + rv *= 10; n--; + } + } + while (n < 0) { /* Right shift */ + if (n <= -5) { + rv /= 100000; n += 5; + } else { + rv /= 10; n++; + } + } + return rv; +} + + +static void ftoa ( + char* buf, /* Buffer to output the floating point string */ + double val, /* Value to output */ + int prec, /* Number of fractional digits */ + TCHAR fmt /* Notation */ +) +{ + int d; + int e = 0, m = 0; + char sign = 0; + double w; + const char *er = 0; + const char ds = FF_PRINT_FLOAT == 2 ? ',' : '.'; + + + if (isnan(val)) { /* Not a number? */ + er = "NaN"; + } else { + if (prec < 0) prec = 6; /* Default precision? (6 fractional digits) */ + if (val < 0) { /* Nagative? */ + val = 0 - val; sign = '-'; + } else { + sign = '+'; + } + if (isinf(val)) { /* Infinite? */ + er = "INF"; + } else { + if (fmt == 'f') { /* Decimal notation? */ + val += i10x(0 - prec) / 2; /* Round (nearest) */ + m = ilog10(val); + if (m < 0) m = 0; + if (m + prec + 3 >= SZ_NUM_BUF) er = "OV"; /* Buffer overflow? */ + } else { /* E notation */ + if (val != 0) { /* Not a true zero? */ + val += i10x(ilog10(val) - prec) / 2; /* Round (nearest) */ + e = ilog10(val); + if (e > 99 || prec + 7 >= SZ_NUM_BUF) { /* Buffer overflow or E > +99? */ + er = "OV"; + } else { + if (e < -99) e = -99; + val /= i10x(e); /* Normalize */ + } + } + } + } + if (!er) { /* Not error condition */ + if (sign == '-') *buf++ = sign; /* Add a - if negative value */ + do { /* Put decimal number */ + if (m == -1) *buf++ = ds; /* Insert a decimal separator when get into fractional part */ + w = i10x(m); /* Snip the highest digit d */ + d = (int)(val / w); val -= d * w; + *buf++ = (char)('0' + d); /* Put the digit */ + } while (--m >= -prec); /* Output all digits specified by prec */ + if (fmt != 'f') { /* Put exponent if needed */ + *buf++ = (char)fmt; + if (e < 0) { + e = 0 - e; *buf++ = '-'; + } else { + *buf++ = '+'; + } + *buf++ = (char)('0' + e / 10); + *buf++ = (char)('0' + e % 10); + } + } + } + if (er) { /* Error condition */ + if (sign) *buf++ = sign; /* Add sign if needed */ + do *buf++ = *er++; while (*er); /* Put error symbol */ + } + *buf = 0; /* Term */ +} +#endif /* FF_PRINT_FLOAT && FF_INTDEF == 2 */ + + + +int f_printf ( + FIL* fp, /* Pointer to the file object */ + const TCHAR* fmt, /* Pointer to the format string */ + ... /* Optional arguments... */ +) +{ + va_list arp; + putbuff pb; + UINT i, j, w, f, r; + int prec; +#if FF_PRINT_LLI && FF_INTDEF == 2 + QWORD v; +#else + DWORD v; +#endif + TCHAR tc, pad, *tp; + TCHAR nul = 0; + char d, str[SZ_NUM_BUF]; + + + putc_init(&pb, fp); + + va_start(arp, fmt); + + for (;;) { + tc = *fmt++; + if (tc == 0) break; /* End of format string */ + if (tc != '%') { /* Not an escape character (pass-through) */ + putc_bfd(&pb, tc); + continue; + } + f = w = 0; pad = ' '; prec = -1; /* Initialize parms */ + tc = *fmt++; + if (tc == '0') { /* Flag: '0' padded */ + pad = '0'; tc = *fmt++; + } else if (tc == '-') { /* Flag: Left aligned */ + f = 2; tc = *fmt++; + } + if (tc == '*') { /* Minimum width from an argument */ + w = va_arg(arp, int); + tc = *fmt++; + } else { + while (IsDigit(tc)) { /* Minimum width */ + w = w * 10 + tc - '0'; + tc = *fmt++; + } + } + if (tc == '.') { /* Precision */ + tc = *fmt++; + if (tc == '*') { /* Precision from an argument */ + prec = va_arg(arp, int); + tc = *fmt++; + } else { + prec = 0; + while (IsDigit(tc)) { /* Precision */ + prec = prec * 10 + tc - '0'; + tc = *fmt++; + } + } + } + if (tc == 'l') { /* Size: long int */ + f |= 4; tc = *fmt++; +#if FF_PRINT_LLI && FF_INTDEF == 2 + if (tc == 'l') { /* Size: long long int */ + f |= 8; tc = *fmt++; + } +#endif + } + if (tc == 0) break; /* End of format string */ + switch (tc) { /* Atgument type is... */ + case 'b': /* Unsigned binary */ + r = 2; break; + case 'o': /* Unsigned octal */ + r = 8; break; + case 'd': /* Signed decimal */ + case 'u': /* Unsigned decimal */ + r = 10; break; + case 'x': /* Unsigned hexdecimal (lower case) */ + case 'X': /* Unsigned hexdecimal (upper case) */ + r = 16; break; + case 'c': /* Character */ + putc_bfd(&pb, (TCHAR)va_arg(arp, int)); + continue; + case 's': /* String */ + tp = va_arg(arp, TCHAR*); /* Get a pointer argument */ + if (!tp) tp = &nul; /* Null ptr generates a null string */ + for (j = 0; tp[j]; j++) ; /* j = tcslen(tp) */ + if (prec >= 0 && j > (UINT)prec) j = prec; /* Limited length of string body */ + for ( ; !(f & 2) && j < w; j++) putc_bfd(&pb, pad); /* Left pads */ + while (*tp && prec--) putc_bfd(&pb, *tp++); /* Body */ + while (j++ < w) putc_bfd(&pb, ' '); /* Right pads */ + continue; +#if FF_PRINT_FLOAT && FF_INTDEF == 2 + case 'f': /* Floating point (decimal) */ + case 'e': /* Floating point (e) */ + case 'E': /* Floating point (E) */ + ftoa(str, va_arg(arp, double), prec, tc); /* Make a flaoting point string */ + for (j = strlen(str); !(f & 2) && j < w; j++) putc_bfd(&pb, pad); /* Left pads */ + for (i = 0; str[i]; putc_bfd(&pb, str[i++])) ; /* Body */ + while (j++ < w) putc_bfd(&pb, ' '); /* Right pads */ + continue; +#endif + default: /* Unknown type (pass-through) */ + putc_bfd(&pb, tc); continue; + } + + /* Get an integer argument and put it in numeral */ +#if FF_PRINT_LLI && FF_INTDEF == 2 + if (f & 8) { /* long long argument? */ + v = (QWORD)va_arg(arp, LONGLONG); + } else { + if (f & 4) { /* long argument? */ + v = (tc == 'd') ? (QWORD)(LONGLONG)va_arg(arp, long) : (QWORD)va_arg(arp, unsigned long); + } else { /* int/short/char argument */ + v = (tc == 'd') ? (QWORD)(LONGLONG)va_arg(arp, int) : (QWORD)va_arg(arp, unsigned int); + } + } + if (tc == 'd' && (v & 0x8000000000000000)) { /* Negative value? */ + v = 0 - v; f |= 1; + } +#else + if (f & 4) { /* long argument? */ + v = (DWORD)va_arg(arp, long); + } else { /* int/short/char argument */ + v = (tc == 'd') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int); + } + if (tc == 'd' && (v & 0x80000000)) { /* Negative value? */ + v = 0 - v; f |= 1; + } +#endif + i = 0; + do { /* Make an integer number string */ + d = (char)(v % r); v /= r; + if (d > 9) d += (tc == 'x') ? 0x27 : 0x07; + str[i++] = d + '0'; + } while (v && i < SZ_NUM_BUF); + if (f & 1) str[i++] = '-'; /* Sign */ + /* Write it */ + for (j = i; !(f & 2) && j < w; j++) putc_bfd(&pb, pad); /* Left pads */ + do putc_bfd(&pb, (TCHAR)str[--i]); while (i); /* Body */ + while (j++ < w) putc_bfd(&pb, ' '); /* Right pads */ + } + + va_end(arp); + + return putc_flush(&pb); +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_USE_STRFUNC */ + + + +#if FF_CODE_PAGE == 0 +/*-----------------------------------------------------------------------*/ +/* Set Active Codepage for the Path Name */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_setcp ( + WORD cp /* Value to be set as active code page */ +) +{ + static const WORD validcp[22] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 932, 936, 949, 950, 0}; + static const BYTE* const tables[22] = {Ct437, Ct720, Ct737, Ct771, Ct775, Ct850, Ct852, Ct855, Ct857, Ct860, Ct861, Ct862, Ct863, Ct864, Ct865, Ct866, Ct869, Dc932, Dc936, Dc949, Dc950, 0}; + UINT i; + + + for (i = 0; validcp[i] != 0 && validcp[i] != cp; i++) ; /* Find the code page */ + if (validcp[i] != cp) return FR_INVALID_PARAMETER; /* Not found? */ + + CodePage = cp; + if (cp >= 900) { /* DBCS */ + ExCvt = 0; + DbcTbl = tables[i]; + } else { /* SBCS */ + ExCvt = tables[i]; + DbcTbl = 0; + } + return FR_OK; +} +#endif /* FF_CODE_PAGE == 0 */ + diff --git a/lib-hal/ff14b/source/ff.h b/lib-hal/ff14b/source/ff.h new file mode 100755 index 00000000..64bf79db --- /dev/null +++ b/lib-hal/ff14b/source/ff.h @@ -0,0 +1,422 @@ +/*----------------------------------------------------------------------------/ +/ FatFs - Generic FAT Filesystem module R0.14b / +/-----------------------------------------------------------------------------/ +/ +/ Copyright (C) 2021, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: + +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +/ +/----------------------------------------------------------------------------*/ + + +#ifndef FF_DEFINED +#define FF_DEFINED 86631 /* Revision ID */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ffconf.h" /* FatFs configuration options */ + +#if FF_DEFINED != FFCONF_DEF +#error Wrong configuration file (ffconf.h). +#endif + + +/* Integer types used for FatFs API */ + +#if defined(_WIN32) /* Windows VC++ (for development only) */ +#define FF_INTDEF 2 +#include +typedef unsigned __int64 QWORD; +#include +#define isnan(v) _isnan(v) +#define isinf(v) (!_finite(v)) + +#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */ +#define FF_INTDEF 2 +#include +typedef unsigned int UINT; /* int must be 16-bit or 32-bit */ +typedef unsigned char BYTE; /* char must be 8-bit */ +typedef uint16_t WORD; /* 16-bit unsigned integer */ +typedef uint32_t DWORD; /* 32-bit unsigned integer */ +typedef uint64_t QWORD; /* 64-bit unsigned integer */ +typedef WORD WCHAR; /* UTF-16 character type */ + +#else /* Earlier than C99 */ +#define FF_INTDEF 1 +typedef unsigned int UINT; /* int must be 16-bit or 32-bit */ +typedef unsigned char BYTE; /* char must be 8-bit */ +typedef unsigned short WORD; /* 16-bit unsigned integer */ +typedef unsigned long DWORD; /* 32-bit unsigned integer */ +typedef WORD WCHAR; /* UTF-16 character type */ +#endif + + +/* Type of file size and LBA variables */ + +#if FF_FS_EXFAT +#if FF_INTDEF != 2 +#error exFAT feature wants C99 or later +#endif +typedef QWORD FSIZE_t; +#if FF_LBA64 +typedef QWORD LBA_t; +#else +typedef DWORD LBA_t; +#endif +#else +#if FF_LBA64 +#error exFAT needs to be enabled when enable 64-bit LBA +#endif +typedef DWORD FSIZE_t; +typedef DWORD LBA_t; +#endif + + + +/* Type of path name strings on FatFs API (TCHAR) */ + +#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */ +typedef WCHAR TCHAR; +#define _T(x) L ## x +#define _TEXT(x) L ## x +#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */ +typedef char TCHAR; +#define _T(x) u8 ## x +#define _TEXT(x) u8 ## x +#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */ +typedef DWORD TCHAR; +#define _T(x) U ## x +#define _TEXT(x) U ## x +#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3) +#error Wrong FF_LFN_UNICODE setting +#else /* ANSI/OEM code in SBCS/DBCS */ +typedef char TCHAR; +#define _T(x) x +#define _TEXT(x) x +#endif + + + +/* Definitions of volume management */ + +#if FF_MULTI_PARTITION /* Multiple partition configuration */ +typedef struct { + BYTE pd; /* Physical drive number */ + BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ +} PARTITION; +extern PARTITION VolToPart[]; /* Volume - Partition mapping table */ +#endif + +#if FF_STR_VOLUME_ID +#ifndef FF_VOLUME_STRS +extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */ +#endif +#endif + + + +/* Filesystem object structure (FATFS) */ + +typedef struct { + BYTE fs_type; /* Filesystem type (0:not mounted) */ + BYTE pdrv; /* Associated physical drive */ + BYTE n_fats; /* Number of FATs (1 or 2) */ + BYTE wflag; /* win[] flag (b0:dirty) */ + BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ + WORD id; /* Volume mount ID */ + WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ + WORD csize; /* Cluster size [sectors] */ +#if FF_MAX_SS != FF_MIN_SS + WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */ +#endif +#if FF_USE_LFN + WCHAR* lfnbuf; /* LFN working buffer */ +#endif +#if FF_FS_EXFAT + BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */ +#endif +#if FF_FS_REENTRANT + FF_SYNC_t sobj; /* Identifier of sync object */ +#endif +#if !FF_FS_READONLY + DWORD last_clst; /* Last allocated cluster */ + DWORD free_clst; /* Number of free clusters */ +#endif +#if FF_FS_RPATH + DWORD cdir; /* Current directory start cluster (0:root) */ +#if FF_FS_EXFAT + DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ + DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ + DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ +#endif +#endif + DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ + DWORD fsize; /* Size of an FAT [sectors] */ + LBA_t volbase; /* Volume base sector */ + LBA_t fatbase; /* FAT base sector */ + LBA_t dirbase; /* Root directory base sector/cluster */ + LBA_t database; /* Data base sector */ +#if FF_FS_EXFAT + LBA_t bitbase; /* Allocation bitmap base sector */ +#endif + LBA_t winsect; /* Current sector appearing in the win[] */ + BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ +} FATFS; + + + +/* Object ID and allocation information (FFOBJID) */ + +typedef struct { + FATFS* fs; /* Pointer to the hosting volume of this object */ + WORD id; /* Hosting volume mount ID */ + BYTE attr; /* Object attribute */ + BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */ + DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */ + FSIZE_t objsize; /* Object size (valid when sclust != 0) */ +#if FF_FS_EXFAT + DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */ + DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */ + DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */ + DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */ + DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */ +#endif +#if FF_FS_LOCK + UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ +#endif +} FFOBJID; + + + +/* File object structure (FIL) */ + +typedef struct { + FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ + BYTE flag; /* File status flags */ + BYTE err; /* Abort flag (error code) */ + FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */ + DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */ + LBA_t sect; /* Sector number appearing in buf[] (0:invalid) */ +#if !FF_FS_READONLY + LBA_t dir_sect; /* Sector number containing the directory entry (not used at exFAT) */ + BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */ +#endif +#if FF_USE_FASTSEEK + DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ +#endif +#if !FF_FS_TINY + BYTE buf[FF_MAX_SS]; /* File private data read/write window */ +#endif +} FIL; + + + +/* Directory object structure (DIR) */ + +typedef struct { + FFOBJID obj; /* Object identifier */ + DWORD dptr; /* Current read/write offset */ + DWORD clust; /* Current cluster */ + LBA_t sect; /* Current sector (0:Read operation has terminated) */ + BYTE* dir; /* Pointer to the directory item in the win[] */ + BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */ +#if FF_USE_LFN + DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */ +#endif +#if FF_USE_FIND + const TCHAR* pat; /* Pointer to the name matching pattern */ +#endif +} DIR; + + + +/* File information structure (FILINFO) */ + +typedef struct { + FSIZE_t fsize; /* File size */ + WORD fdate; /* Modified date */ + WORD ftime; /* Modified time */ + BYTE fattrib; /* File attribute */ +#if FF_USE_LFN + TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */ + TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */ +#else + TCHAR fname[12 + 1]; /* File name */ +#endif +} FILINFO; + + + +/* Format parameter structure (MKFS_PARM) */ + +typedef struct { + BYTE fmt; /* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */ + BYTE n_fat; /* Number of FATs */ + UINT align; /* Data area alignment (sector) */ + UINT n_root; /* Number of root directory entries */ + DWORD au_size; /* Cluster size (byte) */ +} MKFS_PARM; + + + +/* File function return code (FRESULT) */ + +typedef enum { + FR_OK = 0, /* (0) Succeeded */ + FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ + FR_INT_ERR, /* (2) Assertion failed */ + FR_NOT_READY, /* (3) The physical drive cannot work */ + FR_NO_FILE, /* (4) Could not find the file */ + FR_NO_PATH, /* (5) Could not find the path */ + FR_INVALID_NAME, /* (6) The path name format is invalid */ + FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Access denied due to prohibited access */ + FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ + FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ + FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ + FR_NOT_ENABLED, /* (12) The volume has no work area */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ + FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */ + FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ + FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ + FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ + FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ +} FRESULT; + + + +/*--------------------------------------------------------------*/ +/* FatFs module application interface */ + +FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ +FRESULT f_close (FIL* fp); /* Close an open file object */ +FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ +FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ +FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ +FRESULT f_truncate (FIL* fp); /* Truncate the file */ +FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ +FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */ +FRESULT f_closedir (DIR* dp); /* Close an open directory */ +FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */ +FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */ +FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */ +FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ +FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ +FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ +FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ +FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */ +FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */ +FRESULT f_chdir (const TCHAR* path); /* Change current directory */ +FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ +FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ +FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ +FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ +FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ +FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ +FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */ +FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ +FRESULT f_mkfs (const TCHAR* path, const MKFS_PARM* opt, void* work, UINT len); /* Create a FAT volume */ +FRESULT f_fdisk (BYTE pdrv, const LBA_t ptbl[], void* work); /* Divide a physical drive into some partitions */ +FRESULT f_setcp (WORD cp); /* Set current code page */ +int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ +int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ +int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ +TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ + +#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) +#define f_error(fp) ((fp)->err) +#define f_tell(fp) ((fp)->fptr) +#define f_size(fp) ((fp)->obj.objsize) +#define f_rewind(fp) f_lseek((fp), 0) +#define f_rewinddir(dp) f_readdir((dp), 0) +#define f_rmdir(path) f_unlink(path) +#define f_unmount(path) f_mount(0, path, 0) + + + + +/*--------------------------------------------------------------*/ +/* Additional user defined functions */ + +/* RTC function */ +#if !FF_FS_READONLY && !FF_FS_NORTC +DWORD get_fattime (void); +#endif + +/* LFN support functions */ +#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */ +WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */ +WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */ +DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */ +#endif +#if FF_USE_LFN == 3 /* Dynamic memory allocation */ +void* ff_memalloc (UINT msize); /* Allocate memory block */ +void ff_memfree (void* mblock); /* Free memory block */ +#endif + +/* Sync functions */ +#if FF_FS_REENTRANT +int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */ +int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */ +void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */ +int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */ +#endif + + + + +/*--------------------------------------------------------------*/ +/* Flags and offset address */ + + +/* File access mode and open method flags (3rd argument of f_open) */ +#define FA_READ 0x01 +#define FA_WRITE 0x02 +#define FA_OPEN_EXISTING 0x00 +#define FA_CREATE_NEW 0x04 +#define FA_CREATE_ALWAYS 0x08 +#define FA_OPEN_ALWAYS 0x10 +#define FA_OPEN_APPEND 0x30 + +/* Fast seek controls (2nd argument of f_lseek) */ +#define CREATE_LINKMAP ((FSIZE_t)0 - 1) + +/* Format options (2nd argument of f_mkfs) */ +#define FM_FAT 0x01 +#define FM_FAT32 0x02 +#define FM_EXFAT 0x04 +#define FM_ANY 0x07 +#define FM_SFD 0x08 + +/* Filesystem type (FATFS.fs_type) */ +#define FS_FAT12 1 +#define FS_FAT16 2 +#define FS_FAT32 3 +#define FS_EXFAT 4 + +/* File attribute bits for directory entry (FILINFO.fattrib) */ +#define AM_RDO 0x01 /* Read only */ +#define AM_HID 0x02 /* Hidden */ +#define AM_SYS 0x04 /* System */ +#define AM_DIR 0x10 /* Directory */ +#define AM_ARC 0x20 /* Archive */ + + +#ifdef __cplusplus +} +#endif + +#endif /* FF_DEFINED */ diff --git a/lib-hal/ff14b/source/ffconf.h b/lib-hal/ff14b/source/ffconf.h new file mode 100755 index 00000000..4104abf2 --- /dev/null +++ b/lib-hal/ff14b/source/ffconf.h @@ -0,0 +1,308 @@ +/*---------------------------------------------------------------------------/ +/ FatFs Functional Configurations +/---------------------------------------------------------------------------*/ + +#define FFCONF_DEF 86631 /* Revision ID */ + +/*---------------------------------------------------------------------------/ +/ Function Configurations +/---------------------------------------------------------------------------*/ + +#if defined (CONFIG_FS_ENABLE_WRITE) +# define FF_FS_READONLY 0 +#else +# define FF_FS_READONLY 1 +#endif +/* This option switches read-only configuration. (0:Read/Write or 1:Read-only) +/ Read-only configuration removes writing API functions, f_write(), f_sync(), +/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() +/ and optional writing functions as well. */ + + +#define FF_FS_MINIMIZE 0 +/* This option defines minimization level to remove some basic API functions. +/ +/ 0: Basic functions are fully enabled. +/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() +/ are removed. +/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. +/ 3: f_lseek() function is removed in addition to 2. */ + + +#define FF_USE_FIND 0 +/* This option switches filtered directory read functions, f_findfirst() and +/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ + + +#define FF_USE_MKFS 0 +/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ + + +#define FF_USE_FASTSEEK 0 +/* This option switches fast seek function. (0:Disable or 1:Enable) */ + + +#define FF_USE_EXPAND 0 +/* This option switches f_expand function. (0:Disable or 1:Enable) */ + + +#define FF_USE_CHMOD 0 +/* This option switches attribute manipulation functions, f_chmod() and f_utime(). +/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ + + +#define FF_USE_LABEL 0 +/* This option switches volume label functions, f_getlabel() and f_setlabel(). +/ (0:Disable or 1:Enable) */ + + +#define FF_USE_FORWARD 0 +/* This option switches f_forward() function. (0:Disable or 1:Enable) */ + + +#define FF_USE_STRFUNC 2 +#define FF_PRINT_LLI 0 +#define FF_PRINT_FLOAT 0 +#define FF_STRF_ENCODE 0 +/* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and +/ f_printf(). +/ +/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect. +/ 1: Enable without LF-CRLF conversion. +/ 2: Enable with LF-CRLF conversion. +/ +/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2 + makes f_printf() support floating point argument. These features want C99 or later. +/ When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character +/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE +/ to be read/written via those functions. +/ +/ 0: ANSI/OEM in current CP +/ 1: Unicode in UTF-16LE +/ 2: Unicode in UTF-16BE +/ 3: Unicode in UTF-8 +*/ + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/---------------------------------------------------------------------------*/ + +#define FF_CODE_PAGE 850 +/* This option specifies the OEM code page to be used on the target system. +/ Incorrect code page setting can cause a file open failure. +/ +/ 437 - U.S. +/ 720 - Arabic +/ 737 - Greek +/ 771 - KBL +/ 775 - Baltic +/ 850 - Latin 1 +/ 852 - Latin 2 +/ 855 - Cyrillic +/ 857 - Turkish +/ 860 - Portuguese +/ 861 - Icelandic +/ 862 - Hebrew +/ 863 - Canadian French +/ 864 - Arabic +/ 865 - Nordic +/ 866 - Russian +/ 869 - Greek 2 +/ 932 - Japanese (DBCS) +/ 936 - Simplified Chinese (DBCS) +/ 949 - Korean (DBCS) +/ 950 - Traditional Chinese (DBCS) +/ 0 - Include all code pages above and configured by f_setcp() +*/ + + +#define FF_USE_LFN 1 +#define FF_MAX_LFN 255 +/* The FF_USE_LFN switches the support for LFN (long file name). +/ +/ 0: Disable LFN. FF_MAX_LFN has no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function +/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and +/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled. +/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can +/ be in range of 12 to 255. It is recommended to be set it 255 to fully support LFN +/ specification. +/ When use stack for the working buffer, take care on stack overflow. When use heap +/ memory for the working buffer, memory management functions, ff_memalloc() and +/ ff_memfree() exemplified in ffsystem.c, need to be added to the project. */ + + +#define FF_LFN_UNICODE 0 +/* This option switches the character encoding on the API when LFN is enabled. +/ +/ 0: ANSI/OEM in current CP (TCHAR = char) +/ 1: Unicode in UTF-16 (TCHAR = WCHAR) +/ 2: Unicode in UTF-8 (TCHAR = char) +/ 3: Unicode in UTF-32 (TCHAR = DWORD) +/ +/ Also behavior of string I/O functions will be affected by this option. +/ When LFN is not enabled, this option has no effect. */ + + +#define FF_LFN_BUF 255 +#define FF_SFN_BUF 12 +/* This set of options defines size of file name members in the FILINFO structure +/ which is used to read out directory items. These values should be suffcient for +/ the file names to read. The maximum possible length of the read file name depends +/ on character encoding. When LFN is not enabled, these options have no effect. */ + + +#define FF_FS_RPATH 0 +/* This option configures support for relative path. +/ +/ 0: Disable relative path and remove related functions. +/ 1: Enable relative path. f_chdir() and f_chdrive() are available. +/ 2: f_getcwd() function is available in addition to 1. +*/ + + +/*---------------------------------------------------------------------------/ +/ Drive/Volume Configurations +/---------------------------------------------------------------------------*/ + +#define FF_VOLUMES 1 +/* Number of volumes (logical drives) to be used. (1-10) */ + + +#define FF_STR_VOLUME_ID 0 +#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" +/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. +/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive +/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each +/ logical drives. Number of items must not be less than FF_VOLUMES. Valid +/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are +/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is +/ not defined, a user defined volume string table needs to be defined as: +/ +/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... +*/ + + +#define FF_MULTI_PARTITION 0 +/* This option switches support for multiple volumes on the physical drive. +/ By default (0), each logical drive number is bound to the same physical drive +/ number and only an FAT volume found on the physical drive will be mounted. +/ When this function is enabled (1), each logical drive number can be bound to +/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() +/ funciton will be available. */ + + +#define FF_MIN_SS 512 +#define FF_MAX_SS 512 +/* This set of options configures the range of sector size to be supported. (512, +/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and +/ harddisk, but a larger value may be required for on-board flash memory and some +/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured +/ for variable sector size mode and disk_ioctl() function needs to implement +/ GET_SECTOR_SIZE command. */ + + +#define FF_LBA64 0 +/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable) +/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */ + + +#define FF_MIN_GPT 0x10000000 +/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and +/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */ + + +#define FF_USE_TRIM 0 +/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) +/ To enable Trim function, also CTRL_TRIM command should be implemented to the +/ disk_ioctl() function. */ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_TINY 0 +/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) +/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. +/ Instead of private sector buffer eliminated from the file object, common sector +/ buffer in the filesystem object (FATFS) is used for the file data transfer. */ + +#if defined (SD_EXFAT_SUPPORT) +# define FF_FS_EXFAT 1 +#else +# define FF_FS_EXFAT 0 +#endif +/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) +/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1) +/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ + + +#define FF_FS_NORTC 0 +#define FF_NORTC_MON _TIME_STAMP_MONTH_ +#define FF_NORTC_MDAY _TIME_STAMP_DAY_ +#define FF_NORTC_YEAR _TIME_STAMP_YEAR_ +/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have +/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable +/ the timestamp function. Every object modified by FatFs will have a fixed timestamp +/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. +/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be +/ added to the project to read current time form real-time clock. FF_NORTC_MON, +/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. +/ These options have no effect in read-only configuration (FF_FS_READONLY = 1). */ + + +#define FF_FS_NOFSINFO 0 +/* If you need to know correct free space on the FAT32 volume, set bit 0 of this +/ option, and f_getfree() function at first time after volume mount will force +/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. +/ +/ bit0=0: Use free cluster count in the FSINFO if available. +/ bit0=1: Do not trust free cluster count in the FSINFO. +/ bit1=0: Use last allocated cluster number in the FSINFO if available. +/ bit1=1: Do not trust last allocated cluster number in the FSINFO. +*/ + + +#define FF_FS_LOCK 0 +/* The option FF_FS_LOCK switches file lock function to control duplicated file open +/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY +/ is 1. +/ +/ 0: Disable file lock function. To avoid volume corruption, application program +/ should avoid illegal open, remove and rename to the open objects. +/ >0: Enable file lock function. The value defines how many files/sub-directories +/ can be opened simultaneously under file lock control. Note that the file +/ lock control is independent of re-entrancy. */ + + +/* #include // O/S definitions */ +#define FF_FS_REENTRANT 0 +#define FF_FS_TIMEOUT 1000 +#define FF_SYNC_t HANDLE +/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs +/ module itself. Note that regardless of this option, file access to different +/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() +/ and f_fdisk() function, are always not re-entrant. Only file/directory access +/ to the same volume is under control of this function. +/ +/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. +/ 1: Enable re-entrancy. Also user provided synchronization handlers, +/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() +/ function, must be added to the project. Samples are available in +/ option/syscall.c. +/ +/ The FF_FS_TIMEOUT defines timeout period in unit of time tick. +/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, +/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be +/ included somewhere in the scope of ff.h. */ + + + +/*--- End of configuration options ---*/ diff --git a/lib-hal/ff14b/source/ffsystem.c b/lib-hal/ff14b/source/ffsystem.c new file mode 100755 index 00000000..ad5d7377 --- /dev/null +++ b/lib-hal/ff14b/source/ffsystem.c @@ -0,0 +1,170 @@ +/*------------------------------------------------------------------------*/ +/* Sample Code of OS Dependent Functions for FatFs */ +/* (C)ChaN, 2018 */ +/*------------------------------------------------------------------------*/ + + +#include "ff.h" + + +#if FF_USE_LFN == 3 /* Dynamic memory allocation */ + +/*------------------------------------------------------------------------*/ +/* Allocate a memory block */ +/*------------------------------------------------------------------------*/ + +void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */ + UINT msize /* Number of bytes to allocate */ +) +{ + return malloc(msize); /* Allocate a new memory block with POSIX API */ +} + + +/*------------------------------------------------------------------------*/ +/* Free a memory block */ +/*------------------------------------------------------------------------*/ + +void ff_memfree ( + void* mblock /* Pointer to the memory block to free (nothing to do if null) */ +) +{ + free(mblock); /* Free the memory block with POSIX API */ +} + +#endif + + + +#if FF_FS_REENTRANT /* Mutal exclusion */ + +/*------------------------------------------------------------------------*/ +/* Create a Synchronization Object */ +/*------------------------------------------------------------------------*/ +/* This function is called in f_mount() function to create a new +/ synchronization object for the volume, such as semaphore and mutex. +/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR. +*/ + +//const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */ + + +int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */ + BYTE vol, /* Corresponding volume (logical drive number) */ + FF_SYNC_t* sobj /* Pointer to return the created sync object */ +) +{ + /* Win32 */ + *sobj = CreateMutex(NULL, FALSE, NULL); + return (int)(*sobj != INVALID_HANDLE_VALUE); + + /* uITRON */ +// T_CSEM csem = {TA_TPRI,1,1}; +// *sobj = acre_sem(&csem); +// return (int)(*sobj > 0); + + /* uC/OS-II */ +// OS_ERR err; +// *sobj = OSMutexCreate(0, &err); +// return (int)(err == OS_NO_ERR); + + /* FreeRTOS */ +// *sobj = xSemaphoreCreateMutex(); +// return (int)(*sobj != NULL); + + /* CMSIS-RTOS */ +// *sobj = osMutexCreate(&Mutex[vol]); +// return (int)(*sobj != NULL); +} + + +/*------------------------------------------------------------------------*/ +/* Delete a Synchronization Object */ +/*------------------------------------------------------------------------*/ +/* This function is called in f_mount() function to delete a synchronization +/ object that created with ff_cre_syncobj() function. When a 0 is returned, +/ the f_mount() function fails with FR_INT_ERR. +*/ + +int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */ + FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */ +) +{ + /* Win32 */ + return (int)CloseHandle(sobj); + + /* uITRON */ +// return (int)(del_sem(sobj) == E_OK); + + /* uC/OS-II */ +// OS_ERR err; +// OSMutexDel(sobj, OS_DEL_ALWAYS, &err); +// return (int)(err == OS_NO_ERR); + + /* FreeRTOS */ +// vSemaphoreDelete(sobj); +// return 1; + + /* CMSIS-RTOS */ +// return (int)(osMutexDelete(sobj) == osOK); +} + + +/*------------------------------------------------------------------------*/ +/* Request Grant to Access the Volume */ +/*------------------------------------------------------------------------*/ +/* This function is called on entering file functions to lock the volume. +/ When a 0 is returned, the file function fails with FR_TIMEOUT. +*/ + +int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */ + FF_SYNC_t sobj /* Sync object to wait */ +) +{ + /* Win32 */ + return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0); + + /* uITRON */ +// return (int)(wai_sem(sobj) == E_OK); + + /* uC/OS-II */ +// OS_ERR err; +// OSMutexPend(sobj, FF_FS_TIMEOUT, &err)); +// return (int)(err == OS_NO_ERR); + + /* FreeRTOS */ +// return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE); + + /* CMSIS-RTOS */ +// return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK); +} + + +/*------------------------------------------------------------------------*/ +/* Release Grant to Access the Volume */ +/*------------------------------------------------------------------------*/ +/* This function is called on leaving file functions to unlock the volume. +*/ + +void ff_rel_grant ( + FF_SYNC_t sobj /* Sync object to be signaled */ +) +{ + /* Win32 */ + ReleaseMutex(sobj); + + /* uITRON */ +// sig_sem(sobj); + + /* uC/OS-II */ +// OSMutexPost(sobj); + + /* FreeRTOS */ +// xSemaphoreGive(sobj); + + /* CMSIS-RTOS */ +// osMutexRelease(sobj); +} + +#endif + diff --git a/lib-hal/ff14b/source/ffunicode.c b/lib-hal/ff14b/source/ffunicode.c new file mode 100755 index 00000000..784a10e5 --- /dev/null +++ b/lib-hal/ff14b/source/ffunicode.c @@ -0,0 +1,15593 @@ +/*------------------------------------------------------------------------*/ +/* Unicode handling functions for FatFs R0.13+ */ +/*------------------------------------------------------------------------*/ +/* This module will occupy a huge memory in the .const section when the / +/ FatFs is configured for LFN with DBCS. If the system has any Unicode / +/ utilitiy for the code conversion, this module should be modified to use / +/ that function to avoid silly memory consumption. / +/-------------------------------------------------------------------------*/ +/* +/ Copyright (C) 2014, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: +/ +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +*/ + + +#include "ff.h" + +#if FF_USE_LFN /* This module will be blanked if non-LFN configuration */ + +#define MERGE2(a, b) a ## b +#define CVTBL(tbl, cp) MERGE2(tbl, cp) + + +/*------------------------------------------------------------------------*/ +/* Code Conversion Tables */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE == 932 || FF_CODE_PAGE == 0 /* Japanese */ +static const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */ + 0x00A7, 0x8198, 0x00A8, 0x814E, 0x00B0, 0x818B, 0x00B1, 0x817D, 0x00B4, 0x814C, 0x00B6, 0x81F7, 0x00D7, 0x817E, 0x00F7, 0x8180, + 0x0391, 0x839F, 0x0392, 0x83A0, 0x0393, 0x83A1, 0x0394, 0x83A2, 0x0395, 0x83A3, 0x0396, 0x83A4, 0x0397, 0x83A5, 0x0398, 0x83A6, + 0x0399, 0x83A7, 0x039A, 0x83A8, 0x039B, 0x83A9, 0x039C, 0x83AA, 0x039D, 0x83AB, 0x039E, 0x83AC, 0x039F, 0x83AD, 0x03A0, 0x83AE, + 0x03A1, 0x83AF, 0x03A3, 0x83B0, 0x03A4, 0x83B1, 0x03A5, 0x83B2, 0x03A6, 0x83B3, 0x03A7, 0x83B4, 0x03A8, 0x83B5, 0x03A9, 0x83B6, + 0x03B1, 0x83BF, 0x03B2, 0x83C0, 0x03B3, 0x83C1, 0x03B4, 0x83C2, 0x03B5, 0x83C3, 0x03B6, 0x83C4, 0x03B7, 0x83C5, 0x03B8, 0x83C6, + 0x03B9, 0x83C7, 0x03BA, 0x83C8, 0x03BB, 0x83C9, 0x03BC, 0x83CA, 0x03BD, 0x83CB, 0x03BE, 0x83CC, 0x03BF, 0x83CD, 0x03C0, 0x83CE, + 0x03C1, 0x83CF, 0x03C3, 0x83D0, 0x03C4, 0x83D1, 0x03C5, 0x83D2, 0x03C6, 0x83D3, 0x03C7, 0x83D4, 0x03C8, 0x83D5, 0x03C9, 0x83D6, + 0x0401, 0x8446, 0x0410, 0x8440, 0x0411, 0x8441, 0x0412, 0x8442, 0x0413, 0x8443, 0x0414, 0x8444, 0x0415, 0x8445, 0x0416, 0x8447, + 0x0417, 0x8448, 0x0418, 0x8449, 0x0419, 0x844A, 0x041A, 0x844B, 0x041B, 0x844C, 0x041C, 0x844D, 0x041D, 0x844E, 0x041E, 0x844F, + 0x041F, 0x8450, 0x0420, 0x8451, 0x0421, 0x8452, 0x0422, 0x8453, 0x0423, 0x8454, 0x0424, 0x8455, 0x0425, 0x8456, 0x0426, 0x8457, + 0x0427, 0x8458, 0x0428, 0x8459, 0x0429, 0x845A, 0x042A, 0x845B, 0x042B, 0x845C, 0x042C, 0x845D, 0x042D, 0x845E, 0x042E, 0x845F, + 0x042F, 0x8460, 0x0430, 0x8470, 0x0431, 0x8471, 0x0432, 0x8472, 0x0433, 0x8473, 0x0434, 0x8474, 0x0435, 0x8475, 0x0436, 0x8477, + 0x0437, 0x8478, 0x0438, 0x8479, 0x0439, 0x847A, 0x043A, 0x847B, 0x043B, 0x847C, 0x043C, 0x847D, 0x043D, 0x847E, 0x043E, 0x8480, + 0x043F, 0x8481, 0x0440, 0x8482, 0x0441, 0x8483, 0x0442, 0x8484, 0x0443, 0x8485, 0x0444, 0x8486, 0x0445, 0x8487, 0x0446, 0x8488, + 0x0447, 0x8489, 0x0448, 0x848A, 0x0449, 0x848B, 0x044A, 0x848C, 0x044B, 0x848D, 0x044C, 0x848E, 0x044D, 0x848F, 0x044E, 0x8490, + 0x044F, 0x8491, 0x0451, 0x8476, 0x2010, 0x815D, 0x2015, 0x815C, 0x2018, 0x8165, 0x2019, 0x8166, 0x201C, 0x8167, 0x201D, 0x8168, + 0x2020, 0x81F5, 0x2021, 0x81F6, 0x2025, 0x8164, 0x2026, 0x8163, 0x2030, 0x81F1, 0x2032, 0x818C, 0x2033, 0x818D, 0x203B, 0x81A6, + 0x2103, 0x818E, 0x2116, 0x8782, 0x2121, 0x8784, 0x212B, 0x81F0, 0x2160, 0x8754, 0x2161, 0x8755, 0x2162, 0x8756, 0x2163, 0x8757, + 0x2164, 0x8758, 0x2165, 0x8759, 0x2166, 0x875A, 0x2167, 0x875B, 0x2168, 0x875C, 0x2169, 0x875D, 0x2170, 0xFA40, 0x2171, 0xFA41, + 0x2172, 0xFA42, 0x2173, 0xFA43, 0x2174, 0xFA44, 0x2175, 0xFA45, 0x2176, 0xFA46, 0x2177, 0xFA47, 0x2178, 0xFA48, 0x2179, 0xFA49, + 0x2190, 0x81A9, 0x2191, 0x81AA, 0x2192, 0x81A8, 0x2193, 0x81AB, 0x21D2, 0x81CB, 0x21D4, 0x81CC, 0x2200, 0x81CD, 0x2202, 0x81DD, + 0x2203, 0x81CE, 0x2207, 0x81DE, 0x2208, 0x81B8, 0x220B, 0x81B9, 0x2211, 0x8794, 0x221A, 0x81E3, 0x221D, 0x81E5, 0x221E, 0x8187, + 0x221F, 0x8798, 0x2220, 0x81DA, 0x2225, 0x8161, 0x2227, 0x81C8, 0x2228, 0x81C9, 0x2229, 0x81BF, 0x222A, 0x81BE, 0x222B, 0x81E7, + 0x222C, 0x81E8, 0x222E, 0x8793, 0x2234, 0x8188, 0x2235, 0x81E6, 0x223D, 0x81E4, 0x2252, 0x81E0, 0x2260, 0x8182, 0x2261, 0x81DF, + 0x2266, 0x8185, 0x2267, 0x8186, 0x226A, 0x81E1, 0x226B, 0x81E2, 0x2282, 0x81BC, 0x2283, 0x81BD, 0x2286, 0x81BA, 0x2287, 0x81BB, + 0x22A5, 0x81DB, 0x22BF, 0x8799, 0x2312, 0x81DC, 0x2460, 0x8740, 0x2461, 0x8741, 0x2462, 0x8742, 0x2463, 0x8743, 0x2464, 0x8744, + 0x2465, 0x8745, 0x2466, 0x8746, 0x2467, 0x8747, 0x2468, 0x8748, 0x2469, 0x8749, 0x246A, 0x874A, 0x246B, 0x874B, 0x246C, 0x874C, + 0x246D, 0x874D, 0x246E, 0x874E, 0x246F, 0x874F, 0x2470, 0x8750, 0x2471, 0x8751, 0x2472, 0x8752, 0x2473, 0x8753, 0x2500, 0x849F, + 0x2501, 0x84AA, 0x2502, 0x84A0, 0x2503, 0x84AB, 0x250C, 0x84A1, 0x250F, 0x84AC, 0x2510, 0x84A2, 0x2513, 0x84AD, 0x2514, 0x84A4, + 0x2517, 0x84AF, 0x2518, 0x84A3, 0x251B, 0x84AE, 0x251C, 0x84A5, 0x251D, 0x84BA, 0x2520, 0x84B5, 0x2523, 0x84B0, 0x2524, 0x84A7, + 0x2525, 0x84BC, 0x2528, 0x84B7, 0x252B, 0x84B2, 0x252C, 0x84A6, 0x252F, 0x84B6, 0x2530, 0x84BB, 0x2533, 0x84B1, 0x2534, 0x84A8, + 0x2537, 0x84B8, 0x2538, 0x84BD, 0x253B, 0x84B3, 0x253C, 0x84A9, 0x253F, 0x84B9, 0x2542, 0x84BE, 0x254B, 0x84B4, 0x25A0, 0x81A1, + 0x25A1, 0x81A0, 0x25B2, 0x81A3, 0x25B3, 0x81A2, 0x25BC, 0x81A5, 0x25BD, 0x81A4, 0x25C6, 0x819F, 0x25C7, 0x819E, 0x25CB, 0x819B, + 0x25CE, 0x819D, 0x25CF, 0x819C, 0x25EF, 0x81FC, 0x2605, 0x819A, 0x2606, 0x8199, 0x2640, 0x818A, 0x2642, 0x8189, 0x266A, 0x81F4, + 0x266D, 0x81F3, 0x266F, 0x81F2, 0x3000, 0x8140, 0x3001, 0x8141, 0x3002, 0x8142, 0x3003, 0x8156, 0x3005, 0x8158, 0x3006, 0x8159, + 0x3007, 0x815A, 0x3008, 0x8171, 0x3009, 0x8172, 0x300A, 0x8173, 0x300B, 0x8174, 0x300C, 0x8175, 0x300D, 0x8176, 0x300E, 0x8177, + 0x300F, 0x8178, 0x3010, 0x8179, 0x3011, 0x817A, 0x3012, 0x81A7, 0x3013, 0x81AC, 0x3014, 0x816B, 0x3015, 0x816C, 0x301D, 0x8780, + 0x301F, 0x8781, 0x3041, 0x829F, 0x3042, 0x82A0, 0x3043, 0x82A1, 0x3044, 0x82A2, 0x3045, 0x82A3, 0x3046, 0x82A4, 0x3047, 0x82A5, + 0x3048, 0x82A6, 0x3049, 0x82A7, 0x304A, 0x82A8, 0x304B, 0x82A9, 0x304C, 0x82AA, 0x304D, 0x82AB, 0x304E, 0x82AC, 0x304F, 0x82AD, + 0x3050, 0x82AE, 0x3051, 0x82AF, 0x3052, 0x82B0, 0x3053, 0x82B1, 0x3054, 0x82B2, 0x3055, 0x82B3, 0x3056, 0x82B4, 0x3057, 0x82B5, + 0x3058, 0x82B6, 0x3059, 0x82B7, 0x305A, 0x82B8, 0x305B, 0x82B9, 0x305C, 0x82BA, 0x305D, 0x82BB, 0x305E, 0x82BC, 0x305F, 0x82BD, + 0x3060, 0x82BE, 0x3061, 0x82BF, 0x3062, 0x82C0, 0x3063, 0x82C1, 0x3064, 0x82C2, 0x3065, 0x82C3, 0x3066, 0x82C4, 0x3067, 0x82C5, + 0x3068, 0x82C6, 0x3069, 0x82C7, 0x306A, 0x82C8, 0x306B, 0x82C9, 0x306C, 0x82CA, 0x306D, 0x82CB, 0x306E, 0x82CC, 0x306F, 0x82CD, + 0x3070, 0x82CE, 0x3071, 0x82CF, 0x3072, 0x82D0, 0x3073, 0x82D1, 0x3074, 0x82D2, 0x3075, 0x82D3, 0x3076, 0x82D4, 0x3077, 0x82D5, + 0x3078, 0x82D6, 0x3079, 0x82D7, 0x307A, 0x82D8, 0x307B, 0x82D9, 0x307C, 0x82DA, 0x307D, 0x82DB, 0x307E, 0x82DC, 0x307F, 0x82DD, + 0x3080, 0x82DE, 0x3081, 0x82DF, 0x3082, 0x82E0, 0x3083, 0x82E1, 0x3084, 0x82E2, 0x3085, 0x82E3, 0x3086, 0x82E4, 0x3087, 0x82E5, + 0x3088, 0x82E6, 0x3089, 0x82E7, 0x308A, 0x82E8, 0x308B, 0x82E9, 0x308C, 0x82EA, 0x308D, 0x82EB, 0x308E, 0x82EC, 0x308F, 0x82ED, + 0x3090, 0x82EE, 0x3091, 0x82EF, 0x3092, 0x82F0, 0x3093, 0x82F1, 0x309B, 0x814A, 0x309C, 0x814B, 0x309D, 0x8154, 0x309E, 0x8155, + 0x30A1, 0x8340, 0x30A2, 0x8341, 0x30A3, 0x8342, 0x30A4, 0x8343, 0x30A5, 0x8344, 0x30A6, 0x8345, 0x30A7, 0x8346, 0x30A8, 0x8347, + 0x30A9, 0x8348, 0x30AA, 0x8349, 0x30AB, 0x834A, 0x30AC, 0x834B, 0x30AD, 0x834C, 0x30AE, 0x834D, 0x30AF, 0x834E, 0x30B0, 0x834F, + 0x30B1, 0x8350, 0x30B2, 0x8351, 0x30B3, 0x8352, 0x30B4, 0x8353, 0x30B5, 0x8354, 0x30B6, 0x8355, 0x30B7, 0x8356, 0x30B8, 0x8357, + 0x30B9, 0x8358, 0x30BA, 0x8359, 0x30BB, 0x835A, 0x30BC, 0x835B, 0x30BD, 0x835C, 0x30BE, 0x835D, 0x30BF, 0x835E, 0x30C0, 0x835F, + 0x30C1, 0x8360, 0x30C2, 0x8361, 0x30C3, 0x8362, 0x30C4, 0x8363, 0x30C5, 0x8364, 0x30C6, 0x8365, 0x30C7, 0x8366, 0x30C8, 0x8367, + 0x30C9, 0x8368, 0x30CA, 0x8369, 0x30CB, 0x836A, 0x30CC, 0x836B, 0x30CD, 0x836C, 0x30CE, 0x836D, 0x30CF, 0x836E, 0x30D0, 0x836F, + 0x30D1, 0x8370, 0x30D2, 0x8371, 0x30D3, 0x8372, 0x30D4, 0x8373, 0x30D5, 0x8374, 0x30D6, 0x8375, 0x30D7, 0x8376, 0x30D8, 0x8377, + 0x30D9, 0x8378, 0x30DA, 0x8379, 0x30DB, 0x837A, 0x30DC, 0x837B, 0x30DD, 0x837C, 0x30DE, 0x837D, 0x30DF, 0x837E, 0x30E0, 0x8380, + 0x30E1, 0x8381, 0x30E2, 0x8382, 0x30E3, 0x8383, 0x30E4, 0x8384, 0x30E5, 0x8385, 0x30E6, 0x8386, 0x30E7, 0x8387, 0x30E8, 0x8388, + 0x30E9, 0x8389, 0x30EA, 0x838A, 0x30EB, 0x838B, 0x30EC, 0x838C, 0x30ED, 0x838D, 0x30EE, 0x838E, 0x30EF, 0x838F, 0x30F0, 0x8390, + 0x30F1, 0x8391, 0x30F2, 0x8392, 0x30F3, 0x8393, 0x30F4, 0x8394, 0x30F5, 0x8395, 0x30F6, 0x8396, 0x30FB, 0x8145, 0x30FC, 0x815B, + 0x30FD, 0x8152, 0x30FE, 0x8153, 0x3231, 0x878A, 0x3232, 0x878B, 0x3239, 0x878C, 0x32A4, 0x8785, 0x32A5, 0x8786, 0x32A6, 0x8787, + 0x32A7, 0x8788, 0x32A8, 0x8789, 0x3303, 0x8765, 0x330D, 0x8769, 0x3314, 0x8760, 0x3318, 0x8763, 0x3322, 0x8761, 0x3323, 0x876B, + 0x3326, 0x876A, 0x3327, 0x8764, 0x332B, 0x876C, 0x3336, 0x8766, 0x333B, 0x876E, 0x3349, 0x875F, 0x334A, 0x876D, 0x334D, 0x8762, + 0x3351, 0x8767, 0x3357, 0x8768, 0x337B, 0x877E, 0x337C, 0x878F, 0x337D, 0x878E, 0x337E, 0x878D, 0x338E, 0x8772, 0x338F, 0x8773, + 0x339C, 0x876F, 0x339D, 0x8770, 0x339E, 0x8771, 0x33A1, 0x8775, 0x33C4, 0x8774, 0x33CD, 0x8783, 0x4E00, 0x88EA, 0x4E01, 0x929A, + 0x4E03, 0x8EB5, 0x4E07, 0x969C, 0x4E08, 0x8FE4, 0x4E09, 0x8E4F, 0x4E0A, 0x8FE3, 0x4E0B, 0x89BA, 0x4E0D, 0x9573, 0x4E0E, 0x975E, + 0x4E10, 0x98A0, 0x4E11, 0x894E, 0x4E14, 0x8A8E, 0x4E15, 0x98A1, 0x4E16, 0x90A2, 0x4E17, 0x99C0, 0x4E18, 0x8B75, 0x4E19, 0x95B8, + 0x4E1E, 0x8FE5, 0x4E21, 0x97BC, 0x4E26, 0x95C0, 0x4E28, 0xFA68, 0x4E2A, 0x98A2, 0x4E2D, 0x9286, 0x4E31, 0x98A3, 0x4E32, 0x8BF8, + 0x4E36, 0x98A4, 0x4E38, 0x8ADB, 0x4E39, 0x924F, 0x4E3B, 0x8EE5, 0x4E3C, 0x98A5, 0x4E3F, 0x98A6, 0x4E42, 0x98A7, 0x4E43, 0x9454, + 0x4E45, 0x8B76, 0x4E4B, 0x9456, 0x4E4D, 0x93E1, 0x4E4E, 0x8CC1, 0x4E4F, 0x9652, 0x4E55, 0xE568, 0x4E56, 0x98A8, 0x4E57, 0x8FE6, + 0x4E58, 0x98A9, 0x4E59, 0x89B3, 0x4E5D, 0x8BE3, 0x4E5E, 0x8CEE, 0x4E5F, 0x96E7, 0x4E62, 0x9BA4, 0x4E71, 0x9790, 0x4E73, 0x93FB, + 0x4E7E, 0x8AA3, 0x4E80, 0x8B54, 0x4E82, 0x98AA, 0x4E85, 0x98AB, 0x4E86, 0x97B9, 0x4E88, 0x975C, 0x4E89, 0x9188, 0x4E8A, 0x98AD, + 0x4E8B, 0x8E96, 0x4E8C, 0x93F1, 0x4E8E, 0x98B0, 0x4E91, 0x895D, 0x4E92, 0x8CDD, 0x4E94, 0x8CDC, 0x4E95, 0x88E4, 0x4E98, 0x986A, + 0x4E99, 0x9869, 0x4E9B, 0x8DB1, 0x4E9C, 0x889F, 0x4E9E, 0x98B1, 0x4E9F, 0x98B2, 0x4EA0, 0x98B3, 0x4EA1, 0x9653, 0x4EA2, 0x98B4, + 0x4EA4, 0x8CF0, 0x4EA5, 0x88E5, 0x4EA6, 0x9692, 0x4EA8, 0x8B9C, 0x4EAB, 0x8B9D, 0x4EAC, 0x8B9E, 0x4EAD, 0x92E0, 0x4EAE, 0x97BA, + 0x4EB0, 0x98B5, 0x4EB3, 0x98B6, 0x4EB6, 0x98B7, 0x4EBA, 0x906C, 0x4EC0, 0x8F59, 0x4EC1, 0x906D, 0x4EC2, 0x98BC, 0x4EC4, 0x98BA, + 0x4EC6, 0x98BB, 0x4EC7, 0x8B77, 0x4ECA, 0x8DA1, 0x4ECB, 0x89EE, 0x4ECD, 0x98B9, 0x4ECE, 0x98B8, 0x4ECF, 0x95A7, 0x4ED4, 0x8E65, + 0x4ED5, 0x8E64, 0x4ED6, 0x91BC, 0x4ED7, 0x98BD, 0x4ED8, 0x9574, 0x4ED9, 0x90E5, 0x4EDD, 0x8157, 0x4EDE, 0x98BE, 0x4EDF, 0x98C0, + 0x4EE1, 0xFA69, 0x4EE3, 0x91E3, 0x4EE4, 0x97DF, 0x4EE5, 0x88C8, 0x4EED, 0x98BF, 0x4EEE, 0x89BC, 0x4EF0, 0x8BC2, 0x4EF2, 0x9287, + 0x4EF6, 0x8C8F, 0x4EF7, 0x98C1, 0x4EFB, 0x9443, 0x4EFC, 0xFA6A, 0x4F00, 0xFA6B, 0x4F01, 0x8AE9, 0x4F03, 0xFA6C, 0x4F09, 0x98C2, + 0x4F0A, 0x88C9, 0x4F0D, 0x8CDE, 0x4F0E, 0x8AEA, 0x4F0F, 0x959A, 0x4F10, 0x94B0, 0x4F11, 0x8B78, 0x4F1A, 0x89EF, 0x4F1C, 0x98E5, + 0x4F1D, 0x9360, 0x4F2F, 0x948C, 0x4F30, 0x98C4, 0x4F34, 0x94BA, 0x4F36, 0x97E0, 0x4F38, 0x904C, 0x4F39, 0xFA6D, 0x4F3A, 0x8E66, + 0x4F3C, 0x8E97, 0x4F3D, 0x89BE, 0x4F43, 0x92CF, 0x4F46, 0x9241, 0x4F47, 0x98C8, 0x4F4D, 0x88CA, 0x4F4E, 0x92E1, 0x4F4F, 0x8F5A, + 0x4F50, 0x8DB2, 0x4F51, 0x9743, 0x4F53, 0x91CC, 0x4F55, 0x89BD, 0x4F56, 0xFA6E, 0x4F57, 0x98C7, 0x4F59, 0x975D, 0x4F5A, 0x98C3, + 0x4F5B, 0x98C5, 0x4F5C, 0x8DEC, 0x4F5D, 0x98C6, 0x4F5E, 0x9B43, 0x4F69, 0x98CE, 0x4F6F, 0x98D1, 0x4F70, 0x98CF, 0x4F73, 0x89C0, + 0x4F75, 0x95B9, 0x4F76, 0x98C9, 0x4F7B, 0x98CD, 0x4F7C, 0x8CF1, 0x4F7F, 0x8E67, 0x4F83, 0x8AA4, 0x4F86, 0x98D2, 0x4F88, 0x98CA, + 0x4F8A, 0xFA70, 0x4F8B, 0x97E1, 0x4F8D, 0x8E98, 0x4F8F, 0x98CB, 0x4F91, 0x98D0, 0x4F92, 0xFA6F, 0x4F94, 0xFA72, 0x4F96, 0x98D3, + 0x4F98, 0x98CC, 0x4F9A, 0xFA71, 0x4F9B, 0x8B9F, 0x4F9D, 0x88CB, 0x4FA0, 0x8BA0, 0x4FA1, 0x89BF, 0x4FAB, 0x9B44, 0x4FAD, 0x9699, + 0x4FAE, 0x958E, 0x4FAF, 0x8CF2, 0x4FB5, 0x904E, 0x4FB6, 0x97B5, 0x4FBF, 0x95D6, 0x4FC2, 0x8C57, 0x4FC3, 0x91A3, 0x4FC4, 0x89E2, + 0x4FC9, 0xFA61, 0x4FCA, 0x8F72, 0x4FCD, 0xFA73, 0x4FCE, 0x98D7, 0x4FD0, 0x98DC, 0x4FD1, 0x98DA, 0x4FD4, 0x98D5, 0x4FD7, 0x91AD, + 0x4FD8, 0x98D8, 0x4FDA, 0x98DB, 0x4FDB, 0x98D9, 0x4FDD, 0x95DB, 0x4FDF, 0x98D6, 0x4FE1, 0x904D, 0x4FE3, 0x9693, 0x4FE4, 0x98DD, + 0x4FE5, 0x98DE, 0x4FEE, 0x8F43, 0x4FEF, 0x98EB, 0x4FF3, 0x946F, 0x4FF5, 0x9555, 0x4FF6, 0x98E6, 0x4FF8, 0x95EE, 0x4FFA, 0x89B4, + 0x4FFE, 0x98EA, 0x4FFF, 0xFA76, 0x5005, 0x98E4, 0x5006, 0x98ED, 0x5009, 0x9171, 0x500B, 0x8CC2, 0x500D, 0x947B, 0x500F, 0xE0C5, + 0x5011, 0x98EC, 0x5012, 0x937C, 0x5014, 0x98E1, 0x5016, 0x8CF4, 0x5019, 0x8CF3, 0x501A, 0x98DF, 0x501E, 0xFA77, 0x501F, 0x8ED8, + 0x5021, 0x98E7, 0x5022, 0xFA75, 0x5023, 0x95ED, 0x5024, 0x926C, 0x5025, 0x98E3, 0x5026, 0x8C91, 0x5028, 0x98E0, 0x5029, 0x98E8, + 0x502A, 0x98E2, 0x502B, 0x97CF, 0x502C, 0x98E9, 0x502D, 0x9860, 0x5036, 0x8BE4, 0x5039, 0x8C90, 0x5040, 0xFA74, 0x5042, 0xFA7A, + 0x5043, 0x98EE, 0x5046, 0xFA78, 0x5047, 0x98EF, 0x5048, 0x98F3, 0x5049, 0x88CC, 0x504F, 0x95CE, 0x5050, 0x98F2, 0x5055, 0x98F1, + 0x5056, 0x98F5, 0x505A, 0x98F4, 0x505C, 0x92E2, 0x5065, 0x8C92, 0x506C, 0x98F6, 0x5070, 0xFA79, 0x5072, 0x8EC3, 0x5074, 0x91A4, + 0x5075, 0x92E3, 0x5076, 0x8BF4, 0x5078, 0x98F7, 0x507D, 0x8B55, 0x5080, 0x98F8, 0x5085, 0x98FA, 0x508D, 0x9654, 0x5091, 0x8C86, + 0x5094, 0xFA7B, 0x5098, 0x8E50, 0x5099, 0x94F5, 0x509A, 0x98F9, 0x50AC, 0x8DC3, 0x50AD, 0x9762, 0x50B2, 0x98FC, 0x50B3, 0x9942, + 0x50B4, 0x98FB, 0x50B5, 0x8DC2, 0x50B7, 0x8F9D, 0x50BE, 0x8C58, 0x50C2, 0x9943, 0x50C5, 0x8BCD, 0x50C9, 0x9940, 0x50CA, 0x9941, + 0x50CD, 0x93AD, 0x50CF, 0x919C, 0x50D1, 0x8BA1, 0x50D5, 0x966C, 0x50D6, 0x9944, 0x50D8, 0xFA7D, 0x50DA, 0x97BB, 0x50DE, 0x9945, + 0x50E3, 0x9948, 0x50E5, 0x9946, 0x50E7, 0x916D, 0x50ED, 0x9947, 0x50EE, 0x9949, 0x50F4, 0xFA7C, 0x50F5, 0x994B, 0x50F9, 0x994A, + 0x50FB, 0x95C6, 0x5100, 0x8B56, 0x5101, 0x994D, 0x5102, 0x994E, 0x5104, 0x89AD, 0x5109, 0x994C, 0x5112, 0x8EF2, 0x5114, 0x9951, + 0x5115, 0x9950, 0x5116, 0x994F, 0x5118, 0x98D4, 0x511A, 0x9952, 0x511F, 0x8F9E, 0x5121, 0x9953, 0x512A, 0x9744, 0x5132, 0x96D7, + 0x5137, 0x9955, 0x513A, 0x9954, 0x513B, 0x9957, 0x513C, 0x9956, 0x513F, 0x9958, 0x5140, 0x9959, 0x5141, 0x88F2, 0x5143, 0x8CB3, + 0x5144, 0x8C5A, 0x5145, 0x8F5B, 0x5146, 0x929B, 0x5147, 0x8BA2, 0x5148, 0x90E6, 0x5149, 0x8CF5, 0x514A, 0xFA7E, 0x514B, 0x8D8E, + 0x514C, 0x995B, 0x514D, 0x96C6, 0x514E, 0x9365, 0x5150, 0x8E99, 0x5152, 0x995A, 0x5154, 0x995C, 0x515A, 0x937D, 0x515C, 0x8A95, + 0x5162, 0x995D, 0x5164, 0xFA80, 0x5165, 0x93FC, 0x5168, 0x9153, 0x5169, 0x995F, 0x516A, 0x9960, 0x516B, 0x94AA, 0x516C, 0x8CF6, + 0x516D, 0x985A, 0x516E, 0x9961, 0x5171, 0x8BA4, 0x5175, 0x95BA, 0x5176, 0x91B4, 0x5177, 0x8BEF, 0x5178, 0x9354, 0x517C, 0x8C93, + 0x5180, 0x9962, 0x5182, 0x9963, 0x5185, 0x93E0, 0x5186, 0x897E, 0x5189, 0x9966, 0x518A, 0x8DFB, 0x518C, 0x9965, 0x518D, 0x8DC4, + 0x518F, 0x9967, 0x5190, 0xE3EC, 0x5191, 0x9968, 0x5192, 0x9660, 0x5193, 0x9969, 0x5195, 0x996A, 0x5196, 0x996B, 0x5197, 0x8FE7, + 0x5199, 0x8ECA, 0x519D, 0xFA81, 0x51A0, 0x8AA5, 0x51A2, 0x996E, 0x51A4, 0x996C, 0x51A5, 0x96BB, 0x51A6, 0x996D, 0x51A8, 0x9579, + 0x51A9, 0x996F, 0x51AA, 0x9970, 0x51AB, 0x9971, 0x51AC, 0x937E, 0x51B0, 0x9975, 0x51B1, 0x9973, 0x51B2, 0x9974, 0x51B3, 0x9972, + 0x51B4, 0x8DE1, 0x51B5, 0x9976, 0x51B6, 0x96E8, 0x51B7, 0x97E2, 0x51BD, 0x9977, 0x51BE, 0xFA82, 0x51C4, 0x90A6, 0x51C5, 0x9978, + 0x51C6, 0x8F79, 0x51C9, 0x9979, 0x51CB, 0x929C, 0x51CC, 0x97BD, 0x51CD, 0x9380, 0x51D6, 0x99C3, 0x51DB, 0x997A, 0x51DC, 0xEAA3, + 0x51DD, 0x8BC3, 0x51E0, 0x997B, 0x51E1, 0x967D, 0x51E6, 0x8F88, 0x51E7, 0x91FA, 0x51E9, 0x997D, 0x51EA, 0x93E2, 0x51EC, 0xFA83, + 0x51ED, 0x997E, 0x51F0, 0x9980, 0x51F1, 0x8A4D, 0x51F5, 0x9981, 0x51F6, 0x8BA5, 0x51F8, 0x93CA, 0x51F9, 0x899A, 0x51FA, 0x8F6F, + 0x51FD, 0x949F, 0x51FE, 0x9982, 0x5200, 0x9381, 0x5203, 0x906E, 0x5204, 0x9983, 0x5206, 0x95AA, 0x5207, 0x90D8, 0x5208, 0x8AA0, + 0x520A, 0x8AA7, 0x520B, 0x9984, 0x520E, 0x9986, 0x5211, 0x8C59, 0x5214, 0x9985, 0x5215, 0xFA84, 0x5217, 0x97F1, 0x521D, 0x8F89, + 0x5224, 0x94BB, 0x5225, 0x95CA, 0x5227, 0x9987, 0x5229, 0x9798, 0x522A, 0x9988, 0x522E, 0x9989, 0x5230, 0x939E, 0x5233, 0x998A, + 0x5236, 0x90A7, 0x5237, 0x8DFC, 0x5238, 0x8C94, 0x5239, 0x998B, 0x523A, 0x8E68, 0x523B, 0x8D8F, 0x5243, 0x92E4, 0x5244, 0x998D, + 0x5247, 0x91A5, 0x524A, 0x8DED, 0x524B, 0x998E, 0x524C, 0x998F, 0x524D, 0x914F, 0x524F, 0x998C, 0x5254, 0x9991, 0x5256, 0x9655, + 0x525B, 0x8D84, 0x525E, 0x9990, 0x5263, 0x8C95, 0x5264, 0x8DDC, 0x5265, 0x948D, 0x5269, 0x9994, 0x526A, 0x9992, 0x526F, 0x959B, + 0x5270, 0x8FE8, 0x5271, 0x999B, 0x5272, 0x8A84, 0x5273, 0x9995, 0x5274, 0x9993, 0x5275, 0x916E, 0x527D, 0x9997, 0x527F, 0x9996, + 0x5283, 0x8A63, 0x5287, 0x8C80, 0x5288, 0x999C, 0x5289, 0x97AB, 0x528D, 0x9998, 0x5291, 0x999D, 0x5292, 0x999A, 0x5294, 0x9999, + 0x529B, 0x97CD, 0x529C, 0xFA85, 0x529F, 0x8CF7, 0x52A0, 0x89C1, 0x52A3, 0x97F2, 0x52A6, 0xFA86, 0x52A9, 0x8F95, 0x52AA, 0x9377, + 0x52AB, 0x8D85, 0x52AC, 0x99A0, 0x52AD, 0x99A1, 0x52AF, 0xFB77, 0x52B1, 0x97E3, 0x52B4, 0x984A, 0x52B5, 0x99A3, 0x52B9, 0x8CF8, + 0x52BC, 0x99A2, 0x52BE, 0x8A4E, 0x52C0, 0xFA87, 0x52C1, 0x99A4, 0x52C3, 0x9675, 0x52C5, 0x92BA, 0x52C7, 0x9745, 0x52C9, 0x95D7, + 0x52CD, 0x99A5, 0x52D2, 0xE8D3, 0x52D5, 0x93AE, 0x52D7, 0x99A6, 0x52D8, 0x8AA8, 0x52D9, 0x96B1, 0x52DB, 0xFA88, 0x52DD, 0x8F9F, + 0x52DE, 0x99A7, 0x52DF, 0x95E5, 0x52E0, 0x99AB, 0x52E2, 0x90A8, 0x52E3, 0x99A8, 0x52E4, 0x8BCE, 0x52E6, 0x99A9, 0x52E7, 0x8AA9, + 0x52F2, 0x8C4D, 0x52F3, 0x99AC, 0x52F5, 0x99AD, 0x52F8, 0x99AE, 0x52F9, 0x99AF, 0x52FA, 0x8ED9, 0x52FE, 0x8CF9, 0x52FF, 0x96DC, + 0x5300, 0xFA89, 0x5301, 0x96E6, 0x5302, 0x93F5, 0x5305, 0x95EF, 0x5306, 0x99B0, 0x5307, 0xFA8A, 0x5308, 0x99B1, 0x530D, 0x99B3, + 0x530F, 0x99B5, 0x5310, 0x99B4, 0x5315, 0x99B6, 0x5316, 0x89BB, 0x5317, 0x966B, 0x5319, 0x8DFA, 0x531A, 0x99B7, 0x531D, 0x9178, + 0x5320, 0x8FA0, 0x5321, 0x8BA7, 0x5323, 0x99B8, 0x5324, 0xFA8B, 0x532A, 0x94D9, 0x532F, 0x99B9, 0x5331, 0x99BA, 0x5333, 0x99BB, + 0x5338, 0x99BC, 0x5339, 0x9543, 0x533A, 0x8BE6, 0x533B, 0x88E3, 0x533F, 0x93BD, 0x5340, 0x99BD, 0x5341, 0x8F5C, 0x5343, 0x90E7, + 0x5345, 0x99BF, 0x5346, 0x99BE, 0x5347, 0x8FA1, 0x5348, 0x8CDF, 0x5349, 0x99C1, 0x534A, 0x94BC, 0x534D, 0x99C2, 0x5351, 0x94DA, + 0x5352, 0x91B2, 0x5353, 0x91EC, 0x5354, 0x8BA6, 0x5357, 0x93EC, 0x5358, 0x9250, 0x535A, 0x948E, 0x535C, 0x966D, 0x535E, 0x99C4, + 0x5360, 0x90E8, 0x5366, 0x8C54, 0x5369, 0x99C5, 0x536E, 0x99C6, 0x536F, 0x894B, 0x5370, 0x88F3, 0x5371, 0x8AEB, 0x5372, 0xFA8C, + 0x5373, 0x91A6, 0x5374, 0x8B70, 0x5375, 0x9791, 0x5377, 0x99C9, 0x5378, 0x89B5, 0x537B, 0x99C8, 0x537F, 0x8BA8, 0x5382, 0x99CA, + 0x5384, 0x96EF, 0x5393, 0xFA8D, 0x5396, 0x99CB, 0x5398, 0x97D0, 0x539A, 0x8CFA, 0x539F, 0x8CB4, 0x53A0, 0x99CC, 0x53A5, 0x99CE, + 0x53A6, 0x99CD, 0x53A8, 0x907E, 0x53A9, 0x8958, 0x53AD, 0x897D, 0x53AE, 0x99CF, 0x53B0, 0x99D0, 0x53B2, 0xFA8E, 0x53B3, 0x8CB5, + 0x53B6, 0x99D1, 0x53BB, 0x8B8E, 0x53C2, 0x8E51, 0x53C3, 0x99D2, 0x53C8, 0x9694, 0x53C9, 0x8DB3, 0x53CA, 0x8B79, 0x53CB, 0x9746, + 0x53CC, 0x916F, 0x53CD, 0x94BD, 0x53CE, 0x8EFB, 0x53D4, 0x8F66, 0x53D6, 0x8EE6, 0x53D7, 0x8EF3, 0x53D9, 0x8F96, 0x53DB, 0x94BE, + 0x53DD, 0xFA8F, 0x53DF, 0x99D5, 0x53E1, 0x8962, 0x53E2, 0x9170, 0x53E3, 0x8CFB, 0x53E4, 0x8CC3, 0x53E5, 0x8BE5, 0x53E8, 0x99D9, + 0x53E9, 0x9240, 0x53EA, 0x91FC, 0x53EB, 0x8BA9, 0x53EC, 0x8FA2, 0x53ED, 0x99DA, 0x53EE, 0x99D8, 0x53EF, 0x89C2, 0x53F0, 0x91E4, + 0x53F1, 0x8EB6, 0x53F2, 0x8E6A, 0x53F3, 0x8945, 0x53F6, 0x8A90, 0x53F7, 0x8D86, 0x53F8, 0x8E69, 0x53FA, 0x99DB, 0x5401, 0x99DC, + 0x5403, 0x8B68, 0x5404, 0x8A65, 0x5408, 0x8D87, 0x5409, 0x8B67, 0x540A, 0x92DD, 0x540B, 0x8944, 0x540C, 0x93AF, 0x540D, 0x96BC, + 0x540E, 0x8D40, 0x540F, 0x9799, 0x5410, 0x9366, 0x5411, 0x8CFC, 0x541B, 0x8C4E, 0x541D, 0x99E5, 0x541F, 0x8BE1, 0x5420, 0x9669, + 0x5426, 0x94DB, 0x5429, 0x99E4, 0x542B, 0x8ADC, 0x542C, 0x99DF, 0x542D, 0x99E0, 0x542E, 0x99E2, 0x5436, 0x99E3, 0x5438, 0x8B7A, + 0x5439, 0x9081, 0x543B, 0x95AB, 0x543C, 0x99E1, 0x543D, 0x99DD, 0x543E, 0x8CE1, 0x5440, 0x99DE, 0x5442, 0x9843, 0x5446, 0x95F0, + 0x5448, 0x92E6, 0x5449, 0x8CE0, 0x544A, 0x8D90, 0x544E, 0x99E6, 0x5451, 0x93DB, 0x545F, 0x99EA, 0x5468, 0x8EFC, 0x546A, 0x8EF4, + 0x5470, 0x99ED, 0x5471, 0x99EB, 0x5473, 0x96A1, 0x5475, 0x99E8, 0x5476, 0x99F1, 0x5477, 0x99EC, 0x547B, 0x99EF, 0x547C, 0x8CC4, + 0x547D, 0x96BD, 0x5480, 0x99F0, 0x5484, 0x99F2, 0x5486, 0x99F4, 0x548A, 0xFA92, 0x548B, 0x8DEE, 0x548C, 0x9861, 0x548E, 0x99E9, + 0x548F, 0x99E7, 0x5490, 0x99F3, 0x5492, 0x99EE, 0x549C, 0xFA91, 0x54A2, 0x99F6, 0x54A4, 0x9A42, 0x54A5, 0x99F8, 0x54A8, 0x99FC, + 0x54A9, 0xFA93, 0x54AB, 0x9A40, 0x54AC, 0x99F9, 0x54AF, 0x9A5D, 0x54B2, 0x8DE7, 0x54B3, 0x8A50, 0x54B8, 0x99F7, 0x54BC, 0x9A44, + 0x54BD, 0x88F4, 0x54BE, 0x9A43, 0x54C0, 0x88A3, 0x54C1, 0x9569, 0x54C2, 0x9A41, 0x54C4, 0x99FA, 0x54C7, 0x99F5, 0x54C8, 0x99FB, + 0x54C9, 0x8DC6, 0x54D8, 0x9A45, 0x54E1, 0x88F5, 0x54E2, 0x9A4E, 0x54E5, 0x9A46, 0x54E6, 0x9A47, 0x54E8, 0x8FA3, 0x54E9, 0x9689, + 0x54ED, 0x9A4C, 0x54EE, 0x9A4B, 0x54F2, 0x934E, 0x54FA, 0x9A4D, 0x54FD, 0x9A4A, 0x54FF, 0xFA94, 0x5504, 0x8953, 0x5506, 0x8DB4, + 0x5507, 0x904F, 0x550F, 0x9A48, 0x5510, 0x9382, 0x5514, 0x9A49, 0x5516, 0x88A0, 0x552E, 0x9A53, 0x552F, 0x9742, 0x5531, 0x8FA5, + 0x5533, 0x9A59, 0x5538, 0x9A58, 0x5539, 0x9A4F, 0x553E, 0x91C1, 0x5540, 0x9A50, 0x5544, 0x91ED, 0x5545, 0x9A55, 0x5546, 0x8FA4, + 0x554C, 0x9A52, 0x554F, 0x96E2, 0x5553, 0x8C5B, 0x5556, 0x9A56, 0x5557, 0x9A57, 0x555C, 0x9A54, 0x555D, 0x9A5A, 0x5563, 0x9A51, + 0x557B, 0x9A60, 0x557C, 0x9A65, 0x557E, 0x9A61, 0x5580, 0x9A5C, 0x5583, 0x9A66, 0x5584, 0x9150, 0x5586, 0xFA95, 0x5587, 0x9A68, + 0x5589, 0x8D41, 0x558A, 0x9A5E, 0x558B, 0x929D, 0x5598, 0x9A62, 0x5599, 0x9A5B, 0x559A, 0x8AAB, 0x559C, 0x8AEC, 0x559D, 0x8A85, + 0x559E, 0x9A63, 0x559F, 0x9A5F, 0x55A7, 0x8C96, 0x55A8, 0x9A69, 0x55A9, 0x9A67, 0x55AA, 0x9172, 0x55AB, 0x8B69, 0x55AC, 0x8BAA, + 0x55AE, 0x9A64, 0x55B0, 0x8BF2, 0x55B6, 0x8963, 0x55C4, 0x9A6D, 0x55C5, 0x9A6B, 0x55C7, 0x9AA5, 0x55D4, 0x9A70, 0x55DA, 0x9A6A, + 0x55DC, 0x9A6E, 0x55DF, 0x9A6C, 0x55E3, 0x8E6B, 0x55E4, 0x9A6F, 0x55F7, 0x9A72, 0x55F9, 0x9A77, 0x55FD, 0x9A75, 0x55FE, 0x9A74, + 0x5606, 0x9251, 0x5609, 0x89C3, 0x5614, 0x9A71, 0x5616, 0x9A73, 0x5617, 0x8FA6, 0x5618, 0x8952, 0x561B, 0x9A76, 0x5629, 0x89DC, + 0x562F, 0x9A82, 0x5631, 0x8FFA, 0x5632, 0x9A7D, 0x5634, 0x9A7B, 0x5636, 0x9A7C, 0x5638, 0x9A7E, 0x5642, 0x895C, 0x564C, 0x9158, + 0x564E, 0x9A78, 0x5650, 0x9A79, 0x565B, 0x8A9A, 0x5664, 0x9A81, 0x5668, 0x8AED, 0x566A, 0x9A84, 0x566B, 0x9A80, 0x566C, 0x9A83, + 0x5674, 0x95AC, 0x5678, 0x93D3, 0x567A, 0x94B6, 0x5680, 0x9A86, 0x5686, 0x9A85, 0x5687, 0x8A64, 0x568A, 0x9A87, 0x568F, 0x9A8A, + 0x5694, 0x9A89, 0x56A0, 0x9A88, 0x56A2, 0x9458, 0x56A5, 0x9A8B, 0x56AE, 0x9A8C, 0x56B4, 0x9A8E, 0x56B6, 0x9A8D, 0x56BC, 0x9A90, + 0x56C0, 0x9A93, 0x56C1, 0x9A91, 0x56C2, 0x9A8F, 0x56C3, 0x9A92, 0x56C8, 0x9A94, 0x56CE, 0x9A95, 0x56D1, 0x9A96, 0x56D3, 0x9A97, + 0x56D7, 0x9A98, 0x56D8, 0x9964, 0x56DA, 0x8EFA, 0x56DB, 0x8E6C, 0x56DE, 0x89F1, 0x56E0, 0x88F6, 0x56E3, 0x9263, 0x56EE, 0x9A99, + 0x56F0, 0x8DA2, 0x56F2, 0x88CD, 0x56F3, 0x907D, 0x56F9, 0x9A9A, 0x56FA, 0x8CC5, 0x56FD, 0x8D91, 0x56FF, 0x9A9C, 0x5700, 0x9A9B, + 0x5703, 0x95DE, 0x5704, 0x9A9D, 0x5708, 0x9A9F, 0x5709, 0x9A9E, 0x570B, 0x9AA0, 0x570D, 0x9AA1, 0x570F, 0x8C97, 0x5712, 0x8980, + 0x5713, 0x9AA2, 0x5716, 0x9AA4, 0x5718, 0x9AA3, 0x571C, 0x9AA6, 0x571F, 0x9379, 0x5726, 0x9AA7, 0x5727, 0x88B3, 0x5728, 0x8DDD, + 0x572D, 0x8C5C, 0x5730, 0x926E, 0x5737, 0x9AA8, 0x5738, 0x9AA9, 0x573B, 0x9AAB, 0x5740, 0x9AAC, 0x5742, 0x8DE2, 0x5747, 0x8BCF, + 0x574A, 0x9656, 0x574E, 0x9AAA, 0x574F, 0x9AAD, 0x5750, 0x8DBF, 0x5751, 0x8D42, 0x5759, 0xFA96, 0x5761, 0x9AB1, 0x5764, 0x8DA3, + 0x5765, 0xFA97, 0x5766, 0x9252, 0x5769, 0x9AAE, 0x576A, 0x92D8, 0x577F, 0x9AB2, 0x5782, 0x9082, 0x5788, 0x9AB0, 0x5789, 0x9AB3, + 0x578B, 0x8C5E, 0x5793, 0x9AB4, 0x57A0, 0x9AB5, 0x57A2, 0x8D43, 0x57A3, 0x8A5F, 0x57A4, 0x9AB7, 0x57AA, 0x9AB8, 0x57AC, 0xFA98, + 0x57B0, 0x9AB9, 0x57B3, 0x9AB6, 0x57C0, 0x9AAF, 0x57C3, 0x9ABA, 0x57C6, 0x9ABB, 0x57C7, 0xFA9A, 0x57C8, 0xFA99, 0x57CB, 0x9684, + 0x57CE, 0x8FE9, 0x57D2, 0x9ABD, 0x57D3, 0x9ABE, 0x57D4, 0x9ABC, 0x57D6, 0x9AC0, 0x57DC, 0x9457, 0x57DF, 0x88E6, 0x57E0, 0x9575, + 0x57E3, 0x9AC1, 0x57F4, 0x8FFB, 0x57F7, 0x8EB7, 0x57F9, 0x947C, 0x57FA, 0x8AEE, 0x57FC, 0x8DE9, 0x5800, 0x9678, 0x5802, 0x93B0, + 0x5805, 0x8C98, 0x5806, 0x91CD, 0x580A, 0x9ABF, 0x580B, 0x9AC2, 0x5815, 0x91C2, 0x5819, 0x9AC3, 0x581D, 0x9AC4, 0x5821, 0x9AC6, + 0x5824, 0x92E7, 0x582A, 0x8AAC, 0x582F, 0xEA9F, 0x5830, 0x8981, 0x5831, 0x95F1, 0x5834, 0x8FEA, 0x5835, 0x9367, 0x583A, 0x8DE4, + 0x583D, 0x9ACC, 0x5840, 0x95BB, 0x5841, 0x97DB, 0x584A, 0x89F2, 0x584B, 0x9AC8, 0x5851, 0x9159, 0x5852, 0x9ACB, 0x5854, 0x9383, + 0x5857, 0x9368, 0x5858, 0x9384, 0x5859, 0x94B7, 0x585A, 0x92CB, 0x585E, 0x8DC7, 0x5862, 0x9AC7, 0x5869, 0x8996, 0x586B, 0x9355, + 0x5870, 0x9AC9, 0x5872, 0x9AC5, 0x5875, 0x906F, 0x5879, 0x9ACD, 0x587E, 0x8F6D, 0x5883, 0x8BAB, 0x5885, 0x9ACE, 0x5893, 0x95E6, + 0x5897, 0x919D, 0x589C, 0x92C4, 0x589E, 0xFA9D, 0x589F, 0x9AD0, 0x58A8, 0x966E, 0x58AB, 0x9AD1, 0x58AE, 0x9AD6, 0x58B2, 0xFA9E, + 0x58B3, 0x95AD, 0x58B8, 0x9AD5, 0x58B9, 0x9ACF, 0x58BA, 0x9AD2, 0x58BB, 0x9AD4, 0x58BE, 0x8DA4, 0x58C1, 0x95C7, 0x58C5, 0x9AD7, + 0x58C7, 0x9264, 0x58CA, 0x89F3, 0x58CC, 0x8FEB, 0x58D1, 0x9AD9, 0x58D3, 0x9AD8, 0x58D5, 0x8D88, 0x58D7, 0x9ADA, 0x58D8, 0x9ADC, + 0x58D9, 0x9ADB, 0x58DC, 0x9ADE, 0x58DE, 0x9AD3, 0x58DF, 0x9AE0, 0x58E4, 0x9ADF, 0x58E5, 0x9ADD, 0x58EB, 0x8E6D, 0x58EC, 0x9070, + 0x58EE, 0x9173, 0x58EF, 0x9AE1, 0x58F0, 0x90BA, 0x58F1, 0x88EB, 0x58F2, 0x9484, 0x58F7, 0x92D9, 0x58F9, 0x9AE3, 0x58FA, 0x9AE2, + 0x58FB, 0x9AE4, 0x58FC, 0x9AE5, 0x58FD, 0x9AE6, 0x5902, 0x9AE7, 0x5909, 0x95CF, 0x590A, 0x9AE8, 0x590B, 0xFA9F, 0x590F, 0x89C4, + 0x5910, 0x9AE9, 0x5915, 0x975B, 0x5916, 0x8A4F, 0x5918, 0x99C7, 0x5919, 0x8F67, 0x591A, 0x91BD, 0x591B, 0x9AEA, 0x591C, 0x96E9, + 0x5922, 0x96B2, 0x5925, 0x9AEC, 0x5927, 0x91E5, 0x5929, 0x9356, 0x592A, 0x91BE, 0x592B, 0x9576, 0x592C, 0x9AED, 0x592D, 0x9AEE, + 0x592E, 0x899B, 0x5931, 0x8EB8, 0x5932, 0x9AEF, 0x5937, 0x88CE, 0x5938, 0x9AF0, 0x593E, 0x9AF1, 0x5944, 0x8982, 0x5947, 0x8AEF, + 0x5948, 0x93DE, 0x5949, 0x95F2, 0x594E, 0x9AF5, 0x594F, 0x9174, 0x5950, 0x9AF4, 0x5951, 0x8C5F, 0x5953, 0xFAA0, 0x5954, 0x967A, + 0x5955, 0x9AF3, 0x5957, 0x9385, 0x5958, 0x9AF7, 0x595A, 0x9AF6, 0x595B, 0xFAA1, 0x595D, 0xFAA2, 0x5960, 0x9AF9, 0x5962, 0x9AF8, + 0x5963, 0xFAA3, 0x5965, 0x899C, 0x5967, 0x9AFA, 0x5968, 0x8FA7, 0x5969, 0x9AFC, 0x596A, 0x9244, 0x596C, 0x9AFB, 0x596E, 0x95B1, + 0x5973, 0x8F97, 0x5974, 0x937A, 0x5978, 0x9B40, 0x597D, 0x8D44, 0x5981, 0x9B41, 0x5982, 0x9440, 0x5983, 0x94DC, 0x5984, 0x96CF, + 0x598A, 0x9444, 0x598D, 0x9B4A, 0x5993, 0x8B57, 0x5996, 0x9764, 0x5999, 0x96AD, 0x599B, 0x9BAA, 0x599D, 0x9B42, 0x59A3, 0x9B45, + 0x59A4, 0xFAA4, 0x59A5, 0x91C3, 0x59A8, 0x9657, 0x59AC, 0x9369, 0x59B2, 0x9B46, 0x59B9, 0x9685, 0x59BA, 0xFAA5, 0x59BB, 0x8DC8, + 0x59BE, 0x8FA8, 0x59C6, 0x9B47, 0x59C9, 0x8E6F, 0x59CB, 0x8E6E, 0x59D0, 0x88B7, 0x59D1, 0x8CC6, 0x59D3, 0x90A9, 0x59D4, 0x88CF, + 0x59D9, 0x9B4B, 0x59DA, 0x9B4C, 0x59DC, 0x9B49, 0x59E5, 0x8957, 0x59E6, 0x8AAD, 0x59E8, 0x9B48, 0x59EA, 0x96C3, 0x59EB, 0x9550, + 0x59F6, 0x88A6, 0x59FB, 0x88F7, 0x59FF, 0x8E70, 0x5A01, 0x88D0, 0x5A03, 0x88A1, 0x5A09, 0x9B51, 0x5A11, 0x9B4F, 0x5A18, 0x96BA, + 0x5A1A, 0x9B52, 0x5A1C, 0x9B50, 0x5A1F, 0x9B4E, 0x5A20, 0x9050, 0x5A25, 0x9B4D, 0x5A29, 0x95D8, 0x5A2F, 0x8CE2, 0x5A35, 0x9B56, + 0x5A36, 0x9B57, 0x5A3C, 0x8FA9, 0x5A40, 0x9B53, 0x5A41, 0x984B, 0x5A46, 0x946B, 0x5A49, 0x9B55, 0x5A5A, 0x8DA5, 0x5A62, 0x9B58, + 0x5A66, 0x9577, 0x5A6A, 0x9B59, 0x5A6C, 0x9B54, 0x5A7F, 0x96B9, 0x5A92, 0x947D, 0x5A9A, 0x9B5A, 0x5A9B, 0x9551, 0x5ABC, 0x9B5B, + 0x5ABD, 0x9B5F, 0x5ABE, 0x9B5C, 0x5AC1, 0x89C5, 0x5AC2, 0x9B5E, 0x5AC9, 0x8EB9, 0x5ACB, 0x9B5D, 0x5ACC, 0x8C99, 0x5AD0, 0x9B6B, + 0x5AD6, 0x9B64, 0x5AD7, 0x9B61, 0x5AE1, 0x9284, 0x5AE3, 0x9B60, 0x5AE6, 0x9B62, 0x5AE9, 0x9B63, 0x5AFA, 0x9B65, 0x5AFB, 0x9B66, + 0x5B09, 0x8AF0, 0x5B0B, 0x9B68, 0x5B0C, 0x9B67, 0x5B16, 0x9B69, 0x5B22, 0x8FEC, 0x5B2A, 0x9B6C, 0x5B2C, 0x92DA, 0x5B30, 0x8964, + 0x5B32, 0x9B6A, 0x5B36, 0x9B6D, 0x5B3E, 0x9B6E, 0x5B40, 0x9B71, 0x5B43, 0x9B6F, 0x5B45, 0x9B70, 0x5B50, 0x8E71, 0x5B51, 0x9B72, + 0x5B54, 0x8D45, 0x5B55, 0x9B73, 0x5B56, 0xFAA6, 0x5B57, 0x8E9A, 0x5B58, 0x91B6, 0x5B5A, 0x9B74, 0x5B5B, 0x9B75, 0x5B5C, 0x8E79, + 0x5B5D, 0x8D46, 0x5B5F, 0x96D0, 0x5B63, 0x8B47, 0x5B64, 0x8CC7, 0x5B65, 0x9B76, 0x5B66, 0x8A77, 0x5B69, 0x9B77, 0x5B6B, 0x91B7, + 0x5B70, 0x9B78, 0x5B71, 0x9BA1, 0x5B73, 0x9B79, 0x5B75, 0x9B7A, 0x5B78, 0x9B7B, 0x5B7A, 0x9B7D, 0x5B80, 0x9B7E, 0x5B83, 0x9B80, + 0x5B85, 0x91EE, 0x5B87, 0x8946, 0x5B88, 0x8EE7, 0x5B89, 0x88C0, 0x5B8B, 0x9176, 0x5B8C, 0x8AAE, 0x5B8D, 0x8EB3, 0x5B8F, 0x8D47, + 0x5B95, 0x9386, 0x5B97, 0x8F40, 0x5B98, 0x8AAF, 0x5B99, 0x9288, 0x5B9A, 0x92E8, 0x5B9B, 0x88B6, 0x5B9C, 0x8B58, 0x5B9D, 0x95F3, + 0x5B9F, 0x8EC0, 0x5BA2, 0x8B71, 0x5BA3, 0x90E9, 0x5BA4, 0x8EBA, 0x5BA5, 0x9747, 0x5BA6, 0x9B81, 0x5BAE, 0x8B7B, 0x5BB0, 0x8DC9, + 0x5BB3, 0x8A51, 0x5BB4, 0x8983, 0x5BB5, 0x8FAA, 0x5BB6, 0x89C6, 0x5BB8, 0x9B82, 0x5BB9, 0x9765, 0x5BBF, 0x8F68, 0x5BC0, 0xFAA7, + 0x5BC2, 0x8EE2, 0x5BC3, 0x9B83, 0x5BC4, 0x8AF1, 0x5BC5, 0x93D0, 0x5BC6, 0x96A7, 0x5BC7, 0x9B84, 0x5BC9, 0x9B85, 0x5BCC, 0x9578, + 0x5BD0, 0x9B87, 0x5BD2, 0x8AA6, 0x5BD3, 0x8BF5, 0x5BD4, 0x9B86, 0x5BD8, 0xFAA9, 0x5BDB, 0x8AB0, 0x5BDD, 0x9051, 0x5BDE, 0x9B8B, + 0x5BDF, 0x8E40, 0x5BE1, 0x89C7, 0x5BE2, 0x9B8A, 0x5BE4, 0x9B88, 0x5BE5, 0x9B8C, 0x5BE6, 0x9B89, 0x5BE7, 0x944A, 0x5BE8, 0x9ECB, + 0x5BE9, 0x9052, 0x5BEB, 0x9B8D, 0x5BEC, 0xFAAA, 0x5BEE, 0x97BE, 0x5BF0, 0x9B8E, 0x5BF3, 0x9B90, 0x5BF5, 0x929E, 0x5BF6, 0x9B8F, + 0x5BF8, 0x90A1, 0x5BFA, 0x8E9B, 0x5BFE, 0x91CE, 0x5BFF, 0x8EF5, 0x5C01, 0x9595, 0x5C02, 0x90EA, 0x5C04, 0x8ECB, 0x5C05, 0x9B91, + 0x5C06, 0x8FAB, 0x5C07, 0x9B92, 0x5C08, 0x9B93, 0x5C09, 0x88D1, 0x5C0A, 0x91B8, 0x5C0B, 0x9071, 0x5C0D, 0x9B94, 0x5C0E, 0x93B1, + 0x5C0F, 0x8FAC, 0x5C11, 0x8FAD, 0x5C13, 0x9B95, 0x5C16, 0x90EB, 0x5C1A, 0x8FAE, 0x5C1E, 0xFAAB, 0x5C20, 0x9B96, 0x5C22, 0x9B97, + 0x5C24, 0x96DE, 0x5C28, 0x9B98, 0x5C2D, 0x8BC4, 0x5C31, 0x8F41, 0x5C38, 0x9B99, 0x5C39, 0x9B9A, 0x5C3A, 0x8EDA, 0x5C3B, 0x904B, + 0x5C3C, 0x93F2, 0x5C3D, 0x9073, 0x5C3E, 0x94F6, 0x5C3F, 0x9441, 0x5C40, 0x8BC7, 0x5C41, 0x9B9B, 0x5C45, 0x8B8F, 0x5C46, 0x9B9C, + 0x5C48, 0x8BFC, 0x5C4A, 0x93CD, 0x5C4B, 0x89AE, 0x5C4D, 0x8E72, 0x5C4E, 0x9B9D, 0x5C4F, 0x9BA0, 0x5C50, 0x9B9F, 0x5C51, 0x8BFB, + 0x5C53, 0x9B9E, 0x5C55, 0x9357, 0x5C5E, 0x91AE, 0x5C60, 0x936A, 0x5C61, 0x8EC6, 0x5C64, 0x9177, 0x5C65, 0x979A, 0x5C6C, 0x9BA2, + 0x5C6E, 0x9BA3, 0x5C6F, 0x93D4, 0x5C71, 0x8E52, 0x5C76, 0x9BA5, 0x5C79, 0x9BA6, 0x5C8C, 0x9BA7, 0x5C90, 0x8AF2, 0x5C91, 0x9BA8, + 0x5C94, 0x9BA9, 0x5CA1, 0x89AA, 0x5CA6, 0xFAAC, 0x5CA8, 0x915A, 0x5CA9, 0x8AE2, 0x5CAB, 0x9BAB, 0x5CAC, 0x96A6, 0x5CB1, 0x91D0, + 0x5CB3, 0x8A78, 0x5CB6, 0x9BAD, 0x5CB7, 0x9BAF, 0x5CB8, 0x8ADD, 0x5CBA, 0xFAAD, 0x5CBB, 0x9BAC, 0x5CBC, 0x9BAE, 0x5CBE, 0x9BB1, + 0x5CC5, 0x9BB0, 0x5CC7, 0x9BB2, 0x5CD9, 0x9BB3, 0x5CE0, 0x93BB, 0x5CE1, 0x8BAC, 0x5CE8, 0x89E3, 0x5CE9, 0x9BB4, 0x5CEA, 0x9BB9, + 0x5CED, 0x9BB7, 0x5CEF, 0x95F5, 0x5CF0, 0x95F4, 0x5CF5, 0xFAAE, 0x5CF6, 0x9387, 0x5CFA, 0x9BB6, 0x5CFB, 0x8F73, 0x5CFD, 0x9BB5, + 0x5D07, 0x9092, 0x5D0B, 0x9BBA, 0x5D0E, 0x8DE8, 0x5D11, 0x9BC0, 0x5D14, 0x9BC1, 0x5D15, 0x9BBB, 0x5D16, 0x8A52, 0x5D17, 0x9BBC, + 0x5D18, 0x9BC5, 0x5D19, 0x9BC4, 0x5D1A, 0x9BC3, 0x5D1B, 0x9BBF, 0x5D1F, 0x9BBE, 0x5D22, 0x9BC2, 0x5D27, 0xFAAF, 0x5D29, 0x95F6, + 0x5D42, 0xFAB2, 0x5D4B, 0x9BC9, 0x5D4C, 0x9BC6, 0x5D4E, 0x9BC8, 0x5D50, 0x9792, 0x5D52, 0x9BC7, 0x5D53, 0xFAB0, 0x5D5C, 0x9BBD, + 0x5D69, 0x9093, 0x5D6C, 0x9BCA, 0x5D6D, 0xFAB3, 0x5D6F, 0x8DB5, 0x5D73, 0x9BCB, 0x5D76, 0x9BCC, 0x5D82, 0x9BCF, 0x5D84, 0x9BCE, + 0x5D87, 0x9BCD, 0x5D8B, 0x9388, 0x5D8C, 0x9BB8, 0x5D90, 0x9BD5, 0x5D9D, 0x9BD1, 0x5DA2, 0x9BD0, 0x5DAC, 0x9BD2, 0x5DAE, 0x9BD3, + 0x5DB7, 0x9BD6, 0x5DB8, 0xFAB4, 0x5DB9, 0xFAB5, 0x5DBA, 0x97E4, 0x5DBC, 0x9BD7, 0x5DBD, 0x9BD4, 0x5DC9, 0x9BD8, 0x5DCC, 0x8ADE, + 0x5DCD, 0x9BD9, 0x5DD0, 0xFAB6, 0x5DD2, 0x9BDB, 0x5DD3, 0x9BDA, 0x5DD6, 0x9BDC, 0x5DDB, 0x9BDD, 0x5DDD, 0x90EC, 0x5DDE, 0x8F42, + 0x5DE1, 0x8F84, 0x5DE3, 0x9183, 0x5DE5, 0x8D48, 0x5DE6, 0x8DB6, 0x5DE7, 0x8D49, 0x5DE8, 0x8B90, 0x5DEB, 0x9BDE, 0x5DEE, 0x8DB7, + 0x5DF1, 0x8CC8, 0x5DF2, 0x9BDF, 0x5DF3, 0x96A4, 0x5DF4, 0x9462, 0x5DF5, 0x9BE0, 0x5DF7, 0x8D4A, 0x5DFB, 0x8AAA, 0x5DFD, 0x9246, + 0x5DFE, 0x8BD0, 0x5E02, 0x8E73, 0x5E03, 0x957A, 0x5E06, 0x94BF, 0x5E0B, 0x9BE1, 0x5E0C, 0x8AF3, 0x5E11, 0x9BE4, 0x5E16, 0x929F, + 0x5E19, 0x9BE3, 0x5E1A, 0x9BE2, 0x5E1B, 0x9BE5, 0x5E1D, 0x92E9, 0x5E25, 0x9083, 0x5E2B, 0x8E74, 0x5E2D, 0x90C8, 0x5E2F, 0x91D1, + 0x5E30, 0x8B41, 0x5E33, 0x92A0, 0x5E36, 0x9BE6, 0x5E37, 0x9BE7, 0x5E38, 0x8FED, 0x5E3D, 0x9658, 0x5E40, 0x9BEA, 0x5E43, 0x9BE9, + 0x5E44, 0x9BE8, 0x5E45, 0x959D, 0x5E47, 0x9BF1, 0x5E4C, 0x9679, 0x5E4E, 0x9BEB, 0x5E54, 0x9BED, 0x5E55, 0x968B, 0x5E57, 0x9BEC, + 0x5E5F, 0x9BEE, 0x5E61, 0x94A6, 0x5E62, 0x9BEF, 0x5E63, 0x95BC, 0x5E64, 0x9BF0, 0x5E72, 0x8AB1, 0x5E73, 0x95BD, 0x5E74, 0x944E, + 0x5E75, 0x9BF2, 0x5E76, 0x9BF3, 0x5E78, 0x8D4B, 0x5E79, 0x8AB2, 0x5E7A, 0x9BF4, 0x5E7B, 0x8CB6, 0x5E7C, 0x9763, 0x5E7D, 0x9748, + 0x5E7E, 0x8AF4, 0x5E7F, 0x9BF6, 0x5E81, 0x92A1, 0x5E83, 0x8D4C, 0x5E84, 0x8FAF, 0x5E87, 0x94DD, 0x5E8A, 0x8FB0, 0x5E8F, 0x8F98, + 0x5E95, 0x92EA, 0x5E96, 0x95F7, 0x5E97, 0x9358, 0x5E9A, 0x8D4D, 0x5E9C, 0x957B, 0x5EA0, 0x9BF7, 0x5EA6, 0x9378, 0x5EA7, 0x8DC0, + 0x5EAB, 0x8CC9, 0x5EAD, 0x92EB, 0x5EB5, 0x88C1, 0x5EB6, 0x8F8E, 0x5EB7, 0x8D4E, 0x5EB8, 0x9766, 0x5EC1, 0x9BF8, 0x5EC2, 0x9BF9, + 0x5EC3, 0x9470, 0x5EC8, 0x9BFA, 0x5EC9, 0x97F5, 0x5ECA, 0x984C, 0x5ECF, 0x9BFC, 0x5ED0, 0x9BFB, 0x5ED3, 0x8A66, 0x5ED6, 0x9C40, + 0x5EDA, 0x9C43, 0x5EDB, 0x9C44, 0x5EDD, 0x9C42, 0x5EDF, 0x955F, 0x5EE0, 0x8FB1, 0x5EE1, 0x9C46, 0x5EE2, 0x9C45, 0x5EE3, 0x9C41, + 0x5EE8, 0x9C47, 0x5EE9, 0x9C48, 0x5EEC, 0x9C49, 0x5EF0, 0x9C4C, 0x5EF1, 0x9C4A, 0x5EF3, 0x9C4B, 0x5EF4, 0x9C4D, 0x5EF6, 0x8984, + 0x5EF7, 0x92EC, 0x5EF8, 0x9C4E, 0x5EFA, 0x8C9A, 0x5EFB, 0x89F4, 0x5EFC, 0x9455, 0x5EFE, 0x9C4F, 0x5EFF, 0x93F9, 0x5F01, 0x95D9, + 0x5F03, 0x9C50, 0x5F04, 0x984D, 0x5F09, 0x9C51, 0x5F0A, 0x95BE, 0x5F0B, 0x9C54, 0x5F0C, 0x989F, 0x5F0D, 0x98AF, 0x5F0F, 0x8EAE, + 0x5F10, 0x93F3, 0x5F11, 0x9C55, 0x5F13, 0x8B7C, 0x5F14, 0x92A2, 0x5F15, 0x88F8, 0x5F16, 0x9C56, 0x5F17, 0x95A4, 0x5F18, 0x8D4F, + 0x5F1B, 0x926F, 0x5F1F, 0x92ED, 0x5F21, 0xFAB7, 0x5F25, 0x96ED, 0x5F26, 0x8CB7, 0x5F27, 0x8CCA, 0x5F29, 0x9C57, 0x5F2D, 0x9C58, + 0x5F2F, 0x9C5E, 0x5F31, 0x8EE3, 0x5F34, 0xFAB8, 0x5F35, 0x92A3, 0x5F37, 0x8BAD, 0x5F38, 0x9C59, 0x5F3C, 0x954A, 0x5F3E, 0x9265, + 0x5F41, 0x9C5A, 0x5F45, 0xFA67, 0x5F48, 0x9C5B, 0x5F4A, 0x8BAE, 0x5F4C, 0x9C5C, 0x5F4E, 0x9C5D, 0x5F51, 0x9C5F, 0x5F53, 0x9396, + 0x5F56, 0x9C60, 0x5F57, 0x9C61, 0x5F59, 0x9C62, 0x5F5C, 0x9C53, 0x5F5D, 0x9C52, 0x5F61, 0x9C63, 0x5F62, 0x8C60, 0x5F66, 0x9546, + 0x5F67, 0xFAB9, 0x5F69, 0x8DCA, 0x5F6A, 0x9556, 0x5F6B, 0x92A4, 0x5F6C, 0x956A, 0x5F6D, 0x9C64, 0x5F70, 0x8FB2, 0x5F71, 0x8965, + 0x5F73, 0x9C65, 0x5F77, 0x9C66, 0x5F79, 0x96F0, 0x5F7C, 0x94DE, 0x5F7F, 0x9C69, 0x5F80, 0x899D, 0x5F81, 0x90AA, 0x5F82, 0x9C68, + 0x5F83, 0x9C67, 0x5F84, 0x8C61, 0x5F85, 0x91D2, 0x5F87, 0x9C6D, 0x5F88, 0x9C6B, 0x5F8A, 0x9C6A, 0x5F8B, 0x97A5, 0x5F8C, 0x8CE3, + 0x5F90, 0x8F99, 0x5F91, 0x9C6C, 0x5F92, 0x936B, 0x5F93, 0x8F5D, 0x5F97, 0x93BE, 0x5F98, 0x9C70, 0x5F99, 0x9C6F, 0x5F9E, 0x9C6E, + 0x5FA0, 0x9C71, 0x5FA1, 0x8CE4, 0x5FA8, 0x9C72, 0x5FA9, 0x959C, 0x5FAA, 0x8F7A, 0x5FAD, 0x9C73, 0x5FAE, 0x94F7, 0x5FB3, 0x93BF, + 0x5FB4, 0x92A5, 0x5FB7, 0xFABA, 0x5FB9, 0x934F, 0x5FBC, 0x9C74, 0x5FBD, 0x8B4A, 0x5FC3, 0x9053, 0x5FC5, 0x954B, 0x5FCC, 0x8AF5, + 0x5FCD, 0x9445, 0x5FD6, 0x9C75, 0x5FD7, 0x8E75, 0x5FD8, 0x9659, 0x5FD9, 0x965A, 0x5FDC, 0x899E, 0x5FDD, 0x9C7A, 0x5FDE, 0xFABB, + 0x5FE0, 0x9289, 0x5FE4, 0x9C77, 0x5FEB, 0x89F5, 0x5FF0, 0x9CAB, 0x5FF1, 0x9C79, 0x5FF5, 0x944F, 0x5FF8, 0x9C78, 0x5FFB, 0x9C76, + 0x5FFD, 0x8D9A, 0x5FFF, 0x9C7C, 0x600E, 0x9C83, 0x600F, 0x9C89, 0x6010, 0x9C81, 0x6012, 0x937B, 0x6015, 0x9C86, 0x6016, 0x957C, + 0x6019, 0x9C80, 0x601B, 0x9C85, 0x601C, 0x97E5, 0x601D, 0x8E76, 0x6020, 0x91D3, 0x6021, 0x9C7D, 0x6025, 0x8B7D, 0x6026, 0x9C88, + 0x6027, 0x90AB, 0x6028, 0x8985, 0x6029, 0x9C82, 0x602A, 0x89F6, 0x602B, 0x9C87, 0x602F, 0x8BAF, 0x6031, 0x9C84, 0x603A, 0x9C8A, + 0x6041, 0x9C8C, 0x6042, 0x9C96, 0x6043, 0x9C94, 0x6046, 0x9C91, 0x604A, 0x9C90, 0x604B, 0x97F6, 0x604D, 0x9C92, 0x6050, 0x8BB0, + 0x6052, 0x8D50, 0x6055, 0x8F9A, 0x6059, 0x9C99, 0x605A, 0x9C8B, 0x605D, 0xFABC, 0x605F, 0x9C8F, 0x6060, 0x9C7E, 0x6062, 0x89F8, + 0x6063, 0x9C93, 0x6064, 0x9C95, 0x6065, 0x9270, 0x6068, 0x8DA6, 0x6069, 0x89B6, 0x606A, 0x9C8D, 0x606B, 0x9C98, 0x606C, 0x9C97, + 0x606D, 0x8BB1, 0x606F, 0x91A7, 0x6070, 0x8A86, 0x6075, 0x8C62, 0x6077, 0x9C8E, 0x6081, 0x9C9A, 0x6083, 0x9C9D, 0x6084, 0x9C9F, + 0x6085, 0xFABD, 0x6089, 0x8EBB, 0x608A, 0xFABE, 0x608B, 0x9CA5, 0x608C, 0x92EE, 0x608D, 0x9C9B, 0x6092, 0x9CA3, 0x6094, 0x89F7, + 0x6096, 0x9CA1, 0x6097, 0x9CA2, 0x609A, 0x9C9E, 0x609B, 0x9CA0, 0x609F, 0x8CE5, 0x60A0, 0x9749, 0x60A3, 0x8AB3, 0x60A6, 0x8978, + 0x60A7, 0x9CA4, 0x60A9, 0x9459, 0x60AA, 0x88AB, 0x60B2, 0x94DF, 0x60B3, 0x9C7B, 0x60B4, 0x9CAA, 0x60B5, 0x9CAE, 0x60B6, 0x96E3, + 0x60B8, 0x9CA7, 0x60BC, 0x9389, 0x60BD, 0x9CAC, 0x60C5, 0x8FEE, 0x60C6, 0x9CAD, 0x60C7, 0x93D5, 0x60D1, 0x9866, 0x60D3, 0x9CA9, + 0x60D5, 0xFAC0, 0x60D8, 0x9CAF, 0x60DA, 0x8D9B, 0x60DC, 0x90C9, 0x60DE, 0xFABF, 0x60DF, 0x88D2, 0x60E0, 0x9CA8, 0x60E1, 0x9CA6, + 0x60E3, 0x9179, 0x60E7, 0x9C9C, 0x60E8, 0x8E53, 0x60F0, 0x91C4, 0x60F1, 0x9CBB, 0x60F2, 0xFAC2, 0x60F3, 0x917A, 0x60F4, 0x9CB6, + 0x60F6, 0x9CB3, 0x60F7, 0x9CB4, 0x60F9, 0x8EE4, 0x60FA, 0x9CB7, 0x60FB, 0x9CBA, 0x6100, 0x9CB5, 0x6101, 0x8F44, 0x6103, 0x9CB8, + 0x6106, 0x9CB2, 0x6108, 0x96FA, 0x6109, 0x96F9, 0x610D, 0x9CBC, 0x610E, 0x9CBD, 0x610F, 0x88D3, 0x6111, 0xFAC3, 0x6115, 0x9CB1, + 0x611A, 0x8BF0, 0x611B, 0x88A4, 0x611F, 0x8AB4, 0x6120, 0xFAC1, 0x6121, 0x9CB9, 0x6127, 0x9CC1, 0x6128, 0x9CC0, 0x612C, 0x9CC5, + 0x6130, 0xFAC5, 0x6134, 0x9CC6, 0x6137, 0xFAC4, 0x613C, 0x9CC4, 0x613D, 0x9CC7, 0x613E, 0x9CBF, 0x613F, 0x9CC3, 0x6142, 0x9CC8, + 0x6144, 0x9CC9, 0x6147, 0x9CBE, 0x6148, 0x8E9C, 0x614A, 0x9CC2, 0x614B, 0x91D4, 0x614C, 0x8D51, 0x614D, 0x9CB0, 0x614E, 0x9054, + 0x6153, 0x9CD6, 0x6155, 0x95E7, 0x6158, 0x9CCC, 0x6159, 0x9CCD, 0x615A, 0x9CCE, 0x615D, 0x9CD5, 0x615F, 0x9CD4, 0x6162, 0x969D, + 0x6163, 0x8AB5, 0x6165, 0x9CD2, 0x6167, 0x8C64, 0x6168, 0x8A53, 0x616B, 0x9CCF, 0x616E, 0x97B6, 0x616F, 0x9CD1, 0x6170, 0x88D4, + 0x6171, 0x9CD3, 0x6173, 0x9CCA, 0x6174, 0x9CD0, 0x6175, 0x9CD7, 0x6176, 0x8C63, 0x6177, 0x9CCB, 0x617E, 0x977C, 0x6182, 0x974A, + 0x6187, 0x9CDA, 0x618A, 0x9CDE, 0x618E, 0x919E, 0x6190, 0x97F7, 0x6191, 0x9CDF, 0x6194, 0x9CDC, 0x6196, 0x9CD9, 0x6198, 0xFAC6, + 0x6199, 0x9CD8, 0x619A, 0x9CDD, 0x61A4, 0x95AE, 0x61A7, 0x93B2, 0x61A9, 0x8C65, 0x61AB, 0x9CE0, 0x61AC, 0x9CDB, 0x61AE, 0x9CE1, + 0x61B2, 0x8C9B, 0x61B6, 0x89AF, 0x61BA, 0x9CE9, 0x61BE, 0x8AB6, 0x61C3, 0x9CE7, 0x61C6, 0x9CE8, 0x61C7, 0x8DA7, 0x61C8, 0x9CE6, + 0x61C9, 0x9CE4, 0x61CA, 0x9CE3, 0x61CB, 0x9CEA, 0x61CC, 0x9CE2, 0x61CD, 0x9CEC, 0x61D0, 0x89F9, 0x61E3, 0x9CEE, 0x61E6, 0x9CED, + 0x61F2, 0x92A6, 0x61F4, 0x9CF1, 0x61F6, 0x9CEF, 0x61F7, 0x9CE5, 0x61F8, 0x8C9C, 0x61FA, 0x9CF0, 0x61FC, 0x9CF4, 0x61FD, 0x9CF3, + 0x61FE, 0x9CF5, 0x61FF, 0x9CF2, 0x6200, 0x9CF6, 0x6208, 0x9CF7, 0x6209, 0x9CF8, 0x620A, 0x95E8, 0x620C, 0x9CFA, 0x620D, 0x9CF9, + 0x620E, 0x8F5E, 0x6210, 0x90AC, 0x6211, 0x89E4, 0x6212, 0x89FA, 0x6213, 0xFAC7, 0x6214, 0x9CFB, 0x6216, 0x88BD, 0x621A, 0x90CA, + 0x621B, 0x9CFC, 0x621D, 0xE6C1, 0x621E, 0x9D40, 0x621F, 0x8C81, 0x6221, 0x9D41, 0x6226, 0x90ED, 0x622A, 0x9D42, 0x622E, 0x9D43, + 0x622F, 0x8B59, 0x6230, 0x9D44, 0x6232, 0x9D45, 0x6233, 0x9D46, 0x6234, 0x91D5, 0x6238, 0x8CCB, 0x623B, 0x96DF, 0x623F, 0x965B, + 0x6240, 0x8F8A, 0x6241, 0x9D47, 0x6247, 0x90EE, 0x6248, 0xE7BB, 0x6249, 0x94E0, 0x624B, 0x8EE8, 0x624D, 0x8DCB, 0x624E, 0x9D48, + 0x6253, 0x91C5, 0x6255, 0x95A5, 0x6258, 0x91EF, 0x625B, 0x9D4B, 0x625E, 0x9D49, 0x6260, 0x9D4C, 0x6263, 0x9D4A, 0x6268, 0x9D4D, + 0x626E, 0x95AF, 0x6271, 0x88B5, 0x6276, 0x957D, 0x6279, 0x94E1, 0x627C, 0x9D4E, 0x627E, 0x9D51, 0x627F, 0x8FB3, 0x6280, 0x8B5A, + 0x6282, 0x9D4F, 0x6283, 0x9D56, 0x6284, 0x8FB4, 0x6289, 0x9D50, 0x628A, 0x9463, 0x6291, 0x977D, 0x6292, 0x9D52, 0x6293, 0x9D53, + 0x6294, 0x9D57, 0x6295, 0x938A, 0x6296, 0x9D54, 0x6297, 0x8D52, 0x6298, 0x90DC, 0x629B, 0x9D65, 0x629C, 0x94B2, 0x629E, 0x91F0, + 0x62A6, 0xFAC8, 0x62AB, 0x94E2, 0x62AC, 0x9DAB, 0x62B1, 0x95F8, 0x62B5, 0x92EF, 0x62B9, 0x9695, 0x62BB, 0x9D5A, 0x62BC, 0x899F, + 0x62BD, 0x928A, 0x62C2, 0x9D63, 0x62C5, 0x9253, 0x62C6, 0x9D5D, 0x62C7, 0x9D64, 0x62C8, 0x9D5F, 0x62C9, 0x9D66, 0x62CA, 0x9D62, + 0x62CC, 0x9D61, 0x62CD, 0x948F, 0x62CF, 0x9D5B, 0x62D0, 0x89FB, 0x62D1, 0x9D59, 0x62D2, 0x8B91, 0x62D3, 0x91F1, 0x62D4, 0x9D55, + 0x62D7, 0x9D58, 0x62D8, 0x8D53, 0x62D9, 0x90D9, 0x62DB, 0x8FB5, 0x62DC, 0x9D60, 0x62DD, 0x9471, 0x62E0, 0x8B92, 0x62E1, 0x8A67, + 0x62EC, 0x8A87, 0x62ED, 0x9040, 0x62EE, 0x9D68, 0x62EF, 0x9D6D, 0x62F1, 0x9D69, 0x62F3, 0x8C9D, 0x62F5, 0x9D6E, 0x62F6, 0x8E41, + 0x62F7, 0x8D89, 0x62FE, 0x8F45, 0x62FF, 0x9D5C, 0x6301, 0x8E9D, 0x6302, 0x9D6B, 0x6307, 0x8E77, 0x6308, 0x9D6C, 0x6309, 0x88C2, + 0x630C, 0x9D67, 0x6311, 0x92A7, 0x6319, 0x8B93, 0x631F, 0x8BB2, 0x6327, 0x9D6A, 0x6328, 0x88A5, 0x632B, 0x8DC1, 0x632F, 0x9055, + 0x633A, 0x92F0, 0x633D, 0x94D2, 0x633E, 0x9D70, 0x633F, 0x917D, 0x6349, 0x91A8, 0x634C, 0x8E4A, 0x634D, 0x9D71, 0x634F, 0x9D73, + 0x6350, 0x9D6F, 0x6355, 0x95DF, 0x6357, 0x92BB, 0x635C, 0x917B, 0x6367, 0x95F9, 0x6368, 0x8ECC, 0x6369, 0x9D80, 0x636B, 0x9D7E, + 0x636E, 0x9098, 0x6372, 0x8C9E, 0x6376, 0x9D78, 0x6377, 0x8FB7, 0x637A, 0x93E6, 0x637B, 0x9450, 0x6380, 0x9D76, 0x6383, 0x917C, + 0x6388, 0x8EF6, 0x6389, 0x9D7B, 0x638C, 0x8FB6, 0x638E, 0x9D75, 0x638F, 0x9D7A, 0x6392, 0x9472, 0x6396, 0x9D74, 0x6398, 0x8C40, + 0x639B, 0x8A7C, 0x639F, 0x9D7C, 0x63A0, 0x97A9, 0x63A1, 0x8DCC, 0x63A2, 0x9254, 0x63A3, 0x9D79, 0x63A5, 0x90DA, 0x63A7, 0x8D54, + 0x63A8, 0x9084, 0x63A9, 0x8986, 0x63AA, 0x915B, 0x63AB, 0x9D77, 0x63AC, 0x8B64, 0x63B2, 0x8C66, 0x63B4, 0x92CD, 0x63B5, 0x9D7D, + 0x63BB, 0x917E, 0x63BE, 0x9D81, 0x63C0, 0x9D83, 0x63C3, 0x91B5, 0x63C4, 0x9D89, 0x63C6, 0x9D84, 0x63C9, 0x9D86, 0x63CF, 0x9560, + 0x63D0, 0x92F1, 0x63D2, 0x9D87, 0x63D6, 0x974B, 0x63DA, 0x9767, 0x63DB, 0x8AB7, 0x63E1, 0x88AC, 0x63E3, 0x9D85, 0x63E9, 0x9D82, + 0x63EE, 0x8AF6, 0x63F4, 0x8987, 0x63F5, 0xFAC9, 0x63F6, 0x9D88, 0x63FA, 0x9768, 0x6406, 0x9D8C, 0x640D, 0x91B9, 0x640F, 0x9D93, + 0x6413, 0x9D8D, 0x6416, 0x9D8A, 0x6417, 0x9D91, 0x641C, 0x9D72, 0x6426, 0x9D8E, 0x6428, 0x9D92, 0x642C, 0x94C0, 0x642D, 0x938B, + 0x6434, 0x9D8B, 0x6436, 0x9D8F, 0x643A, 0x8C67, 0x643E, 0x8DEF, 0x6442, 0x90DB, 0x644E, 0x9D97, 0x6458, 0x9345, 0x6460, 0xFACA, + 0x6467, 0x9D94, 0x6469, 0x9680, 0x646F, 0x9D95, 0x6476, 0x9D96, 0x6478, 0x96CC, 0x647A, 0x90A0, 0x6483, 0x8C82, 0x6488, 0x9D9D, + 0x6492, 0x8E54, 0x6493, 0x9D9A, 0x6495, 0x9D99, 0x649A, 0x9451, 0x649D, 0xFACB, 0x649E, 0x93B3, 0x64A4, 0x9350, 0x64A5, 0x9D9B, + 0x64A9, 0x9D9C, 0x64AB, 0x958F, 0x64AD, 0x9464, 0x64AE, 0x8E42, 0x64B0, 0x90EF, 0x64B2, 0x966F, 0x64B9, 0x8A68, 0x64BB, 0x9DA3, + 0x64BC, 0x9D9E, 0x64C1, 0x9769, 0x64C2, 0x9DA5, 0x64C5, 0x9DA1, 0x64C7, 0x9DA2, 0x64CD, 0x9180, 0x64CE, 0xFACC, 0x64D2, 0x9DA0, + 0x64D4, 0x9D5E, 0x64D8, 0x9DA4, 0x64DA, 0x9D9F, 0x64E0, 0x9DA9, 0x64E1, 0x9DAA, 0x64E2, 0x9346, 0x64E3, 0x9DAC, 0x64E6, 0x8E43, + 0x64E7, 0x9DA7, 0x64EC, 0x8B5B, 0x64EF, 0x9DAD, 0x64F1, 0x9DA6, 0x64F2, 0x9DB1, 0x64F4, 0x9DB0, 0x64F6, 0x9DAF, 0x64FA, 0x9DB2, + 0x64FD, 0x9DB4, 0x64FE, 0x8FEF, 0x6500, 0x9DB3, 0x6505, 0x9DB7, 0x6518, 0x9DB5, 0x651C, 0x9DB6, 0x651D, 0x9D90, 0x6523, 0x9DB9, + 0x6524, 0x9DB8, 0x652A, 0x9D98, 0x652B, 0x9DBA, 0x652C, 0x9DAE, 0x652F, 0x8E78, 0x6534, 0x9DBB, 0x6535, 0x9DBC, 0x6536, 0x9DBE, + 0x6537, 0x9DBD, 0x6538, 0x9DBF, 0x6539, 0x89FC, 0x653B, 0x8D55, 0x653E, 0x95FA, 0x653F, 0x90AD, 0x6545, 0x8CCC, 0x6548, 0x9DC1, + 0x654D, 0x9DC4, 0x654E, 0xFACD, 0x654F, 0x9571, 0x6551, 0x8B7E, 0x6555, 0x9DC3, 0x6556, 0x9DC2, 0x6557, 0x9473, 0x6558, 0x9DC5, + 0x6559, 0x8BB3, 0x655D, 0x9DC7, 0x655E, 0x9DC6, 0x6562, 0x8AB8, 0x6563, 0x8E55, 0x6566, 0x93D6, 0x656C, 0x8C68, 0x6570, 0x9094, + 0x6572, 0x9DC8, 0x6574, 0x90AE, 0x6575, 0x9347, 0x6577, 0x957E, 0x6578, 0x9DC9, 0x6582, 0x9DCA, 0x6583, 0x9DCB, 0x6587, 0x95B6, + 0x6588, 0x9B7C, 0x6589, 0x90C4, 0x658C, 0x956B, 0x658E, 0x8DD6, 0x6590, 0x94E3, 0x6591, 0x94C1, 0x6597, 0x936C, 0x6599, 0x97BF, + 0x659B, 0x9DCD, 0x659C, 0x8ECE, 0x659F, 0x9DCE, 0x65A1, 0x88B4, 0x65A4, 0x8BD2, 0x65A5, 0x90CB, 0x65A7, 0x9580, 0x65AB, 0x9DCF, + 0x65AC, 0x8E61, 0x65AD, 0x9266, 0x65AF, 0x8E7A, 0x65B0, 0x9056, 0x65B7, 0x9DD0, 0x65B9, 0x95FB, 0x65BC, 0x8997, 0x65BD, 0x8E7B, + 0x65C1, 0x9DD3, 0x65C3, 0x9DD1, 0x65C4, 0x9DD4, 0x65C5, 0x97B7, 0x65C6, 0x9DD2, 0x65CB, 0x90F9, 0x65CC, 0x9DD5, 0x65CF, 0x91B0, + 0x65D2, 0x9DD6, 0x65D7, 0x8AF8, 0x65D9, 0x9DD8, 0x65DB, 0x9DD7, 0x65E0, 0x9DD9, 0x65E1, 0x9DDA, 0x65E2, 0x8AF9, 0x65E5, 0x93FA, + 0x65E6, 0x9255, 0x65E7, 0x8B8C, 0x65E8, 0x8E7C, 0x65E9, 0x9181, 0x65EC, 0x8F7B, 0x65ED, 0x88AE, 0x65F1, 0x9DDB, 0x65FA, 0x89A0, + 0x65FB, 0x9DDF, 0x6600, 0xFACE, 0x6602, 0x8D56, 0x6603, 0x9DDE, 0x6606, 0x8DA9, 0x6607, 0x8FB8, 0x6609, 0xFAD1, 0x660A, 0x9DDD, + 0x660C, 0x8FB9, 0x660E, 0x96BE, 0x660F, 0x8DA8, 0x6613, 0x88D5, 0x6614, 0x90CC, 0x6615, 0xFACF, 0x661C, 0x9DE4, 0x661E, 0xFAD3, + 0x661F, 0x90AF, 0x6620, 0x8966, 0x6624, 0xFAD4, 0x6625, 0x8F74, 0x6627, 0x9686, 0x6628, 0x8DF0, 0x662D, 0x8FBA, 0x662E, 0xFAD2, + 0x662F, 0x90A5, 0x6631, 0xFA63, 0x6634, 0x9DE3, 0x6635, 0x9DE1, 0x6636, 0x9DE2, 0x663B, 0xFAD0, 0x663C, 0x928B, 0x663F, 0x9E45, + 0x6641, 0x9DE8, 0x6642, 0x8E9E, 0x6643, 0x8D57, 0x6644, 0x9DE6, 0x6649, 0x9DE7, 0x664B, 0x9057, 0x664F, 0x9DE5, 0x6652, 0x8E4E, + 0x6657, 0xFAD6, 0x6659, 0xFAD7, 0x665D, 0x9DEA, 0x665E, 0x9DE9, 0x665F, 0x9DEE, 0x6662, 0x9DEF, 0x6664, 0x9DEB, 0x6665, 0xFAD5, + 0x6666, 0x8A41, 0x6667, 0x9DEC, 0x6668, 0x9DED, 0x6669, 0x94D3, 0x666E, 0x9581, 0x666F, 0x8C69, 0x6670, 0x9DF0, 0x6673, 0xFAD9, + 0x6674, 0x90B0, 0x6676, 0x8FBB, 0x667A, 0x9271, 0x6681, 0x8BC5, 0x6683, 0x9DF1, 0x6684, 0x9DF5, 0x6687, 0x89C9, 0x6688, 0x9DF2, + 0x6689, 0x9DF4, 0x668E, 0x9DF3, 0x6691, 0x8F8B, 0x6696, 0x9267, 0x6697, 0x88C3, 0x6698, 0x9DF6, 0x6699, 0xFADA, 0x669D, 0x9DF7, + 0x66A0, 0xFADB, 0x66A2, 0x92A8, 0x66A6, 0x97EF, 0x66AB, 0x8E62, 0x66AE, 0x95E9, 0x66B2, 0xFADC, 0x66B4, 0x965C, 0x66B8, 0x9E41, + 0x66B9, 0x9DF9, 0x66BC, 0x9DFC, 0x66BE, 0x9DFB, 0x66BF, 0xFADD, 0x66C1, 0x9DF8, 0x66C4, 0x9E40, 0x66C7, 0x93DC, 0x66C9, 0x9DFA, + 0x66D6, 0x9E42, 0x66D9, 0x8F8C, 0x66DA, 0x9E43, 0x66DC, 0x976A, 0x66DD, 0x9498, 0x66E0, 0x9E44, 0x66E6, 0x9E46, 0x66E9, 0x9E47, + 0x66F0, 0x9E48, 0x66F2, 0x8BC8, 0x66F3, 0x8967, 0x66F4, 0x8D58, 0x66F5, 0x9E49, 0x66F7, 0x9E4A, 0x66F8, 0x8F91, 0x66F9, 0x9182, + 0x66FA, 0xFADE, 0x66FB, 0xFA66, 0x66FC, 0x99D6, 0x66FD, 0x915D, 0x66FE, 0x915C, 0x66FF, 0x91D6, 0x6700, 0x8DC5, 0x6703, 0x98F0, + 0x6708, 0x8C8E, 0x6709, 0x974C, 0x670B, 0x95FC, 0x670D, 0x959E, 0x670E, 0xFADF, 0x670F, 0x9E4B, 0x6714, 0x8DF1, 0x6715, 0x92BD, + 0x6716, 0x9E4C, 0x6717, 0x984E, 0x671B, 0x965D, 0x671D, 0x92A9, 0x671E, 0x9E4D, 0x671F, 0x8AFA, 0x6726, 0x9E4E, 0x6727, 0x9E4F, + 0x6728, 0x96D8, 0x672A, 0x96A2, 0x672B, 0x9696, 0x672C, 0x967B, 0x672D, 0x8E44, 0x672E, 0x9E51, 0x6731, 0x8EE9, 0x6734, 0x9670, + 0x6736, 0x9E53, 0x6737, 0x9E56, 0x6738, 0x9E55, 0x673A, 0x8AF7, 0x673D, 0x8B80, 0x673F, 0x9E52, 0x6741, 0x9E54, 0x6746, 0x9E57, + 0x6749, 0x9099, 0x674E, 0x979B, 0x674F, 0x88C7, 0x6750, 0x8DDE, 0x6751, 0x91BA, 0x6753, 0x8EDB, 0x6756, 0x8FF1, 0x6759, 0x9E5A, + 0x675C, 0x936D, 0x675E, 0x9E58, 0x675F, 0x91A9, 0x6760, 0x9E59, 0x6761, 0x8FF0, 0x6762, 0x96DB, 0x6763, 0x9E5B, 0x6764, 0x9E5C, + 0x6765, 0x9788, 0x6766, 0xFAE1, 0x676A, 0x9E61, 0x676D, 0x8D59, 0x676F, 0x9474, 0x6770, 0x9E5E, 0x6771, 0x938C, 0x6772, 0x9DDC, + 0x6773, 0x9DE0, 0x6775, 0x8B6E, 0x6777, 0x9466, 0x677C, 0x9E60, 0x677E, 0x8FBC, 0x677F, 0x94C2, 0x6785, 0x9E66, 0x6787, 0x94F8, + 0x6789, 0x9E5D, 0x678B, 0x9E63, 0x678C, 0x9E62, 0x6790, 0x90CD, 0x6795, 0x968D, 0x6797, 0x97D1, 0x679A, 0x9687, 0x679C, 0x89CA, + 0x679D, 0x8E7D, 0x67A0, 0x9867, 0x67A1, 0x9E65, 0x67A2, 0x9095, 0x67A6, 0x9E64, 0x67A9, 0x9E5F, 0x67AF, 0x8CCD, 0x67B3, 0x9E6B, + 0x67B4, 0x9E69, 0x67B6, 0x89CB, 0x67B7, 0x9E67, 0x67B8, 0x9E6D, 0x67B9, 0x9E73, 0x67BB, 0xFAE2, 0x67C0, 0xFAE4, 0x67C1, 0x91C6, + 0x67C4, 0x95BF, 0x67C6, 0x9E75, 0x67CA, 0x9541, 0x67CE, 0x9E74, 0x67CF, 0x9490, 0x67D0, 0x965E, 0x67D1, 0x8AB9, 0x67D3, 0x90F5, + 0x67D4, 0x8F5F, 0x67D8, 0x92D1, 0x67DA, 0x974D, 0x67DD, 0x9E70, 0x67DE, 0x9E6F, 0x67E2, 0x9E71, 0x67E4, 0x9E6E, 0x67E7, 0x9E76, + 0x67E9, 0x9E6C, 0x67EC, 0x9E6A, 0x67EE, 0x9E72, 0x67EF, 0x9E68, 0x67F1, 0x928C, 0x67F3, 0x96F6, 0x67F4, 0x8EC4, 0x67F5, 0x8DF2, + 0x67FB, 0x8DB8, 0x67FE, 0x968F, 0x67FF, 0x8A60, 0x6801, 0xFAE5, 0x6802, 0x92CC, 0x6803, 0x93C8, 0x6804, 0x8968, 0x6813, 0x90F0, + 0x6816, 0x90B2, 0x6817, 0x8C49, 0x681E, 0x9E78, 0x6821, 0x8D5A, 0x6822, 0x8A9C, 0x6829, 0x9E7A, 0x682A, 0x8A94, 0x682B, 0x9E81, + 0x6832, 0x9E7D, 0x6834, 0x90F1, 0x6838, 0x8A6A, 0x6839, 0x8DAA, 0x683C, 0x8A69, 0x683D, 0x8DCD, 0x6840, 0x9E7B, 0x6841, 0x8C85, + 0x6842, 0x8C6A, 0x6843, 0x938D, 0x6844, 0xFAE6, 0x6846, 0x9E79, 0x6848, 0x88C4, 0x684D, 0x9E7C, 0x684E, 0x9E7E, 0x6850, 0x8BCB, + 0x6851, 0x8C4B, 0x6852, 0xFAE3, 0x6853, 0x8ABA, 0x6854, 0x8B6A, 0x6859, 0x9E82, 0x685C, 0x8DF7, 0x685D, 0x9691, 0x685F, 0x8E56, + 0x6863, 0x9E83, 0x6867, 0x954F, 0x6874, 0x9E8F, 0x6876, 0x89B1, 0x6877, 0x9E84, 0x687E, 0x9E95, 0x687F, 0x9E85, 0x6881, 0x97C0, + 0x6883, 0x9E8C, 0x6885, 0x947E, 0x688D, 0x9E94, 0x688F, 0x9E87, 0x6893, 0x88B2, 0x6894, 0x9E89, 0x6897, 0x8D5B, 0x689B, 0x9E8B, + 0x689D, 0x9E8A, 0x689F, 0x9E86, 0x68A0, 0x9E91, 0x68A2, 0x8FBD, 0x68A6, 0x9AEB, 0x68A7, 0x8CE6, 0x68A8, 0x979C, 0x68AD, 0x9E88, + 0x68AF, 0x92F2, 0x68B0, 0x8A42, 0x68B1, 0x8DAB, 0x68B3, 0x9E80, 0x68B5, 0x9E90, 0x68B6, 0x8A81, 0x68B9, 0x9E8E, 0x68BA, 0x9E92, + 0x68BC, 0x938E, 0x68C4, 0x8AFC, 0x68C6, 0x9EB0, 0x68C8, 0xFA64, 0x68C9, 0x96C7, 0x68CA, 0x9E97, 0x68CB, 0x8AFB, 0x68CD, 0x9E9E, + 0x68CF, 0xFAE7, 0x68D2, 0x965F, 0x68D4, 0x9E9F, 0x68D5, 0x9EA1, 0x68D7, 0x9EA5, 0x68D8, 0x9E99, 0x68DA, 0x9249, 0x68DF, 0x938F, + 0x68E0, 0x9EA9, 0x68E1, 0x9E9C, 0x68E3, 0x9EA6, 0x68E7, 0x9EA0, 0x68EE, 0x9058, 0x68EF, 0x9EAA, 0x68F2, 0x90B1, 0x68F9, 0x9EA8, + 0x68FA, 0x8ABB, 0x6900, 0x986F, 0x6901, 0x9E96, 0x6904, 0x9EA4, 0x6905, 0x88D6, 0x6908, 0x9E98, 0x690B, 0x96B8, 0x690C, 0x9E9D, + 0x690D, 0x9041, 0x690E, 0x92C5, 0x690F, 0x9E93, 0x6912, 0x9EA3, 0x6919, 0x909A, 0x691A, 0x9EAD, 0x691B, 0x8A91, 0x691C, 0x8C9F, + 0x6921, 0x9EAF, 0x6922, 0x9E9A, 0x6923, 0x9EAE, 0x6925, 0x9EA7, 0x6926, 0x9E9B, 0x6928, 0x9EAB, 0x692A, 0x9EAC, 0x6930, 0x9EBD, + 0x6934, 0x93CC, 0x6936, 0x9EA2, 0x6939, 0x9EB9, 0x693D, 0x9EBB, 0x693F, 0x92D6, 0x694A, 0x976B, 0x6953, 0x9596, 0x6954, 0x9EB6, + 0x6955, 0x91C8, 0x6959, 0x9EBC, 0x695A, 0x915E, 0x695C, 0x9EB3, 0x695D, 0x9EC0, 0x695E, 0x9EBF, 0x6960, 0x93ED, 0x6961, 0x9EBE, + 0x6962, 0x93E8, 0x6968, 0xFAE9, 0x696A, 0x9EC2, 0x696B, 0x9EB5, 0x696D, 0x8BC6, 0x696E, 0x9EB8, 0x696F, 0x8F7C, 0x6973, 0x9480, + 0x6974, 0x9EBA, 0x6975, 0x8BC9, 0x6977, 0x9EB2, 0x6978, 0x9EB4, 0x6979, 0x9EB1, 0x697C, 0x984F, 0x697D, 0x8A79, 0x697E, 0x9EB7, + 0x6981, 0x9EC1, 0x6982, 0x8A54, 0x698A, 0x8DE5, 0x698E, 0x897C, 0x6991, 0x9ED2, 0x6994, 0x9850, 0x6995, 0x9ED5, 0x6998, 0xFAEB, + 0x699B, 0x9059, 0x699C, 0x9ED4, 0x69A0, 0x9ED3, 0x69A7, 0x9ED0, 0x69AE, 0x9EC4, 0x69B1, 0x9EE1, 0x69B2, 0x9EC3, 0x69B4, 0x9ED6, + 0x69BB, 0x9ECE, 0x69BE, 0x9EC9, 0x69BF, 0x9EC6, 0x69C1, 0x9EC7, 0x69C3, 0x9ECF, 0x69C7, 0xEAA0, 0x69CA, 0x9ECC, 0x69CB, 0x8D5C, + 0x69CC, 0x92C6, 0x69CD, 0x9184, 0x69CE, 0x9ECA, 0x69D0, 0x9EC5, 0x69D3, 0x9EC8, 0x69D8, 0x976C, 0x69D9, 0x968A, 0x69DD, 0x9ECD, + 0x69DE, 0x9ED7, 0x69E2, 0xFAEC, 0x69E7, 0x9EDF, 0x69E8, 0x9ED8, 0x69EB, 0x9EE5, 0x69ED, 0x9EE3, 0x69F2, 0x9EDE, 0x69F9, 0x9EDD, + 0x69FB, 0x92CE, 0x69FD, 0x9185, 0x69FF, 0x9EDB, 0x6A02, 0x9ED9, 0x6A05, 0x9EE0, 0x6A0A, 0x9EE6, 0x6A0B, 0x94F3, 0x6A0C, 0x9EEC, + 0x6A12, 0x9EE7, 0x6A13, 0x9EEA, 0x6A14, 0x9EE4, 0x6A17, 0x9294, 0x6A19, 0x9557, 0x6A1B, 0x9EDA, 0x6A1E, 0x9EE2, 0x6A1F, 0x8FBE, + 0x6A21, 0x96CD, 0x6A22, 0x9EF6, 0x6A23, 0x9EE9, 0x6A29, 0x8CA0, 0x6A2A, 0x89A1, 0x6A2B, 0x8A7E, 0x6A2E, 0x9ED1, 0x6A30, 0xFAED, + 0x6A35, 0x8FBF, 0x6A36, 0x9EEE, 0x6A38, 0x9EF5, 0x6A39, 0x8EF7, 0x6A3A, 0x8A92, 0x6A3D, 0x924D, 0x6A44, 0x9EEB, 0x6A46, 0xFAEF, + 0x6A47, 0x9EF0, 0x6A48, 0x9EF4, 0x6A4B, 0x8BB4, 0x6A58, 0x8B6B, 0x6A59, 0x9EF2, 0x6A5F, 0x8B40, 0x6A61, 0x93C9, 0x6A62, 0x9EF1, + 0x6A66, 0x9EF3, 0x6A6B, 0xFAEE, 0x6A72, 0x9EED, 0x6A73, 0xFAF0, 0x6A78, 0x9EEF, 0x6A7E, 0xFAF1, 0x6A7F, 0x8A80, 0x6A80, 0x9268, + 0x6A84, 0x9EFA, 0x6A8D, 0x9EF8, 0x6A8E, 0x8CE7, 0x6A90, 0x9EF7, 0x6A97, 0x9F40, 0x6A9C, 0x9E77, 0x6AA0, 0x9EF9, 0x6AA2, 0x9EFB, + 0x6AA3, 0x9EFC, 0x6AAA, 0x9F4B, 0x6AAC, 0x9F47, 0x6AAE, 0x9E8D, 0x6AB3, 0x9F46, 0x6AB8, 0x9F45, 0x6ABB, 0x9F42, 0x6AC1, 0x9EE8, + 0x6AC2, 0x9F44, 0x6AC3, 0x9F43, 0x6AD1, 0x9F49, 0x6AD3, 0x9845, 0x6ADA, 0x9F4C, 0x6ADB, 0x8BF9, 0x6ADE, 0x9F48, 0x6ADF, 0x9F4A, + 0x6AE2, 0xFAF2, 0x6AE4, 0xFAF3, 0x6AE8, 0x94A5, 0x6AEA, 0x9F4D, 0x6AFA, 0x9F51, 0x6AFB, 0x9F4E, 0x6B04, 0x9793, 0x6B05, 0x9F4F, + 0x6B0A, 0x9EDC, 0x6B12, 0x9F52, 0x6B16, 0x9F53, 0x6B1D, 0x8954, 0x6B1F, 0x9F55, 0x6B20, 0x8C87, 0x6B21, 0x8E9F, 0x6B23, 0x8BD3, + 0x6B27, 0x89A2, 0x6B32, 0x977E, 0x6B37, 0x9F57, 0x6B38, 0x9F56, 0x6B39, 0x9F59, 0x6B3A, 0x8B5C, 0x6B3D, 0x8BD4, 0x6B3E, 0x8ABC, + 0x6B43, 0x9F5C, 0x6B47, 0x9F5B, 0x6B49, 0x9F5D, 0x6B4C, 0x89CC, 0x6B4E, 0x9256, 0x6B50, 0x9F5E, 0x6B53, 0x8ABD, 0x6B54, 0x9F60, + 0x6B59, 0x9F5F, 0x6B5B, 0x9F61, 0x6B5F, 0x9F62, 0x6B61, 0x9F63, 0x6B62, 0x8E7E, 0x6B63, 0x90B3, 0x6B64, 0x8D9F, 0x6B66, 0x9590, + 0x6B69, 0x95E0, 0x6B6A, 0x9863, 0x6B6F, 0x8E95, 0x6B73, 0x8DCE, 0x6B74, 0x97F0, 0x6B78, 0x9F64, 0x6B79, 0x9F65, 0x6B7B, 0x8E80, + 0x6B7F, 0x9F66, 0x6B80, 0x9F67, 0x6B83, 0x9F69, 0x6B84, 0x9F68, 0x6B86, 0x9677, 0x6B89, 0x8F7D, 0x6B8A, 0x8EEA, 0x6B8B, 0x8E63, + 0x6B8D, 0x9F6A, 0x6B95, 0x9F6C, 0x6B96, 0x9042, 0x6B98, 0x9F6B, 0x6B9E, 0x9F6D, 0x6BA4, 0x9F6E, 0x6BAA, 0x9F6F, 0x6BAB, 0x9F70, + 0x6BAF, 0x9F71, 0x6BB1, 0x9F73, 0x6BB2, 0x9F72, 0x6BB3, 0x9F74, 0x6BB4, 0x89A3, 0x6BB5, 0x9269, 0x6BB7, 0x9F75, 0x6BBA, 0x8E45, + 0x6BBB, 0x8A6B, 0x6BBC, 0x9F76, 0x6BBF, 0x9361, 0x6BC0, 0x9ACA, 0x6BC5, 0x8B42, 0x6BC6, 0x9F77, 0x6BCB, 0x9F78, 0x6BCD, 0x95EA, + 0x6BCE, 0x9688, 0x6BD2, 0x93C5, 0x6BD3, 0x9F79, 0x6BD4, 0x94E4, 0x6BD6, 0xFAF4, 0x6BD8, 0x94F9, 0x6BDB, 0x96D1, 0x6BDF, 0x9F7A, + 0x6BEB, 0x9F7C, 0x6BEC, 0x9F7B, 0x6BEF, 0x9F7E, 0x6BF3, 0x9F7D, 0x6C08, 0x9F81, 0x6C0F, 0x8E81, 0x6C11, 0x96AF, 0x6C13, 0x9F82, + 0x6C14, 0x9F83, 0x6C17, 0x8B43, 0x6C1B, 0x9F84, 0x6C23, 0x9F86, 0x6C24, 0x9F85, 0x6C34, 0x9085, 0x6C37, 0x9558, 0x6C38, 0x8969, + 0x6C3E, 0x94C3, 0x6C3F, 0xFAF5, 0x6C40, 0x92F3, 0x6C41, 0x8F60, 0x6C42, 0x8B81, 0x6C4E, 0x94C4, 0x6C50, 0x8EAC, 0x6C55, 0x9F88, + 0x6C57, 0x8ABE, 0x6C5A, 0x8998, 0x6C5C, 0xFAF6, 0x6C5D, 0x93F0, 0x6C5E, 0x9F87, 0x6C5F, 0x8D5D, 0x6C60, 0x9272, 0x6C62, 0x9F89, + 0x6C68, 0x9F91, 0x6C6A, 0x9F8A, 0x6C6F, 0xFAF8, 0x6C70, 0x91BF, 0x6C72, 0x8B82, 0x6C73, 0x9F92, 0x6C7A, 0x8C88, 0x6C7D, 0x8B44, + 0x6C7E, 0x9F90, 0x6C81, 0x9F8E, 0x6C82, 0x9F8B, 0x6C83, 0x9780, 0x6C86, 0xFAF7, 0x6C88, 0x92BE, 0x6C8C, 0x93D7, 0x6C8D, 0x9F8C, + 0x6C90, 0x9F94, 0x6C92, 0x9F93, 0x6C93, 0x8C42, 0x6C96, 0x89AB, 0x6C99, 0x8DB9, 0x6C9A, 0x9F8D, 0x6C9B, 0x9F8F, 0x6CA1, 0x9676, + 0x6CA2, 0x91F2, 0x6CAB, 0x9697, 0x6CAE, 0x9F9C, 0x6CB1, 0x9F9D, 0x6CB3, 0x89CD, 0x6CB8, 0x95A6, 0x6CB9, 0x96FB, 0x6CBA, 0x9F9F, + 0x6CBB, 0x8EA1, 0x6CBC, 0x8FC0, 0x6CBD, 0x9F98, 0x6CBE, 0x9F9E, 0x6CBF, 0x8988, 0x6CC1, 0x8BB5, 0x6CC4, 0x9F95, 0x6CC5, 0x9F9A, + 0x6CC9, 0x90F2, 0x6CCA, 0x9491, 0x6CCC, 0x94E5, 0x6CD3, 0x9F97, 0x6CD5, 0x9640, 0x6CD7, 0x9F99, 0x6CD9, 0x9FA2, 0x6CDA, 0xFAF9, + 0x6CDB, 0x9FA0, 0x6CDD, 0x9F9B, 0x6CE1, 0x9641, 0x6CE2, 0x9467, 0x6CE3, 0x8B83, 0x6CE5, 0x9344, 0x6CE8, 0x928D, 0x6CEA, 0x9FA3, + 0x6CEF, 0x9FA1, 0x6CF0, 0x91D7, 0x6CF1, 0x9F96, 0x6CF3, 0x896A, 0x6D04, 0xFAFA, 0x6D0B, 0x976D, 0x6D0C, 0x9FAE, 0x6D12, 0x9FAD, + 0x6D17, 0x90F4, 0x6D19, 0x9FAA, 0x6D1B, 0x978C, 0x6D1E, 0x93B4, 0x6D1F, 0x9FA4, 0x6D25, 0x92C3, 0x6D29, 0x896B, 0x6D2A, 0x8D5E, + 0x6D2B, 0x9FA7, 0x6D32, 0x8F46, 0x6D33, 0x9FAC, 0x6D35, 0x9FAB, 0x6D36, 0x9FA6, 0x6D38, 0x9FA9, 0x6D3B, 0x8A88, 0x6D3D, 0x9FA8, + 0x6D3E, 0x9468, 0x6D41, 0x97AC, 0x6D44, 0x8FF2, 0x6D45, 0x90F3, 0x6D59, 0x9FB4, 0x6D5A, 0x9FB2, 0x6D5C, 0x956C, 0x6D63, 0x9FAF, + 0x6D64, 0x9FB1, 0x6D66, 0x8959, 0x6D69, 0x8D5F, 0x6D6A, 0x9851, 0x6D6C, 0x8A5C, 0x6D6E, 0x9582, 0x6D6F, 0xFAFC, 0x6D74, 0x9781, + 0x6D77, 0x8A43, 0x6D78, 0x905A, 0x6D79, 0x9FB3, 0x6D85, 0x9FB8, 0x6D87, 0xFAFB, 0x6D88, 0x8FC1, 0x6D8C, 0x974F, 0x6D8E, 0x9FB5, + 0x6D93, 0x9FB0, 0x6D95, 0x9FB6, 0x6D96, 0xFB40, 0x6D99, 0x97DC, 0x6D9B, 0x9393, 0x6D9C, 0x93C0, 0x6DAC, 0xFB41, 0x6DAF, 0x8A55, + 0x6DB2, 0x8974, 0x6DB5, 0x9FBC, 0x6DB8, 0x9FBF, 0x6DBC, 0x97C1, 0x6DC0, 0x9784, 0x6DC5, 0x9FC6, 0x6DC6, 0x9FC0, 0x6DC7, 0x9FBD, + 0x6DCB, 0x97D2, 0x6DCC, 0x9FC3, 0x6DCF, 0xFB42, 0x6DD1, 0x8F69, 0x6DD2, 0x9FC5, 0x6DD5, 0x9FCA, 0x6DD8, 0x9391, 0x6DD9, 0x9FC8, + 0x6DDE, 0x9FC2, 0x6DE1, 0x9257, 0x6DE4, 0x9FC9, 0x6DE6, 0x9FBE, 0x6DE8, 0x9FC4, 0x6DEA, 0x9FCB, 0x6DEB, 0x88FA, 0x6DEC, 0x9FC1, + 0x6DEE, 0x9FCC, 0x6DF1, 0x905B, 0x6DF2, 0xFB44, 0x6DF3, 0x8F7E, 0x6DF5, 0x95A3, 0x6DF7, 0x8DAC, 0x6DF8, 0xFB43, 0x6DF9, 0x9FB9, + 0x6DFA, 0x9FC7, 0x6DFB, 0x9359, 0x6DFC, 0xFB45, 0x6E05, 0x90B4, 0x6E07, 0x8A89, 0x6E08, 0x8DCF, 0x6E09, 0x8FC2, 0x6E0A, 0x9FBB, + 0x6E0B, 0x8F61, 0x6E13, 0x8C6B, 0x6E15, 0x9FBA, 0x6E19, 0x9FD0, 0x6E1A, 0x8F8D, 0x6E1B, 0x8CB8, 0x6E1D, 0x9FDF, 0x6E1F, 0x9FD9, + 0x6E20, 0x8B94, 0x6E21, 0x936E, 0x6E23, 0x9FD4, 0x6E24, 0x9FDD, 0x6E25, 0x88AD, 0x6E26, 0x8951, 0x6E27, 0xFB48, 0x6E29, 0x89B7, + 0x6E2B, 0x9FD6, 0x6E2C, 0x91AA, 0x6E2D, 0x9FCD, 0x6E2E, 0x9FCF, 0x6E2F, 0x8D60, 0x6E38, 0x9FE0, 0x6E39, 0xFB46, 0x6E3A, 0x9FDB, + 0x6E3C, 0xFB49, 0x6E3E, 0x9FD3, 0x6E43, 0x9FDA, 0x6E4A, 0x96A9, 0x6E4D, 0x9FD8, 0x6E4E, 0x9FDC, 0x6E56, 0x8CCE, 0x6E58, 0x8FC3, + 0x6E5B, 0x9258, 0x6E5C, 0xFB47, 0x6E5F, 0x9FD2, 0x6E67, 0x974E, 0x6E6B, 0x9FD5, 0x6E6E, 0x9FCE, 0x6E6F, 0x9392, 0x6E72, 0x9FD1, + 0x6E76, 0x9FD7, 0x6E7E, 0x9870, 0x6E7F, 0x8EBC, 0x6E80, 0x969E, 0x6E82, 0x9FE1, 0x6E8C, 0x94AC, 0x6E8F, 0x9FED, 0x6E90, 0x8CB9, + 0x6E96, 0x8F80, 0x6E98, 0x9FE3, 0x6E9C, 0x97AD, 0x6E9D, 0x8D61, 0x6E9F, 0x9FF0, 0x6EA2, 0x88EC, 0x6EA5, 0x9FEE, 0x6EAA, 0x9FE2, + 0x6EAF, 0x9FE8, 0x6EB2, 0x9FEA, 0x6EB6, 0x976E, 0x6EB7, 0x9FE5, 0x6EBA, 0x934D, 0x6EBD, 0x9FE7, 0x6EBF, 0xFB4A, 0x6EC2, 0x9FEF, + 0x6EC4, 0x9FE9, 0x6EC5, 0x96C5, 0x6EC9, 0x9FE4, 0x6ECB, 0x8EA0, 0x6ECC, 0x9FFC, 0x6ED1, 0x8A8A, 0x6ED3, 0x9FE6, 0x6ED4, 0x9FEB, + 0x6ED5, 0x9FEC, 0x6EDD, 0x91EA, 0x6EDE, 0x91D8, 0x6EEC, 0x9FF4, 0x6EEF, 0x9FFA, 0x6EF2, 0x9FF8, 0x6EF4, 0x9348, 0x6EF7, 0xE042, + 0x6EF8, 0x9FF5, 0x6EFE, 0x9FF6, 0x6EFF, 0x9FDE, 0x6F01, 0x8B99, 0x6F02, 0x9559, 0x6F06, 0x8EBD, 0x6F09, 0x8D97, 0x6F0F, 0x9852, + 0x6F11, 0x9FF2, 0x6F13, 0xE041, 0x6F14, 0x8989, 0x6F15, 0x9186, 0x6F20, 0x9499, 0x6F22, 0x8ABF, 0x6F23, 0x97F8, 0x6F2B, 0x969F, + 0x6F2C, 0x92D0, 0x6F31, 0x9FF9, 0x6F32, 0x9FFB, 0x6F38, 0x9151, 0x6F3E, 0xE040, 0x6F3F, 0x9FF7, 0x6F41, 0x9FF1, 0x6F45, 0x8AC1, + 0x6F54, 0x8C89, 0x6F58, 0xE04E, 0x6F5B, 0xE049, 0x6F5C, 0x90F6, 0x6F5F, 0x8A83, 0x6F64, 0x8F81, 0x6F66, 0xE052, 0x6F6D, 0xE04B, + 0x6F6E, 0x92AA, 0x6F6F, 0xE048, 0x6F70, 0x92D7, 0x6F74, 0xE06B, 0x6F78, 0xE045, 0x6F7A, 0xE044, 0x6F7C, 0xE04D, 0x6F80, 0xE047, + 0x6F81, 0xE046, 0x6F82, 0xE04C, 0x6F84, 0x909F, 0x6F86, 0xE043, 0x6F88, 0xFB4B, 0x6F8E, 0xE04F, 0x6F91, 0xE050, 0x6F97, 0x8AC0, + 0x6FA1, 0xE055, 0x6FA3, 0xE054, 0x6FA4, 0xE056, 0x6FAA, 0xE059, 0x6FB1, 0x9362, 0x6FB3, 0xE053, 0x6FB5, 0xFB4C, 0x6FB9, 0xE057, + 0x6FC0, 0x8C83, 0x6FC1, 0x91F7, 0x6FC2, 0xE051, 0x6FC3, 0x945A, 0x6FC6, 0xE058, 0x6FD4, 0xE05D, 0x6FD5, 0xE05B, 0x6FD8, 0xE05E, + 0x6FDB, 0xE061, 0x6FDF, 0xE05A, 0x6FE0, 0x8D8A, 0x6FE1, 0x9447, 0x6FE4, 0x9FB7, 0x6FEB, 0x9794, 0x6FEC, 0xE05C, 0x6FEE, 0xE060, + 0x6FEF, 0x91F3, 0x6FF1, 0xE05F, 0x6FF3, 0xE04A, 0x6FF5, 0xFB4D, 0x6FF6, 0xE889, 0x6FFA, 0xE064, 0x6FFE, 0xE068, 0x7001, 0xE066, + 0x7005, 0xFB4E, 0x7007, 0xFB4F, 0x7009, 0xE062, 0x700B, 0xE063, 0x700F, 0xE067, 0x7011, 0xE065, 0x7015, 0x956D, 0x7018, 0xE06D, + 0x701A, 0xE06A, 0x701B, 0xE069, 0x701D, 0xE06C, 0x701E, 0x93D2, 0x701F, 0xE06E, 0x7026, 0x9295, 0x7027, 0x91EB, 0x7028, 0xFB50, + 0x702C, 0x90A3, 0x7030, 0xE06F, 0x7032, 0xE071, 0x703E, 0xE070, 0x704C, 0x9FF3, 0x7051, 0xE072, 0x7058, 0x93E5, 0x7063, 0xE073, + 0x706B, 0x89CE, 0x706F, 0x9394, 0x7070, 0x8A44, 0x7078, 0x8B84, 0x707C, 0x8EDC, 0x707D, 0x8DD0, 0x7085, 0xFB51, 0x7089, 0x9846, + 0x708A, 0x9086, 0x708E, 0x898A, 0x7092, 0xE075, 0x7099, 0xE074, 0x70AB, 0xFB52, 0x70AC, 0xE078, 0x70AD, 0x9259, 0x70AE, 0xE07B, + 0x70AF, 0xE076, 0x70B3, 0xE07A, 0x70B8, 0xE079, 0x70B9, 0x935F, 0x70BA, 0x88D7, 0x70BB, 0xFA62, 0x70C8, 0x97F3, 0x70CB, 0xE07D, + 0x70CF, 0x8947, 0x70D9, 0xE080, 0x70DD, 0xE07E, 0x70DF, 0xE07C, 0x70F1, 0xE077, 0x70F9, 0x9642, 0x70FD, 0xE082, 0x7104, 0xFB54, + 0x7109, 0xE081, 0x710F, 0xFB53, 0x7114, 0x898B, 0x7119, 0xE084, 0x711A, 0x95B0, 0x711C, 0xE083, 0x7121, 0x96B3, 0x7126, 0x8FC5, + 0x7136, 0x9152, 0x713C, 0x8FC4, 0x7146, 0xFB56, 0x7147, 0xFB57, 0x7149, 0x97F9, 0x714C, 0xE08A, 0x714E, 0x90F7, 0x7155, 0xE086, + 0x7156, 0xE08B, 0x7159, 0x898C, 0x715C, 0xFB55, 0x7162, 0xE089, 0x7164, 0x9481, 0x7165, 0xE085, 0x7166, 0xE088, 0x7167, 0x8FC6, + 0x7169, 0x94CF, 0x716C, 0xE08C, 0x716E, 0x8ECF, 0x717D, 0x90F8, 0x7184, 0xE08F, 0x7188, 0xE087, 0x718A, 0x8C46, 0x718F, 0xE08D, + 0x7194, 0x976F, 0x7195, 0xE090, 0x7199, 0xEAA4, 0x719F, 0x8F6E, 0x71A8, 0xE091, 0x71AC, 0xE092, 0x71B1, 0x944D, 0x71B9, 0xE094, + 0x71BE, 0xE095, 0x71C1, 0xFB59, 0x71C3, 0x9452, 0x71C8, 0x9395, 0x71C9, 0xE097, 0x71CE, 0xE099, 0x71D0, 0x97D3, 0x71D2, 0xE096, + 0x71D4, 0xE098, 0x71D5, 0x898D, 0x71D7, 0xE093, 0x71DF, 0x9A7A, 0x71E0, 0xE09A, 0x71E5, 0x9187, 0x71E6, 0x8E57, 0x71E7, 0xE09C, + 0x71EC, 0xE09B, 0x71ED, 0x9043, 0x71EE, 0x99D7, 0x71F5, 0xE09D, 0x71F9, 0xE09F, 0x71FB, 0xE08E, 0x71FC, 0xE09E, 0x71FE, 0xFB5A, + 0x71FF, 0xE0A0, 0x7206, 0x949A, 0x720D, 0xE0A1, 0x7210, 0xE0A2, 0x721B, 0xE0A3, 0x7228, 0xE0A4, 0x722A, 0x92DC, 0x722C, 0xE0A6, + 0x722D, 0xE0A5, 0x7230, 0xE0A7, 0x7232, 0xE0A8, 0x7235, 0x8EDD, 0x7236, 0x9583, 0x723A, 0x96EA, 0x723B, 0xE0A9, 0x723C, 0xE0AA, + 0x723D, 0x9175, 0x723E, 0x8EA2, 0x723F, 0xE0AB, 0x7240, 0xE0AC, 0x7246, 0xE0AD, 0x7247, 0x95D0, 0x7248, 0x94C5, 0x724B, 0xE0AE, + 0x724C, 0x9476, 0x7252, 0x92AB, 0x7258, 0xE0AF, 0x7259, 0x89E5, 0x725B, 0x8B8D, 0x725D, 0x96C4, 0x725F, 0x96B4, 0x7261, 0x89B2, + 0x7262, 0x9853, 0x7267, 0x9671, 0x7269, 0x95A8, 0x7272, 0x90B5, 0x7274, 0xE0B0, 0x7279, 0x93C1, 0x727D, 0x8CA1, 0x727E, 0xE0B1, + 0x7280, 0x8DD2, 0x7281, 0xE0B3, 0x7282, 0xE0B2, 0x7287, 0xE0B4, 0x7292, 0xE0B5, 0x7296, 0xE0B6, 0x72A0, 0x8B5D, 0x72A2, 0xE0B7, + 0x72A7, 0xE0B8, 0x72AC, 0x8CA2, 0x72AF, 0x94C6, 0x72B1, 0xFB5B, 0x72B2, 0xE0BA, 0x72B6, 0x8FF3, 0x72B9, 0xE0B9, 0x72BE, 0xFB5C, + 0x72C2, 0x8BB6, 0x72C3, 0xE0BB, 0x72C4, 0xE0BD, 0x72C6, 0xE0BC, 0x72CE, 0xE0BE, 0x72D0, 0x8CCF, 0x72D2, 0xE0BF, 0x72D7, 0x8BE7, + 0x72D9, 0x915F, 0x72DB, 0x8D9D, 0x72E0, 0xE0C1, 0x72E1, 0xE0C2, 0x72E2, 0xE0C0, 0x72E9, 0x8EEB, 0x72EC, 0x93C6, 0x72ED, 0x8BB7, + 0x72F7, 0xE0C4, 0x72F8, 0x924B, 0x72F9, 0xE0C3, 0x72FC, 0x9854, 0x72FD, 0x9482, 0x730A, 0xE0C7, 0x7316, 0xE0C9, 0x7317, 0xE0C6, + 0x731B, 0x96D2, 0x731C, 0xE0C8, 0x731D, 0xE0CA, 0x731F, 0x97C2, 0x7324, 0xFB5D, 0x7325, 0xE0CE, 0x7329, 0xE0CD, 0x732A, 0x9296, + 0x732B, 0x944C, 0x732E, 0x8CA3, 0x732F, 0xE0CC, 0x7334, 0xE0CB, 0x7336, 0x9750, 0x7337, 0x9751, 0x733E, 0xE0CF, 0x733F, 0x898E, + 0x7344, 0x8D96, 0x7345, 0x8E82, 0x734E, 0xE0D0, 0x734F, 0xE0D1, 0x7357, 0xE0D3, 0x7363, 0x8F62, 0x7368, 0xE0D5, 0x736A, 0xE0D4, + 0x7370, 0xE0D6, 0x7372, 0x8A6C, 0x7375, 0xE0D8, 0x7377, 0xFB5F, 0x7378, 0xE0D7, 0x737A, 0xE0DA, 0x737B, 0xE0D9, 0x7384, 0x8CBA, + 0x7387, 0x97A6, 0x7389, 0x8BCA, 0x738B, 0x89A4, 0x7396, 0x8BE8, 0x73A9, 0x8ADF, 0x73B2, 0x97E6, 0x73B3, 0xE0DC, 0x73BB, 0xE0DE, + 0x73BD, 0xFB60, 0x73C0, 0xE0DF, 0x73C2, 0x89CF, 0x73C8, 0xE0DB, 0x73C9, 0xFB61, 0x73CA, 0x8E58, 0x73CD, 0x92BF, 0x73CE, 0xE0DD, + 0x73D2, 0xFB64, 0x73D6, 0xFB62, 0x73DE, 0xE0E2, 0x73E0, 0x8EEC, 0x73E3, 0xFB63, 0x73E5, 0xE0E0, 0x73EA, 0x8C5D, 0x73ED, 0x94C7, + 0x73EE, 0xE0E1, 0x73F1, 0xE0FC, 0x73F5, 0xFB66, 0x73F8, 0xE0E7, 0x73FE, 0x8CBB, 0x7403, 0x8B85, 0x7405, 0xE0E4, 0x7406, 0x979D, + 0x7407, 0xFB65, 0x7409, 0x97AE, 0x7422, 0x91F4, 0x7425, 0xE0E6, 0x7426, 0xFB67, 0x7429, 0xFB69, 0x742A, 0xFB68, 0x742E, 0xFB6A, + 0x7432, 0xE0E8, 0x7433, 0x97D4, 0x7434, 0x8BD5, 0x7435, 0x94FA, 0x7436, 0x9469, 0x743A, 0xE0E9, 0x743F, 0xE0EB, 0x7441, 0xE0EE, + 0x7455, 0xE0EA, 0x7459, 0xE0ED, 0x745A, 0x8CE8, 0x745B, 0x896C, 0x745C, 0xE0EF, 0x745E, 0x9090, 0x745F, 0xE0EC, 0x7460, 0x97DA, + 0x7462, 0xFB6B, 0x7463, 0xE0F2, 0x7464, 0xEAA2, 0x7469, 0xE0F0, 0x746A, 0xE0F3, 0x746F, 0xE0E5, 0x7470, 0xE0F1, 0x7473, 0x8DBA, + 0x7476, 0xE0F4, 0x747E, 0xE0F5, 0x7483, 0x979E, 0x7489, 0xFB6C, 0x748B, 0xE0F6, 0x749E, 0xE0F7, 0x749F, 0xFB6D, 0x74A2, 0xE0E3, + 0x74A7, 0xE0F8, 0x74B0, 0x8AC2, 0x74BD, 0x8EA3, 0x74CA, 0xE0F9, 0x74CF, 0xE0FA, 0x74D4, 0xE0FB, 0x74DC, 0x895A, 0x74E0, 0xE140, + 0x74E2, 0x955A, 0x74E3, 0xE141, 0x74E6, 0x8AA2, 0x74E7, 0xE142, 0x74E9, 0xE143, 0x74EE, 0xE144, 0x74F0, 0xE146, 0x74F1, 0xE147, + 0x74F2, 0xE145, 0x74F6, 0x9572, 0x74F7, 0xE149, 0x74F8, 0xE148, 0x7501, 0xFB6E, 0x7503, 0xE14B, 0x7504, 0xE14A, 0x7505, 0xE14C, + 0x750C, 0xE14D, 0x750D, 0xE14F, 0x750E, 0xE14E, 0x7511, 0x8D99, 0x7513, 0xE151, 0x7515, 0xE150, 0x7518, 0x8AC3, 0x751A, 0x9072, + 0x751C, 0x935B, 0x751E, 0xE152, 0x751F, 0x90B6, 0x7523, 0x8E59, 0x7525, 0x8999, 0x7526, 0xE153, 0x7528, 0x9770, 0x752B, 0x95E1, + 0x752C, 0xE154, 0x752F, 0xFAA8, 0x7530, 0x9363, 0x7531, 0x9752, 0x7532, 0x8D62, 0x7533, 0x905C, 0x7537, 0x926A, 0x7538, 0x99B2, + 0x753A, 0x92AC, 0x753B, 0x89E6, 0x753C, 0xE155, 0x7544, 0xE156, 0x7546, 0xE15B, 0x7549, 0xE159, 0x754A, 0xE158, 0x754B, 0x9DC0, + 0x754C, 0x8A45, 0x754D, 0xE157, 0x754F, 0x88D8, 0x7551, 0x94A8, 0x7554, 0x94C8, 0x7559, 0x97AF, 0x755A, 0xE15C, 0x755B, 0xE15A, + 0x755C, 0x927B, 0x755D, 0x90A4, 0x7560, 0x94A9, 0x7562, 0x954C, 0x7564, 0xE15E, 0x7565, 0x97AA, 0x7566, 0x8C6C, 0x7567, 0xE15F, + 0x7569, 0xE15D, 0x756A, 0x94D4, 0x756B, 0xE160, 0x756D, 0xE161, 0x756F, 0xFB6F, 0x7570, 0x88D9, 0x7573, 0x8FF4, 0x7574, 0xE166, + 0x7576, 0xE163, 0x7577, 0x93EB, 0x7578, 0xE162, 0x757F, 0x8B45, 0x7582, 0xE169, 0x7586, 0xE164, 0x7587, 0xE165, 0x7589, 0xE168, + 0x758A, 0xE167, 0x758B, 0x9544, 0x758E, 0x9161, 0x758F, 0x9160, 0x7591, 0x8B5E, 0x7594, 0xE16A, 0x759A, 0xE16B, 0x759D, 0xE16C, + 0x75A3, 0xE16E, 0x75A5, 0xE16D, 0x75AB, 0x8975, 0x75B1, 0xE176, 0x75B2, 0x94E6, 0x75B3, 0xE170, 0x75B5, 0xE172, 0x75B8, 0xE174, + 0x75B9, 0x905D, 0x75BC, 0xE175, 0x75BD, 0xE173, 0x75BE, 0x8EBE, 0x75C2, 0xE16F, 0x75C3, 0xE171, 0x75C5, 0x9561, 0x75C7, 0x8FC7, + 0x75CA, 0xE178, 0x75CD, 0xE177, 0x75D2, 0xE179, 0x75D4, 0x8EA4, 0x75D5, 0x8DAD, 0x75D8, 0x9397, 0x75D9, 0xE17A, 0x75DB, 0x92C9, + 0x75DE, 0xE17C, 0x75E2, 0x979F, 0x75E3, 0xE17B, 0x75E9, 0x9189, 0x75F0, 0xE182, 0x75F2, 0xE184, 0x75F3, 0xE185, 0x75F4, 0x9273, + 0x75FA, 0xE183, 0x75FC, 0xE180, 0x75FE, 0xE17D, 0x75FF, 0xE17E, 0x7601, 0xE181, 0x7609, 0xE188, 0x760B, 0xE186, 0x760D, 0xE187, + 0x761F, 0xE189, 0x7620, 0xE18B, 0x7621, 0xE18C, 0x7622, 0xE18D, 0x7624, 0xE18E, 0x7627, 0xE18A, 0x7630, 0xE190, 0x7634, 0xE18F, + 0x763B, 0xE191, 0x7642, 0x97C3, 0x7646, 0xE194, 0x7647, 0xE192, 0x7648, 0xE193, 0x764C, 0x8AE0, 0x7652, 0x96FC, 0x7656, 0x95C8, + 0x7658, 0xE196, 0x765C, 0xE195, 0x7661, 0xE197, 0x7662, 0xE198, 0x7667, 0xE19C, 0x7668, 0xE199, 0x7669, 0xE19A, 0x766A, 0xE19B, + 0x766C, 0xE19D, 0x7670, 0xE19E, 0x7672, 0xE19F, 0x7676, 0xE1A0, 0x7678, 0xE1A1, 0x767A, 0x94AD, 0x767B, 0x936F, 0x767C, 0xE1A2, + 0x767D, 0x9492, 0x767E, 0x9553, 0x7680, 0xE1A3, 0x7682, 0xFB70, 0x7683, 0xE1A4, 0x7684, 0x9349, 0x7686, 0x8A46, 0x7687, 0x8D63, + 0x7688, 0xE1A5, 0x768B, 0xE1A6, 0x768E, 0xE1A7, 0x7690, 0x8E48, 0x7693, 0xE1A9, 0x7696, 0xE1A8, 0x7699, 0xE1AA, 0x769A, 0xE1AB, + 0x769B, 0xFB73, 0x769C, 0xFB71, 0x769E, 0xFB72, 0x76A6, 0xFB74, 0x76AE, 0x94E7, 0x76B0, 0xE1AC, 0x76B4, 0xE1AD, 0x76B7, 0xEA89, + 0x76B8, 0xE1AE, 0x76B9, 0xE1AF, 0x76BA, 0xE1B0, 0x76BF, 0x8E4D, 0x76C2, 0xE1B1, 0x76C3, 0x9475, 0x76C6, 0x967E, 0x76C8, 0x896D, + 0x76CA, 0x8976, 0x76CD, 0xE1B2, 0x76D2, 0xE1B4, 0x76D6, 0xE1B3, 0x76D7, 0x9390, 0x76DB, 0x90B7, 0x76DC, 0x9F58, 0x76DE, 0xE1B5, + 0x76DF, 0x96BF, 0x76E1, 0xE1B6, 0x76E3, 0x8AC4, 0x76E4, 0x94D5, 0x76E5, 0xE1B7, 0x76E7, 0xE1B8, 0x76EA, 0xE1B9, 0x76EE, 0x96DA, + 0x76F2, 0x96D3, 0x76F4, 0x92BC, 0x76F8, 0x918A, 0x76FB, 0xE1BB, 0x76FE, 0x8F82, 0x7701, 0x8FC8, 0x7704, 0xE1BE, 0x7707, 0xE1BD, + 0x7708, 0xE1BC, 0x7709, 0x94FB, 0x770B, 0x8AC5, 0x770C, 0x8CA7, 0x771B, 0xE1C4, 0x771E, 0xE1C1, 0x771F, 0x905E, 0x7720, 0x96B0, + 0x7724, 0xE1C0, 0x7725, 0xE1C2, 0x7726, 0xE1C3, 0x7729, 0xE1BF, 0x7737, 0xE1C5, 0x7738, 0xE1C6, 0x773A, 0x92AD, 0x773C, 0x8AE1, + 0x7740, 0x9285, 0x7746, 0xFB76, 0x7747, 0xE1C7, 0x775A, 0xE1C8, 0x775B, 0xE1CB, 0x7761, 0x9087, 0x7763, 0x93C2, 0x7765, 0xE1CC, + 0x7766, 0x9672, 0x7768, 0xE1C9, 0x776B, 0xE1CA, 0x7779, 0xE1CF, 0x777E, 0xE1CE, 0x777F, 0xE1CD, 0x778B, 0xE1D1, 0x778E, 0xE1D0, + 0x7791, 0xE1D2, 0x779E, 0xE1D4, 0x77A0, 0xE1D3, 0x77A5, 0x95CB, 0x77AC, 0x8F75, 0x77AD, 0x97C4, 0x77B0, 0xE1D5, 0x77B3, 0x93B5, + 0x77B6, 0xE1D6, 0x77B9, 0xE1D7, 0x77BB, 0xE1DB, 0x77BC, 0xE1D9, 0x77BD, 0xE1DA, 0x77BF, 0xE1D8, 0x77C7, 0xE1DC, 0x77CD, 0xE1DD, + 0x77D7, 0xE1DE, 0x77DA, 0xE1DF, 0x77DB, 0x96B5, 0x77DC, 0xE1E0, 0x77E2, 0x96EE, 0x77E3, 0xE1E1, 0x77E5, 0x926D, 0x77E7, 0x948A, + 0x77E9, 0x8BE9, 0x77ED, 0x925A, 0x77EE, 0xE1E2, 0x77EF, 0x8BB8, 0x77F3, 0x90CE, 0x77FC, 0xE1E3, 0x7802, 0x8DBB, 0x780C, 0xE1E4, + 0x7812, 0xE1E5, 0x7814, 0x8CA4, 0x7815, 0x8DD3, 0x7820, 0xE1E7, 0x7821, 0xFB78, 0x7825, 0x9375, 0x7826, 0x8DD4, 0x7827, 0x8B6D, + 0x7832, 0x9643, 0x7834, 0x946A, 0x783A, 0x9376, 0x783F, 0x8D7B, 0x7845, 0xE1E9, 0x784E, 0xFB79, 0x785D, 0x8FC9, 0x7864, 0xFB7A, + 0x786B, 0x97B0, 0x786C, 0x8D64, 0x786F, 0x8CA5, 0x7872, 0x94A1, 0x7874, 0xE1EB, 0x787A, 0xFB7B, 0x787C, 0xE1ED, 0x7881, 0x8CE9, + 0x7886, 0xE1EC, 0x7887, 0x92F4, 0x788C, 0xE1EF, 0x788D, 0x8A56, 0x788E, 0xE1EA, 0x7891, 0x94E8, 0x7893, 0x894F, 0x7895, 0x8DEA, + 0x7897, 0x9871, 0x789A, 0xE1EE, 0x78A3, 0xE1F0, 0x78A7, 0x95C9, 0x78A9, 0x90D7, 0x78AA, 0xE1F2, 0x78AF, 0xE1F3, 0x78B5, 0xE1F1, + 0x78BA, 0x8A6D, 0x78BC, 0xE1F9, 0x78BE, 0xE1F8, 0x78C1, 0x8EA5, 0x78C5, 0xE1FA, 0x78C6, 0xE1F5, 0x78CA, 0xE1FB, 0x78CB, 0xE1F6, + 0x78D0, 0x94D6, 0x78D1, 0xE1F4, 0x78D4, 0xE1F7, 0x78DA, 0xE241, 0x78E7, 0xE240, 0x78E8, 0x9681, 0x78EC, 0xE1FC, 0x78EF, 0x88E9, + 0x78F4, 0xE243, 0x78FD, 0xE242, 0x7901, 0x8FCA, 0x7907, 0xE244, 0x790E, 0x9162, 0x7911, 0xE246, 0x7912, 0xE245, 0x7919, 0xE247, + 0x7926, 0xE1E6, 0x792A, 0xE1E8, 0x792B, 0xE249, 0x792C, 0xE248, 0x7930, 0xFB7C, 0x793A, 0x8EA6, 0x793C, 0x97E7, 0x793E, 0x8ED0, + 0x7940, 0xE24A, 0x7941, 0x8C56, 0x7947, 0x8B5F, 0x7948, 0x8B46, 0x7949, 0x8E83, 0x7950, 0x9753, 0x7953, 0xE250, 0x7955, 0xE24F, + 0x7956, 0x9163, 0x7957, 0xE24C, 0x795A, 0xE24E, 0x795D, 0x8F6A, 0x795E, 0x905F, 0x795F, 0xE24D, 0x7960, 0xE24B, 0x7962, 0x9449, + 0x7965, 0x8FCB, 0x7968, 0x955B, 0x796D, 0x8DD5, 0x7977, 0x9398, 0x797A, 0xE251, 0x797F, 0xE252, 0x7980, 0xE268, 0x7981, 0x8BD6, + 0x7984, 0x985C, 0x7985, 0x9154, 0x798A, 0xE253, 0x798D, 0x89D0, 0x798E, 0x92F5, 0x798F, 0x959F, 0x7994, 0xFB81, 0x799B, 0xFB83, + 0x799D, 0xE254, 0x79A6, 0x8B9A, 0x79A7, 0xE255, 0x79AA, 0xE257, 0x79AE, 0xE258, 0x79B0, 0x9448, 0x79B3, 0xE259, 0x79B9, 0xE25A, + 0x79BA, 0xE25B, 0x79BD, 0x8BD7, 0x79BE, 0x89D1, 0x79BF, 0x93C3, 0x79C0, 0x8F47, 0x79C1, 0x8E84, 0x79C9, 0xE25C, 0x79CB, 0x8F48, + 0x79D1, 0x89C8, 0x79D2, 0x9562, 0x79D5, 0xE25D, 0x79D8, 0x94E9, 0x79DF, 0x9164, 0x79E1, 0xE260, 0x79E3, 0xE261, 0x79E4, 0x9489, + 0x79E6, 0x9060, 0x79E7, 0xE25E, 0x79E9, 0x9281, 0x79EC, 0xE25F, 0x79F0, 0x8FCC, 0x79FB, 0x88DA, 0x7A00, 0x8B48, 0x7A08, 0xE262, + 0x7A0B, 0x92F6, 0x7A0D, 0xE263, 0x7A0E, 0x90C5, 0x7A14, 0x96AB, 0x7A17, 0x9542, 0x7A18, 0xE264, 0x7A19, 0xE265, 0x7A1A, 0x9274, + 0x7A1C, 0x97C5, 0x7A1F, 0xE267, 0x7A20, 0xE266, 0x7A2E, 0x8EED, 0x7A31, 0xE269, 0x7A32, 0x88EE, 0x7A37, 0xE26C, 0x7A3B, 0xE26A, + 0x7A3C, 0x89D2, 0x7A3D, 0x8C6D, 0x7A3E, 0xE26B, 0x7A3F, 0x8D65, 0x7A40, 0x8D92, 0x7A42, 0x95E4, 0x7A43, 0xE26D, 0x7A46, 0x9673, + 0x7A49, 0xE26F, 0x7A4D, 0x90CF, 0x7A4E, 0x896E, 0x7A4F, 0x89B8, 0x7A50, 0x88AA, 0x7A57, 0xE26E, 0x7A61, 0xE270, 0x7A62, 0xE271, + 0x7A63, 0x8FF5, 0x7A69, 0xE272, 0x7A6B, 0x8A6E, 0x7A70, 0xE274, 0x7A74, 0x8C8A, 0x7A76, 0x8B86, 0x7A79, 0xE275, 0x7A7A, 0x8BF3, + 0x7A7D, 0xE276, 0x7A7F, 0x90FA, 0x7A81, 0x93CB, 0x7A83, 0x90DE, 0x7A84, 0x8DF3, 0x7A88, 0xE277, 0x7A92, 0x9282, 0x7A93, 0x918B, + 0x7A95, 0xE279, 0x7A96, 0xE27B, 0x7A97, 0xE278, 0x7A98, 0xE27A, 0x7A9F, 0x8C41, 0x7AA9, 0xE27C, 0x7AAA, 0x8C45, 0x7AAE, 0x8B87, + 0x7AAF, 0x9771, 0x7AB0, 0xE27E, 0x7AB6, 0xE280, 0x7ABA, 0x894D, 0x7ABF, 0xE283, 0x7AC3, 0x8A96, 0x7AC4, 0xE282, 0x7AC5, 0xE281, + 0x7AC7, 0xE285, 0x7AC8, 0xE27D, 0x7ACA, 0xE286, 0x7ACB, 0x97A7, 0x7ACD, 0xE287, 0x7ACF, 0xE288, 0x7AD1, 0xFB84, 0x7AD2, 0x9AF2, + 0x7AD3, 0xE28A, 0x7AD5, 0xE289, 0x7AD9, 0xE28B, 0x7ADA, 0xE28C, 0x7ADC, 0x97B3, 0x7ADD, 0xE28D, 0x7ADF, 0xE8ED, 0x7AE0, 0x8FCD, + 0x7AE1, 0xE28E, 0x7AE2, 0xE28F, 0x7AE3, 0x8F76, 0x7AE5, 0x93B6, 0x7AE6, 0xE290, 0x7AE7, 0xFB85, 0x7AEA, 0x9247, 0x7AEB, 0xFB87, + 0x7AED, 0xE291, 0x7AEF, 0x925B, 0x7AF0, 0xE292, 0x7AF6, 0x8BA3, 0x7AF8, 0x995E, 0x7AF9, 0x927C, 0x7AFA, 0x8EB1, 0x7AFF, 0x8AC6, + 0x7B02, 0xE293, 0x7B04, 0xE2A0, 0x7B06, 0xE296, 0x7B08, 0x8B88, 0x7B0A, 0xE295, 0x7B0B, 0xE2A2, 0x7B0F, 0xE294, 0x7B11, 0x8FCE, + 0x7B18, 0xE298, 0x7B19, 0xE299, 0x7B1B, 0x934A, 0x7B1E, 0xE29A, 0x7B20, 0x8A7D, 0x7B25, 0x9079, 0x7B26, 0x9584, 0x7B28, 0xE29C, + 0x7B2C, 0x91E6, 0x7B33, 0xE297, 0x7B35, 0xE29B, 0x7B36, 0xE29D, 0x7B39, 0x8DF9, 0x7B45, 0xE2A4, 0x7B46, 0x954D, 0x7B48, 0x94A4, + 0x7B49, 0x9399, 0x7B4B, 0x8BD8, 0x7B4C, 0xE2A3, 0x7B4D, 0xE2A1, 0x7B4F, 0x94B3, 0x7B50, 0xE29E, 0x7B51, 0x927D, 0x7B52, 0x939B, + 0x7B54, 0x939A, 0x7B56, 0x8DF4, 0x7B5D, 0xE2B6, 0x7B65, 0xE2A6, 0x7B67, 0xE2A8, 0x7B6C, 0xE2AB, 0x7B6E, 0xE2AC, 0x7B70, 0xE2A9, + 0x7B71, 0xE2AA, 0x7B74, 0xE2A7, 0x7B75, 0xE2A5, 0x7B7A, 0xE29F, 0x7B86, 0x95CD, 0x7B87, 0x89D3, 0x7B8B, 0xE2B3, 0x7B8D, 0xE2B0, + 0x7B8F, 0xE2B5, 0x7B92, 0xE2B4, 0x7B94, 0x9493, 0x7B95, 0x96A5, 0x7B97, 0x8E5A, 0x7B98, 0xE2AE, 0x7B99, 0xE2B7, 0x7B9A, 0xE2B2, + 0x7B9C, 0xE2B1, 0x7B9D, 0xE2AD, 0x7B9E, 0xFB88, 0x7B9F, 0xE2AF, 0x7BA1, 0x8AC7, 0x7BAA, 0x925C, 0x7BAD, 0x90FB, 0x7BB1, 0x94A0, + 0x7BB4, 0xE2BC, 0x7BB8, 0x94A2, 0x7BC0, 0x90DF, 0x7BC1, 0xE2B9, 0x7BC4, 0x94CD, 0x7BC6, 0xE2BD, 0x7BC7, 0x95D1, 0x7BC9, 0x927A, + 0x7BCB, 0xE2B8, 0x7BCC, 0xE2BA, 0x7BCF, 0xE2BB, 0x7BDD, 0xE2BE, 0x7BE0, 0x8EC2, 0x7BE4, 0x93C4, 0x7BE5, 0xE2C3, 0x7BE6, 0xE2C2, + 0x7BE9, 0xE2BF, 0x7BED, 0x9855, 0x7BF3, 0xE2C8, 0x7BF6, 0xE2CC, 0x7BF7, 0xE2C9, 0x7C00, 0xE2C5, 0x7C07, 0xE2C6, 0x7C0D, 0xE2CB, + 0x7C11, 0xE2C0, 0x7C12, 0x99D3, 0x7C13, 0xE2C7, 0x7C14, 0xE2C1, 0x7C17, 0xE2CA, 0x7C1F, 0xE2D0, 0x7C21, 0x8AC8, 0x7C23, 0xE2CD, + 0x7C27, 0xE2CE, 0x7C2A, 0xE2CF, 0x7C2B, 0xE2D2, 0x7C37, 0xE2D1, 0x7C38, 0x94F4, 0x7C3D, 0xE2D3, 0x7C3E, 0x97FA, 0x7C3F, 0x95EB, + 0x7C40, 0xE2D8, 0x7C43, 0xE2D5, 0x7C4C, 0xE2D4, 0x7C4D, 0x90D0, 0x7C4F, 0xE2D7, 0x7C50, 0xE2D9, 0x7C54, 0xE2D6, 0x7C56, 0xE2DD, + 0x7C58, 0xE2DA, 0x7C5F, 0xE2DB, 0x7C60, 0xE2C4, 0x7C64, 0xE2DC, 0x7C65, 0xE2DE, 0x7C6C, 0xE2DF, 0x7C73, 0x95C4, 0x7C75, 0xE2E0, + 0x7C7E, 0x96E0, 0x7C81, 0x8BCC, 0x7C82, 0x8C48, 0x7C83, 0xE2E1, 0x7C89, 0x95B2, 0x7C8B, 0x9088, 0x7C8D, 0x96AE, 0x7C90, 0xE2E2, + 0x7C92, 0x97B1, 0x7C95, 0x9494, 0x7C97, 0x9165, 0x7C98, 0x9453, 0x7C9B, 0x8F6C, 0x7C9F, 0x88BE, 0x7CA1, 0xE2E7, 0x7CA2, 0xE2E5, + 0x7CA4, 0xE2E3, 0x7CA5, 0x8A9F, 0x7CA7, 0x8FCF, 0x7CA8, 0xE2E8, 0x7CAB, 0xE2E6, 0x7CAD, 0xE2E4, 0x7CAE, 0xE2EC, 0x7CB1, 0xE2EB, + 0x7CB2, 0xE2EA, 0x7CB3, 0xE2E9, 0x7CB9, 0xE2ED, 0x7CBD, 0xE2EE, 0x7CBE, 0x90B8, 0x7CC0, 0xE2EF, 0x7CC2, 0xE2F1, 0x7CC5, 0xE2F0, + 0x7CCA, 0x8CD0, 0x7CCE, 0x9157, 0x7CD2, 0xE2F3, 0x7CD6, 0x939C, 0x7CD8, 0xE2F2, 0x7CDC, 0xE2F4, 0x7CDE, 0x95B3, 0x7CDF, 0x918C, + 0x7CE0, 0x8D66, 0x7CE2, 0xE2F5, 0x7CE7, 0x97C6, 0x7CEF, 0xE2F7, 0x7CF2, 0xE2F8, 0x7CF4, 0xE2F9, 0x7CF6, 0xE2FA, 0x7CF8, 0x8E85, + 0x7CFA, 0xE2FB, 0x7CFB, 0x8C6E, 0x7CFE, 0x8B8A, 0x7D00, 0x8B49, 0x7D02, 0xE340, 0x7D04, 0x96F1, 0x7D05, 0x8D67, 0x7D06, 0xE2FC, + 0x7D0A, 0xE343, 0x7D0B, 0x96E4, 0x7D0D, 0x945B, 0x7D10, 0x9552, 0x7D14, 0x8F83, 0x7D15, 0xE342, 0x7D17, 0x8ED1, 0x7D18, 0x8D68, + 0x7D19, 0x8E86, 0x7D1A, 0x8B89, 0x7D1B, 0x95B4, 0x7D1C, 0xE341, 0x7D20, 0x9166, 0x7D21, 0x9661, 0x7D22, 0x8DF5, 0x7D2B, 0x8E87, + 0x7D2C, 0x92DB, 0x7D2E, 0xE346, 0x7D2F, 0x97DD, 0x7D30, 0x8DD7, 0x7D32, 0xE347, 0x7D33, 0x9061, 0x7D35, 0xE349, 0x7D39, 0x8FD0, + 0x7D3A, 0x8DAE, 0x7D3F, 0xE348, 0x7D42, 0x8F49, 0x7D43, 0x8CBC, 0x7D44, 0x9167, 0x7D45, 0xE344, 0x7D46, 0xE34A, 0x7D48, 0xFB8A, + 0x7D4B, 0xE345, 0x7D4C, 0x8C6F, 0x7D4E, 0xE34D, 0x7D4F, 0xE351, 0x7D50, 0x8C8B, 0x7D56, 0xE34C, 0x7D5B, 0xE355, 0x7D5C, 0xFB8B, + 0x7D5E, 0x8D69, 0x7D61, 0x978D, 0x7D62, 0x88BA, 0x7D63, 0xE352, 0x7D66, 0x8B8B, 0x7D68, 0xE34F, 0x7D6E, 0xE350, 0x7D71, 0x939D, + 0x7D72, 0xE34E, 0x7D73, 0xE34B, 0x7D75, 0x8A47, 0x7D76, 0x90E2, 0x7D79, 0x8CA6, 0x7D7D, 0xE357, 0x7D89, 0xE354, 0x7D8F, 0xE356, + 0x7D93, 0xE353, 0x7D99, 0x8C70, 0x7D9A, 0x91B1, 0x7D9B, 0xE358, 0x7D9C, 0x918E, 0x7D9F, 0xE365, 0x7DA0, 0xFB8D, 0x7DA2, 0xE361, + 0x7DA3, 0xE35B, 0x7DAB, 0xE35F, 0x7DAC, 0x8EF8, 0x7DAD, 0x88DB, 0x7DAE, 0xE35A, 0x7DAF, 0xE362, 0x7DB0, 0xE366, 0x7DB1, 0x8D6A, + 0x7DB2, 0x96D4, 0x7DB4, 0x92D4, 0x7DB5, 0xE35C, 0x7DB7, 0xFB8C, 0x7DB8, 0xE364, 0x7DBA, 0xE359, 0x7DBB, 0x925D, 0x7DBD, 0xE35E, + 0x7DBE, 0x88BB, 0x7DBF, 0x96C8, 0x7DC7, 0xE35D, 0x7DCA, 0x8BD9, 0x7DCB, 0x94EA, 0x7DCF, 0x918D, 0x7DD1, 0x97CE, 0x7DD2, 0x8F8F, + 0x7DD5, 0xE38E, 0x7DD6, 0xFB8E, 0x7DD8, 0xE367, 0x7DDA, 0x90FC, 0x7DDC, 0xE363, 0x7DDD, 0xE368, 0x7DDE, 0xE36A, 0x7DE0, 0x92F7, + 0x7DE1, 0xE36D, 0x7DE4, 0xE369, 0x7DE8, 0x95D2, 0x7DE9, 0x8AC9, 0x7DEC, 0x96C9, 0x7DEF, 0x88DC, 0x7DF2, 0xE36C, 0x7DF4, 0x97FB, + 0x7DFB, 0xE36B, 0x7E01, 0x898F, 0x7E04, 0x93EA, 0x7E05, 0xE36E, 0x7E09, 0xE375, 0x7E0A, 0xE36F, 0x7E0B, 0xE376, 0x7E12, 0xE372, + 0x7E1B, 0x949B, 0x7E1E, 0x8EC8, 0x7E1F, 0xE374, 0x7E21, 0xE371, 0x7E22, 0xE377, 0x7E23, 0xE370, 0x7E26, 0x8F63, 0x7E2B, 0x9644, + 0x7E2E, 0x8F6B, 0x7E31, 0xE373, 0x7E32, 0xE380, 0x7E35, 0xE37B, 0x7E37, 0xE37E, 0x7E39, 0xE37C, 0x7E3A, 0xE381, 0x7E3B, 0xE37A, + 0x7E3D, 0xE360, 0x7E3E, 0x90D1, 0x7E41, 0x94C9, 0x7E43, 0xE37D, 0x7E46, 0xE378, 0x7E4A, 0x9140, 0x7E4B, 0x8C71, 0x7E4D, 0x8F4A, + 0x7E52, 0xFB8F, 0x7E54, 0x9044, 0x7E55, 0x9155, 0x7E56, 0xE384, 0x7E59, 0xE386, 0x7E5A, 0xE387, 0x7E5D, 0xE383, 0x7E5E, 0xE385, + 0x7E66, 0xE379, 0x7E67, 0xE382, 0x7E69, 0xE38A, 0x7E6A, 0xE389, 0x7E6D, 0x969A, 0x7E70, 0x8C4A, 0x7E79, 0xE388, 0x7E7B, 0xE38C, + 0x7E7C, 0xE38B, 0x7E7D, 0xE38F, 0x7E7F, 0xE391, 0x7E82, 0x8E5B, 0x7E83, 0xE38D, 0x7E88, 0xE392, 0x7E89, 0xE393, 0x7E8A, 0xFA5C, + 0x7E8C, 0xE394, 0x7E8E, 0xE39A, 0x7E8F, 0x935A, 0x7E90, 0xE396, 0x7E92, 0xE395, 0x7E93, 0xE397, 0x7E94, 0xE398, 0x7E96, 0xE399, + 0x7E9B, 0xE39B, 0x7E9C, 0xE39C, 0x7F36, 0x8ACA, 0x7F38, 0xE39D, 0x7F3A, 0xE39E, 0x7F45, 0xE39F, 0x7F47, 0xFB90, 0x7F4C, 0xE3A0, + 0x7F4D, 0xE3A1, 0x7F4E, 0xE3A2, 0x7F50, 0xE3A3, 0x7F51, 0xE3A4, 0x7F54, 0xE3A6, 0x7F55, 0xE3A5, 0x7F58, 0xE3A7, 0x7F5F, 0xE3A8, + 0x7F60, 0xE3A9, 0x7F67, 0xE3AC, 0x7F68, 0xE3AA, 0x7F69, 0xE3AB, 0x7F6A, 0x8DDF, 0x7F6B, 0x8C72, 0x7F6E, 0x9275, 0x7F70, 0x94B1, + 0x7F72, 0x8F90, 0x7F75, 0x946C, 0x7F77, 0x94EB, 0x7F78, 0xE3AD, 0x7F79, 0x9CEB, 0x7F82, 0xE3AE, 0x7F83, 0xE3B0, 0x7F85, 0x9785, + 0x7F86, 0xE3AF, 0x7F87, 0xE3B2, 0x7F88, 0xE3B1, 0x7F8A, 0x9772, 0x7F8C, 0xE3B3, 0x7F8E, 0x94FC, 0x7F94, 0xE3B4, 0x7F9A, 0xE3B7, + 0x7F9D, 0xE3B6, 0x7F9E, 0xE3B5, 0x7FA1, 0xFB91, 0x7FA3, 0xE3B8, 0x7FA4, 0x8C51, 0x7FA8, 0x9141, 0x7FA9, 0x8B60, 0x7FAE, 0xE3BC, + 0x7FAF, 0xE3B9, 0x7FB2, 0xE3BA, 0x7FB6, 0xE3BD, 0x7FB8, 0xE3BE, 0x7FB9, 0xE3BB, 0x7FBD, 0x8948, 0x7FC1, 0x89A5, 0x7FC5, 0xE3C0, + 0x7FC6, 0xE3C1, 0x7FCA, 0xE3C2, 0x7FCC, 0x9782, 0x7FD2, 0x8F4B, 0x7FD4, 0xE3C4, 0x7FD5, 0xE3C3, 0x7FE0, 0x9089, 0x7FE1, 0xE3C5, + 0x7FE6, 0xE3C6, 0x7FE9, 0xE3C7, 0x7FEB, 0x8AE3, 0x7FF0, 0x8ACB, 0x7FF3, 0xE3C8, 0x7FF9, 0xE3C9, 0x7FFB, 0x967C, 0x7FFC, 0x9783, + 0x8000, 0x9773, 0x8001, 0x9856, 0x8003, 0x8D6C, 0x8004, 0xE3CC, 0x8005, 0x8ED2, 0x8006, 0xE3CB, 0x800B, 0xE3CD, 0x800C, 0x8EA7, + 0x8010, 0x91CF, 0x8012, 0xE3CE, 0x8015, 0x8D6B, 0x8017, 0x96D5, 0x8018, 0xE3CF, 0x8019, 0xE3D0, 0x801C, 0xE3D1, 0x8021, 0xE3D2, + 0x8028, 0xE3D3, 0x8033, 0x8EA8, 0x8036, 0x96EB, 0x803B, 0xE3D5, 0x803D, 0x925E, 0x803F, 0xE3D4, 0x8046, 0xE3D7, 0x804A, 0xE3D6, + 0x8052, 0xE3D8, 0x8056, 0x90B9, 0x8058, 0xE3D9, 0x805A, 0xE3DA, 0x805E, 0x95B7, 0x805F, 0xE3DB, 0x8061, 0x918F, 0x8062, 0xE3DC, + 0x8068, 0xE3DD, 0x806F, 0x97FC, 0x8070, 0xE3E0, 0x8072, 0xE3DF, 0x8073, 0xE3DE, 0x8074, 0x92AE, 0x8076, 0xE3E1, 0x8077, 0x9045, + 0x8079, 0xE3E2, 0x807D, 0xE3E3, 0x807E, 0x9857, 0x807F, 0xE3E4, 0x8084, 0xE3E5, 0x8085, 0xE3E7, 0x8086, 0xE3E6, 0x8087, 0x94A3, + 0x8089, 0x93F7, 0x808B, 0x985D, 0x808C, 0x94A7, 0x8093, 0xE3E9, 0x8096, 0x8FD1, 0x8098, 0x9549, 0x809A, 0xE3EA, 0x809B, 0xE3E8, + 0x809D, 0x8ACC, 0x80A1, 0x8CD2, 0x80A2, 0x8E88, 0x80A5, 0x94EC, 0x80A9, 0x8CA8, 0x80AA, 0x9662, 0x80AC, 0xE3ED, 0x80AD, 0xE3EB, + 0x80AF, 0x8D6D, 0x80B1, 0x8D6E, 0x80B2, 0x88E7, 0x80B4, 0x8DE6, 0x80BA, 0x9478, 0x80C3, 0x88DD, 0x80C4, 0xE3F2, 0x80C6, 0x925F, + 0x80CC, 0x9477, 0x80CE, 0x91D9, 0x80D6, 0xE3F4, 0x80D9, 0xE3F0, 0x80DA, 0xE3F3, 0x80DB, 0xE3EE, 0x80DD, 0xE3F1, 0x80DE, 0x9645, + 0x80E1, 0x8CD3, 0x80E4, 0x88FB, 0x80E5, 0xE3EF, 0x80EF, 0xE3F6, 0x80F1, 0xE3F7, 0x80F4, 0x93B7, 0x80F8, 0x8BB9, 0x80FC, 0xE445, + 0x80FD, 0x945C, 0x8102, 0x8E89, 0x8105, 0x8BBA, 0x8106, 0x90C6, 0x8107, 0x9865, 0x8108, 0x96AC, 0x8109, 0xE3F5, 0x810A, 0x90D2, + 0x811A, 0x8B72, 0x811B, 0xE3F8, 0x8123, 0xE3FA, 0x8129, 0xE3F9, 0x812F, 0xE3FB, 0x8131, 0x9245, 0x8133, 0x945D, 0x8139, 0x92AF, + 0x813E, 0xE442, 0x8146, 0xE441, 0x814B, 0xE3FC, 0x814E, 0x9074, 0x8150, 0x9585, 0x8151, 0xE444, 0x8153, 0xE443, 0x8154, 0x8D6F, + 0x8155, 0x9872, 0x815F, 0xE454, 0x8165, 0xE448, 0x8166, 0xE449, 0x816B, 0x8EEE, 0x816E, 0xE447, 0x8170, 0x8D98, 0x8171, 0xE446, + 0x8174, 0xE44A, 0x8178, 0x92B0, 0x8179, 0x95A0, 0x817A, 0x9142, 0x817F, 0x91DA, 0x8180, 0xE44E, 0x8182, 0xE44F, 0x8183, 0xE44B, + 0x8188, 0xE44C, 0x818A, 0xE44D, 0x818F, 0x8D70, 0x8193, 0xE455, 0x8195, 0xE451, 0x819A, 0x9586, 0x819C, 0x968C, 0x819D, 0x9547, + 0x81A0, 0xE450, 0x81A3, 0xE453, 0x81A4, 0xE452, 0x81A8, 0x9663, 0x81A9, 0xE456, 0x81B0, 0xE457, 0x81B3, 0x9156, 0x81B5, 0xE458, + 0x81B8, 0xE45A, 0x81BA, 0xE45E, 0x81BD, 0xE45B, 0x81BE, 0xE459, 0x81BF, 0x945E, 0x81C0, 0xE45C, 0x81C2, 0xE45D, 0x81C6, 0x89B0, + 0x81C8, 0xE464, 0x81C9, 0xE45F, 0x81CD, 0xE460, 0x81D1, 0xE461, 0x81D3, 0x919F, 0x81D8, 0xE463, 0x81D9, 0xE462, 0x81DA, 0xE465, + 0x81DF, 0xE466, 0x81E0, 0xE467, 0x81E3, 0x9062, 0x81E5, 0x89E7, 0x81E7, 0xE468, 0x81E8, 0x97D5, 0x81EA, 0x8EA9, 0x81ED, 0x8F4C, + 0x81F3, 0x8E8A, 0x81F4, 0x9276, 0x81FA, 0xE469, 0x81FB, 0xE46A, 0x81FC, 0x8950, 0x81FE, 0xE46B, 0x8201, 0xE46C, 0x8202, 0xE46D, + 0x8205, 0xE46E, 0x8207, 0xE46F, 0x8208, 0x8BBB, 0x8209, 0x9DA8, 0x820A, 0xE470, 0x820C, 0x90E3, 0x820D, 0xE471, 0x820E, 0x8EC9, + 0x8210, 0xE472, 0x8212, 0x98AE, 0x8216, 0xE473, 0x8217, 0x95DC, 0x8218, 0x8ADA, 0x821B, 0x9143, 0x821C, 0x8F77, 0x821E, 0x9591, + 0x821F, 0x8F4D, 0x8229, 0xE474, 0x822A, 0x8D71, 0x822B, 0xE475, 0x822C, 0x94CA, 0x822E, 0xE484, 0x8233, 0xE477, 0x8235, 0x91C7, + 0x8236, 0x9495, 0x8237, 0x8CBD, 0x8238, 0xE476, 0x8239, 0x9144, 0x8240, 0xE478, 0x8247, 0x92F8, 0x8258, 0xE47A, 0x8259, 0xE479, + 0x825A, 0xE47C, 0x825D, 0xE47B, 0x825F, 0xE47D, 0x8262, 0xE480, 0x8264, 0xE47E, 0x8266, 0x8ACD, 0x8268, 0xE481, 0x826A, 0xE482, + 0x826B, 0xE483, 0x826E, 0x8DAF, 0x826F, 0x97C7, 0x8271, 0xE485, 0x8272, 0x9046, 0x8276, 0x8990, 0x8277, 0xE486, 0x8278, 0xE487, + 0x827E, 0xE488, 0x828B, 0x88F0, 0x828D, 0xE489, 0x8292, 0xE48A, 0x8299, 0x9587, 0x829D, 0x8EC5, 0x829F, 0xE48C, 0x82A5, 0x8A48, + 0x82A6, 0x88B0, 0x82AB, 0xE48B, 0x82AC, 0xE48E, 0x82AD, 0x946D, 0x82AF, 0x9063, 0x82B1, 0x89D4, 0x82B3, 0x9646, 0x82B8, 0x8C7C, + 0x82B9, 0x8BDA, 0x82BB, 0xE48D, 0x82BD, 0x89E8, 0x82C5, 0x8AA1, 0x82D1, 0x8991, 0x82D2, 0xE492, 0x82D3, 0x97E8, 0x82D4, 0x91DB, + 0x82D7, 0x9563, 0x82D9, 0xE49E, 0x82DB, 0x89D5, 0x82DC, 0xE49C, 0x82DE, 0xE49A, 0x82DF, 0xE491, 0x82E1, 0xE48F, 0x82E3, 0xE490, + 0x82E5, 0x8EE1, 0x82E6, 0x8BEA, 0x82E7, 0x9297, 0x82EB, 0x93CF, 0x82F1, 0x8970, 0x82F3, 0xE494, 0x82F4, 0xE493, 0x82F9, 0xE499, + 0x82FA, 0xE495, 0x82FB, 0xE498, 0x8301, 0xFB93, 0x8302, 0x96CE, 0x8303, 0xE497, 0x8304, 0x89D6, 0x8305, 0x8A9D, 0x8306, 0xE49B, + 0x8309, 0xE49D, 0x830E, 0x8C73, 0x8316, 0xE4A1, 0x8317, 0xE4AA, 0x8318, 0xE4AB, 0x831C, 0x88A9, 0x8323, 0xE4B2, 0x8328, 0x88EF, + 0x832B, 0xE4A9, 0x832F, 0xE4A8, 0x8331, 0xE4A3, 0x8332, 0xE4A2, 0x8334, 0xE4A0, 0x8335, 0xE49F, 0x8336, 0x9283, 0x8338, 0x91F9, + 0x8339, 0xE4A5, 0x8340, 0xE4A4, 0x8345, 0xE4A7, 0x8349, 0x9190, 0x834A, 0x8C74, 0x834F, 0x8960, 0x8350, 0xE4A6, 0x8352, 0x8D72, + 0x8358, 0x9191, 0x8362, 0xFB94, 0x8373, 0xE4B8, 0x8375, 0xE4B9, 0x8377, 0x89D7, 0x837B, 0x89AC, 0x837C, 0xE4B6, 0x837F, 0xFB95, + 0x8385, 0xE4AC, 0x8387, 0xE4B4, 0x8389, 0xE4BB, 0x838A, 0xE4B5, 0x838E, 0xE4B3, 0x8393, 0xE496, 0x8396, 0xE4B1, 0x839A, 0xE4AD, + 0x839E, 0x8ACE, 0x839F, 0xE4AF, 0x83A0, 0xE4BA, 0x83A2, 0xE4B0, 0x83A8, 0xE4BC, 0x83AA, 0xE4AE, 0x83AB, 0x949C, 0x83B1, 0x9789, + 0x83B5, 0xE4B7, 0x83BD, 0xE4CD, 0x83C1, 0xE4C5, 0x83C5, 0x909B, 0x83C7, 0xFB96, 0x83CA, 0x8B65, 0x83CC, 0x8BDB, 0x83CE, 0xE4C0, + 0x83D3, 0x89D9, 0x83D6, 0x8FD2, 0x83D8, 0xE4C3, 0x83DC, 0x8DD8, 0x83DF, 0x9370, 0x83E0, 0xE4C8, 0x83E9, 0x95EC, 0x83EB, 0xE4BF, + 0x83EF, 0x89D8, 0x83F0, 0x8CD4, 0x83F1, 0x9548, 0x83F2, 0xE4C9, 0x83F4, 0xE4BD, 0x83F6, 0xFB97, 0x83F7, 0xE4C6, 0x83FB, 0xE4D0, + 0x83FD, 0xE4C1, 0x8403, 0xE4C2, 0x8404, 0x93B8, 0x8407, 0xE4C7, 0x840B, 0xE4C4, 0x840C, 0x9647, 0x840D, 0xE4CA, 0x840E, 0x88DE, + 0x8413, 0xE4BE, 0x8420, 0xE4CC, 0x8422, 0xE4CB, 0x8429, 0x948B, 0x842A, 0xE4D2, 0x842C, 0xE4DD, 0x8431, 0x8A9E, 0x8435, 0xE4E0, + 0x8438, 0xE4CE, 0x843C, 0xE4D3, 0x843D, 0x978E, 0x8446, 0xE4DC, 0x8448, 0xFB98, 0x8449, 0x9774, 0x844E, 0x97A8, 0x8457, 0x9298, + 0x845B, 0x8A8B, 0x8461, 0x9592, 0x8462, 0xE4E2, 0x8463, 0x939F, 0x8466, 0x88AF, 0x8469, 0xE4DB, 0x846B, 0xE4D7, 0x846C, 0x9192, + 0x846D, 0xE4D1, 0x846E, 0xE4D9, 0x846F, 0xE4DE, 0x8471, 0x944B, 0x8475, 0x88A8, 0x8477, 0xE4D6, 0x8479, 0xE4DF, 0x847A, 0x9598, + 0x8482, 0xE4DA, 0x8484, 0xE4D5, 0x848B, 0x8FD3, 0x8490, 0x8F4E, 0x8494, 0x8EAA, 0x8499, 0x96D6, 0x849C, 0x9566, 0x849F, 0xE4E5, + 0x84A1, 0xE4EE, 0x84AD, 0xE4D8, 0x84B2, 0x8A97, 0x84B4, 0xFB99, 0x84B8, 0x8FF6, 0x84B9, 0xE4E3, 0x84BB, 0xE4E8, 0x84BC, 0x9193, + 0x84BF, 0xE4E4, 0x84C1, 0xE4EB, 0x84C4, 0x927E, 0x84C6, 0xE4EC, 0x84C9, 0x9775, 0x84CA, 0xE4E1, 0x84CB, 0x8A57, 0x84CD, 0xE4E7, + 0x84D0, 0xE4EA, 0x84D1, 0x96AA, 0x84D6, 0xE4ED, 0x84D9, 0xE4E6, 0x84DA, 0xE4E9, 0x84DC, 0xFA60, 0x84EC, 0x9648, 0x84EE, 0x9840, + 0x84F4, 0xE4F1, 0x84FC, 0xE4F8, 0x84FF, 0xE4F0, 0x8500, 0x8EC1, 0x8506, 0xE4CF, 0x8511, 0x95CC, 0x8513, 0x96A0, 0x8514, 0xE4F7, + 0x8515, 0xE4F6, 0x8517, 0xE4F2, 0x8518, 0xE4F3, 0x851A, 0x8955, 0x851F, 0xE4F5, 0x8521, 0xE4EF, 0x8526, 0x92D3, 0x852C, 0xE4F4, + 0x852D, 0x88FC, 0x8535, 0x91A0, 0x853D, 0x95C1, 0x8540, 0xE4F9, 0x8541, 0xE540, 0x8543, 0x94D7, 0x8548, 0xE4FC, 0x8549, 0x8FD4, + 0x854A, 0x8EC7, 0x854B, 0xE542, 0x854E, 0x8BBC, 0x8553, 0xFB9A, 0x8555, 0xE543, 0x8557, 0x9599, 0x8558, 0xE4FB, 0x8559, 0xFB9B, + 0x855A, 0xE4D4, 0x8563, 0xE4FA, 0x8568, 0x986E, 0x8569, 0x93A0, 0x856A, 0x9593, 0x856B, 0xFB9C, 0x856D, 0xE54A, 0x8577, 0xE550, + 0x857E, 0xE551, 0x8580, 0xE544, 0x8584, 0x9496, 0x8587, 0xE54E, 0x8588, 0xE546, 0x858A, 0xE548, 0x8590, 0xE552, 0x8591, 0xE547, + 0x8594, 0xE54B, 0x8597, 0x8992, 0x8599, 0x93E3, 0x859B, 0xE54C, 0x859C, 0xE54F, 0x85A4, 0xE545, 0x85A6, 0x9145, 0x85A8, 0xE549, + 0x85A9, 0x8E46, 0x85AA, 0x9064, 0x85AB, 0x8C4F, 0x85AC, 0x96F2, 0x85AE, 0x96F7, 0x85AF, 0x8F92, 0x85B0, 0xFB9E, 0x85B9, 0xE556, + 0x85BA, 0xE554, 0x85C1, 0x986D, 0x85C9, 0xE553, 0x85CD, 0x9795, 0x85CF, 0xE555, 0x85D0, 0xE557, 0x85D5, 0xE558, 0x85DC, 0xE55B, + 0x85DD, 0xE559, 0x85E4, 0x93A1, 0x85E5, 0xE55A, 0x85E9, 0x94CB, 0x85EA, 0xE54D, 0x85F7, 0x8F93, 0x85F9, 0xE55C, 0x85FA, 0xE561, + 0x85FB, 0x9194, 0x85FE, 0xE560, 0x8602, 0xE541, 0x8606, 0xE562, 0x8607, 0x9168, 0x860A, 0xE55D, 0x860B, 0xE55F, 0x8613, 0xE55E, + 0x8616, 0x9F50, 0x8617, 0x9F41, 0x861A, 0xE564, 0x8622, 0xE563, 0x862D, 0x9796, 0x862F, 0xE1BA, 0x8630, 0xE565, 0x863F, 0xE566, + 0x864D, 0xE567, 0x864E, 0x8CD5, 0x8650, 0x8B73, 0x8654, 0xE569, 0x8655, 0x997C, 0x865A, 0x8B95, 0x865C, 0x97B8, 0x865E, 0x8BF1, + 0x865F, 0xE56A, 0x8667, 0xE56B, 0x866B, 0x928E, 0x8671, 0xE56C, 0x8679, 0x93F8, 0x867B, 0x88B8, 0x868A, 0x89E1, 0x868B, 0xE571, + 0x868C, 0xE572, 0x8693, 0xE56D, 0x8695, 0x8E5C, 0x86A3, 0xE56E, 0x86A4, 0x9461, 0x86A9, 0xE56F, 0x86AA, 0xE570, 0x86AB, 0xE57A, + 0x86AF, 0xE574, 0x86B0, 0xE577, 0x86B6, 0xE573, 0x86C4, 0xE575, 0x86C6, 0xE576, 0x86C7, 0x8ED6, 0x86C9, 0xE578, 0x86CB, 0x9260, + 0x86CD, 0x8C75, 0x86CE, 0x8A61, 0x86D4, 0xE57B, 0x86D9, 0x8A5E, 0x86DB, 0xE581, 0x86DE, 0xE57C, 0x86DF, 0xE580, 0x86E4, 0x94B8, + 0x86E9, 0xE57D, 0x86EC, 0xE57E, 0x86ED, 0x9567, 0x86EE, 0x94D8, 0x86EF, 0xE582, 0x86F8, 0x91FB, 0x86F9, 0xE58C, 0x86FB, 0xE588, + 0x86FE, 0x89E9, 0x8700, 0xE586, 0x8702, 0x9649, 0x8703, 0xE587, 0x8706, 0xE584, 0x8708, 0xE585, 0x8709, 0xE58A, 0x870A, 0xE58D, + 0x870D, 0xE58B, 0x8711, 0xE589, 0x8712, 0xE583, 0x8718, 0x9277, 0x871A, 0xE594, 0x871C, 0x96A8, 0x8725, 0xE592, 0x8729, 0xE593, + 0x8734, 0xE58E, 0x8737, 0xE590, 0x873B, 0xE591, 0x873F, 0xE58F, 0x8749, 0x90E4, 0x874B, 0x9858, 0x874C, 0xE598, 0x874E, 0xE599, + 0x8753, 0xE59F, 0x8755, 0x9049, 0x8757, 0xE59B, 0x8759, 0xE59E, 0x875F, 0xE596, 0x8760, 0xE595, 0x8763, 0xE5A0, 0x8766, 0x89DA, + 0x8768, 0xE59C, 0x876A, 0xE5A1, 0x876E, 0xE59D, 0x8774, 0xE59A, 0x8776, 0x92B1, 0x8778, 0xE597, 0x877F, 0x9488, 0x8782, 0xE5A5, + 0x878D, 0x975A, 0x879F, 0xE5A4, 0x87A2, 0xE5A3, 0x87AB, 0xE5AC, 0x87AF, 0xE5A6, 0x87B3, 0xE5AE, 0x87BA, 0x9786, 0x87BB, 0xE5B1, + 0x87BD, 0xE5A8, 0x87C0, 0xE5A9, 0x87C4, 0xE5AD, 0x87C6, 0xE5B0, 0x87C7, 0xE5AF, 0x87CB, 0xE5A7, 0x87D0, 0xE5AA, 0x87D2, 0xE5BB, + 0x87E0, 0xE5B4, 0x87EF, 0xE5B2, 0x87F2, 0xE5B3, 0x87F6, 0xE5B8, 0x87F7, 0xE5B9, 0x87F9, 0x8A49, 0x87FB, 0x8B61, 0x87FE, 0xE5B7, + 0x8805, 0xE5A2, 0x8807, 0xFBA1, 0x880D, 0xE5B6, 0x880E, 0xE5BA, 0x880F, 0xE5B5, 0x8811, 0xE5BC, 0x8815, 0xE5BE, 0x8816, 0xE5BD, + 0x8821, 0xE5C0, 0x8822, 0xE5BF, 0x8823, 0xE579, 0x8827, 0xE5C4, 0x8831, 0xE5C1, 0x8836, 0xE5C2, 0x8839, 0xE5C3, 0x883B, 0xE5C5, + 0x8840, 0x8C8C, 0x8842, 0xE5C7, 0x8844, 0xE5C6, 0x8846, 0x8F4F, 0x884C, 0x8D73, 0x884D, 0x9FA5, 0x8852, 0xE5C8, 0x8853, 0x8F70, + 0x8857, 0x8A58, 0x8859, 0xE5C9, 0x885B, 0x8971, 0x885D, 0x8FD5, 0x885E, 0xE5CA, 0x8861, 0x8D74, 0x8862, 0xE5CB, 0x8863, 0x88DF, + 0x8868, 0x955C, 0x886B, 0xE5CC, 0x8870, 0x908A, 0x8872, 0xE5D3, 0x8875, 0xE5D0, 0x8877, 0x928F, 0x887D, 0xE5D1, 0x887E, 0xE5CE, + 0x887F, 0x8BDC, 0x8881, 0xE5CD, 0x8882, 0xE5D4, 0x8888, 0x8C55, 0x888B, 0x91DC, 0x888D, 0xE5DA, 0x8892, 0xE5D6, 0x8896, 0x91B3, + 0x8897, 0xE5D5, 0x8899, 0xE5D8, 0x889E, 0xE5CF, 0x88A2, 0xE5D9, 0x88A4, 0xE5DB, 0x88AB, 0x94ED, 0x88AE, 0xE5D7, 0x88B0, 0xE5DC, + 0x88B1, 0xE5DE, 0x88B4, 0x8CD1, 0x88B5, 0xE5D2, 0x88B7, 0x88BF, 0x88BF, 0xE5DD, 0x88C1, 0x8DD9, 0x88C2, 0x97F4, 0x88C3, 0xE5DF, + 0x88C4, 0xE5E0, 0x88C5, 0x9195, 0x88CF, 0x97A0, 0x88D4, 0xE5E1, 0x88D5, 0x9754, 0x88D8, 0xE5E2, 0x88D9, 0xE5E3, 0x88DC, 0x95E2, + 0x88DD, 0xE5E4, 0x88DF, 0x8DBE, 0x88E1, 0x97A1, 0x88E8, 0xE5E9, 0x88F2, 0xE5EA, 0x88F3, 0x8FD6, 0x88F4, 0xE5E8, 0x88F5, 0xFBA2, + 0x88F8, 0x9787, 0x88F9, 0xE5E5, 0x88FC, 0xE5E7, 0x88FD, 0x90BB, 0x88FE, 0x909E, 0x8902, 0xE5E6, 0x8904, 0xE5EB, 0x8907, 0x95A1, + 0x890A, 0xE5ED, 0x890C, 0xE5EC, 0x8910, 0x8A8C, 0x8912, 0x964A, 0x8913, 0xE5EE, 0x891C, 0xFA5D, 0x891D, 0xE5FA, 0x891E, 0xE5F0, + 0x8925, 0xE5F1, 0x892A, 0xE5F2, 0x892B, 0xE5F3, 0x8936, 0xE5F7, 0x8938, 0xE5F8, 0x893B, 0xE5F6, 0x8941, 0xE5F4, 0x8943, 0xE5EF, + 0x8944, 0xE5F5, 0x894C, 0xE5F9, 0x894D, 0xE8B5, 0x8956, 0x89A6, 0x895E, 0xE5FC, 0x895F, 0x8BDD, 0x8960, 0xE5FB, 0x8964, 0xE641, + 0x8966, 0xE640, 0x896A, 0xE643, 0x896D, 0xE642, 0x896F, 0xE644, 0x8972, 0x8F50, 0x8974, 0xE645, 0x8977, 0xE646, 0x897E, 0xE647, + 0x897F, 0x90BC, 0x8981, 0x9776, 0x8983, 0xE648, 0x8986, 0x95A2, 0x8987, 0x9465, 0x8988, 0xE649, 0x898A, 0xE64A, 0x898B, 0x8CA9, + 0x898F, 0x8B4B, 0x8993, 0xE64B, 0x8996, 0x8E8B, 0x8997, 0x9460, 0x8998, 0xE64C, 0x899A, 0x8A6F, 0x89A1, 0xE64D, 0x89A6, 0xE64F, + 0x89A7, 0x9797, 0x89A9, 0xE64E, 0x89AA, 0x9065, 0x89AC, 0xE650, 0x89AF, 0xE651, 0x89B2, 0xE652, 0x89B3, 0x8ACF, 0x89BA, 0xE653, + 0x89BD, 0xE654, 0x89BF, 0xE655, 0x89C0, 0xE656, 0x89D2, 0x8A70, 0x89DA, 0xE657, 0x89DC, 0xE658, 0x89DD, 0xE659, 0x89E3, 0x89F0, + 0x89E6, 0x9047, 0x89E7, 0xE65A, 0x89F4, 0xE65B, 0x89F8, 0xE65C, 0x8A00, 0x8CBE, 0x8A02, 0x92F9, 0x8A03, 0xE65D, 0x8A08, 0x8C76, + 0x8A0A, 0x9075, 0x8A0C, 0xE660, 0x8A0E, 0x93A2, 0x8A10, 0xE65F, 0x8A12, 0xFBA3, 0x8A13, 0x8C50, 0x8A16, 0xE65E, 0x8A17, 0x91F5, + 0x8A18, 0x8B4C, 0x8A1B, 0xE661, 0x8A1D, 0xE662, 0x8A1F, 0x8FD7, 0x8A23, 0x8C8D, 0x8A25, 0xE663, 0x8A2A, 0x964B, 0x8A2D, 0x90DD, + 0x8A31, 0x8B96, 0x8A33, 0x96F3, 0x8A34, 0x9169, 0x8A36, 0xE664, 0x8A37, 0xFBA4, 0x8A3A, 0x9066, 0x8A3B, 0x9290, 0x8A3C, 0x8FD8, + 0x8A41, 0xE665, 0x8A46, 0xE668, 0x8A48, 0xE669, 0x8A50, 0x8DBC, 0x8A51, 0x91C0, 0x8A52, 0xE667, 0x8A54, 0x8FD9, 0x8A55, 0x955D, + 0x8A5B, 0xE666, 0x8A5E, 0x8E8C, 0x8A60, 0x8972, 0x8A62, 0xE66D, 0x8A63, 0x8C77, 0x8A66, 0x8E8E, 0x8A69, 0x8E8D, 0x8A6B, 0x986C, + 0x8A6C, 0xE66C, 0x8A6D, 0xE66B, 0x8A6E, 0x9146, 0x8A70, 0x8B6C, 0x8A71, 0x9862, 0x8A72, 0x8A59, 0x8A73, 0x8FDA, 0x8A79, 0xFBA5, + 0x8A7C, 0xE66A, 0x8A82, 0xE66F, 0x8A84, 0xE670, 0x8A85, 0xE66E, 0x8A87, 0x8CD6, 0x8A89, 0x975F, 0x8A8C, 0x8E8F, 0x8A8D, 0x9446, + 0x8A91, 0xE673, 0x8A93, 0x90BE, 0x8A95, 0x9261, 0x8A98, 0x9755, 0x8A9A, 0xE676, 0x8A9E, 0x8CEA, 0x8AA0, 0x90BD, 0x8AA1, 0xE672, + 0x8AA3, 0xE677, 0x8AA4, 0x8CEB, 0x8AA5, 0xE674, 0x8AA6, 0xE675, 0x8AA7, 0xFBA6, 0x8AA8, 0xE671, 0x8AAC, 0x90E0, 0x8AAD, 0x93C7, + 0x8AB0, 0x924E, 0x8AB2, 0x89DB, 0x8AB9, 0x94EE, 0x8ABC, 0x8B62, 0x8ABE, 0xFBA7, 0x8ABF, 0x92B2, 0x8AC2, 0xE67A, 0x8AC4, 0xE678, + 0x8AC7, 0x926B, 0x8ACB, 0x90BF, 0x8ACC, 0x8AD0, 0x8ACD, 0xE679, 0x8ACF, 0x907A, 0x8AD2, 0x97C8, 0x8AD6, 0x985F, 0x8ADA, 0xE67B, + 0x8ADB, 0xE687, 0x8ADC, 0x92B3, 0x8ADE, 0xE686, 0x8ADF, 0xFBA8, 0x8AE0, 0xE683, 0x8AE1, 0xE68B, 0x8AE2, 0xE684, 0x8AE4, 0xE680, + 0x8AE6, 0x92FA, 0x8AE7, 0xE67E, 0x8AEB, 0xE67C, 0x8AED, 0x9740, 0x8AEE, 0x8E90, 0x8AF1, 0xE681, 0x8AF3, 0xE67D, 0x8AF6, 0xFBAA, + 0x8AF7, 0xE685, 0x8AF8, 0x8F94, 0x8AFA, 0x8CBF, 0x8AFE, 0x91F8, 0x8B00, 0x9664, 0x8B01, 0x8979, 0x8B02, 0x88E0, 0x8B04, 0x93A3, + 0x8B07, 0xE689, 0x8B0C, 0xE688, 0x8B0E, 0x93E4, 0x8B10, 0xE68D, 0x8B14, 0xE682, 0x8B16, 0xE68C, 0x8B17, 0xE68E, 0x8B19, 0x8CAA, + 0x8B1A, 0xE68A, 0x8B1B, 0x8D75, 0x8B1D, 0x8ED3, 0x8B20, 0xE68F, 0x8B21, 0x9777, 0x8B26, 0xE692, 0x8B28, 0xE695, 0x8B2B, 0xE693, + 0x8B2C, 0x9554, 0x8B33, 0xE690, 0x8B39, 0x8BDE, 0x8B3E, 0xE694, 0x8B41, 0xE696, 0x8B49, 0xE69A, 0x8B4C, 0xE697, 0x8B4E, 0xE699, + 0x8B4F, 0xE698, 0x8B53, 0xFBAB, 0x8B56, 0xE69B, 0x8B58, 0x8EAF, 0x8B5A, 0xE69D, 0x8B5B, 0xE69C, 0x8B5C, 0x9588, 0x8B5F, 0xE69F, + 0x8B66, 0x8C78, 0x8B6B, 0xE69E, 0x8B6C, 0xE6A0, 0x8B6F, 0xE6A1, 0x8B70, 0x8B63, 0x8B71, 0xE3BF, 0x8B72, 0x8FF7, 0x8B74, 0xE6A2, + 0x8B77, 0x8CEC, 0x8B7D, 0xE6A3, 0x8B7F, 0xFBAC, 0x8B80, 0xE6A4, 0x8B83, 0x8E5D, 0x8B8A, 0x9DCC, 0x8B8C, 0xE6A5, 0x8B8E, 0xE6A6, + 0x8B90, 0x8F51, 0x8B92, 0xE6A7, 0x8B93, 0xE6A8, 0x8B96, 0xE6A9, 0x8B99, 0xE6AA, 0x8B9A, 0xE6AB, 0x8C37, 0x924A, 0x8C3A, 0xE6AC, + 0x8C3F, 0xE6AE, 0x8C41, 0xE6AD, 0x8C46, 0x93A4, 0x8C48, 0xE6AF, 0x8C4A, 0x964C, 0x8C4C, 0xE6B0, 0x8C4E, 0xE6B1, 0x8C50, 0xE6B2, + 0x8C55, 0xE6B3, 0x8C5A, 0x93D8, 0x8C61, 0x8FDB, 0x8C62, 0xE6B4, 0x8C6A, 0x8D8B, 0x8C6B, 0x98AC, 0x8C6C, 0xE6B5, 0x8C78, 0xE6B6, + 0x8C79, 0x955E, 0x8C7A, 0xE6B7, 0x8C7C, 0xE6BF, 0x8C82, 0xE6B8, 0x8C85, 0xE6BA, 0x8C89, 0xE6B9, 0x8C8A, 0xE6BB, 0x8C8C, 0x9665, + 0x8C8D, 0xE6BC, 0x8C8E, 0xE6BD, 0x8C94, 0xE6BE, 0x8C98, 0xE6C0, 0x8C9D, 0x8A4C, 0x8C9E, 0x92E5, 0x8CA0, 0x9589, 0x8CA1, 0x8DE0, + 0x8CA2, 0x8D76, 0x8CA7, 0x956E, 0x8CA8, 0x89DD, 0x8CA9, 0x94CC, 0x8CAA, 0xE6C3, 0x8CAB, 0x8AD1, 0x8CAC, 0x90D3, 0x8CAD, 0xE6C2, + 0x8CAE, 0xE6C7, 0x8CAF, 0x9299, 0x8CB0, 0x96E1, 0x8CB2, 0xE6C5, 0x8CB3, 0xE6C6, 0x8CB4, 0x8B4D, 0x8CB6, 0xE6C8, 0x8CB7, 0x9483, + 0x8CB8, 0x91DD, 0x8CBB, 0x94EF, 0x8CBC, 0x935C, 0x8CBD, 0xE6C4, 0x8CBF, 0x9666, 0x8CC0, 0x89EA, 0x8CC1, 0xE6CA, 0x8CC2, 0x9847, + 0x8CC3, 0x92C0, 0x8CC4, 0x9864, 0x8CC7, 0x8E91, 0x8CC8, 0xE6C9, 0x8CCA, 0x91AF, 0x8CCD, 0xE6DA, 0x8CCE, 0x9147, 0x8CD1, 0x93F6, + 0x8CD3, 0x956F, 0x8CDA, 0xE6CD, 0x8CDB, 0x8E5E, 0x8CDC, 0x8E92, 0x8CDE, 0x8FDC, 0x8CE0, 0x9485, 0x8CE2, 0x8CAB, 0x8CE3, 0xE6CC, + 0x8CE4, 0xE6CB, 0x8CE6, 0x958A, 0x8CEA, 0x8EBF, 0x8CED, 0x9371, 0x8CF0, 0xFBAD, 0x8CF4, 0xFBAE, 0x8CFA, 0xE6CF, 0x8CFB, 0xE6D0, + 0x8CFC, 0x8D77, 0x8CFD, 0xE6CE, 0x8D04, 0xE6D1, 0x8D05, 0xE6D2, 0x8D07, 0xE6D4, 0x8D08, 0x91A1, 0x8D0A, 0xE6D3, 0x8D0B, 0x8AE4, + 0x8D0D, 0xE6D6, 0x8D0F, 0xE6D5, 0x8D10, 0xE6D7, 0x8D12, 0xFBAF, 0x8D13, 0xE6D9, 0x8D14, 0xE6DB, 0x8D16, 0xE6DC, 0x8D64, 0x90D4, + 0x8D66, 0x8ECD, 0x8D67, 0xE6DD, 0x8D6B, 0x8A71, 0x8D6D, 0xE6DE, 0x8D70, 0x9196, 0x8D71, 0xE6DF, 0x8D73, 0xE6E0, 0x8D74, 0x958B, + 0x8D76, 0xFBB0, 0x8D77, 0x8B4E, 0x8D81, 0xE6E1, 0x8D85, 0x92B4, 0x8D8A, 0x897A, 0x8D99, 0xE6E2, 0x8DA3, 0x8EEF, 0x8DA8, 0x9096, + 0x8DB3, 0x91AB, 0x8DBA, 0xE6E5, 0x8DBE, 0xE6E4, 0x8DC2, 0xE6E3, 0x8DCB, 0xE6EB, 0x8DCC, 0xE6E9, 0x8DCF, 0xE6E6, 0x8DD6, 0xE6E8, + 0x8DDA, 0xE6E7, 0x8DDB, 0xE6EA, 0x8DDD, 0x8B97, 0x8DDF, 0xE6EE, 0x8DE1, 0x90D5, 0x8DE3, 0xE6EF, 0x8DE8, 0x8CD7, 0x8DEA, 0xE6EC, + 0x8DEB, 0xE6ED, 0x8DEF, 0x9848, 0x8DF3, 0x92B5, 0x8DF5, 0x9148, 0x8DFC, 0xE6F0, 0x8DFF, 0xE6F3, 0x8E08, 0xE6F1, 0x8E09, 0xE6F2, + 0x8E0A, 0x9778, 0x8E0F, 0x93A5, 0x8E10, 0xE6F6, 0x8E1D, 0xE6F4, 0x8E1E, 0xE6F5, 0x8E1F, 0xE6F7, 0x8E2A, 0xE748, 0x8E30, 0xE6FA, + 0x8E34, 0xE6FB, 0x8E35, 0xE6F9, 0x8E42, 0xE6F8, 0x8E44, 0x92FB, 0x8E47, 0xE740, 0x8E48, 0xE744, 0x8E49, 0xE741, 0x8E4A, 0xE6FC, + 0x8E4C, 0xE742, 0x8E50, 0xE743, 0x8E55, 0xE74A, 0x8E59, 0xE745, 0x8E5F, 0x90D6, 0x8E60, 0xE747, 0x8E63, 0xE749, 0x8E64, 0xE746, + 0x8E72, 0xE74C, 0x8E74, 0x8F52, 0x8E76, 0xE74B, 0x8E7C, 0xE74D, 0x8E81, 0xE74E, 0x8E84, 0xE751, 0x8E85, 0xE750, 0x8E87, 0xE74F, + 0x8E8A, 0xE753, 0x8E8B, 0xE752, 0x8E8D, 0x96F4, 0x8E91, 0xE755, 0x8E93, 0xE754, 0x8E94, 0xE756, 0x8E99, 0xE757, 0x8EA1, 0xE759, + 0x8EAA, 0xE758, 0x8EAB, 0x9067, 0x8EAC, 0xE75A, 0x8EAF, 0x8BEB, 0x8EB0, 0xE75B, 0x8EB1, 0xE75D, 0x8EBE, 0xE75E, 0x8EC5, 0xE75F, + 0x8EC6, 0xE75C, 0x8EC8, 0xE760, 0x8ECA, 0x8ED4, 0x8ECB, 0xE761, 0x8ECC, 0x8B4F, 0x8ECD, 0x8C52, 0x8ECF, 0xFBB2, 0x8ED2, 0x8CAC, + 0x8EDB, 0xE762, 0x8EDF, 0x93EE, 0x8EE2, 0x935D, 0x8EE3, 0xE763, 0x8EEB, 0xE766, 0x8EF8, 0x8EB2, 0x8EFB, 0xE765, 0x8EFC, 0xE764, + 0x8EFD, 0x8C79, 0x8EFE, 0xE767, 0x8F03, 0x8A72, 0x8F05, 0xE769, 0x8F09, 0x8DDA, 0x8F0A, 0xE768, 0x8F0C, 0xE771, 0x8F12, 0xE76B, + 0x8F13, 0xE76D, 0x8F14, 0x95E3, 0x8F15, 0xE76A, 0x8F19, 0xE76C, 0x8F1B, 0xE770, 0x8F1C, 0xE76E, 0x8F1D, 0x8B50, 0x8F1F, 0xE76F, + 0x8F26, 0xE772, 0x8F29, 0x9479, 0x8F2A, 0x97D6, 0x8F2F, 0x8F53, 0x8F33, 0xE773, 0x8F38, 0x9741, 0x8F39, 0xE775, 0x8F3B, 0xE774, + 0x8F3E, 0xE778, 0x8F3F, 0x9760, 0x8F42, 0xE777, 0x8F44, 0x8A8D, 0x8F45, 0xE776, 0x8F46, 0xE77B, 0x8F49, 0xE77A, 0x8F4C, 0xE779, + 0x8F4D, 0x9351, 0x8F4E, 0xE77C, 0x8F57, 0xE77D, 0x8F5C, 0xE77E, 0x8F5F, 0x8D8C, 0x8F61, 0x8C44, 0x8F62, 0xE780, 0x8F63, 0xE781, + 0x8F64, 0xE782, 0x8F9B, 0x9068, 0x8F9C, 0xE783, 0x8F9E, 0x8EAB, 0x8F9F, 0xE784, 0x8FA3, 0xE785, 0x8FA7, 0x999F, 0x8FA8, 0x999E, + 0x8FAD, 0xE786, 0x8FAE, 0xE390, 0x8FAF, 0xE787, 0x8FB0, 0x9243, 0x8FB1, 0x904A, 0x8FB2, 0x945F, 0x8FB7, 0xE788, 0x8FBA, 0x95D3, + 0x8FBB, 0x92D2, 0x8FBC, 0x8D9E, 0x8FBF, 0x9248, 0x8FC2, 0x8949, 0x8FC4, 0x9698, 0x8FC5, 0x9076, 0x8FCE, 0x8C7D, 0x8FD1, 0x8BDF, + 0x8FD4, 0x95D4, 0x8FDA, 0xE789, 0x8FE2, 0xE78B, 0x8FE5, 0xE78A, 0x8FE6, 0x89DE, 0x8FE9, 0x93F4, 0x8FEA, 0xE78C, 0x8FEB, 0x9497, + 0x8FED, 0x9352, 0x8FEF, 0xE78D, 0x8FF0, 0x8F71, 0x8FF4, 0xE78F, 0x8FF7, 0x96C0, 0x8FF8, 0xE79E, 0x8FF9, 0xE791, 0x8FFA, 0xE792, + 0x8FFD, 0x92C7, 0x9000, 0x91DE, 0x9001, 0x9197, 0x9003, 0x93A6, 0x9005, 0xE790, 0x9006, 0x8B74, 0x900B, 0xE799, 0x900D, 0xE796, + 0x900E, 0xE7A3, 0x900F, 0x93A7, 0x9010, 0x9280, 0x9011, 0xE793, 0x9013, 0x92FC, 0x9014, 0x9372, 0x9015, 0xE794, 0x9016, 0xE798, + 0x9017, 0x9080, 0x9019, 0x9487, 0x901A, 0x92CA, 0x901D, 0x90C0, 0x901E, 0xE797, 0x901F, 0x91AC, 0x9020, 0x91A2, 0x9021, 0xE795, + 0x9022, 0x88A7, 0x9023, 0x9841, 0x9027, 0xE79A, 0x902E, 0x91DF, 0x9031, 0x8F54, 0x9032, 0x9069, 0x9035, 0xE79C, 0x9036, 0xE79B, + 0x9038, 0x88ED, 0x9039, 0xE79D, 0x903C, 0x954E, 0x903E, 0xE7A5, 0x9041, 0x93D9, 0x9042, 0x908B, 0x9045, 0x9278, 0x9047, 0x8BF6, + 0x9049, 0xE7A4, 0x904A, 0x9756, 0x904B, 0x895E, 0x904D, 0x95D5, 0x904E, 0x89DF, 0x904F, 0xE79F, 0x9050, 0xE7A0, 0x9051, 0xE7A1, + 0x9052, 0xE7A2, 0x9053, 0x93B9, 0x9054, 0x9242, 0x9055, 0x88E1, 0x9056, 0xE7A6, 0x9058, 0xE7A7, 0x9059, 0xEAA1, 0x905C, 0x91BB, + 0x905E, 0xE7A8, 0x9060, 0x8993, 0x9061, 0x916B, 0x9063, 0x8CAD, 0x9065, 0x9779, 0x9067, 0xFBB5, 0x9068, 0xE7A9, 0x9069, 0x934B, + 0x906D, 0x9198, 0x906E, 0x8ED5, 0x906F, 0xE7AA, 0x9072, 0xE7AD, 0x9075, 0x8F85, 0x9076, 0xE7AB, 0x9077, 0x914A, 0x9078, 0x9149, + 0x907A, 0x88E2, 0x907C, 0x97C9, 0x907D, 0xE7AF, 0x907F, 0x94F0, 0x9080, 0xE7B1, 0x9081, 0xE7B0, 0x9082, 0xE7AE, 0x9083, 0xE284, + 0x9084, 0x8AD2, 0x9087, 0xE78E, 0x9089, 0xE7B3, 0x908A, 0xE7B2, 0x908F, 0xE7B4, 0x9091, 0x9757, 0x90A3, 0x93DF, 0x90A6, 0x964D, + 0x90A8, 0xE7B5, 0x90AA, 0x8ED7, 0x90AF, 0xE7B6, 0x90B1, 0xE7B7, 0x90B5, 0xE7B8, 0x90B8, 0x9340, 0x90C1, 0x88E8, 0x90CA, 0x8D78, + 0x90CE, 0x9859, 0x90DB, 0xE7BC, 0x90DE, 0xFBB6, 0x90E1, 0x8C53, 0x90E2, 0xE7B9, 0x90E4, 0xE7BA, 0x90E8, 0x9594, 0x90ED, 0x8A73, + 0x90F5, 0x9758, 0x90F7, 0x8BBD, 0x90FD, 0x9373, 0x9102, 0xE7BD, 0x9112, 0xE7BE, 0x9115, 0xFBB8, 0x9119, 0xE7BF, 0x9127, 0xFBB9, + 0x912D, 0x9341, 0x9130, 0xE7C1, 0x9132, 0xE7C0, 0x9149, 0x93D1, 0x914A, 0xE7C2, 0x914B, 0x8F55, 0x914C, 0x8EDE, 0x914D, 0x947A, + 0x914E, 0x9291, 0x9152, 0x8EF0, 0x9154, 0x908C, 0x9156, 0xE7C3, 0x9158, 0xE7C4, 0x9162, 0x907C, 0x9163, 0xE7C5, 0x9165, 0xE7C6, + 0x9169, 0xE7C7, 0x916A, 0x978F, 0x916C, 0x8F56, 0x9172, 0xE7C9, 0x9173, 0xE7C8, 0x9175, 0x8D79, 0x9177, 0x8D93, 0x9178, 0x8E5F, + 0x9182, 0xE7CC, 0x9187, 0x8F86, 0x9189, 0xE7CB, 0x918B, 0xE7CA, 0x918D, 0x91E7, 0x9190, 0x8CED, 0x9192, 0x90C1, 0x9197, 0x94AE, + 0x919C, 0x8F58, 0x91A2, 0xE7CD, 0x91A4, 0x8FDD, 0x91AA, 0xE7D0, 0x91AB, 0xE7CE, 0x91AF, 0xE7CF, 0x91B4, 0xE7D2, 0x91B5, 0xE7D1, + 0x91B8, 0x8FF8, 0x91BA, 0xE7D3, 0x91C0, 0xE7D4, 0x91C1, 0xE7D5, 0x91C6, 0x94CE, 0x91C7, 0x8DD1, 0x91C8, 0x8EDF, 0x91C9, 0xE7D6, + 0x91CB, 0xE7D7, 0x91CC, 0x97A2, 0x91CD, 0x8F64, 0x91CE, 0x96EC, 0x91CF, 0x97CA, 0x91D0, 0xE7D8, 0x91D1, 0x8BE0, 0x91D6, 0xE7D9, + 0x91D7, 0xFBBB, 0x91D8, 0x9342, 0x91DA, 0xFBBA, 0x91DB, 0xE7DC, 0x91DC, 0x8A98, 0x91DD, 0x906A, 0x91DE, 0xFBBC, 0x91DF, 0xE7DA, + 0x91E1, 0xE7DB, 0x91E3, 0x92DE, 0x91E4, 0xFBBF, 0x91E5, 0xFBC0, 0x91E6, 0x9674, 0x91E7, 0x8BFA, 0x91ED, 0xFBBD, 0x91EE, 0xFBBE, + 0x91F5, 0xE7DE, 0x91F6, 0xE7DF, 0x91FC, 0xE7DD, 0x91FF, 0xE7E1, 0x9206, 0xFBC1, 0x920A, 0xFBC3, 0x920D, 0x93DD, 0x920E, 0x8A62, + 0x9210, 0xFBC2, 0x9211, 0xE7E5, 0x9214, 0xE7E2, 0x9215, 0xE7E4, 0x921E, 0xE7E0, 0x9229, 0xE86E, 0x922C, 0xE7E3, 0x9234, 0x97E9, + 0x9237, 0x8CD8, 0x9239, 0xFBCA, 0x923A, 0xFBC4, 0x923C, 0xFBC6, 0x923F, 0xE7ED, 0x9240, 0xFBC5, 0x9244, 0x9353, 0x9245, 0xE7E8, + 0x9248, 0xE7EB, 0x9249, 0xE7E9, 0x924B, 0xE7EE, 0x924E, 0xFBC7, 0x9250, 0xE7EF, 0x9251, 0xFBC9, 0x9257, 0xE7E7, 0x9259, 0xFBC8, + 0x925A, 0xE7F4, 0x925B, 0x8994, 0x925E, 0xE7E6, 0x9262, 0x94AB, 0x9264, 0xE7EA, 0x9266, 0x8FDE, 0x9267, 0xFBCB, 0x9271, 0x8D7A, + 0x9277, 0xFBCD, 0x9278, 0xFBCE, 0x927E, 0x9667, 0x9280, 0x8BE2, 0x9283, 0x8F65, 0x9285, 0x93BA, 0x9288, 0xFA5F, 0x9291, 0x914C, + 0x9293, 0xE7F2, 0x9295, 0xE7EC, 0x9296, 0xE7F1, 0x9298, 0x96C1, 0x929A, 0x92B6, 0x929B, 0xE7F3, 0x929C, 0xE7F0, 0x92A7, 0xFBCC, + 0x92AD, 0x914B, 0x92B7, 0xE7F7, 0x92B9, 0xE7F6, 0x92CF, 0xE7F5, 0x92D0, 0xFBD2, 0x92D2, 0x964E, 0x92D3, 0xFBD6, 0x92D5, 0xFBD4, + 0x92D7, 0xFBD0, 0x92D9, 0xFBD1, 0x92E0, 0xFBD5, 0x92E4, 0x8F9B, 0x92E7, 0xFBCF, 0x92E9, 0xE7F8, 0x92EA, 0x95DD, 0x92ED, 0x8973, + 0x92F2, 0x9565, 0x92F3, 0x9292, 0x92F8, 0x8B98, 0x92F9, 0xFA65, 0x92FA, 0xE7FA, 0x92FB, 0xFBD9, 0x92FC, 0x8D7C, 0x92FF, 0xFBDC, + 0x9302, 0xFBDE, 0x9306, 0x8E4B, 0x930F, 0xE7F9, 0x9310, 0x908D, 0x9318, 0x908E, 0x9319, 0xE840, 0x931A, 0xE842, 0x931D, 0xFBDD, + 0x931E, 0xFBDB, 0x9320, 0x8FF9, 0x9321, 0xFBD8, 0x9322, 0xE841, 0x9323, 0xE843, 0x9325, 0xFBD7, 0x9326, 0x8BD1, 0x9328, 0x9564, + 0x932B, 0x8EE0, 0x932C, 0x9842, 0x932E, 0xE7FC, 0x932F, 0x8DF6, 0x9332, 0x985E, 0x9335, 0xE845, 0x933A, 0xE844, 0x933B, 0xE846, + 0x9344, 0xE7FB, 0x9348, 0xFA5E, 0x934B, 0x93E7, 0x934D, 0x9374, 0x9354, 0x92D5, 0x9356, 0xE84B, 0x9357, 0xFBE0, 0x935B, 0x9262, + 0x935C, 0xE847, 0x9360, 0xE848, 0x936C, 0x8C4C, 0x936E, 0xE84A, 0x9370, 0xFBDF, 0x9375, 0x8CAE, 0x937C, 0xE849, 0x937E, 0x8FDF, + 0x938C, 0x8A99, 0x9394, 0xE84F, 0x9396, 0x8DBD, 0x9397, 0x9199, 0x939A, 0x92C8, 0x93A4, 0xFBE1, 0x93A7, 0x8A5A, 0x93AC, 0xE84D, + 0x93AD, 0xE84E, 0x93AE, 0x92C1, 0x93B0, 0xE84C, 0x93B9, 0xE850, 0x93C3, 0xE856, 0x93C6, 0xFBE2, 0x93C8, 0xE859, 0x93D0, 0xE858, + 0x93D1, 0x934C, 0x93D6, 0xE851, 0x93D7, 0xE852, 0x93D8, 0xE855, 0x93DD, 0xE857, 0x93DE, 0xFBE3, 0x93E1, 0x8BBE, 0x93E4, 0xE85A, + 0x93E5, 0xE854, 0x93E8, 0xE853, 0x93F8, 0xFBE4, 0x9403, 0xE85E, 0x9407, 0xE85F, 0x9410, 0xE860, 0x9413, 0xE85D, 0x9414, 0xE85C, + 0x9418, 0x8FE0, 0x9419, 0x93A8, 0x941A, 0xE85B, 0x9421, 0xE864, 0x942B, 0xE862, 0x9431, 0xFBE5, 0x9435, 0xE863, 0x9436, 0xE861, + 0x9438, 0x91F6, 0x943A, 0xE865, 0x9441, 0xE866, 0x9444, 0xE868, 0x9445, 0xFBE6, 0x9448, 0xFBE7, 0x9451, 0x8AD3, 0x9452, 0xE867, + 0x9453, 0x96F8, 0x945A, 0xE873, 0x945B, 0xE869, 0x945E, 0xE86C, 0x9460, 0xE86A, 0x9462, 0xE86B, 0x946A, 0xE86D, 0x9470, 0xE86F, + 0x9475, 0xE870, 0x9477, 0xE871, 0x947C, 0xE874, 0x947D, 0xE872, 0x947E, 0xE875, 0x947F, 0xE877, 0x9481, 0xE876, 0x9577, 0x92B7, + 0x9580, 0x96E5, 0x9582, 0xE878, 0x9583, 0x914D, 0x9587, 0xE879, 0x9589, 0x95C2, 0x958A, 0xE87A, 0x958B, 0x8A4A, 0x958F, 0x895B, + 0x9591, 0x8AD5, 0x9592, 0xFBE8, 0x9593, 0x8AD4, 0x9594, 0xE87B, 0x9596, 0xE87C, 0x9598, 0xE87D, 0x9599, 0xE87E, 0x95A0, 0xE880, + 0x95A2, 0x8AD6, 0x95A3, 0x8A74, 0x95A4, 0x8D7D, 0x95A5, 0x94B4, 0x95A7, 0xE882, 0x95A8, 0xE881, 0x95AD, 0xE883, 0x95B2, 0x897B, + 0x95B9, 0xE886, 0x95BB, 0xE885, 0x95BC, 0xE884, 0x95BE, 0xE887, 0x95C3, 0xE88A, 0x95C7, 0x88C5, 0x95CA, 0xE888, 0x95CC, 0xE88C, + 0x95CD, 0xE88B, 0x95D4, 0xE88E, 0x95D5, 0xE88D, 0x95D6, 0xE88F, 0x95D8, 0x93AC, 0x95DC, 0xE890, 0x95E1, 0xE891, 0x95E2, 0xE893, + 0x95E5, 0xE892, 0x961C, 0x958C, 0x9621, 0xE894, 0x9628, 0xE895, 0x962A, 0x8DE3, 0x962E, 0xE896, 0x962F, 0xE897, 0x9632, 0x9668, + 0x963B, 0x916A, 0x963F, 0x88A2, 0x9640, 0x91C9, 0x9642, 0xE898, 0x9644, 0x958D, 0x964B, 0xE89B, 0x964C, 0xE899, 0x964D, 0x8D7E, + 0x964F, 0xE89A, 0x9650, 0x8CC0, 0x965B, 0x95C3, 0x965C, 0xE89D, 0x965D, 0xE89F, 0x965E, 0xE89E, 0x965F, 0xE8A0, 0x9662, 0x8940, + 0x9663, 0x9077, 0x9664, 0x8F9C, 0x9665, 0x8AD7, 0x9666, 0xE8A1, 0x966A, 0x9486, 0x966C, 0xE8A3, 0x9670, 0x8941, 0x9672, 0xE8A2, + 0x9673, 0x92C2, 0x9675, 0x97CB, 0x9676, 0x93A9, 0x9677, 0xE89C, 0x9678, 0x97A4, 0x967A, 0x8CAF, 0x967D, 0x977A, 0x9685, 0x8BF7, + 0x9686, 0x97B2, 0x9688, 0x8C47, 0x968A, 0x91E0, 0x968B, 0xE440, 0x968D, 0xE8A4, 0x968E, 0x8A4B, 0x968F, 0x908F, 0x9694, 0x8A75, + 0x9695, 0xE8A6, 0x9697, 0xE8A7, 0x9698, 0xE8A5, 0x9699, 0x8C84, 0x969B, 0x8DDB, 0x969C, 0x8FE1, 0x969D, 0xFBEB, 0x96A0, 0x8942, + 0x96A3, 0x97D7, 0x96A7, 0xE8A9, 0x96A8, 0xE7AC, 0x96AA, 0xE8A8, 0x96AF, 0xFBEC, 0x96B0, 0xE8AC, 0x96B1, 0xE8AA, 0x96B2, 0xE8AB, + 0x96B4, 0xE8AD, 0x96B6, 0xE8AE, 0x96B7, 0x97EA, 0x96B8, 0xE8AF, 0x96B9, 0xE8B0, 0x96BB, 0x90C7, 0x96BC, 0x94B9, 0x96C0, 0x909D, + 0x96C1, 0x8AE5, 0x96C4, 0x9759, 0x96C5, 0x89EB, 0x96C6, 0x8F57, 0x96C7, 0x8CD9, 0x96C9, 0xE8B3, 0x96CB, 0xE8B2, 0x96CC, 0x8E93, + 0x96CD, 0xE8B4, 0x96CE, 0xE8B1, 0x96D1, 0x8E47, 0x96D5, 0xE8B8, 0x96D6, 0xE5AB, 0x96D9, 0x99D4, 0x96DB, 0x9097, 0x96DC, 0xE8B6, + 0x96E2, 0x97A3, 0x96E3, 0x93EF, 0x96E8, 0x894A, 0x96EA, 0x90E1, 0x96EB, 0x8EB4, 0x96F0, 0x95B5, 0x96F2, 0x895F, 0x96F6, 0x97EB, + 0x96F7, 0x978B, 0x96F9, 0xE8B9, 0x96FB, 0x9364, 0x9700, 0x8EF9, 0x9704, 0xE8BA, 0x9706, 0xE8BB, 0x9707, 0x906B, 0x9708, 0xE8BC, + 0x970A, 0x97EC, 0x970D, 0xE8B7, 0x970E, 0xE8BE, 0x970F, 0xE8C0, 0x9711, 0xE8BF, 0x9713, 0xE8BD, 0x9716, 0xE8C1, 0x9719, 0xE8C2, + 0x971C, 0x919A, 0x971E, 0x89E0, 0x9724, 0xE8C3, 0x9727, 0x96B6, 0x972A, 0xE8C4, 0x9730, 0xE8C5, 0x9732, 0x9849, 0x9733, 0xFBED, + 0x9738, 0x9E50, 0x9739, 0xE8C6, 0x973B, 0xFBEE, 0x973D, 0xE8C7, 0x973E, 0xE8C8, 0x9742, 0xE8CC, 0x9743, 0xFBEF, 0x9744, 0xE8C9, + 0x9746, 0xE8CA, 0x9748, 0xE8CB, 0x9749, 0xE8CD, 0x974D, 0xFBF0, 0x974F, 0xFBF1, 0x9751, 0xFBF2, 0x9752, 0x90C2, 0x9755, 0xFBF3, + 0x9756, 0x96F5, 0x9759, 0x90C3, 0x975C, 0xE8CE, 0x975E, 0x94F1, 0x9760, 0xE8CF, 0x9761, 0xEA72, 0x9762, 0x96CA, 0x9764, 0xE8D0, + 0x9766, 0xE8D1, 0x9768, 0xE8D2, 0x9769, 0x8A76, 0x976B, 0xE8D4, 0x976D, 0x9078, 0x9771, 0xE8D5, 0x9774, 0x8C43, 0x9779, 0xE8D6, + 0x977A, 0xE8DA, 0x977C, 0xE8D8, 0x9781, 0xE8D9, 0x9784, 0x8A93, 0x9785, 0xE8D7, 0x9786, 0xE8DB, 0x978B, 0xE8DC, 0x978D, 0x88C6, + 0x978F, 0xE8DD, 0x9790, 0xE8DE, 0x9798, 0x8FE2, 0x979C, 0xE8DF, 0x97A0, 0x8B66, 0x97A3, 0xE8E2, 0x97A6, 0xE8E1, 0x97A8, 0xE8E0, + 0x97AB, 0xE691, 0x97AD, 0x95DA, 0x97B3, 0xE8E3, 0x97B4, 0xE8E4, 0x97C3, 0xE8E5, 0x97C6, 0xE8E6, 0x97C8, 0xE8E7, 0x97CB, 0xE8E8, + 0x97D3, 0x8AD8, 0x97DC, 0xE8E9, 0x97ED, 0xE8EA, 0x97EE, 0x9442, 0x97F2, 0xE8EC, 0x97F3, 0x89B9, 0x97F5, 0xE8EF, 0x97F6, 0xE8EE, + 0x97FB, 0x8943, 0x97FF, 0x8BBF, 0x9801, 0x95C5, 0x9802, 0x92B8, 0x9803, 0x8DA0, 0x9805, 0x8D80, 0x9806, 0x8F87, 0x9808, 0x907B, + 0x980C, 0xE8F1, 0x980F, 0xE8F0, 0x9810, 0x9761, 0x9811, 0x8AE6, 0x9812, 0x94D0, 0x9813, 0x93DA, 0x9817, 0x909C, 0x9818, 0x97CC, + 0x981A, 0x8C7A, 0x9821, 0xE8F4, 0x9824, 0xE8F3, 0x982C, 0x966A, 0x982D, 0x93AA, 0x9834, 0x896F, 0x9837, 0xE8F5, 0x9838, 0xE8F2, + 0x983B, 0x9570, 0x983C, 0x978A, 0x983D, 0xE8F6, 0x9846, 0xE8F7, 0x984B, 0xE8F9, 0x984C, 0x91E8, 0x984D, 0x8A7A, 0x984E, 0x8A7B, + 0x984F, 0xE8F8, 0x9854, 0x8AE7, 0x9855, 0x8CB0, 0x9857, 0xFBF4, 0x9858, 0x8AE8, 0x985B, 0x935E, 0x985E, 0x97DE, 0x9865, 0xFBF5, + 0x9867, 0x8CDA, 0x986B, 0xE8FA, 0x986F, 0xE8FB, 0x9870, 0xE8FC, 0x9871, 0xE940, 0x9873, 0xE942, 0x9874, 0xE941, 0x98A8, 0x9597, + 0x98AA, 0xE943, 0x98AF, 0xE944, 0x98B1, 0xE945, 0x98B6, 0xE946, 0x98C3, 0xE948, 0x98C4, 0xE947, 0x98C6, 0xE949, 0x98DB, 0x94F2, + 0x98DC, 0xE3CA, 0x98DF, 0x9048, 0x98E2, 0x8B51, 0x98E9, 0xE94A, 0x98EB, 0xE94B, 0x98ED, 0x99AA, 0x98EE, 0x9F5A, 0x98EF, 0x94D1, + 0x98F2, 0x88F9, 0x98F4, 0x88B9, 0x98FC, 0x8E94, 0x98FD, 0x964F, 0x98FE, 0x8FFC, 0x9903, 0xE94C, 0x9905, 0x96DD, 0x9909, 0xE94D, + 0x990A, 0x977B, 0x990C, 0x8961, 0x9910, 0x8E60, 0x9912, 0xE94E, 0x9913, 0x89EC, 0x9914, 0xE94F, 0x9918, 0xE950, 0x991D, 0xE952, + 0x991E, 0xE953, 0x9920, 0xE955, 0x9921, 0xE951, 0x9924, 0xE954, 0x9927, 0xFBF8, 0x9928, 0x8AD9, 0x992C, 0xE956, 0x992E, 0xE957, + 0x993D, 0xE958, 0x993E, 0xE959, 0x9942, 0xE95A, 0x9945, 0xE95C, 0x9949, 0xE95B, 0x994B, 0xE95E, 0x994C, 0xE961, 0x9950, 0xE95D, + 0x9951, 0xE95F, 0x9952, 0xE960, 0x9955, 0xE962, 0x9957, 0x8BC0, 0x9996, 0x8EF1, 0x9997, 0xE963, 0x9998, 0xE964, 0x9999, 0x8D81, + 0x999E, 0xFBFA, 0x99A5, 0xE965, 0x99A8, 0x8A5D, 0x99AC, 0x946E, 0x99AD, 0xE966, 0x99AE, 0xE967, 0x99B3, 0x9279, 0x99B4, 0x93E9, + 0x99BC, 0xE968, 0x99C1, 0x949D, 0x99C4, 0x91CA, 0x99C5, 0x8977, 0x99C6, 0x8BEC, 0x99C8, 0x8BED, 0x99D0, 0x9293, 0x99D1, 0xE96D, + 0x99D2, 0x8BEE, 0x99D5, 0x89ED, 0x99D8, 0xE96C, 0x99DB, 0xE96A, 0x99DD, 0xE96B, 0x99DF, 0xE969, 0x99E2, 0xE977, 0x99ED, 0xE96E, + 0x99EE, 0xE96F, 0x99F1, 0xE970, 0x99F2, 0xE971, 0x99F8, 0xE973, 0x99FB, 0xE972, 0x99FF, 0x8F78, 0x9A01, 0xE974, 0x9A05, 0xE976, + 0x9A0E, 0x8B52, 0x9A0F, 0xE975, 0x9A12, 0x919B, 0x9A13, 0x8CB1, 0x9A19, 0xE978, 0x9A28, 0x91CB, 0x9A2B, 0xE979, 0x9A30, 0x93AB, + 0x9A37, 0xE97A, 0x9A3E, 0xE980, 0x9A40, 0xE97D, 0x9A42, 0xE97C, 0x9A43, 0xE97E, 0x9A45, 0xE97B, 0x9A4D, 0xE982, 0x9A4E, 0xFBFB, + 0x9A55, 0xE981, 0x9A57, 0xE984, 0x9A5A, 0x8BC1, 0x9A5B, 0xE983, 0x9A5F, 0xE985, 0x9A62, 0xE986, 0x9A64, 0xE988, 0x9A65, 0xE987, + 0x9A69, 0xE989, 0x9A6A, 0xE98B, 0x9A6B, 0xE98A, 0x9AA8, 0x8D9C, 0x9AAD, 0xE98C, 0x9AB0, 0xE98D, 0x9AB8, 0x8A5B, 0x9ABC, 0xE98E, + 0x9AC0, 0xE98F, 0x9AC4, 0x9091, 0x9ACF, 0xE990, 0x9AD1, 0xE991, 0x9AD3, 0xE992, 0x9AD4, 0xE993, 0x9AD8, 0x8D82, 0x9AD9, 0xFBFC, + 0x9ADC, 0xFC40, 0x9ADE, 0xE994, 0x9ADF, 0xE995, 0x9AE2, 0xE996, 0x9AE3, 0xE997, 0x9AE6, 0xE998, 0x9AEA, 0x94AF, 0x9AEB, 0xE99A, + 0x9AED, 0x9545, 0x9AEE, 0xE99B, 0x9AEF, 0xE999, 0x9AF1, 0xE99D, 0x9AF4, 0xE99C, 0x9AF7, 0xE99E, 0x9AFB, 0xE99F, 0x9B06, 0xE9A0, + 0x9B18, 0xE9A1, 0x9B1A, 0xE9A2, 0x9B1F, 0xE9A3, 0x9B22, 0xE9A4, 0x9B23, 0xE9A5, 0x9B25, 0xE9A6, 0x9B27, 0xE9A7, 0x9B28, 0xE9A8, + 0x9B29, 0xE9A9, 0x9B2A, 0xE9AA, 0x9B2E, 0xE9AB, 0x9B2F, 0xE9AC, 0x9B31, 0x9F54, 0x9B32, 0xE9AD, 0x9B3B, 0xE2F6, 0x9B3C, 0x8B53, + 0x9B41, 0x8A40, 0x9B42, 0x8DB0, 0x9B43, 0xE9AF, 0x9B44, 0xE9AE, 0x9B45, 0x96A3, 0x9B4D, 0xE9B1, 0x9B4E, 0xE9B2, 0x9B4F, 0xE9B0, + 0x9B51, 0xE9B3, 0x9B54, 0x9682, 0x9B58, 0xE9B4, 0x9B5A, 0x8B9B, 0x9B6F, 0x9844, 0x9B72, 0xFC42, 0x9B74, 0xE9B5, 0x9B75, 0xFC41, + 0x9B83, 0xE9B7, 0x9B8E, 0x88BC, 0x9B8F, 0xFC43, 0x9B91, 0xE9B8, 0x9B92, 0x95A9, 0x9B93, 0xE9B6, 0x9B96, 0xE9B9, 0x9B97, 0xE9BA, + 0x9B9F, 0xE9BB, 0x9BA0, 0xE9BC, 0x9BA8, 0xE9BD, 0x9BAA, 0x968E, 0x9BAB, 0x8E4C, 0x9BAD, 0x8DF8, 0x9BAE, 0x914E, 0x9BB1, 0xFC44, + 0x9BB4, 0xE9BE, 0x9BB9, 0xE9C1, 0x9BBB, 0xFC45, 0x9BC0, 0xE9BF, 0x9BC6, 0xE9C2, 0x9BC9, 0x8CEF, 0x9BCA, 0xE9C0, 0x9BCF, 0xE9C3, + 0x9BD1, 0xE9C4, 0x9BD2, 0xE9C5, 0x9BD4, 0xE9C9, 0x9BD6, 0x8E49, 0x9BDB, 0x91E2, 0x9BE1, 0xE9CA, 0x9BE2, 0xE9C7, 0x9BE3, 0xE9C6, + 0x9BE4, 0xE9C8, 0x9BE8, 0x8C7E, 0x9BF0, 0xE9CE, 0x9BF1, 0xE9CD, 0x9BF2, 0xE9CC, 0x9BF5, 0x88B1, 0x9C00, 0xFC46, 0x9C04, 0xE9D8, + 0x9C06, 0xE9D4, 0x9C08, 0xE9D5, 0x9C09, 0xE9D1, 0x9C0A, 0xE9D7, 0x9C0C, 0xE9D3, 0x9C0D, 0x8A82, 0x9C10, 0x986B, 0x9C12, 0xE9D6, + 0x9C13, 0xE9D2, 0x9C14, 0xE9D0, 0x9C15, 0xE9CF, 0x9C1B, 0xE9DA, 0x9C21, 0xE9DD, 0x9C24, 0xE9DC, 0x9C25, 0xE9DB, 0x9C2D, 0x9568, + 0x9C2E, 0xE9D9, 0x9C2F, 0x88F1, 0x9C30, 0xE9DE, 0x9C32, 0xE9E0, 0x9C39, 0x8A8F, 0x9C3A, 0xE9CB, 0x9C3B, 0x8956, 0x9C3E, 0xE9E2, + 0x9C46, 0xE9E1, 0x9C47, 0xE9DF, 0x9C48, 0x924C, 0x9C52, 0x9690, 0x9C57, 0x97D8, 0x9C5A, 0xE9E3, 0x9C60, 0xE9E4, 0x9C67, 0xE9E5, + 0x9C76, 0xE9E6, 0x9C78, 0xE9E7, 0x9CE5, 0x92B9, 0x9CE7, 0xE9E8, 0x9CE9, 0x94B5, 0x9CEB, 0xE9ED, 0x9CEC, 0xE9E9, 0x9CF0, 0xE9EA, + 0x9CF3, 0x9650, 0x9CF4, 0x96C2, 0x9CF6, 0x93CE, 0x9D03, 0xE9EE, 0x9D06, 0xE9EF, 0x9D07, 0x93BC, 0x9D08, 0xE9EC, 0x9D09, 0xE9EB, + 0x9D0E, 0x89A8, 0x9D12, 0xE9F7, 0x9D15, 0xE9F6, 0x9D1B, 0x8995, 0x9D1F, 0xE9F4, 0x9D23, 0xE9F3, 0x9D26, 0xE9F1, 0x9D28, 0x8A9B, + 0x9D2A, 0xE9F0, 0x9D2B, 0x8EB0, 0x9D2C, 0x89A7, 0x9D3B, 0x8D83, 0x9D3E, 0xE9FA, 0x9D3F, 0xE9F9, 0x9D41, 0xE9F8, 0x9D44, 0xE9F5, + 0x9D46, 0xE9FB, 0x9D48, 0xE9FC, 0x9D50, 0xEA44, 0x9D51, 0xEA43, 0x9D59, 0xEA45, 0x9D5C, 0x894C, 0x9D5D, 0xEA40, 0x9D5E, 0xEA41, + 0x9D60, 0x8D94, 0x9D61, 0x96B7, 0x9D64, 0xEA42, 0x9D6B, 0xFC48, 0x9D6C, 0x9651, 0x9D6F, 0xEA4A, 0x9D70, 0xFC47, 0x9D72, 0xEA46, + 0x9D7A, 0xEA4B, 0x9D87, 0xEA48, 0x9D89, 0xEA47, 0x9D8F, 0x8C7B, 0x9D9A, 0xEA4C, 0x9DA4, 0xEA4D, 0x9DA9, 0xEA4E, 0x9DAB, 0xEA49, + 0x9DAF, 0xE9F2, 0x9DB2, 0xEA4F, 0x9DB4, 0x92DF, 0x9DB8, 0xEA53, 0x9DBA, 0xEA54, 0x9DBB, 0xEA52, 0x9DC1, 0xEA51, 0x9DC2, 0xEA57, + 0x9DC4, 0xEA50, 0x9DC6, 0xEA55, 0x9DCF, 0xEA56, 0x9DD3, 0xEA59, 0x9DD9, 0xEA58, 0x9DE6, 0xEA5B, 0x9DED, 0xEA5C, 0x9DEF, 0xEA5D, + 0x9DF2, 0x9868, 0x9DF8, 0xEA5A, 0x9DF9, 0x91E9, 0x9DFA, 0x8DEB, 0x9DFD, 0xEA5E, 0x9E19, 0xFC4A, 0x9E1A, 0xEA5F, 0x9E1B, 0xEA60, + 0x9E1E, 0xEA61, 0x9E75, 0xEA62, 0x9E78, 0x8CB2, 0x9E79, 0xEA63, 0x9E7D, 0xEA64, 0x9E7F, 0x8EAD, 0x9E81, 0xEA65, 0x9E88, 0xEA66, + 0x9E8B, 0xEA67, 0x9E8C, 0xEA68, 0x9E91, 0xEA6B, 0x9E92, 0xEA69, 0x9E93, 0x985B, 0x9E95, 0xEA6A, 0x9E97, 0x97ED, 0x9E9D, 0xEA6C, + 0x9E9F, 0x97D9, 0x9EA5, 0xEA6D, 0x9EA6, 0x949E, 0x9EA9, 0xEA6E, 0x9EAA, 0xEA70, 0x9EAD, 0xEA71, 0x9EB8, 0xEA6F, 0x9EB9, 0x8D8D, + 0x9EBA, 0x96CB, 0x9EBB, 0x9683, 0x9EBC, 0x9BF5, 0x9EBE, 0x9F80, 0x9EBF, 0x969B, 0x9EC4, 0x89A9, 0x9ECC, 0xEA73, 0x9ECD, 0x8B6F, + 0x9ECE, 0xEA74, 0x9ECF, 0xEA75, 0x9ED0, 0xEA76, 0x9ED1, 0xFC4B, 0x9ED2, 0x8D95, 0x9ED4, 0xEA77, 0x9ED8, 0xE0D2, 0x9ED9, 0x96D9, + 0x9EDB, 0x91E1, 0x9EDC, 0xEA78, 0x9EDD, 0xEA7A, 0x9EDE, 0xEA79, 0x9EE0, 0xEA7B, 0x9EE5, 0xEA7C, 0x9EE8, 0xEA7D, 0x9EEF, 0xEA7E, + 0x9EF4, 0xEA80, 0x9EF6, 0xEA81, 0x9EF7, 0xEA82, 0x9EF9, 0xEA83, 0x9EFB, 0xEA84, 0x9EFC, 0xEA85, 0x9EFD, 0xEA86, 0x9F07, 0xEA87, + 0x9F08, 0xEA88, 0x9F0E, 0x9343, 0x9F13, 0x8CDB, 0x9F15, 0xEA8A, 0x9F20, 0x916C, 0x9F21, 0xEA8B, 0x9F2C, 0xEA8C, 0x9F3B, 0x9540, + 0x9F3E, 0xEA8D, 0x9F4A, 0xEA8E, 0x9F4B, 0xE256, 0x9F4E, 0xE6D8, 0x9F4F, 0xE8EB, 0x9F52, 0xEA8F, 0x9F54, 0xEA90, 0x9F5F, 0xEA92, + 0x9F60, 0xEA93, 0x9F61, 0xEA94, 0x9F62, 0x97EE, 0x9F63, 0xEA91, 0x9F66, 0xEA95, 0x9F67, 0xEA96, 0x9F6A, 0xEA98, 0x9F6C, 0xEA97, + 0x9F72, 0xEA9A, 0x9F76, 0xEA9B, 0x9F77, 0xEA99, 0x9F8D, 0x97B4, 0x9F95, 0xEA9C, 0x9F9C, 0xEA9D, 0x9F9D, 0xE273, 0x9FA0, 0xEA9E, + 0xF929, 0xFAE0, 0xF9DC, 0xFBE9, 0xFA0E, 0xFA90, 0xFA0F, 0xFA9B, 0xFA10, 0xFA9C, 0xFA11, 0xFAB1, 0xFA12, 0xFAD8, 0xFA13, 0xFAE8, + 0xFA14, 0xFAEA, 0xFA15, 0xFB58, 0xFA16, 0xFB5E, 0xFA17, 0xFB75, 0xFA18, 0xFB7D, 0xFA19, 0xFB7E, 0xFA1A, 0xFB80, 0xFA1B, 0xFB82, + 0xFA1C, 0xFB86, 0xFA1D, 0xFB89, 0xFA1E, 0xFB92, 0xFA1F, 0xFB9D, 0xFA20, 0xFB9F, 0xFA21, 0xFBA0, 0xFA22, 0xFBA9, 0xFA23, 0xFBB1, + 0xFA24, 0xFBB3, 0xFA25, 0xFBB4, 0xFA26, 0xFBB7, 0xFA27, 0xFBD3, 0xFA28, 0xFBDA, 0xFA29, 0xFBEA, 0xFA2A, 0xFBF6, 0xFA2B, 0xFBF7, + 0xFA2C, 0xFBF9, 0xFA2D, 0xFC49, 0xFF01, 0x8149, 0xFF02, 0xFA57, 0xFF03, 0x8194, 0xFF04, 0x8190, 0xFF05, 0x8193, 0xFF06, 0x8195, + 0xFF07, 0xFA56, 0xFF08, 0x8169, 0xFF09, 0x816A, 0xFF0A, 0x8196, 0xFF0B, 0x817B, 0xFF0C, 0x8143, 0xFF0D, 0x817C, 0xFF0E, 0x8144, + 0xFF0F, 0x815E, 0xFF10, 0x824F, 0xFF11, 0x8250, 0xFF12, 0x8251, 0xFF13, 0x8252, 0xFF14, 0x8253, 0xFF15, 0x8254, 0xFF16, 0x8255, + 0xFF17, 0x8256, 0xFF18, 0x8257, 0xFF19, 0x8258, 0xFF1A, 0x8146, 0xFF1B, 0x8147, 0xFF1C, 0x8183, 0xFF1D, 0x8181, 0xFF1E, 0x8184, + 0xFF1F, 0x8148, 0xFF20, 0x8197, 0xFF21, 0x8260, 0xFF22, 0x8261, 0xFF23, 0x8262, 0xFF24, 0x8263, 0xFF25, 0x8264, 0xFF26, 0x8265, + 0xFF27, 0x8266, 0xFF28, 0x8267, 0xFF29, 0x8268, 0xFF2A, 0x8269, 0xFF2B, 0x826A, 0xFF2C, 0x826B, 0xFF2D, 0x826C, 0xFF2E, 0x826D, + 0xFF2F, 0x826E, 0xFF30, 0x826F, 0xFF31, 0x8270, 0xFF32, 0x8271, 0xFF33, 0x8272, 0xFF34, 0x8273, 0xFF35, 0x8274, 0xFF36, 0x8275, + 0xFF37, 0x8276, 0xFF38, 0x8277, 0xFF39, 0x8278, 0xFF3A, 0x8279, 0xFF3B, 0x816D, 0xFF3C, 0x815F, 0xFF3D, 0x816E, 0xFF3E, 0x814F, + 0xFF3F, 0x8151, 0xFF40, 0x814D, 0xFF41, 0x8281, 0xFF42, 0x8282, 0xFF43, 0x8283, 0xFF44, 0x8284, 0xFF45, 0x8285, 0xFF46, 0x8286, + 0xFF47, 0x8287, 0xFF48, 0x8288, 0xFF49, 0x8289, 0xFF4A, 0x828A, 0xFF4B, 0x828B, 0xFF4C, 0x828C, 0xFF4D, 0x828D, 0xFF4E, 0x828E, + 0xFF4F, 0x828F, 0xFF50, 0x8290, 0xFF51, 0x8291, 0xFF52, 0x8292, 0xFF53, 0x8293, 0xFF54, 0x8294, 0xFF55, 0x8295, 0xFF56, 0x8296, + 0xFF57, 0x8297, 0xFF58, 0x8298, 0xFF59, 0x8299, 0xFF5A, 0x829A, 0xFF5B, 0x816F, 0xFF5C, 0x8162, 0xFF5D, 0x8170, 0xFF5E, 0x8160, + 0xFF61, 0x00A1, 0xFF62, 0x00A2, 0xFF63, 0x00A3, 0xFF64, 0x00A4, 0xFF65, 0x00A5, 0xFF66, 0x00A6, 0xFF67, 0x00A7, 0xFF68, 0x00A8, + 0xFF69, 0x00A9, 0xFF6A, 0x00AA, 0xFF6B, 0x00AB, 0xFF6C, 0x00AC, 0xFF6D, 0x00AD, 0xFF6E, 0x00AE, 0xFF6F, 0x00AF, 0xFF70, 0x00B0, + 0xFF71, 0x00B1, 0xFF72, 0x00B2, 0xFF73, 0x00B3, 0xFF74, 0x00B4, 0xFF75, 0x00B5, 0xFF76, 0x00B6, 0xFF77, 0x00B7, 0xFF78, 0x00B8, + 0xFF79, 0x00B9, 0xFF7A, 0x00BA, 0xFF7B, 0x00BB, 0xFF7C, 0x00BC, 0xFF7D, 0x00BD, 0xFF7E, 0x00BE, 0xFF7F, 0x00BF, 0xFF80, 0x00C0, + 0xFF81, 0x00C1, 0xFF82, 0x00C2, 0xFF83, 0x00C3, 0xFF84, 0x00C4, 0xFF85, 0x00C5, 0xFF86, 0x00C6, 0xFF87, 0x00C7, 0xFF88, 0x00C8, + 0xFF89, 0x00C9, 0xFF8A, 0x00CA, 0xFF8B, 0x00CB, 0xFF8C, 0x00CC, 0xFF8D, 0x00CD, 0xFF8E, 0x00CE, 0xFF8F, 0x00CF, 0xFF90, 0x00D0, + 0xFF91, 0x00D1, 0xFF92, 0x00D2, 0xFF93, 0x00D3, 0xFF94, 0x00D4, 0xFF95, 0x00D5, 0xFF96, 0x00D6, 0xFF97, 0x00D7, 0xFF98, 0x00D8, + 0xFF99, 0x00D9, 0xFF9A, 0x00DA, 0xFF9B, 0x00DB, 0xFF9C, 0x00DC, 0xFF9D, 0x00DD, 0xFF9E, 0x00DE, 0xFF9F, 0x00DF, 0xFFE0, 0x8191, + 0xFFE1, 0x8192, 0xFFE2, 0x81CA, 0xFFE3, 0x8150, 0xFFE4, 0xFA55, 0xFFE5, 0x818F, 0, 0 +}; + +static const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */ + 0x00A1, 0xFF61, 0x00A2, 0xFF62, 0x00A3, 0xFF63, 0x00A4, 0xFF64, 0x00A5, 0xFF65, 0x00A6, 0xFF66, 0x00A7, 0xFF67, 0x00A8, 0xFF68, + 0x00A9, 0xFF69, 0x00AA, 0xFF6A, 0x00AB, 0xFF6B, 0x00AC, 0xFF6C, 0x00AD, 0xFF6D, 0x00AE, 0xFF6E, 0x00AF, 0xFF6F, 0x00B0, 0xFF70, + 0x00B1, 0xFF71, 0x00B2, 0xFF72, 0x00B3, 0xFF73, 0x00B4, 0xFF74, 0x00B5, 0xFF75, 0x00B6, 0xFF76, 0x00B7, 0xFF77, 0x00B8, 0xFF78, + 0x00B9, 0xFF79, 0x00BA, 0xFF7A, 0x00BB, 0xFF7B, 0x00BC, 0xFF7C, 0x00BD, 0xFF7D, 0x00BE, 0xFF7E, 0x00BF, 0xFF7F, 0x00C0, 0xFF80, + 0x00C1, 0xFF81, 0x00C2, 0xFF82, 0x00C3, 0xFF83, 0x00C4, 0xFF84, 0x00C5, 0xFF85, 0x00C6, 0xFF86, 0x00C7, 0xFF87, 0x00C8, 0xFF88, + 0x00C9, 0xFF89, 0x00CA, 0xFF8A, 0x00CB, 0xFF8B, 0x00CC, 0xFF8C, 0x00CD, 0xFF8D, 0x00CE, 0xFF8E, 0x00CF, 0xFF8F, 0x00D0, 0xFF90, + 0x00D1, 0xFF91, 0x00D2, 0xFF92, 0x00D3, 0xFF93, 0x00D4, 0xFF94, 0x00D5, 0xFF95, 0x00D6, 0xFF96, 0x00D7, 0xFF97, 0x00D8, 0xFF98, + 0x00D9, 0xFF99, 0x00DA, 0xFF9A, 0x00DB, 0xFF9B, 0x00DC, 0xFF9C, 0x00DD, 0xFF9D, 0x00DE, 0xFF9E, 0x00DF, 0xFF9F, 0x8140, 0x3000, + 0x8141, 0x3001, 0x8142, 0x3002, 0x8143, 0xFF0C, 0x8144, 0xFF0E, 0x8145, 0x30FB, 0x8146, 0xFF1A, 0x8147, 0xFF1B, 0x8148, 0xFF1F, + 0x8149, 0xFF01, 0x814A, 0x309B, 0x814B, 0x309C, 0x814C, 0x00B4, 0x814D, 0xFF40, 0x814E, 0x00A8, 0x814F, 0xFF3E, 0x8150, 0xFFE3, + 0x8151, 0xFF3F, 0x8152, 0x30FD, 0x8153, 0x30FE, 0x8154, 0x309D, 0x8155, 0x309E, 0x8156, 0x3003, 0x8157, 0x4EDD, 0x8158, 0x3005, + 0x8159, 0x3006, 0x815A, 0x3007, 0x815B, 0x30FC, 0x815C, 0x2015, 0x815D, 0x2010, 0x815E, 0xFF0F, 0x815F, 0xFF3C, 0x8160, 0xFF5E, + 0x8161, 0x2225, 0x8162, 0xFF5C, 0x8163, 0x2026, 0x8164, 0x2025, 0x8165, 0x2018, 0x8166, 0x2019, 0x8167, 0x201C, 0x8168, 0x201D, + 0x8169, 0xFF08, 0x816A, 0xFF09, 0x816B, 0x3014, 0x816C, 0x3015, 0x816D, 0xFF3B, 0x816E, 0xFF3D, 0x816F, 0xFF5B, 0x8170, 0xFF5D, + 0x8171, 0x3008, 0x8172, 0x3009, 0x8173, 0x300A, 0x8174, 0x300B, 0x8175, 0x300C, 0x8176, 0x300D, 0x8177, 0x300E, 0x8178, 0x300F, + 0x8179, 0x3010, 0x817A, 0x3011, 0x817B, 0xFF0B, 0x817C, 0xFF0D, 0x817D, 0x00B1, 0x817E, 0x00D7, 0x8180, 0x00F7, 0x8181, 0xFF1D, + 0x8182, 0x2260, 0x8183, 0xFF1C, 0x8184, 0xFF1E, 0x8185, 0x2266, 0x8186, 0x2267, 0x8187, 0x221E, 0x8188, 0x2234, 0x8189, 0x2642, + 0x818A, 0x2640, 0x818B, 0x00B0, 0x818C, 0x2032, 0x818D, 0x2033, 0x818E, 0x2103, 0x818F, 0xFFE5, 0x8190, 0xFF04, 0x8191, 0xFFE0, + 0x8192, 0xFFE1, 0x8193, 0xFF05, 0x8194, 0xFF03, 0x8195, 0xFF06, 0x8196, 0xFF0A, 0x8197, 0xFF20, 0x8198, 0x00A7, 0x8199, 0x2606, + 0x819A, 0x2605, 0x819B, 0x25CB, 0x819C, 0x25CF, 0x819D, 0x25CE, 0x819E, 0x25C7, 0x819F, 0x25C6, 0x81A0, 0x25A1, 0x81A1, 0x25A0, + 0x81A2, 0x25B3, 0x81A3, 0x25B2, 0x81A4, 0x25BD, 0x81A5, 0x25BC, 0x81A6, 0x203B, 0x81A7, 0x3012, 0x81A8, 0x2192, 0x81A9, 0x2190, + 0x81AA, 0x2191, 0x81AB, 0x2193, 0x81AC, 0x3013, 0x81B8, 0x2208, 0x81B9, 0x220B, 0x81BA, 0x2286, 0x81BB, 0x2287, 0x81BC, 0x2282, + 0x81BD, 0x2283, 0x81BE, 0x222A, 0x81BF, 0x2229, 0x81C8, 0x2227, 0x81C9, 0x2228, 0x81CA, 0xFFE2, 0x81CB, 0x21D2, 0x81CC, 0x21D4, + 0x81CD, 0x2200, 0x81CE, 0x2203, 0x81DA, 0x2220, 0x81DB, 0x22A5, 0x81DC, 0x2312, 0x81DD, 0x2202, 0x81DE, 0x2207, 0x81DF, 0x2261, + 0x81E0, 0x2252, 0x81E1, 0x226A, 0x81E2, 0x226B, 0x81E3, 0x221A, 0x81E4, 0x223D, 0x81E5, 0x221D, 0x81E6, 0x2235, 0x81E7, 0x222B, + 0x81E8, 0x222C, 0x81F0, 0x212B, 0x81F1, 0x2030, 0x81F2, 0x266F, 0x81F3, 0x266D, 0x81F4, 0x266A, 0x81F5, 0x2020, 0x81F6, 0x2021, + 0x81F7, 0x00B6, 0x81FC, 0x25EF, 0x824F, 0xFF10, 0x8250, 0xFF11, 0x8251, 0xFF12, 0x8252, 0xFF13, 0x8253, 0xFF14, 0x8254, 0xFF15, + 0x8255, 0xFF16, 0x8256, 0xFF17, 0x8257, 0xFF18, 0x8258, 0xFF19, 0x8260, 0xFF21, 0x8261, 0xFF22, 0x8262, 0xFF23, 0x8263, 0xFF24, + 0x8264, 0xFF25, 0x8265, 0xFF26, 0x8266, 0xFF27, 0x8267, 0xFF28, 0x8268, 0xFF29, 0x8269, 0xFF2A, 0x826A, 0xFF2B, 0x826B, 0xFF2C, + 0x826C, 0xFF2D, 0x826D, 0xFF2E, 0x826E, 0xFF2F, 0x826F, 0xFF30, 0x8270, 0xFF31, 0x8271, 0xFF32, 0x8272, 0xFF33, 0x8273, 0xFF34, + 0x8274, 0xFF35, 0x8275, 0xFF36, 0x8276, 0xFF37, 0x8277, 0xFF38, 0x8278, 0xFF39, 0x8279, 0xFF3A, 0x8281, 0xFF41, 0x8282, 0xFF42, + 0x8283, 0xFF43, 0x8284, 0xFF44, 0x8285, 0xFF45, 0x8286, 0xFF46, 0x8287, 0xFF47, 0x8288, 0xFF48, 0x8289, 0xFF49, 0x828A, 0xFF4A, + 0x828B, 0xFF4B, 0x828C, 0xFF4C, 0x828D, 0xFF4D, 0x828E, 0xFF4E, 0x828F, 0xFF4F, 0x8290, 0xFF50, 0x8291, 0xFF51, 0x8292, 0xFF52, + 0x8293, 0xFF53, 0x8294, 0xFF54, 0x8295, 0xFF55, 0x8296, 0xFF56, 0x8297, 0xFF57, 0x8298, 0xFF58, 0x8299, 0xFF59, 0x829A, 0xFF5A, + 0x829F, 0x3041, 0x82A0, 0x3042, 0x82A1, 0x3043, 0x82A2, 0x3044, 0x82A3, 0x3045, 0x82A4, 0x3046, 0x82A5, 0x3047, 0x82A6, 0x3048, + 0x82A7, 0x3049, 0x82A8, 0x304A, 0x82A9, 0x304B, 0x82AA, 0x304C, 0x82AB, 0x304D, 0x82AC, 0x304E, 0x82AD, 0x304F, 0x82AE, 0x3050, + 0x82AF, 0x3051, 0x82B0, 0x3052, 0x82B1, 0x3053, 0x82B2, 0x3054, 0x82B3, 0x3055, 0x82B4, 0x3056, 0x82B5, 0x3057, 0x82B6, 0x3058, + 0x82B7, 0x3059, 0x82B8, 0x305A, 0x82B9, 0x305B, 0x82BA, 0x305C, 0x82BB, 0x305D, 0x82BC, 0x305E, 0x82BD, 0x305F, 0x82BE, 0x3060, + 0x82BF, 0x3061, 0x82C0, 0x3062, 0x82C1, 0x3063, 0x82C2, 0x3064, 0x82C3, 0x3065, 0x82C4, 0x3066, 0x82C5, 0x3067, 0x82C6, 0x3068, + 0x82C7, 0x3069, 0x82C8, 0x306A, 0x82C9, 0x306B, 0x82CA, 0x306C, 0x82CB, 0x306D, 0x82CC, 0x306E, 0x82CD, 0x306F, 0x82CE, 0x3070, + 0x82CF, 0x3071, 0x82D0, 0x3072, 0x82D1, 0x3073, 0x82D2, 0x3074, 0x82D3, 0x3075, 0x82D4, 0x3076, 0x82D5, 0x3077, 0x82D6, 0x3078, + 0x82D7, 0x3079, 0x82D8, 0x307A, 0x82D9, 0x307B, 0x82DA, 0x307C, 0x82DB, 0x307D, 0x82DC, 0x307E, 0x82DD, 0x307F, 0x82DE, 0x3080, + 0x82DF, 0x3081, 0x82E0, 0x3082, 0x82E1, 0x3083, 0x82E2, 0x3084, 0x82E3, 0x3085, 0x82E4, 0x3086, 0x82E5, 0x3087, 0x82E6, 0x3088, + 0x82E7, 0x3089, 0x82E8, 0x308A, 0x82E9, 0x308B, 0x82EA, 0x308C, 0x82EB, 0x308D, 0x82EC, 0x308E, 0x82ED, 0x308F, 0x82EE, 0x3090, + 0x82EF, 0x3091, 0x82F0, 0x3092, 0x82F1, 0x3093, 0x8340, 0x30A1, 0x8341, 0x30A2, 0x8342, 0x30A3, 0x8343, 0x30A4, 0x8344, 0x30A5, + 0x8345, 0x30A6, 0x8346, 0x30A7, 0x8347, 0x30A8, 0x8348, 0x30A9, 0x8349, 0x30AA, 0x834A, 0x30AB, 0x834B, 0x30AC, 0x834C, 0x30AD, + 0x834D, 0x30AE, 0x834E, 0x30AF, 0x834F, 0x30B0, 0x8350, 0x30B1, 0x8351, 0x30B2, 0x8352, 0x30B3, 0x8353, 0x30B4, 0x8354, 0x30B5, + 0x8355, 0x30B6, 0x8356, 0x30B7, 0x8357, 0x30B8, 0x8358, 0x30B9, 0x8359, 0x30BA, 0x835A, 0x30BB, 0x835B, 0x30BC, 0x835C, 0x30BD, + 0x835D, 0x30BE, 0x835E, 0x30BF, 0x835F, 0x30C0, 0x8360, 0x30C1, 0x8361, 0x30C2, 0x8362, 0x30C3, 0x8363, 0x30C4, 0x8364, 0x30C5, + 0x8365, 0x30C6, 0x8366, 0x30C7, 0x8367, 0x30C8, 0x8368, 0x30C9, 0x8369, 0x30CA, 0x836A, 0x30CB, 0x836B, 0x30CC, 0x836C, 0x30CD, + 0x836D, 0x30CE, 0x836E, 0x30CF, 0x836F, 0x30D0, 0x8370, 0x30D1, 0x8371, 0x30D2, 0x8372, 0x30D3, 0x8373, 0x30D4, 0x8374, 0x30D5, + 0x8375, 0x30D6, 0x8376, 0x30D7, 0x8377, 0x30D8, 0x8378, 0x30D9, 0x8379, 0x30DA, 0x837A, 0x30DB, 0x837B, 0x30DC, 0x837C, 0x30DD, + 0x837D, 0x30DE, 0x837E, 0x30DF, 0x8380, 0x30E0, 0x8381, 0x30E1, 0x8382, 0x30E2, 0x8383, 0x30E3, 0x8384, 0x30E4, 0x8385, 0x30E5, + 0x8386, 0x30E6, 0x8387, 0x30E7, 0x8388, 0x30E8, 0x8389, 0x30E9, 0x838A, 0x30EA, 0x838B, 0x30EB, 0x838C, 0x30EC, 0x838D, 0x30ED, + 0x838E, 0x30EE, 0x838F, 0x30EF, 0x8390, 0x30F0, 0x8391, 0x30F1, 0x8392, 0x30F2, 0x8393, 0x30F3, 0x8394, 0x30F4, 0x8395, 0x30F5, + 0x8396, 0x30F6, 0x839F, 0x0391, 0x83A0, 0x0392, 0x83A1, 0x0393, 0x83A2, 0x0394, 0x83A3, 0x0395, 0x83A4, 0x0396, 0x83A5, 0x0397, + 0x83A6, 0x0398, 0x83A7, 0x0399, 0x83A8, 0x039A, 0x83A9, 0x039B, 0x83AA, 0x039C, 0x83AB, 0x039D, 0x83AC, 0x039E, 0x83AD, 0x039F, + 0x83AE, 0x03A0, 0x83AF, 0x03A1, 0x83B0, 0x03A3, 0x83B1, 0x03A4, 0x83B2, 0x03A5, 0x83B3, 0x03A6, 0x83B4, 0x03A7, 0x83B5, 0x03A8, + 0x83B6, 0x03A9, 0x83BF, 0x03B1, 0x83C0, 0x03B2, 0x83C1, 0x03B3, 0x83C2, 0x03B4, 0x83C3, 0x03B5, 0x83C4, 0x03B6, 0x83C5, 0x03B7, + 0x83C6, 0x03B8, 0x83C7, 0x03B9, 0x83C8, 0x03BA, 0x83C9, 0x03BB, 0x83CA, 0x03BC, 0x83CB, 0x03BD, 0x83CC, 0x03BE, 0x83CD, 0x03BF, + 0x83CE, 0x03C0, 0x83CF, 0x03C1, 0x83D0, 0x03C3, 0x83D1, 0x03C4, 0x83D2, 0x03C5, 0x83D3, 0x03C6, 0x83D4, 0x03C7, 0x83D5, 0x03C8, + 0x83D6, 0x03C9, 0x8440, 0x0410, 0x8441, 0x0411, 0x8442, 0x0412, 0x8443, 0x0413, 0x8444, 0x0414, 0x8445, 0x0415, 0x8446, 0x0401, + 0x8447, 0x0416, 0x8448, 0x0417, 0x8449, 0x0418, 0x844A, 0x0419, 0x844B, 0x041A, 0x844C, 0x041B, 0x844D, 0x041C, 0x844E, 0x041D, + 0x844F, 0x041E, 0x8450, 0x041F, 0x8451, 0x0420, 0x8452, 0x0421, 0x8453, 0x0422, 0x8454, 0x0423, 0x8455, 0x0424, 0x8456, 0x0425, + 0x8457, 0x0426, 0x8458, 0x0427, 0x8459, 0x0428, 0x845A, 0x0429, 0x845B, 0x042A, 0x845C, 0x042B, 0x845D, 0x042C, 0x845E, 0x042D, + 0x845F, 0x042E, 0x8460, 0x042F, 0x8470, 0x0430, 0x8471, 0x0431, 0x8472, 0x0432, 0x8473, 0x0433, 0x8474, 0x0434, 0x8475, 0x0435, + 0x8476, 0x0451, 0x8477, 0x0436, 0x8478, 0x0437, 0x8479, 0x0438, 0x847A, 0x0439, 0x847B, 0x043A, 0x847C, 0x043B, 0x847D, 0x043C, + 0x847E, 0x043D, 0x8480, 0x043E, 0x8481, 0x043F, 0x8482, 0x0440, 0x8483, 0x0441, 0x8484, 0x0442, 0x8485, 0x0443, 0x8486, 0x0444, + 0x8487, 0x0445, 0x8488, 0x0446, 0x8489, 0x0447, 0x848A, 0x0448, 0x848B, 0x0449, 0x848C, 0x044A, 0x848D, 0x044B, 0x848E, 0x044C, + 0x848F, 0x044D, 0x8490, 0x044E, 0x8491, 0x044F, 0x849F, 0x2500, 0x84A0, 0x2502, 0x84A1, 0x250C, 0x84A2, 0x2510, 0x84A3, 0x2518, + 0x84A4, 0x2514, 0x84A5, 0x251C, 0x84A6, 0x252C, 0x84A7, 0x2524, 0x84A8, 0x2534, 0x84A9, 0x253C, 0x84AA, 0x2501, 0x84AB, 0x2503, + 0x84AC, 0x250F, 0x84AD, 0x2513, 0x84AE, 0x251B, 0x84AF, 0x2517, 0x84B0, 0x2523, 0x84B1, 0x2533, 0x84B2, 0x252B, 0x84B3, 0x253B, + 0x84B4, 0x254B, 0x84B5, 0x2520, 0x84B6, 0x252F, 0x84B7, 0x2528, 0x84B8, 0x2537, 0x84B9, 0x253F, 0x84BA, 0x251D, 0x84BB, 0x2530, + 0x84BC, 0x2525, 0x84BD, 0x2538, 0x84BE, 0x2542, 0x8740, 0x2460, 0x8741, 0x2461, 0x8742, 0x2462, 0x8743, 0x2463, 0x8744, 0x2464, + 0x8745, 0x2465, 0x8746, 0x2466, 0x8747, 0x2467, 0x8748, 0x2468, 0x8749, 0x2469, 0x874A, 0x246A, 0x874B, 0x246B, 0x874C, 0x246C, + 0x874D, 0x246D, 0x874E, 0x246E, 0x874F, 0x246F, 0x8750, 0x2470, 0x8751, 0x2471, 0x8752, 0x2472, 0x8753, 0x2473, 0x8754, 0x2160, + 0x8755, 0x2161, 0x8756, 0x2162, 0x8757, 0x2163, 0x8758, 0x2164, 0x8759, 0x2165, 0x875A, 0x2166, 0x875B, 0x2167, 0x875C, 0x2168, + 0x875D, 0x2169, 0x875F, 0x3349, 0x8760, 0x3314, 0x8761, 0x3322, 0x8762, 0x334D, 0x8763, 0x3318, 0x8764, 0x3327, 0x8765, 0x3303, + 0x8766, 0x3336, 0x8767, 0x3351, 0x8768, 0x3357, 0x8769, 0x330D, 0x876A, 0x3326, 0x876B, 0x3323, 0x876C, 0x332B, 0x876D, 0x334A, + 0x876E, 0x333B, 0x876F, 0x339C, 0x8770, 0x339D, 0x8771, 0x339E, 0x8772, 0x338E, 0x8773, 0x338F, 0x8774, 0x33C4, 0x8775, 0x33A1, + 0x877E, 0x337B, 0x8780, 0x301D, 0x8781, 0x301F, 0x8782, 0x2116, 0x8783, 0x33CD, 0x8784, 0x2121, 0x8785, 0x32A4, 0x8786, 0x32A5, + 0x8787, 0x32A6, 0x8788, 0x32A7, 0x8789, 0x32A8, 0x878A, 0x3231, 0x878B, 0x3232, 0x878C, 0x3239, 0x878D, 0x337E, 0x878E, 0x337D, + 0x878F, 0x337C, 0x8793, 0x222E, 0x8794, 0x2211, 0x8798, 0x221F, 0x8799, 0x22BF, 0x889F, 0x4E9C, 0x88A0, 0x5516, 0x88A1, 0x5A03, + 0x88A2, 0x963F, 0x88A3, 0x54C0, 0x88A4, 0x611B, 0x88A5, 0x6328, 0x88A6, 0x59F6, 0x88A7, 0x9022, 0x88A8, 0x8475, 0x88A9, 0x831C, + 0x88AA, 0x7A50, 0x88AB, 0x60AA, 0x88AC, 0x63E1, 0x88AD, 0x6E25, 0x88AE, 0x65ED, 0x88AF, 0x8466, 0x88B0, 0x82A6, 0x88B1, 0x9BF5, + 0x88B2, 0x6893, 0x88B3, 0x5727, 0x88B4, 0x65A1, 0x88B5, 0x6271, 0x88B6, 0x5B9B, 0x88B7, 0x59D0, 0x88B8, 0x867B, 0x88B9, 0x98F4, + 0x88BA, 0x7D62, 0x88BB, 0x7DBE, 0x88BC, 0x9B8E, 0x88BD, 0x6216, 0x88BE, 0x7C9F, 0x88BF, 0x88B7, 0x88C0, 0x5B89, 0x88C1, 0x5EB5, + 0x88C2, 0x6309, 0x88C3, 0x6697, 0x88C4, 0x6848, 0x88C5, 0x95C7, 0x88C6, 0x978D, 0x88C7, 0x674F, 0x88C8, 0x4EE5, 0x88C9, 0x4F0A, + 0x88CA, 0x4F4D, 0x88CB, 0x4F9D, 0x88CC, 0x5049, 0x88CD, 0x56F2, 0x88CE, 0x5937, 0x88CF, 0x59D4, 0x88D0, 0x5A01, 0x88D1, 0x5C09, + 0x88D2, 0x60DF, 0x88D3, 0x610F, 0x88D4, 0x6170, 0x88D5, 0x6613, 0x88D6, 0x6905, 0x88D7, 0x70BA, 0x88D8, 0x754F, 0x88D9, 0x7570, + 0x88DA, 0x79FB, 0x88DB, 0x7DAD, 0x88DC, 0x7DEF, 0x88DD, 0x80C3, 0x88DE, 0x840E, 0x88DF, 0x8863, 0x88E0, 0x8B02, 0x88E1, 0x9055, + 0x88E2, 0x907A, 0x88E3, 0x533B, 0x88E4, 0x4E95, 0x88E5, 0x4EA5, 0x88E6, 0x57DF, 0x88E7, 0x80B2, 0x88E8, 0x90C1, 0x88E9, 0x78EF, + 0x88EA, 0x4E00, 0x88EB, 0x58F1, 0x88EC, 0x6EA2, 0x88ED, 0x9038, 0x88EE, 0x7A32, 0x88EF, 0x8328, 0x88F0, 0x828B, 0x88F1, 0x9C2F, + 0x88F2, 0x5141, 0x88F3, 0x5370, 0x88F4, 0x54BD, 0x88F5, 0x54E1, 0x88F6, 0x56E0, 0x88F7, 0x59FB, 0x88F8, 0x5F15, 0x88F9, 0x98F2, + 0x88FA, 0x6DEB, 0x88FB, 0x80E4, 0x88FC, 0x852D, 0x8940, 0x9662, 0x8941, 0x9670, 0x8942, 0x96A0, 0x8943, 0x97FB, 0x8944, 0x540B, + 0x8945, 0x53F3, 0x8946, 0x5B87, 0x8947, 0x70CF, 0x8948, 0x7FBD, 0x8949, 0x8FC2, 0x894A, 0x96E8, 0x894B, 0x536F, 0x894C, 0x9D5C, + 0x894D, 0x7ABA, 0x894E, 0x4E11, 0x894F, 0x7893, 0x8950, 0x81FC, 0x8951, 0x6E26, 0x8952, 0x5618, 0x8953, 0x5504, 0x8954, 0x6B1D, + 0x8955, 0x851A, 0x8956, 0x9C3B, 0x8957, 0x59E5, 0x8958, 0x53A9, 0x8959, 0x6D66, 0x895A, 0x74DC, 0x895B, 0x958F, 0x895C, 0x5642, + 0x895D, 0x4E91, 0x895E, 0x904B, 0x895F, 0x96F2, 0x8960, 0x834F, 0x8961, 0x990C, 0x8962, 0x53E1, 0x8963, 0x55B6, 0x8964, 0x5B30, + 0x8965, 0x5F71, 0x8966, 0x6620, 0x8967, 0x66F3, 0x8968, 0x6804, 0x8969, 0x6C38, 0x896A, 0x6CF3, 0x896B, 0x6D29, 0x896C, 0x745B, + 0x896D, 0x76C8, 0x896E, 0x7A4E, 0x896F, 0x9834, 0x8970, 0x82F1, 0x8971, 0x885B, 0x8972, 0x8A60, 0x8973, 0x92ED, 0x8974, 0x6DB2, + 0x8975, 0x75AB, 0x8976, 0x76CA, 0x8977, 0x99C5, 0x8978, 0x60A6, 0x8979, 0x8B01, 0x897A, 0x8D8A, 0x897B, 0x95B2, 0x897C, 0x698E, + 0x897D, 0x53AD, 0x897E, 0x5186, 0x8980, 0x5712, 0x8981, 0x5830, 0x8982, 0x5944, 0x8983, 0x5BB4, 0x8984, 0x5EF6, 0x8985, 0x6028, + 0x8986, 0x63A9, 0x8987, 0x63F4, 0x8988, 0x6CBF, 0x8989, 0x6F14, 0x898A, 0x708E, 0x898B, 0x7114, 0x898C, 0x7159, 0x898D, 0x71D5, + 0x898E, 0x733F, 0x898F, 0x7E01, 0x8990, 0x8276, 0x8991, 0x82D1, 0x8992, 0x8597, 0x8993, 0x9060, 0x8994, 0x925B, 0x8995, 0x9D1B, + 0x8996, 0x5869, 0x8997, 0x65BC, 0x8998, 0x6C5A, 0x8999, 0x7525, 0x899A, 0x51F9, 0x899B, 0x592E, 0x899C, 0x5965, 0x899D, 0x5F80, + 0x899E, 0x5FDC, 0x899F, 0x62BC, 0x89A0, 0x65FA, 0x89A1, 0x6A2A, 0x89A2, 0x6B27, 0x89A3, 0x6BB4, 0x89A4, 0x738B, 0x89A5, 0x7FC1, + 0x89A6, 0x8956, 0x89A7, 0x9D2C, 0x89A8, 0x9D0E, 0x89A9, 0x9EC4, 0x89AA, 0x5CA1, 0x89AB, 0x6C96, 0x89AC, 0x837B, 0x89AD, 0x5104, + 0x89AE, 0x5C4B, 0x89AF, 0x61B6, 0x89B0, 0x81C6, 0x89B1, 0x6876, 0x89B2, 0x7261, 0x89B3, 0x4E59, 0x89B4, 0x4FFA, 0x89B5, 0x5378, + 0x89B6, 0x6069, 0x89B7, 0x6E29, 0x89B8, 0x7A4F, 0x89B9, 0x97F3, 0x89BA, 0x4E0B, 0x89BB, 0x5316, 0x89BC, 0x4EEE, 0x89BD, 0x4F55, + 0x89BE, 0x4F3D, 0x89BF, 0x4FA1, 0x89C0, 0x4F73, 0x89C1, 0x52A0, 0x89C2, 0x53EF, 0x89C3, 0x5609, 0x89C4, 0x590F, 0x89C5, 0x5AC1, + 0x89C6, 0x5BB6, 0x89C7, 0x5BE1, 0x89C8, 0x79D1, 0x89C9, 0x6687, 0x89CA, 0x679C, 0x89CB, 0x67B6, 0x89CC, 0x6B4C, 0x89CD, 0x6CB3, + 0x89CE, 0x706B, 0x89CF, 0x73C2, 0x89D0, 0x798D, 0x89D1, 0x79BE, 0x89D2, 0x7A3C, 0x89D3, 0x7B87, 0x89D4, 0x82B1, 0x89D5, 0x82DB, + 0x89D6, 0x8304, 0x89D7, 0x8377, 0x89D8, 0x83EF, 0x89D9, 0x83D3, 0x89DA, 0x8766, 0x89DB, 0x8AB2, 0x89DC, 0x5629, 0x89DD, 0x8CA8, + 0x89DE, 0x8FE6, 0x89DF, 0x904E, 0x89E0, 0x971E, 0x89E1, 0x868A, 0x89E2, 0x4FC4, 0x89E3, 0x5CE8, 0x89E4, 0x6211, 0x89E5, 0x7259, + 0x89E6, 0x753B, 0x89E7, 0x81E5, 0x89E8, 0x82BD, 0x89E9, 0x86FE, 0x89EA, 0x8CC0, 0x89EB, 0x96C5, 0x89EC, 0x9913, 0x89ED, 0x99D5, + 0x89EE, 0x4ECB, 0x89EF, 0x4F1A, 0x89F0, 0x89E3, 0x89F1, 0x56DE, 0x89F2, 0x584A, 0x89F3, 0x58CA, 0x89F4, 0x5EFB, 0x89F5, 0x5FEB, + 0x89F6, 0x602A, 0x89F7, 0x6094, 0x89F8, 0x6062, 0x89F9, 0x61D0, 0x89FA, 0x6212, 0x89FB, 0x62D0, 0x89FC, 0x6539, 0x8A40, 0x9B41, + 0x8A41, 0x6666, 0x8A42, 0x68B0, 0x8A43, 0x6D77, 0x8A44, 0x7070, 0x8A45, 0x754C, 0x8A46, 0x7686, 0x8A47, 0x7D75, 0x8A48, 0x82A5, + 0x8A49, 0x87F9, 0x8A4A, 0x958B, 0x8A4B, 0x968E, 0x8A4C, 0x8C9D, 0x8A4D, 0x51F1, 0x8A4E, 0x52BE, 0x8A4F, 0x5916, 0x8A50, 0x54B3, + 0x8A51, 0x5BB3, 0x8A52, 0x5D16, 0x8A53, 0x6168, 0x8A54, 0x6982, 0x8A55, 0x6DAF, 0x8A56, 0x788D, 0x8A57, 0x84CB, 0x8A58, 0x8857, + 0x8A59, 0x8A72, 0x8A5A, 0x93A7, 0x8A5B, 0x9AB8, 0x8A5C, 0x6D6C, 0x8A5D, 0x99A8, 0x8A5E, 0x86D9, 0x8A5F, 0x57A3, 0x8A60, 0x67FF, + 0x8A61, 0x86CE, 0x8A62, 0x920E, 0x8A63, 0x5283, 0x8A64, 0x5687, 0x8A65, 0x5404, 0x8A66, 0x5ED3, 0x8A67, 0x62E1, 0x8A68, 0x64B9, + 0x8A69, 0x683C, 0x8A6A, 0x6838, 0x8A6B, 0x6BBB, 0x8A6C, 0x7372, 0x8A6D, 0x78BA, 0x8A6E, 0x7A6B, 0x8A6F, 0x899A, 0x8A70, 0x89D2, + 0x8A71, 0x8D6B, 0x8A72, 0x8F03, 0x8A73, 0x90ED, 0x8A74, 0x95A3, 0x8A75, 0x9694, 0x8A76, 0x9769, 0x8A77, 0x5B66, 0x8A78, 0x5CB3, + 0x8A79, 0x697D, 0x8A7A, 0x984D, 0x8A7B, 0x984E, 0x8A7C, 0x639B, 0x8A7D, 0x7B20, 0x8A7E, 0x6A2B, 0x8A80, 0x6A7F, 0x8A81, 0x68B6, + 0x8A82, 0x9C0D, 0x8A83, 0x6F5F, 0x8A84, 0x5272, 0x8A85, 0x559D, 0x8A86, 0x6070, 0x8A87, 0x62EC, 0x8A88, 0x6D3B, 0x8A89, 0x6E07, + 0x8A8A, 0x6ED1, 0x8A8B, 0x845B, 0x8A8C, 0x8910, 0x8A8D, 0x8F44, 0x8A8E, 0x4E14, 0x8A8F, 0x9C39, 0x8A90, 0x53F6, 0x8A91, 0x691B, + 0x8A92, 0x6A3A, 0x8A93, 0x9784, 0x8A94, 0x682A, 0x8A95, 0x515C, 0x8A96, 0x7AC3, 0x8A97, 0x84B2, 0x8A98, 0x91DC, 0x8A99, 0x938C, + 0x8A9A, 0x565B, 0x8A9B, 0x9D28, 0x8A9C, 0x6822, 0x8A9D, 0x8305, 0x8A9E, 0x8431, 0x8A9F, 0x7CA5, 0x8AA0, 0x5208, 0x8AA1, 0x82C5, + 0x8AA2, 0x74E6, 0x8AA3, 0x4E7E, 0x8AA4, 0x4F83, 0x8AA5, 0x51A0, 0x8AA6, 0x5BD2, 0x8AA7, 0x520A, 0x8AA8, 0x52D8, 0x8AA9, 0x52E7, + 0x8AAA, 0x5DFB, 0x8AAB, 0x559A, 0x8AAC, 0x582A, 0x8AAD, 0x59E6, 0x8AAE, 0x5B8C, 0x8AAF, 0x5B98, 0x8AB0, 0x5BDB, 0x8AB1, 0x5E72, + 0x8AB2, 0x5E79, 0x8AB3, 0x60A3, 0x8AB4, 0x611F, 0x8AB5, 0x6163, 0x8AB6, 0x61BE, 0x8AB7, 0x63DB, 0x8AB8, 0x6562, 0x8AB9, 0x67D1, + 0x8ABA, 0x6853, 0x8ABB, 0x68FA, 0x8ABC, 0x6B3E, 0x8ABD, 0x6B53, 0x8ABE, 0x6C57, 0x8ABF, 0x6F22, 0x8AC0, 0x6F97, 0x8AC1, 0x6F45, + 0x8AC2, 0x74B0, 0x8AC3, 0x7518, 0x8AC4, 0x76E3, 0x8AC5, 0x770B, 0x8AC6, 0x7AFF, 0x8AC7, 0x7BA1, 0x8AC8, 0x7C21, 0x8AC9, 0x7DE9, + 0x8ACA, 0x7F36, 0x8ACB, 0x7FF0, 0x8ACC, 0x809D, 0x8ACD, 0x8266, 0x8ACE, 0x839E, 0x8ACF, 0x89B3, 0x8AD0, 0x8ACC, 0x8AD1, 0x8CAB, + 0x8AD2, 0x9084, 0x8AD3, 0x9451, 0x8AD4, 0x9593, 0x8AD5, 0x9591, 0x8AD6, 0x95A2, 0x8AD7, 0x9665, 0x8AD8, 0x97D3, 0x8AD9, 0x9928, + 0x8ADA, 0x8218, 0x8ADB, 0x4E38, 0x8ADC, 0x542B, 0x8ADD, 0x5CB8, 0x8ADE, 0x5DCC, 0x8ADF, 0x73A9, 0x8AE0, 0x764C, 0x8AE1, 0x773C, + 0x8AE2, 0x5CA9, 0x8AE3, 0x7FEB, 0x8AE4, 0x8D0B, 0x8AE5, 0x96C1, 0x8AE6, 0x9811, 0x8AE7, 0x9854, 0x8AE8, 0x9858, 0x8AE9, 0x4F01, + 0x8AEA, 0x4F0E, 0x8AEB, 0x5371, 0x8AEC, 0x559C, 0x8AED, 0x5668, 0x8AEE, 0x57FA, 0x8AEF, 0x5947, 0x8AF0, 0x5B09, 0x8AF1, 0x5BC4, + 0x8AF2, 0x5C90, 0x8AF3, 0x5E0C, 0x8AF4, 0x5E7E, 0x8AF5, 0x5FCC, 0x8AF6, 0x63EE, 0x8AF7, 0x673A, 0x8AF8, 0x65D7, 0x8AF9, 0x65E2, + 0x8AFA, 0x671F, 0x8AFB, 0x68CB, 0x8AFC, 0x68C4, 0x8B40, 0x6A5F, 0x8B41, 0x5E30, 0x8B42, 0x6BC5, 0x8B43, 0x6C17, 0x8B44, 0x6C7D, + 0x8B45, 0x757F, 0x8B46, 0x7948, 0x8B47, 0x5B63, 0x8B48, 0x7A00, 0x8B49, 0x7D00, 0x8B4A, 0x5FBD, 0x8B4B, 0x898F, 0x8B4C, 0x8A18, + 0x8B4D, 0x8CB4, 0x8B4E, 0x8D77, 0x8B4F, 0x8ECC, 0x8B50, 0x8F1D, 0x8B51, 0x98E2, 0x8B52, 0x9A0E, 0x8B53, 0x9B3C, 0x8B54, 0x4E80, + 0x8B55, 0x507D, 0x8B56, 0x5100, 0x8B57, 0x5993, 0x8B58, 0x5B9C, 0x8B59, 0x622F, 0x8B5A, 0x6280, 0x8B5B, 0x64EC, 0x8B5C, 0x6B3A, + 0x8B5D, 0x72A0, 0x8B5E, 0x7591, 0x8B5F, 0x7947, 0x8B60, 0x7FA9, 0x8B61, 0x87FB, 0x8B62, 0x8ABC, 0x8B63, 0x8B70, 0x8B64, 0x63AC, + 0x8B65, 0x83CA, 0x8B66, 0x97A0, 0x8B67, 0x5409, 0x8B68, 0x5403, 0x8B69, 0x55AB, 0x8B6A, 0x6854, 0x8B6B, 0x6A58, 0x8B6C, 0x8A70, + 0x8B6D, 0x7827, 0x8B6E, 0x6775, 0x8B6F, 0x9ECD, 0x8B70, 0x5374, 0x8B71, 0x5BA2, 0x8B72, 0x811A, 0x8B73, 0x8650, 0x8B74, 0x9006, + 0x8B75, 0x4E18, 0x8B76, 0x4E45, 0x8B77, 0x4EC7, 0x8B78, 0x4F11, 0x8B79, 0x53CA, 0x8B7A, 0x5438, 0x8B7B, 0x5BAE, 0x8B7C, 0x5F13, + 0x8B7D, 0x6025, 0x8B7E, 0x6551, 0x8B80, 0x673D, 0x8B81, 0x6C42, 0x8B82, 0x6C72, 0x8B83, 0x6CE3, 0x8B84, 0x7078, 0x8B85, 0x7403, + 0x8B86, 0x7A76, 0x8B87, 0x7AAE, 0x8B88, 0x7B08, 0x8B89, 0x7D1A, 0x8B8A, 0x7CFE, 0x8B8B, 0x7D66, 0x8B8C, 0x65E7, 0x8B8D, 0x725B, + 0x8B8E, 0x53BB, 0x8B8F, 0x5C45, 0x8B90, 0x5DE8, 0x8B91, 0x62D2, 0x8B92, 0x62E0, 0x8B93, 0x6319, 0x8B94, 0x6E20, 0x8B95, 0x865A, + 0x8B96, 0x8A31, 0x8B97, 0x8DDD, 0x8B98, 0x92F8, 0x8B99, 0x6F01, 0x8B9A, 0x79A6, 0x8B9B, 0x9B5A, 0x8B9C, 0x4EA8, 0x8B9D, 0x4EAB, + 0x8B9E, 0x4EAC, 0x8B9F, 0x4F9B, 0x8BA0, 0x4FA0, 0x8BA1, 0x50D1, 0x8BA2, 0x5147, 0x8BA3, 0x7AF6, 0x8BA4, 0x5171, 0x8BA5, 0x51F6, + 0x8BA6, 0x5354, 0x8BA7, 0x5321, 0x8BA8, 0x537F, 0x8BA9, 0x53EB, 0x8BAA, 0x55AC, 0x8BAB, 0x5883, 0x8BAC, 0x5CE1, 0x8BAD, 0x5F37, + 0x8BAE, 0x5F4A, 0x8BAF, 0x602F, 0x8BB0, 0x6050, 0x8BB1, 0x606D, 0x8BB2, 0x631F, 0x8BB3, 0x6559, 0x8BB4, 0x6A4B, 0x8BB5, 0x6CC1, + 0x8BB6, 0x72C2, 0x8BB7, 0x72ED, 0x8BB8, 0x77EF, 0x8BB9, 0x80F8, 0x8BBA, 0x8105, 0x8BBB, 0x8208, 0x8BBC, 0x854E, 0x8BBD, 0x90F7, + 0x8BBE, 0x93E1, 0x8BBF, 0x97FF, 0x8BC0, 0x9957, 0x8BC1, 0x9A5A, 0x8BC2, 0x4EF0, 0x8BC3, 0x51DD, 0x8BC4, 0x5C2D, 0x8BC5, 0x6681, + 0x8BC6, 0x696D, 0x8BC7, 0x5C40, 0x8BC8, 0x66F2, 0x8BC9, 0x6975, 0x8BCA, 0x7389, 0x8BCB, 0x6850, 0x8BCC, 0x7C81, 0x8BCD, 0x50C5, + 0x8BCE, 0x52E4, 0x8BCF, 0x5747, 0x8BD0, 0x5DFE, 0x8BD1, 0x9326, 0x8BD2, 0x65A4, 0x8BD3, 0x6B23, 0x8BD4, 0x6B3D, 0x8BD5, 0x7434, + 0x8BD6, 0x7981, 0x8BD7, 0x79BD, 0x8BD8, 0x7B4B, 0x8BD9, 0x7DCA, 0x8BDA, 0x82B9, 0x8BDB, 0x83CC, 0x8BDC, 0x887F, 0x8BDD, 0x895F, + 0x8BDE, 0x8B39, 0x8BDF, 0x8FD1, 0x8BE0, 0x91D1, 0x8BE1, 0x541F, 0x8BE2, 0x9280, 0x8BE3, 0x4E5D, 0x8BE4, 0x5036, 0x8BE5, 0x53E5, + 0x8BE6, 0x533A, 0x8BE7, 0x72D7, 0x8BE8, 0x7396, 0x8BE9, 0x77E9, 0x8BEA, 0x82E6, 0x8BEB, 0x8EAF, 0x8BEC, 0x99C6, 0x8BED, 0x99C8, + 0x8BEE, 0x99D2, 0x8BEF, 0x5177, 0x8BF0, 0x611A, 0x8BF1, 0x865E, 0x8BF2, 0x55B0, 0x8BF3, 0x7A7A, 0x8BF4, 0x5076, 0x8BF5, 0x5BD3, + 0x8BF6, 0x9047, 0x8BF7, 0x9685, 0x8BF8, 0x4E32, 0x8BF9, 0x6ADB, 0x8BFA, 0x91E7, 0x8BFB, 0x5C51, 0x8BFC, 0x5C48, 0x8C40, 0x6398, + 0x8C41, 0x7A9F, 0x8C42, 0x6C93, 0x8C43, 0x9774, 0x8C44, 0x8F61, 0x8C45, 0x7AAA, 0x8C46, 0x718A, 0x8C47, 0x9688, 0x8C48, 0x7C82, + 0x8C49, 0x6817, 0x8C4A, 0x7E70, 0x8C4B, 0x6851, 0x8C4C, 0x936C, 0x8C4D, 0x52F2, 0x8C4E, 0x541B, 0x8C4F, 0x85AB, 0x8C50, 0x8A13, + 0x8C51, 0x7FA4, 0x8C52, 0x8ECD, 0x8C53, 0x90E1, 0x8C54, 0x5366, 0x8C55, 0x8888, 0x8C56, 0x7941, 0x8C57, 0x4FC2, 0x8C58, 0x50BE, + 0x8C59, 0x5211, 0x8C5A, 0x5144, 0x8C5B, 0x5553, 0x8C5C, 0x572D, 0x8C5D, 0x73EA, 0x8C5E, 0x578B, 0x8C5F, 0x5951, 0x8C60, 0x5F62, + 0x8C61, 0x5F84, 0x8C62, 0x6075, 0x8C63, 0x6176, 0x8C64, 0x6167, 0x8C65, 0x61A9, 0x8C66, 0x63B2, 0x8C67, 0x643A, 0x8C68, 0x656C, + 0x8C69, 0x666F, 0x8C6A, 0x6842, 0x8C6B, 0x6E13, 0x8C6C, 0x7566, 0x8C6D, 0x7A3D, 0x8C6E, 0x7CFB, 0x8C6F, 0x7D4C, 0x8C70, 0x7D99, + 0x8C71, 0x7E4B, 0x8C72, 0x7F6B, 0x8C73, 0x830E, 0x8C74, 0x834A, 0x8C75, 0x86CD, 0x8C76, 0x8A08, 0x8C77, 0x8A63, 0x8C78, 0x8B66, + 0x8C79, 0x8EFD, 0x8C7A, 0x981A, 0x8C7B, 0x9D8F, 0x8C7C, 0x82B8, 0x8C7D, 0x8FCE, 0x8C7E, 0x9BE8, 0x8C80, 0x5287, 0x8C81, 0x621F, + 0x8C82, 0x6483, 0x8C83, 0x6FC0, 0x8C84, 0x9699, 0x8C85, 0x6841, 0x8C86, 0x5091, 0x8C87, 0x6B20, 0x8C88, 0x6C7A, 0x8C89, 0x6F54, + 0x8C8A, 0x7A74, 0x8C8B, 0x7D50, 0x8C8C, 0x8840, 0x8C8D, 0x8A23, 0x8C8E, 0x6708, 0x8C8F, 0x4EF6, 0x8C90, 0x5039, 0x8C91, 0x5026, + 0x8C92, 0x5065, 0x8C93, 0x517C, 0x8C94, 0x5238, 0x8C95, 0x5263, 0x8C96, 0x55A7, 0x8C97, 0x570F, 0x8C98, 0x5805, 0x8C99, 0x5ACC, + 0x8C9A, 0x5EFA, 0x8C9B, 0x61B2, 0x8C9C, 0x61F8, 0x8C9D, 0x62F3, 0x8C9E, 0x6372, 0x8C9F, 0x691C, 0x8CA0, 0x6A29, 0x8CA1, 0x727D, + 0x8CA2, 0x72AC, 0x8CA3, 0x732E, 0x8CA4, 0x7814, 0x8CA5, 0x786F, 0x8CA6, 0x7D79, 0x8CA7, 0x770C, 0x8CA8, 0x80A9, 0x8CA9, 0x898B, + 0x8CAA, 0x8B19, 0x8CAB, 0x8CE2, 0x8CAC, 0x8ED2, 0x8CAD, 0x9063, 0x8CAE, 0x9375, 0x8CAF, 0x967A, 0x8CB0, 0x9855, 0x8CB1, 0x9A13, + 0x8CB2, 0x9E78, 0x8CB3, 0x5143, 0x8CB4, 0x539F, 0x8CB5, 0x53B3, 0x8CB6, 0x5E7B, 0x8CB7, 0x5F26, 0x8CB8, 0x6E1B, 0x8CB9, 0x6E90, + 0x8CBA, 0x7384, 0x8CBB, 0x73FE, 0x8CBC, 0x7D43, 0x8CBD, 0x8237, 0x8CBE, 0x8A00, 0x8CBF, 0x8AFA, 0x8CC0, 0x9650, 0x8CC1, 0x4E4E, + 0x8CC2, 0x500B, 0x8CC3, 0x53E4, 0x8CC4, 0x547C, 0x8CC5, 0x56FA, 0x8CC6, 0x59D1, 0x8CC7, 0x5B64, 0x8CC8, 0x5DF1, 0x8CC9, 0x5EAB, + 0x8CCA, 0x5F27, 0x8CCB, 0x6238, 0x8CCC, 0x6545, 0x8CCD, 0x67AF, 0x8CCE, 0x6E56, 0x8CCF, 0x72D0, 0x8CD0, 0x7CCA, 0x8CD1, 0x88B4, + 0x8CD2, 0x80A1, 0x8CD3, 0x80E1, 0x8CD4, 0x83F0, 0x8CD5, 0x864E, 0x8CD6, 0x8A87, 0x8CD7, 0x8DE8, 0x8CD8, 0x9237, 0x8CD9, 0x96C7, + 0x8CDA, 0x9867, 0x8CDB, 0x9F13, 0x8CDC, 0x4E94, 0x8CDD, 0x4E92, 0x8CDE, 0x4F0D, 0x8CDF, 0x5348, 0x8CE0, 0x5449, 0x8CE1, 0x543E, + 0x8CE2, 0x5A2F, 0x8CE3, 0x5F8C, 0x8CE4, 0x5FA1, 0x8CE5, 0x609F, 0x8CE6, 0x68A7, 0x8CE7, 0x6A8E, 0x8CE8, 0x745A, 0x8CE9, 0x7881, + 0x8CEA, 0x8A9E, 0x8CEB, 0x8AA4, 0x8CEC, 0x8B77, 0x8CED, 0x9190, 0x8CEE, 0x4E5E, 0x8CEF, 0x9BC9, 0x8CF0, 0x4EA4, 0x8CF1, 0x4F7C, + 0x8CF2, 0x4FAF, 0x8CF3, 0x5019, 0x8CF4, 0x5016, 0x8CF5, 0x5149, 0x8CF6, 0x516C, 0x8CF7, 0x529F, 0x8CF8, 0x52B9, 0x8CF9, 0x52FE, + 0x8CFA, 0x539A, 0x8CFB, 0x53E3, 0x8CFC, 0x5411, 0x8D40, 0x540E, 0x8D41, 0x5589, 0x8D42, 0x5751, 0x8D43, 0x57A2, 0x8D44, 0x597D, + 0x8D45, 0x5B54, 0x8D46, 0x5B5D, 0x8D47, 0x5B8F, 0x8D48, 0x5DE5, 0x8D49, 0x5DE7, 0x8D4A, 0x5DF7, 0x8D4B, 0x5E78, 0x8D4C, 0x5E83, + 0x8D4D, 0x5E9A, 0x8D4E, 0x5EB7, 0x8D4F, 0x5F18, 0x8D50, 0x6052, 0x8D51, 0x614C, 0x8D52, 0x6297, 0x8D53, 0x62D8, 0x8D54, 0x63A7, + 0x8D55, 0x653B, 0x8D56, 0x6602, 0x8D57, 0x6643, 0x8D58, 0x66F4, 0x8D59, 0x676D, 0x8D5A, 0x6821, 0x8D5B, 0x6897, 0x8D5C, 0x69CB, + 0x8D5D, 0x6C5F, 0x8D5E, 0x6D2A, 0x8D5F, 0x6D69, 0x8D60, 0x6E2F, 0x8D61, 0x6E9D, 0x8D62, 0x7532, 0x8D63, 0x7687, 0x8D64, 0x786C, + 0x8D65, 0x7A3F, 0x8D66, 0x7CE0, 0x8D67, 0x7D05, 0x8D68, 0x7D18, 0x8D69, 0x7D5E, 0x8D6A, 0x7DB1, 0x8D6B, 0x8015, 0x8D6C, 0x8003, + 0x8D6D, 0x80AF, 0x8D6E, 0x80B1, 0x8D6F, 0x8154, 0x8D70, 0x818F, 0x8D71, 0x822A, 0x8D72, 0x8352, 0x8D73, 0x884C, 0x8D74, 0x8861, + 0x8D75, 0x8B1B, 0x8D76, 0x8CA2, 0x8D77, 0x8CFC, 0x8D78, 0x90CA, 0x8D79, 0x9175, 0x8D7A, 0x9271, 0x8D7B, 0x783F, 0x8D7C, 0x92FC, + 0x8D7D, 0x95A4, 0x8D7E, 0x964D, 0x8D80, 0x9805, 0x8D81, 0x9999, 0x8D82, 0x9AD8, 0x8D83, 0x9D3B, 0x8D84, 0x525B, 0x8D85, 0x52AB, + 0x8D86, 0x53F7, 0x8D87, 0x5408, 0x8D88, 0x58D5, 0x8D89, 0x62F7, 0x8D8A, 0x6FE0, 0x8D8B, 0x8C6A, 0x8D8C, 0x8F5F, 0x8D8D, 0x9EB9, + 0x8D8E, 0x514B, 0x8D8F, 0x523B, 0x8D90, 0x544A, 0x8D91, 0x56FD, 0x8D92, 0x7A40, 0x8D93, 0x9177, 0x8D94, 0x9D60, 0x8D95, 0x9ED2, + 0x8D96, 0x7344, 0x8D97, 0x6F09, 0x8D98, 0x8170, 0x8D99, 0x7511, 0x8D9A, 0x5FFD, 0x8D9B, 0x60DA, 0x8D9C, 0x9AA8, 0x8D9D, 0x72DB, + 0x8D9E, 0x8FBC, 0x8D9F, 0x6B64, 0x8DA0, 0x9803, 0x8DA1, 0x4ECA, 0x8DA2, 0x56F0, 0x8DA3, 0x5764, 0x8DA4, 0x58BE, 0x8DA5, 0x5A5A, + 0x8DA6, 0x6068, 0x8DA7, 0x61C7, 0x8DA8, 0x660F, 0x8DA9, 0x6606, 0x8DAA, 0x6839, 0x8DAB, 0x68B1, 0x8DAC, 0x6DF7, 0x8DAD, 0x75D5, + 0x8DAE, 0x7D3A, 0x8DAF, 0x826E, 0x8DB0, 0x9B42, 0x8DB1, 0x4E9B, 0x8DB2, 0x4F50, 0x8DB3, 0x53C9, 0x8DB4, 0x5506, 0x8DB5, 0x5D6F, + 0x8DB6, 0x5DE6, 0x8DB7, 0x5DEE, 0x8DB8, 0x67FB, 0x8DB9, 0x6C99, 0x8DBA, 0x7473, 0x8DBB, 0x7802, 0x8DBC, 0x8A50, 0x8DBD, 0x9396, + 0x8DBE, 0x88DF, 0x8DBF, 0x5750, 0x8DC0, 0x5EA7, 0x8DC1, 0x632B, 0x8DC2, 0x50B5, 0x8DC3, 0x50AC, 0x8DC4, 0x518D, 0x8DC5, 0x6700, + 0x8DC6, 0x54C9, 0x8DC7, 0x585E, 0x8DC8, 0x59BB, 0x8DC9, 0x5BB0, 0x8DCA, 0x5F69, 0x8DCB, 0x624D, 0x8DCC, 0x63A1, 0x8DCD, 0x683D, + 0x8DCE, 0x6B73, 0x8DCF, 0x6E08, 0x8DD0, 0x707D, 0x8DD1, 0x91C7, 0x8DD2, 0x7280, 0x8DD3, 0x7815, 0x8DD4, 0x7826, 0x8DD5, 0x796D, + 0x8DD6, 0x658E, 0x8DD7, 0x7D30, 0x8DD8, 0x83DC, 0x8DD9, 0x88C1, 0x8DDA, 0x8F09, 0x8DDB, 0x969B, 0x8DDC, 0x5264, 0x8DDD, 0x5728, + 0x8DDE, 0x6750, 0x8DDF, 0x7F6A, 0x8DE0, 0x8CA1, 0x8DE1, 0x51B4, 0x8DE2, 0x5742, 0x8DE3, 0x962A, 0x8DE4, 0x583A, 0x8DE5, 0x698A, + 0x8DE6, 0x80B4, 0x8DE7, 0x54B2, 0x8DE8, 0x5D0E, 0x8DE9, 0x57FC, 0x8DEA, 0x7895, 0x8DEB, 0x9DFA, 0x8DEC, 0x4F5C, 0x8DED, 0x524A, + 0x8DEE, 0x548B, 0x8DEF, 0x643E, 0x8DF0, 0x6628, 0x8DF1, 0x6714, 0x8DF2, 0x67F5, 0x8DF3, 0x7A84, 0x8DF4, 0x7B56, 0x8DF5, 0x7D22, + 0x8DF6, 0x932F, 0x8DF7, 0x685C, 0x8DF8, 0x9BAD, 0x8DF9, 0x7B39, 0x8DFA, 0x5319, 0x8DFB, 0x518A, 0x8DFC, 0x5237, 0x8E40, 0x5BDF, + 0x8E41, 0x62F6, 0x8E42, 0x64AE, 0x8E43, 0x64E6, 0x8E44, 0x672D, 0x8E45, 0x6BBA, 0x8E46, 0x85A9, 0x8E47, 0x96D1, 0x8E48, 0x7690, + 0x8E49, 0x9BD6, 0x8E4A, 0x634C, 0x8E4B, 0x9306, 0x8E4C, 0x9BAB, 0x8E4D, 0x76BF, 0x8E4E, 0x6652, 0x8E4F, 0x4E09, 0x8E50, 0x5098, + 0x8E51, 0x53C2, 0x8E52, 0x5C71, 0x8E53, 0x60E8, 0x8E54, 0x6492, 0x8E55, 0x6563, 0x8E56, 0x685F, 0x8E57, 0x71E6, 0x8E58, 0x73CA, + 0x8E59, 0x7523, 0x8E5A, 0x7B97, 0x8E5B, 0x7E82, 0x8E5C, 0x8695, 0x8E5D, 0x8B83, 0x8E5E, 0x8CDB, 0x8E5F, 0x9178, 0x8E60, 0x9910, + 0x8E61, 0x65AC, 0x8E62, 0x66AB, 0x8E63, 0x6B8B, 0x8E64, 0x4ED5, 0x8E65, 0x4ED4, 0x8E66, 0x4F3A, 0x8E67, 0x4F7F, 0x8E68, 0x523A, + 0x8E69, 0x53F8, 0x8E6A, 0x53F2, 0x8E6B, 0x55E3, 0x8E6C, 0x56DB, 0x8E6D, 0x58EB, 0x8E6E, 0x59CB, 0x8E6F, 0x59C9, 0x8E70, 0x59FF, + 0x8E71, 0x5B50, 0x8E72, 0x5C4D, 0x8E73, 0x5E02, 0x8E74, 0x5E2B, 0x8E75, 0x5FD7, 0x8E76, 0x601D, 0x8E77, 0x6307, 0x8E78, 0x652F, + 0x8E79, 0x5B5C, 0x8E7A, 0x65AF, 0x8E7B, 0x65BD, 0x8E7C, 0x65E8, 0x8E7D, 0x679D, 0x8E7E, 0x6B62, 0x8E80, 0x6B7B, 0x8E81, 0x6C0F, + 0x8E82, 0x7345, 0x8E83, 0x7949, 0x8E84, 0x79C1, 0x8E85, 0x7CF8, 0x8E86, 0x7D19, 0x8E87, 0x7D2B, 0x8E88, 0x80A2, 0x8E89, 0x8102, + 0x8E8A, 0x81F3, 0x8E8B, 0x8996, 0x8E8C, 0x8A5E, 0x8E8D, 0x8A69, 0x8E8E, 0x8A66, 0x8E8F, 0x8A8C, 0x8E90, 0x8AEE, 0x8E91, 0x8CC7, + 0x8E92, 0x8CDC, 0x8E93, 0x96CC, 0x8E94, 0x98FC, 0x8E95, 0x6B6F, 0x8E96, 0x4E8B, 0x8E97, 0x4F3C, 0x8E98, 0x4F8D, 0x8E99, 0x5150, + 0x8E9A, 0x5B57, 0x8E9B, 0x5BFA, 0x8E9C, 0x6148, 0x8E9D, 0x6301, 0x8E9E, 0x6642, 0x8E9F, 0x6B21, 0x8EA0, 0x6ECB, 0x8EA1, 0x6CBB, + 0x8EA2, 0x723E, 0x8EA3, 0x74BD, 0x8EA4, 0x75D4, 0x8EA5, 0x78C1, 0x8EA6, 0x793A, 0x8EA7, 0x800C, 0x8EA8, 0x8033, 0x8EA9, 0x81EA, + 0x8EAA, 0x8494, 0x8EAB, 0x8F9E, 0x8EAC, 0x6C50, 0x8EAD, 0x9E7F, 0x8EAE, 0x5F0F, 0x8EAF, 0x8B58, 0x8EB0, 0x9D2B, 0x8EB1, 0x7AFA, + 0x8EB2, 0x8EF8, 0x8EB3, 0x5B8D, 0x8EB4, 0x96EB, 0x8EB5, 0x4E03, 0x8EB6, 0x53F1, 0x8EB7, 0x57F7, 0x8EB8, 0x5931, 0x8EB9, 0x5AC9, + 0x8EBA, 0x5BA4, 0x8EBB, 0x6089, 0x8EBC, 0x6E7F, 0x8EBD, 0x6F06, 0x8EBE, 0x75BE, 0x8EBF, 0x8CEA, 0x8EC0, 0x5B9F, 0x8EC1, 0x8500, + 0x8EC2, 0x7BE0, 0x8EC3, 0x5072, 0x8EC4, 0x67F4, 0x8EC5, 0x829D, 0x8EC6, 0x5C61, 0x8EC7, 0x854A, 0x8EC8, 0x7E1E, 0x8EC9, 0x820E, + 0x8ECA, 0x5199, 0x8ECB, 0x5C04, 0x8ECC, 0x6368, 0x8ECD, 0x8D66, 0x8ECE, 0x659C, 0x8ECF, 0x716E, 0x8ED0, 0x793E, 0x8ED1, 0x7D17, + 0x8ED2, 0x8005, 0x8ED3, 0x8B1D, 0x8ED4, 0x8ECA, 0x8ED5, 0x906E, 0x8ED6, 0x86C7, 0x8ED7, 0x90AA, 0x8ED8, 0x501F, 0x8ED9, 0x52FA, + 0x8EDA, 0x5C3A, 0x8EDB, 0x6753, 0x8EDC, 0x707C, 0x8EDD, 0x7235, 0x8EDE, 0x914C, 0x8EDF, 0x91C8, 0x8EE0, 0x932B, 0x8EE1, 0x82E5, + 0x8EE2, 0x5BC2, 0x8EE3, 0x5F31, 0x8EE4, 0x60F9, 0x8EE5, 0x4E3B, 0x8EE6, 0x53D6, 0x8EE7, 0x5B88, 0x8EE8, 0x624B, 0x8EE9, 0x6731, + 0x8EEA, 0x6B8A, 0x8EEB, 0x72E9, 0x8EEC, 0x73E0, 0x8EED, 0x7A2E, 0x8EEE, 0x816B, 0x8EEF, 0x8DA3, 0x8EF0, 0x9152, 0x8EF1, 0x9996, + 0x8EF2, 0x5112, 0x8EF3, 0x53D7, 0x8EF4, 0x546A, 0x8EF5, 0x5BFF, 0x8EF6, 0x6388, 0x8EF7, 0x6A39, 0x8EF8, 0x7DAC, 0x8EF9, 0x9700, + 0x8EFA, 0x56DA, 0x8EFB, 0x53CE, 0x8EFC, 0x5468, 0x8F40, 0x5B97, 0x8F41, 0x5C31, 0x8F42, 0x5DDE, 0x8F43, 0x4FEE, 0x8F44, 0x6101, + 0x8F45, 0x62FE, 0x8F46, 0x6D32, 0x8F47, 0x79C0, 0x8F48, 0x79CB, 0x8F49, 0x7D42, 0x8F4A, 0x7E4D, 0x8F4B, 0x7FD2, 0x8F4C, 0x81ED, + 0x8F4D, 0x821F, 0x8F4E, 0x8490, 0x8F4F, 0x8846, 0x8F50, 0x8972, 0x8F51, 0x8B90, 0x8F52, 0x8E74, 0x8F53, 0x8F2F, 0x8F54, 0x9031, + 0x8F55, 0x914B, 0x8F56, 0x916C, 0x8F57, 0x96C6, 0x8F58, 0x919C, 0x8F59, 0x4EC0, 0x8F5A, 0x4F4F, 0x8F5B, 0x5145, 0x8F5C, 0x5341, + 0x8F5D, 0x5F93, 0x8F5E, 0x620E, 0x8F5F, 0x67D4, 0x8F60, 0x6C41, 0x8F61, 0x6E0B, 0x8F62, 0x7363, 0x8F63, 0x7E26, 0x8F64, 0x91CD, + 0x8F65, 0x9283, 0x8F66, 0x53D4, 0x8F67, 0x5919, 0x8F68, 0x5BBF, 0x8F69, 0x6DD1, 0x8F6A, 0x795D, 0x8F6B, 0x7E2E, 0x8F6C, 0x7C9B, + 0x8F6D, 0x587E, 0x8F6E, 0x719F, 0x8F6F, 0x51FA, 0x8F70, 0x8853, 0x8F71, 0x8FF0, 0x8F72, 0x4FCA, 0x8F73, 0x5CFB, 0x8F74, 0x6625, + 0x8F75, 0x77AC, 0x8F76, 0x7AE3, 0x8F77, 0x821C, 0x8F78, 0x99FF, 0x8F79, 0x51C6, 0x8F7A, 0x5FAA, 0x8F7B, 0x65EC, 0x8F7C, 0x696F, + 0x8F7D, 0x6B89, 0x8F7E, 0x6DF3, 0x8F80, 0x6E96, 0x8F81, 0x6F64, 0x8F82, 0x76FE, 0x8F83, 0x7D14, 0x8F84, 0x5DE1, 0x8F85, 0x9075, + 0x8F86, 0x9187, 0x8F87, 0x9806, 0x8F88, 0x51E6, 0x8F89, 0x521D, 0x8F8A, 0x6240, 0x8F8B, 0x6691, 0x8F8C, 0x66D9, 0x8F8D, 0x6E1A, + 0x8F8E, 0x5EB6, 0x8F8F, 0x7DD2, 0x8F90, 0x7F72, 0x8F91, 0x66F8, 0x8F92, 0x85AF, 0x8F93, 0x85F7, 0x8F94, 0x8AF8, 0x8F95, 0x52A9, + 0x8F96, 0x53D9, 0x8F97, 0x5973, 0x8F98, 0x5E8F, 0x8F99, 0x5F90, 0x8F9A, 0x6055, 0x8F9B, 0x92E4, 0x8F9C, 0x9664, 0x8F9D, 0x50B7, + 0x8F9E, 0x511F, 0x8F9F, 0x52DD, 0x8FA0, 0x5320, 0x8FA1, 0x5347, 0x8FA2, 0x53EC, 0x8FA3, 0x54E8, 0x8FA4, 0x5546, 0x8FA5, 0x5531, + 0x8FA6, 0x5617, 0x8FA7, 0x5968, 0x8FA8, 0x59BE, 0x8FA9, 0x5A3C, 0x8FAA, 0x5BB5, 0x8FAB, 0x5C06, 0x8FAC, 0x5C0F, 0x8FAD, 0x5C11, + 0x8FAE, 0x5C1A, 0x8FAF, 0x5E84, 0x8FB0, 0x5E8A, 0x8FB1, 0x5EE0, 0x8FB2, 0x5F70, 0x8FB3, 0x627F, 0x8FB4, 0x6284, 0x8FB5, 0x62DB, + 0x8FB6, 0x638C, 0x8FB7, 0x6377, 0x8FB8, 0x6607, 0x8FB9, 0x660C, 0x8FBA, 0x662D, 0x8FBB, 0x6676, 0x8FBC, 0x677E, 0x8FBD, 0x68A2, + 0x8FBE, 0x6A1F, 0x8FBF, 0x6A35, 0x8FC0, 0x6CBC, 0x8FC1, 0x6D88, 0x8FC2, 0x6E09, 0x8FC3, 0x6E58, 0x8FC4, 0x713C, 0x8FC5, 0x7126, + 0x8FC6, 0x7167, 0x8FC7, 0x75C7, 0x8FC8, 0x7701, 0x8FC9, 0x785D, 0x8FCA, 0x7901, 0x8FCB, 0x7965, 0x8FCC, 0x79F0, 0x8FCD, 0x7AE0, + 0x8FCE, 0x7B11, 0x8FCF, 0x7CA7, 0x8FD0, 0x7D39, 0x8FD1, 0x8096, 0x8FD2, 0x83D6, 0x8FD3, 0x848B, 0x8FD4, 0x8549, 0x8FD5, 0x885D, + 0x8FD6, 0x88F3, 0x8FD7, 0x8A1F, 0x8FD8, 0x8A3C, 0x8FD9, 0x8A54, 0x8FDA, 0x8A73, 0x8FDB, 0x8C61, 0x8FDC, 0x8CDE, 0x8FDD, 0x91A4, + 0x8FDE, 0x9266, 0x8FDF, 0x937E, 0x8FE0, 0x9418, 0x8FE1, 0x969C, 0x8FE2, 0x9798, 0x8FE3, 0x4E0A, 0x8FE4, 0x4E08, 0x8FE5, 0x4E1E, + 0x8FE6, 0x4E57, 0x8FE7, 0x5197, 0x8FE8, 0x5270, 0x8FE9, 0x57CE, 0x8FEA, 0x5834, 0x8FEB, 0x58CC, 0x8FEC, 0x5B22, 0x8FED, 0x5E38, + 0x8FEE, 0x60C5, 0x8FEF, 0x64FE, 0x8FF0, 0x6761, 0x8FF1, 0x6756, 0x8FF2, 0x6D44, 0x8FF3, 0x72B6, 0x8FF4, 0x7573, 0x8FF5, 0x7A63, + 0x8FF6, 0x84B8, 0x8FF7, 0x8B72, 0x8FF8, 0x91B8, 0x8FF9, 0x9320, 0x8FFA, 0x5631, 0x8FFB, 0x57F4, 0x8FFC, 0x98FE, 0x9040, 0x62ED, + 0x9041, 0x690D, 0x9042, 0x6B96, 0x9043, 0x71ED, 0x9044, 0x7E54, 0x9045, 0x8077, 0x9046, 0x8272, 0x9047, 0x89E6, 0x9048, 0x98DF, + 0x9049, 0x8755, 0x904A, 0x8FB1, 0x904B, 0x5C3B, 0x904C, 0x4F38, 0x904D, 0x4FE1, 0x904E, 0x4FB5, 0x904F, 0x5507, 0x9050, 0x5A20, + 0x9051, 0x5BDD, 0x9052, 0x5BE9, 0x9053, 0x5FC3, 0x9054, 0x614E, 0x9055, 0x632F, 0x9056, 0x65B0, 0x9057, 0x664B, 0x9058, 0x68EE, + 0x9059, 0x699B, 0x905A, 0x6D78, 0x905B, 0x6DF1, 0x905C, 0x7533, 0x905D, 0x75B9, 0x905E, 0x771F, 0x905F, 0x795E, 0x9060, 0x79E6, + 0x9061, 0x7D33, 0x9062, 0x81E3, 0x9063, 0x82AF, 0x9064, 0x85AA, 0x9065, 0x89AA, 0x9066, 0x8A3A, 0x9067, 0x8EAB, 0x9068, 0x8F9B, + 0x9069, 0x9032, 0x906A, 0x91DD, 0x906B, 0x9707, 0x906C, 0x4EBA, 0x906D, 0x4EC1, 0x906E, 0x5203, 0x906F, 0x5875, 0x9070, 0x58EC, + 0x9071, 0x5C0B, 0x9072, 0x751A, 0x9073, 0x5C3D, 0x9074, 0x814E, 0x9075, 0x8A0A, 0x9076, 0x8FC5, 0x9077, 0x9663, 0x9078, 0x976D, + 0x9079, 0x7B25, 0x907A, 0x8ACF, 0x907B, 0x9808, 0x907C, 0x9162, 0x907D, 0x56F3, 0x907E, 0x53A8, 0x9080, 0x9017, 0x9081, 0x5439, + 0x9082, 0x5782, 0x9083, 0x5E25, 0x9084, 0x63A8, 0x9085, 0x6C34, 0x9086, 0x708A, 0x9087, 0x7761, 0x9088, 0x7C8B, 0x9089, 0x7FE0, + 0x908A, 0x8870, 0x908B, 0x9042, 0x908C, 0x9154, 0x908D, 0x9310, 0x908E, 0x9318, 0x908F, 0x968F, 0x9090, 0x745E, 0x9091, 0x9AC4, + 0x9092, 0x5D07, 0x9093, 0x5D69, 0x9094, 0x6570, 0x9095, 0x67A2, 0x9096, 0x8DA8, 0x9097, 0x96DB, 0x9098, 0x636E, 0x9099, 0x6749, + 0x909A, 0x6919, 0x909B, 0x83C5, 0x909C, 0x9817, 0x909D, 0x96C0, 0x909E, 0x88FE, 0x909F, 0x6F84, 0x90A0, 0x647A, 0x90A1, 0x5BF8, + 0x90A2, 0x4E16, 0x90A3, 0x702C, 0x90A4, 0x755D, 0x90A5, 0x662F, 0x90A6, 0x51C4, 0x90A7, 0x5236, 0x90A8, 0x52E2, 0x90A9, 0x59D3, + 0x90AA, 0x5F81, 0x90AB, 0x6027, 0x90AC, 0x6210, 0x90AD, 0x653F, 0x90AE, 0x6574, 0x90AF, 0x661F, 0x90B0, 0x6674, 0x90B1, 0x68F2, + 0x90B2, 0x6816, 0x90B3, 0x6B63, 0x90B4, 0x6E05, 0x90B5, 0x7272, 0x90B6, 0x751F, 0x90B7, 0x76DB, 0x90B8, 0x7CBE, 0x90B9, 0x8056, + 0x90BA, 0x58F0, 0x90BB, 0x88FD, 0x90BC, 0x897F, 0x90BD, 0x8AA0, 0x90BE, 0x8A93, 0x90BF, 0x8ACB, 0x90C0, 0x901D, 0x90C1, 0x9192, + 0x90C2, 0x9752, 0x90C3, 0x9759, 0x90C4, 0x6589, 0x90C5, 0x7A0E, 0x90C6, 0x8106, 0x90C7, 0x96BB, 0x90C8, 0x5E2D, 0x90C9, 0x60DC, + 0x90CA, 0x621A, 0x90CB, 0x65A5, 0x90CC, 0x6614, 0x90CD, 0x6790, 0x90CE, 0x77F3, 0x90CF, 0x7A4D, 0x90D0, 0x7C4D, 0x90D1, 0x7E3E, + 0x90D2, 0x810A, 0x90D3, 0x8CAC, 0x90D4, 0x8D64, 0x90D5, 0x8DE1, 0x90D6, 0x8E5F, 0x90D7, 0x78A9, 0x90D8, 0x5207, 0x90D9, 0x62D9, + 0x90DA, 0x63A5, 0x90DB, 0x6442, 0x90DC, 0x6298, 0x90DD, 0x8A2D, 0x90DE, 0x7A83, 0x90DF, 0x7BC0, 0x90E0, 0x8AAC, 0x90E1, 0x96EA, + 0x90E2, 0x7D76, 0x90E3, 0x820C, 0x90E4, 0x8749, 0x90E5, 0x4ED9, 0x90E6, 0x5148, 0x90E7, 0x5343, 0x90E8, 0x5360, 0x90E9, 0x5BA3, + 0x90EA, 0x5C02, 0x90EB, 0x5C16, 0x90EC, 0x5DDD, 0x90ED, 0x6226, 0x90EE, 0x6247, 0x90EF, 0x64B0, 0x90F0, 0x6813, 0x90F1, 0x6834, + 0x90F2, 0x6CC9, 0x90F3, 0x6D45, 0x90F4, 0x6D17, 0x90F5, 0x67D3, 0x90F6, 0x6F5C, 0x90F7, 0x714E, 0x90F8, 0x717D, 0x90F9, 0x65CB, + 0x90FA, 0x7A7F, 0x90FB, 0x7BAD, 0x90FC, 0x7DDA, 0x9140, 0x7E4A, 0x9141, 0x7FA8, 0x9142, 0x817A, 0x9143, 0x821B, 0x9144, 0x8239, + 0x9145, 0x85A6, 0x9146, 0x8A6E, 0x9147, 0x8CCE, 0x9148, 0x8DF5, 0x9149, 0x9078, 0x914A, 0x9077, 0x914B, 0x92AD, 0x914C, 0x9291, + 0x914D, 0x9583, 0x914E, 0x9BAE, 0x914F, 0x524D, 0x9150, 0x5584, 0x9151, 0x6F38, 0x9152, 0x7136, 0x9153, 0x5168, 0x9154, 0x7985, + 0x9155, 0x7E55, 0x9156, 0x81B3, 0x9157, 0x7CCE, 0x9158, 0x564C, 0x9159, 0x5851, 0x915A, 0x5CA8, 0x915B, 0x63AA, 0x915C, 0x66FE, + 0x915D, 0x66FD, 0x915E, 0x695A, 0x915F, 0x72D9, 0x9160, 0x758F, 0x9161, 0x758E, 0x9162, 0x790E, 0x9163, 0x7956, 0x9164, 0x79DF, + 0x9165, 0x7C97, 0x9166, 0x7D20, 0x9167, 0x7D44, 0x9168, 0x8607, 0x9169, 0x8A34, 0x916A, 0x963B, 0x916B, 0x9061, 0x916C, 0x9F20, + 0x916D, 0x50E7, 0x916E, 0x5275, 0x916F, 0x53CC, 0x9170, 0x53E2, 0x9171, 0x5009, 0x9172, 0x55AA, 0x9173, 0x58EE, 0x9174, 0x594F, + 0x9175, 0x723D, 0x9176, 0x5B8B, 0x9177, 0x5C64, 0x9178, 0x531D, 0x9179, 0x60E3, 0x917A, 0x60F3, 0x917B, 0x635C, 0x917C, 0x6383, + 0x917D, 0x633F, 0x917E, 0x63BB, 0x9180, 0x64CD, 0x9181, 0x65E9, 0x9182, 0x66F9, 0x9183, 0x5DE3, 0x9184, 0x69CD, 0x9185, 0x69FD, + 0x9186, 0x6F15, 0x9187, 0x71E5, 0x9188, 0x4E89, 0x9189, 0x75E9, 0x918A, 0x76F8, 0x918B, 0x7A93, 0x918C, 0x7CDF, 0x918D, 0x7DCF, + 0x918E, 0x7D9C, 0x918F, 0x8061, 0x9190, 0x8349, 0x9191, 0x8358, 0x9192, 0x846C, 0x9193, 0x84BC, 0x9194, 0x85FB, 0x9195, 0x88C5, + 0x9196, 0x8D70, 0x9197, 0x9001, 0x9198, 0x906D, 0x9199, 0x9397, 0x919A, 0x971C, 0x919B, 0x9A12, 0x919C, 0x50CF, 0x919D, 0x5897, + 0x919E, 0x618E, 0x919F, 0x81D3, 0x91A0, 0x8535, 0x91A1, 0x8D08, 0x91A2, 0x9020, 0x91A3, 0x4FC3, 0x91A4, 0x5074, 0x91A5, 0x5247, + 0x91A6, 0x5373, 0x91A7, 0x606F, 0x91A8, 0x6349, 0x91A9, 0x675F, 0x91AA, 0x6E2C, 0x91AB, 0x8DB3, 0x91AC, 0x901F, 0x91AD, 0x4FD7, + 0x91AE, 0x5C5E, 0x91AF, 0x8CCA, 0x91B0, 0x65CF, 0x91B1, 0x7D9A, 0x91B2, 0x5352, 0x91B3, 0x8896, 0x91B4, 0x5176, 0x91B5, 0x63C3, + 0x91B6, 0x5B58, 0x91B7, 0x5B6B, 0x91B8, 0x5C0A, 0x91B9, 0x640D, 0x91BA, 0x6751, 0x91BB, 0x905C, 0x91BC, 0x4ED6, 0x91BD, 0x591A, + 0x91BE, 0x592A, 0x91BF, 0x6C70, 0x91C0, 0x8A51, 0x91C1, 0x553E, 0x91C2, 0x5815, 0x91C3, 0x59A5, 0x91C4, 0x60F0, 0x91C5, 0x6253, + 0x91C6, 0x67C1, 0x91C7, 0x8235, 0x91C8, 0x6955, 0x91C9, 0x9640, 0x91CA, 0x99C4, 0x91CB, 0x9A28, 0x91CC, 0x4F53, 0x91CD, 0x5806, + 0x91CE, 0x5BFE, 0x91CF, 0x8010, 0x91D0, 0x5CB1, 0x91D1, 0x5E2F, 0x91D2, 0x5F85, 0x91D3, 0x6020, 0x91D4, 0x614B, 0x91D5, 0x6234, + 0x91D6, 0x66FF, 0x91D7, 0x6CF0, 0x91D8, 0x6EDE, 0x91D9, 0x80CE, 0x91DA, 0x817F, 0x91DB, 0x82D4, 0x91DC, 0x888B, 0x91DD, 0x8CB8, + 0x91DE, 0x9000, 0x91DF, 0x902E, 0x91E0, 0x968A, 0x91E1, 0x9EDB, 0x91E2, 0x9BDB, 0x91E3, 0x4EE3, 0x91E4, 0x53F0, 0x91E5, 0x5927, + 0x91E6, 0x7B2C, 0x91E7, 0x918D, 0x91E8, 0x984C, 0x91E9, 0x9DF9, 0x91EA, 0x6EDD, 0x91EB, 0x7027, 0x91EC, 0x5353, 0x91ED, 0x5544, + 0x91EE, 0x5B85, 0x91EF, 0x6258, 0x91F0, 0x629E, 0x91F1, 0x62D3, 0x91F2, 0x6CA2, 0x91F3, 0x6FEF, 0x91F4, 0x7422, 0x91F5, 0x8A17, + 0x91F6, 0x9438, 0x91F7, 0x6FC1, 0x91F8, 0x8AFE, 0x91F9, 0x8338, 0x91FA, 0x51E7, 0x91FB, 0x86F8, 0x91FC, 0x53EA, 0x9240, 0x53E9, + 0x9241, 0x4F46, 0x9242, 0x9054, 0x9243, 0x8FB0, 0x9244, 0x596A, 0x9245, 0x8131, 0x9246, 0x5DFD, 0x9247, 0x7AEA, 0x9248, 0x8FBF, + 0x9249, 0x68DA, 0x924A, 0x8C37, 0x924B, 0x72F8, 0x924C, 0x9C48, 0x924D, 0x6A3D, 0x924E, 0x8AB0, 0x924F, 0x4E39, 0x9250, 0x5358, + 0x9251, 0x5606, 0x9252, 0x5766, 0x9253, 0x62C5, 0x9254, 0x63A2, 0x9255, 0x65E6, 0x9256, 0x6B4E, 0x9257, 0x6DE1, 0x9258, 0x6E5B, + 0x9259, 0x70AD, 0x925A, 0x77ED, 0x925B, 0x7AEF, 0x925C, 0x7BAA, 0x925D, 0x7DBB, 0x925E, 0x803D, 0x925F, 0x80C6, 0x9260, 0x86CB, + 0x9261, 0x8A95, 0x9262, 0x935B, 0x9263, 0x56E3, 0x9264, 0x58C7, 0x9265, 0x5F3E, 0x9266, 0x65AD, 0x9267, 0x6696, 0x9268, 0x6A80, + 0x9269, 0x6BB5, 0x926A, 0x7537, 0x926B, 0x8AC7, 0x926C, 0x5024, 0x926D, 0x77E5, 0x926E, 0x5730, 0x926F, 0x5F1B, 0x9270, 0x6065, + 0x9271, 0x667A, 0x9272, 0x6C60, 0x9273, 0x75F4, 0x9274, 0x7A1A, 0x9275, 0x7F6E, 0x9276, 0x81F4, 0x9277, 0x8718, 0x9278, 0x9045, + 0x9279, 0x99B3, 0x927A, 0x7BC9, 0x927B, 0x755C, 0x927C, 0x7AF9, 0x927D, 0x7B51, 0x927E, 0x84C4, 0x9280, 0x9010, 0x9281, 0x79E9, + 0x9282, 0x7A92, 0x9283, 0x8336, 0x9284, 0x5AE1, 0x9285, 0x7740, 0x9286, 0x4E2D, 0x9287, 0x4EF2, 0x9288, 0x5B99, 0x9289, 0x5FE0, + 0x928A, 0x62BD, 0x928B, 0x663C, 0x928C, 0x67F1, 0x928D, 0x6CE8, 0x928E, 0x866B, 0x928F, 0x8877, 0x9290, 0x8A3B, 0x9291, 0x914E, + 0x9292, 0x92F3, 0x9293, 0x99D0, 0x9294, 0x6A17, 0x9295, 0x7026, 0x9296, 0x732A, 0x9297, 0x82E7, 0x9298, 0x8457, 0x9299, 0x8CAF, + 0x929A, 0x4E01, 0x929B, 0x5146, 0x929C, 0x51CB, 0x929D, 0x558B, 0x929E, 0x5BF5, 0x929F, 0x5E16, 0x92A0, 0x5E33, 0x92A1, 0x5E81, + 0x92A2, 0x5F14, 0x92A3, 0x5F35, 0x92A4, 0x5F6B, 0x92A5, 0x5FB4, 0x92A6, 0x61F2, 0x92A7, 0x6311, 0x92A8, 0x66A2, 0x92A9, 0x671D, + 0x92AA, 0x6F6E, 0x92AB, 0x7252, 0x92AC, 0x753A, 0x92AD, 0x773A, 0x92AE, 0x8074, 0x92AF, 0x8139, 0x92B0, 0x8178, 0x92B1, 0x8776, + 0x92B2, 0x8ABF, 0x92B3, 0x8ADC, 0x92B4, 0x8D85, 0x92B5, 0x8DF3, 0x92B6, 0x929A, 0x92B7, 0x9577, 0x92B8, 0x9802, 0x92B9, 0x9CE5, + 0x92BA, 0x52C5, 0x92BB, 0x6357, 0x92BC, 0x76F4, 0x92BD, 0x6715, 0x92BE, 0x6C88, 0x92BF, 0x73CD, 0x92C0, 0x8CC3, 0x92C1, 0x93AE, + 0x92C2, 0x9673, 0x92C3, 0x6D25, 0x92C4, 0x589C, 0x92C5, 0x690E, 0x92C6, 0x69CC, 0x92C7, 0x8FFD, 0x92C8, 0x939A, 0x92C9, 0x75DB, + 0x92CA, 0x901A, 0x92CB, 0x585A, 0x92CC, 0x6802, 0x92CD, 0x63B4, 0x92CE, 0x69FB, 0x92CF, 0x4F43, 0x92D0, 0x6F2C, 0x92D1, 0x67D8, + 0x92D2, 0x8FBB, 0x92D3, 0x8526, 0x92D4, 0x7DB4, 0x92D5, 0x9354, 0x92D6, 0x693F, 0x92D7, 0x6F70, 0x92D8, 0x576A, 0x92D9, 0x58F7, + 0x92DA, 0x5B2C, 0x92DB, 0x7D2C, 0x92DC, 0x722A, 0x92DD, 0x540A, 0x92DE, 0x91E3, 0x92DF, 0x9DB4, 0x92E0, 0x4EAD, 0x92E1, 0x4F4E, + 0x92E2, 0x505C, 0x92E3, 0x5075, 0x92E4, 0x5243, 0x92E5, 0x8C9E, 0x92E6, 0x5448, 0x92E7, 0x5824, 0x92E8, 0x5B9A, 0x92E9, 0x5E1D, + 0x92EA, 0x5E95, 0x92EB, 0x5EAD, 0x92EC, 0x5EF7, 0x92ED, 0x5F1F, 0x92EE, 0x608C, 0x92EF, 0x62B5, 0x92F0, 0x633A, 0x92F1, 0x63D0, + 0x92F2, 0x68AF, 0x92F3, 0x6C40, 0x92F4, 0x7887, 0x92F5, 0x798E, 0x92F6, 0x7A0B, 0x92F7, 0x7DE0, 0x92F8, 0x8247, 0x92F9, 0x8A02, + 0x92FA, 0x8AE6, 0x92FB, 0x8E44, 0x92FC, 0x9013, 0x9340, 0x90B8, 0x9341, 0x912D, 0x9342, 0x91D8, 0x9343, 0x9F0E, 0x9344, 0x6CE5, + 0x9345, 0x6458, 0x9346, 0x64E2, 0x9347, 0x6575, 0x9348, 0x6EF4, 0x9349, 0x7684, 0x934A, 0x7B1B, 0x934B, 0x9069, 0x934C, 0x93D1, + 0x934D, 0x6EBA, 0x934E, 0x54F2, 0x934F, 0x5FB9, 0x9350, 0x64A4, 0x9351, 0x8F4D, 0x9352, 0x8FED, 0x9353, 0x9244, 0x9354, 0x5178, + 0x9355, 0x586B, 0x9356, 0x5929, 0x9357, 0x5C55, 0x9358, 0x5E97, 0x9359, 0x6DFB, 0x935A, 0x7E8F, 0x935B, 0x751C, 0x935C, 0x8CBC, + 0x935D, 0x8EE2, 0x935E, 0x985B, 0x935F, 0x70B9, 0x9360, 0x4F1D, 0x9361, 0x6BBF, 0x9362, 0x6FB1, 0x9363, 0x7530, 0x9364, 0x96FB, + 0x9365, 0x514E, 0x9366, 0x5410, 0x9367, 0x5835, 0x9368, 0x5857, 0x9369, 0x59AC, 0x936A, 0x5C60, 0x936B, 0x5F92, 0x936C, 0x6597, + 0x936D, 0x675C, 0x936E, 0x6E21, 0x936F, 0x767B, 0x9370, 0x83DF, 0x9371, 0x8CED, 0x9372, 0x9014, 0x9373, 0x90FD, 0x9374, 0x934D, + 0x9375, 0x7825, 0x9376, 0x783A, 0x9377, 0x52AA, 0x9378, 0x5EA6, 0x9379, 0x571F, 0x937A, 0x5974, 0x937B, 0x6012, 0x937C, 0x5012, + 0x937D, 0x515A, 0x937E, 0x51AC, 0x9380, 0x51CD, 0x9381, 0x5200, 0x9382, 0x5510, 0x9383, 0x5854, 0x9384, 0x5858, 0x9385, 0x5957, + 0x9386, 0x5B95, 0x9387, 0x5CF6, 0x9388, 0x5D8B, 0x9389, 0x60BC, 0x938A, 0x6295, 0x938B, 0x642D, 0x938C, 0x6771, 0x938D, 0x6843, + 0x938E, 0x68BC, 0x938F, 0x68DF, 0x9390, 0x76D7, 0x9391, 0x6DD8, 0x9392, 0x6E6F, 0x9393, 0x6D9B, 0x9394, 0x706F, 0x9395, 0x71C8, + 0x9396, 0x5F53, 0x9397, 0x75D8, 0x9398, 0x7977, 0x9399, 0x7B49, 0x939A, 0x7B54, 0x939B, 0x7B52, 0x939C, 0x7CD6, 0x939D, 0x7D71, + 0x939E, 0x5230, 0x939F, 0x8463, 0x93A0, 0x8569, 0x93A1, 0x85E4, 0x93A2, 0x8A0E, 0x93A3, 0x8B04, 0x93A4, 0x8C46, 0x93A5, 0x8E0F, + 0x93A6, 0x9003, 0x93A7, 0x900F, 0x93A8, 0x9419, 0x93A9, 0x9676, 0x93AA, 0x982D, 0x93AB, 0x9A30, 0x93AC, 0x95D8, 0x93AD, 0x50CD, + 0x93AE, 0x52D5, 0x93AF, 0x540C, 0x93B0, 0x5802, 0x93B1, 0x5C0E, 0x93B2, 0x61A7, 0x93B3, 0x649E, 0x93B4, 0x6D1E, 0x93B5, 0x77B3, + 0x93B6, 0x7AE5, 0x93B7, 0x80F4, 0x93B8, 0x8404, 0x93B9, 0x9053, 0x93BA, 0x9285, 0x93BB, 0x5CE0, 0x93BC, 0x9D07, 0x93BD, 0x533F, + 0x93BE, 0x5F97, 0x93BF, 0x5FB3, 0x93C0, 0x6D9C, 0x93C1, 0x7279, 0x93C2, 0x7763, 0x93C3, 0x79BF, 0x93C4, 0x7BE4, 0x93C5, 0x6BD2, + 0x93C6, 0x72EC, 0x93C7, 0x8AAD, 0x93C8, 0x6803, 0x93C9, 0x6A61, 0x93CA, 0x51F8, 0x93CB, 0x7A81, 0x93CC, 0x6934, 0x93CD, 0x5C4A, + 0x93CE, 0x9CF6, 0x93CF, 0x82EB, 0x93D0, 0x5BC5, 0x93D1, 0x9149, 0x93D2, 0x701E, 0x93D3, 0x5678, 0x93D4, 0x5C6F, 0x93D5, 0x60C7, + 0x93D6, 0x6566, 0x93D7, 0x6C8C, 0x93D8, 0x8C5A, 0x93D9, 0x9041, 0x93DA, 0x9813, 0x93DB, 0x5451, 0x93DC, 0x66C7, 0x93DD, 0x920D, + 0x93DE, 0x5948, 0x93DF, 0x90A3, 0x93E0, 0x5185, 0x93E1, 0x4E4D, 0x93E2, 0x51EA, 0x93E3, 0x8599, 0x93E4, 0x8B0E, 0x93E5, 0x7058, + 0x93E6, 0x637A, 0x93E7, 0x934B, 0x93E8, 0x6962, 0x93E9, 0x99B4, 0x93EA, 0x7E04, 0x93EB, 0x7577, 0x93EC, 0x5357, 0x93ED, 0x6960, + 0x93EE, 0x8EDF, 0x93EF, 0x96E3, 0x93F0, 0x6C5D, 0x93F1, 0x4E8C, 0x93F2, 0x5C3C, 0x93F3, 0x5F10, 0x93F4, 0x8FE9, 0x93F5, 0x5302, + 0x93F6, 0x8CD1, 0x93F7, 0x8089, 0x93F8, 0x8679, 0x93F9, 0x5EFF, 0x93FA, 0x65E5, 0x93FB, 0x4E73, 0x93FC, 0x5165, 0x9440, 0x5982, + 0x9441, 0x5C3F, 0x9442, 0x97EE, 0x9443, 0x4EFB, 0x9444, 0x598A, 0x9445, 0x5FCD, 0x9446, 0x8A8D, 0x9447, 0x6FE1, 0x9448, 0x79B0, + 0x9449, 0x7962, 0x944A, 0x5BE7, 0x944B, 0x8471, 0x944C, 0x732B, 0x944D, 0x71B1, 0x944E, 0x5E74, 0x944F, 0x5FF5, 0x9450, 0x637B, + 0x9451, 0x649A, 0x9452, 0x71C3, 0x9453, 0x7C98, 0x9454, 0x4E43, 0x9455, 0x5EFC, 0x9456, 0x4E4B, 0x9457, 0x57DC, 0x9458, 0x56A2, + 0x9459, 0x60A9, 0x945A, 0x6FC3, 0x945B, 0x7D0D, 0x945C, 0x80FD, 0x945D, 0x8133, 0x945E, 0x81BF, 0x945F, 0x8FB2, 0x9460, 0x8997, + 0x9461, 0x86A4, 0x9462, 0x5DF4, 0x9463, 0x628A, 0x9464, 0x64AD, 0x9465, 0x8987, 0x9466, 0x6777, 0x9467, 0x6CE2, 0x9468, 0x6D3E, + 0x9469, 0x7436, 0x946A, 0x7834, 0x946B, 0x5A46, 0x946C, 0x7F75, 0x946D, 0x82AD, 0x946E, 0x99AC, 0x946F, 0x4FF3, 0x9470, 0x5EC3, + 0x9471, 0x62DD, 0x9472, 0x6392, 0x9473, 0x6557, 0x9474, 0x676F, 0x9475, 0x76C3, 0x9476, 0x724C, 0x9477, 0x80CC, 0x9478, 0x80BA, + 0x9479, 0x8F29, 0x947A, 0x914D, 0x947B, 0x500D, 0x947C, 0x57F9, 0x947D, 0x5A92, 0x947E, 0x6885, 0x9480, 0x6973, 0x9481, 0x7164, + 0x9482, 0x72FD, 0x9483, 0x8CB7, 0x9484, 0x58F2, 0x9485, 0x8CE0, 0x9486, 0x966A, 0x9487, 0x9019, 0x9488, 0x877F, 0x9489, 0x79E4, + 0x948A, 0x77E7, 0x948B, 0x8429, 0x948C, 0x4F2F, 0x948D, 0x5265, 0x948E, 0x535A, 0x948F, 0x62CD, 0x9490, 0x67CF, 0x9491, 0x6CCA, + 0x9492, 0x767D, 0x9493, 0x7B94, 0x9494, 0x7C95, 0x9495, 0x8236, 0x9496, 0x8584, 0x9497, 0x8FEB, 0x9498, 0x66DD, 0x9499, 0x6F20, + 0x949A, 0x7206, 0x949B, 0x7E1B, 0x949C, 0x83AB, 0x949D, 0x99C1, 0x949E, 0x9EA6, 0x949F, 0x51FD, 0x94A0, 0x7BB1, 0x94A1, 0x7872, + 0x94A2, 0x7BB8, 0x94A3, 0x8087, 0x94A4, 0x7B48, 0x94A5, 0x6AE8, 0x94A6, 0x5E61, 0x94A7, 0x808C, 0x94A8, 0x7551, 0x94A9, 0x7560, + 0x94AA, 0x516B, 0x94AB, 0x9262, 0x94AC, 0x6E8C, 0x94AD, 0x767A, 0x94AE, 0x9197, 0x94AF, 0x9AEA, 0x94B0, 0x4F10, 0x94B1, 0x7F70, + 0x94B2, 0x629C, 0x94B3, 0x7B4F, 0x94B4, 0x95A5, 0x94B5, 0x9CE9, 0x94B6, 0x567A, 0x94B7, 0x5859, 0x94B8, 0x86E4, 0x94B9, 0x96BC, + 0x94BA, 0x4F34, 0x94BB, 0x5224, 0x94BC, 0x534A, 0x94BD, 0x53CD, 0x94BE, 0x53DB, 0x94BF, 0x5E06, 0x94C0, 0x642C, 0x94C1, 0x6591, + 0x94C2, 0x677F, 0x94C3, 0x6C3E, 0x94C4, 0x6C4E, 0x94C5, 0x7248, 0x94C6, 0x72AF, 0x94C7, 0x73ED, 0x94C8, 0x7554, 0x94C9, 0x7E41, + 0x94CA, 0x822C, 0x94CB, 0x85E9, 0x94CC, 0x8CA9, 0x94CD, 0x7BC4, 0x94CE, 0x91C6, 0x94CF, 0x7169, 0x94D0, 0x9812, 0x94D1, 0x98EF, + 0x94D2, 0x633D, 0x94D3, 0x6669, 0x94D4, 0x756A, 0x94D5, 0x76E4, 0x94D6, 0x78D0, 0x94D7, 0x8543, 0x94D8, 0x86EE, 0x94D9, 0x532A, + 0x94DA, 0x5351, 0x94DB, 0x5426, 0x94DC, 0x5983, 0x94DD, 0x5E87, 0x94DE, 0x5F7C, 0x94DF, 0x60B2, 0x94E0, 0x6249, 0x94E1, 0x6279, + 0x94E2, 0x62AB, 0x94E3, 0x6590, 0x94E4, 0x6BD4, 0x94E5, 0x6CCC, 0x94E6, 0x75B2, 0x94E7, 0x76AE, 0x94E8, 0x7891, 0x94E9, 0x79D8, + 0x94EA, 0x7DCB, 0x94EB, 0x7F77, 0x94EC, 0x80A5, 0x94ED, 0x88AB, 0x94EE, 0x8AB9, 0x94EF, 0x8CBB, 0x94F0, 0x907F, 0x94F1, 0x975E, + 0x94F2, 0x98DB, 0x94F3, 0x6A0B, 0x94F4, 0x7C38, 0x94F5, 0x5099, 0x94F6, 0x5C3E, 0x94F7, 0x5FAE, 0x94F8, 0x6787, 0x94F9, 0x6BD8, + 0x94FA, 0x7435, 0x94FB, 0x7709, 0x94FC, 0x7F8E, 0x9540, 0x9F3B, 0x9541, 0x67CA, 0x9542, 0x7A17, 0x9543, 0x5339, 0x9544, 0x758B, + 0x9545, 0x9AED, 0x9546, 0x5F66, 0x9547, 0x819D, 0x9548, 0x83F1, 0x9549, 0x8098, 0x954A, 0x5F3C, 0x954B, 0x5FC5, 0x954C, 0x7562, + 0x954D, 0x7B46, 0x954E, 0x903C, 0x954F, 0x6867, 0x9550, 0x59EB, 0x9551, 0x5A9B, 0x9552, 0x7D10, 0x9553, 0x767E, 0x9554, 0x8B2C, + 0x9555, 0x4FF5, 0x9556, 0x5F6A, 0x9557, 0x6A19, 0x9558, 0x6C37, 0x9559, 0x6F02, 0x955A, 0x74E2, 0x955B, 0x7968, 0x955C, 0x8868, + 0x955D, 0x8A55, 0x955E, 0x8C79, 0x955F, 0x5EDF, 0x9560, 0x63CF, 0x9561, 0x75C5, 0x9562, 0x79D2, 0x9563, 0x82D7, 0x9564, 0x9328, + 0x9565, 0x92F2, 0x9566, 0x849C, 0x9567, 0x86ED, 0x9568, 0x9C2D, 0x9569, 0x54C1, 0x956A, 0x5F6C, 0x956B, 0x658C, 0x956C, 0x6D5C, + 0x956D, 0x7015, 0x956E, 0x8CA7, 0x956F, 0x8CD3, 0x9570, 0x983B, 0x9571, 0x654F, 0x9572, 0x74F6, 0x9573, 0x4E0D, 0x9574, 0x4ED8, + 0x9575, 0x57E0, 0x9576, 0x592B, 0x9577, 0x5A66, 0x9578, 0x5BCC, 0x9579, 0x51A8, 0x957A, 0x5E03, 0x957B, 0x5E9C, 0x957C, 0x6016, + 0x957D, 0x6276, 0x957E, 0x6577, 0x9580, 0x65A7, 0x9581, 0x666E, 0x9582, 0x6D6E, 0x9583, 0x7236, 0x9584, 0x7B26, 0x9585, 0x8150, + 0x9586, 0x819A, 0x9587, 0x8299, 0x9588, 0x8B5C, 0x9589, 0x8CA0, 0x958A, 0x8CE6, 0x958B, 0x8D74, 0x958C, 0x961C, 0x958D, 0x9644, + 0x958E, 0x4FAE, 0x958F, 0x64AB, 0x9590, 0x6B66, 0x9591, 0x821E, 0x9592, 0x8461, 0x9593, 0x856A, 0x9594, 0x90E8, 0x9595, 0x5C01, + 0x9596, 0x6953, 0x9597, 0x98A8, 0x9598, 0x847A, 0x9599, 0x8557, 0x959A, 0x4F0F, 0x959B, 0x526F, 0x959C, 0x5FA9, 0x959D, 0x5E45, + 0x959E, 0x670D, 0x959F, 0x798F, 0x95A0, 0x8179, 0x95A1, 0x8907, 0x95A2, 0x8986, 0x95A3, 0x6DF5, 0x95A4, 0x5F17, 0x95A5, 0x6255, + 0x95A6, 0x6CB8, 0x95A7, 0x4ECF, 0x95A8, 0x7269, 0x95A9, 0x9B92, 0x95AA, 0x5206, 0x95AB, 0x543B, 0x95AC, 0x5674, 0x95AD, 0x58B3, + 0x95AE, 0x61A4, 0x95AF, 0x626E, 0x95B0, 0x711A, 0x95B1, 0x596E, 0x95B2, 0x7C89, 0x95B3, 0x7CDE, 0x95B4, 0x7D1B, 0x95B5, 0x96F0, + 0x95B6, 0x6587, 0x95B7, 0x805E, 0x95B8, 0x4E19, 0x95B9, 0x4F75, 0x95BA, 0x5175, 0x95BB, 0x5840, 0x95BC, 0x5E63, 0x95BD, 0x5E73, + 0x95BE, 0x5F0A, 0x95BF, 0x67C4, 0x95C0, 0x4E26, 0x95C1, 0x853D, 0x95C2, 0x9589, 0x95C3, 0x965B, 0x95C4, 0x7C73, 0x95C5, 0x9801, + 0x95C6, 0x50FB, 0x95C7, 0x58C1, 0x95C8, 0x7656, 0x95C9, 0x78A7, 0x95CA, 0x5225, 0x95CB, 0x77A5, 0x95CC, 0x8511, 0x95CD, 0x7B86, + 0x95CE, 0x504F, 0x95CF, 0x5909, 0x95D0, 0x7247, 0x95D1, 0x7BC7, 0x95D2, 0x7DE8, 0x95D3, 0x8FBA, 0x95D4, 0x8FD4, 0x95D5, 0x904D, + 0x95D6, 0x4FBF, 0x95D7, 0x52C9, 0x95D8, 0x5A29, 0x95D9, 0x5F01, 0x95DA, 0x97AD, 0x95DB, 0x4FDD, 0x95DC, 0x8217, 0x95DD, 0x92EA, + 0x95DE, 0x5703, 0x95DF, 0x6355, 0x95E0, 0x6B69, 0x95E1, 0x752B, 0x95E2, 0x88DC, 0x95E3, 0x8F14, 0x95E4, 0x7A42, 0x95E5, 0x52DF, + 0x95E6, 0x5893, 0x95E7, 0x6155, 0x95E8, 0x620A, 0x95E9, 0x66AE, 0x95EA, 0x6BCD, 0x95EB, 0x7C3F, 0x95EC, 0x83E9, 0x95ED, 0x5023, + 0x95EE, 0x4FF8, 0x95EF, 0x5305, 0x95F0, 0x5446, 0x95F1, 0x5831, 0x95F2, 0x5949, 0x95F3, 0x5B9D, 0x95F4, 0x5CF0, 0x95F5, 0x5CEF, + 0x95F6, 0x5D29, 0x95F7, 0x5E96, 0x95F8, 0x62B1, 0x95F9, 0x6367, 0x95FA, 0x653E, 0x95FB, 0x65B9, 0x95FC, 0x670B, 0x9640, 0x6CD5, + 0x9641, 0x6CE1, 0x9642, 0x70F9, 0x9643, 0x7832, 0x9644, 0x7E2B, 0x9645, 0x80DE, 0x9646, 0x82B3, 0x9647, 0x840C, 0x9648, 0x84EC, + 0x9649, 0x8702, 0x964A, 0x8912, 0x964B, 0x8A2A, 0x964C, 0x8C4A, 0x964D, 0x90A6, 0x964E, 0x92D2, 0x964F, 0x98FD, 0x9650, 0x9CF3, + 0x9651, 0x9D6C, 0x9652, 0x4E4F, 0x9653, 0x4EA1, 0x9654, 0x508D, 0x9655, 0x5256, 0x9656, 0x574A, 0x9657, 0x59A8, 0x9658, 0x5E3D, + 0x9659, 0x5FD8, 0x965A, 0x5FD9, 0x965B, 0x623F, 0x965C, 0x66B4, 0x965D, 0x671B, 0x965E, 0x67D0, 0x965F, 0x68D2, 0x9660, 0x5192, + 0x9661, 0x7D21, 0x9662, 0x80AA, 0x9663, 0x81A8, 0x9664, 0x8B00, 0x9665, 0x8C8C, 0x9666, 0x8CBF, 0x9667, 0x927E, 0x9668, 0x9632, + 0x9669, 0x5420, 0x966A, 0x982C, 0x966B, 0x5317, 0x966C, 0x50D5, 0x966D, 0x535C, 0x966E, 0x58A8, 0x966F, 0x64B2, 0x9670, 0x6734, + 0x9671, 0x7267, 0x9672, 0x7766, 0x9673, 0x7A46, 0x9674, 0x91E6, 0x9675, 0x52C3, 0x9676, 0x6CA1, 0x9677, 0x6B86, 0x9678, 0x5800, + 0x9679, 0x5E4C, 0x967A, 0x5954, 0x967B, 0x672C, 0x967C, 0x7FFB, 0x967D, 0x51E1, 0x967E, 0x76C6, 0x9680, 0x6469, 0x9681, 0x78E8, + 0x9682, 0x9B54, 0x9683, 0x9EBB, 0x9684, 0x57CB, 0x9685, 0x59B9, 0x9686, 0x6627, 0x9687, 0x679A, 0x9688, 0x6BCE, 0x9689, 0x54E9, + 0x968A, 0x69D9, 0x968B, 0x5E55, 0x968C, 0x819C, 0x968D, 0x6795, 0x968E, 0x9BAA, 0x968F, 0x67FE, 0x9690, 0x9C52, 0x9691, 0x685D, + 0x9692, 0x4EA6, 0x9693, 0x4FE3, 0x9694, 0x53C8, 0x9695, 0x62B9, 0x9696, 0x672B, 0x9697, 0x6CAB, 0x9698, 0x8FC4, 0x9699, 0x4FAD, + 0x969A, 0x7E6D, 0x969B, 0x9EBF, 0x969C, 0x4E07, 0x969D, 0x6162, 0x969E, 0x6E80, 0x969F, 0x6F2B, 0x96A0, 0x8513, 0x96A1, 0x5473, + 0x96A2, 0x672A, 0x96A3, 0x9B45, 0x96A4, 0x5DF3, 0x96A5, 0x7B95, 0x96A6, 0x5CAC, 0x96A7, 0x5BC6, 0x96A8, 0x871C, 0x96A9, 0x6E4A, + 0x96AA, 0x84D1, 0x96AB, 0x7A14, 0x96AC, 0x8108, 0x96AD, 0x5999, 0x96AE, 0x7C8D, 0x96AF, 0x6C11, 0x96B0, 0x7720, 0x96B1, 0x52D9, + 0x96B2, 0x5922, 0x96B3, 0x7121, 0x96B4, 0x725F, 0x96B5, 0x77DB, 0x96B6, 0x9727, 0x96B7, 0x9D61, 0x96B8, 0x690B, 0x96B9, 0x5A7F, + 0x96BA, 0x5A18, 0x96BB, 0x51A5, 0x96BC, 0x540D, 0x96BD, 0x547D, 0x96BE, 0x660E, 0x96BF, 0x76DF, 0x96C0, 0x8FF7, 0x96C1, 0x9298, + 0x96C2, 0x9CF4, 0x96C3, 0x59EA, 0x96C4, 0x725D, 0x96C5, 0x6EC5, 0x96C6, 0x514D, 0x96C7, 0x68C9, 0x96C8, 0x7DBF, 0x96C9, 0x7DEC, + 0x96CA, 0x9762, 0x96CB, 0x9EBA, 0x96CC, 0x6478, 0x96CD, 0x6A21, 0x96CE, 0x8302, 0x96CF, 0x5984, 0x96D0, 0x5B5F, 0x96D1, 0x6BDB, + 0x96D2, 0x731B, 0x96D3, 0x76F2, 0x96D4, 0x7DB2, 0x96D5, 0x8017, 0x96D6, 0x8499, 0x96D7, 0x5132, 0x96D8, 0x6728, 0x96D9, 0x9ED9, + 0x96DA, 0x76EE, 0x96DB, 0x6762, 0x96DC, 0x52FF, 0x96DD, 0x9905, 0x96DE, 0x5C24, 0x96DF, 0x623B, 0x96E0, 0x7C7E, 0x96E1, 0x8CB0, + 0x96E2, 0x554F, 0x96E3, 0x60B6, 0x96E4, 0x7D0B, 0x96E5, 0x9580, 0x96E6, 0x5301, 0x96E7, 0x4E5F, 0x96E8, 0x51B6, 0x96E9, 0x591C, + 0x96EA, 0x723A, 0x96EB, 0x8036, 0x96EC, 0x91CE, 0x96ED, 0x5F25, 0x96EE, 0x77E2, 0x96EF, 0x5384, 0x96F0, 0x5F79, 0x96F1, 0x7D04, + 0x96F2, 0x85AC, 0x96F3, 0x8A33, 0x96F4, 0x8E8D, 0x96F5, 0x9756, 0x96F6, 0x67F3, 0x96F7, 0x85AE, 0x96F8, 0x9453, 0x96F9, 0x6109, + 0x96FA, 0x6108, 0x96FB, 0x6CB9, 0x96FC, 0x7652, 0x9740, 0x8AED, 0x9741, 0x8F38, 0x9742, 0x552F, 0x9743, 0x4F51, 0x9744, 0x512A, + 0x9745, 0x52C7, 0x9746, 0x53CB, 0x9747, 0x5BA5, 0x9748, 0x5E7D, 0x9749, 0x60A0, 0x974A, 0x6182, 0x974B, 0x63D6, 0x974C, 0x6709, + 0x974D, 0x67DA, 0x974E, 0x6E67, 0x974F, 0x6D8C, 0x9750, 0x7336, 0x9751, 0x7337, 0x9752, 0x7531, 0x9753, 0x7950, 0x9754, 0x88D5, + 0x9755, 0x8A98, 0x9756, 0x904A, 0x9757, 0x9091, 0x9758, 0x90F5, 0x9759, 0x96C4, 0x975A, 0x878D, 0x975B, 0x5915, 0x975C, 0x4E88, + 0x975D, 0x4F59, 0x975E, 0x4E0E, 0x975F, 0x8A89, 0x9760, 0x8F3F, 0x9761, 0x9810, 0x9762, 0x50AD, 0x9763, 0x5E7C, 0x9764, 0x5996, + 0x9765, 0x5BB9, 0x9766, 0x5EB8, 0x9767, 0x63DA, 0x9768, 0x63FA, 0x9769, 0x64C1, 0x976A, 0x66DC, 0x976B, 0x694A, 0x976C, 0x69D8, + 0x976D, 0x6D0B, 0x976E, 0x6EB6, 0x976F, 0x7194, 0x9770, 0x7528, 0x9771, 0x7AAF, 0x9772, 0x7F8A, 0x9773, 0x8000, 0x9774, 0x8449, + 0x9775, 0x84C9, 0x9776, 0x8981, 0x9777, 0x8B21, 0x9778, 0x8E0A, 0x9779, 0x9065, 0x977A, 0x967D, 0x977B, 0x990A, 0x977C, 0x617E, + 0x977D, 0x6291, 0x977E, 0x6B32, 0x9780, 0x6C83, 0x9781, 0x6D74, 0x9782, 0x7FCC, 0x9783, 0x7FFC, 0x9784, 0x6DC0, 0x9785, 0x7F85, + 0x9786, 0x87BA, 0x9787, 0x88F8, 0x9788, 0x6765, 0x9789, 0x83B1, 0x978A, 0x983C, 0x978B, 0x96F7, 0x978C, 0x6D1B, 0x978D, 0x7D61, + 0x978E, 0x843D, 0x978F, 0x916A, 0x9790, 0x4E71, 0x9791, 0x5375, 0x9792, 0x5D50, 0x9793, 0x6B04, 0x9794, 0x6FEB, 0x9795, 0x85CD, + 0x9796, 0x862D, 0x9797, 0x89A7, 0x9798, 0x5229, 0x9799, 0x540F, 0x979A, 0x5C65, 0x979B, 0x674E, 0x979C, 0x68A8, 0x979D, 0x7406, + 0x979E, 0x7483, 0x979F, 0x75E2, 0x97A0, 0x88CF, 0x97A1, 0x88E1, 0x97A2, 0x91CC, 0x97A3, 0x96E2, 0x97A4, 0x9678, 0x97A5, 0x5F8B, + 0x97A6, 0x7387, 0x97A7, 0x7ACB, 0x97A8, 0x844E, 0x97A9, 0x63A0, 0x97AA, 0x7565, 0x97AB, 0x5289, 0x97AC, 0x6D41, 0x97AD, 0x6E9C, + 0x97AE, 0x7409, 0x97AF, 0x7559, 0x97B0, 0x786B, 0x97B1, 0x7C92, 0x97B2, 0x9686, 0x97B3, 0x7ADC, 0x97B4, 0x9F8D, 0x97B5, 0x4FB6, + 0x97B6, 0x616E, 0x97B7, 0x65C5, 0x97B8, 0x865C, 0x97B9, 0x4E86, 0x97BA, 0x4EAE, 0x97BB, 0x50DA, 0x97BC, 0x4E21, 0x97BD, 0x51CC, + 0x97BE, 0x5BEE, 0x97BF, 0x6599, 0x97C0, 0x6881, 0x97C1, 0x6DBC, 0x97C2, 0x731F, 0x97C3, 0x7642, 0x97C4, 0x77AD, 0x97C5, 0x7A1C, + 0x97C6, 0x7CE7, 0x97C7, 0x826F, 0x97C8, 0x8AD2, 0x97C9, 0x907C, 0x97CA, 0x91CF, 0x97CB, 0x9675, 0x97CC, 0x9818, 0x97CD, 0x529B, + 0x97CE, 0x7DD1, 0x97CF, 0x502B, 0x97D0, 0x5398, 0x97D1, 0x6797, 0x97D2, 0x6DCB, 0x97D3, 0x71D0, 0x97D4, 0x7433, 0x97D5, 0x81E8, + 0x97D6, 0x8F2A, 0x97D7, 0x96A3, 0x97D8, 0x9C57, 0x97D9, 0x9E9F, 0x97DA, 0x7460, 0x97DB, 0x5841, 0x97DC, 0x6D99, 0x97DD, 0x7D2F, + 0x97DE, 0x985E, 0x97DF, 0x4EE4, 0x97E0, 0x4F36, 0x97E1, 0x4F8B, 0x97E2, 0x51B7, 0x97E3, 0x52B1, 0x97E4, 0x5DBA, 0x97E5, 0x601C, + 0x97E6, 0x73B2, 0x97E7, 0x793C, 0x97E8, 0x82D3, 0x97E9, 0x9234, 0x97EA, 0x96B7, 0x97EB, 0x96F6, 0x97EC, 0x970A, 0x97ED, 0x9E97, + 0x97EE, 0x9F62, 0x97EF, 0x66A6, 0x97F0, 0x6B74, 0x97F1, 0x5217, 0x97F2, 0x52A3, 0x97F3, 0x70C8, 0x97F4, 0x88C2, 0x97F5, 0x5EC9, + 0x97F6, 0x604B, 0x97F7, 0x6190, 0x97F8, 0x6F23, 0x97F9, 0x7149, 0x97FA, 0x7C3E, 0x97FB, 0x7DF4, 0x97FC, 0x806F, 0x9840, 0x84EE, + 0x9841, 0x9023, 0x9842, 0x932C, 0x9843, 0x5442, 0x9844, 0x9B6F, 0x9845, 0x6AD3, 0x9846, 0x7089, 0x9847, 0x8CC2, 0x9848, 0x8DEF, + 0x9849, 0x9732, 0x984A, 0x52B4, 0x984B, 0x5A41, 0x984C, 0x5ECA, 0x984D, 0x5F04, 0x984E, 0x6717, 0x984F, 0x697C, 0x9850, 0x6994, + 0x9851, 0x6D6A, 0x9852, 0x6F0F, 0x9853, 0x7262, 0x9854, 0x72FC, 0x9855, 0x7BED, 0x9856, 0x8001, 0x9857, 0x807E, 0x9858, 0x874B, + 0x9859, 0x90CE, 0x985A, 0x516D, 0x985B, 0x9E93, 0x985C, 0x7984, 0x985D, 0x808B, 0x985E, 0x9332, 0x985F, 0x8AD6, 0x9860, 0x502D, + 0x9861, 0x548C, 0x9862, 0x8A71, 0x9863, 0x6B6A, 0x9864, 0x8CC4, 0x9865, 0x8107, 0x9866, 0x60D1, 0x9867, 0x67A0, 0x9868, 0x9DF2, + 0x9869, 0x4E99, 0x986A, 0x4E98, 0x986B, 0x9C10, 0x986C, 0x8A6B, 0x986D, 0x85C1, 0x986E, 0x8568, 0x986F, 0x6900, 0x9870, 0x6E7E, + 0x9871, 0x7897, 0x9872, 0x8155, 0x989F, 0x5F0C, 0x98A0, 0x4E10, 0x98A1, 0x4E15, 0x98A2, 0x4E2A, 0x98A3, 0x4E31, 0x98A4, 0x4E36, + 0x98A5, 0x4E3C, 0x98A6, 0x4E3F, 0x98A7, 0x4E42, 0x98A8, 0x4E56, 0x98A9, 0x4E58, 0x98AA, 0x4E82, 0x98AB, 0x4E85, 0x98AC, 0x8C6B, + 0x98AD, 0x4E8A, 0x98AE, 0x8212, 0x98AF, 0x5F0D, 0x98B0, 0x4E8E, 0x98B1, 0x4E9E, 0x98B2, 0x4E9F, 0x98B3, 0x4EA0, 0x98B4, 0x4EA2, + 0x98B5, 0x4EB0, 0x98B6, 0x4EB3, 0x98B7, 0x4EB6, 0x98B8, 0x4ECE, 0x98B9, 0x4ECD, 0x98BA, 0x4EC4, 0x98BB, 0x4EC6, 0x98BC, 0x4EC2, + 0x98BD, 0x4ED7, 0x98BE, 0x4EDE, 0x98BF, 0x4EED, 0x98C0, 0x4EDF, 0x98C1, 0x4EF7, 0x98C2, 0x4F09, 0x98C3, 0x4F5A, 0x98C4, 0x4F30, + 0x98C5, 0x4F5B, 0x98C6, 0x4F5D, 0x98C7, 0x4F57, 0x98C8, 0x4F47, 0x98C9, 0x4F76, 0x98CA, 0x4F88, 0x98CB, 0x4F8F, 0x98CC, 0x4F98, + 0x98CD, 0x4F7B, 0x98CE, 0x4F69, 0x98CF, 0x4F70, 0x98D0, 0x4F91, 0x98D1, 0x4F6F, 0x98D2, 0x4F86, 0x98D3, 0x4F96, 0x98D4, 0x5118, + 0x98D5, 0x4FD4, 0x98D6, 0x4FDF, 0x98D7, 0x4FCE, 0x98D8, 0x4FD8, 0x98D9, 0x4FDB, 0x98DA, 0x4FD1, 0x98DB, 0x4FDA, 0x98DC, 0x4FD0, + 0x98DD, 0x4FE4, 0x98DE, 0x4FE5, 0x98DF, 0x501A, 0x98E0, 0x5028, 0x98E1, 0x5014, 0x98E2, 0x502A, 0x98E3, 0x5025, 0x98E4, 0x5005, + 0x98E5, 0x4F1C, 0x98E6, 0x4FF6, 0x98E7, 0x5021, 0x98E8, 0x5029, 0x98E9, 0x502C, 0x98EA, 0x4FFE, 0x98EB, 0x4FEF, 0x98EC, 0x5011, + 0x98ED, 0x5006, 0x98EE, 0x5043, 0x98EF, 0x5047, 0x98F0, 0x6703, 0x98F1, 0x5055, 0x98F2, 0x5050, 0x98F3, 0x5048, 0x98F4, 0x505A, + 0x98F5, 0x5056, 0x98F6, 0x506C, 0x98F7, 0x5078, 0x98F8, 0x5080, 0x98F9, 0x509A, 0x98FA, 0x5085, 0x98FB, 0x50B4, 0x98FC, 0x50B2, + 0x9940, 0x50C9, 0x9941, 0x50CA, 0x9942, 0x50B3, 0x9943, 0x50C2, 0x9944, 0x50D6, 0x9945, 0x50DE, 0x9946, 0x50E5, 0x9947, 0x50ED, + 0x9948, 0x50E3, 0x9949, 0x50EE, 0x994A, 0x50F9, 0x994B, 0x50F5, 0x994C, 0x5109, 0x994D, 0x5101, 0x994E, 0x5102, 0x994F, 0x5116, + 0x9950, 0x5115, 0x9951, 0x5114, 0x9952, 0x511A, 0x9953, 0x5121, 0x9954, 0x513A, 0x9955, 0x5137, 0x9956, 0x513C, 0x9957, 0x513B, + 0x9958, 0x513F, 0x9959, 0x5140, 0x995A, 0x5152, 0x995B, 0x514C, 0x995C, 0x5154, 0x995D, 0x5162, 0x995E, 0x7AF8, 0x995F, 0x5169, + 0x9960, 0x516A, 0x9961, 0x516E, 0x9962, 0x5180, 0x9963, 0x5182, 0x9964, 0x56D8, 0x9965, 0x518C, 0x9966, 0x5189, 0x9967, 0x518F, + 0x9968, 0x5191, 0x9969, 0x5193, 0x996A, 0x5195, 0x996B, 0x5196, 0x996C, 0x51A4, 0x996D, 0x51A6, 0x996E, 0x51A2, 0x996F, 0x51A9, + 0x9970, 0x51AA, 0x9971, 0x51AB, 0x9972, 0x51B3, 0x9973, 0x51B1, 0x9974, 0x51B2, 0x9975, 0x51B0, 0x9976, 0x51B5, 0x9977, 0x51BD, + 0x9978, 0x51C5, 0x9979, 0x51C9, 0x997A, 0x51DB, 0x997B, 0x51E0, 0x997C, 0x8655, 0x997D, 0x51E9, 0x997E, 0x51ED, 0x9980, 0x51F0, + 0x9981, 0x51F5, 0x9982, 0x51FE, 0x9983, 0x5204, 0x9984, 0x520B, 0x9985, 0x5214, 0x9986, 0x520E, 0x9987, 0x5227, 0x9988, 0x522A, + 0x9989, 0x522E, 0x998A, 0x5233, 0x998B, 0x5239, 0x998C, 0x524F, 0x998D, 0x5244, 0x998E, 0x524B, 0x998F, 0x524C, 0x9990, 0x525E, + 0x9991, 0x5254, 0x9992, 0x526A, 0x9993, 0x5274, 0x9994, 0x5269, 0x9995, 0x5273, 0x9996, 0x527F, 0x9997, 0x527D, 0x9998, 0x528D, + 0x9999, 0x5294, 0x999A, 0x5292, 0x999B, 0x5271, 0x999C, 0x5288, 0x999D, 0x5291, 0x999E, 0x8FA8, 0x999F, 0x8FA7, 0x99A0, 0x52AC, + 0x99A1, 0x52AD, 0x99A2, 0x52BC, 0x99A3, 0x52B5, 0x99A4, 0x52C1, 0x99A5, 0x52CD, 0x99A6, 0x52D7, 0x99A7, 0x52DE, 0x99A8, 0x52E3, + 0x99A9, 0x52E6, 0x99AA, 0x98ED, 0x99AB, 0x52E0, 0x99AC, 0x52F3, 0x99AD, 0x52F5, 0x99AE, 0x52F8, 0x99AF, 0x52F9, 0x99B0, 0x5306, + 0x99B1, 0x5308, 0x99B2, 0x7538, 0x99B3, 0x530D, 0x99B4, 0x5310, 0x99B5, 0x530F, 0x99B6, 0x5315, 0x99B7, 0x531A, 0x99B8, 0x5323, + 0x99B9, 0x532F, 0x99BA, 0x5331, 0x99BB, 0x5333, 0x99BC, 0x5338, 0x99BD, 0x5340, 0x99BE, 0x5346, 0x99BF, 0x5345, 0x99C0, 0x4E17, + 0x99C1, 0x5349, 0x99C2, 0x534D, 0x99C3, 0x51D6, 0x99C4, 0x535E, 0x99C5, 0x5369, 0x99C6, 0x536E, 0x99C7, 0x5918, 0x99C8, 0x537B, + 0x99C9, 0x5377, 0x99CA, 0x5382, 0x99CB, 0x5396, 0x99CC, 0x53A0, 0x99CD, 0x53A6, 0x99CE, 0x53A5, 0x99CF, 0x53AE, 0x99D0, 0x53B0, + 0x99D1, 0x53B6, 0x99D2, 0x53C3, 0x99D3, 0x7C12, 0x99D4, 0x96D9, 0x99D5, 0x53DF, 0x99D6, 0x66FC, 0x99D7, 0x71EE, 0x99D8, 0x53EE, + 0x99D9, 0x53E8, 0x99DA, 0x53ED, 0x99DB, 0x53FA, 0x99DC, 0x5401, 0x99DD, 0x543D, 0x99DE, 0x5440, 0x99DF, 0x542C, 0x99E0, 0x542D, + 0x99E1, 0x543C, 0x99E2, 0x542E, 0x99E3, 0x5436, 0x99E4, 0x5429, 0x99E5, 0x541D, 0x99E6, 0x544E, 0x99E7, 0x548F, 0x99E8, 0x5475, + 0x99E9, 0x548E, 0x99EA, 0x545F, 0x99EB, 0x5471, 0x99EC, 0x5477, 0x99ED, 0x5470, 0x99EE, 0x5492, 0x99EF, 0x547B, 0x99F0, 0x5480, + 0x99F1, 0x5476, 0x99F2, 0x5484, 0x99F3, 0x5490, 0x99F4, 0x5486, 0x99F5, 0x54C7, 0x99F6, 0x54A2, 0x99F7, 0x54B8, 0x99F8, 0x54A5, + 0x99F9, 0x54AC, 0x99FA, 0x54C4, 0x99FB, 0x54C8, 0x99FC, 0x54A8, 0x9A40, 0x54AB, 0x9A41, 0x54C2, 0x9A42, 0x54A4, 0x9A43, 0x54BE, + 0x9A44, 0x54BC, 0x9A45, 0x54D8, 0x9A46, 0x54E5, 0x9A47, 0x54E6, 0x9A48, 0x550F, 0x9A49, 0x5514, 0x9A4A, 0x54FD, 0x9A4B, 0x54EE, + 0x9A4C, 0x54ED, 0x9A4D, 0x54FA, 0x9A4E, 0x54E2, 0x9A4F, 0x5539, 0x9A50, 0x5540, 0x9A51, 0x5563, 0x9A52, 0x554C, 0x9A53, 0x552E, + 0x9A54, 0x555C, 0x9A55, 0x5545, 0x9A56, 0x5556, 0x9A57, 0x5557, 0x9A58, 0x5538, 0x9A59, 0x5533, 0x9A5A, 0x555D, 0x9A5B, 0x5599, + 0x9A5C, 0x5580, 0x9A5D, 0x54AF, 0x9A5E, 0x558A, 0x9A5F, 0x559F, 0x9A60, 0x557B, 0x9A61, 0x557E, 0x9A62, 0x5598, 0x9A63, 0x559E, + 0x9A64, 0x55AE, 0x9A65, 0x557C, 0x9A66, 0x5583, 0x9A67, 0x55A9, 0x9A68, 0x5587, 0x9A69, 0x55A8, 0x9A6A, 0x55DA, 0x9A6B, 0x55C5, + 0x9A6C, 0x55DF, 0x9A6D, 0x55C4, 0x9A6E, 0x55DC, 0x9A6F, 0x55E4, 0x9A70, 0x55D4, 0x9A71, 0x5614, 0x9A72, 0x55F7, 0x9A73, 0x5616, + 0x9A74, 0x55FE, 0x9A75, 0x55FD, 0x9A76, 0x561B, 0x9A77, 0x55F9, 0x9A78, 0x564E, 0x9A79, 0x5650, 0x9A7A, 0x71DF, 0x9A7B, 0x5634, + 0x9A7C, 0x5636, 0x9A7D, 0x5632, 0x9A7E, 0x5638, 0x9A80, 0x566B, 0x9A81, 0x5664, 0x9A82, 0x562F, 0x9A83, 0x566C, 0x9A84, 0x566A, + 0x9A85, 0x5686, 0x9A86, 0x5680, 0x9A87, 0x568A, 0x9A88, 0x56A0, 0x9A89, 0x5694, 0x9A8A, 0x568F, 0x9A8B, 0x56A5, 0x9A8C, 0x56AE, + 0x9A8D, 0x56B6, 0x9A8E, 0x56B4, 0x9A8F, 0x56C2, 0x9A90, 0x56BC, 0x9A91, 0x56C1, 0x9A92, 0x56C3, 0x9A93, 0x56C0, 0x9A94, 0x56C8, + 0x9A95, 0x56CE, 0x9A96, 0x56D1, 0x9A97, 0x56D3, 0x9A98, 0x56D7, 0x9A99, 0x56EE, 0x9A9A, 0x56F9, 0x9A9B, 0x5700, 0x9A9C, 0x56FF, + 0x9A9D, 0x5704, 0x9A9E, 0x5709, 0x9A9F, 0x5708, 0x9AA0, 0x570B, 0x9AA1, 0x570D, 0x9AA2, 0x5713, 0x9AA3, 0x5718, 0x9AA4, 0x5716, + 0x9AA5, 0x55C7, 0x9AA6, 0x571C, 0x9AA7, 0x5726, 0x9AA8, 0x5737, 0x9AA9, 0x5738, 0x9AAA, 0x574E, 0x9AAB, 0x573B, 0x9AAC, 0x5740, + 0x9AAD, 0x574F, 0x9AAE, 0x5769, 0x9AAF, 0x57C0, 0x9AB0, 0x5788, 0x9AB1, 0x5761, 0x9AB2, 0x577F, 0x9AB3, 0x5789, 0x9AB4, 0x5793, + 0x9AB5, 0x57A0, 0x9AB6, 0x57B3, 0x9AB7, 0x57A4, 0x9AB8, 0x57AA, 0x9AB9, 0x57B0, 0x9ABA, 0x57C3, 0x9ABB, 0x57C6, 0x9ABC, 0x57D4, + 0x9ABD, 0x57D2, 0x9ABE, 0x57D3, 0x9ABF, 0x580A, 0x9AC0, 0x57D6, 0x9AC1, 0x57E3, 0x9AC2, 0x580B, 0x9AC3, 0x5819, 0x9AC4, 0x581D, + 0x9AC5, 0x5872, 0x9AC6, 0x5821, 0x9AC7, 0x5862, 0x9AC8, 0x584B, 0x9AC9, 0x5870, 0x9ACA, 0x6BC0, 0x9ACB, 0x5852, 0x9ACC, 0x583D, + 0x9ACD, 0x5879, 0x9ACE, 0x5885, 0x9ACF, 0x58B9, 0x9AD0, 0x589F, 0x9AD1, 0x58AB, 0x9AD2, 0x58BA, 0x9AD3, 0x58DE, 0x9AD4, 0x58BB, + 0x9AD5, 0x58B8, 0x9AD6, 0x58AE, 0x9AD7, 0x58C5, 0x9AD8, 0x58D3, 0x9AD9, 0x58D1, 0x9ADA, 0x58D7, 0x9ADB, 0x58D9, 0x9ADC, 0x58D8, + 0x9ADD, 0x58E5, 0x9ADE, 0x58DC, 0x9ADF, 0x58E4, 0x9AE0, 0x58DF, 0x9AE1, 0x58EF, 0x9AE2, 0x58FA, 0x9AE3, 0x58F9, 0x9AE4, 0x58FB, + 0x9AE5, 0x58FC, 0x9AE6, 0x58FD, 0x9AE7, 0x5902, 0x9AE8, 0x590A, 0x9AE9, 0x5910, 0x9AEA, 0x591B, 0x9AEB, 0x68A6, 0x9AEC, 0x5925, + 0x9AED, 0x592C, 0x9AEE, 0x592D, 0x9AEF, 0x5932, 0x9AF0, 0x5938, 0x9AF1, 0x593E, 0x9AF2, 0x7AD2, 0x9AF3, 0x5955, 0x9AF4, 0x5950, + 0x9AF5, 0x594E, 0x9AF6, 0x595A, 0x9AF7, 0x5958, 0x9AF8, 0x5962, 0x9AF9, 0x5960, 0x9AFA, 0x5967, 0x9AFB, 0x596C, 0x9AFC, 0x5969, + 0x9B40, 0x5978, 0x9B41, 0x5981, 0x9B42, 0x599D, 0x9B43, 0x4F5E, 0x9B44, 0x4FAB, 0x9B45, 0x59A3, 0x9B46, 0x59B2, 0x9B47, 0x59C6, + 0x9B48, 0x59E8, 0x9B49, 0x59DC, 0x9B4A, 0x598D, 0x9B4B, 0x59D9, 0x9B4C, 0x59DA, 0x9B4D, 0x5A25, 0x9B4E, 0x5A1F, 0x9B4F, 0x5A11, + 0x9B50, 0x5A1C, 0x9B51, 0x5A09, 0x9B52, 0x5A1A, 0x9B53, 0x5A40, 0x9B54, 0x5A6C, 0x9B55, 0x5A49, 0x9B56, 0x5A35, 0x9B57, 0x5A36, + 0x9B58, 0x5A62, 0x9B59, 0x5A6A, 0x9B5A, 0x5A9A, 0x9B5B, 0x5ABC, 0x9B5C, 0x5ABE, 0x9B5D, 0x5ACB, 0x9B5E, 0x5AC2, 0x9B5F, 0x5ABD, + 0x9B60, 0x5AE3, 0x9B61, 0x5AD7, 0x9B62, 0x5AE6, 0x9B63, 0x5AE9, 0x9B64, 0x5AD6, 0x9B65, 0x5AFA, 0x9B66, 0x5AFB, 0x9B67, 0x5B0C, + 0x9B68, 0x5B0B, 0x9B69, 0x5B16, 0x9B6A, 0x5B32, 0x9B6B, 0x5AD0, 0x9B6C, 0x5B2A, 0x9B6D, 0x5B36, 0x9B6E, 0x5B3E, 0x9B6F, 0x5B43, + 0x9B70, 0x5B45, 0x9B71, 0x5B40, 0x9B72, 0x5B51, 0x9B73, 0x5B55, 0x9B74, 0x5B5A, 0x9B75, 0x5B5B, 0x9B76, 0x5B65, 0x9B77, 0x5B69, + 0x9B78, 0x5B70, 0x9B79, 0x5B73, 0x9B7A, 0x5B75, 0x9B7B, 0x5B78, 0x9B7C, 0x6588, 0x9B7D, 0x5B7A, 0x9B7E, 0x5B80, 0x9B80, 0x5B83, + 0x9B81, 0x5BA6, 0x9B82, 0x5BB8, 0x9B83, 0x5BC3, 0x9B84, 0x5BC7, 0x9B85, 0x5BC9, 0x9B86, 0x5BD4, 0x9B87, 0x5BD0, 0x9B88, 0x5BE4, + 0x9B89, 0x5BE6, 0x9B8A, 0x5BE2, 0x9B8B, 0x5BDE, 0x9B8C, 0x5BE5, 0x9B8D, 0x5BEB, 0x9B8E, 0x5BF0, 0x9B8F, 0x5BF6, 0x9B90, 0x5BF3, + 0x9B91, 0x5C05, 0x9B92, 0x5C07, 0x9B93, 0x5C08, 0x9B94, 0x5C0D, 0x9B95, 0x5C13, 0x9B96, 0x5C20, 0x9B97, 0x5C22, 0x9B98, 0x5C28, + 0x9B99, 0x5C38, 0x9B9A, 0x5C39, 0x9B9B, 0x5C41, 0x9B9C, 0x5C46, 0x9B9D, 0x5C4E, 0x9B9E, 0x5C53, 0x9B9F, 0x5C50, 0x9BA0, 0x5C4F, + 0x9BA1, 0x5B71, 0x9BA2, 0x5C6C, 0x9BA3, 0x5C6E, 0x9BA4, 0x4E62, 0x9BA5, 0x5C76, 0x9BA6, 0x5C79, 0x9BA7, 0x5C8C, 0x9BA8, 0x5C91, + 0x9BA9, 0x5C94, 0x9BAA, 0x599B, 0x9BAB, 0x5CAB, 0x9BAC, 0x5CBB, 0x9BAD, 0x5CB6, 0x9BAE, 0x5CBC, 0x9BAF, 0x5CB7, 0x9BB0, 0x5CC5, + 0x9BB1, 0x5CBE, 0x9BB2, 0x5CC7, 0x9BB3, 0x5CD9, 0x9BB4, 0x5CE9, 0x9BB5, 0x5CFD, 0x9BB6, 0x5CFA, 0x9BB7, 0x5CED, 0x9BB8, 0x5D8C, + 0x9BB9, 0x5CEA, 0x9BBA, 0x5D0B, 0x9BBB, 0x5D15, 0x9BBC, 0x5D17, 0x9BBD, 0x5D5C, 0x9BBE, 0x5D1F, 0x9BBF, 0x5D1B, 0x9BC0, 0x5D11, + 0x9BC1, 0x5D14, 0x9BC2, 0x5D22, 0x9BC3, 0x5D1A, 0x9BC4, 0x5D19, 0x9BC5, 0x5D18, 0x9BC6, 0x5D4C, 0x9BC7, 0x5D52, 0x9BC8, 0x5D4E, + 0x9BC9, 0x5D4B, 0x9BCA, 0x5D6C, 0x9BCB, 0x5D73, 0x9BCC, 0x5D76, 0x9BCD, 0x5D87, 0x9BCE, 0x5D84, 0x9BCF, 0x5D82, 0x9BD0, 0x5DA2, + 0x9BD1, 0x5D9D, 0x9BD2, 0x5DAC, 0x9BD3, 0x5DAE, 0x9BD4, 0x5DBD, 0x9BD5, 0x5D90, 0x9BD6, 0x5DB7, 0x9BD7, 0x5DBC, 0x9BD8, 0x5DC9, + 0x9BD9, 0x5DCD, 0x9BDA, 0x5DD3, 0x9BDB, 0x5DD2, 0x9BDC, 0x5DD6, 0x9BDD, 0x5DDB, 0x9BDE, 0x5DEB, 0x9BDF, 0x5DF2, 0x9BE0, 0x5DF5, + 0x9BE1, 0x5E0B, 0x9BE2, 0x5E1A, 0x9BE3, 0x5E19, 0x9BE4, 0x5E11, 0x9BE5, 0x5E1B, 0x9BE6, 0x5E36, 0x9BE7, 0x5E37, 0x9BE8, 0x5E44, + 0x9BE9, 0x5E43, 0x9BEA, 0x5E40, 0x9BEB, 0x5E4E, 0x9BEC, 0x5E57, 0x9BED, 0x5E54, 0x9BEE, 0x5E5F, 0x9BEF, 0x5E62, 0x9BF0, 0x5E64, + 0x9BF1, 0x5E47, 0x9BF2, 0x5E75, 0x9BF3, 0x5E76, 0x9BF4, 0x5E7A, 0x9BF5, 0x9EBC, 0x9BF6, 0x5E7F, 0x9BF7, 0x5EA0, 0x9BF8, 0x5EC1, + 0x9BF9, 0x5EC2, 0x9BFA, 0x5EC8, 0x9BFB, 0x5ED0, 0x9BFC, 0x5ECF, 0x9C40, 0x5ED6, 0x9C41, 0x5EE3, 0x9C42, 0x5EDD, 0x9C43, 0x5EDA, + 0x9C44, 0x5EDB, 0x9C45, 0x5EE2, 0x9C46, 0x5EE1, 0x9C47, 0x5EE8, 0x9C48, 0x5EE9, 0x9C49, 0x5EEC, 0x9C4A, 0x5EF1, 0x9C4B, 0x5EF3, + 0x9C4C, 0x5EF0, 0x9C4D, 0x5EF4, 0x9C4E, 0x5EF8, 0x9C4F, 0x5EFE, 0x9C50, 0x5F03, 0x9C51, 0x5F09, 0x9C52, 0x5F5D, 0x9C53, 0x5F5C, + 0x9C54, 0x5F0B, 0x9C55, 0x5F11, 0x9C56, 0x5F16, 0x9C57, 0x5F29, 0x9C58, 0x5F2D, 0x9C59, 0x5F38, 0x9C5A, 0x5F41, 0x9C5B, 0x5F48, + 0x9C5C, 0x5F4C, 0x9C5D, 0x5F4E, 0x9C5E, 0x5F2F, 0x9C5F, 0x5F51, 0x9C60, 0x5F56, 0x9C61, 0x5F57, 0x9C62, 0x5F59, 0x9C63, 0x5F61, + 0x9C64, 0x5F6D, 0x9C65, 0x5F73, 0x9C66, 0x5F77, 0x9C67, 0x5F83, 0x9C68, 0x5F82, 0x9C69, 0x5F7F, 0x9C6A, 0x5F8A, 0x9C6B, 0x5F88, + 0x9C6C, 0x5F91, 0x9C6D, 0x5F87, 0x9C6E, 0x5F9E, 0x9C6F, 0x5F99, 0x9C70, 0x5F98, 0x9C71, 0x5FA0, 0x9C72, 0x5FA8, 0x9C73, 0x5FAD, + 0x9C74, 0x5FBC, 0x9C75, 0x5FD6, 0x9C76, 0x5FFB, 0x9C77, 0x5FE4, 0x9C78, 0x5FF8, 0x9C79, 0x5FF1, 0x9C7A, 0x5FDD, 0x9C7B, 0x60B3, + 0x9C7C, 0x5FFF, 0x9C7D, 0x6021, 0x9C7E, 0x6060, 0x9C80, 0x6019, 0x9C81, 0x6010, 0x9C82, 0x6029, 0x9C83, 0x600E, 0x9C84, 0x6031, + 0x9C85, 0x601B, 0x9C86, 0x6015, 0x9C87, 0x602B, 0x9C88, 0x6026, 0x9C89, 0x600F, 0x9C8A, 0x603A, 0x9C8B, 0x605A, 0x9C8C, 0x6041, + 0x9C8D, 0x606A, 0x9C8E, 0x6077, 0x9C8F, 0x605F, 0x9C90, 0x604A, 0x9C91, 0x6046, 0x9C92, 0x604D, 0x9C93, 0x6063, 0x9C94, 0x6043, + 0x9C95, 0x6064, 0x9C96, 0x6042, 0x9C97, 0x606C, 0x9C98, 0x606B, 0x9C99, 0x6059, 0x9C9A, 0x6081, 0x9C9B, 0x608D, 0x9C9C, 0x60E7, + 0x9C9D, 0x6083, 0x9C9E, 0x609A, 0x9C9F, 0x6084, 0x9CA0, 0x609B, 0x9CA1, 0x6096, 0x9CA2, 0x6097, 0x9CA3, 0x6092, 0x9CA4, 0x60A7, + 0x9CA5, 0x608B, 0x9CA6, 0x60E1, 0x9CA7, 0x60B8, 0x9CA8, 0x60E0, 0x9CA9, 0x60D3, 0x9CAA, 0x60B4, 0x9CAB, 0x5FF0, 0x9CAC, 0x60BD, + 0x9CAD, 0x60C6, 0x9CAE, 0x60B5, 0x9CAF, 0x60D8, 0x9CB0, 0x614D, 0x9CB1, 0x6115, 0x9CB2, 0x6106, 0x9CB3, 0x60F6, 0x9CB4, 0x60F7, + 0x9CB5, 0x6100, 0x9CB6, 0x60F4, 0x9CB7, 0x60FA, 0x9CB8, 0x6103, 0x9CB9, 0x6121, 0x9CBA, 0x60FB, 0x9CBB, 0x60F1, 0x9CBC, 0x610D, + 0x9CBD, 0x610E, 0x9CBE, 0x6147, 0x9CBF, 0x613E, 0x9CC0, 0x6128, 0x9CC1, 0x6127, 0x9CC2, 0x614A, 0x9CC3, 0x613F, 0x9CC4, 0x613C, + 0x9CC5, 0x612C, 0x9CC6, 0x6134, 0x9CC7, 0x613D, 0x9CC8, 0x6142, 0x9CC9, 0x6144, 0x9CCA, 0x6173, 0x9CCB, 0x6177, 0x9CCC, 0x6158, + 0x9CCD, 0x6159, 0x9CCE, 0x615A, 0x9CCF, 0x616B, 0x9CD0, 0x6174, 0x9CD1, 0x616F, 0x9CD2, 0x6165, 0x9CD3, 0x6171, 0x9CD4, 0x615F, + 0x9CD5, 0x615D, 0x9CD6, 0x6153, 0x9CD7, 0x6175, 0x9CD8, 0x6199, 0x9CD9, 0x6196, 0x9CDA, 0x6187, 0x9CDB, 0x61AC, 0x9CDC, 0x6194, + 0x9CDD, 0x619A, 0x9CDE, 0x618A, 0x9CDF, 0x6191, 0x9CE0, 0x61AB, 0x9CE1, 0x61AE, 0x9CE2, 0x61CC, 0x9CE3, 0x61CA, 0x9CE4, 0x61C9, + 0x9CE5, 0x61F7, 0x9CE6, 0x61C8, 0x9CE7, 0x61C3, 0x9CE8, 0x61C6, 0x9CE9, 0x61BA, 0x9CEA, 0x61CB, 0x9CEB, 0x7F79, 0x9CEC, 0x61CD, + 0x9CED, 0x61E6, 0x9CEE, 0x61E3, 0x9CEF, 0x61F6, 0x9CF0, 0x61FA, 0x9CF1, 0x61F4, 0x9CF2, 0x61FF, 0x9CF3, 0x61FD, 0x9CF4, 0x61FC, + 0x9CF5, 0x61FE, 0x9CF6, 0x6200, 0x9CF7, 0x6208, 0x9CF8, 0x6209, 0x9CF9, 0x620D, 0x9CFA, 0x620C, 0x9CFB, 0x6214, 0x9CFC, 0x621B, + 0x9D40, 0x621E, 0x9D41, 0x6221, 0x9D42, 0x622A, 0x9D43, 0x622E, 0x9D44, 0x6230, 0x9D45, 0x6232, 0x9D46, 0x6233, 0x9D47, 0x6241, + 0x9D48, 0x624E, 0x9D49, 0x625E, 0x9D4A, 0x6263, 0x9D4B, 0x625B, 0x9D4C, 0x6260, 0x9D4D, 0x6268, 0x9D4E, 0x627C, 0x9D4F, 0x6282, + 0x9D50, 0x6289, 0x9D51, 0x627E, 0x9D52, 0x6292, 0x9D53, 0x6293, 0x9D54, 0x6296, 0x9D55, 0x62D4, 0x9D56, 0x6283, 0x9D57, 0x6294, + 0x9D58, 0x62D7, 0x9D59, 0x62D1, 0x9D5A, 0x62BB, 0x9D5B, 0x62CF, 0x9D5C, 0x62FF, 0x9D5D, 0x62C6, 0x9D5E, 0x64D4, 0x9D5F, 0x62C8, + 0x9D60, 0x62DC, 0x9D61, 0x62CC, 0x9D62, 0x62CA, 0x9D63, 0x62C2, 0x9D64, 0x62C7, 0x9D65, 0x629B, 0x9D66, 0x62C9, 0x9D67, 0x630C, + 0x9D68, 0x62EE, 0x9D69, 0x62F1, 0x9D6A, 0x6327, 0x9D6B, 0x6302, 0x9D6C, 0x6308, 0x9D6D, 0x62EF, 0x9D6E, 0x62F5, 0x9D6F, 0x6350, + 0x9D70, 0x633E, 0x9D71, 0x634D, 0x9D72, 0x641C, 0x9D73, 0x634F, 0x9D74, 0x6396, 0x9D75, 0x638E, 0x9D76, 0x6380, 0x9D77, 0x63AB, + 0x9D78, 0x6376, 0x9D79, 0x63A3, 0x9D7A, 0x638F, 0x9D7B, 0x6389, 0x9D7C, 0x639F, 0x9D7D, 0x63B5, 0x9D7E, 0x636B, 0x9D80, 0x6369, + 0x9D81, 0x63BE, 0x9D82, 0x63E9, 0x9D83, 0x63C0, 0x9D84, 0x63C6, 0x9D85, 0x63E3, 0x9D86, 0x63C9, 0x9D87, 0x63D2, 0x9D88, 0x63F6, + 0x9D89, 0x63C4, 0x9D8A, 0x6416, 0x9D8B, 0x6434, 0x9D8C, 0x6406, 0x9D8D, 0x6413, 0x9D8E, 0x6426, 0x9D8F, 0x6436, 0x9D90, 0x651D, + 0x9D91, 0x6417, 0x9D92, 0x6428, 0x9D93, 0x640F, 0x9D94, 0x6467, 0x9D95, 0x646F, 0x9D96, 0x6476, 0x9D97, 0x644E, 0x9D98, 0x652A, + 0x9D99, 0x6495, 0x9D9A, 0x6493, 0x9D9B, 0x64A5, 0x9D9C, 0x64A9, 0x9D9D, 0x6488, 0x9D9E, 0x64BC, 0x9D9F, 0x64DA, 0x9DA0, 0x64D2, + 0x9DA1, 0x64C5, 0x9DA2, 0x64C7, 0x9DA3, 0x64BB, 0x9DA4, 0x64D8, 0x9DA5, 0x64C2, 0x9DA6, 0x64F1, 0x9DA7, 0x64E7, 0x9DA8, 0x8209, + 0x9DA9, 0x64E0, 0x9DAA, 0x64E1, 0x9DAB, 0x62AC, 0x9DAC, 0x64E3, 0x9DAD, 0x64EF, 0x9DAE, 0x652C, 0x9DAF, 0x64F6, 0x9DB0, 0x64F4, + 0x9DB1, 0x64F2, 0x9DB2, 0x64FA, 0x9DB3, 0x6500, 0x9DB4, 0x64FD, 0x9DB5, 0x6518, 0x9DB6, 0x651C, 0x9DB7, 0x6505, 0x9DB8, 0x6524, + 0x9DB9, 0x6523, 0x9DBA, 0x652B, 0x9DBB, 0x6534, 0x9DBC, 0x6535, 0x9DBD, 0x6537, 0x9DBE, 0x6536, 0x9DBF, 0x6538, 0x9DC0, 0x754B, + 0x9DC1, 0x6548, 0x9DC2, 0x6556, 0x9DC3, 0x6555, 0x9DC4, 0x654D, 0x9DC5, 0x6558, 0x9DC6, 0x655E, 0x9DC7, 0x655D, 0x9DC8, 0x6572, + 0x9DC9, 0x6578, 0x9DCA, 0x6582, 0x9DCB, 0x6583, 0x9DCC, 0x8B8A, 0x9DCD, 0x659B, 0x9DCE, 0x659F, 0x9DCF, 0x65AB, 0x9DD0, 0x65B7, + 0x9DD1, 0x65C3, 0x9DD2, 0x65C6, 0x9DD3, 0x65C1, 0x9DD4, 0x65C4, 0x9DD5, 0x65CC, 0x9DD6, 0x65D2, 0x9DD7, 0x65DB, 0x9DD8, 0x65D9, + 0x9DD9, 0x65E0, 0x9DDA, 0x65E1, 0x9DDB, 0x65F1, 0x9DDC, 0x6772, 0x9DDD, 0x660A, 0x9DDE, 0x6603, 0x9DDF, 0x65FB, 0x9DE0, 0x6773, + 0x9DE1, 0x6635, 0x9DE2, 0x6636, 0x9DE3, 0x6634, 0x9DE4, 0x661C, 0x9DE5, 0x664F, 0x9DE6, 0x6644, 0x9DE7, 0x6649, 0x9DE8, 0x6641, + 0x9DE9, 0x665E, 0x9DEA, 0x665D, 0x9DEB, 0x6664, 0x9DEC, 0x6667, 0x9DED, 0x6668, 0x9DEE, 0x665F, 0x9DEF, 0x6662, 0x9DF0, 0x6670, + 0x9DF1, 0x6683, 0x9DF2, 0x6688, 0x9DF3, 0x668E, 0x9DF4, 0x6689, 0x9DF5, 0x6684, 0x9DF6, 0x6698, 0x9DF7, 0x669D, 0x9DF8, 0x66C1, + 0x9DF9, 0x66B9, 0x9DFA, 0x66C9, 0x9DFB, 0x66BE, 0x9DFC, 0x66BC, 0x9E40, 0x66C4, 0x9E41, 0x66B8, 0x9E42, 0x66D6, 0x9E43, 0x66DA, + 0x9E44, 0x66E0, 0x9E45, 0x663F, 0x9E46, 0x66E6, 0x9E47, 0x66E9, 0x9E48, 0x66F0, 0x9E49, 0x66F5, 0x9E4A, 0x66F7, 0x9E4B, 0x670F, + 0x9E4C, 0x6716, 0x9E4D, 0x671E, 0x9E4E, 0x6726, 0x9E4F, 0x6727, 0x9E50, 0x9738, 0x9E51, 0x672E, 0x9E52, 0x673F, 0x9E53, 0x6736, + 0x9E54, 0x6741, 0x9E55, 0x6738, 0x9E56, 0x6737, 0x9E57, 0x6746, 0x9E58, 0x675E, 0x9E59, 0x6760, 0x9E5A, 0x6759, 0x9E5B, 0x6763, + 0x9E5C, 0x6764, 0x9E5D, 0x6789, 0x9E5E, 0x6770, 0x9E5F, 0x67A9, 0x9E60, 0x677C, 0x9E61, 0x676A, 0x9E62, 0x678C, 0x9E63, 0x678B, + 0x9E64, 0x67A6, 0x9E65, 0x67A1, 0x9E66, 0x6785, 0x9E67, 0x67B7, 0x9E68, 0x67EF, 0x9E69, 0x67B4, 0x9E6A, 0x67EC, 0x9E6B, 0x67B3, + 0x9E6C, 0x67E9, 0x9E6D, 0x67B8, 0x9E6E, 0x67E4, 0x9E6F, 0x67DE, 0x9E70, 0x67DD, 0x9E71, 0x67E2, 0x9E72, 0x67EE, 0x9E73, 0x67B9, + 0x9E74, 0x67CE, 0x9E75, 0x67C6, 0x9E76, 0x67E7, 0x9E77, 0x6A9C, 0x9E78, 0x681E, 0x9E79, 0x6846, 0x9E7A, 0x6829, 0x9E7B, 0x6840, + 0x9E7C, 0x684D, 0x9E7D, 0x6832, 0x9E7E, 0x684E, 0x9E80, 0x68B3, 0x9E81, 0x682B, 0x9E82, 0x6859, 0x9E83, 0x6863, 0x9E84, 0x6877, + 0x9E85, 0x687F, 0x9E86, 0x689F, 0x9E87, 0x688F, 0x9E88, 0x68AD, 0x9E89, 0x6894, 0x9E8A, 0x689D, 0x9E8B, 0x689B, 0x9E8C, 0x6883, + 0x9E8D, 0x6AAE, 0x9E8E, 0x68B9, 0x9E8F, 0x6874, 0x9E90, 0x68B5, 0x9E91, 0x68A0, 0x9E92, 0x68BA, 0x9E93, 0x690F, 0x9E94, 0x688D, + 0x9E95, 0x687E, 0x9E96, 0x6901, 0x9E97, 0x68CA, 0x9E98, 0x6908, 0x9E99, 0x68D8, 0x9E9A, 0x6922, 0x9E9B, 0x6926, 0x9E9C, 0x68E1, + 0x9E9D, 0x690C, 0x9E9E, 0x68CD, 0x9E9F, 0x68D4, 0x9EA0, 0x68E7, 0x9EA1, 0x68D5, 0x9EA2, 0x6936, 0x9EA3, 0x6912, 0x9EA4, 0x6904, + 0x9EA5, 0x68D7, 0x9EA6, 0x68E3, 0x9EA7, 0x6925, 0x9EA8, 0x68F9, 0x9EA9, 0x68E0, 0x9EAA, 0x68EF, 0x9EAB, 0x6928, 0x9EAC, 0x692A, + 0x9EAD, 0x691A, 0x9EAE, 0x6923, 0x9EAF, 0x6921, 0x9EB0, 0x68C6, 0x9EB1, 0x6979, 0x9EB2, 0x6977, 0x9EB3, 0x695C, 0x9EB4, 0x6978, + 0x9EB5, 0x696B, 0x9EB6, 0x6954, 0x9EB7, 0x697E, 0x9EB8, 0x696E, 0x9EB9, 0x6939, 0x9EBA, 0x6974, 0x9EBB, 0x693D, 0x9EBC, 0x6959, + 0x9EBD, 0x6930, 0x9EBE, 0x6961, 0x9EBF, 0x695E, 0x9EC0, 0x695D, 0x9EC1, 0x6981, 0x9EC2, 0x696A, 0x9EC3, 0x69B2, 0x9EC4, 0x69AE, + 0x9EC5, 0x69D0, 0x9EC6, 0x69BF, 0x9EC7, 0x69C1, 0x9EC8, 0x69D3, 0x9EC9, 0x69BE, 0x9ECA, 0x69CE, 0x9ECB, 0x5BE8, 0x9ECC, 0x69CA, + 0x9ECD, 0x69DD, 0x9ECE, 0x69BB, 0x9ECF, 0x69C3, 0x9ED0, 0x69A7, 0x9ED1, 0x6A2E, 0x9ED2, 0x6991, 0x9ED3, 0x69A0, 0x9ED4, 0x699C, + 0x9ED5, 0x6995, 0x9ED6, 0x69B4, 0x9ED7, 0x69DE, 0x9ED8, 0x69E8, 0x9ED9, 0x6A02, 0x9EDA, 0x6A1B, 0x9EDB, 0x69FF, 0x9EDC, 0x6B0A, + 0x9EDD, 0x69F9, 0x9EDE, 0x69F2, 0x9EDF, 0x69E7, 0x9EE0, 0x6A05, 0x9EE1, 0x69B1, 0x9EE2, 0x6A1E, 0x9EE3, 0x69ED, 0x9EE4, 0x6A14, + 0x9EE5, 0x69EB, 0x9EE6, 0x6A0A, 0x9EE7, 0x6A12, 0x9EE8, 0x6AC1, 0x9EE9, 0x6A23, 0x9EEA, 0x6A13, 0x9EEB, 0x6A44, 0x9EEC, 0x6A0C, + 0x9EED, 0x6A72, 0x9EEE, 0x6A36, 0x9EEF, 0x6A78, 0x9EF0, 0x6A47, 0x9EF1, 0x6A62, 0x9EF2, 0x6A59, 0x9EF3, 0x6A66, 0x9EF4, 0x6A48, + 0x9EF5, 0x6A38, 0x9EF6, 0x6A22, 0x9EF7, 0x6A90, 0x9EF8, 0x6A8D, 0x9EF9, 0x6AA0, 0x9EFA, 0x6A84, 0x9EFB, 0x6AA2, 0x9EFC, 0x6AA3, + 0x9F40, 0x6A97, 0x9F41, 0x8617, 0x9F42, 0x6ABB, 0x9F43, 0x6AC3, 0x9F44, 0x6AC2, 0x9F45, 0x6AB8, 0x9F46, 0x6AB3, 0x9F47, 0x6AAC, + 0x9F48, 0x6ADE, 0x9F49, 0x6AD1, 0x9F4A, 0x6ADF, 0x9F4B, 0x6AAA, 0x9F4C, 0x6ADA, 0x9F4D, 0x6AEA, 0x9F4E, 0x6AFB, 0x9F4F, 0x6B05, + 0x9F50, 0x8616, 0x9F51, 0x6AFA, 0x9F52, 0x6B12, 0x9F53, 0x6B16, 0x9F54, 0x9B31, 0x9F55, 0x6B1F, 0x9F56, 0x6B38, 0x9F57, 0x6B37, + 0x9F58, 0x76DC, 0x9F59, 0x6B39, 0x9F5A, 0x98EE, 0x9F5B, 0x6B47, 0x9F5C, 0x6B43, 0x9F5D, 0x6B49, 0x9F5E, 0x6B50, 0x9F5F, 0x6B59, + 0x9F60, 0x6B54, 0x9F61, 0x6B5B, 0x9F62, 0x6B5F, 0x9F63, 0x6B61, 0x9F64, 0x6B78, 0x9F65, 0x6B79, 0x9F66, 0x6B7F, 0x9F67, 0x6B80, + 0x9F68, 0x6B84, 0x9F69, 0x6B83, 0x9F6A, 0x6B8D, 0x9F6B, 0x6B98, 0x9F6C, 0x6B95, 0x9F6D, 0x6B9E, 0x9F6E, 0x6BA4, 0x9F6F, 0x6BAA, + 0x9F70, 0x6BAB, 0x9F71, 0x6BAF, 0x9F72, 0x6BB2, 0x9F73, 0x6BB1, 0x9F74, 0x6BB3, 0x9F75, 0x6BB7, 0x9F76, 0x6BBC, 0x9F77, 0x6BC6, + 0x9F78, 0x6BCB, 0x9F79, 0x6BD3, 0x9F7A, 0x6BDF, 0x9F7B, 0x6BEC, 0x9F7C, 0x6BEB, 0x9F7D, 0x6BF3, 0x9F7E, 0x6BEF, 0x9F80, 0x9EBE, + 0x9F81, 0x6C08, 0x9F82, 0x6C13, 0x9F83, 0x6C14, 0x9F84, 0x6C1B, 0x9F85, 0x6C24, 0x9F86, 0x6C23, 0x9F87, 0x6C5E, 0x9F88, 0x6C55, + 0x9F89, 0x6C62, 0x9F8A, 0x6C6A, 0x9F8B, 0x6C82, 0x9F8C, 0x6C8D, 0x9F8D, 0x6C9A, 0x9F8E, 0x6C81, 0x9F8F, 0x6C9B, 0x9F90, 0x6C7E, + 0x9F91, 0x6C68, 0x9F92, 0x6C73, 0x9F93, 0x6C92, 0x9F94, 0x6C90, 0x9F95, 0x6CC4, 0x9F96, 0x6CF1, 0x9F97, 0x6CD3, 0x9F98, 0x6CBD, + 0x9F99, 0x6CD7, 0x9F9A, 0x6CC5, 0x9F9B, 0x6CDD, 0x9F9C, 0x6CAE, 0x9F9D, 0x6CB1, 0x9F9E, 0x6CBE, 0x9F9F, 0x6CBA, 0x9FA0, 0x6CDB, + 0x9FA1, 0x6CEF, 0x9FA2, 0x6CD9, 0x9FA3, 0x6CEA, 0x9FA4, 0x6D1F, 0x9FA5, 0x884D, 0x9FA6, 0x6D36, 0x9FA7, 0x6D2B, 0x9FA8, 0x6D3D, + 0x9FA9, 0x6D38, 0x9FAA, 0x6D19, 0x9FAB, 0x6D35, 0x9FAC, 0x6D33, 0x9FAD, 0x6D12, 0x9FAE, 0x6D0C, 0x9FAF, 0x6D63, 0x9FB0, 0x6D93, + 0x9FB1, 0x6D64, 0x9FB2, 0x6D5A, 0x9FB3, 0x6D79, 0x9FB4, 0x6D59, 0x9FB5, 0x6D8E, 0x9FB6, 0x6D95, 0x9FB7, 0x6FE4, 0x9FB8, 0x6D85, + 0x9FB9, 0x6DF9, 0x9FBA, 0x6E15, 0x9FBB, 0x6E0A, 0x9FBC, 0x6DB5, 0x9FBD, 0x6DC7, 0x9FBE, 0x6DE6, 0x9FBF, 0x6DB8, 0x9FC0, 0x6DC6, + 0x9FC1, 0x6DEC, 0x9FC2, 0x6DDE, 0x9FC3, 0x6DCC, 0x9FC4, 0x6DE8, 0x9FC5, 0x6DD2, 0x9FC6, 0x6DC5, 0x9FC7, 0x6DFA, 0x9FC8, 0x6DD9, + 0x9FC9, 0x6DE4, 0x9FCA, 0x6DD5, 0x9FCB, 0x6DEA, 0x9FCC, 0x6DEE, 0x9FCD, 0x6E2D, 0x9FCE, 0x6E6E, 0x9FCF, 0x6E2E, 0x9FD0, 0x6E19, + 0x9FD1, 0x6E72, 0x9FD2, 0x6E5F, 0x9FD3, 0x6E3E, 0x9FD4, 0x6E23, 0x9FD5, 0x6E6B, 0x9FD6, 0x6E2B, 0x9FD7, 0x6E76, 0x9FD8, 0x6E4D, + 0x9FD9, 0x6E1F, 0x9FDA, 0x6E43, 0x9FDB, 0x6E3A, 0x9FDC, 0x6E4E, 0x9FDD, 0x6E24, 0x9FDE, 0x6EFF, 0x9FDF, 0x6E1D, 0x9FE0, 0x6E38, + 0x9FE1, 0x6E82, 0x9FE2, 0x6EAA, 0x9FE3, 0x6E98, 0x9FE4, 0x6EC9, 0x9FE5, 0x6EB7, 0x9FE6, 0x6ED3, 0x9FE7, 0x6EBD, 0x9FE8, 0x6EAF, + 0x9FE9, 0x6EC4, 0x9FEA, 0x6EB2, 0x9FEB, 0x6ED4, 0x9FEC, 0x6ED5, 0x9FED, 0x6E8F, 0x9FEE, 0x6EA5, 0x9FEF, 0x6EC2, 0x9FF0, 0x6E9F, + 0x9FF1, 0x6F41, 0x9FF2, 0x6F11, 0x9FF3, 0x704C, 0x9FF4, 0x6EEC, 0x9FF5, 0x6EF8, 0x9FF6, 0x6EFE, 0x9FF7, 0x6F3F, 0x9FF8, 0x6EF2, + 0x9FF9, 0x6F31, 0x9FFA, 0x6EEF, 0x9FFB, 0x6F32, 0x9FFC, 0x6ECC, 0xE040, 0x6F3E, 0xE041, 0x6F13, 0xE042, 0x6EF7, 0xE043, 0x6F86, + 0xE044, 0x6F7A, 0xE045, 0x6F78, 0xE046, 0x6F81, 0xE047, 0x6F80, 0xE048, 0x6F6F, 0xE049, 0x6F5B, 0xE04A, 0x6FF3, 0xE04B, 0x6F6D, + 0xE04C, 0x6F82, 0xE04D, 0x6F7C, 0xE04E, 0x6F58, 0xE04F, 0x6F8E, 0xE050, 0x6F91, 0xE051, 0x6FC2, 0xE052, 0x6F66, 0xE053, 0x6FB3, + 0xE054, 0x6FA3, 0xE055, 0x6FA1, 0xE056, 0x6FA4, 0xE057, 0x6FB9, 0xE058, 0x6FC6, 0xE059, 0x6FAA, 0xE05A, 0x6FDF, 0xE05B, 0x6FD5, + 0xE05C, 0x6FEC, 0xE05D, 0x6FD4, 0xE05E, 0x6FD8, 0xE05F, 0x6FF1, 0xE060, 0x6FEE, 0xE061, 0x6FDB, 0xE062, 0x7009, 0xE063, 0x700B, + 0xE064, 0x6FFA, 0xE065, 0x7011, 0xE066, 0x7001, 0xE067, 0x700F, 0xE068, 0x6FFE, 0xE069, 0x701B, 0xE06A, 0x701A, 0xE06B, 0x6F74, + 0xE06C, 0x701D, 0xE06D, 0x7018, 0xE06E, 0x701F, 0xE06F, 0x7030, 0xE070, 0x703E, 0xE071, 0x7032, 0xE072, 0x7051, 0xE073, 0x7063, + 0xE074, 0x7099, 0xE075, 0x7092, 0xE076, 0x70AF, 0xE077, 0x70F1, 0xE078, 0x70AC, 0xE079, 0x70B8, 0xE07A, 0x70B3, 0xE07B, 0x70AE, + 0xE07C, 0x70DF, 0xE07D, 0x70CB, 0xE07E, 0x70DD, 0xE080, 0x70D9, 0xE081, 0x7109, 0xE082, 0x70FD, 0xE083, 0x711C, 0xE084, 0x7119, + 0xE085, 0x7165, 0xE086, 0x7155, 0xE087, 0x7188, 0xE088, 0x7166, 0xE089, 0x7162, 0xE08A, 0x714C, 0xE08B, 0x7156, 0xE08C, 0x716C, + 0xE08D, 0x718F, 0xE08E, 0x71FB, 0xE08F, 0x7184, 0xE090, 0x7195, 0xE091, 0x71A8, 0xE092, 0x71AC, 0xE093, 0x71D7, 0xE094, 0x71B9, + 0xE095, 0x71BE, 0xE096, 0x71D2, 0xE097, 0x71C9, 0xE098, 0x71D4, 0xE099, 0x71CE, 0xE09A, 0x71E0, 0xE09B, 0x71EC, 0xE09C, 0x71E7, + 0xE09D, 0x71F5, 0xE09E, 0x71FC, 0xE09F, 0x71F9, 0xE0A0, 0x71FF, 0xE0A1, 0x720D, 0xE0A2, 0x7210, 0xE0A3, 0x721B, 0xE0A4, 0x7228, + 0xE0A5, 0x722D, 0xE0A6, 0x722C, 0xE0A7, 0x7230, 0xE0A8, 0x7232, 0xE0A9, 0x723B, 0xE0AA, 0x723C, 0xE0AB, 0x723F, 0xE0AC, 0x7240, + 0xE0AD, 0x7246, 0xE0AE, 0x724B, 0xE0AF, 0x7258, 0xE0B0, 0x7274, 0xE0B1, 0x727E, 0xE0B2, 0x7282, 0xE0B3, 0x7281, 0xE0B4, 0x7287, + 0xE0B5, 0x7292, 0xE0B6, 0x7296, 0xE0B7, 0x72A2, 0xE0B8, 0x72A7, 0xE0B9, 0x72B9, 0xE0BA, 0x72B2, 0xE0BB, 0x72C3, 0xE0BC, 0x72C6, + 0xE0BD, 0x72C4, 0xE0BE, 0x72CE, 0xE0BF, 0x72D2, 0xE0C0, 0x72E2, 0xE0C1, 0x72E0, 0xE0C2, 0x72E1, 0xE0C3, 0x72F9, 0xE0C4, 0x72F7, + 0xE0C5, 0x500F, 0xE0C6, 0x7317, 0xE0C7, 0x730A, 0xE0C8, 0x731C, 0xE0C9, 0x7316, 0xE0CA, 0x731D, 0xE0CB, 0x7334, 0xE0CC, 0x732F, + 0xE0CD, 0x7329, 0xE0CE, 0x7325, 0xE0CF, 0x733E, 0xE0D0, 0x734E, 0xE0D1, 0x734F, 0xE0D2, 0x9ED8, 0xE0D3, 0x7357, 0xE0D4, 0x736A, + 0xE0D5, 0x7368, 0xE0D6, 0x7370, 0xE0D7, 0x7378, 0xE0D8, 0x7375, 0xE0D9, 0x737B, 0xE0DA, 0x737A, 0xE0DB, 0x73C8, 0xE0DC, 0x73B3, + 0xE0DD, 0x73CE, 0xE0DE, 0x73BB, 0xE0DF, 0x73C0, 0xE0E0, 0x73E5, 0xE0E1, 0x73EE, 0xE0E2, 0x73DE, 0xE0E3, 0x74A2, 0xE0E4, 0x7405, + 0xE0E5, 0x746F, 0xE0E6, 0x7425, 0xE0E7, 0x73F8, 0xE0E8, 0x7432, 0xE0E9, 0x743A, 0xE0EA, 0x7455, 0xE0EB, 0x743F, 0xE0EC, 0x745F, + 0xE0ED, 0x7459, 0xE0EE, 0x7441, 0xE0EF, 0x745C, 0xE0F0, 0x7469, 0xE0F1, 0x7470, 0xE0F2, 0x7463, 0xE0F3, 0x746A, 0xE0F4, 0x7476, + 0xE0F5, 0x747E, 0xE0F6, 0x748B, 0xE0F7, 0x749E, 0xE0F8, 0x74A7, 0xE0F9, 0x74CA, 0xE0FA, 0x74CF, 0xE0FB, 0x74D4, 0xE0FC, 0x73F1, + 0xE140, 0x74E0, 0xE141, 0x74E3, 0xE142, 0x74E7, 0xE143, 0x74E9, 0xE144, 0x74EE, 0xE145, 0x74F2, 0xE146, 0x74F0, 0xE147, 0x74F1, + 0xE148, 0x74F8, 0xE149, 0x74F7, 0xE14A, 0x7504, 0xE14B, 0x7503, 0xE14C, 0x7505, 0xE14D, 0x750C, 0xE14E, 0x750E, 0xE14F, 0x750D, + 0xE150, 0x7515, 0xE151, 0x7513, 0xE152, 0x751E, 0xE153, 0x7526, 0xE154, 0x752C, 0xE155, 0x753C, 0xE156, 0x7544, 0xE157, 0x754D, + 0xE158, 0x754A, 0xE159, 0x7549, 0xE15A, 0x755B, 0xE15B, 0x7546, 0xE15C, 0x755A, 0xE15D, 0x7569, 0xE15E, 0x7564, 0xE15F, 0x7567, + 0xE160, 0x756B, 0xE161, 0x756D, 0xE162, 0x7578, 0xE163, 0x7576, 0xE164, 0x7586, 0xE165, 0x7587, 0xE166, 0x7574, 0xE167, 0x758A, + 0xE168, 0x7589, 0xE169, 0x7582, 0xE16A, 0x7594, 0xE16B, 0x759A, 0xE16C, 0x759D, 0xE16D, 0x75A5, 0xE16E, 0x75A3, 0xE16F, 0x75C2, + 0xE170, 0x75B3, 0xE171, 0x75C3, 0xE172, 0x75B5, 0xE173, 0x75BD, 0xE174, 0x75B8, 0xE175, 0x75BC, 0xE176, 0x75B1, 0xE177, 0x75CD, + 0xE178, 0x75CA, 0xE179, 0x75D2, 0xE17A, 0x75D9, 0xE17B, 0x75E3, 0xE17C, 0x75DE, 0xE17D, 0x75FE, 0xE17E, 0x75FF, 0xE180, 0x75FC, + 0xE181, 0x7601, 0xE182, 0x75F0, 0xE183, 0x75FA, 0xE184, 0x75F2, 0xE185, 0x75F3, 0xE186, 0x760B, 0xE187, 0x760D, 0xE188, 0x7609, + 0xE189, 0x761F, 0xE18A, 0x7627, 0xE18B, 0x7620, 0xE18C, 0x7621, 0xE18D, 0x7622, 0xE18E, 0x7624, 0xE18F, 0x7634, 0xE190, 0x7630, + 0xE191, 0x763B, 0xE192, 0x7647, 0xE193, 0x7648, 0xE194, 0x7646, 0xE195, 0x765C, 0xE196, 0x7658, 0xE197, 0x7661, 0xE198, 0x7662, + 0xE199, 0x7668, 0xE19A, 0x7669, 0xE19B, 0x766A, 0xE19C, 0x7667, 0xE19D, 0x766C, 0xE19E, 0x7670, 0xE19F, 0x7672, 0xE1A0, 0x7676, + 0xE1A1, 0x7678, 0xE1A2, 0x767C, 0xE1A3, 0x7680, 0xE1A4, 0x7683, 0xE1A5, 0x7688, 0xE1A6, 0x768B, 0xE1A7, 0x768E, 0xE1A8, 0x7696, + 0xE1A9, 0x7693, 0xE1AA, 0x7699, 0xE1AB, 0x769A, 0xE1AC, 0x76B0, 0xE1AD, 0x76B4, 0xE1AE, 0x76B8, 0xE1AF, 0x76B9, 0xE1B0, 0x76BA, + 0xE1B1, 0x76C2, 0xE1B2, 0x76CD, 0xE1B3, 0x76D6, 0xE1B4, 0x76D2, 0xE1B5, 0x76DE, 0xE1B6, 0x76E1, 0xE1B7, 0x76E5, 0xE1B8, 0x76E7, + 0xE1B9, 0x76EA, 0xE1BA, 0x862F, 0xE1BB, 0x76FB, 0xE1BC, 0x7708, 0xE1BD, 0x7707, 0xE1BE, 0x7704, 0xE1BF, 0x7729, 0xE1C0, 0x7724, + 0xE1C1, 0x771E, 0xE1C2, 0x7725, 0xE1C3, 0x7726, 0xE1C4, 0x771B, 0xE1C5, 0x7737, 0xE1C6, 0x7738, 0xE1C7, 0x7747, 0xE1C8, 0x775A, + 0xE1C9, 0x7768, 0xE1CA, 0x776B, 0xE1CB, 0x775B, 0xE1CC, 0x7765, 0xE1CD, 0x777F, 0xE1CE, 0x777E, 0xE1CF, 0x7779, 0xE1D0, 0x778E, + 0xE1D1, 0x778B, 0xE1D2, 0x7791, 0xE1D3, 0x77A0, 0xE1D4, 0x779E, 0xE1D5, 0x77B0, 0xE1D6, 0x77B6, 0xE1D7, 0x77B9, 0xE1D8, 0x77BF, + 0xE1D9, 0x77BC, 0xE1DA, 0x77BD, 0xE1DB, 0x77BB, 0xE1DC, 0x77C7, 0xE1DD, 0x77CD, 0xE1DE, 0x77D7, 0xE1DF, 0x77DA, 0xE1E0, 0x77DC, + 0xE1E1, 0x77E3, 0xE1E2, 0x77EE, 0xE1E3, 0x77FC, 0xE1E4, 0x780C, 0xE1E5, 0x7812, 0xE1E6, 0x7926, 0xE1E7, 0x7820, 0xE1E8, 0x792A, + 0xE1E9, 0x7845, 0xE1EA, 0x788E, 0xE1EB, 0x7874, 0xE1EC, 0x7886, 0xE1ED, 0x787C, 0xE1EE, 0x789A, 0xE1EF, 0x788C, 0xE1F0, 0x78A3, + 0xE1F1, 0x78B5, 0xE1F2, 0x78AA, 0xE1F3, 0x78AF, 0xE1F4, 0x78D1, 0xE1F5, 0x78C6, 0xE1F6, 0x78CB, 0xE1F7, 0x78D4, 0xE1F8, 0x78BE, + 0xE1F9, 0x78BC, 0xE1FA, 0x78C5, 0xE1FB, 0x78CA, 0xE1FC, 0x78EC, 0xE240, 0x78E7, 0xE241, 0x78DA, 0xE242, 0x78FD, 0xE243, 0x78F4, + 0xE244, 0x7907, 0xE245, 0x7912, 0xE246, 0x7911, 0xE247, 0x7919, 0xE248, 0x792C, 0xE249, 0x792B, 0xE24A, 0x7940, 0xE24B, 0x7960, + 0xE24C, 0x7957, 0xE24D, 0x795F, 0xE24E, 0x795A, 0xE24F, 0x7955, 0xE250, 0x7953, 0xE251, 0x797A, 0xE252, 0x797F, 0xE253, 0x798A, + 0xE254, 0x799D, 0xE255, 0x79A7, 0xE256, 0x9F4B, 0xE257, 0x79AA, 0xE258, 0x79AE, 0xE259, 0x79B3, 0xE25A, 0x79B9, 0xE25B, 0x79BA, + 0xE25C, 0x79C9, 0xE25D, 0x79D5, 0xE25E, 0x79E7, 0xE25F, 0x79EC, 0xE260, 0x79E1, 0xE261, 0x79E3, 0xE262, 0x7A08, 0xE263, 0x7A0D, + 0xE264, 0x7A18, 0xE265, 0x7A19, 0xE266, 0x7A20, 0xE267, 0x7A1F, 0xE268, 0x7980, 0xE269, 0x7A31, 0xE26A, 0x7A3B, 0xE26B, 0x7A3E, + 0xE26C, 0x7A37, 0xE26D, 0x7A43, 0xE26E, 0x7A57, 0xE26F, 0x7A49, 0xE270, 0x7A61, 0xE271, 0x7A62, 0xE272, 0x7A69, 0xE273, 0x9F9D, + 0xE274, 0x7A70, 0xE275, 0x7A79, 0xE276, 0x7A7D, 0xE277, 0x7A88, 0xE278, 0x7A97, 0xE279, 0x7A95, 0xE27A, 0x7A98, 0xE27B, 0x7A96, + 0xE27C, 0x7AA9, 0xE27D, 0x7AC8, 0xE27E, 0x7AB0, 0xE280, 0x7AB6, 0xE281, 0x7AC5, 0xE282, 0x7AC4, 0xE283, 0x7ABF, 0xE284, 0x9083, + 0xE285, 0x7AC7, 0xE286, 0x7ACA, 0xE287, 0x7ACD, 0xE288, 0x7ACF, 0xE289, 0x7AD5, 0xE28A, 0x7AD3, 0xE28B, 0x7AD9, 0xE28C, 0x7ADA, + 0xE28D, 0x7ADD, 0xE28E, 0x7AE1, 0xE28F, 0x7AE2, 0xE290, 0x7AE6, 0xE291, 0x7AED, 0xE292, 0x7AF0, 0xE293, 0x7B02, 0xE294, 0x7B0F, + 0xE295, 0x7B0A, 0xE296, 0x7B06, 0xE297, 0x7B33, 0xE298, 0x7B18, 0xE299, 0x7B19, 0xE29A, 0x7B1E, 0xE29B, 0x7B35, 0xE29C, 0x7B28, + 0xE29D, 0x7B36, 0xE29E, 0x7B50, 0xE29F, 0x7B7A, 0xE2A0, 0x7B04, 0xE2A1, 0x7B4D, 0xE2A2, 0x7B0B, 0xE2A3, 0x7B4C, 0xE2A4, 0x7B45, + 0xE2A5, 0x7B75, 0xE2A6, 0x7B65, 0xE2A7, 0x7B74, 0xE2A8, 0x7B67, 0xE2A9, 0x7B70, 0xE2AA, 0x7B71, 0xE2AB, 0x7B6C, 0xE2AC, 0x7B6E, + 0xE2AD, 0x7B9D, 0xE2AE, 0x7B98, 0xE2AF, 0x7B9F, 0xE2B0, 0x7B8D, 0xE2B1, 0x7B9C, 0xE2B2, 0x7B9A, 0xE2B3, 0x7B8B, 0xE2B4, 0x7B92, + 0xE2B5, 0x7B8F, 0xE2B6, 0x7B5D, 0xE2B7, 0x7B99, 0xE2B8, 0x7BCB, 0xE2B9, 0x7BC1, 0xE2BA, 0x7BCC, 0xE2BB, 0x7BCF, 0xE2BC, 0x7BB4, + 0xE2BD, 0x7BC6, 0xE2BE, 0x7BDD, 0xE2BF, 0x7BE9, 0xE2C0, 0x7C11, 0xE2C1, 0x7C14, 0xE2C2, 0x7BE6, 0xE2C3, 0x7BE5, 0xE2C4, 0x7C60, + 0xE2C5, 0x7C00, 0xE2C6, 0x7C07, 0xE2C7, 0x7C13, 0xE2C8, 0x7BF3, 0xE2C9, 0x7BF7, 0xE2CA, 0x7C17, 0xE2CB, 0x7C0D, 0xE2CC, 0x7BF6, + 0xE2CD, 0x7C23, 0xE2CE, 0x7C27, 0xE2CF, 0x7C2A, 0xE2D0, 0x7C1F, 0xE2D1, 0x7C37, 0xE2D2, 0x7C2B, 0xE2D3, 0x7C3D, 0xE2D4, 0x7C4C, + 0xE2D5, 0x7C43, 0xE2D6, 0x7C54, 0xE2D7, 0x7C4F, 0xE2D8, 0x7C40, 0xE2D9, 0x7C50, 0xE2DA, 0x7C58, 0xE2DB, 0x7C5F, 0xE2DC, 0x7C64, + 0xE2DD, 0x7C56, 0xE2DE, 0x7C65, 0xE2DF, 0x7C6C, 0xE2E0, 0x7C75, 0xE2E1, 0x7C83, 0xE2E2, 0x7C90, 0xE2E3, 0x7CA4, 0xE2E4, 0x7CAD, + 0xE2E5, 0x7CA2, 0xE2E6, 0x7CAB, 0xE2E7, 0x7CA1, 0xE2E8, 0x7CA8, 0xE2E9, 0x7CB3, 0xE2EA, 0x7CB2, 0xE2EB, 0x7CB1, 0xE2EC, 0x7CAE, + 0xE2ED, 0x7CB9, 0xE2EE, 0x7CBD, 0xE2EF, 0x7CC0, 0xE2F0, 0x7CC5, 0xE2F1, 0x7CC2, 0xE2F2, 0x7CD8, 0xE2F3, 0x7CD2, 0xE2F4, 0x7CDC, + 0xE2F5, 0x7CE2, 0xE2F6, 0x9B3B, 0xE2F7, 0x7CEF, 0xE2F8, 0x7CF2, 0xE2F9, 0x7CF4, 0xE2FA, 0x7CF6, 0xE2FB, 0x7CFA, 0xE2FC, 0x7D06, + 0xE340, 0x7D02, 0xE341, 0x7D1C, 0xE342, 0x7D15, 0xE343, 0x7D0A, 0xE344, 0x7D45, 0xE345, 0x7D4B, 0xE346, 0x7D2E, 0xE347, 0x7D32, + 0xE348, 0x7D3F, 0xE349, 0x7D35, 0xE34A, 0x7D46, 0xE34B, 0x7D73, 0xE34C, 0x7D56, 0xE34D, 0x7D4E, 0xE34E, 0x7D72, 0xE34F, 0x7D68, + 0xE350, 0x7D6E, 0xE351, 0x7D4F, 0xE352, 0x7D63, 0xE353, 0x7D93, 0xE354, 0x7D89, 0xE355, 0x7D5B, 0xE356, 0x7D8F, 0xE357, 0x7D7D, + 0xE358, 0x7D9B, 0xE359, 0x7DBA, 0xE35A, 0x7DAE, 0xE35B, 0x7DA3, 0xE35C, 0x7DB5, 0xE35D, 0x7DC7, 0xE35E, 0x7DBD, 0xE35F, 0x7DAB, + 0xE360, 0x7E3D, 0xE361, 0x7DA2, 0xE362, 0x7DAF, 0xE363, 0x7DDC, 0xE364, 0x7DB8, 0xE365, 0x7D9F, 0xE366, 0x7DB0, 0xE367, 0x7DD8, + 0xE368, 0x7DDD, 0xE369, 0x7DE4, 0xE36A, 0x7DDE, 0xE36B, 0x7DFB, 0xE36C, 0x7DF2, 0xE36D, 0x7DE1, 0xE36E, 0x7E05, 0xE36F, 0x7E0A, + 0xE370, 0x7E23, 0xE371, 0x7E21, 0xE372, 0x7E12, 0xE373, 0x7E31, 0xE374, 0x7E1F, 0xE375, 0x7E09, 0xE376, 0x7E0B, 0xE377, 0x7E22, + 0xE378, 0x7E46, 0xE379, 0x7E66, 0xE37A, 0x7E3B, 0xE37B, 0x7E35, 0xE37C, 0x7E39, 0xE37D, 0x7E43, 0xE37E, 0x7E37, 0xE380, 0x7E32, + 0xE381, 0x7E3A, 0xE382, 0x7E67, 0xE383, 0x7E5D, 0xE384, 0x7E56, 0xE385, 0x7E5E, 0xE386, 0x7E59, 0xE387, 0x7E5A, 0xE388, 0x7E79, + 0xE389, 0x7E6A, 0xE38A, 0x7E69, 0xE38B, 0x7E7C, 0xE38C, 0x7E7B, 0xE38D, 0x7E83, 0xE38E, 0x7DD5, 0xE38F, 0x7E7D, 0xE390, 0x8FAE, + 0xE391, 0x7E7F, 0xE392, 0x7E88, 0xE393, 0x7E89, 0xE394, 0x7E8C, 0xE395, 0x7E92, 0xE396, 0x7E90, 0xE397, 0x7E93, 0xE398, 0x7E94, + 0xE399, 0x7E96, 0xE39A, 0x7E8E, 0xE39B, 0x7E9B, 0xE39C, 0x7E9C, 0xE39D, 0x7F38, 0xE39E, 0x7F3A, 0xE39F, 0x7F45, 0xE3A0, 0x7F4C, + 0xE3A1, 0x7F4D, 0xE3A2, 0x7F4E, 0xE3A3, 0x7F50, 0xE3A4, 0x7F51, 0xE3A5, 0x7F55, 0xE3A6, 0x7F54, 0xE3A7, 0x7F58, 0xE3A8, 0x7F5F, + 0xE3A9, 0x7F60, 0xE3AA, 0x7F68, 0xE3AB, 0x7F69, 0xE3AC, 0x7F67, 0xE3AD, 0x7F78, 0xE3AE, 0x7F82, 0xE3AF, 0x7F86, 0xE3B0, 0x7F83, + 0xE3B1, 0x7F88, 0xE3B2, 0x7F87, 0xE3B3, 0x7F8C, 0xE3B4, 0x7F94, 0xE3B5, 0x7F9E, 0xE3B6, 0x7F9D, 0xE3B7, 0x7F9A, 0xE3B8, 0x7FA3, + 0xE3B9, 0x7FAF, 0xE3BA, 0x7FB2, 0xE3BB, 0x7FB9, 0xE3BC, 0x7FAE, 0xE3BD, 0x7FB6, 0xE3BE, 0x7FB8, 0xE3BF, 0x8B71, 0xE3C0, 0x7FC5, + 0xE3C1, 0x7FC6, 0xE3C2, 0x7FCA, 0xE3C3, 0x7FD5, 0xE3C4, 0x7FD4, 0xE3C5, 0x7FE1, 0xE3C6, 0x7FE6, 0xE3C7, 0x7FE9, 0xE3C8, 0x7FF3, + 0xE3C9, 0x7FF9, 0xE3CA, 0x98DC, 0xE3CB, 0x8006, 0xE3CC, 0x8004, 0xE3CD, 0x800B, 0xE3CE, 0x8012, 0xE3CF, 0x8018, 0xE3D0, 0x8019, + 0xE3D1, 0x801C, 0xE3D2, 0x8021, 0xE3D3, 0x8028, 0xE3D4, 0x803F, 0xE3D5, 0x803B, 0xE3D6, 0x804A, 0xE3D7, 0x8046, 0xE3D8, 0x8052, + 0xE3D9, 0x8058, 0xE3DA, 0x805A, 0xE3DB, 0x805F, 0xE3DC, 0x8062, 0xE3DD, 0x8068, 0xE3DE, 0x8073, 0xE3DF, 0x8072, 0xE3E0, 0x8070, + 0xE3E1, 0x8076, 0xE3E2, 0x8079, 0xE3E3, 0x807D, 0xE3E4, 0x807F, 0xE3E5, 0x8084, 0xE3E6, 0x8086, 0xE3E7, 0x8085, 0xE3E8, 0x809B, + 0xE3E9, 0x8093, 0xE3EA, 0x809A, 0xE3EB, 0x80AD, 0xE3EC, 0x5190, 0xE3ED, 0x80AC, 0xE3EE, 0x80DB, 0xE3EF, 0x80E5, 0xE3F0, 0x80D9, + 0xE3F1, 0x80DD, 0xE3F2, 0x80C4, 0xE3F3, 0x80DA, 0xE3F4, 0x80D6, 0xE3F5, 0x8109, 0xE3F6, 0x80EF, 0xE3F7, 0x80F1, 0xE3F8, 0x811B, + 0xE3F9, 0x8129, 0xE3FA, 0x8123, 0xE3FB, 0x812F, 0xE3FC, 0x814B, 0xE440, 0x968B, 0xE441, 0x8146, 0xE442, 0x813E, 0xE443, 0x8153, + 0xE444, 0x8151, 0xE445, 0x80FC, 0xE446, 0x8171, 0xE447, 0x816E, 0xE448, 0x8165, 0xE449, 0x8166, 0xE44A, 0x8174, 0xE44B, 0x8183, + 0xE44C, 0x8188, 0xE44D, 0x818A, 0xE44E, 0x8180, 0xE44F, 0x8182, 0xE450, 0x81A0, 0xE451, 0x8195, 0xE452, 0x81A4, 0xE453, 0x81A3, + 0xE454, 0x815F, 0xE455, 0x8193, 0xE456, 0x81A9, 0xE457, 0x81B0, 0xE458, 0x81B5, 0xE459, 0x81BE, 0xE45A, 0x81B8, 0xE45B, 0x81BD, + 0xE45C, 0x81C0, 0xE45D, 0x81C2, 0xE45E, 0x81BA, 0xE45F, 0x81C9, 0xE460, 0x81CD, 0xE461, 0x81D1, 0xE462, 0x81D9, 0xE463, 0x81D8, + 0xE464, 0x81C8, 0xE465, 0x81DA, 0xE466, 0x81DF, 0xE467, 0x81E0, 0xE468, 0x81E7, 0xE469, 0x81FA, 0xE46A, 0x81FB, 0xE46B, 0x81FE, + 0xE46C, 0x8201, 0xE46D, 0x8202, 0xE46E, 0x8205, 0xE46F, 0x8207, 0xE470, 0x820A, 0xE471, 0x820D, 0xE472, 0x8210, 0xE473, 0x8216, + 0xE474, 0x8229, 0xE475, 0x822B, 0xE476, 0x8238, 0xE477, 0x8233, 0xE478, 0x8240, 0xE479, 0x8259, 0xE47A, 0x8258, 0xE47B, 0x825D, + 0xE47C, 0x825A, 0xE47D, 0x825F, 0xE47E, 0x8264, 0xE480, 0x8262, 0xE481, 0x8268, 0xE482, 0x826A, 0xE483, 0x826B, 0xE484, 0x822E, + 0xE485, 0x8271, 0xE486, 0x8277, 0xE487, 0x8278, 0xE488, 0x827E, 0xE489, 0x828D, 0xE48A, 0x8292, 0xE48B, 0x82AB, 0xE48C, 0x829F, + 0xE48D, 0x82BB, 0xE48E, 0x82AC, 0xE48F, 0x82E1, 0xE490, 0x82E3, 0xE491, 0x82DF, 0xE492, 0x82D2, 0xE493, 0x82F4, 0xE494, 0x82F3, + 0xE495, 0x82FA, 0xE496, 0x8393, 0xE497, 0x8303, 0xE498, 0x82FB, 0xE499, 0x82F9, 0xE49A, 0x82DE, 0xE49B, 0x8306, 0xE49C, 0x82DC, + 0xE49D, 0x8309, 0xE49E, 0x82D9, 0xE49F, 0x8335, 0xE4A0, 0x8334, 0xE4A1, 0x8316, 0xE4A2, 0x8332, 0xE4A3, 0x8331, 0xE4A4, 0x8340, + 0xE4A5, 0x8339, 0xE4A6, 0x8350, 0xE4A7, 0x8345, 0xE4A8, 0x832F, 0xE4A9, 0x832B, 0xE4AA, 0x8317, 0xE4AB, 0x8318, 0xE4AC, 0x8385, + 0xE4AD, 0x839A, 0xE4AE, 0x83AA, 0xE4AF, 0x839F, 0xE4B0, 0x83A2, 0xE4B1, 0x8396, 0xE4B2, 0x8323, 0xE4B3, 0x838E, 0xE4B4, 0x8387, + 0xE4B5, 0x838A, 0xE4B6, 0x837C, 0xE4B7, 0x83B5, 0xE4B8, 0x8373, 0xE4B9, 0x8375, 0xE4BA, 0x83A0, 0xE4BB, 0x8389, 0xE4BC, 0x83A8, + 0xE4BD, 0x83F4, 0xE4BE, 0x8413, 0xE4BF, 0x83EB, 0xE4C0, 0x83CE, 0xE4C1, 0x83FD, 0xE4C2, 0x8403, 0xE4C3, 0x83D8, 0xE4C4, 0x840B, + 0xE4C5, 0x83C1, 0xE4C6, 0x83F7, 0xE4C7, 0x8407, 0xE4C8, 0x83E0, 0xE4C9, 0x83F2, 0xE4CA, 0x840D, 0xE4CB, 0x8422, 0xE4CC, 0x8420, + 0xE4CD, 0x83BD, 0xE4CE, 0x8438, 0xE4CF, 0x8506, 0xE4D0, 0x83FB, 0xE4D1, 0x846D, 0xE4D2, 0x842A, 0xE4D3, 0x843C, 0xE4D4, 0x855A, + 0xE4D5, 0x8484, 0xE4D6, 0x8477, 0xE4D7, 0x846B, 0xE4D8, 0x84AD, 0xE4D9, 0x846E, 0xE4DA, 0x8482, 0xE4DB, 0x8469, 0xE4DC, 0x8446, + 0xE4DD, 0x842C, 0xE4DE, 0x846F, 0xE4DF, 0x8479, 0xE4E0, 0x8435, 0xE4E1, 0x84CA, 0xE4E2, 0x8462, 0xE4E3, 0x84B9, 0xE4E4, 0x84BF, + 0xE4E5, 0x849F, 0xE4E6, 0x84D9, 0xE4E7, 0x84CD, 0xE4E8, 0x84BB, 0xE4E9, 0x84DA, 0xE4EA, 0x84D0, 0xE4EB, 0x84C1, 0xE4EC, 0x84C6, + 0xE4ED, 0x84D6, 0xE4EE, 0x84A1, 0xE4EF, 0x8521, 0xE4F0, 0x84FF, 0xE4F1, 0x84F4, 0xE4F2, 0x8517, 0xE4F3, 0x8518, 0xE4F4, 0x852C, + 0xE4F5, 0x851F, 0xE4F6, 0x8515, 0xE4F7, 0x8514, 0xE4F8, 0x84FC, 0xE4F9, 0x8540, 0xE4FA, 0x8563, 0xE4FB, 0x8558, 0xE4FC, 0x8548, + 0xE540, 0x8541, 0xE541, 0x8602, 0xE542, 0x854B, 0xE543, 0x8555, 0xE544, 0x8580, 0xE545, 0x85A4, 0xE546, 0x8588, 0xE547, 0x8591, + 0xE548, 0x858A, 0xE549, 0x85A8, 0xE54A, 0x856D, 0xE54B, 0x8594, 0xE54C, 0x859B, 0xE54D, 0x85EA, 0xE54E, 0x8587, 0xE54F, 0x859C, + 0xE550, 0x8577, 0xE551, 0x857E, 0xE552, 0x8590, 0xE553, 0x85C9, 0xE554, 0x85BA, 0xE555, 0x85CF, 0xE556, 0x85B9, 0xE557, 0x85D0, + 0xE558, 0x85D5, 0xE559, 0x85DD, 0xE55A, 0x85E5, 0xE55B, 0x85DC, 0xE55C, 0x85F9, 0xE55D, 0x860A, 0xE55E, 0x8613, 0xE55F, 0x860B, + 0xE560, 0x85FE, 0xE561, 0x85FA, 0xE562, 0x8606, 0xE563, 0x8622, 0xE564, 0x861A, 0xE565, 0x8630, 0xE566, 0x863F, 0xE567, 0x864D, + 0xE568, 0x4E55, 0xE569, 0x8654, 0xE56A, 0x865F, 0xE56B, 0x8667, 0xE56C, 0x8671, 0xE56D, 0x8693, 0xE56E, 0x86A3, 0xE56F, 0x86A9, + 0xE570, 0x86AA, 0xE571, 0x868B, 0xE572, 0x868C, 0xE573, 0x86B6, 0xE574, 0x86AF, 0xE575, 0x86C4, 0xE576, 0x86C6, 0xE577, 0x86B0, + 0xE578, 0x86C9, 0xE579, 0x8823, 0xE57A, 0x86AB, 0xE57B, 0x86D4, 0xE57C, 0x86DE, 0xE57D, 0x86E9, 0xE57E, 0x86EC, 0xE580, 0x86DF, + 0xE581, 0x86DB, 0xE582, 0x86EF, 0xE583, 0x8712, 0xE584, 0x8706, 0xE585, 0x8708, 0xE586, 0x8700, 0xE587, 0x8703, 0xE588, 0x86FB, + 0xE589, 0x8711, 0xE58A, 0x8709, 0xE58B, 0x870D, 0xE58C, 0x86F9, 0xE58D, 0x870A, 0xE58E, 0x8734, 0xE58F, 0x873F, 0xE590, 0x8737, + 0xE591, 0x873B, 0xE592, 0x8725, 0xE593, 0x8729, 0xE594, 0x871A, 0xE595, 0x8760, 0xE596, 0x875F, 0xE597, 0x8778, 0xE598, 0x874C, + 0xE599, 0x874E, 0xE59A, 0x8774, 0xE59B, 0x8757, 0xE59C, 0x8768, 0xE59D, 0x876E, 0xE59E, 0x8759, 0xE59F, 0x8753, 0xE5A0, 0x8763, + 0xE5A1, 0x876A, 0xE5A2, 0x8805, 0xE5A3, 0x87A2, 0xE5A4, 0x879F, 0xE5A5, 0x8782, 0xE5A6, 0x87AF, 0xE5A7, 0x87CB, 0xE5A8, 0x87BD, + 0xE5A9, 0x87C0, 0xE5AA, 0x87D0, 0xE5AB, 0x96D6, 0xE5AC, 0x87AB, 0xE5AD, 0x87C4, 0xE5AE, 0x87B3, 0xE5AF, 0x87C7, 0xE5B0, 0x87C6, + 0xE5B1, 0x87BB, 0xE5B2, 0x87EF, 0xE5B3, 0x87F2, 0xE5B4, 0x87E0, 0xE5B5, 0x880F, 0xE5B6, 0x880D, 0xE5B7, 0x87FE, 0xE5B8, 0x87F6, + 0xE5B9, 0x87F7, 0xE5BA, 0x880E, 0xE5BB, 0x87D2, 0xE5BC, 0x8811, 0xE5BD, 0x8816, 0xE5BE, 0x8815, 0xE5BF, 0x8822, 0xE5C0, 0x8821, + 0xE5C1, 0x8831, 0xE5C2, 0x8836, 0xE5C3, 0x8839, 0xE5C4, 0x8827, 0xE5C5, 0x883B, 0xE5C6, 0x8844, 0xE5C7, 0x8842, 0xE5C8, 0x8852, + 0xE5C9, 0x8859, 0xE5CA, 0x885E, 0xE5CB, 0x8862, 0xE5CC, 0x886B, 0xE5CD, 0x8881, 0xE5CE, 0x887E, 0xE5CF, 0x889E, 0xE5D0, 0x8875, + 0xE5D1, 0x887D, 0xE5D2, 0x88B5, 0xE5D3, 0x8872, 0xE5D4, 0x8882, 0xE5D5, 0x8897, 0xE5D6, 0x8892, 0xE5D7, 0x88AE, 0xE5D8, 0x8899, + 0xE5D9, 0x88A2, 0xE5DA, 0x888D, 0xE5DB, 0x88A4, 0xE5DC, 0x88B0, 0xE5DD, 0x88BF, 0xE5DE, 0x88B1, 0xE5DF, 0x88C3, 0xE5E0, 0x88C4, + 0xE5E1, 0x88D4, 0xE5E2, 0x88D8, 0xE5E3, 0x88D9, 0xE5E4, 0x88DD, 0xE5E5, 0x88F9, 0xE5E6, 0x8902, 0xE5E7, 0x88FC, 0xE5E8, 0x88F4, + 0xE5E9, 0x88E8, 0xE5EA, 0x88F2, 0xE5EB, 0x8904, 0xE5EC, 0x890C, 0xE5ED, 0x890A, 0xE5EE, 0x8913, 0xE5EF, 0x8943, 0xE5F0, 0x891E, + 0xE5F1, 0x8925, 0xE5F2, 0x892A, 0xE5F3, 0x892B, 0xE5F4, 0x8941, 0xE5F5, 0x8944, 0xE5F6, 0x893B, 0xE5F7, 0x8936, 0xE5F8, 0x8938, + 0xE5F9, 0x894C, 0xE5FA, 0x891D, 0xE5FB, 0x8960, 0xE5FC, 0x895E, 0xE640, 0x8966, 0xE641, 0x8964, 0xE642, 0x896D, 0xE643, 0x896A, + 0xE644, 0x896F, 0xE645, 0x8974, 0xE646, 0x8977, 0xE647, 0x897E, 0xE648, 0x8983, 0xE649, 0x8988, 0xE64A, 0x898A, 0xE64B, 0x8993, + 0xE64C, 0x8998, 0xE64D, 0x89A1, 0xE64E, 0x89A9, 0xE64F, 0x89A6, 0xE650, 0x89AC, 0xE651, 0x89AF, 0xE652, 0x89B2, 0xE653, 0x89BA, + 0xE654, 0x89BD, 0xE655, 0x89BF, 0xE656, 0x89C0, 0xE657, 0x89DA, 0xE658, 0x89DC, 0xE659, 0x89DD, 0xE65A, 0x89E7, 0xE65B, 0x89F4, + 0xE65C, 0x89F8, 0xE65D, 0x8A03, 0xE65E, 0x8A16, 0xE65F, 0x8A10, 0xE660, 0x8A0C, 0xE661, 0x8A1B, 0xE662, 0x8A1D, 0xE663, 0x8A25, + 0xE664, 0x8A36, 0xE665, 0x8A41, 0xE666, 0x8A5B, 0xE667, 0x8A52, 0xE668, 0x8A46, 0xE669, 0x8A48, 0xE66A, 0x8A7C, 0xE66B, 0x8A6D, + 0xE66C, 0x8A6C, 0xE66D, 0x8A62, 0xE66E, 0x8A85, 0xE66F, 0x8A82, 0xE670, 0x8A84, 0xE671, 0x8AA8, 0xE672, 0x8AA1, 0xE673, 0x8A91, + 0xE674, 0x8AA5, 0xE675, 0x8AA6, 0xE676, 0x8A9A, 0xE677, 0x8AA3, 0xE678, 0x8AC4, 0xE679, 0x8ACD, 0xE67A, 0x8AC2, 0xE67B, 0x8ADA, + 0xE67C, 0x8AEB, 0xE67D, 0x8AF3, 0xE67E, 0x8AE7, 0xE680, 0x8AE4, 0xE681, 0x8AF1, 0xE682, 0x8B14, 0xE683, 0x8AE0, 0xE684, 0x8AE2, + 0xE685, 0x8AF7, 0xE686, 0x8ADE, 0xE687, 0x8ADB, 0xE688, 0x8B0C, 0xE689, 0x8B07, 0xE68A, 0x8B1A, 0xE68B, 0x8AE1, 0xE68C, 0x8B16, + 0xE68D, 0x8B10, 0xE68E, 0x8B17, 0xE68F, 0x8B20, 0xE690, 0x8B33, 0xE691, 0x97AB, 0xE692, 0x8B26, 0xE693, 0x8B2B, 0xE694, 0x8B3E, + 0xE695, 0x8B28, 0xE696, 0x8B41, 0xE697, 0x8B4C, 0xE698, 0x8B4F, 0xE699, 0x8B4E, 0xE69A, 0x8B49, 0xE69B, 0x8B56, 0xE69C, 0x8B5B, + 0xE69D, 0x8B5A, 0xE69E, 0x8B6B, 0xE69F, 0x8B5F, 0xE6A0, 0x8B6C, 0xE6A1, 0x8B6F, 0xE6A2, 0x8B74, 0xE6A3, 0x8B7D, 0xE6A4, 0x8B80, + 0xE6A5, 0x8B8C, 0xE6A6, 0x8B8E, 0xE6A7, 0x8B92, 0xE6A8, 0x8B93, 0xE6A9, 0x8B96, 0xE6AA, 0x8B99, 0xE6AB, 0x8B9A, 0xE6AC, 0x8C3A, + 0xE6AD, 0x8C41, 0xE6AE, 0x8C3F, 0xE6AF, 0x8C48, 0xE6B0, 0x8C4C, 0xE6B1, 0x8C4E, 0xE6B2, 0x8C50, 0xE6B3, 0x8C55, 0xE6B4, 0x8C62, + 0xE6B5, 0x8C6C, 0xE6B6, 0x8C78, 0xE6B7, 0x8C7A, 0xE6B8, 0x8C82, 0xE6B9, 0x8C89, 0xE6BA, 0x8C85, 0xE6BB, 0x8C8A, 0xE6BC, 0x8C8D, + 0xE6BD, 0x8C8E, 0xE6BE, 0x8C94, 0xE6BF, 0x8C7C, 0xE6C0, 0x8C98, 0xE6C1, 0x621D, 0xE6C2, 0x8CAD, 0xE6C3, 0x8CAA, 0xE6C4, 0x8CBD, + 0xE6C5, 0x8CB2, 0xE6C6, 0x8CB3, 0xE6C7, 0x8CAE, 0xE6C8, 0x8CB6, 0xE6C9, 0x8CC8, 0xE6CA, 0x8CC1, 0xE6CB, 0x8CE4, 0xE6CC, 0x8CE3, + 0xE6CD, 0x8CDA, 0xE6CE, 0x8CFD, 0xE6CF, 0x8CFA, 0xE6D0, 0x8CFB, 0xE6D1, 0x8D04, 0xE6D2, 0x8D05, 0xE6D3, 0x8D0A, 0xE6D4, 0x8D07, + 0xE6D5, 0x8D0F, 0xE6D6, 0x8D0D, 0xE6D7, 0x8D10, 0xE6D8, 0x9F4E, 0xE6D9, 0x8D13, 0xE6DA, 0x8CCD, 0xE6DB, 0x8D14, 0xE6DC, 0x8D16, + 0xE6DD, 0x8D67, 0xE6DE, 0x8D6D, 0xE6DF, 0x8D71, 0xE6E0, 0x8D73, 0xE6E1, 0x8D81, 0xE6E2, 0x8D99, 0xE6E3, 0x8DC2, 0xE6E4, 0x8DBE, + 0xE6E5, 0x8DBA, 0xE6E6, 0x8DCF, 0xE6E7, 0x8DDA, 0xE6E8, 0x8DD6, 0xE6E9, 0x8DCC, 0xE6EA, 0x8DDB, 0xE6EB, 0x8DCB, 0xE6EC, 0x8DEA, + 0xE6ED, 0x8DEB, 0xE6EE, 0x8DDF, 0xE6EF, 0x8DE3, 0xE6F0, 0x8DFC, 0xE6F1, 0x8E08, 0xE6F2, 0x8E09, 0xE6F3, 0x8DFF, 0xE6F4, 0x8E1D, + 0xE6F5, 0x8E1E, 0xE6F6, 0x8E10, 0xE6F7, 0x8E1F, 0xE6F8, 0x8E42, 0xE6F9, 0x8E35, 0xE6FA, 0x8E30, 0xE6FB, 0x8E34, 0xE6FC, 0x8E4A, + 0xE740, 0x8E47, 0xE741, 0x8E49, 0xE742, 0x8E4C, 0xE743, 0x8E50, 0xE744, 0x8E48, 0xE745, 0x8E59, 0xE746, 0x8E64, 0xE747, 0x8E60, + 0xE748, 0x8E2A, 0xE749, 0x8E63, 0xE74A, 0x8E55, 0xE74B, 0x8E76, 0xE74C, 0x8E72, 0xE74D, 0x8E7C, 0xE74E, 0x8E81, 0xE74F, 0x8E87, + 0xE750, 0x8E85, 0xE751, 0x8E84, 0xE752, 0x8E8B, 0xE753, 0x8E8A, 0xE754, 0x8E93, 0xE755, 0x8E91, 0xE756, 0x8E94, 0xE757, 0x8E99, + 0xE758, 0x8EAA, 0xE759, 0x8EA1, 0xE75A, 0x8EAC, 0xE75B, 0x8EB0, 0xE75C, 0x8EC6, 0xE75D, 0x8EB1, 0xE75E, 0x8EBE, 0xE75F, 0x8EC5, + 0xE760, 0x8EC8, 0xE761, 0x8ECB, 0xE762, 0x8EDB, 0xE763, 0x8EE3, 0xE764, 0x8EFC, 0xE765, 0x8EFB, 0xE766, 0x8EEB, 0xE767, 0x8EFE, + 0xE768, 0x8F0A, 0xE769, 0x8F05, 0xE76A, 0x8F15, 0xE76B, 0x8F12, 0xE76C, 0x8F19, 0xE76D, 0x8F13, 0xE76E, 0x8F1C, 0xE76F, 0x8F1F, + 0xE770, 0x8F1B, 0xE771, 0x8F0C, 0xE772, 0x8F26, 0xE773, 0x8F33, 0xE774, 0x8F3B, 0xE775, 0x8F39, 0xE776, 0x8F45, 0xE777, 0x8F42, + 0xE778, 0x8F3E, 0xE779, 0x8F4C, 0xE77A, 0x8F49, 0xE77B, 0x8F46, 0xE77C, 0x8F4E, 0xE77D, 0x8F57, 0xE77E, 0x8F5C, 0xE780, 0x8F62, + 0xE781, 0x8F63, 0xE782, 0x8F64, 0xE783, 0x8F9C, 0xE784, 0x8F9F, 0xE785, 0x8FA3, 0xE786, 0x8FAD, 0xE787, 0x8FAF, 0xE788, 0x8FB7, + 0xE789, 0x8FDA, 0xE78A, 0x8FE5, 0xE78B, 0x8FE2, 0xE78C, 0x8FEA, 0xE78D, 0x8FEF, 0xE78E, 0x9087, 0xE78F, 0x8FF4, 0xE790, 0x9005, + 0xE791, 0x8FF9, 0xE792, 0x8FFA, 0xE793, 0x9011, 0xE794, 0x9015, 0xE795, 0x9021, 0xE796, 0x900D, 0xE797, 0x901E, 0xE798, 0x9016, + 0xE799, 0x900B, 0xE79A, 0x9027, 0xE79B, 0x9036, 0xE79C, 0x9035, 0xE79D, 0x9039, 0xE79E, 0x8FF8, 0xE79F, 0x904F, 0xE7A0, 0x9050, + 0xE7A1, 0x9051, 0xE7A2, 0x9052, 0xE7A3, 0x900E, 0xE7A4, 0x9049, 0xE7A5, 0x903E, 0xE7A6, 0x9056, 0xE7A7, 0x9058, 0xE7A8, 0x905E, + 0xE7A9, 0x9068, 0xE7AA, 0x906F, 0xE7AB, 0x9076, 0xE7AC, 0x96A8, 0xE7AD, 0x9072, 0xE7AE, 0x9082, 0xE7AF, 0x907D, 0xE7B0, 0x9081, + 0xE7B1, 0x9080, 0xE7B2, 0x908A, 0xE7B3, 0x9089, 0xE7B4, 0x908F, 0xE7B5, 0x90A8, 0xE7B6, 0x90AF, 0xE7B7, 0x90B1, 0xE7B8, 0x90B5, + 0xE7B9, 0x90E2, 0xE7BA, 0x90E4, 0xE7BB, 0x6248, 0xE7BC, 0x90DB, 0xE7BD, 0x9102, 0xE7BE, 0x9112, 0xE7BF, 0x9119, 0xE7C0, 0x9132, + 0xE7C1, 0x9130, 0xE7C2, 0x914A, 0xE7C3, 0x9156, 0xE7C4, 0x9158, 0xE7C5, 0x9163, 0xE7C6, 0x9165, 0xE7C7, 0x9169, 0xE7C8, 0x9173, + 0xE7C9, 0x9172, 0xE7CA, 0x918B, 0xE7CB, 0x9189, 0xE7CC, 0x9182, 0xE7CD, 0x91A2, 0xE7CE, 0x91AB, 0xE7CF, 0x91AF, 0xE7D0, 0x91AA, + 0xE7D1, 0x91B5, 0xE7D2, 0x91B4, 0xE7D3, 0x91BA, 0xE7D4, 0x91C0, 0xE7D5, 0x91C1, 0xE7D6, 0x91C9, 0xE7D7, 0x91CB, 0xE7D8, 0x91D0, + 0xE7D9, 0x91D6, 0xE7DA, 0x91DF, 0xE7DB, 0x91E1, 0xE7DC, 0x91DB, 0xE7DD, 0x91FC, 0xE7DE, 0x91F5, 0xE7DF, 0x91F6, 0xE7E0, 0x921E, + 0xE7E1, 0x91FF, 0xE7E2, 0x9214, 0xE7E3, 0x922C, 0xE7E4, 0x9215, 0xE7E5, 0x9211, 0xE7E6, 0x925E, 0xE7E7, 0x9257, 0xE7E8, 0x9245, + 0xE7E9, 0x9249, 0xE7EA, 0x9264, 0xE7EB, 0x9248, 0xE7EC, 0x9295, 0xE7ED, 0x923F, 0xE7EE, 0x924B, 0xE7EF, 0x9250, 0xE7F0, 0x929C, + 0xE7F1, 0x9296, 0xE7F2, 0x9293, 0xE7F3, 0x929B, 0xE7F4, 0x925A, 0xE7F5, 0x92CF, 0xE7F6, 0x92B9, 0xE7F7, 0x92B7, 0xE7F8, 0x92E9, + 0xE7F9, 0x930F, 0xE7FA, 0x92FA, 0xE7FB, 0x9344, 0xE7FC, 0x932E, 0xE840, 0x9319, 0xE841, 0x9322, 0xE842, 0x931A, 0xE843, 0x9323, + 0xE844, 0x933A, 0xE845, 0x9335, 0xE846, 0x933B, 0xE847, 0x935C, 0xE848, 0x9360, 0xE849, 0x937C, 0xE84A, 0x936E, 0xE84B, 0x9356, + 0xE84C, 0x93B0, 0xE84D, 0x93AC, 0xE84E, 0x93AD, 0xE84F, 0x9394, 0xE850, 0x93B9, 0xE851, 0x93D6, 0xE852, 0x93D7, 0xE853, 0x93E8, + 0xE854, 0x93E5, 0xE855, 0x93D8, 0xE856, 0x93C3, 0xE857, 0x93DD, 0xE858, 0x93D0, 0xE859, 0x93C8, 0xE85A, 0x93E4, 0xE85B, 0x941A, + 0xE85C, 0x9414, 0xE85D, 0x9413, 0xE85E, 0x9403, 0xE85F, 0x9407, 0xE860, 0x9410, 0xE861, 0x9436, 0xE862, 0x942B, 0xE863, 0x9435, + 0xE864, 0x9421, 0xE865, 0x943A, 0xE866, 0x9441, 0xE867, 0x9452, 0xE868, 0x9444, 0xE869, 0x945B, 0xE86A, 0x9460, 0xE86B, 0x9462, + 0xE86C, 0x945E, 0xE86D, 0x946A, 0xE86E, 0x9229, 0xE86F, 0x9470, 0xE870, 0x9475, 0xE871, 0x9477, 0xE872, 0x947D, 0xE873, 0x945A, + 0xE874, 0x947C, 0xE875, 0x947E, 0xE876, 0x9481, 0xE877, 0x947F, 0xE878, 0x9582, 0xE879, 0x9587, 0xE87A, 0x958A, 0xE87B, 0x9594, + 0xE87C, 0x9596, 0xE87D, 0x9598, 0xE87E, 0x9599, 0xE880, 0x95A0, 0xE881, 0x95A8, 0xE882, 0x95A7, 0xE883, 0x95AD, 0xE884, 0x95BC, + 0xE885, 0x95BB, 0xE886, 0x95B9, 0xE887, 0x95BE, 0xE888, 0x95CA, 0xE889, 0x6FF6, 0xE88A, 0x95C3, 0xE88B, 0x95CD, 0xE88C, 0x95CC, + 0xE88D, 0x95D5, 0xE88E, 0x95D4, 0xE88F, 0x95D6, 0xE890, 0x95DC, 0xE891, 0x95E1, 0xE892, 0x95E5, 0xE893, 0x95E2, 0xE894, 0x9621, + 0xE895, 0x9628, 0xE896, 0x962E, 0xE897, 0x962F, 0xE898, 0x9642, 0xE899, 0x964C, 0xE89A, 0x964F, 0xE89B, 0x964B, 0xE89C, 0x9677, + 0xE89D, 0x965C, 0xE89E, 0x965E, 0xE89F, 0x965D, 0xE8A0, 0x965F, 0xE8A1, 0x9666, 0xE8A2, 0x9672, 0xE8A3, 0x966C, 0xE8A4, 0x968D, + 0xE8A5, 0x9698, 0xE8A6, 0x9695, 0xE8A7, 0x9697, 0xE8A8, 0x96AA, 0xE8A9, 0x96A7, 0xE8AA, 0x96B1, 0xE8AB, 0x96B2, 0xE8AC, 0x96B0, + 0xE8AD, 0x96B4, 0xE8AE, 0x96B6, 0xE8AF, 0x96B8, 0xE8B0, 0x96B9, 0xE8B1, 0x96CE, 0xE8B2, 0x96CB, 0xE8B3, 0x96C9, 0xE8B4, 0x96CD, + 0xE8B5, 0x894D, 0xE8B6, 0x96DC, 0xE8B7, 0x970D, 0xE8B8, 0x96D5, 0xE8B9, 0x96F9, 0xE8BA, 0x9704, 0xE8BB, 0x9706, 0xE8BC, 0x9708, + 0xE8BD, 0x9713, 0xE8BE, 0x970E, 0xE8BF, 0x9711, 0xE8C0, 0x970F, 0xE8C1, 0x9716, 0xE8C2, 0x9719, 0xE8C3, 0x9724, 0xE8C4, 0x972A, + 0xE8C5, 0x9730, 0xE8C6, 0x9739, 0xE8C7, 0x973D, 0xE8C8, 0x973E, 0xE8C9, 0x9744, 0xE8CA, 0x9746, 0xE8CB, 0x9748, 0xE8CC, 0x9742, + 0xE8CD, 0x9749, 0xE8CE, 0x975C, 0xE8CF, 0x9760, 0xE8D0, 0x9764, 0xE8D1, 0x9766, 0xE8D2, 0x9768, 0xE8D3, 0x52D2, 0xE8D4, 0x976B, + 0xE8D5, 0x9771, 0xE8D6, 0x9779, 0xE8D7, 0x9785, 0xE8D8, 0x977C, 0xE8D9, 0x9781, 0xE8DA, 0x977A, 0xE8DB, 0x9786, 0xE8DC, 0x978B, + 0xE8DD, 0x978F, 0xE8DE, 0x9790, 0xE8DF, 0x979C, 0xE8E0, 0x97A8, 0xE8E1, 0x97A6, 0xE8E2, 0x97A3, 0xE8E3, 0x97B3, 0xE8E4, 0x97B4, + 0xE8E5, 0x97C3, 0xE8E6, 0x97C6, 0xE8E7, 0x97C8, 0xE8E8, 0x97CB, 0xE8E9, 0x97DC, 0xE8EA, 0x97ED, 0xE8EB, 0x9F4F, 0xE8EC, 0x97F2, + 0xE8ED, 0x7ADF, 0xE8EE, 0x97F6, 0xE8EF, 0x97F5, 0xE8F0, 0x980F, 0xE8F1, 0x980C, 0xE8F2, 0x9838, 0xE8F3, 0x9824, 0xE8F4, 0x9821, + 0xE8F5, 0x9837, 0xE8F6, 0x983D, 0xE8F7, 0x9846, 0xE8F8, 0x984F, 0xE8F9, 0x984B, 0xE8FA, 0x986B, 0xE8FB, 0x986F, 0xE8FC, 0x9870, + 0xE940, 0x9871, 0xE941, 0x9874, 0xE942, 0x9873, 0xE943, 0x98AA, 0xE944, 0x98AF, 0xE945, 0x98B1, 0xE946, 0x98B6, 0xE947, 0x98C4, + 0xE948, 0x98C3, 0xE949, 0x98C6, 0xE94A, 0x98E9, 0xE94B, 0x98EB, 0xE94C, 0x9903, 0xE94D, 0x9909, 0xE94E, 0x9912, 0xE94F, 0x9914, + 0xE950, 0x9918, 0xE951, 0x9921, 0xE952, 0x991D, 0xE953, 0x991E, 0xE954, 0x9924, 0xE955, 0x9920, 0xE956, 0x992C, 0xE957, 0x992E, + 0xE958, 0x993D, 0xE959, 0x993E, 0xE95A, 0x9942, 0xE95B, 0x9949, 0xE95C, 0x9945, 0xE95D, 0x9950, 0xE95E, 0x994B, 0xE95F, 0x9951, + 0xE960, 0x9952, 0xE961, 0x994C, 0xE962, 0x9955, 0xE963, 0x9997, 0xE964, 0x9998, 0xE965, 0x99A5, 0xE966, 0x99AD, 0xE967, 0x99AE, + 0xE968, 0x99BC, 0xE969, 0x99DF, 0xE96A, 0x99DB, 0xE96B, 0x99DD, 0xE96C, 0x99D8, 0xE96D, 0x99D1, 0xE96E, 0x99ED, 0xE96F, 0x99EE, + 0xE970, 0x99F1, 0xE971, 0x99F2, 0xE972, 0x99FB, 0xE973, 0x99F8, 0xE974, 0x9A01, 0xE975, 0x9A0F, 0xE976, 0x9A05, 0xE977, 0x99E2, + 0xE978, 0x9A19, 0xE979, 0x9A2B, 0xE97A, 0x9A37, 0xE97B, 0x9A45, 0xE97C, 0x9A42, 0xE97D, 0x9A40, 0xE97E, 0x9A43, 0xE980, 0x9A3E, + 0xE981, 0x9A55, 0xE982, 0x9A4D, 0xE983, 0x9A5B, 0xE984, 0x9A57, 0xE985, 0x9A5F, 0xE986, 0x9A62, 0xE987, 0x9A65, 0xE988, 0x9A64, + 0xE989, 0x9A69, 0xE98A, 0x9A6B, 0xE98B, 0x9A6A, 0xE98C, 0x9AAD, 0xE98D, 0x9AB0, 0xE98E, 0x9ABC, 0xE98F, 0x9AC0, 0xE990, 0x9ACF, + 0xE991, 0x9AD1, 0xE992, 0x9AD3, 0xE993, 0x9AD4, 0xE994, 0x9ADE, 0xE995, 0x9ADF, 0xE996, 0x9AE2, 0xE997, 0x9AE3, 0xE998, 0x9AE6, + 0xE999, 0x9AEF, 0xE99A, 0x9AEB, 0xE99B, 0x9AEE, 0xE99C, 0x9AF4, 0xE99D, 0x9AF1, 0xE99E, 0x9AF7, 0xE99F, 0x9AFB, 0xE9A0, 0x9B06, + 0xE9A1, 0x9B18, 0xE9A2, 0x9B1A, 0xE9A3, 0x9B1F, 0xE9A4, 0x9B22, 0xE9A5, 0x9B23, 0xE9A6, 0x9B25, 0xE9A7, 0x9B27, 0xE9A8, 0x9B28, + 0xE9A9, 0x9B29, 0xE9AA, 0x9B2A, 0xE9AB, 0x9B2E, 0xE9AC, 0x9B2F, 0xE9AD, 0x9B32, 0xE9AE, 0x9B44, 0xE9AF, 0x9B43, 0xE9B0, 0x9B4F, + 0xE9B1, 0x9B4D, 0xE9B2, 0x9B4E, 0xE9B3, 0x9B51, 0xE9B4, 0x9B58, 0xE9B5, 0x9B74, 0xE9B6, 0x9B93, 0xE9B7, 0x9B83, 0xE9B8, 0x9B91, + 0xE9B9, 0x9B96, 0xE9BA, 0x9B97, 0xE9BB, 0x9B9F, 0xE9BC, 0x9BA0, 0xE9BD, 0x9BA8, 0xE9BE, 0x9BB4, 0xE9BF, 0x9BC0, 0xE9C0, 0x9BCA, + 0xE9C1, 0x9BB9, 0xE9C2, 0x9BC6, 0xE9C3, 0x9BCF, 0xE9C4, 0x9BD1, 0xE9C5, 0x9BD2, 0xE9C6, 0x9BE3, 0xE9C7, 0x9BE2, 0xE9C8, 0x9BE4, + 0xE9C9, 0x9BD4, 0xE9CA, 0x9BE1, 0xE9CB, 0x9C3A, 0xE9CC, 0x9BF2, 0xE9CD, 0x9BF1, 0xE9CE, 0x9BF0, 0xE9CF, 0x9C15, 0xE9D0, 0x9C14, + 0xE9D1, 0x9C09, 0xE9D2, 0x9C13, 0xE9D3, 0x9C0C, 0xE9D4, 0x9C06, 0xE9D5, 0x9C08, 0xE9D6, 0x9C12, 0xE9D7, 0x9C0A, 0xE9D8, 0x9C04, + 0xE9D9, 0x9C2E, 0xE9DA, 0x9C1B, 0xE9DB, 0x9C25, 0xE9DC, 0x9C24, 0xE9DD, 0x9C21, 0xE9DE, 0x9C30, 0xE9DF, 0x9C47, 0xE9E0, 0x9C32, + 0xE9E1, 0x9C46, 0xE9E2, 0x9C3E, 0xE9E3, 0x9C5A, 0xE9E4, 0x9C60, 0xE9E5, 0x9C67, 0xE9E6, 0x9C76, 0xE9E7, 0x9C78, 0xE9E8, 0x9CE7, + 0xE9E9, 0x9CEC, 0xE9EA, 0x9CF0, 0xE9EB, 0x9D09, 0xE9EC, 0x9D08, 0xE9ED, 0x9CEB, 0xE9EE, 0x9D03, 0xE9EF, 0x9D06, 0xE9F0, 0x9D2A, + 0xE9F1, 0x9D26, 0xE9F2, 0x9DAF, 0xE9F3, 0x9D23, 0xE9F4, 0x9D1F, 0xE9F5, 0x9D44, 0xE9F6, 0x9D15, 0xE9F7, 0x9D12, 0xE9F8, 0x9D41, + 0xE9F9, 0x9D3F, 0xE9FA, 0x9D3E, 0xE9FB, 0x9D46, 0xE9FC, 0x9D48, 0xEA40, 0x9D5D, 0xEA41, 0x9D5E, 0xEA42, 0x9D64, 0xEA43, 0x9D51, + 0xEA44, 0x9D50, 0xEA45, 0x9D59, 0xEA46, 0x9D72, 0xEA47, 0x9D89, 0xEA48, 0x9D87, 0xEA49, 0x9DAB, 0xEA4A, 0x9D6F, 0xEA4B, 0x9D7A, + 0xEA4C, 0x9D9A, 0xEA4D, 0x9DA4, 0xEA4E, 0x9DA9, 0xEA4F, 0x9DB2, 0xEA50, 0x9DC4, 0xEA51, 0x9DC1, 0xEA52, 0x9DBB, 0xEA53, 0x9DB8, + 0xEA54, 0x9DBA, 0xEA55, 0x9DC6, 0xEA56, 0x9DCF, 0xEA57, 0x9DC2, 0xEA58, 0x9DD9, 0xEA59, 0x9DD3, 0xEA5A, 0x9DF8, 0xEA5B, 0x9DE6, + 0xEA5C, 0x9DED, 0xEA5D, 0x9DEF, 0xEA5E, 0x9DFD, 0xEA5F, 0x9E1A, 0xEA60, 0x9E1B, 0xEA61, 0x9E1E, 0xEA62, 0x9E75, 0xEA63, 0x9E79, + 0xEA64, 0x9E7D, 0xEA65, 0x9E81, 0xEA66, 0x9E88, 0xEA67, 0x9E8B, 0xEA68, 0x9E8C, 0xEA69, 0x9E92, 0xEA6A, 0x9E95, 0xEA6B, 0x9E91, + 0xEA6C, 0x9E9D, 0xEA6D, 0x9EA5, 0xEA6E, 0x9EA9, 0xEA6F, 0x9EB8, 0xEA70, 0x9EAA, 0xEA71, 0x9EAD, 0xEA72, 0x9761, 0xEA73, 0x9ECC, + 0xEA74, 0x9ECE, 0xEA75, 0x9ECF, 0xEA76, 0x9ED0, 0xEA77, 0x9ED4, 0xEA78, 0x9EDC, 0xEA79, 0x9EDE, 0xEA7A, 0x9EDD, 0xEA7B, 0x9EE0, + 0xEA7C, 0x9EE5, 0xEA7D, 0x9EE8, 0xEA7E, 0x9EEF, 0xEA80, 0x9EF4, 0xEA81, 0x9EF6, 0xEA82, 0x9EF7, 0xEA83, 0x9EF9, 0xEA84, 0x9EFB, + 0xEA85, 0x9EFC, 0xEA86, 0x9EFD, 0xEA87, 0x9F07, 0xEA88, 0x9F08, 0xEA89, 0x76B7, 0xEA8A, 0x9F15, 0xEA8B, 0x9F21, 0xEA8C, 0x9F2C, + 0xEA8D, 0x9F3E, 0xEA8E, 0x9F4A, 0xEA8F, 0x9F52, 0xEA90, 0x9F54, 0xEA91, 0x9F63, 0xEA92, 0x9F5F, 0xEA93, 0x9F60, 0xEA94, 0x9F61, + 0xEA95, 0x9F66, 0xEA96, 0x9F67, 0xEA97, 0x9F6C, 0xEA98, 0x9F6A, 0xEA99, 0x9F77, 0xEA9A, 0x9F72, 0xEA9B, 0x9F76, 0xEA9C, 0x9F95, + 0xEA9D, 0x9F9C, 0xEA9E, 0x9FA0, 0xEA9F, 0x582F, 0xEAA0, 0x69C7, 0xEAA1, 0x9059, 0xEAA2, 0x7464, 0xEAA3, 0x51DC, 0xEAA4, 0x7199, + 0xFA40, 0x2170, 0xFA41, 0x2171, 0xFA42, 0x2172, 0xFA43, 0x2173, 0xFA44, 0x2174, 0xFA45, 0x2175, 0xFA46, 0x2176, 0xFA47, 0x2177, + 0xFA48, 0x2178, 0xFA49, 0x2179, 0xFA55, 0xFFE4, 0xFA56, 0xFF07, 0xFA57, 0xFF02, 0xFA5C, 0x7E8A, 0xFA5D, 0x891C, 0xFA5E, 0x9348, + 0xFA5F, 0x9288, 0xFA60, 0x84DC, 0xFA61, 0x4FC9, 0xFA62, 0x70BB, 0xFA63, 0x6631, 0xFA64, 0x68C8, 0xFA65, 0x92F9, 0xFA66, 0x66FB, + 0xFA67, 0x5F45, 0xFA68, 0x4E28, 0xFA69, 0x4EE1, 0xFA6A, 0x4EFC, 0xFA6B, 0x4F00, 0xFA6C, 0x4F03, 0xFA6D, 0x4F39, 0xFA6E, 0x4F56, + 0xFA6F, 0x4F92, 0xFA70, 0x4F8A, 0xFA71, 0x4F9A, 0xFA72, 0x4F94, 0xFA73, 0x4FCD, 0xFA74, 0x5040, 0xFA75, 0x5022, 0xFA76, 0x4FFF, + 0xFA77, 0x501E, 0xFA78, 0x5046, 0xFA79, 0x5070, 0xFA7A, 0x5042, 0xFA7B, 0x5094, 0xFA7C, 0x50F4, 0xFA7D, 0x50D8, 0xFA7E, 0x514A, + 0xFA80, 0x5164, 0xFA81, 0x519D, 0xFA82, 0x51BE, 0xFA83, 0x51EC, 0xFA84, 0x5215, 0xFA85, 0x529C, 0xFA86, 0x52A6, 0xFA87, 0x52C0, + 0xFA88, 0x52DB, 0xFA89, 0x5300, 0xFA8A, 0x5307, 0xFA8B, 0x5324, 0xFA8C, 0x5372, 0xFA8D, 0x5393, 0xFA8E, 0x53B2, 0xFA8F, 0x53DD, + 0xFA90, 0xFA0E, 0xFA91, 0x549C, 0xFA92, 0x548A, 0xFA93, 0x54A9, 0xFA94, 0x54FF, 0xFA95, 0x5586, 0xFA96, 0x5759, 0xFA97, 0x5765, + 0xFA98, 0x57AC, 0xFA99, 0x57C8, 0xFA9A, 0x57C7, 0xFA9B, 0xFA0F, 0xFA9C, 0xFA10, 0xFA9D, 0x589E, 0xFA9E, 0x58B2, 0xFA9F, 0x590B, + 0xFAA0, 0x5953, 0xFAA1, 0x595B, 0xFAA2, 0x595D, 0xFAA3, 0x5963, 0xFAA4, 0x59A4, 0xFAA5, 0x59BA, 0xFAA6, 0x5B56, 0xFAA7, 0x5BC0, + 0xFAA8, 0x752F, 0xFAA9, 0x5BD8, 0xFAAA, 0x5BEC, 0xFAAB, 0x5C1E, 0xFAAC, 0x5CA6, 0xFAAD, 0x5CBA, 0xFAAE, 0x5CF5, 0xFAAF, 0x5D27, + 0xFAB0, 0x5D53, 0xFAB1, 0xFA11, 0xFAB2, 0x5D42, 0xFAB3, 0x5D6D, 0xFAB4, 0x5DB8, 0xFAB5, 0x5DB9, 0xFAB6, 0x5DD0, 0xFAB7, 0x5F21, + 0xFAB8, 0x5F34, 0xFAB9, 0x5F67, 0xFABA, 0x5FB7, 0xFABB, 0x5FDE, 0xFABC, 0x605D, 0xFABD, 0x6085, 0xFABE, 0x608A, 0xFABF, 0x60DE, + 0xFAC0, 0x60D5, 0xFAC1, 0x6120, 0xFAC2, 0x60F2, 0xFAC3, 0x6111, 0xFAC4, 0x6137, 0xFAC5, 0x6130, 0xFAC6, 0x6198, 0xFAC7, 0x6213, + 0xFAC8, 0x62A6, 0xFAC9, 0x63F5, 0xFACA, 0x6460, 0xFACB, 0x649D, 0xFACC, 0x64CE, 0xFACD, 0x654E, 0xFACE, 0x6600, 0xFACF, 0x6615, + 0xFAD0, 0x663B, 0xFAD1, 0x6609, 0xFAD2, 0x662E, 0xFAD3, 0x661E, 0xFAD4, 0x6624, 0xFAD5, 0x6665, 0xFAD6, 0x6657, 0xFAD7, 0x6659, + 0xFAD8, 0xFA12, 0xFAD9, 0x6673, 0xFADA, 0x6699, 0xFADB, 0x66A0, 0xFADC, 0x66B2, 0xFADD, 0x66BF, 0xFADE, 0x66FA, 0xFADF, 0x670E, + 0xFAE0, 0xF929, 0xFAE1, 0x6766, 0xFAE2, 0x67BB, 0xFAE3, 0x6852, 0xFAE4, 0x67C0, 0xFAE5, 0x6801, 0xFAE6, 0x6844, 0xFAE7, 0x68CF, + 0xFAE8, 0xFA13, 0xFAE9, 0x6968, 0xFAEA, 0xFA14, 0xFAEB, 0x6998, 0xFAEC, 0x69E2, 0xFAED, 0x6A30, 0xFAEE, 0x6A6B, 0xFAEF, 0x6A46, + 0xFAF0, 0x6A73, 0xFAF1, 0x6A7E, 0xFAF2, 0x6AE2, 0xFAF3, 0x6AE4, 0xFAF4, 0x6BD6, 0xFAF5, 0x6C3F, 0xFAF6, 0x6C5C, 0xFAF7, 0x6C86, + 0xFAF8, 0x6C6F, 0xFAF9, 0x6CDA, 0xFAFA, 0x6D04, 0xFAFB, 0x6D87, 0xFAFC, 0x6D6F, 0xFB40, 0x6D96, 0xFB41, 0x6DAC, 0xFB42, 0x6DCF, + 0xFB43, 0x6DF8, 0xFB44, 0x6DF2, 0xFB45, 0x6DFC, 0xFB46, 0x6E39, 0xFB47, 0x6E5C, 0xFB48, 0x6E27, 0xFB49, 0x6E3C, 0xFB4A, 0x6EBF, + 0xFB4B, 0x6F88, 0xFB4C, 0x6FB5, 0xFB4D, 0x6FF5, 0xFB4E, 0x7005, 0xFB4F, 0x7007, 0xFB50, 0x7028, 0xFB51, 0x7085, 0xFB52, 0x70AB, + 0xFB53, 0x710F, 0xFB54, 0x7104, 0xFB55, 0x715C, 0xFB56, 0x7146, 0xFB57, 0x7147, 0xFB58, 0xFA15, 0xFB59, 0x71C1, 0xFB5A, 0x71FE, + 0xFB5B, 0x72B1, 0xFB5C, 0x72BE, 0xFB5D, 0x7324, 0xFB5E, 0xFA16, 0xFB5F, 0x7377, 0xFB60, 0x73BD, 0xFB61, 0x73C9, 0xFB62, 0x73D6, + 0xFB63, 0x73E3, 0xFB64, 0x73D2, 0xFB65, 0x7407, 0xFB66, 0x73F5, 0xFB67, 0x7426, 0xFB68, 0x742A, 0xFB69, 0x7429, 0xFB6A, 0x742E, + 0xFB6B, 0x7462, 0xFB6C, 0x7489, 0xFB6D, 0x749F, 0xFB6E, 0x7501, 0xFB6F, 0x756F, 0xFB70, 0x7682, 0xFB71, 0x769C, 0xFB72, 0x769E, + 0xFB73, 0x769B, 0xFB74, 0x76A6, 0xFB75, 0xFA17, 0xFB76, 0x7746, 0xFB77, 0x52AF, 0xFB78, 0x7821, 0xFB79, 0x784E, 0xFB7A, 0x7864, + 0xFB7B, 0x787A, 0xFB7C, 0x7930, 0xFB7D, 0xFA18, 0xFB7E, 0xFA19, 0xFB80, 0xFA1A, 0xFB81, 0x7994, 0xFB82, 0xFA1B, 0xFB83, 0x799B, + 0xFB84, 0x7AD1, 0xFB85, 0x7AE7, 0xFB86, 0xFA1C, 0xFB87, 0x7AEB, 0xFB88, 0x7B9E, 0xFB89, 0xFA1D, 0xFB8A, 0x7D48, 0xFB8B, 0x7D5C, + 0xFB8C, 0x7DB7, 0xFB8D, 0x7DA0, 0xFB8E, 0x7DD6, 0xFB8F, 0x7E52, 0xFB90, 0x7F47, 0xFB91, 0x7FA1, 0xFB92, 0xFA1E, 0xFB93, 0x8301, + 0xFB94, 0x8362, 0xFB95, 0x837F, 0xFB96, 0x83C7, 0xFB97, 0x83F6, 0xFB98, 0x8448, 0xFB99, 0x84B4, 0xFB9A, 0x8553, 0xFB9B, 0x8559, + 0xFB9C, 0x856B, 0xFB9D, 0xFA1F, 0xFB9E, 0x85B0, 0xFB9F, 0xFA20, 0xFBA0, 0xFA21, 0xFBA1, 0x8807, 0xFBA2, 0x88F5, 0xFBA3, 0x8A12, + 0xFBA4, 0x8A37, 0xFBA5, 0x8A79, 0xFBA6, 0x8AA7, 0xFBA7, 0x8ABE, 0xFBA8, 0x8ADF, 0xFBA9, 0xFA22, 0xFBAA, 0x8AF6, 0xFBAB, 0x8B53, + 0xFBAC, 0x8B7F, 0xFBAD, 0x8CF0, 0xFBAE, 0x8CF4, 0xFBAF, 0x8D12, 0xFBB0, 0x8D76, 0xFBB1, 0xFA23, 0xFBB2, 0x8ECF, 0xFBB3, 0xFA24, + 0xFBB4, 0xFA25, 0xFBB5, 0x9067, 0xFBB6, 0x90DE, 0xFBB7, 0xFA26, 0xFBB8, 0x9115, 0xFBB9, 0x9127, 0xFBBA, 0x91DA, 0xFBBB, 0x91D7, + 0xFBBC, 0x91DE, 0xFBBD, 0x91ED, 0xFBBE, 0x91EE, 0xFBBF, 0x91E4, 0xFBC0, 0x91E5, 0xFBC1, 0x9206, 0xFBC2, 0x9210, 0xFBC3, 0x920A, + 0xFBC4, 0x923A, 0xFBC5, 0x9240, 0xFBC6, 0x923C, 0xFBC7, 0x924E, 0xFBC8, 0x9259, 0xFBC9, 0x9251, 0xFBCA, 0x9239, 0xFBCB, 0x9267, + 0xFBCC, 0x92A7, 0xFBCD, 0x9277, 0xFBCE, 0x9278, 0xFBCF, 0x92E7, 0xFBD0, 0x92D7, 0xFBD1, 0x92D9, 0xFBD2, 0x92D0, 0xFBD3, 0xFA27, + 0xFBD4, 0x92D5, 0xFBD5, 0x92E0, 0xFBD6, 0x92D3, 0xFBD7, 0x9325, 0xFBD8, 0x9321, 0xFBD9, 0x92FB, 0xFBDA, 0xFA28, 0xFBDB, 0x931E, + 0xFBDC, 0x92FF, 0xFBDD, 0x931D, 0xFBDE, 0x9302, 0xFBDF, 0x9370, 0xFBE0, 0x9357, 0xFBE1, 0x93A4, 0xFBE2, 0x93C6, 0xFBE3, 0x93DE, + 0xFBE4, 0x93F8, 0xFBE5, 0x9431, 0xFBE6, 0x9445, 0xFBE7, 0x9448, 0xFBE8, 0x9592, 0xFBE9, 0xF9DC, 0xFBEA, 0xFA29, 0xFBEB, 0x969D, + 0xFBEC, 0x96AF, 0xFBED, 0x9733, 0xFBEE, 0x973B, 0xFBEF, 0x9743, 0xFBF0, 0x974D, 0xFBF1, 0x974F, 0xFBF2, 0x9751, 0xFBF3, 0x9755, + 0xFBF4, 0x9857, 0xFBF5, 0x9865, 0xFBF6, 0xFA2A, 0xFBF7, 0xFA2B, 0xFBF8, 0x9927, 0xFBF9, 0xFA2C, 0xFBFA, 0x999E, 0xFBFB, 0x9A4E, + 0xFBFC, 0x9AD9, 0xFC40, 0x9ADC, 0xFC41, 0x9B75, 0xFC42, 0x9B72, 0xFC43, 0x9B8F, 0xFC44, 0x9BB1, 0xFC45, 0x9BBB, 0xFC46, 0x9C00, + 0xFC47, 0x9D70, 0xFC48, 0x9D6B, 0xFC49, 0xFA2D, 0xFC4A, 0x9E19, 0xFC4B, 0x9ED1, 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 936 || FF_CODE_PAGE == 0 /* Simplified Chinese */ +static const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */ + 0x00A4, 0xA1E8, 0x00A7, 0xA1EC, 0x00A8, 0xA1A7, 0x00B0, 0xA1E3, 0x00B1, 0xA1C0, 0x00B7, 0xA1A4, 0x00D7, 0xA1C1, 0x00E0, 0xA8A4, + 0x00E1, 0xA8A2, 0x00E8, 0xA8A8, 0x00E9, 0xA8A6, 0x00EA, 0xA8BA, 0x00EC, 0xA8AC, 0x00ED, 0xA8AA, 0x00F2, 0xA8B0, 0x00F3, 0xA8AE, + 0x00F7, 0xA1C2, 0x00F9, 0xA8B4, 0x00FA, 0xA8B2, 0x00FC, 0xA8B9, 0x0101, 0xA8A1, 0x0113, 0xA8A5, 0x011B, 0xA8A7, 0x012B, 0xA8A9, + 0x0144, 0xA8BD, 0x0148, 0xA8BE, 0x014D, 0xA8AD, 0x016B, 0xA8B1, 0x01CE, 0xA8A3, 0x01D0, 0xA8AB, 0x01D2, 0xA8AF, 0x01D4, 0xA8B3, + 0x01D6, 0xA8B5, 0x01D8, 0xA8B6, 0x01DA, 0xA8B7, 0x01DC, 0xA8B8, 0x0251, 0xA8BB, 0x0261, 0xA8C0, 0x02C7, 0xA1A6, 0x02C9, 0xA1A5, + 0x02CA, 0xA840, 0x02CB, 0xA841, 0x02D9, 0xA842, 0x0391, 0xA6A1, 0x0392, 0xA6A2, 0x0393, 0xA6A3, 0x0394, 0xA6A4, 0x0395, 0xA6A5, + 0x0396, 0xA6A6, 0x0397, 0xA6A7, 0x0398, 0xA6A8, 0x0399, 0xA6A9, 0x039A, 0xA6AA, 0x039B, 0xA6AB, 0x039C, 0xA6AC, 0x039D, 0xA6AD, + 0x039E, 0xA6AE, 0x039F, 0xA6AF, 0x03A0, 0xA6B0, 0x03A1, 0xA6B1, 0x03A3, 0xA6B2, 0x03A4, 0xA6B3, 0x03A5, 0xA6B4, 0x03A6, 0xA6B5, + 0x03A7, 0xA6B6, 0x03A8, 0xA6B7, 0x03A9, 0xA6B8, 0x03B1, 0xA6C1, 0x03B2, 0xA6C2, 0x03B3, 0xA6C3, 0x03B4, 0xA6C4, 0x03B5, 0xA6C5, + 0x03B6, 0xA6C6, 0x03B7, 0xA6C7, 0x03B8, 0xA6C8, 0x03B9, 0xA6C9, 0x03BA, 0xA6CA, 0x03BB, 0xA6CB, 0x03BC, 0xA6CC, 0x03BD, 0xA6CD, + 0x03BE, 0xA6CE, 0x03BF, 0xA6CF, 0x03C0, 0xA6D0, 0x03C1, 0xA6D1, 0x03C3, 0xA6D2, 0x03C4, 0xA6D3, 0x03C5, 0xA6D4, 0x03C6, 0xA6D5, + 0x03C7, 0xA6D6, 0x03C8, 0xA6D7, 0x03C9, 0xA6D8, 0x0401, 0xA7A7, 0x0410, 0xA7A1, 0x0411, 0xA7A2, 0x0412, 0xA7A3, 0x0413, 0xA7A4, + 0x0414, 0xA7A5, 0x0415, 0xA7A6, 0x0416, 0xA7A8, 0x0417, 0xA7A9, 0x0418, 0xA7AA, 0x0419, 0xA7AB, 0x041A, 0xA7AC, 0x041B, 0xA7AD, + 0x041C, 0xA7AE, 0x041D, 0xA7AF, 0x041E, 0xA7B0, 0x041F, 0xA7B1, 0x0420, 0xA7B2, 0x0421, 0xA7B3, 0x0422, 0xA7B4, 0x0423, 0xA7B5, + 0x0424, 0xA7B6, 0x0425, 0xA7B7, 0x0426, 0xA7B8, 0x0427, 0xA7B9, 0x0428, 0xA7BA, 0x0429, 0xA7BB, 0x042A, 0xA7BC, 0x042B, 0xA7BD, + 0x042C, 0xA7BE, 0x042D, 0xA7BF, 0x042E, 0xA7C0, 0x042F, 0xA7C1, 0x0430, 0xA7D1, 0x0431, 0xA7D2, 0x0432, 0xA7D3, 0x0433, 0xA7D4, + 0x0434, 0xA7D5, 0x0435, 0xA7D6, 0x0436, 0xA7D8, 0x0437, 0xA7D9, 0x0438, 0xA7DA, 0x0439, 0xA7DB, 0x043A, 0xA7DC, 0x043B, 0xA7DD, + 0x043C, 0xA7DE, 0x043D, 0xA7DF, 0x043E, 0xA7E0, 0x043F, 0xA7E1, 0x0440, 0xA7E2, 0x0441, 0xA7E3, 0x0442, 0xA7E4, 0x0443, 0xA7E5, + 0x0444, 0xA7E6, 0x0445, 0xA7E7, 0x0446, 0xA7E8, 0x0447, 0xA7E9, 0x0448, 0xA7EA, 0x0449, 0xA7EB, 0x044A, 0xA7EC, 0x044B, 0xA7ED, + 0x044C, 0xA7EE, 0x044D, 0xA7EF, 0x044E, 0xA7F0, 0x044F, 0xA7F1, 0x0451, 0xA7D7, 0x2010, 0xA95C, 0x2013, 0xA843, 0x2014, 0xA1AA, + 0x2015, 0xA844, 0x2016, 0xA1AC, 0x2018, 0xA1AE, 0x2019, 0xA1AF, 0x201C, 0xA1B0, 0x201D, 0xA1B1, 0x2025, 0xA845, 0x2026, 0xA1AD, + 0x2030, 0xA1EB, 0x2032, 0xA1E4, 0x2033, 0xA1E5, 0x2035, 0xA846, 0x203B, 0xA1F9, 0x20AC, 0x0080, 0x2103, 0xA1E6, 0x2105, 0xA847, + 0x2109, 0xA848, 0x2116, 0xA1ED, 0x2121, 0xA959, 0x2160, 0xA2F1, 0x2161, 0xA2F2, 0x2162, 0xA2F3, 0x2163, 0xA2F4, 0x2164, 0xA2F5, + 0x2165, 0xA2F6, 0x2166, 0xA2F7, 0x2167, 0xA2F8, 0x2168, 0xA2F9, 0x2169, 0xA2FA, 0x216A, 0xA2FB, 0x216B, 0xA2FC, 0x2170, 0xA2A1, + 0x2171, 0xA2A2, 0x2172, 0xA2A3, 0x2173, 0xA2A4, 0x2174, 0xA2A5, 0x2175, 0xA2A6, 0x2176, 0xA2A7, 0x2177, 0xA2A8, 0x2178, 0xA2A9, + 0x2179, 0xA2AA, 0x2190, 0xA1FB, 0x2191, 0xA1FC, 0x2192, 0xA1FA, 0x2193, 0xA1FD, 0x2196, 0xA849, 0x2197, 0xA84A, 0x2198, 0xA84B, + 0x2199, 0xA84C, 0x2208, 0xA1CA, 0x220F, 0xA1C7, 0x2211, 0xA1C6, 0x2215, 0xA84D, 0x221A, 0xA1CC, 0x221D, 0xA1D8, 0x221E, 0xA1DE, + 0x221F, 0xA84E, 0x2220, 0xA1CF, 0x2223, 0xA84F, 0x2225, 0xA1CE, 0x2227, 0xA1C4, 0x2228, 0xA1C5, 0x2229, 0xA1C9, 0x222A, 0xA1C8, + 0x222B, 0xA1D2, 0x222E, 0xA1D3, 0x2234, 0xA1E0, 0x2235, 0xA1DF, 0x2236, 0xA1C3, 0x2237, 0xA1CB, 0x223D, 0xA1D7, 0x2248, 0xA1D6, + 0x224C, 0xA1D5, 0x2252, 0xA850, 0x2260, 0xA1D9, 0x2261, 0xA1D4, 0x2264, 0xA1DC, 0x2265, 0xA1DD, 0x2266, 0xA851, 0x2267, 0xA852, + 0x226E, 0xA1DA, 0x226F, 0xA1DB, 0x2295, 0xA892, 0x2299, 0xA1D1, 0x22A5, 0xA1CD, 0x22BF, 0xA853, 0x2312, 0xA1D0, 0x2460, 0xA2D9, + 0x2461, 0xA2DA, 0x2462, 0xA2DB, 0x2463, 0xA2DC, 0x2464, 0xA2DD, 0x2465, 0xA2DE, 0x2466, 0xA2DF, 0x2467, 0xA2E0, 0x2468, 0xA2E1, + 0x2469, 0xA2E2, 0x2474, 0xA2C5, 0x2475, 0xA2C6, 0x2476, 0xA2C7, 0x2477, 0xA2C8, 0x2478, 0xA2C9, 0x2479, 0xA2CA, 0x247A, 0xA2CB, + 0x247B, 0xA2CC, 0x247C, 0xA2CD, 0x247D, 0xA2CE, 0x247E, 0xA2CF, 0x247F, 0xA2D0, 0x2480, 0xA2D1, 0x2481, 0xA2D2, 0x2482, 0xA2D3, + 0x2483, 0xA2D4, 0x2484, 0xA2D5, 0x2485, 0xA2D6, 0x2486, 0xA2D7, 0x2487, 0xA2D8, 0x2488, 0xA2B1, 0x2489, 0xA2B2, 0x248A, 0xA2B3, + 0x248B, 0xA2B4, 0x248C, 0xA2B5, 0x248D, 0xA2B6, 0x248E, 0xA2B7, 0x248F, 0xA2B8, 0x2490, 0xA2B9, 0x2491, 0xA2BA, 0x2492, 0xA2BB, + 0x2493, 0xA2BC, 0x2494, 0xA2BD, 0x2495, 0xA2BE, 0x2496, 0xA2BF, 0x2497, 0xA2C0, 0x2498, 0xA2C1, 0x2499, 0xA2C2, 0x249A, 0xA2C3, + 0x249B, 0xA2C4, 0x2500, 0xA9A4, 0x2501, 0xA9A5, 0x2502, 0xA9A6, 0x2503, 0xA9A7, 0x2504, 0xA9A8, 0x2505, 0xA9A9, 0x2506, 0xA9AA, + 0x2507, 0xA9AB, 0x2508, 0xA9AC, 0x2509, 0xA9AD, 0x250A, 0xA9AE, 0x250B, 0xA9AF, 0x250C, 0xA9B0, 0x250D, 0xA9B1, 0x250E, 0xA9B2, + 0x250F, 0xA9B3, 0x2510, 0xA9B4, 0x2511, 0xA9B5, 0x2512, 0xA9B6, 0x2513, 0xA9B7, 0x2514, 0xA9B8, 0x2515, 0xA9B9, 0x2516, 0xA9BA, + 0x2517, 0xA9BB, 0x2518, 0xA9BC, 0x2519, 0xA9BD, 0x251A, 0xA9BE, 0x251B, 0xA9BF, 0x251C, 0xA9C0, 0x251D, 0xA9C1, 0x251E, 0xA9C2, + 0x251F, 0xA9C3, 0x2520, 0xA9C4, 0x2521, 0xA9C5, 0x2522, 0xA9C6, 0x2523, 0xA9C7, 0x2524, 0xA9C8, 0x2525, 0xA9C9, 0x2526, 0xA9CA, + 0x2527, 0xA9CB, 0x2528, 0xA9CC, 0x2529, 0xA9CD, 0x252A, 0xA9CE, 0x252B, 0xA9CF, 0x252C, 0xA9D0, 0x252D, 0xA9D1, 0x252E, 0xA9D2, + 0x252F, 0xA9D3, 0x2530, 0xA9D4, 0x2531, 0xA9D5, 0x2532, 0xA9D6, 0x2533, 0xA9D7, 0x2534, 0xA9D8, 0x2535, 0xA9D9, 0x2536, 0xA9DA, + 0x2537, 0xA9DB, 0x2538, 0xA9DC, 0x2539, 0xA9DD, 0x253A, 0xA9DE, 0x253B, 0xA9DF, 0x253C, 0xA9E0, 0x253D, 0xA9E1, 0x253E, 0xA9E2, + 0x253F, 0xA9E3, 0x2540, 0xA9E4, 0x2541, 0xA9E5, 0x2542, 0xA9E6, 0x2543, 0xA9E7, 0x2544, 0xA9E8, 0x2545, 0xA9E9, 0x2546, 0xA9EA, + 0x2547, 0xA9EB, 0x2548, 0xA9EC, 0x2549, 0xA9ED, 0x254A, 0xA9EE, 0x254B, 0xA9EF, 0x2550, 0xA854, 0x2551, 0xA855, 0x2552, 0xA856, + 0x2553, 0xA857, 0x2554, 0xA858, 0x2555, 0xA859, 0x2556, 0xA85A, 0x2557, 0xA85B, 0x2558, 0xA85C, 0x2559, 0xA85D, 0x255A, 0xA85E, + 0x255B, 0xA85F, 0x255C, 0xA860, 0x255D, 0xA861, 0x255E, 0xA862, 0x255F, 0xA863, 0x2560, 0xA864, 0x2561, 0xA865, 0x2562, 0xA866, + 0x2563, 0xA867, 0x2564, 0xA868, 0x2565, 0xA869, 0x2566, 0xA86A, 0x2567, 0xA86B, 0x2568, 0xA86C, 0x2569, 0xA86D, 0x256A, 0xA86E, + 0x256B, 0xA86F, 0x256C, 0xA870, 0x256D, 0xA871, 0x256E, 0xA872, 0x256F, 0xA873, 0x2570, 0xA874, 0x2571, 0xA875, 0x2572, 0xA876, + 0x2573, 0xA877, 0x2581, 0xA878, 0x2582, 0xA879, 0x2583, 0xA87A, 0x2584, 0xA87B, 0x2585, 0xA87C, 0x2586, 0xA87D, 0x2587, 0xA87E, + 0x2588, 0xA880, 0x2589, 0xA881, 0x258A, 0xA882, 0x258B, 0xA883, 0x258C, 0xA884, 0x258D, 0xA885, 0x258E, 0xA886, 0x258F, 0xA887, + 0x2593, 0xA888, 0x2594, 0xA889, 0x2595, 0xA88A, 0x25A0, 0xA1F6, 0x25A1, 0xA1F5, 0x25B2, 0xA1F8, 0x25B3, 0xA1F7, 0x25BC, 0xA88B, + 0x25BD, 0xA88C, 0x25C6, 0xA1F4, 0x25C7, 0xA1F3, 0x25CB, 0xA1F0, 0x25CE, 0xA1F2, 0x25CF, 0xA1F1, 0x25E2, 0xA88D, 0x25E3, 0xA88E, + 0x25E4, 0xA88F, 0x25E5, 0xA890, 0x2605, 0xA1EF, 0x2606, 0xA1EE, 0x2609, 0xA891, 0x2640, 0xA1E2, 0x2642, 0xA1E1, 0x3000, 0xA1A1, + 0x3001, 0xA1A2, 0x3002, 0xA1A3, 0x3003, 0xA1A8, 0x3005, 0xA1A9, 0x3006, 0xA965, 0x3007, 0xA996, 0x3008, 0xA1B4, 0x3009, 0xA1B5, + 0x300A, 0xA1B6, 0x300B, 0xA1B7, 0x300C, 0xA1B8, 0x300D, 0xA1B9, 0x300E, 0xA1BA, 0x300F, 0xA1BB, 0x3010, 0xA1BE, 0x3011, 0xA1BF, + 0x3012, 0xA893, 0x3013, 0xA1FE, 0x3014, 0xA1B2, 0x3015, 0xA1B3, 0x3016, 0xA1BC, 0x3017, 0xA1BD, 0x301D, 0xA894, 0x301E, 0xA895, + 0x3021, 0xA940, 0x3022, 0xA941, 0x3023, 0xA942, 0x3024, 0xA943, 0x3025, 0xA944, 0x3026, 0xA945, 0x3027, 0xA946, 0x3028, 0xA947, + 0x3029, 0xA948, 0x3041, 0xA4A1, 0x3042, 0xA4A2, 0x3043, 0xA4A3, 0x3044, 0xA4A4, 0x3045, 0xA4A5, 0x3046, 0xA4A6, 0x3047, 0xA4A7, + 0x3048, 0xA4A8, 0x3049, 0xA4A9, 0x304A, 0xA4AA, 0x304B, 0xA4AB, 0x304C, 0xA4AC, 0x304D, 0xA4AD, 0x304E, 0xA4AE, 0x304F, 0xA4AF, + 0x3050, 0xA4B0, 0x3051, 0xA4B1, 0x3052, 0xA4B2, 0x3053, 0xA4B3, 0x3054, 0xA4B4, 0x3055, 0xA4B5, 0x3056, 0xA4B6, 0x3057, 0xA4B7, + 0x3058, 0xA4B8, 0x3059, 0xA4B9, 0x305A, 0xA4BA, 0x305B, 0xA4BB, 0x305C, 0xA4BC, 0x305D, 0xA4BD, 0x305E, 0xA4BE, 0x305F, 0xA4BF, + 0x3060, 0xA4C0, 0x3061, 0xA4C1, 0x3062, 0xA4C2, 0x3063, 0xA4C3, 0x3064, 0xA4C4, 0x3065, 0xA4C5, 0x3066, 0xA4C6, 0x3067, 0xA4C7, + 0x3068, 0xA4C8, 0x3069, 0xA4C9, 0x306A, 0xA4CA, 0x306B, 0xA4CB, 0x306C, 0xA4CC, 0x306D, 0xA4CD, 0x306E, 0xA4CE, 0x306F, 0xA4CF, + 0x3070, 0xA4D0, 0x3071, 0xA4D1, 0x3072, 0xA4D2, 0x3073, 0xA4D3, 0x3074, 0xA4D4, 0x3075, 0xA4D5, 0x3076, 0xA4D6, 0x3077, 0xA4D7, + 0x3078, 0xA4D8, 0x3079, 0xA4D9, 0x307A, 0xA4DA, 0x307B, 0xA4DB, 0x307C, 0xA4DC, 0x307D, 0xA4DD, 0x307E, 0xA4DE, 0x307F, 0xA4DF, + 0x3080, 0xA4E0, 0x3081, 0xA4E1, 0x3082, 0xA4E2, 0x3083, 0xA4E3, 0x3084, 0xA4E4, 0x3085, 0xA4E5, 0x3086, 0xA4E6, 0x3087, 0xA4E7, + 0x3088, 0xA4E8, 0x3089, 0xA4E9, 0x308A, 0xA4EA, 0x308B, 0xA4EB, 0x308C, 0xA4EC, 0x308D, 0xA4ED, 0x308E, 0xA4EE, 0x308F, 0xA4EF, + 0x3090, 0xA4F0, 0x3091, 0xA4F1, 0x3092, 0xA4F2, 0x3093, 0xA4F3, 0x309B, 0xA961, 0x309C, 0xA962, 0x309D, 0xA966, 0x309E, 0xA967, + 0x30A1, 0xA5A1, 0x30A2, 0xA5A2, 0x30A3, 0xA5A3, 0x30A4, 0xA5A4, 0x30A5, 0xA5A5, 0x30A6, 0xA5A6, 0x30A7, 0xA5A7, 0x30A8, 0xA5A8, + 0x30A9, 0xA5A9, 0x30AA, 0xA5AA, 0x30AB, 0xA5AB, 0x30AC, 0xA5AC, 0x30AD, 0xA5AD, 0x30AE, 0xA5AE, 0x30AF, 0xA5AF, 0x30B0, 0xA5B0, + 0x30B1, 0xA5B1, 0x30B2, 0xA5B2, 0x30B3, 0xA5B3, 0x30B4, 0xA5B4, 0x30B5, 0xA5B5, 0x30B6, 0xA5B6, 0x30B7, 0xA5B7, 0x30B8, 0xA5B8, + 0x30B9, 0xA5B9, 0x30BA, 0xA5BA, 0x30BB, 0xA5BB, 0x30BC, 0xA5BC, 0x30BD, 0xA5BD, 0x30BE, 0xA5BE, 0x30BF, 0xA5BF, 0x30C0, 0xA5C0, + 0x30C1, 0xA5C1, 0x30C2, 0xA5C2, 0x30C3, 0xA5C3, 0x30C4, 0xA5C4, 0x30C5, 0xA5C5, 0x30C6, 0xA5C6, 0x30C7, 0xA5C7, 0x30C8, 0xA5C8, + 0x30C9, 0xA5C9, 0x30CA, 0xA5CA, 0x30CB, 0xA5CB, 0x30CC, 0xA5CC, 0x30CD, 0xA5CD, 0x30CE, 0xA5CE, 0x30CF, 0xA5CF, 0x30D0, 0xA5D0, + 0x30D1, 0xA5D1, 0x30D2, 0xA5D2, 0x30D3, 0xA5D3, 0x30D4, 0xA5D4, 0x30D5, 0xA5D5, 0x30D6, 0xA5D6, 0x30D7, 0xA5D7, 0x30D8, 0xA5D8, + 0x30D9, 0xA5D9, 0x30DA, 0xA5DA, 0x30DB, 0xA5DB, 0x30DC, 0xA5DC, 0x30DD, 0xA5DD, 0x30DE, 0xA5DE, 0x30DF, 0xA5DF, 0x30E0, 0xA5E0, + 0x30E1, 0xA5E1, 0x30E2, 0xA5E2, 0x30E3, 0xA5E3, 0x30E4, 0xA5E4, 0x30E5, 0xA5E5, 0x30E6, 0xA5E6, 0x30E7, 0xA5E7, 0x30E8, 0xA5E8, + 0x30E9, 0xA5E9, 0x30EA, 0xA5EA, 0x30EB, 0xA5EB, 0x30EC, 0xA5EC, 0x30ED, 0xA5ED, 0x30EE, 0xA5EE, 0x30EF, 0xA5EF, 0x30F0, 0xA5F0, + 0x30F1, 0xA5F1, 0x30F2, 0xA5F2, 0x30F3, 0xA5F3, 0x30F4, 0xA5F4, 0x30F5, 0xA5F5, 0x30F6, 0xA5F6, 0x30FC, 0xA960, 0x30FD, 0xA963, + 0x30FE, 0xA964, 0x3105, 0xA8C5, 0x3106, 0xA8C6, 0x3107, 0xA8C7, 0x3108, 0xA8C8, 0x3109, 0xA8C9, 0x310A, 0xA8CA, 0x310B, 0xA8CB, + 0x310C, 0xA8CC, 0x310D, 0xA8CD, 0x310E, 0xA8CE, 0x310F, 0xA8CF, 0x3110, 0xA8D0, 0x3111, 0xA8D1, 0x3112, 0xA8D2, 0x3113, 0xA8D3, + 0x3114, 0xA8D4, 0x3115, 0xA8D5, 0x3116, 0xA8D6, 0x3117, 0xA8D7, 0x3118, 0xA8D8, 0x3119, 0xA8D9, 0x311A, 0xA8DA, 0x311B, 0xA8DB, + 0x311C, 0xA8DC, 0x311D, 0xA8DD, 0x311E, 0xA8DE, 0x311F, 0xA8DF, 0x3120, 0xA8E0, 0x3121, 0xA8E1, 0x3122, 0xA8E2, 0x3123, 0xA8E3, + 0x3124, 0xA8E4, 0x3125, 0xA8E5, 0x3126, 0xA8E6, 0x3127, 0xA8E7, 0x3128, 0xA8E8, 0x3129, 0xA8E9, 0x3220, 0xA2E5, 0x3221, 0xA2E6, + 0x3222, 0xA2E7, 0x3223, 0xA2E8, 0x3224, 0xA2E9, 0x3225, 0xA2EA, 0x3226, 0xA2EB, 0x3227, 0xA2EC, 0x3228, 0xA2ED, 0x3229, 0xA2EE, + 0x3231, 0xA95A, 0x32A3, 0xA949, 0x338E, 0xA94A, 0x338F, 0xA94B, 0x339C, 0xA94C, 0x339D, 0xA94D, 0x339E, 0xA94E, 0x33A1, 0xA94F, + 0x33C4, 0xA950, 0x33CE, 0xA951, 0x33D1, 0xA952, 0x33D2, 0xA953, 0x33D5, 0xA954, 0x4E00, 0xD2BB, 0x4E01, 0xB6A1, 0x4E02, 0x8140, + 0x4E03, 0xC6DF, 0x4E04, 0x8141, 0x4E05, 0x8142, 0x4E06, 0x8143, 0x4E07, 0xCDF2, 0x4E08, 0xD5C9, 0x4E09, 0xC8FD, 0x4E0A, 0xC9CF, + 0x4E0B, 0xCFC2, 0x4E0C, 0xD8A2, 0x4E0D, 0xB2BB, 0x4E0E, 0xD3EB, 0x4E0F, 0x8144, 0x4E10, 0xD8A4, 0x4E11, 0xB3F3, 0x4E12, 0x8145, + 0x4E13, 0xD7A8, 0x4E14, 0xC7D2, 0x4E15, 0xD8A7, 0x4E16, 0xCAC0, 0x4E17, 0x8146, 0x4E18, 0xC7F0, 0x4E19, 0xB1FB, 0x4E1A, 0xD2B5, + 0x4E1B, 0xB4D4, 0x4E1C, 0xB6AB, 0x4E1D, 0xCBBF, 0x4E1E, 0xD8A9, 0x4E1F, 0x8147, 0x4E20, 0x8148, 0x4E21, 0x8149, 0x4E22, 0xB6AA, + 0x4E23, 0x814A, 0x4E24, 0xC1BD, 0x4E25, 0xD1CF, 0x4E26, 0x814B, 0x4E27, 0xC9A5, 0x4E28, 0xD8AD, 0x4E29, 0x814C, 0x4E2A, 0xB8F6, + 0x4E2B, 0xD1BE, 0x4E2C, 0xE3DC, 0x4E2D, 0xD6D0, 0x4E2E, 0x814D, 0x4E2F, 0x814E, 0x4E30, 0xB7E1, 0x4E31, 0x814F, 0x4E32, 0xB4AE, + 0x4E33, 0x8150, 0x4E34, 0xC1D9, 0x4E35, 0x8151, 0x4E36, 0xD8BC, 0x4E37, 0x8152, 0x4E38, 0xCDE8, 0x4E39, 0xB5A4, 0x4E3A, 0xCEAA, + 0x4E3B, 0xD6F7, 0x4E3C, 0x8153, 0x4E3D, 0xC0F6, 0x4E3E, 0xBED9, 0x4E3F, 0xD8AF, 0x4E40, 0x8154, 0x4E41, 0x8155, 0x4E42, 0x8156, + 0x4E43, 0xC4CB, 0x4E44, 0x8157, 0x4E45, 0xBEC3, 0x4E46, 0x8158, 0x4E47, 0xD8B1, 0x4E48, 0xC3B4, 0x4E49, 0xD2E5, 0x4E4A, 0x8159, + 0x4E4B, 0xD6AE, 0x4E4C, 0xCEDA, 0x4E4D, 0xD5A7, 0x4E4E, 0xBAF5, 0x4E4F, 0xB7A6, 0x4E50, 0xC0D6, 0x4E51, 0x815A, 0x4E52, 0xC6B9, + 0x4E53, 0xC5D2, 0x4E54, 0xC7C7, 0x4E55, 0x815B, 0x4E56, 0xB9D4, 0x4E57, 0x815C, 0x4E58, 0xB3CB, 0x4E59, 0xD2D2, 0x4E5A, 0x815D, + 0x4E5B, 0x815E, 0x4E5C, 0xD8BF, 0x4E5D, 0xBEC5, 0x4E5E, 0xC6F2, 0x4E5F, 0xD2B2, 0x4E60, 0xCFB0, 0x4E61, 0xCFE7, 0x4E62, 0x815F, + 0x4E63, 0x8160, 0x4E64, 0x8161, 0x4E65, 0x8162, 0x4E66, 0xCAE9, 0x4E67, 0x8163, 0x4E68, 0x8164, 0x4E69, 0xD8C0, 0x4E6A, 0x8165, + 0x4E6B, 0x8166, 0x4E6C, 0x8167, 0x4E6D, 0x8168, 0x4E6E, 0x8169, 0x4E6F, 0x816A, 0x4E70, 0xC2F2, 0x4E71, 0xC2D2, 0x4E72, 0x816B, + 0x4E73, 0xC8E9, 0x4E74, 0x816C, 0x4E75, 0x816D, 0x4E76, 0x816E, 0x4E77, 0x816F, 0x4E78, 0x8170, 0x4E79, 0x8171, 0x4E7A, 0x8172, + 0x4E7B, 0x8173, 0x4E7C, 0x8174, 0x4E7D, 0x8175, 0x4E7E, 0xC7AC, 0x4E7F, 0x8176, 0x4E80, 0x8177, 0x4E81, 0x8178, 0x4E82, 0x8179, + 0x4E83, 0x817A, 0x4E84, 0x817B, 0x4E85, 0x817C, 0x4E86, 0xC1CB, 0x4E87, 0x817D, 0x4E88, 0xD3E8, 0x4E89, 0xD5F9, 0x4E8A, 0x817E, + 0x4E8B, 0xCAC2, 0x4E8C, 0xB6FE, 0x4E8D, 0xD8A1, 0x4E8E, 0xD3DA, 0x4E8F, 0xBFF7, 0x4E90, 0x8180, 0x4E91, 0xD4C6, 0x4E92, 0xBBA5, + 0x4E93, 0xD8C1, 0x4E94, 0xCEE5, 0x4E95, 0xBEAE, 0x4E96, 0x8181, 0x4E97, 0x8182, 0x4E98, 0xD8A8, 0x4E99, 0x8183, 0x4E9A, 0xD1C7, + 0x4E9B, 0xD0A9, 0x4E9C, 0x8184, 0x4E9D, 0x8185, 0x4E9E, 0x8186, 0x4E9F, 0xD8BD, 0x4EA0, 0xD9EF, 0x4EA1, 0xCDF6, 0x4EA2, 0xBFBA, + 0x4EA3, 0x8187, 0x4EA4, 0xBDBB, 0x4EA5, 0xBAA5, 0x4EA6, 0xD2E0, 0x4EA7, 0xB2FA, 0x4EA8, 0xBAE0, 0x4EA9, 0xC4B6, 0x4EAA, 0x8188, + 0x4EAB, 0xCFED, 0x4EAC, 0xBEA9, 0x4EAD, 0xCDA4, 0x4EAE, 0xC1C1, 0x4EAF, 0x8189, 0x4EB0, 0x818A, 0x4EB1, 0x818B, 0x4EB2, 0xC7D7, + 0x4EB3, 0xD9F1, 0x4EB4, 0x818C, 0x4EB5, 0xD9F4, 0x4EB6, 0x818D, 0x4EB7, 0x818E, 0x4EB8, 0x818F, 0x4EB9, 0x8190, 0x4EBA, 0xC8CB, + 0x4EBB, 0xD8E9, 0x4EBC, 0x8191, 0x4EBD, 0x8192, 0x4EBE, 0x8193, 0x4EBF, 0xD2DA, 0x4EC0, 0xCAB2, 0x4EC1, 0xC8CA, 0x4EC2, 0xD8EC, + 0x4EC3, 0xD8EA, 0x4EC4, 0xD8C6, 0x4EC5, 0xBDF6, 0x4EC6, 0xC6CD, 0x4EC7, 0xB3F0, 0x4EC8, 0x8194, 0x4EC9, 0xD8EB, 0x4ECA, 0xBDF1, + 0x4ECB, 0xBDE9, 0x4ECC, 0x8195, 0x4ECD, 0xC8D4, 0x4ECE, 0xB4D3, 0x4ECF, 0x8196, 0x4ED0, 0x8197, 0x4ED1, 0xC2D8, 0x4ED2, 0x8198, + 0x4ED3, 0xB2D6, 0x4ED4, 0xD7D0, 0x4ED5, 0xCACB, 0x4ED6, 0xCBFB, 0x4ED7, 0xD5CC, 0x4ED8, 0xB8B6, 0x4ED9, 0xCFC9, 0x4EDA, 0x8199, + 0x4EDB, 0x819A, 0x4EDC, 0x819B, 0x4EDD, 0xD9DA, 0x4EDE, 0xD8F0, 0x4EDF, 0xC7AA, 0x4EE0, 0x819C, 0x4EE1, 0xD8EE, 0x4EE2, 0x819D, + 0x4EE3, 0xB4FA, 0x4EE4, 0xC1EE, 0x4EE5, 0xD2D4, 0x4EE6, 0x819E, 0x4EE7, 0x819F, 0x4EE8, 0xD8ED, 0x4EE9, 0x81A0, 0x4EEA, 0xD2C7, + 0x4EEB, 0xD8EF, 0x4EEC, 0xC3C7, 0x4EED, 0x81A1, 0x4EEE, 0x81A2, 0x4EEF, 0x81A3, 0x4EF0, 0xD1F6, 0x4EF1, 0x81A4, 0x4EF2, 0xD6D9, + 0x4EF3, 0xD8F2, 0x4EF4, 0x81A5, 0x4EF5, 0xD8F5, 0x4EF6, 0xBCFE, 0x4EF7, 0xBCDB, 0x4EF8, 0x81A6, 0x4EF9, 0x81A7, 0x4EFA, 0x81A8, + 0x4EFB, 0xC8CE, 0x4EFC, 0x81A9, 0x4EFD, 0xB7DD, 0x4EFE, 0x81AA, 0x4EFF, 0xB7C2, 0x4F00, 0x81AB, 0x4F01, 0xC6F3, 0x4F02, 0x81AC, + 0x4F03, 0x81AD, 0x4F04, 0x81AE, 0x4F05, 0x81AF, 0x4F06, 0x81B0, 0x4F07, 0x81B1, 0x4F08, 0x81B2, 0x4F09, 0xD8F8, 0x4F0A, 0xD2C1, + 0x4F0B, 0x81B3, 0x4F0C, 0x81B4, 0x4F0D, 0xCEE9, 0x4F0E, 0xBCBF, 0x4F0F, 0xB7FC, 0x4F10, 0xB7A5, 0x4F11, 0xD0DD, 0x4F12, 0x81B5, + 0x4F13, 0x81B6, 0x4F14, 0x81B7, 0x4F15, 0x81B8, 0x4F16, 0x81B9, 0x4F17, 0xD6DA, 0x4F18, 0xD3C5, 0x4F19, 0xBBEF, 0x4F1A, 0xBBE1, + 0x4F1B, 0xD8F1, 0x4F1C, 0x81BA, 0x4F1D, 0x81BB, 0x4F1E, 0xC9A1, 0x4F1F, 0xCEB0, 0x4F20, 0xB4AB, 0x4F21, 0x81BC, 0x4F22, 0xD8F3, + 0x4F23, 0x81BD, 0x4F24, 0xC9CB, 0x4F25, 0xD8F6, 0x4F26, 0xC2D7, 0x4F27, 0xD8F7, 0x4F28, 0x81BE, 0x4F29, 0x81BF, 0x4F2A, 0xCEB1, + 0x4F2B, 0xD8F9, 0x4F2C, 0x81C0, 0x4F2D, 0x81C1, 0x4F2E, 0x81C2, 0x4F2F, 0xB2AE, 0x4F30, 0xB9C0, 0x4F31, 0x81C3, 0x4F32, 0xD9A3, + 0x4F33, 0x81C4, 0x4F34, 0xB0E9, 0x4F35, 0x81C5, 0x4F36, 0xC1E6, 0x4F37, 0x81C6, 0x4F38, 0xC9EC, 0x4F39, 0x81C7, 0x4F3A, 0xCBC5, + 0x4F3B, 0x81C8, 0x4F3C, 0xCBC6, 0x4F3D, 0xD9A4, 0x4F3E, 0x81C9, 0x4F3F, 0x81CA, 0x4F40, 0x81CB, 0x4F41, 0x81CC, 0x4F42, 0x81CD, + 0x4F43, 0xB5E8, 0x4F44, 0x81CE, 0x4F45, 0x81CF, 0x4F46, 0xB5AB, 0x4F47, 0x81D0, 0x4F48, 0x81D1, 0x4F49, 0x81D2, 0x4F4A, 0x81D3, + 0x4F4B, 0x81D4, 0x4F4C, 0x81D5, 0x4F4D, 0xCEBB, 0x4F4E, 0xB5CD, 0x4F4F, 0xD7A1, 0x4F50, 0xD7F4, 0x4F51, 0xD3D3, 0x4F52, 0x81D6, + 0x4F53, 0xCCE5, 0x4F54, 0x81D7, 0x4F55, 0xBACE, 0x4F56, 0x81D8, 0x4F57, 0xD9A2, 0x4F58, 0xD9DC, 0x4F59, 0xD3E0, 0x4F5A, 0xD8FD, + 0x4F5B, 0xB7F0, 0x4F5C, 0xD7F7, 0x4F5D, 0xD8FE, 0x4F5E, 0xD8FA, 0x4F5F, 0xD9A1, 0x4F60, 0xC4E3, 0x4F61, 0x81D9, 0x4F62, 0x81DA, + 0x4F63, 0xD3B6, 0x4F64, 0xD8F4, 0x4F65, 0xD9DD, 0x4F66, 0x81DB, 0x4F67, 0xD8FB, 0x4F68, 0x81DC, 0x4F69, 0xC5E5, 0x4F6A, 0x81DD, + 0x4F6B, 0x81DE, 0x4F6C, 0xC0D0, 0x4F6D, 0x81DF, 0x4F6E, 0x81E0, 0x4F6F, 0xD1F0, 0x4F70, 0xB0DB, 0x4F71, 0x81E1, 0x4F72, 0x81E2, + 0x4F73, 0xBCD1, 0x4F74, 0xD9A6, 0x4F75, 0x81E3, 0x4F76, 0xD9A5, 0x4F77, 0x81E4, 0x4F78, 0x81E5, 0x4F79, 0x81E6, 0x4F7A, 0x81E7, + 0x4F7B, 0xD9AC, 0x4F7C, 0xD9AE, 0x4F7D, 0x81E8, 0x4F7E, 0xD9AB, 0x4F7F, 0xCAB9, 0x4F80, 0x81E9, 0x4F81, 0x81EA, 0x4F82, 0x81EB, + 0x4F83, 0xD9A9, 0x4F84, 0xD6B6, 0x4F85, 0x81EC, 0x4F86, 0x81ED, 0x4F87, 0x81EE, 0x4F88, 0xB3DE, 0x4F89, 0xD9A8, 0x4F8A, 0x81EF, + 0x4F8B, 0xC0FD, 0x4F8C, 0x81F0, 0x4F8D, 0xCACC, 0x4F8E, 0x81F1, 0x4F8F, 0xD9AA, 0x4F90, 0x81F2, 0x4F91, 0xD9A7, 0x4F92, 0x81F3, + 0x4F93, 0x81F4, 0x4F94, 0xD9B0, 0x4F95, 0x81F5, 0x4F96, 0x81F6, 0x4F97, 0xB6B1, 0x4F98, 0x81F7, 0x4F99, 0x81F8, 0x4F9A, 0x81F9, + 0x4F9B, 0xB9A9, 0x4F9C, 0x81FA, 0x4F9D, 0xD2C0, 0x4F9E, 0x81FB, 0x4F9F, 0x81FC, 0x4FA0, 0xCFC0, 0x4FA1, 0x81FD, 0x4FA2, 0x81FE, + 0x4FA3, 0xC2C2, 0x4FA4, 0x8240, 0x4FA5, 0xBDC4, 0x4FA6, 0xD5EC, 0x4FA7, 0xB2E0, 0x4FA8, 0xC7C8, 0x4FA9, 0xBFEB, 0x4FAA, 0xD9AD, + 0x4FAB, 0x8241, 0x4FAC, 0xD9AF, 0x4FAD, 0x8242, 0x4FAE, 0xCEEA, 0x4FAF, 0xBAEE, 0x4FB0, 0x8243, 0x4FB1, 0x8244, 0x4FB2, 0x8245, + 0x4FB3, 0x8246, 0x4FB4, 0x8247, 0x4FB5, 0xC7D6, 0x4FB6, 0x8248, 0x4FB7, 0x8249, 0x4FB8, 0x824A, 0x4FB9, 0x824B, 0x4FBA, 0x824C, + 0x4FBB, 0x824D, 0x4FBC, 0x824E, 0x4FBD, 0x824F, 0x4FBE, 0x8250, 0x4FBF, 0xB1E3, 0x4FC0, 0x8251, 0x4FC1, 0x8252, 0x4FC2, 0x8253, + 0x4FC3, 0xB4D9, 0x4FC4, 0xB6ED, 0x4FC5, 0xD9B4, 0x4FC6, 0x8254, 0x4FC7, 0x8255, 0x4FC8, 0x8256, 0x4FC9, 0x8257, 0x4FCA, 0xBFA1, + 0x4FCB, 0x8258, 0x4FCC, 0x8259, 0x4FCD, 0x825A, 0x4FCE, 0xD9DE, 0x4FCF, 0xC7CE, 0x4FD0, 0xC0FE, 0x4FD1, 0xD9B8, 0x4FD2, 0x825B, + 0x4FD3, 0x825C, 0x4FD4, 0x825D, 0x4FD5, 0x825E, 0x4FD6, 0x825F, 0x4FD7, 0xCBD7, 0x4FD8, 0xB7FD, 0x4FD9, 0x8260, 0x4FDA, 0xD9B5, + 0x4FDB, 0x8261, 0x4FDC, 0xD9B7, 0x4FDD, 0xB1A3, 0x4FDE, 0xD3E1, 0x4FDF, 0xD9B9, 0x4FE0, 0x8262, 0x4FE1, 0xD0C5, 0x4FE2, 0x8263, + 0x4FE3, 0xD9B6, 0x4FE4, 0x8264, 0x4FE5, 0x8265, 0x4FE6, 0xD9B1, 0x4FE7, 0x8266, 0x4FE8, 0xD9B2, 0x4FE9, 0xC1A9, 0x4FEA, 0xD9B3, + 0x4FEB, 0x8267, 0x4FEC, 0x8268, 0x4FED, 0xBCF3, 0x4FEE, 0xD0DE, 0x4FEF, 0xB8A9, 0x4FF0, 0x8269, 0x4FF1, 0xBEE3, 0x4FF2, 0x826A, + 0x4FF3, 0xD9BD, 0x4FF4, 0x826B, 0x4FF5, 0x826C, 0x4FF6, 0x826D, 0x4FF7, 0x826E, 0x4FF8, 0xD9BA, 0x4FF9, 0x826F, 0x4FFA, 0xB0B3, + 0x4FFB, 0x8270, 0x4FFC, 0x8271, 0x4FFD, 0x8272, 0x4FFE, 0xD9C2, 0x4FFF, 0x8273, 0x5000, 0x8274, 0x5001, 0x8275, 0x5002, 0x8276, + 0x5003, 0x8277, 0x5004, 0x8278, 0x5005, 0x8279, 0x5006, 0x827A, 0x5007, 0x827B, 0x5008, 0x827C, 0x5009, 0x827D, 0x500A, 0x827E, + 0x500B, 0x8280, 0x500C, 0xD9C4, 0x500D, 0xB1B6, 0x500E, 0x8281, 0x500F, 0xD9BF, 0x5010, 0x8282, 0x5011, 0x8283, 0x5012, 0xB5B9, + 0x5013, 0x8284, 0x5014, 0xBEF3, 0x5015, 0x8285, 0x5016, 0x8286, 0x5017, 0x8287, 0x5018, 0xCCC8, 0x5019, 0xBAF2, 0x501A, 0xD2D0, + 0x501B, 0x8288, 0x501C, 0xD9C3, 0x501D, 0x8289, 0x501E, 0x828A, 0x501F, 0xBDE8, 0x5020, 0x828B, 0x5021, 0xB3AB, 0x5022, 0x828C, + 0x5023, 0x828D, 0x5024, 0x828E, 0x5025, 0xD9C5, 0x5026, 0xBEEB, 0x5027, 0x828F, 0x5028, 0xD9C6, 0x5029, 0xD9BB, 0x502A, 0xC4DF, + 0x502B, 0x8290, 0x502C, 0xD9BE, 0x502D, 0xD9C1, 0x502E, 0xD9C0, 0x502F, 0x8291, 0x5030, 0x8292, 0x5031, 0x8293, 0x5032, 0x8294, + 0x5033, 0x8295, 0x5034, 0x8296, 0x5035, 0x8297, 0x5036, 0x8298, 0x5037, 0x8299, 0x5038, 0x829A, 0x5039, 0x829B, 0x503A, 0xD5AE, + 0x503B, 0x829C, 0x503C, 0xD6B5, 0x503D, 0x829D, 0x503E, 0xC7E3, 0x503F, 0x829E, 0x5040, 0x829F, 0x5041, 0x82A0, 0x5042, 0x82A1, + 0x5043, 0xD9C8, 0x5044, 0x82A2, 0x5045, 0x82A3, 0x5046, 0x82A4, 0x5047, 0xBCD9, 0x5048, 0xD9CA, 0x5049, 0x82A5, 0x504A, 0x82A6, + 0x504B, 0x82A7, 0x504C, 0xD9BC, 0x504D, 0x82A8, 0x504E, 0xD9CB, 0x504F, 0xC6AB, 0x5050, 0x82A9, 0x5051, 0x82AA, 0x5052, 0x82AB, + 0x5053, 0x82AC, 0x5054, 0x82AD, 0x5055, 0xD9C9, 0x5056, 0x82AE, 0x5057, 0x82AF, 0x5058, 0x82B0, 0x5059, 0x82B1, 0x505A, 0xD7F6, + 0x505B, 0x82B2, 0x505C, 0xCDA3, 0x505D, 0x82B3, 0x505E, 0x82B4, 0x505F, 0x82B5, 0x5060, 0x82B6, 0x5061, 0x82B7, 0x5062, 0x82B8, + 0x5063, 0x82B9, 0x5064, 0x82BA, 0x5065, 0xBDA1, 0x5066, 0x82BB, 0x5067, 0x82BC, 0x5068, 0x82BD, 0x5069, 0x82BE, 0x506A, 0x82BF, + 0x506B, 0x82C0, 0x506C, 0xD9CC, 0x506D, 0x82C1, 0x506E, 0x82C2, 0x506F, 0x82C3, 0x5070, 0x82C4, 0x5071, 0x82C5, 0x5072, 0x82C6, + 0x5073, 0x82C7, 0x5074, 0x82C8, 0x5075, 0x82C9, 0x5076, 0xC5BC, 0x5077, 0xCDB5, 0x5078, 0x82CA, 0x5079, 0x82CB, 0x507A, 0x82CC, + 0x507B, 0xD9CD, 0x507C, 0x82CD, 0x507D, 0x82CE, 0x507E, 0xD9C7, 0x507F, 0xB3A5, 0x5080, 0xBFFE, 0x5081, 0x82CF, 0x5082, 0x82D0, + 0x5083, 0x82D1, 0x5084, 0x82D2, 0x5085, 0xB8B5, 0x5086, 0x82D3, 0x5087, 0x82D4, 0x5088, 0xC0FC, 0x5089, 0x82D5, 0x508A, 0x82D6, + 0x508B, 0x82D7, 0x508C, 0x82D8, 0x508D, 0xB0F8, 0x508E, 0x82D9, 0x508F, 0x82DA, 0x5090, 0x82DB, 0x5091, 0x82DC, 0x5092, 0x82DD, + 0x5093, 0x82DE, 0x5094, 0x82DF, 0x5095, 0x82E0, 0x5096, 0x82E1, 0x5097, 0x82E2, 0x5098, 0x82E3, 0x5099, 0x82E4, 0x509A, 0x82E5, + 0x509B, 0x82E6, 0x509C, 0x82E7, 0x509D, 0x82E8, 0x509E, 0x82E9, 0x509F, 0x82EA, 0x50A0, 0x82EB, 0x50A1, 0x82EC, 0x50A2, 0x82ED, + 0x50A3, 0xB4F6, 0x50A4, 0x82EE, 0x50A5, 0xD9CE, 0x50A6, 0x82EF, 0x50A7, 0xD9CF, 0x50A8, 0xB4A2, 0x50A9, 0xD9D0, 0x50AA, 0x82F0, + 0x50AB, 0x82F1, 0x50AC, 0xB4DF, 0x50AD, 0x82F2, 0x50AE, 0x82F3, 0x50AF, 0x82F4, 0x50B0, 0x82F5, 0x50B1, 0x82F6, 0x50B2, 0xB0C1, + 0x50B3, 0x82F7, 0x50B4, 0x82F8, 0x50B5, 0x82F9, 0x50B6, 0x82FA, 0x50B7, 0x82FB, 0x50B8, 0x82FC, 0x50B9, 0x82FD, 0x50BA, 0xD9D1, + 0x50BB, 0xC9B5, 0x50BC, 0x82FE, 0x50BD, 0x8340, 0x50BE, 0x8341, 0x50BF, 0x8342, 0x50C0, 0x8343, 0x50C1, 0x8344, 0x50C2, 0x8345, + 0x50C3, 0x8346, 0x50C4, 0x8347, 0x50C5, 0x8348, 0x50C6, 0x8349, 0x50C7, 0x834A, 0x50C8, 0x834B, 0x50C9, 0x834C, 0x50CA, 0x834D, + 0x50CB, 0x834E, 0x50CC, 0x834F, 0x50CD, 0x8350, 0x50CE, 0x8351, 0x50CF, 0xCFF1, 0x50D0, 0x8352, 0x50D1, 0x8353, 0x50D2, 0x8354, + 0x50D3, 0x8355, 0x50D4, 0x8356, 0x50D5, 0x8357, 0x50D6, 0xD9D2, 0x50D7, 0x8358, 0x50D8, 0x8359, 0x50D9, 0x835A, 0x50DA, 0xC1C5, + 0x50DB, 0x835B, 0x50DC, 0x835C, 0x50DD, 0x835D, 0x50DE, 0x835E, 0x50DF, 0x835F, 0x50E0, 0x8360, 0x50E1, 0x8361, 0x50E2, 0x8362, + 0x50E3, 0x8363, 0x50E4, 0x8364, 0x50E5, 0x8365, 0x50E6, 0xD9D6, 0x50E7, 0xC9AE, 0x50E8, 0x8366, 0x50E9, 0x8367, 0x50EA, 0x8368, + 0x50EB, 0x8369, 0x50EC, 0xD9D5, 0x50ED, 0xD9D4, 0x50EE, 0xD9D7, 0x50EF, 0x836A, 0x50F0, 0x836B, 0x50F1, 0x836C, 0x50F2, 0x836D, + 0x50F3, 0xCBDB, 0x50F4, 0x836E, 0x50F5, 0xBDA9, 0x50F6, 0x836F, 0x50F7, 0x8370, 0x50F8, 0x8371, 0x50F9, 0x8372, 0x50FA, 0x8373, + 0x50FB, 0xC6A7, 0x50FC, 0x8374, 0x50FD, 0x8375, 0x50FE, 0x8376, 0x50FF, 0x8377, 0x5100, 0x8378, 0x5101, 0x8379, 0x5102, 0x837A, + 0x5103, 0x837B, 0x5104, 0x837C, 0x5105, 0x837D, 0x5106, 0xD9D3, 0x5107, 0xD9D8, 0x5108, 0x837E, 0x5109, 0x8380, 0x510A, 0x8381, + 0x510B, 0xD9D9, 0x510C, 0x8382, 0x510D, 0x8383, 0x510E, 0x8384, 0x510F, 0x8385, 0x5110, 0x8386, 0x5111, 0x8387, 0x5112, 0xC8E5, + 0x5113, 0x8388, 0x5114, 0x8389, 0x5115, 0x838A, 0x5116, 0x838B, 0x5117, 0x838C, 0x5118, 0x838D, 0x5119, 0x838E, 0x511A, 0x838F, + 0x511B, 0x8390, 0x511C, 0x8391, 0x511D, 0x8392, 0x511E, 0x8393, 0x511F, 0x8394, 0x5120, 0x8395, 0x5121, 0xC0DC, 0x5122, 0x8396, + 0x5123, 0x8397, 0x5124, 0x8398, 0x5125, 0x8399, 0x5126, 0x839A, 0x5127, 0x839B, 0x5128, 0x839C, 0x5129, 0x839D, 0x512A, 0x839E, + 0x512B, 0x839F, 0x512C, 0x83A0, 0x512D, 0x83A1, 0x512E, 0x83A2, 0x512F, 0x83A3, 0x5130, 0x83A4, 0x5131, 0x83A5, 0x5132, 0x83A6, + 0x5133, 0x83A7, 0x5134, 0x83A8, 0x5135, 0x83A9, 0x5136, 0x83AA, 0x5137, 0x83AB, 0x5138, 0x83AC, 0x5139, 0x83AD, 0x513A, 0x83AE, + 0x513B, 0x83AF, 0x513C, 0x83B0, 0x513D, 0x83B1, 0x513E, 0x83B2, 0x513F, 0xB6F9, 0x5140, 0xD8A3, 0x5141, 0xD4CA, 0x5142, 0x83B3, + 0x5143, 0xD4AA, 0x5144, 0xD0D6, 0x5145, 0xB3E4, 0x5146, 0xD5D7, 0x5147, 0x83B4, 0x5148, 0xCFC8, 0x5149, 0xB9E2, 0x514A, 0x83B5, + 0x514B, 0xBFCB, 0x514C, 0x83B6, 0x514D, 0xC3E2, 0x514E, 0x83B7, 0x514F, 0x83B8, 0x5150, 0x83B9, 0x5151, 0xB6D2, 0x5152, 0x83BA, + 0x5153, 0x83BB, 0x5154, 0xCDC3, 0x5155, 0xD9EE, 0x5156, 0xD9F0, 0x5157, 0x83BC, 0x5158, 0x83BD, 0x5159, 0x83BE, 0x515A, 0xB5B3, + 0x515B, 0x83BF, 0x515C, 0xB6B5, 0x515D, 0x83C0, 0x515E, 0x83C1, 0x515F, 0x83C2, 0x5160, 0x83C3, 0x5161, 0x83C4, 0x5162, 0xBEA4, + 0x5163, 0x83C5, 0x5164, 0x83C6, 0x5165, 0xC8EB, 0x5166, 0x83C7, 0x5167, 0x83C8, 0x5168, 0xC8AB, 0x5169, 0x83C9, 0x516A, 0x83CA, + 0x516B, 0xB0CB, 0x516C, 0xB9AB, 0x516D, 0xC1F9, 0x516E, 0xD9E2, 0x516F, 0x83CB, 0x5170, 0xC0BC, 0x5171, 0xB9B2, 0x5172, 0x83CC, + 0x5173, 0xB9D8, 0x5174, 0xD0CB, 0x5175, 0xB1F8, 0x5176, 0xC6E4, 0x5177, 0xBEDF, 0x5178, 0xB5E4, 0x5179, 0xD7C8, 0x517A, 0x83CD, + 0x517B, 0xD1F8, 0x517C, 0xBCE6, 0x517D, 0xCADE, 0x517E, 0x83CE, 0x517F, 0x83CF, 0x5180, 0xBCBD, 0x5181, 0xD9E6, 0x5182, 0xD8E7, + 0x5183, 0x83D0, 0x5184, 0x83D1, 0x5185, 0xC4DA, 0x5186, 0x83D2, 0x5187, 0x83D3, 0x5188, 0xB8D4, 0x5189, 0xC8BD, 0x518A, 0x83D4, + 0x518B, 0x83D5, 0x518C, 0xB2E1, 0x518D, 0xD4D9, 0x518E, 0x83D6, 0x518F, 0x83D7, 0x5190, 0x83D8, 0x5191, 0x83D9, 0x5192, 0xC3B0, + 0x5193, 0x83DA, 0x5194, 0x83DB, 0x5195, 0xC3E1, 0x5196, 0xDAA2, 0x5197, 0xC8DF, 0x5198, 0x83DC, 0x5199, 0xD0B4, 0x519A, 0x83DD, + 0x519B, 0xBEFC, 0x519C, 0xC5A9, 0x519D, 0x83DE, 0x519E, 0x83DF, 0x519F, 0x83E0, 0x51A0, 0xB9DA, 0x51A1, 0x83E1, 0x51A2, 0xDAA3, + 0x51A3, 0x83E2, 0x51A4, 0xD4A9, 0x51A5, 0xDAA4, 0x51A6, 0x83E3, 0x51A7, 0x83E4, 0x51A8, 0x83E5, 0x51A9, 0x83E6, 0x51AA, 0x83E7, + 0x51AB, 0xD9FB, 0x51AC, 0xB6AC, 0x51AD, 0x83E8, 0x51AE, 0x83E9, 0x51AF, 0xB7EB, 0x51B0, 0xB1F9, 0x51B1, 0xD9FC, 0x51B2, 0xB3E5, + 0x51B3, 0xBEF6, 0x51B4, 0x83EA, 0x51B5, 0xBFF6, 0x51B6, 0xD2B1, 0x51B7, 0xC0E4, 0x51B8, 0x83EB, 0x51B9, 0x83EC, 0x51BA, 0x83ED, + 0x51BB, 0xB6B3, 0x51BC, 0xD9FE, 0x51BD, 0xD9FD, 0x51BE, 0x83EE, 0x51BF, 0x83EF, 0x51C0, 0xBEBB, 0x51C1, 0x83F0, 0x51C2, 0x83F1, + 0x51C3, 0x83F2, 0x51C4, 0xC6E0, 0x51C5, 0x83F3, 0x51C6, 0xD7BC, 0x51C7, 0xDAA1, 0x51C8, 0x83F4, 0x51C9, 0xC1B9, 0x51CA, 0x83F5, + 0x51CB, 0xB5F2, 0x51CC, 0xC1E8, 0x51CD, 0x83F6, 0x51CE, 0x83F7, 0x51CF, 0xBCF5, 0x51D0, 0x83F8, 0x51D1, 0xB4D5, 0x51D2, 0x83F9, + 0x51D3, 0x83FA, 0x51D4, 0x83FB, 0x51D5, 0x83FC, 0x51D6, 0x83FD, 0x51D7, 0x83FE, 0x51D8, 0x8440, 0x51D9, 0x8441, 0x51DA, 0x8442, + 0x51DB, 0xC1DD, 0x51DC, 0x8443, 0x51DD, 0xC4FD, 0x51DE, 0x8444, 0x51DF, 0x8445, 0x51E0, 0xBCB8, 0x51E1, 0xB7B2, 0x51E2, 0x8446, + 0x51E3, 0x8447, 0x51E4, 0xB7EF, 0x51E5, 0x8448, 0x51E6, 0x8449, 0x51E7, 0x844A, 0x51E8, 0x844B, 0x51E9, 0x844C, 0x51EA, 0x844D, + 0x51EB, 0xD9EC, 0x51EC, 0x844E, 0x51ED, 0xC6BE, 0x51EE, 0x844F, 0x51EF, 0xBFAD, 0x51F0, 0xBBCB, 0x51F1, 0x8450, 0x51F2, 0x8451, + 0x51F3, 0xB5CA, 0x51F4, 0x8452, 0x51F5, 0xDBC9, 0x51F6, 0xD0D7, 0x51F7, 0x8453, 0x51F8, 0xCDB9, 0x51F9, 0xB0BC, 0x51FA, 0xB3F6, + 0x51FB, 0xBBF7, 0x51FC, 0xDBCA, 0x51FD, 0xBAAF, 0x51FE, 0x8454, 0x51FF, 0xD4E4, 0x5200, 0xB5B6, 0x5201, 0xB5F3, 0x5202, 0xD8D6, + 0x5203, 0xC8D0, 0x5204, 0x8455, 0x5205, 0x8456, 0x5206, 0xB7D6, 0x5207, 0xC7D0, 0x5208, 0xD8D7, 0x5209, 0x8457, 0x520A, 0xBFAF, + 0x520B, 0x8458, 0x520C, 0x8459, 0x520D, 0xDBBB, 0x520E, 0xD8D8, 0x520F, 0x845A, 0x5210, 0x845B, 0x5211, 0xD0CC, 0x5212, 0xBBAE, + 0x5213, 0x845C, 0x5214, 0x845D, 0x5215, 0x845E, 0x5216, 0xEBBE, 0x5217, 0xC1D0, 0x5218, 0xC1F5, 0x5219, 0xD4F2, 0x521A, 0xB8D5, + 0x521B, 0xB4B4, 0x521C, 0x845F, 0x521D, 0xB3F5, 0x521E, 0x8460, 0x521F, 0x8461, 0x5220, 0xC9BE, 0x5221, 0x8462, 0x5222, 0x8463, + 0x5223, 0x8464, 0x5224, 0xC5D0, 0x5225, 0x8465, 0x5226, 0x8466, 0x5227, 0x8467, 0x5228, 0xC5D9, 0x5229, 0xC0FB, 0x522A, 0x8468, + 0x522B, 0xB1F0, 0x522C, 0x8469, 0x522D, 0xD8D9, 0x522E, 0xB9CE, 0x522F, 0x846A, 0x5230, 0xB5BD, 0x5231, 0x846B, 0x5232, 0x846C, + 0x5233, 0xD8DA, 0x5234, 0x846D, 0x5235, 0x846E, 0x5236, 0xD6C6, 0x5237, 0xCBA2, 0x5238, 0xC8AF, 0x5239, 0xC9B2, 0x523A, 0xB4CC, + 0x523B, 0xBFCC, 0x523C, 0x846F, 0x523D, 0xB9F4, 0x523E, 0x8470, 0x523F, 0xD8DB, 0x5240, 0xD8DC, 0x5241, 0xB6E7, 0x5242, 0xBCC1, + 0x5243, 0xCCEA, 0x5244, 0x8471, 0x5245, 0x8472, 0x5246, 0x8473, 0x5247, 0x8474, 0x5248, 0x8475, 0x5249, 0x8476, 0x524A, 0xCFF7, + 0x524B, 0x8477, 0x524C, 0xD8DD, 0x524D, 0xC7B0, 0x524E, 0x8478, 0x524F, 0x8479, 0x5250, 0xB9D0, 0x5251, 0xBDA3, 0x5252, 0x847A, + 0x5253, 0x847B, 0x5254, 0xCCDE, 0x5255, 0x847C, 0x5256, 0xC6CA, 0x5257, 0x847D, 0x5258, 0x847E, 0x5259, 0x8480, 0x525A, 0x8481, + 0x525B, 0x8482, 0x525C, 0xD8E0, 0x525D, 0x8483, 0x525E, 0xD8DE, 0x525F, 0x8484, 0x5260, 0x8485, 0x5261, 0xD8DF, 0x5262, 0x8486, + 0x5263, 0x8487, 0x5264, 0x8488, 0x5265, 0xB0FE, 0x5266, 0x8489, 0x5267, 0xBEE7, 0x5268, 0x848A, 0x5269, 0xCAA3, 0x526A, 0xBCF4, + 0x526B, 0x848B, 0x526C, 0x848C, 0x526D, 0x848D, 0x526E, 0x848E, 0x526F, 0xB8B1, 0x5270, 0x848F, 0x5271, 0x8490, 0x5272, 0xB8EE, + 0x5273, 0x8491, 0x5274, 0x8492, 0x5275, 0x8493, 0x5276, 0x8494, 0x5277, 0x8495, 0x5278, 0x8496, 0x5279, 0x8497, 0x527A, 0x8498, + 0x527B, 0x8499, 0x527C, 0x849A, 0x527D, 0xD8E2, 0x527E, 0x849B, 0x527F, 0xBDCB, 0x5280, 0x849C, 0x5281, 0xD8E4, 0x5282, 0xD8E3, + 0x5283, 0x849D, 0x5284, 0x849E, 0x5285, 0x849F, 0x5286, 0x84A0, 0x5287, 0x84A1, 0x5288, 0xC5FC, 0x5289, 0x84A2, 0x528A, 0x84A3, + 0x528B, 0x84A4, 0x528C, 0x84A5, 0x528D, 0x84A6, 0x528E, 0x84A7, 0x528F, 0x84A8, 0x5290, 0xD8E5, 0x5291, 0x84A9, 0x5292, 0x84AA, + 0x5293, 0xD8E6, 0x5294, 0x84AB, 0x5295, 0x84AC, 0x5296, 0x84AD, 0x5297, 0x84AE, 0x5298, 0x84AF, 0x5299, 0x84B0, 0x529A, 0x84B1, + 0x529B, 0xC1A6, 0x529C, 0x84B2, 0x529D, 0xC8B0, 0x529E, 0xB0EC, 0x529F, 0xB9A6, 0x52A0, 0xBCD3, 0x52A1, 0xCEF1, 0x52A2, 0xDBBD, + 0x52A3, 0xC1D3, 0x52A4, 0x84B3, 0x52A5, 0x84B4, 0x52A6, 0x84B5, 0x52A7, 0x84B6, 0x52A8, 0xB6AF, 0x52A9, 0xD6FA, 0x52AA, 0xC5AC, + 0x52AB, 0xBDD9, 0x52AC, 0xDBBE, 0x52AD, 0xDBBF, 0x52AE, 0x84B7, 0x52AF, 0x84B8, 0x52B0, 0x84B9, 0x52B1, 0xC0F8, 0x52B2, 0xBEA2, + 0x52B3, 0xC0CD, 0x52B4, 0x84BA, 0x52B5, 0x84BB, 0x52B6, 0x84BC, 0x52B7, 0x84BD, 0x52B8, 0x84BE, 0x52B9, 0x84BF, 0x52BA, 0x84C0, + 0x52BB, 0x84C1, 0x52BC, 0x84C2, 0x52BD, 0x84C3, 0x52BE, 0xDBC0, 0x52BF, 0xCAC6, 0x52C0, 0x84C4, 0x52C1, 0x84C5, 0x52C2, 0x84C6, + 0x52C3, 0xB2AA, 0x52C4, 0x84C7, 0x52C5, 0x84C8, 0x52C6, 0x84C9, 0x52C7, 0xD3C2, 0x52C8, 0x84CA, 0x52C9, 0xC3E3, 0x52CA, 0x84CB, + 0x52CB, 0xD1AB, 0x52CC, 0x84CC, 0x52CD, 0x84CD, 0x52CE, 0x84CE, 0x52CF, 0x84CF, 0x52D0, 0xDBC2, 0x52D1, 0x84D0, 0x52D2, 0xC0D5, + 0x52D3, 0x84D1, 0x52D4, 0x84D2, 0x52D5, 0x84D3, 0x52D6, 0xDBC3, 0x52D7, 0x84D4, 0x52D8, 0xBFB1, 0x52D9, 0x84D5, 0x52DA, 0x84D6, + 0x52DB, 0x84D7, 0x52DC, 0x84D8, 0x52DD, 0x84D9, 0x52DE, 0x84DA, 0x52DF, 0xC4BC, 0x52E0, 0x84DB, 0x52E1, 0x84DC, 0x52E2, 0x84DD, + 0x52E3, 0x84DE, 0x52E4, 0xC7DA, 0x52E5, 0x84DF, 0x52E6, 0x84E0, 0x52E7, 0x84E1, 0x52E8, 0x84E2, 0x52E9, 0x84E3, 0x52EA, 0x84E4, + 0x52EB, 0x84E5, 0x52EC, 0x84E6, 0x52ED, 0x84E7, 0x52EE, 0x84E8, 0x52EF, 0x84E9, 0x52F0, 0xDBC4, 0x52F1, 0x84EA, 0x52F2, 0x84EB, + 0x52F3, 0x84EC, 0x52F4, 0x84ED, 0x52F5, 0x84EE, 0x52F6, 0x84EF, 0x52F7, 0x84F0, 0x52F8, 0x84F1, 0x52F9, 0xD9E8, 0x52FA, 0xC9D7, + 0x52FB, 0x84F2, 0x52FC, 0x84F3, 0x52FD, 0x84F4, 0x52FE, 0xB9B4, 0x52FF, 0xCEF0, 0x5300, 0xD4C8, 0x5301, 0x84F5, 0x5302, 0x84F6, + 0x5303, 0x84F7, 0x5304, 0x84F8, 0x5305, 0xB0FC, 0x5306, 0xB4D2, 0x5307, 0x84F9, 0x5308, 0xD0D9, 0x5309, 0x84FA, 0x530A, 0x84FB, + 0x530B, 0x84FC, 0x530C, 0x84FD, 0x530D, 0xD9E9, 0x530E, 0x84FE, 0x530F, 0xDECB, 0x5310, 0xD9EB, 0x5311, 0x8540, 0x5312, 0x8541, + 0x5313, 0x8542, 0x5314, 0x8543, 0x5315, 0xD8B0, 0x5316, 0xBBAF, 0x5317, 0xB1B1, 0x5318, 0x8544, 0x5319, 0xB3D7, 0x531A, 0xD8CE, + 0x531B, 0x8545, 0x531C, 0x8546, 0x531D, 0xD4D1, 0x531E, 0x8547, 0x531F, 0x8548, 0x5320, 0xBDB3, 0x5321, 0xBFEF, 0x5322, 0x8549, + 0x5323, 0xCFBB, 0x5324, 0x854A, 0x5325, 0x854B, 0x5326, 0xD8D0, 0x5327, 0x854C, 0x5328, 0x854D, 0x5329, 0x854E, 0x532A, 0xB7CB, + 0x532B, 0x854F, 0x532C, 0x8550, 0x532D, 0x8551, 0x532E, 0xD8D1, 0x532F, 0x8552, 0x5330, 0x8553, 0x5331, 0x8554, 0x5332, 0x8555, + 0x5333, 0x8556, 0x5334, 0x8557, 0x5335, 0x8558, 0x5336, 0x8559, 0x5337, 0x855A, 0x5338, 0x855B, 0x5339, 0xC6A5, 0x533A, 0xC7F8, + 0x533B, 0xD2BD, 0x533C, 0x855C, 0x533D, 0x855D, 0x533E, 0xD8D2, 0x533F, 0xC4E4, 0x5340, 0x855E, 0x5341, 0xCAAE, 0x5342, 0x855F, + 0x5343, 0xC7A7, 0x5344, 0x8560, 0x5345, 0xD8A6, 0x5346, 0x8561, 0x5347, 0xC9FD, 0x5348, 0xCEE7, 0x5349, 0xBBDC, 0x534A, 0xB0EB, + 0x534B, 0x8562, 0x534C, 0x8563, 0x534D, 0x8564, 0x534E, 0xBBAA, 0x534F, 0xD0AD, 0x5350, 0x8565, 0x5351, 0xB1B0, 0x5352, 0xD7E4, + 0x5353, 0xD7BF, 0x5354, 0x8566, 0x5355, 0xB5A5, 0x5356, 0xC2F4, 0x5357, 0xC4CF, 0x5358, 0x8567, 0x5359, 0x8568, 0x535A, 0xB2A9, + 0x535B, 0x8569, 0x535C, 0xB2B7, 0x535D, 0x856A, 0x535E, 0xB1E5, 0x535F, 0xDFB2, 0x5360, 0xD5BC, 0x5361, 0xBFA8, 0x5362, 0xC2AC, + 0x5363, 0xD8D5, 0x5364, 0xC2B1, 0x5365, 0x856B, 0x5366, 0xD8D4, 0x5367, 0xCED4, 0x5368, 0x856C, 0x5369, 0xDAE0, 0x536A, 0x856D, + 0x536B, 0xCEC0, 0x536C, 0x856E, 0x536D, 0x856F, 0x536E, 0xD8B4, 0x536F, 0xC3AE, 0x5370, 0xD3A1, 0x5371, 0xCEA3, 0x5372, 0x8570, + 0x5373, 0xBCB4, 0x5374, 0xC8B4, 0x5375, 0xC2D1, 0x5376, 0x8571, 0x5377, 0xBEED, 0x5378, 0xD0B6, 0x5379, 0x8572, 0x537A, 0xDAE1, + 0x537B, 0x8573, 0x537C, 0x8574, 0x537D, 0x8575, 0x537E, 0x8576, 0x537F, 0xC7E4, 0x5380, 0x8577, 0x5381, 0x8578, 0x5382, 0xB3A7, + 0x5383, 0x8579, 0x5384, 0xB6F2, 0x5385, 0xCCFC, 0x5386, 0xC0FA, 0x5387, 0x857A, 0x5388, 0x857B, 0x5389, 0xC0F7, 0x538A, 0x857C, + 0x538B, 0xD1B9, 0x538C, 0xD1E1, 0x538D, 0xD8C7, 0x538E, 0x857D, 0x538F, 0x857E, 0x5390, 0x8580, 0x5391, 0x8581, 0x5392, 0x8582, + 0x5393, 0x8583, 0x5394, 0x8584, 0x5395, 0xB2DE, 0x5396, 0x8585, 0x5397, 0x8586, 0x5398, 0xC0E5, 0x5399, 0x8587, 0x539A, 0xBAF1, + 0x539B, 0x8588, 0x539C, 0x8589, 0x539D, 0xD8C8, 0x539E, 0x858A, 0x539F, 0xD4AD, 0x53A0, 0x858B, 0x53A1, 0x858C, 0x53A2, 0xCFE1, + 0x53A3, 0xD8C9, 0x53A4, 0x858D, 0x53A5, 0xD8CA, 0x53A6, 0xCFC3, 0x53A7, 0x858E, 0x53A8, 0xB3F8, 0x53A9, 0xBEC7, 0x53AA, 0x858F, + 0x53AB, 0x8590, 0x53AC, 0x8591, 0x53AD, 0x8592, 0x53AE, 0xD8CB, 0x53AF, 0x8593, 0x53B0, 0x8594, 0x53B1, 0x8595, 0x53B2, 0x8596, + 0x53B3, 0x8597, 0x53B4, 0x8598, 0x53B5, 0x8599, 0x53B6, 0xDBCC, 0x53B7, 0x859A, 0x53B8, 0x859B, 0x53B9, 0x859C, 0x53BA, 0x859D, + 0x53BB, 0xC8A5, 0x53BC, 0x859E, 0x53BD, 0x859F, 0x53BE, 0x85A0, 0x53BF, 0xCFD8, 0x53C0, 0x85A1, 0x53C1, 0xC8FE, 0x53C2, 0xB2CE, + 0x53C3, 0x85A2, 0x53C4, 0x85A3, 0x53C5, 0x85A4, 0x53C6, 0x85A5, 0x53C7, 0x85A6, 0x53C8, 0xD3D6, 0x53C9, 0xB2E6, 0x53CA, 0xBCB0, + 0x53CB, 0xD3D1, 0x53CC, 0xCBAB, 0x53CD, 0xB7B4, 0x53CE, 0x85A7, 0x53CF, 0x85A8, 0x53D0, 0x85A9, 0x53D1, 0xB7A2, 0x53D2, 0x85AA, + 0x53D3, 0x85AB, 0x53D4, 0xCAE5, 0x53D5, 0x85AC, 0x53D6, 0xC8A1, 0x53D7, 0xCADC, 0x53D8, 0xB1E4, 0x53D9, 0xD0F0, 0x53DA, 0x85AD, + 0x53DB, 0xC5D1, 0x53DC, 0x85AE, 0x53DD, 0x85AF, 0x53DE, 0x85B0, 0x53DF, 0xDBC5, 0x53E0, 0xB5FE, 0x53E1, 0x85B1, 0x53E2, 0x85B2, + 0x53E3, 0xBFDA, 0x53E4, 0xB9C5, 0x53E5, 0xBEE4, 0x53E6, 0xC1ED, 0x53E7, 0x85B3, 0x53E8, 0xDFB6, 0x53E9, 0xDFB5, 0x53EA, 0xD6BB, + 0x53EB, 0xBDD0, 0x53EC, 0xD5D9, 0x53ED, 0xB0C8, 0x53EE, 0xB6A3, 0x53EF, 0xBFC9, 0x53F0, 0xCCA8, 0x53F1, 0xDFB3, 0x53F2, 0xCAB7, + 0x53F3, 0xD3D2, 0x53F4, 0x85B4, 0x53F5, 0xD8CF, 0x53F6, 0xD2B6, 0x53F7, 0xBAC5, 0x53F8, 0xCBBE, 0x53F9, 0xCCBE, 0x53FA, 0x85B5, + 0x53FB, 0xDFB7, 0x53FC, 0xB5F0, 0x53FD, 0xDFB4, 0x53FE, 0x85B6, 0x53FF, 0x85B7, 0x5400, 0x85B8, 0x5401, 0xD3F5, 0x5402, 0x85B9, + 0x5403, 0xB3D4, 0x5404, 0xB8F7, 0x5405, 0x85BA, 0x5406, 0xDFBA, 0x5407, 0x85BB, 0x5408, 0xBACF, 0x5409, 0xBCAA, 0x540A, 0xB5F5, + 0x540B, 0x85BC, 0x540C, 0xCDAC, 0x540D, 0xC3FB, 0x540E, 0xBAF3, 0x540F, 0xC0F4, 0x5410, 0xCDC2, 0x5411, 0xCFF2, 0x5412, 0xDFB8, + 0x5413, 0xCFC5, 0x5414, 0x85BD, 0x5415, 0xC2C0, 0x5416, 0xDFB9, 0x5417, 0xC2F0, 0x5418, 0x85BE, 0x5419, 0x85BF, 0x541A, 0x85C0, + 0x541B, 0xBEFD, 0x541C, 0x85C1, 0x541D, 0xC1DF, 0x541E, 0xCDCC, 0x541F, 0xD2F7, 0x5420, 0xB7CD, 0x5421, 0xDFC1, 0x5422, 0x85C2, + 0x5423, 0xDFC4, 0x5424, 0x85C3, 0x5425, 0x85C4, 0x5426, 0xB7F1, 0x5427, 0xB0C9, 0x5428, 0xB6D6, 0x5429, 0xB7D4, 0x542A, 0x85C5, + 0x542B, 0xBAAC, 0x542C, 0xCCFD, 0x542D, 0xBFD4, 0x542E, 0xCBB1, 0x542F, 0xC6F4, 0x5430, 0x85C6, 0x5431, 0xD6A8, 0x5432, 0xDFC5, + 0x5433, 0x85C7, 0x5434, 0xCEE2, 0x5435, 0xB3B3, 0x5436, 0x85C8, 0x5437, 0x85C9, 0x5438, 0xCEFC, 0x5439, 0xB4B5, 0x543A, 0x85CA, + 0x543B, 0xCEC7, 0x543C, 0xBAF0, 0x543D, 0x85CB, 0x543E, 0xCEE1, 0x543F, 0x85CC, 0x5440, 0xD1BD, 0x5441, 0x85CD, 0x5442, 0x85CE, + 0x5443, 0xDFC0, 0x5444, 0x85CF, 0x5445, 0x85D0, 0x5446, 0xB4F4, 0x5447, 0x85D1, 0x5448, 0xB3CA, 0x5449, 0x85D2, 0x544A, 0xB8E6, + 0x544B, 0xDFBB, 0x544C, 0x85D3, 0x544D, 0x85D4, 0x544E, 0x85D5, 0x544F, 0x85D6, 0x5450, 0xC4C5, 0x5451, 0x85D7, 0x5452, 0xDFBC, + 0x5453, 0xDFBD, 0x5454, 0xDFBE, 0x5455, 0xC5BB, 0x5456, 0xDFBF, 0x5457, 0xDFC2, 0x5458, 0xD4B1, 0x5459, 0xDFC3, 0x545A, 0x85D8, + 0x545B, 0xC7BA, 0x545C, 0xCED8, 0x545D, 0x85D9, 0x545E, 0x85DA, 0x545F, 0x85DB, 0x5460, 0x85DC, 0x5461, 0x85DD, 0x5462, 0xC4D8, + 0x5463, 0x85DE, 0x5464, 0xDFCA, 0x5465, 0x85DF, 0x5466, 0xDFCF, 0x5467, 0x85E0, 0x5468, 0xD6DC, 0x5469, 0x85E1, 0x546A, 0x85E2, + 0x546B, 0x85E3, 0x546C, 0x85E4, 0x546D, 0x85E5, 0x546E, 0x85E6, 0x546F, 0x85E7, 0x5470, 0x85E8, 0x5471, 0xDFC9, 0x5472, 0xDFDA, + 0x5473, 0xCEB6, 0x5474, 0x85E9, 0x5475, 0xBAC7, 0x5476, 0xDFCE, 0x5477, 0xDFC8, 0x5478, 0xC5DE, 0x5479, 0x85EA, 0x547A, 0x85EB, + 0x547B, 0xC9EB, 0x547C, 0xBAF4, 0x547D, 0xC3FC, 0x547E, 0x85EC, 0x547F, 0x85ED, 0x5480, 0xBED7, 0x5481, 0x85EE, 0x5482, 0xDFC6, + 0x5483, 0x85EF, 0x5484, 0xDFCD, 0x5485, 0x85F0, 0x5486, 0xC5D8, 0x5487, 0x85F1, 0x5488, 0x85F2, 0x5489, 0x85F3, 0x548A, 0x85F4, + 0x548B, 0xD5A6, 0x548C, 0xBACD, 0x548D, 0x85F5, 0x548E, 0xBECC, 0x548F, 0xD3BD, 0x5490, 0xB8C0, 0x5491, 0x85F6, 0x5492, 0xD6E4, + 0x5493, 0x85F7, 0x5494, 0xDFC7, 0x5495, 0xB9BE, 0x5496, 0xBFA7, 0x5497, 0x85F8, 0x5498, 0x85F9, 0x5499, 0xC1FC, 0x549A, 0xDFCB, + 0x549B, 0xDFCC, 0x549C, 0x85FA, 0x549D, 0xDFD0, 0x549E, 0x85FB, 0x549F, 0x85FC, 0x54A0, 0x85FD, 0x54A1, 0x85FE, 0x54A2, 0x8640, + 0x54A3, 0xDFDB, 0x54A4, 0xDFE5, 0x54A5, 0x8641, 0x54A6, 0xDFD7, 0x54A7, 0xDFD6, 0x54A8, 0xD7C9, 0x54A9, 0xDFE3, 0x54AA, 0xDFE4, + 0x54AB, 0xE5EB, 0x54AC, 0xD2A7, 0x54AD, 0xDFD2, 0x54AE, 0x8642, 0x54AF, 0xBFA9, 0x54B0, 0x8643, 0x54B1, 0xD4DB, 0x54B2, 0x8644, + 0x54B3, 0xBFC8, 0x54B4, 0xDFD4, 0x54B5, 0x8645, 0x54B6, 0x8646, 0x54B7, 0x8647, 0x54B8, 0xCFCC, 0x54B9, 0x8648, 0x54BA, 0x8649, + 0x54BB, 0xDFDD, 0x54BC, 0x864A, 0x54BD, 0xD1CA, 0x54BE, 0x864B, 0x54BF, 0xDFDE, 0x54C0, 0xB0A7, 0x54C1, 0xC6B7, 0x54C2, 0xDFD3, + 0x54C3, 0x864C, 0x54C4, 0xBAE5, 0x54C5, 0x864D, 0x54C6, 0xB6DF, 0x54C7, 0xCDDB, 0x54C8, 0xB9FE, 0x54C9, 0xD4D5, 0x54CA, 0x864E, + 0x54CB, 0x864F, 0x54CC, 0xDFDF, 0x54CD, 0xCFEC, 0x54CE, 0xB0A5, 0x54CF, 0xDFE7, 0x54D0, 0xDFD1, 0x54D1, 0xD1C6, 0x54D2, 0xDFD5, + 0x54D3, 0xDFD8, 0x54D4, 0xDFD9, 0x54D5, 0xDFDC, 0x54D6, 0x8650, 0x54D7, 0xBBA9, 0x54D8, 0x8651, 0x54D9, 0xDFE0, 0x54DA, 0xDFE1, + 0x54DB, 0x8652, 0x54DC, 0xDFE2, 0x54DD, 0xDFE6, 0x54DE, 0xDFE8, 0x54DF, 0xD3B4, 0x54E0, 0x8653, 0x54E1, 0x8654, 0x54E2, 0x8655, + 0x54E3, 0x8656, 0x54E4, 0x8657, 0x54E5, 0xB8E7, 0x54E6, 0xC5B6, 0x54E7, 0xDFEA, 0x54E8, 0xC9DA, 0x54E9, 0xC1A8, 0x54EA, 0xC4C4, + 0x54EB, 0x8658, 0x54EC, 0x8659, 0x54ED, 0xBFDE, 0x54EE, 0xCFF8, 0x54EF, 0x865A, 0x54F0, 0x865B, 0x54F1, 0x865C, 0x54F2, 0xD5DC, + 0x54F3, 0xDFEE, 0x54F4, 0x865D, 0x54F5, 0x865E, 0x54F6, 0x865F, 0x54F7, 0x8660, 0x54F8, 0x8661, 0x54F9, 0x8662, 0x54FA, 0xB2B8, + 0x54FB, 0x8663, 0x54FC, 0xBADF, 0x54FD, 0xDFEC, 0x54FE, 0x8664, 0x54FF, 0xDBC1, 0x5500, 0x8665, 0x5501, 0xD1E4, 0x5502, 0x8666, + 0x5503, 0x8667, 0x5504, 0x8668, 0x5505, 0x8669, 0x5506, 0xCBF4, 0x5507, 0xB4BD, 0x5508, 0x866A, 0x5509, 0xB0A6, 0x550A, 0x866B, + 0x550B, 0x866C, 0x550C, 0x866D, 0x550D, 0x866E, 0x550E, 0x866F, 0x550F, 0xDFF1, 0x5510, 0xCCC6, 0x5511, 0xDFF2, 0x5512, 0x8670, + 0x5513, 0x8671, 0x5514, 0xDFED, 0x5515, 0x8672, 0x5516, 0x8673, 0x5517, 0x8674, 0x5518, 0x8675, 0x5519, 0x8676, 0x551A, 0x8677, + 0x551B, 0xDFE9, 0x551C, 0x8678, 0x551D, 0x8679, 0x551E, 0x867A, 0x551F, 0x867B, 0x5520, 0xDFEB, 0x5521, 0x867C, 0x5522, 0xDFEF, + 0x5523, 0xDFF0, 0x5524, 0xBBBD, 0x5525, 0x867D, 0x5526, 0x867E, 0x5527, 0xDFF3, 0x5528, 0x8680, 0x5529, 0x8681, 0x552A, 0xDFF4, + 0x552B, 0x8682, 0x552C, 0xBBA3, 0x552D, 0x8683, 0x552E, 0xCADB, 0x552F, 0xCEA8, 0x5530, 0xE0A7, 0x5531, 0xB3AA, 0x5532, 0x8684, + 0x5533, 0xE0A6, 0x5534, 0x8685, 0x5535, 0x8686, 0x5536, 0x8687, 0x5537, 0xE0A1, 0x5538, 0x8688, 0x5539, 0x8689, 0x553A, 0x868A, + 0x553B, 0x868B, 0x553C, 0xDFFE, 0x553D, 0x868C, 0x553E, 0xCDD9, 0x553F, 0xDFFC, 0x5540, 0x868D, 0x5541, 0xDFFA, 0x5542, 0x868E, + 0x5543, 0xBFD0, 0x5544, 0xD7C4, 0x5545, 0x868F, 0x5546, 0xC9CC, 0x5547, 0x8690, 0x5548, 0x8691, 0x5549, 0xDFF8, 0x554A, 0xB0A1, + 0x554B, 0x8692, 0x554C, 0x8693, 0x554D, 0x8694, 0x554E, 0x8695, 0x554F, 0x8696, 0x5550, 0xDFFD, 0x5551, 0x8697, 0x5552, 0x8698, + 0x5553, 0x8699, 0x5554, 0x869A, 0x5555, 0xDFFB, 0x5556, 0xE0A2, 0x5557, 0x869B, 0x5558, 0x869C, 0x5559, 0x869D, 0x555A, 0x869E, + 0x555B, 0x869F, 0x555C, 0xE0A8, 0x555D, 0x86A0, 0x555E, 0x86A1, 0x555F, 0x86A2, 0x5560, 0x86A3, 0x5561, 0xB7C8, 0x5562, 0x86A4, + 0x5563, 0x86A5, 0x5564, 0xC6A1, 0x5565, 0xC9B6, 0x5566, 0xC0B2, 0x5567, 0xDFF5, 0x5568, 0x86A6, 0x5569, 0x86A7, 0x556A, 0xC5BE, + 0x556B, 0x86A8, 0x556C, 0xD8C4, 0x556D, 0xDFF9, 0x556E, 0xC4F6, 0x556F, 0x86A9, 0x5570, 0x86AA, 0x5571, 0x86AB, 0x5572, 0x86AC, + 0x5573, 0x86AD, 0x5574, 0x86AE, 0x5575, 0xE0A3, 0x5576, 0xE0A4, 0x5577, 0xE0A5, 0x5578, 0xD0A5, 0x5579, 0x86AF, 0x557A, 0x86B0, + 0x557B, 0xE0B4, 0x557C, 0xCCE4, 0x557D, 0x86B1, 0x557E, 0xE0B1, 0x557F, 0x86B2, 0x5580, 0xBFA6, 0x5581, 0xE0AF, 0x5582, 0xCEB9, + 0x5583, 0xE0AB, 0x5584, 0xC9C6, 0x5585, 0x86B3, 0x5586, 0x86B4, 0x5587, 0xC0AE, 0x5588, 0xE0AE, 0x5589, 0xBAED, 0x558A, 0xBAB0, + 0x558B, 0xE0A9, 0x558C, 0x86B5, 0x558D, 0x86B6, 0x558E, 0x86B7, 0x558F, 0xDFF6, 0x5590, 0x86B8, 0x5591, 0xE0B3, 0x5592, 0x86B9, + 0x5593, 0x86BA, 0x5594, 0xE0B8, 0x5595, 0x86BB, 0x5596, 0x86BC, 0x5597, 0x86BD, 0x5598, 0xB4AD, 0x5599, 0xE0B9, 0x559A, 0x86BE, + 0x559B, 0x86BF, 0x559C, 0xCFB2, 0x559D, 0xBAC8, 0x559E, 0x86C0, 0x559F, 0xE0B0, 0x55A0, 0x86C1, 0x55A1, 0x86C2, 0x55A2, 0x86C3, + 0x55A3, 0x86C4, 0x55A4, 0x86C5, 0x55A5, 0x86C6, 0x55A6, 0x86C7, 0x55A7, 0xD0FA, 0x55A8, 0x86C8, 0x55A9, 0x86C9, 0x55AA, 0x86CA, + 0x55AB, 0x86CB, 0x55AC, 0x86CC, 0x55AD, 0x86CD, 0x55AE, 0x86CE, 0x55AF, 0x86CF, 0x55B0, 0x86D0, 0x55B1, 0xE0AC, 0x55B2, 0x86D1, + 0x55B3, 0xD4FB, 0x55B4, 0x86D2, 0x55B5, 0xDFF7, 0x55B6, 0x86D3, 0x55B7, 0xC5E7, 0x55B8, 0x86D4, 0x55B9, 0xE0AD, 0x55BA, 0x86D5, + 0x55BB, 0xD3F7, 0x55BC, 0x86D6, 0x55BD, 0xE0B6, 0x55BE, 0xE0B7, 0x55BF, 0x86D7, 0x55C0, 0x86D8, 0x55C1, 0x86D9, 0x55C2, 0x86DA, + 0x55C3, 0x86DB, 0x55C4, 0xE0C4, 0x55C5, 0xD0E1, 0x55C6, 0x86DC, 0x55C7, 0x86DD, 0x55C8, 0x86DE, 0x55C9, 0xE0BC, 0x55CA, 0x86DF, + 0x55CB, 0x86E0, 0x55CC, 0xE0C9, 0x55CD, 0xE0CA, 0x55CE, 0x86E1, 0x55CF, 0x86E2, 0x55D0, 0x86E3, 0x55D1, 0xE0BE, 0x55D2, 0xE0AA, + 0x55D3, 0xC9A4, 0x55D4, 0xE0C1, 0x55D5, 0x86E4, 0x55D6, 0xE0B2, 0x55D7, 0x86E5, 0x55D8, 0x86E6, 0x55D9, 0x86E7, 0x55DA, 0x86E8, + 0x55DB, 0x86E9, 0x55DC, 0xCAC8, 0x55DD, 0xE0C3, 0x55DE, 0x86EA, 0x55DF, 0xE0B5, 0x55E0, 0x86EB, 0x55E1, 0xCECB, 0x55E2, 0x86EC, + 0x55E3, 0xCBC3, 0x55E4, 0xE0CD, 0x55E5, 0xE0C6, 0x55E6, 0xE0C2, 0x55E7, 0x86ED, 0x55E8, 0xE0CB, 0x55E9, 0x86EE, 0x55EA, 0xE0BA, + 0x55EB, 0xE0BF, 0x55EC, 0xE0C0, 0x55ED, 0x86EF, 0x55EE, 0x86F0, 0x55EF, 0xE0C5, 0x55F0, 0x86F1, 0x55F1, 0x86F2, 0x55F2, 0xE0C7, + 0x55F3, 0xE0C8, 0x55F4, 0x86F3, 0x55F5, 0xE0CC, 0x55F6, 0x86F4, 0x55F7, 0xE0BB, 0x55F8, 0x86F5, 0x55F9, 0x86F6, 0x55FA, 0x86F7, + 0x55FB, 0x86F8, 0x55FC, 0x86F9, 0x55FD, 0xCBD4, 0x55FE, 0xE0D5, 0x55FF, 0x86FA, 0x5600, 0xE0D6, 0x5601, 0xE0D2, 0x5602, 0x86FB, + 0x5603, 0x86FC, 0x5604, 0x86FD, 0x5605, 0x86FE, 0x5606, 0x8740, 0x5607, 0x8741, 0x5608, 0xE0D0, 0x5609, 0xBCCE, 0x560A, 0x8742, + 0x560B, 0x8743, 0x560C, 0xE0D1, 0x560D, 0x8744, 0x560E, 0xB8C2, 0x560F, 0xD8C5, 0x5610, 0x8745, 0x5611, 0x8746, 0x5612, 0x8747, + 0x5613, 0x8748, 0x5614, 0x8749, 0x5615, 0x874A, 0x5616, 0x874B, 0x5617, 0x874C, 0x5618, 0xD0EA, 0x5619, 0x874D, 0x561A, 0x874E, + 0x561B, 0xC2EF, 0x561C, 0x874F, 0x561D, 0x8750, 0x561E, 0xE0CF, 0x561F, 0xE0BD, 0x5620, 0x8751, 0x5621, 0x8752, 0x5622, 0x8753, + 0x5623, 0xE0D4, 0x5624, 0xE0D3, 0x5625, 0x8754, 0x5626, 0x8755, 0x5627, 0xE0D7, 0x5628, 0x8756, 0x5629, 0x8757, 0x562A, 0x8758, + 0x562B, 0x8759, 0x562C, 0xE0DC, 0x562D, 0xE0D8, 0x562E, 0x875A, 0x562F, 0x875B, 0x5630, 0x875C, 0x5631, 0xD6F6, 0x5632, 0xB3B0, + 0x5633, 0x875D, 0x5634, 0xD7EC, 0x5635, 0x875E, 0x5636, 0xCBBB, 0x5637, 0x875F, 0x5638, 0x8760, 0x5639, 0xE0DA, 0x563A, 0x8761, + 0x563B, 0xCEFB, 0x563C, 0x8762, 0x563D, 0x8763, 0x563E, 0x8764, 0x563F, 0xBAD9, 0x5640, 0x8765, 0x5641, 0x8766, 0x5642, 0x8767, + 0x5643, 0x8768, 0x5644, 0x8769, 0x5645, 0x876A, 0x5646, 0x876B, 0x5647, 0x876C, 0x5648, 0x876D, 0x5649, 0x876E, 0x564A, 0x876F, + 0x564B, 0x8770, 0x564C, 0xE0E1, 0x564D, 0xE0DD, 0x564E, 0xD2AD, 0x564F, 0x8771, 0x5650, 0x8772, 0x5651, 0x8773, 0x5652, 0x8774, + 0x5653, 0x8775, 0x5654, 0xE0E2, 0x5655, 0x8776, 0x5656, 0x8777, 0x5657, 0xE0DB, 0x5658, 0xE0D9, 0x5659, 0xE0DF, 0x565A, 0x8778, + 0x565B, 0x8779, 0x565C, 0xE0E0, 0x565D, 0x877A, 0x565E, 0x877B, 0x565F, 0x877C, 0x5660, 0x877D, 0x5661, 0x877E, 0x5662, 0xE0DE, + 0x5663, 0x8780, 0x5664, 0xE0E4, 0x5665, 0x8781, 0x5666, 0x8782, 0x5667, 0x8783, 0x5668, 0xC6F7, 0x5669, 0xD8AC, 0x566A, 0xD4EB, + 0x566B, 0xE0E6, 0x566C, 0xCAC9, 0x566D, 0x8784, 0x566E, 0x8785, 0x566F, 0x8786, 0x5670, 0x8787, 0x5671, 0xE0E5, 0x5672, 0x8788, + 0x5673, 0x8789, 0x5674, 0x878A, 0x5675, 0x878B, 0x5676, 0xB8C1, 0x5677, 0x878C, 0x5678, 0x878D, 0x5679, 0x878E, 0x567A, 0x878F, + 0x567B, 0xE0E7, 0x567C, 0xE0E8, 0x567D, 0x8790, 0x567E, 0x8791, 0x567F, 0x8792, 0x5680, 0x8793, 0x5681, 0x8794, 0x5682, 0x8795, + 0x5683, 0x8796, 0x5684, 0x8797, 0x5685, 0xE0E9, 0x5686, 0xE0E3, 0x5687, 0x8798, 0x5688, 0x8799, 0x5689, 0x879A, 0x568A, 0x879B, + 0x568B, 0x879C, 0x568C, 0x879D, 0x568D, 0x879E, 0x568E, 0xBABF, 0x568F, 0xCCE7, 0x5690, 0x879F, 0x5691, 0x87A0, 0x5692, 0x87A1, + 0x5693, 0xE0EA, 0x5694, 0x87A2, 0x5695, 0x87A3, 0x5696, 0x87A4, 0x5697, 0x87A5, 0x5698, 0x87A6, 0x5699, 0x87A7, 0x569A, 0x87A8, + 0x569B, 0x87A9, 0x569C, 0x87AA, 0x569D, 0x87AB, 0x569E, 0x87AC, 0x569F, 0x87AD, 0x56A0, 0x87AE, 0x56A1, 0x87AF, 0x56A2, 0x87B0, + 0x56A3, 0xCFF9, 0x56A4, 0x87B1, 0x56A5, 0x87B2, 0x56A6, 0x87B3, 0x56A7, 0x87B4, 0x56A8, 0x87B5, 0x56A9, 0x87B6, 0x56AA, 0x87B7, + 0x56AB, 0x87B8, 0x56AC, 0x87B9, 0x56AD, 0x87BA, 0x56AE, 0x87BB, 0x56AF, 0xE0EB, 0x56B0, 0x87BC, 0x56B1, 0x87BD, 0x56B2, 0x87BE, + 0x56B3, 0x87BF, 0x56B4, 0x87C0, 0x56B5, 0x87C1, 0x56B6, 0x87C2, 0x56B7, 0xC8C2, 0x56B8, 0x87C3, 0x56B9, 0x87C4, 0x56BA, 0x87C5, + 0x56BB, 0x87C6, 0x56BC, 0xBDC0, 0x56BD, 0x87C7, 0x56BE, 0x87C8, 0x56BF, 0x87C9, 0x56C0, 0x87CA, 0x56C1, 0x87CB, 0x56C2, 0x87CC, + 0x56C3, 0x87CD, 0x56C4, 0x87CE, 0x56C5, 0x87CF, 0x56C6, 0x87D0, 0x56C7, 0x87D1, 0x56C8, 0x87D2, 0x56C9, 0x87D3, 0x56CA, 0xC4D2, + 0x56CB, 0x87D4, 0x56CC, 0x87D5, 0x56CD, 0x87D6, 0x56CE, 0x87D7, 0x56CF, 0x87D8, 0x56D0, 0x87D9, 0x56D1, 0x87DA, 0x56D2, 0x87DB, + 0x56D3, 0x87DC, 0x56D4, 0xE0EC, 0x56D5, 0x87DD, 0x56D6, 0x87DE, 0x56D7, 0xE0ED, 0x56D8, 0x87DF, 0x56D9, 0x87E0, 0x56DA, 0xC7F4, + 0x56DB, 0xCBC4, 0x56DC, 0x87E1, 0x56DD, 0xE0EE, 0x56DE, 0xBBD8, 0x56DF, 0xD8B6, 0x56E0, 0xD2F2, 0x56E1, 0xE0EF, 0x56E2, 0xCDC5, + 0x56E3, 0x87E2, 0x56E4, 0xB6DA, 0x56E5, 0x87E3, 0x56E6, 0x87E4, 0x56E7, 0x87E5, 0x56E8, 0x87E6, 0x56E9, 0x87E7, 0x56EA, 0x87E8, + 0x56EB, 0xE0F1, 0x56EC, 0x87E9, 0x56ED, 0xD4B0, 0x56EE, 0x87EA, 0x56EF, 0x87EB, 0x56F0, 0xC0A7, 0x56F1, 0xB4D1, 0x56F2, 0x87EC, + 0x56F3, 0x87ED, 0x56F4, 0xCEA7, 0x56F5, 0xE0F0, 0x56F6, 0x87EE, 0x56F7, 0x87EF, 0x56F8, 0x87F0, 0x56F9, 0xE0F2, 0x56FA, 0xB9CC, + 0x56FB, 0x87F1, 0x56FC, 0x87F2, 0x56FD, 0xB9FA, 0x56FE, 0xCDBC, 0x56FF, 0xE0F3, 0x5700, 0x87F3, 0x5701, 0x87F4, 0x5702, 0x87F5, + 0x5703, 0xC6D4, 0x5704, 0xE0F4, 0x5705, 0x87F6, 0x5706, 0xD4B2, 0x5707, 0x87F7, 0x5708, 0xC8A6, 0x5709, 0xE0F6, 0x570A, 0xE0F5, + 0x570B, 0x87F8, 0x570C, 0x87F9, 0x570D, 0x87FA, 0x570E, 0x87FB, 0x570F, 0x87FC, 0x5710, 0x87FD, 0x5711, 0x87FE, 0x5712, 0x8840, + 0x5713, 0x8841, 0x5714, 0x8842, 0x5715, 0x8843, 0x5716, 0x8844, 0x5717, 0x8845, 0x5718, 0x8846, 0x5719, 0x8847, 0x571A, 0x8848, + 0x571B, 0x8849, 0x571C, 0xE0F7, 0x571D, 0x884A, 0x571E, 0x884B, 0x571F, 0xCDC1, 0x5720, 0x884C, 0x5721, 0x884D, 0x5722, 0x884E, + 0x5723, 0xCAA5, 0x5724, 0x884F, 0x5725, 0x8850, 0x5726, 0x8851, 0x5727, 0x8852, 0x5728, 0xD4DA, 0x5729, 0xDBD7, 0x572A, 0xDBD9, + 0x572B, 0x8853, 0x572C, 0xDBD8, 0x572D, 0xB9E7, 0x572E, 0xDBDC, 0x572F, 0xDBDD, 0x5730, 0xB5D8, 0x5731, 0x8854, 0x5732, 0x8855, + 0x5733, 0xDBDA, 0x5734, 0x8856, 0x5735, 0x8857, 0x5736, 0x8858, 0x5737, 0x8859, 0x5738, 0x885A, 0x5739, 0xDBDB, 0x573A, 0xB3A1, + 0x573B, 0xDBDF, 0x573C, 0x885B, 0x573D, 0x885C, 0x573E, 0xBBF8, 0x573F, 0x885D, 0x5740, 0xD6B7, 0x5741, 0x885E, 0x5742, 0xDBE0, + 0x5743, 0x885F, 0x5744, 0x8860, 0x5745, 0x8861, 0x5746, 0x8862, 0x5747, 0xBEF9, 0x5748, 0x8863, 0x5749, 0x8864, 0x574A, 0xB7BB, + 0x574B, 0x8865, 0x574C, 0xDBD0, 0x574D, 0xCCAE, 0x574E, 0xBFB2, 0x574F, 0xBBB5, 0x5750, 0xD7F8, 0x5751, 0xBFD3, 0x5752, 0x8866, + 0x5753, 0x8867, 0x5754, 0x8868, 0x5755, 0x8869, 0x5756, 0x886A, 0x5757, 0xBFE9, 0x5758, 0x886B, 0x5759, 0x886C, 0x575A, 0xBCE1, + 0x575B, 0xCCB3, 0x575C, 0xDBDE, 0x575D, 0xB0D3, 0x575E, 0xCEEB, 0x575F, 0xB7D8, 0x5760, 0xD7B9, 0x5761, 0xC6C2, 0x5762, 0x886D, + 0x5763, 0x886E, 0x5764, 0xC0A4, 0x5765, 0x886F, 0x5766, 0xCCB9, 0x5767, 0x8870, 0x5768, 0xDBE7, 0x5769, 0xDBE1, 0x576A, 0xC6BA, + 0x576B, 0xDBE3, 0x576C, 0x8871, 0x576D, 0xDBE8, 0x576E, 0x8872, 0x576F, 0xC5F7, 0x5770, 0x8873, 0x5771, 0x8874, 0x5772, 0x8875, + 0x5773, 0xDBEA, 0x5774, 0x8876, 0x5775, 0x8877, 0x5776, 0xDBE9, 0x5777, 0xBFC0, 0x5778, 0x8878, 0x5779, 0x8879, 0x577A, 0x887A, + 0x577B, 0xDBE6, 0x577C, 0xDBE5, 0x577D, 0x887B, 0x577E, 0x887C, 0x577F, 0x887D, 0x5780, 0x887E, 0x5781, 0x8880, 0x5782, 0xB4B9, + 0x5783, 0xC0AC, 0x5784, 0xC2A2, 0x5785, 0xDBE2, 0x5786, 0xDBE4, 0x5787, 0x8881, 0x5788, 0x8882, 0x5789, 0x8883, 0x578A, 0x8884, + 0x578B, 0xD0CD, 0x578C, 0xDBED, 0x578D, 0x8885, 0x578E, 0x8886, 0x578F, 0x8887, 0x5790, 0x8888, 0x5791, 0x8889, 0x5792, 0xC0DD, + 0x5793, 0xDBF2, 0x5794, 0x888A, 0x5795, 0x888B, 0x5796, 0x888C, 0x5797, 0x888D, 0x5798, 0x888E, 0x5799, 0x888F, 0x579A, 0x8890, + 0x579B, 0xB6E2, 0x579C, 0x8891, 0x579D, 0x8892, 0x579E, 0x8893, 0x579F, 0x8894, 0x57A0, 0xDBF3, 0x57A1, 0xDBD2, 0x57A2, 0xB9B8, + 0x57A3, 0xD4AB, 0x57A4, 0xDBEC, 0x57A5, 0x8895, 0x57A6, 0xBFD1, 0x57A7, 0xDBF0, 0x57A8, 0x8896, 0x57A9, 0xDBD1, 0x57AA, 0x8897, + 0x57AB, 0xB5E6, 0x57AC, 0x8898, 0x57AD, 0xDBEB, 0x57AE, 0xBFE5, 0x57AF, 0x8899, 0x57B0, 0x889A, 0x57B1, 0x889B, 0x57B2, 0xDBEE, + 0x57B3, 0x889C, 0x57B4, 0xDBF1, 0x57B5, 0x889D, 0x57B6, 0x889E, 0x57B7, 0x889F, 0x57B8, 0xDBF9, 0x57B9, 0x88A0, 0x57BA, 0x88A1, + 0x57BB, 0x88A2, 0x57BC, 0x88A3, 0x57BD, 0x88A4, 0x57BE, 0x88A5, 0x57BF, 0x88A6, 0x57C0, 0x88A7, 0x57C1, 0x88A8, 0x57C2, 0xB9A1, + 0x57C3, 0xB0A3, 0x57C4, 0x88A9, 0x57C5, 0x88AA, 0x57C6, 0x88AB, 0x57C7, 0x88AC, 0x57C8, 0x88AD, 0x57C9, 0x88AE, 0x57CA, 0x88AF, + 0x57CB, 0xC2F1, 0x57CC, 0x88B0, 0x57CD, 0x88B1, 0x57CE, 0xB3C7, 0x57CF, 0xDBEF, 0x57D0, 0x88B2, 0x57D1, 0x88B3, 0x57D2, 0xDBF8, + 0x57D3, 0x88B4, 0x57D4, 0xC6D2, 0x57D5, 0xDBF4, 0x57D6, 0x88B5, 0x57D7, 0x88B6, 0x57D8, 0xDBF5, 0x57D9, 0xDBF7, 0x57DA, 0xDBF6, + 0x57DB, 0x88B7, 0x57DC, 0x88B8, 0x57DD, 0xDBFE, 0x57DE, 0x88B9, 0x57DF, 0xD3F2, 0x57E0, 0xB2BA, 0x57E1, 0x88BA, 0x57E2, 0x88BB, + 0x57E3, 0x88BC, 0x57E4, 0xDBFD, 0x57E5, 0x88BD, 0x57E6, 0x88BE, 0x57E7, 0x88BF, 0x57E8, 0x88C0, 0x57E9, 0x88C1, 0x57EA, 0x88C2, + 0x57EB, 0x88C3, 0x57EC, 0x88C4, 0x57ED, 0xDCA4, 0x57EE, 0x88C5, 0x57EF, 0xDBFB, 0x57F0, 0x88C6, 0x57F1, 0x88C7, 0x57F2, 0x88C8, + 0x57F3, 0x88C9, 0x57F4, 0xDBFA, 0x57F5, 0x88CA, 0x57F6, 0x88CB, 0x57F7, 0x88CC, 0x57F8, 0xDBFC, 0x57F9, 0xC5E0, 0x57FA, 0xBBF9, + 0x57FB, 0x88CD, 0x57FC, 0x88CE, 0x57FD, 0xDCA3, 0x57FE, 0x88CF, 0x57FF, 0x88D0, 0x5800, 0xDCA5, 0x5801, 0x88D1, 0x5802, 0xCCC3, + 0x5803, 0x88D2, 0x5804, 0x88D3, 0x5805, 0x88D4, 0x5806, 0xB6D1, 0x5807, 0xDDC0, 0x5808, 0x88D5, 0x5809, 0x88D6, 0x580A, 0x88D7, + 0x580B, 0xDCA1, 0x580C, 0x88D8, 0x580D, 0xDCA2, 0x580E, 0x88D9, 0x580F, 0x88DA, 0x5810, 0x88DB, 0x5811, 0xC7B5, 0x5812, 0x88DC, + 0x5813, 0x88DD, 0x5814, 0x88DE, 0x5815, 0xB6E9, 0x5816, 0x88DF, 0x5817, 0x88E0, 0x5818, 0x88E1, 0x5819, 0xDCA7, 0x581A, 0x88E2, + 0x581B, 0x88E3, 0x581C, 0x88E4, 0x581D, 0x88E5, 0x581E, 0xDCA6, 0x581F, 0x88E6, 0x5820, 0xDCA9, 0x5821, 0xB1A4, 0x5822, 0x88E7, + 0x5823, 0x88E8, 0x5824, 0xB5CC, 0x5825, 0x88E9, 0x5826, 0x88EA, 0x5827, 0x88EB, 0x5828, 0x88EC, 0x5829, 0x88ED, 0x582A, 0xBFB0, + 0x582B, 0x88EE, 0x582C, 0x88EF, 0x582D, 0x88F0, 0x582E, 0x88F1, 0x582F, 0x88F2, 0x5830, 0xD1DF, 0x5831, 0x88F3, 0x5832, 0x88F4, + 0x5833, 0x88F5, 0x5834, 0x88F6, 0x5835, 0xB6C2, 0x5836, 0x88F7, 0x5837, 0x88F8, 0x5838, 0x88F9, 0x5839, 0x88FA, 0x583A, 0x88FB, + 0x583B, 0x88FC, 0x583C, 0x88FD, 0x583D, 0x88FE, 0x583E, 0x8940, 0x583F, 0x8941, 0x5840, 0x8942, 0x5841, 0x8943, 0x5842, 0x8944, + 0x5843, 0x8945, 0x5844, 0xDCA8, 0x5845, 0x8946, 0x5846, 0x8947, 0x5847, 0x8948, 0x5848, 0x8949, 0x5849, 0x894A, 0x584A, 0x894B, + 0x584B, 0x894C, 0x584C, 0xCBFA, 0x584D, 0xEBF3, 0x584E, 0x894D, 0x584F, 0x894E, 0x5850, 0x894F, 0x5851, 0xCBDC, 0x5852, 0x8950, + 0x5853, 0x8951, 0x5854, 0xCBFE, 0x5855, 0x8952, 0x5856, 0x8953, 0x5857, 0x8954, 0x5858, 0xCCC1, 0x5859, 0x8955, 0x585A, 0x8956, + 0x585B, 0x8957, 0x585C, 0x8958, 0x585D, 0x8959, 0x585E, 0xC8FB, 0x585F, 0x895A, 0x5860, 0x895B, 0x5861, 0x895C, 0x5862, 0x895D, + 0x5863, 0x895E, 0x5864, 0x895F, 0x5865, 0xDCAA, 0x5866, 0x8960, 0x5867, 0x8961, 0x5868, 0x8962, 0x5869, 0x8963, 0x586A, 0x8964, + 0x586B, 0xCCEE, 0x586C, 0xDCAB, 0x586D, 0x8965, 0x586E, 0x8966, 0x586F, 0x8967, 0x5870, 0x8968, 0x5871, 0x8969, 0x5872, 0x896A, + 0x5873, 0x896B, 0x5874, 0x896C, 0x5875, 0x896D, 0x5876, 0x896E, 0x5877, 0x896F, 0x5878, 0x8970, 0x5879, 0x8971, 0x587A, 0x8972, + 0x587B, 0x8973, 0x587C, 0x8974, 0x587D, 0x8975, 0x587E, 0xDBD3, 0x587F, 0x8976, 0x5880, 0xDCAF, 0x5881, 0xDCAC, 0x5882, 0x8977, + 0x5883, 0xBEB3, 0x5884, 0x8978, 0x5885, 0xCAFB, 0x5886, 0x8979, 0x5887, 0x897A, 0x5888, 0x897B, 0x5889, 0xDCAD, 0x588A, 0x897C, + 0x588B, 0x897D, 0x588C, 0x897E, 0x588D, 0x8980, 0x588E, 0x8981, 0x588F, 0x8982, 0x5890, 0x8983, 0x5891, 0x8984, 0x5892, 0xC9CA, + 0x5893, 0xC4B9, 0x5894, 0x8985, 0x5895, 0x8986, 0x5896, 0x8987, 0x5897, 0x8988, 0x5898, 0x8989, 0x5899, 0xC7BD, 0x589A, 0xDCAE, + 0x589B, 0x898A, 0x589C, 0x898B, 0x589D, 0x898C, 0x589E, 0xD4F6, 0x589F, 0xD0E6, 0x58A0, 0x898D, 0x58A1, 0x898E, 0x58A2, 0x898F, + 0x58A3, 0x8990, 0x58A4, 0x8991, 0x58A5, 0x8992, 0x58A6, 0x8993, 0x58A7, 0x8994, 0x58A8, 0xC4AB, 0x58A9, 0xB6D5, 0x58AA, 0x8995, + 0x58AB, 0x8996, 0x58AC, 0x8997, 0x58AD, 0x8998, 0x58AE, 0x8999, 0x58AF, 0x899A, 0x58B0, 0x899B, 0x58B1, 0x899C, 0x58B2, 0x899D, + 0x58B3, 0x899E, 0x58B4, 0x899F, 0x58B5, 0x89A0, 0x58B6, 0x89A1, 0x58B7, 0x89A2, 0x58B8, 0x89A3, 0x58B9, 0x89A4, 0x58BA, 0x89A5, + 0x58BB, 0x89A6, 0x58BC, 0xDBD4, 0x58BD, 0x89A7, 0x58BE, 0x89A8, 0x58BF, 0x89A9, 0x58C0, 0x89AA, 0x58C1, 0xB1DA, 0x58C2, 0x89AB, + 0x58C3, 0x89AC, 0x58C4, 0x89AD, 0x58C5, 0xDBD5, 0x58C6, 0x89AE, 0x58C7, 0x89AF, 0x58C8, 0x89B0, 0x58C9, 0x89B1, 0x58CA, 0x89B2, + 0x58CB, 0x89B3, 0x58CC, 0x89B4, 0x58CD, 0x89B5, 0x58CE, 0x89B6, 0x58CF, 0x89B7, 0x58D0, 0x89B8, 0x58D1, 0xDBD6, 0x58D2, 0x89B9, + 0x58D3, 0x89BA, 0x58D4, 0x89BB, 0x58D5, 0xBABE, 0x58D6, 0x89BC, 0x58D7, 0x89BD, 0x58D8, 0x89BE, 0x58D9, 0x89BF, 0x58DA, 0x89C0, + 0x58DB, 0x89C1, 0x58DC, 0x89C2, 0x58DD, 0x89C3, 0x58DE, 0x89C4, 0x58DF, 0x89C5, 0x58E0, 0x89C6, 0x58E1, 0x89C7, 0x58E2, 0x89C8, + 0x58E3, 0x89C9, 0x58E4, 0xC8C0, 0x58E5, 0x89CA, 0x58E6, 0x89CB, 0x58E7, 0x89CC, 0x58E8, 0x89CD, 0x58E9, 0x89CE, 0x58EA, 0x89CF, + 0x58EB, 0xCABF, 0x58EC, 0xC8C9, 0x58ED, 0x89D0, 0x58EE, 0xD7B3, 0x58EF, 0x89D1, 0x58F0, 0xC9F9, 0x58F1, 0x89D2, 0x58F2, 0x89D3, + 0x58F3, 0xBFC7, 0x58F4, 0x89D4, 0x58F5, 0x89D5, 0x58F6, 0xBAF8, 0x58F7, 0x89D6, 0x58F8, 0x89D7, 0x58F9, 0xD2BC, 0x58FA, 0x89D8, + 0x58FB, 0x89D9, 0x58FC, 0x89DA, 0x58FD, 0x89DB, 0x58FE, 0x89DC, 0x58FF, 0x89DD, 0x5900, 0x89DE, 0x5901, 0x89DF, 0x5902, 0xE2BA, + 0x5903, 0x89E0, 0x5904, 0xB4A6, 0x5905, 0x89E1, 0x5906, 0x89E2, 0x5907, 0xB1B8, 0x5908, 0x89E3, 0x5909, 0x89E4, 0x590A, 0x89E5, + 0x590B, 0x89E6, 0x590C, 0x89E7, 0x590D, 0xB8B4, 0x590E, 0x89E8, 0x590F, 0xCFC4, 0x5910, 0x89E9, 0x5911, 0x89EA, 0x5912, 0x89EB, + 0x5913, 0x89EC, 0x5914, 0xD9E7, 0x5915, 0xCFA6, 0x5916, 0xCDE2, 0x5917, 0x89ED, 0x5918, 0x89EE, 0x5919, 0xD9ED, 0x591A, 0xB6E0, + 0x591B, 0x89EF, 0x591C, 0xD2B9, 0x591D, 0x89F0, 0x591E, 0x89F1, 0x591F, 0xB9BB, 0x5920, 0x89F2, 0x5921, 0x89F3, 0x5922, 0x89F4, + 0x5923, 0x89F5, 0x5924, 0xE2B9, 0x5925, 0xE2B7, 0x5926, 0x89F6, 0x5927, 0xB4F3, 0x5928, 0x89F7, 0x5929, 0xCCEC, 0x592A, 0xCCAB, + 0x592B, 0xB7F2, 0x592C, 0x89F8, 0x592D, 0xD8B2, 0x592E, 0xD1EB, 0x592F, 0xBABB, 0x5930, 0x89F9, 0x5931, 0xCAA7, 0x5932, 0x89FA, + 0x5933, 0x89FB, 0x5934, 0xCDB7, 0x5935, 0x89FC, 0x5936, 0x89FD, 0x5937, 0xD2C4, 0x5938, 0xBFE4, 0x5939, 0xBCD0, 0x593A, 0xB6E1, + 0x593B, 0x89FE, 0x593C, 0xDEC5, 0x593D, 0x8A40, 0x593E, 0x8A41, 0x593F, 0x8A42, 0x5940, 0x8A43, 0x5941, 0xDEC6, 0x5942, 0xDBBC, + 0x5943, 0x8A44, 0x5944, 0xD1D9, 0x5945, 0x8A45, 0x5946, 0x8A46, 0x5947, 0xC6E6, 0x5948, 0xC4CE, 0x5949, 0xB7EE, 0x594A, 0x8A47, + 0x594B, 0xB7DC, 0x594C, 0x8A48, 0x594D, 0x8A49, 0x594E, 0xBFFC, 0x594F, 0xD7E0, 0x5950, 0x8A4A, 0x5951, 0xC6F5, 0x5952, 0x8A4B, + 0x5953, 0x8A4C, 0x5954, 0xB1BC, 0x5955, 0xDEC8, 0x5956, 0xBDB1, 0x5957, 0xCCD7, 0x5958, 0xDECA, 0x5959, 0x8A4D, 0x595A, 0xDEC9, + 0x595B, 0x8A4E, 0x595C, 0x8A4F, 0x595D, 0x8A50, 0x595E, 0x8A51, 0x595F, 0x8A52, 0x5960, 0xB5EC, 0x5961, 0x8A53, 0x5962, 0xC9DD, + 0x5963, 0x8A54, 0x5964, 0x8A55, 0x5965, 0xB0C2, 0x5966, 0x8A56, 0x5967, 0x8A57, 0x5968, 0x8A58, 0x5969, 0x8A59, 0x596A, 0x8A5A, + 0x596B, 0x8A5B, 0x596C, 0x8A5C, 0x596D, 0x8A5D, 0x596E, 0x8A5E, 0x596F, 0x8A5F, 0x5970, 0x8A60, 0x5971, 0x8A61, 0x5972, 0x8A62, + 0x5973, 0xC5AE, 0x5974, 0xC5AB, 0x5975, 0x8A63, 0x5976, 0xC4CC, 0x5977, 0x8A64, 0x5978, 0xBCE9, 0x5979, 0xCBFD, 0x597A, 0x8A65, + 0x597B, 0x8A66, 0x597C, 0x8A67, 0x597D, 0xBAC3, 0x597E, 0x8A68, 0x597F, 0x8A69, 0x5980, 0x8A6A, 0x5981, 0xE5F9, 0x5982, 0xC8E7, + 0x5983, 0xE5FA, 0x5984, 0xCDFD, 0x5985, 0x8A6B, 0x5986, 0xD7B1, 0x5987, 0xB8BE, 0x5988, 0xC2E8, 0x5989, 0x8A6C, 0x598A, 0xC8D1, + 0x598B, 0x8A6D, 0x598C, 0x8A6E, 0x598D, 0xE5FB, 0x598E, 0x8A6F, 0x598F, 0x8A70, 0x5990, 0x8A71, 0x5991, 0x8A72, 0x5992, 0xB6CA, + 0x5993, 0xBCCB, 0x5994, 0x8A73, 0x5995, 0x8A74, 0x5996, 0xD1FD, 0x5997, 0xE6A1, 0x5998, 0x8A75, 0x5999, 0xC3EE, 0x599A, 0x8A76, + 0x599B, 0x8A77, 0x599C, 0x8A78, 0x599D, 0x8A79, 0x599E, 0xE6A4, 0x599F, 0x8A7A, 0x59A0, 0x8A7B, 0x59A1, 0x8A7C, 0x59A2, 0x8A7D, + 0x59A3, 0xE5FE, 0x59A4, 0xE6A5, 0x59A5, 0xCDD7, 0x59A6, 0x8A7E, 0x59A7, 0x8A80, 0x59A8, 0xB7C1, 0x59A9, 0xE5FC, 0x59AA, 0xE5FD, + 0x59AB, 0xE6A3, 0x59AC, 0x8A81, 0x59AD, 0x8A82, 0x59AE, 0xC4DD, 0x59AF, 0xE6A8, 0x59B0, 0x8A83, 0x59B1, 0x8A84, 0x59B2, 0xE6A7, + 0x59B3, 0x8A85, 0x59B4, 0x8A86, 0x59B5, 0x8A87, 0x59B6, 0x8A88, 0x59B7, 0x8A89, 0x59B8, 0x8A8A, 0x59B9, 0xC3C3, 0x59BA, 0x8A8B, + 0x59BB, 0xC6DE, 0x59BC, 0x8A8C, 0x59BD, 0x8A8D, 0x59BE, 0xE6AA, 0x59BF, 0x8A8E, 0x59C0, 0x8A8F, 0x59C1, 0x8A90, 0x59C2, 0x8A91, + 0x59C3, 0x8A92, 0x59C4, 0x8A93, 0x59C5, 0x8A94, 0x59C6, 0xC4B7, 0x59C7, 0x8A95, 0x59C8, 0x8A96, 0x59C9, 0x8A97, 0x59CA, 0xE6A2, + 0x59CB, 0xCABC, 0x59CC, 0x8A98, 0x59CD, 0x8A99, 0x59CE, 0x8A9A, 0x59CF, 0x8A9B, 0x59D0, 0xBDE3, 0x59D1, 0xB9C3, 0x59D2, 0xE6A6, + 0x59D3, 0xD0D5, 0x59D4, 0xCEAF, 0x59D5, 0x8A9C, 0x59D6, 0x8A9D, 0x59D7, 0xE6A9, 0x59D8, 0xE6B0, 0x59D9, 0x8A9E, 0x59DA, 0xD2A6, + 0x59DB, 0x8A9F, 0x59DC, 0xBDAA, 0x59DD, 0xE6AD, 0x59DE, 0x8AA0, 0x59DF, 0x8AA1, 0x59E0, 0x8AA2, 0x59E1, 0x8AA3, 0x59E2, 0x8AA4, + 0x59E3, 0xE6AF, 0x59E4, 0x8AA5, 0x59E5, 0xC0D1, 0x59E6, 0x8AA6, 0x59E7, 0x8AA7, 0x59E8, 0xD2CC, 0x59E9, 0x8AA8, 0x59EA, 0x8AA9, + 0x59EB, 0x8AAA, 0x59EC, 0xBCA7, 0x59ED, 0x8AAB, 0x59EE, 0x8AAC, 0x59EF, 0x8AAD, 0x59F0, 0x8AAE, 0x59F1, 0x8AAF, 0x59F2, 0x8AB0, + 0x59F3, 0x8AB1, 0x59F4, 0x8AB2, 0x59F5, 0x8AB3, 0x59F6, 0x8AB4, 0x59F7, 0x8AB5, 0x59F8, 0x8AB6, 0x59F9, 0xE6B1, 0x59FA, 0x8AB7, + 0x59FB, 0xD2F6, 0x59FC, 0x8AB8, 0x59FD, 0x8AB9, 0x59FE, 0x8ABA, 0x59FF, 0xD7CB, 0x5A00, 0x8ABB, 0x5A01, 0xCDFE, 0x5A02, 0x8ABC, + 0x5A03, 0xCDDE, 0x5A04, 0xC2A6, 0x5A05, 0xE6AB, 0x5A06, 0xE6AC, 0x5A07, 0xBDBF, 0x5A08, 0xE6AE, 0x5A09, 0xE6B3, 0x5A0A, 0x8ABD, + 0x5A0B, 0x8ABE, 0x5A0C, 0xE6B2, 0x5A0D, 0x8ABF, 0x5A0E, 0x8AC0, 0x5A0F, 0x8AC1, 0x5A10, 0x8AC2, 0x5A11, 0xE6B6, 0x5A12, 0x8AC3, + 0x5A13, 0xE6B8, 0x5A14, 0x8AC4, 0x5A15, 0x8AC5, 0x5A16, 0x8AC6, 0x5A17, 0x8AC7, 0x5A18, 0xC4EF, 0x5A19, 0x8AC8, 0x5A1A, 0x8AC9, + 0x5A1B, 0x8ACA, 0x5A1C, 0xC4C8, 0x5A1D, 0x8ACB, 0x5A1E, 0x8ACC, 0x5A1F, 0xBEEA, 0x5A20, 0xC9EF, 0x5A21, 0x8ACD, 0x5A22, 0x8ACE, + 0x5A23, 0xE6B7, 0x5A24, 0x8ACF, 0x5A25, 0xB6F0, 0x5A26, 0x8AD0, 0x5A27, 0x8AD1, 0x5A28, 0x8AD2, 0x5A29, 0xC3E4, 0x5A2A, 0x8AD3, + 0x5A2B, 0x8AD4, 0x5A2C, 0x8AD5, 0x5A2D, 0x8AD6, 0x5A2E, 0x8AD7, 0x5A2F, 0x8AD8, 0x5A30, 0x8AD9, 0x5A31, 0xD3E9, 0x5A32, 0xE6B4, + 0x5A33, 0x8ADA, 0x5A34, 0xE6B5, 0x5A35, 0x8ADB, 0x5A36, 0xC8A2, 0x5A37, 0x8ADC, 0x5A38, 0x8ADD, 0x5A39, 0x8ADE, 0x5A3A, 0x8ADF, + 0x5A3B, 0x8AE0, 0x5A3C, 0xE6BD, 0x5A3D, 0x8AE1, 0x5A3E, 0x8AE2, 0x5A3F, 0x8AE3, 0x5A40, 0xE6B9, 0x5A41, 0x8AE4, 0x5A42, 0x8AE5, + 0x5A43, 0x8AE6, 0x5A44, 0x8AE7, 0x5A45, 0x8AE8, 0x5A46, 0xC6C5, 0x5A47, 0x8AE9, 0x5A48, 0x8AEA, 0x5A49, 0xCDF1, 0x5A4A, 0xE6BB, + 0x5A4B, 0x8AEB, 0x5A4C, 0x8AEC, 0x5A4D, 0x8AED, 0x5A4E, 0x8AEE, 0x5A4F, 0x8AEF, 0x5A50, 0x8AF0, 0x5A51, 0x8AF1, 0x5A52, 0x8AF2, + 0x5A53, 0x8AF3, 0x5A54, 0x8AF4, 0x5A55, 0xE6BC, 0x5A56, 0x8AF5, 0x5A57, 0x8AF6, 0x5A58, 0x8AF7, 0x5A59, 0x8AF8, 0x5A5A, 0xBBE9, + 0x5A5B, 0x8AF9, 0x5A5C, 0x8AFA, 0x5A5D, 0x8AFB, 0x5A5E, 0x8AFC, 0x5A5F, 0x8AFD, 0x5A60, 0x8AFE, 0x5A61, 0x8B40, 0x5A62, 0xE6BE, + 0x5A63, 0x8B41, 0x5A64, 0x8B42, 0x5A65, 0x8B43, 0x5A66, 0x8B44, 0x5A67, 0xE6BA, 0x5A68, 0x8B45, 0x5A69, 0x8B46, 0x5A6A, 0xC0B7, + 0x5A6B, 0x8B47, 0x5A6C, 0x8B48, 0x5A6D, 0x8B49, 0x5A6E, 0x8B4A, 0x5A6F, 0x8B4B, 0x5A70, 0x8B4C, 0x5A71, 0x8B4D, 0x5A72, 0x8B4E, + 0x5A73, 0x8B4F, 0x5A74, 0xD3A4, 0x5A75, 0xE6BF, 0x5A76, 0xC9F4, 0x5A77, 0xE6C3, 0x5A78, 0x8B50, 0x5A79, 0x8B51, 0x5A7A, 0xE6C4, + 0x5A7B, 0x8B52, 0x5A7C, 0x8B53, 0x5A7D, 0x8B54, 0x5A7E, 0x8B55, 0x5A7F, 0xD0F6, 0x5A80, 0x8B56, 0x5A81, 0x8B57, 0x5A82, 0x8B58, + 0x5A83, 0x8B59, 0x5A84, 0x8B5A, 0x5A85, 0x8B5B, 0x5A86, 0x8B5C, 0x5A87, 0x8B5D, 0x5A88, 0x8B5E, 0x5A89, 0x8B5F, 0x5A8A, 0x8B60, + 0x5A8B, 0x8B61, 0x5A8C, 0x8B62, 0x5A8D, 0x8B63, 0x5A8E, 0x8B64, 0x5A8F, 0x8B65, 0x5A90, 0x8B66, 0x5A91, 0x8B67, 0x5A92, 0xC3BD, + 0x5A93, 0x8B68, 0x5A94, 0x8B69, 0x5A95, 0x8B6A, 0x5A96, 0x8B6B, 0x5A97, 0x8B6C, 0x5A98, 0x8B6D, 0x5A99, 0x8B6E, 0x5A9A, 0xC3C4, + 0x5A9B, 0xE6C2, 0x5A9C, 0x8B6F, 0x5A9D, 0x8B70, 0x5A9E, 0x8B71, 0x5A9F, 0x8B72, 0x5AA0, 0x8B73, 0x5AA1, 0x8B74, 0x5AA2, 0x8B75, + 0x5AA3, 0x8B76, 0x5AA4, 0x8B77, 0x5AA5, 0x8B78, 0x5AA6, 0x8B79, 0x5AA7, 0x8B7A, 0x5AA8, 0x8B7B, 0x5AA9, 0x8B7C, 0x5AAA, 0xE6C1, + 0x5AAB, 0x8B7D, 0x5AAC, 0x8B7E, 0x5AAD, 0x8B80, 0x5AAE, 0x8B81, 0x5AAF, 0x8B82, 0x5AB0, 0x8B83, 0x5AB1, 0x8B84, 0x5AB2, 0xE6C7, + 0x5AB3, 0xCFB1, 0x5AB4, 0x8B85, 0x5AB5, 0xEBF4, 0x5AB6, 0x8B86, 0x5AB7, 0x8B87, 0x5AB8, 0xE6CA, 0x5AB9, 0x8B88, 0x5ABA, 0x8B89, + 0x5ABB, 0x8B8A, 0x5ABC, 0x8B8B, 0x5ABD, 0x8B8C, 0x5ABE, 0xE6C5, 0x5ABF, 0x8B8D, 0x5AC0, 0x8B8E, 0x5AC1, 0xBCDE, 0x5AC2, 0xC9A9, + 0x5AC3, 0x8B8F, 0x5AC4, 0x8B90, 0x5AC5, 0x8B91, 0x5AC6, 0x8B92, 0x5AC7, 0x8B93, 0x5AC8, 0x8B94, 0x5AC9, 0xBCB5, 0x5ACA, 0x8B95, + 0x5ACB, 0x8B96, 0x5ACC, 0xCFD3, 0x5ACD, 0x8B97, 0x5ACE, 0x8B98, 0x5ACF, 0x8B99, 0x5AD0, 0x8B9A, 0x5AD1, 0x8B9B, 0x5AD2, 0xE6C8, + 0x5AD3, 0x8B9C, 0x5AD4, 0xE6C9, 0x5AD5, 0x8B9D, 0x5AD6, 0xE6CE, 0x5AD7, 0x8B9E, 0x5AD8, 0xE6D0, 0x5AD9, 0x8B9F, 0x5ADA, 0x8BA0, + 0x5ADB, 0x8BA1, 0x5ADC, 0xE6D1, 0x5ADD, 0x8BA2, 0x5ADE, 0x8BA3, 0x5ADF, 0x8BA4, 0x5AE0, 0xE6CB, 0x5AE1, 0xB5D5, 0x5AE2, 0x8BA5, + 0x5AE3, 0xE6CC, 0x5AE4, 0x8BA6, 0x5AE5, 0x8BA7, 0x5AE6, 0xE6CF, 0x5AE7, 0x8BA8, 0x5AE8, 0x8BA9, 0x5AE9, 0xC4DB, 0x5AEA, 0x8BAA, + 0x5AEB, 0xE6C6, 0x5AEC, 0x8BAB, 0x5AED, 0x8BAC, 0x5AEE, 0x8BAD, 0x5AEF, 0x8BAE, 0x5AF0, 0x8BAF, 0x5AF1, 0xE6CD, 0x5AF2, 0x8BB0, + 0x5AF3, 0x8BB1, 0x5AF4, 0x8BB2, 0x5AF5, 0x8BB3, 0x5AF6, 0x8BB4, 0x5AF7, 0x8BB5, 0x5AF8, 0x8BB6, 0x5AF9, 0x8BB7, 0x5AFA, 0x8BB8, + 0x5AFB, 0x8BB9, 0x5AFC, 0x8BBA, 0x5AFD, 0x8BBB, 0x5AFE, 0x8BBC, 0x5AFF, 0x8BBD, 0x5B00, 0x8BBE, 0x5B01, 0x8BBF, 0x5B02, 0x8BC0, + 0x5B03, 0x8BC1, 0x5B04, 0x8BC2, 0x5B05, 0x8BC3, 0x5B06, 0x8BC4, 0x5B07, 0x8BC5, 0x5B08, 0x8BC6, 0x5B09, 0xE6D2, 0x5B0A, 0x8BC7, + 0x5B0B, 0x8BC8, 0x5B0C, 0x8BC9, 0x5B0D, 0x8BCA, 0x5B0E, 0x8BCB, 0x5B0F, 0x8BCC, 0x5B10, 0x8BCD, 0x5B11, 0x8BCE, 0x5B12, 0x8BCF, + 0x5B13, 0x8BD0, 0x5B14, 0x8BD1, 0x5B15, 0x8BD2, 0x5B16, 0xE6D4, 0x5B17, 0xE6D3, 0x5B18, 0x8BD3, 0x5B19, 0x8BD4, 0x5B1A, 0x8BD5, + 0x5B1B, 0x8BD6, 0x5B1C, 0x8BD7, 0x5B1D, 0x8BD8, 0x5B1E, 0x8BD9, 0x5B1F, 0x8BDA, 0x5B20, 0x8BDB, 0x5B21, 0x8BDC, 0x5B22, 0x8BDD, + 0x5B23, 0x8BDE, 0x5B24, 0x8BDF, 0x5B25, 0x8BE0, 0x5B26, 0x8BE1, 0x5B27, 0x8BE2, 0x5B28, 0x8BE3, 0x5B29, 0x8BE4, 0x5B2A, 0x8BE5, + 0x5B2B, 0x8BE6, 0x5B2C, 0x8BE7, 0x5B2D, 0x8BE8, 0x5B2E, 0x8BE9, 0x5B2F, 0x8BEA, 0x5B30, 0x8BEB, 0x5B31, 0x8BEC, 0x5B32, 0xE6D5, + 0x5B33, 0x8BED, 0x5B34, 0xD9F8, 0x5B35, 0x8BEE, 0x5B36, 0x8BEF, 0x5B37, 0xE6D6, 0x5B38, 0x8BF0, 0x5B39, 0x8BF1, 0x5B3A, 0x8BF2, + 0x5B3B, 0x8BF3, 0x5B3C, 0x8BF4, 0x5B3D, 0x8BF5, 0x5B3E, 0x8BF6, 0x5B3F, 0x8BF7, 0x5B40, 0xE6D7, 0x5B41, 0x8BF8, 0x5B42, 0x8BF9, + 0x5B43, 0x8BFA, 0x5B44, 0x8BFB, 0x5B45, 0x8BFC, 0x5B46, 0x8BFD, 0x5B47, 0x8BFE, 0x5B48, 0x8C40, 0x5B49, 0x8C41, 0x5B4A, 0x8C42, + 0x5B4B, 0x8C43, 0x5B4C, 0x8C44, 0x5B4D, 0x8C45, 0x5B4E, 0x8C46, 0x5B4F, 0x8C47, 0x5B50, 0xD7D3, 0x5B51, 0xE6DD, 0x5B52, 0x8C48, + 0x5B53, 0xE6DE, 0x5B54, 0xBFD7, 0x5B55, 0xD4D0, 0x5B56, 0x8C49, 0x5B57, 0xD7D6, 0x5B58, 0xB4E6, 0x5B59, 0xCBEF, 0x5B5A, 0xE6DA, + 0x5B5B, 0xD8C3, 0x5B5C, 0xD7CE, 0x5B5D, 0xD0A2, 0x5B5E, 0x8C4A, 0x5B5F, 0xC3CF, 0x5B60, 0x8C4B, 0x5B61, 0x8C4C, 0x5B62, 0xE6DF, + 0x5B63, 0xBCBE, 0x5B64, 0xB9C2, 0x5B65, 0xE6DB, 0x5B66, 0xD1A7, 0x5B67, 0x8C4D, 0x5B68, 0x8C4E, 0x5B69, 0xBAA2, 0x5B6A, 0xC2CF, + 0x5B6B, 0x8C4F, 0x5B6C, 0xD8AB, 0x5B6D, 0x8C50, 0x5B6E, 0x8C51, 0x5B6F, 0x8C52, 0x5B70, 0xCAEB, 0x5B71, 0xE5EE, 0x5B72, 0x8C53, + 0x5B73, 0xE6DC, 0x5B74, 0x8C54, 0x5B75, 0xB7F5, 0x5B76, 0x8C55, 0x5B77, 0x8C56, 0x5B78, 0x8C57, 0x5B79, 0x8C58, 0x5B7A, 0xC8E6, + 0x5B7B, 0x8C59, 0x5B7C, 0x8C5A, 0x5B7D, 0xC4F5, 0x5B7E, 0x8C5B, 0x5B7F, 0x8C5C, 0x5B80, 0xE5B2, 0x5B81, 0xC4FE, 0x5B82, 0x8C5D, + 0x5B83, 0xCBFC, 0x5B84, 0xE5B3, 0x5B85, 0xD5AC, 0x5B86, 0x8C5E, 0x5B87, 0xD3EE, 0x5B88, 0xCAD8, 0x5B89, 0xB0B2, 0x5B8A, 0x8C5F, + 0x5B8B, 0xCBCE, 0x5B8C, 0xCDEA, 0x5B8D, 0x8C60, 0x5B8E, 0x8C61, 0x5B8F, 0xBAEA, 0x5B90, 0x8C62, 0x5B91, 0x8C63, 0x5B92, 0x8C64, + 0x5B93, 0xE5B5, 0x5B94, 0x8C65, 0x5B95, 0xE5B4, 0x5B96, 0x8C66, 0x5B97, 0xD7DA, 0x5B98, 0xB9D9, 0x5B99, 0xD6E6, 0x5B9A, 0xB6A8, + 0x5B9B, 0xCDF0, 0x5B9C, 0xD2CB, 0x5B9D, 0xB1A6, 0x5B9E, 0xCAB5, 0x5B9F, 0x8C67, 0x5BA0, 0xB3E8, 0x5BA1, 0xC9F3, 0x5BA2, 0xBFCD, + 0x5BA3, 0xD0FB, 0x5BA4, 0xCAD2, 0x5BA5, 0xE5B6, 0x5BA6, 0xBBC2, 0x5BA7, 0x8C68, 0x5BA8, 0x8C69, 0x5BA9, 0x8C6A, 0x5BAA, 0xCFDC, + 0x5BAB, 0xB9AC, 0x5BAC, 0x8C6B, 0x5BAD, 0x8C6C, 0x5BAE, 0x8C6D, 0x5BAF, 0x8C6E, 0x5BB0, 0xD4D7, 0x5BB1, 0x8C6F, 0x5BB2, 0x8C70, + 0x5BB3, 0xBAA6, 0x5BB4, 0xD1E7, 0x5BB5, 0xCFFC, 0x5BB6, 0xBCD2, 0x5BB7, 0x8C71, 0x5BB8, 0xE5B7, 0x5BB9, 0xC8DD, 0x5BBA, 0x8C72, + 0x5BBB, 0x8C73, 0x5BBC, 0x8C74, 0x5BBD, 0xBFED, 0x5BBE, 0xB1F6, 0x5BBF, 0xCBDE, 0x5BC0, 0x8C75, 0x5BC1, 0x8C76, 0x5BC2, 0xBCC5, + 0x5BC3, 0x8C77, 0x5BC4, 0xBCC4, 0x5BC5, 0xD2FA, 0x5BC6, 0xC3DC, 0x5BC7, 0xBFDC, 0x5BC8, 0x8C78, 0x5BC9, 0x8C79, 0x5BCA, 0x8C7A, + 0x5BCB, 0x8C7B, 0x5BCC, 0xB8BB, 0x5BCD, 0x8C7C, 0x5BCE, 0x8C7D, 0x5BCF, 0x8C7E, 0x5BD0, 0xC3C2, 0x5BD1, 0x8C80, 0x5BD2, 0xBAAE, + 0x5BD3, 0xD4A2, 0x5BD4, 0x8C81, 0x5BD5, 0x8C82, 0x5BD6, 0x8C83, 0x5BD7, 0x8C84, 0x5BD8, 0x8C85, 0x5BD9, 0x8C86, 0x5BDA, 0x8C87, + 0x5BDB, 0x8C88, 0x5BDC, 0x8C89, 0x5BDD, 0xC7DE, 0x5BDE, 0xC4AF, 0x5BDF, 0xB2EC, 0x5BE0, 0x8C8A, 0x5BE1, 0xB9D1, 0x5BE2, 0x8C8B, + 0x5BE3, 0x8C8C, 0x5BE4, 0xE5BB, 0x5BE5, 0xC1C8, 0x5BE6, 0x8C8D, 0x5BE7, 0x8C8E, 0x5BE8, 0xD5AF, 0x5BE9, 0x8C8F, 0x5BEA, 0x8C90, + 0x5BEB, 0x8C91, 0x5BEC, 0x8C92, 0x5BED, 0x8C93, 0x5BEE, 0xE5BC, 0x5BEF, 0x8C94, 0x5BF0, 0xE5BE, 0x5BF1, 0x8C95, 0x5BF2, 0x8C96, + 0x5BF3, 0x8C97, 0x5BF4, 0x8C98, 0x5BF5, 0x8C99, 0x5BF6, 0x8C9A, 0x5BF7, 0x8C9B, 0x5BF8, 0xB4E7, 0x5BF9, 0xB6D4, 0x5BFA, 0xCBC2, + 0x5BFB, 0xD1B0, 0x5BFC, 0xB5BC, 0x5BFD, 0x8C9C, 0x5BFE, 0x8C9D, 0x5BFF, 0xCAD9, 0x5C00, 0x8C9E, 0x5C01, 0xB7E2, 0x5C02, 0x8C9F, + 0x5C03, 0x8CA0, 0x5C04, 0xC9E4, 0x5C05, 0x8CA1, 0x5C06, 0xBDAB, 0x5C07, 0x8CA2, 0x5C08, 0x8CA3, 0x5C09, 0xCEBE, 0x5C0A, 0xD7F0, + 0x5C0B, 0x8CA4, 0x5C0C, 0x8CA5, 0x5C0D, 0x8CA6, 0x5C0E, 0x8CA7, 0x5C0F, 0xD0A1, 0x5C10, 0x8CA8, 0x5C11, 0xC9D9, 0x5C12, 0x8CA9, + 0x5C13, 0x8CAA, 0x5C14, 0xB6FB, 0x5C15, 0xE6D8, 0x5C16, 0xBCE2, 0x5C17, 0x8CAB, 0x5C18, 0xB3BE, 0x5C19, 0x8CAC, 0x5C1A, 0xC9D0, + 0x5C1B, 0x8CAD, 0x5C1C, 0xE6D9, 0x5C1D, 0xB3A2, 0x5C1E, 0x8CAE, 0x5C1F, 0x8CAF, 0x5C20, 0x8CB0, 0x5C21, 0x8CB1, 0x5C22, 0xDECC, + 0x5C23, 0x8CB2, 0x5C24, 0xD3C8, 0x5C25, 0xDECD, 0x5C26, 0x8CB3, 0x5C27, 0xD2A2, 0x5C28, 0x8CB4, 0x5C29, 0x8CB5, 0x5C2A, 0x8CB6, + 0x5C2B, 0x8CB7, 0x5C2C, 0xDECE, 0x5C2D, 0x8CB8, 0x5C2E, 0x8CB9, 0x5C2F, 0x8CBA, 0x5C30, 0x8CBB, 0x5C31, 0xBECD, 0x5C32, 0x8CBC, + 0x5C33, 0x8CBD, 0x5C34, 0xDECF, 0x5C35, 0x8CBE, 0x5C36, 0x8CBF, 0x5C37, 0x8CC0, 0x5C38, 0xCAAC, 0x5C39, 0xD2FC, 0x5C3A, 0xB3DF, + 0x5C3B, 0xE5EA, 0x5C3C, 0xC4E1, 0x5C3D, 0xBEA1, 0x5C3E, 0xCEB2, 0x5C3F, 0xC4F2, 0x5C40, 0xBED6, 0x5C41, 0xC6A8, 0x5C42, 0xB2E3, + 0x5C43, 0x8CC1, 0x5C44, 0x8CC2, 0x5C45, 0xBED3, 0x5C46, 0x8CC3, 0x5C47, 0x8CC4, 0x5C48, 0xC7FC, 0x5C49, 0xCCEB, 0x5C4A, 0xBDEC, + 0x5C4B, 0xCEDD, 0x5C4C, 0x8CC5, 0x5C4D, 0x8CC6, 0x5C4E, 0xCABA, 0x5C4F, 0xC6C1, 0x5C50, 0xE5EC, 0x5C51, 0xD0BC, 0x5C52, 0x8CC7, + 0x5C53, 0x8CC8, 0x5C54, 0x8CC9, 0x5C55, 0xD5B9, 0x5C56, 0x8CCA, 0x5C57, 0x8CCB, 0x5C58, 0x8CCC, 0x5C59, 0xE5ED, 0x5C5A, 0x8CCD, + 0x5C5B, 0x8CCE, 0x5C5C, 0x8CCF, 0x5C5D, 0x8CD0, 0x5C5E, 0xCAF4, 0x5C5F, 0x8CD1, 0x5C60, 0xCDC0, 0x5C61, 0xC2C5, 0x5C62, 0x8CD2, + 0x5C63, 0xE5EF, 0x5C64, 0x8CD3, 0x5C65, 0xC2C4, 0x5C66, 0xE5F0, 0x5C67, 0x8CD4, 0x5C68, 0x8CD5, 0x5C69, 0x8CD6, 0x5C6A, 0x8CD7, + 0x5C6B, 0x8CD8, 0x5C6C, 0x8CD9, 0x5C6D, 0x8CDA, 0x5C6E, 0xE5F8, 0x5C6F, 0xCDCD, 0x5C70, 0x8CDB, 0x5C71, 0xC9BD, 0x5C72, 0x8CDC, + 0x5C73, 0x8CDD, 0x5C74, 0x8CDE, 0x5C75, 0x8CDF, 0x5C76, 0x8CE0, 0x5C77, 0x8CE1, 0x5C78, 0x8CE2, 0x5C79, 0xD2D9, 0x5C7A, 0xE1A8, + 0x5C7B, 0x8CE3, 0x5C7C, 0x8CE4, 0x5C7D, 0x8CE5, 0x5C7E, 0x8CE6, 0x5C7F, 0xD3EC, 0x5C80, 0x8CE7, 0x5C81, 0xCBEA, 0x5C82, 0xC6F1, + 0x5C83, 0x8CE8, 0x5C84, 0x8CE9, 0x5C85, 0x8CEA, 0x5C86, 0x8CEB, 0x5C87, 0x8CEC, 0x5C88, 0xE1AC, 0x5C89, 0x8CED, 0x5C8A, 0x8CEE, + 0x5C8B, 0x8CEF, 0x5C8C, 0xE1A7, 0x5C8D, 0xE1A9, 0x5C8E, 0x8CF0, 0x5C8F, 0x8CF1, 0x5C90, 0xE1AA, 0x5C91, 0xE1AF, 0x5C92, 0x8CF2, + 0x5C93, 0x8CF3, 0x5C94, 0xB2ED, 0x5C95, 0x8CF4, 0x5C96, 0xE1AB, 0x5C97, 0xB8DA, 0x5C98, 0xE1AD, 0x5C99, 0xE1AE, 0x5C9A, 0xE1B0, + 0x5C9B, 0xB5BA, 0x5C9C, 0xE1B1, 0x5C9D, 0x8CF5, 0x5C9E, 0x8CF6, 0x5C9F, 0x8CF7, 0x5CA0, 0x8CF8, 0x5CA1, 0x8CF9, 0x5CA2, 0xE1B3, + 0x5CA3, 0xE1B8, 0x5CA4, 0x8CFA, 0x5CA5, 0x8CFB, 0x5CA6, 0x8CFC, 0x5CA7, 0x8CFD, 0x5CA8, 0x8CFE, 0x5CA9, 0xD1D2, 0x5CAA, 0x8D40, + 0x5CAB, 0xE1B6, 0x5CAC, 0xE1B5, 0x5CAD, 0xC1EB, 0x5CAE, 0x8D41, 0x5CAF, 0x8D42, 0x5CB0, 0x8D43, 0x5CB1, 0xE1B7, 0x5CB2, 0x8D44, + 0x5CB3, 0xD4C0, 0x5CB4, 0x8D45, 0x5CB5, 0xE1B2, 0x5CB6, 0x8D46, 0x5CB7, 0xE1BA, 0x5CB8, 0xB0B6, 0x5CB9, 0x8D47, 0x5CBA, 0x8D48, + 0x5CBB, 0x8D49, 0x5CBC, 0x8D4A, 0x5CBD, 0xE1B4, 0x5CBE, 0x8D4B, 0x5CBF, 0xBFF9, 0x5CC0, 0x8D4C, 0x5CC1, 0xE1B9, 0x5CC2, 0x8D4D, + 0x5CC3, 0x8D4E, 0x5CC4, 0xE1BB, 0x5CC5, 0x8D4F, 0x5CC6, 0x8D50, 0x5CC7, 0x8D51, 0x5CC8, 0x8D52, 0x5CC9, 0x8D53, 0x5CCA, 0x8D54, + 0x5CCB, 0xE1BE, 0x5CCC, 0x8D55, 0x5CCD, 0x8D56, 0x5CCE, 0x8D57, 0x5CCF, 0x8D58, 0x5CD0, 0x8D59, 0x5CD1, 0x8D5A, 0x5CD2, 0xE1BC, + 0x5CD3, 0x8D5B, 0x5CD4, 0x8D5C, 0x5CD5, 0x8D5D, 0x5CD6, 0x8D5E, 0x5CD7, 0x8D5F, 0x5CD8, 0x8D60, 0x5CD9, 0xD6C5, 0x5CDA, 0x8D61, + 0x5CDB, 0x8D62, 0x5CDC, 0x8D63, 0x5CDD, 0x8D64, 0x5CDE, 0x8D65, 0x5CDF, 0x8D66, 0x5CE0, 0x8D67, 0x5CE1, 0xCFBF, 0x5CE2, 0x8D68, + 0x5CE3, 0x8D69, 0x5CE4, 0xE1BD, 0x5CE5, 0xE1BF, 0x5CE6, 0xC2CD, 0x5CE7, 0x8D6A, 0x5CE8, 0xB6EB, 0x5CE9, 0x8D6B, 0x5CEA, 0xD3F8, + 0x5CEB, 0x8D6C, 0x5CEC, 0x8D6D, 0x5CED, 0xC7CD, 0x5CEE, 0x8D6E, 0x5CEF, 0x8D6F, 0x5CF0, 0xB7E5, 0x5CF1, 0x8D70, 0x5CF2, 0x8D71, + 0x5CF3, 0x8D72, 0x5CF4, 0x8D73, 0x5CF5, 0x8D74, 0x5CF6, 0x8D75, 0x5CF7, 0x8D76, 0x5CF8, 0x8D77, 0x5CF9, 0x8D78, 0x5CFA, 0x8D79, + 0x5CFB, 0xBEFE, 0x5CFC, 0x8D7A, 0x5CFD, 0x8D7B, 0x5CFE, 0x8D7C, 0x5CFF, 0x8D7D, 0x5D00, 0x8D7E, 0x5D01, 0x8D80, 0x5D02, 0xE1C0, + 0x5D03, 0xE1C1, 0x5D04, 0x8D81, 0x5D05, 0x8D82, 0x5D06, 0xE1C7, 0x5D07, 0xB3E7, 0x5D08, 0x8D83, 0x5D09, 0x8D84, 0x5D0A, 0x8D85, + 0x5D0B, 0x8D86, 0x5D0C, 0x8D87, 0x5D0D, 0x8D88, 0x5D0E, 0xC6E9, 0x5D0F, 0x8D89, 0x5D10, 0x8D8A, 0x5D11, 0x8D8B, 0x5D12, 0x8D8C, + 0x5D13, 0x8D8D, 0x5D14, 0xB4DE, 0x5D15, 0x8D8E, 0x5D16, 0xD1C2, 0x5D17, 0x8D8F, 0x5D18, 0x8D90, 0x5D19, 0x8D91, 0x5D1A, 0x8D92, + 0x5D1B, 0xE1C8, 0x5D1C, 0x8D93, 0x5D1D, 0x8D94, 0x5D1E, 0xE1C6, 0x5D1F, 0x8D95, 0x5D20, 0x8D96, 0x5D21, 0x8D97, 0x5D22, 0x8D98, + 0x5D23, 0x8D99, 0x5D24, 0xE1C5, 0x5D25, 0x8D9A, 0x5D26, 0xE1C3, 0x5D27, 0xE1C2, 0x5D28, 0x8D9B, 0x5D29, 0xB1C0, 0x5D2A, 0x8D9C, + 0x5D2B, 0x8D9D, 0x5D2C, 0x8D9E, 0x5D2D, 0xD5B8, 0x5D2E, 0xE1C4, 0x5D2F, 0x8D9F, 0x5D30, 0x8DA0, 0x5D31, 0x8DA1, 0x5D32, 0x8DA2, + 0x5D33, 0x8DA3, 0x5D34, 0xE1CB, 0x5D35, 0x8DA4, 0x5D36, 0x8DA5, 0x5D37, 0x8DA6, 0x5D38, 0x8DA7, 0x5D39, 0x8DA8, 0x5D3A, 0x8DA9, + 0x5D3B, 0x8DAA, 0x5D3C, 0x8DAB, 0x5D3D, 0xE1CC, 0x5D3E, 0xE1CA, 0x5D3F, 0x8DAC, 0x5D40, 0x8DAD, 0x5D41, 0x8DAE, 0x5D42, 0x8DAF, + 0x5D43, 0x8DB0, 0x5D44, 0x8DB1, 0x5D45, 0x8DB2, 0x5D46, 0x8DB3, 0x5D47, 0xEFFA, 0x5D48, 0x8DB4, 0x5D49, 0x8DB5, 0x5D4A, 0xE1D3, + 0x5D4B, 0xE1D2, 0x5D4C, 0xC7B6, 0x5D4D, 0x8DB6, 0x5D4E, 0x8DB7, 0x5D4F, 0x8DB8, 0x5D50, 0x8DB9, 0x5D51, 0x8DBA, 0x5D52, 0x8DBB, + 0x5D53, 0x8DBC, 0x5D54, 0x8DBD, 0x5D55, 0x8DBE, 0x5D56, 0x8DBF, 0x5D57, 0x8DC0, 0x5D58, 0xE1C9, 0x5D59, 0x8DC1, 0x5D5A, 0x8DC2, + 0x5D5B, 0xE1CE, 0x5D5C, 0x8DC3, 0x5D5D, 0xE1D0, 0x5D5E, 0x8DC4, 0x5D5F, 0x8DC5, 0x5D60, 0x8DC6, 0x5D61, 0x8DC7, 0x5D62, 0x8DC8, + 0x5D63, 0x8DC9, 0x5D64, 0x8DCA, 0x5D65, 0x8DCB, 0x5D66, 0x8DCC, 0x5D67, 0x8DCD, 0x5D68, 0x8DCE, 0x5D69, 0xE1D4, 0x5D6A, 0x8DCF, + 0x5D6B, 0xE1D1, 0x5D6C, 0xE1CD, 0x5D6D, 0x8DD0, 0x5D6E, 0x8DD1, 0x5D6F, 0xE1CF, 0x5D70, 0x8DD2, 0x5D71, 0x8DD3, 0x5D72, 0x8DD4, + 0x5D73, 0x8DD5, 0x5D74, 0xE1D5, 0x5D75, 0x8DD6, 0x5D76, 0x8DD7, 0x5D77, 0x8DD8, 0x5D78, 0x8DD9, 0x5D79, 0x8DDA, 0x5D7A, 0x8DDB, + 0x5D7B, 0x8DDC, 0x5D7C, 0x8DDD, 0x5D7D, 0x8DDE, 0x5D7E, 0x8DDF, 0x5D7F, 0x8DE0, 0x5D80, 0x8DE1, 0x5D81, 0x8DE2, 0x5D82, 0xE1D6, + 0x5D83, 0x8DE3, 0x5D84, 0x8DE4, 0x5D85, 0x8DE5, 0x5D86, 0x8DE6, 0x5D87, 0x8DE7, 0x5D88, 0x8DE8, 0x5D89, 0x8DE9, 0x5D8A, 0x8DEA, + 0x5D8B, 0x8DEB, 0x5D8C, 0x8DEC, 0x5D8D, 0x8DED, 0x5D8E, 0x8DEE, 0x5D8F, 0x8DEF, 0x5D90, 0x8DF0, 0x5D91, 0x8DF1, 0x5D92, 0x8DF2, + 0x5D93, 0x8DF3, 0x5D94, 0x8DF4, 0x5D95, 0x8DF5, 0x5D96, 0x8DF6, 0x5D97, 0x8DF7, 0x5D98, 0x8DF8, 0x5D99, 0xE1D7, 0x5D9A, 0x8DF9, + 0x5D9B, 0x8DFA, 0x5D9C, 0x8DFB, 0x5D9D, 0xE1D8, 0x5D9E, 0x8DFC, 0x5D9F, 0x8DFD, 0x5DA0, 0x8DFE, 0x5DA1, 0x8E40, 0x5DA2, 0x8E41, + 0x5DA3, 0x8E42, 0x5DA4, 0x8E43, 0x5DA5, 0x8E44, 0x5DA6, 0x8E45, 0x5DA7, 0x8E46, 0x5DA8, 0x8E47, 0x5DA9, 0x8E48, 0x5DAA, 0x8E49, + 0x5DAB, 0x8E4A, 0x5DAC, 0x8E4B, 0x5DAD, 0x8E4C, 0x5DAE, 0x8E4D, 0x5DAF, 0x8E4E, 0x5DB0, 0x8E4F, 0x5DB1, 0x8E50, 0x5DB2, 0x8E51, + 0x5DB3, 0x8E52, 0x5DB4, 0x8E53, 0x5DB5, 0x8E54, 0x5DB6, 0x8E55, 0x5DB7, 0xE1DA, 0x5DB8, 0x8E56, 0x5DB9, 0x8E57, 0x5DBA, 0x8E58, + 0x5DBB, 0x8E59, 0x5DBC, 0x8E5A, 0x5DBD, 0x8E5B, 0x5DBE, 0x8E5C, 0x5DBF, 0x8E5D, 0x5DC0, 0x8E5E, 0x5DC1, 0x8E5F, 0x5DC2, 0x8E60, + 0x5DC3, 0x8E61, 0x5DC4, 0x8E62, 0x5DC5, 0xE1DB, 0x5DC6, 0x8E63, 0x5DC7, 0x8E64, 0x5DC8, 0x8E65, 0x5DC9, 0x8E66, 0x5DCA, 0x8E67, + 0x5DCB, 0x8E68, 0x5DCC, 0x8E69, 0x5DCD, 0xCEA1, 0x5DCE, 0x8E6A, 0x5DCF, 0x8E6B, 0x5DD0, 0x8E6C, 0x5DD1, 0x8E6D, 0x5DD2, 0x8E6E, + 0x5DD3, 0x8E6F, 0x5DD4, 0x8E70, 0x5DD5, 0x8E71, 0x5DD6, 0x8E72, 0x5DD7, 0x8E73, 0x5DD8, 0x8E74, 0x5DD9, 0x8E75, 0x5DDA, 0x8E76, + 0x5DDB, 0xE7DD, 0x5DDC, 0x8E77, 0x5DDD, 0xB4A8, 0x5DDE, 0xD6DD, 0x5DDF, 0x8E78, 0x5DE0, 0x8E79, 0x5DE1, 0xD1B2, 0x5DE2, 0xB3B2, + 0x5DE3, 0x8E7A, 0x5DE4, 0x8E7B, 0x5DE5, 0xB9A4, 0x5DE6, 0xD7F3, 0x5DE7, 0xC7C9, 0x5DE8, 0xBEDE, 0x5DE9, 0xB9AE, 0x5DEA, 0x8E7C, + 0x5DEB, 0xCED7, 0x5DEC, 0x8E7D, 0x5DED, 0x8E7E, 0x5DEE, 0xB2EE, 0x5DEF, 0xDBCF, 0x5DF0, 0x8E80, 0x5DF1, 0xBCBA, 0x5DF2, 0xD2D1, + 0x5DF3, 0xCBC8, 0x5DF4, 0xB0CD, 0x5DF5, 0x8E81, 0x5DF6, 0x8E82, 0x5DF7, 0xCFEF, 0x5DF8, 0x8E83, 0x5DF9, 0x8E84, 0x5DFA, 0x8E85, + 0x5DFB, 0x8E86, 0x5DFC, 0x8E87, 0x5DFD, 0xD9E3, 0x5DFE, 0xBDED, 0x5DFF, 0x8E88, 0x5E00, 0x8E89, 0x5E01, 0xB1D2, 0x5E02, 0xCAD0, + 0x5E03, 0xB2BC, 0x5E04, 0x8E8A, 0x5E05, 0xCBA7, 0x5E06, 0xB7AB, 0x5E07, 0x8E8B, 0x5E08, 0xCAA6, 0x5E09, 0x8E8C, 0x5E0A, 0x8E8D, + 0x5E0B, 0x8E8E, 0x5E0C, 0xCFA3, 0x5E0D, 0x8E8F, 0x5E0E, 0x8E90, 0x5E0F, 0xE0F8, 0x5E10, 0xD5CA, 0x5E11, 0xE0FB, 0x5E12, 0x8E91, + 0x5E13, 0x8E92, 0x5E14, 0xE0FA, 0x5E15, 0xC5C1, 0x5E16, 0xCCFB, 0x5E17, 0x8E93, 0x5E18, 0xC1B1, 0x5E19, 0xE0F9, 0x5E1A, 0xD6E3, + 0x5E1B, 0xB2AF, 0x5E1C, 0xD6C4, 0x5E1D, 0xB5DB, 0x5E1E, 0x8E94, 0x5E1F, 0x8E95, 0x5E20, 0x8E96, 0x5E21, 0x8E97, 0x5E22, 0x8E98, + 0x5E23, 0x8E99, 0x5E24, 0x8E9A, 0x5E25, 0x8E9B, 0x5E26, 0xB4F8, 0x5E27, 0xD6A1, 0x5E28, 0x8E9C, 0x5E29, 0x8E9D, 0x5E2A, 0x8E9E, + 0x5E2B, 0x8E9F, 0x5E2C, 0x8EA0, 0x5E2D, 0xCFAF, 0x5E2E, 0xB0EF, 0x5E2F, 0x8EA1, 0x5E30, 0x8EA2, 0x5E31, 0xE0FC, 0x5E32, 0x8EA3, + 0x5E33, 0x8EA4, 0x5E34, 0x8EA5, 0x5E35, 0x8EA6, 0x5E36, 0x8EA7, 0x5E37, 0xE1A1, 0x5E38, 0xB3A3, 0x5E39, 0x8EA8, 0x5E3A, 0x8EA9, + 0x5E3B, 0xE0FD, 0x5E3C, 0xE0FE, 0x5E3D, 0xC3B1, 0x5E3E, 0x8EAA, 0x5E3F, 0x8EAB, 0x5E40, 0x8EAC, 0x5E41, 0x8EAD, 0x5E42, 0xC3DD, + 0x5E43, 0x8EAE, 0x5E44, 0xE1A2, 0x5E45, 0xB7F9, 0x5E46, 0x8EAF, 0x5E47, 0x8EB0, 0x5E48, 0x8EB1, 0x5E49, 0x8EB2, 0x5E4A, 0x8EB3, + 0x5E4B, 0x8EB4, 0x5E4C, 0xBBCF, 0x5E4D, 0x8EB5, 0x5E4E, 0x8EB6, 0x5E4F, 0x8EB7, 0x5E50, 0x8EB8, 0x5E51, 0x8EB9, 0x5E52, 0x8EBA, + 0x5E53, 0x8EBB, 0x5E54, 0xE1A3, 0x5E55, 0xC4BB, 0x5E56, 0x8EBC, 0x5E57, 0x8EBD, 0x5E58, 0x8EBE, 0x5E59, 0x8EBF, 0x5E5A, 0x8EC0, + 0x5E5B, 0xE1A4, 0x5E5C, 0x8EC1, 0x5E5D, 0x8EC2, 0x5E5E, 0xE1A5, 0x5E5F, 0x8EC3, 0x5E60, 0x8EC4, 0x5E61, 0xE1A6, 0x5E62, 0xB4B1, + 0x5E63, 0x8EC5, 0x5E64, 0x8EC6, 0x5E65, 0x8EC7, 0x5E66, 0x8EC8, 0x5E67, 0x8EC9, 0x5E68, 0x8ECA, 0x5E69, 0x8ECB, 0x5E6A, 0x8ECC, + 0x5E6B, 0x8ECD, 0x5E6C, 0x8ECE, 0x5E6D, 0x8ECF, 0x5E6E, 0x8ED0, 0x5E6F, 0x8ED1, 0x5E70, 0x8ED2, 0x5E71, 0x8ED3, 0x5E72, 0xB8C9, + 0x5E73, 0xC6BD, 0x5E74, 0xC4EA, 0x5E75, 0x8ED4, 0x5E76, 0xB2A2, 0x5E77, 0x8ED5, 0x5E78, 0xD0D2, 0x5E79, 0x8ED6, 0x5E7A, 0xE7DB, + 0x5E7B, 0xBBC3, 0x5E7C, 0xD3D7, 0x5E7D, 0xD3C4, 0x5E7E, 0x8ED7, 0x5E7F, 0xB9E3, 0x5E80, 0xE2CF, 0x5E81, 0x8ED8, 0x5E82, 0x8ED9, + 0x5E83, 0x8EDA, 0x5E84, 0xD7AF, 0x5E85, 0x8EDB, 0x5E86, 0xC7EC, 0x5E87, 0xB1D3, 0x5E88, 0x8EDC, 0x5E89, 0x8EDD, 0x5E8A, 0xB4B2, + 0x5E8B, 0xE2D1, 0x5E8C, 0x8EDE, 0x5E8D, 0x8EDF, 0x5E8E, 0x8EE0, 0x5E8F, 0xD0F2, 0x5E90, 0xC2AE, 0x5E91, 0xE2D0, 0x5E92, 0x8EE1, + 0x5E93, 0xBFE2, 0x5E94, 0xD3A6, 0x5E95, 0xB5D7, 0x5E96, 0xE2D2, 0x5E97, 0xB5EA, 0x5E98, 0x8EE2, 0x5E99, 0xC3ED, 0x5E9A, 0xB8FD, + 0x5E9B, 0x8EE3, 0x5E9C, 0xB8AE, 0x5E9D, 0x8EE4, 0x5E9E, 0xC5D3, 0x5E9F, 0xB7CF, 0x5EA0, 0xE2D4, 0x5EA1, 0x8EE5, 0x5EA2, 0x8EE6, + 0x5EA3, 0x8EE7, 0x5EA4, 0x8EE8, 0x5EA5, 0xE2D3, 0x5EA6, 0xB6C8, 0x5EA7, 0xD7F9, 0x5EA8, 0x8EE9, 0x5EA9, 0x8EEA, 0x5EAA, 0x8EEB, + 0x5EAB, 0x8EEC, 0x5EAC, 0x8EED, 0x5EAD, 0xCDA5, 0x5EAE, 0x8EEE, 0x5EAF, 0x8EEF, 0x5EB0, 0x8EF0, 0x5EB1, 0x8EF1, 0x5EB2, 0x8EF2, + 0x5EB3, 0xE2D8, 0x5EB4, 0x8EF3, 0x5EB5, 0xE2D6, 0x5EB6, 0xCAFC, 0x5EB7, 0xBFB5, 0x5EB8, 0xD3B9, 0x5EB9, 0xE2D5, 0x5EBA, 0x8EF4, + 0x5EBB, 0x8EF5, 0x5EBC, 0x8EF6, 0x5EBD, 0x8EF7, 0x5EBE, 0xE2D7, 0x5EBF, 0x8EF8, 0x5EC0, 0x8EF9, 0x5EC1, 0x8EFA, 0x5EC2, 0x8EFB, + 0x5EC3, 0x8EFC, 0x5EC4, 0x8EFD, 0x5EC5, 0x8EFE, 0x5EC6, 0x8F40, 0x5EC7, 0x8F41, 0x5EC8, 0x8F42, 0x5EC9, 0xC1AE, 0x5ECA, 0xC0C8, + 0x5ECB, 0x8F43, 0x5ECC, 0x8F44, 0x5ECD, 0x8F45, 0x5ECE, 0x8F46, 0x5ECF, 0x8F47, 0x5ED0, 0x8F48, 0x5ED1, 0xE2DB, 0x5ED2, 0xE2DA, + 0x5ED3, 0xC0AA, 0x5ED4, 0x8F49, 0x5ED5, 0x8F4A, 0x5ED6, 0xC1CE, 0x5ED7, 0x8F4B, 0x5ED8, 0x8F4C, 0x5ED9, 0x8F4D, 0x5EDA, 0x8F4E, + 0x5EDB, 0xE2DC, 0x5EDC, 0x8F4F, 0x5EDD, 0x8F50, 0x5EDE, 0x8F51, 0x5EDF, 0x8F52, 0x5EE0, 0x8F53, 0x5EE1, 0x8F54, 0x5EE2, 0x8F55, + 0x5EE3, 0x8F56, 0x5EE4, 0x8F57, 0x5EE5, 0x8F58, 0x5EE6, 0x8F59, 0x5EE7, 0x8F5A, 0x5EE8, 0xE2DD, 0x5EE9, 0x8F5B, 0x5EEA, 0xE2DE, + 0x5EEB, 0x8F5C, 0x5EEC, 0x8F5D, 0x5EED, 0x8F5E, 0x5EEE, 0x8F5F, 0x5EEF, 0x8F60, 0x5EF0, 0x8F61, 0x5EF1, 0x8F62, 0x5EF2, 0x8F63, + 0x5EF3, 0x8F64, 0x5EF4, 0xDBC8, 0x5EF5, 0x8F65, 0x5EF6, 0xD1D3, 0x5EF7, 0xCDA2, 0x5EF8, 0x8F66, 0x5EF9, 0x8F67, 0x5EFA, 0xBDA8, + 0x5EFB, 0x8F68, 0x5EFC, 0x8F69, 0x5EFD, 0x8F6A, 0x5EFE, 0xDEC3, 0x5EFF, 0xD8A5, 0x5F00, 0xBFAA, 0x5F01, 0xDBCD, 0x5F02, 0xD2EC, + 0x5F03, 0xC6FA, 0x5F04, 0xC5AA, 0x5F05, 0x8F6B, 0x5F06, 0x8F6C, 0x5F07, 0x8F6D, 0x5F08, 0xDEC4, 0x5F09, 0x8F6E, 0x5F0A, 0xB1D7, + 0x5F0B, 0xDFAE, 0x5F0C, 0x8F6F, 0x5F0D, 0x8F70, 0x5F0E, 0x8F71, 0x5F0F, 0xCABD, 0x5F10, 0x8F72, 0x5F11, 0xDFB1, 0x5F12, 0x8F73, + 0x5F13, 0xB9AD, 0x5F14, 0x8F74, 0x5F15, 0xD2FD, 0x5F16, 0x8F75, 0x5F17, 0xB8A5, 0x5F18, 0xBAEB, 0x5F19, 0x8F76, 0x5F1A, 0x8F77, + 0x5F1B, 0xB3DA, 0x5F1C, 0x8F78, 0x5F1D, 0x8F79, 0x5F1E, 0x8F7A, 0x5F1F, 0xB5DC, 0x5F20, 0xD5C5, 0x5F21, 0x8F7B, 0x5F22, 0x8F7C, + 0x5F23, 0x8F7D, 0x5F24, 0x8F7E, 0x5F25, 0xC3D6, 0x5F26, 0xCFD2, 0x5F27, 0xBBA1, 0x5F28, 0x8F80, 0x5F29, 0xE5F3, 0x5F2A, 0xE5F2, + 0x5F2B, 0x8F81, 0x5F2C, 0x8F82, 0x5F2D, 0xE5F4, 0x5F2E, 0x8F83, 0x5F2F, 0xCDE4, 0x5F30, 0x8F84, 0x5F31, 0xC8F5, 0x5F32, 0x8F85, + 0x5F33, 0x8F86, 0x5F34, 0x8F87, 0x5F35, 0x8F88, 0x5F36, 0x8F89, 0x5F37, 0x8F8A, 0x5F38, 0x8F8B, 0x5F39, 0xB5AF, 0x5F3A, 0xC7BF, + 0x5F3B, 0x8F8C, 0x5F3C, 0xE5F6, 0x5F3D, 0x8F8D, 0x5F3E, 0x8F8E, 0x5F3F, 0x8F8F, 0x5F40, 0xECB0, 0x5F41, 0x8F90, 0x5F42, 0x8F91, + 0x5F43, 0x8F92, 0x5F44, 0x8F93, 0x5F45, 0x8F94, 0x5F46, 0x8F95, 0x5F47, 0x8F96, 0x5F48, 0x8F97, 0x5F49, 0x8F98, 0x5F4A, 0x8F99, + 0x5F4B, 0x8F9A, 0x5F4C, 0x8F9B, 0x5F4D, 0x8F9C, 0x5F4E, 0x8F9D, 0x5F4F, 0x8F9E, 0x5F50, 0xE5E6, 0x5F51, 0x8F9F, 0x5F52, 0xB9E9, + 0x5F53, 0xB5B1, 0x5F54, 0x8FA0, 0x5F55, 0xC2BC, 0x5F56, 0xE5E8, 0x5F57, 0xE5E7, 0x5F58, 0xE5E9, 0x5F59, 0x8FA1, 0x5F5A, 0x8FA2, + 0x5F5B, 0x8FA3, 0x5F5C, 0x8FA4, 0x5F5D, 0xD2CD, 0x5F5E, 0x8FA5, 0x5F5F, 0x8FA6, 0x5F60, 0x8FA7, 0x5F61, 0xE1EA, 0x5F62, 0xD0CE, + 0x5F63, 0x8FA8, 0x5F64, 0xCDAE, 0x5F65, 0x8FA9, 0x5F66, 0xD1E5, 0x5F67, 0x8FAA, 0x5F68, 0x8FAB, 0x5F69, 0xB2CA, 0x5F6A, 0xB1EB, + 0x5F6B, 0x8FAC, 0x5F6C, 0xB1F2, 0x5F6D, 0xC5ED, 0x5F6E, 0x8FAD, 0x5F6F, 0x8FAE, 0x5F70, 0xD5C3, 0x5F71, 0xD3B0, 0x5F72, 0x8FAF, + 0x5F73, 0xE1DC, 0x5F74, 0x8FB0, 0x5F75, 0x8FB1, 0x5F76, 0x8FB2, 0x5F77, 0xE1DD, 0x5F78, 0x8FB3, 0x5F79, 0xD2DB, 0x5F7A, 0x8FB4, + 0x5F7B, 0xB3B9, 0x5F7C, 0xB1CB, 0x5F7D, 0x8FB5, 0x5F7E, 0x8FB6, 0x5F7F, 0x8FB7, 0x5F80, 0xCDF9, 0x5F81, 0xD5F7, 0x5F82, 0xE1DE, + 0x5F83, 0x8FB8, 0x5F84, 0xBEB6, 0x5F85, 0xB4FD, 0x5F86, 0x8FB9, 0x5F87, 0xE1DF, 0x5F88, 0xBADC, 0x5F89, 0xE1E0, 0x5F8A, 0xBBB2, + 0x5F8B, 0xC2C9, 0x5F8C, 0xE1E1, 0x5F8D, 0x8FBA, 0x5F8E, 0x8FBB, 0x5F8F, 0x8FBC, 0x5F90, 0xD0EC, 0x5F91, 0x8FBD, 0x5F92, 0xCDBD, + 0x5F93, 0x8FBE, 0x5F94, 0x8FBF, 0x5F95, 0xE1E2, 0x5F96, 0x8FC0, 0x5F97, 0xB5C3, 0x5F98, 0xC5C7, 0x5F99, 0xE1E3, 0x5F9A, 0x8FC1, + 0x5F9B, 0x8FC2, 0x5F9C, 0xE1E4, 0x5F9D, 0x8FC3, 0x5F9E, 0x8FC4, 0x5F9F, 0x8FC5, 0x5FA0, 0x8FC6, 0x5FA1, 0xD3F9, 0x5FA2, 0x8FC7, + 0x5FA3, 0x8FC8, 0x5FA4, 0x8FC9, 0x5FA5, 0x8FCA, 0x5FA6, 0x8FCB, 0x5FA7, 0x8FCC, 0x5FA8, 0xE1E5, 0x5FA9, 0x8FCD, 0x5FAA, 0xD1AD, + 0x5FAB, 0x8FCE, 0x5FAC, 0x8FCF, 0x5FAD, 0xE1E6, 0x5FAE, 0xCEA2, 0x5FAF, 0x8FD0, 0x5FB0, 0x8FD1, 0x5FB1, 0x8FD2, 0x5FB2, 0x8FD3, + 0x5FB3, 0x8FD4, 0x5FB4, 0x8FD5, 0x5FB5, 0xE1E7, 0x5FB6, 0x8FD6, 0x5FB7, 0xB5C2, 0x5FB8, 0x8FD7, 0x5FB9, 0x8FD8, 0x5FBA, 0x8FD9, + 0x5FBB, 0x8FDA, 0x5FBC, 0xE1E8, 0x5FBD, 0xBBD5, 0x5FBE, 0x8FDB, 0x5FBF, 0x8FDC, 0x5FC0, 0x8FDD, 0x5FC1, 0x8FDE, 0x5FC2, 0x8FDF, + 0x5FC3, 0xD0C4, 0x5FC4, 0xE2E0, 0x5FC5, 0xB1D8, 0x5FC6, 0xD2E4, 0x5FC7, 0x8FE0, 0x5FC8, 0x8FE1, 0x5FC9, 0xE2E1, 0x5FCA, 0x8FE2, + 0x5FCB, 0x8FE3, 0x5FCC, 0xBCC9, 0x5FCD, 0xC8CC, 0x5FCE, 0x8FE4, 0x5FCF, 0xE2E3, 0x5FD0, 0xECFE, 0x5FD1, 0xECFD, 0x5FD2, 0xDFAF, + 0x5FD3, 0x8FE5, 0x5FD4, 0x8FE6, 0x5FD5, 0x8FE7, 0x5FD6, 0xE2E2, 0x5FD7, 0xD6BE, 0x5FD8, 0xCDFC, 0x5FD9, 0xC3A6, 0x5FDA, 0x8FE8, + 0x5FDB, 0x8FE9, 0x5FDC, 0x8FEA, 0x5FDD, 0xE3C3, 0x5FDE, 0x8FEB, 0x5FDF, 0x8FEC, 0x5FE0, 0xD6D2, 0x5FE1, 0xE2E7, 0x5FE2, 0x8FED, + 0x5FE3, 0x8FEE, 0x5FE4, 0xE2E8, 0x5FE5, 0x8FEF, 0x5FE6, 0x8FF0, 0x5FE7, 0xD3C7, 0x5FE8, 0x8FF1, 0x5FE9, 0x8FF2, 0x5FEA, 0xE2EC, + 0x5FEB, 0xBFEC, 0x5FEC, 0x8FF3, 0x5FED, 0xE2ED, 0x5FEE, 0xE2E5, 0x5FEF, 0x8FF4, 0x5FF0, 0x8FF5, 0x5FF1, 0xB3C0, 0x5FF2, 0x8FF6, + 0x5FF3, 0x8FF7, 0x5FF4, 0x8FF8, 0x5FF5, 0xC4EE, 0x5FF6, 0x8FF9, 0x5FF7, 0x8FFA, 0x5FF8, 0xE2EE, 0x5FF9, 0x8FFB, 0x5FFA, 0x8FFC, + 0x5FFB, 0xD0C3, 0x5FFC, 0x8FFD, 0x5FFD, 0xBAF6, 0x5FFE, 0xE2E9, 0x5FFF, 0xB7DE, 0x6000, 0xBBB3, 0x6001, 0xCCAC, 0x6002, 0xCBCB, + 0x6003, 0xE2E4, 0x6004, 0xE2E6, 0x6005, 0xE2EA, 0x6006, 0xE2EB, 0x6007, 0x8FFE, 0x6008, 0x9040, 0x6009, 0x9041, 0x600A, 0xE2F7, + 0x600B, 0x9042, 0x600C, 0x9043, 0x600D, 0xE2F4, 0x600E, 0xD4F5, 0x600F, 0xE2F3, 0x6010, 0x9044, 0x6011, 0x9045, 0x6012, 0xC5AD, + 0x6013, 0x9046, 0x6014, 0xD5FA, 0x6015, 0xC5C2, 0x6016, 0xB2C0, 0x6017, 0x9047, 0x6018, 0x9048, 0x6019, 0xE2EF, 0x601A, 0x9049, + 0x601B, 0xE2F2, 0x601C, 0xC1AF, 0x601D, 0xCBBC, 0x601E, 0x904A, 0x601F, 0x904B, 0x6020, 0xB5A1, 0x6021, 0xE2F9, 0x6022, 0x904C, + 0x6023, 0x904D, 0x6024, 0x904E, 0x6025, 0xBCB1, 0x6026, 0xE2F1, 0x6027, 0xD0D4, 0x6028, 0xD4B9, 0x6029, 0xE2F5, 0x602A, 0xB9D6, + 0x602B, 0xE2F6, 0x602C, 0x904F, 0x602D, 0x9050, 0x602E, 0x9051, 0x602F, 0xC7D3, 0x6030, 0x9052, 0x6031, 0x9053, 0x6032, 0x9054, + 0x6033, 0x9055, 0x6034, 0x9056, 0x6035, 0xE2F0, 0x6036, 0x9057, 0x6037, 0x9058, 0x6038, 0x9059, 0x6039, 0x905A, 0x603A, 0x905B, + 0x603B, 0xD7DC, 0x603C, 0xEDA1, 0x603D, 0x905C, 0x603E, 0x905D, 0x603F, 0xE2F8, 0x6040, 0x905E, 0x6041, 0xEDA5, 0x6042, 0xE2FE, + 0x6043, 0xCAD1, 0x6044, 0x905F, 0x6045, 0x9060, 0x6046, 0x9061, 0x6047, 0x9062, 0x6048, 0x9063, 0x6049, 0x9064, 0x604A, 0x9065, + 0x604B, 0xC1B5, 0x604C, 0x9066, 0x604D, 0xBBD0, 0x604E, 0x9067, 0x604F, 0x9068, 0x6050, 0xBFD6, 0x6051, 0x9069, 0x6052, 0xBAE3, + 0x6053, 0x906A, 0x6054, 0x906B, 0x6055, 0xCBA1, 0x6056, 0x906C, 0x6057, 0x906D, 0x6058, 0x906E, 0x6059, 0xEDA6, 0x605A, 0xEDA3, + 0x605B, 0x906F, 0x605C, 0x9070, 0x605D, 0xEDA2, 0x605E, 0x9071, 0x605F, 0x9072, 0x6060, 0x9073, 0x6061, 0x9074, 0x6062, 0xBBD6, + 0x6063, 0xEDA7, 0x6064, 0xD0F4, 0x6065, 0x9075, 0x6066, 0x9076, 0x6067, 0xEDA4, 0x6068, 0xBADE, 0x6069, 0xB6F7, 0x606A, 0xE3A1, + 0x606B, 0xB6B2, 0x606C, 0xCCF1, 0x606D, 0xB9A7, 0x606E, 0x9077, 0x606F, 0xCFA2, 0x6070, 0xC7A1, 0x6071, 0x9078, 0x6072, 0x9079, + 0x6073, 0xBFD2, 0x6074, 0x907A, 0x6075, 0x907B, 0x6076, 0xB6F1, 0x6077, 0x907C, 0x6078, 0xE2FA, 0x6079, 0xE2FB, 0x607A, 0xE2FD, + 0x607B, 0xE2FC, 0x607C, 0xC4D5, 0x607D, 0xE3A2, 0x607E, 0x907D, 0x607F, 0xD3C1, 0x6080, 0x907E, 0x6081, 0x9080, 0x6082, 0x9081, + 0x6083, 0xE3A7, 0x6084, 0xC7C4, 0x6085, 0x9082, 0x6086, 0x9083, 0x6087, 0x9084, 0x6088, 0x9085, 0x6089, 0xCFA4, 0x608A, 0x9086, + 0x608B, 0x9087, 0x608C, 0xE3A9, 0x608D, 0xBAB7, 0x608E, 0x9088, 0x608F, 0x9089, 0x6090, 0x908A, 0x6091, 0x908B, 0x6092, 0xE3A8, + 0x6093, 0x908C, 0x6094, 0xBBDA, 0x6095, 0x908D, 0x6096, 0xE3A3, 0x6097, 0x908E, 0x6098, 0x908F, 0x6099, 0x9090, 0x609A, 0xE3A4, + 0x609B, 0xE3AA, 0x609C, 0x9091, 0x609D, 0xE3A6, 0x609E, 0x9092, 0x609F, 0xCEF2, 0x60A0, 0xD3C6, 0x60A1, 0x9093, 0x60A2, 0x9094, + 0x60A3, 0xBBBC, 0x60A4, 0x9095, 0x60A5, 0x9096, 0x60A6, 0xD4C3, 0x60A7, 0x9097, 0x60A8, 0xC4FA, 0x60A9, 0x9098, 0x60AA, 0x9099, + 0x60AB, 0xEDA8, 0x60AC, 0xD0FC, 0x60AD, 0xE3A5, 0x60AE, 0x909A, 0x60AF, 0xC3F5, 0x60B0, 0x909B, 0x60B1, 0xE3AD, 0x60B2, 0xB1AF, + 0x60B3, 0x909C, 0x60B4, 0xE3B2, 0x60B5, 0x909D, 0x60B6, 0x909E, 0x60B7, 0x909F, 0x60B8, 0xBCC2, 0x60B9, 0x90A0, 0x60BA, 0x90A1, + 0x60BB, 0xE3AC, 0x60BC, 0xB5BF, 0x60BD, 0x90A2, 0x60BE, 0x90A3, 0x60BF, 0x90A4, 0x60C0, 0x90A5, 0x60C1, 0x90A6, 0x60C2, 0x90A7, + 0x60C3, 0x90A8, 0x60C4, 0x90A9, 0x60C5, 0xC7E9, 0x60C6, 0xE3B0, 0x60C7, 0x90AA, 0x60C8, 0x90AB, 0x60C9, 0x90AC, 0x60CA, 0xBEAA, + 0x60CB, 0xCDEF, 0x60CC, 0x90AD, 0x60CD, 0x90AE, 0x60CE, 0x90AF, 0x60CF, 0x90B0, 0x60D0, 0x90B1, 0x60D1, 0xBBF3, 0x60D2, 0x90B2, + 0x60D3, 0x90B3, 0x60D4, 0x90B4, 0x60D5, 0xCCE8, 0x60D6, 0x90B5, 0x60D7, 0x90B6, 0x60D8, 0xE3AF, 0x60D9, 0x90B7, 0x60DA, 0xE3B1, + 0x60DB, 0x90B8, 0x60DC, 0xCFA7, 0x60DD, 0xE3AE, 0x60DE, 0x90B9, 0x60DF, 0xCEA9, 0x60E0, 0xBBDD, 0x60E1, 0x90BA, 0x60E2, 0x90BB, + 0x60E3, 0x90BC, 0x60E4, 0x90BD, 0x60E5, 0x90BE, 0x60E6, 0xB5EB, 0x60E7, 0xBEE5, 0x60E8, 0xB2D2, 0x60E9, 0xB3CD, 0x60EA, 0x90BF, + 0x60EB, 0xB1B9, 0x60EC, 0xE3AB, 0x60ED, 0xB2D1, 0x60EE, 0xB5AC, 0x60EF, 0xB9DF, 0x60F0, 0xB6E8, 0x60F1, 0x90C0, 0x60F2, 0x90C1, + 0x60F3, 0xCFEB, 0x60F4, 0xE3B7, 0x60F5, 0x90C2, 0x60F6, 0xBBCC, 0x60F7, 0x90C3, 0x60F8, 0x90C4, 0x60F9, 0xC8C7, 0x60FA, 0xD0CA, + 0x60FB, 0x90C5, 0x60FC, 0x90C6, 0x60FD, 0x90C7, 0x60FE, 0x90C8, 0x60FF, 0x90C9, 0x6100, 0xE3B8, 0x6101, 0xB3EE, 0x6102, 0x90CA, + 0x6103, 0x90CB, 0x6104, 0x90CC, 0x6105, 0x90CD, 0x6106, 0xEDA9, 0x6107, 0x90CE, 0x6108, 0xD3FA, 0x6109, 0xD3E4, 0x610A, 0x90CF, + 0x610B, 0x90D0, 0x610C, 0x90D1, 0x610D, 0xEDAA, 0x610E, 0xE3B9, 0x610F, 0xD2E2, 0x6110, 0x90D2, 0x6111, 0x90D3, 0x6112, 0x90D4, + 0x6113, 0x90D5, 0x6114, 0x90D6, 0x6115, 0xE3B5, 0x6116, 0x90D7, 0x6117, 0x90D8, 0x6118, 0x90D9, 0x6119, 0x90DA, 0x611A, 0xD3DE, + 0x611B, 0x90DB, 0x611C, 0x90DC, 0x611D, 0x90DD, 0x611E, 0x90DE, 0x611F, 0xB8D0, 0x6120, 0xE3B3, 0x6121, 0x90DF, 0x6122, 0x90E0, + 0x6123, 0xE3B6, 0x6124, 0xB7DF, 0x6125, 0x90E1, 0x6126, 0xE3B4, 0x6127, 0xC0A2, 0x6128, 0x90E2, 0x6129, 0x90E3, 0x612A, 0x90E4, + 0x612B, 0xE3BA, 0x612C, 0x90E5, 0x612D, 0x90E6, 0x612E, 0x90E7, 0x612F, 0x90E8, 0x6130, 0x90E9, 0x6131, 0x90EA, 0x6132, 0x90EB, + 0x6133, 0x90EC, 0x6134, 0x90ED, 0x6135, 0x90EE, 0x6136, 0x90EF, 0x6137, 0x90F0, 0x6138, 0x90F1, 0x6139, 0x90F2, 0x613A, 0x90F3, + 0x613B, 0x90F4, 0x613C, 0x90F5, 0x613D, 0x90F6, 0x613E, 0x90F7, 0x613F, 0xD4B8, 0x6140, 0x90F8, 0x6141, 0x90F9, 0x6142, 0x90FA, + 0x6143, 0x90FB, 0x6144, 0x90FC, 0x6145, 0x90FD, 0x6146, 0x90FE, 0x6147, 0x9140, 0x6148, 0xB4C8, 0x6149, 0x9141, 0x614A, 0xE3BB, + 0x614B, 0x9142, 0x614C, 0xBBC5, 0x614D, 0x9143, 0x614E, 0xC9F7, 0x614F, 0x9144, 0x6150, 0x9145, 0x6151, 0xC9E5, 0x6152, 0x9146, + 0x6153, 0x9147, 0x6154, 0x9148, 0x6155, 0xC4BD, 0x6156, 0x9149, 0x6157, 0x914A, 0x6158, 0x914B, 0x6159, 0x914C, 0x615A, 0x914D, + 0x615B, 0x914E, 0x615C, 0x914F, 0x615D, 0xEDAB, 0x615E, 0x9150, 0x615F, 0x9151, 0x6160, 0x9152, 0x6161, 0x9153, 0x6162, 0xC2FD, + 0x6163, 0x9154, 0x6164, 0x9155, 0x6165, 0x9156, 0x6166, 0x9157, 0x6167, 0xBBDB, 0x6168, 0xBFAE, 0x6169, 0x9158, 0x616A, 0x9159, + 0x616B, 0x915A, 0x616C, 0x915B, 0x616D, 0x915C, 0x616E, 0x915D, 0x616F, 0x915E, 0x6170, 0xCEBF, 0x6171, 0x915F, 0x6172, 0x9160, + 0x6173, 0x9161, 0x6174, 0x9162, 0x6175, 0xE3BC, 0x6176, 0x9163, 0x6177, 0xBFB6, 0x6178, 0x9164, 0x6179, 0x9165, 0x617A, 0x9166, + 0x617B, 0x9167, 0x617C, 0x9168, 0x617D, 0x9169, 0x617E, 0x916A, 0x617F, 0x916B, 0x6180, 0x916C, 0x6181, 0x916D, 0x6182, 0x916E, + 0x6183, 0x916F, 0x6184, 0x9170, 0x6185, 0x9171, 0x6186, 0x9172, 0x6187, 0x9173, 0x6188, 0x9174, 0x6189, 0x9175, 0x618A, 0x9176, + 0x618B, 0xB1EF, 0x618C, 0x9177, 0x618D, 0x9178, 0x618E, 0xD4F7, 0x618F, 0x9179, 0x6190, 0x917A, 0x6191, 0x917B, 0x6192, 0x917C, + 0x6193, 0x917D, 0x6194, 0xE3BE, 0x6195, 0x917E, 0x6196, 0x9180, 0x6197, 0x9181, 0x6198, 0x9182, 0x6199, 0x9183, 0x619A, 0x9184, + 0x619B, 0x9185, 0x619C, 0x9186, 0x619D, 0xEDAD, 0x619E, 0x9187, 0x619F, 0x9188, 0x61A0, 0x9189, 0x61A1, 0x918A, 0x61A2, 0x918B, + 0x61A3, 0x918C, 0x61A4, 0x918D, 0x61A5, 0x918E, 0x61A6, 0x918F, 0x61A7, 0xE3BF, 0x61A8, 0xBAA9, 0x61A9, 0xEDAC, 0x61AA, 0x9190, + 0x61AB, 0x9191, 0x61AC, 0xE3BD, 0x61AD, 0x9192, 0x61AE, 0x9193, 0x61AF, 0x9194, 0x61B0, 0x9195, 0x61B1, 0x9196, 0x61B2, 0x9197, + 0x61B3, 0x9198, 0x61B4, 0x9199, 0x61B5, 0x919A, 0x61B6, 0x919B, 0x61B7, 0xE3C0, 0x61B8, 0x919C, 0x61B9, 0x919D, 0x61BA, 0x919E, + 0x61BB, 0x919F, 0x61BC, 0x91A0, 0x61BD, 0x91A1, 0x61BE, 0xBAB6, 0x61BF, 0x91A2, 0x61C0, 0x91A3, 0x61C1, 0x91A4, 0x61C2, 0xB6AE, + 0x61C3, 0x91A5, 0x61C4, 0x91A6, 0x61C5, 0x91A7, 0x61C6, 0x91A8, 0x61C7, 0x91A9, 0x61C8, 0xD0B8, 0x61C9, 0x91AA, 0x61CA, 0xB0C3, + 0x61CB, 0xEDAE, 0x61CC, 0x91AB, 0x61CD, 0x91AC, 0x61CE, 0x91AD, 0x61CF, 0x91AE, 0x61D0, 0x91AF, 0x61D1, 0xEDAF, 0x61D2, 0xC0C1, + 0x61D3, 0x91B0, 0x61D4, 0xE3C1, 0x61D5, 0x91B1, 0x61D6, 0x91B2, 0x61D7, 0x91B3, 0x61D8, 0x91B4, 0x61D9, 0x91B5, 0x61DA, 0x91B6, + 0x61DB, 0x91B7, 0x61DC, 0x91B8, 0x61DD, 0x91B9, 0x61DE, 0x91BA, 0x61DF, 0x91BB, 0x61E0, 0x91BC, 0x61E1, 0x91BD, 0x61E2, 0x91BE, + 0x61E3, 0x91BF, 0x61E4, 0x91C0, 0x61E5, 0x91C1, 0x61E6, 0xC5B3, 0x61E7, 0x91C2, 0x61E8, 0x91C3, 0x61E9, 0x91C4, 0x61EA, 0x91C5, + 0x61EB, 0x91C6, 0x61EC, 0x91C7, 0x61ED, 0x91C8, 0x61EE, 0x91C9, 0x61EF, 0x91CA, 0x61F0, 0x91CB, 0x61F1, 0x91CC, 0x61F2, 0x91CD, + 0x61F3, 0x91CE, 0x61F4, 0x91CF, 0x61F5, 0xE3C2, 0x61F6, 0x91D0, 0x61F7, 0x91D1, 0x61F8, 0x91D2, 0x61F9, 0x91D3, 0x61FA, 0x91D4, + 0x61FB, 0x91D5, 0x61FC, 0x91D6, 0x61FD, 0x91D7, 0x61FE, 0x91D8, 0x61FF, 0xDCB2, 0x6200, 0x91D9, 0x6201, 0x91DA, 0x6202, 0x91DB, + 0x6203, 0x91DC, 0x6204, 0x91DD, 0x6205, 0x91DE, 0x6206, 0xEDB0, 0x6207, 0x91DF, 0x6208, 0xB8EA, 0x6209, 0x91E0, 0x620A, 0xCEEC, + 0x620B, 0xEAA7, 0x620C, 0xD0E7, 0x620D, 0xCAF9, 0x620E, 0xC8D6, 0x620F, 0xCFB7, 0x6210, 0xB3C9, 0x6211, 0xCED2, 0x6212, 0xBDE4, + 0x6213, 0x91E1, 0x6214, 0x91E2, 0x6215, 0xE3DE, 0x6216, 0xBBF2, 0x6217, 0xEAA8, 0x6218, 0xD5BD, 0x6219, 0x91E3, 0x621A, 0xC6DD, + 0x621B, 0xEAA9, 0x621C, 0x91E4, 0x621D, 0x91E5, 0x621E, 0x91E6, 0x621F, 0xEAAA, 0x6220, 0x91E7, 0x6221, 0xEAAC, 0x6222, 0xEAAB, + 0x6223, 0x91E8, 0x6224, 0xEAAE, 0x6225, 0xEAAD, 0x6226, 0x91E9, 0x6227, 0x91EA, 0x6228, 0x91EB, 0x6229, 0x91EC, 0x622A, 0xBDD8, + 0x622B, 0x91ED, 0x622C, 0xEAAF, 0x622D, 0x91EE, 0x622E, 0xC2BE, 0x622F, 0x91EF, 0x6230, 0x91F0, 0x6231, 0x91F1, 0x6232, 0x91F2, + 0x6233, 0xB4C1, 0x6234, 0xB4F7, 0x6235, 0x91F3, 0x6236, 0x91F4, 0x6237, 0xBBA7, 0x6238, 0x91F5, 0x6239, 0x91F6, 0x623A, 0x91F7, + 0x623B, 0x91F8, 0x623C, 0x91F9, 0x623D, 0xECE6, 0x623E, 0xECE5, 0x623F, 0xB7BF, 0x6240, 0xCBF9, 0x6241, 0xB1E2, 0x6242, 0x91FA, + 0x6243, 0xECE7, 0x6244, 0x91FB, 0x6245, 0x91FC, 0x6246, 0x91FD, 0x6247, 0xC9C8, 0x6248, 0xECE8, 0x6249, 0xECE9, 0x624A, 0x91FE, + 0x624B, 0xCAD6, 0x624C, 0xDED0, 0x624D, 0xB2C5, 0x624E, 0xD4FA, 0x624F, 0x9240, 0x6250, 0x9241, 0x6251, 0xC6CB, 0x6252, 0xB0C7, + 0x6253, 0xB4F2, 0x6254, 0xC8D3, 0x6255, 0x9242, 0x6256, 0x9243, 0x6257, 0x9244, 0x6258, 0xCDD0, 0x6259, 0x9245, 0x625A, 0x9246, + 0x625B, 0xBFB8, 0x625C, 0x9247, 0x625D, 0x9248, 0x625E, 0x9249, 0x625F, 0x924A, 0x6260, 0x924B, 0x6261, 0x924C, 0x6262, 0x924D, + 0x6263, 0xBFDB, 0x6264, 0x924E, 0x6265, 0x924F, 0x6266, 0xC7A4, 0x6267, 0xD6B4, 0x6268, 0x9250, 0x6269, 0xC0A9, 0x626A, 0xDED1, + 0x626B, 0xC9A8, 0x626C, 0xD1EF, 0x626D, 0xC5A4, 0x626E, 0xB0E7, 0x626F, 0xB3B6, 0x6270, 0xC8C5, 0x6271, 0x9251, 0x6272, 0x9252, + 0x6273, 0xB0E2, 0x6274, 0x9253, 0x6275, 0x9254, 0x6276, 0xB7F6, 0x6277, 0x9255, 0x6278, 0x9256, 0x6279, 0xC5FA, 0x627A, 0x9257, + 0x627B, 0x9258, 0x627C, 0xB6F3, 0x627D, 0x9259, 0x627E, 0xD5D2, 0x627F, 0xB3D0, 0x6280, 0xBCBC, 0x6281, 0x925A, 0x6282, 0x925B, + 0x6283, 0x925C, 0x6284, 0xB3AD, 0x6285, 0x925D, 0x6286, 0x925E, 0x6287, 0x925F, 0x6288, 0x9260, 0x6289, 0xBEF1, 0x628A, 0xB0D1, + 0x628B, 0x9261, 0x628C, 0x9262, 0x628D, 0x9263, 0x628E, 0x9264, 0x628F, 0x9265, 0x6290, 0x9266, 0x6291, 0xD2D6, 0x6292, 0xCAE3, + 0x6293, 0xD7A5, 0x6294, 0x9267, 0x6295, 0xCDB6, 0x6296, 0xB6B6, 0x6297, 0xBFB9, 0x6298, 0xD5DB, 0x6299, 0x9268, 0x629A, 0xB8A7, + 0x629B, 0xC5D7, 0x629C, 0x9269, 0x629D, 0x926A, 0x629E, 0x926B, 0x629F, 0xDED2, 0x62A0, 0xBFD9, 0x62A1, 0xC2D5, 0x62A2, 0xC7C0, + 0x62A3, 0x926C, 0x62A4, 0xBBA4, 0x62A5, 0xB1A8, 0x62A6, 0x926D, 0x62A7, 0x926E, 0x62A8, 0xC5EA, 0x62A9, 0x926F, 0x62AA, 0x9270, + 0x62AB, 0xC5FB, 0x62AC, 0xCCA7, 0x62AD, 0x9271, 0x62AE, 0x9272, 0x62AF, 0x9273, 0x62B0, 0x9274, 0x62B1, 0xB1A7, 0x62B2, 0x9275, + 0x62B3, 0x9276, 0x62B4, 0x9277, 0x62B5, 0xB5D6, 0x62B6, 0x9278, 0x62B7, 0x9279, 0x62B8, 0x927A, 0x62B9, 0xC4A8, 0x62BA, 0x927B, + 0x62BB, 0xDED3, 0x62BC, 0xD1BA, 0x62BD, 0xB3E9, 0x62BE, 0x927C, 0x62BF, 0xC3F2, 0x62C0, 0x927D, 0x62C1, 0x927E, 0x62C2, 0xB7F7, + 0x62C3, 0x9280, 0x62C4, 0xD6F4, 0x62C5, 0xB5A3, 0x62C6, 0xB2F0, 0x62C7, 0xC4B4, 0x62C8, 0xC4E9, 0x62C9, 0xC0AD, 0x62CA, 0xDED4, + 0x62CB, 0x9281, 0x62CC, 0xB0E8, 0x62CD, 0xC5C4, 0x62CE, 0xC1E0, 0x62CF, 0x9282, 0x62D0, 0xB9D5, 0x62D1, 0x9283, 0x62D2, 0xBEDC, + 0x62D3, 0xCDD8, 0x62D4, 0xB0CE, 0x62D5, 0x9284, 0x62D6, 0xCDCF, 0x62D7, 0xDED6, 0x62D8, 0xBED0, 0x62D9, 0xD7BE, 0x62DA, 0xDED5, + 0x62DB, 0xD5D0, 0x62DC, 0xB0DD, 0x62DD, 0x9285, 0x62DE, 0x9286, 0x62DF, 0xC4E2, 0x62E0, 0x9287, 0x62E1, 0x9288, 0x62E2, 0xC2A3, + 0x62E3, 0xBCF0, 0x62E4, 0x9289, 0x62E5, 0xD3B5, 0x62E6, 0xC0B9, 0x62E7, 0xC5A1, 0x62E8, 0xB2A6, 0x62E9, 0xD4F1, 0x62EA, 0x928A, + 0x62EB, 0x928B, 0x62EC, 0xC0A8, 0x62ED, 0xCAC3, 0x62EE, 0xDED7, 0x62EF, 0xD5FC, 0x62F0, 0x928C, 0x62F1, 0xB9B0, 0x62F2, 0x928D, + 0x62F3, 0xC8AD, 0x62F4, 0xCBA9, 0x62F5, 0x928E, 0x62F6, 0xDED9, 0x62F7, 0xBFBD, 0x62F8, 0x928F, 0x62F9, 0x9290, 0x62FA, 0x9291, + 0x62FB, 0x9292, 0x62FC, 0xC6B4, 0x62FD, 0xD7A7, 0x62FE, 0xCAB0, 0x62FF, 0xC4C3, 0x6300, 0x9293, 0x6301, 0xB3D6, 0x6302, 0xB9D2, + 0x6303, 0x9294, 0x6304, 0x9295, 0x6305, 0x9296, 0x6306, 0x9297, 0x6307, 0xD6B8, 0x6308, 0xEAFC, 0x6309, 0xB0B4, 0x630A, 0x9298, + 0x630B, 0x9299, 0x630C, 0x929A, 0x630D, 0x929B, 0x630E, 0xBFE6, 0x630F, 0x929C, 0x6310, 0x929D, 0x6311, 0xCCF4, 0x6312, 0x929E, + 0x6313, 0x929F, 0x6314, 0x92A0, 0x6315, 0x92A1, 0x6316, 0xCDDA, 0x6317, 0x92A2, 0x6318, 0x92A3, 0x6319, 0x92A4, 0x631A, 0xD6BF, + 0x631B, 0xC2CE, 0x631C, 0x92A5, 0x631D, 0xCECE, 0x631E, 0xCCA2, 0x631F, 0xD0AE, 0x6320, 0xC4D3, 0x6321, 0xB5B2, 0x6322, 0xDED8, + 0x6323, 0xD5F5, 0x6324, 0xBCB7, 0x6325, 0xBBD3, 0x6326, 0x92A6, 0x6327, 0x92A7, 0x6328, 0xB0A4, 0x6329, 0x92A8, 0x632A, 0xC5B2, + 0x632B, 0xB4EC, 0x632C, 0x92A9, 0x632D, 0x92AA, 0x632E, 0x92AB, 0x632F, 0xD5F1, 0x6330, 0x92AC, 0x6331, 0x92AD, 0x6332, 0xEAFD, + 0x6333, 0x92AE, 0x6334, 0x92AF, 0x6335, 0x92B0, 0x6336, 0x92B1, 0x6337, 0x92B2, 0x6338, 0x92B3, 0x6339, 0xDEDA, 0x633A, 0xCDA6, + 0x633B, 0x92B4, 0x633C, 0x92B5, 0x633D, 0xCDEC, 0x633E, 0x92B6, 0x633F, 0x92B7, 0x6340, 0x92B8, 0x6341, 0x92B9, 0x6342, 0xCEE6, + 0x6343, 0xDEDC, 0x6344, 0x92BA, 0x6345, 0xCDB1, 0x6346, 0xC0A6, 0x6347, 0x92BB, 0x6348, 0x92BC, 0x6349, 0xD7BD, 0x634A, 0x92BD, + 0x634B, 0xDEDB, 0x634C, 0xB0C6, 0x634D, 0xBAB4, 0x634E, 0xC9D3, 0x634F, 0xC4F3, 0x6350, 0xBEE8, 0x6351, 0x92BE, 0x6352, 0x92BF, + 0x6353, 0x92C0, 0x6354, 0x92C1, 0x6355, 0xB2B6, 0x6356, 0x92C2, 0x6357, 0x92C3, 0x6358, 0x92C4, 0x6359, 0x92C5, 0x635A, 0x92C6, + 0x635B, 0x92C7, 0x635C, 0x92C8, 0x635D, 0x92C9, 0x635E, 0xC0CC, 0x635F, 0xCBF0, 0x6360, 0x92CA, 0x6361, 0xBCF1, 0x6362, 0xBBBB, + 0x6363, 0xB5B7, 0x6364, 0x92CB, 0x6365, 0x92CC, 0x6366, 0x92CD, 0x6367, 0xC5F5, 0x6368, 0x92CE, 0x6369, 0xDEE6, 0x636A, 0x92CF, + 0x636B, 0x92D0, 0x636C, 0x92D1, 0x636D, 0xDEE3, 0x636E, 0xBEDD, 0x636F, 0x92D2, 0x6370, 0x92D3, 0x6371, 0xDEDF, 0x6372, 0x92D4, + 0x6373, 0x92D5, 0x6374, 0x92D6, 0x6375, 0x92D7, 0x6376, 0xB4B7, 0x6377, 0xBDDD, 0x6378, 0x92D8, 0x6379, 0x92D9, 0x637A, 0xDEE0, + 0x637B, 0xC4ED, 0x637C, 0x92DA, 0x637D, 0x92DB, 0x637E, 0x92DC, 0x637F, 0x92DD, 0x6380, 0xCFC6, 0x6381, 0x92DE, 0x6382, 0xB5E0, + 0x6383, 0x92DF, 0x6384, 0x92E0, 0x6385, 0x92E1, 0x6386, 0x92E2, 0x6387, 0xB6DE, 0x6388, 0xCADA, 0x6389, 0xB5F4, 0x638A, 0xDEE5, + 0x638B, 0x92E3, 0x638C, 0xD5C6, 0x638D, 0x92E4, 0x638E, 0xDEE1, 0x638F, 0xCCCD, 0x6390, 0xC6FE, 0x6391, 0x92E5, 0x6392, 0xC5C5, + 0x6393, 0x92E6, 0x6394, 0x92E7, 0x6395, 0x92E8, 0x6396, 0xD2B4, 0x6397, 0x92E9, 0x6398, 0xBEF2, 0x6399, 0x92EA, 0x639A, 0x92EB, + 0x639B, 0x92EC, 0x639C, 0x92ED, 0x639D, 0x92EE, 0x639E, 0x92EF, 0x639F, 0x92F0, 0x63A0, 0xC2D3, 0x63A1, 0x92F1, 0x63A2, 0xCCBD, + 0x63A3, 0xB3B8, 0x63A4, 0x92F2, 0x63A5, 0xBDD3, 0x63A6, 0x92F3, 0x63A7, 0xBFD8, 0x63A8, 0xCDC6, 0x63A9, 0xD1DA, 0x63AA, 0xB4EB, + 0x63AB, 0x92F4, 0x63AC, 0xDEE4, 0x63AD, 0xDEDD, 0x63AE, 0xDEE7, 0x63AF, 0x92F5, 0x63B0, 0xEAFE, 0x63B1, 0x92F6, 0x63B2, 0x92F7, + 0x63B3, 0xC2B0, 0x63B4, 0xDEE2, 0x63B5, 0x92F8, 0x63B6, 0x92F9, 0x63B7, 0xD6C0, 0x63B8, 0xB5A7, 0x63B9, 0x92FA, 0x63BA, 0xB2F4, + 0x63BB, 0x92FB, 0x63BC, 0xDEE8, 0x63BD, 0x92FC, 0x63BE, 0xDEF2, 0x63BF, 0x92FD, 0x63C0, 0x92FE, 0x63C1, 0x9340, 0x63C2, 0x9341, + 0x63C3, 0x9342, 0x63C4, 0xDEED, 0x63C5, 0x9343, 0x63C6, 0xDEF1, 0x63C7, 0x9344, 0x63C8, 0x9345, 0x63C9, 0xC8E0, 0x63CA, 0x9346, + 0x63CB, 0x9347, 0x63CC, 0x9348, 0x63CD, 0xD7E1, 0x63CE, 0xDEEF, 0x63CF, 0xC3E8, 0x63D0, 0xCCE1, 0x63D1, 0x9349, 0x63D2, 0xB2E5, + 0x63D3, 0x934A, 0x63D4, 0x934B, 0x63D5, 0x934C, 0x63D6, 0xD2BE, 0x63D7, 0x934D, 0x63D8, 0x934E, 0x63D9, 0x934F, 0x63DA, 0x9350, + 0x63DB, 0x9351, 0x63DC, 0x9352, 0x63DD, 0x9353, 0x63DE, 0xDEEE, 0x63DF, 0x9354, 0x63E0, 0xDEEB, 0x63E1, 0xCED5, 0x63E2, 0x9355, + 0x63E3, 0xB4A7, 0x63E4, 0x9356, 0x63E5, 0x9357, 0x63E6, 0x9358, 0x63E7, 0x9359, 0x63E8, 0x935A, 0x63E9, 0xBFAB, 0x63EA, 0xBEBE, + 0x63EB, 0x935B, 0x63EC, 0x935C, 0x63ED, 0xBDD2, 0x63EE, 0x935D, 0x63EF, 0x935E, 0x63F0, 0x935F, 0x63F1, 0x9360, 0x63F2, 0xDEE9, + 0x63F3, 0x9361, 0x63F4, 0xD4AE, 0x63F5, 0x9362, 0x63F6, 0xDEDE, 0x63F7, 0x9363, 0x63F8, 0xDEEA, 0x63F9, 0x9364, 0x63FA, 0x9365, + 0x63FB, 0x9366, 0x63FC, 0x9367, 0x63FD, 0xC0BF, 0x63FE, 0x9368, 0x63FF, 0xDEEC, 0x6400, 0xB2F3, 0x6401, 0xB8E9, 0x6402, 0xC2A7, + 0x6403, 0x9369, 0x6404, 0x936A, 0x6405, 0xBDC1, 0x6406, 0x936B, 0x6407, 0x936C, 0x6408, 0x936D, 0x6409, 0x936E, 0x640A, 0x936F, + 0x640B, 0xDEF5, 0x640C, 0xDEF8, 0x640D, 0x9370, 0x640E, 0x9371, 0x640F, 0xB2AB, 0x6410, 0xB4A4, 0x6411, 0x9372, 0x6412, 0x9373, + 0x6413, 0xB4EA, 0x6414, 0xC9A6, 0x6415, 0x9374, 0x6416, 0x9375, 0x6417, 0x9376, 0x6418, 0x9377, 0x6419, 0x9378, 0x641A, 0x9379, + 0x641B, 0xDEF6, 0x641C, 0xCBD1, 0x641D, 0x937A, 0x641E, 0xB8E3, 0x641F, 0x937B, 0x6420, 0xDEF7, 0x6421, 0xDEFA, 0x6422, 0x937C, + 0x6423, 0x937D, 0x6424, 0x937E, 0x6425, 0x9380, 0x6426, 0xDEF9, 0x6427, 0x9381, 0x6428, 0x9382, 0x6429, 0x9383, 0x642A, 0xCCC2, + 0x642B, 0x9384, 0x642C, 0xB0E1, 0x642D, 0xB4EE, 0x642E, 0x9385, 0x642F, 0x9386, 0x6430, 0x9387, 0x6431, 0x9388, 0x6432, 0x9389, + 0x6433, 0x938A, 0x6434, 0xE5BA, 0x6435, 0x938B, 0x6436, 0x938C, 0x6437, 0x938D, 0x6438, 0x938E, 0x6439, 0x938F, 0x643A, 0xD0AF, + 0x643B, 0x9390, 0x643C, 0x9391, 0x643D, 0xB2EB, 0x643E, 0x9392, 0x643F, 0xEBA1, 0x6440, 0x9393, 0x6441, 0xDEF4, 0x6442, 0x9394, + 0x6443, 0x9395, 0x6444, 0xC9E3, 0x6445, 0xDEF3, 0x6446, 0xB0DA, 0x6447, 0xD2A1, 0x6448, 0xB1F7, 0x6449, 0x9396, 0x644A, 0xCCAF, + 0x644B, 0x9397, 0x644C, 0x9398, 0x644D, 0x9399, 0x644E, 0x939A, 0x644F, 0x939B, 0x6450, 0x939C, 0x6451, 0x939D, 0x6452, 0xDEF0, + 0x6453, 0x939E, 0x6454, 0xCBA4, 0x6455, 0x939F, 0x6456, 0x93A0, 0x6457, 0x93A1, 0x6458, 0xD5AA, 0x6459, 0x93A2, 0x645A, 0x93A3, + 0x645B, 0x93A4, 0x645C, 0x93A5, 0x645D, 0x93A6, 0x645E, 0xDEFB, 0x645F, 0x93A7, 0x6460, 0x93A8, 0x6461, 0x93A9, 0x6462, 0x93AA, + 0x6463, 0x93AB, 0x6464, 0x93AC, 0x6465, 0x93AD, 0x6466, 0x93AE, 0x6467, 0xB4DD, 0x6468, 0x93AF, 0x6469, 0xC4A6, 0x646A, 0x93B0, + 0x646B, 0x93B1, 0x646C, 0x93B2, 0x646D, 0xDEFD, 0x646E, 0x93B3, 0x646F, 0x93B4, 0x6470, 0x93B5, 0x6471, 0x93B6, 0x6472, 0x93B7, + 0x6473, 0x93B8, 0x6474, 0x93B9, 0x6475, 0x93BA, 0x6476, 0x93BB, 0x6477, 0x93BC, 0x6478, 0xC3FE, 0x6479, 0xC4A1, 0x647A, 0xDFA1, + 0x647B, 0x93BD, 0x647C, 0x93BE, 0x647D, 0x93BF, 0x647E, 0x93C0, 0x647F, 0x93C1, 0x6480, 0x93C2, 0x6481, 0x93C3, 0x6482, 0xC1CC, + 0x6483, 0x93C4, 0x6484, 0xDEFC, 0x6485, 0xBEEF, 0x6486, 0x93C5, 0x6487, 0xC6B2, 0x6488, 0x93C6, 0x6489, 0x93C7, 0x648A, 0x93C8, + 0x648B, 0x93C9, 0x648C, 0x93CA, 0x648D, 0x93CB, 0x648E, 0x93CC, 0x648F, 0x93CD, 0x6490, 0x93CE, 0x6491, 0xB3C5, 0x6492, 0xC8F6, + 0x6493, 0x93CF, 0x6494, 0x93D0, 0x6495, 0xCBBA, 0x6496, 0xDEFE, 0x6497, 0x93D1, 0x6498, 0x93D2, 0x6499, 0xDFA4, 0x649A, 0x93D3, + 0x649B, 0x93D4, 0x649C, 0x93D5, 0x649D, 0x93D6, 0x649E, 0xD7B2, 0x649F, 0x93D7, 0x64A0, 0x93D8, 0x64A1, 0x93D9, 0x64A2, 0x93DA, + 0x64A3, 0x93DB, 0x64A4, 0xB3B7, 0x64A5, 0x93DC, 0x64A6, 0x93DD, 0x64A7, 0x93DE, 0x64A8, 0x93DF, 0x64A9, 0xC1C3, 0x64AA, 0x93E0, + 0x64AB, 0x93E1, 0x64AC, 0xC7CB, 0x64AD, 0xB2A5, 0x64AE, 0xB4E9, 0x64AF, 0x93E2, 0x64B0, 0xD7AB, 0x64B1, 0x93E3, 0x64B2, 0x93E4, + 0x64B3, 0x93E5, 0x64B4, 0x93E6, 0x64B5, 0xC4EC, 0x64B6, 0x93E7, 0x64B7, 0xDFA2, 0x64B8, 0xDFA3, 0x64B9, 0x93E8, 0x64BA, 0xDFA5, + 0x64BB, 0x93E9, 0x64BC, 0xBAB3, 0x64BD, 0x93EA, 0x64BE, 0x93EB, 0x64BF, 0x93EC, 0x64C0, 0xDFA6, 0x64C1, 0x93ED, 0x64C2, 0xC0DE, + 0x64C3, 0x93EE, 0x64C4, 0x93EF, 0x64C5, 0xC9C3, 0x64C6, 0x93F0, 0x64C7, 0x93F1, 0x64C8, 0x93F2, 0x64C9, 0x93F3, 0x64CA, 0x93F4, + 0x64CB, 0x93F5, 0x64CC, 0x93F6, 0x64CD, 0xB2D9, 0x64CE, 0xC7E6, 0x64CF, 0x93F7, 0x64D0, 0xDFA7, 0x64D1, 0x93F8, 0x64D2, 0xC7DC, + 0x64D3, 0x93F9, 0x64D4, 0x93FA, 0x64D5, 0x93FB, 0x64D6, 0x93FC, 0x64D7, 0xDFA8, 0x64D8, 0xEBA2, 0x64D9, 0x93FD, 0x64DA, 0x93FE, + 0x64DB, 0x9440, 0x64DC, 0x9441, 0x64DD, 0x9442, 0x64DE, 0xCBD3, 0x64DF, 0x9443, 0x64E0, 0x9444, 0x64E1, 0x9445, 0x64E2, 0xDFAA, + 0x64E3, 0x9446, 0x64E4, 0xDFA9, 0x64E5, 0x9447, 0x64E6, 0xB2C1, 0x64E7, 0x9448, 0x64E8, 0x9449, 0x64E9, 0x944A, 0x64EA, 0x944B, + 0x64EB, 0x944C, 0x64EC, 0x944D, 0x64ED, 0x944E, 0x64EE, 0x944F, 0x64EF, 0x9450, 0x64F0, 0x9451, 0x64F1, 0x9452, 0x64F2, 0x9453, + 0x64F3, 0x9454, 0x64F4, 0x9455, 0x64F5, 0x9456, 0x64F6, 0x9457, 0x64F7, 0x9458, 0x64F8, 0x9459, 0x64F9, 0x945A, 0x64FA, 0x945B, + 0x64FB, 0x945C, 0x64FC, 0x945D, 0x64FD, 0x945E, 0x64FE, 0x945F, 0x64FF, 0x9460, 0x6500, 0xC5CA, 0x6501, 0x9461, 0x6502, 0x9462, + 0x6503, 0x9463, 0x6504, 0x9464, 0x6505, 0x9465, 0x6506, 0x9466, 0x6507, 0x9467, 0x6508, 0x9468, 0x6509, 0xDFAB, 0x650A, 0x9469, + 0x650B, 0x946A, 0x650C, 0x946B, 0x650D, 0x946C, 0x650E, 0x946D, 0x650F, 0x946E, 0x6510, 0x946F, 0x6511, 0x9470, 0x6512, 0xD4DC, + 0x6513, 0x9471, 0x6514, 0x9472, 0x6515, 0x9473, 0x6516, 0x9474, 0x6517, 0x9475, 0x6518, 0xC8C1, 0x6519, 0x9476, 0x651A, 0x9477, + 0x651B, 0x9478, 0x651C, 0x9479, 0x651D, 0x947A, 0x651E, 0x947B, 0x651F, 0x947C, 0x6520, 0x947D, 0x6521, 0x947E, 0x6522, 0x9480, + 0x6523, 0x9481, 0x6524, 0x9482, 0x6525, 0xDFAC, 0x6526, 0x9483, 0x6527, 0x9484, 0x6528, 0x9485, 0x6529, 0x9486, 0x652A, 0x9487, + 0x652B, 0xBEF0, 0x652C, 0x9488, 0x652D, 0x9489, 0x652E, 0xDFAD, 0x652F, 0xD6A7, 0x6530, 0x948A, 0x6531, 0x948B, 0x6532, 0x948C, + 0x6533, 0x948D, 0x6534, 0xEAB7, 0x6535, 0xEBB6, 0x6536, 0xCAD5, 0x6537, 0x948E, 0x6538, 0xD8FC, 0x6539, 0xB8C4, 0x653A, 0x948F, + 0x653B, 0xB9A5, 0x653C, 0x9490, 0x653D, 0x9491, 0x653E, 0xB7C5, 0x653F, 0xD5FE, 0x6540, 0x9492, 0x6541, 0x9493, 0x6542, 0x9494, + 0x6543, 0x9495, 0x6544, 0x9496, 0x6545, 0xB9CA, 0x6546, 0x9497, 0x6547, 0x9498, 0x6548, 0xD0A7, 0x6549, 0xF4CD, 0x654A, 0x9499, + 0x654B, 0x949A, 0x654C, 0xB5D0, 0x654D, 0x949B, 0x654E, 0x949C, 0x654F, 0xC3F4, 0x6550, 0x949D, 0x6551, 0xBEC8, 0x6552, 0x949E, + 0x6553, 0x949F, 0x6554, 0x94A0, 0x6555, 0xEBB7, 0x6556, 0xB0BD, 0x6557, 0x94A1, 0x6558, 0x94A2, 0x6559, 0xBDCC, 0x655A, 0x94A3, + 0x655B, 0xC1B2, 0x655C, 0x94A4, 0x655D, 0xB1D6, 0x655E, 0xB3A8, 0x655F, 0x94A5, 0x6560, 0x94A6, 0x6561, 0x94A7, 0x6562, 0xB8D2, + 0x6563, 0xC9A2, 0x6564, 0x94A8, 0x6565, 0x94A9, 0x6566, 0xB6D8, 0x6567, 0x94AA, 0x6568, 0x94AB, 0x6569, 0x94AC, 0x656A, 0x94AD, + 0x656B, 0xEBB8, 0x656C, 0xBEB4, 0x656D, 0x94AE, 0x656E, 0x94AF, 0x656F, 0x94B0, 0x6570, 0xCAFD, 0x6571, 0x94B1, 0x6572, 0xC7C3, + 0x6573, 0x94B2, 0x6574, 0xD5FB, 0x6575, 0x94B3, 0x6576, 0x94B4, 0x6577, 0xB7F3, 0x6578, 0x94B5, 0x6579, 0x94B6, 0x657A, 0x94B7, + 0x657B, 0x94B8, 0x657C, 0x94B9, 0x657D, 0x94BA, 0x657E, 0x94BB, 0x657F, 0x94BC, 0x6580, 0x94BD, 0x6581, 0x94BE, 0x6582, 0x94BF, + 0x6583, 0x94C0, 0x6584, 0x94C1, 0x6585, 0x94C2, 0x6586, 0x94C3, 0x6587, 0xCEC4, 0x6588, 0x94C4, 0x6589, 0x94C5, 0x658A, 0x94C6, + 0x658B, 0xD5AB, 0x658C, 0xB1F3, 0x658D, 0x94C7, 0x658E, 0x94C8, 0x658F, 0x94C9, 0x6590, 0xECB3, 0x6591, 0xB0DF, 0x6592, 0x94CA, + 0x6593, 0xECB5, 0x6594, 0x94CB, 0x6595, 0x94CC, 0x6596, 0x94CD, 0x6597, 0xB6B7, 0x6598, 0x94CE, 0x6599, 0xC1CF, 0x659A, 0x94CF, + 0x659B, 0xF5FA, 0x659C, 0xD0B1, 0x659D, 0x94D0, 0x659E, 0x94D1, 0x659F, 0xD5E5, 0x65A0, 0x94D2, 0x65A1, 0xCED3, 0x65A2, 0x94D3, + 0x65A3, 0x94D4, 0x65A4, 0xBDEF, 0x65A5, 0xB3E2, 0x65A6, 0x94D5, 0x65A7, 0xB8AB, 0x65A8, 0x94D6, 0x65A9, 0xD5B6, 0x65AA, 0x94D7, + 0x65AB, 0xEDBD, 0x65AC, 0x94D8, 0x65AD, 0xB6CF, 0x65AE, 0x94D9, 0x65AF, 0xCBB9, 0x65B0, 0xD0C2, 0x65B1, 0x94DA, 0x65B2, 0x94DB, + 0x65B3, 0x94DC, 0x65B4, 0x94DD, 0x65B5, 0x94DE, 0x65B6, 0x94DF, 0x65B7, 0x94E0, 0x65B8, 0x94E1, 0x65B9, 0xB7BD, 0x65BA, 0x94E2, + 0x65BB, 0x94E3, 0x65BC, 0xECB6, 0x65BD, 0xCAA9, 0x65BE, 0x94E4, 0x65BF, 0x94E5, 0x65C0, 0x94E6, 0x65C1, 0xC5D4, 0x65C2, 0x94E7, + 0x65C3, 0xECB9, 0x65C4, 0xECB8, 0x65C5, 0xC2C3, 0x65C6, 0xECB7, 0x65C7, 0x94E8, 0x65C8, 0x94E9, 0x65C9, 0x94EA, 0x65CA, 0x94EB, + 0x65CB, 0xD0FD, 0x65CC, 0xECBA, 0x65CD, 0x94EC, 0x65CE, 0xECBB, 0x65CF, 0xD7E5, 0x65D0, 0x94ED, 0x65D1, 0x94EE, 0x65D2, 0xECBC, + 0x65D3, 0x94EF, 0x65D4, 0x94F0, 0x65D5, 0x94F1, 0x65D6, 0xECBD, 0x65D7, 0xC6EC, 0x65D8, 0x94F2, 0x65D9, 0x94F3, 0x65DA, 0x94F4, + 0x65DB, 0x94F5, 0x65DC, 0x94F6, 0x65DD, 0x94F7, 0x65DE, 0x94F8, 0x65DF, 0x94F9, 0x65E0, 0xCEDE, 0x65E1, 0x94FA, 0x65E2, 0xBCC8, + 0x65E3, 0x94FB, 0x65E4, 0x94FC, 0x65E5, 0xC8D5, 0x65E6, 0xB5A9, 0x65E7, 0xBEC9, 0x65E8, 0xD6BC, 0x65E9, 0xD4E7, 0x65EA, 0x94FD, + 0x65EB, 0x94FE, 0x65EC, 0xD1AE, 0x65ED, 0xD0F1, 0x65EE, 0xEAB8, 0x65EF, 0xEAB9, 0x65F0, 0xEABA, 0x65F1, 0xBAB5, 0x65F2, 0x9540, + 0x65F3, 0x9541, 0x65F4, 0x9542, 0x65F5, 0x9543, 0x65F6, 0xCAB1, 0x65F7, 0xBFF5, 0x65F8, 0x9544, 0x65F9, 0x9545, 0x65FA, 0xCDFA, + 0x65FB, 0x9546, 0x65FC, 0x9547, 0x65FD, 0x9548, 0x65FE, 0x9549, 0x65FF, 0x954A, 0x6600, 0xEAC0, 0x6601, 0x954B, 0x6602, 0xB0BA, + 0x6603, 0xEABE, 0x6604, 0x954C, 0x6605, 0x954D, 0x6606, 0xC0A5, 0x6607, 0x954E, 0x6608, 0x954F, 0x6609, 0x9550, 0x660A, 0xEABB, + 0x660B, 0x9551, 0x660C, 0xB2FD, 0x660D, 0x9552, 0x660E, 0xC3F7, 0x660F, 0xBBE8, 0x6610, 0x9553, 0x6611, 0x9554, 0x6612, 0x9555, + 0x6613, 0xD2D7, 0x6614, 0xCEF4, 0x6615, 0xEABF, 0x6616, 0x9556, 0x6617, 0x9557, 0x6618, 0x9558, 0x6619, 0xEABC, 0x661A, 0x9559, + 0x661B, 0x955A, 0x661C, 0x955B, 0x661D, 0xEAC3, 0x661E, 0x955C, 0x661F, 0xD0C7, 0x6620, 0xD3B3, 0x6621, 0x955D, 0x6622, 0x955E, + 0x6623, 0x955F, 0x6624, 0x9560, 0x6625, 0xB4BA, 0x6626, 0x9561, 0x6627, 0xC3C1, 0x6628, 0xD7F2, 0x6629, 0x9562, 0x662A, 0x9563, + 0x662B, 0x9564, 0x662C, 0x9565, 0x662D, 0xD5D1, 0x662E, 0x9566, 0x662F, 0xCAC7, 0x6630, 0x9567, 0x6631, 0xEAC5, 0x6632, 0x9568, + 0x6633, 0x9569, 0x6634, 0xEAC4, 0x6635, 0xEAC7, 0x6636, 0xEAC6, 0x6637, 0x956A, 0x6638, 0x956B, 0x6639, 0x956C, 0x663A, 0x956D, + 0x663B, 0x956E, 0x663C, 0xD6E7, 0x663D, 0x956F, 0x663E, 0xCFD4, 0x663F, 0x9570, 0x6640, 0x9571, 0x6641, 0xEACB, 0x6642, 0x9572, + 0x6643, 0xBBCE, 0x6644, 0x9573, 0x6645, 0x9574, 0x6646, 0x9575, 0x6647, 0x9576, 0x6648, 0x9577, 0x6649, 0x9578, 0x664A, 0x9579, + 0x664B, 0xBDFA, 0x664C, 0xC9CE, 0x664D, 0x957A, 0x664E, 0x957B, 0x664F, 0xEACC, 0x6650, 0x957C, 0x6651, 0x957D, 0x6652, 0xC9B9, + 0x6653, 0xCFFE, 0x6654, 0xEACA, 0x6655, 0xD4CE, 0x6656, 0xEACD, 0x6657, 0xEACF, 0x6658, 0x957E, 0x6659, 0x9580, 0x665A, 0xCDED, + 0x665B, 0x9581, 0x665C, 0x9582, 0x665D, 0x9583, 0x665E, 0x9584, 0x665F, 0xEAC9, 0x6660, 0x9585, 0x6661, 0xEACE, 0x6662, 0x9586, + 0x6663, 0x9587, 0x6664, 0xCEEE, 0x6665, 0x9588, 0x6666, 0xBBDE, 0x6667, 0x9589, 0x6668, 0xB3BF, 0x6669, 0x958A, 0x666A, 0x958B, + 0x666B, 0x958C, 0x666C, 0x958D, 0x666D, 0x958E, 0x666E, 0xC6D5, 0x666F, 0xBEB0, 0x6670, 0xCEFA, 0x6671, 0x958F, 0x6672, 0x9590, + 0x6673, 0x9591, 0x6674, 0xC7E7, 0x6675, 0x9592, 0x6676, 0xBEA7, 0x6677, 0xEAD0, 0x6678, 0x9593, 0x6679, 0x9594, 0x667A, 0xD6C7, + 0x667B, 0x9595, 0x667C, 0x9596, 0x667D, 0x9597, 0x667E, 0xC1C0, 0x667F, 0x9598, 0x6680, 0x9599, 0x6681, 0x959A, 0x6682, 0xD4DD, + 0x6683, 0x959B, 0x6684, 0xEAD1, 0x6685, 0x959C, 0x6686, 0x959D, 0x6687, 0xCFBE, 0x6688, 0x959E, 0x6689, 0x959F, 0x668A, 0x95A0, + 0x668B, 0x95A1, 0x668C, 0xEAD2, 0x668D, 0x95A2, 0x668E, 0x95A3, 0x668F, 0x95A4, 0x6690, 0x95A5, 0x6691, 0xCAEE, 0x6692, 0x95A6, + 0x6693, 0x95A7, 0x6694, 0x95A8, 0x6695, 0x95A9, 0x6696, 0xC5AF, 0x6697, 0xB0B5, 0x6698, 0x95AA, 0x6699, 0x95AB, 0x669A, 0x95AC, + 0x669B, 0x95AD, 0x669C, 0x95AE, 0x669D, 0xEAD4, 0x669E, 0x95AF, 0x669F, 0x95B0, 0x66A0, 0x95B1, 0x66A1, 0x95B2, 0x66A2, 0x95B3, + 0x66A3, 0x95B4, 0x66A4, 0x95B5, 0x66A5, 0x95B6, 0x66A6, 0x95B7, 0x66A7, 0xEAD3, 0x66A8, 0xF4DF, 0x66A9, 0x95B8, 0x66AA, 0x95B9, + 0x66AB, 0x95BA, 0x66AC, 0x95BB, 0x66AD, 0x95BC, 0x66AE, 0xC4BA, 0x66AF, 0x95BD, 0x66B0, 0x95BE, 0x66B1, 0x95BF, 0x66B2, 0x95C0, + 0x66B3, 0x95C1, 0x66B4, 0xB1A9, 0x66B5, 0x95C2, 0x66B6, 0x95C3, 0x66B7, 0x95C4, 0x66B8, 0x95C5, 0x66B9, 0xE5DF, 0x66BA, 0x95C6, + 0x66BB, 0x95C7, 0x66BC, 0x95C8, 0x66BD, 0x95C9, 0x66BE, 0xEAD5, 0x66BF, 0x95CA, 0x66C0, 0x95CB, 0x66C1, 0x95CC, 0x66C2, 0x95CD, + 0x66C3, 0x95CE, 0x66C4, 0x95CF, 0x66C5, 0x95D0, 0x66C6, 0x95D1, 0x66C7, 0x95D2, 0x66C8, 0x95D3, 0x66C9, 0x95D4, 0x66CA, 0x95D5, + 0x66CB, 0x95D6, 0x66CC, 0x95D7, 0x66CD, 0x95D8, 0x66CE, 0x95D9, 0x66CF, 0x95DA, 0x66D0, 0x95DB, 0x66D1, 0x95DC, 0x66D2, 0x95DD, + 0x66D3, 0x95DE, 0x66D4, 0x95DF, 0x66D5, 0x95E0, 0x66D6, 0x95E1, 0x66D7, 0x95E2, 0x66D8, 0x95E3, 0x66D9, 0xCAEF, 0x66DA, 0x95E4, + 0x66DB, 0xEAD6, 0x66DC, 0xEAD7, 0x66DD, 0xC6D8, 0x66DE, 0x95E5, 0x66DF, 0x95E6, 0x66E0, 0x95E7, 0x66E1, 0x95E8, 0x66E2, 0x95E9, + 0x66E3, 0x95EA, 0x66E4, 0x95EB, 0x66E5, 0x95EC, 0x66E6, 0xEAD8, 0x66E7, 0x95ED, 0x66E8, 0x95EE, 0x66E9, 0xEAD9, 0x66EA, 0x95EF, + 0x66EB, 0x95F0, 0x66EC, 0x95F1, 0x66ED, 0x95F2, 0x66EE, 0x95F3, 0x66EF, 0x95F4, 0x66F0, 0xD4BB, 0x66F1, 0x95F5, 0x66F2, 0xC7FA, + 0x66F3, 0xD2B7, 0x66F4, 0xB8FC, 0x66F5, 0x95F6, 0x66F6, 0x95F7, 0x66F7, 0xEAC2, 0x66F8, 0x95F8, 0x66F9, 0xB2DC, 0x66FA, 0x95F9, + 0x66FB, 0x95FA, 0x66FC, 0xC2FC, 0x66FD, 0x95FB, 0x66FE, 0xD4F8, 0x66FF, 0xCCE6, 0x6700, 0xD7EE, 0x6701, 0x95FC, 0x6702, 0x95FD, + 0x6703, 0x95FE, 0x6704, 0x9640, 0x6705, 0x9641, 0x6706, 0x9642, 0x6707, 0x9643, 0x6708, 0xD4C2, 0x6709, 0xD3D0, 0x670A, 0xEBC3, + 0x670B, 0xC5F3, 0x670C, 0x9644, 0x670D, 0xB7FE, 0x670E, 0x9645, 0x670F, 0x9646, 0x6710, 0xEBD4, 0x6711, 0x9647, 0x6712, 0x9648, + 0x6713, 0x9649, 0x6714, 0xCBB7, 0x6715, 0xEBDE, 0x6716, 0x964A, 0x6717, 0xC0CA, 0x6718, 0x964B, 0x6719, 0x964C, 0x671A, 0x964D, + 0x671B, 0xCDFB, 0x671C, 0x964E, 0x671D, 0xB3AF, 0x671E, 0x964F, 0x671F, 0xC6DA, 0x6720, 0x9650, 0x6721, 0x9651, 0x6722, 0x9652, + 0x6723, 0x9653, 0x6724, 0x9654, 0x6725, 0x9655, 0x6726, 0xEBFC, 0x6727, 0x9656, 0x6728, 0xC4BE, 0x6729, 0x9657, 0x672A, 0xCEB4, + 0x672B, 0xC4A9, 0x672C, 0xB1BE, 0x672D, 0xD4FD, 0x672E, 0x9658, 0x672F, 0xCAF5, 0x6730, 0x9659, 0x6731, 0xD6EC, 0x6732, 0x965A, + 0x6733, 0x965B, 0x6734, 0xC6D3, 0x6735, 0xB6E4, 0x6736, 0x965C, 0x6737, 0x965D, 0x6738, 0x965E, 0x6739, 0x965F, 0x673A, 0xBBFA, + 0x673B, 0x9660, 0x673C, 0x9661, 0x673D, 0xD0E0, 0x673E, 0x9662, 0x673F, 0x9663, 0x6740, 0xC9B1, 0x6741, 0x9664, 0x6742, 0xD4D3, + 0x6743, 0xC8A8, 0x6744, 0x9665, 0x6745, 0x9666, 0x6746, 0xB8CB, 0x6747, 0x9667, 0x6748, 0xE8BE, 0x6749, 0xC9BC, 0x674A, 0x9668, + 0x674B, 0x9669, 0x674C, 0xE8BB, 0x674D, 0x966A, 0x674E, 0xC0EE, 0x674F, 0xD0D3, 0x6750, 0xB2C4, 0x6751, 0xB4E5, 0x6752, 0x966B, + 0x6753, 0xE8BC, 0x6754, 0x966C, 0x6755, 0x966D, 0x6756, 0xD5C8, 0x6757, 0x966E, 0x6758, 0x966F, 0x6759, 0x9670, 0x675A, 0x9671, + 0x675B, 0x9672, 0x675C, 0xB6C5, 0x675D, 0x9673, 0x675E, 0xE8BD, 0x675F, 0xCAF8, 0x6760, 0xB8DC, 0x6761, 0xCCF5, 0x6762, 0x9674, + 0x6763, 0x9675, 0x6764, 0x9676, 0x6765, 0xC0B4, 0x6766, 0x9677, 0x6767, 0x9678, 0x6768, 0xD1EE, 0x6769, 0xE8BF, 0x676A, 0xE8C2, + 0x676B, 0x9679, 0x676C, 0x967A, 0x676D, 0xBABC, 0x676E, 0x967B, 0x676F, 0xB1AD, 0x6770, 0xBDDC, 0x6771, 0x967C, 0x6772, 0xEABD, + 0x6773, 0xE8C3, 0x6774, 0x967D, 0x6775, 0xE8C6, 0x6776, 0x967E, 0x6777, 0xE8CB, 0x6778, 0x9680, 0x6779, 0x9681, 0x677A, 0x9682, + 0x677B, 0x9683, 0x677C, 0xE8CC, 0x677D, 0x9684, 0x677E, 0xCBC9, 0x677F, 0xB0E5, 0x6780, 0x9685, 0x6781, 0xBCAB, 0x6782, 0x9686, + 0x6783, 0x9687, 0x6784, 0xB9B9, 0x6785, 0x9688, 0x6786, 0x9689, 0x6787, 0xE8C1, 0x6788, 0x968A, 0x6789, 0xCDF7, 0x678A, 0x968B, + 0x678B, 0xE8CA, 0x678C, 0x968C, 0x678D, 0x968D, 0x678E, 0x968E, 0x678F, 0x968F, 0x6790, 0xCEF6, 0x6791, 0x9690, 0x6792, 0x9691, + 0x6793, 0x9692, 0x6794, 0x9693, 0x6795, 0xD5ED, 0x6796, 0x9694, 0x6797, 0xC1D6, 0x6798, 0xE8C4, 0x6799, 0x9695, 0x679A, 0xC3B6, + 0x679B, 0x9696, 0x679C, 0xB9FB, 0x679D, 0xD6A6, 0x679E, 0xE8C8, 0x679F, 0x9697, 0x67A0, 0x9698, 0x67A1, 0x9699, 0x67A2, 0xCAE0, + 0x67A3, 0xD4E6, 0x67A4, 0x969A, 0x67A5, 0xE8C0, 0x67A6, 0x969B, 0x67A7, 0xE8C5, 0x67A8, 0xE8C7, 0x67A9, 0x969C, 0x67AA, 0xC7B9, + 0x67AB, 0xB7E3, 0x67AC, 0x969D, 0x67AD, 0xE8C9, 0x67AE, 0x969E, 0x67AF, 0xBFDD, 0x67B0, 0xE8D2, 0x67B1, 0x969F, 0x67B2, 0x96A0, + 0x67B3, 0xE8D7, 0x67B4, 0x96A1, 0x67B5, 0xE8D5, 0x67B6, 0xBCDC, 0x67B7, 0xBCCF, 0x67B8, 0xE8DB, 0x67B9, 0x96A2, 0x67BA, 0x96A3, + 0x67BB, 0x96A4, 0x67BC, 0x96A5, 0x67BD, 0x96A6, 0x67BE, 0x96A7, 0x67BF, 0x96A8, 0x67C0, 0x96A9, 0x67C1, 0xE8DE, 0x67C2, 0x96AA, + 0x67C3, 0xE8DA, 0x67C4, 0xB1FA, 0x67C5, 0x96AB, 0x67C6, 0x96AC, 0x67C7, 0x96AD, 0x67C8, 0x96AE, 0x67C9, 0x96AF, 0x67CA, 0x96B0, + 0x67CB, 0x96B1, 0x67CC, 0x96B2, 0x67CD, 0x96B3, 0x67CE, 0x96B4, 0x67CF, 0xB0D8, 0x67D0, 0xC4B3, 0x67D1, 0xB8CC, 0x67D2, 0xC6E2, + 0x67D3, 0xC8BE, 0x67D4, 0xC8E1, 0x67D5, 0x96B5, 0x67D6, 0x96B6, 0x67D7, 0x96B7, 0x67D8, 0xE8CF, 0x67D9, 0xE8D4, 0x67DA, 0xE8D6, + 0x67DB, 0x96B8, 0x67DC, 0xB9F1, 0x67DD, 0xE8D8, 0x67DE, 0xD7F5, 0x67DF, 0x96B9, 0x67E0, 0xC4FB, 0x67E1, 0x96BA, 0x67E2, 0xE8DC, + 0x67E3, 0x96BB, 0x67E4, 0x96BC, 0x67E5, 0xB2E9, 0x67E6, 0x96BD, 0x67E7, 0x96BE, 0x67E8, 0x96BF, 0x67E9, 0xE8D1, 0x67EA, 0x96C0, + 0x67EB, 0x96C1, 0x67EC, 0xBCED, 0x67ED, 0x96C2, 0x67EE, 0x96C3, 0x67EF, 0xBFC2, 0x67F0, 0xE8CD, 0x67F1, 0xD6F9, 0x67F2, 0x96C4, + 0x67F3, 0xC1F8, 0x67F4, 0xB2F1, 0x67F5, 0x96C5, 0x67F6, 0x96C6, 0x67F7, 0x96C7, 0x67F8, 0x96C8, 0x67F9, 0x96C9, 0x67FA, 0x96CA, + 0x67FB, 0x96CB, 0x67FC, 0x96CC, 0x67FD, 0xE8DF, 0x67FE, 0x96CD, 0x67FF, 0xCAC1, 0x6800, 0xE8D9, 0x6801, 0x96CE, 0x6802, 0x96CF, + 0x6803, 0x96D0, 0x6804, 0x96D1, 0x6805, 0xD5A4, 0x6806, 0x96D2, 0x6807, 0xB1EA, 0x6808, 0xD5BB, 0x6809, 0xE8CE, 0x680A, 0xE8D0, + 0x680B, 0xB6B0, 0x680C, 0xE8D3, 0x680D, 0x96D3, 0x680E, 0xE8DD, 0x680F, 0xC0B8, 0x6810, 0x96D4, 0x6811, 0xCAF7, 0x6812, 0x96D5, + 0x6813, 0xCBA8, 0x6814, 0x96D6, 0x6815, 0x96D7, 0x6816, 0xC6DC, 0x6817, 0xC0F5, 0x6818, 0x96D8, 0x6819, 0x96D9, 0x681A, 0x96DA, + 0x681B, 0x96DB, 0x681C, 0x96DC, 0x681D, 0xE8E9, 0x681E, 0x96DD, 0x681F, 0x96DE, 0x6820, 0x96DF, 0x6821, 0xD0A3, 0x6822, 0x96E0, + 0x6823, 0x96E1, 0x6824, 0x96E2, 0x6825, 0x96E3, 0x6826, 0x96E4, 0x6827, 0x96E5, 0x6828, 0x96E6, 0x6829, 0xE8F2, 0x682A, 0xD6EA, + 0x682B, 0x96E7, 0x682C, 0x96E8, 0x682D, 0x96E9, 0x682E, 0x96EA, 0x682F, 0x96EB, 0x6830, 0x96EC, 0x6831, 0x96ED, 0x6832, 0xE8E0, + 0x6833, 0xE8E1, 0x6834, 0x96EE, 0x6835, 0x96EF, 0x6836, 0x96F0, 0x6837, 0xD1F9, 0x6838, 0xBACB, 0x6839, 0xB8F9, 0x683A, 0x96F1, + 0x683B, 0x96F2, 0x683C, 0xB8F1, 0x683D, 0xD4D4, 0x683E, 0xE8EF, 0x683F, 0x96F3, 0x6840, 0xE8EE, 0x6841, 0xE8EC, 0x6842, 0xB9F0, + 0x6843, 0xCCD2, 0x6844, 0xE8E6, 0x6845, 0xCEA6, 0x6846, 0xBFF2, 0x6847, 0x96F4, 0x6848, 0xB0B8, 0x6849, 0xE8F1, 0x684A, 0xE8F0, + 0x684B, 0x96F5, 0x684C, 0xD7C0, 0x684D, 0x96F6, 0x684E, 0xE8E4, 0x684F, 0x96F7, 0x6850, 0xCDA9, 0x6851, 0xC9A3, 0x6852, 0x96F8, + 0x6853, 0xBBB8, 0x6854, 0xBDDB, 0x6855, 0xE8EA, 0x6856, 0x96F9, 0x6857, 0x96FA, 0x6858, 0x96FB, 0x6859, 0x96FC, 0x685A, 0x96FD, + 0x685B, 0x96FE, 0x685C, 0x9740, 0x685D, 0x9741, 0x685E, 0x9742, 0x685F, 0x9743, 0x6860, 0xE8E2, 0x6861, 0xE8E3, 0x6862, 0xE8E5, + 0x6863, 0xB5B5, 0x6864, 0xE8E7, 0x6865, 0xC7C5, 0x6866, 0xE8EB, 0x6867, 0xE8ED, 0x6868, 0xBDB0, 0x6869, 0xD7AE, 0x686A, 0x9744, + 0x686B, 0xE8F8, 0x686C, 0x9745, 0x686D, 0x9746, 0x686E, 0x9747, 0x686F, 0x9748, 0x6870, 0x9749, 0x6871, 0x974A, 0x6872, 0x974B, + 0x6873, 0x974C, 0x6874, 0xE8F5, 0x6875, 0x974D, 0x6876, 0xCDB0, 0x6877, 0xE8F6, 0x6878, 0x974E, 0x6879, 0x974F, 0x687A, 0x9750, + 0x687B, 0x9751, 0x687C, 0x9752, 0x687D, 0x9753, 0x687E, 0x9754, 0x687F, 0x9755, 0x6880, 0x9756, 0x6881, 0xC1BA, 0x6882, 0x9757, + 0x6883, 0xE8E8, 0x6884, 0x9758, 0x6885, 0xC3B7, 0x6886, 0xB0F0, 0x6887, 0x9759, 0x6888, 0x975A, 0x6889, 0x975B, 0x688A, 0x975C, + 0x688B, 0x975D, 0x688C, 0x975E, 0x688D, 0x975F, 0x688E, 0x9760, 0x688F, 0xE8F4, 0x6890, 0x9761, 0x6891, 0x9762, 0x6892, 0x9763, + 0x6893, 0xE8F7, 0x6894, 0x9764, 0x6895, 0x9765, 0x6896, 0x9766, 0x6897, 0xB9A3, 0x6898, 0x9767, 0x6899, 0x9768, 0x689A, 0x9769, + 0x689B, 0x976A, 0x689C, 0x976B, 0x689D, 0x976C, 0x689E, 0x976D, 0x689F, 0x976E, 0x68A0, 0x976F, 0x68A1, 0x9770, 0x68A2, 0xC9D2, + 0x68A3, 0x9771, 0x68A4, 0x9772, 0x68A5, 0x9773, 0x68A6, 0xC3CE, 0x68A7, 0xCEE0, 0x68A8, 0xC0E6, 0x68A9, 0x9774, 0x68AA, 0x9775, + 0x68AB, 0x9776, 0x68AC, 0x9777, 0x68AD, 0xCBF3, 0x68AE, 0x9778, 0x68AF, 0xCCDD, 0x68B0, 0xD0B5, 0x68B1, 0x9779, 0x68B2, 0x977A, + 0x68B3, 0xCAE1, 0x68B4, 0x977B, 0x68B5, 0xE8F3, 0x68B6, 0x977C, 0x68B7, 0x977D, 0x68B8, 0x977E, 0x68B9, 0x9780, 0x68BA, 0x9781, + 0x68BB, 0x9782, 0x68BC, 0x9783, 0x68BD, 0x9784, 0x68BE, 0x9785, 0x68BF, 0x9786, 0x68C0, 0xBCEC, 0x68C1, 0x9787, 0x68C2, 0xE8F9, + 0x68C3, 0x9788, 0x68C4, 0x9789, 0x68C5, 0x978A, 0x68C6, 0x978B, 0x68C7, 0x978C, 0x68C8, 0x978D, 0x68C9, 0xC3DE, 0x68CA, 0x978E, + 0x68CB, 0xC6E5, 0x68CC, 0x978F, 0x68CD, 0xB9F7, 0x68CE, 0x9790, 0x68CF, 0x9791, 0x68D0, 0x9792, 0x68D1, 0x9793, 0x68D2, 0xB0F4, + 0x68D3, 0x9794, 0x68D4, 0x9795, 0x68D5, 0xD7D8, 0x68D6, 0x9796, 0x68D7, 0x9797, 0x68D8, 0xBCAC, 0x68D9, 0x9798, 0x68DA, 0xC5EF, + 0x68DB, 0x9799, 0x68DC, 0x979A, 0x68DD, 0x979B, 0x68DE, 0x979C, 0x68DF, 0x979D, 0x68E0, 0xCCC4, 0x68E1, 0x979E, 0x68E2, 0x979F, + 0x68E3, 0xE9A6, 0x68E4, 0x97A0, 0x68E5, 0x97A1, 0x68E6, 0x97A2, 0x68E7, 0x97A3, 0x68E8, 0x97A4, 0x68E9, 0x97A5, 0x68EA, 0x97A6, + 0x68EB, 0x97A7, 0x68EC, 0x97A8, 0x68ED, 0x97A9, 0x68EE, 0xC9AD, 0x68EF, 0x97AA, 0x68F0, 0xE9A2, 0x68F1, 0xC0E2, 0x68F2, 0x97AB, + 0x68F3, 0x97AC, 0x68F4, 0x97AD, 0x68F5, 0xBFC3, 0x68F6, 0x97AE, 0x68F7, 0x97AF, 0x68F8, 0x97B0, 0x68F9, 0xE8FE, 0x68FA, 0xB9D7, + 0x68FB, 0x97B1, 0x68FC, 0xE8FB, 0x68FD, 0x97B2, 0x68FE, 0x97B3, 0x68FF, 0x97B4, 0x6900, 0x97B5, 0x6901, 0xE9A4, 0x6902, 0x97B6, + 0x6903, 0x97B7, 0x6904, 0x97B8, 0x6905, 0xD2CE, 0x6906, 0x97B9, 0x6907, 0x97BA, 0x6908, 0x97BB, 0x6909, 0x97BC, 0x690A, 0x97BD, + 0x690B, 0xE9A3, 0x690C, 0x97BE, 0x690D, 0xD6B2, 0x690E, 0xD7B5, 0x690F, 0x97BF, 0x6910, 0xE9A7, 0x6911, 0x97C0, 0x6912, 0xBDB7, + 0x6913, 0x97C1, 0x6914, 0x97C2, 0x6915, 0x97C3, 0x6916, 0x97C4, 0x6917, 0x97C5, 0x6918, 0x97C6, 0x6919, 0x97C7, 0x691A, 0x97C8, + 0x691B, 0x97C9, 0x691C, 0x97CA, 0x691D, 0x97CB, 0x691E, 0x97CC, 0x691F, 0xE8FC, 0x6920, 0xE8FD, 0x6921, 0x97CD, 0x6922, 0x97CE, + 0x6923, 0x97CF, 0x6924, 0xE9A1, 0x6925, 0x97D0, 0x6926, 0x97D1, 0x6927, 0x97D2, 0x6928, 0x97D3, 0x6929, 0x97D4, 0x692A, 0x97D5, + 0x692B, 0x97D6, 0x692C, 0x97D7, 0x692D, 0xCDD6, 0x692E, 0x97D8, 0x692F, 0x97D9, 0x6930, 0xD2AC, 0x6931, 0x97DA, 0x6932, 0x97DB, + 0x6933, 0x97DC, 0x6934, 0xE9B2, 0x6935, 0x97DD, 0x6936, 0x97DE, 0x6937, 0x97DF, 0x6938, 0x97E0, 0x6939, 0xE9A9, 0x693A, 0x97E1, + 0x693B, 0x97E2, 0x693C, 0x97E3, 0x693D, 0xB4AA, 0x693E, 0x97E4, 0x693F, 0xB4BB, 0x6940, 0x97E5, 0x6941, 0x97E6, 0x6942, 0xE9AB, + 0x6943, 0x97E7, 0x6944, 0x97E8, 0x6945, 0x97E9, 0x6946, 0x97EA, 0x6947, 0x97EB, 0x6948, 0x97EC, 0x6949, 0x97ED, 0x694A, 0x97EE, + 0x694B, 0x97EF, 0x694C, 0x97F0, 0x694D, 0x97F1, 0x694E, 0x97F2, 0x694F, 0x97F3, 0x6950, 0x97F4, 0x6951, 0x97F5, 0x6952, 0x97F6, + 0x6953, 0x97F7, 0x6954, 0xD0A8, 0x6955, 0x97F8, 0x6956, 0x97F9, 0x6957, 0xE9A5, 0x6958, 0x97FA, 0x6959, 0x97FB, 0x695A, 0xB3FE, + 0x695B, 0x97FC, 0x695C, 0x97FD, 0x695D, 0xE9AC, 0x695E, 0xC0E3, 0x695F, 0x97FE, 0x6960, 0xE9AA, 0x6961, 0x9840, 0x6962, 0x9841, + 0x6963, 0xE9B9, 0x6964, 0x9842, 0x6965, 0x9843, 0x6966, 0xE9B8, 0x6967, 0x9844, 0x6968, 0x9845, 0x6969, 0x9846, 0x696A, 0x9847, + 0x696B, 0xE9AE, 0x696C, 0x9848, 0x696D, 0x9849, 0x696E, 0xE8FA, 0x696F, 0x984A, 0x6970, 0x984B, 0x6971, 0xE9A8, 0x6972, 0x984C, + 0x6973, 0x984D, 0x6974, 0x984E, 0x6975, 0x984F, 0x6976, 0x9850, 0x6977, 0xBFAC, 0x6978, 0xE9B1, 0x6979, 0xE9BA, 0x697A, 0x9851, + 0x697B, 0x9852, 0x697C, 0xC2A5, 0x697D, 0x9853, 0x697E, 0x9854, 0x697F, 0x9855, 0x6980, 0xE9AF, 0x6981, 0x9856, 0x6982, 0xB8C5, + 0x6983, 0x9857, 0x6984, 0xE9AD, 0x6985, 0x9858, 0x6986, 0xD3DC, 0x6987, 0xE9B4, 0x6988, 0xE9B5, 0x6989, 0xE9B7, 0x698A, 0x9859, + 0x698B, 0x985A, 0x698C, 0x985B, 0x698D, 0xE9C7, 0x698E, 0x985C, 0x698F, 0x985D, 0x6990, 0x985E, 0x6991, 0x985F, 0x6992, 0x9860, + 0x6993, 0x9861, 0x6994, 0xC0C6, 0x6995, 0xE9C5, 0x6996, 0x9862, 0x6997, 0x9863, 0x6998, 0xE9B0, 0x6999, 0x9864, 0x699A, 0x9865, + 0x699B, 0xE9BB, 0x699C, 0xB0F1, 0x699D, 0x9866, 0x699E, 0x9867, 0x699F, 0x9868, 0x69A0, 0x9869, 0x69A1, 0x986A, 0x69A2, 0x986B, + 0x69A3, 0x986C, 0x69A4, 0x986D, 0x69A5, 0x986E, 0x69A6, 0x986F, 0x69A7, 0xE9BC, 0x69A8, 0xD5A5, 0x69A9, 0x9870, 0x69AA, 0x9871, + 0x69AB, 0xE9BE, 0x69AC, 0x9872, 0x69AD, 0xE9BF, 0x69AE, 0x9873, 0x69AF, 0x9874, 0x69B0, 0x9875, 0x69B1, 0xE9C1, 0x69B2, 0x9876, + 0x69B3, 0x9877, 0x69B4, 0xC1F1, 0x69B5, 0x9878, 0x69B6, 0x9879, 0x69B7, 0xC8B6, 0x69B8, 0x987A, 0x69B9, 0x987B, 0x69BA, 0x987C, + 0x69BB, 0xE9BD, 0x69BC, 0x987D, 0x69BD, 0x987E, 0x69BE, 0x9880, 0x69BF, 0x9881, 0x69C0, 0x9882, 0x69C1, 0xE9C2, 0x69C2, 0x9883, + 0x69C3, 0x9884, 0x69C4, 0x9885, 0x69C5, 0x9886, 0x69C6, 0x9887, 0x69C7, 0x9888, 0x69C8, 0x9889, 0x69C9, 0x988A, 0x69CA, 0xE9C3, + 0x69CB, 0x988B, 0x69CC, 0xE9B3, 0x69CD, 0x988C, 0x69CE, 0xE9B6, 0x69CF, 0x988D, 0x69D0, 0xBBB1, 0x69D1, 0x988E, 0x69D2, 0x988F, + 0x69D3, 0x9890, 0x69D4, 0xE9C0, 0x69D5, 0x9891, 0x69D6, 0x9892, 0x69D7, 0x9893, 0x69D8, 0x9894, 0x69D9, 0x9895, 0x69DA, 0x9896, + 0x69DB, 0xBCF7, 0x69DC, 0x9897, 0x69DD, 0x9898, 0x69DE, 0x9899, 0x69DF, 0xE9C4, 0x69E0, 0xE9C6, 0x69E1, 0x989A, 0x69E2, 0x989B, + 0x69E3, 0x989C, 0x69E4, 0x989D, 0x69E5, 0x989E, 0x69E6, 0x989F, 0x69E7, 0x98A0, 0x69E8, 0x98A1, 0x69E9, 0x98A2, 0x69EA, 0x98A3, + 0x69EB, 0x98A4, 0x69EC, 0x98A5, 0x69ED, 0xE9CA, 0x69EE, 0x98A6, 0x69EF, 0x98A7, 0x69F0, 0x98A8, 0x69F1, 0x98A9, 0x69F2, 0xE9CE, + 0x69F3, 0x98AA, 0x69F4, 0x98AB, 0x69F5, 0x98AC, 0x69F6, 0x98AD, 0x69F7, 0x98AE, 0x69F8, 0x98AF, 0x69F9, 0x98B0, 0x69FA, 0x98B1, + 0x69FB, 0x98B2, 0x69FC, 0x98B3, 0x69FD, 0xB2DB, 0x69FE, 0x98B4, 0x69FF, 0xE9C8, 0x6A00, 0x98B5, 0x6A01, 0x98B6, 0x6A02, 0x98B7, + 0x6A03, 0x98B8, 0x6A04, 0x98B9, 0x6A05, 0x98BA, 0x6A06, 0x98BB, 0x6A07, 0x98BC, 0x6A08, 0x98BD, 0x6A09, 0x98BE, 0x6A0A, 0xB7AE, + 0x6A0B, 0x98BF, 0x6A0C, 0x98C0, 0x6A0D, 0x98C1, 0x6A0E, 0x98C2, 0x6A0F, 0x98C3, 0x6A10, 0x98C4, 0x6A11, 0x98C5, 0x6A12, 0x98C6, + 0x6A13, 0x98C7, 0x6A14, 0x98C8, 0x6A15, 0x98C9, 0x6A16, 0x98CA, 0x6A17, 0xE9CB, 0x6A18, 0xE9CC, 0x6A19, 0x98CB, 0x6A1A, 0x98CC, + 0x6A1B, 0x98CD, 0x6A1C, 0x98CE, 0x6A1D, 0x98CF, 0x6A1E, 0x98D0, 0x6A1F, 0xD5C1, 0x6A20, 0x98D1, 0x6A21, 0xC4A3, 0x6A22, 0x98D2, + 0x6A23, 0x98D3, 0x6A24, 0x98D4, 0x6A25, 0x98D5, 0x6A26, 0x98D6, 0x6A27, 0x98D7, 0x6A28, 0xE9D8, 0x6A29, 0x98D8, 0x6A2A, 0xBAE1, + 0x6A2B, 0x98D9, 0x6A2C, 0x98DA, 0x6A2D, 0x98DB, 0x6A2E, 0x98DC, 0x6A2F, 0xE9C9, 0x6A30, 0x98DD, 0x6A31, 0xD3A3, 0x6A32, 0x98DE, + 0x6A33, 0x98DF, 0x6A34, 0x98E0, 0x6A35, 0xE9D4, 0x6A36, 0x98E1, 0x6A37, 0x98E2, 0x6A38, 0x98E3, 0x6A39, 0x98E4, 0x6A3A, 0x98E5, + 0x6A3B, 0x98E6, 0x6A3C, 0x98E7, 0x6A3D, 0xE9D7, 0x6A3E, 0xE9D0, 0x6A3F, 0x98E8, 0x6A40, 0x98E9, 0x6A41, 0x98EA, 0x6A42, 0x98EB, + 0x6A43, 0x98EC, 0x6A44, 0xE9CF, 0x6A45, 0x98ED, 0x6A46, 0x98EE, 0x6A47, 0xC7C1, 0x6A48, 0x98EF, 0x6A49, 0x98F0, 0x6A4A, 0x98F1, + 0x6A4B, 0x98F2, 0x6A4C, 0x98F3, 0x6A4D, 0x98F4, 0x6A4E, 0x98F5, 0x6A4F, 0x98F6, 0x6A50, 0xE9D2, 0x6A51, 0x98F7, 0x6A52, 0x98F8, + 0x6A53, 0x98F9, 0x6A54, 0x98FA, 0x6A55, 0x98FB, 0x6A56, 0x98FC, 0x6A57, 0x98FD, 0x6A58, 0xE9D9, 0x6A59, 0xB3C8, 0x6A5A, 0x98FE, + 0x6A5B, 0xE9D3, 0x6A5C, 0x9940, 0x6A5D, 0x9941, 0x6A5E, 0x9942, 0x6A5F, 0x9943, 0x6A60, 0x9944, 0x6A61, 0xCFF0, 0x6A62, 0x9945, + 0x6A63, 0x9946, 0x6A64, 0x9947, 0x6A65, 0xE9CD, 0x6A66, 0x9948, 0x6A67, 0x9949, 0x6A68, 0x994A, 0x6A69, 0x994B, 0x6A6A, 0x994C, + 0x6A6B, 0x994D, 0x6A6C, 0x994E, 0x6A6D, 0x994F, 0x6A6E, 0x9950, 0x6A6F, 0x9951, 0x6A70, 0x9952, 0x6A71, 0xB3F7, 0x6A72, 0x9953, + 0x6A73, 0x9954, 0x6A74, 0x9955, 0x6A75, 0x9956, 0x6A76, 0x9957, 0x6A77, 0x9958, 0x6A78, 0x9959, 0x6A79, 0xE9D6, 0x6A7A, 0x995A, + 0x6A7B, 0x995B, 0x6A7C, 0xE9DA, 0x6A7D, 0x995C, 0x6A7E, 0x995D, 0x6A7F, 0x995E, 0x6A80, 0xCCB4, 0x6A81, 0x995F, 0x6A82, 0x9960, + 0x6A83, 0x9961, 0x6A84, 0xCFAD, 0x6A85, 0x9962, 0x6A86, 0x9963, 0x6A87, 0x9964, 0x6A88, 0x9965, 0x6A89, 0x9966, 0x6A8A, 0x9967, + 0x6A8B, 0x9968, 0x6A8C, 0x9969, 0x6A8D, 0x996A, 0x6A8E, 0xE9D5, 0x6A8F, 0x996B, 0x6A90, 0xE9DC, 0x6A91, 0xE9DB, 0x6A92, 0x996C, + 0x6A93, 0x996D, 0x6A94, 0x996E, 0x6A95, 0x996F, 0x6A96, 0x9970, 0x6A97, 0xE9DE, 0x6A98, 0x9971, 0x6A99, 0x9972, 0x6A9A, 0x9973, + 0x6A9B, 0x9974, 0x6A9C, 0x9975, 0x6A9D, 0x9976, 0x6A9E, 0x9977, 0x6A9F, 0x9978, 0x6AA0, 0xE9D1, 0x6AA1, 0x9979, 0x6AA2, 0x997A, + 0x6AA3, 0x997B, 0x6AA4, 0x997C, 0x6AA5, 0x997D, 0x6AA6, 0x997E, 0x6AA7, 0x9980, 0x6AA8, 0x9981, 0x6AA9, 0xE9DD, 0x6AAA, 0x9982, + 0x6AAB, 0xE9DF, 0x6AAC, 0xC3CA, 0x6AAD, 0x9983, 0x6AAE, 0x9984, 0x6AAF, 0x9985, 0x6AB0, 0x9986, 0x6AB1, 0x9987, 0x6AB2, 0x9988, + 0x6AB3, 0x9989, 0x6AB4, 0x998A, 0x6AB5, 0x998B, 0x6AB6, 0x998C, 0x6AB7, 0x998D, 0x6AB8, 0x998E, 0x6AB9, 0x998F, 0x6ABA, 0x9990, + 0x6ABB, 0x9991, 0x6ABC, 0x9992, 0x6ABD, 0x9993, 0x6ABE, 0x9994, 0x6ABF, 0x9995, 0x6AC0, 0x9996, 0x6AC1, 0x9997, 0x6AC2, 0x9998, + 0x6AC3, 0x9999, 0x6AC4, 0x999A, 0x6AC5, 0x999B, 0x6AC6, 0x999C, 0x6AC7, 0x999D, 0x6AC8, 0x999E, 0x6AC9, 0x999F, 0x6ACA, 0x99A0, + 0x6ACB, 0x99A1, 0x6ACC, 0x99A2, 0x6ACD, 0x99A3, 0x6ACE, 0x99A4, 0x6ACF, 0x99A5, 0x6AD0, 0x99A6, 0x6AD1, 0x99A7, 0x6AD2, 0x99A8, + 0x6AD3, 0x99A9, 0x6AD4, 0x99AA, 0x6AD5, 0x99AB, 0x6AD6, 0x99AC, 0x6AD7, 0x99AD, 0x6AD8, 0x99AE, 0x6AD9, 0x99AF, 0x6ADA, 0x99B0, + 0x6ADB, 0x99B1, 0x6ADC, 0x99B2, 0x6ADD, 0x99B3, 0x6ADE, 0x99B4, 0x6ADF, 0x99B5, 0x6AE0, 0x99B6, 0x6AE1, 0x99B7, 0x6AE2, 0x99B8, + 0x6AE3, 0x99B9, 0x6AE4, 0x99BA, 0x6AE5, 0x99BB, 0x6AE6, 0x99BC, 0x6AE7, 0x99BD, 0x6AE8, 0x99BE, 0x6AE9, 0x99BF, 0x6AEA, 0x99C0, + 0x6AEB, 0x99C1, 0x6AEC, 0x99C2, 0x6AED, 0x99C3, 0x6AEE, 0x99C4, 0x6AEF, 0x99C5, 0x6AF0, 0x99C6, 0x6AF1, 0x99C7, 0x6AF2, 0x99C8, + 0x6AF3, 0x99C9, 0x6AF4, 0x99CA, 0x6AF5, 0x99CB, 0x6AF6, 0x99CC, 0x6AF7, 0x99CD, 0x6AF8, 0x99CE, 0x6AF9, 0x99CF, 0x6AFA, 0x99D0, + 0x6AFB, 0x99D1, 0x6AFC, 0x99D2, 0x6AFD, 0x99D3, 0x6AFE, 0x99D4, 0x6AFF, 0x99D5, 0x6B00, 0x99D6, 0x6B01, 0x99D7, 0x6B02, 0x99D8, + 0x6B03, 0x99D9, 0x6B04, 0x99DA, 0x6B05, 0x99DB, 0x6B06, 0x99DC, 0x6B07, 0x99DD, 0x6B08, 0x99DE, 0x6B09, 0x99DF, 0x6B0A, 0x99E0, + 0x6B0B, 0x99E1, 0x6B0C, 0x99E2, 0x6B0D, 0x99E3, 0x6B0E, 0x99E4, 0x6B0F, 0x99E5, 0x6B10, 0x99E6, 0x6B11, 0x99E7, 0x6B12, 0x99E8, + 0x6B13, 0x99E9, 0x6B14, 0x99EA, 0x6B15, 0x99EB, 0x6B16, 0x99EC, 0x6B17, 0x99ED, 0x6B18, 0x99EE, 0x6B19, 0x99EF, 0x6B1A, 0x99F0, + 0x6B1B, 0x99F1, 0x6B1C, 0x99F2, 0x6B1D, 0x99F3, 0x6B1E, 0x99F4, 0x6B1F, 0x99F5, 0x6B20, 0xC7B7, 0x6B21, 0xB4CE, 0x6B22, 0xBBB6, + 0x6B23, 0xD0C0, 0x6B24, 0xECA3, 0x6B25, 0x99F6, 0x6B26, 0x99F7, 0x6B27, 0xC5B7, 0x6B28, 0x99F8, 0x6B29, 0x99F9, 0x6B2A, 0x99FA, + 0x6B2B, 0x99FB, 0x6B2C, 0x99FC, 0x6B2D, 0x99FD, 0x6B2E, 0x99FE, 0x6B2F, 0x9A40, 0x6B30, 0x9A41, 0x6B31, 0x9A42, 0x6B32, 0xD3FB, + 0x6B33, 0x9A43, 0x6B34, 0x9A44, 0x6B35, 0x9A45, 0x6B36, 0x9A46, 0x6B37, 0xECA4, 0x6B38, 0x9A47, 0x6B39, 0xECA5, 0x6B3A, 0xC6DB, + 0x6B3B, 0x9A48, 0x6B3C, 0x9A49, 0x6B3D, 0x9A4A, 0x6B3E, 0xBFEE, 0x6B3F, 0x9A4B, 0x6B40, 0x9A4C, 0x6B41, 0x9A4D, 0x6B42, 0x9A4E, + 0x6B43, 0xECA6, 0x6B44, 0x9A4F, 0x6B45, 0x9A50, 0x6B46, 0xECA7, 0x6B47, 0xD0AA, 0x6B48, 0x9A51, 0x6B49, 0xC7B8, 0x6B4A, 0x9A52, + 0x6B4B, 0x9A53, 0x6B4C, 0xB8E8, 0x6B4D, 0x9A54, 0x6B4E, 0x9A55, 0x6B4F, 0x9A56, 0x6B50, 0x9A57, 0x6B51, 0x9A58, 0x6B52, 0x9A59, + 0x6B53, 0x9A5A, 0x6B54, 0x9A5B, 0x6B55, 0x9A5C, 0x6B56, 0x9A5D, 0x6B57, 0x9A5E, 0x6B58, 0x9A5F, 0x6B59, 0xECA8, 0x6B5A, 0x9A60, + 0x6B5B, 0x9A61, 0x6B5C, 0x9A62, 0x6B5D, 0x9A63, 0x6B5E, 0x9A64, 0x6B5F, 0x9A65, 0x6B60, 0x9A66, 0x6B61, 0x9A67, 0x6B62, 0xD6B9, + 0x6B63, 0xD5FD, 0x6B64, 0xB4CB, 0x6B65, 0xB2BD, 0x6B66, 0xCEE4, 0x6B67, 0xC6E7, 0x6B68, 0x9A68, 0x6B69, 0x9A69, 0x6B6A, 0xCDE1, + 0x6B6B, 0x9A6A, 0x6B6C, 0x9A6B, 0x6B6D, 0x9A6C, 0x6B6E, 0x9A6D, 0x6B6F, 0x9A6E, 0x6B70, 0x9A6F, 0x6B71, 0x9A70, 0x6B72, 0x9A71, + 0x6B73, 0x9A72, 0x6B74, 0x9A73, 0x6B75, 0x9A74, 0x6B76, 0x9A75, 0x6B77, 0x9A76, 0x6B78, 0x9A77, 0x6B79, 0xB4F5, 0x6B7A, 0x9A78, + 0x6B7B, 0xCBC0, 0x6B7C, 0xBCDF, 0x6B7D, 0x9A79, 0x6B7E, 0x9A7A, 0x6B7F, 0x9A7B, 0x6B80, 0x9A7C, 0x6B81, 0xE9E2, 0x6B82, 0xE9E3, + 0x6B83, 0xD1EA, 0x6B84, 0xE9E5, 0x6B85, 0x9A7D, 0x6B86, 0xB4F9, 0x6B87, 0xE9E4, 0x6B88, 0x9A7E, 0x6B89, 0xD1B3, 0x6B8A, 0xCAE2, + 0x6B8B, 0xB2D0, 0x6B8C, 0x9A80, 0x6B8D, 0xE9E8, 0x6B8E, 0x9A81, 0x6B8F, 0x9A82, 0x6B90, 0x9A83, 0x6B91, 0x9A84, 0x6B92, 0xE9E6, + 0x6B93, 0xE9E7, 0x6B94, 0x9A85, 0x6B95, 0x9A86, 0x6B96, 0xD6B3, 0x6B97, 0x9A87, 0x6B98, 0x9A88, 0x6B99, 0x9A89, 0x6B9A, 0xE9E9, + 0x6B9B, 0xE9EA, 0x6B9C, 0x9A8A, 0x6B9D, 0x9A8B, 0x6B9E, 0x9A8C, 0x6B9F, 0x9A8D, 0x6BA0, 0x9A8E, 0x6BA1, 0xE9EB, 0x6BA2, 0x9A8F, + 0x6BA3, 0x9A90, 0x6BA4, 0x9A91, 0x6BA5, 0x9A92, 0x6BA6, 0x9A93, 0x6BA7, 0x9A94, 0x6BA8, 0x9A95, 0x6BA9, 0x9A96, 0x6BAA, 0xE9EC, + 0x6BAB, 0x9A97, 0x6BAC, 0x9A98, 0x6BAD, 0x9A99, 0x6BAE, 0x9A9A, 0x6BAF, 0x9A9B, 0x6BB0, 0x9A9C, 0x6BB1, 0x9A9D, 0x6BB2, 0x9A9E, + 0x6BB3, 0xECAF, 0x6BB4, 0xC5B9, 0x6BB5, 0xB6CE, 0x6BB6, 0x9A9F, 0x6BB7, 0xD2F3, 0x6BB8, 0x9AA0, 0x6BB9, 0x9AA1, 0x6BBA, 0x9AA2, + 0x6BBB, 0x9AA3, 0x6BBC, 0x9AA4, 0x6BBD, 0x9AA5, 0x6BBE, 0x9AA6, 0x6BBF, 0xB5EE, 0x6BC0, 0x9AA7, 0x6BC1, 0xBBD9, 0x6BC2, 0xECB1, + 0x6BC3, 0x9AA8, 0x6BC4, 0x9AA9, 0x6BC5, 0xD2E3, 0x6BC6, 0x9AAA, 0x6BC7, 0x9AAB, 0x6BC8, 0x9AAC, 0x6BC9, 0x9AAD, 0x6BCA, 0x9AAE, + 0x6BCB, 0xCEE3, 0x6BCC, 0x9AAF, 0x6BCD, 0xC4B8, 0x6BCE, 0x9AB0, 0x6BCF, 0xC3BF, 0x6BD0, 0x9AB1, 0x6BD1, 0x9AB2, 0x6BD2, 0xB6BE, + 0x6BD3, 0xD8B9, 0x6BD4, 0xB1C8, 0x6BD5, 0xB1CF, 0x6BD6, 0xB1D1, 0x6BD7, 0xC5FE, 0x6BD8, 0x9AB3, 0x6BD9, 0xB1D0, 0x6BDA, 0x9AB4, + 0x6BDB, 0xC3AB, 0x6BDC, 0x9AB5, 0x6BDD, 0x9AB6, 0x6BDE, 0x9AB7, 0x6BDF, 0x9AB8, 0x6BE0, 0x9AB9, 0x6BE1, 0xD5B1, 0x6BE2, 0x9ABA, + 0x6BE3, 0x9ABB, 0x6BE4, 0x9ABC, 0x6BE5, 0x9ABD, 0x6BE6, 0x9ABE, 0x6BE7, 0x9ABF, 0x6BE8, 0x9AC0, 0x6BE9, 0x9AC1, 0x6BEA, 0xEBA4, + 0x6BEB, 0xBAC1, 0x6BEC, 0x9AC2, 0x6BED, 0x9AC3, 0x6BEE, 0x9AC4, 0x6BEF, 0xCCBA, 0x6BF0, 0x9AC5, 0x6BF1, 0x9AC6, 0x6BF2, 0x9AC7, + 0x6BF3, 0xEBA5, 0x6BF4, 0x9AC8, 0x6BF5, 0xEBA7, 0x6BF6, 0x9AC9, 0x6BF7, 0x9ACA, 0x6BF8, 0x9ACB, 0x6BF9, 0xEBA8, 0x6BFA, 0x9ACC, + 0x6BFB, 0x9ACD, 0x6BFC, 0x9ACE, 0x6BFD, 0xEBA6, 0x6BFE, 0x9ACF, 0x6BFF, 0x9AD0, 0x6C00, 0x9AD1, 0x6C01, 0x9AD2, 0x6C02, 0x9AD3, + 0x6C03, 0x9AD4, 0x6C04, 0x9AD5, 0x6C05, 0xEBA9, 0x6C06, 0xEBAB, 0x6C07, 0xEBAA, 0x6C08, 0x9AD6, 0x6C09, 0x9AD7, 0x6C0A, 0x9AD8, + 0x6C0B, 0x9AD9, 0x6C0C, 0x9ADA, 0x6C0D, 0xEBAC, 0x6C0E, 0x9ADB, 0x6C0F, 0xCACF, 0x6C10, 0xD8B5, 0x6C11, 0xC3F1, 0x6C12, 0x9ADC, + 0x6C13, 0xC3A5, 0x6C14, 0xC6F8, 0x6C15, 0xEBAD, 0x6C16, 0xC4CA, 0x6C17, 0x9ADD, 0x6C18, 0xEBAE, 0x6C19, 0xEBAF, 0x6C1A, 0xEBB0, + 0x6C1B, 0xB7D5, 0x6C1C, 0x9ADE, 0x6C1D, 0x9ADF, 0x6C1E, 0x9AE0, 0x6C1F, 0xB7FA, 0x6C20, 0x9AE1, 0x6C21, 0xEBB1, 0x6C22, 0xC7E2, + 0x6C23, 0x9AE2, 0x6C24, 0xEBB3, 0x6C25, 0x9AE3, 0x6C26, 0xBAA4, 0x6C27, 0xD1F5, 0x6C28, 0xB0B1, 0x6C29, 0xEBB2, 0x6C2A, 0xEBB4, + 0x6C2B, 0x9AE4, 0x6C2C, 0x9AE5, 0x6C2D, 0x9AE6, 0x6C2E, 0xB5AA, 0x6C2F, 0xC2C8, 0x6C30, 0xC7E8, 0x6C31, 0x9AE7, 0x6C32, 0xEBB5, + 0x6C33, 0x9AE8, 0x6C34, 0xCBAE, 0x6C35, 0xE3DF, 0x6C36, 0x9AE9, 0x6C37, 0x9AEA, 0x6C38, 0xD3C0, 0x6C39, 0x9AEB, 0x6C3A, 0x9AEC, + 0x6C3B, 0x9AED, 0x6C3C, 0x9AEE, 0x6C3D, 0xD9DB, 0x6C3E, 0x9AEF, 0x6C3F, 0x9AF0, 0x6C40, 0xCDA1, 0x6C41, 0xD6AD, 0x6C42, 0xC7F3, + 0x6C43, 0x9AF1, 0x6C44, 0x9AF2, 0x6C45, 0x9AF3, 0x6C46, 0xD9E0, 0x6C47, 0xBBE3, 0x6C48, 0x9AF4, 0x6C49, 0xBABA, 0x6C4A, 0xE3E2, + 0x6C4B, 0x9AF5, 0x6C4C, 0x9AF6, 0x6C4D, 0x9AF7, 0x6C4E, 0x9AF8, 0x6C4F, 0x9AF9, 0x6C50, 0xCFAB, 0x6C51, 0x9AFA, 0x6C52, 0x9AFB, + 0x6C53, 0x9AFC, 0x6C54, 0xE3E0, 0x6C55, 0xC9C7, 0x6C56, 0x9AFD, 0x6C57, 0xBAB9, 0x6C58, 0x9AFE, 0x6C59, 0x9B40, 0x6C5A, 0x9B41, + 0x6C5B, 0xD1B4, 0x6C5C, 0xE3E1, 0x6C5D, 0xC8EA, 0x6C5E, 0xB9AF, 0x6C5F, 0xBDAD, 0x6C60, 0xB3D8, 0x6C61, 0xCEDB, 0x6C62, 0x9B42, + 0x6C63, 0x9B43, 0x6C64, 0xCCC0, 0x6C65, 0x9B44, 0x6C66, 0x9B45, 0x6C67, 0x9B46, 0x6C68, 0xE3E8, 0x6C69, 0xE3E9, 0x6C6A, 0xCDF4, + 0x6C6B, 0x9B47, 0x6C6C, 0x9B48, 0x6C6D, 0x9B49, 0x6C6E, 0x9B4A, 0x6C6F, 0x9B4B, 0x6C70, 0xCCAD, 0x6C71, 0x9B4C, 0x6C72, 0xBCB3, + 0x6C73, 0x9B4D, 0x6C74, 0xE3EA, 0x6C75, 0x9B4E, 0x6C76, 0xE3EB, 0x6C77, 0x9B4F, 0x6C78, 0x9B50, 0x6C79, 0xD0DA, 0x6C7A, 0x9B51, + 0x6C7B, 0x9B52, 0x6C7C, 0x9B53, 0x6C7D, 0xC6FB, 0x6C7E, 0xB7DA, 0x6C7F, 0x9B54, 0x6C80, 0x9B55, 0x6C81, 0xC7DF, 0x6C82, 0xD2CA, + 0x6C83, 0xCED6, 0x6C84, 0x9B56, 0x6C85, 0xE3E4, 0x6C86, 0xE3EC, 0x6C87, 0x9B57, 0x6C88, 0xC9F2, 0x6C89, 0xB3C1, 0x6C8A, 0x9B58, + 0x6C8B, 0x9B59, 0x6C8C, 0xE3E7, 0x6C8D, 0x9B5A, 0x6C8E, 0x9B5B, 0x6C8F, 0xC6E3, 0x6C90, 0xE3E5, 0x6C91, 0x9B5C, 0x6C92, 0x9B5D, + 0x6C93, 0xEDB3, 0x6C94, 0xE3E6, 0x6C95, 0x9B5E, 0x6C96, 0x9B5F, 0x6C97, 0x9B60, 0x6C98, 0x9B61, 0x6C99, 0xC9B3, 0x6C9A, 0x9B62, + 0x6C9B, 0xC5E6, 0x6C9C, 0x9B63, 0x6C9D, 0x9B64, 0x6C9E, 0x9B65, 0x6C9F, 0xB9B5, 0x6CA0, 0x9B66, 0x6CA1, 0xC3BB, 0x6CA2, 0x9B67, + 0x6CA3, 0xE3E3, 0x6CA4, 0xC5BD, 0x6CA5, 0xC1A4, 0x6CA6, 0xC2D9, 0x6CA7, 0xB2D7, 0x6CA8, 0x9B68, 0x6CA9, 0xE3ED, 0x6CAA, 0xBBA6, + 0x6CAB, 0xC4AD, 0x6CAC, 0x9B69, 0x6CAD, 0xE3F0, 0x6CAE, 0xBEDA, 0x6CAF, 0x9B6A, 0x6CB0, 0x9B6B, 0x6CB1, 0xE3FB, 0x6CB2, 0xE3F5, + 0x6CB3, 0xBAD3, 0x6CB4, 0x9B6C, 0x6CB5, 0x9B6D, 0x6CB6, 0x9B6E, 0x6CB7, 0x9B6F, 0x6CB8, 0xB7D0, 0x6CB9, 0xD3CD, 0x6CBA, 0x9B70, + 0x6CBB, 0xD6CE, 0x6CBC, 0xD5D3, 0x6CBD, 0xB9C1, 0x6CBE, 0xD5B4, 0x6CBF, 0xD1D8, 0x6CC0, 0x9B71, 0x6CC1, 0x9B72, 0x6CC2, 0x9B73, + 0x6CC3, 0x9B74, 0x6CC4, 0xD0B9, 0x6CC5, 0xC7F6, 0x6CC6, 0x9B75, 0x6CC7, 0x9B76, 0x6CC8, 0x9B77, 0x6CC9, 0xC8AA, 0x6CCA, 0xB2B4, + 0x6CCB, 0x9B78, 0x6CCC, 0xC3DA, 0x6CCD, 0x9B79, 0x6CCE, 0x9B7A, 0x6CCF, 0x9B7B, 0x6CD0, 0xE3EE, 0x6CD1, 0x9B7C, 0x6CD2, 0x9B7D, + 0x6CD3, 0xE3FC, 0x6CD4, 0xE3EF, 0x6CD5, 0xB7A8, 0x6CD6, 0xE3F7, 0x6CD7, 0xE3F4, 0x6CD8, 0x9B7E, 0x6CD9, 0x9B80, 0x6CDA, 0x9B81, + 0x6CDB, 0xB7BA, 0x6CDC, 0x9B82, 0x6CDD, 0x9B83, 0x6CDE, 0xC5A2, 0x6CDF, 0x9B84, 0x6CE0, 0xE3F6, 0x6CE1, 0xC5DD, 0x6CE2, 0xB2A8, + 0x6CE3, 0xC6FC, 0x6CE4, 0x9B85, 0x6CE5, 0xC4E0, 0x6CE6, 0x9B86, 0x6CE7, 0x9B87, 0x6CE8, 0xD7A2, 0x6CE9, 0x9B88, 0x6CEA, 0xC0E1, + 0x6CEB, 0xE3F9, 0x6CEC, 0x9B89, 0x6CED, 0x9B8A, 0x6CEE, 0xE3FA, 0x6CEF, 0xE3FD, 0x6CF0, 0xCCA9, 0x6CF1, 0xE3F3, 0x6CF2, 0x9B8B, + 0x6CF3, 0xD3BE, 0x6CF4, 0x9B8C, 0x6CF5, 0xB1C3, 0x6CF6, 0xEDB4, 0x6CF7, 0xE3F1, 0x6CF8, 0xE3F2, 0x6CF9, 0x9B8D, 0x6CFA, 0xE3F8, + 0x6CFB, 0xD0BA, 0x6CFC, 0xC6C3, 0x6CFD, 0xD4F3, 0x6CFE, 0xE3FE, 0x6CFF, 0x9B8E, 0x6D00, 0x9B8F, 0x6D01, 0xBDE0, 0x6D02, 0x9B90, + 0x6D03, 0x9B91, 0x6D04, 0xE4A7, 0x6D05, 0x9B92, 0x6D06, 0x9B93, 0x6D07, 0xE4A6, 0x6D08, 0x9B94, 0x6D09, 0x9B95, 0x6D0A, 0x9B96, + 0x6D0B, 0xD1F3, 0x6D0C, 0xE4A3, 0x6D0D, 0x9B97, 0x6D0E, 0xE4A9, 0x6D0F, 0x9B98, 0x6D10, 0x9B99, 0x6D11, 0x9B9A, 0x6D12, 0xC8F7, + 0x6D13, 0x9B9B, 0x6D14, 0x9B9C, 0x6D15, 0x9B9D, 0x6D16, 0x9B9E, 0x6D17, 0xCFB4, 0x6D18, 0x9B9F, 0x6D19, 0xE4A8, 0x6D1A, 0xE4AE, + 0x6D1B, 0xC2E5, 0x6D1C, 0x9BA0, 0x6D1D, 0x9BA1, 0x6D1E, 0xB6B4, 0x6D1F, 0x9BA2, 0x6D20, 0x9BA3, 0x6D21, 0x9BA4, 0x6D22, 0x9BA5, + 0x6D23, 0x9BA6, 0x6D24, 0x9BA7, 0x6D25, 0xBDF2, 0x6D26, 0x9BA8, 0x6D27, 0xE4A2, 0x6D28, 0x9BA9, 0x6D29, 0x9BAA, 0x6D2A, 0xBAE9, + 0x6D2B, 0xE4AA, 0x6D2C, 0x9BAB, 0x6D2D, 0x9BAC, 0x6D2E, 0xE4AC, 0x6D2F, 0x9BAD, 0x6D30, 0x9BAE, 0x6D31, 0xB6FD, 0x6D32, 0xD6DE, + 0x6D33, 0xE4B2, 0x6D34, 0x9BAF, 0x6D35, 0xE4AD, 0x6D36, 0x9BB0, 0x6D37, 0x9BB1, 0x6D38, 0x9BB2, 0x6D39, 0xE4A1, 0x6D3A, 0x9BB3, + 0x6D3B, 0xBBEE, 0x6D3C, 0xCDDD, 0x6D3D, 0xC7A2, 0x6D3E, 0xC5C9, 0x6D3F, 0x9BB4, 0x6D40, 0x9BB5, 0x6D41, 0xC1F7, 0x6D42, 0x9BB6, + 0x6D43, 0xE4A4, 0x6D44, 0x9BB7, 0x6D45, 0xC7B3, 0x6D46, 0xBDAC, 0x6D47, 0xBDBD, 0x6D48, 0xE4A5, 0x6D49, 0x9BB8, 0x6D4A, 0xD7C7, + 0x6D4B, 0xB2E2, 0x6D4C, 0x9BB9, 0x6D4D, 0xE4AB, 0x6D4E, 0xBCC3, 0x6D4F, 0xE4AF, 0x6D50, 0x9BBA, 0x6D51, 0xBBEB, 0x6D52, 0xE4B0, + 0x6D53, 0xC5A8, 0x6D54, 0xE4B1, 0x6D55, 0x9BBB, 0x6D56, 0x9BBC, 0x6D57, 0x9BBD, 0x6D58, 0x9BBE, 0x6D59, 0xD5E3, 0x6D5A, 0xBFA3, + 0x6D5B, 0x9BBF, 0x6D5C, 0xE4BA, 0x6D5D, 0x9BC0, 0x6D5E, 0xE4B7, 0x6D5F, 0x9BC1, 0x6D60, 0xE4BB, 0x6D61, 0x9BC2, 0x6D62, 0x9BC3, + 0x6D63, 0xE4BD, 0x6D64, 0x9BC4, 0x6D65, 0x9BC5, 0x6D66, 0xC6D6, 0x6D67, 0x9BC6, 0x6D68, 0x9BC7, 0x6D69, 0xBAC6, 0x6D6A, 0xC0CB, + 0x6D6B, 0x9BC8, 0x6D6C, 0x9BC9, 0x6D6D, 0x9BCA, 0x6D6E, 0xB8A1, 0x6D6F, 0xE4B4, 0x6D70, 0x9BCB, 0x6D71, 0x9BCC, 0x6D72, 0x9BCD, + 0x6D73, 0x9BCE, 0x6D74, 0xD4A1, 0x6D75, 0x9BCF, 0x6D76, 0x9BD0, 0x6D77, 0xBAA3, 0x6D78, 0xBDFE, 0x6D79, 0x9BD1, 0x6D7A, 0x9BD2, + 0x6D7B, 0x9BD3, 0x6D7C, 0xE4BC, 0x6D7D, 0x9BD4, 0x6D7E, 0x9BD5, 0x6D7F, 0x9BD6, 0x6D80, 0x9BD7, 0x6D81, 0x9BD8, 0x6D82, 0xCDBF, + 0x6D83, 0x9BD9, 0x6D84, 0x9BDA, 0x6D85, 0xC4F9, 0x6D86, 0x9BDB, 0x6D87, 0x9BDC, 0x6D88, 0xCFFB, 0x6D89, 0xC9E6, 0x6D8A, 0x9BDD, + 0x6D8B, 0x9BDE, 0x6D8C, 0xD3BF, 0x6D8D, 0x9BDF, 0x6D8E, 0xCFD1, 0x6D8F, 0x9BE0, 0x6D90, 0x9BE1, 0x6D91, 0xE4B3, 0x6D92, 0x9BE2, + 0x6D93, 0xE4B8, 0x6D94, 0xE4B9, 0x6D95, 0xCCE9, 0x6D96, 0x9BE3, 0x6D97, 0x9BE4, 0x6D98, 0x9BE5, 0x6D99, 0x9BE6, 0x6D9A, 0x9BE7, + 0x6D9B, 0xCCCE, 0x6D9C, 0x9BE8, 0x6D9D, 0xC0D4, 0x6D9E, 0xE4B5, 0x6D9F, 0xC1B0, 0x6DA0, 0xE4B6, 0x6DA1, 0xCED0, 0x6DA2, 0x9BE9, + 0x6DA3, 0xBBC1, 0x6DA4, 0xB5D3, 0x6DA5, 0x9BEA, 0x6DA6, 0xC8F3, 0x6DA7, 0xBDA7, 0x6DA8, 0xD5C7, 0x6DA9, 0xC9AC, 0x6DAA, 0xB8A2, + 0x6DAB, 0xE4CA, 0x6DAC, 0x9BEB, 0x6DAD, 0x9BEC, 0x6DAE, 0xE4CC, 0x6DAF, 0xD1C4, 0x6DB0, 0x9BED, 0x6DB1, 0x9BEE, 0x6DB2, 0xD2BA, + 0x6DB3, 0x9BEF, 0x6DB4, 0x9BF0, 0x6DB5, 0xBAAD, 0x6DB6, 0x9BF1, 0x6DB7, 0x9BF2, 0x6DB8, 0xBAD4, 0x6DB9, 0x9BF3, 0x6DBA, 0x9BF4, + 0x6DBB, 0x9BF5, 0x6DBC, 0x9BF6, 0x6DBD, 0x9BF7, 0x6DBE, 0x9BF8, 0x6DBF, 0xE4C3, 0x6DC0, 0xB5ED, 0x6DC1, 0x9BF9, 0x6DC2, 0x9BFA, + 0x6DC3, 0x9BFB, 0x6DC4, 0xD7CD, 0x6DC5, 0xE4C0, 0x6DC6, 0xCFFD, 0x6DC7, 0xE4BF, 0x6DC8, 0x9BFC, 0x6DC9, 0x9BFD, 0x6DCA, 0x9BFE, + 0x6DCB, 0xC1DC, 0x6DCC, 0xCCCA, 0x6DCD, 0x9C40, 0x6DCE, 0x9C41, 0x6DCF, 0x9C42, 0x6DD0, 0x9C43, 0x6DD1, 0xCAE7, 0x6DD2, 0x9C44, + 0x6DD3, 0x9C45, 0x6DD4, 0x9C46, 0x6DD5, 0x9C47, 0x6DD6, 0xC4D7, 0x6DD7, 0x9C48, 0x6DD8, 0xCCD4, 0x6DD9, 0xE4C8, 0x6DDA, 0x9C49, + 0x6DDB, 0x9C4A, 0x6DDC, 0x9C4B, 0x6DDD, 0xE4C7, 0x6DDE, 0xE4C1, 0x6DDF, 0x9C4C, 0x6DE0, 0xE4C4, 0x6DE1, 0xB5AD, 0x6DE2, 0x9C4D, + 0x6DE3, 0x9C4E, 0x6DE4, 0xD3D9, 0x6DE5, 0x9C4F, 0x6DE6, 0xE4C6, 0x6DE7, 0x9C50, 0x6DE8, 0x9C51, 0x6DE9, 0x9C52, 0x6DEA, 0x9C53, + 0x6DEB, 0xD2F9, 0x6DEC, 0xB4E3, 0x6DED, 0x9C54, 0x6DEE, 0xBBB4, 0x6DEF, 0x9C55, 0x6DF0, 0x9C56, 0x6DF1, 0xC9EE, 0x6DF2, 0x9C57, + 0x6DF3, 0xB4BE, 0x6DF4, 0x9C58, 0x6DF5, 0x9C59, 0x6DF6, 0x9C5A, 0x6DF7, 0xBBEC, 0x6DF8, 0x9C5B, 0x6DF9, 0xD1CD, 0x6DFA, 0x9C5C, + 0x6DFB, 0xCCED, 0x6DFC, 0xEDB5, 0x6DFD, 0x9C5D, 0x6DFE, 0x9C5E, 0x6DFF, 0x9C5F, 0x6E00, 0x9C60, 0x6E01, 0x9C61, 0x6E02, 0x9C62, + 0x6E03, 0x9C63, 0x6E04, 0x9C64, 0x6E05, 0xC7E5, 0x6E06, 0x9C65, 0x6E07, 0x9C66, 0x6E08, 0x9C67, 0x6E09, 0x9C68, 0x6E0A, 0xD4A8, + 0x6E0B, 0x9C69, 0x6E0C, 0xE4CB, 0x6E0D, 0xD7D5, 0x6E0E, 0xE4C2, 0x6E0F, 0x9C6A, 0x6E10, 0xBDA5, 0x6E11, 0xE4C5, 0x6E12, 0x9C6B, + 0x6E13, 0x9C6C, 0x6E14, 0xD3E6, 0x6E15, 0x9C6D, 0x6E16, 0xE4C9, 0x6E17, 0xC9F8, 0x6E18, 0x9C6E, 0x6E19, 0x9C6F, 0x6E1A, 0xE4BE, + 0x6E1B, 0x9C70, 0x6E1C, 0x9C71, 0x6E1D, 0xD3E5, 0x6E1E, 0x9C72, 0x6E1F, 0x9C73, 0x6E20, 0xC7FE, 0x6E21, 0xB6C9, 0x6E22, 0x9C74, + 0x6E23, 0xD4FC, 0x6E24, 0xB2B3, 0x6E25, 0xE4D7, 0x6E26, 0x9C75, 0x6E27, 0x9C76, 0x6E28, 0x9C77, 0x6E29, 0xCEC2, 0x6E2A, 0x9C78, + 0x6E2B, 0xE4CD, 0x6E2C, 0x9C79, 0x6E2D, 0xCEBC, 0x6E2E, 0x9C7A, 0x6E2F, 0xB8DB, 0x6E30, 0x9C7B, 0x6E31, 0x9C7C, 0x6E32, 0xE4D6, + 0x6E33, 0x9C7D, 0x6E34, 0xBFCA, 0x6E35, 0x9C7E, 0x6E36, 0x9C80, 0x6E37, 0x9C81, 0x6E38, 0xD3CE, 0x6E39, 0x9C82, 0x6E3A, 0xC3EC, + 0x6E3B, 0x9C83, 0x6E3C, 0x9C84, 0x6E3D, 0x9C85, 0x6E3E, 0x9C86, 0x6E3F, 0x9C87, 0x6E40, 0x9C88, 0x6E41, 0x9C89, 0x6E42, 0x9C8A, + 0x6E43, 0xC5C8, 0x6E44, 0xE4D8, 0x6E45, 0x9C8B, 0x6E46, 0x9C8C, 0x6E47, 0x9C8D, 0x6E48, 0x9C8E, 0x6E49, 0x9C8F, 0x6E4A, 0x9C90, + 0x6E4B, 0x9C91, 0x6E4C, 0x9C92, 0x6E4D, 0xCDC4, 0x6E4E, 0xE4CF, 0x6E4F, 0x9C93, 0x6E50, 0x9C94, 0x6E51, 0x9C95, 0x6E52, 0x9C96, + 0x6E53, 0xE4D4, 0x6E54, 0xE4D5, 0x6E55, 0x9C97, 0x6E56, 0xBAFE, 0x6E57, 0x9C98, 0x6E58, 0xCFE6, 0x6E59, 0x9C99, 0x6E5A, 0x9C9A, + 0x6E5B, 0xD5BF, 0x6E5C, 0x9C9B, 0x6E5D, 0x9C9C, 0x6E5E, 0x9C9D, 0x6E5F, 0xE4D2, 0x6E60, 0x9C9E, 0x6E61, 0x9C9F, 0x6E62, 0x9CA0, + 0x6E63, 0x9CA1, 0x6E64, 0x9CA2, 0x6E65, 0x9CA3, 0x6E66, 0x9CA4, 0x6E67, 0x9CA5, 0x6E68, 0x9CA6, 0x6E69, 0x9CA7, 0x6E6A, 0x9CA8, + 0x6E6B, 0xE4D0, 0x6E6C, 0x9CA9, 0x6E6D, 0x9CAA, 0x6E6E, 0xE4CE, 0x6E6F, 0x9CAB, 0x6E70, 0x9CAC, 0x6E71, 0x9CAD, 0x6E72, 0x9CAE, + 0x6E73, 0x9CAF, 0x6E74, 0x9CB0, 0x6E75, 0x9CB1, 0x6E76, 0x9CB2, 0x6E77, 0x9CB3, 0x6E78, 0x9CB4, 0x6E79, 0x9CB5, 0x6E7A, 0x9CB6, + 0x6E7B, 0x9CB7, 0x6E7C, 0x9CB8, 0x6E7D, 0x9CB9, 0x6E7E, 0xCDE5, 0x6E7F, 0xCAAA, 0x6E80, 0x9CBA, 0x6E81, 0x9CBB, 0x6E82, 0x9CBC, + 0x6E83, 0xC0A3, 0x6E84, 0x9CBD, 0x6E85, 0xBDA6, 0x6E86, 0xE4D3, 0x6E87, 0x9CBE, 0x6E88, 0x9CBF, 0x6E89, 0xB8C8, 0x6E8A, 0x9CC0, + 0x6E8B, 0x9CC1, 0x6E8C, 0x9CC2, 0x6E8D, 0x9CC3, 0x6E8E, 0x9CC4, 0x6E8F, 0xE4E7, 0x6E90, 0xD4B4, 0x6E91, 0x9CC5, 0x6E92, 0x9CC6, + 0x6E93, 0x9CC7, 0x6E94, 0x9CC8, 0x6E95, 0x9CC9, 0x6E96, 0x9CCA, 0x6E97, 0x9CCB, 0x6E98, 0xE4DB, 0x6E99, 0x9CCC, 0x6E9A, 0x9CCD, + 0x6E9B, 0x9CCE, 0x6E9C, 0xC1EF, 0x6E9D, 0x9CCF, 0x6E9E, 0x9CD0, 0x6E9F, 0xE4E9, 0x6EA0, 0x9CD1, 0x6EA1, 0x9CD2, 0x6EA2, 0xD2E7, + 0x6EA3, 0x9CD3, 0x6EA4, 0x9CD4, 0x6EA5, 0xE4DF, 0x6EA6, 0x9CD5, 0x6EA7, 0xE4E0, 0x6EA8, 0x9CD6, 0x6EA9, 0x9CD7, 0x6EAA, 0xCFAA, + 0x6EAB, 0x9CD8, 0x6EAC, 0x9CD9, 0x6EAD, 0x9CDA, 0x6EAE, 0x9CDB, 0x6EAF, 0xCBDD, 0x6EB0, 0x9CDC, 0x6EB1, 0xE4DA, 0x6EB2, 0xE4D1, + 0x6EB3, 0x9CDD, 0x6EB4, 0xE4E5, 0x6EB5, 0x9CDE, 0x6EB6, 0xC8DC, 0x6EB7, 0xE4E3, 0x6EB8, 0x9CDF, 0x6EB9, 0x9CE0, 0x6EBA, 0xC4E7, + 0x6EBB, 0xE4E2, 0x6EBC, 0x9CE1, 0x6EBD, 0xE4E1, 0x6EBE, 0x9CE2, 0x6EBF, 0x9CE3, 0x6EC0, 0x9CE4, 0x6EC1, 0xB3FC, 0x6EC2, 0xE4E8, + 0x6EC3, 0x9CE5, 0x6EC4, 0x9CE6, 0x6EC5, 0x9CE7, 0x6EC6, 0x9CE8, 0x6EC7, 0xB5E1, 0x6EC8, 0x9CE9, 0x6EC9, 0x9CEA, 0x6ECA, 0x9CEB, + 0x6ECB, 0xD7CC, 0x6ECC, 0x9CEC, 0x6ECD, 0x9CED, 0x6ECE, 0x9CEE, 0x6ECF, 0xE4E6, 0x6ED0, 0x9CEF, 0x6ED1, 0xBBAC, 0x6ED2, 0x9CF0, + 0x6ED3, 0xD7D2, 0x6ED4, 0xCCCF, 0x6ED5, 0xEBF8, 0x6ED6, 0x9CF1, 0x6ED7, 0xE4E4, 0x6ED8, 0x9CF2, 0x6ED9, 0x9CF3, 0x6EDA, 0xB9F6, + 0x6EDB, 0x9CF4, 0x6EDC, 0x9CF5, 0x6EDD, 0x9CF6, 0x6EDE, 0xD6CD, 0x6EDF, 0xE4D9, 0x6EE0, 0xE4DC, 0x6EE1, 0xC2FA, 0x6EE2, 0xE4DE, + 0x6EE3, 0x9CF7, 0x6EE4, 0xC2CB, 0x6EE5, 0xC0C4, 0x6EE6, 0xC2D0, 0x6EE7, 0x9CF8, 0x6EE8, 0xB1F5, 0x6EE9, 0xCCB2, 0x6EEA, 0x9CF9, + 0x6EEB, 0x9CFA, 0x6EEC, 0x9CFB, 0x6EED, 0x9CFC, 0x6EEE, 0x9CFD, 0x6EEF, 0x9CFE, 0x6EF0, 0x9D40, 0x6EF1, 0x9D41, 0x6EF2, 0x9D42, + 0x6EF3, 0x9D43, 0x6EF4, 0xB5CE, 0x6EF5, 0x9D44, 0x6EF6, 0x9D45, 0x6EF7, 0x9D46, 0x6EF8, 0x9D47, 0x6EF9, 0xE4EF, 0x6EFA, 0x9D48, + 0x6EFB, 0x9D49, 0x6EFC, 0x9D4A, 0x6EFD, 0x9D4B, 0x6EFE, 0x9D4C, 0x6EFF, 0x9D4D, 0x6F00, 0x9D4E, 0x6F01, 0x9D4F, 0x6F02, 0xC6AF, + 0x6F03, 0x9D50, 0x6F04, 0x9D51, 0x6F05, 0x9D52, 0x6F06, 0xC6E1, 0x6F07, 0x9D53, 0x6F08, 0x9D54, 0x6F09, 0xE4F5, 0x6F0A, 0x9D55, + 0x6F0B, 0x9D56, 0x6F0C, 0x9D57, 0x6F0D, 0x9D58, 0x6F0E, 0x9D59, 0x6F0F, 0xC2A9, 0x6F10, 0x9D5A, 0x6F11, 0x9D5B, 0x6F12, 0x9D5C, + 0x6F13, 0xC0EC, 0x6F14, 0xD1DD, 0x6F15, 0xE4EE, 0x6F16, 0x9D5D, 0x6F17, 0x9D5E, 0x6F18, 0x9D5F, 0x6F19, 0x9D60, 0x6F1A, 0x9D61, + 0x6F1B, 0x9D62, 0x6F1C, 0x9D63, 0x6F1D, 0x9D64, 0x6F1E, 0x9D65, 0x6F1F, 0x9D66, 0x6F20, 0xC4AE, 0x6F21, 0x9D67, 0x6F22, 0x9D68, + 0x6F23, 0x9D69, 0x6F24, 0xE4ED, 0x6F25, 0x9D6A, 0x6F26, 0x9D6B, 0x6F27, 0x9D6C, 0x6F28, 0x9D6D, 0x6F29, 0xE4F6, 0x6F2A, 0xE4F4, + 0x6F2B, 0xC2FE, 0x6F2C, 0x9D6E, 0x6F2D, 0xE4DD, 0x6F2E, 0x9D6F, 0x6F2F, 0xE4F0, 0x6F30, 0x9D70, 0x6F31, 0xCAFE, 0x6F32, 0x9D71, + 0x6F33, 0xD5C4, 0x6F34, 0x9D72, 0x6F35, 0x9D73, 0x6F36, 0xE4F1, 0x6F37, 0x9D74, 0x6F38, 0x9D75, 0x6F39, 0x9D76, 0x6F3A, 0x9D77, + 0x6F3B, 0x9D78, 0x6F3C, 0x9D79, 0x6F3D, 0x9D7A, 0x6F3E, 0xD1FA, 0x6F3F, 0x9D7B, 0x6F40, 0x9D7C, 0x6F41, 0x9D7D, 0x6F42, 0x9D7E, + 0x6F43, 0x9D80, 0x6F44, 0x9D81, 0x6F45, 0x9D82, 0x6F46, 0xE4EB, 0x6F47, 0xE4EC, 0x6F48, 0x9D83, 0x6F49, 0x9D84, 0x6F4A, 0x9D85, + 0x6F4B, 0xE4F2, 0x6F4C, 0x9D86, 0x6F4D, 0xCEAB, 0x6F4E, 0x9D87, 0x6F4F, 0x9D88, 0x6F50, 0x9D89, 0x6F51, 0x9D8A, 0x6F52, 0x9D8B, + 0x6F53, 0x9D8C, 0x6F54, 0x9D8D, 0x6F55, 0x9D8E, 0x6F56, 0x9D8F, 0x6F57, 0x9D90, 0x6F58, 0xC5CB, 0x6F59, 0x9D91, 0x6F5A, 0x9D92, + 0x6F5B, 0x9D93, 0x6F5C, 0xC7B1, 0x6F5D, 0x9D94, 0x6F5E, 0xC2BA, 0x6F5F, 0x9D95, 0x6F60, 0x9D96, 0x6F61, 0x9D97, 0x6F62, 0xE4EA, + 0x6F63, 0x9D98, 0x6F64, 0x9D99, 0x6F65, 0x9D9A, 0x6F66, 0xC1CA, 0x6F67, 0x9D9B, 0x6F68, 0x9D9C, 0x6F69, 0x9D9D, 0x6F6A, 0x9D9E, + 0x6F6B, 0x9D9F, 0x6F6C, 0x9DA0, 0x6F6D, 0xCCB6, 0x6F6E, 0xB3B1, 0x6F6F, 0x9DA1, 0x6F70, 0x9DA2, 0x6F71, 0x9DA3, 0x6F72, 0xE4FB, + 0x6F73, 0x9DA4, 0x6F74, 0xE4F3, 0x6F75, 0x9DA5, 0x6F76, 0x9DA6, 0x6F77, 0x9DA7, 0x6F78, 0xE4FA, 0x6F79, 0x9DA8, 0x6F7A, 0xE4FD, + 0x6F7B, 0x9DA9, 0x6F7C, 0xE4FC, 0x6F7D, 0x9DAA, 0x6F7E, 0x9DAB, 0x6F7F, 0x9DAC, 0x6F80, 0x9DAD, 0x6F81, 0x9DAE, 0x6F82, 0x9DAF, + 0x6F83, 0x9DB0, 0x6F84, 0xB3CE, 0x6F85, 0x9DB1, 0x6F86, 0x9DB2, 0x6F87, 0x9DB3, 0x6F88, 0xB3BA, 0x6F89, 0xE4F7, 0x6F8A, 0x9DB4, + 0x6F8B, 0x9DB5, 0x6F8C, 0xE4F9, 0x6F8D, 0xE4F8, 0x6F8E, 0xC5EC, 0x6F8F, 0x9DB6, 0x6F90, 0x9DB7, 0x6F91, 0x9DB8, 0x6F92, 0x9DB9, + 0x6F93, 0x9DBA, 0x6F94, 0x9DBB, 0x6F95, 0x9DBC, 0x6F96, 0x9DBD, 0x6F97, 0x9DBE, 0x6F98, 0x9DBF, 0x6F99, 0x9DC0, 0x6F9A, 0x9DC1, + 0x6F9B, 0x9DC2, 0x6F9C, 0xC0BD, 0x6F9D, 0x9DC3, 0x6F9E, 0x9DC4, 0x6F9F, 0x9DC5, 0x6FA0, 0x9DC6, 0x6FA1, 0xD4E8, 0x6FA2, 0x9DC7, + 0x6FA3, 0x9DC8, 0x6FA4, 0x9DC9, 0x6FA5, 0x9DCA, 0x6FA6, 0x9DCB, 0x6FA7, 0xE5A2, 0x6FA8, 0x9DCC, 0x6FA9, 0x9DCD, 0x6FAA, 0x9DCE, + 0x6FAB, 0x9DCF, 0x6FAC, 0x9DD0, 0x6FAD, 0x9DD1, 0x6FAE, 0x9DD2, 0x6FAF, 0x9DD3, 0x6FB0, 0x9DD4, 0x6FB1, 0x9DD5, 0x6FB2, 0x9DD6, + 0x6FB3, 0xB0C4, 0x6FB4, 0x9DD7, 0x6FB5, 0x9DD8, 0x6FB6, 0xE5A4, 0x6FB7, 0x9DD9, 0x6FB8, 0x9DDA, 0x6FB9, 0xE5A3, 0x6FBA, 0x9DDB, + 0x6FBB, 0x9DDC, 0x6FBC, 0x9DDD, 0x6FBD, 0x9DDE, 0x6FBE, 0x9DDF, 0x6FBF, 0x9DE0, 0x6FC0, 0xBCA4, 0x6FC1, 0x9DE1, 0x6FC2, 0xE5A5, + 0x6FC3, 0x9DE2, 0x6FC4, 0x9DE3, 0x6FC5, 0x9DE4, 0x6FC6, 0x9DE5, 0x6FC7, 0x9DE6, 0x6FC8, 0x9DE7, 0x6FC9, 0xE5A1, 0x6FCA, 0x9DE8, + 0x6FCB, 0x9DE9, 0x6FCC, 0x9DEA, 0x6FCD, 0x9DEB, 0x6FCE, 0x9DEC, 0x6FCF, 0x9DED, 0x6FD0, 0x9DEE, 0x6FD1, 0xE4FE, 0x6FD2, 0xB1F4, + 0x6FD3, 0x9DEF, 0x6FD4, 0x9DF0, 0x6FD5, 0x9DF1, 0x6FD6, 0x9DF2, 0x6FD7, 0x9DF3, 0x6FD8, 0x9DF4, 0x6FD9, 0x9DF5, 0x6FDA, 0x9DF6, + 0x6FDB, 0x9DF7, 0x6FDC, 0x9DF8, 0x6FDD, 0x9DF9, 0x6FDE, 0xE5A8, 0x6FDF, 0x9DFA, 0x6FE0, 0xE5A9, 0x6FE1, 0xE5A6, 0x6FE2, 0x9DFB, + 0x6FE3, 0x9DFC, 0x6FE4, 0x9DFD, 0x6FE5, 0x9DFE, 0x6FE6, 0x9E40, 0x6FE7, 0x9E41, 0x6FE8, 0x9E42, 0x6FE9, 0x9E43, 0x6FEA, 0x9E44, + 0x6FEB, 0x9E45, 0x6FEC, 0x9E46, 0x6FED, 0x9E47, 0x6FEE, 0xE5A7, 0x6FEF, 0xE5AA, 0x6FF0, 0x9E48, 0x6FF1, 0x9E49, 0x6FF2, 0x9E4A, + 0x6FF3, 0x9E4B, 0x6FF4, 0x9E4C, 0x6FF5, 0x9E4D, 0x6FF6, 0x9E4E, 0x6FF7, 0x9E4F, 0x6FF8, 0x9E50, 0x6FF9, 0x9E51, 0x6FFA, 0x9E52, + 0x6FFB, 0x9E53, 0x6FFC, 0x9E54, 0x6FFD, 0x9E55, 0x6FFE, 0x9E56, 0x6FFF, 0x9E57, 0x7000, 0x9E58, 0x7001, 0x9E59, 0x7002, 0x9E5A, + 0x7003, 0x9E5B, 0x7004, 0x9E5C, 0x7005, 0x9E5D, 0x7006, 0x9E5E, 0x7007, 0x9E5F, 0x7008, 0x9E60, 0x7009, 0x9E61, 0x700A, 0x9E62, + 0x700B, 0x9E63, 0x700C, 0x9E64, 0x700D, 0x9E65, 0x700E, 0x9E66, 0x700F, 0x9E67, 0x7010, 0x9E68, 0x7011, 0xC6D9, 0x7012, 0x9E69, + 0x7013, 0x9E6A, 0x7014, 0x9E6B, 0x7015, 0x9E6C, 0x7016, 0x9E6D, 0x7017, 0x9E6E, 0x7018, 0x9E6F, 0x7019, 0x9E70, 0x701A, 0xE5AB, + 0x701B, 0xE5AD, 0x701C, 0x9E71, 0x701D, 0x9E72, 0x701E, 0x9E73, 0x701F, 0x9E74, 0x7020, 0x9E75, 0x7021, 0x9E76, 0x7022, 0x9E77, + 0x7023, 0xE5AC, 0x7024, 0x9E78, 0x7025, 0x9E79, 0x7026, 0x9E7A, 0x7027, 0x9E7B, 0x7028, 0x9E7C, 0x7029, 0x9E7D, 0x702A, 0x9E7E, + 0x702B, 0x9E80, 0x702C, 0x9E81, 0x702D, 0x9E82, 0x702E, 0x9E83, 0x702F, 0x9E84, 0x7030, 0x9E85, 0x7031, 0x9E86, 0x7032, 0x9E87, + 0x7033, 0x9E88, 0x7034, 0x9E89, 0x7035, 0xE5AF, 0x7036, 0x9E8A, 0x7037, 0x9E8B, 0x7038, 0x9E8C, 0x7039, 0xE5AE, 0x703A, 0x9E8D, + 0x703B, 0x9E8E, 0x703C, 0x9E8F, 0x703D, 0x9E90, 0x703E, 0x9E91, 0x703F, 0x9E92, 0x7040, 0x9E93, 0x7041, 0x9E94, 0x7042, 0x9E95, + 0x7043, 0x9E96, 0x7044, 0x9E97, 0x7045, 0x9E98, 0x7046, 0x9E99, 0x7047, 0x9E9A, 0x7048, 0x9E9B, 0x7049, 0x9E9C, 0x704A, 0x9E9D, + 0x704B, 0x9E9E, 0x704C, 0xB9E0, 0x704D, 0x9E9F, 0x704E, 0x9EA0, 0x704F, 0xE5B0, 0x7050, 0x9EA1, 0x7051, 0x9EA2, 0x7052, 0x9EA3, + 0x7053, 0x9EA4, 0x7054, 0x9EA5, 0x7055, 0x9EA6, 0x7056, 0x9EA7, 0x7057, 0x9EA8, 0x7058, 0x9EA9, 0x7059, 0x9EAA, 0x705A, 0x9EAB, + 0x705B, 0x9EAC, 0x705C, 0x9EAD, 0x705D, 0x9EAE, 0x705E, 0xE5B1, 0x705F, 0x9EAF, 0x7060, 0x9EB0, 0x7061, 0x9EB1, 0x7062, 0x9EB2, + 0x7063, 0x9EB3, 0x7064, 0x9EB4, 0x7065, 0x9EB5, 0x7066, 0x9EB6, 0x7067, 0x9EB7, 0x7068, 0x9EB8, 0x7069, 0x9EB9, 0x706A, 0x9EBA, + 0x706B, 0xBBF0, 0x706C, 0xECE1, 0x706D, 0xC3F0, 0x706E, 0x9EBB, 0x706F, 0xB5C6, 0x7070, 0xBBD2, 0x7071, 0x9EBC, 0x7072, 0x9EBD, + 0x7073, 0x9EBE, 0x7074, 0x9EBF, 0x7075, 0xC1E9, 0x7076, 0xD4EE, 0x7077, 0x9EC0, 0x7078, 0xBEC4, 0x7079, 0x9EC1, 0x707A, 0x9EC2, + 0x707B, 0x9EC3, 0x707C, 0xD7C6, 0x707D, 0x9EC4, 0x707E, 0xD4D6, 0x707F, 0xB2D3, 0x7080, 0xECBE, 0x7081, 0x9EC5, 0x7082, 0x9EC6, + 0x7083, 0x9EC7, 0x7084, 0x9EC8, 0x7085, 0xEAC1, 0x7086, 0x9EC9, 0x7087, 0x9ECA, 0x7088, 0x9ECB, 0x7089, 0xC2AF, 0x708A, 0xB4B6, + 0x708B, 0x9ECC, 0x708C, 0x9ECD, 0x708D, 0x9ECE, 0x708E, 0xD1D7, 0x708F, 0x9ECF, 0x7090, 0x9ED0, 0x7091, 0x9ED1, 0x7092, 0xB3B4, + 0x7093, 0x9ED2, 0x7094, 0xC8B2, 0x7095, 0xBFBB, 0x7096, 0xECC0, 0x7097, 0x9ED3, 0x7098, 0x9ED4, 0x7099, 0xD6CB, 0x709A, 0x9ED5, + 0x709B, 0x9ED6, 0x709C, 0xECBF, 0x709D, 0xECC1, 0x709E, 0x9ED7, 0x709F, 0x9ED8, 0x70A0, 0x9ED9, 0x70A1, 0x9EDA, 0x70A2, 0x9EDB, + 0x70A3, 0x9EDC, 0x70A4, 0x9EDD, 0x70A5, 0x9EDE, 0x70A6, 0x9EDF, 0x70A7, 0x9EE0, 0x70A8, 0x9EE1, 0x70A9, 0x9EE2, 0x70AA, 0x9EE3, + 0x70AB, 0xECC5, 0x70AC, 0xBEE6, 0x70AD, 0xCCBF, 0x70AE, 0xC5DA, 0x70AF, 0xBEBC, 0x70B0, 0x9EE4, 0x70B1, 0xECC6, 0x70B2, 0x9EE5, + 0x70B3, 0xB1FE, 0x70B4, 0x9EE6, 0x70B5, 0x9EE7, 0x70B6, 0x9EE8, 0x70B7, 0xECC4, 0x70B8, 0xD5A8, 0x70B9, 0xB5E3, 0x70BA, 0x9EE9, + 0x70BB, 0xECC2, 0x70BC, 0xC1B6, 0x70BD, 0xB3E3, 0x70BE, 0x9EEA, 0x70BF, 0x9EEB, 0x70C0, 0xECC3, 0x70C1, 0xCBB8, 0x70C2, 0xC0C3, + 0x70C3, 0xCCFE, 0x70C4, 0x9EEC, 0x70C5, 0x9EED, 0x70C6, 0x9EEE, 0x70C7, 0x9EEF, 0x70C8, 0xC1D2, 0x70C9, 0x9EF0, 0x70CA, 0xECC8, + 0x70CB, 0x9EF1, 0x70CC, 0x9EF2, 0x70CD, 0x9EF3, 0x70CE, 0x9EF4, 0x70CF, 0x9EF5, 0x70D0, 0x9EF6, 0x70D1, 0x9EF7, 0x70D2, 0x9EF8, + 0x70D3, 0x9EF9, 0x70D4, 0x9EFA, 0x70D5, 0x9EFB, 0x70D6, 0x9EFC, 0x70D7, 0x9EFD, 0x70D8, 0xBAE6, 0x70D9, 0xC0D3, 0x70DA, 0x9EFE, + 0x70DB, 0xD6F2, 0x70DC, 0x9F40, 0x70DD, 0x9F41, 0x70DE, 0x9F42, 0x70DF, 0xD1CC, 0x70E0, 0x9F43, 0x70E1, 0x9F44, 0x70E2, 0x9F45, + 0x70E3, 0x9F46, 0x70E4, 0xBFBE, 0x70E5, 0x9F47, 0x70E6, 0xB7B3, 0x70E7, 0xC9D5, 0x70E8, 0xECC7, 0x70E9, 0xBBE2, 0x70EA, 0x9F48, + 0x70EB, 0xCCCC, 0x70EC, 0xBDFD, 0x70ED, 0xC8C8, 0x70EE, 0x9F49, 0x70EF, 0xCFA9, 0x70F0, 0x9F4A, 0x70F1, 0x9F4B, 0x70F2, 0x9F4C, + 0x70F3, 0x9F4D, 0x70F4, 0x9F4E, 0x70F5, 0x9F4F, 0x70F6, 0x9F50, 0x70F7, 0xCDE9, 0x70F8, 0x9F51, 0x70F9, 0xC5EB, 0x70FA, 0x9F52, + 0x70FB, 0x9F53, 0x70FC, 0x9F54, 0x70FD, 0xB7E9, 0x70FE, 0x9F55, 0x70FF, 0x9F56, 0x7100, 0x9F57, 0x7101, 0x9F58, 0x7102, 0x9F59, + 0x7103, 0x9F5A, 0x7104, 0x9F5B, 0x7105, 0x9F5C, 0x7106, 0x9F5D, 0x7107, 0x9F5E, 0x7108, 0x9F5F, 0x7109, 0xD1C9, 0x710A, 0xBAB8, + 0x710B, 0x9F60, 0x710C, 0x9F61, 0x710D, 0x9F62, 0x710E, 0x9F63, 0x710F, 0x9F64, 0x7110, 0xECC9, 0x7111, 0x9F65, 0x7112, 0x9F66, + 0x7113, 0xECCA, 0x7114, 0x9F67, 0x7115, 0xBBC0, 0x7116, 0xECCB, 0x7117, 0x9F68, 0x7118, 0xECE2, 0x7119, 0xB1BA, 0x711A, 0xB7D9, + 0x711B, 0x9F69, 0x711C, 0x9F6A, 0x711D, 0x9F6B, 0x711E, 0x9F6C, 0x711F, 0x9F6D, 0x7120, 0x9F6E, 0x7121, 0x9F6F, 0x7122, 0x9F70, + 0x7123, 0x9F71, 0x7124, 0x9F72, 0x7125, 0x9F73, 0x7126, 0xBDB9, 0x7127, 0x9F74, 0x7128, 0x9F75, 0x7129, 0x9F76, 0x712A, 0x9F77, + 0x712B, 0x9F78, 0x712C, 0x9F79, 0x712D, 0x9F7A, 0x712E, 0x9F7B, 0x712F, 0xECCC, 0x7130, 0xD1E6, 0x7131, 0xECCD, 0x7132, 0x9F7C, + 0x7133, 0x9F7D, 0x7134, 0x9F7E, 0x7135, 0x9F80, 0x7136, 0xC8BB, 0x7137, 0x9F81, 0x7138, 0x9F82, 0x7139, 0x9F83, 0x713A, 0x9F84, + 0x713B, 0x9F85, 0x713C, 0x9F86, 0x713D, 0x9F87, 0x713E, 0x9F88, 0x713F, 0x9F89, 0x7140, 0x9F8A, 0x7141, 0x9F8B, 0x7142, 0x9F8C, + 0x7143, 0x9F8D, 0x7144, 0x9F8E, 0x7145, 0xECD1, 0x7146, 0x9F8F, 0x7147, 0x9F90, 0x7148, 0x9F91, 0x7149, 0x9F92, 0x714A, 0xECD3, + 0x714B, 0x9F93, 0x714C, 0xBBCD, 0x714D, 0x9F94, 0x714E, 0xBCE5, 0x714F, 0x9F95, 0x7150, 0x9F96, 0x7151, 0x9F97, 0x7152, 0x9F98, + 0x7153, 0x9F99, 0x7154, 0x9F9A, 0x7155, 0x9F9B, 0x7156, 0x9F9C, 0x7157, 0x9F9D, 0x7158, 0x9F9E, 0x7159, 0x9F9F, 0x715A, 0x9FA0, + 0x715B, 0x9FA1, 0x715C, 0xECCF, 0x715D, 0x9FA2, 0x715E, 0xC9B7, 0x715F, 0x9FA3, 0x7160, 0x9FA4, 0x7161, 0x9FA5, 0x7162, 0x9FA6, + 0x7163, 0x9FA7, 0x7164, 0xC3BA, 0x7165, 0x9FA8, 0x7166, 0xECE3, 0x7167, 0xD5D5, 0x7168, 0xECD0, 0x7169, 0x9FA9, 0x716A, 0x9FAA, + 0x716B, 0x9FAB, 0x716C, 0x9FAC, 0x716D, 0x9FAD, 0x716E, 0xD6F3, 0x716F, 0x9FAE, 0x7170, 0x9FAF, 0x7171, 0x9FB0, 0x7172, 0xECD2, + 0x7173, 0xECCE, 0x7174, 0x9FB1, 0x7175, 0x9FB2, 0x7176, 0x9FB3, 0x7177, 0x9FB4, 0x7178, 0xECD4, 0x7179, 0x9FB5, 0x717A, 0xECD5, + 0x717B, 0x9FB6, 0x717C, 0x9FB7, 0x717D, 0xC9BF, 0x717E, 0x9FB8, 0x717F, 0x9FB9, 0x7180, 0x9FBA, 0x7181, 0x9FBB, 0x7182, 0x9FBC, + 0x7183, 0x9FBD, 0x7184, 0xCFA8, 0x7185, 0x9FBE, 0x7186, 0x9FBF, 0x7187, 0x9FC0, 0x7188, 0x9FC1, 0x7189, 0x9FC2, 0x718A, 0xD0DC, + 0x718B, 0x9FC3, 0x718C, 0x9FC4, 0x718D, 0x9FC5, 0x718E, 0x9FC6, 0x718F, 0xD1AC, 0x7190, 0x9FC7, 0x7191, 0x9FC8, 0x7192, 0x9FC9, + 0x7193, 0x9FCA, 0x7194, 0xC8DB, 0x7195, 0x9FCB, 0x7196, 0x9FCC, 0x7197, 0x9FCD, 0x7198, 0xECD6, 0x7199, 0xCEF5, 0x719A, 0x9FCE, + 0x719B, 0x9FCF, 0x719C, 0x9FD0, 0x719D, 0x9FD1, 0x719E, 0x9FD2, 0x719F, 0xCAEC, 0x71A0, 0xECDA, 0x71A1, 0x9FD3, 0x71A2, 0x9FD4, + 0x71A3, 0x9FD5, 0x71A4, 0x9FD6, 0x71A5, 0x9FD7, 0x71A6, 0x9FD8, 0x71A7, 0x9FD9, 0x71A8, 0xECD9, 0x71A9, 0x9FDA, 0x71AA, 0x9FDB, + 0x71AB, 0x9FDC, 0x71AC, 0xB0BE, 0x71AD, 0x9FDD, 0x71AE, 0x9FDE, 0x71AF, 0x9FDF, 0x71B0, 0x9FE0, 0x71B1, 0x9FE1, 0x71B2, 0x9FE2, + 0x71B3, 0xECD7, 0x71B4, 0x9FE3, 0x71B5, 0xECD8, 0x71B6, 0x9FE4, 0x71B7, 0x9FE5, 0x71B8, 0x9FE6, 0x71B9, 0xECE4, 0x71BA, 0x9FE7, + 0x71BB, 0x9FE8, 0x71BC, 0x9FE9, 0x71BD, 0x9FEA, 0x71BE, 0x9FEB, 0x71BF, 0x9FEC, 0x71C0, 0x9FED, 0x71C1, 0x9FEE, 0x71C2, 0x9FEF, + 0x71C3, 0xC8BC, 0x71C4, 0x9FF0, 0x71C5, 0x9FF1, 0x71C6, 0x9FF2, 0x71C7, 0x9FF3, 0x71C8, 0x9FF4, 0x71C9, 0x9FF5, 0x71CA, 0x9FF6, + 0x71CB, 0x9FF7, 0x71CC, 0x9FF8, 0x71CD, 0x9FF9, 0x71CE, 0xC1C7, 0x71CF, 0x9FFA, 0x71D0, 0x9FFB, 0x71D1, 0x9FFC, 0x71D2, 0x9FFD, + 0x71D3, 0x9FFE, 0x71D4, 0xECDC, 0x71D5, 0xD1E0, 0x71D6, 0xA040, 0x71D7, 0xA041, 0x71D8, 0xA042, 0x71D9, 0xA043, 0x71DA, 0xA044, + 0x71DB, 0xA045, 0x71DC, 0xA046, 0x71DD, 0xA047, 0x71DE, 0xA048, 0x71DF, 0xA049, 0x71E0, 0xECDB, 0x71E1, 0xA04A, 0x71E2, 0xA04B, + 0x71E3, 0xA04C, 0x71E4, 0xA04D, 0x71E5, 0xD4EF, 0x71E6, 0xA04E, 0x71E7, 0xECDD, 0x71E8, 0xA04F, 0x71E9, 0xA050, 0x71EA, 0xA051, + 0x71EB, 0xA052, 0x71EC, 0xA053, 0x71ED, 0xA054, 0x71EE, 0xDBC6, 0x71EF, 0xA055, 0x71F0, 0xA056, 0x71F1, 0xA057, 0x71F2, 0xA058, + 0x71F3, 0xA059, 0x71F4, 0xA05A, 0x71F5, 0xA05B, 0x71F6, 0xA05C, 0x71F7, 0xA05D, 0x71F8, 0xA05E, 0x71F9, 0xECDE, 0x71FA, 0xA05F, + 0x71FB, 0xA060, 0x71FC, 0xA061, 0x71FD, 0xA062, 0x71FE, 0xA063, 0x71FF, 0xA064, 0x7200, 0xA065, 0x7201, 0xA066, 0x7202, 0xA067, + 0x7203, 0xA068, 0x7204, 0xA069, 0x7205, 0xA06A, 0x7206, 0xB1AC, 0x7207, 0xA06B, 0x7208, 0xA06C, 0x7209, 0xA06D, 0x720A, 0xA06E, + 0x720B, 0xA06F, 0x720C, 0xA070, 0x720D, 0xA071, 0x720E, 0xA072, 0x720F, 0xA073, 0x7210, 0xA074, 0x7211, 0xA075, 0x7212, 0xA076, + 0x7213, 0xA077, 0x7214, 0xA078, 0x7215, 0xA079, 0x7216, 0xA07A, 0x7217, 0xA07B, 0x7218, 0xA07C, 0x7219, 0xA07D, 0x721A, 0xA07E, + 0x721B, 0xA080, 0x721C, 0xA081, 0x721D, 0xECDF, 0x721E, 0xA082, 0x721F, 0xA083, 0x7220, 0xA084, 0x7221, 0xA085, 0x7222, 0xA086, + 0x7223, 0xA087, 0x7224, 0xA088, 0x7225, 0xA089, 0x7226, 0xA08A, 0x7227, 0xA08B, 0x7228, 0xECE0, 0x7229, 0xA08C, 0x722A, 0xD7A6, + 0x722B, 0xA08D, 0x722C, 0xC5C0, 0x722D, 0xA08E, 0x722E, 0xA08F, 0x722F, 0xA090, 0x7230, 0xEBBC, 0x7231, 0xB0AE, 0x7232, 0xA091, + 0x7233, 0xA092, 0x7234, 0xA093, 0x7235, 0xBEF4, 0x7236, 0xB8B8, 0x7237, 0xD2AF, 0x7238, 0xB0D6, 0x7239, 0xB5F9, 0x723A, 0xA094, + 0x723B, 0xD8B3, 0x723C, 0xA095, 0x723D, 0xCBAC, 0x723E, 0xA096, 0x723F, 0xE3DD, 0x7240, 0xA097, 0x7241, 0xA098, 0x7242, 0xA099, + 0x7243, 0xA09A, 0x7244, 0xA09B, 0x7245, 0xA09C, 0x7246, 0xA09D, 0x7247, 0xC6AC, 0x7248, 0xB0E6, 0x7249, 0xA09E, 0x724A, 0xA09F, + 0x724B, 0xA0A0, 0x724C, 0xC5C6, 0x724D, 0xEBB9, 0x724E, 0xA0A1, 0x724F, 0xA0A2, 0x7250, 0xA0A3, 0x7251, 0xA0A4, 0x7252, 0xEBBA, + 0x7253, 0xA0A5, 0x7254, 0xA0A6, 0x7255, 0xA0A7, 0x7256, 0xEBBB, 0x7257, 0xA0A8, 0x7258, 0xA0A9, 0x7259, 0xD1C0, 0x725A, 0xA0AA, + 0x725B, 0xC5A3, 0x725C, 0xA0AB, 0x725D, 0xEAF2, 0x725E, 0xA0AC, 0x725F, 0xC4B2, 0x7260, 0xA0AD, 0x7261, 0xC4B5, 0x7262, 0xC0CE, + 0x7263, 0xA0AE, 0x7264, 0xA0AF, 0x7265, 0xA0B0, 0x7266, 0xEAF3, 0x7267, 0xC4C1, 0x7268, 0xA0B1, 0x7269, 0xCEEF, 0x726A, 0xA0B2, + 0x726B, 0xA0B3, 0x726C, 0xA0B4, 0x726D, 0xA0B5, 0x726E, 0xEAF0, 0x726F, 0xEAF4, 0x7270, 0xA0B6, 0x7271, 0xA0B7, 0x7272, 0xC9FC, + 0x7273, 0xA0B8, 0x7274, 0xA0B9, 0x7275, 0xC7A3, 0x7276, 0xA0BA, 0x7277, 0xA0BB, 0x7278, 0xA0BC, 0x7279, 0xCCD8, 0x727A, 0xCEFE, + 0x727B, 0xA0BD, 0x727C, 0xA0BE, 0x727D, 0xA0BF, 0x727E, 0xEAF5, 0x727F, 0xEAF6, 0x7280, 0xCFAC, 0x7281, 0xC0E7, 0x7282, 0xA0C0, + 0x7283, 0xA0C1, 0x7284, 0xEAF7, 0x7285, 0xA0C2, 0x7286, 0xA0C3, 0x7287, 0xA0C4, 0x7288, 0xA0C5, 0x7289, 0xA0C6, 0x728A, 0xB6BF, + 0x728B, 0xEAF8, 0x728C, 0xA0C7, 0x728D, 0xEAF9, 0x728E, 0xA0C8, 0x728F, 0xEAFA, 0x7290, 0xA0C9, 0x7291, 0xA0CA, 0x7292, 0xEAFB, + 0x7293, 0xA0CB, 0x7294, 0xA0CC, 0x7295, 0xA0CD, 0x7296, 0xA0CE, 0x7297, 0xA0CF, 0x7298, 0xA0D0, 0x7299, 0xA0D1, 0x729A, 0xA0D2, + 0x729B, 0xA0D3, 0x729C, 0xA0D4, 0x729D, 0xA0D5, 0x729E, 0xA0D6, 0x729F, 0xEAF1, 0x72A0, 0xA0D7, 0x72A1, 0xA0D8, 0x72A2, 0xA0D9, + 0x72A3, 0xA0DA, 0x72A4, 0xA0DB, 0x72A5, 0xA0DC, 0x72A6, 0xA0DD, 0x72A7, 0xA0DE, 0x72A8, 0xA0DF, 0x72A9, 0xA0E0, 0x72AA, 0xA0E1, + 0x72AB, 0xA0E2, 0x72AC, 0xC8AE, 0x72AD, 0xE1EB, 0x72AE, 0xA0E3, 0x72AF, 0xB7B8, 0x72B0, 0xE1EC, 0x72B1, 0xA0E4, 0x72B2, 0xA0E5, + 0x72B3, 0xA0E6, 0x72B4, 0xE1ED, 0x72B5, 0xA0E7, 0x72B6, 0xD7B4, 0x72B7, 0xE1EE, 0x72B8, 0xE1EF, 0x72B9, 0xD3CC, 0x72BA, 0xA0E8, + 0x72BB, 0xA0E9, 0x72BC, 0xA0EA, 0x72BD, 0xA0EB, 0x72BE, 0xA0EC, 0x72BF, 0xA0ED, 0x72C0, 0xA0EE, 0x72C1, 0xE1F1, 0x72C2, 0xBFF1, + 0x72C3, 0xE1F0, 0x72C4, 0xB5D2, 0x72C5, 0xA0EF, 0x72C6, 0xA0F0, 0x72C7, 0xA0F1, 0x72C8, 0xB1B7, 0x72C9, 0xA0F2, 0x72CA, 0xA0F3, + 0x72CB, 0xA0F4, 0x72CC, 0xA0F5, 0x72CD, 0xE1F3, 0x72CE, 0xE1F2, 0x72CF, 0xA0F6, 0x72D0, 0xBAFC, 0x72D1, 0xA0F7, 0x72D2, 0xE1F4, + 0x72D3, 0xA0F8, 0x72D4, 0xA0F9, 0x72D5, 0xA0FA, 0x72D6, 0xA0FB, 0x72D7, 0xB9B7, 0x72D8, 0xA0FC, 0x72D9, 0xBED1, 0x72DA, 0xA0FD, + 0x72DB, 0xA0FE, 0x72DC, 0xAA40, 0x72DD, 0xAA41, 0x72DE, 0xC4FC, 0x72DF, 0xAA42, 0x72E0, 0xBADD, 0x72E1, 0xBDC6, 0x72E2, 0xAA43, + 0x72E3, 0xAA44, 0x72E4, 0xAA45, 0x72E5, 0xAA46, 0x72E6, 0xAA47, 0x72E7, 0xAA48, 0x72E8, 0xE1F5, 0x72E9, 0xE1F7, 0x72EA, 0xAA49, + 0x72EB, 0xAA4A, 0x72EC, 0xB6C0, 0x72ED, 0xCFC1, 0x72EE, 0xCAA8, 0x72EF, 0xE1F6, 0x72F0, 0xD5F8, 0x72F1, 0xD3FC, 0x72F2, 0xE1F8, + 0x72F3, 0xE1FC, 0x72F4, 0xE1F9, 0x72F5, 0xAA4B, 0x72F6, 0xAA4C, 0x72F7, 0xE1FA, 0x72F8, 0xC0EA, 0x72F9, 0xAA4D, 0x72FA, 0xE1FE, + 0x72FB, 0xE2A1, 0x72FC, 0xC0C7, 0x72FD, 0xAA4E, 0x72FE, 0xAA4F, 0x72FF, 0xAA50, 0x7300, 0xAA51, 0x7301, 0xE1FB, 0x7302, 0xAA52, + 0x7303, 0xE1FD, 0x7304, 0xAA53, 0x7305, 0xAA54, 0x7306, 0xAA55, 0x7307, 0xAA56, 0x7308, 0xAA57, 0x7309, 0xAA58, 0x730A, 0xE2A5, + 0x730B, 0xAA59, 0x730C, 0xAA5A, 0x730D, 0xAA5B, 0x730E, 0xC1D4, 0x730F, 0xAA5C, 0x7310, 0xAA5D, 0x7311, 0xAA5E, 0x7312, 0xAA5F, + 0x7313, 0xE2A3, 0x7314, 0xAA60, 0x7315, 0xE2A8, 0x7316, 0xB2FE, 0x7317, 0xE2A2, 0x7318, 0xAA61, 0x7319, 0xAA62, 0x731A, 0xAA63, + 0x731B, 0xC3CD, 0x731C, 0xB2C2, 0x731D, 0xE2A7, 0x731E, 0xE2A6, 0x731F, 0xAA64, 0x7320, 0xAA65, 0x7321, 0xE2A4, 0x7322, 0xE2A9, + 0x7323, 0xAA66, 0x7324, 0xAA67, 0x7325, 0xE2AB, 0x7326, 0xAA68, 0x7327, 0xAA69, 0x7328, 0xAA6A, 0x7329, 0xD0C9, 0x732A, 0xD6ED, + 0x732B, 0xC3A8, 0x732C, 0xE2AC, 0x732D, 0xAA6B, 0x732E, 0xCFD7, 0x732F, 0xAA6C, 0x7330, 0xAA6D, 0x7331, 0xE2AE, 0x7332, 0xAA6E, + 0x7333, 0xAA6F, 0x7334, 0xBAEF, 0x7335, 0xAA70, 0x7336, 0xAA71, 0x7337, 0xE9E0, 0x7338, 0xE2AD, 0x7339, 0xE2AA, 0x733A, 0xAA72, + 0x733B, 0xAA73, 0x733C, 0xAA74, 0x733D, 0xAA75, 0x733E, 0xBBAB, 0x733F, 0xD4B3, 0x7340, 0xAA76, 0x7341, 0xAA77, 0x7342, 0xAA78, + 0x7343, 0xAA79, 0x7344, 0xAA7A, 0x7345, 0xAA7B, 0x7346, 0xAA7C, 0x7347, 0xAA7D, 0x7348, 0xAA7E, 0x7349, 0xAA80, 0x734A, 0xAA81, + 0x734B, 0xAA82, 0x734C, 0xAA83, 0x734D, 0xE2B0, 0x734E, 0xAA84, 0x734F, 0xAA85, 0x7350, 0xE2AF, 0x7351, 0xAA86, 0x7352, 0xE9E1, + 0x7353, 0xAA87, 0x7354, 0xAA88, 0x7355, 0xAA89, 0x7356, 0xAA8A, 0x7357, 0xE2B1, 0x7358, 0xAA8B, 0x7359, 0xAA8C, 0x735A, 0xAA8D, + 0x735B, 0xAA8E, 0x735C, 0xAA8F, 0x735D, 0xAA90, 0x735E, 0xAA91, 0x735F, 0xAA92, 0x7360, 0xE2B2, 0x7361, 0xAA93, 0x7362, 0xAA94, + 0x7363, 0xAA95, 0x7364, 0xAA96, 0x7365, 0xAA97, 0x7366, 0xAA98, 0x7367, 0xAA99, 0x7368, 0xAA9A, 0x7369, 0xAA9B, 0x736A, 0xAA9C, + 0x736B, 0xAA9D, 0x736C, 0xE2B3, 0x736D, 0xCCA1, 0x736E, 0xAA9E, 0x736F, 0xE2B4, 0x7370, 0xAA9F, 0x7371, 0xAAA0, 0x7372, 0xAB40, + 0x7373, 0xAB41, 0x7374, 0xAB42, 0x7375, 0xAB43, 0x7376, 0xAB44, 0x7377, 0xAB45, 0x7378, 0xAB46, 0x7379, 0xAB47, 0x737A, 0xAB48, + 0x737B, 0xAB49, 0x737C, 0xAB4A, 0x737D, 0xAB4B, 0x737E, 0xE2B5, 0x737F, 0xAB4C, 0x7380, 0xAB4D, 0x7381, 0xAB4E, 0x7382, 0xAB4F, + 0x7383, 0xAB50, 0x7384, 0xD0FE, 0x7385, 0xAB51, 0x7386, 0xAB52, 0x7387, 0xC2CA, 0x7388, 0xAB53, 0x7389, 0xD3F1, 0x738A, 0xAB54, + 0x738B, 0xCDF5, 0x738C, 0xAB55, 0x738D, 0xAB56, 0x738E, 0xE7E0, 0x738F, 0xAB57, 0x7390, 0xAB58, 0x7391, 0xE7E1, 0x7392, 0xAB59, + 0x7393, 0xAB5A, 0x7394, 0xAB5B, 0x7395, 0xAB5C, 0x7396, 0xBEC1, 0x7397, 0xAB5D, 0x7398, 0xAB5E, 0x7399, 0xAB5F, 0x739A, 0xAB60, + 0x739B, 0xC2EA, 0x739C, 0xAB61, 0x739D, 0xAB62, 0x739E, 0xAB63, 0x739F, 0xE7E4, 0x73A0, 0xAB64, 0x73A1, 0xAB65, 0x73A2, 0xE7E3, + 0x73A3, 0xAB66, 0x73A4, 0xAB67, 0x73A5, 0xAB68, 0x73A6, 0xAB69, 0x73A7, 0xAB6A, 0x73A8, 0xAB6B, 0x73A9, 0xCDE6, 0x73AA, 0xAB6C, + 0x73AB, 0xC3B5, 0x73AC, 0xAB6D, 0x73AD, 0xAB6E, 0x73AE, 0xE7E2, 0x73AF, 0xBBB7, 0x73B0, 0xCFD6, 0x73B1, 0xAB6F, 0x73B2, 0xC1E1, + 0x73B3, 0xE7E9, 0x73B4, 0xAB70, 0x73B5, 0xAB71, 0x73B6, 0xAB72, 0x73B7, 0xE7E8, 0x73B8, 0xAB73, 0x73B9, 0xAB74, 0x73BA, 0xE7F4, + 0x73BB, 0xB2A3, 0x73BC, 0xAB75, 0x73BD, 0xAB76, 0x73BE, 0xAB77, 0x73BF, 0xAB78, 0x73C0, 0xE7EA, 0x73C1, 0xAB79, 0x73C2, 0xE7E6, + 0x73C3, 0xAB7A, 0x73C4, 0xAB7B, 0x73C5, 0xAB7C, 0x73C6, 0xAB7D, 0x73C7, 0xAB7E, 0x73C8, 0xE7EC, 0x73C9, 0xE7EB, 0x73CA, 0xC9BA, + 0x73CB, 0xAB80, 0x73CC, 0xAB81, 0x73CD, 0xD5E4, 0x73CE, 0xAB82, 0x73CF, 0xE7E5, 0x73D0, 0xB7A9, 0x73D1, 0xE7E7, 0x73D2, 0xAB83, + 0x73D3, 0xAB84, 0x73D4, 0xAB85, 0x73D5, 0xAB86, 0x73D6, 0xAB87, 0x73D7, 0xAB88, 0x73D8, 0xAB89, 0x73D9, 0xE7EE, 0x73DA, 0xAB8A, + 0x73DB, 0xAB8B, 0x73DC, 0xAB8C, 0x73DD, 0xAB8D, 0x73DE, 0xE7F3, 0x73DF, 0xAB8E, 0x73E0, 0xD6E9, 0x73E1, 0xAB8F, 0x73E2, 0xAB90, + 0x73E3, 0xAB91, 0x73E4, 0xAB92, 0x73E5, 0xE7ED, 0x73E6, 0xAB93, 0x73E7, 0xE7F2, 0x73E8, 0xAB94, 0x73E9, 0xE7F1, 0x73EA, 0xAB95, + 0x73EB, 0xAB96, 0x73EC, 0xAB97, 0x73ED, 0xB0E0, 0x73EE, 0xAB98, 0x73EF, 0xAB99, 0x73F0, 0xAB9A, 0x73F1, 0xAB9B, 0x73F2, 0xE7F5, + 0x73F3, 0xAB9C, 0x73F4, 0xAB9D, 0x73F5, 0xAB9E, 0x73F6, 0xAB9F, 0x73F7, 0xABA0, 0x73F8, 0xAC40, 0x73F9, 0xAC41, 0x73FA, 0xAC42, + 0x73FB, 0xAC43, 0x73FC, 0xAC44, 0x73FD, 0xAC45, 0x73FE, 0xAC46, 0x73FF, 0xAC47, 0x7400, 0xAC48, 0x7401, 0xAC49, 0x7402, 0xAC4A, + 0x7403, 0xC7F2, 0x7404, 0xAC4B, 0x7405, 0xC0C5, 0x7406, 0xC0ED, 0x7407, 0xAC4C, 0x7408, 0xAC4D, 0x7409, 0xC1F0, 0x740A, 0xE7F0, + 0x740B, 0xAC4E, 0x740C, 0xAC4F, 0x740D, 0xAC50, 0x740E, 0xAC51, 0x740F, 0xE7F6, 0x7410, 0xCBF6, 0x7411, 0xAC52, 0x7412, 0xAC53, + 0x7413, 0xAC54, 0x7414, 0xAC55, 0x7415, 0xAC56, 0x7416, 0xAC57, 0x7417, 0xAC58, 0x7418, 0xAC59, 0x7419, 0xAC5A, 0x741A, 0xE8A2, + 0x741B, 0xE8A1, 0x741C, 0xAC5B, 0x741D, 0xAC5C, 0x741E, 0xAC5D, 0x741F, 0xAC5E, 0x7420, 0xAC5F, 0x7421, 0xAC60, 0x7422, 0xD7C1, + 0x7423, 0xAC61, 0x7424, 0xAC62, 0x7425, 0xE7FA, 0x7426, 0xE7F9, 0x7427, 0xAC63, 0x7428, 0xE7FB, 0x7429, 0xAC64, 0x742A, 0xE7F7, + 0x742B, 0xAC65, 0x742C, 0xE7FE, 0x742D, 0xAC66, 0x742E, 0xE7FD, 0x742F, 0xAC67, 0x7430, 0xE7FC, 0x7431, 0xAC68, 0x7432, 0xAC69, + 0x7433, 0xC1D5, 0x7434, 0xC7D9, 0x7435, 0xC5FD, 0x7436, 0xC5C3, 0x7437, 0xAC6A, 0x7438, 0xAC6B, 0x7439, 0xAC6C, 0x743A, 0xAC6D, + 0x743B, 0xAC6E, 0x743C, 0xC7ED, 0x743D, 0xAC6F, 0x743E, 0xAC70, 0x743F, 0xAC71, 0x7440, 0xAC72, 0x7441, 0xE8A3, 0x7442, 0xAC73, + 0x7443, 0xAC74, 0x7444, 0xAC75, 0x7445, 0xAC76, 0x7446, 0xAC77, 0x7447, 0xAC78, 0x7448, 0xAC79, 0x7449, 0xAC7A, 0x744A, 0xAC7B, + 0x744B, 0xAC7C, 0x744C, 0xAC7D, 0x744D, 0xAC7E, 0x744E, 0xAC80, 0x744F, 0xAC81, 0x7450, 0xAC82, 0x7451, 0xAC83, 0x7452, 0xAC84, + 0x7453, 0xAC85, 0x7454, 0xAC86, 0x7455, 0xE8A6, 0x7456, 0xAC87, 0x7457, 0xE8A5, 0x7458, 0xAC88, 0x7459, 0xE8A7, 0x745A, 0xBAF7, + 0x745B, 0xE7F8, 0x745C, 0xE8A4, 0x745D, 0xAC89, 0x745E, 0xC8F0, 0x745F, 0xC9AA, 0x7460, 0xAC8A, 0x7461, 0xAC8B, 0x7462, 0xAC8C, + 0x7463, 0xAC8D, 0x7464, 0xAC8E, 0x7465, 0xAC8F, 0x7466, 0xAC90, 0x7467, 0xAC91, 0x7468, 0xAC92, 0x7469, 0xAC93, 0x746A, 0xAC94, + 0x746B, 0xAC95, 0x746C, 0xAC96, 0x746D, 0xE8A9, 0x746E, 0xAC97, 0x746F, 0xAC98, 0x7470, 0xB9E5, 0x7471, 0xAC99, 0x7472, 0xAC9A, + 0x7473, 0xAC9B, 0x7474, 0xAC9C, 0x7475, 0xAC9D, 0x7476, 0xD1FE, 0x7477, 0xE8A8, 0x7478, 0xAC9E, 0x7479, 0xAC9F, 0x747A, 0xACA0, + 0x747B, 0xAD40, 0x747C, 0xAD41, 0x747D, 0xAD42, 0x747E, 0xE8AA, 0x747F, 0xAD43, 0x7480, 0xE8AD, 0x7481, 0xE8AE, 0x7482, 0xAD44, + 0x7483, 0xC1A7, 0x7484, 0xAD45, 0x7485, 0xAD46, 0x7486, 0xAD47, 0x7487, 0xE8AF, 0x7488, 0xAD48, 0x7489, 0xAD49, 0x748A, 0xAD4A, + 0x748B, 0xE8B0, 0x748C, 0xAD4B, 0x748D, 0xAD4C, 0x748E, 0xE8AC, 0x748F, 0xAD4D, 0x7490, 0xE8B4, 0x7491, 0xAD4E, 0x7492, 0xAD4F, + 0x7493, 0xAD50, 0x7494, 0xAD51, 0x7495, 0xAD52, 0x7496, 0xAD53, 0x7497, 0xAD54, 0x7498, 0xAD55, 0x7499, 0xAD56, 0x749A, 0xAD57, + 0x749B, 0xAD58, 0x749C, 0xE8AB, 0x749D, 0xAD59, 0x749E, 0xE8B1, 0x749F, 0xAD5A, 0x74A0, 0xAD5B, 0x74A1, 0xAD5C, 0x74A2, 0xAD5D, + 0x74A3, 0xAD5E, 0x74A4, 0xAD5F, 0x74A5, 0xAD60, 0x74A6, 0xAD61, 0x74A7, 0xE8B5, 0x74A8, 0xE8B2, 0x74A9, 0xE8B3, 0x74AA, 0xAD62, + 0x74AB, 0xAD63, 0x74AC, 0xAD64, 0x74AD, 0xAD65, 0x74AE, 0xAD66, 0x74AF, 0xAD67, 0x74B0, 0xAD68, 0x74B1, 0xAD69, 0x74B2, 0xAD6A, + 0x74B3, 0xAD6B, 0x74B4, 0xAD6C, 0x74B5, 0xAD6D, 0x74B6, 0xAD6E, 0x74B7, 0xAD6F, 0x74B8, 0xAD70, 0x74B9, 0xAD71, 0x74BA, 0xE8B7, + 0x74BB, 0xAD72, 0x74BC, 0xAD73, 0x74BD, 0xAD74, 0x74BE, 0xAD75, 0x74BF, 0xAD76, 0x74C0, 0xAD77, 0x74C1, 0xAD78, 0x74C2, 0xAD79, + 0x74C3, 0xAD7A, 0x74C4, 0xAD7B, 0x74C5, 0xAD7C, 0x74C6, 0xAD7D, 0x74C7, 0xAD7E, 0x74C8, 0xAD80, 0x74C9, 0xAD81, 0x74CA, 0xAD82, + 0x74CB, 0xAD83, 0x74CC, 0xAD84, 0x74CD, 0xAD85, 0x74CE, 0xAD86, 0x74CF, 0xAD87, 0x74D0, 0xAD88, 0x74D1, 0xAD89, 0x74D2, 0xE8B6, + 0x74D3, 0xAD8A, 0x74D4, 0xAD8B, 0x74D5, 0xAD8C, 0x74D6, 0xAD8D, 0x74D7, 0xAD8E, 0x74D8, 0xAD8F, 0x74D9, 0xAD90, 0x74DA, 0xAD91, + 0x74DB, 0xAD92, 0x74DC, 0xB9CF, 0x74DD, 0xAD93, 0x74DE, 0xF0AC, 0x74DF, 0xAD94, 0x74E0, 0xF0AD, 0x74E1, 0xAD95, 0x74E2, 0xC6B0, + 0x74E3, 0xB0EA, 0x74E4, 0xC8BF, 0x74E5, 0xAD96, 0x74E6, 0xCDDF, 0x74E7, 0xAD97, 0x74E8, 0xAD98, 0x74E9, 0xAD99, 0x74EA, 0xAD9A, + 0x74EB, 0xAD9B, 0x74EC, 0xAD9C, 0x74ED, 0xAD9D, 0x74EE, 0xCECD, 0x74EF, 0xEAB1, 0x74F0, 0xAD9E, 0x74F1, 0xAD9F, 0x74F2, 0xADA0, + 0x74F3, 0xAE40, 0x74F4, 0xEAB2, 0x74F5, 0xAE41, 0x74F6, 0xC6BF, 0x74F7, 0xB4C9, 0x74F8, 0xAE42, 0x74F9, 0xAE43, 0x74FA, 0xAE44, + 0x74FB, 0xAE45, 0x74FC, 0xAE46, 0x74FD, 0xAE47, 0x74FE, 0xAE48, 0x74FF, 0xEAB3, 0x7500, 0xAE49, 0x7501, 0xAE4A, 0x7502, 0xAE4B, + 0x7503, 0xAE4C, 0x7504, 0xD5E7, 0x7505, 0xAE4D, 0x7506, 0xAE4E, 0x7507, 0xAE4F, 0x7508, 0xAE50, 0x7509, 0xAE51, 0x750A, 0xAE52, + 0x750B, 0xAE53, 0x750C, 0xAE54, 0x750D, 0xDDF9, 0x750E, 0xAE55, 0x750F, 0xEAB4, 0x7510, 0xAE56, 0x7511, 0xEAB5, 0x7512, 0xAE57, + 0x7513, 0xEAB6, 0x7514, 0xAE58, 0x7515, 0xAE59, 0x7516, 0xAE5A, 0x7517, 0xAE5B, 0x7518, 0xB8CA, 0x7519, 0xDFB0, 0x751A, 0xC9F5, + 0x751B, 0xAE5C, 0x751C, 0xCCF0, 0x751D, 0xAE5D, 0x751E, 0xAE5E, 0x751F, 0xC9FA, 0x7520, 0xAE5F, 0x7521, 0xAE60, 0x7522, 0xAE61, + 0x7523, 0xAE62, 0x7524, 0xAE63, 0x7525, 0xC9FB, 0x7526, 0xAE64, 0x7527, 0xAE65, 0x7528, 0xD3C3, 0x7529, 0xCBA6, 0x752A, 0xAE66, + 0x752B, 0xB8A6, 0x752C, 0xF0AE, 0x752D, 0xB1C2, 0x752E, 0xAE67, 0x752F, 0xE5B8, 0x7530, 0xCCEF, 0x7531, 0xD3C9, 0x7532, 0xBCD7, + 0x7533, 0xC9EA, 0x7534, 0xAE68, 0x7535, 0xB5E7, 0x7536, 0xAE69, 0x7537, 0xC4D0, 0x7538, 0xB5E9, 0x7539, 0xAE6A, 0x753A, 0xEEAE, + 0x753B, 0xBBAD, 0x753C, 0xAE6B, 0x753D, 0xAE6C, 0x753E, 0xE7DE, 0x753F, 0xAE6D, 0x7540, 0xEEAF, 0x7541, 0xAE6E, 0x7542, 0xAE6F, + 0x7543, 0xAE70, 0x7544, 0xAE71, 0x7545, 0xB3A9, 0x7546, 0xAE72, 0x7547, 0xAE73, 0x7548, 0xEEB2, 0x7549, 0xAE74, 0x754A, 0xAE75, + 0x754B, 0xEEB1, 0x754C, 0xBDE7, 0x754D, 0xAE76, 0x754E, 0xEEB0, 0x754F, 0xCEB7, 0x7550, 0xAE77, 0x7551, 0xAE78, 0x7552, 0xAE79, + 0x7553, 0xAE7A, 0x7554, 0xC5CF, 0x7555, 0xAE7B, 0x7556, 0xAE7C, 0x7557, 0xAE7D, 0x7558, 0xAE7E, 0x7559, 0xC1F4, 0x755A, 0xDBCE, + 0x755B, 0xEEB3, 0x755C, 0xD0F3, 0x755D, 0xAE80, 0x755E, 0xAE81, 0x755F, 0xAE82, 0x7560, 0xAE83, 0x7561, 0xAE84, 0x7562, 0xAE85, + 0x7563, 0xAE86, 0x7564, 0xAE87, 0x7565, 0xC2D4, 0x7566, 0xC6E8, 0x7567, 0xAE88, 0x7568, 0xAE89, 0x7569, 0xAE8A, 0x756A, 0xB7AC, + 0x756B, 0xAE8B, 0x756C, 0xAE8C, 0x756D, 0xAE8D, 0x756E, 0xAE8E, 0x756F, 0xAE8F, 0x7570, 0xAE90, 0x7571, 0xAE91, 0x7572, 0xEEB4, + 0x7573, 0xAE92, 0x7574, 0xB3EB, 0x7575, 0xAE93, 0x7576, 0xAE94, 0x7577, 0xAE95, 0x7578, 0xBBFB, 0x7579, 0xEEB5, 0x757A, 0xAE96, + 0x757B, 0xAE97, 0x757C, 0xAE98, 0x757D, 0xAE99, 0x757E, 0xAE9A, 0x757F, 0xE7DC, 0x7580, 0xAE9B, 0x7581, 0xAE9C, 0x7582, 0xAE9D, + 0x7583, 0xEEB6, 0x7584, 0xAE9E, 0x7585, 0xAE9F, 0x7586, 0xBDAE, 0x7587, 0xAEA0, 0x7588, 0xAF40, 0x7589, 0xAF41, 0x758A, 0xAF42, + 0x758B, 0xF1E2, 0x758C, 0xAF43, 0x758D, 0xAF44, 0x758E, 0xAF45, 0x758F, 0xCAE8, 0x7590, 0xAF46, 0x7591, 0xD2C9, 0x7592, 0xF0DA, + 0x7593, 0xAF47, 0x7594, 0xF0DB, 0x7595, 0xAF48, 0x7596, 0xF0DC, 0x7597, 0xC1C6, 0x7598, 0xAF49, 0x7599, 0xB8ED, 0x759A, 0xBECE, + 0x759B, 0xAF4A, 0x759C, 0xAF4B, 0x759D, 0xF0DE, 0x759E, 0xAF4C, 0x759F, 0xC5B1, 0x75A0, 0xF0DD, 0x75A1, 0xD1F1, 0x75A2, 0xAF4D, + 0x75A3, 0xF0E0, 0x75A4, 0xB0CC, 0x75A5, 0xBDEA, 0x75A6, 0xAF4E, 0x75A7, 0xAF4F, 0x75A8, 0xAF50, 0x75A9, 0xAF51, 0x75AA, 0xAF52, + 0x75AB, 0xD2DF, 0x75AC, 0xF0DF, 0x75AD, 0xAF53, 0x75AE, 0xB4AF, 0x75AF, 0xB7E8, 0x75B0, 0xF0E6, 0x75B1, 0xF0E5, 0x75B2, 0xC6A3, + 0x75B3, 0xF0E1, 0x75B4, 0xF0E2, 0x75B5, 0xB4C3, 0x75B6, 0xAF54, 0x75B7, 0xAF55, 0x75B8, 0xF0E3, 0x75B9, 0xD5EE, 0x75BA, 0xAF56, + 0x75BB, 0xAF57, 0x75BC, 0xCCDB, 0x75BD, 0xBED2, 0x75BE, 0xBCB2, 0x75BF, 0xAF58, 0x75C0, 0xAF59, 0x75C1, 0xAF5A, 0x75C2, 0xF0E8, + 0x75C3, 0xF0E7, 0x75C4, 0xF0E4, 0x75C5, 0xB2A1, 0x75C6, 0xAF5B, 0x75C7, 0xD6A2, 0x75C8, 0xD3B8, 0x75C9, 0xBEB7, 0x75CA, 0xC8AC, + 0x75CB, 0xAF5C, 0x75CC, 0xAF5D, 0x75CD, 0xF0EA, 0x75CE, 0xAF5E, 0x75CF, 0xAF5F, 0x75D0, 0xAF60, 0x75D1, 0xAF61, 0x75D2, 0xD1F7, + 0x75D3, 0xAF62, 0x75D4, 0xD6CC, 0x75D5, 0xBADB, 0x75D6, 0xF0E9, 0x75D7, 0xAF63, 0x75D8, 0xB6BB, 0x75D9, 0xAF64, 0x75DA, 0xAF65, + 0x75DB, 0xCDB4, 0x75DC, 0xAF66, 0x75DD, 0xAF67, 0x75DE, 0xC6A6, 0x75DF, 0xAF68, 0x75E0, 0xAF69, 0x75E1, 0xAF6A, 0x75E2, 0xC1A1, + 0x75E3, 0xF0EB, 0x75E4, 0xF0EE, 0x75E5, 0xAF6B, 0x75E6, 0xF0ED, 0x75E7, 0xF0F0, 0x75E8, 0xF0EC, 0x75E9, 0xAF6C, 0x75EA, 0xBBBE, + 0x75EB, 0xF0EF, 0x75EC, 0xAF6D, 0x75ED, 0xAF6E, 0x75EE, 0xAF6F, 0x75EF, 0xAF70, 0x75F0, 0xCCB5, 0x75F1, 0xF0F2, 0x75F2, 0xAF71, + 0x75F3, 0xAF72, 0x75F4, 0xB3D5, 0x75F5, 0xAF73, 0x75F6, 0xAF74, 0x75F7, 0xAF75, 0x75F8, 0xAF76, 0x75F9, 0xB1D4, 0x75FA, 0xAF77, + 0x75FB, 0xAF78, 0x75FC, 0xF0F3, 0x75FD, 0xAF79, 0x75FE, 0xAF7A, 0x75FF, 0xF0F4, 0x7600, 0xF0F6, 0x7601, 0xB4E1, 0x7602, 0xAF7B, + 0x7603, 0xF0F1, 0x7604, 0xAF7C, 0x7605, 0xF0F7, 0x7606, 0xAF7D, 0x7607, 0xAF7E, 0x7608, 0xAF80, 0x7609, 0xAF81, 0x760A, 0xF0FA, + 0x760B, 0xAF82, 0x760C, 0xF0F8, 0x760D, 0xAF83, 0x760E, 0xAF84, 0x760F, 0xAF85, 0x7610, 0xF0F5, 0x7611, 0xAF86, 0x7612, 0xAF87, + 0x7613, 0xAF88, 0x7614, 0xAF89, 0x7615, 0xF0FD, 0x7616, 0xAF8A, 0x7617, 0xF0F9, 0x7618, 0xF0FC, 0x7619, 0xF0FE, 0x761A, 0xAF8B, + 0x761B, 0xF1A1, 0x761C, 0xAF8C, 0x761D, 0xAF8D, 0x761E, 0xAF8E, 0x761F, 0xCEC1, 0x7620, 0xF1A4, 0x7621, 0xAF8F, 0x7622, 0xF1A3, + 0x7623, 0xAF90, 0x7624, 0xC1F6, 0x7625, 0xF0FB, 0x7626, 0xCADD, 0x7627, 0xAF91, 0x7628, 0xAF92, 0x7629, 0xB4F1, 0x762A, 0xB1F1, + 0x762B, 0xCCB1, 0x762C, 0xAF93, 0x762D, 0xF1A6, 0x762E, 0xAF94, 0x762F, 0xAF95, 0x7630, 0xF1A7, 0x7631, 0xAF96, 0x7632, 0xAF97, + 0x7633, 0xF1AC, 0x7634, 0xD5CE, 0x7635, 0xF1A9, 0x7636, 0xAF98, 0x7637, 0xAF99, 0x7638, 0xC8B3, 0x7639, 0xAF9A, 0x763A, 0xAF9B, + 0x763B, 0xAF9C, 0x763C, 0xF1A2, 0x763D, 0xAF9D, 0x763E, 0xF1AB, 0x763F, 0xF1A8, 0x7640, 0xF1A5, 0x7641, 0xAF9E, 0x7642, 0xAF9F, + 0x7643, 0xF1AA, 0x7644, 0xAFA0, 0x7645, 0xB040, 0x7646, 0xB041, 0x7647, 0xB042, 0x7648, 0xB043, 0x7649, 0xB044, 0x764A, 0xB045, + 0x764B, 0xB046, 0x764C, 0xB0A9, 0x764D, 0xF1AD, 0x764E, 0xB047, 0x764F, 0xB048, 0x7650, 0xB049, 0x7651, 0xB04A, 0x7652, 0xB04B, + 0x7653, 0xB04C, 0x7654, 0xF1AF, 0x7655, 0xB04D, 0x7656, 0xF1B1, 0x7657, 0xB04E, 0x7658, 0xB04F, 0x7659, 0xB050, 0x765A, 0xB051, + 0x765B, 0xB052, 0x765C, 0xF1B0, 0x765D, 0xB053, 0x765E, 0xF1AE, 0x765F, 0xB054, 0x7660, 0xB055, 0x7661, 0xB056, 0x7662, 0xB057, + 0x7663, 0xD1A2, 0x7664, 0xB058, 0x7665, 0xB059, 0x7666, 0xB05A, 0x7667, 0xB05B, 0x7668, 0xB05C, 0x7669, 0xB05D, 0x766A, 0xB05E, + 0x766B, 0xF1B2, 0x766C, 0xB05F, 0x766D, 0xB060, 0x766E, 0xB061, 0x766F, 0xF1B3, 0x7670, 0xB062, 0x7671, 0xB063, 0x7672, 0xB064, + 0x7673, 0xB065, 0x7674, 0xB066, 0x7675, 0xB067, 0x7676, 0xB068, 0x7677, 0xB069, 0x7678, 0xB9EF, 0x7679, 0xB06A, 0x767A, 0xB06B, + 0x767B, 0xB5C7, 0x767C, 0xB06C, 0x767D, 0xB0D7, 0x767E, 0xB0D9, 0x767F, 0xB06D, 0x7680, 0xB06E, 0x7681, 0xB06F, 0x7682, 0xD4ED, + 0x7683, 0xB070, 0x7684, 0xB5C4, 0x7685, 0xB071, 0x7686, 0xBDD4, 0x7687, 0xBBCA, 0x7688, 0xF0A7, 0x7689, 0xB072, 0x768A, 0xB073, + 0x768B, 0xB8DE, 0x768C, 0xB074, 0x768D, 0xB075, 0x768E, 0xF0A8, 0x768F, 0xB076, 0x7690, 0xB077, 0x7691, 0xB0A8, 0x7692, 0xB078, + 0x7693, 0xF0A9, 0x7694, 0xB079, 0x7695, 0xB07A, 0x7696, 0xCDEE, 0x7697, 0xB07B, 0x7698, 0xB07C, 0x7699, 0xF0AA, 0x769A, 0xB07D, + 0x769B, 0xB07E, 0x769C, 0xB080, 0x769D, 0xB081, 0x769E, 0xB082, 0x769F, 0xB083, 0x76A0, 0xB084, 0x76A1, 0xB085, 0x76A2, 0xB086, + 0x76A3, 0xB087, 0x76A4, 0xF0AB, 0x76A5, 0xB088, 0x76A6, 0xB089, 0x76A7, 0xB08A, 0x76A8, 0xB08B, 0x76A9, 0xB08C, 0x76AA, 0xB08D, + 0x76AB, 0xB08E, 0x76AC, 0xB08F, 0x76AD, 0xB090, 0x76AE, 0xC6A4, 0x76AF, 0xB091, 0x76B0, 0xB092, 0x76B1, 0xD6E5, 0x76B2, 0xF1E4, + 0x76B3, 0xB093, 0x76B4, 0xF1E5, 0x76B5, 0xB094, 0x76B6, 0xB095, 0x76B7, 0xB096, 0x76B8, 0xB097, 0x76B9, 0xB098, 0x76BA, 0xB099, + 0x76BB, 0xB09A, 0x76BC, 0xB09B, 0x76BD, 0xB09C, 0x76BE, 0xB09D, 0x76BF, 0xC3F3, 0x76C0, 0xB09E, 0x76C1, 0xB09F, 0x76C2, 0xD3DB, + 0x76C3, 0xB0A0, 0x76C4, 0xB140, 0x76C5, 0xD6D1, 0x76C6, 0xC5E8, 0x76C7, 0xB141, 0x76C8, 0xD3AF, 0x76C9, 0xB142, 0x76CA, 0xD2E6, + 0x76CB, 0xB143, 0x76CC, 0xB144, 0x76CD, 0xEEC1, 0x76CE, 0xB0BB, 0x76CF, 0xD5B5, 0x76D0, 0xD1CE, 0x76D1, 0xBCE0, 0x76D2, 0xBAD0, + 0x76D3, 0xB145, 0x76D4, 0xBFF8, 0x76D5, 0xB146, 0x76D6, 0xB8C7, 0x76D7, 0xB5C1, 0x76D8, 0xC5CC, 0x76D9, 0xB147, 0x76DA, 0xB148, + 0x76DB, 0xCAA2, 0x76DC, 0xB149, 0x76DD, 0xB14A, 0x76DE, 0xB14B, 0x76DF, 0xC3CB, 0x76E0, 0xB14C, 0x76E1, 0xB14D, 0x76E2, 0xB14E, + 0x76E3, 0xB14F, 0x76E4, 0xB150, 0x76E5, 0xEEC2, 0x76E6, 0xB151, 0x76E7, 0xB152, 0x76E8, 0xB153, 0x76E9, 0xB154, 0x76EA, 0xB155, + 0x76EB, 0xB156, 0x76EC, 0xB157, 0x76ED, 0xB158, 0x76EE, 0xC4BF, 0x76EF, 0xB6A2, 0x76F0, 0xB159, 0x76F1, 0xEDEC, 0x76F2, 0xC3A4, + 0x76F3, 0xB15A, 0x76F4, 0xD6B1, 0x76F5, 0xB15B, 0x76F6, 0xB15C, 0x76F7, 0xB15D, 0x76F8, 0xCFE0, 0x76F9, 0xEDEF, 0x76FA, 0xB15E, + 0x76FB, 0xB15F, 0x76FC, 0xC5CE, 0x76FD, 0xB160, 0x76FE, 0xB6DC, 0x76FF, 0xB161, 0x7700, 0xB162, 0x7701, 0xCAA1, 0x7702, 0xB163, + 0x7703, 0xB164, 0x7704, 0xEDED, 0x7705, 0xB165, 0x7706, 0xB166, 0x7707, 0xEDF0, 0x7708, 0xEDF1, 0x7709, 0xC3BC, 0x770A, 0xB167, + 0x770B, 0xBFB4, 0x770C, 0xB168, 0x770D, 0xEDEE, 0x770E, 0xB169, 0x770F, 0xB16A, 0x7710, 0xB16B, 0x7711, 0xB16C, 0x7712, 0xB16D, + 0x7713, 0xB16E, 0x7714, 0xB16F, 0x7715, 0xB170, 0x7716, 0xB171, 0x7717, 0xB172, 0x7718, 0xB173, 0x7719, 0xEDF4, 0x771A, 0xEDF2, + 0x771B, 0xB174, 0x771C, 0xB175, 0x771D, 0xB176, 0x771E, 0xB177, 0x771F, 0xD5E6, 0x7720, 0xC3DF, 0x7721, 0xB178, 0x7722, 0xEDF3, + 0x7723, 0xB179, 0x7724, 0xB17A, 0x7725, 0xB17B, 0x7726, 0xEDF6, 0x7727, 0xB17C, 0x7728, 0xD5A3, 0x7729, 0xD1A3, 0x772A, 0xB17D, + 0x772B, 0xB17E, 0x772C, 0xB180, 0x772D, 0xEDF5, 0x772E, 0xB181, 0x772F, 0xC3D0, 0x7730, 0xB182, 0x7731, 0xB183, 0x7732, 0xB184, + 0x7733, 0xB185, 0x7734, 0xB186, 0x7735, 0xEDF7, 0x7736, 0xBFF4, 0x7737, 0xBEEC, 0x7738, 0xEDF8, 0x7739, 0xB187, 0x773A, 0xCCF7, + 0x773B, 0xB188, 0x773C, 0xD1DB, 0x773D, 0xB189, 0x773E, 0xB18A, 0x773F, 0xB18B, 0x7740, 0xD7C5, 0x7741, 0xD5F6, 0x7742, 0xB18C, + 0x7743, 0xEDFC, 0x7744, 0xB18D, 0x7745, 0xB18E, 0x7746, 0xB18F, 0x7747, 0xEDFB, 0x7748, 0xB190, 0x7749, 0xB191, 0x774A, 0xB192, + 0x774B, 0xB193, 0x774C, 0xB194, 0x774D, 0xB195, 0x774E, 0xB196, 0x774F, 0xB197, 0x7750, 0xEDF9, 0x7751, 0xEDFA, 0x7752, 0xB198, + 0x7753, 0xB199, 0x7754, 0xB19A, 0x7755, 0xB19B, 0x7756, 0xB19C, 0x7757, 0xB19D, 0x7758, 0xB19E, 0x7759, 0xB19F, 0x775A, 0xEDFD, + 0x775B, 0xBEA6, 0x775C, 0xB1A0, 0x775D, 0xB240, 0x775E, 0xB241, 0x775F, 0xB242, 0x7760, 0xB243, 0x7761, 0xCBAF, 0x7762, 0xEEA1, + 0x7763, 0xB6BD, 0x7764, 0xB244, 0x7765, 0xEEA2, 0x7766, 0xC4C0, 0x7767, 0xB245, 0x7768, 0xEDFE, 0x7769, 0xB246, 0x776A, 0xB247, + 0x776B, 0xBDDE, 0x776C, 0xB2C7, 0x776D, 0xB248, 0x776E, 0xB249, 0x776F, 0xB24A, 0x7770, 0xB24B, 0x7771, 0xB24C, 0x7772, 0xB24D, + 0x7773, 0xB24E, 0x7774, 0xB24F, 0x7775, 0xB250, 0x7776, 0xB251, 0x7777, 0xB252, 0x7778, 0xB253, 0x7779, 0xB6C3, 0x777A, 0xB254, + 0x777B, 0xB255, 0x777C, 0xB256, 0x777D, 0xEEA5, 0x777E, 0xD8BA, 0x777F, 0xEEA3, 0x7780, 0xEEA6, 0x7781, 0xB257, 0x7782, 0xB258, + 0x7783, 0xB259, 0x7784, 0xC3E9, 0x7785, 0xB3F2, 0x7786, 0xB25A, 0x7787, 0xB25B, 0x7788, 0xB25C, 0x7789, 0xB25D, 0x778A, 0xB25E, + 0x778B, 0xB25F, 0x778C, 0xEEA7, 0x778D, 0xEEA4, 0x778E, 0xCFB9, 0x778F, 0xB260, 0x7790, 0xB261, 0x7791, 0xEEA8, 0x7792, 0xC2F7, + 0x7793, 0xB262, 0x7794, 0xB263, 0x7795, 0xB264, 0x7796, 0xB265, 0x7797, 0xB266, 0x7798, 0xB267, 0x7799, 0xB268, 0x779A, 0xB269, + 0x779B, 0xB26A, 0x779C, 0xB26B, 0x779D, 0xB26C, 0x779E, 0xB26D, 0x779F, 0xEEA9, 0x77A0, 0xEEAA, 0x77A1, 0xB26E, 0x77A2, 0xDEAB, + 0x77A3, 0xB26F, 0x77A4, 0xB270, 0x77A5, 0xC6B3, 0x77A6, 0xB271, 0x77A7, 0xC7C6, 0x77A8, 0xB272, 0x77A9, 0xD6F5, 0x77AA, 0xB5C9, + 0x77AB, 0xB273, 0x77AC, 0xCBB2, 0x77AD, 0xB274, 0x77AE, 0xB275, 0x77AF, 0xB276, 0x77B0, 0xEEAB, 0x77B1, 0xB277, 0x77B2, 0xB278, + 0x77B3, 0xCDAB, 0x77B4, 0xB279, 0x77B5, 0xEEAC, 0x77B6, 0xB27A, 0x77B7, 0xB27B, 0x77B8, 0xB27C, 0x77B9, 0xB27D, 0x77BA, 0xB27E, + 0x77BB, 0xD5B0, 0x77BC, 0xB280, 0x77BD, 0xEEAD, 0x77BE, 0xB281, 0x77BF, 0xF6C4, 0x77C0, 0xB282, 0x77C1, 0xB283, 0x77C2, 0xB284, + 0x77C3, 0xB285, 0x77C4, 0xB286, 0x77C5, 0xB287, 0x77C6, 0xB288, 0x77C7, 0xB289, 0x77C8, 0xB28A, 0x77C9, 0xB28B, 0x77CA, 0xB28C, + 0x77CB, 0xB28D, 0x77CC, 0xB28E, 0x77CD, 0xDBC7, 0x77CE, 0xB28F, 0x77CF, 0xB290, 0x77D0, 0xB291, 0x77D1, 0xB292, 0x77D2, 0xB293, + 0x77D3, 0xB294, 0x77D4, 0xB295, 0x77D5, 0xB296, 0x77D6, 0xB297, 0x77D7, 0xB4A3, 0x77D8, 0xB298, 0x77D9, 0xB299, 0x77DA, 0xB29A, + 0x77DB, 0xC3AC, 0x77DC, 0xF1E6, 0x77DD, 0xB29B, 0x77DE, 0xB29C, 0x77DF, 0xB29D, 0x77E0, 0xB29E, 0x77E1, 0xB29F, 0x77E2, 0xCAB8, + 0x77E3, 0xD2D3, 0x77E4, 0xB2A0, 0x77E5, 0xD6AA, 0x77E6, 0xB340, 0x77E7, 0xEFF2, 0x77E8, 0xB341, 0x77E9, 0xBED8, 0x77EA, 0xB342, + 0x77EB, 0xBDC3, 0x77EC, 0xEFF3, 0x77ED, 0xB6CC, 0x77EE, 0xB0AB, 0x77EF, 0xB343, 0x77F0, 0xB344, 0x77F1, 0xB345, 0x77F2, 0xB346, + 0x77F3, 0xCAAF, 0x77F4, 0xB347, 0x77F5, 0xB348, 0x77F6, 0xEDB6, 0x77F7, 0xB349, 0x77F8, 0xEDB7, 0x77F9, 0xB34A, 0x77FA, 0xB34B, + 0x77FB, 0xB34C, 0x77FC, 0xB34D, 0x77FD, 0xCEF9, 0x77FE, 0xB7AF, 0x77FF, 0xBFF3, 0x7800, 0xEDB8, 0x7801, 0xC2EB, 0x7802, 0xC9B0, + 0x7803, 0xB34E, 0x7804, 0xB34F, 0x7805, 0xB350, 0x7806, 0xB351, 0x7807, 0xB352, 0x7808, 0xB353, 0x7809, 0xEDB9, 0x780A, 0xB354, + 0x780B, 0xB355, 0x780C, 0xC6F6, 0x780D, 0xBFB3, 0x780E, 0xB356, 0x780F, 0xB357, 0x7810, 0xB358, 0x7811, 0xEDBC, 0x7812, 0xC5F8, + 0x7813, 0xB359, 0x7814, 0xD1D0, 0x7815, 0xB35A, 0x7816, 0xD7A9, 0x7817, 0xEDBA, 0x7818, 0xEDBB, 0x7819, 0xB35B, 0x781A, 0xD1E2, + 0x781B, 0xB35C, 0x781C, 0xEDBF, 0x781D, 0xEDC0, 0x781E, 0xB35D, 0x781F, 0xEDC4, 0x7820, 0xB35E, 0x7821, 0xB35F, 0x7822, 0xB360, + 0x7823, 0xEDC8, 0x7824, 0xB361, 0x7825, 0xEDC6, 0x7826, 0xEDCE, 0x7827, 0xD5E8, 0x7828, 0xB362, 0x7829, 0xEDC9, 0x782A, 0xB363, + 0x782B, 0xB364, 0x782C, 0xEDC7, 0x782D, 0xEDBE, 0x782E, 0xB365, 0x782F, 0xB366, 0x7830, 0xC5E9, 0x7831, 0xB367, 0x7832, 0xB368, + 0x7833, 0xB369, 0x7834, 0xC6C6, 0x7835, 0xB36A, 0x7836, 0xB36B, 0x7837, 0xC9E9, 0x7838, 0xD4D2, 0x7839, 0xEDC1, 0x783A, 0xEDC2, + 0x783B, 0xEDC3, 0x783C, 0xEDC5, 0x783D, 0xB36C, 0x783E, 0xC0F9, 0x783F, 0xB36D, 0x7840, 0xB4A1, 0x7841, 0xB36E, 0x7842, 0xB36F, + 0x7843, 0xB370, 0x7844, 0xB371, 0x7845, 0xB9E8, 0x7846, 0xB372, 0x7847, 0xEDD0, 0x7848, 0xB373, 0x7849, 0xB374, 0x784A, 0xB375, + 0x784B, 0xB376, 0x784C, 0xEDD1, 0x784D, 0xB377, 0x784E, 0xEDCA, 0x784F, 0xB378, 0x7850, 0xEDCF, 0x7851, 0xB379, 0x7852, 0xCEF8, + 0x7853, 0xB37A, 0x7854, 0xB37B, 0x7855, 0xCBB6, 0x7856, 0xEDCC, 0x7857, 0xEDCD, 0x7858, 0xB37C, 0x7859, 0xB37D, 0x785A, 0xB37E, + 0x785B, 0xB380, 0x785C, 0xB381, 0x785D, 0xCFF5, 0x785E, 0xB382, 0x785F, 0xB383, 0x7860, 0xB384, 0x7861, 0xB385, 0x7862, 0xB386, + 0x7863, 0xB387, 0x7864, 0xB388, 0x7865, 0xB389, 0x7866, 0xB38A, 0x7867, 0xB38B, 0x7868, 0xB38C, 0x7869, 0xB38D, 0x786A, 0xEDD2, + 0x786B, 0xC1F2, 0x786C, 0xD3B2, 0x786D, 0xEDCB, 0x786E, 0xC8B7, 0x786F, 0xB38E, 0x7870, 0xB38F, 0x7871, 0xB390, 0x7872, 0xB391, + 0x7873, 0xB392, 0x7874, 0xB393, 0x7875, 0xB394, 0x7876, 0xB395, 0x7877, 0xBCEF, 0x7878, 0xB396, 0x7879, 0xB397, 0x787A, 0xB398, + 0x787B, 0xB399, 0x787C, 0xC5F0, 0x787D, 0xB39A, 0x787E, 0xB39B, 0x787F, 0xB39C, 0x7880, 0xB39D, 0x7881, 0xB39E, 0x7882, 0xB39F, + 0x7883, 0xB3A0, 0x7884, 0xB440, 0x7885, 0xB441, 0x7886, 0xB442, 0x7887, 0xEDD6, 0x7888, 0xB443, 0x7889, 0xB5EF, 0x788A, 0xB444, + 0x788B, 0xB445, 0x788C, 0xC2B5, 0x788D, 0xB0AD, 0x788E, 0xCBE9, 0x788F, 0xB446, 0x7890, 0xB447, 0x7891, 0xB1AE, 0x7892, 0xB448, + 0x7893, 0xEDD4, 0x7894, 0xB449, 0x7895, 0xB44A, 0x7896, 0xB44B, 0x7897, 0xCDEB, 0x7898, 0xB5E2, 0x7899, 0xB44C, 0x789A, 0xEDD5, + 0x789B, 0xEDD3, 0x789C, 0xEDD7, 0x789D, 0xB44D, 0x789E, 0xB44E, 0x789F, 0xB5FA, 0x78A0, 0xB44F, 0x78A1, 0xEDD8, 0x78A2, 0xB450, + 0x78A3, 0xEDD9, 0x78A4, 0xB451, 0x78A5, 0xEDDC, 0x78A6, 0xB452, 0x78A7, 0xB1CC, 0x78A8, 0xB453, 0x78A9, 0xB454, 0x78AA, 0xB455, + 0x78AB, 0xB456, 0x78AC, 0xB457, 0x78AD, 0xB458, 0x78AE, 0xB459, 0x78AF, 0xB45A, 0x78B0, 0xC5F6, 0x78B1, 0xBCEE, 0x78B2, 0xEDDA, + 0x78B3, 0xCCBC, 0x78B4, 0xB2EA, 0x78B5, 0xB45B, 0x78B6, 0xB45C, 0x78B7, 0xB45D, 0x78B8, 0xB45E, 0x78B9, 0xEDDB, 0x78BA, 0xB45F, + 0x78BB, 0xB460, 0x78BC, 0xB461, 0x78BD, 0xB462, 0x78BE, 0xC4EB, 0x78BF, 0xB463, 0x78C0, 0xB464, 0x78C1, 0xB4C5, 0x78C2, 0xB465, + 0x78C3, 0xB466, 0x78C4, 0xB467, 0x78C5, 0xB0F5, 0x78C6, 0xB468, 0x78C7, 0xB469, 0x78C8, 0xB46A, 0x78C9, 0xEDDF, 0x78CA, 0xC0DA, + 0x78CB, 0xB4E8, 0x78CC, 0xB46B, 0x78CD, 0xB46C, 0x78CE, 0xB46D, 0x78CF, 0xB46E, 0x78D0, 0xC5CD, 0x78D1, 0xB46F, 0x78D2, 0xB470, + 0x78D3, 0xB471, 0x78D4, 0xEDDD, 0x78D5, 0xBFC4, 0x78D6, 0xB472, 0x78D7, 0xB473, 0x78D8, 0xB474, 0x78D9, 0xEDDE, 0x78DA, 0xB475, + 0x78DB, 0xB476, 0x78DC, 0xB477, 0x78DD, 0xB478, 0x78DE, 0xB479, 0x78DF, 0xB47A, 0x78E0, 0xB47B, 0x78E1, 0xB47C, 0x78E2, 0xB47D, + 0x78E3, 0xB47E, 0x78E4, 0xB480, 0x78E5, 0xB481, 0x78E6, 0xB482, 0x78E7, 0xB483, 0x78E8, 0xC4A5, 0x78E9, 0xB484, 0x78EA, 0xB485, + 0x78EB, 0xB486, 0x78EC, 0xEDE0, 0x78ED, 0xB487, 0x78EE, 0xB488, 0x78EF, 0xB489, 0x78F0, 0xB48A, 0x78F1, 0xB48B, 0x78F2, 0xEDE1, + 0x78F3, 0xB48C, 0x78F4, 0xEDE3, 0x78F5, 0xB48D, 0x78F6, 0xB48E, 0x78F7, 0xC1D7, 0x78F8, 0xB48F, 0x78F9, 0xB490, 0x78FA, 0xBBC7, + 0x78FB, 0xB491, 0x78FC, 0xB492, 0x78FD, 0xB493, 0x78FE, 0xB494, 0x78FF, 0xB495, 0x7900, 0xB496, 0x7901, 0xBDB8, 0x7902, 0xB497, + 0x7903, 0xB498, 0x7904, 0xB499, 0x7905, 0xEDE2, 0x7906, 0xB49A, 0x7907, 0xB49B, 0x7908, 0xB49C, 0x7909, 0xB49D, 0x790A, 0xB49E, + 0x790B, 0xB49F, 0x790C, 0xB4A0, 0x790D, 0xB540, 0x790E, 0xB541, 0x790F, 0xB542, 0x7910, 0xB543, 0x7911, 0xB544, 0x7912, 0xB545, + 0x7913, 0xEDE4, 0x7914, 0xB546, 0x7915, 0xB547, 0x7916, 0xB548, 0x7917, 0xB549, 0x7918, 0xB54A, 0x7919, 0xB54B, 0x791A, 0xB54C, + 0x791B, 0xB54D, 0x791C, 0xB54E, 0x791D, 0xB54F, 0x791E, 0xEDE6, 0x791F, 0xB550, 0x7920, 0xB551, 0x7921, 0xB552, 0x7922, 0xB553, + 0x7923, 0xB554, 0x7924, 0xEDE5, 0x7925, 0xB555, 0x7926, 0xB556, 0x7927, 0xB557, 0x7928, 0xB558, 0x7929, 0xB559, 0x792A, 0xB55A, + 0x792B, 0xB55B, 0x792C, 0xB55C, 0x792D, 0xB55D, 0x792E, 0xB55E, 0x792F, 0xB55F, 0x7930, 0xB560, 0x7931, 0xB561, 0x7932, 0xB562, + 0x7933, 0xB563, 0x7934, 0xEDE7, 0x7935, 0xB564, 0x7936, 0xB565, 0x7937, 0xB566, 0x7938, 0xB567, 0x7939, 0xB568, 0x793A, 0xCABE, + 0x793B, 0xECEA, 0x793C, 0xC0F1, 0x793D, 0xB569, 0x793E, 0xC9E7, 0x793F, 0xB56A, 0x7940, 0xECEB, 0x7941, 0xC6EE, 0x7942, 0xB56B, + 0x7943, 0xB56C, 0x7944, 0xB56D, 0x7945, 0xB56E, 0x7946, 0xECEC, 0x7947, 0xB56F, 0x7948, 0xC6ED, 0x7949, 0xECED, 0x794A, 0xB570, + 0x794B, 0xB571, 0x794C, 0xB572, 0x794D, 0xB573, 0x794E, 0xB574, 0x794F, 0xB575, 0x7950, 0xB576, 0x7951, 0xB577, 0x7952, 0xB578, + 0x7953, 0xECF0, 0x7954, 0xB579, 0x7955, 0xB57A, 0x7956, 0xD7E6, 0x7957, 0xECF3, 0x7958, 0xB57B, 0x7959, 0xB57C, 0x795A, 0xECF1, + 0x795B, 0xECEE, 0x795C, 0xECEF, 0x795D, 0xD7A3, 0x795E, 0xC9F1, 0x795F, 0xCBEE, 0x7960, 0xECF4, 0x7961, 0xB57D, 0x7962, 0xECF2, + 0x7963, 0xB57E, 0x7964, 0xB580, 0x7965, 0xCFE9, 0x7966, 0xB581, 0x7967, 0xECF6, 0x7968, 0xC6B1, 0x7969, 0xB582, 0x796A, 0xB583, + 0x796B, 0xB584, 0x796C, 0xB585, 0x796D, 0xBCC0, 0x796E, 0xB586, 0x796F, 0xECF5, 0x7970, 0xB587, 0x7971, 0xB588, 0x7972, 0xB589, + 0x7973, 0xB58A, 0x7974, 0xB58B, 0x7975, 0xB58C, 0x7976, 0xB58D, 0x7977, 0xB5BB, 0x7978, 0xBBF6, 0x7979, 0xB58E, 0x797A, 0xECF7, + 0x797B, 0xB58F, 0x797C, 0xB590, 0x797D, 0xB591, 0x797E, 0xB592, 0x797F, 0xB593, 0x7980, 0xD9F7, 0x7981, 0xBDFB, 0x7982, 0xB594, + 0x7983, 0xB595, 0x7984, 0xC2BB, 0x7985, 0xECF8, 0x7986, 0xB596, 0x7987, 0xB597, 0x7988, 0xB598, 0x7989, 0xB599, 0x798A, 0xECF9, + 0x798B, 0xB59A, 0x798C, 0xB59B, 0x798D, 0xB59C, 0x798E, 0xB59D, 0x798F, 0xB8A3, 0x7990, 0xB59E, 0x7991, 0xB59F, 0x7992, 0xB5A0, + 0x7993, 0xB640, 0x7994, 0xB641, 0x7995, 0xB642, 0x7996, 0xB643, 0x7997, 0xB644, 0x7998, 0xB645, 0x7999, 0xB646, 0x799A, 0xECFA, + 0x799B, 0xB647, 0x799C, 0xB648, 0x799D, 0xB649, 0x799E, 0xB64A, 0x799F, 0xB64B, 0x79A0, 0xB64C, 0x79A1, 0xB64D, 0x79A2, 0xB64E, + 0x79A3, 0xB64F, 0x79A4, 0xB650, 0x79A5, 0xB651, 0x79A6, 0xB652, 0x79A7, 0xECFB, 0x79A8, 0xB653, 0x79A9, 0xB654, 0x79AA, 0xB655, + 0x79AB, 0xB656, 0x79AC, 0xB657, 0x79AD, 0xB658, 0x79AE, 0xB659, 0x79AF, 0xB65A, 0x79B0, 0xB65B, 0x79B1, 0xB65C, 0x79B2, 0xB65D, + 0x79B3, 0xECFC, 0x79B4, 0xB65E, 0x79B5, 0xB65F, 0x79B6, 0xB660, 0x79B7, 0xB661, 0x79B8, 0xB662, 0x79B9, 0xD3ED, 0x79BA, 0xD8AE, + 0x79BB, 0xC0EB, 0x79BC, 0xB663, 0x79BD, 0xC7DD, 0x79BE, 0xBACC, 0x79BF, 0xB664, 0x79C0, 0xD0E3, 0x79C1, 0xCBBD, 0x79C2, 0xB665, + 0x79C3, 0xCDBA, 0x79C4, 0xB666, 0x79C5, 0xB667, 0x79C6, 0xB8D1, 0x79C7, 0xB668, 0x79C8, 0xB669, 0x79C9, 0xB1FC, 0x79CA, 0xB66A, + 0x79CB, 0xC7EF, 0x79CC, 0xB66B, 0x79CD, 0xD6D6, 0x79CE, 0xB66C, 0x79CF, 0xB66D, 0x79D0, 0xB66E, 0x79D1, 0xBFC6, 0x79D2, 0xC3EB, + 0x79D3, 0xB66F, 0x79D4, 0xB670, 0x79D5, 0xEFF5, 0x79D6, 0xB671, 0x79D7, 0xB672, 0x79D8, 0xC3D8, 0x79D9, 0xB673, 0x79DA, 0xB674, + 0x79DB, 0xB675, 0x79DC, 0xB676, 0x79DD, 0xB677, 0x79DE, 0xB678, 0x79DF, 0xD7E2, 0x79E0, 0xB679, 0x79E1, 0xB67A, 0x79E2, 0xB67B, + 0x79E3, 0xEFF7, 0x79E4, 0xB3D3, 0x79E5, 0xB67C, 0x79E6, 0xC7D8, 0x79E7, 0xD1ED, 0x79E8, 0xB67D, 0x79E9, 0xD6C8, 0x79EA, 0xB67E, + 0x79EB, 0xEFF8, 0x79EC, 0xB680, 0x79ED, 0xEFF6, 0x79EE, 0xB681, 0x79EF, 0xBBFD, 0x79F0, 0xB3C6, 0x79F1, 0xB682, 0x79F2, 0xB683, + 0x79F3, 0xB684, 0x79F4, 0xB685, 0x79F5, 0xB686, 0x79F6, 0xB687, 0x79F7, 0xB688, 0x79F8, 0xBDD5, 0x79F9, 0xB689, 0x79FA, 0xB68A, + 0x79FB, 0xD2C6, 0x79FC, 0xB68B, 0x79FD, 0xBBE0, 0x79FE, 0xB68C, 0x79FF, 0xB68D, 0x7A00, 0xCFA1, 0x7A01, 0xB68E, 0x7A02, 0xEFFC, + 0x7A03, 0xEFFB, 0x7A04, 0xB68F, 0x7A05, 0xB690, 0x7A06, 0xEFF9, 0x7A07, 0xB691, 0x7A08, 0xB692, 0x7A09, 0xB693, 0x7A0A, 0xB694, + 0x7A0B, 0xB3CC, 0x7A0C, 0xB695, 0x7A0D, 0xC9D4, 0x7A0E, 0xCBB0, 0x7A0F, 0xB696, 0x7A10, 0xB697, 0x7A11, 0xB698, 0x7A12, 0xB699, + 0x7A13, 0xB69A, 0x7A14, 0xEFFE, 0x7A15, 0xB69B, 0x7A16, 0xB69C, 0x7A17, 0xB0DE, 0x7A18, 0xB69D, 0x7A19, 0xB69E, 0x7A1A, 0xD6C9, + 0x7A1B, 0xB69F, 0x7A1C, 0xB6A0, 0x7A1D, 0xB740, 0x7A1E, 0xEFFD, 0x7A1F, 0xB741, 0x7A20, 0xB3ED, 0x7A21, 0xB742, 0x7A22, 0xB743, + 0x7A23, 0xF6D5, 0x7A24, 0xB744, 0x7A25, 0xB745, 0x7A26, 0xB746, 0x7A27, 0xB747, 0x7A28, 0xB748, 0x7A29, 0xB749, 0x7A2A, 0xB74A, + 0x7A2B, 0xB74B, 0x7A2C, 0xB74C, 0x7A2D, 0xB74D, 0x7A2E, 0xB74E, 0x7A2F, 0xB74F, 0x7A30, 0xB750, 0x7A31, 0xB751, 0x7A32, 0xB752, + 0x7A33, 0xCEC8, 0x7A34, 0xB753, 0x7A35, 0xB754, 0x7A36, 0xB755, 0x7A37, 0xF0A2, 0x7A38, 0xB756, 0x7A39, 0xF0A1, 0x7A3A, 0xB757, + 0x7A3B, 0xB5BE, 0x7A3C, 0xBCDA, 0x7A3D, 0xBBFC, 0x7A3E, 0xB758, 0x7A3F, 0xB8E5, 0x7A40, 0xB759, 0x7A41, 0xB75A, 0x7A42, 0xB75B, + 0x7A43, 0xB75C, 0x7A44, 0xB75D, 0x7A45, 0xB75E, 0x7A46, 0xC4C2, 0x7A47, 0xB75F, 0x7A48, 0xB760, 0x7A49, 0xB761, 0x7A4A, 0xB762, + 0x7A4B, 0xB763, 0x7A4C, 0xB764, 0x7A4D, 0xB765, 0x7A4E, 0xB766, 0x7A4F, 0xB767, 0x7A50, 0xB768, 0x7A51, 0xF0A3, 0x7A52, 0xB769, + 0x7A53, 0xB76A, 0x7A54, 0xB76B, 0x7A55, 0xB76C, 0x7A56, 0xB76D, 0x7A57, 0xCBEB, 0x7A58, 0xB76E, 0x7A59, 0xB76F, 0x7A5A, 0xB770, + 0x7A5B, 0xB771, 0x7A5C, 0xB772, 0x7A5D, 0xB773, 0x7A5E, 0xB774, 0x7A5F, 0xB775, 0x7A60, 0xB776, 0x7A61, 0xB777, 0x7A62, 0xB778, + 0x7A63, 0xB779, 0x7A64, 0xB77A, 0x7A65, 0xB77B, 0x7A66, 0xB77C, 0x7A67, 0xB77D, 0x7A68, 0xB77E, 0x7A69, 0xB780, 0x7A6A, 0xB781, + 0x7A6B, 0xB782, 0x7A6C, 0xB783, 0x7A6D, 0xB784, 0x7A6E, 0xB785, 0x7A6F, 0xB786, 0x7A70, 0xF0A6, 0x7A71, 0xB787, 0x7A72, 0xB788, + 0x7A73, 0xB789, 0x7A74, 0xD1A8, 0x7A75, 0xB78A, 0x7A76, 0xBEBF, 0x7A77, 0xC7EE, 0x7A78, 0xF1B6, 0x7A79, 0xF1B7, 0x7A7A, 0xBFD5, + 0x7A7B, 0xB78B, 0x7A7C, 0xB78C, 0x7A7D, 0xB78D, 0x7A7E, 0xB78E, 0x7A7F, 0xB4A9, 0x7A80, 0xF1B8, 0x7A81, 0xCDBB, 0x7A82, 0xB78F, + 0x7A83, 0xC7D4, 0x7A84, 0xD5AD, 0x7A85, 0xB790, 0x7A86, 0xF1B9, 0x7A87, 0xB791, 0x7A88, 0xF1BA, 0x7A89, 0xB792, 0x7A8A, 0xB793, + 0x7A8B, 0xB794, 0x7A8C, 0xB795, 0x7A8D, 0xC7CF, 0x7A8E, 0xB796, 0x7A8F, 0xB797, 0x7A90, 0xB798, 0x7A91, 0xD2A4, 0x7A92, 0xD6CF, + 0x7A93, 0xB799, 0x7A94, 0xB79A, 0x7A95, 0xF1BB, 0x7A96, 0xBDD1, 0x7A97, 0xB4B0, 0x7A98, 0xBEBD, 0x7A99, 0xB79B, 0x7A9A, 0xB79C, + 0x7A9B, 0xB79D, 0x7A9C, 0xB4DC, 0x7A9D, 0xCED1, 0x7A9E, 0xB79E, 0x7A9F, 0xBFDF, 0x7AA0, 0xF1BD, 0x7AA1, 0xB79F, 0x7AA2, 0xB7A0, + 0x7AA3, 0xB840, 0x7AA4, 0xB841, 0x7AA5, 0xBFFA, 0x7AA6, 0xF1BC, 0x7AA7, 0xB842, 0x7AA8, 0xF1BF, 0x7AA9, 0xB843, 0x7AAA, 0xB844, + 0x7AAB, 0xB845, 0x7AAC, 0xF1BE, 0x7AAD, 0xF1C0, 0x7AAE, 0xB846, 0x7AAF, 0xB847, 0x7AB0, 0xB848, 0x7AB1, 0xB849, 0x7AB2, 0xB84A, + 0x7AB3, 0xF1C1, 0x7AB4, 0xB84B, 0x7AB5, 0xB84C, 0x7AB6, 0xB84D, 0x7AB7, 0xB84E, 0x7AB8, 0xB84F, 0x7AB9, 0xB850, 0x7ABA, 0xB851, + 0x7ABB, 0xB852, 0x7ABC, 0xB853, 0x7ABD, 0xB854, 0x7ABE, 0xB855, 0x7ABF, 0xC1FE, 0x7AC0, 0xB856, 0x7AC1, 0xB857, 0x7AC2, 0xB858, + 0x7AC3, 0xB859, 0x7AC4, 0xB85A, 0x7AC5, 0xB85B, 0x7AC6, 0xB85C, 0x7AC7, 0xB85D, 0x7AC8, 0xB85E, 0x7AC9, 0xB85F, 0x7ACA, 0xB860, + 0x7ACB, 0xC1A2, 0x7ACC, 0xB861, 0x7ACD, 0xB862, 0x7ACE, 0xB863, 0x7ACF, 0xB864, 0x7AD0, 0xB865, 0x7AD1, 0xB866, 0x7AD2, 0xB867, + 0x7AD3, 0xB868, 0x7AD4, 0xB869, 0x7AD5, 0xB86A, 0x7AD6, 0xCAFA, 0x7AD7, 0xB86B, 0x7AD8, 0xB86C, 0x7AD9, 0xD5BE, 0x7ADA, 0xB86D, + 0x7ADB, 0xB86E, 0x7ADC, 0xB86F, 0x7ADD, 0xB870, 0x7ADE, 0xBEBA, 0x7ADF, 0xBEB9, 0x7AE0, 0xD5C2, 0x7AE1, 0xB871, 0x7AE2, 0xB872, + 0x7AE3, 0xBFA2, 0x7AE4, 0xB873, 0x7AE5, 0xCDAF, 0x7AE6, 0xF1B5, 0x7AE7, 0xB874, 0x7AE8, 0xB875, 0x7AE9, 0xB876, 0x7AEA, 0xB877, + 0x7AEB, 0xB878, 0x7AEC, 0xB879, 0x7AED, 0xBDDF, 0x7AEE, 0xB87A, 0x7AEF, 0xB6CB, 0x7AF0, 0xB87B, 0x7AF1, 0xB87C, 0x7AF2, 0xB87D, + 0x7AF3, 0xB87E, 0x7AF4, 0xB880, 0x7AF5, 0xB881, 0x7AF6, 0xB882, 0x7AF7, 0xB883, 0x7AF8, 0xB884, 0x7AF9, 0xD6F1, 0x7AFA, 0xF3C3, + 0x7AFB, 0xB885, 0x7AFC, 0xB886, 0x7AFD, 0xF3C4, 0x7AFE, 0xB887, 0x7AFF, 0xB8CD, 0x7B00, 0xB888, 0x7B01, 0xB889, 0x7B02, 0xB88A, + 0x7B03, 0xF3C6, 0x7B04, 0xF3C7, 0x7B05, 0xB88B, 0x7B06, 0xB0CA, 0x7B07, 0xB88C, 0x7B08, 0xF3C5, 0x7B09, 0xB88D, 0x7B0A, 0xF3C9, + 0x7B0B, 0xCBF1, 0x7B0C, 0xB88E, 0x7B0D, 0xB88F, 0x7B0E, 0xB890, 0x7B0F, 0xF3CB, 0x7B10, 0xB891, 0x7B11, 0xD0A6, 0x7B12, 0xB892, + 0x7B13, 0xB893, 0x7B14, 0xB1CA, 0x7B15, 0xF3C8, 0x7B16, 0xB894, 0x7B17, 0xB895, 0x7B18, 0xB896, 0x7B19, 0xF3CF, 0x7B1A, 0xB897, + 0x7B1B, 0xB5D1, 0x7B1C, 0xB898, 0x7B1D, 0xB899, 0x7B1E, 0xF3D7, 0x7B1F, 0xB89A, 0x7B20, 0xF3D2, 0x7B21, 0xB89B, 0x7B22, 0xB89C, + 0x7B23, 0xB89D, 0x7B24, 0xF3D4, 0x7B25, 0xF3D3, 0x7B26, 0xB7FB, 0x7B27, 0xB89E, 0x7B28, 0xB1BF, 0x7B29, 0xB89F, 0x7B2A, 0xF3CE, + 0x7B2B, 0xF3CA, 0x7B2C, 0xB5DA, 0x7B2D, 0xB8A0, 0x7B2E, 0xF3D0, 0x7B2F, 0xB940, 0x7B30, 0xB941, 0x7B31, 0xF3D1, 0x7B32, 0xB942, + 0x7B33, 0xF3D5, 0x7B34, 0xB943, 0x7B35, 0xB944, 0x7B36, 0xB945, 0x7B37, 0xB946, 0x7B38, 0xF3CD, 0x7B39, 0xB947, 0x7B3A, 0xBCE3, + 0x7B3B, 0xB948, 0x7B3C, 0xC1FD, 0x7B3D, 0xB949, 0x7B3E, 0xF3D6, 0x7B3F, 0xB94A, 0x7B40, 0xB94B, 0x7B41, 0xB94C, 0x7B42, 0xB94D, + 0x7B43, 0xB94E, 0x7B44, 0xB94F, 0x7B45, 0xF3DA, 0x7B46, 0xB950, 0x7B47, 0xF3CC, 0x7B48, 0xB951, 0x7B49, 0xB5C8, 0x7B4A, 0xB952, + 0x7B4B, 0xBDEE, 0x7B4C, 0xF3DC, 0x7B4D, 0xB953, 0x7B4E, 0xB954, 0x7B4F, 0xB7A4, 0x7B50, 0xBFF0, 0x7B51, 0xD6FE, 0x7B52, 0xCDB2, + 0x7B53, 0xB955, 0x7B54, 0xB4F0, 0x7B55, 0xB956, 0x7B56, 0xB2DF, 0x7B57, 0xB957, 0x7B58, 0xF3D8, 0x7B59, 0xB958, 0x7B5A, 0xF3D9, + 0x7B5B, 0xC9B8, 0x7B5C, 0xB959, 0x7B5D, 0xF3DD, 0x7B5E, 0xB95A, 0x7B5F, 0xB95B, 0x7B60, 0xF3DE, 0x7B61, 0xB95C, 0x7B62, 0xF3E1, + 0x7B63, 0xB95D, 0x7B64, 0xB95E, 0x7B65, 0xB95F, 0x7B66, 0xB960, 0x7B67, 0xB961, 0x7B68, 0xB962, 0x7B69, 0xB963, 0x7B6A, 0xB964, + 0x7B6B, 0xB965, 0x7B6C, 0xB966, 0x7B6D, 0xB967, 0x7B6E, 0xF3DF, 0x7B6F, 0xB968, 0x7B70, 0xB969, 0x7B71, 0xF3E3, 0x7B72, 0xF3E2, + 0x7B73, 0xB96A, 0x7B74, 0xB96B, 0x7B75, 0xF3DB, 0x7B76, 0xB96C, 0x7B77, 0xBFEA, 0x7B78, 0xB96D, 0x7B79, 0xB3EF, 0x7B7A, 0xB96E, + 0x7B7B, 0xF3E0, 0x7B7C, 0xB96F, 0x7B7D, 0xB970, 0x7B7E, 0xC7A9, 0x7B7F, 0xB971, 0x7B80, 0xBCF2, 0x7B81, 0xB972, 0x7B82, 0xB973, + 0x7B83, 0xB974, 0x7B84, 0xB975, 0x7B85, 0xF3EB, 0x7B86, 0xB976, 0x7B87, 0xB977, 0x7B88, 0xB978, 0x7B89, 0xB979, 0x7B8A, 0xB97A, + 0x7B8B, 0xB97B, 0x7B8C, 0xB97C, 0x7B8D, 0xB9BF, 0x7B8E, 0xB97D, 0x7B8F, 0xB97E, 0x7B90, 0xF3E4, 0x7B91, 0xB980, 0x7B92, 0xB981, + 0x7B93, 0xB982, 0x7B94, 0xB2AD, 0x7B95, 0xBBFE, 0x7B96, 0xB983, 0x7B97, 0xCBE3, 0x7B98, 0xB984, 0x7B99, 0xB985, 0x7B9A, 0xB986, + 0x7B9B, 0xB987, 0x7B9C, 0xF3ED, 0x7B9D, 0xF3E9, 0x7B9E, 0xB988, 0x7B9F, 0xB989, 0x7BA0, 0xB98A, 0x7BA1, 0xB9DC, 0x7BA2, 0xF3EE, + 0x7BA3, 0xB98B, 0x7BA4, 0xB98C, 0x7BA5, 0xB98D, 0x7BA6, 0xF3E5, 0x7BA7, 0xF3E6, 0x7BA8, 0xF3EA, 0x7BA9, 0xC2E1, 0x7BAA, 0xF3EC, + 0x7BAB, 0xF3EF, 0x7BAC, 0xF3E8, 0x7BAD, 0xBCFD, 0x7BAE, 0xB98E, 0x7BAF, 0xB98F, 0x7BB0, 0xB990, 0x7BB1, 0xCFE4, 0x7BB2, 0xB991, + 0x7BB3, 0xB992, 0x7BB4, 0xF3F0, 0x7BB5, 0xB993, 0x7BB6, 0xB994, 0x7BB7, 0xB995, 0x7BB8, 0xF3E7, 0x7BB9, 0xB996, 0x7BBA, 0xB997, + 0x7BBB, 0xB998, 0x7BBC, 0xB999, 0x7BBD, 0xB99A, 0x7BBE, 0xB99B, 0x7BBF, 0xB99C, 0x7BC0, 0xB99D, 0x7BC1, 0xF3F2, 0x7BC2, 0xB99E, + 0x7BC3, 0xB99F, 0x7BC4, 0xB9A0, 0x7BC5, 0xBA40, 0x7BC6, 0xD7AD, 0x7BC7, 0xC6AA, 0x7BC8, 0xBA41, 0x7BC9, 0xBA42, 0x7BCA, 0xBA43, + 0x7BCB, 0xBA44, 0x7BCC, 0xF3F3, 0x7BCD, 0xBA45, 0x7BCE, 0xBA46, 0x7BCF, 0xBA47, 0x7BD0, 0xBA48, 0x7BD1, 0xF3F1, 0x7BD2, 0xBA49, + 0x7BD3, 0xC2A8, 0x7BD4, 0xBA4A, 0x7BD5, 0xBA4B, 0x7BD6, 0xBA4C, 0x7BD7, 0xBA4D, 0x7BD8, 0xBA4E, 0x7BD9, 0xB8DD, 0x7BDA, 0xF3F5, + 0x7BDB, 0xBA4F, 0x7BDC, 0xBA50, 0x7BDD, 0xF3F4, 0x7BDE, 0xBA51, 0x7BDF, 0xBA52, 0x7BE0, 0xBA53, 0x7BE1, 0xB4DB, 0x7BE2, 0xBA54, + 0x7BE3, 0xBA55, 0x7BE4, 0xBA56, 0x7BE5, 0xF3F6, 0x7BE6, 0xF3F7, 0x7BE7, 0xBA57, 0x7BE8, 0xBA58, 0x7BE9, 0xBA59, 0x7BEA, 0xF3F8, + 0x7BEB, 0xBA5A, 0x7BEC, 0xBA5B, 0x7BED, 0xBA5C, 0x7BEE, 0xC0BA, 0x7BEF, 0xBA5D, 0x7BF0, 0xBA5E, 0x7BF1, 0xC0E9, 0x7BF2, 0xBA5F, + 0x7BF3, 0xBA60, 0x7BF4, 0xBA61, 0x7BF5, 0xBA62, 0x7BF6, 0xBA63, 0x7BF7, 0xC5F1, 0x7BF8, 0xBA64, 0x7BF9, 0xBA65, 0x7BFA, 0xBA66, + 0x7BFB, 0xBA67, 0x7BFC, 0xF3FB, 0x7BFD, 0xBA68, 0x7BFE, 0xF3FA, 0x7BFF, 0xBA69, 0x7C00, 0xBA6A, 0x7C01, 0xBA6B, 0x7C02, 0xBA6C, + 0x7C03, 0xBA6D, 0x7C04, 0xBA6E, 0x7C05, 0xBA6F, 0x7C06, 0xBA70, 0x7C07, 0xB4D8, 0x7C08, 0xBA71, 0x7C09, 0xBA72, 0x7C0A, 0xBA73, + 0x7C0B, 0xF3FE, 0x7C0C, 0xF3F9, 0x7C0D, 0xBA74, 0x7C0E, 0xBA75, 0x7C0F, 0xF3FC, 0x7C10, 0xBA76, 0x7C11, 0xBA77, 0x7C12, 0xBA78, + 0x7C13, 0xBA79, 0x7C14, 0xBA7A, 0x7C15, 0xBA7B, 0x7C16, 0xF3FD, 0x7C17, 0xBA7C, 0x7C18, 0xBA7D, 0x7C19, 0xBA7E, 0x7C1A, 0xBA80, + 0x7C1B, 0xBA81, 0x7C1C, 0xBA82, 0x7C1D, 0xBA83, 0x7C1E, 0xBA84, 0x7C1F, 0xF4A1, 0x7C20, 0xBA85, 0x7C21, 0xBA86, 0x7C22, 0xBA87, + 0x7C23, 0xBA88, 0x7C24, 0xBA89, 0x7C25, 0xBA8A, 0x7C26, 0xF4A3, 0x7C27, 0xBBC9, 0x7C28, 0xBA8B, 0x7C29, 0xBA8C, 0x7C2A, 0xF4A2, + 0x7C2B, 0xBA8D, 0x7C2C, 0xBA8E, 0x7C2D, 0xBA8F, 0x7C2E, 0xBA90, 0x7C2F, 0xBA91, 0x7C30, 0xBA92, 0x7C31, 0xBA93, 0x7C32, 0xBA94, + 0x7C33, 0xBA95, 0x7C34, 0xBA96, 0x7C35, 0xBA97, 0x7C36, 0xBA98, 0x7C37, 0xBA99, 0x7C38, 0xF4A4, 0x7C39, 0xBA9A, 0x7C3A, 0xBA9B, + 0x7C3B, 0xBA9C, 0x7C3C, 0xBA9D, 0x7C3D, 0xBA9E, 0x7C3E, 0xBA9F, 0x7C3F, 0xB2BE, 0x7C40, 0xF4A6, 0x7C41, 0xF4A5, 0x7C42, 0xBAA0, + 0x7C43, 0xBB40, 0x7C44, 0xBB41, 0x7C45, 0xBB42, 0x7C46, 0xBB43, 0x7C47, 0xBB44, 0x7C48, 0xBB45, 0x7C49, 0xBB46, 0x7C4A, 0xBB47, + 0x7C4B, 0xBB48, 0x7C4C, 0xBB49, 0x7C4D, 0xBCAE, 0x7C4E, 0xBB4A, 0x7C4F, 0xBB4B, 0x7C50, 0xBB4C, 0x7C51, 0xBB4D, 0x7C52, 0xBB4E, + 0x7C53, 0xBB4F, 0x7C54, 0xBB50, 0x7C55, 0xBB51, 0x7C56, 0xBB52, 0x7C57, 0xBB53, 0x7C58, 0xBB54, 0x7C59, 0xBB55, 0x7C5A, 0xBB56, + 0x7C5B, 0xBB57, 0x7C5C, 0xBB58, 0x7C5D, 0xBB59, 0x7C5E, 0xBB5A, 0x7C5F, 0xBB5B, 0x7C60, 0xBB5C, 0x7C61, 0xBB5D, 0x7C62, 0xBB5E, + 0x7C63, 0xBB5F, 0x7C64, 0xBB60, 0x7C65, 0xBB61, 0x7C66, 0xBB62, 0x7C67, 0xBB63, 0x7C68, 0xBB64, 0x7C69, 0xBB65, 0x7C6A, 0xBB66, + 0x7C6B, 0xBB67, 0x7C6C, 0xBB68, 0x7C6D, 0xBB69, 0x7C6E, 0xBB6A, 0x7C6F, 0xBB6B, 0x7C70, 0xBB6C, 0x7C71, 0xBB6D, 0x7C72, 0xBB6E, + 0x7C73, 0xC3D7, 0x7C74, 0xD9E1, 0x7C75, 0xBB6F, 0x7C76, 0xBB70, 0x7C77, 0xBB71, 0x7C78, 0xBB72, 0x7C79, 0xBB73, 0x7C7A, 0xBB74, + 0x7C7B, 0xC0E0, 0x7C7C, 0xF4CC, 0x7C7D, 0xD7D1, 0x7C7E, 0xBB75, 0x7C7F, 0xBB76, 0x7C80, 0xBB77, 0x7C81, 0xBB78, 0x7C82, 0xBB79, + 0x7C83, 0xBB7A, 0x7C84, 0xBB7B, 0x7C85, 0xBB7C, 0x7C86, 0xBB7D, 0x7C87, 0xBB7E, 0x7C88, 0xBB80, 0x7C89, 0xB7DB, 0x7C8A, 0xBB81, + 0x7C8B, 0xBB82, 0x7C8C, 0xBB83, 0x7C8D, 0xBB84, 0x7C8E, 0xBB85, 0x7C8F, 0xBB86, 0x7C90, 0xBB87, 0x7C91, 0xF4CE, 0x7C92, 0xC1A3, + 0x7C93, 0xBB88, 0x7C94, 0xBB89, 0x7C95, 0xC6C9, 0x7C96, 0xBB8A, 0x7C97, 0xB4D6, 0x7C98, 0xD5B3, 0x7C99, 0xBB8B, 0x7C9A, 0xBB8C, + 0x7C9B, 0xBB8D, 0x7C9C, 0xF4D0, 0x7C9D, 0xF4CF, 0x7C9E, 0xF4D1, 0x7C9F, 0xCBDA, 0x7CA0, 0xBB8E, 0x7CA1, 0xBB8F, 0x7CA2, 0xF4D2, + 0x7CA3, 0xBB90, 0x7CA4, 0xD4C1, 0x7CA5, 0xD6E0, 0x7CA6, 0xBB91, 0x7CA7, 0xBB92, 0x7CA8, 0xBB93, 0x7CA9, 0xBB94, 0x7CAA, 0xB7E0, + 0x7CAB, 0xBB95, 0x7CAC, 0xBB96, 0x7CAD, 0xBB97, 0x7CAE, 0xC1B8, 0x7CAF, 0xBB98, 0x7CB0, 0xBB99, 0x7CB1, 0xC1BB, 0x7CB2, 0xF4D3, + 0x7CB3, 0xBEAC, 0x7CB4, 0xBB9A, 0x7CB5, 0xBB9B, 0x7CB6, 0xBB9C, 0x7CB7, 0xBB9D, 0x7CB8, 0xBB9E, 0x7CB9, 0xB4E2, 0x7CBA, 0xBB9F, + 0x7CBB, 0xBBA0, 0x7CBC, 0xF4D4, 0x7CBD, 0xF4D5, 0x7CBE, 0xBEAB, 0x7CBF, 0xBC40, 0x7CC0, 0xBC41, 0x7CC1, 0xF4D6, 0x7CC2, 0xBC42, + 0x7CC3, 0xBC43, 0x7CC4, 0xBC44, 0x7CC5, 0xF4DB, 0x7CC6, 0xBC45, 0x7CC7, 0xF4D7, 0x7CC8, 0xF4DA, 0x7CC9, 0xBC46, 0x7CCA, 0xBAFD, + 0x7CCB, 0xBC47, 0x7CCC, 0xF4D8, 0x7CCD, 0xF4D9, 0x7CCE, 0xBC48, 0x7CCF, 0xBC49, 0x7CD0, 0xBC4A, 0x7CD1, 0xBC4B, 0x7CD2, 0xBC4C, + 0x7CD3, 0xBC4D, 0x7CD4, 0xBC4E, 0x7CD5, 0xB8E2, 0x7CD6, 0xCCC7, 0x7CD7, 0xF4DC, 0x7CD8, 0xBC4F, 0x7CD9, 0xB2DA, 0x7CDA, 0xBC50, + 0x7CDB, 0xBC51, 0x7CDC, 0xC3D3, 0x7CDD, 0xBC52, 0x7CDE, 0xBC53, 0x7CDF, 0xD4E3, 0x7CE0, 0xBFB7, 0x7CE1, 0xBC54, 0x7CE2, 0xBC55, + 0x7CE3, 0xBC56, 0x7CE4, 0xBC57, 0x7CE5, 0xBC58, 0x7CE6, 0xBC59, 0x7CE7, 0xBC5A, 0x7CE8, 0xF4DD, 0x7CE9, 0xBC5B, 0x7CEA, 0xBC5C, + 0x7CEB, 0xBC5D, 0x7CEC, 0xBC5E, 0x7CED, 0xBC5F, 0x7CEE, 0xBC60, 0x7CEF, 0xC5B4, 0x7CF0, 0xBC61, 0x7CF1, 0xBC62, 0x7CF2, 0xBC63, + 0x7CF3, 0xBC64, 0x7CF4, 0xBC65, 0x7CF5, 0xBC66, 0x7CF6, 0xBC67, 0x7CF7, 0xBC68, 0x7CF8, 0xF4E9, 0x7CF9, 0xBC69, 0x7CFA, 0xBC6A, + 0x7CFB, 0xCFB5, 0x7CFC, 0xBC6B, 0x7CFD, 0xBC6C, 0x7CFE, 0xBC6D, 0x7CFF, 0xBC6E, 0x7D00, 0xBC6F, 0x7D01, 0xBC70, 0x7D02, 0xBC71, + 0x7D03, 0xBC72, 0x7D04, 0xBC73, 0x7D05, 0xBC74, 0x7D06, 0xBC75, 0x7D07, 0xBC76, 0x7D08, 0xBC77, 0x7D09, 0xBC78, 0x7D0A, 0xCEC9, + 0x7D0B, 0xBC79, 0x7D0C, 0xBC7A, 0x7D0D, 0xBC7B, 0x7D0E, 0xBC7C, 0x7D0F, 0xBC7D, 0x7D10, 0xBC7E, 0x7D11, 0xBC80, 0x7D12, 0xBC81, + 0x7D13, 0xBC82, 0x7D14, 0xBC83, 0x7D15, 0xBC84, 0x7D16, 0xBC85, 0x7D17, 0xBC86, 0x7D18, 0xBC87, 0x7D19, 0xBC88, 0x7D1A, 0xBC89, + 0x7D1B, 0xBC8A, 0x7D1C, 0xBC8B, 0x7D1D, 0xBC8C, 0x7D1E, 0xBC8D, 0x7D1F, 0xBC8E, 0x7D20, 0xCBD8, 0x7D21, 0xBC8F, 0x7D22, 0xCBF7, + 0x7D23, 0xBC90, 0x7D24, 0xBC91, 0x7D25, 0xBC92, 0x7D26, 0xBC93, 0x7D27, 0xBDF4, 0x7D28, 0xBC94, 0x7D29, 0xBC95, 0x7D2A, 0xBC96, + 0x7D2B, 0xD7CF, 0x7D2C, 0xBC97, 0x7D2D, 0xBC98, 0x7D2E, 0xBC99, 0x7D2F, 0xC0DB, 0x7D30, 0xBC9A, 0x7D31, 0xBC9B, 0x7D32, 0xBC9C, + 0x7D33, 0xBC9D, 0x7D34, 0xBC9E, 0x7D35, 0xBC9F, 0x7D36, 0xBCA0, 0x7D37, 0xBD40, 0x7D38, 0xBD41, 0x7D39, 0xBD42, 0x7D3A, 0xBD43, + 0x7D3B, 0xBD44, 0x7D3C, 0xBD45, 0x7D3D, 0xBD46, 0x7D3E, 0xBD47, 0x7D3F, 0xBD48, 0x7D40, 0xBD49, 0x7D41, 0xBD4A, 0x7D42, 0xBD4B, + 0x7D43, 0xBD4C, 0x7D44, 0xBD4D, 0x7D45, 0xBD4E, 0x7D46, 0xBD4F, 0x7D47, 0xBD50, 0x7D48, 0xBD51, 0x7D49, 0xBD52, 0x7D4A, 0xBD53, + 0x7D4B, 0xBD54, 0x7D4C, 0xBD55, 0x7D4D, 0xBD56, 0x7D4E, 0xBD57, 0x7D4F, 0xBD58, 0x7D50, 0xBD59, 0x7D51, 0xBD5A, 0x7D52, 0xBD5B, + 0x7D53, 0xBD5C, 0x7D54, 0xBD5D, 0x7D55, 0xBD5E, 0x7D56, 0xBD5F, 0x7D57, 0xBD60, 0x7D58, 0xBD61, 0x7D59, 0xBD62, 0x7D5A, 0xBD63, + 0x7D5B, 0xBD64, 0x7D5C, 0xBD65, 0x7D5D, 0xBD66, 0x7D5E, 0xBD67, 0x7D5F, 0xBD68, 0x7D60, 0xBD69, 0x7D61, 0xBD6A, 0x7D62, 0xBD6B, + 0x7D63, 0xBD6C, 0x7D64, 0xBD6D, 0x7D65, 0xBD6E, 0x7D66, 0xBD6F, 0x7D67, 0xBD70, 0x7D68, 0xBD71, 0x7D69, 0xBD72, 0x7D6A, 0xBD73, + 0x7D6B, 0xBD74, 0x7D6C, 0xBD75, 0x7D6D, 0xBD76, 0x7D6E, 0xD0F5, 0x7D6F, 0xBD77, 0x7D70, 0xBD78, 0x7D71, 0xBD79, 0x7D72, 0xBD7A, + 0x7D73, 0xBD7B, 0x7D74, 0xBD7C, 0x7D75, 0xBD7D, 0x7D76, 0xBD7E, 0x7D77, 0xF4EA, 0x7D78, 0xBD80, 0x7D79, 0xBD81, 0x7D7A, 0xBD82, + 0x7D7B, 0xBD83, 0x7D7C, 0xBD84, 0x7D7D, 0xBD85, 0x7D7E, 0xBD86, 0x7D7F, 0xBD87, 0x7D80, 0xBD88, 0x7D81, 0xBD89, 0x7D82, 0xBD8A, + 0x7D83, 0xBD8B, 0x7D84, 0xBD8C, 0x7D85, 0xBD8D, 0x7D86, 0xBD8E, 0x7D87, 0xBD8F, 0x7D88, 0xBD90, 0x7D89, 0xBD91, 0x7D8A, 0xBD92, + 0x7D8B, 0xBD93, 0x7D8C, 0xBD94, 0x7D8D, 0xBD95, 0x7D8E, 0xBD96, 0x7D8F, 0xBD97, 0x7D90, 0xBD98, 0x7D91, 0xBD99, 0x7D92, 0xBD9A, + 0x7D93, 0xBD9B, 0x7D94, 0xBD9C, 0x7D95, 0xBD9D, 0x7D96, 0xBD9E, 0x7D97, 0xBD9F, 0x7D98, 0xBDA0, 0x7D99, 0xBE40, 0x7D9A, 0xBE41, + 0x7D9B, 0xBE42, 0x7D9C, 0xBE43, 0x7D9D, 0xBE44, 0x7D9E, 0xBE45, 0x7D9F, 0xBE46, 0x7DA0, 0xBE47, 0x7DA1, 0xBE48, 0x7DA2, 0xBE49, + 0x7DA3, 0xBE4A, 0x7DA4, 0xBE4B, 0x7DA5, 0xBE4C, 0x7DA6, 0xF4EB, 0x7DA7, 0xBE4D, 0x7DA8, 0xBE4E, 0x7DA9, 0xBE4F, 0x7DAA, 0xBE50, + 0x7DAB, 0xBE51, 0x7DAC, 0xBE52, 0x7DAD, 0xBE53, 0x7DAE, 0xF4EC, 0x7DAF, 0xBE54, 0x7DB0, 0xBE55, 0x7DB1, 0xBE56, 0x7DB2, 0xBE57, + 0x7DB3, 0xBE58, 0x7DB4, 0xBE59, 0x7DB5, 0xBE5A, 0x7DB6, 0xBE5B, 0x7DB7, 0xBE5C, 0x7DB8, 0xBE5D, 0x7DB9, 0xBE5E, 0x7DBA, 0xBE5F, + 0x7DBB, 0xBE60, 0x7DBC, 0xBE61, 0x7DBD, 0xBE62, 0x7DBE, 0xBE63, 0x7DBF, 0xBE64, 0x7DC0, 0xBE65, 0x7DC1, 0xBE66, 0x7DC2, 0xBE67, + 0x7DC3, 0xBE68, 0x7DC4, 0xBE69, 0x7DC5, 0xBE6A, 0x7DC6, 0xBE6B, 0x7DC7, 0xBE6C, 0x7DC8, 0xBE6D, 0x7DC9, 0xBE6E, 0x7DCA, 0xBE6F, + 0x7DCB, 0xBE70, 0x7DCC, 0xBE71, 0x7DCD, 0xBE72, 0x7DCE, 0xBE73, 0x7DCF, 0xBE74, 0x7DD0, 0xBE75, 0x7DD1, 0xBE76, 0x7DD2, 0xBE77, + 0x7DD3, 0xBE78, 0x7DD4, 0xBE79, 0x7DD5, 0xBE7A, 0x7DD6, 0xBE7B, 0x7DD7, 0xBE7C, 0x7DD8, 0xBE7D, 0x7DD9, 0xBE7E, 0x7DDA, 0xBE80, + 0x7DDB, 0xBE81, 0x7DDC, 0xBE82, 0x7DDD, 0xBE83, 0x7DDE, 0xBE84, 0x7DDF, 0xBE85, 0x7DE0, 0xBE86, 0x7DE1, 0xBE87, 0x7DE2, 0xBE88, + 0x7DE3, 0xBE89, 0x7DE4, 0xBE8A, 0x7DE5, 0xBE8B, 0x7DE6, 0xBE8C, 0x7DE7, 0xBE8D, 0x7DE8, 0xBE8E, 0x7DE9, 0xBE8F, 0x7DEA, 0xBE90, + 0x7DEB, 0xBE91, 0x7DEC, 0xBE92, 0x7DED, 0xBE93, 0x7DEE, 0xBE94, 0x7DEF, 0xBE95, 0x7DF0, 0xBE96, 0x7DF1, 0xBE97, 0x7DF2, 0xBE98, + 0x7DF3, 0xBE99, 0x7DF4, 0xBE9A, 0x7DF5, 0xBE9B, 0x7DF6, 0xBE9C, 0x7DF7, 0xBE9D, 0x7DF8, 0xBE9E, 0x7DF9, 0xBE9F, 0x7DFA, 0xBEA0, + 0x7DFB, 0xBF40, 0x7DFC, 0xBF41, 0x7DFD, 0xBF42, 0x7DFE, 0xBF43, 0x7DFF, 0xBF44, 0x7E00, 0xBF45, 0x7E01, 0xBF46, 0x7E02, 0xBF47, + 0x7E03, 0xBF48, 0x7E04, 0xBF49, 0x7E05, 0xBF4A, 0x7E06, 0xBF4B, 0x7E07, 0xBF4C, 0x7E08, 0xBF4D, 0x7E09, 0xBF4E, 0x7E0A, 0xBF4F, + 0x7E0B, 0xBF50, 0x7E0C, 0xBF51, 0x7E0D, 0xBF52, 0x7E0E, 0xBF53, 0x7E0F, 0xBF54, 0x7E10, 0xBF55, 0x7E11, 0xBF56, 0x7E12, 0xBF57, + 0x7E13, 0xBF58, 0x7E14, 0xBF59, 0x7E15, 0xBF5A, 0x7E16, 0xBF5B, 0x7E17, 0xBF5C, 0x7E18, 0xBF5D, 0x7E19, 0xBF5E, 0x7E1A, 0xBF5F, + 0x7E1B, 0xBF60, 0x7E1C, 0xBF61, 0x7E1D, 0xBF62, 0x7E1E, 0xBF63, 0x7E1F, 0xBF64, 0x7E20, 0xBF65, 0x7E21, 0xBF66, 0x7E22, 0xBF67, + 0x7E23, 0xBF68, 0x7E24, 0xBF69, 0x7E25, 0xBF6A, 0x7E26, 0xBF6B, 0x7E27, 0xBF6C, 0x7E28, 0xBF6D, 0x7E29, 0xBF6E, 0x7E2A, 0xBF6F, + 0x7E2B, 0xBF70, 0x7E2C, 0xBF71, 0x7E2D, 0xBF72, 0x7E2E, 0xBF73, 0x7E2F, 0xBF74, 0x7E30, 0xBF75, 0x7E31, 0xBF76, 0x7E32, 0xBF77, + 0x7E33, 0xBF78, 0x7E34, 0xBF79, 0x7E35, 0xBF7A, 0x7E36, 0xBF7B, 0x7E37, 0xBF7C, 0x7E38, 0xBF7D, 0x7E39, 0xBF7E, 0x7E3A, 0xBF80, + 0x7E3B, 0xF7E3, 0x7E3C, 0xBF81, 0x7E3D, 0xBF82, 0x7E3E, 0xBF83, 0x7E3F, 0xBF84, 0x7E40, 0xBF85, 0x7E41, 0xB7B1, 0x7E42, 0xBF86, + 0x7E43, 0xBF87, 0x7E44, 0xBF88, 0x7E45, 0xBF89, 0x7E46, 0xBF8A, 0x7E47, 0xF4ED, 0x7E48, 0xBF8B, 0x7E49, 0xBF8C, 0x7E4A, 0xBF8D, + 0x7E4B, 0xBF8E, 0x7E4C, 0xBF8F, 0x7E4D, 0xBF90, 0x7E4E, 0xBF91, 0x7E4F, 0xBF92, 0x7E50, 0xBF93, 0x7E51, 0xBF94, 0x7E52, 0xBF95, + 0x7E53, 0xBF96, 0x7E54, 0xBF97, 0x7E55, 0xBF98, 0x7E56, 0xBF99, 0x7E57, 0xBF9A, 0x7E58, 0xBF9B, 0x7E59, 0xBF9C, 0x7E5A, 0xBF9D, + 0x7E5B, 0xBF9E, 0x7E5C, 0xBF9F, 0x7E5D, 0xBFA0, 0x7E5E, 0xC040, 0x7E5F, 0xC041, 0x7E60, 0xC042, 0x7E61, 0xC043, 0x7E62, 0xC044, + 0x7E63, 0xC045, 0x7E64, 0xC046, 0x7E65, 0xC047, 0x7E66, 0xC048, 0x7E67, 0xC049, 0x7E68, 0xC04A, 0x7E69, 0xC04B, 0x7E6A, 0xC04C, + 0x7E6B, 0xC04D, 0x7E6C, 0xC04E, 0x7E6D, 0xC04F, 0x7E6E, 0xC050, 0x7E6F, 0xC051, 0x7E70, 0xC052, 0x7E71, 0xC053, 0x7E72, 0xC054, + 0x7E73, 0xC055, 0x7E74, 0xC056, 0x7E75, 0xC057, 0x7E76, 0xC058, 0x7E77, 0xC059, 0x7E78, 0xC05A, 0x7E79, 0xC05B, 0x7E7A, 0xC05C, + 0x7E7B, 0xC05D, 0x7E7C, 0xC05E, 0x7E7D, 0xC05F, 0x7E7E, 0xC060, 0x7E7F, 0xC061, 0x7E80, 0xC062, 0x7E81, 0xC063, 0x7E82, 0xD7EB, + 0x7E83, 0xC064, 0x7E84, 0xC065, 0x7E85, 0xC066, 0x7E86, 0xC067, 0x7E87, 0xC068, 0x7E88, 0xC069, 0x7E89, 0xC06A, 0x7E8A, 0xC06B, + 0x7E8B, 0xC06C, 0x7E8C, 0xC06D, 0x7E8D, 0xC06E, 0x7E8E, 0xC06F, 0x7E8F, 0xC070, 0x7E90, 0xC071, 0x7E91, 0xC072, 0x7E92, 0xC073, + 0x7E93, 0xC074, 0x7E94, 0xC075, 0x7E95, 0xC076, 0x7E96, 0xC077, 0x7E97, 0xC078, 0x7E98, 0xC079, 0x7E99, 0xC07A, 0x7E9A, 0xC07B, + 0x7E9B, 0xF4EE, 0x7E9C, 0xC07C, 0x7E9D, 0xC07D, 0x7E9E, 0xC07E, 0x7E9F, 0xE6F9, 0x7EA0, 0xBEC0, 0x7EA1, 0xE6FA, 0x7EA2, 0xBAEC, + 0x7EA3, 0xE6FB, 0x7EA4, 0xCFCB, 0x7EA5, 0xE6FC, 0x7EA6, 0xD4BC, 0x7EA7, 0xBCB6, 0x7EA8, 0xE6FD, 0x7EA9, 0xE6FE, 0x7EAA, 0xBCCD, + 0x7EAB, 0xC8D2, 0x7EAC, 0xCEB3, 0x7EAD, 0xE7A1, 0x7EAE, 0xC080, 0x7EAF, 0xB4BF, 0x7EB0, 0xE7A2, 0x7EB1, 0xC9B4, 0x7EB2, 0xB8D9, + 0x7EB3, 0xC4C9, 0x7EB4, 0xC081, 0x7EB5, 0xD7DD, 0x7EB6, 0xC2DA, 0x7EB7, 0xB7D7, 0x7EB8, 0xD6BD, 0x7EB9, 0xCEC6, 0x7EBA, 0xB7C4, + 0x7EBB, 0xC082, 0x7EBC, 0xC083, 0x7EBD, 0xC5A6, 0x7EBE, 0xE7A3, 0x7EBF, 0xCFDF, 0x7EC0, 0xE7A4, 0x7EC1, 0xE7A5, 0x7EC2, 0xE7A6, + 0x7EC3, 0xC1B7, 0x7EC4, 0xD7E9, 0x7EC5, 0xC9F0, 0x7EC6, 0xCFB8, 0x7EC7, 0xD6AF, 0x7EC8, 0xD6D5, 0x7EC9, 0xE7A7, 0x7ECA, 0xB0ED, + 0x7ECB, 0xE7A8, 0x7ECC, 0xE7A9, 0x7ECD, 0xC9DC, 0x7ECE, 0xD2EF, 0x7ECF, 0xBEAD, 0x7ED0, 0xE7AA, 0x7ED1, 0xB0F3, 0x7ED2, 0xC8DE, + 0x7ED3, 0xBDE1, 0x7ED4, 0xE7AB, 0x7ED5, 0xC8C6, 0x7ED6, 0xC084, 0x7ED7, 0xE7AC, 0x7ED8, 0xBBE6, 0x7ED9, 0xB8F8, 0x7EDA, 0xD1A4, + 0x7EDB, 0xE7AD, 0x7EDC, 0xC2E7, 0x7EDD, 0xBEF8, 0x7EDE, 0xBDCA, 0x7EDF, 0xCDB3, 0x7EE0, 0xE7AE, 0x7EE1, 0xE7AF, 0x7EE2, 0xBEEE, + 0x7EE3, 0xD0E5, 0x7EE4, 0xC085, 0x7EE5, 0xCBE7, 0x7EE6, 0xCCD0, 0x7EE7, 0xBCCC, 0x7EE8, 0xE7B0, 0x7EE9, 0xBCA8, 0x7EEA, 0xD0F7, + 0x7EEB, 0xE7B1, 0x7EEC, 0xC086, 0x7EED, 0xD0F8, 0x7EEE, 0xE7B2, 0x7EEF, 0xE7B3, 0x7EF0, 0xB4C2, 0x7EF1, 0xE7B4, 0x7EF2, 0xE7B5, + 0x7EF3, 0xC9FE, 0x7EF4, 0xCEAC, 0x7EF5, 0xC3E0, 0x7EF6, 0xE7B7, 0x7EF7, 0xB1C1, 0x7EF8, 0xB3F1, 0x7EF9, 0xC087, 0x7EFA, 0xE7B8, + 0x7EFB, 0xE7B9, 0x7EFC, 0xD7DB, 0x7EFD, 0xD5C0, 0x7EFE, 0xE7BA, 0x7EFF, 0xC2CC, 0x7F00, 0xD7BA, 0x7F01, 0xE7BB, 0x7F02, 0xE7BC, + 0x7F03, 0xE7BD, 0x7F04, 0xBCEA, 0x7F05, 0xC3E5, 0x7F06, 0xC0C2, 0x7F07, 0xE7BE, 0x7F08, 0xE7BF, 0x7F09, 0xBCA9, 0x7F0A, 0xC088, + 0x7F0B, 0xE7C0, 0x7F0C, 0xE7C1, 0x7F0D, 0xE7B6, 0x7F0E, 0xB6D0, 0x7F0F, 0xE7C2, 0x7F10, 0xC089, 0x7F11, 0xE7C3, 0x7F12, 0xE7C4, + 0x7F13, 0xBBBA, 0x7F14, 0xB5DE, 0x7F15, 0xC2C6, 0x7F16, 0xB1E0, 0x7F17, 0xE7C5, 0x7F18, 0xD4B5, 0x7F19, 0xE7C6, 0x7F1A, 0xB8BF, + 0x7F1B, 0xE7C8, 0x7F1C, 0xE7C7, 0x7F1D, 0xB7EC, 0x7F1E, 0xC08A, 0x7F1F, 0xE7C9, 0x7F20, 0xB2F8, 0x7F21, 0xE7CA, 0x7F22, 0xE7CB, + 0x7F23, 0xE7CC, 0x7F24, 0xE7CD, 0x7F25, 0xE7CE, 0x7F26, 0xE7CF, 0x7F27, 0xE7D0, 0x7F28, 0xD3A7, 0x7F29, 0xCBF5, 0x7F2A, 0xE7D1, + 0x7F2B, 0xE7D2, 0x7F2C, 0xE7D3, 0x7F2D, 0xE7D4, 0x7F2E, 0xC9C9, 0x7F2F, 0xE7D5, 0x7F30, 0xE7D6, 0x7F31, 0xE7D7, 0x7F32, 0xE7D8, + 0x7F33, 0xE7D9, 0x7F34, 0xBDC9, 0x7F35, 0xE7DA, 0x7F36, 0xF3BE, 0x7F37, 0xC08B, 0x7F38, 0xB8D7, 0x7F39, 0xC08C, 0x7F3A, 0xC8B1, + 0x7F3B, 0xC08D, 0x7F3C, 0xC08E, 0x7F3D, 0xC08F, 0x7F3E, 0xC090, 0x7F3F, 0xC091, 0x7F40, 0xC092, 0x7F41, 0xC093, 0x7F42, 0xF3BF, + 0x7F43, 0xC094, 0x7F44, 0xF3C0, 0x7F45, 0xF3C1, 0x7F46, 0xC095, 0x7F47, 0xC096, 0x7F48, 0xC097, 0x7F49, 0xC098, 0x7F4A, 0xC099, + 0x7F4B, 0xC09A, 0x7F4C, 0xC09B, 0x7F4D, 0xC09C, 0x7F4E, 0xC09D, 0x7F4F, 0xC09E, 0x7F50, 0xB9DE, 0x7F51, 0xCDF8, 0x7F52, 0xC09F, + 0x7F53, 0xC0A0, 0x7F54, 0xD8E8, 0x7F55, 0xBAB1, 0x7F56, 0xC140, 0x7F57, 0xC2DE, 0x7F58, 0xEEB7, 0x7F59, 0xC141, 0x7F5A, 0xB7A3, + 0x7F5B, 0xC142, 0x7F5C, 0xC143, 0x7F5D, 0xC144, 0x7F5E, 0xC145, 0x7F5F, 0xEEB9, 0x7F60, 0xC146, 0x7F61, 0xEEB8, 0x7F62, 0xB0D5, + 0x7F63, 0xC147, 0x7F64, 0xC148, 0x7F65, 0xC149, 0x7F66, 0xC14A, 0x7F67, 0xC14B, 0x7F68, 0xEEBB, 0x7F69, 0xD5D6, 0x7F6A, 0xD7EF, + 0x7F6B, 0xC14C, 0x7F6C, 0xC14D, 0x7F6D, 0xC14E, 0x7F6E, 0xD6C3, 0x7F6F, 0xC14F, 0x7F70, 0xC150, 0x7F71, 0xEEBD, 0x7F72, 0xCAF0, + 0x7F73, 0xC151, 0x7F74, 0xEEBC, 0x7F75, 0xC152, 0x7F76, 0xC153, 0x7F77, 0xC154, 0x7F78, 0xC155, 0x7F79, 0xEEBE, 0x7F7A, 0xC156, + 0x7F7B, 0xC157, 0x7F7C, 0xC158, 0x7F7D, 0xC159, 0x7F7E, 0xEEC0, 0x7F7F, 0xC15A, 0x7F80, 0xC15B, 0x7F81, 0xEEBF, 0x7F82, 0xC15C, + 0x7F83, 0xC15D, 0x7F84, 0xC15E, 0x7F85, 0xC15F, 0x7F86, 0xC160, 0x7F87, 0xC161, 0x7F88, 0xC162, 0x7F89, 0xC163, 0x7F8A, 0xD1F2, + 0x7F8B, 0xC164, 0x7F8C, 0xC7BC, 0x7F8D, 0xC165, 0x7F8E, 0xC3C0, 0x7F8F, 0xC166, 0x7F90, 0xC167, 0x7F91, 0xC168, 0x7F92, 0xC169, + 0x7F93, 0xC16A, 0x7F94, 0xB8E1, 0x7F95, 0xC16B, 0x7F96, 0xC16C, 0x7F97, 0xC16D, 0x7F98, 0xC16E, 0x7F99, 0xC16F, 0x7F9A, 0xC1E7, + 0x7F9B, 0xC170, 0x7F9C, 0xC171, 0x7F9D, 0xF4C6, 0x7F9E, 0xD0DF, 0x7F9F, 0xF4C7, 0x7FA0, 0xC172, 0x7FA1, 0xCFDB, 0x7FA2, 0xC173, + 0x7FA3, 0xC174, 0x7FA4, 0xC8BA, 0x7FA5, 0xC175, 0x7FA6, 0xC176, 0x7FA7, 0xF4C8, 0x7FA8, 0xC177, 0x7FA9, 0xC178, 0x7FAA, 0xC179, + 0x7FAB, 0xC17A, 0x7FAC, 0xC17B, 0x7FAD, 0xC17C, 0x7FAE, 0xC17D, 0x7FAF, 0xF4C9, 0x7FB0, 0xF4CA, 0x7FB1, 0xC17E, 0x7FB2, 0xF4CB, + 0x7FB3, 0xC180, 0x7FB4, 0xC181, 0x7FB5, 0xC182, 0x7FB6, 0xC183, 0x7FB7, 0xC184, 0x7FB8, 0xD9FA, 0x7FB9, 0xB8FE, 0x7FBA, 0xC185, + 0x7FBB, 0xC186, 0x7FBC, 0xE5F1, 0x7FBD, 0xD3F0, 0x7FBE, 0xC187, 0x7FBF, 0xF4E0, 0x7FC0, 0xC188, 0x7FC1, 0xCECC, 0x7FC2, 0xC189, + 0x7FC3, 0xC18A, 0x7FC4, 0xC18B, 0x7FC5, 0xB3E1, 0x7FC6, 0xC18C, 0x7FC7, 0xC18D, 0x7FC8, 0xC18E, 0x7FC9, 0xC18F, 0x7FCA, 0xF1B4, + 0x7FCB, 0xC190, 0x7FCC, 0xD2EE, 0x7FCD, 0xC191, 0x7FCE, 0xF4E1, 0x7FCF, 0xC192, 0x7FD0, 0xC193, 0x7FD1, 0xC194, 0x7FD2, 0xC195, + 0x7FD3, 0xC196, 0x7FD4, 0xCFE8, 0x7FD5, 0xF4E2, 0x7FD6, 0xC197, 0x7FD7, 0xC198, 0x7FD8, 0xC7CC, 0x7FD9, 0xC199, 0x7FDA, 0xC19A, + 0x7FDB, 0xC19B, 0x7FDC, 0xC19C, 0x7FDD, 0xC19D, 0x7FDE, 0xC19E, 0x7FDF, 0xB5D4, 0x7FE0, 0xB4E4, 0x7FE1, 0xF4E4, 0x7FE2, 0xC19F, + 0x7FE3, 0xC1A0, 0x7FE4, 0xC240, 0x7FE5, 0xF4E3, 0x7FE6, 0xF4E5, 0x7FE7, 0xC241, 0x7FE8, 0xC242, 0x7FE9, 0xF4E6, 0x7FEA, 0xC243, + 0x7FEB, 0xC244, 0x7FEC, 0xC245, 0x7FED, 0xC246, 0x7FEE, 0xF4E7, 0x7FEF, 0xC247, 0x7FF0, 0xBAB2, 0x7FF1, 0xB0BF, 0x7FF2, 0xC248, + 0x7FF3, 0xF4E8, 0x7FF4, 0xC249, 0x7FF5, 0xC24A, 0x7FF6, 0xC24B, 0x7FF7, 0xC24C, 0x7FF8, 0xC24D, 0x7FF9, 0xC24E, 0x7FFA, 0xC24F, + 0x7FFB, 0xB7AD, 0x7FFC, 0xD2ED, 0x7FFD, 0xC250, 0x7FFE, 0xC251, 0x7FFF, 0xC252, 0x8000, 0xD2AB, 0x8001, 0xC0CF, 0x8002, 0xC253, + 0x8003, 0xBFBC, 0x8004, 0xEBA3, 0x8005, 0xD5DF, 0x8006, 0xEAC8, 0x8007, 0xC254, 0x8008, 0xC255, 0x8009, 0xC256, 0x800A, 0xC257, + 0x800B, 0xF1F3, 0x800C, 0xB6F8, 0x800D, 0xCBA3, 0x800E, 0xC258, 0x800F, 0xC259, 0x8010, 0xC4CD, 0x8011, 0xC25A, 0x8012, 0xF1E7, + 0x8013, 0xC25B, 0x8014, 0xF1E8, 0x8015, 0xB8FB, 0x8016, 0xF1E9, 0x8017, 0xBAC4, 0x8018, 0xD4C5, 0x8019, 0xB0D2, 0x801A, 0xC25C, + 0x801B, 0xC25D, 0x801C, 0xF1EA, 0x801D, 0xC25E, 0x801E, 0xC25F, 0x801F, 0xC260, 0x8020, 0xF1EB, 0x8021, 0xC261, 0x8022, 0xF1EC, + 0x8023, 0xC262, 0x8024, 0xC263, 0x8025, 0xF1ED, 0x8026, 0xF1EE, 0x8027, 0xF1EF, 0x8028, 0xF1F1, 0x8029, 0xF1F0, 0x802A, 0xC5D5, + 0x802B, 0xC264, 0x802C, 0xC265, 0x802D, 0xC266, 0x802E, 0xC267, 0x802F, 0xC268, 0x8030, 0xC269, 0x8031, 0xF1F2, 0x8032, 0xC26A, + 0x8033, 0xB6FA, 0x8034, 0xC26B, 0x8035, 0xF1F4, 0x8036, 0xD2AE, 0x8037, 0xDEC7, 0x8038, 0xCBCA, 0x8039, 0xC26C, 0x803A, 0xC26D, + 0x803B, 0xB3DC, 0x803C, 0xC26E, 0x803D, 0xB5A2, 0x803E, 0xC26F, 0x803F, 0xB9A2, 0x8040, 0xC270, 0x8041, 0xC271, 0x8042, 0xC4F4, + 0x8043, 0xF1F5, 0x8044, 0xC272, 0x8045, 0xC273, 0x8046, 0xF1F6, 0x8047, 0xC274, 0x8048, 0xC275, 0x8049, 0xC276, 0x804A, 0xC1C4, + 0x804B, 0xC1FB, 0x804C, 0xD6B0, 0x804D, 0xF1F7, 0x804E, 0xC277, 0x804F, 0xC278, 0x8050, 0xC279, 0x8051, 0xC27A, 0x8052, 0xF1F8, + 0x8053, 0xC27B, 0x8054, 0xC1AA, 0x8055, 0xC27C, 0x8056, 0xC27D, 0x8057, 0xC27E, 0x8058, 0xC6B8, 0x8059, 0xC280, 0x805A, 0xBEDB, + 0x805B, 0xC281, 0x805C, 0xC282, 0x805D, 0xC283, 0x805E, 0xC284, 0x805F, 0xC285, 0x8060, 0xC286, 0x8061, 0xC287, 0x8062, 0xC288, + 0x8063, 0xC289, 0x8064, 0xC28A, 0x8065, 0xC28B, 0x8066, 0xC28C, 0x8067, 0xC28D, 0x8068, 0xC28E, 0x8069, 0xF1F9, 0x806A, 0xB4CF, + 0x806B, 0xC28F, 0x806C, 0xC290, 0x806D, 0xC291, 0x806E, 0xC292, 0x806F, 0xC293, 0x8070, 0xC294, 0x8071, 0xF1FA, 0x8072, 0xC295, + 0x8073, 0xC296, 0x8074, 0xC297, 0x8075, 0xC298, 0x8076, 0xC299, 0x8077, 0xC29A, 0x8078, 0xC29B, 0x8079, 0xC29C, 0x807A, 0xC29D, + 0x807B, 0xC29E, 0x807C, 0xC29F, 0x807D, 0xC2A0, 0x807E, 0xC340, 0x807F, 0xEDB2, 0x8080, 0xEDB1, 0x8081, 0xC341, 0x8082, 0xC342, + 0x8083, 0xCBE0, 0x8084, 0xD2DE, 0x8085, 0xC343, 0x8086, 0xCBC1, 0x8087, 0xD5D8, 0x8088, 0xC344, 0x8089, 0xC8E2, 0x808A, 0xC345, + 0x808B, 0xC0DF, 0x808C, 0xBCA1, 0x808D, 0xC346, 0x808E, 0xC347, 0x808F, 0xC348, 0x8090, 0xC349, 0x8091, 0xC34A, 0x8092, 0xC34B, + 0x8093, 0xEBC1, 0x8094, 0xC34C, 0x8095, 0xC34D, 0x8096, 0xD0A4, 0x8097, 0xC34E, 0x8098, 0xD6E2, 0x8099, 0xC34F, 0x809A, 0xB6C7, + 0x809B, 0xB8D8, 0x809C, 0xEBC0, 0x809D, 0xB8CE, 0x809E, 0xC350, 0x809F, 0xEBBF, 0x80A0, 0xB3A6, 0x80A1, 0xB9C9, 0x80A2, 0xD6AB, + 0x80A3, 0xC351, 0x80A4, 0xB7F4, 0x80A5, 0xB7CA, 0x80A6, 0xC352, 0x80A7, 0xC353, 0x80A8, 0xC354, 0x80A9, 0xBCE7, 0x80AA, 0xB7BE, + 0x80AB, 0xEBC6, 0x80AC, 0xC355, 0x80AD, 0xEBC7, 0x80AE, 0xB0B9, 0x80AF, 0xBFCF, 0x80B0, 0xC356, 0x80B1, 0xEBC5, 0x80B2, 0xD3FD, + 0x80B3, 0xC357, 0x80B4, 0xEBC8, 0x80B5, 0xC358, 0x80B6, 0xC359, 0x80B7, 0xEBC9, 0x80B8, 0xC35A, 0x80B9, 0xC35B, 0x80BA, 0xB7CE, + 0x80BB, 0xC35C, 0x80BC, 0xEBC2, 0x80BD, 0xEBC4, 0x80BE, 0xC9F6, 0x80BF, 0xD6D7, 0x80C0, 0xD5CD, 0x80C1, 0xD0B2, 0x80C2, 0xEBCF, + 0x80C3, 0xCEB8, 0x80C4, 0xEBD0, 0x80C5, 0xC35D, 0x80C6, 0xB5A8, 0x80C7, 0xC35E, 0x80C8, 0xC35F, 0x80C9, 0xC360, 0x80CA, 0xC361, + 0x80CB, 0xC362, 0x80CC, 0xB1B3, 0x80CD, 0xEBD2, 0x80CE, 0xCCA5, 0x80CF, 0xC363, 0x80D0, 0xC364, 0x80D1, 0xC365, 0x80D2, 0xC366, + 0x80D3, 0xC367, 0x80D4, 0xC368, 0x80D5, 0xC369, 0x80D6, 0xC5D6, 0x80D7, 0xEBD3, 0x80D8, 0xC36A, 0x80D9, 0xEBD1, 0x80DA, 0xC5DF, + 0x80DB, 0xEBCE, 0x80DC, 0xCAA4, 0x80DD, 0xEBD5, 0x80DE, 0xB0FB, 0x80DF, 0xC36B, 0x80E0, 0xC36C, 0x80E1, 0xBAFA, 0x80E2, 0xC36D, + 0x80E3, 0xC36E, 0x80E4, 0xD8B7, 0x80E5, 0xF1E3, 0x80E6, 0xC36F, 0x80E7, 0xEBCA, 0x80E8, 0xEBCB, 0x80E9, 0xEBCC, 0x80EA, 0xEBCD, + 0x80EB, 0xEBD6, 0x80EC, 0xE6C0, 0x80ED, 0xEBD9, 0x80EE, 0xC370, 0x80EF, 0xBFE8, 0x80F0, 0xD2C8, 0x80F1, 0xEBD7, 0x80F2, 0xEBDC, + 0x80F3, 0xB8EC, 0x80F4, 0xEBD8, 0x80F5, 0xC371, 0x80F6, 0xBDBA, 0x80F7, 0xC372, 0x80F8, 0xD0D8, 0x80F9, 0xC373, 0x80FA, 0xB0B7, + 0x80FB, 0xC374, 0x80FC, 0xEBDD, 0x80FD, 0xC4DC, 0x80FE, 0xC375, 0x80FF, 0xC376, 0x8100, 0xC377, 0x8101, 0xC378, 0x8102, 0xD6AC, + 0x8103, 0xC379, 0x8104, 0xC37A, 0x8105, 0xC37B, 0x8106, 0xB4E0, 0x8107, 0xC37C, 0x8108, 0xC37D, 0x8109, 0xC2F6, 0x810A, 0xBCB9, + 0x810B, 0xC37E, 0x810C, 0xC380, 0x810D, 0xEBDA, 0x810E, 0xEBDB, 0x810F, 0xD4E0, 0x8110, 0xC6EA, 0x8111, 0xC4D4, 0x8112, 0xEBDF, + 0x8113, 0xC5A7, 0x8114, 0xD9F5, 0x8115, 0xC381, 0x8116, 0xB2B1, 0x8117, 0xC382, 0x8118, 0xEBE4, 0x8119, 0xC383, 0x811A, 0xBDC5, + 0x811B, 0xC384, 0x811C, 0xC385, 0x811D, 0xC386, 0x811E, 0xEBE2, 0x811F, 0xC387, 0x8120, 0xC388, 0x8121, 0xC389, 0x8122, 0xC38A, + 0x8123, 0xC38B, 0x8124, 0xC38C, 0x8125, 0xC38D, 0x8126, 0xC38E, 0x8127, 0xC38F, 0x8128, 0xC390, 0x8129, 0xC391, 0x812A, 0xC392, + 0x812B, 0xC393, 0x812C, 0xEBE3, 0x812D, 0xC394, 0x812E, 0xC395, 0x812F, 0xB8AC, 0x8130, 0xC396, 0x8131, 0xCDD1, 0x8132, 0xEBE5, + 0x8133, 0xC397, 0x8134, 0xC398, 0x8135, 0xC399, 0x8136, 0xEBE1, 0x8137, 0xC39A, 0x8138, 0xC1B3, 0x8139, 0xC39B, 0x813A, 0xC39C, + 0x813B, 0xC39D, 0x813C, 0xC39E, 0x813D, 0xC39F, 0x813E, 0xC6A2, 0x813F, 0xC3A0, 0x8140, 0xC440, 0x8141, 0xC441, 0x8142, 0xC442, + 0x8143, 0xC443, 0x8144, 0xC444, 0x8145, 0xC445, 0x8146, 0xCCF3, 0x8147, 0xC446, 0x8148, 0xEBE6, 0x8149, 0xC447, 0x814A, 0xC0B0, + 0x814B, 0xD2B8, 0x814C, 0xEBE7, 0x814D, 0xC448, 0x814E, 0xC449, 0x814F, 0xC44A, 0x8150, 0xB8AF, 0x8151, 0xB8AD, 0x8152, 0xC44B, + 0x8153, 0xEBE8, 0x8154, 0xC7BB, 0x8155, 0xCDF3, 0x8156, 0xC44C, 0x8157, 0xC44D, 0x8158, 0xC44E, 0x8159, 0xEBEA, 0x815A, 0xEBEB, + 0x815B, 0xC44F, 0x815C, 0xC450, 0x815D, 0xC451, 0x815E, 0xC452, 0x815F, 0xC453, 0x8160, 0xEBED, 0x8161, 0xC454, 0x8162, 0xC455, + 0x8163, 0xC456, 0x8164, 0xC457, 0x8165, 0xD0C8, 0x8166, 0xC458, 0x8167, 0xEBF2, 0x8168, 0xC459, 0x8169, 0xEBEE, 0x816A, 0xC45A, + 0x816B, 0xC45B, 0x816C, 0xC45C, 0x816D, 0xEBF1, 0x816E, 0xC8F9, 0x816F, 0xC45D, 0x8170, 0xD1FC, 0x8171, 0xEBEC, 0x8172, 0xC45E, + 0x8173, 0xC45F, 0x8174, 0xEBE9, 0x8175, 0xC460, 0x8176, 0xC461, 0x8177, 0xC462, 0x8178, 0xC463, 0x8179, 0xB8B9, 0x817A, 0xCFD9, + 0x817B, 0xC4E5, 0x817C, 0xEBEF, 0x817D, 0xEBF0, 0x817E, 0xCCDA, 0x817F, 0xCDC8, 0x8180, 0xB0F2, 0x8181, 0xC464, 0x8182, 0xEBF6, + 0x8183, 0xC465, 0x8184, 0xC466, 0x8185, 0xC467, 0x8186, 0xC468, 0x8187, 0xC469, 0x8188, 0xEBF5, 0x8189, 0xC46A, 0x818A, 0xB2B2, + 0x818B, 0xC46B, 0x818C, 0xC46C, 0x818D, 0xC46D, 0x818E, 0xC46E, 0x818F, 0xB8E0, 0x8190, 0xC46F, 0x8191, 0xEBF7, 0x8192, 0xC470, + 0x8193, 0xC471, 0x8194, 0xC472, 0x8195, 0xC473, 0x8196, 0xC474, 0x8197, 0xC475, 0x8198, 0xB1EC, 0x8199, 0xC476, 0x819A, 0xC477, + 0x819B, 0xCCC5, 0x819C, 0xC4A4, 0x819D, 0xCFA5, 0x819E, 0xC478, 0x819F, 0xC479, 0x81A0, 0xC47A, 0x81A1, 0xC47B, 0x81A2, 0xC47C, + 0x81A3, 0xEBF9, 0x81A4, 0xC47D, 0x81A5, 0xC47E, 0x81A6, 0xECA2, 0x81A7, 0xC480, 0x81A8, 0xC5F2, 0x81A9, 0xC481, 0x81AA, 0xEBFA, + 0x81AB, 0xC482, 0x81AC, 0xC483, 0x81AD, 0xC484, 0x81AE, 0xC485, 0x81AF, 0xC486, 0x81B0, 0xC487, 0x81B1, 0xC488, 0x81B2, 0xC489, + 0x81B3, 0xC9C5, 0x81B4, 0xC48A, 0x81B5, 0xC48B, 0x81B6, 0xC48C, 0x81B7, 0xC48D, 0x81B8, 0xC48E, 0x81B9, 0xC48F, 0x81BA, 0xE2DF, + 0x81BB, 0xEBFE, 0x81BC, 0xC490, 0x81BD, 0xC491, 0x81BE, 0xC492, 0x81BF, 0xC493, 0x81C0, 0xCDCE, 0x81C1, 0xECA1, 0x81C2, 0xB1DB, + 0x81C3, 0xD3B7, 0x81C4, 0xC494, 0x81C5, 0xC495, 0x81C6, 0xD2DC, 0x81C7, 0xC496, 0x81C8, 0xC497, 0x81C9, 0xC498, 0x81CA, 0xEBFD, + 0x81CB, 0xC499, 0x81CC, 0xEBFB, 0x81CD, 0xC49A, 0x81CE, 0xC49B, 0x81CF, 0xC49C, 0x81D0, 0xC49D, 0x81D1, 0xC49E, 0x81D2, 0xC49F, + 0x81D3, 0xC4A0, 0x81D4, 0xC540, 0x81D5, 0xC541, 0x81D6, 0xC542, 0x81D7, 0xC543, 0x81D8, 0xC544, 0x81D9, 0xC545, 0x81DA, 0xC546, + 0x81DB, 0xC547, 0x81DC, 0xC548, 0x81DD, 0xC549, 0x81DE, 0xC54A, 0x81DF, 0xC54B, 0x81E0, 0xC54C, 0x81E1, 0xC54D, 0x81E2, 0xC54E, + 0x81E3, 0xB3BC, 0x81E4, 0xC54F, 0x81E5, 0xC550, 0x81E6, 0xC551, 0x81E7, 0xEAB0, 0x81E8, 0xC552, 0x81E9, 0xC553, 0x81EA, 0xD7D4, + 0x81EB, 0xC554, 0x81EC, 0xF4AB, 0x81ED, 0xB3F4, 0x81EE, 0xC555, 0x81EF, 0xC556, 0x81F0, 0xC557, 0x81F1, 0xC558, 0x81F2, 0xC559, + 0x81F3, 0xD6C1, 0x81F4, 0xD6C2, 0x81F5, 0xC55A, 0x81F6, 0xC55B, 0x81F7, 0xC55C, 0x81F8, 0xC55D, 0x81F9, 0xC55E, 0x81FA, 0xC55F, + 0x81FB, 0xD5E9, 0x81FC, 0xBECA, 0x81FD, 0xC560, 0x81FE, 0xF4A7, 0x81FF, 0xC561, 0x8200, 0xD2A8, 0x8201, 0xF4A8, 0x8202, 0xF4A9, + 0x8203, 0xC562, 0x8204, 0xF4AA, 0x8205, 0xBECB, 0x8206, 0xD3DF, 0x8207, 0xC563, 0x8208, 0xC564, 0x8209, 0xC565, 0x820A, 0xC566, + 0x820B, 0xC567, 0x820C, 0xC9E0, 0x820D, 0xC9E1, 0x820E, 0xC568, 0x820F, 0xC569, 0x8210, 0xF3C2, 0x8211, 0xC56A, 0x8212, 0xCAE6, + 0x8213, 0xC56B, 0x8214, 0xCCF2, 0x8215, 0xC56C, 0x8216, 0xC56D, 0x8217, 0xC56E, 0x8218, 0xC56F, 0x8219, 0xC570, 0x821A, 0xC571, + 0x821B, 0xE2B6, 0x821C, 0xCBB4, 0x821D, 0xC572, 0x821E, 0xCEE8, 0x821F, 0xD6DB, 0x8220, 0xC573, 0x8221, 0xF4AD, 0x8222, 0xF4AE, + 0x8223, 0xF4AF, 0x8224, 0xC574, 0x8225, 0xC575, 0x8226, 0xC576, 0x8227, 0xC577, 0x8228, 0xF4B2, 0x8229, 0xC578, 0x822A, 0xBABD, + 0x822B, 0xF4B3, 0x822C, 0xB0E3, 0x822D, 0xF4B0, 0x822E, 0xC579, 0x822F, 0xF4B1, 0x8230, 0xBDA2, 0x8231, 0xB2D5, 0x8232, 0xC57A, + 0x8233, 0xF4B6, 0x8234, 0xF4B7, 0x8235, 0xB6E6, 0x8236, 0xB2B0, 0x8237, 0xCFCF, 0x8238, 0xF4B4, 0x8239, 0xB4AC, 0x823A, 0xC57B, + 0x823B, 0xF4B5, 0x823C, 0xC57C, 0x823D, 0xC57D, 0x823E, 0xF4B8, 0x823F, 0xC57E, 0x8240, 0xC580, 0x8241, 0xC581, 0x8242, 0xC582, + 0x8243, 0xC583, 0x8244, 0xF4B9, 0x8245, 0xC584, 0x8246, 0xC585, 0x8247, 0xCDA7, 0x8248, 0xC586, 0x8249, 0xF4BA, 0x824A, 0xC587, + 0x824B, 0xF4BB, 0x824C, 0xC588, 0x824D, 0xC589, 0x824E, 0xC58A, 0x824F, 0xF4BC, 0x8250, 0xC58B, 0x8251, 0xC58C, 0x8252, 0xC58D, + 0x8253, 0xC58E, 0x8254, 0xC58F, 0x8255, 0xC590, 0x8256, 0xC591, 0x8257, 0xC592, 0x8258, 0xCBD2, 0x8259, 0xC593, 0x825A, 0xF4BD, + 0x825B, 0xC594, 0x825C, 0xC595, 0x825D, 0xC596, 0x825E, 0xC597, 0x825F, 0xF4BE, 0x8260, 0xC598, 0x8261, 0xC599, 0x8262, 0xC59A, + 0x8263, 0xC59B, 0x8264, 0xC59C, 0x8265, 0xC59D, 0x8266, 0xC59E, 0x8267, 0xC59F, 0x8268, 0xF4BF, 0x8269, 0xC5A0, 0x826A, 0xC640, + 0x826B, 0xC641, 0x826C, 0xC642, 0x826D, 0xC643, 0x826E, 0xF4DE, 0x826F, 0xC1BC, 0x8270, 0xBCE8, 0x8271, 0xC644, 0x8272, 0xC9AB, + 0x8273, 0xD1DE, 0x8274, 0xE5F5, 0x8275, 0xC645, 0x8276, 0xC646, 0x8277, 0xC647, 0x8278, 0xC648, 0x8279, 0xDCB3, 0x827A, 0xD2D5, + 0x827B, 0xC649, 0x827C, 0xC64A, 0x827D, 0xDCB4, 0x827E, 0xB0AC, 0x827F, 0xDCB5, 0x8280, 0xC64B, 0x8281, 0xC64C, 0x8282, 0xBDDA, + 0x8283, 0xC64D, 0x8284, 0xDCB9, 0x8285, 0xC64E, 0x8286, 0xC64F, 0x8287, 0xC650, 0x8288, 0xD8C2, 0x8289, 0xC651, 0x828A, 0xDCB7, + 0x828B, 0xD3F3, 0x828C, 0xC652, 0x828D, 0xC9D6, 0x828E, 0xDCBA, 0x828F, 0xDCB6, 0x8290, 0xC653, 0x8291, 0xDCBB, 0x8292, 0xC3A2, + 0x8293, 0xC654, 0x8294, 0xC655, 0x8295, 0xC656, 0x8296, 0xC657, 0x8297, 0xDCBC, 0x8298, 0xDCC5, 0x8299, 0xDCBD, 0x829A, 0xC658, + 0x829B, 0xC659, 0x829C, 0xCEDF, 0x829D, 0xD6A5, 0x829E, 0xC65A, 0x829F, 0xDCCF, 0x82A0, 0xC65B, 0x82A1, 0xDCCD, 0x82A2, 0xC65C, + 0x82A3, 0xC65D, 0x82A4, 0xDCD2, 0x82A5, 0xBDE6, 0x82A6, 0xC2AB, 0x82A7, 0xC65E, 0x82A8, 0xDCB8, 0x82A9, 0xDCCB, 0x82AA, 0xDCCE, + 0x82AB, 0xDCBE, 0x82AC, 0xB7D2, 0x82AD, 0xB0C5, 0x82AE, 0xDCC7, 0x82AF, 0xD0BE, 0x82B0, 0xDCC1, 0x82B1, 0xBBA8, 0x82B2, 0xC65F, + 0x82B3, 0xB7BC, 0x82B4, 0xDCCC, 0x82B5, 0xC660, 0x82B6, 0xC661, 0x82B7, 0xDCC6, 0x82B8, 0xDCBF, 0x82B9, 0xC7DB, 0x82BA, 0xC662, + 0x82BB, 0xC663, 0x82BC, 0xC664, 0x82BD, 0xD1BF, 0x82BE, 0xDCC0, 0x82BF, 0xC665, 0x82C0, 0xC666, 0x82C1, 0xDCCA, 0x82C2, 0xC667, + 0x82C3, 0xC668, 0x82C4, 0xDCD0, 0x82C5, 0xC669, 0x82C6, 0xC66A, 0x82C7, 0xCEAD, 0x82C8, 0xDCC2, 0x82C9, 0xC66B, 0x82CA, 0xDCC3, + 0x82CB, 0xDCC8, 0x82CC, 0xDCC9, 0x82CD, 0xB2D4, 0x82CE, 0xDCD1, 0x82CF, 0xCBD5, 0x82D0, 0xC66C, 0x82D1, 0xD4B7, 0x82D2, 0xDCDB, + 0x82D3, 0xDCDF, 0x82D4, 0xCCA6, 0x82D5, 0xDCE6, 0x82D6, 0xC66D, 0x82D7, 0xC3E7, 0x82D8, 0xDCDC, 0x82D9, 0xC66E, 0x82DA, 0xC66F, + 0x82DB, 0xBFC1, 0x82DC, 0xDCD9, 0x82DD, 0xC670, 0x82DE, 0xB0FA, 0x82DF, 0xB9B6, 0x82E0, 0xDCE5, 0x82E1, 0xDCD3, 0x82E2, 0xC671, + 0x82E3, 0xDCC4, 0x82E4, 0xDCD6, 0x82E5, 0xC8F4, 0x82E6, 0xBFE0, 0x82E7, 0xC672, 0x82E8, 0xC673, 0x82E9, 0xC674, 0x82EA, 0xC675, + 0x82EB, 0xC9BB, 0x82EC, 0xC676, 0x82ED, 0xC677, 0x82EE, 0xC678, 0x82EF, 0xB1BD, 0x82F0, 0xC679, 0x82F1, 0xD3A2, 0x82F2, 0xC67A, + 0x82F3, 0xC67B, 0x82F4, 0xDCDA, 0x82F5, 0xC67C, 0x82F6, 0xC67D, 0x82F7, 0xDCD5, 0x82F8, 0xC67E, 0x82F9, 0xC6BB, 0x82FA, 0xC680, + 0x82FB, 0xDCDE, 0x82FC, 0xC681, 0x82FD, 0xC682, 0x82FE, 0xC683, 0x82FF, 0xC684, 0x8300, 0xC685, 0x8301, 0xD7C2, 0x8302, 0xC3AF, + 0x8303, 0xB7B6, 0x8304, 0xC7D1, 0x8305, 0xC3A9, 0x8306, 0xDCE2, 0x8307, 0xDCD8, 0x8308, 0xDCEB, 0x8309, 0xDCD4, 0x830A, 0xC686, + 0x830B, 0xC687, 0x830C, 0xDCDD, 0x830D, 0xC688, 0x830E, 0xBEA5, 0x830F, 0xDCD7, 0x8310, 0xC689, 0x8311, 0xDCE0, 0x8312, 0xC68A, + 0x8313, 0xC68B, 0x8314, 0xDCE3, 0x8315, 0xDCE4, 0x8316, 0xC68C, 0x8317, 0xDCF8, 0x8318, 0xC68D, 0x8319, 0xC68E, 0x831A, 0xDCE1, + 0x831B, 0xDDA2, 0x831C, 0xDCE7, 0x831D, 0xC68F, 0x831E, 0xC690, 0x831F, 0xC691, 0x8320, 0xC692, 0x8321, 0xC693, 0x8322, 0xC694, + 0x8323, 0xC695, 0x8324, 0xC696, 0x8325, 0xC697, 0x8326, 0xC698, 0x8327, 0xBCEB, 0x8328, 0xB4C4, 0x8329, 0xC699, 0x832A, 0xC69A, + 0x832B, 0xC3A3, 0x832C, 0xB2E7, 0x832D, 0xDCFA, 0x832E, 0xC69B, 0x832F, 0xDCF2, 0x8330, 0xC69C, 0x8331, 0xDCEF, 0x8332, 0xC69D, + 0x8333, 0xDCFC, 0x8334, 0xDCEE, 0x8335, 0xD2F0, 0x8336, 0xB2E8, 0x8337, 0xC69E, 0x8338, 0xC8D7, 0x8339, 0xC8E3, 0x833A, 0xDCFB, + 0x833B, 0xC69F, 0x833C, 0xDCED, 0x833D, 0xC6A0, 0x833E, 0xC740, 0x833F, 0xC741, 0x8340, 0xDCF7, 0x8341, 0xC742, 0x8342, 0xC743, + 0x8343, 0xDCF5, 0x8344, 0xC744, 0x8345, 0xC745, 0x8346, 0xBEA3, 0x8347, 0xDCF4, 0x8348, 0xC746, 0x8349, 0xB2DD, 0x834A, 0xC747, + 0x834B, 0xC748, 0x834C, 0xC749, 0x834D, 0xC74A, 0x834E, 0xC74B, 0x834F, 0xDCF3, 0x8350, 0xBCF6, 0x8351, 0xDCE8, 0x8352, 0xBBC4, + 0x8353, 0xC74C, 0x8354, 0xC0F3, 0x8355, 0xC74D, 0x8356, 0xC74E, 0x8357, 0xC74F, 0x8358, 0xC750, 0x8359, 0xC751, 0x835A, 0xBCD4, + 0x835B, 0xDCE9, 0x835C, 0xDCEA, 0x835D, 0xC752, 0x835E, 0xDCF1, 0x835F, 0xDCF6, 0x8360, 0xDCF9, 0x8361, 0xB5B4, 0x8362, 0xC753, + 0x8363, 0xC8D9, 0x8364, 0xBBE7, 0x8365, 0xDCFE, 0x8366, 0xDCFD, 0x8367, 0xD3AB, 0x8368, 0xDDA1, 0x8369, 0xDDA3, 0x836A, 0xDDA5, + 0x836B, 0xD2F1, 0x836C, 0xDDA4, 0x836D, 0xDDA6, 0x836E, 0xDDA7, 0x836F, 0xD2A9, 0x8370, 0xC754, 0x8371, 0xC755, 0x8372, 0xC756, + 0x8373, 0xC757, 0x8374, 0xC758, 0x8375, 0xC759, 0x8376, 0xC75A, 0x8377, 0xBAC9, 0x8378, 0xDDA9, 0x8379, 0xC75B, 0x837A, 0xC75C, + 0x837B, 0xDDB6, 0x837C, 0xDDB1, 0x837D, 0xDDB4, 0x837E, 0xC75D, 0x837F, 0xC75E, 0x8380, 0xC75F, 0x8381, 0xC760, 0x8382, 0xC761, + 0x8383, 0xC762, 0x8384, 0xC763, 0x8385, 0xDDB0, 0x8386, 0xC6CE, 0x8387, 0xC764, 0x8388, 0xC765, 0x8389, 0xC0F2, 0x838A, 0xC766, + 0x838B, 0xC767, 0x838C, 0xC768, 0x838D, 0xC769, 0x838E, 0xC9AF, 0x838F, 0xC76A, 0x8390, 0xC76B, 0x8391, 0xC76C, 0x8392, 0xDCEC, + 0x8393, 0xDDAE, 0x8394, 0xC76D, 0x8395, 0xC76E, 0x8396, 0xC76F, 0x8397, 0xC770, 0x8398, 0xDDB7, 0x8399, 0xC771, 0x839A, 0xC772, + 0x839B, 0xDCF0, 0x839C, 0xDDAF, 0x839D, 0xC773, 0x839E, 0xDDB8, 0x839F, 0xC774, 0x83A0, 0xDDAC, 0x83A1, 0xC775, 0x83A2, 0xC776, + 0x83A3, 0xC777, 0x83A4, 0xC778, 0x83A5, 0xC779, 0x83A6, 0xC77A, 0x83A7, 0xC77B, 0x83A8, 0xDDB9, 0x83A9, 0xDDB3, 0x83AA, 0xDDAD, + 0x83AB, 0xC4AA, 0x83AC, 0xC77C, 0x83AD, 0xC77D, 0x83AE, 0xC77E, 0x83AF, 0xC780, 0x83B0, 0xDDA8, 0x83B1, 0xC0B3, 0x83B2, 0xC1AB, + 0x83B3, 0xDDAA, 0x83B4, 0xDDAB, 0x83B5, 0xC781, 0x83B6, 0xDDB2, 0x83B7, 0xBBF1, 0x83B8, 0xDDB5, 0x83B9, 0xD3A8, 0x83BA, 0xDDBA, + 0x83BB, 0xC782, 0x83BC, 0xDDBB, 0x83BD, 0xC3A7, 0x83BE, 0xC783, 0x83BF, 0xC784, 0x83C0, 0xDDD2, 0x83C1, 0xDDBC, 0x83C2, 0xC785, + 0x83C3, 0xC786, 0x83C4, 0xC787, 0x83C5, 0xDDD1, 0x83C6, 0xC788, 0x83C7, 0xB9BD, 0x83C8, 0xC789, 0x83C9, 0xC78A, 0x83CA, 0xBED5, + 0x83CB, 0xC78B, 0x83CC, 0xBEFA, 0x83CD, 0xC78C, 0x83CE, 0xC78D, 0x83CF, 0xBACA, 0x83D0, 0xC78E, 0x83D1, 0xC78F, 0x83D2, 0xC790, + 0x83D3, 0xC791, 0x83D4, 0xDDCA, 0x83D5, 0xC792, 0x83D6, 0xDDC5, 0x83D7, 0xC793, 0x83D8, 0xDDBF, 0x83D9, 0xC794, 0x83DA, 0xC795, + 0x83DB, 0xC796, 0x83DC, 0xB2CB, 0x83DD, 0xDDC3, 0x83DE, 0xC797, 0x83DF, 0xDDCB, 0x83E0, 0xB2A4, 0x83E1, 0xDDD5, 0x83E2, 0xC798, + 0x83E3, 0xC799, 0x83E4, 0xC79A, 0x83E5, 0xDDBE, 0x83E6, 0xC79B, 0x83E7, 0xC79C, 0x83E8, 0xC79D, 0x83E9, 0xC6D0, 0x83EA, 0xDDD0, + 0x83EB, 0xC79E, 0x83EC, 0xC79F, 0x83ED, 0xC7A0, 0x83EE, 0xC840, 0x83EF, 0xC841, 0x83F0, 0xDDD4, 0x83F1, 0xC1E2, 0x83F2, 0xB7C6, + 0x83F3, 0xC842, 0x83F4, 0xC843, 0x83F5, 0xC844, 0x83F6, 0xC845, 0x83F7, 0xC846, 0x83F8, 0xDDCE, 0x83F9, 0xDDCF, 0x83FA, 0xC847, + 0x83FB, 0xC848, 0x83FC, 0xC849, 0x83FD, 0xDDC4, 0x83FE, 0xC84A, 0x83FF, 0xC84B, 0x8400, 0xC84C, 0x8401, 0xDDBD, 0x8402, 0xC84D, + 0x8403, 0xDDCD, 0x8404, 0xCCD1, 0x8405, 0xC84E, 0x8406, 0xDDC9, 0x8407, 0xC84F, 0x8408, 0xC850, 0x8409, 0xC851, 0x840A, 0xC852, + 0x840B, 0xDDC2, 0x840C, 0xC3C8, 0x840D, 0xC6BC, 0x840E, 0xCEAE, 0x840F, 0xDDCC, 0x8410, 0xC853, 0x8411, 0xDDC8, 0x8412, 0xC854, + 0x8413, 0xC855, 0x8414, 0xC856, 0x8415, 0xC857, 0x8416, 0xC858, 0x8417, 0xC859, 0x8418, 0xDDC1, 0x8419, 0xC85A, 0x841A, 0xC85B, + 0x841B, 0xC85C, 0x841C, 0xDDC6, 0x841D, 0xC2DC, 0x841E, 0xC85D, 0x841F, 0xC85E, 0x8420, 0xC85F, 0x8421, 0xC860, 0x8422, 0xC861, + 0x8423, 0xC862, 0x8424, 0xD3A9, 0x8425, 0xD3AA, 0x8426, 0xDDD3, 0x8427, 0xCFF4, 0x8428, 0xC8F8, 0x8429, 0xC863, 0x842A, 0xC864, + 0x842B, 0xC865, 0x842C, 0xC866, 0x842D, 0xC867, 0x842E, 0xC868, 0x842F, 0xC869, 0x8430, 0xC86A, 0x8431, 0xDDE6, 0x8432, 0xC86B, + 0x8433, 0xC86C, 0x8434, 0xC86D, 0x8435, 0xC86E, 0x8436, 0xC86F, 0x8437, 0xC870, 0x8438, 0xDDC7, 0x8439, 0xC871, 0x843A, 0xC872, + 0x843B, 0xC873, 0x843C, 0xDDE0, 0x843D, 0xC2E4, 0x843E, 0xC874, 0x843F, 0xC875, 0x8440, 0xC876, 0x8441, 0xC877, 0x8442, 0xC878, + 0x8443, 0xC879, 0x8444, 0xC87A, 0x8445, 0xC87B, 0x8446, 0xDDE1, 0x8447, 0xC87C, 0x8448, 0xC87D, 0x8449, 0xC87E, 0x844A, 0xC880, + 0x844B, 0xC881, 0x844C, 0xC882, 0x844D, 0xC883, 0x844E, 0xC884, 0x844F, 0xC885, 0x8450, 0xC886, 0x8451, 0xDDD7, 0x8452, 0xC887, + 0x8453, 0xC888, 0x8454, 0xC889, 0x8455, 0xC88A, 0x8456, 0xC88B, 0x8457, 0xD6F8, 0x8458, 0xC88C, 0x8459, 0xDDD9, 0x845A, 0xDDD8, + 0x845B, 0xB8F0, 0x845C, 0xDDD6, 0x845D, 0xC88D, 0x845E, 0xC88E, 0x845F, 0xC88F, 0x8460, 0xC890, 0x8461, 0xC6CF, 0x8462, 0xC891, + 0x8463, 0xB6AD, 0x8464, 0xC892, 0x8465, 0xC893, 0x8466, 0xC894, 0x8467, 0xC895, 0x8468, 0xC896, 0x8469, 0xDDE2, 0x846A, 0xC897, + 0x846B, 0xBAF9, 0x846C, 0xD4E1, 0x846D, 0xDDE7, 0x846E, 0xC898, 0x846F, 0xC899, 0x8470, 0xC89A, 0x8471, 0xB4D0, 0x8472, 0xC89B, + 0x8473, 0xDDDA, 0x8474, 0xC89C, 0x8475, 0xBFFB, 0x8476, 0xDDE3, 0x8477, 0xC89D, 0x8478, 0xDDDF, 0x8479, 0xC89E, 0x847A, 0xDDDD, + 0x847B, 0xC89F, 0x847C, 0xC8A0, 0x847D, 0xC940, 0x847E, 0xC941, 0x847F, 0xC942, 0x8480, 0xC943, 0x8481, 0xC944, 0x8482, 0xB5D9, + 0x8483, 0xC945, 0x8484, 0xC946, 0x8485, 0xC947, 0x8486, 0xC948, 0x8487, 0xDDDB, 0x8488, 0xDDDC, 0x8489, 0xDDDE, 0x848A, 0xC949, + 0x848B, 0xBDAF, 0x848C, 0xDDE4, 0x848D, 0xC94A, 0x848E, 0xDDE5, 0x848F, 0xC94B, 0x8490, 0xC94C, 0x8491, 0xC94D, 0x8492, 0xC94E, + 0x8493, 0xC94F, 0x8494, 0xC950, 0x8495, 0xC951, 0x8496, 0xC952, 0x8497, 0xDDF5, 0x8498, 0xC953, 0x8499, 0xC3C9, 0x849A, 0xC954, + 0x849B, 0xC955, 0x849C, 0xCBE2, 0x849D, 0xC956, 0x849E, 0xC957, 0x849F, 0xC958, 0x84A0, 0xC959, 0x84A1, 0xDDF2, 0x84A2, 0xC95A, + 0x84A3, 0xC95B, 0x84A4, 0xC95C, 0x84A5, 0xC95D, 0x84A6, 0xC95E, 0x84A7, 0xC95F, 0x84A8, 0xC960, 0x84A9, 0xC961, 0x84AA, 0xC962, + 0x84AB, 0xC963, 0x84AC, 0xC964, 0x84AD, 0xC965, 0x84AE, 0xC966, 0x84AF, 0xD8E1, 0x84B0, 0xC967, 0x84B1, 0xC968, 0x84B2, 0xC6D1, + 0x84B3, 0xC969, 0x84B4, 0xDDF4, 0x84B5, 0xC96A, 0x84B6, 0xC96B, 0x84B7, 0xC96C, 0x84B8, 0xD5F4, 0x84B9, 0xDDF3, 0x84BA, 0xDDF0, + 0x84BB, 0xC96D, 0x84BC, 0xC96E, 0x84BD, 0xDDEC, 0x84BE, 0xC96F, 0x84BF, 0xDDEF, 0x84C0, 0xC970, 0x84C1, 0xDDE8, 0x84C2, 0xC971, + 0x84C3, 0xC972, 0x84C4, 0xD0EE, 0x84C5, 0xC973, 0x84C6, 0xC974, 0x84C7, 0xC975, 0x84C8, 0xC976, 0x84C9, 0xC8D8, 0x84CA, 0xDDEE, + 0x84CB, 0xC977, 0x84CC, 0xC978, 0x84CD, 0xDDE9, 0x84CE, 0xC979, 0x84CF, 0xC97A, 0x84D0, 0xDDEA, 0x84D1, 0xCBF2, 0x84D2, 0xC97B, + 0x84D3, 0xDDED, 0x84D4, 0xC97C, 0x84D5, 0xC97D, 0x84D6, 0xB1CD, 0x84D7, 0xC97E, 0x84D8, 0xC980, 0x84D9, 0xC981, 0x84DA, 0xC982, + 0x84DB, 0xC983, 0x84DC, 0xC984, 0x84DD, 0xC0B6, 0x84DE, 0xC985, 0x84DF, 0xBCBB, 0x84E0, 0xDDF1, 0x84E1, 0xC986, 0x84E2, 0xC987, + 0x84E3, 0xDDF7, 0x84E4, 0xC988, 0x84E5, 0xDDF6, 0x84E6, 0xDDEB, 0x84E7, 0xC989, 0x84E8, 0xC98A, 0x84E9, 0xC98B, 0x84EA, 0xC98C, + 0x84EB, 0xC98D, 0x84EC, 0xC5EE, 0x84ED, 0xC98E, 0x84EE, 0xC98F, 0x84EF, 0xC990, 0x84F0, 0xDDFB, 0x84F1, 0xC991, 0x84F2, 0xC992, + 0x84F3, 0xC993, 0x84F4, 0xC994, 0x84F5, 0xC995, 0x84F6, 0xC996, 0x84F7, 0xC997, 0x84F8, 0xC998, 0x84F9, 0xC999, 0x84FA, 0xC99A, + 0x84FB, 0xC99B, 0x84FC, 0xDEA4, 0x84FD, 0xC99C, 0x84FE, 0xC99D, 0x84FF, 0xDEA3, 0x8500, 0xC99E, 0x8501, 0xC99F, 0x8502, 0xC9A0, + 0x8503, 0xCA40, 0x8504, 0xCA41, 0x8505, 0xCA42, 0x8506, 0xCA43, 0x8507, 0xCA44, 0x8508, 0xCA45, 0x8509, 0xCA46, 0x850A, 0xCA47, + 0x850B, 0xCA48, 0x850C, 0xDDF8, 0x850D, 0xCA49, 0x850E, 0xCA4A, 0x850F, 0xCA4B, 0x8510, 0xCA4C, 0x8511, 0xC3EF, 0x8512, 0xCA4D, + 0x8513, 0xC2FB, 0x8514, 0xCA4E, 0x8515, 0xCA4F, 0x8516, 0xCA50, 0x8517, 0xD5E1, 0x8518, 0xCA51, 0x8519, 0xCA52, 0x851A, 0xCEB5, + 0x851B, 0xCA53, 0x851C, 0xCA54, 0x851D, 0xCA55, 0x851E, 0xCA56, 0x851F, 0xDDFD, 0x8520, 0xCA57, 0x8521, 0xB2CC, 0x8522, 0xCA58, + 0x8523, 0xCA59, 0x8524, 0xCA5A, 0x8525, 0xCA5B, 0x8526, 0xCA5C, 0x8527, 0xCA5D, 0x8528, 0xCA5E, 0x8529, 0xCA5F, 0x852A, 0xCA60, + 0x852B, 0xC4E8, 0x852C, 0xCADF, 0x852D, 0xCA61, 0x852E, 0xCA62, 0x852F, 0xCA63, 0x8530, 0xCA64, 0x8531, 0xCA65, 0x8532, 0xCA66, + 0x8533, 0xCA67, 0x8534, 0xCA68, 0x8535, 0xCA69, 0x8536, 0xCA6A, 0x8537, 0xC7BE, 0x8538, 0xDDFA, 0x8539, 0xDDFC, 0x853A, 0xDDFE, + 0x853B, 0xDEA2, 0x853C, 0xB0AA, 0x853D, 0xB1CE, 0x853E, 0xCA6B, 0x853F, 0xCA6C, 0x8540, 0xCA6D, 0x8541, 0xCA6E, 0x8542, 0xCA6F, + 0x8543, 0xDEAC, 0x8544, 0xCA70, 0x8545, 0xCA71, 0x8546, 0xCA72, 0x8547, 0xCA73, 0x8548, 0xDEA6, 0x8549, 0xBDB6, 0x854A, 0xC8EF, + 0x854B, 0xCA74, 0x854C, 0xCA75, 0x854D, 0xCA76, 0x854E, 0xCA77, 0x854F, 0xCA78, 0x8550, 0xCA79, 0x8551, 0xCA7A, 0x8552, 0xCA7B, + 0x8553, 0xCA7C, 0x8554, 0xCA7D, 0x8555, 0xCA7E, 0x8556, 0xDEA1, 0x8557, 0xCA80, 0x8558, 0xCA81, 0x8559, 0xDEA5, 0x855A, 0xCA82, + 0x855B, 0xCA83, 0x855C, 0xCA84, 0x855D, 0xCA85, 0x855E, 0xDEA9, 0x855F, 0xCA86, 0x8560, 0xCA87, 0x8561, 0xCA88, 0x8562, 0xCA89, + 0x8563, 0xCA8A, 0x8564, 0xDEA8, 0x8565, 0xCA8B, 0x8566, 0xCA8C, 0x8567, 0xCA8D, 0x8568, 0xDEA7, 0x8569, 0xCA8E, 0x856A, 0xCA8F, + 0x856B, 0xCA90, 0x856C, 0xCA91, 0x856D, 0xCA92, 0x856E, 0xCA93, 0x856F, 0xCA94, 0x8570, 0xCA95, 0x8571, 0xCA96, 0x8572, 0xDEAD, + 0x8573, 0xCA97, 0x8574, 0xD4CC, 0x8575, 0xCA98, 0x8576, 0xCA99, 0x8577, 0xCA9A, 0x8578, 0xCA9B, 0x8579, 0xDEB3, 0x857A, 0xDEAA, + 0x857B, 0xDEAE, 0x857C, 0xCA9C, 0x857D, 0xCA9D, 0x857E, 0xC0D9, 0x857F, 0xCA9E, 0x8580, 0xCA9F, 0x8581, 0xCAA0, 0x8582, 0xCB40, + 0x8583, 0xCB41, 0x8584, 0xB1A1, 0x8585, 0xDEB6, 0x8586, 0xCB42, 0x8587, 0xDEB1, 0x8588, 0xCB43, 0x8589, 0xCB44, 0x858A, 0xCB45, + 0x858B, 0xCB46, 0x858C, 0xCB47, 0x858D, 0xCB48, 0x858E, 0xCB49, 0x858F, 0xDEB2, 0x8590, 0xCB4A, 0x8591, 0xCB4B, 0x8592, 0xCB4C, + 0x8593, 0xCB4D, 0x8594, 0xCB4E, 0x8595, 0xCB4F, 0x8596, 0xCB50, 0x8597, 0xCB51, 0x8598, 0xCB52, 0x8599, 0xCB53, 0x859A, 0xCB54, + 0x859B, 0xD1A6, 0x859C, 0xDEB5, 0x859D, 0xCB55, 0x859E, 0xCB56, 0x859F, 0xCB57, 0x85A0, 0xCB58, 0x85A1, 0xCB59, 0x85A2, 0xCB5A, + 0x85A3, 0xCB5B, 0x85A4, 0xDEAF, 0x85A5, 0xCB5C, 0x85A6, 0xCB5D, 0x85A7, 0xCB5E, 0x85A8, 0xDEB0, 0x85A9, 0xCB5F, 0x85AA, 0xD0BD, + 0x85AB, 0xCB60, 0x85AC, 0xCB61, 0x85AD, 0xCB62, 0x85AE, 0xDEB4, 0x85AF, 0xCAED, 0x85B0, 0xDEB9, 0x85B1, 0xCB63, 0x85B2, 0xCB64, + 0x85B3, 0xCB65, 0x85B4, 0xCB66, 0x85B5, 0xCB67, 0x85B6, 0xCB68, 0x85B7, 0xDEB8, 0x85B8, 0xCB69, 0x85B9, 0xDEB7, 0x85BA, 0xCB6A, + 0x85BB, 0xCB6B, 0x85BC, 0xCB6C, 0x85BD, 0xCB6D, 0x85BE, 0xCB6E, 0x85BF, 0xCB6F, 0x85C0, 0xCB70, 0x85C1, 0xDEBB, 0x85C2, 0xCB71, + 0x85C3, 0xCB72, 0x85C4, 0xCB73, 0x85C5, 0xCB74, 0x85C6, 0xCB75, 0x85C7, 0xCB76, 0x85C8, 0xCB77, 0x85C9, 0xBDE5, 0x85CA, 0xCB78, + 0x85CB, 0xCB79, 0x85CC, 0xCB7A, 0x85CD, 0xCB7B, 0x85CE, 0xCB7C, 0x85CF, 0xB2D8, 0x85D0, 0xC3EA, 0x85D1, 0xCB7D, 0x85D2, 0xCB7E, + 0x85D3, 0xDEBA, 0x85D4, 0xCB80, 0x85D5, 0xC5BA, 0x85D6, 0xCB81, 0x85D7, 0xCB82, 0x85D8, 0xCB83, 0x85D9, 0xCB84, 0x85DA, 0xCB85, + 0x85DB, 0xCB86, 0x85DC, 0xDEBC, 0x85DD, 0xCB87, 0x85DE, 0xCB88, 0x85DF, 0xCB89, 0x85E0, 0xCB8A, 0x85E1, 0xCB8B, 0x85E2, 0xCB8C, + 0x85E3, 0xCB8D, 0x85E4, 0xCCD9, 0x85E5, 0xCB8E, 0x85E6, 0xCB8F, 0x85E7, 0xCB90, 0x85E8, 0xCB91, 0x85E9, 0xB7AA, 0x85EA, 0xCB92, + 0x85EB, 0xCB93, 0x85EC, 0xCB94, 0x85ED, 0xCB95, 0x85EE, 0xCB96, 0x85EF, 0xCB97, 0x85F0, 0xCB98, 0x85F1, 0xCB99, 0x85F2, 0xCB9A, + 0x85F3, 0xCB9B, 0x85F4, 0xCB9C, 0x85F5, 0xCB9D, 0x85F6, 0xCB9E, 0x85F7, 0xCB9F, 0x85F8, 0xCBA0, 0x85F9, 0xCC40, 0x85FA, 0xCC41, + 0x85FB, 0xD4E5, 0x85FC, 0xCC42, 0x85FD, 0xCC43, 0x85FE, 0xCC44, 0x85FF, 0xDEBD, 0x8600, 0xCC45, 0x8601, 0xCC46, 0x8602, 0xCC47, + 0x8603, 0xCC48, 0x8604, 0xCC49, 0x8605, 0xDEBF, 0x8606, 0xCC4A, 0x8607, 0xCC4B, 0x8608, 0xCC4C, 0x8609, 0xCC4D, 0x860A, 0xCC4E, + 0x860B, 0xCC4F, 0x860C, 0xCC50, 0x860D, 0xCC51, 0x860E, 0xCC52, 0x860F, 0xCC53, 0x8610, 0xCC54, 0x8611, 0xC4A2, 0x8612, 0xCC55, + 0x8613, 0xCC56, 0x8614, 0xCC57, 0x8615, 0xCC58, 0x8616, 0xDEC1, 0x8617, 0xCC59, 0x8618, 0xCC5A, 0x8619, 0xCC5B, 0x861A, 0xCC5C, + 0x861B, 0xCC5D, 0x861C, 0xCC5E, 0x861D, 0xCC5F, 0x861E, 0xCC60, 0x861F, 0xCC61, 0x8620, 0xCC62, 0x8621, 0xCC63, 0x8622, 0xCC64, + 0x8623, 0xCC65, 0x8624, 0xCC66, 0x8625, 0xCC67, 0x8626, 0xCC68, 0x8627, 0xDEBE, 0x8628, 0xCC69, 0x8629, 0xDEC0, 0x862A, 0xCC6A, + 0x862B, 0xCC6B, 0x862C, 0xCC6C, 0x862D, 0xCC6D, 0x862E, 0xCC6E, 0x862F, 0xCC6F, 0x8630, 0xCC70, 0x8631, 0xCC71, 0x8632, 0xCC72, + 0x8633, 0xCC73, 0x8634, 0xCC74, 0x8635, 0xCC75, 0x8636, 0xCC76, 0x8637, 0xCC77, 0x8638, 0xD5BA, 0x8639, 0xCC78, 0x863A, 0xCC79, + 0x863B, 0xCC7A, 0x863C, 0xDEC2, 0x863D, 0xCC7B, 0x863E, 0xCC7C, 0x863F, 0xCC7D, 0x8640, 0xCC7E, 0x8641, 0xCC80, 0x8642, 0xCC81, + 0x8643, 0xCC82, 0x8644, 0xCC83, 0x8645, 0xCC84, 0x8646, 0xCC85, 0x8647, 0xCC86, 0x8648, 0xCC87, 0x8649, 0xCC88, 0x864A, 0xCC89, + 0x864B, 0xCC8A, 0x864C, 0xCC8B, 0x864D, 0xF2AE, 0x864E, 0xBBA2, 0x864F, 0xC2B2, 0x8650, 0xC5B0, 0x8651, 0xC2C7, 0x8652, 0xCC8C, + 0x8653, 0xCC8D, 0x8654, 0xF2AF, 0x8655, 0xCC8E, 0x8656, 0xCC8F, 0x8657, 0xCC90, 0x8658, 0xCC91, 0x8659, 0xCC92, 0x865A, 0xD0E9, + 0x865B, 0xCC93, 0x865C, 0xCC94, 0x865D, 0xCC95, 0x865E, 0xD3DD, 0x865F, 0xCC96, 0x8660, 0xCC97, 0x8661, 0xCC98, 0x8662, 0xEBBD, + 0x8663, 0xCC99, 0x8664, 0xCC9A, 0x8665, 0xCC9B, 0x8666, 0xCC9C, 0x8667, 0xCC9D, 0x8668, 0xCC9E, 0x8669, 0xCC9F, 0x866A, 0xCCA0, + 0x866B, 0xB3E6, 0x866C, 0xF2B0, 0x866D, 0xCD40, 0x866E, 0xF2B1, 0x866F, 0xCD41, 0x8670, 0xCD42, 0x8671, 0xCAAD, 0x8672, 0xCD43, + 0x8673, 0xCD44, 0x8674, 0xCD45, 0x8675, 0xCD46, 0x8676, 0xCD47, 0x8677, 0xCD48, 0x8678, 0xCD49, 0x8679, 0xBAE7, 0x867A, 0xF2B3, + 0x867B, 0xF2B5, 0x867C, 0xF2B4, 0x867D, 0xCBE4, 0x867E, 0xCFBA, 0x867F, 0xF2B2, 0x8680, 0xCAB4, 0x8681, 0xD2CF, 0x8682, 0xC2EC, + 0x8683, 0xCD4A, 0x8684, 0xCD4B, 0x8685, 0xCD4C, 0x8686, 0xCD4D, 0x8687, 0xCD4E, 0x8688, 0xCD4F, 0x8689, 0xCD50, 0x868A, 0xCEC3, + 0x868B, 0xF2B8, 0x868C, 0xB0F6, 0x868D, 0xF2B7, 0x868E, 0xCD51, 0x868F, 0xCD52, 0x8690, 0xCD53, 0x8691, 0xCD54, 0x8692, 0xCD55, + 0x8693, 0xF2BE, 0x8694, 0xCD56, 0x8695, 0xB2CF, 0x8696, 0xCD57, 0x8697, 0xCD58, 0x8698, 0xCD59, 0x8699, 0xCD5A, 0x869A, 0xCD5B, + 0x869B, 0xCD5C, 0x869C, 0xD1C1, 0x869D, 0xF2BA, 0x869E, 0xCD5D, 0x869F, 0xCD5E, 0x86A0, 0xCD5F, 0x86A1, 0xCD60, 0x86A2, 0xCD61, + 0x86A3, 0xF2BC, 0x86A4, 0xD4E9, 0x86A5, 0xCD62, 0x86A6, 0xCD63, 0x86A7, 0xF2BB, 0x86A8, 0xF2B6, 0x86A9, 0xF2BF, 0x86AA, 0xF2BD, + 0x86AB, 0xCD64, 0x86AC, 0xF2B9, 0x86AD, 0xCD65, 0x86AE, 0xCD66, 0x86AF, 0xF2C7, 0x86B0, 0xF2C4, 0x86B1, 0xF2C6, 0x86B2, 0xCD67, + 0x86B3, 0xCD68, 0x86B4, 0xF2CA, 0x86B5, 0xF2C2, 0x86B6, 0xF2C0, 0x86B7, 0xCD69, 0x86B8, 0xCD6A, 0x86B9, 0xCD6B, 0x86BA, 0xF2C5, + 0x86BB, 0xCD6C, 0x86BC, 0xCD6D, 0x86BD, 0xCD6E, 0x86BE, 0xCD6F, 0x86BF, 0xCD70, 0x86C0, 0xD6FB, 0x86C1, 0xCD71, 0x86C2, 0xCD72, + 0x86C3, 0xCD73, 0x86C4, 0xF2C1, 0x86C5, 0xCD74, 0x86C6, 0xC7F9, 0x86C7, 0xC9DF, 0x86C8, 0xCD75, 0x86C9, 0xF2C8, 0x86CA, 0xB9C6, + 0x86CB, 0xB5B0, 0x86CC, 0xCD76, 0x86CD, 0xCD77, 0x86CE, 0xF2C3, 0x86CF, 0xF2C9, 0x86D0, 0xF2D0, 0x86D1, 0xF2D6, 0x86D2, 0xCD78, + 0x86D3, 0xCD79, 0x86D4, 0xBBD7, 0x86D5, 0xCD7A, 0x86D6, 0xCD7B, 0x86D7, 0xCD7C, 0x86D8, 0xF2D5, 0x86D9, 0xCDDC, 0x86DA, 0xCD7D, + 0x86DB, 0xD6EB, 0x86DC, 0xCD7E, 0x86DD, 0xCD80, 0x86DE, 0xF2D2, 0x86DF, 0xF2D4, 0x86E0, 0xCD81, 0x86E1, 0xCD82, 0x86E2, 0xCD83, + 0x86E3, 0xCD84, 0x86E4, 0xB8F2, 0x86E5, 0xCD85, 0x86E6, 0xCD86, 0x86E7, 0xCD87, 0x86E8, 0xCD88, 0x86E9, 0xF2CB, 0x86EA, 0xCD89, + 0x86EB, 0xCD8A, 0x86EC, 0xCD8B, 0x86ED, 0xF2CE, 0x86EE, 0xC2F9, 0x86EF, 0xCD8C, 0x86F0, 0xD5DD, 0x86F1, 0xF2CC, 0x86F2, 0xF2CD, + 0x86F3, 0xF2CF, 0x86F4, 0xF2D3, 0x86F5, 0xCD8D, 0x86F6, 0xCD8E, 0x86F7, 0xCD8F, 0x86F8, 0xF2D9, 0x86F9, 0xD3BC, 0x86FA, 0xCD90, + 0x86FB, 0xCD91, 0x86FC, 0xCD92, 0x86FD, 0xCD93, 0x86FE, 0xB6EA, 0x86FF, 0xCD94, 0x8700, 0xCAF1, 0x8701, 0xCD95, 0x8702, 0xB7E4, + 0x8703, 0xF2D7, 0x8704, 0xCD96, 0x8705, 0xCD97, 0x8706, 0xCD98, 0x8707, 0xF2D8, 0x8708, 0xF2DA, 0x8709, 0xF2DD, 0x870A, 0xF2DB, + 0x870B, 0xCD99, 0x870C, 0xCD9A, 0x870D, 0xF2DC, 0x870E, 0xCD9B, 0x870F, 0xCD9C, 0x8710, 0xCD9D, 0x8711, 0xCD9E, 0x8712, 0xD1D1, + 0x8713, 0xF2D1, 0x8714, 0xCD9F, 0x8715, 0xCDC9, 0x8716, 0xCDA0, 0x8717, 0xCECF, 0x8718, 0xD6A9, 0x8719, 0xCE40, 0x871A, 0xF2E3, + 0x871B, 0xCE41, 0x871C, 0xC3DB, 0x871D, 0xCE42, 0x871E, 0xF2E0, 0x871F, 0xCE43, 0x8720, 0xCE44, 0x8721, 0xC0AF, 0x8722, 0xF2EC, + 0x8723, 0xF2DE, 0x8724, 0xCE45, 0x8725, 0xF2E1, 0x8726, 0xCE46, 0x8727, 0xCE47, 0x8728, 0xCE48, 0x8729, 0xF2E8, 0x872A, 0xCE49, + 0x872B, 0xCE4A, 0x872C, 0xCE4B, 0x872D, 0xCE4C, 0x872E, 0xF2E2, 0x872F, 0xCE4D, 0x8730, 0xCE4E, 0x8731, 0xF2E7, 0x8732, 0xCE4F, + 0x8733, 0xCE50, 0x8734, 0xF2E6, 0x8735, 0xCE51, 0x8736, 0xCE52, 0x8737, 0xF2E9, 0x8738, 0xCE53, 0x8739, 0xCE54, 0x873A, 0xCE55, + 0x873B, 0xF2DF, 0x873C, 0xCE56, 0x873D, 0xCE57, 0x873E, 0xF2E4, 0x873F, 0xF2EA, 0x8740, 0xCE58, 0x8741, 0xCE59, 0x8742, 0xCE5A, + 0x8743, 0xCE5B, 0x8744, 0xCE5C, 0x8745, 0xCE5D, 0x8746, 0xCE5E, 0x8747, 0xD3AC, 0x8748, 0xF2E5, 0x8749, 0xB2F5, 0x874A, 0xCE5F, + 0x874B, 0xCE60, 0x874C, 0xF2F2, 0x874D, 0xCE61, 0x874E, 0xD0AB, 0x874F, 0xCE62, 0x8750, 0xCE63, 0x8751, 0xCE64, 0x8752, 0xCE65, + 0x8753, 0xF2F5, 0x8754, 0xCE66, 0x8755, 0xCE67, 0x8756, 0xCE68, 0x8757, 0xBBC8, 0x8758, 0xCE69, 0x8759, 0xF2F9, 0x875A, 0xCE6A, + 0x875B, 0xCE6B, 0x875C, 0xCE6C, 0x875D, 0xCE6D, 0x875E, 0xCE6E, 0x875F, 0xCE6F, 0x8760, 0xF2F0, 0x8761, 0xCE70, 0x8762, 0xCE71, + 0x8763, 0xF2F6, 0x8764, 0xF2F8, 0x8765, 0xF2FA, 0x8766, 0xCE72, 0x8767, 0xCE73, 0x8768, 0xCE74, 0x8769, 0xCE75, 0x876A, 0xCE76, + 0x876B, 0xCE77, 0x876C, 0xCE78, 0x876D, 0xCE79, 0x876E, 0xF2F3, 0x876F, 0xCE7A, 0x8770, 0xF2F1, 0x8771, 0xCE7B, 0x8772, 0xCE7C, + 0x8773, 0xCE7D, 0x8774, 0xBAFB, 0x8775, 0xCE7E, 0x8776, 0xB5FB, 0x8777, 0xCE80, 0x8778, 0xCE81, 0x8779, 0xCE82, 0x877A, 0xCE83, + 0x877B, 0xF2EF, 0x877C, 0xF2F7, 0x877D, 0xF2ED, 0x877E, 0xF2EE, 0x877F, 0xCE84, 0x8780, 0xCE85, 0x8781, 0xCE86, 0x8782, 0xF2EB, + 0x8783, 0xF3A6, 0x8784, 0xCE87, 0x8785, 0xF3A3, 0x8786, 0xCE88, 0x8787, 0xCE89, 0x8788, 0xF3A2, 0x8789, 0xCE8A, 0x878A, 0xCE8B, + 0x878B, 0xF2F4, 0x878C, 0xCE8C, 0x878D, 0xC8DA, 0x878E, 0xCE8D, 0x878F, 0xCE8E, 0x8790, 0xCE8F, 0x8791, 0xCE90, 0x8792, 0xCE91, + 0x8793, 0xF2FB, 0x8794, 0xCE92, 0x8795, 0xCE93, 0x8796, 0xCE94, 0x8797, 0xF3A5, 0x8798, 0xCE95, 0x8799, 0xCE96, 0x879A, 0xCE97, + 0x879B, 0xCE98, 0x879C, 0xCE99, 0x879D, 0xCE9A, 0x879E, 0xCE9B, 0x879F, 0xC3F8, 0x87A0, 0xCE9C, 0x87A1, 0xCE9D, 0x87A2, 0xCE9E, + 0x87A3, 0xCE9F, 0x87A4, 0xCEA0, 0x87A5, 0xCF40, 0x87A6, 0xCF41, 0x87A7, 0xCF42, 0x87A8, 0xF2FD, 0x87A9, 0xCF43, 0x87AA, 0xCF44, + 0x87AB, 0xF3A7, 0x87AC, 0xF3A9, 0x87AD, 0xF3A4, 0x87AE, 0xCF45, 0x87AF, 0xF2FC, 0x87B0, 0xCF46, 0x87B1, 0xCF47, 0x87B2, 0xCF48, + 0x87B3, 0xF3AB, 0x87B4, 0xCF49, 0x87B5, 0xF3AA, 0x87B6, 0xCF4A, 0x87B7, 0xCF4B, 0x87B8, 0xCF4C, 0x87B9, 0xCF4D, 0x87BA, 0xC2DD, + 0x87BB, 0xCF4E, 0x87BC, 0xCF4F, 0x87BD, 0xF3AE, 0x87BE, 0xCF50, 0x87BF, 0xCF51, 0x87C0, 0xF3B0, 0x87C1, 0xCF52, 0x87C2, 0xCF53, + 0x87C3, 0xCF54, 0x87C4, 0xCF55, 0x87C5, 0xCF56, 0x87C6, 0xF3A1, 0x87C7, 0xCF57, 0x87C8, 0xCF58, 0x87C9, 0xCF59, 0x87CA, 0xF3B1, + 0x87CB, 0xF3AC, 0x87CC, 0xCF5A, 0x87CD, 0xCF5B, 0x87CE, 0xCF5C, 0x87CF, 0xCF5D, 0x87D0, 0xCF5E, 0x87D1, 0xF3AF, 0x87D2, 0xF2FE, + 0x87D3, 0xF3AD, 0x87D4, 0xCF5F, 0x87D5, 0xCF60, 0x87D6, 0xCF61, 0x87D7, 0xCF62, 0x87D8, 0xCF63, 0x87D9, 0xCF64, 0x87DA, 0xCF65, + 0x87DB, 0xF3B2, 0x87DC, 0xCF66, 0x87DD, 0xCF67, 0x87DE, 0xCF68, 0x87DF, 0xCF69, 0x87E0, 0xF3B4, 0x87E1, 0xCF6A, 0x87E2, 0xCF6B, + 0x87E3, 0xCF6C, 0x87E4, 0xCF6D, 0x87E5, 0xF3A8, 0x87E6, 0xCF6E, 0x87E7, 0xCF6F, 0x87E8, 0xCF70, 0x87E9, 0xCF71, 0x87EA, 0xF3B3, + 0x87EB, 0xCF72, 0x87EC, 0xCF73, 0x87ED, 0xCF74, 0x87EE, 0xF3B5, 0x87EF, 0xCF75, 0x87F0, 0xCF76, 0x87F1, 0xCF77, 0x87F2, 0xCF78, + 0x87F3, 0xCF79, 0x87F4, 0xCF7A, 0x87F5, 0xCF7B, 0x87F6, 0xCF7C, 0x87F7, 0xCF7D, 0x87F8, 0xCF7E, 0x87F9, 0xD0B7, 0x87FA, 0xCF80, + 0x87FB, 0xCF81, 0x87FC, 0xCF82, 0x87FD, 0xCF83, 0x87FE, 0xF3B8, 0x87FF, 0xCF84, 0x8800, 0xCF85, 0x8801, 0xCF86, 0x8802, 0xCF87, + 0x8803, 0xD9F9, 0x8804, 0xCF88, 0x8805, 0xCF89, 0x8806, 0xCF8A, 0x8807, 0xCF8B, 0x8808, 0xCF8C, 0x8809, 0xCF8D, 0x880A, 0xF3B9, + 0x880B, 0xCF8E, 0x880C, 0xCF8F, 0x880D, 0xCF90, 0x880E, 0xCF91, 0x880F, 0xCF92, 0x8810, 0xCF93, 0x8811, 0xCF94, 0x8812, 0xCF95, + 0x8813, 0xF3B7, 0x8814, 0xCF96, 0x8815, 0xC8E4, 0x8816, 0xF3B6, 0x8817, 0xCF97, 0x8818, 0xCF98, 0x8819, 0xCF99, 0x881A, 0xCF9A, + 0x881B, 0xF3BA, 0x881C, 0xCF9B, 0x881D, 0xCF9C, 0x881E, 0xCF9D, 0x881F, 0xCF9E, 0x8820, 0xCF9F, 0x8821, 0xF3BB, 0x8822, 0xB4C0, + 0x8823, 0xCFA0, 0x8824, 0xD040, 0x8825, 0xD041, 0x8826, 0xD042, 0x8827, 0xD043, 0x8828, 0xD044, 0x8829, 0xD045, 0x882A, 0xD046, + 0x882B, 0xD047, 0x882C, 0xD048, 0x882D, 0xD049, 0x882E, 0xD04A, 0x882F, 0xD04B, 0x8830, 0xD04C, 0x8831, 0xD04D, 0x8832, 0xEEC3, + 0x8833, 0xD04E, 0x8834, 0xD04F, 0x8835, 0xD050, 0x8836, 0xD051, 0x8837, 0xD052, 0x8838, 0xD053, 0x8839, 0xF3BC, 0x883A, 0xD054, + 0x883B, 0xD055, 0x883C, 0xF3BD, 0x883D, 0xD056, 0x883E, 0xD057, 0x883F, 0xD058, 0x8840, 0xD1AA, 0x8841, 0xD059, 0x8842, 0xD05A, + 0x8843, 0xD05B, 0x8844, 0xF4AC, 0x8845, 0xD0C6, 0x8846, 0xD05C, 0x8847, 0xD05D, 0x8848, 0xD05E, 0x8849, 0xD05F, 0x884A, 0xD060, + 0x884B, 0xD061, 0x884C, 0xD0D0, 0x884D, 0xD1DC, 0x884E, 0xD062, 0x884F, 0xD063, 0x8850, 0xD064, 0x8851, 0xD065, 0x8852, 0xD066, + 0x8853, 0xD067, 0x8854, 0xCFCE, 0x8855, 0xD068, 0x8856, 0xD069, 0x8857, 0xBDD6, 0x8858, 0xD06A, 0x8859, 0xD1C3, 0x885A, 0xD06B, + 0x885B, 0xD06C, 0x885C, 0xD06D, 0x885D, 0xD06E, 0x885E, 0xD06F, 0x885F, 0xD070, 0x8860, 0xD071, 0x8861, 0xBAE2, 0x8862, 0xE1E9, + 0x8863, 0xD2C2, 0x8864, 0xF1C2, 0x8865, 0xB2B9, 0x8866, 0xD072, 0x8867, 0xD073, 0x8868, 0xB1ED, 0x8869, 0xF1C3, 0x886A, 0xD074, + 0x886B, 0xC9C0, 0x886C, 0xB3C4, 0x886D, 0xD075, 0x886E, 0xD9F2, 0x886F, 0xD076, 0x8870, 0xCBA5, 0x8871, 0xD077, 0x8872, 0xF1C4, + 0x8873, 0xD078, 0x8874, 0xD079, 0x8875, 0xD07A, 0x8876, 0xD07B, 0x8877, 0xD6D4, 0x8878, 0xD07C, 0x8879, 0xD07D, 0x887A, 0xD07E, + 0x887B, 0xD080, 0x887C, 0xD081, 0x887D, 0xF1C5, 0x887E, 0xF4C0, 0x887F, 0xF1C6, 0x8880, 0xD082, 0x8881, 0xD4AC, 0x8882, 0xF1C7, + 0x8883, 0xD083, 0x8884, 0xB0C0, 0x8885, 0xF4C1, 0x8886, 0xD084, 0x8887, 0xD085, 0x8888, 0xF4C2, 0x8889, 0xD086, 0x888A, 0xD087, + 0x888B, 0xB4FC, 0x888C, 0xD088, 0x888D, 0xC5DB, 0x888E, 0xD089, 0x888F, 0xD08A, 0x8890, 0xD08B, 0x8891, 0xD08C, 0x8892, 0xCCBB, + 0x8893, 0xD08D, 0x8894, 0xD08E, 0x8895, 0xD08F, 0x8896, 0xD0E4, 0x8897, 0xD090, 0x8898, 0xD091, 0x8899, 0xD092, 0x889A, 0xD093, + 0x889B, 0xD094, 0x889C, 0xCDE0, 0x889D, 0xD095, 0x889E, 0xD096, 0x889F, 0xD097, 0x88A0, 0xD098, 0x88A1, 0xD099, 0x88A2, 0xF1C8, + 0x88A3, 0xD09A, 0x88A4, 0xD9F3, 0x88A5, 0xD09B, 0x88A6, 0xD09C, 0x88A7, 0xD09D, 0x88A8, 0xD09E, 0x88A9, 0xD09F, 0x88AA, 0xD0A0, + 0x88AB, 0xB1BB, 0x88AC, 0xD140, 0x88AD, 0xCFAE, 0x88AE, 0xD141, 0x88AF, 0xD142, 0x88B0, 0xD143, 0x88B1, 0xB8A4, 0x88B2, 0xD144, + 0x88B3, 0xD145, 0x88B4, 0xD146, 0x88B5, 0xD147, 0x88B6, 0xD148, 0x88B7, 0xF1CA, 0x88B8, 0xD149, 0x88B9, 0xD14A, 0x88BA, 0xD14B, + 0x88BB, 0xD14C, 0x88BC, 0xF1CB, 0x88BD, 0xD14D, 0x88BE, 0xD14E, 0x88BF, 0xD14F, 0x88C0, 0xD150, 0x88C1, 0xB2C3, 0x88C2, 0xC1D1, + 0x88C3, 0xD151, 0x88C4, 0xD152, 0x88C5, 0xD7B0, 0x88C6, 0xF1C9, 0x88C7, 0xD153, 0x88C8, 0xD154, 0x88C9, 0xF1CC, 0x88CA, 0xD155, + 0x88CB, 0xD156, 0x88CC, 0xD157, 0x88CD, 0xD158, 0x88CE, 0xF1CE, 0x88CF, 0xD159, 0x88D0, 0xD15A, 0x88D1, 0xD15B, 0x88D2, 0xD9F6, + 0x88D3, 0xD15C, 0x88D4, 0xD2E1, 0x88D5, 0xD4A3, 0x88D6, 0xD15D, 0x88D7, 0xD15E, 0x88D8, 0xF4C3, 0x88D9, 0xC8B9, 0x88DA, 0xD15F, + 0x88DB, 0xD160, 0x88DC, 0xD161, 0x88DD, 0xD162, 0x88DE, 0xD163, 0x88DF, 0xF4C4, 0x88E0, 0xD164, 0x88E1, 0xD165, 0x88E2, 0xF1CD, + 0x88E3, 0xF1CF, 0x88E4, 0xBFE3, 0x88E5, 0xF1D0, 0x88E6, 0xD166, 0x88E7, 0xD167, 0x88E8, 0xF1D4, 0x88E9, 0xD168, 0x88EA, 0xD169, + 0x88EB, 0xD16A, 0x88EC, 0xD16B, 0x88ED, 0xD16C, 0x88EE, 0xD16D, 0x88EF, 0xD16E, 0x88F0, 0xF1D6, 0x88F1, 0xF1D1, 0x88F2, 0xD16F, + 0x88F3, 0xC9D1, 0x88F4, 0xC5E1, 0x88F5, 0xD170, 0x88F6, 0xD171, 0x88F7, 0xD172, 0x88F8, 0xC2E3, 0x88F9, 0xB9FC, 0x88FA, 0xD173, + 0x88FB, 0xD174, 0x88FC, 0xF1D3, 0x88FD, 0xD175, 0x88FE, 0xF1D5, 0x88FF, 0xD176, 0x8900, 0xD177, 0x8901, 0xD178, 0x8902, 0xB9D3, + 0x8903, 0xD179, 0x8904, 0xD17A, 0x8905, 0xD17B, 0x8906, 0xD17C, 0x8907, 0xD17D, 0x8908, 0xD17E, 0x8909, 0xD180, 0x890A, 0xF1DB, + 0x890B, 0xD181, 0x890C, 0xD182, 0x890D, 0xD183, 0x890E, 0xD184, 0x890F, 0xD185, 0x8910, 0xBAD6, 0x8911, 0xD186, 0x8912, 0xB0FD, + 0x8913, 0xF1D9, 0x8914, 0xD187, 0x8915, 0xD188, 0x8916, 0xD189, 0x8917, 0xD18A, 0x8918, 0xD18B, 0x8919, 0xF1D8, 0x891A, 0xF1D2, + 0x891B, 0xF1DA, 0x891C, 0xD18C, 0x891D, 0xD18D, 0x891E, 0xD18E, 0x891F, 0xD18F, 0x8920, 0xD190, 0x8921, 0xF1D7, 0x8922, 0xD191, + 0x8923, 0xD192, 0x8924, 0xD193, 0x8925, 0xC8EC, 0x8926, 0xD194, 0x8927, 0xD195, 0x8928, 0xD196, 0x8929, 0xD197, 0x892A, 0xCDCA, + 0x892B, 0xF1DD, 0x892C, 0xD198, 0x892D, 0xD199, 0x892E, 0xD19A, 0x892F, 0xD19B, 0x8930, 0xE5BD, 0x8931, 0xD19C, 0x8932, 0xD19D, + 0x8933, 0xD19E, 0x8934, 0xF1DC, 0x8935, 0xD19F, 0x8936, 0xF1DE, 0x8937, 0xD1A0, 0x8938, 0xD240, 0x8939, 0xD241, 0x893A, 0xD242, + 0x893B, 0xD243, 0x893C, 0xD244, 0x893D, 0xD245, 0x893E, 0xD246, 0x893F, 0xD247, 0x8940, 0xD248, 0x8941, 0xF1DF, 0x8942, 0xD249, + 0x8943, 0xD24A, 0x8944, 0xCFE5, 0x8945, 0xD24B, 0x8946, 0xD24C, 0x8947, 0xD24D, 0x8948, 0xD24E, 0x8949, 0xD24F, 0x894A, 0xD250, + 0x894B, 0xD251, 0x894C, 0xD252, 0x894D, 0xD253, 0x894E, 0xD254, 0x894F, 0xD255, 0x8950, 0xD256, 0x8951, 0xD257, 0x8952, 0xD258, + 0x8953, 0xD259, 0x8954, 0xD25A, 0x8955, 0xD25B, 0x8956, 0xD25C, 0x8957, 0xD25D, 0x8958, 0xD25E, 0x8959, 0xD25F, 0x895A, 0xD260, + 0x895B, 0xD261, 0x895C, 0xD262, 0x895D, 0xD263, 0x895E, 0xF4C5, 0x895F, 0xBDF3, 0x8960, 0xD264, 0x8961, 0xD265, 0x8962, 0xD266, + 0x8963, 0xD267, 0x8964, 0xD268, 0x8965, 0xD269, 0x8966, 0xF1E0, 0x8967, 0xD26A, 0x8968, 0xD26B, 0x8969, 0xD26C, 0x896A, 0xD26D, + 0x896B, 0xD26E, 0x896C, 0xD26F, 0x896D, 0xD270, 0x896E, 0xD271, 0x896F, 0xD272, 0x8970, 0xD273, 0x8971, 0xD274, 0x8972, 0xD275, + 0x8973, 0xD276, 0x8974, 0xD277, 0x8975, 0xD278, 0x8976, 0xD279, 0x8977, 0xD27A, 0x8978, 0xD27B, 0x8979, 0xD27C, 0x897A, 0xD27D, + 0x897B, 0xF1E1, 0x897C, 0xD27E, 0x897D, 0xD280, 0x897E, 0xD281, 0x897F, 0xCEF7, 0x8980, 0xD282, 0x8981, 0xD2AA, 0x8982, 0xD283, + 0x8983, 0xF1FB, 0x8984, 0xD284, 0x8985, 0xD285, 0x8986, 0xB8B2, 0x8987, 0xD286, 0x8988, 0xD287, 0x8989, 0xD288, 0x898A, 0xD289, + 0x898B, 0xD28A, 0x898C, 0xD28B, 0x898D, 0xD28C, 0x898E, 0xD28D, 0x898F, 0xD28E, 0x8990, 0xD28F, 0x8991, 0xD290, 0x8992, 0xD291, + 0x8993, 0xD292, 0x8994, 0xD293, 0x8995, 0xD294, 0x8996, 0xD295, 0x8997, 0xD296, 0x8998, 0xD297, 0x8999, 0xD298, 0x899A, 0xD299, + 0x899B, 0xD29A, 0x899C, 0xD29B, 0x899D, 0xD29C, 0x899E, 0xD29D, 0x899F, 0xD29E, 0x89A0, 0xD29F, 0x89A1, 0xD2A0, 0x89A2, 0xD340, + 0x89A3, 0xD341, 0x89A4, 0xD342, 0x89A5, 0xD343, 0x89A6, 0xD344, 0x89A7, 0xD345, 0x89A8, 0xD346, 0x89A9, 0xD347, 0x89AA, 0xD348, + 0x89AB, 0xD349, 0x89AC, 0xD34A, 0x89AD, 0xD34B, 0x89AE, 0xD34C, 0x89AF, 0xD34D, 0x89B0, 0xD34E, 0x89B1, 0xD34F, 0x89B2, 0xD350, + 0x89B3, 0xD351, 0x89B4, 0xD352, 0x89B5, 0xD353, 0x89B6, 0xD354, 0x89B7, 0xD355, 0x89B8, 0xD356, 0x89B9, 0xD357, 0x89BA, 0xD358, + 0x89BB, 0xD359, 0x89BC, 0xD35A, 0x89BD, 0xD35B, 0x89BE, 0xD35C, 0x89BF, 0xD35D, 0x89C0, 0xD35E, 0x89C1, 0xBCFB, 0x89C2, 0xB9DB, + 0x89C3, 0xD35F, 0x89C4, 0xB9E6, 0x89C5, 0xC3D9, 0x89C6, 0xCAD3, 0x89C7, 0xEAE8, 0x89C8, 0xC0C0, 0x89C9, 0xBEF5, 0x89CA, 0xEAE9, + 0x89CB, 0xEAEA, 0x89CC, 0xEAEB, 0x89CD, 0xD360, 0x89CE, 0xEAEC, 0x89CF, 0xEAED, 0x89D0, 0xEAEE, 0x89D1, 0xEAEF, 0x89D2, 0xBDC7, + 0x89D3, 0xD361, 0x89D4, 0xD362, 0x89D5, 0xD363, 0x89D6, 0xF5FB, 0x89D7, 0xD364, 0x89D8, 0xD365, 0x89D9, 0xD366, 0x89DA, 0xF5FD, + 0x89DB, 0xD367, 0x89DC, 0xF5FE, 0x89DD, 0xD368, 0x89DE, 0xF5FC, 0x89DF, 0xD369, 0x89E0, 0xD36A, 0x89E1, 0xD36B, 0x89E2, 0xD36C, + 0x89E3, 0xBDE2, 0x89E4, 0xD36D, 0x89E5, 0xF6A1, 0x89E6, 0xB4A5, 0x89E7, 0xD36E, 0x89E8, 0xD36F, 0x89E9, 0xD370, 0x89EA, 0xD371, + 0x89EB, 0xF6A2, 0x89EC, 0xD372, 0x89ED, 0xD373, 0x89EE, 0xD374, 0x89EF, 0xF6A3, 0x89F0, 0xD375, 0x89F1, 0xD376, 0x89F2, 0xD377, + 0x89F3, 0xECB2, 0x89F4, 0xD378, 0x89F5, 0xD379, 0x89F6, 0xD37A, 0x89F7, 0xD37B, 0x89F8, 0xD37C, 0x89F9, 0xD37D, 0x89FA, 0xD37E, + 0x89FB, 0xD380, 0x89FC, 0xD381, 0x89FD, 0xD382, 0x89FE, 0xD383, 0x89FF, 0xD384, 0x8A00, 0xD1D4, 0x8A01, 0xD385, 0x8A02, 0xD386, + 0x8A03, 0xD387, 0x8A04, 0xD388, 0x8A05, 0xD389, 0x8A06, 0xD38A, 0x8A07, 0xD9EA, 0x8A08, 0xD38B, 0x8A09, 0xD38C, 0x8A0A, 0xD38D, + 0x8A0B, 0xD38E, 0x8A0C, 0xD38F, 0x8A0D, 0xD390, 0x8A0E, 0xD391, 0x8A0F, 0xD392, 0x8A10, 0xD393, 0x8A11, 0xD394, 0x8A12, 0xD395, + 0x8A13, 0xD396, 0x8A14, 0xD397, 0x8A15, 0xD398, 0x8A16, 0xD399, 0x8A17, 0xD39A, 0x8A18, 0xD39B, 0x8A19, 0xD39C, 0x8A1A, 0xD39D, + 0x8A1B, 0xD39E, 0x8A1C, 0xD39F, 0x8A1D, 0xD3A0, 0x8A1E, 0xD440, 0x8A1F, 0xD441, 0x8A20, 0xD442, 0x8A21, 0xD443, 0x8A22, 0xD444, + 0x8A23, 0xD445, 0x8A24, 0xD446, 0x8A25, 0xD447, 0x8A26, 0xD448, 0x8A27, 0xD449, 0x8A28, 0xD44A, 0x8A29, 0xD44B, 0x8A2A, 0xD44C, + 0x8A2B, 0xD44D, 0x8A2C, 0xD44E, 0x8A2D, 0xD44F, 0x8A2E, 0xD450, 0x8A2F, 0xD451, 0x8A30, 0xD452, 0x8A31, 0xD453, 0x8A32, 0xD454, + 0x8A33, 0xD455, 0x8A34, 0xD456, 0x8A35, 0xD457, 0x8A36, 0xD458, 0x8A37, 0xD459, 0x8A38, 0xD45A, 0x8A39, 0xD45B, 0x8A3A, 0xD45C, + 0x8A3B, 0xD45D, 0x8A3C, 0xD45E, 0x8A3D, 0xD45F, 0x8A3E, 0xF6A4, 0x8A3F, 0xD460, 0x8A40, 0xD461, 0x8A41, 0xD462, 0x8A42, 0xD463, + 0x8A43, 0xD464, 0x8A44, 0xD465, 0x8A45, 0xD466, 0x8A46, 0xD467, 0x8A47, 0xD468, 0x8A48, 0xEEBA, 0x8A49, 0xD469, 0x8A4A, 0xD46A, + 0x8A4B, 0xD46B, 0x8A4C, 0xD46C, 0x8A4D, 0xD46D, 0x8A4E, 0xD46E, 0x8A4F, 0xD46F, 0x8A50, 0xD470, 0x8A51, 0xD471, 0x8A52, 0xD472, + 0x8A53, 0xD473, 0x8A54, 0xD474, 0x8A55, 0xD475, 0x8A56, 0xD476, 0x8A57, 0xD477, 0x8A58, 0xD478, 0x8A59, 0xD479, 0x8A5A, 0xD47A, + 0x8A5B, 0xD47B, 0x8A5C, 0xD47C, 0x8A5D, 0xD47D, 0x8A5E, 0xD47E, 0x8A5F, 0xD480, 0x8A60, 0xD481, 0x8A61, 0xD482, 0x8A62, 0xD483, + 0x8A63, 0xD484, 0x8A64, 0xD485, 0x8A65, 0xD486, 0x8A66, 0xD487, 0x8A67, 0xD488, 0x8A68, 0xD489, 0x8A69, 0xD48A, 0x8A6A, 0xD48B, + 0x8A6B, 0xD48C, 0x8A6C, 0xD48D, 0x8A6D, 0xD48E, 0x8A6E, 0xD48F, 0x8A6F, 0xD490, 0x8A70, 0xD491, 0x8A71, 0xD492, 0x8A72, 0xD493, + 0x8A73, 0xD494, 0x8A74, 0xD495, 0x8A75, 0xD496, 0x8A76, 0xD497, 0x8A77, 0xD498, 0x8A78, 0xD499, 0x8A79, 0xD5B2, 0x8A7A, 0xD49A, + 0x8A7B, 0xD49B, 0x8A7C, 0xD49C, 0x8A7D, 0xD49D, 0x8A7E, 0xD49E, 0x8A7F, 0xD49F, 0x8A80, 0xD4A0, 0x8A81, 0xD540, 0x8A82, 0xD541, + 0x8A83, 0xD542, 0x8A84, 0xD543, 0x8A85, 0xD544, 0x8A86, 0xD545, 0x8A87, 0xD546, 0x8A88, 0xD547, 0x8A89, 0xD3FE, 0x8A8A, 0xCCDC, + 0x8A8B, 0xD548, 0x8A8C, 0xD549, 0x8A8D, 0xD54A, 0x8A8E, 0xD54B, 0x8A8F, 0xD54C, 0x8A90, 0xD54D, 0x8A91, 0xD54E, 0x8A92, 0xD54F, + 0x8A93, 0xCAC4, 0x8A94, 0xD550, 0x8A95, 0xD551, 0x8A96, 0xD552, 0x8A97, 0xD553, 0x8A98, 0xD554, 0x8A99, 0xD555, 0x8A9A, 0xD556, + 0x8A9B, 0xD557, 0x8A9C, 0xD558, 0x8A9D, 0xD559, 0x8A9E, 0xD55A, 0x8A9F, 0xD55B, 0x8AA0, 0xD55C, 0x8AA1, 0xD55D, 0x8AA2, 0xD55E, + 0x8AA3, 0xD55F, 0x8AA4, 0xD560, 0x8AA5, 0xD561, 0x8AA6, 0xD562, 0x8AA7, 0xD563, 0x8AA8, 0xD564, 0x8AA9, 0xD565, 0x8AAA, 0xD566, + 0x8AAB, 0xD567, 0x8AAC, 0xD568, 0x8AAD, 0xD569, 0x8AAE, 0xD56A, 0x8AAF, 0xD56B, 0x8AB0, 0xD56C, 0x8AB1, 0xD56D, 0x8AB2, 0xD56E, + 0x8AB3, 0xD56F, 0x8AB4, 0xD570, 0x8AB5, 0xD571, 0x8AB6, 0xD572, 0x8AB7, 0xD573, 0x8AB8, 0xD574, 0x8AB9, 0xD575, 0x8ABA, 0xD576, + 0x8ABB, 0xD577, 0x8ABC, 0xD578, 0x8ABD, 0xD579, 0x8ABE, 0xD57A, 0x8ABF, 0xD57B, 0x8AC0, 0xD57C, 0x8AC1, 0xD57D, 0x8AC2, 0xD57E, + 0x8AC3, 0xD580, 0x8AC4, 0xD581, 0x8AC5, 0xD582, 0x8AC6, 0xD583, 0x8AC7, 0xD584, 0x8AC8, 0xD585, 0x8AC9, 0xD586, 0x8ACA, 0xD587, + 0x8ACB, 0xD588, 0x8ACC, 0xD589, 0x8ACD, 0xD58A, 0x8ACE, 0xD58B, 0x8ACF, 0xD58C, 0x8AD0, 0xD58D, 0x8AD1, 0xD58E, 0x8AD2, 0xD58F, + 0x8AD3, 0xD590, 0x8AD4, 0xD591, 0x8AD5, 0xD592, 0x8AD6, 0xD593, 0x8AD7, 0xD594, 0x8AD8, 0xD595, 0x8AD9, 0xD596, 0x8ADA, 0xD597, + 0x8ADB, 0xD598, 0x8ADC, 0xD599, 0x8ADD, 0xD59A, 0x8ADE, 0xD59B, 0x8ADF, 0xD59C, 0x8AE0, 0xD59D, 0x8AE1, 0xD59E, 0x8AE2, 0xD59F, + 0x8AE3, 0xD5A0, 0x8AE4, 0xD640, 0x8AE5, 0xD641, 0x8AE6, 0xD642, 0x8AE7, 0xD643, 0x8AE8, 0xD644, 0x8AE9, 0xD645, 0x8AEA, 0xD646, + 0x8AEB, 0xD647, 0x8AEC, 0xD648, 0x8AED, 0xD649, 0x8AEE, 0xD64A, 0x8AEF, 0xD64B, 0x8AF0, 0xD64C, 0x8AF1, 0xD64D, 0x8AF2, 0xD64E, + 0x8AF3, 0xD64F, 0x8AF4, 0xD650, 0x8AF5, 0xD651, 0x8AF6, 0xD652, 0x8AF7, 0xD653, 0x8AF8, 0xD654, 0x8AF9, 0xD655, 0x8AFA, 0xD656, + 0x8AFB, 0xD657, 0x8AFC, 0xD658, 0x8AFD, 0xD659, 0x8AFE, 0xD65A, 0x8AFF, 0xD65B, 0x8B00, 0xD65C, 0x8B01, 0xD65D, 0x8B02, 0xD65E, + 0x8B03, 0xD65F, 0x8B04, 0xD660, 0x8B05, 0xD661, 0x8B06, 0xD662, 0x8B07, 0xE5C0, 0x8B08, 0xD663, 0x8B09, 0xD664, 0x8B0A, 0xD665, + 0x8B0B, 0xD666, 0x8B0C, 0xD667, 0x8B0D, 0xD668, 0x8B0E, 0xD669, 0x8B0F, 0xD66A, 0x8B10, 0xD66B, 0x8B11, 0xD66C, 0x8B12, 0xD66D, + 0x8B13, 0xD66E, 0x8B14, 0xD66F, 0x8B15, 0xD670, 0x8B16, 0xD671, 0x8B17, 0xD672, 0x8B18, 0xD673, 0x8B19, 0xD674, 0x8B1A, 0xD675, + 0x8B1B, 0xD676, 0x8B1C, 0xD677, 0x8B1D, 0xD678, 0x8B1E, 0xD679, 0x8B1F, 0xD67A, 0x8B20, 0xD67B, 0x8B21, 0xD67C, 0x8B22, 0xD67D, + 0x8B23, 0xD67E, 0x8B24, 0xD680, 0x8B25, 0xD681, 0x8B26, 0xF6A5, 0x8B27, 0xD682, 0x8B28, 0xD683, 0x8B29, 0xD684, 0x8B2A, 0xD685, + 0x8B2B, 0xD686, 0x8B2C, 0xD687, 0x8B2D, 0xD688, 0x8B2E, 0xD689, 0x8B2F, 0xD68A, 0x8B30, 0xD68B, 0x8B31, 0xD68C, 0x8B32, 0xD68D, + 0x8B33, 0xD68E, 0x8B34, 0xD68F, 0x8B35, 0xD690, 0x8B36, 0xD691, 0x8B37, 0xD692, 0x8B38, 0xD693, 0x8B39, 0xD694, 0x8B3A, 0xD695, + 0x8B3B, 0xD696, 0x8B3C, 0xD697, 0x8B3D, 0xD698, 0x8B3E, 0xD699, 0x8B3F, 0xD69A, 0x8B40, 0xD69B, 0x8B41, 0xD69C, 0x8B42, 0xD69D, + 0x8B43, 0xD69E, 0x8B44, 0xD69F, 0x8B45, 0xD6A0, 0x8B46, 0xD740, 0x8B47, 0xD741, 0x8B48, 0xD742, 0x8B49, 0xD743, 0x8B4A, 0xD744, + 0x8B4B, 0xD745, 0x8B4C, 0xD746, 0x8B4D, 0xD747, 0x8B4E, 0xD748, 0x8B4F, 0xD749, 0x8B50, 0xD74A, 0x8B51, 0xD74B, 0x8B52, 0xD74C, + 0x8B53, 0xD74D, 0x8B54, 0xD74E, 0x8B55, 0xD74F, 0x8B56, 0xD750, 0x8B57, 0xD751, 0x8B58, 0xD752, 0x8B59, 0xD753, 0x8B5A, 0xD754, + 0x8B5B, 0xD755, 0x8B5C, 0xD756, 0x8B5D, 0xD757, 0x8B5E, 0xD758, 0x8B5F, 0xD759, 0x8B60, 0xD75A, 0x8B61, 0xD75B, 0x8B62, 0xD75C, + 0x8B63, 0xD75D, 0x8B64, 0xD75E, 0x8B65, 0xD75F, 0x8B66, 0xBEAF, 0x8B67, 0xD760, 0x8B68, 0xD761, 0x8B69, 0xD762, 0x8B6A, 0xD763, + 0x8B6B, 0xD764, 0x8B6C, 0xC6A9, 0x8B6D, 0xD765, 0x8B6E, 0xD766, 0x8B6F, 0xD767, 0x8B70, 0xD768, 0x8B71, 0xD769, 0x8B72, 0xD76A, + 0x8B73, 0xD76B, 0x8B74, 0xD76C, 0x8B75, 0xD76D, 0x8B76, 0xD76E, 0x8B77, 0xD76F, 0x8B78, 0xD770, 0x8B79, 0xD771, 0x8B7A, 0xD772, + 0x8B7B, 0xD773, 0x8B7C, 0xD774, 0x8B7D, 0xD775, 0x8B7E, 0xD776, 0x8B7F, 0xD777, 0x8B80, 0xD778, 0x8B81, 0xD779, 0x8B82, 0xD77A, + 0x8B83, 0xD77B, 0x8B84, 0xD77C, 0x8B85, 0xD77D, 0x8B86, 0xD77E, 0x8B87, 0xD780, 0x8B88, 0xD781, 0x8B89, 0xD782, 0x8B8A, 0xD783, + 0x8B8B, 0xD784, 0x8B8C, 0xD785, 0x8B8D, 0xD786, 0x8B8E, 0xD787, 0x8B8F, 0xD788, 0x8B90, 0xD789, 0x8B91, 0xD78A, 0x8B92, 0xD78B, + 0x8B93, 0xD78C, 0x8B94, 0xD78D, 0x8B95, 0xD78E, 0x8B96, 0xD78F, 0x8B97, 0xD790, 0x8B98, 0xD791, 0x8B99, 0xD792, 0x8B9A, 0xD793, + 0x8B9B, 0xD794, 0x8B9C, 0xD795, 0x8B9D, 0xD796, 0x8B9E, 0xD797, 0x8B9F, 0xD798, 0x8BA0, 0xDAA5, 0x8BA1, 0xBCC6, 0x8BA2, 0xB6A9, + 0x8BA3, 0xB8BC, 0x8BA4, 0xC8CF, 0x8BA5, 0xBCA5, 0x8BA6, 0xDAA6, 0x8BA7, 0xDAA7, 0x8BA8, 0xCCD6, 0x8BA9, 0xC8C3, 0x8BAA, 0xDAA8, + 0x8BAB, 0xC6FD, 0x8BAC, 0xD799, 0x8BAD, 0xD1B5, 0x8BAE, 0xD2E9, 0x8BAF, 0xD1B6, 0x8BB0, 0xBCC7, 0x8BB1, 0xD79A, 0x8BB2, 0xBDB2, + 0x8BB3, 0xBBE4, 0x8BB4, 0xDAA9, 0x8BB5, 0xDAAA, 0x8BB6, 0xD1C8, 0x8BB7, 0xDAAB, 0x8BB8, 0xD0ED, 0x8BB9, 0xB6EF, 0x8BBA, 0xC2DB, + 0x8BBB, 0xD79B, 0x8BBC, 0xCBCF, 0x8BBD, 0xB7ED, 0x8BBE, 0xC9E8, 0x8BBF, 0xB7C3, 0x8BC0, 0xBEF7, 0x8BC1, 0xD6A4, 0x8BC2, 0xDAAC, + 0x8BC3, 0xDAAD, 0x8BC4, 0xC6C0, 0x8BC5, 0xD7E7, 0x8BC6, 0xCAB6, 0x8BC7, 0xD79C, 0x8BC8, 0xD5A9, 0x8BC9, 0xCBDF, 0x8BCA, 0xD5EF, + 0x8BCB, 0xDAAE, 0x8BCC, 0xD6DF, 0x8BCD, 0xB4CA, 0x8BCE, 0xDAB0, 0x8BCF, 0xDAAF, 0x8BD0, 0xD79D, 0x8BD1, 0xD2EB, 0x8BD2, 0xDAB1, + 0x8BD3, 0xDAB2, 0x8BD4, 0xDAB3, 0x8BD5, 0xCAD4, 0x8BD6, 0xDAB4, 0x8BD7, 0xCAAB, 0x8BD8, 0xDAB5, 0x8BD9, 0xDAB6, 0x8BDA, 0xB3CF, + 0x8BDB, 0xD6EF, 0x8BDC, 0xDAB7, 0x8BDD, 0xBBB0, 0x8BDE, 0xB5AE, 0x8BDF, 0xDAB8, 0x8BE0, 0xDAB9, 0x8BE1, 0xB9EE, 0x8BE2, 0xD1AF, + 0x8BE3, 0xD2E8, 0x8BE4, 0xDABA, 0x8BE5, 0xB8C3, 0x8BE6, 0xCFEA, 0x8BE7, 0xB2EF, 0x8BE8, 0xDABB, 0x8BE9, 0xDABC, 0x8BEA, 0xD79E, + 0x8BEB, 0xBDEB, 0x8BEC, 0xCEDC, 0x8BED, 0xD3EF, 0x8BEE, 0xDABD, 0x8BEF, 0xCEF3, 0x8BF0, 0xDABE, 0x8BF1, 0xD3D5, 0x8BF2, 0xBBE5, + 0x8BF3, 0xDABF, 0x8BF4, 0xCBB5, 0x8BF5, 0xCBD0, 0x8BF6, 0xDAC0, 0x8BF7, 0xC7EB, 0x8BF8, 0xD6EE, 0x8BF9, 0xDAC1, 0x8BFA, 0xC5B5, + 0x8BFB, 0xB6C1, 0x8BFC, 0xDAC2, 0x8BFD, 0xB7CC, 0x8BFE, 0xBFCE, 0x8BFF, 0xDAC3, 0x8C00, 0xDAC4, 0x8C01, 0xCBAD, 0x8C02, 0xDAC5, + 0x8C03, 0xB5F7, 0x8C04, 0xDAC6, 0x8C05, 0xC1C2, 0x8C06, 0xD7BB, 0x8C07, 0xDAC7, 0x8C08, 0xCCB8, 0x8C09, 0xD79F, 0x8C0A, 0xD2EA, + 0x8C0B, 0xC4B1, 0x8C0C, 0xDAC8, 0x8C0D, 0xB5FD, 0x8C0E, 0xBBD1, 0x8C0F, 0xDAC9, 0x8C10, 0xD0B3, 0x8C11, 0xDACA, 0x8C12, 0xDACB, + 0x8C13, 0xCEBD, 0x8C14, 0xDACC, 0x8C15, 0xDACD, 0x8C16, 0xDACE, 0x8C17, 0xB2F7, 0x8C18, 0xDAD1, 0x8C19, 0xDACF, 0x8C1A, 0xD1E8, + 0x8C1B, 0xDAD0, 0x8C1C, 0xC3D5, 0x8C1D, 0xDAD2, 0x8C1E, 0xD7A0, 0x8C1F, 0xDAD3, 0x8C20, 0xDAD4, 0x8C21, 0xDAD5, 0x8C22, 0xD0BB, + 0x8C23, 0xD2A5, 0x8C24, 0xB0F9, 0x8C25, 0xDAD6, 0x8C26, 0xC7AB, 0x8C27, 0xDAD7, 0x8C28, 0xBDF7, 0x8C29, 0xC3A1, 0x8C2A, 0xDAD8, + 0x8C2B, 0xDAD9, 0x8C2C, 0xC3FD, 0x8C2D, 0xCCB7, 0x8C2E, 0xDADA, 0x8C2F, 0xDADB, 0x8C30, 0xC0BE, 0x8C31, 0xC6D7, 0x8C32, 0xDADC, + 0x8C33, 0xDADD, 0x8C34, 0xC7B4, 0x8C35, 0xDADE, 0x8C36, 0xDADF, 0x8C37, 0xB9C8, 0x8C38, 0xD840, 0x8C39, 0xD841, 0x8C3A, 0xD842, + 0x8C3B, 0xD843, 0x8C3C, 0xD844, 0x8C3D, 0xD845, 0x8C3E, 0xD846, 0x8C3F, 0xD847, 0x8C40, 0xD848, 0x8C41, 0xBBED, 0x8C42, 0xD849, + 0x8C43, 0xD84A, 0x8C44, 0xD84B, 0x8C45, 0xD84C, 0x8C46, 0xB6B9, 0x8C47, 0xF4F8, 0x8C48, 0xD84D, 0x8C49, 0xF4F9, 0x8C4A, 0xD84E, + 0x8C4B, 0xD84F, 0x8C4C, 0xCDE3, 0x8C4D, 0xD850, 0x8C4E, 0xD851, 0x8C4F, 0xD852, 0x8C50, 0xD853, 0x8C51, 0xD854, 0x8C52, 0xD855, + 0x8C53, 0xD856, 0x8C54, 0xD857, 0x8C55, 0xF5B9, 0x8C56, 0xD858, 0x8C57, 0xD859, 0x8C58, 0xD85A, 0x8C59, 0xD85B, 0x8C5A, 0xEBE0, + 0x8C5B, 0xD85C, 0x8C5C, 0xD85D, 0x8C5D, 0xD85E, 0x8C5E, 0xD85F, 0x8C5F, 0xD860, 0x8C60, 0xD861, 0x8C61, 0xCFF3, 0x8C62, 0xBBBF, + 0x8C63, 0xD862, 0x8C64, 0xD863, 0x8C65, 0xD864, 0x8C66, 0xD865, 0x8C67, 0xD866, 0x8C68, 0xD867, 0x8C69, 0xD868, 0x8C6A, 0xBAC0, + 0x8C6B, 0xD4A5, 0x8C6C, 0xD869, 0x8C6D, 0xD86A, 0x8C6E, 0xD86B, 0x8C6F, 0xD86C, 0x8C70, 0xD86D, 0x8C71, 0xD86E, 0x8C72, 0xD86F, + 0x8C73, 0xE1D9, 0x8C74, 0xD870, 0x8C75, 0xD871, 0x8C76, 0xD872, 0x8C77, 0xD873, 0x8C78, 0xF5F4, 0x8C79, 0xB1AA, 0x8C7A, 0xB2F2, + 0x8C7B, 0xD874, 0x8C7C, 0xD875, 0x8C7D, 0xD876, 0x8C7E, 0xD877, 0x8C7F, 0xD878, 0x8C80, 0xD879, 0x8C81, 0xD87A, 0x8C82, 0xF5F5, + 0x8C83, 0xD87B, 0x8C84, 0xD87C, 0x8C85, 0xF5F7, 0x8C86, 0xD87D, 0x8C87, 0xD87E, 0x8C88, 0xD880, 0x8C89, 0xBAD1, 0x8C8A, 0xF5F6, + 0x8C8B, 0xD881, 0x8C8C, 0xC3B2, 0x8C8D, 0xD882, 0x8C8E, 0xD883, 0x8C8F, 0xD884, 0x8C90, 0xD885, 0x8C91, 0xD886, 0x8C92, 0xD887, + 0x8C93, 0xD888, 0x8C94, 0xF5F9, 0x8C95, 0xD889, 0x8C96, 0xD88A, 0x8C97, 0xD88B, 0x8C98, 0xF5F8, 0x8C99, 0xD88C, 0x8C9A, 0xD88D, + 0x8C9B, 0xD88E, 0x8C9C, 0xD88F, 0x8C9D, 0xD890, 0x8C9E, 0xD891, 0x8C9F, 0xD892, 0x8CA0, 0xD893, 0x8CA1, 0xD894, 0x8CA2, 0xD895, + 0x8CA3, 0xD896, 0x8CA4, 0xD897, 0x8CA5, 0xD898, 0x8CA6, 0xD899, 0x8CA7, 0xD89A, 0x8CA8, 0xD89B, 0x8CA9, 0xD89C, 0x8CAA, 0xD89D, + 0x8CAB, 0xD89E, 0x8CAC, 0xD89F, 0x8CAD, 0xD8A0, 0x8CAE, 0xD940, 0x8CAF, 0xD941, 0x8CB0, 0xD942, 0x8CB1, 0xD943, 0x8CB2, 0xD944, + 0x8CB3, 0xD945, 0x8CB4, 0xD946, 0x8CB5, 0xD947, 0x8CB6, 0xD948, 0x8CB7, 0xD949, 0x8CB8, 0xD94A, 0x8CB9, 0xD94B, 0x8CBA, 0xD94C, + 0x8CBB, 0xD94D, 0x8CBC, 0xD94E, 0x8CBD, 0xD94F, 0x8CBE, 0xD950, 0x8CBF, 0xD951, 0x8CC0, 0xD952, 0x8CC1, 0xD953, 0x8CC2, 0xD954, + 0x8CC3, 0xD955, 0x8CC4, 0xD956, 0x8CC5, 0xD957, 0x8CC6, 0xD958, 0x8CC7, 0xD959, 0x8CC8, 0xD95A, 0x8CC9, 0xD95B, 0x8CCA, 0xD95C, + 0x8CCB, 0xD95D, 0x8CCC, 0xD95E, 0x8CCD, 0xD95F, 0x8CCE, 0xD960, 0x8CCF, 0xD961, 0x8CD0, 0xD962, 0x8CD1, 0xD963, 0x8CD2, 0xD964, + 0x8CD3, 0xD965, 0x8CD4, 0xD966, 0x8CD5, 0xD967, 0x8CD6, 0xD968, 0x8CD7, 0xD969, 0x8CD8, 0xD96A, 0x8CD9, 0xD96B, 0x8CDA, 0xD96C, + 0x8CDB, 0xD96D, 0x8CDC, 0xD96E, 0x8CDD, 0xD96F, 0x8CDE, 0xD970, 0x8CDF, 0xD971, 0x8CE0, 0xD972, 0x8CE1, 0xD973, 0x8CE2, 0xD974, + 0x8CE3, 0xD975, 0x8CE4, 0xD976, 0x8CE5, 0xD977, 0x8CE6, 0xD978, 0x8CE7, 0xD979, 0x8CE8, 0xD97A, 0x8CE9, 0xD97B, 0x8CEA, 0xD97C, + 0x8CEB, 0xD97D, 0x8CEC, 0xD97E, 0x8CED, 0xD980, 0x8CEE, 0xD981, 0x8CEF, 0xD982, 0x8CF0, 0xD983, 0x8CF1, 0xD984, 0x8CF2, 0xD985, + 0x8CF3, 0xD986, 0x8CF4, 0xD987, 0x8CF5, 0xD988, 0x8CF6, 0xD989, 0x8CF7, 0xD98A, 0x8CF8, 0xD98B, 0x8CF9, 0xD98C, 0x8CFA, 0xD98D, + 0x8CFB, 0xD98E, 0x8CFC, 0xD98F, 0x8CFD, 0xD990, 0x8CFE, 0xD991, 0x8CFF, 0xD992, 0x8D00, 0xD993, 0x8D01, 0xD994, 0x8D02, 0xD995, + 0x8D03, 0xD996, 0x8D04, 0xD997, 0x8D05, 0xD998, 0x8D06, 0xD999, 0x8D07, 0xD99A, 0x8D08, 0xD99B, 0x8D09, 0xD99C, 0x8D0A, 0xD99D, + 0x8D0B, 0xD99E, 0x8D0C, 0xD99F, 0x8D0D, 0xD9A0, 0x8D0E, 0xDA40, 0x8D0F, 0xDA41, 0x8D10, 0xDA42, 0x8D11, 0xDA43, 0x8D12, 0xDA44, + 0x8D13, 0xDA45, 0x8D14, 0xDA46, 0x8D15, 0xDA47, 0x8D16, 0xDA48, 0x8D17, 0xDA49, 0x8D18, 0xDA4A, 0x8D19, 0xDA4B, 0x8D1A, 0xDA4C, + 0x8D1B, 0xDA4D, 0x8D1C, 0xDA4E, 0x8D1D, 0xB1B4, 0x8D1E, 0xD5EA, 0x8D1F, 0xB8BA, 0x8D20, 0xDA4F, 0x8D21, 0xB9B1, 0x8D22, 0xB2C6, + 0x8D23, 0xD4F0, 0x8D24, 0xCFCD, 0x8D25, 0xB0DC, 0x8D26, 0xD5CB, 0x8D27, 0xBBF5, 0x8D28, 0xD6CA, 0x8D29, 0xB7B7, 0x8D2A, 0xCCB0, + 0x8D2B, 0xC6B6, 0x8D2C, 0xB1E1, 0x8D2D, 0xB9BA, 0x8D2E, 0xD6FC, 0x8D2F, 0xB9E1, 0x8D30, 0xB7A1, 0x8D31, 0xBCFA, 0x8D32, 0xEADA, + 0x8D33, 0xEADB, 0x8D34, 0xCCF9, 0x8D35, 0xB9F3, 0x8D36, 0xEADC, 0x8D37, 0xB4FB, 0x8D38, 0xC3B3, 0x8D39, 0xB7D1, 0x8D3A, 0xBAD8, + 0x8D3B, 0xEADD, 0x8D3C, 0xD4F4, 0x8D3D, 0xEADE, 0x8D3E, 0xBCD6, 0x8D3F, 0xBBDF, 0x8D40, 0xEADF, 0x8D41, 0xC1DE, 0x8D42, 0xC2B8, + 0x8D43, 0xD4DF, 0x8D44, 0xD7CA, 0x8D45, 0xEAE0, 0x8D46, 0xEAE1, 0x8D47, 0xEAE4, 0x8D48, 0xEAE2, 0x8D49, 0xEAE3, 0x8D4A, 0xC9DE, + 0x8D4B, 0xB8B3, 0x8D4C, 0xB6C4, 0x8D4D, 0xEAE5, 0x8D4E, 0xCAEA, 0x8D4F, 0xC9CD, 0x8D50, 0xB4CD, 0x8D51, 0xDA50, 0x8D52, 0xDA51, + 0x8D53, 0xE2D9, 0x8D54, 0xC5E2, 0x8D55, 0xEAE6, 0x8D56, 0xC0B5, 0x8D57, 0xDA52, 0x8D58, 0xD7B8, 0x8D59, 0xEAE7, 0x8D5A, 0xD7AC, + 0x8D5B, 0xC8FC, 0x8D5C, 0xD8D3, 0x8D5D, 0xD8CD, 0x8D5E, 0xD4DE, 0x8D5F, 0xDA53, 0x8D60, 0xD4F9, 0x8D61, 0xC9C4, 0x8D62, 0xD3AE, + 0x8D63, 0xB8D3, 0x8D64, 0xB3E0, 0x8D65, 0xDA54, 0x8D66, 0xC9E2, 0x8D67, 0xF4F6, 0x8D68, 0xDA55, 0x8D69, 0xDA56, 0x8D6A, 0xDA57, + 0x8D6B, 0xBAD5, 0x8D6C, 0xDA58, 0x8D6D, 0xF4F7, 0x8D6E, 0xDA59, 0x8D6F, 0xDA5A, 0x8D70, 0xD7DF, 0x8D71, 0xDA5B, 0x8D72, 0xDA5C, + 0x8D73, 0xF4F1, 0x8D74, 0xB8B0, 0x8D75, 0xD5D4, 0x8D76, 0xB8CF, 0x8D77, 0xC6F0, 0x8D78, 0xDA5D, 0x8D79, 0xDA5E, 0x8D7A, 0xDA5F, + 0x8D7B, 0xDA60, 0x8D7C, 0xDA61, 0x8D7D, 0xDA62, 0x8D7E, 0xDA63, 0x8D7F, 0xDA64, 0x8D80, 0xDA65, 0x8D81, 0xB3C3, 0x8D82, 0xDA66, + 0x8D83, 0xDA67, 0x8D84, 0xF4F2, 0x8D85, 0xB3AC, 0x8D86, 0xDA68, 0x8D87, 0xDA69, 0x8D88, 0xDA6A, 0x8D89, 0xDA6B, 0x8D8A, 0xD4BD, + 0x8D8B, 0xC7F7, 0x8D8C, 0xDA6C, 0x8D8D, 0xDA6D, 0x8D8E, 0xDA6E, 0x8D8F, 0xDA6F, 0x8D90, 0xDA70, 0x8D91, 0xF4F4, 0x8D92, 0xDA71, + 0x8D93, 0xDA72, 0x8D94, 0xF4F3, 0x8D95, 0xDA73, 0x8D96, 0xDA74, 0x8D97, 0xDA75, 0x8D98, 0xDA76, 0x8D99, 0xDA77, 0x8D9A, 0xDA78, + 0x8D9B, 0xDA79, 0x8D9C, 0xDA7A, 0x8D9D, 0xDA7B, 0x8D9E, 0xDA7C, 0x8D9F, 0xCCCB, 0x8DA0, 0xDA7D, 0x8DA1, 0xDA7E, 0x8DA2, 0xDA80, + 0x8DA3, 0xC8A4, 0x8DA4, 0xDA81, 0x8DA5, 0xDA82, 0x8DA6, 0xDA83, 0x8DA7, 0xDA84, 0x8DA8, 0xDA85, 0x8DA9, 0xDA86, 0x8DAA, 0xDA87, + 0x8DAB, 0xDA88, 0x8DAC, 0xDA89, 0x8DAD, 0xDA8A, 0x8DAE, 0xDA8B, 0x8DAF, 0xDA8C, 0x8DB0, 0xDA8D, 0x8DB1, 0xF4F5, 0x8DB2, 0xDA8E, + 0x8DB3, 0xD7E3, 0x8DB4, 0xC5BF, 0x8DB5, 0xF5C0, 0x8DB6, 0xDA8F, 0x8DB7, 0xDA90, 0x8DB8, 0xF5BB, 0x8DB9, 0xDA91, 0x8DBA, 0xF5C3, + 0x8DBB, 0xDA92, 0x8DBC, 0xF5C2, 0x8DBD, 0xDA93, 0x8DBE, 0xD6BA, 0x8DBF, 0xF5C1, 0x8DC0, 0xDA94, 0x8DC1, 0xDA95, 0x8DC2, 0xDA96, + 0x8DC3, 0xD4BE, 0x8DC4, 0xF5C4, 0x8DC5, 0xDA97, 0x8DC6, 0xF5CC, 0x8DC7, 0xDA98, 0x8DC8, 0xDA99, 0x8DC9, 0xDA9A, 0x8DCA, 0xDA9B, + 0x8DCB, 0xB0CF, 0x8DCC, 0xB5F8, 0x8DCD, 0xDA9C, 0x8DCE, 0xF5C9, 0x8DCF, 0xF5CA, 0x8DD0, 0xDA9D, 0x8DD1, 0xC5DC, 0x8DD2, 0xDA9E, + 0x8DD3, 0xDA9F, 0x8DD4, 0xDAA0, 0x8DD5, 0xDB40, 0x8DD6, 0xF5C5, 0x8DD7, 0xF5C6, 0x8DD8, 0xDB41, 0x8DD9, 0xDB42, 0x8DDA, 0xF5C7, + 0x8DDB, 0xF5CB, 0x8DDC, 0xDB43, 0x8DDD, 0xBEE0, 0x8DDE, 0xF5C8, 0x8DDF, 0xB8FA, 0x8DE0, 0xDB44, 0x8DE1, 0xDB45, 0x8DE2, 0xDB46, + 0x8DE3, 0xF5D0, 0x8DE4, 0xF5D3, 0x8DE5, 0xDB47, 0x8DE6, 0xDB48, 0x8DE7, 0xDB49, 0x8DE8, 0xBFE7, 0x8DE9, 0xDB4A, 0x8DEA, 0xB9F2, + 0x8DEB, 0xF5BC, 0x8DEC, 0xF5CD, 0x8DED, 0xDB4B, 0x8DEE, 0xDB4C, 0x8DEF, 0xC2B7, 0x8DF0, 0xDB4D, 0x8DF1, 0xDB4E, 0x8DF2, 0xDB4F, + 0x8DF3, 0xCCF8, 0x8DF4, 0xDB50, 0x8DF5, 0xBCF9, 0x8DF6, 0xDB51, 0x8DF7, 0xF5CE, 0x8DF8, 0xF5CF, 0x8DF9, 0xF5D1, 0x8DFA, 0xB6E5, + 0x8DFB, 0xF5D2, 0x8DFC, 0xDB52, 0x8DFD, 0xF5D5, 0x8DFE, 0xDB53, 0x8DFF, 0xDB54, 0x8E00, 0xDB55, 0x8E01, 0xDB56, 0x8E02, 0xDB57, + 0x8E03, 0xDB58, 0x8E04, 0xDB59, 0x8E05, 0xF5BD, 0x8E06, 0xDB5A, 0x8E07, 0xDB5B, 0x8E08, 0xDB5C, 0x8E09, 0xF5D4, 0x8E0A, 0xD3BB, + 0x8E0B, 0xDB5D, 0x8E0C, 0xB3EC, 0x8E0D, 0xDB5E, 0x8E0E, 0xDB5F, 0x8E0F, 0xCCA4, 0x8E10, 0xDB60, 0x8E11, 0xDB61, 0x8E12, 0xDB62, + 0x8E13, 0xDB63, 0x8E14, 0xF5D6, 0x8E15, 0xDB64, 0x8E16, 0xDB65, 0x8E17, 0xDB66, 0x8E18, 0xDB67, 0x8E19, 0xDB68, 0x8E1A, 0xDB69, + 0x8E1B, 0xDB6A, 0x8E1C, 0xDB6B, 0x8E1D, 0xF5D7, 0x8E1E, 0xBEE1, 0x8E1F, 0xF5D8, 0x8E20, 0xDB6C, 0x8E21, 0xDB6D, 0x8E22, 0xCCDF, + 0x8E23, 0xF5DB, 0x8E24, 0xDB6E, 0x8E25, 0xDB6F, 0x8E26, 0xDB70, 0x8E27, 0xDB71, 0x8E28, 0xDB72, 0x8E29, 0xB2C8, 0x8E2A, 0xD7D9, + 0x8E2B, 0xDB73, 0x8E2C, 0xF5D9, 0x8E2D, 0xDB74, 0x8E2E, 0xF5DA, 0x8E2F, 0xF5DC, 0x8E30, 0xDB75, 0x8E31, 0xF5E2, 0x8E32, 0xDB76, + 0x8E33, 0xDB77, 0x8E34, 0xDB78, 0x8E35, 0xF5E0, 0x8E36, 0xDB79, 0x8E37, 0xDB7A, 0x8E38, 0xDB7B, 0x8E39, 0xF5DF, 0x8E3A, 0xF5DD, + 0x8E3B, 0xDB7C, 0x8E3C, 0xDB7D, 0x8E3D, 0xF5E1, 0x8E3E, 0xDB7E, 0x8E3F, 0xDB80, 0x8E40, 0xF5DE, 0x8E41, 0xF5E4, 0x8E42, 0xF5E5, + 0x8E43, 0xDB81, 0x8E44, 0xCCE3, 0x8E45, 0xDB82, 0x8E46, 0xDB83, 0x8E47, 0xE5BF, 0x8E48, 0xB5B8, 0x8E49, 0xF5E3, 0x8E4A, 0xF5E8, + 0x8E4B, 0xCCA3, 0x8E4C, 0xDB84, 0x8E4D, 0xDB85, 0x8E4E, 0xDB86, 0x8E4F, 0xDB87, 0x8E50, 0xDB88, 0x8E51, 0xF5E6, 0x8E52, 0xF5E7, + 0x8E53, 0xDB89, 0x8E54, 0xDB8A, 0x8E55, 0xDB8B, 0x8E56, 0xDB8C, 0x8E57, 0xDB8D, 0x8E58, 0xDB8E, 0x8E59, 0xF5BE, 0x8E5A, 0xDB8F, + 0x8E5B, 0xDB90, 0x8E5C, 0xDB91, 0x8E5D, 0xDB92, 0x8E5E, 0xDB93, 0x8E5F, 0xDB94, 0x8E60, 0xDB95, 0x8E61, 0xDB96, 0x8E62, 0xDB97, + 0x8E63, 0xDB98, 0x8E64, 0xDB99, 0x8E65, 0xDB9A, 0x8E66, 0xB1C4, 0x8E67, 0xDB9B, 0x8E68, 0xDB9C, 0x8E69, 0xF5BF, 0x8E6A, 0xDB9D, + 0x8E6B, 0xDB9E, 0x8E6C, 0xB5C5, 0x8E6D, 0xB2E4, 0x8E6E, 0xDB9F, 0x8E6F, 0xF5EC, 0x8E70, 0xF5E9, 0x8E71, 0xDBA0, 0x8E72, 0xB6D7, + 0x8E73, 0xDC40, 0x8E74, 0xF5ED, 0x8E75, 0xDC41, 0x8E76, 0xF5EA, 0x8E77, 0xDC42, 0x8E78, 0xDC43, 0x8E79, 0xDC44, 0x8E7A, 0xDC45, + 0x8E7B, 0xDC46, 0x8E7C, 0xF5EB, 0x8E7D, 0xDC47, 0x8E7E, 0xDC48, 0x8E7F, 0xB4DA, 0x8E80, 0xDC49, 0x8E81, 0xD4EA, 0x8E82, 0xDC4A, + 0x8E83, 0xDC4B, 0x8E84, 0xDC4C, 0x8E85, 0xF5EE, 0x8E86, 0xDC4D, 0x8E87, 0xB3F9, 0x8E88, 0xDC4E, 0x8E89, 0xDC4F, 0x8E8A, 0xDC50, + 0x8E8B, 0xDC51, 0x8E8C, 0xDC52, 0x8E8D, 0xDC53, 0x8E8E, 0xDC54, 0x8E8F, 0xF5EF, 0x8E90, 0xF5F1, 0x8E91, 0xDC55, 0x8E92, 0xDC56, + 0x8E93, 0xDC57, 0x8E94, 0xF5F0, 0x8E95, 0xDC58, 0x8E96, 0xDC59, 0x8E97, 0xDC5A, 0x8E98, 0xDC5B, 0x8E99, 0xDC5C, 0x8E9A, 0xDC5D, + 0x8E9B, 0xDC5E, 0x8E9C, 0xF5F2, 0x8E9D, 0xDC5F, 0x8E9E, 0xF5F3, 0x8E9F, 0xDC60, 0x8EA0, 0xDC61, 0x8EA1, 0xDC62, 0x8EA2, 0xDC63, + 0x8EA3, 0xDC64, 0x8EA4, 0xDC65, 0x8EA5, 0xDC66, 0x8EA6, 0xDC67, 0x8EA7, 0xDC68, 0x8EA8, 0xDC69, 0x8EA9, 0xDC6A, 0x8EAA, 0xDC6B, + 0x8EAB, 0xC9ED, 0x8EAC, 0xB9AA, 0x8EAD, 0xDC6C, 0x8EAE, 0xDC6D, 0x8EAF, 0xC7FB, 0x8EB0, 0xDC6E, 0x8EB1, 0xDC6F, 0x8EB2, 0xB6E3, + 0x8EB3, 0xDC70, 0x8EB4, 0xDC71, 0x8EB5, 0xDC72, 0x8EB6, 0xDC73, 0x8EB7, 0xDC74, 0x8EB8, 0xDC75, 0x8EB9, 0xDC76, 0x8EBA, 0xCCC9, + 0x8EBB, 0xDC77, 0x8EBC, 0xDC78, 0x8EBD, 0xDC79, 0x8EBE, 0xDC7A, 0x8EBF, 0xDC7B, 0x8EC0, 0xDC7C, 0x8EC1, 0xDC7D, 0x8EC2, 0xDC7E, + 0x8EC3, 0xDC80, 0x8EC4, 0xDC81, 0x8EC5, 0xDC82, 0x8EC6, 0xDC83, 0x8EC7, 0xDC84, 0x8EC8, 0xDC85, 0x8EC9, 0xDC86, 0x8ECA, 0xDC87, + 0x8ECB, 0xDC88, 0x8ECC, 0xDC89, 0x8ECD, 0xDC8A, 0x8ECE, 0xEAA6, 0x8ECF, 0xDC8B, 0x8ED0, 0xDC8C, 0x8ED1, 0xDC8D, 0x8ED2, 0xDC8E, + 0x8ED3, 0xDC8F, 0x8ED4, 0xDC90, 0x8ED5, 0xDC91, 0x8ED6, 0xDC92, 0x8ED7, 0xDC93, 0x8ED8, 0xDC94, 0x8ED9, 0xDC95, 0x8EDA, 0xDC96, + 0x8EDB, 0xDC97, 0x8EDC, 0xDC98, 0x8EDD, 0xDC99, 0x8EDE, 0xDC9A, 0x8EDF, 0xDC9B, 0x8EE0, 0xDC9C, 0x8EE1, 0xDC9D, 0x8EE2, 0xDC9E, + 0x8EE3, 0xDC9F, 0x8EE4, 0xDCA0, 0x8EE5, 0xDD40, 0x8EE6, 0xDD41, 0x8EE7, 0xDD42, 0x8EE8, 0xDD43, 0x8EE9, 0xDD44, 0x8EEA, 0xDD45, + 0x8EEB, 0xDD46, 0x8EEC, 0xDD47, 0x8EED, 0xDD48, 0x8EEE, 0xDD49, 0x8EEF, 0xDD4A, 0x8EF0, 0xDD4B, 0x8EF1, 0xDD4C, 0x8EF2, 0xDD4D, + 0x8EF3, 0xDD4E, 0x8EF4, 0xDD4F, 0x8EF5, 0xDD50, 0x8EF6, 0xDD51, 0x8EF7, 0xDD52, 0x8EF8, 0xDD53, 0x8EF9, 0xDD54, 0x8EFA, 0xDD55, + 0x8EFB, 0xDD56, 0x8EFC, 0xDD57, 0x8EFD, 0xDD58, 0x8EFE, 0xDD59, 0x8EFF, 0xDD5A, 0x8F00, 0xDD5B, 0x8F01, 0xDD5C, 0x8F02, 0xDD5D, + 0x8F03, 0xDD5E, 0x8F04, 0xDD5F, 0x8F05, 0xDD60, 0x8F06, 0xDD61, 0x8F07, 0xDD62, 0x8F08, 0xDD63, 0x8F09, 0xDD64, 0x8F0A, 0xDD65, + 0x8F0B, 0xDD66, 0x8F0C, 0xDD67, 0x8F0D, 0xDD68, 0x8F0E, 0xDD69, 0x8F0F, 0xDD6A, 0x8F10, 0xDD6B, 0x8F11, 0xDD6C, 0x8F12, 0xDD6D, + 0x8F13, 0xDD6E, 0x8F14, 0xDD6F, 0x8F15, 0xDD70, 0x8F16, 0xDD71, 0x8F17, 0xDD72, 0x8F18, 0xDD73, 0x8F19, 0xDD74, 0x8F1A, 0xDD75, + 0x8F1B, 0xDD76, 0x8F1C, 0xDD77, 0x8F1D, 0xDD78, 0x8F1E, 0xDD79, 0x8F1F, 0xDD7A, 0x8F20, 0xDD7B, 0x8F21, 0xDD7C, 0x8F22, 0xDD7D, + 0x8F23, 0xDD7E, 0x8F24, 0xDD80, 0x8F25, 0xDD81, 0x8F26, 0xDD82, 0x8F27, 0xDD83, 0x8F28, 0xDD84, 0x8F29, 0xDD85, 0x8F2A, 0xDD86, + 0x8F2B, 0xDD87, 0x8F2C, 0xDD88, 0x8F2D, 0xDD89, 0x8F2E, 0xDD8A, 0x8F2F, 0xDD8B, 0x8F30, 0xDD8C, 0x8F31, 0xDD8D, 0x8F32, 0xDD8E, + 0x8F33, 0xDD8F, 0x8F34, 0xDD90, 0x8F35, 0xDD91, 0x8F36, 0xDD92, 0x8F37, 0xDD93, 0x8F38, 0xDD94, 0x8F39, 0xDD95, 0x8F3A, 0xDD96, + 0x8F3B, 0xDD97, 0x8F3C, 0xDD98, 0x8F3D, 0xDD99, 0x8F3E, 0xDD9A, 0x8F3F, 0xDD9B, 0x8F40, 0xDD9C, 0x8F41, 0xDD9D, 0x8F42, 0xDD9E, + 0x8F43, 0xDD9F, 0x8F44, 0xDDA0, 0x8F45, 0xDE40, 0x8F46, 0xDE41, 0x8F47, 0xDE42, 0x8F48, 0xDE43, 0x8F49, 0xDE44, 0x8F4A, 0xDE45, + 0x8F4B, 0xDE46, 0x8F4C, 0xDE47, 0x8F4D, 0xDE48, 0x8F4E, 0xDE49, 0x8F4F, 0xDE4A, 0x8F50, 0xDE4B, 0x8F51, 0xDE4C, 0x8F52, 0xDE4D, + 0x8F53, 0xDE4E, 0x8F54, 0xDE4F, 0x8F55, 0xDE50, 0x8F56, 0xDE51, 0x8F57, 0xDE52, 0x8F58, 0xDE53, 0x8F59, 0xDE54, 0x8F5A, 0xDE55, + 0x8F5B, 0xDE56, 0x8F5C, 0xDE57, 0x8F5D, 0xDE58, 0x8F5E, 0xDE59, 0x8F5F, 0xDE5A, 0x8F60, 0xDE5B, 0x8F61, 0xDE5C, 0x8F62, 0xDE5D, + 0x8F63, 0xDE5E, 0x8F64, 0xDE5F, 0x8F65, 0xDE60, 0x8F66, 0xB3B5, 0x8F67, 0xD4FE, 0x8F68, 0xB9EC, 0x8F69, 0xD0F9, 0x8F6A, 0xDE61, + 0x8F6B, 0xE9ED, 0x8F6C, 0xD7AA, 0x8F6D, 0xE9EE, 0x8F6E, 0xC2D6, 0x8F6F, 0xC8ED, 0x8F70, 0xBAE4, 0x8F71, 0xE9EF, 0x8F72, 0xE9F0, + 0x8F73, 0xE9F1, 0x8F74, 0xD6E1, 0x8F75, 0xE9F2, 0x8F76, 0xE9F3, 0x8F77, 0xE9F5, 0x8F78, 0xE9F4, 0x8F79, 0xE9F6, 0x8F7A, 0xE9F7, + 0x8F7B, 0xC7E1, 0x8F7C, 0xE9F8, 0x8F7D, 0xD4D8, 0x8F7E, 0xE9F9, 0x8F7F, 0xBDCE, 0x8F80, 0xDE62, 0x8F81, 0xE9FA, 0x8F82, 0xE9FB, + 0x8F83, 0xBDCF, 0x8F84, 0xE9FC, 0x8F85, 0xB8A8, 0x8F86, 0xC1BE, 0x8F87, 0xE9FD, 0x8F88, 0xB1B2, 0x8F89, 0xBBD4, 0x8F8A, 0xB9F5, + 0x8F8B, 0xE9FE, 0x8F8C, 0xDE63, 0x8F8D, 0xEAA1, 0x8F8E, 0xEAA2, 0x8F8F, 0xEAA3, 0x8F90, 0xB7F8, 0x8F91, 0xBCAD, 0x8F92, 0xDE64, + 0x8F93, 0xCAE4, 0x8F94, 0xE0CE, 0x8F95, 0xD4AF, 0x8F96, 0xCFBD, 0x8F97, 0xD5B7, 0x8F98, 0xEAA4, 0x8F99, 0xD5DE, 0x8F9A, 0xEAA5, + 0x8F9B, 0xD0C1, 0x8F9C, 0xB9BC, 0x8F9D, 0xDE65, 0x8F9E, 0xB4C7, 0x8F9F, 0xB1D9, 0x8FA0, 0xDE66, 0x8FA1, 0xDE67, 0x8FA2, 0xDE68, + 0x8FA3, 0xC0B1, 0x8FA4, 0xDE69, 0x8FA5, 0xDE6A, 0x8FA6, 0xDE6B, 0x8FA7, 0xDE6C, 0x8FA8, 0xB1E6, 0x8FA9, 0xB1E7, 0x8FAA, 0xDE6D, + 0x8FAB, 0xB1E8, 0x8FAC, 0xDE6E, 0x8FAD, 0xDE6F, 0x8FAE, 0xDE70, 0x8FAF, 0xDE71, 0x8FB0, 0xB3BD, 0x8FB1, 0xC8E8, 0x8FB2, 0xDE72, + 0x8FB3, 0xDE73, 0x8FB4, 0xDE74, 0x8FB5, 0xDE75, 0x8FB6, 0xE5C1, 0x8FB7, 0xDE76, 0x8FB8, 0xDE77, 0x8FB9, 0xB1DF, 0x8FBA, 0xDE78, + 0x8FBB, 0xDE79, 0x8FBC, 0xDE7A, 0x8FBD, 0xC1C9, 0x8FBE, 0xB4EF, 0x8FBF, 0xDE7B, 0x8FC0, 0xDE7C, 0x8FC1, 0xC7A8, 0x8FC2, 0xD3D8, + 0x8FC3, 0xDE7D, 0x8FC4, 0xC6F9, 0x8FC5, 0xD1B8, 0x8FC6, 0xDE7E, 0x8FC7, 0xB9FD, 0x8FC8, 0xC2F5, 0x8FC9, 0xDE80, 0x8FCA, 0xDE81, + 0x8FCB, 0xDE82, 0x8FCC, 0xDE83, 0x8FCD, 0xDE84, 0x8FCE, 0xD3AD, 0x8FCF, 0xDE85, 0x8FD0, 0xD4CB, 0x8FD1, 0xBDFC, 0x8FD2, 0xDE86, + 0x8FD3, 0xE5C2, 0x8FD4, 0xB7B5, 0x8FD5, 0xE5C3, 0x8FD6, 0xDE87, 0x8FD7, 0xDE88, 0x8FD8, 0xBBB9, 0x8FD9, 0xD5E2, 0x8FDA, 0xDE89, + 0x8FDB, 0xBDF8, 0x8FDC, 0xD4B6, 0x8FDD, 0xCEA5, 0x8FDE, 0xC1AC, 0x8FDF, 0xB3D9, 0x8FE0, 0xDE8A, 0x8FE1, 0xDE8B, 0x8FE2, 0xCCF6, + 0x8FE3, 0xDE8C, 0x8FE4, 0xE5C6, 0x8FE5, 0xE5C4, 0x8FE6, 0xE5C8, 0x8FE7, 0xDE8D, 0x8FE8, 0xE5CA, 0x8FE9, 0xE5C7, 0x8FEA, 0xB5CF, + 0x8FEB, 0xC6C8, 0x8FEC, 0xDE8E, 0x8FED, 0xB5FC, 0x8FEE, 0xE5C5, 0x8FEF, 0xDE8F, 0x8FF0, 0xCAF6, 0x8FF1, 0xDE90, 0x8FF2, 0xDE91, + 0x8FF3, 0xE5C9, 0x8FF4, 0xDE92, 0x8FF5, 0xDE93, 0x8FF6, 0xDE94, 0x8FF7, 0xC3D4, 0x8FF8, 0xB1C5, 0x8FF9, 0xBCA3, 0x8FFA, 0xDE95, + 0x8FFB, 0xDE96, 0x8FFC, 0xDE97, 0x8FFD, 0xD7B7, 0x8FFE, 0xDE98, 0x8FFF, 0xDE99, 0x9000, 0xCDCB, 0x9001, 0xCBCD, 0x9002, 0xCACA, + 0x9003, 0xCCD3, 0x9004, 0xE5CC, 0x9005, 0xE5CB, 0x9006, 0xC4E6, 0x9007, 0xDE9A, 0x9008, 0xDE9B, 0x9009, 0xD1A1, 0x900A, 0xD1B7, + 0x900B, 0xE5CD, 0x900C, 0xDE9C, 0x900D, 0xE5D0, 0x900E, 0xDE9D, 0x900F, 0xCDB8, 0x9010, 0xD6F0, 0x9011, 0xE5CF, 0x9012, 0xB5DD, + 0x9013, 0xDE9E, 0x9014, 0xCDBE, 0x9015, 0xDE9F, 0x9016, 0xE5D1, 0x9017, 0xB6BA, 0x9018, 0xDEA0, 0x9019, 0xDF40, 0x901A, 0xCDA8, + 0x901B, 0xB9E4, 0x901C, 0xDF41, 0x901D, 0xCAC5, 0x901E, 0xB3D1, 0x901F, 0xCBD9, 0x9020, 0xD4EC, 0x9021, 0xE5D2, 0x9022, 0xB7EA, + 0x9023, 0xDF42, 0x9024, 0xDF43, 0x9025, 0xDF44, 0x9026, 0xE5CE, 0x9027, 0xDF45, 0x9028, 0xDF46, 0x9029, 0xDF47, 0x902A, 0xDF48, + 0x902B, 0xDF49, 0x902C, 0xDF4A, 0x902D, 0xE5D5, 0x902E, 0xB4FE, 0x902F, 0xE5D6, 0x9030, 0xDF4B, 0x9031, 0xDF4C, 0x9032, 0xDF4D, + 0x9033, 0xDF4E, 0x9034, 0xDF4F, 0x9035, 0xE5D3, 0x9036, 0xE5D4, 0x9037, 0xDF50, 0x9038, 0xD2DD, 0x9039, 0xDF51, 0x903A, 0xDF52, + 0x903B, 0xC2DF, 0x903C, 0xB1C6, 0x903D, 0xDF53, 0x903E, 0xD3E2, 0x903F, 0xDF54, 0x9040, 0xDF55, 0x9041, 0xB6DD, 0x9042, 0xCBEC, + 0x9043, 0xDF56, 0x9044, 0xE5D7, 0x9045, 0xDF57, 0x9046, 0xDF58, 0x9047, 0xD3F6, 0x9048, 0xDF59, 0x9049, 0xDF5A, 0x904A, 0xDF5B, + 0x904B, 0xDF5C, 0x904C, 0xDF5D, 0x904D, 0xB1E9, 0x904E, 0xDF5E, 0x904F, 0xB6F4, 0x9050, 0xE5DA, 0x9051, 0xE5D8, 0x9052, 0xE5D9, + 0x9053, 0xB5C0, 0x9054, 0xDF5F, 0x9055, 0xDF60, 0x9056, 0xDF61, 0x9057, 0xD2C5, 0x9058, 0xE5DC, 0x9059, 0xDF62, 0x905A, 0xDF63, + 0x905B, 0xE5DE, 0x905C, 0xDF64, 0x905D, 0xDF65, 0x905E, 0xDF66, 0x905F, 0xDF67, 0x9060, 0xDF68, 0x9061, 0xDF69, 0x9062, 0xE5DD, + 0x9063, 0xC7B2, 0x9064, 0xDF6A, 0x9065, 0xD2A3, 0x9066, 0xDF6B, 0x9067, 0xDF6C, 0x9068, 0xE5DB, 0x9069, 0xDF6D, 0x906A, 0xDF6E, + 0x906B, 0xDF6F, 0x906C, 0xDF70, 0x906D, 0xD4E2, 0x906E, 0xD5DA, 0x906F, 0xDF71, 0x9070, 0xDF72, 0x9071, 0xDF73, 0x9072, 0xDF74, + 0x9073, 0xDF75, 0x9074, 0xE5E0, 0x9075, 0xD7F1, 0x9076, 0xDF76, 0x9077, 0xDF77, 0x9078, 0xDF78, 0x9079, 0xDF79, 0x907A, 0xDF7A, + 0x907B, 0xDF7B, 0x907C, 0xDF7C, 0x907D, 0xE5E1, 0x907E, 0xDF7D, 0x907F, 0xB1DC, 0x9080, 0xD1FB, 0x9081, 0xDF7E, 0x9082, 0xE5E2, + 0x9083, 0xE5E4, 0x9084, 0xDF80, 0x9085, 0xDF81, 0x9086, 0xDF82, 0x9087, 0xDF83, 0x9088, 0xE5E3, 0x9089, 0xDF84, 0x908A, 0xDF85, + 0x908B, 0xE5E5, 0x908C, 0xDF86, 0x908D, 0xDF87, 0x908E, 0xDF88, 0x908F, 0xDF89, 0x9090, 0xDF8A, 0x9091, 0xD2D8, 0x9092, 0xDF8B, + 0x9093, 0xB5CB, 0x9094, 0xDF8C, 0x9095, 0xE7DF, 0x9096, 0xDF8D, 0x9097, 0xDAF5, 0x9098, 0xDF8E, 0x9099, 0xDAF8, 0x909A, 0xDF8F, + 0x909B, 0xDAF6, 0x909C, 0xDF90, 0x909D, 0xDAF7, 0x909E, 0xDF91, 0x909F, 0xDF92, 0x90A0, 0xDF93, 0x90A1, 0xDAFA, 0x90A2, 0xD0CF, + 0x90A3, 0xC4C7, 0x90A4, 0xDF94, 0x90A5, 0xDF95, 0x90A6, 0xB0EE, 0x90A7, 0xDF96, 0x90A8, 0xDF97, 0x90A9, 0xDF98, 0x90AA, 0xD0B0, + 0x90AB, 0xDF99, 0x90AC, 0xDAF9, 0x90AD, 0xDF9A, 0x90AE, 0xD3CA, 0x90AF, 0xBAAA, 0x90B0, 0xDBA2, 0x90B1, 0xC7F1, 0x90B2, 0xDF9B, + 0x90B3, 0xDAFC, 0x90B4, 0xDAFB, 0x90B5, 0xC9DB, 0x90B6, 0xDAFD, 0x90B7, 0xDF9C, 0x90B8, 0xDBA1, 0x90B9, 0xD7DE, 0x90BA, 0xDAFE, + 0x90BB, 0xC1DA, 0x90BC, 0xDF9D, 0x90BD, 0xDF9E, 0x90BE, 0xDBA5, 0x90BF, 0xDF9F, 0x90C0, 0xDFA0, 0x90C1, 0xD3F4, 0x90C2, 0xE040, + 0x90C3, 0xE041, 0x90C4, 0xDBA7, 0x90C5, 0xDBA4, 0x90C6, 0xE042, 0x90C7, 0xDBA8, 0x90C8, 0xE043, 0x90C9, 0xE044, 0x90CA, 0xBDBC, + 0x90CB, 0xE045, 0x90CC, 0xE046, 0x90CD, 0xE047, 0x90CE, 0xC0C9, 0x90CF, 0xDBA3, 0x90D0, 0xDBA6, 0x90D1, 0xD6A3, 0x90D2, 0xE048, + 0x90D3, 0xDBA9, 0x90D4, 0xE049, 0x90D5, 0xE04A, 0x90D6, 0xE04B, 0x90D7, 0xDBAD, 0x90D8, 0xE04C, 0x90D9, 0xE04D, 0x90DA, 0xE04E, + 0x90DB, 0xDBAE, 0x90DC, 0xDBAC, 0x90DD, 0xBAC2, 0x90DE, 0xE04F, 0x90DF, 0xE050, 0x90E0, 0xE051, 0x90E1, 0xBFA4, 0x90E2, 0xDBAB, + 0x90E3, 0xE052, 0x90E4, 0xE053, 0x90E5, 0xE054, 0x90E6, 0xDBAA, 0x90E7, 0xD4C7, 0x90E8, 0xB2BF, 0x90E9, 0xE055, 0x90EA, 0xE056, + 0x90EB, 0xDBAF, 0x90EC, 0xE057, 0x90ED, 0xB9F9, 0x90EE, 0xE058, 0x90EF, 0xDBB0, 0x90F0, 0xE059, 0x90F1, 0xE05A, 0x90F2, 0xE05B, + 0x90F3, 0xE05C, 0x90F4, 0xB3BB, 0x90F5, 0xE05D, 0x90F6, 0xE05E, 0x90F7, 0xE05F, 0x90F8, 0xB5A6, 0x90F9, 0xE060, 0x90FA, 0xE061, + 0x90FB, 0xE062, 0x90FC, 0xE063, 0x90FD, 0xB6BC, 0x90FE, 0xDBB1, 0x90FF, 0xE064, 0x9100, 0xE065, 0x9101, 0xE066, 0x9102, 0xB6F5, + 0x9103, 0xE067, 0x9104, 0xDBB2, 0x9105, 0xE068, 0x9106, 0xE069, 0x9107, 0xE06A, 0x9108, 0xE06B, 0x9109, 0xE06C, 0x910A, 0xE06D, + 0x910B, 0xE06E, 0x910C, 0xE06F, 0x910D, 0xE070, 0x910E, 0xE071, 0x910F, 0xE072, 0x9110, 0xE073, 0x9111, 0xE074, 0x9112, 0xE075, + 0x9113, 0xE076, 0x9114, 0xE077, 0x9115, 0xE078, 0x9116, 0xE079, 0x9117, 0xE07A, 0x9118, 0xE07B, 0x9119, 0xB1C9, 0x911A, 0xE07C, + 0x911B, 0xE07D, 0x911C, 0xE07E, 0x911D, 0xE080, 0x911E, 0xDBB4, 0x911F, 0xE081, 0x9120, 0xE082, 0x9121, 0xE083, 0x9122, 0xDBB3, + 0x9123, 0xDBB5, 0x9124, 0xE084, 0x9125, 0xE085, 0x9126, 0xE086, 0x9127, 0xE087, 0x9128, 0xE088, 0x9129, 0xE089, 0x912A, 0xE08A, + 0x912B, 0xE08B, 0x912C, 0xE08C, 0x912D, 0xE08D, 0x912E, 0xE08E, 0x912F, 0xDBB7, 0x9130, 0xE08F, 0x9131, 0xDBB6, 0x9132, 0xE090, + 0x9133, 0xE091, 0x9134, 0xE092, 0x9135, 0xE093, 0x9136, 0xE094, 0x9137, 0xE095, 0x9138, 0xE096, 0x9139, 0xDBB8, 0x913A, 0xE097, + 0x913B, 0xE098, 0x913C, 0xE099, 0x913D, 0xE09A, 0x913E, 0xE09B, 0x913F, 0xE09C, 0x9140, 0xE09D, 0x9141, 0xE09E, 0x9142, 0xE09F, + 0x9143, 0xDBB9, 0x9144, 0xE0A0, 0x9145, 0xE140, 0x9146, 0xDBBA, 0x9147, 0xE141, 0x9148, 0xE142, 0x9149, 0xD3CF, 0x914A, 0xF4FA, + 0x914B, 0xC7F5, 0x914C, 0xD7C3, 0x914D, 0xC5E4, 0x914E, 0xF4FC, 0x914F, 0xF4FD, 0x9150, 0xF4FB, 0x9151, 0xE143, 0x9152, 0xBEC6, + 0x9153, 0xE144, 0x9154, 0xE145, 0x9155, 0xE146, 0x9156, 0xE147, 0x9157, 0xD0EF, 0x9158, 0xE148, 0x9159, 0xE149, 0x915A, 0xB7D3, + 0x915B, 0xE14A, 0x915C, 0xE14B, 0x915D, 0xD4CD, 0x915E, 0xCCAA, 0x915F, 0xE14C, 0x9160, 0xE14D, 0x9161, 0xF5A2, 0x9162, 0xF5A1, + 0x9163, 0xBAA8, 0x9164, 0xF4FE, 0x9165, 0xCBD6, 0x9166, 0xE14E, 0x9167, 0xE14F, 0x9168, 0xE150, 0x9169, 0xF5A4, 0x916A, 0xC0D2, + 0x916B, 0xE151, 0x916C, 0xB3EA, 0x916D, 0xE152, 0x916E, 0xCDAA, 0x916F, 0xF5A5, 0x9170, 0xF5A3, 0x9171, 0xBDB4, 0x9172, 0xF5A8, + 0x9173, 0xE153, 0x9174, 0xF5A9, 0x9175, 0xBDCD, 0x9176, 0xC3B8, 0x9177, 0xBFE1, 0x9178, 0xCBE1, 0x9179, 0xF5AA, 0x917A, 0xE154, + 0x917B, 0xE155, 0x917C, 0xE156, 0x917D, 0xF5A6, 0x917E, 0xF5A7, 0x917F, 0xC4F0, 0x9180, 0xE157, 0x9181, 0xE158, 0x9182, 0xE159, + 0x9183, 0xE15A, 0x9184, 0xE15B, 0x9185, 0xF5AC, 0x9186, 0xE15C, 0x9187, 0xB4BC, 0x9188, 0xE15D, 0x9189, 0xD7ED, 0x918A, 0xE15E, + 0x918B, 0xB4D7, 0x918C, 0xF5AB, 0x918D, 0xF5AE, 0x918E, 0xE15F, 0x918F, 0xE160, 0x9190, 0xF5AD, 0x9191, 0xF5AF, 0x9192, 0xD0D1, + 0x9193, 0xE161, 0x9194, 0xE162, 0x9195, 0xE163, 0x9196, 0xE164, 0x9197, 0xE165, 0x9198, 0xE166, 0x9199, 0xE167, 0x919A, 0xC3D1, + 0x919B, 0xC8A9, 0x919C, 0xE168, 0x919D, 0xE169, 0x919E, 0xE16A, 0x919F, 0xE16B, 0x91A0, 0xE16C, 0x91A1, 0xE16D, 0x91A2, 0xF5B0, + 0x91A3, 0xF5B1, 0x91A4, 0xE16E, 0x91A5, 0xE16F, 0x91A6, 0xE170, 0x91A7, 0xE171, 0x91A8, 0xE172, 0x91A9, 0xE173, 0x91AA, 0xF5B2, + 0x91AB, 0xE174, 0x91AC, 0xE175, 0x91AD, 0xF5B3, 0x91AE, 0xF5B4, 0x91AF, 0xF5B5, 0x91B0, 0xE176, 0x91B1, 0xE177, 0x91B2, 0xE178, + 0x91B3, 0xE179, 0x91B4, 0xF5B7, 0x91B5, 0xF5B6, 0x91B6, 0xE17A, 0x91B7, 0xE17B, 0x91B8, 0xE17C, 0x91B9, 0xE17D, 0x91BA, 0xF5B8, + 0x91BB, 0xE17E, 0x91BC, 0xE180, 0x91BD, 0xE181, 0x91BE, 0xE182, 0x91BF, 0xE183, 0x91C0, 0xE184, 0x91C1, 0xE185, 0x91C2, 0xE186, + 0x91C3, 0xE187, 0x91C4, 0xE188, 0x91C5, 0xE189, 0x91C6, 0xE18A, 0x91C7, 0xB2C9, 0x91C8, 0xE18B, 0x91C9, 0xD3D4, 0x91CA, 0xCACD, + 0x91CB, 0xE18C, 0x91CC, 0xC0EF, 0x91CD, 0xD6D8, 0x91CE, 0xD2B0, 0x91CF, 0xC1BF, 0x91D0, 0xE18D, 0x91D1, 0xBDF0, 0x91D2, 0xE18E, + 0x91D3, 0xE18F, 0x91D4, 0xE190, 0x91D5, 0xE191, 0x91D6, 0xE192, 0x91D7, 0xE193, 0x91D8, 0xE194, 0x91D9, 0xE195, 0x91DA, 0xE196, + 0x91DB, 0xE197, 0x91DC, 0xB8AA, 0x91DD, 0xE198, 0x91DE, 0xE199, 0x91DF, 0xE19A, 0x91E0, 0xE19B, 0x91E1, 0xE19C, 0x91E2, 0xE19D, + 0x91E3, 0xE19E, 0x91E4, 0xE19F, 0x91E5, 0xE1A0, 0x91E6, 0xE240, 0x91E7, 0xE241, 0x91E8, 0xE242, 0x91E9, 0xE243, 0x91EA, 0xE244, + 0x91EB, 0xE245, 0x91EC, 0xE246, 0x91ED, 0xE247, 0x91EE, 0xE248, 0x91EF, 0xE249, 0x91F0, 0xE24A, 0x91F1, 0xE24B, 0x91F2, 0xE24C, + 0x91F3, 0xE24D, 0x91F4, 0xE24E, 0x91F5, 0xE24F, 0x91F6, 0xE250, 0x91F7, 0xE251, 0x91F8, 0xE252, 0x91F9, 0xE253, 0x91FA, 0xE254, + 0x91FB, 0xE255, 0x91FC, 0xE256, 0x91FD, 0xE257, 0x91FE, 0xE258, 0x91FF, 0xE259, 0x9200, 0xE25A, 0x9201, 0xE25B, 0x9202, 0xE25C, + 0x9203, 0xE25D, 0x9204, 0xE25E, 0x9205, 0xE25F, 0x9206, 0xE260, 0x9207, 0xE261, 0x9208, 0xE262, 0x9209, 0xE263, 0x920A, 0xE264, + 0x920B, 0xE265, 0x920C, 0xE266, 0x920D, 0xE267, 0x920E, 0xE268, 0x920F, 0xE269, 0x9210, 0xE26A, 0x9211, 0xE26B, 0x9212, 0xE26C, + 0x9213, 0xE26D, 0x9214, 0xE26E, 0x9215, 0xE26F, 0x9216, 0xE270, 0x9217, 0xE271, 0x9218, 0xE272, 0x9219, 0xE273, 0x921A, 0xE274, + 0x921B, 0xE275, 0x921C, 0xE276, 0x921D, 0xE277, 0x921E, 0xE278, 0x921F, 0xE279, 0x9220, 0xE27A, 0x9221, 0xE27B, 0x9222, 0xE27C, + 0x9223, 0xE27D, 0x9224, 0xE27E, 0x9225, 0xE280, 0x9226, 0xE281, 0x9227, 0xE282, 0x9228, 0xE283, 0x9229, 0xE284, 0x922A, 0xE285, + 0x922B, 0xE286, 0x922C, 0xE287, 0x922D, 0xE288, 0x922E, 0xE289, 0x922F, 0xE28A, 0x9230, 0xE28B, 0x9231, 0xE28C, 0x9232, 0xE28D, + 0x9233, 0xE28E, 0x9234, 0xE28F, 0x9235, 0xE290, 0x9236, 0xE291, 0x9237, 0xE292, 0x9238, 0xE293, 0x9239, 0xE294, 0x923A, 0xE295, + 0x923B, 0xE296, 0x923C, 0xE297, 0x923D, 0xE298, 0x923E, 0xE299, 0x923F, 0xE29A, 0x9240, 0xE29B, 0x9241, 0xE29C, 0x9242, 0xE29D, + 0x9243, 0xE29E, 0x9244, 0xE29F, 0x9245, 0xE2A0, 0x9246, 0xE340, 0x9247, 0xE341, 0x9248, 0xE342, 0x9249, 0xE343, 0x924A, 0xE344, + 0x924B, 0xE345, 0x924C, 0xE346, 0x924D, 0xE347, 0x924E, 0xE348, 0x924F, 0xE349, 0x9250, 0xE34A, 0x9251, 0xE34B, 0x9252, 0xE34C, + 0x9253, 0xE34D, 0x9254, 0xE34E, 0x9255, 0xE34F, 0x9256, 0xE350, 0x9257, 0xE351, 0x9258, 0xE352, 0x9259, 0xE353, 0x925A, 0xE354, + 0x925B, 0xE355, 0x925C, 0xE356, 0x925D, 0xE357, 0x925E, 0xE358, 0x925F, 0xE359, 0x9260, 0xE35A, 0x9261, 0xE35B, 0x9262, 0xE35C, + 0x9263, 0xE35D, 0x9264, 0xE35E, 0x9265, 0xE35F, 0x9266, 0xE360, 0x9267, 0xE361, 0x9268, 0xE362, 0x9269, 0xE363, 0x926A, 0xE364, + 0x926B, 0xE365, 0x926C, 0xE366, 0x926D, 0xE367, 0x926E, 0xE368, 0x926F, 0xE369, 0x9270, 0xE36A, 0x9271, 0xE36B, 0x9272, 0xE36C, + 0x9273, 0xE36D, 0x9274, 0xBCF8, 0x9275, 0xE36E, 0x9276, 0xE36F, 0x9277, 0xE370, 0x9278, 0xE371, 0x9279, 0xE372, 0x927A, 0xE373, + 0x927B, 0xE374, 0x927C, 0xE375, 0x927D, 0xE376, 0x927E, 0xE377, 0x927F, 0xE378, 0x9280, 0xE379, 0x9281, 0xE37A, 0x9282, 0xE37B, + 0x9283, 0xE37C, 0x9284, 0xE37D, 0x9285, 0xE37E, 0x9286, 0xE380, 0x9287, 0xE381, 0x9288, 0xE382, 0x9289, 0xE383, 0x928A, 0xE384, + 0x928B, 0xE385, 0x928C, 0xE386, 0x928D, 0xE387, 0x928E, 0xF6C6, 0x928F, 0xE388, 0x9290, 0xE389, 0x9291, 0xE38A, 0x9292, 0xE38B, + 0x9293, 0xE38C, 0x9294, 0xE38D, 0x9295, 0xE38E, 0x9296, 0xE38F, 0x9297, 0xE390, 0x9298, 0xE391, 0x9299, 0xE392, 0x929A, 0xE393, + 0x929B, 0xE394, 0x929C, 0xE395, 0x929D, 0xE396, 0x929E, 0xE397, 0x929F, 0xE398, 0x92A0, 0xE399, 0x92A1, 0xE39A, 0x92A2, 0xE39B, + 0x92A3, 0xE39C, 0x92A4, 0xE39D, 0x92A5, 0xE39E, 0x92A6, 0xE39F, 0x92A7, 0xE3A0, 0x92A8, 0xE440, 0x92A9, 0xE441, 0x92AA, 0xE442, + 0x92AB, 0xE443, 0x92AC, 0xE444, 0x92AD, 0xE445, 0x92AE, 0xF6C7, 0x92AF, 0xE446, 0x92B0, 0xE447, 0x92B1, 0xE448, 0x92B2, 0xE449, + 0x92B3, 0xE44A, 0x92B4, 0xE44B, 0x92B5, 0xE44C, 0x92B6, 0xE44D, 0x92B7, 0xE44E, 0x92B8, 0xE44F, 0x92B9, 0xE450, 0x92BA, 0xE451, + 0x92BB, 0xE452, 0x92BC, 0xE453, 0x92BD, 0xE454, 0x92BE, 0xE455, 0x92BF, 0xE456, 0x92C0, 0xE457, 0x92C1, 0xE458, 0x92C2, 0xE459, + 0x92C3, 0xE45A, 0x92C4, 0xE45B, 0x92C5, 0xE45C, 0x92C6, 0xE45D, 0x92C7, 0xE45E, 0x92C8, 0xF6C8, 0x92C9, 0xE45F, 0x92CA, 0xE460, + 0x92CB, 0xE461, 0x92CC, 0xE462, 0x92CD, 0xE463, 0x92CE, 0xE464, 0x92CF, 0xE465, 0x92D0, 0xE466, 0x92D1, 0xE467, 0x92D2, 0xE468, + 0x92D3, 0xE469, 0x92D4, 0xE46A, 0x92D5, 0xE46B, 0x92D6, 0xE46C, 0x92D7, 0xE46D, 0x92D8, 0xE46E, 0x92D9, 0xE46F, 0x92DA, 0xE470, + 0x92DB, 0xE471, 0x92DC, 0xE472, 0x92DD, 0xE473, 0x92DE, 0xE474, 0x92DF, 0xE475, 0x92E0, 0xE476, 0x92E1, 0xE477, 0x92E2, 0xE478, + 0x92E3, 0xE479, 0x92E4, 0xE47A, 0x92E5, 0xE47B, 0x92E6, 0xE47C, 0x92E7, 0xE47D, 0x92E8, 0xE47E, 0x92E9, 0xE480, 0x92EA, 0xE481, + 0x92EB, 0xE482, 0x92EC, 0xE483, 0x92ED, 0xE484, 0x92EE, 0xE485, 0x92EF, 0xE486, 0x92F0, 0xE487, 0x92F1, 0xE488, 0x92F2, 0xE489, + 0x92F3, 0xE48A, 0x92F4, 0xE48B, 0x92F5, 0xE48C, 0x92F6, 0xE48D, 0x92F7, 0xE48E, 0x92F8, 0xE48F, 0x92F9, 0xE490, 0x92FA, 0xE491, + 0x92FB, 0xE492, 0x92FC, 0xE493, 0x92FD, 0xE494, 0x92FE, 0xE495, 0x92FF, 0xE496, 0x9300, 0xE497, 0x9301, 0xE498, 0x9302, 0xE499, + 0x9303, 0xE49A, 0x9304, 0xE49B, 0x9305, 0xE49C, 0x9306, 0xE49D, 0x9307, 0xE49E, 0x9308, 0xE49F, 0x9309, 0xE4A0, 0x930A, 0xE540, + 0x930B, 0xE541, 0x930C, 0xE542, 0x930D, 0xE543, 0x930E, 0xE544, 0x930F, 0xE545, 0x9310, 0xE546, 0x9311, 0xE547, 0x9312, 0xE548, + 0x9313, 0xE549, 0x9314, 0xE54A, 0x9315, 0xE54B, 0x9316, 0xE54C, 0x9317, 0xE54D, 0x9318, 0xE54E, 0x9319, 0xE54F, 0x931A, 0xE550, + 0x931B, 0xE551, 0x931C, 0xE552, 0x931D, 0xE553, 0x931E, 0xE554, 0x931F, 0xE555, 0x9320, 0xE556, 0x9321, 0xE557, 0x9322, 0xE558, + 0x9323, 0xE559, 0x9324, 0xE55A, 0x9325, 0xE55B, 0x9326, 0xE55C, 0x9327, 0xE55D, 0x9328, 0xE55E, 0x9329, 0xE55F, 0x932A, 0xE560, + 0x932B, 0xE561, 0x932C, 0xE562, 0x932D, 0xE563, 0x932E, 0xE564, 0x932F, 0xE565, 0x9330, 0xE566, 0x9331, 0xE567, 0x9332, 0xE568, + 0x9333, 0xE569, 0x9334, 0xE56A, 0x9335, 0xE56B, 0x9336, 0xE56C, 0x9337, 0xE56D, 0x9338, 0xE56E, 0x9339, 0xE56F, 0x933A, 0xE570, + 0x933B, 0xE571, 0x933C, 0xE572, 0x933D, 0xE573, 0x933E, 0xF6C9, 0x933F, 0xE574, 0x9340, 0xE575, 0x9341, 0xE576, 0x9342, 0xE577, + 0x9343, 0xE578, 0x9344, 0xE579, 0x9345, 0xE57A, 0x9346, 0xE57B, 0x9347, 0xE57C, 0x9348, 0xE57D, 0x9349, 0xE57E, 0x934A, 0xE580, + 0x934B, 0xE581, 0x934C, 0xE582, 0x934D, 0xE583, 0x934E, 0xE584, 0x934F, 0xE585, 0x9350, 0xE586, 0x9351, 0xE587, 0x9352, 0xE588, + 0x9353, 0xE589, 0x9354, 0xE58A, 0x9355, 0xE58B, 0x9356, 0xE58C, 0x9357, 0xE58D, 0x9358, 0xE58E, 0x9359, 0xE58F, 0x935A, 0xE590, + 0x935B, 0xE591, 0x935C, 0xE592, 0x935D, 0xE593, 0x935E, 0xE594, 0x935F, 0xE595, 0x9360, 0xE596, 0x9361, 0xE597, 0x9362, 0xE598, + 0x9363, 0xE599, 0x9364, 0xE59A, 0x9365, 0xE59B, 0x9366, 0xE59C, 0x9367, 0xE59D, 0x9368, 0xE59E, 0x9369, 0xE59F, 0x936A, 0xF6CA, + 0x936B, 0xE5A0, 0x936C, 0xE640, 0x936D, 0xE641, 0x936E, 0xE642, 0x936F, 0xE643, 0x9370, 0xE644, 0x9371, 0xE645, 0x9372, 0xE646, + 0x9373, 0xE647, 0x9374, 0xE648, 0x9375, 0xE649, 0x9376, 0xE64A, 0x9377, 0xE64B, 0x9378, 0xE64C, 0x9379, 0xE64D, 0x937A, 0xE64E, + 0x937B, 0xE64F, 0x937C, 0xE650, 0x937D, 0xE651, 0x937E, 0xE652, 0x937F, 0xE653, 0x9380, 0xE654, 0x9381, 0xE655, 0x9382, 0xE656, + 0x9383, 0xE657, 0x9384, 0xE658, 0x9385, 0xE659, 0x9386, 0xE65A, 0x9387, 0xE65B, 0x9388, 0xE65C, 0x9389, 0xE65D, 0x938A, 0xE65E, + 0x938B, 0xE65F, 0x938C, 0xE660, 0x938D, 0xE661, 0x938E, 0xE662, 0x938F, 0xF6CC, 0x9390, 0xE663, 0x9391, 0xE664, 0x9392, 0xE665, + 0x9393, 0xE666, 0x9394, 0xE667, 0x9395, 0xE668, 0x9396, 0xE669, 0x9397, 0xE66A, 0x9398, 0xE66B, 0x9399, 0xE66C, 0x939A, 0xE66D, + 0x939B, 0xE66E, 0x939C, 0xE66F, 0x939D, 0xE670, 0x939E, 0xE671, 0x939F, 0xE672, 0x93A0, 0xE673, 0x93A1, 0xE674, 0x93A2, 0xE675, + 0x93A3, 0xE676, 0x93A4, 0xE677, 0x93A5, 0xE678, 0x93A6, 0xE679, 0x93A7, 0xE67A, 0x93A8, 0xE67B, 0x93A9, 0xE67C, 0x93AA, 0xE67D, + 0x93AB, 0xE67E, 0x93AC, 0xE680, 0x93AD, 0xE681, 0x93AE, 0xE682, 0x93AF, 0xE683, 0x93B0, 0xE684, 0x93B1, 0xE685, 0x93B2, 0xE686, + 0x93B3, 0xE687, 0x93B4, 0xE688, 0x93B5, 0xE689, 0x93B6, 0xE68A, 0x93B7, 0xE68B, 0x93B8, 0xE68C, 0x93B9, 0xE68D, 0x93BA, 0xE68E, + 0x93BB, 0xE68F, 0x93BC, 0xE690, 0x93BD, 0xE691, 0x93BE, 0xE692, 0x93BF, 0xE693, 0x93C0, 0xE694, 0x93C1, 0xE695, 0x93C2, 0xE696, + 0x93C3, 0xE697, 0x93C4, 0xE698, 0x93C5, 0xE699, 0x93C6, 0xE69A, 0x93C7, 0xE69B, 0x93C8, 0xE69C, 0x93C9, 0xE69D, 0x93CA, 0xF6CB, + 0x93CB, 0xE69E, 0x93CC, 0xE69F, 0x93CD, 0xE6A0, 0x93CE, 0xE740, 0x93CF, 0xE741, 0x93D0, 0xE742, 0x93D1, 0xE743, 0x93D2, 0xE744, + 0x93D3, 0xE745, 0x93D4, 0xE746, 0x93D5, 0xE747, 0x93D6, 0xF7E9, 0x93D7, 0xE748, 0x93D8, 0xE749, 0x93D9, 0xE74A, 0x93DA, 0xE74B, + 0x93DB, 0xE74C, 0x93DC, 0xE74D, 0x93DD, 0xE74E, 0x93DE, 0xE74F, 0x93DF, 0xE750, 0x93E0, 0xE751, 0x93E1, 0xE752, 0x93E2, 0xE753, + 0x93E3, 0xE754, 0x93E4, 0xE755, 0x93E5, 0xE756, 0x93E6, 0xE757, 0x93E7, 0xE758, 0x93E8, 0xE759, 0x93E9, 0xE75A, 0x93EA, 0xE75B, + 0x93EB, 0xE75C, 0x93EC, 0xE75D, 0x93ED, 0xE75E, 0x93EE, 0xE75F, 0x93EF, 0xE760, 0x93F0, 0xE761, 0x93F1, 0xE762, 0x93F2, 0xE763, + 0x93F3, 0xE764, 0x93F4, 0xE765, 0x93F5, 0xE766, 0x93F6, 0xE767, 0x93F7, 0xE768, 0x93F8, 0xE769, 0x93F9, 0xE76A, 0x93FA, 0xE76B, + 0x93FB, 0xE76C, 0x93FC, 0xE76D, 0x93FD, 0xE76E, 0x93FE, 0xE76F, 0x93FF, 0xE770, 0x9400, 0xE771, 0x9401, 0xE772, 0x9402, 0xE773, + 0x9403, 0xE774, 0x9404, 0xE775, 0x9405, 0xE776, 0x9406, 0xE777, 0x9407, 0xE778, 0x9408, 0xE779, 0x9409, 0xE77A, 0x940A, 0xE77B, + 0x940B, 0xE77C, 0x940C, 0xE77D, 0x940D, 0xE77E, 0x940E, 0xE780, 0x940F, 0xE781, 0x9410, 0xE782, 0x9411, 0xE783, 0x9412, 0xE784, + 0x9413, 0xE785, 0x9414, 0xE786, 0x9415, 0xE787, 0x9416, 0xE788, 0x9417, 0xE789, 0x9418, 0xE78A, 0x9419, 0xE78B, 0x941A, 0xE78C, + 0x941B, 0xE78D, 0x941C, 0xE78E, 0x941D, 0xE78F, 0x941E, 0xE790, 0x941F, 0xE791, 0x9420, 0xE792, 0x9421, 0xE793, 0x9422, 0xE794, + 0x9423, 0xE795, 0x9424, 0xE796, 0x9425, 0xE797, 0x9426, 0xE798, 0x9427, 0xE799, 0x9428, 0xE79A, 0x9429, 0xE79B, 0x942A, 0xE79C, + 0x942B, 0xE79D, 0x942C, 0xE79E, 0x942D, 0xE79F, 0x942E, 0xE7A0, 0x942F, 0xE840, 0x9430, 0xE841, 0x9431, 0xE842, 0x9432, 0xE843, + 0x9433, 0xE844, 0x9434, 0xE845, 0x9435, 0xE846, 0x9436, 0xE847, 0x9437, 0xE848, 0x9438, 0xE849, 0x9439, 0xE84A, 0x943A, 0xE84B, + 0x943B, 0xE84C, 0x943C, 0xE84D, 0x943D, 0xE84E, 0x943E, 0xF6CD, 0x943F, 0xE84F, 0x9440, 0xE850, 0x9441, 0xE851, 0x9442, 0xE852, + 0x9443, 0xE853, 0x9444, 0xE854, 0x9445, 0xE855, 0x9446, 0xE856, 0x9447, 0xE857, 0x9448, 0xE858, 0x9449, 0xE859, 0x944A, 0xE85A, + 0x944B, 0xE85B, 0x944C, 0xE85C, 0x944D, 0xE85D, 0x944E, 0xE85E, 0x944F, 0xE85F, 0x9450, 0xE860, 0x9451, 0xE861, 0x9452, 0xE862, + 0x9453, 0xE863, 0x9454, 0xE864, 0x9455, 0xE865, 0x9456, 0xE866, 0x9457, 0xE867, 0x9458, 0xE868, 0x9459, 0xE869, 0x945A, 0xE86A, + 0x945B, 0xE86B, 0x945C, 0xE86C, 0x945D, 0xE86D, 0x945E, 0xE86E, 0x945F, 0xE86F, 0x9460, 0xE870, 0x9461, 0xE871, 0x9462, 0xE872, + 0x9463, 0xE873, 0x9464, 0xE874, 0x9465, 0xE875, 0x9466, 0xE876, 0x9467, 0xE877, 0x9468, 0xE878, 0x9469, 0xE879, 0x946A, 0xE87A, + 0x946B, 0xF6CE, 0x946C, 0xE87B, 0x946D, 0xE87C, 0x946E, 0xE87D, 0x946F, 0xE87E, 0x9470, 0xE880, 0x9471, 0xE881, 0x9472, 0xE882, + 0x9473, 0xE883, 0x9474, 0xE884, 0x9475, 0xE885, 0x9476, 0xE886, 0x9477, 0xE887, 0x9478, 0xE888, 0x9479, 0xE889, 0x947A, 0xE88A, + 0x947B, 0xE88B, 0x947C, 0xE88C, 0x947D, 0xE88D, 0x947E, 0xE88E, 0x947F, 0xE88F, 0x9480, 0xE890, 0x9481, 0xE891, 0x9482, 0xE892, + 0x9483, 0xE893, 0x9484, 0xE894, 0x9485, 0xEEC4, 0x9486, 0xEEC5, 0x9487, 0xEEC6, 0x9488, 0xD5EB, 0x9489, 0xB6A4, 0x948A, 0xEEC8, + 0x948B, 0xEEC7, 0x948C, 0xEEC9, 0x948D, 0xEECA, 0x948E, 0xC7A5, 0x948F, 0xEECB, 0x9490, 0xEECC, 0x9491, 0xE895, 0x9492, 0xB7B0, + 0x9493, 0xB5F6, 0x9494, 0xEECD, 0x9495, 0xEECF, 0x9496, 0xE896, 0x9497, 0xEECE, 0x9498, 0xE897, 0x9499, 0xB8C6, 0x949A, 0xEED0, + 0x949B, 0xEED1, 0x949C, 0xEED2, 0x949D, 0xB6DB, 0x949E, 0xB3AE, 0x949F, 0xD6D3, 0x94A0, 0xC4C6, 0x94A1, 0xB1B5, 0x94A2, 0xB8D6, + 0x94A3, 0xEED3, 0x94A4, 0xEED4, 0x94A5, 0xD4BF, 0x94A6, 0xC7D5, 0x94A7, 0xBEFB, 0x94A8, 0xCED9, 0x94A9, 0xB9B3, 0x94AA, 0xEED6, + 0x94AB, 0xEED5, 0x94AC, 0xEED8, 0x94AD, 0xEED7, 0x94AE, 0xC5A5, 0x94AF, 0xEED9, 0x94B0, 0xEEDA, 0x94B1, 0xC7AE, 0x94B2, 0xEEDB, + 0x94B3, 0xC7AF, 0x94B4, 0xEEDC, 0x94B5, 0xB2A7, 0x94B6, 0xEEDD, 0x94B7, 0xEEDE, 0x94B8, 0xEEDF, 0x94B9, 0xEEE0, 0x94BA, 0xEEE1, + 0x94BB, 0xD7EA, 0x94BC, 0xEEE2, 0x94BD, 0xEEE3, 0x94BE, 0xBCD8, 0x94BF, 0xEEE4, 0x94C0, 0xD3CB, 0x94C1, 0xCCFA, 0x94C2, 0xB2AC, + 0x94C3, 0xC1E5, 0x94C4, 0xEEE5, 0x94C5, 0xC7A6, 0x94C6, 0xC3AD, 0x94C7, 0xE898, 0x94C8, 0xEEE6, 0x94C9, 0xEEE7, 0x94CA, 0xEEE8, + 0x94CB, 0xEEE9, 0x94CC, 0xEEEA, 0x94CD, 0xEEEB, 0x94CE, 0xEEEC, 0x94CF, 0xE899, 0x94D0, 0xEEED, 0x94D1, 0xEEEE, 0x94D2, 0xEEEF, + 0x94D3, 0xE89A, 0x94D4, 0xE89B, 0x94D5, 0xEEF0, 0x94D6, 0xEEF1, 0x94D7, 0xEEF2, 0x94D8, 0xEEF4, 0x94D9, 0xEEF3, 0x94DA, 0xE89C, + 0x94DB, 0xEEF5, 0x94DC, 0xCDAD, 0x94DD, 0xC2C1, 0x94DE, 0xEEF6, 0x94DF, 0xEEF7, 0x94E0, 0xEEF8, 0x94E1, 0xD5A1, 0x94E2, 0xEEF9, + 0x94E3, 0xCFB3, 0x94E4, 0xEEFA, 0x94E5, 0xEEFB, 0x94E6, 0xE89D, 0x94E7, 0xEEFC, 0x94E8, 0xEEFD, 0x94E9, 0xEFA1, 0x94EA, 0xEEFE, + 0x94EB, 0xEFA2, 0x94EC, 0xB8F5, 0x94ED, 0xC3FA, 0x94EE, 0xEFA3, 0x94EF, 0xEFA4, 0x94F0, 0xBDC2, 0x94F1, 0xD2BF, 0x94F2, 0xB2F9, + 0x94F3, 0xEFA5, 0x94F4, 0xEFA6, 0x94F5, 0xEFA7, 0x94F6, 0xD2F8, 0x94F7, 0xEFA8, 0x94F8, 0xD6FD, 0x94F9, 0xEFA9, 0x94FA, 0xC6CC, + 0x94FB, 0xE89E, 0x94FC, 0xEFAA, 0x94FD, 0xEFAB, 0x94FE, 0xC1B4, 0x94FF, 0xEFAC, 0x9500, 0xCFFA, 0x9501, 0xCBF8, 0x9502, 0xEFAE, + 0x9503, 0xEFAD, 0x9504, 0xB3FA, 0x9505, 0xB9F8, 0x9506, 0xEFAF, 0x9507, 0xEFB0, 0x9508, 0xD0E2, 0x9509, 0xEFB1, 0x950A, 0xEFB2, + 0x950B, 0xB7E6, 0x950C, 0xD0BF, 0x950D, 0xEFB3, 0x950E, 0xEFB4, 0x950F, 0xEFB5, 0x9510, 0xC8F1, 0x9511, 0xCCE0, 0x9512, 0xEFB6, + 0x9513, 0xEFB7, 0x9514, 0xEFB8, 0x9515, 0xEFB9, 0x9516, 0xEFBA, 0x9517, 0xD5E0, 0x9518, 0xEFBB, 0x9519, 0xB4ED, 0x951A, 0xC3AA, + 0x951B, 0xEFBC, 0x951C, 0xE89F, 0x951D, 0xEFBD, 0x951E, 0xEFBE, 0x951F, 0xEFBF, 0x9520, 0xE8A0, 0x9521, 0xCEFD, 0x9522, 0xEFC0, + 0x9523, 0xC2E0, 0x9524, 0xB4B8, 0x9525, 0xD7B6, 0x9526, 0xBDF5, 0x9527, 0xE940, 0x9528, 0xCFC7, 0x9529, 0xEFC3, 0x952A, 0xEFC1, + 0x952B, 0xEFC2, 0x952C, 0xEFC4, 0x952D, 0xB6A7, 0x952E, 0xBCFC, 0x952F, 0xBEE2, 0x9530, 0xC3CC, 0x9531, 0xEFC5, 0x9532, 0xEFC6, + 0x9533, 0xE941, 0x9534, 0xEFC7, 0x9535, 0xEFCF, 0x9536, 0xEFC8, 0x9537, 0xEFC9, 0x9538, 0xEFCA, 0x9539, 0xC7C2, 0x953A, 0xEFF1, + 0x953B, 0xB6CD, 0x953C, 0xEFCB, 0x953D, 0xE942, 0x953E, 0xEFCC, 0x953F, 0xEFCD, 0x9540, 0xB6C6, 0x9541, 0xC3BE, 0x9542, 0xEFCE, + 0x9543, 0xE943, 0x9544, 0xEFD0, 0x9545, 0xEFD1, 0x9546, 0xEFD2, 0x9547, 0xD5F2, 0x9548, 0xE944, 0x9549, 0xEFD3, 0x954A, 0xC4F7, + 0x954B, 0xE945, 0x954C, 0xEFD4, 0x954D, 0xC4F8, 0x954E, 0xEFD5, 0x954F, 0xEFD6, 0x9550, 0xB8E4, 0x9551, 0xB0F7, 0x9552, 0xEFD7, + 0x9553, 0xEFD8, 0x9554, 0xEFD9, 0x9555, 0xE946, 0x9556, 0xEFDA, 0x9557, 0xEFDB, 0x9558, 0xEFDC, 0x9559, 0xEFDD, 0x955A, 0xE947, + 0x955B, 0xEFDE, 0x955C, 0xBEB5, 0x955D, 0xEFE1, 0x955E, 0xEFDF, 0x955F, 0xEFE0, 0x9560, 0xE948, 0x9561, 0xEFE2, 0x9562, 0xEFE3, + 0x9563, 0xC1CD, 0x9564, 0xEFE4, 0x9565, 0xEFE5, 0x9566, 0xEFE6, 0x9567, 0xEFE7, 0x9568, 0xEFE8, 0x9569, 0xEFE9, 0x956A, 0xEFEA, + 0x956B, 0xEFEB, 0x956C, 0xEFEC, 0x956D, 0xC0D8, 0x956E, 0xE949, 0x956F, 0xEFED, 0x9570, 0xC1AD, 0x9571, 0xEFEE, 0x9572, 0xEFEF, + 0x9573, 0xEFF0, 0x9574, 0xE94A, 0x9575, 0xE94B, 0x9576, 0xCFE2, 0x9577, 0xE94C, 0x9578, 0xE94D, 0x9579, 0xE94E, 0x957A, 0xE94F, + 0x957B, 0xE950, 0x957C, 0xE951, 0x957D, 0xE952, 0x957E, 0xE953, 0x957F, 0xB3A4, 0x9580, 0xE954, 0x9581, 0xE955, 0x9582, 0xE956, + 0x9583, 0xE957, 0x9584, 0xE958, 0x9585, 0xE959, 0x9586, 0xE95A, 0x9587, 0xE95B, 0x9588, 0xE95C, 0x9589, 0xE95D, 0x958A, 0xE95E, + 0x958B, 0xE95F, 0x958C, 0xE960, 0x958D, 0xE961, 0x958E, 0xE962, 0x958F, 0xE963, 0x9590, 0xE964, 0x9591, 0xE965, 0x9592, 0xE966, + 0x9593, 0xE967, 0x9594, 0xE968, 0x9595, 0xE969, 0x9596, 0xE96A, 0x9597, 0xE96B, 0x9598, 0xE96C, 0x9599, 0xE96D, 0x959A, 0xE96E, + 0x959B, 0xE96F, 0x959C, 0xE970, 0x959D, 0xE971, 0x959E, 0xE972, 0x959F, 0xE973, 0x95A0, 0xE974, 0x95A1, 0xE975, 0x95A2, 0xE976, + 0x95A3, 0xE977, 0x95A4, 0xE978, 0x95A5, 0xE979, 0x95A6, 0xE97A, 0x95A7, 0xE97B, 0x95A8, 0xE97C, 0x95A9, 0xE97D, 0x95AA, 0xE97E, + 0x95AB, 0xE980, 0x95AC, 0xE981, 0x95AD, 0xE982, 0x95AE, 0xE983, 0x95AF, 0xE984, 0x95B0, 0xE985, 0x95B1, 0xE986, 0x95B2, 0xE987, + 0x95B3, 0xE988, 0x95B4, 0xE989, 0x95B5, 0xE98A, 0x95B6, 0xE98B, 0x95B7, 0xE98C, 0x95B8, 0xE98D, 0x95B9, 0xE98E, 0x95BA, 0xE98F, + 0x95BB, 0xE990, 0x95BC, 0xE991, 0x95BD, 0xE992, 0x95BE, 0xE993, 0x95BF, 0xE994, 0x95C0, 0xE995, 0x95C1, 0xE996, 0x95C2, 0xE997, + 0x95C3, 0xE998, 0x95C4, 0xE999, 0x95C5, 0xE99A, 0x95C6, 0xE99B, 0x95C7, 0xE99C, 0x95C8, 0xE99D, 0x95C9, 0xE99E, 0x95CA, 0xE99F, + 0x95CB, 0xE9A0, 0x95CC, 0xEA40, 0x95CD, 0xEA41, 0x95CE, 0xEA42, 0x95CF, 0xEA43, 0x95D0, 0xEA44, 0x95D1, 0xEA45, 0x95D2, 0xEA46, + 0x95D3, 0xEA47, 0x95D4, 0xEA48, 0x95D5, 0xEA49, 0x95D6, 0xEA4A, 0x95D7, 0xEA4B, 0x95D8, 0xEA4C, 0x95D9, 0xEA4D, 0x95DA, 0xEA4E, + 0x95DB, 0xEA4F, 0x95DC, 0xEA50, 0x95DD, 0xEA51, 0x95DE, 0xEA52, 0x95DF, 0xEA53, 0x95E0, 0xEA54, 0x95E1, 0xEA55, 0x95E2, 0xEA56, + 0x95E3, 0xEA57, 0x95E4, 0xEA58, 0x95E5, 0xEA59, 0x95E6, 0xEA5A, 0x95E7, 0xEA5B, 0x95E8, 0xC3C5, 0x95E9, 0xE3C5, 0x95EA, 0xC9C1, + 0x95EB, 0xE3C6, 0x95EC, 0xEA5C, 0x95ED, 0xB1D5, 0x95EE, 0xCECA, 0x95EF, 0xB4B3, 0x95F0, 0xC8F2, 0x95F1, 0xE3C7, 0x95F2, 0xCFD0, + 0x95F3, 0xE3C8, 0x95F4, 0xBCE4, 0x95F5, 0xE3C9, 0x95F6, 0xE3CA, 0x95F7, 0xC3C6, 0x95F8, 0xD5A2, 0x95F9, 0xC4D6, 0x95FA, 0xB9EB, + 0x95FB, 0xCEC5, 0x95FC, 0xE3CB, 0x95FD, 0xC3F6, 0x95FE, 0xE3CC, 0x95FF, 0xEA5D, 0x9600, 0xB7A7, 0x9601, 0xB8F3, 0x9602, 0xBAD2, + 0x9603, 0xE3CD, 0x9604, 0xE3CE, 0x9605, 0xD4C4, 0x9606, 0xE3CF, 0x9607, 0xEA5E, 0x9608, 0xE3D0, 0x9609, 0xD1CB, 0x960A, 0xE3D1, + 0x960B, 0xE3D2, 0x960C, 0xE3D3, 0x960D, 0xE3D4, 0x960E, 0xD1D6, 0x960F, 0xE3D5, 0x9610, 0xB2FB, 0x9611, 0xC0BB, 0x9612, 0xE3D6, + 0x9613, 0xEA5F, 0x9614, 0xC0AB, 0x9615, 0xE3D7, 0x9616, 0xE3D8, 0x9617, 0xE3D9, 0x9618, 0xEA60, 0x9619, 0xE3DA, 0x961A, 0xE3DB, + 0x961B, 0xEA61, 0x961C, 0xB8B7, 0x961D, 0xDAE2, 0x961E, 0xEA62, 0x961F, 0xB6D3, 0x9620, 0xEA63, 0x9621, 0xDAE4, 0x9622, 0xDAE3, + 0x9623, 0xEA64, 0x9624, 0xEA65, 0x9625, 0xEA66, 0x9626, 0xEA67, 0x9627, 0xEA68, 0x9628, 0xEA69, 0x9629, 0xEA6A, 0x962A, 0xDAE6, + 0x962B, 0xEA6B, 0x962C, 0xEA6C, 0x962D, 0xEA6D, 0x962E, 0xC8EE, 0x962F, 0xEA6E, 0x9630, 0xEA6F, 0x9631, 0xDAE5, 0x9632, 0xB7C0, + 0x9633, 0xD1F4, 0x9634, 0xD2F5, 0x9635, 0xD5F3, 0x9636, 0xBDD7, 0x9637, 0xEA70, 0x9638, 0xEA71, 0x9639, 0xEA72, 0x963A, 0xEA73, + 0x963B, 0xD7E8, 0x963C, 0xDAE8, 0x963D, 0xDAE7, 0x963E, 0xEA74, 0x963F, 0xB0A2, 0x9640, 0xCDD3, 0x9641, 0xEA75, 0x9642, 0xDAE9, + 0x9643, 0xEA76, 0x9644, 0xB8BD, 0x9645, 0xBCCA, 0x9646, 0xC2BD, 0x9647, 0xC2A4, 0x9648, 0xB3C2, 0x9649, 0xDAEA, 0x964A, 0xEA77, + 0x964B, 0xC2AA, 0x964C, 0xC4B0, 0x964D, 0xBDB5, 0x964E, 0xEA78, 0x964F, 0xEA79, 0x9650, 0xCFDE, 0x9651, 0xEA7A, 0x9652, 0xEA7B, + 0x9653, 0xEA7C, 0x9654, 0xDAEB, 0x9655, 0xC9C2, 0x9656, 0xEA7D, 0x9657, 0xEA7E, 0x9658, 0xEA80, 0x9659, 0xEA81, 0x965A, 0xEA82, + 0x965B, 0xB1DD, 0x965C, 0xEA83, 0x965D, 0xEA84, 0x965E, 0xEA85, 0x965F, 0xDAEC, 0x9660, 0xEA86, 0x9661, 0xB6B8, 0x9662, 0xD4BA, + 0x9663, 0xEA87, 0x9664, 0xB3FD, 0x9665, 0xEA88, 0x9666, 0xEA89, 0x9667, 0xDAED, 0x9668, 0xD4C9, 0x9669, 0xCFD5, 0x966A, 0xC5E3, + 0x966B, 0xEA8A, 0x966C, 0xDAEE, 0x966D, 0xEA8B, 0x966E, 0xEA8C, 0x966F, 0xEA8D, 0x9670, 0xEA8E, 0x9671, 0xEA8F, 0x9672, 0xDAEF, + 0x9673, 0xEA90, 0x9674, 0xDAF0, 0x9675, 0xC1EA, 0x9676, 0xCCD5, 0x9677, 0xCFDD, 0x9678, 0xEA91, 0x9679, 0xEA92, 0x967A, 0xEA93, + 0x967B, 0xEA94, 0x967C, 0xEA95, 0x967D, 0xEA96, 0x967E, 0xEA97, 0x967F, 0xEA98, 0x9680, 0xEA99, 0x9681, 0xEA9A, 0x9682, 0xEA9B, + 0x9683, 0xEA9C, 0x9684, 0xEA9D, 0x9685, 0xD3E7, 0x9686, 0xC2A1, 0x9687, 0xEA9E, 0x9688, 0xDAF1, 0x9689, 0xEA9F, 0x968A, 0xEAA0, + 0x968B, 0xCBE5, 0x968C, 0xEB40, 0x968D, 0xDAF2, 0x968E, 0xEB41, 0x968F, 0xCBE6, 0x9690, 0xD2FE, 0x9691, 0xEB42, 0x9692, 0xEB43, + 0x9693, 0xEB44, 0x9694, 0xB8F4, 0x9695, 0xEB45, 0x9696, 0xEB46, 0x9697, 0xDAF3, 0x9698, 0xB0AF, 0x9699, 0xCFB6, 0x969A, 0xEB47, + 0x969B, 0xEB48, 0x969C, 0xD5CF, 0x969D, 0xEB49, 0x969E, 0xEB4A, 0x969F, 0xEB4B, 0x96A0, 0xEB4C, 0x96A1, 0xEB4D, 0x96A2, 0xEB4E, + 0x96A3, 0xEB4F, 0x96A4, 0xEB50, 0x96A5, 0xEB51, 0x96A6, 0xEB52, 0x96A7, 0xCBED, 0x96A8, 0xEB53, 0x96A9, 0xEB54, 0x96AA, 0xEB55, + 0x96AB, 0xEB56, 0x96AC, 0xEB57, 0x96AD, 0xEB58, 0x96AE, 0xEB59, 0x96AF, 0xEB5A, 0x96B0, 0xDAF4, 0x96B1, 0xEB5B, 0x96B2, 0xEB5C, + 0x96B3, 0xE3C4, 0x96B4, 0xEB5D, 0x96B5, 0xEB5E, 0x96B6, 0xC1A5, 0x96B7, 0xEB5F, 0x96B8, 0xEB60, 0x96B9, 0xF6BF, 0x96BA, 0xEB61, + 0x96BB, 0xEB62, 0x96BC, 0xF6C0, 0x96BD, 0xF6C1, 0x96BE, 0xC4D1, 0x96BF, 0xEB63, 0x96C0, 0xC8B8, 0x96C1, 0xD1E3, 0x96C2, 0xEB64, + 0x96C3, 0xEB65, 0x96C4, 0xD0DB, 0x96C5, 0xD1C5, 0x96C6, 0xBCAF, 0x96C7, 0xB9CD, 0x96C8, 0xEB66, 0x96C9, 0xEFF4, 0x96CA, 0xEB67, + 0x96CB, 0xEB68, 0x96CC, 0xB4C6, 0x96CD, 0xD3BA, 0x96CE, 0xF6C2, 0x96CF, 0xB3FB, 0x96D0, 0xEB69, 0x96D1, 0xEB6A, 0x96D2, 0xF6C3, + 0x96D3, 0xEB6B, 0x96D4, 0xEB6C, 0x96D5, 0xB5F1, 0x96D6, 0xEB6D, 0x96D7, 0xEB6E, 0x96D8, 0xEB6F, 0x96D9, 0xEB70, 0x96DA, 0xEB71, + 0x96DB, 0xEB72, 0x96DC, 0xEB73, 0x96DD, 0xEB74, 0x96DE, 0xEB75, 0x96DF, 0xEB76, 0x96E0, 0xF6C5, 0x96E1, 0xEB77, 0x96E2, 0xEB78, + 0x96E3, 0xEB79, 0x96E4, 0xEB7A, 0x96E5, 0xEB7B, 0x96E6, 0xEB7C, 0x96E7, 0xEB7D, 0x96E8, 0xD3EA, 0x96E9, 0xF6A7, 0x96EA, 0xD1A9, + 0x96EB, 0xEB7E, 0x96EC, 0xEB80, 0x96ED, 0xEB81, 0x96EE, 0xEB82, 0x96EF, 0xF6A9, 0x96F0, 0xEB83, 0x96F1, 0xEB84, 0x96F2, 0xEB85, + 0x96F3, 0xF6A8, 0x96F4, 0xEB86, 0x96F5, 0xEB87, 0x96F6, 0xC1E3, 0x96F7, 0xC0D7, 0x96F8, 0xEB88, 0x96F9, 0xB1A2, 0x96FA, 0xEB89, + 0x96FB, 0xEB8A, 0x96FC, 0xEB8B, 0x96FD, 0xEB8C, 0x96FE, 0xCEED, 0x96FF, 0xEB8D, 0x9700, 0xD0E8, 0x9701, 0xF6AB, 0x9702, 0xEB8E, + 0x9703, 0xEB8F, 0x9704, 0xCFF6, 0x9705, 0xEB90, 0x9706, 0xF6AA, 0x9707, 0xD5F0, 0x9708, 0xF6AC, 0x9709, 0xC3B9, 0x970A, 0xEB91, + 0x970B, 0xEB92, 0x970C, 0xEB93, 0x970D, 0xBBF4, 0x970E, 0xF6AE, 0x970F, 0xF6AD, 0x9710, 0xEB94, 0x9711, 0xEB95, 0x9712, 0xEB96, + 0x9713, 0xC4DE, 0x9714, 0xEB97, 0x9715, 0xEB98, 0x9716, 0xC1D8, 0x9717, 0xEB99, 0x9718, 0xEB9A, 0x9719, 0xEB9B, 0x971A, 0xEB9C, + 0x971B, 0xEB9D, 0x971C, 0xCBAA, 0x971D, 0xEB9E, 0x971E, 0xCFBC, 0x971F, 0xEB9F, 0x9720, 0xEBA0, 0x9721, 0xEC40, 0x9722, 0xEC41, + 0x9723, 0xEC42, 0x9724, 0xEC43, 0x9725, 0xEC44, 0x9726, 0xEC45, 0x9727, 0xEC46, 0x9728, 0xEC47, 0x9729, 0xEC48, 0x972A, 0xF6AF, + 0x972B, 0xEC49, 0x972C, 0xEC4A, 0x972D, 0xF6B0, 0x972E, 0xEC4B, 0x972F, 0xEC4C, 0x9730, 0xF6B1, 0x9731, 0xEC4D, 0x9732, 0xC2B6, + 0x9733, 0xEC4E, 0x9734, 0xEC4F, 0x9735, 0xEC50, 0x9736, 0xEC51, 0x9737, 0xEC52, 0x9738, 0xB0D4, 0x9739, 0xC5F9, 0x973A, 0xEC53, + 0x973B, 0xEC54, 0x973C, 0xEC55, 0x973D, 0xEC56, 0x973E, 0xF6B2, 0x973F, 0xEC57, 0x9740, 0xEC58, 0x9741, 0xEC59, 0x9742, 0xEC5A, + 0x9743, 0xEC5B, 0x9744, 0xEC5C, 0x9745, 0xEC5D, 0x9746, 0xEC5E, 0x9747, 0xEC5F, 0x9748, 0xEC60, 0x9749, 0xEC61, 0x974A, 0xEC62, + 0x974B, 0xEC63, 0x974C, 0xEC64, 0x974D, 0xEC65, 0x974E, 0xEC66, 0x974F, 0xEC67, 0x9750, 0xEC68, 0x9751, 0xEC69, 0x9752, 0xC7E0, + 0x9753, 0xF6A6, 0x9754, 0xEC6A, 0x9755, 0xEC6B, 0x9756, 0xBEB8, 0x9757, 0xEC6C, 0x9758, 0xEC6D, 0x9759, 0xBEB2, 0x975A, 0xEC6E, + 0x975B, 0xB5E5, 0x975C, 0xEC6F, 0x975D, 0xEC70, 0x975E, 0xB7C7, 0x975F, 0xEC71, 0x9760, 0xBFBF, 0x9761, 0xC3D2, 0x9762, 0xC3E6, + 0x9763, 0xEC72, 0x9764, 0xEC73, 0x9765, 0xD8CC, 0x9766, 0xEC74, 0x9767, 0xEC75, 0x9768, 0xEC76, 0x9769, 0xB8EF, 0x976A, 0xEC77, + 0x976B, 0xEC78, 0x976C, 0xEC79, 0x976D, 0xEC7A, 0x976E, 0xEC7B, 0x976F, 0xEC7C, 0x9770, 0xEC7D, 0x9771, 0xEC7E, 0x9772, 0xEC80, + 0x9773, 0xBDF9, 0x9774, 0xD1A5, 0x9775, 0xEC81, 0x9776, 0xB0D0, 0x9777, 0xEC82, 0x9778, 0xEC83, 0x9779, 0xEC84, 0x977A, 0xEC85, + 0x977B, 0xEC86, 0x977C, 0xF7B0, 0x977D, 0xEC87, 0x977E, 0xEC88, 0x977F, 0xEC89, 0x9780, 0xEC8A, 0x9781, 0xEC8B, 0x9782, 0xEC8C, + 0x9783, 0xEC8D, 0x9784, 0xEC8E, 0x9785, 0xF7B1, 0x9786, 0xEC8F, 0x9787, 0xEC90, 0x9788, 0xEC91, 0x9789, 0xEC92, 0x978A, 0xEC93, + 0x978B, 0xD0AC, 0x978C, 0xEC94, 0x978D, 0xB0B0, 0x978E, 0xEC95, 0x978F, 0xEC96, 0x9790, 0xEC97, 0x9791, 0xF7B2, 0x9792, 0xF7B3, + 0x9793, 0xEC98, 0x9794, 0xF7B4, 0x9795, 0xEC99, 0x9796, 0xEC9A, 0x9797, 0xEC9B, 0x9798, 0xC7CA, 0x9799, 0xEC9C, 0x979A, 0xEC9D, + 0x979B, 0xEC9E, 0x979C, 0xEC9F, 0x979D, 0xECA0, 0x979E, 0xED40, 0x979F, 0xED41, 0x97A0, 0xBECF, 0x97A1, 0xED42, 0x97A2, 0xED43, + 0x97A3, 0xF7B7, 0x97A4, 0xED44, 0x97A5, 0xED45, 0x97A6, 0xED46, 0x97A7, 0xED47, 0x97A8, 0xED48, 0x97A9, 0xED49, 0x97AA, 0xED4A, + 0x97AB, 0xF7B6, 0x97AC, 0xED4B, 0x97AD, 0xB1DE, 0x97AE, 0xED4C, 0x97AF, 0xF7B5, 0x97B0, 0xED4D, 0x97B1, 0xED4E, 0x97B2, 0xF7B8, + 0x97B3, 0xED4F, 0x97B4, 0xF7B9, 0x97B5, 0xED50, 0x97B6, 0xED51, 0x97B7, 0xED52, 0x97B8, 0xED53, 0x97B9, 0xED54, 0x97BA, 0xED55, + 0x97BB, 0xED56, 0x97BC, 0xED57, 0x97BD, 0xED58, 0x97BE, 0xED59, 0x97BF, 0xED5A, 0x97C0, 0xED5B, 0x97C1, 0xED5C, 0x97C2, 0xED5D, + 0x97C3, 0xED5E, 0x97C4, 0xED5F, 0x97C5, 0xED60, 0x97C6, 0xED61, 0x97C7, 0xED62, 0x97C8, 0xED63, 0x97C9, 0xED64, 0x97CA, 0xED65, + 0x97CB, 0xED66, 0x97CC, 0xED67, 0x97CD, 0xED68, 0x97CE, 0xED69, 0x97CF, 0xED6A, 0x97D0, 0xED6B, 0x97D1, 0xED6C, 0x97D2, 0xED6D, + 0x97D3, 0xED6E, 0x97D4, 0xED6F, 0x97D5, 0xED70, 0x97D6, 0xED71, 0x97D7, 0xED72, 0x97D8, 0xED73, 0x97D9, 0xED74, 0x97DA, 0xED75, + 0x97DB, 0xED76, 0x97DC, 0xED77, 0x97DD, 0xED78, 0x97DE, 0xED79, 0x97DF, 0xED7A, 0x97E0, 0xED7B, 0x97E1, 0xED7C, 0x97E2, 0xED7D, + 0x97E3, 0xED7E, 0x97E4, 0xED80, 0x97E5, 0xED81, 0x97E6, 0xCEA4, 0x97E7, 0xC8CD, 0x97E8, 0xED82, 0x97E9, 0xBAAB, 0x97EA, 0xE8B8, + 0x97EB, 0xE8B9, 0x97EC, 0xE8BA, 0x97ED, 0xBEC2, 0x97EE, 0xED83, 0x97EF, 0xED84, 0x97F0, 0xED85, 0x97F1, 0xED86, 0x97F2, 0xED87, + 0x97F3, 0xD2F4, 0x97F4, 0xED88, 0x97F5, 0xD4CF, 0x97F6, 0xC9D8, 0x97F7, 0xED89, 0x97F8, 0xED8A, 0x97F9, 0xED8B, 0x97FA, 0xED8C, + 0x97FB, 0xED8D, 0x97FC, 0xED8E, 0x97FD, 0xED8F, 0x97FE, 0xED90, 0x97FF, 0xED91, 0x9800, 0xED92, 0x9801, 0xED93, 0x9802, 0xED94, + 0x9803, 0xED95, 0x9804, 0xED96, 0x9805, 0xED97, 0x9806, 0xED98, 0x9807, 0xED99, 0x9808, 0xED9A, 0x9809, 0xED9B, 0x980A, 0xED9C, + 0x980B, 0xED9D, 0x980C, 0xED9E, 0x980D, 0xED9F, 0x980E, 0xEDA0, 0x980F, 0xEE40, 0x9810, 0xEE41, 0x9811, 0xEE42, 0x9812, 0xEE43, + 0x9813, 0xEE44, 0x9814, 0xEE45, 0x9815, 0xEE46, 0x9816, 0xEE47, 0x9817, 0xEE48, 0x9818, 0xEE49, 0x9819, 0xEE4A, 0x981A, 0xEE4B, + 0x981B, 0xEE4C, 0x981C, 0xEE4D, 0x981D, 0xEE4E, 0x981E, 0xEE4F, 0x981F, 0xEE50, 0x9820, 0xEE51, 0x9821, 0xEE52, 0x9822, 0xEE53, + 0x9823, 0xEE54, 0x9824, 0xEE55, 0x9825, 0xEE56, 0x9826, 0xEE57, 0x9827, 0xEE58, 0x9828, 0xEE59, 0x9829, 0xEE5A, 0x982A, 0xEE5B, + 0x982B, 0xEE5C, 0x982C, 0xEE5D, 0x982D, 0xEE5E, 0x982E, 0xEE5F, 0x982F, 0xEE60, 0x9830, 0xEE61, 0x9831, 0xEE62, 0x9832, 0xEE63, + 0x9833, 0xEE64, 0x9834, 0xEE65, 0x9835, 0xEE66, 0x9836, 0xEE67, 0x9837, 0xEE68, 0x9838, 0xEE69, 0x9839, 0xEE6A, 0x983A, 0xEE6B, + 0x983B, 0xEE6C, 0x983C, 0xEE6D, 0x983D, 0xEE6E, 0x983E, 0xEE6F, 0x983F, 0xEE70, 0x9840, 0xEE71, 0x9841, 0xEE72, 0x9842, 0xEE73, + 0x9843, 0xEE74, 0x9844, 0xEE75, 0x9845, 0xEE76, 0x9846, 0xEE77, 0x9847, 0xEE78, 0x9848, 0xEE79, 0x9849, 0xEE7A, 0x984A, 0xEE7B, + 0x984B, 0xEE7C, 0x984C, 0xEE7D, 0x984D, 0xEE7E, 0x984E, 0xEE80, 0x984F, 0xEE81, 0x9850, 0xEE82, 0x9851, 0xEE83, 0x9852, 0xEE84, + 0x9853, 0xEE85, 0x9854, 0xEE86, 0x9855, 0xEE87, 0x9856, 0xEE88, 0x9857, 0xEE89, 0x9858, 0xEE8A, 0x9859, 0xEE8B, 0x985A, 0xEE8C, + 0x985B, 0xEE8D, 0x985C, 0xEE8E, 0x985D, 0xEE8F, 0x985E, 0xEE90, 0x985F, 0xEE91, 0x9860, 0xEE92, 0x9861, 0xEE93, 0x9862, 0xEE94, + 0x9863, 0xEE95, 0x9864, 0xEE96, 0x9865, 0xEE97, 0x9866, 0xEE98, 0x9867, 0xEE99, 0x9868, 0xEE9A, 0x9869, 0xEE9B, 0x986A, 0xEE9C, + 0x986B, 0xEE9D, 0x986C, 0xEE9E, 0x986D, 0xEE9F, 0x986E, 0xEEA0, 0x986F, 0xEF40, 0x9870, 0xEF41, 0x9871, 0xEF42, 0x9872, 0xEF43, + 0x9873, 0xEF44, 0x9874, 0xEF45, 0x9875, 0xD2B3, 0x9876, 0xB6A5, 0x9877, 0xC7EA, 0x9878, 0xF1FC, 0x9879, 0xCFEE, 0x987A, 0xCBB3, + 0x987B, 0xD0EB, 0x987C, 0xE7EF, 0x987D, 0xCDE7, 0x987E, 0xB9CB, 0x987F, 0xB6D9, 0x9880, 0xF1FD, 0x9881, 0xB0E4, 0x9882, 0xCBCC, + 0x9883, 0xF1FE, 0x9884, 0xD4A4, 0x9885, 0xC2AD, 0x9886, 0xC1EC, 0x9887, 0xC6C4, 0x9888, 0xBEB1, 0x9889, 0xF2A1, 0x988A, 0xBCD5, + 0x988B, 0xEF46, 0x988C, 0xF2A2, 0x988D, 0xF2A3, 0x988E, 0xEF47, 0x988F, 0xF2A4, 0x9890, 0xD2C3, 0x9891, 0xC6B5, 0x9892, 0xEF48, + 0x9893, 0xCDC7, 0x9894, 0xF2A5, 0x9895, 0xEF49, 0x9896, 0xD3B1, 0x9897, 0xBFC5, 0x9898, 0xCCE2, 0x9899, 0xEF4A, 0x989A, 0xF2A6, + 0x989B, 0xF2A7, 0x989C, 0xD1D5, 0x989D, 0xB6EE, 0x989E, 0xF2A8, 0x989F, 0xF2A9, 0x98A0, 0xB5DF, 0x98A1, 0xF2AA, 0x98A2, 0xF2AB, + 0x98A3, 0xEF4B, 0x98A4, 0xB2FC, 0x98A5, 0xF2AC, 0x98A6, 0xF2AD, 0x98A7, 0xC8A7, 0x98A8, 0xEF4C, 0x98A9, 0xEF4D, 0x98AA, 0xEF4E, + 0x98AB, 0xEF4F, 0x98AC, 0xEF50, 0x98AD, 0xEF51, 0x98AE, 0xEF52, 0x98AF, 0xEF53, 0x98B0, 0xEF54, 0x98B1, 0xEF55, 0x98B2, 0xEF56, + 0x98B3, 0xEF57, 0x98B4, 0xEF58, 0x98B5, 0xEF59, 0x98B6, 0xEF5A, 0x98B7, 0xEF5B, 0x98B8, 0xEF5C, 0x98B9, 0xEF5D, 0x98BA, 0xEF5E, + 0x98BB, 0xEF5F, 0x98BC, 0xEF60, 0x98BD, 0xEF61, 0x98BE, 0xEF62, 0x98BF, 0xEF63, 0x98C0, 0xEF64, 0x98C1, 0xEF65, 0x98C2, 0xEF66, + 0x98C3, 0xEF67, 0x98C4, 0xEF68, 0x98C5, 0xEF69, 0x98C6, 0xEF6A, 0x98C7, 0xEF6B, 0x98C8, 0xEF6C, 0x98C9, 0xEF6D, 0x98CA, 0xEF6E, + 0x98CB, 0xEF6F, 0x98CC, 0xEF70, 0x98CD, 0xEF71, 0x98CE, 0xB7E7, 0x98CF, 0xEF72, 0x98D0, 0xEF73, 0x98D1, 0xECA9, 0x98D2, 0xECAA, + 0x98D3, 0xECAB, 0x98D4, 0xEF74, 0x98D5, 0xECAC, 0x98D6, 0xEF75, 0x98D7, 0xEF76, 0x98D8, 0xC6AE, 0x98D9, 0xECAD, 0x98DA, 0xECAE, + 0x98DB, 0xEF77, 0x98DC, 0xEF78, 0x98DD, 0xEF79, 0x98DE, 0xB7C9, 0x98DF, 0xCAB3, 0x98E0, 0xEF7A, 0x98E1, 0xEF7B, 0x98E2, 0xEF7C, + 0x98E3, 0xEF7D, 0x98E4, 0xEF7E, 0x98E5, 0xEF80, 0x98E6, 0xEF81, 0x98E7, 0xE2B8, 0x98E8, 0xF7CF, 0x98E9, 0xEF82, 0x98EA, 0xEF83, + 0x98EB, 0xEF84, 0x98EC, 0xEF85, 0x98ED, 0xEF86, 0x98EE, 0xEF87, 0x98EF, 0xEF88, 0x98F0, 0xEF89, 0x98F1, 0xEF8A, 0x98F2, 0xEF8B, + 0x98F3, 0xEF8C, 0x98F4, 0xEF8D, 0x98F5, 0xEF8E, 0x98F6, 0xEF8F, 0x98F7, 0xEF90, 0x98F8, 0xEF91, 0x98F9, 0xEF92, 0x98FA, 0xEF93, + 0x98FB, 0xEF94, 0x98FC, 0xEF95, 0x98FD, 0xEF96, 0x98FE, 0xEF97, 0x98FF, 0xEF98, 0x9900, 0xEF99, 0x9901, 0xEF9A, 0x9902, 0xEF9B, + 0x9903, 0xEF9C, 0x9904, 0xEF9D, 0x9905, 0xEF9E, 0x9906, 0xEF9F, 0x9907, 0xEFA0, 0x9908, 0xF040, 0x9909, 0xF041, 0x990A, 0xF042, + 0x990B, 0xF043, 0x990C, 0xF044, 0x990D, 0xF7D0, 0x990E, 0xF045, 0x990F, 0xF046, 0x9910, 0xB2CD, 0x9911, 0xF047, 0x9912, 0xF048, + 0x9913, 0xF049, 0x9914, 0xF04A, 0x9915, 0xF04B, 0x9916, 0xF04C, 0x9917, 0xF04D, 0x9918, 0xF04E, 0x9919, 0xF04F, 0x991A, 0xF050, + 0x991B, 0xF051, 0x991C, 0xF052, 0x991D, 0xF053, 0x991E, 0xF054, 0x991F, 0xF055, 0x9920, 0xF056, 0x9921, 0xF057, 0x9922, 0xF058, + 0x9923, 0xF059, 0x9924, 0xF05A, 0x9925, 0xF05B, 0x9926, 0xF05C, 0x9927, 0xF05D, 0x9928, 0xF05E, 0x9929, 0xF05F, 0x992A, 0xF060, + 0x992B, 0xF061, 0x992C, 0xF062, 0x992D, 0xF063, 0x992E, 0xF7D1, 0x992F, 0xF064, 0x9930, 0xF065, 0x9931, 0xF066, 0x9932, 0xF067, + 0x9933, 0xF068, 0x9934, 0xF069, 0x9935, 0xF06A, 0x9936, 0xF06B, 0x9937, 0xF06C, 0x9938, 0xF06D, 0x9939, 0xF06E, 0x993A, 0xF06F, + 0x993B, 0xF070, 0x993C, 0xF071, 0x993D, 0xF072, 0x993E, 0xF073, 0x993F, 0xF074, 0x9940, 0xF075, 0x9941, 0xF076, 0x9942, 0xF077, + 0x9943, 0xF078, 0x9944, 0xF079, 0x9945, 0xF07A, 0x9946, 0xF07B, 0x9947, 0xF07C, 0x9948, 0xF07D, 0x9949, 0xF07E, 0x994A, 0xF080, + 0x994B, 0xF081, 0x994C, 0xF082, 0x994D, 0xF083, 0x994E, 0xF084, 0x994F, 0xF085, 0x9950, 0xF086, 0x9951, 0xF087, 0x9952, 0xF088, + 0x9953, 0xF089, 0x9954, 0xF7D3, 0x9955, 0xF7D2, 0x9956, 0xF08A, 0x9957, 0xF08B, 0x9958, 0xF08C, 0x9959, 0xF08D, 0x995A, 0xF08E, + 0x995B, 0xF08F, 0x995C, 0xF090, 0x995D, 0xF091, 0x995E, 0xF092, 0x995F, 0xF093, 0x9960, 0xF094, 0x9961, 0xF095, 0x9962, 0xF096, + 0x9963, 0xE2BB, 0x9964, 0xF097, 0x9965, 0xBCA2, 0x9966, 0xF098, 0x9967, 0xE2BC, 0x9968, 0xE2BD, 0x9969, 0xE2BE, 0x996A, 0xE2BF, + 0x996B, 0xE2C0, 0x996C, 0xE2C1, 0x996D, 0xB7B9, 0x996E, 0xD2FB, 0x996F, 0xBDA4, 0x9970, 0xCACE, 0x9971, 0xB1A5, 0x9972, 0xCBC7, + 0x9973, 0xF099, 0x9974, 0xE2C2, 0x9975, 0xB6FC, 0x9976, 0xC8C4, 0x9977, 0xE2C3, 0x9978, 0xF09A, 0x9979, 0xF09B, 0x997A, 0xBDC8, + 0x997B, 0xF09C, 0x997C, 0xB1FD, 0x997D, 0xE2C4, 0x997E, 0xF09D, 0x997F, 0xB6F6, 0x9980, 0xE2C5, 0x9981, 0xC4D9, 0x9982, 0xF09E, + 0x9983, 0xF09F, 0x9984, 0xE2C6, 0x9985, 0xCFDA, 0x9986, 0xB9DD, 0x9987, 0xE2C7, 0x9988, 0xC0A1, 0x9989, 0xF0A0, 0x998A, 0xE2C8, + 0x998B, 0xB2F6, 0x998C, 0xF140, 0x998D, 0xE2C9, 0x998E, 0xF141, 0x998F, 0xC1F3, 0x9990, 0xE2CA, 0x9991, 0xE2CB, 0x9992, 0xC2F8, + 0x9993, 0xE2CC, 0x9994, 0xE2CD, 0x9995, 0xE2CE, 0x9996, 0xCAD7, 0x9997, 0xD8B8, 0x9998, 0xD9E5, 0x9999, 0xCFE3, 0x999A, 0xF142, + 0x999B, 0xF143, 0x999C, 0xF144, 0x999D, 0xF145, 0x999E, 0xF146, 0x999F, 0xF147, 0x99A0, 0xF148, 0x99A1, 0xF149, 0x99A2, 0xF14A, + 0x99A3, 0xF14B, 0x99A4, 0xF14C, 0x99A5, 0xF0A5, 0x99A6, 0xF14D, 0x99A7, 0xF14E, 0x99A8, 0xDCB0, 0x99A9, 0xF14F, 0x99AA, 0xF150, + 0x99AB, 0xF151, 0x99AC, 0xF152, 0x99AD, 0xF153, 0x99AE, 0xF154, 0x99AF, 0xF155, 0x99B0, 0xF156, 0x99B1, 0xF157, 0x99B2, 0xF158, + 0x99B3, 0xF159, 0x99B4, 0xF15A, 0x99B5, 0xF15B, 0x99B6, 0xF15C, 0x99B7, 0xF15D, 0x99B8, 0xF15E, 0x99B9, 0xF15F, 0x99BA, 0xF160, + 0x99BB, 0xF161, 0x99BC, 0xF162, 0x99BD, 0xF163, 0x99BE, 0xF164, 0x99BF, 0xF165, 0x99C0, 0xF166, 0x99C1, 0xF167, 0x99C2, 0xF168, + 0x99C3, 0xF169, 0x99C4, 0xF16A, 0x99C5, 0xF16B, 0x99C6, 0xF16C, 0x99C7, 0xF16D, 0x99C8, 0xF16E, 0x99C9, 0xF16F, 0x99CA, 0xF170, + 0x99CB, 0xF171, 0x99CC, 0xF172, 0x99CD, 0xF173, 0x99CE, 0xF174, 0x99CF, 0xF175, 0x99D0, 0xF176, 0x99D1, 0xF177, 0x99D2, 0xF178, + 0x99D3, 0xF179, 0x99D4, 0xF17A, 0x99D5, 0xF17B, 0x99D6, 0xF17C, 0x99D7, 0xF17D, 0x99D8, 0xF17E, 0x99D9, 0xF180, 0x99DA, 0xF181, + 0x99DB, 0xF182, 0x99DC, 0xF183, 0x99DD, 0xF184, 0x99DE, 0xF185, 0x99DF, 0xF186, 0x99E0, 0xF187, 0x99E1, 0xF188, 0x99E2, 0xF189, + 0x99E3, 0xF18A, 0x99E4, 0xF18B, 0x99E5, 0xF18C, 0x99E6, 0xF18D, 0x99E7, 0xF18E, 0x99E8, 0xF18F, 0x99E9, 0xF190, 0x99EA, 0xF191, + 0x99EB, 0xF192, 0x99EC, 0xF193, 0x99ED, 0xF194, 0x99EE, 0xF195, 0x99EF, 0xF196, 0x99F0, 0xF197, 0x99F1, 0xF198, 0x99F2, 0xF199, + 0x99F3, 0xF19A, 0x99F4, 0xF19B, 0x99F5, 0xF19C, 0x99F6, 0xF19D, 0x99F7, 0xF19E, 0x99F8, 0xF19F, 0x99F9, 0xF1A0, 0x99FA, 0xF240, + 0x99FB, 0xF241, 0x99FC, 0xF242, 0x99FD, 0xF243, 0x99FE, 0xF244, 0x99FF, 0xF245, 0x9A00, 0xF246, 0x9A01, 0xF247, 0x9A02, 0xF248, + 0x9A03, 0xF249, 0x9A04, 0xF24A, 0x9A05, 0xF24B, 0x9A06, 0xF24C, 0x9A07, 0xF24D, 0x9A08, 0xF24E, 0x9A09, 0xF24F, 0x9A0A, 0xF250, + 0x9A0B, 0xF251, 0x9A0C, 0xF252, 0x9A0D, 0xF253, 0x9A0E, 0xF254, 0x9A0F, 0xF255, 0x9A10, 0xF256, 0x9A11, 0xF257, 0x9A12, 0xF258, + 0x9A13, 0xF259, 0x9A14, 0xF25A, 0x9A15, 0xF25B, 0x9A16, 0xF25C, 0x9A17, 0xF25D, 0x9A18, 0xF25E, 0x9A19, 0xF25F, 0x9A1A, 0xF260, + 0x9A1B, 0xF261, 0x9A1C, 0xF262, 0x9A1D, 0xF263, 0x9A1E, 0xF264, 0x9A1F, 0xF265, 0x9A20, 0xF266, 0x9A21, 0xF267, 0x9A22, 0xF268, + 0x9A23, 0xF269, 0x9A24, 0xF26A, 0x9A25, 0xF26B, 0x9A26, 0xF26C, 0x9A27, 0xF26D, 0x9A28, 0xF26E, 0x9A29, 0xF26F, 0x9A2A, 0xF270, + 0x9A2B, 0xF271, 0x9A2C, 0xF272, 0x9A2D, 0xF273, 0x9A2E, 0xF274, 0x9A2F, 0xF275, 0x9A30, 0xF276, 0x9A31, 0xF277, 0x9A32, 0xF278, + 0x9A33, 0xF279, 0x9A34, 0xF27A, 0x9A35, 0xF27B, 0x9A36, 0xF27C, 0x9A37, 0xF27D, 0x9A38, 0xF27E, 0x9A39, 0xF280, 0x9A3A, 0xF281, + 0x9A3B, 0xF282, 0x9A3C, 0xF283, 0x9A3D, 0xF284, 0x9A3E, 0xF285, 0x9A3F, 0xF286, 0x9A40, 0xF287, 0x9A41, 0xF288, 0x9A42, 0xF289, + 0x9A43, 0xF28A, 0x9A44, 0xF28B, 0x9A45, 0xF28C, 0x9A46, 0xF28D, 0x9A47, 0xF28E, 0x9A48, 0xF28F, 0x9A49, 0xF290, 0x9A4A, 0xF291, + 0x9A4B, 0xF292, 0x9A4C, 0xF293, 0x9A4D, 0xF294, 0x9A4E, 0xF295, 0x9A4F, 0xF296, 0x9A50, 0xF297, 0x9A51, 0xF298, 0x9A52, 0xF299, + 0x9A53, 0xF29A, 0x9A54, 0xF29B, 0x9A55, 0xF29C, 0x9A56, 0xF29D, 0x9A57, 0xF29E, 0x9A58, 0xF29F, 0x9A59, 0xF2A0, 0x9A5A, 0xF340, + 0x9A5B, 0xF341, 0x9A5C, 0xF342, 0x9A5D, 0xF343, 0x9A5E, 0xF344, 0x9A5F, 0xF345, 0x9A60, 0xF346, 0x9A61, 0xF347, 0x9A62, 0xF348, + 0x9A63, 0xF349, 0x9A64, 0xF34A, 0x9A65, 0xF34B, 0x9A66, 0xF34C, 0x9A67, 0xF34D, 0x9A68, 0xF34E, 0x9A69, 0xF34F, 0x9A6A, 0xF350, + 0x9A6B, 0xF351, 0x9A6C, 0xC2ED, 0x9A6D, 0xD4A6, 0x9A6E, 0xCDD4, 0x9A6F, 0xD1B1, 0x9A70, 0xB3DB, 0x9A71, 0xC7FD, 0x9A72, 0xF352, + 0x9A73, 0xB2B5, 0x9A74, 0xC2BF, 0x9A75, 0xE6E0, 0x9A76, 0xCABB, 0x9A77, 0xE6E1, 0x9A78, 0xE6E2, 0x9A79, 0xBED4, 0x9A7A, 0xE6E3, + 0x9A7B, 0xD7A4, 0x9A7C, 0xCDD5, 0x9A7D, 0xE6E5, 0x9A7E, 0xBCDD, 0x9A7F, 0xE6E4, 0x9A80, 0xE6E6, 0x9A81, 0xE6E7, 0x9A82, 0xC2EE, + 0x9A83, 0xF353, 0x9A84, 0xBDBE, 0x9A85, 0xE6E8, 0x9A86, 0xC2E6, 0x9A87, 0xBAA7, 0x9A88, 0xE6E9, 0x9A89, 0xF354, 0x9A8A, 0xE6EA, + 0x9A8B, 0xB3D2, 0x9A8C, 0xD1E9, 0x9A8D, 0xF355, 0x9A8E, 0xF356, 0x9A8F, 0xBFA5, 0x9A90, 0xE6EB, 0x9A91, 0xC6EF, 0x9A92, 0xE6EC, + 0x9A93, 0xE6ED, 0x9A94, 0xF357, 0x9A95, 0xF358, 0x9A96, 0xE6EE, 0x9A97, 0xC6AD, 0x9A98, 0xE6EF, 0x9A99, 0xF359, 0x9A9A, 0xC9A7, + 0x9A9B, 0xE6F0, 0x9A9C, 0xE6F1, 0x9A9D, 0xE6F2, 0x9A9E, 0xE5B9, 0x9A9F, 0xE6F3, 0x9AA0, 0xE6F4, 0x9AA1, 0xC2E2, 0x9AA2, 0xE6F5, + 0x9AA3, 0xE6F6, 0x9AA4, 0xD6E8, 0x9AA5, 0xE6F7, 0x9AA6, 0xF35A, 0x9AA7, 0xE6F8, 0x9AA8, 0xB9C7, 0x9AA9, 0xF35B, 0x9AAA, 0xF35C, + 0x9AAB, 0xF35D, 0x9AAC, 0xF35E, 0x9AAD, 0xF35F, 0x9AAE, 0xF360, 0x9AAF, 0xF361, 0x9AB0, 0xF7BB, 0x9AB1, 0xF7BA, 0x9AB2, 0xF362, + 0x9AB3, 0xF363, 0x9AB4, 0xF364, 0x9AB5, 0xF365, 0x9AB6, 0xF7BE, 0x9AB7, 0xF7BC, 0x9AB8, 0xBAA1, 0x9AB9, 0xF366, 0x9ABA, 0xF7BF, + 0x9ABB, 0xF367, 0x9ABC, 0xF7C0, 0x9ABD, 0xF368, 0x9ABE, 0xF369, 0x9ABF, 0xF36A, 0x9AC0, 0xF7C2, 0x9AC1, 0xF7C1, 0x9AC2, 0xF7C4, + 0x9AC3, 0xF36B, 0x9AC4, 0xF36C, 0x9AC5, 0xF7C3, 0x9AC6, 0xF36D, 0x9AC7, 0xF36E, 0x9AC8, 0xF36F, 0x9AC9, 0xF370, 0x9ACA, 0xF371, + 0x9ACB, 0xF7C5, 0x9ACC, 0xF7C6, 0x9ACD, 0xF372, 0x9ACE, 0xF373, 0x9ACF, 0xF374, 0x9AD0, 0xF375, 0x9AD1, 0xF7C7, 0x9AD2, 0xF376, + 0x9AD3, 0xCBE8, 0x9AD4, 0xF377, 0x9AD5, 0xF378, 0x9AD6, 0xF379, 0x9AD7, 0xF37A, 0x9AD8, 0xB8DF, 0x9AD9, 0xF37B, 0x9ADA, 0xF37C, + 0x9ADB, 0xF37D, 0x9ADC, 0xF37E, 0x9ADD, 0xF380, 0x9ADE, 0xF381, 0x9ADF, 0xF7D4, 0x9AE0, 0xF382, 0x9AE1, 0xF7D5, 0x9AE2, 0xF383, + 0x9AE3, 0xF384, 0x9AE4, 0xF385, 0x9AE5, 0xF386, 0x9AE6, 0xF7D6, 0x9AE7, 0xF387, 0x9AE8, 0xF388, 0x9AE9, 0xF389, 0x9AEA, 0xF38A, + 0x9AEB, 0xF7D8, 0x9AEC, 0xF38B, 0x9AED, 0xF7DA, 0x9AEE, 0xF38C, 0x9AEF, 0xF7D7, 0x9AF0, 0xF38D, 0x9AF1, 0xF38E, 0x9AF2, 0xF38F, + 0x9AF3, 0xF390, 0x9AF4, 0xF391, 0x9AF5, 0xF392, 0x9AF6, 0xF393, 0x9AF7, 0xF394, 0x9AF8, 0xF395, 0x9AF9, 0xF7DB, 0x9AFA, 0xF396, + 0x9AFB, 0xF7D9, 0x9AFC, 0xF397, 0x9AFD, 0xF398, 0x9AFE, 0xF399, 0x9AFF, 0xF39A, 0x9B00, 0xF39B, 0x9B01, 0xF39C, 0x9B02, 0xF39D, + 0x9B03, 0xD7D7, 0x9B04, 0xF39E, 0x9B05, 0xF39F, 0x9B06, 0xF3A0, 0x9B07, 0xF440, 0x9B08, 0xF7DC, 0x9B09, 0xF441, 0x9B0A, 0xF442, + 0x9B0B, 0xF443, 0x9B0C, 0xF444, 0x9B0D, 0xF445, 0x9B0E, 0xF446, 0x9B0F, 0xF7DD, 0x9B10, 0xF447, 0x9B11, 0xF448, 0x9B12, 0xF449, + 0x9B13, 0xF7DE, 0x9B14, 0xF44A, 0x9B15, 0xF44B, 0x9B16, 0xF44C, 0x9B17, 0xF44D, 0x9B18, 0xF44E, 0x9B19, 0xF44F, 0x9B1A, 0xF450, + 0x9B1B, 0xF451, 0x9B1C, 0xF452, 0x9B1D, 0xF453, 0x9B1E, 0xF454, 0x9B1F, 0xF7DF, 0x9B20, 0xF455, 0x9B21, 0xF456, 0x9B22, 0xF457, + 0x9B23, 0xF7E0, 0x9B24, 0xF458, 0x9B25, 0xF459, 0x9B26, 0xF45A, 0x9B27, 0xF45B, 0x9B28, 0xF45C, 0x9B29, 0xF45D, 0x9B2A, 0xF45E, + 0x9B2B, 0xF45F, 0x9B2C, 0xF460, 0x9B2D, 0xF461, 0x9B2E, 0xF462, 0x9B2F, 0xDBCB, 0x9B30, 0xF463, 0x9B31, 0xF464, 0x9B32, 0xD8AA, + 0x9B33, 0xF465, 0x9B34, 0xF466, 0x9B35, 0xF467, 0x9B36, 0xF468, 0x9B37, 0xF469, 0x9B38, 0xF46A, 0x9B39, 0xF46B, 0x9B3A, 0xF46C, + 0x9B3B, 0xE5F7, 0x9B3C, 0xB9ED, 0x9B3D, 0xF46D, 0x9B3E, 0xF46E, 0x9B3F, 0xF46F, 0x9B40, 0xF470, 0x9B41, 0xBFFD, 0x9B42, 0xBBEA, + 0x9B43, 0xF7C9, 0x9B44, 0xC6C7, 0x9B45, 0xF7C8, 0x9B46, 0xF471, 0x9B47, 0xF7CA, 0x9B48, 0xF7CC, 0x9B49, 0xF7CB, 0x9B4A, 0xF472, + 0x9B4B, 0xF473, 0x9B4C, 0xF474, 0x9B4D, 0xF7CD, 0x9B4E, 0xF475, 0x9B4F, 0xCEBA, 0x9B50, 0xF476, 0x9B51, 0xF7CE, 0x9B52, 0xF477, + 0x9B53, 0xF478, 0x9B54, 0xC4A7, 0x9B55, 0xF479, 0x9B56, 0xF47A, 0x9B57, 0xF47B, 0x9B58, 0xF47C, 0x9B59, 0xF47D, 0x9B5A, 0xF47E, + 0x9B5B, 0xF480, 0x9B5C, 0xF481, 0x9B5D, 0xF482, 0x9B5E, 0xF483, 0x9B5F, 0xF484, 0x9B60, 0xF485, 0x9B61, 0xF486, 0x9B62, 0xF487, + 0x9B63, 0xF488, 0x9B64, 0xF489, 0x9B65, 0xF48A, 0x9B66, 0xF48B, 0x9B67, 0xF48C, 0x9B68, 0xF48D, 0x9B69, 0xF48E, 0x9B6A, 0xF48F, + 0x9B6B, 0xF490, 0x9B6C, 0xF491, 0x9B6D, 0xF492, 0x9B6E, 0xF493, 0x9B6F, 0xF494, 0x9B70, 0xF495, 0x9B71, 0xF496, 0x9B72, 0xF497, + 0x9B73, 0xF498, 0x9B74, 0xF499, 0x9B75, 0xF49A, 0x9B76, 0xF49B, 0x9B77, 0xF49C, 0x9B78, 0xF49D, 0x9B79, 0xF49E, 0x9B7A, 0xF49F, + 0x9B7B, 0xF4A0, 0x9B7C, 0xF540, 0x9B7D, 0xF541, 0x9B7E, 0xF542, 0x9B7F, 0xF543, 0x9B80, 0xF544, 0x9B81, 0xF545, 0x9B82, 0xF546, + 0x9B83, 0xF547, 0x9B84, 0xF548, 0x9B85, 0xF549, 0x9B86, 0xF54A, 0x9B87, 0xF54B, 0x9B88, 0xF54C, 0x9B89, 0xF54D, 0x9B8A, 0xF54E, + 0x9B8B, 0xF54F, 0x9B8C, 0xF550, 0x9B8D, 0xF551, 0x9B8E, 0xF552, 0x9B8F, 0xF553, 0x9B90, 0xF554, 0x9B91, 0xF555, 0x9B92, 0xF556, + 0x9B93, 0xF557, 0x9B94, 0xF558, 0x9B95, 0xF559, 0x9B96, 0xF55A, 0x9B97, 0xF55B, 0x9B98, 0xF55C, 0x9B99, 0xF55D, 0x9B9A, 0xF55E, + 0x9B9B, 0xF55F, 0x9B9C, 0xF560, 0x9B9D, 0xF561, 0x9B9E, 0xF562, 0x9B9F, 0xF563, 0x9BA0, 0xF564, 0x9BA1, 0xF565, 0x9BA2, 0xF566, + 0x9BA3, 0xF567, 0x9BA4, 0xF568, 0x9BA5, 0xF569, 0x9BA6, 0xF56A, 0x9BA7, 0xF56B, 0x9BA8, 0xF56C, 0x9BA9, 0xF56D, 0x9BAA, 0xF56E, + 0x9BAB, 0xF56F, 0x9BAC, 0xF570, 0x9BAD, 0xF571, 0x9BAE, 0xF572, 0x9BAF, 0xF573, 0x9BB0, 0xF574, 0x9BB1, 0xF575, 0x9BB2, 0xF576, + 0x9BB3, 0xF577, 0x9BB4, 0xF578, 0x9BB5, 0xF579, 0x9BB6, 0xF57A, 0x9BB7, 0xF57B, 0x9BB8, 0xF57C, 0x9BB9, 0xF57D, 0x9BBA, 0xF57E, + 0x9BBB, 0xF580, 0x9BBC, 0xF581, 0x9BBD, 0xF582, 0x9BBE, 0xF583, 0x9BBF, 0xF584, 0x9BC0, 0xF585, 0x9BC1, 0xF586, 0x9BC2, 0xF587, + 0x9BC3, 0xF588, 0x9BC4, 0xF589, 0x9BC5, 0xF58A, 0x9BC6, 0xF58B, 0x9BC7, 0xF58C, 0x9BC8, 0xF58D, 0x9BC9, 0xF58E, 0x9BCA, 0xF58F, + 0x9BCB, 0xF590, 0x9BCC, 0xF591, 0x9BCD, 0xF592, 0x9BCE, 0xF593, 0x9BCF, 0xF594, 0x9BD0, 0xF595, 0x9BD1, 0xF596, 0x9BD2, 0xF597, + 0x9BD3, 0xF598, 0x9BD4, 0xF599, 0x9BD5, 0xF59A, 0x9BD6, 0xF59B, 0x9BD7, 0xF59C, 0x9BD8, 0xF59D, 0x9BD9, 0xF59E, 0x9BDA, 0xF59F, + 0x9BDB, 0xF5A0, 0x9BDC, 0xF640, 0x9BDD, 0xF641, 0x9BDE, 0xF642, 0x9BDF, 0xF643, 0x9BE0, 0xF644, 0x9BE1, 0xF645, 0x9BE2, 0xF646, + 0x9BE3, 0xF647, 0x9BE4, 0xF648, 0x9BE5, 0xF649, 0x9BE6, 0xF64A, 0x9BE7, 0xF64B, 0x9BE8, 0xF64C, 0x9BE9, 0xF64D, 0x9BEA, 0xF64E, + 0x9BEB, 0xF64F, 0x9BEC, 0xF650, 0x9BED, 0xF651, 0x9BEE, 0xF652, 0x9BEF, 0xF653, 0x9BF0, 0xF654, 0x9BF1, 0xF655, 0x9BF2, 0xF656, + 0x9BF3, 0xF657, 0x9BF4, 0xF658, 0x9BF5, 0xF659, 0x9BF6, 0xF65A, 0x9BF7, 0xF65B, 0x9BF8, 0xF65C, 0x9BF9, 0xF65D, 0x9BFA, 0xF65E, + 0x9BFB, 0xF65F, 0x9BFC, 0xF660, 0x9BFD, 0xF661, 0x9BFE, 0xF662, 0x9BFF, 0xF663, 0x9C00, 0xF664, 0x9C01, 0xF665, 0x9C02, 0xF666, + 0x9C03, 0xF667, 0x9C04, 0xF668, 0x9C05, 0xF669, 0x9C06, 0xF66A, 0x9C07, 0xF66B, 0x9C08, 0xF66C, 0x9C09, 0xF66D, 0x9C0A, 0xF66E, + 0x9C0B, 0xF66F, 0x9C0C, 0xF670, 0x9C0D, 0xF671, 0x9C0E, 0xF672, 0x9C0F, 0xF673, 0x9C10, 0xF674, 0x9C11, 0xF675, 0x9C12, 0xF676, + 0x9C13, 0xF677, 0x9C14, 0xF678, 0x9C15, 0xF679, 0x9C16, 0xF67A, 0x9C17, 0xF67B, 0x9C18, 0xF67C, 0x9C19, 0xF67D, 0x9C1A, 0xF67E, + 0x9C1B, 0xF680, 0x9C1C, 0xF681, 0x9C1D, 0xF682, 0x9C1E, 0xF683, 0x9C1F, 0xF684, 0x9C20, 0xF685, 0x9C21, 0xF686, 0x9C22, 0xF687, + 0x9C23, 0xF688, 0x9C24, 0xF689, 0x9C25, 0xF68A, 0x9C26, 0xF68B, 0x9C27, 0xF68C, 0x9C28, 0xF68D, 0x9C29, 0xF68E, 0x9C2A, 0xF68F, + 0x9C2B, 0xF690, 0x9C2C, 0xF691, 0x9C2D, 0xF692, 0x9C2E, 0xF693, 0x9C2F, 0xF694, 0x9C30, 0xF695, 0x9C31, 0xF696, 0x9C32, 0xF697, + 0x9C33, 0xF698, 0x9C34, 0xF699, 0x9C35, 0xF69A, 0x9C36, 0xF69B, 0x9C37, 0xF69C, 0x9C38, 0xF69D, 0x9C39, 0xF69E, 0x9C3A, 0xF69F, + 0x9C3B, 0xF6A0, 0x9C3C, 0xF740, 0x9C3D, 0xF741, 0x9C3E, 0xF742, 0x9C3F, 0xF743, 0x9C40, 0xF744, 0x9C41, 0xF745, 0x9C42, 0xF746, + 0x9C43, 0xF747, 0x9C44, 0xF748, 0x9C45, 0xF749, 0x9C46, 0xF74A, 0x9C47, 0xF74B, 0x9C48, 0xF74C, 0x9C49, 0xF74D, 0x9C4A, 0xF74E, + 0x9C4B, 0xF74F, 0x9C4C, 0xF750, 0x9C4D, 0xF751, 0x9C4E, 0xF752, 0x9C4F, 0xF753, 0x9C50, 0xF754, 0x9C51, 0xF755, 0x9C52, 0xF756, + 0x9C53, 0xF757, 0x9C54, 0xF758, 0x9C55, 0xF759, 0x9C56, 0xF75A, 0x9C57, 0xF75B, 0x9C58, 0xF75C, 0x9C59, 0xF75D, 0x9C5A, 0xF75E, + 0x9C5B, 0xF75F, 0x9C5C, 0xF760, 0x9C5D, 0xF761, 0x9C5E, 0xF762, 0x9C5F, 0xF763, 0x9C60, 0xF764, 0x9C61, 0xF765, 0x9C62, 0xF766, + 0x9C63, 0xF767, 0x9C64, 0xF768, 0x9C65, 0xF769, 0x9C66, 0xF76A, 0x9C67, 0xF76B, 0x9C68, 0xF76C, 0x9C69, 0xF76D, 0x9C6A, 0xF76E, + 0x9C6B, 0xF76F, 0x9C6C, 0xF770, 0x9C6D, 0xF771, 0x9C6E, 0xF772, 0x9C6F, 0xF773, 0x9C70, 0xF774, 0x9C71, 0xF775, 0x9C72, 0xF776, + 0x9C73, 0xF777, 0x9C74, 0xF778, 0x9C75, 0xF779, 0x9C76, 0xF77A, 0x9C77, 0xF77B, 0x9C78, 0xF77C, 0x9C79, 0xF77D, 0x9C7A, 0xF77E, + 0x9C7B, 0xF780, 0x9C7C, 0xD3E3, 0x9C7D, 0xF781, 0x9C7E, 0xF782, 0x9C7F, 0xF6CF, 0x9C80, 0xF783, 0x9C81, 0xC2B3, 0x9C82, 0xF6D0, + 0x9C83, 0xF784, 0x9C84, 0xF785, 0x9C85, 0xF6D1, 0x9C86, 0xF6D2, 0x9C87, 0xF6D3, 0x9C88, 0xF6D4, 0x9C89, 0xF786, 0x9C8A, 0xF787, + 0x9C8B, 0xF6D6, 0x9C8C, 0xF788, 0x9C8D, 0xB1AB, 0x9C8E, 0xF6D7, 0x9C8F, 0xF789, 0x9C90, 0xF6D8, 0x9C91, 0xF6D9, 0x9C92, 0xF6DA, + 0x9C93, 0xF78A, 0x9C94, 0xF6DB, 0x9C95, 0xF6DC, 0x9C96, 0xF78B, 0x9C97, 0xF78C, 0x9C98, 0xF78D, 0x9C99, 0xF78E, 0x9C9A, 0xF6DD, + 0x9C9B, 0xF6DE, 0x9C9C, 0xCFCA, 0x9C9D, 0xF78F, 0x9C9E, 0xF6DF, 0x9C9F, 0xF6E0, 0x9CA0, 0xF6E1, 0x9CA1, 0xF6E2, 0x9CA2, 0xF6E3, + 0x9CA3, 0xF6E4, 0x9CA4, 0xC0F0, 0x9CA5, 0xF6E5, 0x9CA6, 0xF6E6, 0x9CA7, 0xF6E7, 0x9CA8, 0xF6E8, 0x9CA9, 0xF6E9, 0x9CAA, 0xF790, + 0x9CAB, 0xF6EA, 0x9CAC, 0xF791, 0x9CAD, 0xF6EB, 0x9CAE, 0xF6EC, 0x9CAF, 0xF792, 0x9CB0, 0xF6ED, 0x9CB1, 0xF6EE, 0x9CB2, 0xF6EF, + 0x9CB3, 0xF6F0, 0x9CB4, 0xF6F1, 0x9CB5, 0xF6F2, 0x9CB6, 0xF6F3, 0x9CB7, 0xF6F4, 0x9CB8, 0xBEA8, 0x9CB9, 0xF793, 0x9CBA, 0xF6F5, + 0x9CBB, 0xF6F6, 0x9CBC, 0xF6F7, 0x9CBD, 0xF6F8, 0x9CBE, 0xF794, 0x9CBF, 0xF795, 0x9CC0, 0xF796, 0x9CC1, 0xF797, 0x9CC2, 0xF798, + 0x9CC3, 0xC8FA, 0x9CC4, 0xF6F9, 0x9CC5, 0xF6FA, 0x9CC6, 0xF6FB, 0x9CC7, 0xF6FC, 0x9CC8, 0xF799, 0x9CC9, 0xF79A, 0x9CCA, 0xF6FD, + 0x9CCB, 0xF6FE, 0x9CCC, 0xF7A1, 0x9CCD, 0xF7A2, 0x9CCE, 0xF7A3, 0x9CCF, 0xF7A4, 0x9CD0, 0xF7A5, 0x9CD1, 0xF79B, 0x9CD2, 0xF79C, + 0x9CD3, 0xF7A6, 0x9CD4, 0xF7A7, 0x9CD5, 0xF7A8, 0x9CD6, 0xB1EE, 0x9CD7, 0xF7A9, 0x9CD8, 0xF7AA, 0x9CD9, 0xF7AB, 0x9CDA, 0xF79D, + 0x9CDB, 0xF79E, 0x9CDC, 0xF7AC, 0x9CDD, 0xF7AD, 0x9CDE, 0xC1DB, 0x9CDF, 0xF7AE, 0x9CE0, 0xF79F, 0x9CE1, 0xF7A0, 0x9CE2, 0xF7AF, + 0x9CE3, 0xF840, 0x9CE4, 0xF841, 0x9CE5, 0xF842, 0x9CE6, 0xF843, 0x9CE7, 0xF844, 0x9CE8, 0xF845, 0x9CE9, 0xF846, 0x9CEA, 0xF847, + 0x9CEB, 0xF848, 0x9CEC, 0xF849, 0x9CED, 0xF84A, 0x9CEE, 0xF84B, 0x9CEF, 0xF84C, 0x9CF0, 0xF84D, 0x9CF1, 0xF84E, 0x9CF2, 0xF84F, + 0x9CF3, 0xF850, 0x9CF4, 0xF851, 0x9CF5, 0xF852, 0x9CF6, 0xF853, 0x9CF7, 0xF854, 0x9CF8, 0xF855, 0x9CF9, 0xF856, 0x9CFA, 0xF857, + 0x9CFB, 0xF858, 0x9CFC, 0xF859, 0x9CFD, 0xF85A, 0x9CFE, 0xF85B, 0x9CFF, 0xF85C, 0x9D00, 0xF85D, 0x9D01, 0xF85E, 0x9D02, 0xF85F, + 0x9D03, 0xF860, 0x9D04, 0xF861, 0x9D05, 0xF862, 0x9D06, 0xF863, 0x9D07, 0xF864, 0x9D08, 0xF865, 0x9D09, 0xF866, 0x9D0A, 0xF867, + 0x9D0B, 0xF868, 0x9D0C, 0xF869, 0x9D0D, 0xF86A, 0x9D0E, 0xF86B, 0x9D0F, 0xF86C, 0x9D10, 0xF86D, 0x9D11, 0xF86E, 0x9D12, 0xF86F, + 0x9D13, 0xF870, 0x9D14, 0xF871, 0x9D15, 0xF872, 0x9D16, 0xF873, 0x9D17, 0xF874, 0x9D18, 0xF875, 0x9D19, 0xF876, 0x9D1A, 0xF877, + 0x9D1B, 0xF878, 0x9D1C, 0xF879, 0x9D1D, 0xF87A, 0x9D1E, 0xF87B, 0x9D1F, 0xF87C, 0x9D20, 0xF87D, 0x9D21, 0xF87E, 0x9D22, 0xF880, + 0x9D23, 0xF881, 0x9D24, 0xF882, 0x9D25, 0xF883, 0x9D26, 0xF884, 0x9D27, 0xF885, 0x9D28, 0xF886, 0x9D29, 0xF887, 0x9D2A, 0xF888, + 0x9D2B, 0xF889, 0x9D2C, 0xF88A, 0x9D2D, 0xF88B, 0x9D2E, 0xF88C, 0x9D2F, 0xF88D, 0x9D30, 0xF88E, 0x9D31, 0xF88F, 0x9D32, 0xF890, + 0x9D33, 0xF891, 0x9D34, 0xF892, 0x9D35, 0xF893, 0x9D36, 0xF894, 0x9D37, 0xF895, 0x9D38, 0xF896, 0x9D39, 0xF897, 0x9D3A, 0xF898, + 0x9D3B, 0xF899, 0x9D3C, 0xF89A, 0x9D3D, 0xF89B, 0x9D3E, 0xF89C, 0x9D3F, 0xF89D, 0x9D40, 0xF89E, 0x9D41, 0xF89F, 0x9D42, 0xF8A0, + 0x9D43, 0xF940, 0x9D44, 0xF941, 0x9D45, 0xF942, 0x9D46, 0xF943, 0x9D47, 0xF944, 0x9D48, 0xF945, 0x9D49, 0xF946, 0x9D4A, 0xF947, + 0x9D4B, 0xF948, 0x9D4C, 0xF949, 0x9D4D, 0xF94A, 0x9D4E, 0xF94B, 0x9D4F, 0xF94C, 0x9D50, 0xF94D, 0x9D51, 0xF94E, 0x9D52, 0xF94F, + 0x9D53, 0xF950, 0x9D54, 0xF951, 0x9D55, 0xF952, 0x9D56, 0xF953, 0x9D57, 0xF954, 0x9D58, 0xF955, 0x9D59, 0xF956, 0x9D5A, 0xF957, + 0x9D5B, 0xF958, 0x9D5C, 0xF959, 0x9D5D, 0xF95A, 0x9D5E, 0xF95B, 0x9D5F, 0xF95C, 0x9D60, 0xF95D, 0x9D61, 0xF95E, 0x9D62, 0xF95F, + 0x9D63, 0xF960, 0x9D64, 0xF961, 0x9D65, 0xF962, 0x9D66, 0xF963, 0x9D67, 0xF964, 0x9D68, 0xF965, 0x9D69, 0xF966, 0x9D6A, 0xF967, + 0x9D6B, 0xF968, 0x9D6C, 0xF969, 0x9D6D, 0xF96A, 0x9D6E, 0xF96B, 0x9D6F, 0xF96C, 0x9D70, 0xF96D, 0x9D71, 0xF96E, 0x9D72, 0xF96F, + 0x9D73, 0xF970, 0x9D74, 0xF971, 0x9D75, 0xF972, 0x9D76, 0xF973, 0x9D77, 0xF974, 0x9D78, 0xF975, 0x9D79, 0xF976, 0x9D7A, 0xF977, + 0x9D7B, 0xF978, 0x9D7C, 0xF979, 0x9D7D, 0xF97A, 0x9D7E, 0xF97B, 0x9D7F, 0xF97C, 0x9D80, 0xF97D, 0x9D81, 0xF97E, 0x9D82, 0xF980, + 0x9D83, 0xF981, 0x9D84, 0xF982, 0x9D85, 0xF983, 0x9D86, 0xF984, 0x9D87, 0xF985, 0x9D88, 0xF986, 0x9D89, 0xF987, 0x9D8A, 0xF988, + 0x9D8B, 0xF989, 0x9D8C, 0xF98A, 0x9D8D, 0xF98B, 0x9D8E, 0xF98C, 0x9D8F, 0xF98D, 0x9D90, 0xF98E, 0x9D91, 0xF98F, 0x9D92, 0xF990, + 0x9D93, 0xF991, 0x9D94, 0xF992, 0x9D95, 0xF993, 0x9D96, 0xF994, 0x9D97, 0xF995, 0x9D98, 0xF996, 0x9D99, 0xF997, 0x9D9A, 0xF998, + 0x9D9B, 0xF999, 0x9D9C, 0xF99A, 0x9D9D, 0xF99B, 0x9D9E, 0xF99C, 0x9D9F, 0xF99D, 0x9DA0, 0xF99E, 0x9DA1, 0xF99F, 0x9DA2, 0xF9A0, + 0x9DA3, 0xFA40, 0x9DA4, 0xFA41, 0x9DA5, 0xFA42, 0x9DA6, 0xFA43, 0x9DA7, 0xFA44, 0x9DA8, 0xFA45, 0x9DA9, 0xFA46, 0x9DAA, 0xFA47, + 0x9DAB, 0xFA48, 0x9DAC, 0xFA49, 0x9DAD, 0xFA4A, 0x9DAE, 0xFA4B, 0x9DAF, 0xFA4C, 0x9DB0, 0xFA4D, 0x9DB1, 0xFA4E, 0x9DB2, 0xFA4F, + 0x9DB3, 0xFA50, 0x9DB4, 0xFA51, 0x9DB5, 0xFA52, 0x9DB6, 0xFA53, 0x9DB7, 0xFA54, 0x9DB8, 0xFA55, 0x9DB9, 0xFA56, 0x9DBA, 0xFA57, + 0x9DBB, 0xFA58, 0x9DBC, 0xFA59, 0x9DBD, 0xFA5A, 0x9DBE, 0xFA5B, 0x9DBF, 0xFA5C, 0x9DC0, 0xFA5D, 0x9DC1, 0xFA5E, 0x9DC2, 0xFA5F, + 0x9DC3, 0xFA60, 0x9DC4, 0xFA61, 0x9DC5, 0xFA62, 0x9DC6, 0xFA63, 0x9DC7, 0xFA64, 0x9DC8, 0xFA65, 0x9DC9, 0xFA66, 0x9DCA, 0xFA67, + 0x9DCB, 0xFA68, 0x9DCC, 0xFA69, 0x9DCD, 0xFA6A, 0x9DCE, 0xFA6B, 0x9DCF, 0xFA6C, 0x9DD0, 0xFA6D, 0x9DD1, 0xFA6E, 0x9DD2, 0xFA6F, + 0x9DD3, 0xFA70, 0x9DD4, 0xFA71, 0x9DD5, 0xFA72, 0x9DD6, 0xFA73, 0x9DD7, 0xFA74, 0x9DD8, 0xFA75, 0x9DD9, 0xFA76, 0x9DDA, 0xFA77, + 0x9DDB, 0xFA78, 0x9DDC, 0xFA79, 0x9DDD, 0xFA7A, 0x9DDE, 0xFA7B, 0x9DDF, 0xFA7C, 0x9DE0, 0xFA7D, 0x9DE1, 0xFA7E, 0x9DE2, 0xFA80, + 0x9DE3, 0xFA81, 0x9DE4, 0xFA82, 0x9DE5, 0xFA83, 0x9DE6, 0xFA84, 0x9DE7, 0xFA85, 0x9DE8, 0xFA86, 0x9DE9, 0xFA87, 0x9DEA, 0xFA88, + 0x9DEB, 0xFA89, 0x9DEC, 0xFA8A, 0x9DED, 0xFA8B, 0x9DEE, 0xFA8C, 0x9DEF, 0xFA8D, 0x9DF0, 0xFA8E, 0x9DF1, 0xFA8F, 0x9DF2, 0xFA90, + 0x9DF3, 0xFA91, 0x9DF4, 0xFA92, 0x9DF5, 0xFA93, 0x9DF6, 0xFA94, 0x9DF7, 0xFA95, 0x9DF8, 0xFA96, 0x9DF9, 0xFA97, 0x9DFA, 0xFA98, + 0x9DFB, 0xFA99, 0x9DFC, 0xFA9A, 0x9DFD, 0xFA9B, 0x9DFE, 0xFA9C, 0x9DFF, 0xFA9D, 0x9E00, 0xFA9E, 0x9E01, 0xFA9F, 0x9E02, 0xFAA0, + 0x9E03, 0xFB40, 0x9E04, 0xFB41, 0x9E05, 0xFB42, 0x9E06, 0xFB43, 0x9E07, 0xFB44, 0x9E08, 0xFB45, 0x9E09, 0xFB46, 0x9E0A, 0xFB47, + 0x9E0B, 0xFB48, 0x9E0C, 0xFB49, 0x9E0D, 0xFB4A, 0x9E0E, 0xFB4B, 0x9E0F, 0xFB4C, 0x9E10, 0xFB4D, 0x9E11, 0xFB4E, 0x9E12, 0xFB4F, + 0x9E13, 0xFB50, 0x9E14, 0xFB51, 0x9E15, 0xFB52, 0x9E16, 0xFB53, 0x9E17, 0xFB54, 0x9E18, 0xFB55, 0x9E19, 0xFB56, 0x9E1A, 0xFB57, + 0x9E1B, 0xFB58, 0x9E1C, 0xFB59, 0x9E1D, 0xFB5A, 0x9E1E, 0xFB5B, 0x9E1F, 0xC4F1, 0x9E20, 0xF0AF, 0x9E21, 0xBCA6, 0x9E22, 0xF0B0, + 0x9E23, 0xC3F9, 0x9E24, 0xFB5C, 0x9E25, 0xC5B8, 0x9E26, 0xD1BB, 0x9E27, 0xFB5D, 0x9E28, 0xF0B1, 0x9E29, 0xF0B2, 0x9E2A, 0xF0B3, + 0x9E2B, 0xF0B4, 0x9E2C, 0xF0B5, 0x9E2D, 0xD1BC, 0x9E2E, 0xFB5E, 0x9E2F, 0xD1EC, 0x9E30, 0xFB5F, 0x9E31, 0xF0B7, 0x9E32, 0xF0B6, + 0x9E33, 0xD4A7, 0x9E34, 0xFB60, 0x9E35, 0xCDD2, 0x9E36, 0xF0B8, 0x9E37, 0xF0BA, 0x9E38, 0xF0B9, 0x9E39, 0xF0BB, 0x9E3A, 0xF0BC, + 0x9E3B, 0xFB61, 0x9E3C, 0xFB62, 0x9E3D, 0xB8EB, 0x9E3E, 0xF0BD, 0x9E3F, 0xBAE8, 0x9E40, 0xFB63, 0x9E41, 0xF0BE, 0x9E42, 0xF0BF, + 0x9E43, 0xBEE9, 0x9E44, 0xF0C0, 0x9E45, 0xB6EC, 0x9E46, 0xF0C1, 0x9E47, 0xF0C2, 0x9E48, 0xF0C3, 0x9E49, 0xF0C4, 0x9E4A, 0xC8B5, + 0x9E4B, 0xF0C5, 0x9E4C, 0xF0C6, 0x9E4D, 0xFB64, 0x9E4E, 0xF0C7, 0x9E4F, 0xC5F4, 0x9E50, 0xFB65, 0x9E51, 0xF0C8, 0x9E52, 0xFB66, + 0x9E53, 0xFB67, 0x9E54, 0xFB68, 0x9E55, 0xF0C9, 0x9E56, 0xFB69, 0x9E57, 0xF0CA, 0x9E58, 0xF7BD, 0x9E59, 0xFB6A, 0x9E5A, 0xF0CB, + 0x9E5B, 0xF0CC, 0x9E5C, 0xF0CD, 0x9E5D, 0xFB6B, 0x9E5E, 0xF0CE, 0x9E5F, 0xFB6C, 0x9E60, 0xFB6D, 0x9E61, 0xFB6E, 0x9E62, 0xFB6F, + 0x9E63, 0xF0CF, 0x9E64, 0xBAD7, 0x9E65, 0xFB70, 0x9E66, 0xF0D0, 0x9E67, 0xF0D1, 0x9E68, 0xF0D2, 0x9E69, 0xF0D3, 0x9E6A, 0xF0D4, + 0x9E6B, 0xF0D5, 0x9E6C, 0xF0D6, 0x9E6D, 0xF0D8, 0x9E6E, 0xFB71, 0x9E6F, 0xFB72, 0x9E70, 0xD3A5, 0x9E71, 0xF0D7, 0x9E72, 0xFB73, + 0x9E73, 0xF0D9, 0x9E74, 0xFB74, 0x9E75, 0xFB75, 0x9E76, 0xFB76, 0x9E77, 0xFB77, 0x9E78, 0xFB78, 0x9E79, 0xFB79, 0x9E7A, 0xFB7A, + 0x9E7B, 0xFB7B, 0x9E7C, 0xFB7C, 0x9E7D, 0xFB7D, 0x9E7E, 0xF5BA, 0x9E7F, 0xC2B9, 0x9E80, 0xFB7E, 0x9E81, 0xFB80, 0x9E82, 0xF7E4, + 0x9E83, 0xFB81, 0x9E84, 0xFB82, 0x9E85, 0xFB83, 0x9E86, 0xFB84, 0x9E87, 0xF7E5, 0x9E88, 0xF7E6, 0x9E89, 0xFB85, 0x9E8A, 0xFB86, + 0x9E8B, 0xF7E7, 0x9E8C, 0xFB87, 0x9E8D, 0xFB88, 0x9E8E, 0xFB89, 0x9E8F, 0xFB8A, 0x9E90, 0xFB8B, 0x9E91, 0xFB8C, 0x9E92, 0xF7E8, + 0x9E93, 0xC2B4, 0x9E94, 0xFB8D, 0x9E95, 0xFB8E, 0x9E96, 0xFB8F, 0x9E97, 0xFB90, 0x9E98, 0xFB91, 0x9E99, 0xFB92, 0x9E9A, 0xFB93, + 0x9E9B, 0xFB94, 0x9E9C, 0xFB95, 0x9E9D, 0xF7EA, 0x9E9E, 0xFB96, 0x9E9F, 0xF7EB, 0x9EA0, 0xFB97, 0x9EA1, 0xFB98, 0x9EA2, 0xFB99, + 0x9EA3, 0xFB9A, 0x9EA4, 0xFB9B, 0x9EA5, 0xFB9C, 0x9EA6, 0xC2F3, 0x9EA7, 0xFB9D, 0x9EA8, 0xFB9E, 0x9EA9, 0xFB9F, 0x9EAA, 0xFBA0, + 0x9EAB, 0xFC40, 0x9EAC, 0xFC41, 0x9EAD, 0xFC42, 0x9EAE, 0xFC43, 0x9EAF, 0xFC44, 0x9EB0, 0xFC45, 0x9EB1, 0xFC46, 0x9EB2, 0xFC47, + 0x9EB3, 0xFC48, 0x9EB4, 0xF4F0, 0x9EB5, 0xFC49, 0x9EB6, 0xFC4A, 0x9EB7, 0xFC4B, 0x9EB8, 0xF4EF, 0x9EB9, 0xFC4C, 0x9EBA, 0xFC4D, + 0x9EBB, 0xC2E9, 0x9EBC, 0xFC4E, 0x9EBD, 0xF7E1, 0x9EBE, 0xF7E2, 0x9EBF, 0xFC4F, 0x9EC0, 0xFC50, 0x9EC1, 0xFC51, 0x9EC2, 0xFC52, + 0x9EC3, 0xFC53, 0x9EC4, 0xBBC6, 0x9EC5, 0xFC54, 0x9EC6, 0xFC55, 0x9EC7, 0xFC56, 0x9EC8, 0xFC57, 0x9EC9, 0xD9E4, 0x9ECA, 0xFC58, + 0x9ECB, 0xFC59, 0x9ECC, 0xFC5A, 0x9ECD, 0xCAF2, 0x9ECE, 0xC0E8, 0x9ECF, 0xF0A4, 0x9ED0, 0xFC5B, 0x9ED1, 0xBADA, 0x9ED2, 0xFC5C, + 0x9ED3, 0xFC5D, 0x9ED4, 0xC7AD, 0x9ED5, 0xFC5E, 0x9ED6, 0xFC5F, 0x9ED7, 0xFC60, 0x9ED8, 0xC4AC, 0x9ED9, 0xFC61, 0x9EDA, 0xFC62, + 0x9EDB, 0xF7EC, 0x9EDC, 0xF7ED, 0x9EDD, 0xF7EE, 0x9EDE, 0xFC63, 0x9EDF, 0xF7F0, 0x9EE0, 0xF7EF, 0x9EE1, 0xFC64, 0x9EE2, 0xF7F1, + 0x9EE3, 0xFC65, 0x9EE4, 0xFC66, 0x9EE5, 0xF7F4, 0x9EE6, 0xFC67, 0x9EE7, 0xF7F3, 0x9EE8, 0xFC68, 0x9EE9, 0xF7F2, 0x9EEA, 0xF7F5, + 0x9EEB, 0xFC69, 0x9EEC, 0xFC6A, 0x9EED, 0xFC6B, 0x9EEE, 0xFC6C, 0x9EEF, 0xF7F6, 0x9EF0, 0xFC6D, 0x9EF1, 0xFC6E, 0x9EF2, 0xFC6F, + 0x9EF3, 0xFC70, 0x9EF4, 0xFC71, 0x9EF5, 0xFC72, 0x9EF6, 0xFC73, 0x9EF7, 0xFC74, 0x9EF8, 0xFC75, 0x9EF9, 0xEDE9, 0x9EFA, 0xFC76, + 0x9EFB, 0xEDEA, 0x9EFC, 0xEDEB, 0x9EFD, 0xFC77, 0x9EFE, 0xF6BC, 0x9EFF, 0xFC78, 0x9F00, 0xFC79, 0x9F01, 0xFC7A, 0x9F02, 0xFC7B, + 0x9F03, 0xFC7C, 0x9F04, 0xFC7D, 0x9F05, 0xFC7E, 0x9F06, 0xFC80, 0x9F07, 0xFC81, 0x9F08, 0xFC82, 0x9F09, 0xFC83, 0x9F0A, 0xFC84, + 0x9F0B, 0xF6BD, 0x9F0C, 0xFC85, 0x9F0D, 0xF6BE, 0x9F0E, 0xB6A6, 0x9F0F, 0xFC86, 0x9F10, 0xD8BE, 0x9F11, 0xFC87, 0x9F12, 0xFC88, + 0x9F13, 0xB9C4, 0x9F14, 0xFC89, 0x9F15, 0xFC8A, 0x9F16, 0xFC8B, 0x9F17, 0xD8BB, 0x9F18, 0xFC8C, 0x9F19, 0xDCB1, 0x9F1A, 0xFC8D, + 0x9F1B, 0xFC8E, 0x9F1C, 0xFC8F, 0x9F1D, 0xFC90, 0x9F1E, 0xFC91, 0x9F1F, 0xFC92, 0x9F20, 0xCAF3, 0x9F21, 0xFC93, 0x9F22, 0xF7F7, + 0x9F23, 0xFC94, 0x9F24, 0xFC95, 0x9F25, 0xFC96, 0x9F26, 0xFC97, 0x9F27, 0xFC98, 0x9F28, 0xFC99, 0x9F29, 0xFC9A, 0x9F2A, 0xFC9B, + 0x9F2B, 0xFC9C, 0x9F2C, 0xF7F8, 0x9F2D, 0xFC9D, 0x9F2E, 0xFC9E, 0x9F2F, 0xF7F9, 0x9F30, 0xFC9F, 0x9F31, 0xFCA0, 0x9F32, 0xFD40, + 0x9F33, 0xFD41, 0x9F34, 0xFD42, 0x9F35, 0xFD43, 0x9F36, 0xFD44, 0x9F37, 0xF7FB, 0x9F38, 0xFD45, 0x9F39, 0xF7FA, 0x9F3A, 0xFD46, + 0x9F3B, 0xB1C7, 0x9F3C, 0xFD47, 0x9F3D, 0xF7FC, 0x9F3E, 0xF7FD, 0x9F3F, 0xFD48, 0x9F40, 0xFD49, 0x9F41, 0xFD4A, 0x9F42, 0xFD4B, + 0x9F43, 0xFD4C, 0x9F44, 0xF7FE, 0x9F45, 0xFD4D, 0x9F46, 0xFD4E, 0x9F47, 0xFD4F, 0x9F48, 0xFD50, 0x9F49, 0xFD51, 0x9F4A, 0xFD52, + 0x9F4B, 0xFD53, 0x9F4C, 0xFD54, 0x9F4D, 0xFD55, 0x9F4E, 0xFD56, 0x9F4F, 0xFD57, 0x9F50, 0xC6EB, 0x9F51, 0xECB4, 0x9F52, 0xFD58, + 0x9F53, 0xFD59, 0x9F54, 0xFD5A, 0x9F55, 0xFD5B, 0x9F56, 0xFD5C, 0x9F57, 0xFD5D, 0x9F58, 0xFD5E, 0x9F59, 0xFD5F, 0x9F5A, 0xFD60, + 0x9F5B, 0xFD61, 0x9F5C, 0xFD62, 0x9F5D, 0xFD63, 0x9F5E, 0xFD64, 0x9F5F, 0xFD65, 0x9F60, 0xFD66, 0x9F61, 0xFD67, 0x9F62, 0xFD68, + 0x9F63, 0xFD69, 0x9F64, 0xFD6A, 0x9F65, 0xFD6B, 0x9F66, 0xFD6C, 0x9F67, 0xFD6D, 0x9F68, 0xFD6E, 0x9F69, 0xFD6F, 0x9F6A, 0xFD70, + 0x9F6B, 0xFD71, 0x9F6C, 0xFD72, 0x9F6D, 0xFD73, 0x9F6E, 0xFD74, 0x9F6F, 0xFD75, 0x9F70, 0xFD76, 0x9F71, 0xFD77, 0x9F72, 0xFD78, + 0x9F73, 0xFD79, 0x9F74, 0xFD7A, 0x9F75, 0xFD7B, 0x9F76, 0xFD7C, 0x9F77, 0xFD7D, 0x9F78, 0xFD7E, 0x9F79, 0xFD80, 0x9F7A, 0xFD81, + 0x9F7B, 0xFD82, 0x9F7C, 0xFD83, 0x9F7D, 0xFD84, 0x9F7E, 0xFD85, 0x9F7F, 0xB3DD, 0x9F80, 0xF6B3, 0x9F81, 0xFD86, 0x9F82, 0xFD87, + 0x9F83, 0xF6B4, 0x9F84, 0xC1E4, 0x9F85, 0xF6B5, 0x9F86, 0xF6B6, 0x9F87, 0xF6B7, 0x9F88, 0xF6B8, 0x9F89, 0xF6B9, 0x9F8A, 0xF6BA, + 0x9F8B, 0xC8A3, 0x9F8C, 0xF6BB, 0x9F8D, 0xFD88, 0x9F8E, 0xFD89, 0x9F8F, 0xFD8A, 0x9F90, 0xFD8B, 0x9F91, 0xFD8C, 0x9F92, 0xFD8D, + 0x9F93, 0xFD8E, 0x9F94, 0xFD8F, 0x9F95, 0xFD90, 0x9F96, 0xFD91, 0x9F97, 0xFD92, 0x9F98, 0xFD93, 0x9F99, 0xC1FA, 0x9F9A, 0xB9A8, + 0x9F9B, 0xEDE8, 0x9F9C, 0xFD94, 0x9F9D, 0xFD95, 0x9F9E, 0xFD96, 0x9F9F, 0xB9EA, 0x9FA0, 0xD9DF, 0x9FA1, 0xFD97, 0x9FA2, 0xFD98, + 0x9FA3, 0xFD99, 0x9FA4, 0xFD9A, 0x9FA5, 0xFD9B, 0xF92C, 0xFD9C, 0xF979, 0xFD9D, 0xF995, 0xFD9E, 0xF9E7, 0xFD9F, 0xF9F1, 0xFDA0, + 0xFA0C, 0xFE40, 0xFA0D, 0xFE41, 0xFA0E, 0xFE42, 0xFA0F, 0xFE43, 0xFA11, 0xFE44, 0xFA13, 0xFE45, 0xFA14, 0xFE46, 0xFA18, 0xFE47, + 0xFA1F, 0xFE48, 0xFA20, 0xFE49, 0xFA21, 0xFE4A, 0xFA23, 0xFE4B, 0xFA24, 0xFE4C, 0xFA27, 0xFE4D, 0xFA28, 0xFE4E, 0xFA29, 0xFE4F, + 0xFE30, 0xA955, 0xFE31, 0xA6F2, 0xFE33, 0xA6F4, 0xFE34, 0xA6F5, 0xFE35, 0xA6E0, 0xFE36, 0xA6E1, 0xFE37, 0xA6F0, 0xFE38, 0xA6F1, + 0xFE39, 0xA6E2, 0xFE3A, 0xA6E3, 0xFE3B, 0xA6EE, 0xFE3C, 0xA6EF, 0xFE3D, 0xA6E6, 0xFE3E, 0xA6E7, 0xFE3F, 0xA6E4, 0xFE40, 0xA6E5, + 0xFE41, 0xA6E8, 0xFE42, 0xA6E9, 0xFE43, 0xA6EA, 0xFE44, 0xA6EB, 0xFE49, 0xA968, 0xFE4A, 0xA969, 0xFE4B, 0xA96A, 0xFE4C, 0xA96B, + 0xFE4D, 0xA96C, 0xFE4E, 0xA96D, 0xFE4F, 0xA96E, 0xFE50, 0xA96F, 0xFE51, 0xA970, 0xFE52, 0xA971, 0xFE54, 0xA972, 0xFE55, 0xA973, + 0xFE56, 0xA974, 0xFE57, 0xA975, 0xFE59, 0xA976, 0xFE5A, 0xA977, 0xFE5B, 0xA978, 0xFE5C, 0xA979, 0xFE5D, 0xA97A, 0xFE5E, 0xA97B, + 0xFE5F, 0xA97C, 0xFE60, 0xA97D, 0xFE61, 0xA97E, 0xFE62, 0xA980, 0xFE63, 0xA981, 0xFE64, 0xA982, 0xFE65, 0xA983, 0xFE66, 0xA984, + 0xFE68, 0xA985, 0xFE69, 0xA986, 0xFE6A, 0xA987, 0xFE6B, 0xA988, 0xFF01, 0xA3A1, 0xFF02, 0xA3A2, 0xFF03, 0xA3A3, 0xFF04, 0xA1E7, + 0xFF05, 0xA3A5, 0xFF06, 0xA3A6, 0xFF07, 0xA3A7, 0xFF08, 0xA3A8, 0xFF09, 0xA3A9, 0xFF0A, 0xA3AA, 0xFF0B, 0xA3AB, 0xFF0C, 0xA3AC, + 0xFF0D, 0xA3AD, 0xFF0E, 0xA3AE, 0xFF0F, 0xA3AF, 0xFF10, 0xA3B0, 0xFF11, 0xA3B1, 0xFF12, 0xA3B2, 0xFF13, 0xA3B3, 0xFF14, 0xA3B4, + 0xFF15, 0xA3B5, 0xFF16, 0xA3B6, 0xFF17, 0xA3B7, 0xFF18, 0xA3B8, 0xFF19, 0xA3B9, 0xFF1A, 0xA3BA, 0xFF1B, 0xA3BB, 0xFF1C, 0xA3BC, + 0xFF1D, 0xA3BD, 0xFF1E, 0xA3BE, 0xFF1F, 0xA3BF, 0xFF20, 0xA3C0, 0xFF21, 0xA3C1, 0xFF22, 0xA3C2, 0xFF23, 0xA3C3, 0xFF24, 0xA3C4, + 0xFF25, 0xA3C5, 0xFF26, 0xA3C6, 0xFF27, 0xA3C7, 0xFF28, 0xA3C8, 0xFF29, 0xA3C9, 0xFF2A, 0xA3CA, 0xFF2B, 0xA3CB, 0xFF2C, 0xA3CC, + 0xFF2D, 0xA3CD, 0xFF2E, 0xA3CE, 0xFF2F, 0xA3CF, 0xFF30, 0xA3D0, 0xFF31, 0xA3D1, 0xFF32, 0xA3D2, 0xFF33, 0xA3D3, 0xFF34, 0xA3D4, + 0xFF35, 0xA3D5, 0xFF36, 0xA3D6, 0xFF37, 0xA3D7, 0xFF38, 0xA3D8, 0xFF39, 0xA3D9, 0xFF3A, 0xA3DA, 0xFF3B, 0xA3DB, 0xFF3C, 0xA3DC, + 0xFF3D, 0xA3DD, 0xFF3E, 0xA3DE, 0xFF3F, 0xA3DF, 0xFF40, 0xA3E0, 0xFF41, 0xA3E1, 0xFF42, 0xA3E2, 0xFF43, 0xA3E3, 0xFF44, 0xA3E4, + 0xFF45, 0xA3E5, 0xFF46, 0xA3E6, 0xFF47, 0xA3E7, 0xFF48, 0xA3E8, 0xFF49, 0xA3E9, 0xFF4A, 0xA3EA, 0xFF4B, 0xA3EB, 0xFF4C, 0xA3EC, + 0xFF4D, 0xA3ED, 0xFF4E, 0xA3EE, 0xFF4F, 0xA3EF, 0xFF50, 0xA3F0, 0xFF51, 0xA3F1, 0xFF52, 0xA3F2, 0xFF53, 0xA3F3, 0xFF54, 0xA3F4, + 0xFF55, 0xA3F5, 0xFF56, 0xA3F6, 0xFF57, 0xA3F7, 0xFF58, 0xA3F8, 0xFF59, 0xA3F9, 0xFF5A, 0xA3FA, 0xFF5B, 0xA3FB, 0xFF5C, 0xA3FC, + 0xFF5D, 0xA3FD, 0xFF5E, 0xA1AB, 0xFFE0, 0xA1E9, 0xFFE1, 0xA1EA, 0xFFE2, 0xA956, 0xFFE3, 0xA3FE, 0xFFE4, 0xA957, 0xFFE5, 0xA3A4, + 0, 0 +}; + +static const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */ + 0x0080, 0x20AC, 0x8140, 0x4E02, 0x8141, 0x4E04, 0x8142, 0x4E05, 0x8143, 0x4E06, 0x8144, 0x4E0F, 0x8145, 0x4E12, 0x8146, 0x4E17, + 0x8147, 0x4E1F, 0x8148, 0x4E20, 0x8149, 0x4E21, 0x814A, 0x4E23, 0x814B, 0x4E26, 0x814C, 0x4E29, 0x814D, 0x4E2E, 0x814E, 0x4E2F, + 0x814F, 0x4E31, 0x8150, 0x4E33, 0x8151, 0x4E35, 0x8152, 0x4E37, 0x8153, 0x4E3C, 0x8154, 0x4E40, 0x8155, 0x4E41, 0x8156, 0x4E42, + 0x8157, 0x4E44, 0x8158, 0x4E46, 0x8159, 0x4E4A, 0x815A, 0x4E51, 0x815B, 0x4E55, 0x815C, 0x4E57, 0x815D, 0x4E5A, 0x815E, 0x4E5B, + 0x815F, 0x4E62, 0x8160, 0x4E63, 0x8161, 0x4E64, 0x8162, 0x4E65, 0x8163, 0x4E67, 0x8164, 0x4E68, 0x8165, 0x4E6A, 0x8166, 0x4E6B, + 0x8167, 0x4E6C, 0x8168, 0x4E6D, 0x8169, 0x4E6E, 0x816A, 0x4E6F, 0x816B, 0x4E72, 0x816C, 0x4E74, 0x816D, 0x4E75, 0x816E, 0x4E76, + 0x816F, 0x4E77, 0x8170, 0x4E78, 0x8171, 0x4E79, 0x8172, 0x4E7A, 0x8173, 0x4E7B, 0x8174, 0x4E7C, 0x8175, 0x4E7D, 0x8176, 0x4E7F, + 0x8177, 0x4E80, 0x8178, 0x4E81, 0x8179, 0x4E82, 0x817A, 0x4E83, 0x817B, 0x4E84, 0x817C, 0x4E85, 0x817D, 0x4E87, 0x817E, 0x4E8A, + 0x8180, 0x4E90, 0x8181, 0x4E96, 0x8182, 0x4E97, 0x8183, 0x4E99, 0x8184, 0x4E9C, 0x8185, 0x4E9D, 0x8186, 0x4E9E, 0x8187, 0x4EA3, + 0x8188, 0x4EAA, 0x8189, 0x4EAF, 0x818A, 0x4EB0, 0x818B, 0x4EB1, 0x818C, 0x4EB4, 0x818D, 0x4EB6, 0x818E, 0x4EB7, 0x818F, 0x4EB8, + 0x8190, 0x4EB9, 0x8191, 0x4EBC, 0x8192, 0x4EBD, 0x8193, 0x4EBE, 0x8194, 0x4EC8, 0x8195, 0x4ECC, 0x8196, 0x4ECF, 0x8197, 0x4ED0, + 0x8198, 0x4ED2, 0x8199, 0x4EDA, 0x819A, 0x4EDB, 0x819B, 0x4EDC, 0x819C, 0x4EE0, 0x819D, 0x4EE2, 0x819E, 0x4EE6, 0x819F, 0x4EE7, + 0x81A0, 0x4EE9, 0x81A1, 0x4EED, 0x81A2, 0x4EEE, 0x81A3, 0x4EEF, 0x81A4, 0x4EF1, 0x81A5, 0x4EF4, 0x81A6, 0x4EF8, 0x81A7, 0x4EF9, + 0x81A8, 0x4EFA, 0x81A9, 0x4EFC, 0x81AA, 0x4EFE, 0x81AB, 0x4F00, 0x81AC, 0x4F02, 0x81AD, 0x4F03, 0x81AE, 0x4F04, 0x81AF, 0x4F05, + 0x81B0, 0x4F06, 0x81B1, 0x4F07, 0x81B2, 0x4F08, 0x81B3, 0x4F0B, 0x81B4, 0x4F0C, 0x81B5, 0x4F12, 0x81B6, 0x4F13, 0x81B7, 0x4F14, + 0x81B8, 0x4F15, 0x81B9, 0x4F16, 0x81BA, 0x4F1C, 0x81BB, 0x4F1D, 0x81BC, 0x4F21, 0x81BD, 0x4F23, 0x81BE, 0x4F28, 0x81BF, 0x4F29, + 0x81C0, 0x4F2C, 0x81C1, 0x4F2D, 0x81C2, 0x4F2E, 0x81C3, 0x4F31, 0x81C4, 0x4F33, 0x81C5, 0x4F35, 0x81C6, 0x4F37, 0x81C7, 0x4F39, + 0x81C8, 0x4F3B, 0x81C9, 0x4F3E, 0x81CA, 0x4F3F, 0x81CB, 0x4F40, 0x81CC, 0x4F41, 0x81CD, 0x4F42, 0x81CE, 0x4F44, 0x81CF, 0x4F45, + 0x81D0, 0x4F47, 0x81D1, 0x4F48, 0x81D2, 0x4F49, 0x81D3, 0x4F4A, 0x81D4, 0x4F4B, 0x81D5, 0x4F4C, 0x81D6, 0x4F52, 0x81D7, 0x4F54, + 0x81D8, 0x4F56, 0x81D9, 0x4F61, 0x81DA, 0x4F62, 0x81DB, 0x4F66, 0x81DC, 0x4F68, 0x81DD, 0x4F6A, 0x81DE, 0x4F6B, 0x81DF, 0x4F6D, + 0x81E0, 0x4F6E, 0x81E1, 0x4F71, 0x81E2, 0x4F72, 0x81E3, 0x4F75, 0x81E4, 0x4F77, 0x81E5, 0x4F78, 0x81E6, 0x4F79, 0x81E7, 0x4F7A, + 0x81E8, 0x4F7D, 0x81E9, 0x4F80, 0x81EA, 0x4F81, 0x81EB, 0x4F82, 0x81EC, 0x4F85, 0x81ED, 0x4F86, 0x81EE, 0x4F87, 0x81EF, 0x4F8A, + 0x81F0, 0x4F8C, 0x81F1, 0x4F8E, 0x81F2, 0x4F90, 0x81F3, 0x4F92, 0x81F4, 0x4F93, 0x81F5, 0x4F95, 0x81F6, 0x4F96, 0x81F7, 0x4F98, + 0x81F8, 0x4F99, 0x81F9, 0x4F9A, 0x81FA, 0x4F9C, 0x81FB, 0x4F9E, 0x81FC, 0x4F9F, 0x81FD, 0x4FA1, 0x81FE, 0x4FA2, 0x8240, 0x4FA4, + 0x8241, 0x4FAB, 0x8242, 0x4FAD, 0x8243, 0x4FB0, 0x8244, 0x4FB1, 0x8245, 0x4FB2, 0x8246, 0x4FB3, 0x8247, 0x4FB4, 0x8248, 0x4FB6, + 0x8249, 0x4FB7, 0x824A, 0x4FB8, 0x824B, 0x4FB9, 0x824C, 0x4FBA, 0x824D, 0x4FBB, 0x824E, 0x4FBC, 0x824F, 0x4FBD, 0x8250, 0x4FBE, + 0x8251, 0x4FC0, 0x8252, 0x4FC1, 0x8253, 0x4FC2, 0x8254, 0x4FC6, 0x8255, 0x4FC7, 0x8256, 0x4FC8, 0x8257, 0x4FC9, 0x8258, 0x4FCB, + 0x8259, 0x4FCC, 0x825A, 0x4FCD, 0x825B, 0x4FD2, 0x825C, 0x4FD3, 0x825D, 0x4FD4, 0x825E, 0x4FD5, 0x825F, 0x4FD6, 0x8260, 0x4FD9, + 0x8261, 0x4FDB, 0x8262, 0x4FE0, 0x8263, 0x4FE2, 0x8264, 0x4FE4, 0x8265, 0x4FE5, 0x8266, 0x4FE7, 0x8267, 0x4FEB, 0x8268, 0x4FEC, + 0x8269, 0x4FF0, 0x826A, 0x4FF2, 0x826B, 0x4FF4, 0x826C, 0x4FF5, 0x826D, 0x4FF6, 0x826E, 0x4FF7, 0x826F, 0x4FF9, 0x8270, 0x4FFB, + 0x8271, 0x4FFC, 0x8272, 0x4FFD, 0x8273, 0x4FFF, 0x8274, 0x5000, 0x8275, 0x5001, 0x8276, 0x5002, 0x8277, 0x5003, 0x8278, 0x5004, + 0x8279, 0x5005, 0x827A, 0x5006, 0x827B, 0x5007, 0x827C, 0x5008, 0x827D, 0x5009, 0x827E, 0x500A, 0x8280, 0x500B, 0x8281, 0x500E, + 0x8282, 0x5010, 0x8283, 0x5011, 0x8284, 0x5013, 0x8285, 0x5015, 0x8286, 0x5016, 0x8287, 0x5017, 0x8288, 0x501B, 0x8289, 0x501D, + 0x828A, 0x501E, 0x828B, 0x5020, 0x828C, 0x5022, 0x828D, 0x5023, 0x828E, 0x5024, 0x828F, 0x5027, 0x8290, 0x502B, 0x8291, 0x502F, + 0x8292, 0x5030, 0x8293, 0x5031, 0x8294, 0x5032, 0x8295, 0x5033, 0x8296, 0x5034, 0x8297, 0x5035, 0x8298, 0x5036, 0x8299, 0x5037, + 0x829A, 0x5038, 0x829B, 0x5039, 0x829C, 0x503B, 0x829D, 0x503D, 0x829E, 0x503F, 0x829F, 0x5040, 0x82A0, 0x5041, 0x82A1, 0x5042, + 0x82A2, 0x5044, 0x82A3, 0x5045, 0x82A4, 0x5046, 0x82A5, 0x5049, 0x82A6, 0x504A, 0x82A7, 0x504B, 0x82A8, 0x504D, 0x82A9, 0x5050, + 0x82AA, 0x5051, 0x82AB, 0x5052, 0x82AC, 0x5053, 0x82AD, 0x5054, 0x82AE, 0x5056, 0x82AF, 0x5057, 0x82B0, 0x5058, 0x82B1, 0x5059, + 0x82B2, 0x505B, 0x82B3, 0x505D, 0x82B4, 0x505E, 0x82B5, 0x505F, 0x82B6, 0x5060, 0x82B7, 0x5061, 0x82B8, 0x5062, 0x82B9, 0x5063, + 0x82BA, 0x5064, 0x82BB, 0x5066, 0x82BC, 0x5067, 0x82BD, 0x5068, 0x82BE, 0x5069, 0x82BF, 0x506A, 0x82C0, 0x506B, 0x82C1, 0x506D, + 0x82C2, 0x506E, 0x82C3, 0x506F, 0x82C4, 0x5070, 0x82C5, 0x5071, 0x82C6, 0x5072, 0x82C7, 0x5073, 0x82C8, 0x5074, 0x82C9, 0x5075, + 0x82CA, 0x5078, 0x82CB, 0x5079, 0x82CC, 0x507A, 0x82CD, 0x507C, 0x82CE, 0x507D, 0x82CF, 0x5081, 0x82D0, 0x5082, 0x82D1, 0x5083, + 0x82D2, 0x5084, 0x82D3, 0x5086, 0x82D4, 0x5087, 0x82D5, 0x5089, 0x82D6, 0x508A, 0x82D7, 0x508B, 0x82D8, 0x508C, 0x82D9, 0x508E, + 0x82DA, 0x508F, 0x82DB, 0x5090, 0x82DC, 0x5091, 0x82DD, 0x5092, 0x82DE, 0x5093, 0x82DF, 0x5094, 0x82E0, 0x5095, 0x82E1, 0x5096, + 0x82E2, 0x5097, 0x82E3, 0x5098, 0x82E4, 0x5099, 0x82E5, 0x509A, 0x82E6, 0x509B, 0x82E7, 0x509C, 0x82E8, 0x509D, 0x82E9, 0x509E, + 0x82EA, 0x509F, 0x82EB, 0x50A0, 0x82EC, 0x50A1, 0x82ED, 0x50A2, 0x82EE, 0x50A4, 0x82EF, 0x50A6, 0x82F0, 0x50AA, 0x82F1, 0x50AB, + 0x82F2, 0x50AD, 0x82F3, 0x50AE, 0x82F4, 0x50AF, 0x82F5, 0x50B0, 0x82F6, 0x50B1, 0x82F7, 0x50B3, 0x82F8, 0x50B4, 0x82F9, 0x50B5, + 0x82FA, 0x50B6, 0x82FB, 0x50B7, 0x82FC, 0x50B8, 0x82FD, 0x50B9, 0x82FE, 0x50BC, 0x8340, 0x50BD, 0x8341, 0x50BE, 0x8342, 0x50BF, + 0x8343, 0x50C0, 0x8344, 0x50C1, 0x8345, 0x50C2, 0x8346, 0x50C3, 0x8347, 0x50C4, 0x8348, 0x50C5, 0x8349, 0x50C6, 0x834A, 0x50C7, + 0x834B, 0x50C8, 0x834C, 0x50C9, 0x834D, 0x50CA, 0x834E, 0x50CB, 0x834F, 0x50CC, 0x8350, 0x50CD, 0x8351, 0x50CE, 0x8352, 0x50D0, + 0x8353, 0x50D1, 0x8354, 0x50D2, 0x8355, 0x50D3, 0x8356, 0x50D4, 0x8357, 0x50D5, 0x8358, 0x50D7, 0x8359, 0x50D8, 0x835A, 0x50D9, + 0x835B, 0x50DB, 0x835C, 0x50DC, 0x835D, 0x50DD, 0x835E, 0x50DE, 0x835F, 0x50DF, 0x8360, 0x50E0, 0x8361, 0x50E1, 0x8362, 0x50E2, + 0x8363, 0x50E3, 0x8364, 0x50E4, 0x8365, 0x50E5, 0x8366, 0x50E8, 0x8367, 0x50E9, 0x8368, 0x50EA, 0x8369, 0x50EB, 0x836A, 0x50EF, + 0x836B, 0x50F0, 0x836C, 0x50F1, 0x836D, 0x50F2, 0x836E, 0x50F4, 0x836F, 0x50F6, 0x8370, 0x50F7, 0x8371, 0x50F8, 0x8372, 0x50F9, + 0x8373, 0x50FA, 0x8374, 0x50FC, 0x8375, 0x50FD, 0x8376, 0x50FE, 0x8377, 0x50FF, 0x8378, 0x5100, 0x8379, 0x5101, 0x837A, 0x5102, + 0x837B, 0x5103, 0x837C, 0x5104, 0x837D, 0x5105, 0x837E, 0x5108, 0x8380, 0x5109, 0x8381, 0x510A, 0x8382, 0x510C, 0x8383, 0x510D, + 0x8384, 0x510E, 0x8385, 0x510F, 0x8386, 0x5110, 0x8387, 0x5111, 0x8388, 0x5113, 0x8389, 0x5114, 0x838A, 0x5115, 0x838B, 0x5116, + 0x838C, 0x5117, 0x838D, 0x5118, 0x838E, 0x5119, 0x838F, 0x511A, 0x8390, 0x511B, 0x8391, 0x511C, 0x8392, 0x511D, 0x8393, 0x511E, + 0x8394, 0x511F, 0x8395, 0x5120, 0x8396, 0x5122, 0x8397, 0x5123, 0x8398, 0x5124, 0x8399, 0x5125, 0x839A, 0x5126, 0x839B, 0x5127, + 0x839C, 0x5128, 0x839D, 0x5129, 0x839E, 0x512A, 0x839F, 0x512B, 0x83A0, 0x512C, 0x83A1, 0x512D, 0x83A2, 0x512E, 0x83A3, 0x512F, + 0x83A4, 0x5130, 0x83A5, 0x5131, 0x83A6, 0x5132, 0x83A7, 0x5133, 0x83A8, 0x5134, 0x83A9, 0x5135, 0x83AA, 0x5136, 0x83AB, 0x5137, + 0x83AC, 0x5138, 0x83AD, 0x5139, 0x83AE, 0x513A, 0x83AF, 0x513B, 0x83B0, 0x513C, 0x83B1, 0x513D, 0x83B2, 0x513E, 0x83B3, 0x5142, + 0x83B4, 0x5147, 0x83B5, 0x514A, 0x83B6, 0x514C, 0x83B7, 0x514E, 0x83B8, 0x514F, 0x83B9, 0x5150, 0x83BA, 0x5152, 0x83BB, 0x5153, + 0x83BC, 0x5157, 0x83BD, 0x5158, 0x83BE, 0x5159, 0x83BF, 0x515B, 0x83C0, 0x515D, 0x83C1, 0x515E, 0x83C2, 0x515F, 0x83C3, 0x5160, + 0x83C4, 0x5161, 0x83C5, 0x5163, 0x83C6, 0x5164, 0x83C7, 0x5166, 0x83C8, 0x5167, 0x83C9, 0x5169, 0x83CA, 0x516A, 0x83CB, 0x516F, + 0x83CC, 0x5172, 0x83CD, 0x517A, 0x83CE, 0x517E, 0x83CF, 0x517F, 0x83D0, 0x5183, 0x83D1, 0x5184, 0x83D2, 0x5186, 0x83D3, 0x5187, + 0x83D4, 0x518A, 0x83D5, 0x518B, 0x83D6, 0x518E, 0x83D7, 0x518F, 0x83D8, 0x5190, 0x83D9, 0x5191, 0x83DA, 0x5193, 0x83DB, 0x5194, + 0x83DC, 0x5198, 0x83DD, 0x519A, 0x83DE, 0x519D, 0x83DF, 0x519E, 0x83E0, 0x519F, 0x83E1, 0x51A1, 0x83E2, 0x51A3, 0x83E3, 0x51A6, + 0x83E4, 0x51A7, 0x83E5, 0x51A8, 0x83E6, 0x51A9, 0x83E7, 0x51AA, 0x83E8, 0x51AD, 0x83E9, 0x51AE, 0x83EA, 0x51B4, 0x83EB, 0x51B8, + 0x83EC, 0x51B9, 0x83ED, 0x51BA, 0x83EE, 0x51BE, 0x83EF, 0x51BF, 0x83F0, 0x51C1, 0x83F1, 0x51C2, 0x83F2, 0x51C3, 0x83F3, 0x51C5, + 0x83F4, 0x51C8, 0x83F5, 0x51CA, 0x83F6, 0x51CD, 0x83F7, 0x51CE, 0x83F8, 0x51D0, 0x83F9, 0x51D2, 0x83FA, 0x51D3, 0x83FB, 0x51D4, + 0x83FC, 0x51D5, 0x83FD, 0x51D6, 0x83FE, 0x51D7, 0x8440, 0x51D8, 0x8441, 0x51D9, 0x8442, 0x51DA, 0x8443, 0x51DC, 0x8444, 0x51DE, + 0x8445, 0x51DF, 0x8446, 0x51E2, 0x8447, 0x51E3, 0x8448, 0x51E5, 0x8449, 0x51E6, 0x844A, 0x51E7, 0x844B, 0x51E8, 0x844C, 0x51E9, + 0x844D, 0x51EA, 0x844E, 0x51EC, 0x844F, 0x51EE, 0x8450, 0x51F1, 0x8451, 0x51F2, 0x8452, 0x51F4, 0x8453, 0x51F7, 0x8454, 0x51FE, + 0x8455, 0x5204, 0x8456, 0x5205, 0x8457, 0x5209, 0x8458, 0x520B, 0x8459, 0x520C, 0x845A, 0x520F, 0x845B, 0x5210, 0x845C, 0x5213, + 0x845D, 0x5214, 0x845E, 0x5215, 0x845F, 0x521C, 0x8460, 0x521E, 0x8461, 0x521F, 0x8462, 0x5221, 0x8463, 0x5222, 0x8464, 0x5223, + 0x8465, 0x5225, 0x8466, 0x5226, 0x8467, 0x5227, 0x8468, 0x522A, 0x8469, 0x522C, 0x846A, 0x522F, 0x846B, 0x5231, 0x846C, 0x5232, + 0x846D, 0x5234, 0x846E, 0x5235, 0x846F, 0x523C, 0x8470, 0x523E, 0x8471, 0x5244, 0x8472, 0x5245, 0x8473, 0x5246, 0x8474, 0x5247, + 0x8475, 0x5248, 0x8476, 0x5249, 0x8477, 0x524B, 0x8478, 0x524E, 0x8479, 0x524F, 0x847A, 0x5252, 0x847B, 0x5253, 0x847C, 0x5255, + 0x847D, 0x5257, 0x847E, 0x5258, 0x8480, 0x5259, 0x8481, 0x525A, 0x8482, 0x525B, 0x8483, 0x525D, 0x8484, 0x525F, 0x8485, 0x5260, + 0x8486, 0x5262, 0x8487, 0x5263, 0x8488, 0x5264, 0x8489, 0x5266, 0x848A, 0x5268, 0x848B, 0x526B, 0x848C, 0x526C, 0x848D, 0x526D, + 0x848E, 0x526E, 0x848F, 0x5270, 0x8490, 0x5271, 0x8491, 0x5273, 0x8492, 0x5274, 0x8493, 0x5275, 0x8494, 0x5276, 0x8495, 0x5277, + 0x8496, 0x5278, 0x8497, 0x5279, 0x8498, 0x527A, 0x8499, 0x527B, 0x849A, 0x527C, 0x849B, 0x527E, 0x849C, 0x5280, 0x849D, 0x5283, + 0x849E, 0x5284, 0x849F, 0x5285, 0x84A0, 0x5286, 0x84A1, 0x5287, 0x84A2, 0x5289, 0x84A3, 0x528A, 0x84A4, 0x528B, 0x84A5, 0x528C, + 0x84A6, 0x528D, 0x84A7, 0x528E, 0x84A8, 0x528F, 0x84A9, 0x5291, 0x84AA, 0x5292, 0x84AB, 0x5294, 0x84AC, 0x5295, 0x84AD, 0x5296, + 0x84AE, 0x5297, 0x84AF, 0x5298, 0x84B0, 0x5299, 0x84B1, 0x529A, 0x84B2, 0x529C, 0x84B3, 0x52A4, 0x84B4, 0x52A5, 0x84B5, 0x52A6, + 0x84B6, 0x52A7, 0x84B7, 0x52AE, 0x84B8, 0x52AF, 0x84B9, 0x52B0, 0x84BA, 0x52B4, 0x84BB, 0x52B5, 0x84BC, 0x52B6, 0x84BD, 0x52B7, + 0x84BE, 0x52B8, 0x84BF, 0x52B9, 0x84C0, 0x52BA, 0x84C1, 0x52BB, 0x84C2, 0x52BC, 0x84C3, 0x52BD, 0x84C4, 0x52C0, 0x84C5, 0x52C1, + 0x84C6, 0x52C2, 0x84C7, 0x52C4, 0x84C8, 0x52C5, 0x84C9, 0x52C6, 0x84CA, 0x52C8, 0x84CB, 0x52CA, 0x84CC, 0x52CC, 0x84CD, 0x52CD, + 0x84CE, 0x52CE, 0x84CF, 0x52CF, 0x84D0, 0x52D1, 0x84D1, 0x52D3, 0x84D2, 0x52D4, 0x84D3, 0x52D5, 0x84D4, 0x52D7, 0x84D5, 0x52D9, + 0x84D6, 0x52DA, 0x84D7, 0x52DB, 0x84D8, 0x52DC, 0x84D9, 0x52DD, 0x84DA, 0x52DE, 0x84DB, 0x52E0, 0x84DC, 0x52E1, 0x84DD, 0x52E2, + 0x84DE, 0x52E3, 0x84DF, 0x52E5, 0x84E0, 0x52E6, 0x84E1, 0x52E7, 0x84E2, 0x52E8, 0x84E3, 0x52E9, 0x84E4, 0x52EA, 0x84E5, 0x52EB, + 0x84E6, 0x52EC, 0x84E7, 0x52ED, 0x84E8, 0x52EE, 0x84E9, 0x52EF, 0x84EA, 0x52F1, 0x84EB, 0x52F2, 0x84EC, 0x52F3, 0x84ED, 0x52F4, + 0x84EE, 0x52F5, 0x84EF, 0x52F6, 0x84F0, 0x52F7, 0x84F1, 0x52F8, 0x84F2, 0x52FB, 0x84F3, 0x52FC, 0x84F4, 0x52FD, 0x84F5, 0x5301, + 0x84F6, 0x5302, 0x84F7, 0x5303, 0x84F8, 0x5304, 0x84F9, 0x5307, 0x84FA, 0x5309, 0x84FB, 0x530A, 0x84FC, 0x530B, 0x84FD, 0x530C, + 0x84FE, 0x530E, 0x8540, 0x5311, 0x8541, 0x5312, 0x8542, 0x5313, 0x8543, 0x5314, 0x8544, 0x5318, 0x8545, 0x531B, 0x8546, 0x531C, + 0x8547, 0x531E, 0x8548, 0x531F, 0x8549, 0x5322, 0x854A, 0x5324, 0x854B, 0x5325, 0x854C, 0x5327, 0x854D, 0x5328, 0x854E, 0x5329, + 0x854F, 0x532B, 0x8550, 0x532C, 0x8551, 0x532D, 0x8552, 0x532F, 0x8553, 0x5330, 0x8554, 0x5331, 0x8555, 0x5332, 0x8556, 0x5333, + 0x8557, 0x5334, 0x8558, 0x5335, 0x8559, 0x5336, 0x855A, 0x5337, 0x855B, 0x5338, 0x855C, 0x533C, 0x855D, 0x533D, 0x855E, 0x5340, + 0x855F, 0x5342, 0x8560, 0x5344, 0x8561, 0x5346, 0x8562, 0x534B, 0x8563, 0x534C, 0x8564, 0x534D, 0x8565, 0x5350, 0x8566, 0x5354, + 0x8567, 0x5358, 0x8568, 0x5359, 0x8569, 0x535B, 0x856A, 0x535D, 0x856B, 0x5365, 0x856C, 0x5368, 0x856D, 0x536A, 0x856E, 0x536C, + 0x856F, 0x536D, 0x8570, 0x5372, 0x8571, 0x5376, 0x8572, 0x5379, 0x8573, 0x537B, 0x8574, 0x537C, 0x8575, 0x537D, 0x8576, 0x537E, + 0x8577, 0x5380, 0x8578, 0x5381, 0x8579, 0x5383, 0x857A, 0x5387, 0x857B, 0x5388, 0x857C, 0x538A, 0x857D, 0x538E, 0x857E, 0x538F, + 0x8580, 0x5390, 0x8581, 0x5391, 0x8582, 0x5392, 0x8583, 0x5393, 0x8584, 0x5394, 0x8585, 0x5396, 0x8586, 0x5397, 0x8587, 0x5399, + 0x8588, 0x539B, 0x8589, 0x539C, 0x858A, 0x539E, 0x858B, 0x53A0, 0x858C, 0x53A1, 0x858D, 0x53A4, 0x858E, 0x53A7, 0x858F, 0x53AA, + 0x8590, 0x53AB, 0x8591, 0x53AC, 0x8592, 0x53AD, 0x8593, 0x53AF, 0x8594, 0x53B0, 0x8595, 0x53B1, 0x8596, 0x53B2, 0x8597, 0x53B3, + 0x8598, 0x53B4, 0x8599, 0x53B5, 0x859A, 0x53B7, 0x859B, 0x53B8, 0x859C, 0x53B9, 0x859D, 0x53BA, 0x859E, 0x53BC, 0x859F, 0x53BD, + 0x85A0, 0x53BE, 0x85A1, 0x53C0, 0x85A2, 0x53C3, 0x85A3, 0x53C4, 0x85A4, 0x53C5, 0x85A5, 0x53C6, 0x85A6, 0x53C7, 0x85A7, 0x53CE, + 0x85A8, 0x53CF, 0x85A9, 0x53D0, 0x85AA, 0x53D2, 0x85AB, 0x53D3, 0x85AC, 0x53D5, 0x85AD, 0x53DA, 0x85AE, 0x53DC, 0x85AF, 0x53DD, + 0x85B0, 0x53DE, 0x85B1, 0x53E1, 0x85B2, 0x53E2, 0x85B3, 0x53E7, 0x85B4, 0x53F4, 0x85B5, 0x53FA, 0x85B6, 0x53FE, 0x85B7, 0x53FF, + 0x85B8, 0x5400, 0x85B9, 0x5402, 0x85BA, 0x5405, 0x85BB, 0x5407, 0x85BC, 0x540B, 0x85BD, 0x5414, 0x85BE, 0x5418, 0x85BF, 0x5419, + 0x85C0, 0x541A, 0x85C1, 0x541C, 0x85C2, 0x5422, 0x85C3, 0x5424, 0x85C4, 0x5425, 0x85C5, 0x542A, 0x85C6, 0x5430, 0x85C7, 0x5433, + 0x85C8, 0x5436, 0x85C9, 0x5437, 0x85CA, 0x543A, 0x85CB, 0x543D, 0x85CC, 0x543F, 0x85CD, 0x5441, 0x85CE, 0x5442, 0x85CF, 0x5444, + 0x85D0, 0x5445, 0x85D1, 0x5447, 0x85D2, 0x5449, 0x85D3, 0x544C, 0x85D4, 0x544D, 0x85D5, 0x544E, 0x85D6, 0x544F, 0x85D7, 0x5451, + 0x85D8, 0x545A, 0x85D9, 0x545D, 0x85DA, 0x545E, 0x85DB, 0x545F, 0x85DC, 0x5460, 0x85DD, 0x5461, 0x85DE, 0x5463, 0x85DF, 0x5465, + 0x85E0, 0x5467, 0x85E1, 0x5469, 0x85E2, 0x546A, 0x85E3, 0x546B, 0x85E4, 0x546C, 0x85E5, 0x546D, 0x85E6, 0x546E, 0x85E7, 0x546F, + 0x85E8, 0x5470, 0x85E9, 0x5474, 0x85EA, 0x5479, 0x85EB, 0x547A, 0x85EC, 0x547E, 0x85ED, 0x547F, 0x85EE, 0x5481, 0x85EF, 0x5483, + 0x85F0, 0x5485, 0x85F1, 0x5487, 0x85F2, 0x5488, 0x85F3, 0x5489, 0x85F4, 0x548A, 0x85F5, 0x548D, 0x85F6, 0x5491, 0x85F7, 0x5493, + 0x85F8, 0x5497, 0x85F9, 0x5498, 0x85FA, 0x549C, 0x85FB, 0x549E, 0x85FC, 0x549F, 0x85FD, 0x54A0, 0x85FE, 0x54A1, 0x8640, 0x54A2, + 0x8641, 0x54A5, 0x8642, 0x54AE, 0x8643, 0x54B0, 0x8644, 0x54B2, 0x8645, 0x54B5, 0x8646, 0x54B6, 0x8647, 0x54B7, 0x8648, 0x54B9, + 0x8649, 0x54BA, 0x864A, 0x54BC, 0x864B, 0x54BE, 0x864C, 0x54C3, 0x864D, 0x54C5, 0x864E, 0x54CA, 0x864F, 0x54CB, 0x8650, 0x54D6, + 0x8651, 0x54D8, 0x8652, 0x54DB, 0x8653, 0x54E0, 0x8654, 0x54E1, 0x8655, 0x54E2, 0x8656, 0x54E3, 0x8657, 0x54E4, 0x8658, 0x54EB, + 0x8659, 0x54EC, 0x865A, 0x54EF, 0x865B, 0x54F0, 0x865C, 0x54F1, 0x865D, 0x54F4, 0x865E, 0x54F5, 0x865F, 0x54F6, 0x8660, 0x54F7, + 0x8661, 0x54F8, 0x8662, 0x54F9, 0x8663, 0x54FB, 0x8664, 0x54FE, 0x8665, 0x5500, 0x8666, 0x5502, 0x8667, 0x5503, 0x8668, 0x5504, + 0x8669, 0x5505, 0x866A, 0x5508, 0x866B, 0x550A, 0x866C, 0x550B, 0x866D, 0x550C, 0x866E, 0x550D, 0x866F, 0x550E, 0x8670, 0x5512, + 0x8671, 0x5513, 0x8672, 0x5515, 0x8673, 0x5516, 0x8674, 0x5517, 0x8675, 0x5518, 0x8676, 0x5519, 0x8677, 0x551A, 0x8678, 0x551C, + 0x8679, 0x551D, 0x867A, 0x551E, 0x867B, 0x551F, 0x867C, 0x5521, 0x867D, 0x5525, 0x867E, 0x5526, 0x8680, 0x5528, 0x8681, 0x5529, + 0x8682, 0x552B, 0x8683, 0x552D, 0x8684, 0x5532, 0x8685, 0x5534, 0x8686, 0x5535, 0x8687, 0x5536, 0x8688, 0x5538, 0x8689, 0x5539, + 0x868A, 0x553A, 0x868B, 0x553B, 0x868C, 0x553D, 0x868D, 0x5540, 0x868E, 0x5542, 0x868F, 0x5545, 0x8690, 0x5547, 0x8691, 0x5548, + 0x8692, 0x554B, 0x8693, 0x554C, 0x8694, 0x554D, 0x8695, 0x554E, 0x8696, 0x554F, 0x8697, 0x5551, 0x8698, 0x5552, 0x8699, 0x5553, + 0x869A, 0x5554, 0x869B, 0x5557, 0x869C, 0x5558, 0x869D, 0x5559, 0x869E, 0x555A, 0x869F, 0x555B, 0x86A0, 0x555D, 0x86A1, 0x555E, + 0x86A2, 0x555F, 0x86A3, 0x5560, 0x86A4, 0x5562, 0x86A5, 0x5563, 0x86A6, 0x5568, 0x86A7, 0x5569, 0x86A8, 0x556B, 0x86A9, 0x556F, + 0x86AA, 0x5570, 0x86AB, 0x5571, 0x86AC, 0x5572, 0x86AD, 0x5573, 0x86AE, 0x5574, 0x86AF, 0x5579, 0x86B0, 0x557A, 0x86B1, 0x557D, + 0x86B2, 0x557F, 0x86B3, 0x5585, 0x86B4, 0x5586, 0x86B5, 0x558C, 0x86B6, 0x558D, 0x86B7, 0x558E, 0x86B8, 0x5590, 0x86B9, 0x5592, + 0x86BA, 0x5593, 0x86BB, 0x5595, 0x86BC, 0x5596, 0x86BD, 0x5597, 0x86BE, 0x559A, 0x86BF, 0x559B, 0x86C0, 0x559E, 0x86C1, 0x55A0, + 0x86C2, 0x55A1, 0x86C3, 0x55A2, 0x86C4, 0x55A3, 0x86C5, 0x55A4, 0x86C6, 0x55A5, 0x86C7, 0x55A6, 0x86C8, 0x55A8, 0x86C9, 0x55A9, + 0x86CA, 0x55AA, 0x86CB, 0x55AB, 0x86CC, 0x55AC, 0x86CD, 0x55AD, 0x86CE, 0x55AE, 0x86CF, 0x55AF, 0x86D0, 0x55B0, 0x86D1, 0x55B2, + 0x86D2, 0x55B4, 0x86D3, 0x55B6, 0x86D4, 0x55B8, 0x86D5, 0x55BA, 0x86D6, 0x55BC, 0x86D7, 0x55BF, 0x86D8, 0x55C0, 0x86D9, 0x55C1, + 0x86DA, 0x55C2, 0x86DB, 0x55C3, 0x86DC, 0x55C6, 0x86DD, 0x55C7, 0x86DE, 0x55C8, 0x86DF, 0x55CA, 0x86E0, 0x55CB, 0x86E1, 0x55CE, + 0x86E2, 0x55CF, 0x86E3, 0x55D0, 0x86E4, 0x55D5, 0x86E5, 0x55D7, 0x86E6, 0x55D8, 0x86E7, 0x55D9, 0x86E8, 0x55DA, 0x86E9, 0x55DB, + 0x86EA, 0x55DE, 0x86EB, 0x55E0, 0x86EC, 0x55E2, 0x86ED, 0x55E7, 0x86EE, 0x55E9, 0x86EF, 0x55ED, 0x86F0, 0x55EE, 0x86F1, 0x55F0, + 0x86F2, 0x55F1, 0x86F3, 0x55F4, 0x86F4, 0x55F6, 0x86F5, 0x55F8, 0x86F6, 0x55F9, 0x86F7, 0x55FA, 0x86F8, 0x55FB, 0x86F9, 0x55FC, + 0x86FA, 0x55FF, 0x86FB, 0x5602, 0x86FC, 0x5603, 0x86FD, 0x5604, 0x86FE, 0x5605, 0x8740, 0x5606, 0x8741, 0x5607, 0x8742, 0x560A, + 0x8743, 0x560B, 0x8744, 0x560D, 0x8745, 0x5610, 0x8746, 0x5611, 0x8747, 0x5612, 0x8748, 0x5613, 0x8749, 0x5614, 0x874A, 0x5615, + 0x874B, 0x5616, 0x874C, 0x5617, 0x874D, 0x5619, 0x874E, 0x561A, 0x874F, 0x561C, 0x8750, 0x561D, 0x8751, 0x5620, 0x8752, 0x5621, + 0x8753, 0x5622, 0x8754, 0x5625, 0x8755, 0x5626, 0x8756, 0x5628, 0x8757, 0x5629, 0x8758, 0x562A, 0x8759, 0x562B, 0x875A, 0x562E, + 0x875B, 0x562F, 0x875C, 0x5630, 0x875D, 0x5633, 0x875E, 0x5635, 0x875F, 0x5637, 0x8760, 0x5638, 0x8761, 0x563A, 0x8762, 0x563C, + 0x8763, 0x563D, 0x8764, 0x563E, 0x8765, 0x5640, 0x8766, 0x5641, 0x8767, 0x5642, 0x8768, 0x5643, 0x8769, 0x5644, 0x876A, 0x5645, + 0x876B, 0x5646, 0x876C, 0x5647, 0x876D, 0x5648, 0x876E, 0x5649, 0x876F, 0x564A, 0x8770, 0x564B, 0x8771, 0x564F, 0x8772, 0x5650, + 0x8773, 0x5651, 0x8774, 0x5652, 0x8775, 0x5653, 0x8776, 0x5655, 0x8777, 0x5656, 0x8778, 0x565A, 0x8779, 0x565B, 0x877A, 0x565D, + 0x877B, 0x565E, 0x877C, 0x565F, 0x877D, 0x5660, 0x877E, 0x5661, 0x8780, 0x5663, 0x8781, 0x5665, 0x8782, 0x5666, 0x8783, 0x5667, + 0x8784, 0x566D, 0x8785, 0x566E, 0x8786, 0x566F, 0x8787, 0x5670, 0x8788, 0x5672, 0x8789, 0x5673, 0x878A, 0x5674, 0x878B, 0x5675, + 0x878C, 0x5677, 0x878D, 0x5678, 0x878E, 0x5679, 0x878F, 0x567A, 0x8790, 0x567D, 0x8791, 0x567E, 0x8792, 0x567F, 0x8793, 0x5680, + 0x8794, 0x5681, 0x8795, 0x5682, 0x8796, 0x5683, 0x8797, 0x5684, 0x8798, 0x5687, 0x8799, 0x5688, 0x879A, 0x5689, 0x879B, 0x568A, + 0x879C, 0x568B, 0x879D, 0x568C, 0x879E, 0x568D, 0x879F, 0x5690, 0x87A0, 0x5691, 0x87A1, 0x5692, 0x87A2, 0x5694, 0x87A3, 0x5695, + 0x87A4, 0x5696, 0x87A5, 0x5697, 0x87A6, 0x5698, 0x87A7, 0x5699, 0x87A8, 0x569A, 0x87A9, 0x569B, 0x87AA, 0x569C, 0x87AB, 0x569D, + 0x87AC, 0x569E, 0x87AD, 0x569F, 0x87AE, 0x56A0, 0x87AF, 0x56A1, 0x87B0, 0x56A2, 0x87B1, 0x56A4, 0x87B2, 0x56A5, 0x87B3, 0x56A6, + 0x87B4, 0x56A7, 0x87B5, 0x56A8, 0x87B6, 0x56A9, 0x87B7, 0x56AA, 0x87B8, 0x56AB, 0x87B9, 0x56AC, 0x87BA, 0x56AD, 0x87BB, 0x56AE, + 0x87BC, 0x56B0, 0x87BD, 0x56B1, 0x87BE, 0x56B2, 0x87BF, 0x56B3, 0x87C0, 0x56B4, 0x87C1, 0x56B5, 0x87C2, 0x56B6, 0x87C3, 0x56B8, + 0x87C4, 0x56B9, 0x87C5, 0x56BA, 0x87C6, 0x56BB, 0x87C7, 0x56BD, 0x87C8, 0x56BE, 0x87C9, 0x56BF, 0x87CA, 0x56C0, 0x87CB, 0x56C1, + 0x87CC, 0x56C2, 0x87CD, 0x56C3, 0x87CE, 0x56C4, 0x87CF, 0x56C5, 0x87D0, 0x56C6, 0x87D1, 0x56C7, 0x87D2, 0x56C8, 0x87D3, 0x56C9, + 0x87D4, 0x56CB, 0x87D5, 0x56CC, 0x87D6, 0x56CD, 0x87D7, 0x56CE, 0x87D8, 0x56CF, 0x87D9, 0x56D0, 0x87DA, 0x56D1, 0x87DB, 0x56D2, + 0x87DC, 0x56D3, 0x87DD, 0x56D5, 0x87DE, 0x56D6, 0x87DF, 0x56D8, 0x87E0, 0x56D9, 0x87E1, 0x56DC, 0x87E2, 0x56E3, 0x87E3, 0x56E5, + 0x87E4, 0x56E6, 0x87E5, 0x56E7, 0x87E6, 0x56E8, 0x87E7, 0x56E9, 0x87E8, 0x56EA, 0x87E9, 0x56EC, 0x87EA, 0x56EE, 0x87EB, 0x56EF, + 0x87EC, 0x56F2, 0x87ED, 0x56F3, 0x87EE, 0x56F6, 0x87EF, 0x56F7, 0x87F0, 0x56F8, 0x87F1, 0x56FB, 0x87F2, 0x56FC, 0x87F3, 0x5700, + 0x87F4, 0x5701, 0x87F5, 0x5702, 0x87F6, 0x5705, 0x87F7, 0x5707, 0x87F8, 0x570B, 0x87F9, 0x570C, 0x87FA, 0x570D, 0x87FB, 0x570E, + 0x87FC, 0x570F, 0x87FD, 0x5710, 0x87FE, 0x5711, 0x8840, 0x5712, 0x8841, 0x5713, 0x8842, 0x5714, 0x8843, 0x5715, 0x8844, 0x5716, + 0x8845, 0x5717, 0x8846, 0x5718, 0x8847, 0x5719, 0x8848, 0x571A, 0x8849, 0x571B, 0x884A, 0x571D, 0x884B, 0x571E, 0x884C, 0x5720, + 0x884D, 0x5721, 0x884E, 0x5722, 0x884F, 0x5724, 0x8850, 0x5725, 0x8851, 0x5726, 0x8852, 0x5727, 0x8853, 0x572B, 0x8854, 0x5731, + 0x8855, 0x5732, 0x8856, 0x5734, 0x8857, 0x5735, 0x8858, 0x5736, 0x8859, 0x5737, 0x885A, 0x5738, 0x885B, 0x573C, 0x885C, 0x573D, + 0x885D, 0x573F, 0x885E, 0x5741, 0x885F, 0x5743, 0x8860, 0x5744, 0x8861, 0x5745, 0x8862, 0x5746, 0x8863, 0x5748, 0x8864, 0x5749, + 0x8865, 0x574B, 0x8866, 0x5752, 0x8867, 0x5753, 0x8868, 0x5754, 0x8869, 0x5755, 0x886A, 0x5756, 0x886B, 0x5758, 0x886C, 0x5759, + 0x886D, 0x5762, 0x886E, 0x5763, 0x886F, 0x5765, 0x8870, 0x5767, 0x8871, 0x576C, 0x8872, 0x576E, 0x8873, 0x5770, 0x8874, 0x5771, + 0x8875, 0x5772, 0x8876, 0x5774, 0x8877, 0x5775, 0x8878, 0x5778, 0x8879, 0x5779, 0x887A, 0x577A, 0x887B, 0x577D, 0x887C, 0x577E, + 0x887D, 0x577F, 0x887E, 0x5780, 0x8880, 0x5781, 0x8881, 0x5787, 0x8882, 0x5788, 0x8883, 0x5789, 0x8884, 0x578A, 0x8885, 0x578D, + 0x8886, 0x578E, 0x8887, 0x578F, 0x8888, 0x5790, 0x8889, 0x5791, 0x888A, 0x5794, 0x888B, 0x5795, 0x888C, 0x5796, 0x888D, 0x5797, + 0x888E, 0x5798, 0x888F, 0x5799, 0x8890, 0x579A, 0x8891, 0x579C, 0x8892, 0x579D, 0x8893, 0x579E, 0x8894, 0x579F, 0x8895, 0x57A5, + 0x8896, 0x57A8, 0x8897, 0x57AA, 0x8898, 0x57AC, 0x8899, 0x57AF, 0x889A, 0x57B0, 0x889B, 0x57B1, 0x889C, 0x57B3, 0x889D, 0x57B5, + 0x889E, 0x57B6, 0x889F, 0x57B7, 0x88A0, 0x57B9, 0x88A1, 0x57BA, 0x88A2, 0x57BB, 0x88A3, 0x57BC, 0x88A4, 0x57BD, 0x88A5, 0x57BE, + 0x88A6, 0x57BF, 0x88A7, 0x57C0, 0x88A8, 0x57C1, 0x88A9, 0x57C4, 0x88AA, 0x57C5, 0x88AB, 0x57C6, 0x88AC, 0x57C7, 0x88AD, 0x57C8, + 0x88AE, 0x57C9, 0x88AF, 0x57CA, 0x88B0, 0x57CC, 0x88B1, 0x57CD, 0x88B2, 0x57D0, 0x88B3, 0x57D1, 0x88B4, 0x57D3, 0x88B5, 0x57D6, + 0x88B6, 0x57D7, 0x88B7, 0x57DB, 0x88B8, 0x57DC, 0x88B9, 0x57DE, 0x88BA, 0x57E1, 0x88BB, 0x57E2, 0x88BC, 0x57E3, 0x88BD, 0x57E5, + 0x88BE, 0x57E6, 0x88BF, 0x57E7, 0x88C0, 0x57E8, 0x88C1, 0x57E9, 0x88C2, 0x57EA, 0x88C3, 0x57EB, 0x88C4, 0x57EC, 0x88C5, 0x57EE, + 0x88C6, 0x57F0, 0x88C7, 0x57F1, 0x88C8, 0x57F2, 0x88C9, 0x57F3, 0x88CA, 0x57F5, 0x88CB, 0x57F6, 0x88CC, 0x57F7, 0x88CD, 0x57FB, + 0x88CE, 0x57FC, 0x88CF, 0x57FE, 0x88D0, 0x57FF, 0x88D1, 0x5801, 0x88D2, 0x5803, 0x88D3, 0x5804, 0x88D4, 0x5805, 0x88D5, 0x5808, + 0x88D6, 0x5809, 0x88D7, 0x580A, 0x88D8, 0x580C, 0x88D9, 0x580E, 0x88DA, 0x580F, 0x88DB, 0x5810, 0x88DC, 0x5812, 0x88DD, 0x5813, + 0x88DE, 0x5814, 0x88DF, 0x5816, 0x88E0, 0x5817, 0x88E1, 0x5818, 0x88E2, 0x581A, 0x88E3, 0x581B, 0x88E4, 0x581C, 0x88E5, 0x581D, + 0x88E6, 0x581F, 0x88E7, 0x5822, 0x88E8, 0x5823, 0x88E9, 0x5825, 0x88EA, 0x5826, 0x88EB, 0x5827, 0x88EC, 0x5828, 0x88ED, 0x5829, + 0x88EE, 0x582B, 0x88EF, 0x582C, 0x88F0, 0x582D, 0x88F1, 0x582E, 0x88F2, 0x582F, 0x88F3, 0x5831, 0x88F4, 0x5832, 0x88F5, 0x5833, + 0x88F6, 0x5834, 0x88F7, 0x5836, 0x88F8, 0x5837, 0x88F9, 0x5838, 0x88FA, 0x5839, 0x88FB, 0x583A, 0x88FC, 0x583B, 0x88FD, 0x583C, + 0x88FE, 0x583D, 0x8940, 0x583E, 0x8941, 0x583F, 0x8942, 0x5840, 0x8943, 0x5841, 0x8944, 0x5842, 0x8945, 0x5843, 0x8946, 0x5845, + 0x8947, 0x5846, 0x8948, 0x5847, 0x8949, 0x5848, 0x894A, 0x5849, 0x894B, 0x584A, 0x894C, 0x584B, 0x894D, 0x584E, 0x894E, 0x584F, + 0x894F, 0x5850, 0x8950, 0x5852, 0x8951, 0x5853, 0x8952, 0x5855, 0x8953, 0x5856, 0x8954, 0x5857, 0x8955, 0x5859, 0x8956, 0x585A, + 0x8957, 0x585B, 0x8958, 0x585C, 0x8959, 0x585D, 0x895A, 0x585F, 0x895B, 0x5860, 0x895C, 0x5861, 0x895D, 0x5862, 0x895E, 0x5863, + 0x895F, 0x5864, 0x8960, 0x5866, 0x8961, 0x5867, 0x8962, 0x5868, 0x8963, 0x5869, 0x8964, 0x586A, 0x8965, 0x586D, 0x8966, 0x586E, + 0x8967, 0x586F, 0x8968, 0x5870, 0x8969, 0x5871, 0x896A, 0x5872, 0x896B, 0x5873, 0x896C, 0x5874, 0x896D, 0x5875, 0x896E, 0x5876, + 0x896F, 0x5877, 0x8970, 0x5878, 0x8971, 0x5879, 0x8972, 0x587A, 0x8973, 0x587B, 0x8974, 0x587C, 0x8975, 0x587D, 0x8976, 0x587F, + 0x8977, 0x5882, 0x8978, 0x5884, 0x8979, 0x5886, 0x897A, 0x5887, 0x897B, 0x5888, 0x897C, 0x588A, 0x897D, 0x588B, 0x897E, 0x588C, + 0x8980, 0x588D, 0x8981, 0x588E, 0x8982, 0x588F, 0x8983, 0x5890, 0x8984, 0x5891, 0x8985, 0x5894, 0x8986, 0x5895, 0x8987, 0x5896, + 0x8988, 0x5897, 0x8989, 0x5898, 0x898A, 0x589B, 0x898B, 0x589C, 0x898C, 0x589D, 0x898D, 0x58A0, 0x898E, 0x58A1, 0x898F, 0x58A2, + 0x8990, 0x58A3, 0x8991, 0x58A4, 0x8992, 0x58A5, 0x8993, 0x58A6, 0x8994, 0x58A7, 0x8995, 0x58AA, 0x8996, 0x58AB, 0x8997, 0x58AC, + 0x8998, 0x58AD, 0x8999, 0x58AE, 0x899A, 0x58AF, 0x899B, 0x58B0, 0x899C, 0x58B1, 0x899D, 0x58B2, 0x899E, 0x58B3, 0x899F, 0x58B4, + 0x89A0, 0x58B5, 0x89A1, 0x58B6, 0x89A2, 0x58B7, 0x89A3, 0x58B8, 0x89A4, 0x58B9, 0x89A5, 0x58BA, 0x89A6, 0x58BB, 0x89A7, 0x58BD, + 0x89A8, 0x58BE, 0x89A9, 0x58BF, 0x89AA, 0x58C0, 0x89AB, 0x58C2, 0x89AC, 0x58C3, 0x89AD, 0x58C4, 0x89AE, 0x58C6, 0x89AF, 0x58C7, + 0x89B0, 0x58C8, 0x89B1, 0x58C9, 0x89B2, 0x58CA, 0x89B3, 0x58CB, 0x89B4, 0x58CC, 0x89B5, 0x58CD, 0x89B6, 0x58CE, 0x89B7, 0x58CF, + 0x89B8, 0x58D0, 0x89B9, 0x58D2, 0x89BA, 0x58D3, 0x89BB, 0x58D4, 0x89BC, 0x58D6, 0x89BD, 0x58D7, 0x89BE, 0x58D8, 0x89BF, 0x58D9, + 0x89C0, 0x58DA, 0x89C1, 0x58DB, 0x89C2, 0x58DC, 0x89C3, 0x58DD, 0x89C4, 0x58DE, 0x89C5, 0x58DF, 0x89C6, 0x58E0, 0x89C7, 0x58E1, + 0x89C8, 0x58E2, 0x89C9, 0x58E3, 0x89CA, 0x58E5, 0x89CB, 0x58E6, 0x89CC, 0x58E7, 0x89CD, 0x58E8, 0x89CE, 0x58E9, 0x89CF, 0x58EA, + 0x89D0, 0x58ED, 0x89D1, 0x58EF, 0x89D2, 0x58F1, 0x89D3, 0x58F2, 0x89D4, 0x58F4, 0x89D5, 0x58F5, 0x89D6, 0x58F7, 0x89D7, 0x58F8, + 0x89D8, 0x58FA, 0x89D9, 0x58FB, 0x89DA, 0x58FC, 0x89DB, 0x58FD, 0x89DC, 0x58FE, 0x89DD, 0x58FF, 0x89DE, 0x5900, 0x89DF, 0x5901, + 0x89E0, 0x5903, 0x89E1, 0x5905, 0x89E2, 0x5906, 0x89E3, 0x5908, 0x89E4, 0x5909, 0x89E5, 0x590A, 0x89E6, 0x590B, 0x89E7, 0x590C, + 0x89E8, 0x590E, 0x89E9, 0x5910, 0x89EA, 0x5911, 0x89EB, 0x5912, 0x89EC, 0x5913, 0x89ED, 0x5917, 0x89EE, 0x5918, 0x89EF, 0x591B, + 0x89F0, 0x591D, 0x89F1, 0x591E, 0x89F2, 0x5920, 0x89F3, 0x5921, 0x89F4, 0x5922, 0x89F5, 0x5923, 0x89F6, 0x5926, 0x89F7, 0x5928, + 0x89F8, 0x592C, 0x89F9, 0x5930, 0x89FA, 0x5932, 0x89FB, 0x5933, 0x89FC, 0x5935, 0x89FD, 0x5936, 0x89FE, 0x593B, 0x8A40, 0x593D, + 0x8A41, 0x593E, 0x8A42, 0x593F, 0x8A43, 0x5940, 0x8A44, 0x5943, 0x8A45, 0x5945, 0x8A46, 0x5946, 0x8A47, 0x594A, 0x8A48, 0x594C, + 0x8A49, 0x594D, 0x8A4A, 0x5950, 0x8A4B, 0x5952, 0x8A4C, 0x5953, 0x8A4D, 0x5959, 0x8A4E, 0x595B, 0x8A4F, 0x595C, 0x8A50, 0x595D, + 0x8A51, 0x595E, 0x8A52, 0x595F, 0x8A53, 0x5961, 0x8A54, 0x5963, 0x8A55, 0x5964, 0x8A56, 0x5966, 0x8A57, 0x5967, 0x8A58, 0x5968, + 0x8A59, 0x5969, 0x8A5A, 0x596A, 0x8A5B, 0x596B, 0x8A5C, 0x596C, 0x8A5D, 0x596D, 0x8A5E, 0x596E, 0x8A5F, 0x596F, 0x8A60, 0x5970, + 0x8A61, 0x5971, 0x8A62, 0x5972, 0x8A63, 0x5975, 0x8A64, 0x5977, 0x8A65, 0x597A, 0x8A66, 0x597B, 0x8A67, 0x597C, 0x8A68, 0x597E, + 0x8A69, 0x597F, 0x8A6A, 0x5980, 0x8A6B, 0x5985, 0x8A6C, 0x5989, 0x8A6D, 0x598B, 0x8A6E, 0x598C, 0x8A6F, 0x598E, 0x8A70, 0x598F, + 0x8A71, 0x5990, 0x8A72, 0x5991, 0x8A73, 0x5994, 0x8A74, 0x5995, 0x8A75, 0x5998, 0x8A76, 0x599A, 0x8A77, 0x599B, 0x8A78, 0x599C, + 0x8A79, 0x599D, 0x8A7A, 0x599F, 0x8A7B, 0x59A0, 0x8A7C, 0x59A1, 0x8A7D, 0x59A2, 0x8A7E, 0x59A6, 0x8A80, 0x59A7, 0x8A81, 0x59AC, + 0x8A82, 0x59AD, 0x8A83, 0x59B0, 0x8A84, 0x59B1, 0x8A85, 0x59B3, 0x8A86, 0x59B4, 0x8A87, 0x59B5, 0x8A88, 0x59B6, 0x8A89, 0x59B7, + 0x8A8A, 0x59B8, 0x8A8B, 0x59BA, 0x8A8C, 0x59BC, 0x8A8D, 0x59BD, 0x8A8E, 0x59BF, 0x8A8F, 0x59C0, 0x8A90, 0x59C1, 0x8A91, 0x59C2, + 0x8A92, 0x59C3, 0x8A93, 0x59C4, 0x8A94, 0x59C5, 0x8A95, 0x59C7, 0x8A96, 0x59C8, 0x8A97, 0x59C9, 0x8A98, 0x59CC, 0x8A99, 0x59CD, + 0x8A9A, 0x59CE, 0x8A9B, 0x59CF, 0x8A9C, 0x59D5, 0x8A9D, 0x59D6, 0x8A9E, 0x59D9, 0x8A9F, 0x59DB, 0x8AA0, 0x59DE, 0x8AA1, 0x59DF, + 0x8AA2, 0x59E0, 0x8AA3, 0x59E1, 0x8AA4, 0x59E2, 0x8AA5, 0x59E4, 0x8AA6, 0x59E6, 0x8AA7, 0x59E7, 0x8AA8, 0x59E9, 0x8AA9, 0x59EA, + 0x8AAA, 0x59EB, 0x8AAB, 0x59ED, 0x8AAC, 0x59EE, 0x8AAD, 0x59EF, 0x8AAE, 0x59F0, 0x8AAF, 0x59F1, 0x8AB0, 0x59F2, 0x8AB1, 0x59F3, + 0x8AB2, 0x59F4, 0x8AB3, 0x59F5, 0x8AB4, 0x59F6, 0x8AB5, 0x59F7, 0x8AB6, 0x59F8, 0x8AB7, 0x59FA, 0x8AB8, 0x59FC, 0x8AB9, 0x59FD, + 0x8ABA, 0x59FE, 0x8ABB, 0x5A00, 0x8ABC, 0x5A02, 0x8ABD, 0x5A0A, 0x8ABE, 0x5A0B, 0x8ABF, 0x5A0D, 0x8AC0, 0x5A0E, 0x8AC1, 0x5A0F, + 0x8AC2, 0x5A10, 0x8AC3, 0x5A12, 0x8AC4, 0x5A14, 0x8AC5, 0x5A15, 0x8AC6, 0x5A16, 0x8AC7, 0x5A17, 0x8AC8, 0x5A19, 0x8AC9, 0x5A1A, + 0x8ACA, 0x5A1B, 0x8ACB, 0x5A1D, 0x8ACC, 0x5A1E, 0x8ACD, 0x5A21, 0x8ACE, 0x5A22, 0x8ACF, 0x5A24, 0x8AD0, 0x5A26, 0x8AD1, 0x5A27, + 0x8AD2, 0x5A28, 0x8AD3, 0x5A2A, 0x8AD4, 0x5A2B, 0x8AD5, 0x5A2C, 0x8AD6, 0x5A2D, 0x8AD7, 0x5A2E, 0x8AD8, 0x5A2F, 0x8AD9, 0x5A30, + 0x8ADA, 0x5A33, 0x8ADB, 0x5A35, 0x8ADC, 0x5A37, 0x8ADD, 0x5A38, 0x8ADE, 0x5A39, 0x8ADF, 0x5A3A, 0x8AE0, 0x5A3B, 0x8AE1, 0x5A3D, + 0x8AE2, 0x5A3E, 0x8AE3, 0x5A3F, 0x8AE4, 0x5A41, 0x8AE5, 0x5A42, 0x8AE6, 0x5A43, 0x8AE7, 0x5A44, 0x8AE8, 0x5A45, 0x8AE9, 0x5A47, + 0x8AEA, 0x5A48, 0x8AEB, 0x5A4B, 0x8AEC, 0x5A4C, 0x8AED, 0x5A4D, 0x8AEE, 0x5A4E, 0x8AEF, 0x5A4F, 0x8AF0, 0x5A50, 0x8AF1, 0x5A51, + 0x8AF2, 0x5A52, 0x8AF3, 0x5A53, 0x8AF4, 0x5A54, 0x8AF5, 0x5A56, 0x8AF6, 0x5A57, 0x8AF7, 0x5A58, 0x8AF8, 0x5A59, 0x8AF9, 0x5A5B, + 0x8AFA, 0x5A5C, 0x8AFB, 0x5A5D, 0x8AFC, 0x5A5E, 0x8AFD, 0x5A5F, 0x8AFE, 0x5A60, 0x8B40, 0x5A61, 0x8B41, 0x5A63, 0x8B42, 0x5A64, + 0x8B43, 0x5A65, 0x8B44, 0x5A66, 0x8B45, 0x5A68, 0x8B46, 0x5A69, 0x8B47, 0x5A6B, 0x8B48, 0x5A6C, 0x8B49, 0x5A6D, 0x8B4A, 0x5A6E, + 0x8B4B, 0x5A6F, 0x8B4C, 0x5A70, 0x8B4D, 0x5A71, 0x8B4E, 0x5A72, 0x8B4F, 0x5A73, 0x8B50, 0x5A78, 0x8B51, 0x5A79, 0x8B52, 0x5A7B, + 0x8B53, 0x5A7C, 0x8B54, 0x5A7D, 0x8B55, 0x5A7E, 0x8B56, 0x5A80, 0x8B57, 0x5A81, 0x8B58, 0x5A82, 0x8B59, 0x5A83, 0x8B5A, 0x5A84, + 0x8B5B, 0x5A85, 0x8B5C, 0x5A86, 0x8B5D, 0x5A87, 0x8B5E, 0x5A88, 0x8B5F, 0x5A89, 0x8B60, 0x5A8A, 0x8B61, 0x5A8B, 0x8B62, 0x5A8C, + 0x8B63, 0x5A8D, 0x8B64, 0x5A8E, 0x8B65, 0x5A8F, 0x8B66, 0x5A90, 0x8B67, 0x5A91, 0x8B68, 0x5A93, 0x8B69, 0x5A94, 0x8B6A, 0x5A95, + 0x8B6B, 0x5A96, 0x8B6C, 0x5A97, 0x8B6D, 0x5A98, 0x8B6E, 0x5A99, 0x8B6F, 0x5A9C, 0x8B70, 0x5A9D, 0x8B71, 0x5A9E, 0x8B72, 0x5A9F, + 0x8B73, 0x5AA0, 0x8B74, 0x5AA1, 0x8B75, 0x5AA2, 0x8B76, 0x5AA3, 0x8B77, 0x5AA4, 0x8B78, 0x5AA5, 0x8B79, 0x5AA6, 0x8B7A, 0x5AA7, + 0x8B7B, 0x5AA8, 0x8B7C, 0x5AA9, 0x8B7D, 0x5AAB, 0x8B7E, 0x5AAC, 0x8B80, 0x5AAD, 0x8B81, 0x5AAE, 0x8B82, 0x5AAF, 0x8B83, 0x5AB0, + 0x8B84, 0x5AB1, 0x8B85, 0x5AB4, 0x8B86, 0x5AB6, 0x8B87, 0x5AB7, 0x8B88, 0x5AB9, 0x8B89, 0x5ABA, 0x8B8A, 0x5ABB, 0x8B8B, 0x5ABC, + 0x8B8C, 0x5ABD, 0x8B8D, 0x5ABF, 0x8B8E, 0x5AC0, 0x8B8F, 0x5AC3, 0x8B90, 0x5AC4, 0x8B91, 0x5AC5, 0x8B92, 0x5AC6, 0x8B93, 0x5AC7, + 0x8B94, 0x5AC8, 0x8B95, 0x5ACA, 0x8B96, 0x5ACB, 0x8B97, 0x5ACD, 0x8B98, 0x5ACE, 0x8B99, 0x5ACF, 0x8B9A, 0x5AD0, 0x8B9B, 0x5AD1, + 0x8B9C, 0x5AD3, 0x8B9D, 0x5AD5, 0x8B9E, 0x5AD7, 0x8B9F, 0x5AD9, 0x8BA0, 0x5ADA, 0x8BA1, 0x5ADB, 0x8BA2, 0x5ADD, 0x8BA3, 0x5ADE, + 0x8BA4, 0x5ADF, 0x8BA5, 0x5AE2, 0x8BA6, 0x5AE4, 0x8BA7, 0x5AE5, 0x8BA8, 0x5AE7, 0x8BA9, 0x5AE8, 0x8BAA, 0x5AEA, 0x8BAB, 0x5AEC, + 0x8BAC, 0x5AED, 0x8BAD, 0x5AEE, 0x8BAE, 0x5AEF, 0x8BAF, 0x5AF0, 0x8BB0, 0x5AF2, 0x8BB1, 0x5AF3, 0x8BB2, 0x5AF4, 0x8BB3, 0x5AF5, + 0x8BB4, 0x5AF6, 0x8BB5, 0x5AF7, 0x8BB6, 0x5AF8, 0x8BB7, 0x5AF9, 0x8BB8, 0x5AFA, 0x8BB9, 0x5AFB, 0x8BBA, 0x5AFC, 0x8BBB, 0x5AFD, + 0x8BBC, 0x5AFE, 0x8BBD, 0x5AFF, 0x8BBE, 0x5B00, 0x8BBF, 0x5B01, 0x8BC0, 0x5B02, 0x8BC1, 0x5B03, 0x8BC2, 0x5B04, 0x8BC3, 0x5B05, + 0x8BC4, 0x5B06, 0x8BC5, 0x5B07, 0x8BC6, 0x5B08, 0x8BC7, 0x5B0A, 0x8BC8, 0x5B0B, 0x8BC9, 0x5B0C, 0x8BCA, 0x5B0D, 0x8BCB, 0x5B0E, + 0x8BCC, 0x5B0F, 0x8BCD, 0x5B10, 0x8BCE, 0x5B11, 0x8BCF, 0x5B12, 0x8BD0, 0x5B13, 0x8BD1, 0x5B14, 0x8BD2, 0x5B15, 0x8BD3, 0x5B18, + 0x8BD4, 0x5B19, 0x8BD5, 0x5B1A, 0x8BD6, 0x5B1B, 0x8BD7, 0x5B1C, 0x8BD8, 0x5B1D, 0x8BD9, 0x5B1E, 0x8BDA, 0x5B1F, 0x8BDB, 0x5B20, + 0x8BDC, 0x5B21, 0x8BDD, 0x5B22, 0x8BDE, 0x5B23, 0x8BDF, 0x5B24, 0x8BE0, 0x5B25, 0x8BE1, 0x5B26, 0x8BE2, 0x5B27, 0x8BE3, 0x5B28, + 0x8BE4, 0x5B29, 0x8BE5, 0x5B2A, 0x8BE6, 0x5B2B, 0x8BE7, 0x5B2C, 0x8BE8, 0x5B2D, 0x8BE9, 0x5B2E, 0x8BEA, 0x5B2F, 0x8BEB, 0x5B30, + 0x8BEC, 0x5B31, 0x8BED, 0x5B33, 0x8BEE, 0x5B35, 0x8BEF, 0x5B36, 0x8BF0, 0x5B38, 0x8BF1, 0x5B39, 0x8BF2, 0x5B3A, 0x8BF3, 0x5B3B, + 0x8BF4, 0x5B3C, 0x8BF5, 0x5B3D, 0x8BF6, 0x5B3E, 0x8BF7, 0x5B3F, 0x8BF8, 0x5B41, 0x8BF9, 0x5B42, 0x8BFA, 0x5B43, 0x8BFB, 0x5B44, + 0x8BFC, 0x5B45, 0x8BFD, 0x5B46, 0x8BFE, 0x5B47, 0x8C40, 0x5B48, 0x8C41, 0x5B49, 0x8C42, 0x5B4A, 0x8C43, 0x5B4B, 0x8C44, 0x5B4C, + 0x8C45, 0x5B4D, 0x8C46, 0x5B4E, 0x8C47, 0x5B4F, 0x8C48, 0x5B52, 0x8C49, 0x5B56, 0x8C4A, 0x5B5E, 0x8C4B, 0x5B60, 0x8C4C, 0x5B61, + 0x8C4D, 0x5B67, 0x8C4E, 0x5B68, 0x8C4F, 0x5B6B, 0x8C50, 0x5B6D, 0x8C51, 0x5B6E, 0x8C52, 0x5B6F, 0x8C53, 0x5B72, 0x8C54, 0x5B74, + 0x8C55, 0x5B76, 0x8C56, 0x5B77, 0x8C57, 0x5B78, 0x8C58, 0x5B79, 0x8C59, 0x5B7B, 0x8C5A, 0x5B7C, 0x8C5B, 0x5B7E, 0x8C5C, 0x5B7F, + 0x8C5D, 0x5B82, 0x8C5E, 0x5B86, 0x8C5F, 0x5B8A, 0x8C60, 0x5B8D, 0x8C61, 0x5B8E, 0x8C62, 0x5B90, 0x8C63, 0x5B91, 0x8C64, 0x5B92, + 0x8C65, 0x5B94, 0x8C66, 0x5B96, 0x8C67, 0x5B9F, 0x8C68, 0x5BA7, 0x8C69, 0x5BA8, 0x8C6A, 0x5BA9, 0x8C6B, 0x5BAC, 0x8C6C, 0x5BAD, + 0x8C6D, 0x5BAE, 0x8C6E, 0x5BAF, 0x8C6F, 0x5BB1, 0x8C70, 0x5BB2, 0x8C71, 0x5BB7, 0x8C72, 0x5BBA, 0x8C73, 0x5BBB, 0x8C74, 0x5BBC, + 0x8C75, 0x5BC0, 0x8C76, 0x5BC1, 0x8C77, 0x5BC3, 0x8C78, 0x5BC8, 0x8C79, 0x5BC9, 0x8C7A, 0x5BCA, 0x8C7B, 0x5BCB, 0x8C7C, 0x5BCD, + 0x8C7D, 0x5BCE, 0x8C7E, 0x5BCF, 0x8C80, 0x5BD1, 0x8C81, 0x5BD4, 0x8C82, 0x5BD5, 0x8C83, 0x5BD6, 0x8C84, 0x5BD7, 0x8C85, 0x5BD8, + 0x8C86, 0x5BD9, 0x8C87, 0x5BDA, 0x8C88, 0x5BDB, 0x8C89, 0x5BDC, 0x8C8A, 0x5BE0, 0x8C8B, 0x5BE2, 0x8C8C, 0x5BE3, 0x8C8D, 0x5BE6, + 0x8C8E, 0x5BE7, 0x8C8F, 0x5BE9, 0x8C90, 0x5BEA, 0x8C91, 0x5BEB, 0x8C92, 0x5BEC, 0x8C93, 0x5BED, 0x8C94, 0x5BEF, 0x8C95, 0x5BF1, + 0x8C96, 0x5BF2, 0x8C97, 0x5BF3, 0x8C98, 0x5BF4, 0x8C99, 0x5BF5, 0x8C9A, 0x5BF6, 0x8C9B, 0x5BF7, 0x8C9C, 0x5BFD, 0x8C9D, 0x5BFE, + 0x8C9E, 0x5C00, 0x8C9F, 0x5C02, 0x8CA0, 0x5C03, 0x8CA1, 0x5C05, 0x8CA2, 0x5C07, 0x8CA3, 0x5C08, 0x8CA4, 0x5C0B, 0x8CA5, 0x5C0C, + 0x8CA6, 0x5C0D, 0x8CA7, 0x5C0E, 0x8CA8, 0x5C10, 0x8CA9, 0x5C12, 0x8CAA, 0x5C13, 0x8CAB, 0x5C17, 0x8CAC, 0x5C19, 0x8CAD, 0x5C1B, + 0x8CAE, 0x5C1E, 0x8CAF, 0x5C1F, 0x8CB0, 0x5C20, 0x8CB1, 0x5C21, 0x8CB2, 0x5C23, 0x8CB3, 0x5C26, 0x8CB4, 0x5C28, 0x8CB5, 0x5C29, + 0x8CB6, 0x5C2A, 0x8CB7, 0x5C2B, 0x8CB8, 0x5C2D, 0x8CB9, 0x5C2E, 0x8CBA, 0x5C2F, 0x8CBB, 0x5C30, 0x8CBC, 0x5C32, 0x8CBD, 0x5C33, + 0x8CBE, 0x5C35, 0x8CBF, 0x5C36, 0x8CC0, 0x5C37, 0x8CC1, 0x5C43, 0x8CC2, 0x5C44, 0x8CC3, 0x5C46, 0x8CC4, 0x5C47, 0x8CC5, 0x5C4C, + 0x8CC6, 0x5C4D, 0x8CC7, 0x5C52, 0x8CC8, 0x5C53, 0x8CC9, 0x5C54, 0x8CCA, 0x5C56, 0x8CCB, 0x5C57, 0x8CCC, 0x5C58, 0x8CCD, 0x5C5A, + 0x8CCE, 0x5C5B, 0x8CCF, 0x5C5C, 0x8CD0, 0x5C5D, 0x8CD1, 0x5C5F, 0x8CD2, 0x5C62, 0x8CD3, 0x5C64, 0x8CD4, 0x5C67, 0x8CD5, 0x5C68, + 0x8CD6, 0x5C69, 0x8CD7, 0x5C6A, 0x8CD8, 0x5C6B, 0x8CD9, 0x5C6C, 0x8CDA, 0x5C6D, 0x8CDB, 0x5C70, 0x8CDC, 0x5C72, 0x8CDD, 0x5C73, + 0x8CDE, 0x5C74, 0x8CDF, 0x5C75, 0x8CE0, 0x5C76, 0x8CE1, 0x5C77, 0x8CE2, 0x5C78, 0x8CE3, 0x5C7B, 0x8CE4, 0x5C7C, 0x8CE5, 0x5C7D, + 0x8CE6, 0x5C7E, 0x8CE7, 0x5C80, 0x8CE8, 0x5C83, 0x8CE9, 0x5C84, 0x8CEA, 0x5C85, 0x8CEB, 0x5C86, 0x8CEC, 0x5C87, 0x8CED, 0x5C89, + 0x8CEE, 0x5C8A, 0x8CEF, 0x5C8B, 0x8CF0, 0x5C8E, 0x8CF1, 0x5C8F, 0x8CF2, 0x5C92, 0x8CF3, 0x5C93, 0x8CF4, 0x5C95, 0x8CF5, 0x5C9D, + 0x8CF6, 0x5C9E, 0x8CF7, 0x5C9F, 0x8CF8, 0x5CA0, 0x8CF9, 0x5CA1, 0x8CFA, 0x5CA4, 0x8CFB, 0x5CA5, 0x8CFC, 0x5CA6, 0x8CFD, 0x5CA7, + 0x8CFE, 0x5CA8, 0x8D40, 0x5CAA, 0x8D41, 0x5CAE, 0x8D42, 0x5CAF, 0x8D43, 0x5CB0, 0x8D44, 0x5CB2, 0x8D45, 0x5CB4, 0x8D46, 0x5CB6, + 0x8D47, 0x5CB9, 0x8D48, 0x5CBA, 0x8D49, 0x5CBB, 0x8D4A, 0x5CBC, 0x8D4B, 0x5CBE, 0x8D4C, 0x5CC0, 0x8D4D, 0x5CC2, 0x8D4E, 0x5CC3, + 0x8D4F, 0x5CC5, 0x8D50, 0x5CC6, 0x8D51, 0x5CC7, 0x8D52, 0x5CC8, 0x8D53, 0x5CC9, 0x8D54, 0x5CCA, 0x8D55, 0x5CCC, 0x8D56, 0x5CCD, + 0x8D57, 0x5CCE, 0x8D58, 0x5CCF, 0x8D59, 0x5CD0, 0x8D5A, 0x5CD1, 0x8D5B, 0x5CD3, 0x8D5C, 0x5CD4, 0x8D5D, 0x5CD5, 0x8D5E, 0x5CD6, + 0x8D5F, 0x5CD7, 0x8D60, 0x5CD8, 0x8D61, 0x5CDA, 0x8D62, 0x5CDB, 0x8D63, 0x5CDC, 0x8D64, 0x5CDD, 0x8D65, 0x5CDE, 0x8D66, 0x5CDF, + 0x8D67, 0x5CE0, 0x8D68, 0x5CE2, 0x8D69, 0x5CE3, 0x8D6A, 0x5CE7, 0x8D6B, 0x5CE9, 0x8D6C, 0x5CEB, 0x8D6D, 0x5CEC, 0x8D6E, 0x5CEE, + 0x8D6F, 0x5CEF, 0x8D70, 0x5CF1, 0x8D71, 0x5CF2, 0x8D72, 0x5CF3, 0x8D73, 0x5CF4, 0x8D74, 0x5CF5, 0x8D75, 0x5CF6, 0x8D76, 0x5CF7, + 0x8D77, 0x5CF8, 0x8D78, 0x5CF9, 0x8D79, 0x5CFA, 0x8D7A, 0x5CFC, 0x8D7B, 0x5CFD, 0x8D7C, 0x5CFE, 0x8D7D, 0x5CFF, 0x8D7E, 0x5D00, + 0x8D80, 0x5D01, 0x8D81, 0x5D04, 0x8D82, 0x5D05, 0x8D83, 0x5D08, 0x8D84, 0x5D09, 0x8D85, 0x5D0A, 0x8D86, 0x5D0B, 0x8D87, 0x5D0C, + 0x8D88, 0x5D0D, 0x8D89, 0x5D0F, 0x8D8A, 0x5D10, 0x8D8B, 0x5D11, 0x8D8C, 0x5D12, 0x8D8D, 0x5D13, 0x8D8E, 0x5D15, 0x8D8F, 0x5D17, + 0x8D90, 0x5D18, 0x8D91, 0x5D19, 0x8D92, 0x5D1A, 0x8D93, 0x5D1C, 0x8D94, 0x5D1D, 0x8D95, 0x5D1F, 0x8D96, 0x5D20, 0x8D97, 0x5D21, + 0x8D98, 0x5D22, 0x8D99, 0x5D23, 0x8D9A, 0x5D25, 0x8D9B, 0x5D28, 0x8D9C, 0x5D2A, 0x8D9D, 0x5D2B, 0x8D9E, 0x5D2C, 0x8D9F, 0x5D2F, + 0x8DA0, 0x5D30, 0x8DA1, 0x5D31, 0x8DA2, 0x5D32, 0x8DA3, 0x5D33, 0x8DA4, 0x5D35, 0x8DA5, 0x5D36, 0x8DA6, 0x5D37, 0x8DA7, 0x5D38, + 0x8DA8, 0x5D39, 0x8DA9, 0x5D3A, 0x8DAA, 0x5D3B, 0x8DAB, 0x5D3C, 0x8DAC, 0x5D3F, 0x8DAD, 0x5D40, 0x8DAE, 0x5D41, 0x8DAF, 0x5D42, + 0x8DB0, 0x5D43, 0x8DB1, 0x5D44, 0x8DB2, 0x5D45, 0x8DB3, 0x5D46, 0x8DB4, 0x5D48, 0x8DB5, 0x5D49, 0x8DB6, 0x5D4D, 0x8DB7, 0x5D4E, + 0x8DB8, 0x5D4F, 0x8DB9, 0x5D50, 0x8DBA, 0x5D51, 0x8DBB, 0x5D52, 0x8DBC, 0x5D53, 0x8DBD, 0x5D54, 0x8DBE, 0x5D55, 0x8DBF, 0x5D56, + 0x8DC0, 0x5D57, 0x8DC1, 0x5D59, 0x8DC2, 0x5D5A, 0x8DC3, 0x5D5C, 0x8DC4, 0x5D5E, 0x8DC5, 0x5D5F, 0x8DC6, 0x5D60, 0x8DC7, 0x5D61, + 0x8DC8, 0x5D62, 0x8DC9, 0x5D63, 0x8DCA, 0x5D64, 0x8DCB, 0x5D65, 0x8DCC, 0x5D66, 0x8DCD, 0x5D67, 0x8DCE, 0x5D68, 0x8DCF, 0x5D6A, + 0x8DD0, 0x5D6D, 0x8DD1, 0x5D6E, 0x8DD2, 0x5D70, 0x8DD3, 0x5D71, 0x8DD4, 0x5D72, 0x8DD5, 0x5D73, 0x8DD6, 0x5D75, 0x8DD7, 0x5D76, + 0x8DD8, 0x5D77, 0x8DD9, 0x5D78, 0x8DDA, 0x5D79, 0x8DDB, 0x5D7A, 0x8DDC, 0x5D7B, 0x8DDD, 0x5D7C, 0x8DDE, 0x5D7D, 0x8DDF, 0x5D7E, + 0x8DE0, 0x5D7F, 0x8DE1, 0x5D80, 0x8DE2, 0x5D81, 0x8DE3, 0x5D83, 0x8DE4, 0x5D84, 0x8DE5, 0x5D85, 0x8DE6, 0x5D86, 0x8DE7, 0x5D87, + 0x8DE8, 0x5D88, 0x8DE9, 0x5D89, 0x8DEA, 0x5D8A, 0x8DEB, 0x5D8B, 0x8DEC, 0x5D8C, 0x8DED, 0x5D8D, 0x8DEE, 0x5D8E, 0x8DEF, 0x5D8F, + 0x8DF0, 0x5D90, 0x8DF1, 0x5D91, 0x8DF2, 0x5D92, 0x8DF3, 0x5D93, 0x8DF4, 0x5D94, 0x8DF5, 0x5D95, 0x8DF6, 0x5D96, 0x8DF7, 0x5D97, + 0x8DF8, 0x5D98, 0x8DF9, 0x5D9A, 0x8DFA, 0x5D9B, 0x8DFB, 0x5D9C, 0x8DFC, 0x5D9E, 0x8DFD, 0x5D9F, 0x8DFE, 0x5DA0, 0x8E40, 0x5DA1, + 0x8E41, 0x5DA2, 0x8E42, 0x5DA3, 0x8E43, 0x5DA4, 0x8E44, 0x5DA5, 0x8E45, 0x5DA6, 0x8E46, 0x5DA7, 0x8E47, 0x5DA8, 0x8E48, 0x5DA9, + 0x8E49, 0x5DAA, 0x8E4A, 0x5DAB, 0x8E4B, 0x5DAC, 0x8E4C, 0x5DAD, 0x8E4D, 0x5DAE, 0x8E4E, 0x5DAF, 0x8E4F, 0x5DB0, 0x8E50, 0x5DB1, + 0x8E51, 0x5DB2, 0x8E52, 0x5DB3, 0x8E53, 0x5DB4, 0x8E54, 0x5DB5, 0x8E55, 0x5DB6, 0x8E56, 0x5DB8, 0x8E57, 0x5DB9, 0x8E58, 0x5DBA, + 0x8E59, 0x5DBB, 0x8E5A, 0x5DBC, 0x8E5B, 0x5DBD, 0x8E5C, 0x5DBE, 0x8E5D, 0x5DBF, 0x8E5E, 0x5DC0, 0x8E5F, 0x5DC1, 0x8E60, 0x5DC2, + 0x8E61, 0x5DC3, 0x8E62, 0x5DC4, 0x8E63, 0x5DC6, 0x8E64, 0x5DC7, 0x8E65, 0x5DC8, 0x8E66, 0x5DC9, 0x8E67, 0x5DCA, 0x8E68, 0x5DCB, + 0x8E69, 0x5DCC, 0x8E6A, 0x5DCE, 0x8E6B, 0x5DCF, 0x8E6C, 0x5DD0, 0x8E6D, 0x5DD1, 0x8E6E, 0x5DD2, 0x8E6F, 0x5DD3, 0x8E70, 0x5DD4, + 0x8E71, 0x5DD5, 0x8E72, 0x5DD6, 0x8E73, 0x5DD7, 0x8E74, 0x5DD8, 0x8E75, 0x5DD9, 0x8E76, 0x5DDA, 0x8E77, 0x5DDC, 0x8E78, 0x5DDF, + 0x8E79, 0x5DE0, 0x8E7A, 0x5DE3, 0x8E7B, 0x5DE4, 0x8E7C, 0x5DEA, 0x8E7D, 0x5DEC, 0x8E7E, 0x5DED, 0x8E80, 0x5DF0, 0x8E81, 0x5DF5, + 0x8E82, 0x5DF6, 0x8E83, 0x5DF8, 0x8E84, 0x5DF9, 0x8E85, 0x5DFA, 0x8E86, 0x5DFB, 0x8E87, 0x5DFC, 0x8E88, 0x5DFF, 0x8E89, 0x5E00, + 0x8E8A, 0x5E04, 0x8E8B, 0x5E07, 0x8E8C, 0x5E09, 0x8E8D, 0x5E0A, 0x8E8E, 0x5E0B, 0x8E8F, 0x5E0D, 0x8E90, 0x5E0E, 0x8E91, 0x5E12, + 0x8E92, 0x5E13, 0x8E93, 0x5E17, 0x8E94, 0x5E1E, 0x8E95, 0x5E1F, 0x8E96, 0x5E20, 0x8E97, 0x5E21, 0x8E98, 0x5E22, 0x8E99, 0x5E23, + 0x8E9A, 0x5E24, 0x8E9B, 0x5E25, 0x8E9C, 0x5E28, 0x8E9D, 0x5E29, 0x8E9E, 0x5E2A, 0x8E9F, 0x5E2B, 0x8EA0, 0x5E2C, 0x8EA1, 0x5E2F, + 0x8EA2, 0x5E30, 0x8EA3, 0x5E32, 0x8EA4, 0x5E33, 0x8EA5, 0x5E34, 0x8EA6, 0x5E35, 0x8EA7, 0x5E36, 0x8EA8, 0x5E39, 0x8EA9, 0x5E3A, + 0x8EAA, 0x5E3E, 0x8EAB, 0x5E3F, 0x8EAC, 0x5E40, 0x8EAD, 0x5E41, 0x8EAE, 0x5E43, 0x8EAF, 0x5E46, 0x8EB0, 0x5E47, 0x8EB1, 0x5E48, + 0x8EB2, 0x5E49, 0x8EB3, 0x5E4A, 0x8EB4, 0x5E4B, 0x8EB5, 0x5E4D, 0x8EB6, 0x5E4E, 0x8EB7, 0x5E4F, 0x8EB8, 0x5E50, 0x8EB9, 0x5E51, + 0x8EBA, 0x5E52, 0x8EBB, 0x5E53, 0x8EBC, 0x5E56, 0x8EBD, 0x5E57, 0x8EBE, 0x5E58, 0x8EBF, 0x5E59, 0x8EC0, 0x5E5A, 0x8EC1, 0x5E5C, + 0x8EC2, 0x5E5D, 0x8EC3, 0x5E5F, 0x8EC4, 0x5E60, 0x8EC5, 0x5E63, 0x8EC6, 0x5E64, 0x8EC7, 0x5E65, 0x8EC8, 0x5E66, 0x8EC9, 0x5E67, + 0x8ECA, 0x5E68, 0x8ECB, 0x5E69, 0x8ECC, 0x5E6A, 0x8ECD, 0x5E6B, 0x8ECE, 0x5E6C, 0x8ECF, 0x5E6D, 0x8ED0, 0x5E6E, 0x8ED1, 0x5E6F, + 0x8ED2, 0x5E70, 0x8ED3, 0x5E71, 0x8ED4, 0x5E75, 0x8ED5, 0x5E77, 0x8ED6, 0x5E79, 0x8ED7, 0x5E7E, 0x8ED8, 0x5E81, 0x8ED9, 0x5E82, + 0x8EDA, 0x5E83, 0x8EDB, 0x5E85, 0x8EDC, 0x5E88, 0x8EDD, 0x5E89, 0x8EDE, 0x5E8C, 0x8EDF, 0x5E8D, 0x8EE0, 0x5E8E, 0x8EE1, 0x5E92, + 0x8EE2, 0x5E98, 0x8EE3, 0x5E9B, 0x8EE4, 0x5E9D, 0x8EE5, 0x5EA1, 0x8EE6, 0x5EA2, 0x8EE7, 0x5EA3, 0x8EE8, 0x5EA4, 0x8EE9, 0x5EA8, + 0x8EEA, 0x5EA9, 0x8EEB, 0x5EAA, 0x8EEC, 0x5EAB, 0x8EED, 0x5EAC, 0x8EEE, 0x5EAE, 0x8EEF, 0x5EAF, 0x8EF0, 0x5EB0, 0x8EF1, 0x5EB1, + 0x8EF2, 0x5EB2, 0x8EF3, 0x5EB4, 0x8EF4, 0x5EBA, 0x8EF5, 0x5EBB, 0x8EF6, 0x5EBC, 0x8EF7, 0x5EBD, 0x8EF8, 0x5EBF, 0x8EF9, 0x5EC0, + 0x8EFA, 0x5EC1, 0x8EFB, 0x5EC2, 0x8EFC, 0x5EC3, 0x8EFD, 0x5EC4, 0x8EFE, 0x5EC5, 0x8F40, 0x5EC6, 0x8F41, 0x5EC7, 0x8F42, 0x5EC8, + 0x8F43, 0x5ECB, 0x8F44, 0x5ECC, 0x8F45, 0x5ECD, 0x8F46, 0x5ECE, 0x8F47, 0x5ECF, 0x8F48, 0x5ED0, 0x8F49, 0x5ED4, 0x8F4A, 0x5ED5, + 0x8F4B, 0x5ED7, 0x8F4C, 0x5ED8, 0x8F4D, 0x5ED9, 0x8F4E, 0x5EDA, 0x8F4F, 0x5EDC, 0x8F50, 0x5EDD, 0x8F51, 0x5EDE, 0x8F52, 0x5EDF, + 0x8F53, 0x5EE0, 0x8F54, 0x5EE1, 0x8F55, 0x5EE2, 0x8F56, 0x5EE3, 0x8F57, 0x5EE4, 0x8F58, 0x5EE5, 0x8F59, 0x5EE6, 0x8F5A, 0x5EE7, + 0x8F5B, 0x5EE9, 0x8F5C, 0x5EEB, 0x8F5D, 0x5EEC, 0x8F5E, 0x5EED, 0x8F5F, 0x5EEE, 0x8F60, 0x5EEF, 0x8F61, 0x5EF0, 0x8F62, 0x5EF1, + 0x8F63, 0x5EF2, 0x8F64, 0x5EF3, 0x8F65, 0x5EF5, 0x8F66, 0x5EF8, 0x8F67, 0x5EF9, 0x8F68, 0x5EFB, 0x8F69, 0x5EFC, 0x8F6A, 0x5EFD, + 0x8F6B, 0x5F05, 0x8F6C, 0x5F06, 0x8F6D, 0x5F07, 0x8F6E, 0x5F09, 0x8F6F, 0x5F0C, 0x8F70, 0x5F0D, 0x8F71, 0x5F0E, 0x8F72, 0x5F10, + 0x8F73, 0x5F12, 0x8F74, 0x5F14, 0x8F75, 0x5F16, 0x8F76, 0x5F19, 0x8F77, 0x5F1A, 0x8F78, 0x5F1C, 0x8F79, 0x5F1D, 0x8F7A, 0x5F1E, + 0x8F7B, 0x5F21, 0x8F7C, 0x5F22, 0x8F7D, 0x5F23, 0x8F7E, 0x5F24, 0x8F80, 0x5F28, 0x8F81, 0x5F2B, 0x8F82, 0x5F2C, 0x8F83, 0x5F2E, + 0x8F84, 0x5F30, 0x8F85, 0x5F32, 0x8F86, 0x5F33, 0x8F87, 0x5F34, 0x8F88, 0x5F35, 0x8F89, 0x5F36, 0x8F8A, 0x5F37, 0x8F8B, 0x5F38, + 0x8F8C, 0x5F3B, 0x8F8D, 0x5F3D, 0x8F8E, 0x5F3E, 0x8F8F, 0x5F3F, 0x8F90, 0x5F41, 0x8F91, 0x5F42, 0x8F92, 0x5F43, 0x8F93, 0x5F44, + 0x8F94, 0x5F45, 0x8F95, 0x5F46, 0x8F96, 0x5F47, 0x8F97, 0x5F48, 0x8F98, 0x5F49, 0x8F99, 0x5F4A, 0x8F9A, 0x5F4B, 0x8F9B, 0x5F4C, + 0x8F9C, 0x5F4D, 0x8F9D, 0x5F4E, 0x8F9E, 0x5F4F, 0x8F9F, 0x5F51, 0x8FA0, 0x5F54, 0x8FA1, 0x5F59, 0x8FA2, 0x5F5A, 0x8FA3, 0x5F5B, + 0x8FA4, 0x5F5C, 0x8FA5, 0x5F5E, 0x8FA6, 0x5F5F, 0x8FA7, 0x5F60, 0x8FA8, 0x5F63, 0x8FA9, 0x5F65, 0x8FAA, 0x5F67, 0x8FAB, 0x5F68, + 0x8FAC, 0x5F6B, 0x8FAD, 0x5F6E, 0x8FAE, 0x5F6F, 0x8FAF, 0x5F72, 0x8FB0, 0x5F74, 0x8FB1, 0x5F75, 0x8FB2, 0x5F76, 0x8FB3, 0x5F78, + 0x8FB4, 0x5F7A, 0x8FB5, 0x5F7D, 0x8FB6, 0x5F7E, 0x8FB7, 0x5F7F, 0x8FB8, 0x5F83, 0x8FB9, 0x5F86, 0x8FBA, 0x5F8D, 0x8FBB, 0x5F8E, + 0x8FBC, 0x5F8F, 0x8FBD, 0x5F91, 0x8FBE, 0x5F93, 0x8FBF, 0x5F94, 0x8FC0, 0x5F96, 0x8FC1, 0x5F9A, 0x8FC2, 0x5F9B, 0x8FC3, 0x5F9D, + 0x8FC4, 0x5F9E, 0x8FC5, 0x5F9F, 0x8FC6, 0x5FA0, 0x8FC7, 0x5FA2, 0x8FC8, 0x5FA3, 0x8FC9, 0x5FA4, 0x8FCA, 0x5FA5, 0x8FCB, 0x5FA6, + 0x8FCC, 0x5FA7, 0x8FCD, 0x5FA9, 0x8FCE, 0x5FAB, 0x8FCF, 0x5FAC, 0x8FD0, 0x5FAF, 0x8FD1, 0x5FB0, 0x8FD2, 0x5FB1, 0x8FD3, 0x5FB2, + 0x8FD4, 0x5FB3, 0x8FD5, 0x5FB4, 0x8FD6, 0x5FB6, 0x8FD7, 0x5FB8, 0x8FD8, 0x5FB9, 0x8FD9, 0x5FBA, 0x8FDA, 0x5FBB, 0x8FDB, 0x5FBE, + 0x8FDC, 0x5FBF, 0x8FDD, 0x5FC0, 0x8FDE, 0x5FC1, 0x8FDF, 0x5FC2, 0x8FE0, 0x5FC7, 0x8FE1, 0x5FC8, 0x8FE2, 0x5FCA, 0x8FE3, 0x5FCB, + 0x8FE4, 0x5FCE, 0x8FE5, 0x5FD3, 0x8FE6, 0x5FD4, 0x8FE7, 0x5FD5, 0x8FE8, 0x5FDA, 0x8FE9, 0x5FDB, 0x8FEA, 0x5FDC, 0x8FEB, 0x5FDE, + 0x8FEC, 0x5FDF, 0x8FED, 0x5FE2, 0x8FEE, 0x5FE3, 0x8FEF, 0x5FE5, 0x8FF0, 0x5FE6, 0x8FF1, 0x5FE8, 0x8FF2, 0x5FE9, 0x8FF3, 0x5FEC, + 0x8FF4, 0x5FEF, 0x8FF5, 0x5FF0, 0x8FF6, 0x5FF2, 0x8FF7, 0x5FF3, 0x8FF8, 0x5FF4, 0x8FF9, 0x5FF6, 0x8FFA, 0x5FF7, 0x8FFB, 0x5FF9, + 0x8FFC, 0x5FFA, 0x8FFD, 0x5FFC, 0x8FFE, 0x6007, 0x9040, 0x6008, 0x9041, 0x6009, 0x9042, 0x600B, 0x9043, 0x600C, 0x9044, 0x6010, + 0x9045, 0x6011, 0x9046, 0x6013, 0x9047, 0x6017, 0x9048, 0x6018, 0x9049, 0x601A, 0x904A, 0x601E, 0x904B, 0x601F, 0x904C, 0x6022, + 0x904D, 0x6023, 0x904E, 0x6024, 0x904F, 0x602C, 0x9050, 0x602D, 0x9051, 0x602E, 0x9052, 0x6030, 0x9053, 0x6031, 0x9054, 0x6032, + 0x9055, 0x6033, 0x9056, 0x6034, 0x9057, 0x6036, 0x9058, 0x6037, 0x9059, 0x6038, 0x905A, 0x6039, 0x905B, 0x603A, 0x905C, 0x603D, + 0x905D, 0x603E, 0x905E, 0x6040, 0x905F, 0x6044, 0x9060, 0x6045, 0x9061, 0x6046, 0x9062, 0x6047, 0x9063, 0x6048, 0x9064, 0x6049, + 0x9065, 0x604A, 0x9066, 0x604C, 0x9067, 0x604E, 0x9068, 0x604F, 0x9069, 0x6051, 0x906A, 0x6053, 0x906B, 0x6054, 0x906C, 0x6056, + 0x906D, 0x6057, 0x906E, 0x6058, 0x906F, 0x605B, 0x9070, 0x605C, 0x9071, 0x605E, 0x9072, 0x605F, 0x9073, 0x6060, 0x9074, 0x6061, + 0x9075, 0x6065, 0x9076, 0x6066, 0x9077, 0x606E, 0x9078, 0x6071, 0x9079, 0x6072, 0x907A, 0x6074, 0x907B, 0x6075, 0x907C, 0x6077, + 0x907D, 0x607E, 0x907E, 0x6080, 0x9080, 0x6081, 0x9081, 0x6082, 0x9082, 0x6085, 0x9083, 0x6086, 0x9084, 0x6087, 0x9085, 0x6088, + 0x9086, 0x608A, 0x9087, 0x608B, 0x9088, 0x608E, 0x9089, 0x608F, 0x908A, 0x6090, 0x908B, 0x6091, 0x908C, 0x6093, 0x908D, 0x6095, + 0x908E, 0x6097, 0x908F, 0x6098, 0x9090, 0x6099, 0x9091, 0x609C, 0x9092, 0x609E, 0x9093, 0x60A1, 0x9094, 0x60A2, 0x9095, 0x60A4, + 0x9096, 0x60A5, 0x9097, 0x60A7, 0x9098, 0x60A9, 0x9099, 0x60AA, 0x909A, 0x60AE, 0x909B, 0x60B0, 0x909C, 0x60B3, 0x909D, 0x60B5, + 0x909E, 0x60B6, 0x909F, 0x60B7, 0x90A0, 0x60B9, 0x90A1, 0x60BA, 0x90A2, 0x60BD, 0x90A3, 0x60BE, 0x90A4, 0x60BF, 0x90A5, 0x60C0, + 0x90A6, 0x60C1, 0x90A7, 0x60C2, 0x90A8, 0x60C3, 0x90A9, 0x60C4, 0x90AA, 0x60C7, 0x90AB, 0x60C8, 0x90AC, 0x60C9, 0x90AD, 0x60CC, + 0x90AE, 0x60CD, 0x90AF, 0x60CE, 0x90B0, 0x60CF, 0x90B1, 0x60D0, 0x90B2, 0x60D2, 0x90B3, 0x60D3, 0x90B4, 0x60D4, 0x90B5, 0x60D6, + 0x90B6, 0x60D7, 0x90B7, 0x60D9, 0x90B8, 0x60DB, 0x90B9, 0x60DE, 0x90BA, 0x60E1, 0x90BB, 0x60E2, 0x90BC, 0x60E3, 0x90BD, 0x60E4, + 0x90BE, 0x60E5, 0x90BF, 0x60EA, 0x90C0, 0x60F1, 0x90C1, 0x60F2, 0x90C2, 0x60F5, 0x90C3, 0x60F7, 0x90C4, 0x60F8, 0x90C5, 0x60FB, + 0x90C6, 0x60FC, 0x90C7, 0x60FD, 0x90C8, 0x60FE, 0x90C9, 0x60FF, 0x90CA, 0x6102, 0x90CB, 0x6103, 0x90CC, 0x6104, 0x90CD, 0x6105, + 0x90CE, 0x6107, 0x90CF, 0x610A, 0x90D0, 0x610B, 0x90D1, 0x610C, 0x90D2, 0x6110, 0x90D3, 0x6111, 0x90D4, 0x6112, 0x90D5, 0x6113, + 0x90D6, 0x6114, 0x90D7, 0x6116, 0x90D8, 0x6117, 0x90D9, 0x6118, 0x90DA, 0x6119, 0x90DB, 0x611B, 0x90DC, 0x611C, 0x90DD, 0x611D, + 0x90DE, 0x611E, 0x90DF, 0x6121, 0x90E0, 0x6122, 0x90E1, 0x6125, 0x90E2, 0x6128, 0x90E3, 0x6129, 0x90E4, 0x612A, 0x90E5, 0x612C, + 0x90E6, 0x612D, 0x90E7, 0x612E, 0x90E8, 0x612F, 0x90E9, 0x6130, 0x90EA, 0x6131, 0x90EB, 0x6132, 0x90EC, 0x6133, 0x90ED, 0x6134, + 0x90EE, 0x6135, 0x90EF, 0x6136, 0x90F0, 0x6137, 0x90F1, 0x6138, 0x90F2, 0x6139, 0x90F3, 0x613A, 0x90F4, 0x613B, 0x90F5, 0x613C, + 0x90F6, 0x613D, 0x90F7, 0x613E, 0x90F8, 0x6140, 0x90F9, 0x6141, 0x90FA, 0x6142, 0x90FB, 0x6143, 0x90FC, 0x6144, 0x90FD, 0x6145, + 0x90FE, 0x6146, 0x9140, 0x6147, 0x9141, 0x6149, 0x9142, 0x614B, 0x9143, 0x614D, 0x9144, 0x614F, 0x9145, 0x6150, 0x9146, 0x6152, + 0x9147, 0x6153, 0x9148, 0x6154, 0x9149, 0x6156, 0x914A, 0x6157, 0x914B, 0x6158, 0x914C, 0x6159, 0x914D, 0x615A, 0x914E, 0x615B, + 0x914F, 0x615C, 0x9150, 0x615E, 0x9151, 0x615F, 0x9152, 0x6160, 0x9153, 0x6161, 0x9154, 0x6163, 0x9155, 0x6164, 0x9156, 0x6165, + 0x9157, 0x6166, 0x9158, 0x6169, 0x9159, 0x616A, 0x915A, 0x616B, 0x915B, 0x616C, 0x915C, 0x616D, 0x915D, 0x616E, 0x915E, 0x616F, + 0x915F, 0x6171, 0x9160, 0x6172, 0x9161, 0x6173, 0x9162, 0x6174, 0x9163, 0x6176, 0x9164, 0x6178, 0x9165, 0x6179, 0x9166, 0x617A, + 0x9167, 0x617B, 0x9168, 0x617C, 0x9169, 0x617D, 0x916A, 0x617E, 0x916B, 0x617F, 0x916C, 0x6180, 0x916D, 0x6181, 0x916E, 0x6182, + 0x916F, 0x6183, 0x9170, 0x6184, 0x9171, 0x6185, 0x9172, 0x6186, 0x9173, 0x6187, 0x9174, 0x6188, 0x9175, 0x6189, 0x9176, 0x618A, + 0x9177, 0x618C, 0x9178, 0x618D, 0x9179, 0x618F, 0x917A, 0x6190, 0x917B, 0x6191, 0x917C, 0x6192, 0x917D, 0x6193, 0x917E, 0x6195, + 0x9180, 0x6196, 0x9181, 0x6197, 0x9182, 0x6198, 0x9183, 0x6199, 0x9184, 0x619A, 0x9185, 0x619B, 0x9186, 0x619C, 0x9187, 0x619E, + 0x9188, 0x619F, 0x9189, 0x61A0, 0x918A, 0x61A1, 0x918B, 0x61A2, 0x918C, 0x61A3, 0x918D, 0x61A4, 0x918E, 0x61A5, 0x918F, 0x61A6, + 0x9190, 0x61AA, 0x9191, 0x61AB, 0x9192, 0x61AD, 0x9193, 0x61AE, 0x9194, 0x61AF, 0x9195, 0x61B0, 0x9196, 0x61B1, 0x9197, 0x61B2, + 0x9198, 0x61B3, 0x9199, 0x61B4, 0x919A, 0x61B5, 0x919B, 0x61B6, 0x919C, 0x61B8, 0x919D, 0x61B9, 0x919E, 0x61BA, 0x919F, 0x61BB, + 0x91A0, 0x61BC, 0x91A1, 0x61BD, 0x91A2, 0x61BF, 0x91A3, 0x61C0, 0x91A4, 0x61C1, 0x91A5, 0x61C3, 0x91A6, 0x61C4, 0x91A7, 0x61C5, + 0x91A8, 0x61C6, 0x91A9, 0x61C7, 0x91AA, 0x61C9, 0x91AB, 0x61CC, 0x91AC, 0x61CD, 0x91AD, 0x61CE, 0x91AE, 0x61CF, 0x91AF, 0x61D0, + 0x91B0, 0x61D3, 0x91B1, 0x61D5, 0x91B2, 0x61D6, 0x91B3, 0x61D7, 0x91B4, 0x61D8, 0x91B5, 0x61D9, 0x91B6, 0x61DA, 0x91B7, 0x61DB, + 0x91B8, 0x61DC, 0x91B9, 0x61DD, 0x91BA, 0x61DE, 0x91BB, 0x61DF, 0x91BC, 0x61E0, 0x91BD, 0x61E1, 0x91BE, 0x61E2, 0x91BF, 0x61E3, + 0x91C0, 0x61E4, 0x91C1, 0x61E5, 0x91C2, 0x61E7, 0x91C3, 0x61E8, 0x91C4, 0x61E9, 0x91C5, 0x61EA, 0x91C6, 0x61EB, 0x91C7, 0x61EC, + 0x91C8, 0x61ED, 0x91C9, 0x61EE, 0x91CA, 0x61EF, 0x91CB, 0x61F0, 0x91CC, 0x61F1, 0x91CD, 0x61F2, 0x91CE, 0x61F3, 0x91CF, 0x61F4, + 0x91D0, 0x61F6, 0x91D1, 0x61F7, 0x91D2, 0x61F8, 0x91D3, 0x61F9, 0x91D4, 0x61FA, 0x91D5, 0x61FB, 0x91D6, 0x61FC, 0x91D7, 0x61FD, + 0x91D8, 0x61FE, 0x91D9, 0x6200, 0x91DA, 0x6201, 0x91DB, 0x6202, 0x91DC, 0x6203, 0x91DD, 0x6204, 0x91DE, 0x6205, 0x91DF, 0x6207, + 0x91E0, 0x6209, 0x91E1, 0x6213, 0x91E2, 0x6214, 0x91E3, 0x6219, 0x91E4, 0x621C, 0x91E5, 0x621D, 0x91E6, 0x621E, 0x91E7, 0x6220, + 0x91E8, 0x6223, 0x91E9, 0x6226, 0x91EA, 0x6227, 0x91EB, 0x6228, 0x91EC, 0x6229, 0x91ED, 0x622B, 0x91EE, 0x622D, 0x91EF, 0x622F, + 0x91F0, 0x6230, 0x91F1, 0x6231, 0x91F2, 0x6232, 0x91F3, 0x6235, 0x91F4, 0x6236, 0x91F5, 0x6238, 0x91F6, 0x6239, 0x91F7, 0x623A, + 0x91F8, 0x623B, 0x91F9, 0x623C, 0x91FA, 0x6242, 0x91FB, 0x6244, 0x91FC, 0x6245, 0x91FD, 0x6246, 0x91FE, 0x624A, 0x9240, 0x624F, + 0x9241, 0x6250, 0x9242, 0x6255, 0x9243, 0x6256, 0x9244, 0x6257, 0x9245, 0x6259, 0x9246, 0x625A, 0x9247, 0x625C, 0x9248, 0x625D, + 0x9249, 0x625E, 0x924A, 0x625F, 0x924B, 0x6260, 0x924C, 0x6261, 0x924D, 0x6262, 0x924E, 0x6264, 0x924F, 0x6265, 0x9250, 0x6268, + 0x9251, 0x6271, 0x9252, 0x6272, 0x9253, 0x6274, 0x9254, 0x6275, 0x9255, 0x6277, 0x9256, 0x6278, 0x9257, 0x627A, 0x9258, 0x627B, + 0x9259, 0x627D, 0x925A, 0x6281, 0x925B, 0x6282, 0x925C, 0x6283, 0x925D, 0x6285, 0x925E, 0x6286, 0x925F, 0x6287, 0x9260, 0x6288, + 0x9261, 0x628B, 0x9262, 0x628C, 0x9263, 0x628D, 0x9264, 0x628E, 0x9265, 0x628F, 0x9266, 0x6290, 0x9267, 0x6294, 0x9268, 0x6299, + 0x9269, 0x629C, 0x926A, 0x629D, 0x926B, 0x629E, 0x926C, 0x62A3, 0x926D, 0x62A6, 0x926E, 0x62A7, 0x926F, 0x62A9, 0x9270, 0x62AA, + 0x9271, 0x62AD, 0x9272, 0x62AE, 0x9273, 0x62AF, 0x9274, 0x62B0, 0x9275, 0x62B2, 0x9276, 0x62B3, 0x9277, 0x62B4, 0x9278, 0x62B6, + 0x9279, 0x62B7, 0x927A, 0x62B8, 0x927B, 0x62BA, 0x927C, 0x62BE, 0x927D, 0x62C0, 0x927E, 0x62C1, 0x9280, 0x62C3, 0x9281, 0x62CB, + 0x9282, 0x62CF, 0x9283, 0x62D1, 0x9284, 0x62D5, 0x9285, 0x62DD, 0x9286, 0x62DE, 0x9287, 0x62E0, 0x9288, 0x62E1, 0x9289, 0x62E4, + 0x928A, 0x62EA, 0x928B, 0x62EB, 0x928C, 0x62F0, 0x928D, 0x62F2, 0x928E, 0x62F5, 0x928F, 0x62F8, 0x9290, 0x62F9, 0x9291, 0x62FA, + 0x9292, 0x62FB, 0x9293, 0x6300, 0x9294, 0x6303, 0x9295, 0x6304, 0x9296, 0x6305, 0x9297, 0x6306, 0x9298, 0x630A, 0x9299, 0x630B, + 0x929A, 0x630C, 0x929B, 0x630D, 0x929C, 0x630F, 0x929D, 0x6310, 0x929E, 0x6312, 0x929F, 0x6313, 0x92A0, 0x6314, 0x92A1, 0x6315, + 0x92A2, 0x6317, 0x92A3, 0x6318, 0x92A4, 0x6319, 0x92A5, 0x631C, 0x92A6, 0x6326, 0x92A7, 0x6327, 0x92A8, 0x6329, 0x92A9, 0x632C, + 0x92AA, 0x632D, 0x92AB, 0x632E, 0x92AC, 0x6330, 0x92AD, 0x6331, 0x92AE, 0x6333, 0x92AF, 0x6334, 0x92B0, 0x6335, 0x92B1, 0x6336, + 0x92B2, 0x6337, 0x92B3, 0x6338, 0x92B4, 0x633B, 0x92B5, 0x633C, 0x92B6, 0x633E, 0x92B7, 0x633F, 0x92B8, 0x6340, 0x92B9, 0x6341, + 0x92BA, 0x6344, 0x92BB, 0x6347, 0x92BC, 0x6348, 0x92BD, 0x634A, 0x92BE, 0x6351, 0x92BF, 0x6352, 0x92C0, 0x6353, 0x92C1, 0x6354, + 0x92C2, 0x6356, 0x92C3, 0x6357, 0x92C4, 0x6358, 0x92C5, 0x6359, 0x92C6, 0x635A, 0x92C7, 0x635B, 0x92C8, 0x635C, 0x92C9, 0x635D, + 0x92CA, 0x6360, 0x92CB, 0x6364, 0x92CC, 0x6365, 0x92CD, 0x6366, 0x92CE, 0x6368, 0x92CF, 0x636A, 0x92D0, 0x636B, 0x92D1, 0x636C, + 0x92D2, 0x636F, 0x92D3, 0x6370, 0x92D4, 0x6372, 0x92D5, 0x6373, 0x92D6, 0x6374, 0x92D7, 0x6375, 0x92D8, 0x6378, 0x92D9, 0x6379, + 0x92DA, 0x637C, 0x92DB, 0x637D, 0x92DC, 0x637E, 0x92DD, 0x637F, 0x92DE, 0x6381, 0x92DF, 0x6383, 0x92E0, 0x6384, 0x92E1, 0x6385, + 0x92E2, 0x6386, 0x92E3, 0x638B, 0x92E4, 0x638D, 0x92E5, 0x6391, 0x92E6, 0x6393, 0x92E7, 0x6394, 0x92E8, 0x6395, 0x92E9, 0x6397, + 0x92EA, 0x6399, 0x92EB, 0x639A, 0x92EC, 0x639B, 0x92ED, 0x639C, 0x92EE, 0x639D, 0x92EF, 0x639E, 0x92F0, 0x639F, 0x92F1, 0x63A1, + 0x92F2, 0x63A4, 0x92F3, 0x63A6, 0x92F4, 0x63AB, 0x92F5, 0x63AF, 0x92F6, 0x63B1, 0x92F7, 0x63B2, 0x92F8, 0x63B5, 0x92F9, 0x63B6, + 0x92FA, 0x63B9, 0x92FB, 0x63BB, 0x92FC, 0x63BD, 0x92FD, 0x63BF, 0x92FE, 0x63C0, 0x9340, 0x63C1, 0x9341, 0x63C2, 0x9342, 0x63C3, + 0x9343, 0x63C5, 0x9344, 0x63C7, 0x9345, 0x63C8, 0x9346, 0x63CA, 0x9347, 0x63CB, 0x9348, 0x63CC, 0x9349, 0x63D1, 0x934A, 0x63D3, + 0x934B, 0x63D4, 0x934C, 0x63D5, 0x934D, 0x63D7, 0x934E, 0x63D8, 0x934F, 0x63D9, 0x9350, 0x63DA, 0x9351, 0x63DB, 0x9352, 0x63DC, + 0x9353, 0x63DD, 0x9354, 0x63DF, 0x9355, 0x63E2, 0x9356, 0x63E4, 0x9357, 0x63E5, 0x9358, 0x63E6, 0x9359, 0x63E7, 0x935A, 0x63E8, + 0x935B, 0x63EB, 0x935C, 0x63EC, 0x935D, 0x63EE, 0x935E, 0x63EF, 0x935F, 0x63F0, 0x9360, 0x63F1, 0x9361, 0x63F3, 0x9362, 0x63F5, + 0x9363, 0x63F7, 0x9364, 0x63F9, 0x9365, 0x63FA, 0x9366, 0x63FB, 0x9367, 0x63FC, 0x9368, 0x63FE, 0x9369, 0x6403, 0x936A, 0x6404, + 0x936B, 0x6406, 0x936C, 0x6407, 0x936D, 0x6408, 0x936E, 0x6409, 0x936F, 0x640A, 0x9370, 0x640D, 0x9371, 0x640E, 0x9372, 0x6411, + 0x9373, 0x6412, 0x9374, 0x6415, 0x9375, 0x6416, 0x9376, 0x6417, 0x9377, 0x6418, 0x9378, 0x6419, 0x9379, 0x641A, 0x937A, 0x641D, + 0x937B, 0x641F, 0x937C, 0x6422, 0x937D, 0x6423, 0x937E, 0x6424, 0x9380, 0x6425, 0x9381, 0x6427, 0x9382, 0x6428, 0x9383, 0x6429, + 0x9384, 0x642B, 0x9385, 0x642E, 0x9386, 0x642F, 0x9387, 0x6430, 0x9388, 0x6431, 0x9389, 0x6432, 0x938A, 0x6433, 0x938B, 0x6435, + 0x938C, 0x6436, 0x938D, 0x6437, 0x938E, 0x6438, 0x938F, 0x6439, 0x9390, 0x643B, 0x9391, 0x643C, 0x9392, 0x643E, 0x9393, 0x6440, + 0x9394, 0x6442, 0x9395, 0x6443, 0x9396, 0x6449, 0x9397, 0x644B, 0x9398, 0x644C, 0x9399, 0x644D, 0x939A, 0x644E, 0x939B, 0x644F, + 0x939C, 0x6450, 0x939D, 0x6451, 0x939E, 0x6453, 0x939F, 0x6455, 0x93A0, 0x6456, 0x93A1, 0x6457, 0x93A2, 0x6459, 0x93A3, 0x645A, + 0x93A4, 0x645B, 0x93A5, 0x645C, 0x93A6, 0x645D, 0x93A7, 0x645F, 0x93A8, 0x6460, 0x93A9, 0x6461, 0x93AA, 0x6462, 0x93AB, 0x6463, + 0x93AC, 0x6464, 0x93AD, 0x6465, 0x93AE, 0x6466, 0x93AF, 0x6468, 0x93B0, 0x646A, 0x93B1, 0x646B, 0x93B2, 0x646C, 0x93B3, 0x646E, + 0x93B4, 0x646F, 0x93B5, 0x6470, 0x93B6, 0x6471, 0x93B7, 0x6472, 0x93B8, 0x6473, 0x93B9, 0x6474, 0x93BA, 0x6475, 0x93BB, 0x6476, + 0x93BC, 0x6477, 0x93BD, 0x647B, 0x93BE, 0x647C, 0x93BF, 0x647D, 0x93C0, 0x647E, 0x93C1, 0x647F, 0x93C2, 0x6480, 0x93C3, 0x6481, + 0x93C4, 0x6483, 0x93C5, 0x6486, 0x93C6, 0x6488, 0x93C7, 0x6489, 0x93C8, 0x648A, 0x93C9, 0x648B, 0x93CA, 0x648C, 0x93CB, 0x648D, + 0x93CC, 0x648E, 0x93CD, 0x648F, 0x93CE, 0x6490, 0x93CF, 0x6493, 0x93D0, 0x6494, 0x93D1, 0x6497, 0x93D2, 0x6498, 0x93D3, 0x649A, + 0x93D4, 0x649B, 0x93D5, 0x649C, 0x93D6, 0x649D, 0x93D7, 0x649F, 0x93D8, 0x64A0, 0x93D9, 0x64A1, 0x93DA, 0x64A2, 0x93DB, 0x64A3, + 0x93DC, 0x64A5, 0x93DD, 0x64A6, 0x93DE, 0x64A7, 0x93DF, 0x64A8, 0x93E0, 0x64AA, 0x93E1, 0x64AB, 0x93E2, 0x64AF, 0x93E3, 0x64B1, + 0x93E4, 0x64B2, 0x93E5, 0x64B3, 0x93E6, 0x64B4, 0x93E7, 0x64B6, 0x93E8, 0x64B9, 0x93E9, 0x64BB, 0x93EA, 0x64BD, 0x93EB, 0x64BE, + 0x93EC, 0x64BF, 0x93ED, 0x64C1, 0x93EE, 0x64C3, 0x93EF, 0x64C4, 0x93F0, 0x64C6, 0x93F1, 0x64C7, 0x93F2, 0x64C8, 0x93F3, 0x64C9, + 0x93F4, 0x64CA, 0x93F5, 0x64CB, 0x93F6, 0x64CC, 0x93F7, 0x64CF, 0x93F8, 0x64D1, 0x93F9, 0x64D3, 0x93FA, 0x64D4, 0x93FB, 0x64D5, + 0x93FC, 0x64D6, 0x93FD, 0x64D9, 0x93FE, 0x64DA, 0x9440, 0x64DB, 0x9441, 0x64DC, 0x9442, 0x64DD, 0x9443, 0x64DF, 0x9444, 0x64E0, + 0x9445, 0x64E1, 0x9446, 0x64E3, 0x9447, 0x64E5, 0x9448, 0x64E7, 0x9449, 0x64E8, 0x944A, 0x64E9, 0x944B, 0x64EA, 0x944C, 0x64EB, + 0x944D, 0x64EC, 0x944E, 0x64ED, 0x944F, 0x64EE, 0x9450, 0x64EF, 0x9451, 0x64F0, 0x9452, 0x64F1, 0x9453, 0x64F2, 0x9454, 0x64F3, + 0x9455, 0x64F4, 0x9456, 0x64F5, 0x9457, 0x64F6, 0x9458, 0x64F7, 0x9459, 0x64F8, 0x945A, 0x64F9, 0x945B, 0x64FA, 0x945C, 0x64FB, + 0x945D, 0x64FC, 0x945E, 0x64FD, 0x945F, 0x64FE, 0x9460, 0x64FF, 0x9461, 0x6501, 0x9462, 0x6502, 0x9463, 0x6503, 0x9464, 0x6504, + 0x9465, 0x6505, 0x9466, 0x6506, 0x9467, 0x6507, 0x9468, 0x6508, 0x9469, 0x650A, 0x946A, 0x650B, 0x946B, 0x650C, 0x946C, 0x650D, + 0x946D, 0x650E, 0x946E, 0x650F, 0x946F, 0x6510, 0x9470, 0x6511, 0x9471, 0x6513, 0x9472, 0x6514, 0x9473, 0x6515, 0x9474, 0x6516, + 0x9475, 0x6517, 0x9476, 0x6519, 0x9477, 0x651A, 0x9478, 0x651B, 0x9479, 0x651C, 0x947A, 0x651D, 0x947B, 0x651E, 0x947C, 0x651F, + 0x947D, 0x6520, 0x947E, 0x6521, 0x9480, 0x6522, 0x9481, 0x6523, 0x9482, 0x6524, 0x9483, 0x6526, 0x9484, 0x6527, 0x9485, 0x6528, + 0x9486, 0x6529, 0x9487, 0x652A, 0x9488, 0x652C, 0x9489, 0x652D, 0x948A, 0x6530, 0x948B, 0x6531, 0x948C, 0x6532, 0x948D, 0x6533, + 0x948E, 0x6537, 0x948F, 0x653A, 0x9490, 0x653C, 0x9491, 0x653D, 0x9492, 0x6540, 0x9493, 0x6541, 0x9494, 0x6542, 0x9495, 0x6543, + 0x9496, 0x6544, 0x9497, 0x6546, 0x9498, 0x6547, 0x9499, 0x654A, 0x949A, 0x654B, 0x949B, 0x654D, 0x949C, 0x654E, 0x949D, 0x6550, + 0x949E, 0x6552, 0x949F, 0x6553, 0x94A0, 0x6554, 0x94A1, 0x6557, 0x94A2, 0x6558, 0x94A3, 0x655A, 0x94A4, 0x655C, 0x94A5, 0x655F, + 0x94A6, 0x6560, 0x94A7, 0x6561, 0x94A8, 0x6564, 0x94A9, 0x6565, 0x94AA, 0x6567, 0x94AB, 0x6568, 0x94AC, 0x6569, 0x94AD, 0x656A, + 0x94AE, 0x656D, 0x94AF, 0x656E, 0x94B0, 0x656F, 0x94B1, 0x6571, 0x94B2, 0x6573, 0x94B3, 0x6575, 0x94B4, 0x6576, 0x94B5, 0x6578, + 0x94B6, 0x6579, 0x94B7, 0x657A, 0x94B8, 0x657B, 0x94B9, 0x657C, 0x94BA, 0x657D, 0x94BB, 0x657E, 0x94BC, 0x657F, 0x94BD, 0x6580, + 0x94BE, 0x6581, 0x94BF, 0x6582, 0x94C0, 0x6583, 0x94C1, 0x6584, 0x94C2, 0x6585, 0x94C3, 0x6586, 0x94C4, 0x6588, 0x94C5, 0x6589, + 0x94C6, 0x658A, 0x94C7, 0x658D, 0x94C8, 0x658E, 0x94C9, 0x658F, 0x94CA, 0x6592, 0x94CB, 0x6594, 0x94CC, 0x6595, 0x94CD, 0x6596, + 0x94CE, 0x6598, 0x94CF, 0x659A, 0x94D0, 0x659D, 0x94D1, 0x659E, 0x94D2, 0x65A0, 0x94D3, 0x65A2, 0x94D4, 0x65A3, 0x94D5, 0x65A6, + 0x94D6, 0x65A8, 0x94D7, 0x65AA, 0x94D8, 0x65AC, 0x94D9, 0x65AE, 0x94DA, 0x65B1, 0x94DB, 0x65B2, 0x94DC, 0x65B3, 0x94DD, 0x65B4, + 0x94DE, 0x65B5, 0x94DF, 0x65B6, 0x94E0, 0x65B7, 0x94E1, 0x65B8, 0x94E2, 0x65BA, 0x94E3, 0x65BB, 0x94E4, 0x65BE, 0x94E5, 0x65BF, + 0x94E6, 0x65C0, 0x94E7, 0x65C2, 0x94E8, 0x65C7, 0x94E9, 0x65C8, 0x94EA, 0x65C9, 0x94EB, 0x65CA, 0x94EC, 0x65CD, 0x94ED, 0x65D0, + 0x94EE, 0x65D1, 0x94EF, 0x65D3, 0x94F0, 0x65D4, 0x94F1, 0x65D5, 0x94F2, 0x65D8, 0x94F3, 0x65D9, 0x94F4, 0x65DA, 0x94F5, 0x65DB, + 0x94F6, 0x65DC, 0x94F7, 0x65DD, 0x94F8, 0x65DE, 0x94F9, 0x65DF, 0x94FA, 0x65E1, 0x94FB, 0x65E3, 0x94FC, 0x65E4, 0x94FD, 0x65EA, + 0x94FE, 0x65EB, 0x9540, 0x65F2, 0x9541, 0x65F3, 0x9542, 0x65F4, 0x9543, 0x65F5, 0x9544, 0x65F8, 0x9545, 0x65F9, 0x9546, 0x65FB, + 0x9547, 0x65FC, 0x9548, 0x65FD, 0x9549, 0x65FE, 0x954A, 0x65FF, 0x954B, 0x6601, 0x954C, 0x6604, 0x954D, 0x6605, 0x954E, 0x6607, + 0x954F, 0x6608, 0x9550, 0x6609, 0x9551, 0x660B, 0x9552, 0x660D, 0x9553, 0x6610, 0x9554, 0x6611, 0x9555, 0x6612, 0x9556, 0x6616, + 0x9557, 0x6617, 0x9558, 0x6618, 0x9559, 0x661A, 0x955A, 0x661B, 0x955B, 0x661C, 0x955C, 0x661E, 0x955D, 0x6621, 0x955E, 0x6622, + 0x955F, 0x6623, 0x9560, 0x6624, 0x9561, 0x6626, 0x9562, 0x6629, 0x9563, 0x662A, 0x9564, 0x662B, 0x9565, 0x662C, 0x9566, 0x662E, + 0x9567, 0x6630, 0x9568, 0x6632, 0x9569, 0x6633, 0x956A, 0x6637, 0x956B, 0x6638, 0x956C, 0x6639, 0x956D, 0x663A, 0x956E, 0x663B, + 0x956F, 0x663D, 0x9570, 0x663F, 0x9571, 0x6640, 0x9572, 0x6642, 0x9573, 0x6644, 0x9574, 0x6645, 0x9575, 0x6646, 0x9576, 0x6647, + 0x9577, 0x6648, 0x9578, 0x6649, 0x9579, 0x664A, 0x957A, 0x664D, 0x957B, 0x664E, 0x957C, 0x6650, 0x957D, 0x6651, 0x957E, 0x6658, + 0x9580, 0x6659, 0x9581, 0x665B, 0x9582, 0x665C, 0x9583, 0x665D, 0x9584, 0x665E, 0x9585, 0x6660, 0x9586, 0x6662, 0x9587, 0x6663, + 0x9588, 0x6665, 0x9589, 0x6667, 0x958A, 0x6669, 0x958B, 0x666A, 0x958C, 0x666B, 0x958D, 0x666C, 0x958E, 0x666D, 0x958F, 0x6671, + 0x9590, 0x6672, 0x9591, 0x6673, 0x9592, 0x6675, 0x9593, 0x6678, 0x9594, 0x6679, 0x9595, 0x667B, 0x9596, 0x667C, 0x9597, 0x667D, + 0x9598, 0x667F, 0x9599, 0x6680, 0x959A, 0x6681, 0x959B, 0x6683, 0x959C, 0x6685, 0x959D, 0x6686, 0x959E, 0x6688, 0x959F, 0x6689, + 0x95A0, 0x668A, 0x95A1, 0x668B, 0x95A2, 0x668D, 0x95A3, 0x668E, 0x95A4, 0x668F, 0x95A5, 0x6690, 0x95A6, 0x6692, 0x95A7, 0x6693, + 0x95A8, 0x6694, 0x95A9, 0x6695, 0x95AA, 0x6698, 0x95AB, 0x6699, 0x95AC, 0x669A, 0x95AD, 0x669B, 0x95AE, 0x669C, 0x95AF, 0x669E, + 0x95B0, 0x669F, 0x95B1, 0x66A0, 0x95B2, 0x66A1, 0x95B3, 0x66A2, 0x95B4, 0x66A3, 0x95B5, 0x66A4, 0x95B6, 0x66A5, 0x95B7, 0x66A6, + 0x95B8, 0x66A9, 0x95B9, 0x66AA, 0x95BA, 0x66AB, 0x95BB, 0x66AC, 0x95BC, 0x66AD, 0x95BD, 0x66AF, 0x95BE, 0x66B0, 0x95BF, 0x66B1, + 0x95C0, 0x66B2, 0x95C1, 0x66B3, 0x95C2, 0x66B5, 0x95C3, 0x66B6, 0x95C4, 0x66B7, 0x95C5, 0x66B8, 0x95C6, 0x66BA, 0x95C7, 0x66BB, + 0x95C8, 0x66BC, 0x95C9, 0x66BD, 0x95CA, 0x66BF, 0x95CB, 0x66C0, 0x95CC, 0x66C1, 0x95CD, 0x66C2, 0x95CE, 0x66C3, 0x95CF, 0x66C4, + 0x95D0, 0x66C5, 0x95D1, 0x66C6, 0x95D2, 0x66C7, 0x95D3, 0x66C8, 0x95D4, 0x66C9, 0x95D5, 0x66CA, 0x95D6, 0x66CB, 0x95D7, 0x66CC, + 0x95D8, 0x66CD, 0x95D9, 0x66CE, 0x95DA, 0x66CF, 0x95DB, 0x66D0, 0x95DC, 0x66D1, 0x95DD, 0x66D2, 0x95DE, 0x66D3, 0x95DF, 0x66D4, + 0x95E0, 0x66D5, 0x95E1, 0x66D6, 0x95E2, 0x66D7, 0x95E3, 0x66D8, 0x95E4, 0x66DA, 0x95E5, 0x66DE, 0x95E6, 0x66DF, 0x95E7, 0x66E0, + 0x95E8, 0x66E1, 0x95E9, 0x66E2, 0x95EA, 0x66E3, 0x95EB, 0x66E4, 0x95EC, 0x66E5, 0x95ED, 0x66E7, 0x95EE, 0x66E8, 0x95EF, 0x66EA, + 0x95F0, 0x66EB, 0x95F1, 0x66EC, 0x95F2, 0x66ED, 0x95F3, 0x66EE, 0x95F4, 0x66EF, 0x95F5, 0x66F1, 0x95F6, 0x66F5, 0x95F7, 0x66F6, + 0x95F8, 0x66F8, 0x95F9, 0x66FA, 0x95FA, 0x66FB, 0x95FB, 0x66FD, 0x95FC, 0x6701, 0x95FD, 0x6702, 0x95FE, 0x6703, 0x9640, 0x6704, + 0x9641, 0x6705, 0x9642, 0x6706, 0x9643, 0x6707, 0x9644, 0x670C, 0x9645, 0x670E, 0x9646, 0x670F, 0x9647, 0x6711, 0x9648, 0x6712, + 0x9649, 0x6713, 0x964A, 0x6716, 0x964B, 0x6718, 0x964C, 0x6719, 0x964D, 0x671A, 0x964E, 0x671C, 0x964F, 0x671E, 0x9650, 0x6720, + 0x9651, 0x6721, 0x9652, 0x6722, 0x9653, 0x6723, 0x9654, 0x6724, 0x9655, 0x6725, 0x9656, 0x6727, 0x9657, 0x6729, 0x9658, 0x672E, + 0x9659, 0x6730, 0x965A, 0x6732, 0x965B, 0x6733, 0x965C, 0x6736, 0x965D, 0x6737, 0x965E, 0x6738, 0x965F, 0x6739, 0x9660, 0x673B, + 0x9661, 0x673C, 0x9662, 0x673E, 0x9663, 0x673F, 0x9664, 0x6741, 0x9665, 0x6744, 0x9666, 0x6745, 0x9667, 0x6747, 0x9668, 0x674A, + 0x9669, 0x674B, 0x966A, 0x674D, 0x966B, 0x6752, 0x966C, 0x6754, 0x966D, 0x6755, 0x966E, 0x6757, 0x966F, 0x6758, 0x9670, 0x6759, + 0x9671, 0x675A, 0x9672, 0x675B, 0x9673, 0x675D, 0x9674, 0x6762, 0x9675, 0x6763, 0x9676, 0x6764, 0x9677, 0x6766, 0x9678, 0x6767, + 0x9679, 0x676B, 0x967A, 0x676C, 0x967B, 0x676E, 0x967C, 0x6771, 0x967D, 0x6774, 0x967E, 0x6776, 0x9680, 0x6778, 0x9681, 0x6779, + 0x9682, 0x677A, 0x9683, 0x677B, 0x9684, 0x677D, 0x9685, 0x6780, 0x9686, 0x6782, 0x9687, 0x6783, 0x9688, 0x6785, 0x9689, 0x6786, + 0x968A, 0x6788, 0x968B, 0x678A, 0x968C, 0x678C, 0x968D, 0x678D, 0x968E, 0x678E, 0x968F, 0x678F, 0x9690, 0x6791, 0x9691, 0x6792, + 0x9692, 0x6793, 0x9693, 0x6794, 0x9694, 0x6796, 0x9695, 0x6799, 0x9696, 0x679B, 0x9697, 0x679F, 0x9698, 0x67A0, 0x9699, 0x67A1, + 0x969A, 0x67A4, 0x969B, 0x67A6, 0x969C, 0x67A9, 0x969D, 0x67AC, 0x969E, 0x67AE, 0x969F, 0x67B1, 0x96A0, 0x67B2, 0x96A1, 0x67B4, + 0x96A2, 0x67B9, 0x96A3, 0x67BA, 0x96A4, 0x67BB, 0x96A5, 0x67BC, 0x96A6, 0x67BD, 0x96A7, 0x67BE, 0x96A8, 0x67BF, 0x96A9, 0x67C0, + 0x96AA, 0x67C2, 0x96AB, 0x67C5, 0x96AC, 0x67C6, 0x96AD, 0x67C7, 0x96AE, 0x67C8, 0x96AF, 0x67C9, 0x96B0, 0x67CA, 0x96B1, 0x67CB, + 0x96B2, 0x67CC, 0x96B3, 0x67CD, 0x96B4, 0x67CE, 0x96B5, 0x67D5, 0x96B6, 0x67D6, 0x96B7, 0x67D7, 0x96B8, 0x67DB, 0x96B9, 0x67DF, + 0x96BA, 0x67E1, 0x96BB, 0x67E3, 0x96BC, 0x67E4, 0x96BD, 0x67E6, 0x96BE, 0x67E7, 0x96BF, 0x67E8, 0x96C0, 0x67EA, 0x96C1, 0x67EB, + 0x96C2, 0x67ED, 0x96C3, 0x67EE, 0x96C4, 0x67F2, 0x96C5, 0x67F5, 0x96C6, 0x67F6, 0x96C7, 0x67F7, 0x96C8, 0x67F8, 0x96C9, 0x67F9, + 0x96CA, 0x67FA, 0x96CB, 0x67FB, 0x96CC, 0x67FC, 0x96CD, 0x67FE, 0x96CE, 0x6801, 0x96CF, 0x6802, 0x96D0, 0x6803, 0x96D1, 0x6804, + 0x96D2, 0x6806, 0x96D3, 0x680D, 0x96D4, 0x6810, 0x96D5, 0x6812, 0x96D6, 0x6814, 0x96D7, 0x6815, 0x96D8, 0x6818, 0x96D9, 0x6819, + 0x96DA, 0x681A, 0x96DB, 0x681B, 0x96DC, 0x681C, 0x96DD, 0x681E, 0x96DE, 0x681F, 0x96DF, 0x6820, 0x96E0, 0x6822, 0x96E1, 0x6823, + 0x96E2, 0x6824, 0x96E3, 0x6825, 0x96E4, 0x6826, 0x96E5, 0x6827, 0x96E6, 0x6828, 0x96E7, 0x682B, 0x96E8, 0x682C, 0x96E9, 0x682D, + 0x96EA, 0x682E, 0x96EB, 0x682F, 0x96EC, 0x6830, 0x96ED, 0x6831, 0x96EE, 0x6834, 0x96EF, 0x6835, 0x96F0, 0x6836, 0x96F1, 0x683A, + 0x96F2, 0x683B, 0x96F3, 0x683F, 0x96F4, 0x6847, 0x96F5, 0x684B, 0x96F6, 0x684D, 0x96F7, 0x684F, 0x96F8, 0x6852, 0x96F9, 0x6856, + 0x96FA, 0x6857, 0x96FB, 0x6858, 0x96FC, 0x6859, 0x96FD, 0x685A, 0x96FE, 0x685B, 0x9740, 0x685C, 0x9741, 0x685D, 0x9742, 0x685E, + 0x9743, 0x685F, 0x9744, 0x686A, 0x9745, 0x686C, 0x9746, 0x686D, 0x9747, 0x686E, 0x9748, 0x686F, 0x9749, 0x6870, 0x974A, 0x6871, + 0x974B, 0x6872, 0x974C, 0x6873, 0x974D, 0x6875, 0x974E, 0x6878, 0x974F, 0x6879, 0x9750, 0x687A, 0x9751, 0x687B, 0x9752, 0x687C, + 0x9753, 0x687D, 0x9754, 0x687E, 0x9755, 0x687F, 0x9756, 0x6880, 0x9757, 0x6882, 0x9758, 0x6884, 0x9759, 0x6887, 0x975A, 0x6888, + 0x975B, 0x6889, 0x975C, 0x688A, 0x975D, 0x688B, 0x975E, 0x688C, 0x975F, 0x688D, 0x9760, 0x688E, 0x9761, 0x6890, 0x9762, 0x6891, + 0x9763, 0x6892, 0x9764, 0x6894, 0x9765, 0x6895, 0x9766, 0x6896, 0x9767, 0x6898, 0x9768, 0x6899, 0x9769, 0x689A, 0x976A, 0x689B, + 0x976B, 0x689C, 0x976C, 0x689D, 0x976D, 0x689E, 0x976E, 0x689F, 0x976F, 0x68A0, 0x9770, 0x68A1, 0x9771, 0x68A3, 0x9772, 0x68A4, + 0x9773, 0x68A5, 0x9774, 0x68A9, 0x9775, 0x68AA, 0x9776, 0x68AB, 0x9777, 0x68AC, 0x9778, 0x68AE, 0x9779, 0x68B1, 0x977A, 0x68B2, + 0x977B, 0x68B4, 0x977C, 0x68B6, 0x977D, 0x68B7, 0x977E, 0x68B8, 0x9780, 0x68B9, 0x9781, 0x68BA, 0x9782, 0x68BB, 0x9783, 0x68BC, + 0x9784, 0x68BD, 0x9785, 0x68BE, 0x9786, 0x68BF, 0x9787, 0x68C1, 0x9788, 0x68C3, 0x9789, 0x68C4, 0x978A, 0x68C5, 0x978B, 0x68C6, + 0x978C, 0x68C7, 0x978D, 0x68C8, 0x978E, 0x68CA, 0x978F, 0x68CC, 0x9790, 0x68CE, 0x9791, 0x68CF, 0x9792, 0x68D0, 0x9793, 0x68D1, + 0x9794, 0x68D3, 0x9795, 0x68D4, 0x9796, 0x68D6, 0x9797, 0x68D7, 0x9798, 0x68D9, 0x9799, 0x68DB, 0x979A, 0x68DC, 0x979B, 0x68DD, + 0x979C, 0x68DE, 0x979D, 0x68DF, 0x979E, 0x68E1, 0x979F, 0x68E2, 0x97A0, 0x68E4, 0x97A1, 0x68E5, 0x97A2, 0x68E6, 0x97A3, 0x68E7, + 0x97A4, 0x68E8, 0x97A5, 0x68E9, 0x97A6, 0x68EA, 0x97A7, 0x68EB, 0x97A8, 0x68EC, 0x97A9, 0x68ED, 0x97AA, 0x68EF, 0x97AB, 0x68F2, + 0x97AC, 0x68F3, 0x97AD, 0x68F4, 0x97AE, 0x68F6, 0x97AF, 0x68F7, 0x97B0, 0x68F8, 0x97B1, 0x68FB, 0x97B2, 0x68FD, 0x97B3, 0x68FE, + 0x97B4, 0x68FF, 0x97B5, 0x6900, 0x97B6, 0x6902, 0x97B7, 0x6903, 0x97B8, 0x6904, 0x97B9, 0x6906, 0x97BA, 0x6907, 0x97BB, 0x6908, + 0x97BC, 0x6909, 0x97BD, 0x690A, 0x97BE, 0x690C, 0x97BF, 0x690F, 0x97C0, 0x6911, 0x97C1, 0x6913, 0x97C2, 0x6914, 0x97C3, 0x6915, + 0x97C4, 0x6916, 0x97C5, 0x6917, 0x97C6, 0x6918, 0x97C7, 0x6919, 0x97C8, 0x691A, 0x97C9, 0x691B, 0x97CA, 0x691C, 0x97CB, 0x691D, + 0x97CC, 0x691E, 0x97CD, 0x6921, 0x97CE, 0x6922, 0x97CF, 0x6923, 0x97D0, 0x6925, 0x97D1, 0x6926, 0x97D2, 0x6927, 0x97D3, 0x6928, + 0x97D4, 0x6929, 0x97D5, 0x692A, 0x97D6, 0x692B, 0x97D7, 0x692C, 0x97D8, 0x692E, 0x97D9, 0x692F, 0x97DA, 0x6931, 0x97DB, 0x6932, + 0x97DC, 0x6933, 0x97DD, 0x6935, 0x97DE, 0x6936, 0x97DF, 0x6937, 0x97E0, 0x6938, 0x97E1, 0x693A, 0x97E2, 0x693B, 0x97E3, 0x693C, + 0x97E4, 0x693E, 0x97E5, 0x6940, 0x97E6, 0x6941, 0x97E7, 0x6943, 0x97E8, 0x6944, 0x97E9, 0x6945, 0x97EA, 0x6946, 0x97EB, 0x6947, + 0x97EC, 0x6948, 0x97ED, 0x6949, 0x97EE, 0x694A, 0x97EF, 0x694B, 0x97F0, 0x694C, 0x97F1, 0x694D, 0x97F2, 0x694E, 0x97F3, 0x694F, + 0x97F4, 0x6950, 0x97F5, 0x6951, 0x97F6, 0x6952, 0x97F7, 0x6953, 0x97F8, 0x6955, 0x97F9, 0x6956, 0x97FA, 0x6958, 0x97FB, 0x6959, + 0x97FC, 0x695B, 0x97FD, 0x695C, 0x97FE, 0x695F, 0x9840, 0x6961, 0x9841, 0x6962, 0x9842, 0x6964, 0x9843, 0x6965, 0x9844, 0x6967, + 0x9845, 0x6968, 0x9846, 0x6969, 0x9847, 0x696A, 0x9848, 0x696C, 0x9849, 0x696D, 0x984A, 0x696F, 0x984B, 0x6970, 0x984C, 0x6972, + 0x984D, 0x6973, 0x984E, 0x6974, 0x984F, 0x6975, 0x9850, 0x6976, 0x9851, 0x697A, 0x9852, 0x697B, 0x9853, 0x697D, 0x9854, 0x697E, + 0x9855, 0x697F, 0x9856, 0x6981, 0x9857, 0x6983, 0x9858, 0x6985, 0x9859, 0x698A, 0x985A, 0x698B, 0x985B, 0x698C, 0x985C, 0x698E, + 0x985D, 0x698F, 0x985E, 0x6990, 0x985F, 0x6991, 0x9860, 0x6992, 0x9861, 0x6993, 0x9862, 0x6996, 0x9863, 0x6997, 0x9864, 0x6999, + 0x9865, 0x699A, 0x9866, 0x699D, 0x9867, 0x699E, 0x9868, 0x699F, 0x9869, 0x69A0, 0x986A, 0x69A1, 0x986B, 0x69A2, 0x986C, 0x69A3, + 0x986D, 0x69A4, 0x986E, 0x69A5, 0x986F, 0x69A6, 0x9870, 0x69A9, 0x9871, 0x69AA, 0x9872, 0x69AC, 0x9873, 0x69AE, 0x9874, 0x69AF, + 0x9875, 0x69B0, 0x9876, 0x69B2, 0x9877, 0x69B3, 0x9878, 0x69B5, 0x9879, 0x69B6, 0x987A, 0x69B8, 0x987B, 0x69B9, 0x987C, 0x69BA, + 0x987D, 0x69BC, 0x987E, 0x69BD, 0x9880, 0x69BE, 0x9881, 0x69BF, 0x9882, 0x69C0, 0x9883, 0x69C2, 0x9884, 0x69C3, 0x9885, 0x69C4, + 0x9886, 0x69C5, 0x9887, 0x69C6, 0x9888, 0x69C7, 0x9889, 0x69C8, 0x988A, 0x69C9, 0x988B, 0x69CB, 0x988C, 0x69CD, 0x988D, 0x69CF, + 0x988E, 0x69D1, 0x988F, 0x69D2, 0x9890, 0x69D3, 0x9891, 0x69D5, 0x9892, 0x69D6, 0x9893, 0x69D7, 0x9894, 0x69D8, 0x9895, 0x69D9, + 0x9896, 0x69DA, 0x9897, 0x69DC, 0x9898, 0x69DD, 0x9899, 0x69DE, 0x989A, 0x69E1, 0x989B, 0x69E2, 0x989C, 0x69E3, 0x989D, 0x69E4, + 0x989E, 0x69E5, 0x989F, 0x69E6, 0x98A0, 0x69E7, 0x98A1, 0x69E8, 0x98A2, 0x69E9, 0x98A3, 0x69EA, 0x98A4, 0x69EB, 0x98A5, 0x69EC, + 0x98A6, 0x69EE, 0x98A7, 0x69EF, 0x98A8, 0x69F0, 0x98A9, 0x69F1, 0x98AA, 0x69F3, 0x98AB, 0x69F4, 0x98AC, 0x69F5, 0x98AD, 0x69F6, + 0x98AE, 0x69F7, 0x98AF, 0x69F8, 0x98B0, 0x69F9, 0x98B1, 0x69FA, 0x98B2, 0x69FB, 0x98B3, 0x69FC, 0x98B4, 0x69FE, 0x98B5, 0x6A00, + 0x98B6, 0x6A01, 0x98B7, 0x6A02, 0x98B8, 0x6A03, 0x98B9, 0x6A04, 0x98BA, 0x6A05, 0x98BB, 0x6A06, 0x98BC, 0x6A07, 0x98BD, 0x6A08, + 0x98BE, 0x6A09, 0x98BF, 0x6A0B, 0x98C0, 0x6A0C, 0x98C1, 0x6A0D, 0x98C2, 0x6A0E, 0x98C3, 0x6A0F, 0x98C4, 0x6A10, 0x98C5, 0x6A11, + 0x98C6, 0x6A12, 0x98C7, 0x6A13, 0x98C8, 0x6A14, 0x98C9, 0x6A15, 0x98CA, 0x6A16, 0x98CB, 0x6A19, 0x98CC, 0x6A1A, 0x98CD, 0x6A1B, + 0x98CE, 0x6A1C, 0x98CF, 0x6A1D, 0x98D0, 0x6A1E, 0x98D1, 0x6A20, 0x98D2, 0x6A22, 0x98D3, 0x6A23, 0x98D4, 0x6A24, 0x98D5, 0x6A25, + 0x98D6, 0x6A26, 0x98D7, 0x6A27, 0x98D8, 0x6A29, 0x98D9, 0x6A2B, 0x98DA, 0x6A2C, 0x98DB, 0x6A2D, 0x98DC, 0x6A2E, 0x98DD, 0x6A30, + 0x98DE, 0x6A32, 0x98DF, 0x6A33, 0x98E0, 0x6A34, 0x98E1, 0x6A36, 0x98E2, 0x6A37, 0x98E3, 0x6A38, 0x98E4, 0x6A39, 0x98E5, 0x6A3A, + 0x98E6, 0x6A3B, 0x98E7, 0x6A3C, 0x98E8, 0x6A3F, 0x98E9, 0x6A40, 0x98EA, 0x6A41, 0x98EB, 0x6A42, 0x98EC, 0x6A43, 0x98ED, 0x6A45, + 0x98EE, 0x6A46, 0x98EF, 0x6A48, 0x98F0, 0x6A49, 0x98F1, 0x6A4A, 0x98F2, 0x6A4B, 0x98F3, 0x6A4C, 0x98F4, 0x6A4D, 0x98F5, 0x6A4E, + 0x98F6, 0x6A4F, 0x98F7, 0x6A51, 0x98F8, 0x6A52, 0x98F9, 0x6A53, 0x98FA, 0x6A54, 0x98FB, 0x6A55, 0x98FC, 0x6A56, 0x98FD, 0x6A57, + 0x98FE, 0x6A5A, 0x9940, 0x6A5C, 0x9941, 0x6A5D, 0x9942, 0x6A5E, 0x9943, 0x6A5F, 0x9944, 0x6A60, 0x9945, 0x6A62, 0x9946, 0x6A63, + 0x9947, 0x6A64, 0x9948, 0x6A66, 0x9949, 0x6A67, 0x994A, 0x6A68, 0x994B, 0x6A69, 0x994C, 0x6A6A, 0x994D, 0x6A6B, 0x994E, 0x6A6C, + 0x994F, 0x6A6D, 0x9950, 0x6A6E, 0x9951, 0x6A6F, 0x9952, 0x6A70, 0x9953, 0x6A72, 0x9954, 0x6A73, 0x9955, 0x6A74, 0x9956, 0x6A75, + 0x9957, 0x6A76, 0x9958, 0x6A77, 0x9959, 0x6A78, 0x995A, 0x6A7A, 0x995B, 0x6A7B, 0x995C, 0x6A7D, 0x995D, 0x6A7E, 0x995E, 0x6A7F, + 0x995F, 0x6A81, 0x9960, 0x6A82, 0x9961, 0x6A83, 0x9962, 0x6A85, 0x9963, 0x6A86, 0x9964, 0x6A87, 0x9965, 0x6A88, 0x9966, 0x6A89, + 0x9967, 0x6A8A, 0x9968, 0x6A8B, 0x9969, 0x6A8C, 0x996A, 0x6A8D, 0x996B, 0x6A8F, 0x996C, 0x6A92, 0x996D, 0x6A93, 0x996E, 0x6A94, + 0x996F, 0x6A95, 0x9970, 0x6A96, 0x9971, 0x6A98, 0x9972, 0x6A99, 0x9973, 0x6A9A, 0x9974, 0x6A9B, 0x9975, 0x6A9C, 0x9976, 0x6A9D, + 0x9977, 0x6A9E, 0x9978, 0x6A9F, 0x9979, 0x6AA1, 0x997A, 0x6AA2, 0x997B, 0x6AA3, 0x997C, 0x6AA4, 0x997D, 0x6AA5, 0x997E, 0x6AA6, + 0x9980, 0x6AA7, 0x9981, 0x6AA8, 0x9982, 0x6AAA, 0x9983, 0x6AAD, 0x9984, 0x6AAE, 0x9985, 0x6AAF, 0x9986, 0x6AB0, 0x9987, 0x6AB1, + 0x9988, 0x6AB2, 0x9989, 0x6AB3, 0x998A, 0x6AB4, 0x998B, 0x6AB5, 0x998C, 0x6AB6, 0x998D, 0x6AB7, 0x998E, 0x6AB8, 0x998F, 0x6AB9, + 0x9990, 0x6ABA, 0x9991, 0x6ABB, 0x9992, 0x6ABC, 0x9993, 0x6ABD, 0x9994, 0x6ABE, 0x9995, 0x6ABF, 0x9996, 0x6AC0, 0x9997, 0x6AC1, + 0x9998, 0x6AC2, 0x9999, 0x6AC3, 0x999A, 0x6AC4, 0x999B, 0x6AC5, 0x999C, 0x6AC6, 0x999D, 0x6AC7, 0x999E, 0x6AC8, 0x999F, 0x6AC9, + 0x99A0, 0x6ACA, 0x99A1, 0x6ACB, 0x99A2, 0x6ACC, 0x99A3, 0x6ACD, 0x99A4, 0x6ACE, 0x99A5, 0x6ACF, 0x99A6, 0x6AD0, 0x99A7, 0x6AD1, + 0x99A8, 0x6AD2, 0x99A9, 0x6AD3, 0x99AA, 0x6AD4, 0x99AB, 0x6AD5, 0x99AC, 0x6AD6, 0x99AD, 0x6AD7, 0x99AE, 0x6AD8, 0x99AF, 0x6AD9, + 0x99B0, 0x6ADA, 0x99B1, 0x6ADB, 0x99B2, 0x6ADC, 0x99B3, 0x6ADD, 0x99B4, 0x6ADE, 0x99B5, 0x6ADF, 0x99B6, 0x6AE0, 0x99B7, 0x6AE1, + 0x99B8, 0x6AE2, 0x99B9, 0x6AE3, 0x99BA, 0x6AE4, 0x99BB, 0x6AE5, 0x99BC, 0x6AE6, 0x99BD, 0x6AE7, 0x99BE, 0x6AE8, 0x99BF, 0x6AE9, + 0x99C0, 0x6AEA, 0x99C1, 0x6AEB, 0x99C2, 0x6AEC, 0x99C3, 0x6AED, 0x99C4, 0x6AEE, 0x99C5, 0x6AEF, 0x99C6, 0x6AF0, 0x99C7, 0x6AF1, + 0x99C8, 0x6AF2, 0x99C9, 0x6AF3, 0x99CA, 0x6AF4, 0x99CB, 0x6AF5, 0x99CC, 0x6AF6, 0x99CD, 0x6AF7, 0x99CE, 0x6AF8, 0x99CF, 0x6AF9, + 0x99D0, 0x6AFA, 0x99D1, 0x6AFB, 0x99D2, 0x6AFC, 0x99D3, 0x6AFD, 0x99D4, 0x6AFE, 0x99D5, 0x6AFF, 0x99D6, 0x6B00, 0x99D7, 0x6B01, + 0x99D8, 0x6B02, 0x99D9, 0x6B03, 0x99DA, 0x6B04, 0x99DB, 0x6B05, 0x99DC, 0x6B06, 0x99DD, 0x6B07, 0x99DE, 0x6B08, 0x99DF, 0x6B09, + 0x99E0, 0x6B0A, 0x99E1, 0x6B0B, 0x99E2, 0x6B0C, 0x99E3, 0x6B0D, 0x99E4, 0x6B0E, 0x99E5, 0x6B0F, 0x99E6, 0x6B10, 0x99E7, 0x6B11, + 0x99E8, 0x6B12, 0x99E9, 0x6B13, 0x99EA, 0x6B14, 0x99EB, 0x6B15, 0x99EC, 0x6B16, 0x99ED, 0x6B17, 0x99EE, 0x6B18, 0x99EF, 0x6B19, + 0x99F0, 0x6B1A, 0x99F1, 0x6B1B, 0x99F2, 0x6B1C, 0x99F3, 0x6B1D, 0x99F4, 0x6B1E, 0x99F5, 0x6B1F, 0x99F6, 0x6B25, 0x99F7, 0x6B26, + 0x99F8, 0x6B28, 0x99F9, 0x6B29, 0x99FA, 0x6B2A, 0x99FB, 0x6B2B, 0x99FC, 0x6B2C, 0x99FD, 0x6B2D, 0x99FE, 0x6B2E, 0x9A40, 0x6B2F, + 0x9A41, 0x6B30, 0x9A42, 0x6B31, 0x9A43, 0x6B33, 0x9A44, 0x6B34, 0x9A45, 0x6B35, 0x9A46, 0x6B36, 0x9A47, 0x6B38, 0x9A48, 0x6B3B, + 0x9A49, 0x6B3C, 0x9A4A, 0x6B3D, 0x9A4B, 0x6B3F, 0x9A4C, 0x6B40, 0x9A4D, 0x6B41, 0x9A4E, 0x6B42, 0x9A4F, 0x6B44, 0x9A50, 0x6B45, + 0x9A51, 0x6B48, 0x9A52, 0x6B4A, 0x9A53, 0x6B4B, 0x9A54, 0x6B4D, 0x9A55, 0x6B4E, 0x9A56, 0x6B4F, 0x9A57, 0x6B50, 0x9A58, 0x6B51, + 0x9A59, 0x6B52, 0x9A5A, 0x6B53, 0x9A5B, 0x6B54, 0x9A5C, 0x6B55, 0x9A5D, 0x6B56, 0x9A5E, 0x6B57, 0x9A5F, 0x6B58, 0x9A60, 0x6B5A, + 0x9A61, 0x6B5B, 0x9A62, 0x6B5C, 0x9A63, 0x6B5D, 0x9A64, 0x6B5E, 0x9A65, 0x6B5F, 0x9A66, 0x6B60, 0x9A67, 0x6B61, 0x9A68, 0x6B68, + 0x9A69, 0x6B69, 0x9A6A, 0x6B6B, 0x9A6B, 0x6B6C, 0x9A6C, 0x6B6D, 0x9A6D, 0x6B6E, 0x9A6E, 0x6B6F, 0x9A6F, 0x6B70, 0x9A70, 0x6B71, + 0x9A71, 0x6B72, 0x9A72, 0x6B73, 0x9A73, 0x6B74, 0x9A74, 0x6B75, 0x9A75, 0x6B76, 0x9A76, 0x6B77, 0x9A77, 0x6B78, 0x9A78, 0x6B7A, + 0x9A79, 0x6B7D, 0x9A7A, 0x6B7E, 0x9A7B, 0x6B7F, 0x9A7C, 0x6B80, 0x9A7D, 0x6B85, 0x9A7E, 0x6B88, 0x9A80, 0x6B8C, 0x9A81, 0x6B8E, + 0x9A82, 0x6B8F, 0x9A83, 0x6B90, 0x9A84, 0x6B91, 0x9A85, 0x6B94, 0x9A86, 0x6B95, 0x9A87, 0x6B97, 0x9A88, 0x6B98, 0x9A89, 0x6B99, + 0x9A8A, 0x6B9C, 0x9A8B, 0x6B9D, 0x9A8C, 0x6B9E, 0x9A8D, 0x6B9F, 0x9A8E, 0x6BA0, 0x9A8F, 0x6BA2, 0x9A90, 0x6BA3, 0x9A91, 0x6BA4, + 0x9A92, 0x6BA5, 0x9A93, 0x6BA6, 0x9A94, 0x6BA7, 0x9A95, 0x6BA8, 0x9A96, 0x6BA9, 0x9A97, 0x6BAB, 0x9A98, 0x6BAC, 0x9A99, 0x6BAD, + 0x9A9A, 0x6BAE, 0x9A9B, 0x6BAF, 0x9A9C, 0x6BB0, 0x9A9D, 0x6BB1, 0x9A9E, 0x6BB2, 0x9A9F, 0x6BB6, 0x9AA0, 0x6BB8, 0x9AA1, 0x6BB9, + 0x9AA2, 0x6BBA, 0x9AA3, 0x6BBB, 0x9AA4, 0x6BBC, 0x9AA5, 0x6BBD, 0x9AA6, 0x6BBE, 0x9AA7, 0x6BC0, 0x9AA8, 0x6BC3, 0x9AA9, 0x6BC4, + 0x9AAA, 0x6BC6, 0x9AAB, 0x6BC7, 0x9AAC, 0x6BC8, 0x9AAD, 0x6BC9, 0x9AAE, 0x6BCA, 0x9AAF, 0x6BCC, 0x9AB0, 0x6BCE, 0x9AB1, 0x6BD0, + 0x9AB2, 0x6BD1, 0x9AB3, 0x6BD8, 0x9AB4, 0x6BDA, 0x9AB5, 0x6BDC, 0x9AB6, 0x6BDD, 0x9AB7, 0x6BDE, 0x9AB8, 0x6BDF, 0x9AB9, 0x6BE0, + 0x9ABA, 0x6BE2, 0x9ABB, 0x6BE3, 0x9ABC, 0x6BE4, 0x9ABD, 0x6BE5, 0x9ABE, 0x6BE6, 0x9ABF, 0x6BE7, 0x9AC0, 0x6BE8, 0x9AC1, 0x6BE9, + 0x9AC2, 0x6BEC, 0x9AC3, 0x6BED, 0x9AC4, 0x6BEE, 0x9AC5, 0x6BF0, 0x9AC6, 0x6BF1, 0x9AC7, 0x6BF2, 0x9AC8, 0x6BF4, 0x9AC9, 0x6BF6, + 0x9ACA, 0x6BF7, 0x9ACB, 0x6BF8, 0x9ACC, 0x6BFA, 0x9ACD, 0x6BFB, 0x9ACE, 0x6BFC, 0x9ACF, 0x6BFE, 0x9AD0, 0x6BFF, 0x9AD1, 0x6C00, + 0x9AD2, 0x6C01, 0x9AD3, 0x6C02, 0x9AD4, 0x6C03, 0x9AD5, 0x6C04, 0x9AD6, 0x6C08, 0x9AD7, 0x6C09, 0x9AD8, 0x6C0A, 0x9AD9, 0x6C0B, + 0x9ADA, 0x6C0C, 0x9ADB, 0x6C0E, 0x9ADC, 0x6C12, 0x9ADD, 0x6C17, 0x9ADE, 0x6C1C, 0x9ADF, 0x6C1D, 0x9AE0, 0x6C1E, 0x9AE1, 0x6C20, + 0x9AE2, 0x6C23, 0x9AE3, 0x6C25, 0x9AE4, 0x6C2B, 0x9AE5, 0x6C2C, 0x9AE6, 0x6C2D, 0x9AE7, 0x6C31, 0x9AE8, 0x6C33, 0x9AE9, 0x6C36, + 0x9AEA, 0x6C37, 0x9AEB, 0x6C39, 0x9AEC, 0x6C3A, 0x9AED, 0x6C3B, 0x9AEE, 0x6C3C, 0x9AEF, 0x6C3E, 0x9AF0, 0x6C3F, 0x9AF1, 0x6C43, + 0x9AF2, 0x6C44, 0x9AF3, 0x6C45, 0x9AF4, 0x6C48, 0x9AF5, 0x6C4B, 0x9AF6, 0x6C4C, 0x9AF7, 0x6C4D, 0x9AF8, 0x6C4E, 0x9AF9, 0x6C4F, + 0x9AFA, 0x6C51, 0x9AFB, 0x6C52, 0x9AFC, 0x6C53, 0x9AFD, 0x6C56, 0x9AFE, 0x6C58, 0x9B40, 0x6C59, 0x9B41, 0x6C5A, 0x9B42, 0x6C62, + 0x9B43, 0x6C63, 0x9B44, 0x6C65, 0x9B45, 0x6C66, 0x9B46, 0x6C67, 0x9B47, 0x6C6B, 0x9B48, 0x6C6C, 0x9B49, 0x6C6D, 0x9B4A, 0x6C6E, + 0x9B4B, 0x6C6F, 0x9B4C, 0x6C71, 0x9B4D, 0x6C73, 0x9B4E, 0x6C75, 0x9B4F, 0x6C77, 0x9B50, 0x6C78, 0x9B51, 0x6C7A, 0x9B52, 0x6C7B, + 0x9B53, 0x6C7C, 0x9B54, 0x6C7F, 0x9B55, 0x6C80, 0x9B56, 0x6C84, 0x9B57, 0x6C87, 0x9B58, 0x6C8A, 0x9B59, 0x6C8B, 0x9B5A, 0x6C8D, + 0x9B5B, 0x6C8E, 0x9B5C, 0x6C91, 0x9B5D, 0x6C92, 0x9B5E, 0x6C95, 0x9B5F, 0x6C96, 0x9B60, 0x6C97, 0x9B61, 0x6C98, 0x9B62, 0x6C9A, + 0x9B63, 0x6C9C, 0x9B64, 0x6C9D, 0x9B65, 0x6C9E, 0x9B66, 0x6CA0, 0x9B67, 0x6CA2, 0x9B68, 0x6CA8, 0x9B69, 0x6CAC, 0x9B6A, 0x6CAF, + 0x9B6B, 0x6CB0, 0x9B6C, 0x6CB4, 0x9B6D, 0x6CB5, 0x9B6E, 0x6CB6, 0x9B6F, 0x6CB7, 0x9B70, 0x6CBA, 0x9B71, 0x6CC0, 0x9B72, 0x6CC1, + 0x9B73, 0x6CC2, 0x9B74, 0x6CC3, 0x9B75, 0x6CC6, 0x9B76, 0x6CC7, 0x9B77, 0x6CC8, 0x9B78, 0x6CCB, 0x9B79, 0x6CCD, 0x9B7A, 0x6CCE, + 0x9B7B, 0x6CCF, 0x9B7C, 0x6CD1, 0x9B7D, 0x6CD2, 0x9B7E, 0x6CD8, 0x9B80, 0x6CD9, 0x9B81, 0x6CDA, 0x9B82, 0x6CDC, 0x9B83, 0x6CDD, + 0x9B84, 0x6CDF, 0x9B85, 0x6CE4, 0x9B86, 0x6CE6, 0x9B87, 0x6CE7, 0x9B88, 0x6CE9, 0x9B89, 0x6CEC, 0x9B8A, 0x6CED, 0x9B8B, 0x6CF2, + 0x9B8C, 0x6CF4, 0x9B8D, 0x6CF9, 0x9B8E, 0x6CFF, 0x9B8F, 0x6D00, 0x9B90, 0x6D02, 0x9B91, 0x6D03, 0x9B92, 0x6D05, 0x9B93, 0x6D06, + 0x9B94, 0x6D08, 0x9B95, 0x6D09, 0x9B96, 0x6D0A, 0x9B97, 0x6D0D, 0x9B98, 0x6D0F, 0x9B99, 0x6D10, 0x9B9A, 0x6D11, 0x9B9B, 0x6D13, + 0x9B9C, 0x6D14, 0x9B9D, 0x6D15, 0x9B9E, 0x6D16, 0x9B9F, 0x6D18, 0x9BA0, 0x6D1C, 0x9BA1, 0x6D1D, 0x9BA2, 0x6D1F, 0x9BA3, 0x6D20, + 0x9BA4, 0x6D21, 0x9BA5, 0x6D22, 0x9BA6, 0x6D23, 0x9BA7, 0x6D24, 0x9BA8, 0x6D26, 0x9BA9, 0x6D28, 0x9BAA, 0x6D29, 0x9BAB, 0x6D2C, + 0x9BAC, 0x6D2D, 0x9BAD, 0x6D2F, 0x9BAE, 0x6D30, 0x9BAF, 0x6D34, 0x9BB0, 0x6D36, 0x9BB1, 0x6D37, 0x9BB2, 0x6D38, 0x9BB3, 0x6D3A, + 0x9BB4, 0x6D3F, 0x9BB5, 0x6D40, 0x9BB6, 0x6D42, 0x9BB7, 0x6D44, 0x9BB8, 0x6D49, 0x9BB9, 0x6D4C, 0x9BBA, 0x6D50, 0x9BBB, 0x6D55, + 0x9BBC, 0x6D56, 0x9BBD, 0x6D57, 0x9BBE, 0x6D58, 0x9BBF, 0x6D5B, 0x9BC0, 0x6D5D, 0x9BC1, 0x6D5F, 0x9BC2, 0x6D61, 0x9BC3, 0x6D62, + 0x9BC4, 0x6D64, 0x9BC5, 0x6D65, 0x9BC6, 0x6D67, 0x9BC7, 0x6D68, 0x9BC8, 0x6D6B, 0x9BC9, 0x6D6C, 0x9BCA, 0x6D6D, 0x9BCB, 0x6D70, + 0x9BCC, 0x6D71, 0x9BCD, 0x6D72, 0x9BCE, 0x6D73, 0x9BCF, 0x6D75, 0x9BD0, 0x6D76, 0x9BD1, 0x6D79, 0x9BD2, 0x6D7A, 0x9BD3, 0x6D7B, + 0x9BD4, 0x6D7D, 0x9BD5, 0x6D7E, 0x9BD6, 0x6D7F, 0x9BD7, 0x6D80, 0x9BD8, 0x6D81, 0x9BD9, 0x6D83, 0x9BDA, 0x6D84, 0x9BDB, 0x6D86, + 0x9BDC, 0x6D87, 0x9BDD, 0x6D8A, 0x9BDE, 0x6D8B, 0x9BDF, 0x6D8D, 0x9BE0, 0x6D8F, 0x9BE1, 0x6D90, 0x9BE2, 0x6D92, 0x9BE3, 0x6D96, + 0x9BE4, 0x6D97, 0x9BE5, 0x6D98, 0x9BE6, 0x6D99, 0x9BE7, 0x6D9A, 0x9BE8, 0x6D9C, 0x9BE9, 0x6DA2, 0x9BEA, 0x6DA5, 0x9BEB, 0x6DAC, + 0x9BEC, 0x6DAD, 0x9BED, 0x6DB0, 0x9BEE, 0x6DB1, 0x9BEF, 0x6DB3, 0x9BF0, 0x6DB4, 0x9BF1, 0x6DB6, 0x9BF2, 0x6DB7, 0x9BF3, 0x6DB9, + 0x9BF4, 0x6DBA, 0x9BF5, 0x6DBB, 0x9BF6, 0x6DBC, 0x9BF7, 0x6DBD, 0x9BF8, 0x6DBE, 0x9BF9, 0x6DC1, 0x9BFA, 0x6DC2, 0x9BFB, 0x6DC3, + 0x9BFC, 0x6DC8, 0x9BFD, 0x6DC9, 0x9BFE, 0x6DCA, 0x9C40, 0x6DCD, 0x9C41, 0x6DCE, 0x9C42, 0x6DCF, 0x9C43, 0x6DD0, 0x9C44, 0x6DD2, + 0x9C45, 0x6DD3, 0x9C46, 0x6DD4, 0x9C47, 0x6DD5, 0x9C48, 0x6DD7, 0x9C49, 0x6DDA, 0x9C4A, 0x6DDB, 0x9C4B, 0x6DDC, 0x9C4C, 0x6DDF, + 0x9C4D, 0x6DE2, 0x9C4E, 0x6DE3, 0x9C4F, 0x6DE5, 0x9C50, 0x6DE7, 0x9C51, 0x6DE8, 0x9C52, 0x6DE9, 0x9C53, 0x6DEA, 0x9C54, 0x6DED, + 0x9C55, 0x6DEF, 0x9C56, 0x6DF0, 0x9C57, 0x6DF2, 0x9C58, 0x6DF4, 0x9C59, 0x6DF5, 0x9C5A, 0x6DF6, 0x9C5B, 0x6DF8, 0x9C5C, 0x6DFA, + 0x9C5D, 0x6DFD, 0x9C5E, 0x6DFE, 0x9C5F, 0x6DFF, 0x9C60, 0x6E00, 0x9C61, 0x6E01, 0x9C62, 0x6E02, 0x9C63, 0x6E03, 0x9C64, 0x6E04, + 0x9C65, 0x6E06, 0x9C66, 0x6E07, 0x9C67, 0x6E08, 0x9C68, 0x6E09, 0x9C69, 0x6E0B, 0x9C6A, 0x6E0F, 0x9C6B, 0x6E12, 0x9C6C, 0x6E13, + 0x9C6D, 0x6E15, 0x9C6E, 0x6E18, 0x9C6F, 0x6E19, 0x9C70, 0x6E1B, 0x9C71, 0x6E1C, 0x9C72, 0x6E1E, 0x9C73, 0x6E1F, 0x9C74, 0x6E22, + 0x9C75, 0x6E26, 0x9C76, 0x6E27, 0x9C77, 0x6E28, 0x9C78, 0x6E2A, 0x9C79, 0x6E2C, 0x9C7A, 0x6E2E, 0x9C7B, 0x6E30, 0x9C7C, 0x6E31, + 0x9C7D, 0x6E33, 0x9C7E, 0x6E35, 0x9C80, 0x6E36, 0x9C81, 0x6E37, 0x9C82, 0x6E39, 0x9C83, 0x6E3B, 0x9C84, 0x6E3C, 0x9C85, 0x6E3D, + 0x9C86, 0x6E3E, 0x9C87, 0x6E3F, 0x9C88, 0x6E40, 0x9C89, 0x6E41, 0x9C8A, 0x6E42, 0x9C8B, 0x6E45, 0x9C8C, 0x6E46, 0x9C8D, 0x6E47, + 0x9C8E, 0x6E48, 0x9C8F, 0x6E49, 0x9C90, 0x6E4A, 0x9C91, 0x6E4B, 0x9C92, 0x6E4C, 0x9C93, 0x6E4F, 0x9C94, 0x6E50, 0x9C95, 0x6E51, + 0x9C96, 0x6E52, 0x9C97, 0x6E55, 0x9C98, 0x6E57, 0x9C99, 0x6E59, 0x9C9A, 0x6E5A, 0x9C9B, 0x6E5C, 0x9C9C, 0x6E5D, 0x9C9D, 0x6E5E, + 0x9C9E, 0x6E60, 0x9C9F, 0x6E61, 0x9CA0, 0x6E62, 0x9CA1, 0x6E63, 0x9CA2, 0x6E64, 0x9CA3, 0x6E65, 0x9CA4, 0x6E66, 0x9CA5, 0x6E67, + 0x9CA6, 0x6E68, 0x9CA7, 0x6E69, 0x9CA8, 0x6E6A, 0x9CA9, 0x6E6C, 0x9CAA, 0x6E6D, 0x9CAB, 0x6E6F, 0x9CAC, 0x6E70, 0x9CAD, 0x6E71, + 0x9CAE, 0x6E72, 0x9CAF, 0x6E73, 0x9CB0, 0x6E74, 0x9CB1, 0x6E75, 0x9CB2, 0x6E76, 0x9CB3, 0x6E77, 0x9CB4, 0x6E78, 0x9CB5, 0x6E79, + 0x9CB6, 0x6E7A, 0x9CB7, 0x6E7B, 0x9CB8, 0x6E7C, 0x9CB9, 0x6E7D, 0x9CBA, 0x6E80, 0x9CBB, 0x6E81, 0x9CBC, 0x6E82, 0x9CBD, 0x6E84, + 0x9CBE, 0x6E87, 0x9CBF, 0x6E88, 0x9CC0, 0x6E8A, 0x9CC1, 0x6E8B, 0x9CC2, 0x6E8C, 0x9CC3, 0x6E8D, 0x9CC4, 0x6E8E, 0x9CC5, 0x6E91, + 0x9CC6, 0x6E92, 0x9CC7, 0x6E93, 0x9CC8, 0x6E94, 0x9CC9, 0x6E95, 0x9CCA, 0x6E96, 0x9CCB, 0x6E97, 0x9CCC, 0x6E99, 0x9CCD, 0x6E9A, + 0x9CCE, 0x6E9B, 0x9CCF, 0x6E9D, 0x9CD0, 0x6E9E, 0x9CD1, 0x6EA0, 0x9CD2, 0x6EA1, 0x9CD3, 0x6EA3, 0x9CD4, 0x6EA4, 0x9CD5, 0x6EA6, + 0x9CD6, 0x6EA8, 0x9CD7, 0x6EA9, 0x9CD8, 0x6EAB, 0x9CD9, 0x6EAC, 0x9CDA, 0x6EAD, 0x9CDB, 0x6EAE, 0x9CDC, 0x6EB0, 0x9CDD, 0x6EB3, + 0x9CDE, 0x6EB5, 0x9CDF, 0x6EB8, 0x9CE0, 0x6EB9, 0x9CE1, 0x6EBC, 0x9CE2, 0x6EBE, 0x9CE3, 0x6EBF, 0x9CE4, 0x6EC0, 0x9CE5, 0x6EC3, + 0x9CE6, 0x6EC4, 0x9CE7, 0x6EC5, 0x9CE8, 0x6EC6, 0x9CE9, 0x6EC8, 0x9CEA, 0x6EC9, 0x9CEB, 0x6ECA, 0x9CEC, 0x6ECC, 0x9CED, 0x6ECD, + 0x9CEE, 0x6ECE, 0x9CEF, 0x6ED0, 0x9CF0, 0x6ED2, 0x9CF1, 0x6ED6, 0x9CF2, 0x6ED8, 0x9CF3, 0x6ED9, 0x9CF4, 0x6EDB, 0x9CF5, 0x6EDC, + 0x9CF6, 0x6EDD, 0x9CF7, 0x6EE3, 0x9CF8, 0x6EE7, 0x9CF9, 0x6EEA, 0x9CFA, 0x6EEB, 0x9CFB, 0x6EEC, 0x9CFC, 0x6EED, 0x9CFD, 0x6EEE, + 0x9CFE, 0x6EEF, 0x9D40, 0x6EF0, 0x9D41, 0x6EF1, 0x9D42, 0x6EF2, 0x9D43, 0x6EF3, 0x9D44, 0x6EF5, 0x9D45, 0x6EF6, 0x9D46, 0x6EF7, + 0x9D47, 0x6EF8, 0x9D48, 0x6EFA, 0x9D49, 0x6EFB, 0x9D4A, 0x6EFC, 0x9D4B, 0x6EFD, 0x9D4C, 0x6EFE, 0x9D4D, 0x6EFF, 0x9D4E, 0x6F00, + 0x9D4F, 0x6F01, 0x9D50, 0x6F03, 0x9D51, 0x6F04, 0x9D52, 0x6F05, 0x9D53, 0x6F07, 0x9D54, 0x6F08, 0x9D55, 0x6F0A, 0x9D56, 0x6F0B, + 0x9D57, 0x6F0C, 0x9D58, 0x6F0D, 0x9D59, 0x6F0E, 0x9D5A, 0x6F10, 0x9D5B, 0x6F11, 0x9D5C, 0x6F12, 0x9D5D, 0x6F16, 0x9D5E, 0x6F17, + 0x9D5F, 0x6F18, 0x9D60, 0x6F19, 0x9D61, 0x6F1A, 0x9D62, 0x6F1B, 0x9D63, 0x6F1C, 0x9D64, 0x6F1D, 0x9D65, 0x6F1E, 0x9D66, 0x6F1F, + 0x9D67, 0x6F21, 0x9D68, 0x6F22, 0x9D69, 0x6F23, 0x9D6A, 0x6F25, 0x9D6B, 0x6F26, 0x9D6C, 0x6F27, 0x9D6D, 0x6F28, 0x9D6E, 0x6F2C, + 0x9D6F, 0x6F2E, 0x9D70, 0x6F30, 0x9D71, 0x6F32, 0x9D72, 0x6F34, 0x9D73, 0x6F35, 0x9D74, 0x6F37, 0x9D75, 0x6F38, 0x9D76, 0x6F39, + 0x9D77, 0x6F3A, 0x9D78, 0x6F3B, 0x9D79, 0x6F3C, 0x9D7A, 0x6F3D, 0x9D7B, 0x6F3F, 0x9D7C, 0x6F40, 0x9D7D, 0x6F41, 0x9D7E, 0x6F42, + 0x9D80, 0x6F43, 0x9D81, 0x6F44, 0x9D82, 0x6F45, 0x9D83, 0x6F48, 0x9D84, 0x6F49, 0x9D85, 0x6F4A, 0x9D86, 0x6F4C, 0x9D87, 0x6F4E, + 0x9D88, 0x6F4F, 0x9D89, 0x6F50, 0x9D8A, 0x6F51, 0x9D8B, 0x6F52, 0x9D8C, 0x6F53, 0x9D8D, 0x6F54, 0x9D8E, 0x6F55, 0x9D8F, 0x6F56, + 0x9D90, 0x6F57, 0x9D91, 0x6F59, 0x9D92, 0x6F5A, 0x9D93, 0x6F5B, 0x9D94, 0x6F5D, 0x9D95, 0x6F5F, 0x9D96, 0x6F60, 0x9D97, 0x6F61, + 0x9D98, 0x6F63, 0x9D99, 0x6F64, 0x9D9A, 0x6F65, 0x9D9B, 0x6F67, 0x9D9C, 0x6F68, 0x9D9D, 0x6F69, 0x9D9E, 0x6F6A, 0x9D9F, 0x6F6B, + 0x9DA0, 0x6F6C, 0x9DA1, 0x6F6F, 0x9DA2, 0x6F70, 0x9DA3, 0x6F71, 0x9DA4, 0x6F73, 0x9DA5, 0x6F75, 0x9DA6, 0x6F76, 0x9DA7, 0x6F77, + 0x9DA8, 0x6F79, 0x9DA9, 0x6F7B, 0x9DAA, 0x6F7D, 0x9DAB, 0x6F7E, 0x9DAC, 0x6F7F, 0x9DAD, 0x6F80, 0x9DAE, 0x6F81, 0x9DAF, 0x6F82, + 0x9DB0, 0x6F83, 0x9DB1, 0x6F85, 0x9DB2, 0x6F86, 0x9DB3, 0x6F87, 0x9DB4, 0x6F8A, 0x9DB5, 0x6F8B, 0x9DB6, 0x6F8F, 0x9DB7, 0x6F90, + 0x9DB8, 0x6F91, 0x9DB9, 0x6F92, 0x9DBA, 0x6F93, 0x9DBB, 0x6F94, 0x9DBC, 0x6F95, 0x9DBD, 0x6F96, 0x9DBE, 0x6F97, 0x9DBF, 0x6F98, + 0x9DC0, 0x6F99, 0x9DC1, 0x6F9A, 0x9DC2, 0x6F9B, 0x9DC3, 0x6F9D, 0x9DC4, 0x6F9E, 0x9DC5, 0x6F9F, 0x9DC6, 0x6FA0, 0x9DC7, 0x6FA2, + 0x9DC8, 0x6FA3, 0x9DC9, 0x6FA4, 0x9DCA, 0x6FA5, 0x9DCB, 0x6FA6, 0x9DCC, 0x6FA8, 0x9DCD, 0x6FA9, 0x9DCE, 0x6FAA, 0x9DCF, 0x6FAB, + 0x9DD0, 0x6FAC, 0x9DD1, 0x6FAD, 0x9DD2, 0x6FAE, 0x9DD3, 0x6FAF, 0x9DD4, 0x6FB0, 0x9DD5, 0x6FB1, 0x9DD6, 0x6FB2, 0x9DD7, 0x6FB4, + 0x9DD8, 0x6FB5, 0x9DD9, 0x6FB7, 0x9DDA, 0x6FB8, 0x9DDB, 0x6FBA, 0x9DDC, 0x6FBB, 0x9DDD, 0x6FBC, 0x9DDE, 0x6FBD, 0x9DDF, 0x6FBE, + 0x9DE0, 0x6FBF, 0x9DE1, 0x6FC1, 0x9DE2, 0x6FC3, 0x9DE3, 0x6FC4, 0x9DE4, 0x6FC5, 0x9DE5, 0x6FC6, 0x9DE6, 0x6FC7, 0x9DE7, 0x6FC8, + 0x9DE8, 0x6FCA, 0x9DE9, 0x6FCB, 0x9DEA, 0x6FCC, 0x9DEB, 0x6FCD, 0x9DEC, 0x6FCE, 0x9DED, 0x6FCF, 0x9DEE, 0x6FD0, 0x9DEF, 0x6FD3, + 0x9DF0, 0x6FD4, 0x9DF1, 0x6FD5, 0x9DF2, 0x6FD6, 0x9DF3, 0x6FD7, 0x9DF4, 0x6FD8, 0x9DF5, 0x6FD9, 0x9DF6, 0x6FDA, 0x9DF7, 0x6FDB, + 0x9DF8, 0x6FDC, 0x9DF9, 0x6FDD, 0x9DFA, 0x6FDF, 0x9DFB, 0x6FE2, 0x9DFC, 0x6FE3, 0x9DFD, 0x6FE4, 0x9DFE, 0x6FE5, 0x9E40, 0x6FE6, + 0x9E41, 0x6FE7, 0x9E42, 0x6FE8, 0x9E43, 0x6FE9, 0x9E44, 0x6FEA, 0x9E45, 0x6FEB, 0x9E46, 0x6FEC, 0x9E47, 0x6FED, 0x9E48, 0x6FF0, + 0x9E49, 0x6FF1, 0x9E4A, 0x6FF2, 0x9E4B, 0x6FF3, 0x9E4C, 0x6FF4, 0x9E4D, 0x6FF5, 0x9E4E, 0x6FF6, 0x9E4F, 0x6FF7, 0x9E50, 0x6FF8, + 0x9E51, 0x6FF9, 0x9E52, 0x6FFA, 0x9E53, 0x6FFB, 0x9E54, 0x6FFC, 0x9E55, 0x6FFD, 0x9E56, 0x6FFE, 0x9E57, 0x6FFF, 0x9E58, 0x7000, + 0x9E59, 0x7001, 0x9E5A, 0x7002, 0x9E5B, 0x7003, 0x9E5C, 0x7004, 0x9E5D, 0x7005, 0x9E5E, 0x7006, 0x9E5F, 0x7007, 0x9E60, 0x7008, + 0x9E61, 0x7009, 0x9E62, 0x700A, 0x9E63, 0x700B, 0x9E64, 0x700C, 0x9E65, 0x700D, 0x9E66, 0x700E, 0x9E67, 0x700F, 0x9E68, 0x7010, + 0x9E69, 0x7012, 0x9E6A, 0x7013, 0x9E6B, 0x7014, 0x9E6C, 0x7015, 0x9E6D, 0x7016, 0x9E6E, 0x7017, 0x9E6F, 0x7018, 0x9E70, 0x7019, + 0x9E71, 0x701C, 0x9E72, 0x701D, 0x9E73, 0x701E, 0x9E74, 0x701F, 0x9E75, 0x7020, 0x9E76, 0x7021, 0x9E77, 0x7022, 0x9E78, 0x7024, + 0x9E79, 0x7025, 0x9E7A, 0x7026, 0x9E7B, 0x7027, 0x9E7C, 0x7028, 0x9E7D, 0x7029, 0x9E7E, 0x702A, 0x9E80, 0x702B, 0x9E81, 0x702C, + 0x9E82, 0x702D, 0x9E83, 0x702E, 0x9E84, 0x702F, 0x9E85, 0x7030, 0x9E86, 0x7031, 0x9E87, 0x7032, 0x9E88, 0x7033, 0x9E89, 0x7034, + 0x9E8A, 0x7036, 0x9E8B, 0x7037, 0x9E8C, 0x7038, 0x9E8D, 0x703A, 0x9E8E, 0x703B, 0x9E8F, 0x703C, 0x9E90, 0x703D, 0x9E91, 0x703E, + 0x9E92, 0x703F, 0x9E93, 0x7040, 0x9E94, 0x7041, 0x9E95, 0x7042, 0x9E96, 0x7043, 0x9E97, 0x7044, 0x9E98, 0x7045, 0x9E99, 0x7046, + 0x9E9A, 0x7047, 0x9E9B, 0x7048, 0x9E9C, 0x7049, 0x9E9D, 0x704A, 0x9E9E, 0x704B, 0x9E9F, 0x704D, 0x9EA0, 0x704E, 0x9EA1, 0x7050, + 0x9EA2, 0x7051, 0x9EA3, 0x7052, 0x9EA4, 0x7053, 0x9EA5, 0x7054, 0x9EA6, 0x7055, 0x9EA7, 0x7056, 0x9EA8, 0x7057, 0x9EA9, 0x7058, + 0x9EAA, 0x7059, 0x9EAB, 0x705A, 0x9EAC, 0x705B, 0x9EAD, 0x705C, 0x9EAE, 0x705D, 0x9EAF, 0x705F, 0x9EB0, 0x7060, 0x9EB1, 0x7061, + 0x9EB2, 0x7062, 0x9EB3, 0x7063, 0x9EB4, 0x7064, 0x9EB5, 0x7065, 0x9EB6, 0x7066, 0x9EB7, 0x7067, 0x9EB8, 0x7068, 0x9EB9, 0x7069, + 0x9EBA, 0x706A, 0x9EBB, 0x706E, 0x9EBC, 0x7071, 0x9EBD, 0x7072, 0x9EBE, 0x7073, 0x9EBF, 0x7074, 0x9EC0, 0x7077, 0x9EC1, 0x7079, + 0x9EC2, 0x707A, 0x9EC3, 0x707B, 0x9EC4, 0x707D, 0x9EC5, 0x7081, 0x9EC6, 0x7082, 0x9EC7, 0x7083, 0x9EC8, 0x7084, 0x9EC9, 0x7086, + 0x9ECA, 0x7087, 0x9ECB, 0x7088, 0x9ECC, 0x708B, 0x9ECD, 0x708C, 0x9ECE, 0x708D, 0x9ECF, 0x708F, 0x9ED0, 0x7090, 0x9ED1, 0x7091, + 0x9ED2, 0x7093, 0x9ED3, 0x7097, 0x9ED4, 0x7098, 0x9ED5, 0x709A, 0x9ED6, 0x709B, 0x9ED7, 0x709E, 0x9ED8, 0x709F, 0x9ED9, 0x70A0, + 0x9EDA, 0x70A1, 0x9EDB, 0x70A2, 0x9EDC, 0x70A3, 0x9EDD, 0x70A4, 0x9EDE, 0x70A5, 0x9EDF, 0x70A6, 0x9EE0, 0x70A7, 0x9EE1, 0x70A8, + 0x9EE2, 0x70A9, 0x9EE3, 0x70AA, 0x9EE4, 0x70B0, 0x9EE5, 0x70B2, 0x9EE6, 0x70B4, 0x9EE7, 0x70B5, 0x9EE8, 0x70B6, 0x9EE9, 0x70BA, + 0x9EEA, 0x70BE, 0x9EEB, 0x70BF, 0x9EEC, 0x70C4, 0x9EED, 0x70C5, 0x9EEE, 0x70C6, 0x9EEF, 0x70C7, 0x9EF0, 0x70C9, 0x9EF1, 0x70CB, + 0x9EF2, 0x70CC, 0x9EF3, 0x70CD, 0x9EF4, 0x70CE, 0x9EF5, 0x70CF, 0x9EF6, 0x70D0, 0x9EF7, 0x70D1, 0x9EF8, 0x70D2, 0x9EF9, 0x70D3, + 0x9EFA, 0x70D4, 0x9EFB, 0x70D5, 0x9EFC, 0x70D6, 0x9EFD, 0x70D7, 0x9EFE, 0x70DA, 0x9F40, 0x70DC, 0x9F41, 0x70DD, 0x9F42, 0x70DE, + 0x9F43, 0x70E0, 0x9F44, 0x70E1, 0x9F45, 0x70E2, 0x9F46, 0x70E3, 0x9F47, 0x70E5, 0x9F48, 0x70EA, 0x9F49, 0x70EE, 0x9F4A, 0x70F0, + 0x9F4B, 0x70F1, 0x9F4C, 0x70F2, 0x9F4D, 0x70F3, 0x9F4E, 0x70F4, 0x9F4F, 0x70F5, 0x9F50, 0x70F6, 0x9F51, 0x70F8, 0x9F52, 0x70FA, + 0x9F53, 0x70FB, 0x9F54, 0x70FC, 0x9F55, 0x70FE, 0x9F56, 0x70FF, 0x9F57, 0x7100, 0x9F58, 0x7101, 0x9F59, 0x7102, 0x9F5A, 0x7103, + 0x9F5B, 0x7104, 0x9F5C, 0x7105, 0x9F5D, 0x7106, 0x9F5E, 0x7107, 0x9F5F, 0x7108, 0x9F60, 0x710B, 0x9F61, 0x710C, 0x9F62, 0x710D, + 0x9F63, 0x710E, 0x9F64, 0x710F, 0x9F65, 0x7111, 0x9F66, 0x7112, 0x9F67, 0x7114, 0x9F68, 0x7117, 0x9F69, 0x711B, 0x9F6A, 0x711C, + 0x9F6B, 0x711D, 0x9F6C, 0x711E, 0x9F6D, 0x711F, 0x9F6E, 0x7120, 0x9F6F, 0x7121, 0x9F70, 0x7122, 0x9F71, 0x7123, 0x9F72, 0x7124, + 0x9F73, 0x7125, 0x9F74, 0x7127, 0x9F75, 0x7128, 0x9F76, 0x7129, 0x9F77, 0x712A, 0x9F78, 0x712B, 0x9F79, 0x712C, 0x9F7A, 0x712D, + 0x9F7B, 0x712E, 0x9F7C, 0x7132, 0x9F7D, 0x7133, 0x9F7E, 0x7134, 0x9F80, 0x7135, 0x9F81, 0x7137, 0x9F82, 0x7138, 0x9F83, 0x7139, + 0x9F84, 0x713A, 0x9F85, 0x713B, 0x9F86, 0x713C, 0x9F87, 0x713D, 0x9F88, 0x713E, 0x9F89, 0x713F, 0x9F8A, 0x7140, 0x9F8B, 0x7141, + 0x9F8C, 0x7142, 0x9F8D, 0x7143, 0x9F8E, 0x7144, 0x9F8F, 0x7146, 0x9F90, 0x7147, 0x9F91, 0x7148, 0x9F92, 0x7149, 0x9F93, 0x714B, + 0x9F94, 0x714D, 0x9F95, 0x714F, 0x9F96, 0x7150, 0x9F97, 0x7151, 0x9F98, 0x7152, 0x9F99, 0x7153, 0x9F9A, 0x7154, 0x9F9B, 0x7155, + 0x9F9C, 0x7156, 0x9F9D, 0x7157, 0x9F9E, 0x7158, 0x9F9F, 0x7159, 0x9FA0, 0x715A, 0x9FA1, 0x715B, 0x9FA2, 0x715D, 0x9FA3, 0x715F, + 0x9FA4, 0x7160, 0x9FA5, 0x7161, 0x9FA6, 0x7162, 0x9FA7, 0x7163, 0x9FA8, 0x7165, 0x9FA9, 0x7169, 0x9FAA, 0x716A, 0x9FAB, 0x716B, + 0x9FAC, 0x716C, 0x9FAD, 0x716D, 0x9FAE, 0x716F, 0x9FAF, 0x7170, 0x9FB0, 0x7171, 0x9FB1, 0x7174, 0x9FB2, 0x7175, 0x9FB3, 0x7176, + 0x9FB4, 0x7177, 0x9FB5, 0x7179, 0x9FB6, 0x717B, 0x9FB7, 0x717C, 0x9FB8, 0x717E, 0x9FB9, 0x717F, 0x9FBA, 0x7180, 0x9FBB, 0x7181, + 0x9FBC, 0x7182, 0x9FBD, 0x7183, 0x9FBE, 0x7185, 0x9FBF, 0x7186, 0x9FC0, 0x7187, 0x9FC1, 0x7188, 0x9FC2, 0x7189, 0x9FC3, 0x718B, + 0x9FC4, 0x718C, 0x9FC5, 0x718D, 0x9FC6, 0x718E, 0x9FC7, 0x7190, 0x9FC8, 0x7191, 0x9FC9, 0x7192, 0x9FCA, 0x7193, 0x9FCB, 0x7195, + 0x9FCC, 0x7196, 0x9FCD, 0x7197, 0x9FCE, 0x719A, 0x9FCF, 0x719B, 0x9FD0, 0x719C, 0x9FD1, 0x719D, 0x9FD2, 0x719E, 0x9FD3, 0x71A1, + 0x9FD4, 0x71A2, 0x9FD5, 0x71A3, 0x9FD6, 0x71A4, 0x9FD7, 0x71A5, 0x9FD8, 0x71A6, 0x9FD9, 0x71A7, 0x9FDA, 0x71A9, 0x9FDB, 0x71AA, + 0x9FDC, 0x71AB, 0x9FDD, 0x71AD, 0x9FDE, 0x71AE, 0x9FDF, 0x71AF, 0x9FE0, 0x71B0, 0x9FE1, 0x71B1, 0x9FE2, 0x71B2, 0x9FE3, 0x71B4, + 0x9FE4, 0x71B6, 0x9FE5, 0x71B7, 0x9FE6, 0x71B8, 0x9FE7, 0x71BA, 0x9FE8, 0x71BB, 0x9FE9, 0x71BC, 0x9FEA, 0x71BD, 0x9FEB, 0x71BE, + 0x9FEC, 0x71BF, 0x9FED, 0x71C0, 0x9FEE, 0x71C1, 0x9FEF, 0x71C2, 0x9FF0, 0x71C4, 0x9FF1, 0x71C5, 0x9FF2, 0x71C6, 0x9FF3, 0x71C7, + 0x9FF4, 0x71C8, 0x9FF5, 0x71C9, 0x9FF6, 0x71CA, 0x9FF7, 0x71CB, 0x9FF8, 0x71CC, 0x9FF9, 0x71CD, 0x9FFA, 0x71CF, 0x9FFB, 0x71D0, + 0x9FFC, 0x71D1, 0x9FFD, 0x71D2, 0x9FFE, 0x71D3, 0xA040, 0x71D6, 0xA041, 0x71D7, 0xA042, 0x71D8, 0xA043, 0x71D9, 0xA044, 0x71DA, + 0xA045, 0x71DB, 0xA046, 0x71DC, 0xA047, 0x71DD, 0xA048, 0x71DE, 0xA049, 0x71DF, 0xA04A, 0x71E1, 0xA04B, 0x71E2, 0xA04C, 0x71E3, + 0xA04D, 0x71E4, 0xA04E, 0x71E6, 0xA04F, 0x71E8, 0xA050, 0x71E9, 0xA051, 0x71EA, 0xA052, 0x71EB, 0xA053, 0x71EC, 0xA054, 0x71ED, + 0xA055, 0x71EF, 0xA056, 0x71F0, 0xA057, 0x71F1, 0xA058, 0x71F2, 0xA059, 0x71F3, 0xA05A, 0x71F4, 0xA05B, 0x71F5, 0xA05C, 0x71F6, + 0xA05D, 0x71F7, 0xA05E, 0x71F8, 0xA05F, 0x71FA, 0xA060, 0x71FB, 0xA061, 0x71FC, 0xA062, 0x71FD, 0xA063, 0x71FE, 0xA064, 0x71FF, + 0xA065, 0x7200, 0xA066, 0x7201, 0xA067, 0x7202, 0xA068, 0x7203, 0xA069, 0x7204, 0xA06A, 0x7205, 0xA06B, 0x7207, 0xA06C, 0x7208, + 0xA06D, 0x7209, 0xA06E, 0x720A, 0xA06F, 0x720B, 0xA070, 0x720C, 0xA071, 0x720D, 0xA072, 0x720E, 0xA073, 0x720F, 0xA074, 0x7210, + 0xA075, 0x7211, 0xA076, 0x7212, 0xA077, 0x7213, 0xA078, 0x7214, 0xA079, 0x7215, 0xA07A, 0x7216, 0xA07B, 0x7217, 0xA07C, 0x7218, + 0xA07D, 0x7219, 0xA07E, 0x721A, 0xA080, 0x721B, 0xA081, 0x721C, 0xA082, 0x721E, 0xA083, 0x721F, 0xA084, 0x7220, 0xA085, 0x7221, + 0xA086, 0x7222, 0xA087, 0x7223, 0xA088, 0x7224, 0xA089, 0x7225, 0xA08A, 0x7226, 0xA08B, 0x7227, 0xA08C, 0x7229, 0xA08D, 0x722B, + 0xA08E, 0x722D, 0xA08F, 0x722E, 0xA090, 0x722F, 0xA091, 0x7232, 0xA092, 0x7233, 0xA093, 0x7234, 0xA094, 0x723A, 0xA095, 0x723C, + 0xA096, 0x723E, 0xA097, 0x7240, 0xA098, 0x7241, 0xA099, 0x7242, 0xA09A, 0x7243, 0xA09B, 0x7244, 0xA09C, 0x7245, 0xA09D, 0x7246, + 0xA09E, 0x7249, 0xA09F, 0x724A, 0xA0A0, 0x724B, 0xA0A1, 0x724E, 0xA0A2, 0x724F, 0xA0A3, 0x7250, 0xA0A4, 0x7251, 0xA0A5, 0x7253, + 0xA0A6, 0x7254, 0xA0A7, 0x7255, 0xA0A8, 0x7257, 0xA0A9, 0x7258, 0xA0AA, 0x725A, 0xA0AB, 0x725C, 0xA0AC, 0x725E, 0xA0AD, 0x7260, + 0xA0AE, 0x7263, 0xA0AF, 0x7264, 0xA0B0, 0x7265, 0xA0B1, 0x7268, 0xA0B2, 0x726A, 0xA0B3, 0x726B, 0xA0B4, 0x726C, 0xA0B5, 0x726D, + 0xA0B6, 0x7270, 0xA0B7, 0x7271, 0xA0B8, 0x7273, 0xA0B9, 0x7274, 0xA0BA, 0x7276, 0xA0BB, 0x7277, 0xA0BC, 0x7278, 0xA0BD, 0x727B, + 0xA0BE, 0x727C, 0xA0BF, 0x727D, 0xA0C0, 0x7282, 0xA0C1, 0x7283, 0xA0C2, 0x7285, 0xA0C3, 0x7286, 0xA0C4, 0x7287, 0xA0C5, 0x7288, + 0xA0C6, 0x7289, 0xA0C7, 0x728C, 0xA0C8, 0x728E, 0xA0C9, 0x7290, 0xA0CA, 0x7291, 0xA0CB, 0x7293, 0xA0CC, 0x7294, 0xA0CD, 0x7295, + 0xA0CE, 0x7296, 0xA0CF, 0x7297, 0xA0D0, 0x7298, 0xA0D1, 0x7299, 0xA0D2, 0x729A, 0xA0D3, 0x729B, 0xA0D4, 0x729C, 0xA0D5, 0x729D, + 0xA0D6, 0x729E, 0xA0D7, 0x72A0, 0xA0D8, 0x72A1, 0xA0D9, 0x72A2, 0xA0DA, 0x72A3, 0xA0DB, 0x72A4, 0xA0DC, 0x72A5, 0xA0DD, 0x72A6, + 0xA0DE, 0x72A7, 0xA0DF, 0x72A8, 0xA0E0, 0x72A9, 0xA0E1, 0x72AA, 0xA0E2, 0x72AB, 0xA0E3, 0x72AE, 0xA0E4, 0x72B1, 0xA0E5, 0x72B2, + 0xA0E6, 0x72B3, 0xA0E7, 0x72B5, 0xA0E8, 0x72BA, 0xA0E9, 0x72BB, 0xA0EA, 0x72BC, 0xA0EB, 0x72BD, 0xA0EC, 0x72BE, 0xA0ED, 0x72BF, + 0xA0EE, 0x72C0, 0xA0EF, 0x72C5, 0xA0F0, 0x72C6, 0xA0F1, 0x72C7, 0xA0F2, 0x72C9, 0xA0F3, 0x72CA, 0xA0F4, 0x72CB, 0xA0F5, 0x72CC, + 0xA0F6, 0x72CF, 0xA0F7, 0x72D1, 0xA0F8, 0x72D3, 0xA0F9, 0x72D4, 0xA0FA, 0x72D5, 0xA0FB, 0x72D6, 0xA0FC, 0x72D8, 0xA0FD, 0x72DA, + 0xA0FE, 0x72DB, 0xA1A1, 0x3000, 0xA1A2, 0x3001, 0xA1A3, 0x3002, 0xA1A4, 0x00B7, 0xA1A5, 0x02C9, 0xA1A6, 0x02C7, 0xA1A7, 0x00A8, + 0xA1A8, 0x3003, 0xA1A9, 0x3005, 0xA1AA, 0x2014, 0xA1AB, 0xFF5E, 0xA1AC, 0x2016, 0xA1AD, 0x2026, 0xA1AE, 0x2018, 0xA1AF, 0x2019, + 0xA1B0, 0x201C, 0xA1B1, 0x201D, 0xA1B2, 0x3014, 0xA1B3, 0x3015, 0xA1B4, 0x3008, 0xA1B5, 0x3009, 0xA1B6, 0x300A, 0xA1B7, 0x300B, + 0xA1B8, 0x300C, 0xA1B9, 0x300D, 0xA1BA, 0x300E, 0xA1BB, 0x300F, 0xA1BC, 0x3016, 0xA1BD, 0x3017, 0xA1BE, 0x3010, 0xA1BF, 0x3011, + 0xA1C0, 0x00B1, 0xA1C1, 0x00D7, 0xA1C2, 0x00F7, 0xA1C3, 0x2236, 0xA1C4, 0x2227, 0xA1C5, 0x2228, 0xA1C6, 0x2211, 0xA1C7, 0x220F, + 0xA1C8, 0x222A, 0xA1C9, 0x2229, 0xA1CA, 0x2208, 0xA1CB, 0x2237, 0xA1CC, 0x221A, 0xA1CD, 0x22A5, 0xA1CE, 0x2225, 0xA1CF, 0x2220, + 0xA1D0, 0x2312, 0xA1D1, 0x2299, 0xA1D2, 0x222B, 0xA1D3, 0x222E, 0xA1D4, 0x2261, 0xA1D5, 0x224C, 0xA1D6, 0x2248, 0xA1D7, 0x223D, + 0xA1D8, 0x221D, 0xA1D9, 0x2260, 0xA1DA, 0x226E, 0xA1DB, 0x226F, 0xA1DC, 0x2264, 0xA1DD, 0x2265, 0xA1DE, 0x221E, 0xA1DF, 0x2235, + 0xA1E0, 0x2234, 0xA1E1, 0x2642, 0xA1E2, 0x2640, 0xA1E3, 0x00B0, 0xA1E4, 0x2032, 0xA1E5, 0x2033, 0xA1E6, 0x2103, 0xA1E7, 0xFF04, + 0xA1E8, 0x00A4, 0xA1E9, 0xFFE0, 0xA1EA, 0xFFE1, 0xA1EB, 0x2030, 0xA1EC, 0x00A7, 0xA1ED, 0x2116, 0xA1EE, 0x2606, 0xA1EF, 0x2605, + 0xA1F0, 0x25CB, 0xA1F1, 0x25CF, 0xA1F2, 0x25CE, 0xA1F3, 0x25C7, 0xA1F4, 0x25C6, 0xA1F5, 0x25A1, 0xA1F6, 0x25A0, 0xA1F7, 0x25B3, + 0xA1F8, 0x25B2, 0xA1F9, 0x203B, 0xA1FA, 0x2192, 0xA1FB, 0x2190, 0xA1FC, 0x2191, 0xA1FD, 0x2193, 0xA1FE, 0x3013, 0xA2A1, 0x2170, + 0xA2A2, 0x2171, 0xA2A3, 0x2172, 0xA2A4, 0x2173, 0xA2A5, 0x2174, 0xA2A6, 0x2175, 0xA2A7, 0x2176, 0xA2A8, 0x2177, 0xA2A9, 0x2178, + 0xA2AA, 0x2179, 0xA2B1, 0x2488, 0xA2B2, 0x2489, 0xA2B3, 0x248A, 0xA2B4, 0x248B, 0xA2B5, 0x248C, 0xA2B6, 0x248D, 0xA2B7, 0x248E, + 0xA2B8, 0x248F, 0xA2B9, 0x2490, 0xA2BA, 0x2491, 0xA2BB, 0x2492, 0xA2BC, 0x2493, 0xA2BD, 0x2494, 0xA2BE, 0x2495, 0xA2BF, 0x2496, + 0xA2C0, 0x2497, 0xA2C1, 0x2498, 0xA2C2, 0x2499, 0xA2C3, 0x249A, 0xA2C4, 0x249B, 0xA2C5, 0x2474, 0xA2C6, 0x2475, 0xA2C7, 0x2476, + 0xA2C8, 0x2477, 0xA2C9, 0x2478, 0xA2CA, 0x2479, 0xA2CB, 0x247A, 0xA2CC, 0x247B, 0xA2CD, 0x247C, 0xA2CE, 0x247D, 0xA2CF, 0x247E, + 0xA2D0, 0x247F, 0xA2D1, 0x2480, 0xA2D2, 0x2481, 0xA2D3, 0x2482, 0xA2D4, 0x2483, 0xA2D5, 0x2484, 0xA2D6, 0x2485, 0xA2D7, 0x2486, + 0xA2D8, 0x2487, 0xA2D9, 0x2460, 0xA2DA, 0x2461, 0xA2DB, 0x2462, 0xA2DC, 0x2463, 0xA2DD, 0x2464, 0xA2DE, 0x2465, 0xA2DF, 0x2466, + 0xA2E0, 0x2467, 0xA2E1, 0x2468, 0xA2E2, 0x2469, 0xA2E5, 0x3220, 0xA2E6, 0x3221, 0xA2E7, 0x3222, 0xA2E8, 0x3223, 0xA2E9, 0x3224, + 0xA2EA, 0x3225, 0xA2EB, 0x3226, 0xA2EC, 0x3227, 0xA2ED, 0x3228, 0xA2EE, 0x3229, 0xA2F1, 0x2160, 0xA2F2, 0x2161, 0xA2F3, 0x2162, + 0xA2F4, 0x2163, 0xA2F5, 0x2164, 0xA2F6, 0x2165, 0xA2F7, 0x2166, 0xA2F8, 0x2167, 0xA2F9, 0x2168, 0xA2FA, 0x2169, 0xA2FB, 0x216A, + 0xA2FC, 0x216B, 0xA3A1, 0xFF01, 0xA3A2, 0xFF02, 0xA3A3, 0xFF03, 0xA3A4, 0xFFE5, 0xA3A5, 0xFF05, 0xA3A6, 0xFF06, 0xA3A7, 0xFF07, + 0xA3A8, 0xFF08, 0xA3A9, 0xFF09, 0xA3AA, 0xFF0A, 0xA3AB, 0xFF0B, 0xA3AC, 0xFF0C, 0xA3AD, 0xFF0D, 0xA3AE, 0xFF0E, 0xA3AF, 0xFF0F, + 0xA3B0, 0xFF10, 0xA3B1, 0xFF11, 0xA3B2, 0xFF12, 0xA3B3, 0xFF13, 0xA3B4, 0xFF14, 0xA3B5, 0xFF15, 0xA3B6, 0xFF16, 0xA3B7, 0xFF17, + 0xA3B8, 0xFF18, 0xA3B9, 0xFF19, 0xA3BA, 0xFF1A, 0xA3BB, 0xFF1B, 0xA3BC, 0xFF1C, 0xA3BD, 0xFF1D, 0xA3BE, 0xFF1E, 0xA3BF, 0xFF1F, + 0xA3C0, 0xFF20, 0xA3C1, 0xFF21, 0xA3C2, 0xFF22, 0xA3C3, 0xFF23, 0xA3C4, 0xFF24, 0xA3C5, 0xFF25, 0xA3C6, 0xFF26, 0xA3C7, 0xFF27, + 0xA3C8, 0xFF28, 0xA3C9, 0xFF29, 0xA3CA, 0xFF2A, 0xA3CB, 0xFF2B, 0xA3CC, 0xFF2C, 0xA3CD, 0xFF2D, 0xA3CE, 0xFF2E, 0xA3CF, 0xFF2F, + 0xA3D0, 0xFF30, 0xA3D1, 0xFF31, 0xA3D2, 0xFF32, 0xA3D3, 0xFF33, 0xA3D4, 0xFF34, 0xA3D5, 0xFF35, 0xA3D6, 0xFF36, 0xA3D7, 0xFF37, + 0xA3D8, 0xFF38, 0xA3D9, 0xFF39, 0xA3DA, 0xFF3A, 0xA3DB, 0xFF3B, 0xA3DC, 0xFF3C, 0xA3DD, 0xFF3D, 0xA3DE, 0xFF3E, 0xA3DF, 0xFF3F, + 0xA3E0, 0xFF40, 0xA3E1, 0xFF41, 0xA3E2, 0xFF42, 0xA3E3, 0xFF43, 0xA3E4, 0xFF44, 0xA3E5, 0xFF45, 0xA3E6, 0xFF46, 0xA3E7, 0xFF47, + 0xA3E8, 0xFF48, 0xA3E9, 0xFF49, 0xA3EA, 0xFF4A, 0xA3EB, 0xFF4B, 0xA3EC, 0xFF4C, 0xA3ED, 0xFF4D, 0xA3EE, 0xFF4E, 0xA3EF, 0xFF4F, + 0xA3F0, 0xFF50, 0xA3F1, 0xFF51, 0xA3F2, 0xFF52, 0xA3F3, 0xFF53, 0xA3F4, 0xFF54, 0xA3F5, 0xFF55, 0xA3F6, 0xFF56, 0xA3F7, 0xFF57, + 0xA3F8, 0xFF58, 0xA3F9, 0xFF59, 0xA3FA, 0xFF5A, 0xA3FB, 0xFF5B, 0xA3FC, 0xFF5C, 0xA3FD, 0xFF5D, 0xA3FE, 0xFFE3, 0xA4A1, 0x3041, + 0xA4A2, 0x3042, 0xA4A3, 0x3043, 0xA4A4, 0x3044, 0xA4A5, 0x3045, 0xA4A6, 0x3046, 0xA4A7, 0x3047, 0xA4A8, 0x3048, 0xA4A9, 0x3049, + 0xA4AA, 0x304A, 0xA4AB, 0x304B, 0xA4AC, 0x304C, 0xA4AD, 0x304D, 0xA4AE, 0x304E, 0xA4AF, 0x304F, 0xA4B0, 0x3050, 0xA4B1, 0x3051, + 0xA4B2, 0x3052, 0xA4B3, 0x3053, 0xA4B4, 0x3054, 0xA4B5, 0x3055, 0xA4B6, 0x3056, 0xA4B7, 0x3057, 0xA4B8, 0x3058, 0xA4B9, 0x3059, + 0xA4BA, 0x305A, 0xA4BB, 0x305B, 0xA4BC, 0x305C, 0xA4BD, 0x305D, 0xA4BE, 0x305E, 0xA4BF, 0x305F, 0xA4C0, 0x3060, 0xA4C1, 0x3061, + 0xA4C2, 0x3062, 0xA4C3, 0x3063, 0xA4C4, 0x3064, 0xA4C5, 0x3065, 0xA4C6, 0x3066, 0xA4C7, 0x3067, 0xA4C8, 0x3068, 0xA4C9, 0x3069, + 0xA4CA, 0x306A, 0xA4CB, 0x306B, 0xA4CC, 0x306C, 0xA4CD, 0x306D, 0xA4CE, 0x306E, 0xA4CF, 0x306F, 0xA4D0, 0x3070, 0xA4D1, 0x3071, + 0xA4D2, 0x3072, 0xA4D3, 0x3073, 0xA4D4, 0x3074, 0xA4D5, 0x3075, 0xA4D6, 0x3076, 0xA4D7, 0x3077, 0xA4D8, 0x3078, 0xA4D9, 0x3079, + 0xA4DA, 0x307A, 0xA4DB, 0x307B, 0xA4DC, 0x307C, 0xA4DD, 0x307D, 0xA4DE, 0x307E, 0xA4DF, 0x307F, 0xA4E0, 0x3080, 0xA4E1, 0x3081, + 0xA4E2, 0x3082, 0xA4E3, 0x3083, 0xA4E4, 0x3084, 0xA4E5, 0x3085, 0xA4E6, 0x3086, 0xA4E7, 0x3087, 0xA4E8, 0x3088, 0xA4E9, 0x3089, + 0xA4EA, 0x308A, 0xA4EB, 0x308B, 0xA4EC, 0x308C, 0xA4ED, 0x308D, 0xA4EE, 0x308E, 0xA4EF, 0x308F, 0xA4F0, 0x3090, 0xA4F1, 0x3091, + 0xA4F2, 0x3092, 0xA4F3, 0x3093, 0xA5A1, 0x30A1, 0xA5A2, 0x30A2, 0xA5A3, 0x30A3, 0xA5A4, 0x30A4, 0xA5A5, 0x30A5, 0xA5A6, 0x30A6, + 0xA5A7, 0x30A7, 0xA5A8, 0x30A8, 0xA5A9, 0x30A9, 0xA5AA, 0x30AA, 0xA5AB, 0x30AB, 0xA5AC, 0x30AC, 0xA5AD, 0x30AD, 0xA5AE, 0x30AE, + 0xA5AF, 0x30AF, 0xA5B0, 0x30B0, 0xA5B1, 0x30B1, 0xA5B2, 0x30B2, 0xA5B3, 0x30B3, 0xA5B4, 0x30B4, 0xA5B5, 0x30B5, 0xA5B6, 0x30B6, + 0xA5B7, 0x30B7, 0xA5B8, 0x30B8, 0xA5B9, 0x30B9, 0xA5BA, 0x30BA, 0xA5BB, 0x30BB, 0xA5BC, 0x30BC, 0xA5BD, 0x30BD, 0xA5BE, 0x30BE, + 0xA5BF, 0x30BF, 0xA5C0, 0x30C0, 0xA5C1, 0x30C1, 0xA5C2, 0x30C2, 0xA5C3, 0x30C3, 0xA5C4, 0x30C4, 0xA5C5, 0x30C5, 0xA5C6, 0x30C6, + 0xA5C7, 0x30C7, 0xA5C8, 0x30C8, 0xA5C9, 0x30C9, 0xA5CA, 0x30CA, 0xA5CB, 0x30CB, 0xA5CC, 0x30CC, 0xA5CD, 0x30CD, 0xA5CE, 0x30CE, + 0xA5CF, 0x30CF, 0xA5D0, 0x30D0, 0xA5D1, 0x30D1, 0xA5D2, 0x30D2, 0xA5D3, 0x30D3, 0xA5D4, 0x30D4, 0xA5D5, 0x30D5, 0xA5D6, 0x30D6, + 0xA5D7, 0x30D7, 0xA5D8, 0x30D8, 0xA5D9, 0x30D9, 0xA5DA, 0x30DA, 0xA5DB, 0x30DB, 0xA5DC, 0x30DC, 0xA5DD, 0x30DD, 0xA5DE, 0x30DE, + 0xA5DF, 0x30DF, 0xA5E0, 0x30E0, 0xA5E1, 0x30E1, 0xA5E2, 0x30E2, 0xA5E3, 0x30E3, 0xA5E4, 0x30E4, 0xA5E5, 0x30E5, 0xA5E6, 0x30E6, + 0xA5E7, 0x30E7, 0xA5E8, 0x30E8, 0xA5E9, 0x30E9, 0xA5EA, 0x30EA, 0xA5EB, 0x30EB, 0xA5EC, 0x30EC, 0xA5ED, 0x30ED, 0xA5EE, 0x30EE, + 0xA5EF, 0x30EF, 0xA5F0, 0x30F0, 0xA5F1, 0x30F1, 0xA5F2, 0x30F2, 0xA5F3, 0x30F3, 0xA5F4, 0x30F4, 0xA5F5, 0x30F5, 0xA5F6, 0x30F6, + 0xA6A1, 0x0391, 0xA6A2, 0x0392, 0xA6A3, 0x0393, 0xA6A4, 0x0394, 0xA6A5, 0x0395, 0xA6A6, 0x0396, 0xA6A7, 0x0397, 0xA6A8, 0x0398, + 0xA6A9, 0x0399, 0xA6AA, 0x039A, 0xA6AB, 0x039B, 0xA6AC, 0x039C, 0xA6AD, 0x039D, 0xA6AE, 0x039E, 0xA6AF, 0x039F, 0xA6B0, 0x03A0, + 0xA6B1, 0x03A1, 0xA6B2, 0x03A3, 0xA6B3, 0x03A4, 0xA6B4, 0x03A5, 0xA6B5, 0x03A6, 0xA6B6, 0x03A7, 0xA6B7, 0x03A8, 0xA6B8, 0x03A9, + 0xA6C1, 0x03B1, 0xA6C2, 0x03B2, 0xA6C3, 0x03B3, 0xA6C4, 0x03B4, 0xA6C5, 0x03B5, 0xA6C6, 0x03B6, 0xA6C7, 0x03B7, 0xA6C8, 0x03B8, + 0xA6C9, 0x03B9, 0xA6CA, 0x03BA, 0xA6CB, 0x03BB, 0xA6CC, 0x03BC, 0xA6CD, 0x03BD, 0xA6CE, 0x03BE, 0xA6CF, 0x03BF, 0xA6D0, 0x03C0, + 0xA6D1, 0x03C1, 0xA6D2, 0x03C3, 0xA6D3, 0x03C4, 0xA6D4, 0x03C5, 0xA6D5, 0x03C6, 0xA6D6, 0x03C7, 0xA6D7, 0x03C8, 0xA6D8, 0x03C9, + 0xA6E0, 0xFE35, 0xA6E1, 0xFE36, 0xA6E2, 0xFE39, 0xA6E3, 0xFE3A, 0xA6E4, 0xFE3F, 0xA6E5, 0xFE40, 0xA6E6, 0xFE3D, 0xA6E7, 0xFE3E, + 0xA6E8, 0xFE41, 0xA6E9, 0xFE42, 0xA6EA, 0xFE43, 0xA6EB, 0xFE44, 0xA6EE, 0xFE3B, 0xA6EF, 0xFE3C, 0xA6F0, 0xFE37, 0xA6F1, 0xFE38, + 0xA6F2, 0xFE31, 0xA6F4, 0xFE33, 0xA6F5, 0xFE34, 0xA7A1, 0x0410, 0xA7A2, 0x0411, 0xA7A3, 0x0412, 0xA7A4, 0x0413, 0xA7A5, 0x0414, + 0xA7A6, 0x0415, 0xA7A7, 0x0401, 0xA7A8, 0x0416, 0xA7A9, 0x0417, 0xA7AA, 0x0418, 0xA7AB, 0x0419, 0xA7AC, 0x041A, 0xA7AD, 0x041B, + 0xA7AE, 0x041C, 0xA7AF, 0x041D, 0xA7B0, 0x041E, 0xA7B1, 0x041F, 0xA7B2, 0x0420, 0xA7B3, 0x0421, 0xA7B4, 0x0422, 0xA7B5, 0x0423, + 0xA7B6, 0x0424, 0xA7B7, 0x0425, 0xA7B8, 0x0426, 0xA7B9, 0x0427, 0xA7BA, 0x0428, 0xA7BB, 0x0429, 0xA7BC, 0x042A, 0xA7BD, 0x042B, + 0xA7BE, 0x042C, 0xA7BF, 0x042D, 0xA7C0, 0x042E, 0xA7C1, 0x042F, 0xA7D1, 0x0430, 0xA7D2, 0x0431, 0xA7D3, 0x0432, 0xA7D4, 0x0433, + 0xA7D5, 0x0434, 0xA7D6, 0x0435, 0xA7D7, 0x0451, 0xA7D8, 0x0436, 0xA7D9, 0x0437, 0xA7DA, 0x0438, 0xA7DB, 0x0439, 0xA7DC, 0x043A, + 0xA7DD, 0x043B, 0xA7DE, 0x043C, 0xA7DF, 0x043D, 0xA7E0, 0x043E, 0xA7E1, 0x043F, 0xA7E2, 0x0440, 0xA7E3, 0x0441, 0xA7E4, 0x0442, + 0xA7E5, 0x0443, 0xA7E6, 0x0444, 0xA7E7, 0x0445, 0xA7E8, 0x0446, 0xA7E9, 0x0447, 0xA7EA, 0x0448, 0xA7EB, 0x0449, 0xA7EC, 0x044A, + 0xA7ED, 0x044B, 0xA7EE, 0x044C, 0xA7EF, 0x044D, 0xA7F0, 0x044E, 0xA7F1, 0x044F, 0xA840, 0x02CA, 0xA841, 0x02CB, 0xA842, 0x02D9, + 0xA843, 0x2013, 0xA844, 0x2015, 0xA845, 0x2025, 0xA846, 0x2035, 0xA847, 0x2105, 0xA848, 0x2109, 0xA849, 0x2196, 0xA84A, 0x2197, + 0xA84B, 0x2198, 0xA84C, 0x2199, 0xA84D, 0x2215, 0xA84E, 0x221F, 0xA84F, 0x2223, 0xA850, 0x2252, 0xA851, 0x2266, 0xA852, 0x2267, + 0xA853, 0x22BF, 0xA854, 0x2550, 0xA855, 0x2551, 0xA856, 0x2552, 0xA857, 0x2553, 0xA858, 0x2554, 0xA859, 0x2555, 0xA85A, 0x2556, + 0xA85B, 0x2557, 0xA85C, 0x2558, 0xA85D, 0x2559, 0xA85E, 0x255A, 0xA85F, 0x255B, 0xA860, 0x255C, 0xA861, 0x255D, 0xA862, 0x255E, + 0xA863, 0x255F, 0xA864, 0x2560, 0xA865, 0x2561, 0xA866, 0x2562, 0xA867, 0x2563, 0xA868, 0x2564, 0xA869, 0x2565, 0xA86A, 0x2566, + 0xA86B, 0x2567, 0xA86C, 0x2568, 0xA86D, 0x2569, 0xA86E, 0x256A, 0xA86F, 0x256B, 0xA870, 0x256C, 0xA871, 0x256D, 0xA872, 0x256E, + 0xA873, 0x256F, 0xA874, 0x2570, 0xA875, 0x2571, 0xA876, 0x2572, 0xA877, 0x2573, 0xA878, 0x2581, 0xA879, 0x2582, 0xA87A, 0x2583, + 0xA87B, 0x2584, 0xA87C, 0x2585, 0xA87D, 0x2586, 0xA87E, 0x2587, 0xA880, 0x2588, 0xA881, 0x2589, 0xA882, 0x258A, 0xA883, 0x258B, + 0xA884, 0x258C, 0xA885, 0x258D, 0xA886, 0x258E, 0xA887, 0x258F, 0xA888, 0x2593, 0xA889, 0x2594, 0xA88A, 0x2595, 0xA88B, 0x25BC, + 0xA88C, 0x25BD, 0xA88D, 0x25E2, 0xA88E, 0x25E3, 0xA88F, 0x25E4, 0xA890, 0x25E5, 0xA891, 0x2609, 0xA892, 0x2295, 0xA893, 0x3012, + 0xA894, 0x301D, 0xA895, 0x301E, 0xA8A1, 0x0101, 0xA8A2, 0x00E1, 0xA8A3, 0x01CE, 0xA8A4, 0x00E0, 0xA8A5, 0x0113, 0xA8A6, 0x00E9, + 0xA8A7, 0x011B, 0xA8A8, 0x00E8, 0xA8A9, 0x012B, 0xA8AA, 0x00ED, 0xA8AB, 0x01D0, 0xA8AC, 0x00EC, 0xA8AD, 0x014D, 0xA8AE, 0x00F3, + 0xA8AF, 0x01D2, 0xA8B0, 0x00F2, 0xA8B1, 0x016B, 0xA8B2, 0x00FA, 0xA8B3, 0x01D4, 0xA8B4, 0x00F9, 0xA8B5, 0x01D6, 0xA8B6, 0x01D8, + 0xA8B7, 0x01DA, 0xA8B8, 0x01DC, 0xA8B9, 0x00FC, 0xA8BA, 0x00EA, 0xA8BB, 0x0251, 0xA8BD, 0x0144, 0xA8BE, 0x0148, 0xA8C0, 0x0261, + 0xA8C5, 0x3105, 0xA8C6, 0x3106, 0xA8C7, 0x3107, 0xA8C8, 0x3108, 0xA8C9, 0x3109, 0xA8CA, 0x310A, 0xA8CB, 0x310B, 0xA8CC, 0x310C, + 0xA8CD, 0x310D, 0xA8CE, 0x310E, 0xA8CF, 0x310F, 0xA8D0, 0x3110, 0xA8D1, 0x3111, 0xA8D2, 0x3112, 0xA8D3, 0x3113, 0xA8D4, 0x3114, + 0xA8D5, 0x3115, 0xA8D6, 0x3116, 0xA8D7, 0x3117, 0xA8D8, 0x3118, 0xA8D9, 0x3119, 0xA8DA, 0x311A, 0xA8DB, 0x311B, 0xA8DC, 0x311C, + 0xA8DD, 0x311D, 0xA8DE, 0x311E, 0xA8DF, 0x311F, 0xA8E0, 0x3120, 0xA8E1, 0x3121, 0xA8E2, 0x3122, 0xA8E3, 0x3123, 0xA8E4, 0x3124, + 0xA8E5, 0x3125, 0xA8E6, 0x3126, 0xA8E7, 0x3127, 0xA8E8, 0x3128, 0xA8E9, 0x3129, 0xA940, 0x3021, 0xA941, 0x3022, 0xA942, 0x3023, + 0xA943, 0x3024, 0xA944, 0x3025, 0xA945, 0x3026, 0xA946, 0x3027, 0xA947, 0x3028, 0xA948, 0x3029, 0xA949, 0x32A3, 0xA94A, 0x338E, + 0xA94B, 0x338F, 0xA94C, 0x339C, 0xA94D, 0x339D, 0xA94E, 0x339E, 0xA94F, 0x33A1, 0xA950, 0x33C4, 0xA951, 0x33CE, 0xA952, 0x33D1, + 0xA953, 0x33D2, 0xA954, 0x33D5, 0xA955, 0xFE30, 0xA956, 0xFFE2, 0xA957, 0xFFE4, 0xA959, 0x2121, 0xA95A, 0x3231, 0xA95C, 0x2010, + 0xA960, 0x30FC, 0xA961, 0x309B, 0xA962, 0x309C, 0xA963, 0x30FD, 0xA964, 0x30FE, 0xA965, 0x3006, 0xA966, 0x309D, 0xA967, 0x309E, + 0xA968, 0xFE49, 0xA969, 0xFE4A, 0xA96A, 0xFE4B, 0xA96B, 0xFE4C, 0xA96C, 0xFE4D, 0xA96D, 0xFE4E, 0xA96E, 0xFE4F, 0xA96F, 0xFE50, + 0xA970, 0xFE51, 0xA971, 0xFE52, 0xA972, 0xFE54, 0xA973, 0xFE55, 0xA974, 0xFE56, 0xA975, 0xFE57, 0xA976, 0xFE59, 0xA977, 0xFE5A, + 0xA978, 0xFE5B, 0xA979, 0xFE5C, 0xA97A, 0xFE5D, 0xA97B, 0xFE5E, 0xA97C, 0xFE5F, 0xA97D, 0xFE60, 0xA97E, 0xFE61, 0xA980, 0xFE62, + 0xA981, 0xFE63, 0xA982, 0xFE64, 0xA983, 0xFE65, 0xA984, 0xFE66, 0xA985, 0xFE68, 0xA986, 0xFE69, 0xA987, 0xFE6A, 0xA988, 0xFE6B, + 0xA996, 0x3007, 0xA9A4, 0x2500, 0xA9A5, 0x2501, 0xA9A6, 0x2502, 0xA9A7, 0x2503, 0xA9A8, 0x2504, 0xA9A9, 0x2505, 0xA9AA, 0x2506, + 0xA9AB, 0x2507, 0xA9AC, 0x2508, 0xA9AD, 0x2509, 0xA9AE, 0x250A, 0xA9AF, 0x250B, 0xA9B0, 0x250C, 0xA9B1, 0x250D, 0xA9B2, 0x250E, + 0xA9B3, 0x250F, 0xA9B4, 0x2510, 0xA9B5, 0x2511, 0xA9B6, 0x2512, 0xA9B7, 0x2513, 0xA9B8, 0x2514, 0xA9B9, 0x2515, 0xA9BA, 0x2516, + 0xA9BB, 0x2517, 0xA9BC, 0x2518, 0xA9BD, 0x2519, 0xA9BE, 0x251A, 0xA9BF, 0x251B, 0xA9C0, 0x251C, 0xA9C1, 0x251D, 0xA9C2, 0x251E, + 0xA9C3, 0x251F, 0xA9C4, 0x2520, 0xA9C5, 0x2521, 0xA9C6, 0x2522, 0xA9C7, 0x2523, 0xA9C8, 0x2524, 0xA9C9, 0x2525, 0xA9CA, 0x2526, + 0xA9CB, 0x2527, 0xA9CC, 0x2528, 0xA9CD, 0x2529, 0xA9CE, 0x252A, 0xA9CF, 0x252B, 0xA9D0, 0x252C, 0xA9D1, 0x252D, 0xA9D2, 0x252E, + 0xA9D3, 0x252F, 0xA9D4, 0x2530, 0xA9D5, 0x2531, 0xA9D6, 0x2532, 0xA9D7, 0x2533, 0xA9D8, 0x2534, 0xA9D9, 0x2535, 0xA9DA, 0x2536, + 0xA9DB, 0x2537, 0xA9DC, 0x2538, 0xA9DD, 0x2539, 0xA9DE, 0x253A, 0xA9DF, 0x253B, 0xA9E0, 0x253C, 0xA9E1, 0x253D, 0xA9E2, 0x253E, + 0xA9E3, 0x253F, 0xA9E4, 0x2540, 0xA9E5, 0x2541, 0xA9E6, 0x2542, 0xA9E7, 0x2543, 0xA9E8, 0x2544, 0xA9E9, 0x2545, 0xA9EA, 0x2546, + 0xA9EB, 0x2547, 0xA9EC, 0x2548, 0xA9ED, 0x2549, 0xA9EE, 0x254A, 0xA9EF, 0x254B, 0xAA40, 0x72DC, 0xAA41, 0x72DD, 0xAA42, 0x72DF, + 0xAA43, 0x72E2, 0xAA44, 0x72E3, 0xAA45, 0x72E4, 0xAA46, 0x72E5, 0xAA47, 0x72E6, 0xAA48, 0x72E7, 0xAA49, 0x72EA, 0xAA4A, 0x72EB, + 0xAA4B, 0x72F5, 0xAA4C, 0x72F6, 0xAA4D, 0x72F9, 0xAA4E, 0x72FD, 0xAA4F, 0x72FE, 0xAA50, 0x72FF, 0xAA51, 0x7300, 0xAA52, 0x7302, + 0xAA53, 0x7304, 0xAA54, 0x7305, 0xAA55, 0x7306, 0xAA56, 0x7307, 0xAA57, 0x7308, 0xAA58, 0x7309, 0xAA59, 0x730B, 0xAA5A, 0x730C, + 0xAA5B, 0x730D, 0xAA5C, 0x730F, 0xAA5D, 0x7310, 0xAA5E, 0x7311, 0xAA5F, 0x7312, 0xAA60, 0x7314, 0xAA61, 0x7318, 0xAA62, 0x7319, + 0xAA63, 0x731A, 0xAA64, 0x731F, 0xAA65, 0x7320, 0xAA66, 0x7323, 0xAA67, 0x7324, 0xAA68, 0x7326, 0xAA69, 0x7327, 0xAA6A, 0x7328, + 0xAA6B, 0x732D, 0xAA6C, 0x732F, 0xAA6D, 0x7330, 0xAA6E, 0x7332, 0xAA6F, 0x7333, 0xAA70, 0x7335, 0xAA71, 0x7336, 0xAA72, 0x733A, + 0xAA73, 0x733B, 0xAA74, 0x733C, 0xAA75, 0x733D, 0xAA76, 0x7340, 0xAA77, 0x7341, 0xAA78, 0x7342, 0xAA79, 0x7343, 0xAA7A, 0x7344, + 0xAA7B, 0x7345, 0xAA7C, 0x7346, 0xAA7D, 0x7347, 0xAA7E, 0x7348, 0xAA80, 0x7349, 0xAA81, 0x734A, 0xAA82, 0x734B, 0xAA83, 0x734C, + 0xAA84, 0x734E, 0xAA85, 0x734F, 0xAA86, 0x7351, 0xAA87, 0x7353, 0xAA88, 0x7354, 0xAA89, 0x7355, 0xAA8A, 0x7356, 0xAA8B, 0x7358, + 0xAA8C, 0x7359, 0xAA8D, 0x735A, 0xAA8E, 0x735B, 0xAA8F, 0x735C, 0xAA90, 0x735D, 0xAA91, 0x735E, 0xAA92, 0x735F, 0xAA93, 0x7361, + 0xAA94, 0x7362, 0xAA95, 0x7363, 0xAA96, 0x7364, 0xAA97, 0x7365, 0xAA98, 0x7366, 0xAA99, 0x7367, 0xAA9A, 0x7368, 0xAA9B, 0x7369, + 0xAA9C, 0x736A, 0xAA9D, 0x736B, 0xAA9E, 0x736E, 0xAA9F, 0x7370, 0xAAA0, 0x7371, 0xAB40, 0x7372, 0xAB41, 0x7373, 0xAB42, 0x7374, + 0xAB43, 0x7375, 0xAB44, 0x7376, 0xAB45, 0x7377, 0xAB46, 0x7378, 0xAB47, 0x7379, 0xAB48, 0x737A, 0xAB49, 0x737B, 0xAB4A, 0x737C, + 0xAB4B, 0x737D, 0xAB4C, 0x737F, 0xAB4D, 0x7380, 0xAB4E, 0x7381, 0xAB4F, 0x7382, 0xAB50, 0x7383, 0xAB51, 0x7385, 0xAB52, 0x7386, + 0xAB53, 0x7388, 0xAB54, 0x738A, 0xAB55, 0x738C, 0xAB56, 0x738D, 0xAB57, 0x738F, 0xAB58, 0x7390, 0xAB59, 0x7392, 0xAB5A, 0x7393, + 0xAB5B, 0x7394, 0xAB5C, 0x7395, 0xAB5D, 0x7397, 0xAB5E, 0x7398, 0xAB5F, 0x7399, 0xAB60, 0x739A, 0xAB61, 0x739C, 0xAB62, 0x739D, + 0xAB63, 0x739E, 0xAB64, 0x73A0, 0xAB65, 0x73A1, 0xAB66, 0x73A3, 0xAB67, 0x73A4, 0xAB68, 0x73A5, 0xAB69, 0x73A6, 0xAB6A, 0x73A7, + 0xAB6B, 0x73A8, 0xAB6C, 0x73AA, 0xAB6D, 0x73AC, 0xAB6E, 0x73AD, 0xAB6F, 0x73B1, 0xAB70, 0x73B4, 0xAB71, 0x73B5, 0xAB72, 0x73B6, + 0xAB73, 0x73B8, 0xAB74, 0x73B9, 0xAB75, 0x73BC, 0xAB76, 0x73BD, 0xAB77, 0x73BE, 0xAB78, 0x73BF, 0xAB79, 0x73C1, 0xAB7A, 0x73C3, + 0xAB7B, 0x73C4, 0xAB7C, 0x73C5, 0xAB7D, 0x73C6, 0xAB7E, 0x73C7, 0xAB80, 0x73CB, 0xAB81, 0x73CC, 0xAB82, 0x73CE, 0xAB83, 0x73D2, + 0xAB84, 0x73D3, 0xAB85, 0x73D4, 0xAB86, 0x73D5, 0xAB87, 0x73D6, 0xAB88, 0x73D7, 0xAB89, 0x73D8, 0xAB8A, 0x73DA, 0xAB8B, 0x73DB, + 0xAB8C, 0x73DC, 0xAB8D, 0x73DD, 0xAB8E, 0x73DF, 0xAB8F, 0x73E1, 0xAB90, 0x73E2, 0xAB91, 0x73E3, 0xAB92, 0x73E4, 0xAB93, 0x73E6, + 0xAB94, 0x73E8, 0xAB95, 0x73EA, 0xAB96, 0x73EB, 0xAB97, 0x73EC, 0xAB98, 0x73EE, 0xAB99, 0x73EF, 0xAB9A, 0x73F0, 0xAB9B, 0x73F1, + 0xAB9C, 0x73F3, 0xAB9D, 0x73F4, 0xAB9E, 0x73F5, 0xAB9F, 0x73F6, 0xABA0, 0x73F7, 0xAC40, 0x73F8, 0xAC41, 0x73F9, 0xAC42, 0x73FA, + 0xAC43, 0x73FB, 0xAC44, 0x73FC, 0xAC45, 0x73FD, 0xAC46, 0x73FE, 0xAC47, 0x73FF, 0xAC48, 0x7400, 0xAC49, 0x7401, 0xAC4A, 0x7402, + 0xAC4B, 0x7404, 0xAC4C, 0x7407, 0xAC4D, 0x7408, 0xAC4E, 0x740B, 0xAC4F, 0x740C, 0xAC50, 0x740D, 0xAC51, 0x740E, 0xAC52, 0x7411, + 0xAC53, 0x7412, 0xAC54, 0x7413, 0xAC55, 0x7414, 0xAC56, 0x7415, 0xAC57, 0x7416, 0xAC58, 0x7417, 0xAC59, 0x7418, 0xAC5A, 0x7419, + 0xAC5B, 0x741C, 0xAC5C, 0x741D, 0xAC5D, 0x741E, 0xAC5E, 0x741F, 0xAC5F, 0x7420, 0xAC60, 0x7421, 0xAC61, 0x7423, 0xAC62, 0x7424, + 0xAC63, 0x7427, 0xAC64, 0x7429, 0xAC65, 0x742B, 0xAC66, 0x742D, 0xAC67, 0x742F, 0xAC68, 0x7431, 0xAC69, 0x7432, 0xAC6A, 0x7437, + 0xAC6B, 0x7438, 0xAC6C, 0x7439, 0xAC6D, 0x743A, 0xAC6E, 0x743B, 0xAC6F, 0x743D, 0xAC70, 0x743E, 0xAC71, 0x743F, 0xAC72, 0x7440, + 0xAC73, 0x7442, 0xAC74, 0x7443, 0xAC75, 0x7444, 0xAC76, 0x7445, 0xAC77, 0x7446, 0xAC78, 0x7447, 0xAC79, 0x7448, 0xAC7A, 0x7449, + 0xAC7B, 0x744A, 0xAC7C, 0x744B, 0xAC7D, 0x744C, 0xAC7E, 0x744D, 0xAC80, 0x744E, 0xAC81, 0x744F, 0xAC82, 0x7450, 0xAC83, 0x7451, + 0xAC84, 0x7452, 0xAC85, 0x7453, 0xAC86, 0x7454, 0xAC87, 0x7456, 0xAC88, 0x7458, 0xAC89, 0x745D, 0xAC8A, 0x7460, 0xAC8B, 0x7461, + 0xAC8C, 0x7462, 0xAC8D, 0x7463, 0xAC8E, 0x7464, 0xAC8F, 0x7465, 0xAC90, 0x7466, 0xAC91, 0x7467, 0xAC92, 0x7468, 0xAC93, 0x7469, + 0xAC94, 0x746A, 0xAC95, 0x746B, 0xAC96, 0x746C, 0xAC97, 0x746E, 0xAC98, 0x746F, 0xAC99, 0x7471, 0xAC9A, 0x7472, 0xAC9B, 0x7473, + 0xAC9C, 0x7474, 0xAC9D, 0x7475, 0xAC9E, 0x7478, 0xAC9F, 0x7479, 0xACA0, 0x747A, 0xAD40, 0x747B, 0xAD41, 0x747C, 0xAD42, 0x747D, + 0xAD43, 0x747F, 0xAD44, 0x7482, 0xAD45, 0x7484, 0xAD46, 0x7485, 0xAD47, 0x7486, 0xAD48, 0x7488, 0xAD49, 0x7489, 0xAD4A, 0x748A, + 0xAD4B, 0x748C, 0xAD4C, 0x748D, 0xAD4D, 0x748F, 0xAD4E, 0x7491, 0xAD4F, 0x7492, 0xAD50, 0x7493, 0xAD51, 0x7494, 0xAD52, 0x7495, + 0xAD53, 0x7496, 0xAD54, 0x7497, 0xAD55, 0x7498, 0xAD56, 0x7499, 0xAD57, 0x749A, 0xAD58, 0x749B, 0xAD59, 0x749D, 0xAD5A, 0x749F, + 0xAD5B, 0x74A0, 0xAD5C, 0x74A1, 0xAD5D, 0x74A2, 0xAD5E, 0x74A3, 0xAD5F, 0x74A4, 0xAD60, 0x74A5, 0xAD61, 0x74A6, 0xAD62, 0x74AA, + 0xAD63, 0x74AB, 0xAD64, 0x74AC, 0xAD65, 0x74AD, 0xAD66, 0x74AE, 0xAD67, 0x74AF, 0xAD68, 0x74B0, 0xAD69, 0x74B1, 0xAD6A, 0x74B2, + 0xAD6B, 0x74B3, 0xAD6C, 0x74B4, 0xAD6D, 0x74B5, 0xAD6E, 0x74B6, 0xAD6F, 0x74B7, 0xAD70, 0x74B8, 0xAD71, 0x74B9, 0xAD72, 0x74BB, + 0xAD73, 0x74BC, 0xAD74, 0x74BD, 0xAD75, 0x74BE, 0xAD76, 0x74BF, 0xAD77, 0x74C0, 0xAD78, 0x74C1, 0xAD79, 0x74C2, 0xAD7A, 0x74C3, + 0xAD7B, 0x74C4, 0xAD7C, 0x74C5, 0xAD7D, 0x74C6, 0xAD7E, 0x74C7, 0xAD80, 0x74C8, 0xAD81, 0x74C9, 0xAD82, 0x74CA, 0xAD83, 0x74CB, + 0xAD84, 0x74CC, 0xAD85, 0x74CD, 0xAD86, 0x74CE, 0xAD87, 0x74CF, 0xAD88, 0x74D0, 0xAD89, 0x74D1, 0xAD8A, 0x74D3, 0xAD8B, 0x74D4, + 0xAD8C, 0x74D5, 0xAD8D, 0x74D6, 0xAD8E, 0x74D7, 0xAD8F, 0x74D8, 0xAD90, 0x74D9, 0xAD91, 0x74DA, 0xAD92, 0x74DB, 0xAD93, 0x74DD, + 0xAD94, 0x74DF, 0xAD95, 0x74E1, 0xAD96, 0x74E5, 0xAD97, 0x74E7, 0xAD98, 0x74E8, 0xAD99, 0x74E9, 0xAD9A, 0x74EA, 0xAD9B, 0x74EB, + 0xAD9C, 0x74EC, 0xAD9D, 0x74ED, 0xAD9E, 0x74F0, 0xAD9F, 0x74F1, 0xADA0, 0x74F2, 0xAE40, 0x74F3, 0xAE41, 0x74F5, 0xAE42, 0x74F8, + 0xAE43, 0x74F9, 0xAE44, 0x74FA, 0xAE45, 0x74FB, 0xAE46, 0x74FC, 0xAE47, 0x74FD, 0xAE48, 0x74FE, 0xAE49, 0x7500, 0xAE4A, 0x7501, + 0xAE4B, 0x7502, 0xAE4C, 0x7503, 0xAE4D, 0x7505, 0xAE4E, 0x7506, 0xAE4F, 0x7507, 0xAE50, 0x7508, 0xAE51, 0x7509, 0xAE52, 0x750A, + 0xAE53, 0x750B, 0xAE54, 0x750C, 0xAE55, 0x750E, 0xAE56, 0x7510, 0xAE57, 0x7512, 0xAE58, 0x7514, 0xAE59, 0x7515, 0xAE5A, 0x7516, + 0xAE5B, 0x7517, 0xAE5C, 0x751B, 0xAE5D, 0x751D, 0xAE5E, 0x751E, 0xAE5F, 0x7520, 0xAE60, 0x7521, 0xAE61, 0x7522, 0xAE62, 0x7523, + 0xAE63, 0x7524, 0xAE64, 0x7526, 0xAE65, 0x7527, 0xAE66, 0x752A, 0xAE67, 0x752E, 0xAE68, 0x7534, 0xAE69, 0x7536, 0xAE6A, 0x7539, + 0xAE6B, 0x753C, 0xAE6C, 0x753D, 0xAE6D, 0x753F, 0xAE6E, 0x7541, 0xAE6F, 0x7542, 0xAE70, 0x7543, 0xAE71, 0x7544, 0xAE72, 0x7546, + 0xAE73, 0x7547, 0xAE74, 0x7549, 0xAE75, 0x754A, 0xAE76, 0x754D, 0xAE77, 0x7550, 0xAE78, 0x7551, 0xAE79, 0x7552, 0xAE7A, 0x7553, + 0xAE7B, 0x7555, 0xAE7C, 0x7556, 0xAE7D, 0x7557, 0xAE7E, 0x7558, 0xAE80, 0x755D, 0xAE81, 0x755E, 0xAE82, 0x755F, 0xAE83, 0x7560, + 0xAE84, 0x7561, 0xAE85, 0x7562, 0xAE86, 0x7563, 0xAE87, 0x7564, 0xAE88, 0x7567, 0xAE89, 0x7568, 0xAE8A, 0x7569, 0xAE8B, 0x756B, + 0xAE8C, 0x756C, 0xAE8D, 0x756D, 0xAE8E, 0x756E, 0xAE8F, 0x756F, 0xAE90, 0x7570, 0xAE91, 0x7571, 0xAE92, 0x7573, 0xAE93, 0x7575, + 0xAE94, 0x7576, 0xAE95, 0x7577, 0xAE96, 0x757A, 0xAE97, 0x757B, 0xAE98, 0x757C, 0xAE99, 0x757D, 0xAE9A, 0x757E, 0xAE9B, 0x7580, + 0xAE9C, 0x7581, 0xAE9D, 0x7582, 0xAE9E, 0x7584, 0xAE9F, 0x7585, 0xAEA0, 0x7587, 0xAF40, 0x7588, 0xAF41, 0x7589, 0xAF42, 0x758A, + 0xAF43, 0x758C, 0xAF44, 0x758D, 0xAF45, 0x758E, 0xAF46, 0x7590, 0xAF47, 0x7593, 0xAF48, 0x7595, 0xAF49, 0x7598, 0xAF4A, 0x759B, + 0xAF4B, 0x759C, 0xAF4C, 0x759E, 0xAF4D, 0x75A2, 0xAF4E, 0x75A6, 0xAF4F, 0x75A7, 0xAF50, 0x75A8, 0xAF51, 0x75A9, 0xAF52, 0x75AA, + 0xAF53, 0x75AD, 0xAF54, 0x75B6, 0xAF55, 0x75B7, 0xAF56, 0x75BA, 0xAF57, 0x75BB, 0xAF58, 0x75BF, 0xAF59, 0x75C0, 0xAF5A, 0x75C1, + 0xAF5B, 0x75C6, 0xAF5C, 0x75CB, 0xAF5D, 0x75CC, 0xAF5E, 0x75CE, 0xAF5F, 0x75CF, 0xAF60, 0x75D0, 0xAF61, 0x75D1, 0xAF62, 0x75D3, + 0xAF63, 0x75D7, 0xAF64, 0x75D9, 0xAF65, 0x75DA, 0xAF66, 0x75DC, 0xAF67, 0x75DD, 0xAF68, 0x75DF, 0xAF69, 0x75E0, 0xAF6A, 0x75E1, + 0xAF6B, 0x75E5, 0xAF6C, 0x75E9, 0xAF6D, 0x75EC, 0xAF6E, 0x75ED, 0xAF6F, 0x75EE, 0xAF70, 0x75EF, 0xAF71, 0x75F2, 0xAF72, 0x75F3, + 0xAF73, 0x75F5, 0xAF74, 0x75F6, 0xAF75, 0x75F7, 0xAF76, 0x75F8, 0xAF77, 0x75FA, 0xAF78, 0x75FB, 0xAF79, 0x75FD, 0xAF7A, 0x75FE, + 0xAF7B, 0x7602, 0xAF7C, 0x7604, 0xAF7D, 0x7606, 0xAF7E, 0x7607, 0xAF80, 0x7608, 0xAF81, 0x7609, 0xAF82, 0x760B, 0xAF83, 0x760D, + 0xAF84, 0x760E, 0xAF85, 0x760F, 0xAF86, 0x7611, 0xAF87, 0x7612, 0xAF88, 0x7613, 0xAF89, 0x7614, 0xAF8A, 0x7616, 0xAF8B, 0x761A, + 0xAF8C, 0x761C, 0xAF8D, 0x761D, 0xAF8E, 0x761E, 0xAF8F, 0x7621, 0xAF90, 0x7623, 0xAF91, 0x7627, 0xAF92, 0x7628, 0xAF93, 0x762C, + 0xAF94, 0x762E, 0xAF95, 0x762F, 0xAF96, 0x7631, 0xAF97, 0x7632, 0xAF98, 0x7636, 0xAF99, 0x7637, 0xAF9A, 0x7639, 0xAF9B, 0x763A, + 0xAF9C, 0x763B, 0xAF9D, 0x763D, 0xAF9E, 0x7641, 0xAF9F, 0x7642, 0xAFA0, 0x7644, 0xB040, 0x7645, 0xB041, 0x7646, 0xB042, 0x7647, + 0xB043, 0x7648, 0xB044, 0x7649, 0xB045, 0x764A, 0xB046, 0x764B, 0xB047, 0x764E, 0xB048, 0x764F, 0xB049, 0x7650, 0xB04A, 0x7651, + 0xB04B, 0x7652, 0xB04C, 0x7653, 0xB04D, 0x7655, 0xB04E, 0x7657, 0xB04F, 0x7658, 0xB050, 0x7659, 0xB051, 0x765A, 0xB052, 0x765B, + 0xB053, 0x765D, 0xB054, 0x765F, 0xB055, 0x7660, 0xB056, 0x7661, 0xB057, 0x7662, 0xB058, 0x7664, 0xB059, 0x7665, 0xB05A, 0x7666, + 0xB05B, 0x7667, 0xB05C, 0x7668, 0xB05D, 0x7669, 0xB05E, 0x766A, 0xB05F, 0x766C, 0xB060, 0x766D, 0xB061, 0x766E, 0xB062, 0x7670, + 0xB063, 0x7671, 0xB064, 0x7672, 0xB065, 0x7673, 0xB066, 0x7674, 0xB067, 0x7675, 0xB068, 0x7676, 0xB069, 0x7677, 0xB06A, 0x7679, + 0xB06B, 0x767A, 0xB06C, 0x767C, 0xB06D, 0x767F, 0xB06E, 0x7680, 0xB06F, 0x7681, 0xB070, 0x7683, 0xB071, 0x7685, 0xB072, 0x7689, + 0xB073, 0x768A, 0xB074, 0x768C, 0xB075, 0x768D, 0xB076, 0x768F, 0xB077, 0x7690, 0xB078, 0x7692, 0xB079, 0x7694, 0xB07A, 0x7695, + 0xB07B, 0x7697, 0xB07C, 0x7698, 0xB07D, 0x769A, 0xB07E, 0x769B, 0xB080, 0x769C, 0xB081, 0x769D, 0xB082, 0x769E, 0xB083, 0x769F, + 0xB084, 0x76A0, 0xB085, 0x76A1, 0xB086, 0x76A2, 0xB087, 0x76A3, 0xB088, 0x76A5, 0xB089, 0x76A6, 0xB08A, 0x76A7, 0xB08B, 0x76A8, + 0xB08C, 0x76A9, 0xB08D, 0x76AA, 0xB08E, 0x76AB, 0xB08F, 0x76AC, 0xB090, 0x76AD, 0xB091, 0x76AF, 0xB092, 0x76B0, 0xB093, 0x76B3, + 0xB094, 0x76B5, 0xB095, 0x76B6, 0xB096, 0x76B7, 0xB097, 0x76B8, 0xB098, 0x76B9, 0xB099, 0x76BA, 0xB09A, 0x76BB, 0xB09B, 0x76BC, + 0xB09C, 0x76BD, 0xB09D, 0x76BE, 0xB09E, 0x76C0, 0xB09F, 0x76C1, 0xB0A0, 0x76C3, 0xB0A1, 0x554A, 0xB0A2, 0x963F, 0xB0A3, 0x57C3, + 0xB0A4, 0x6328, 0xB0A5, 0x54CE, 0xB0A6, 0x5509, 0xB0A7, 0x54C0, 0xB0A8, 0x7691, 0xB0A9, 0x764C, 0xB0AA, 0x853C, 0xB0AB, 0x77EE, + 0xB0AC, 0x827E, 0xB0AD, 0x788D, 0xB0AE, 0x7231, 0xB0AF, 0x9698, 0xB0B0, 0x978D, 0xB0B1, 0x6C28, 0xB0B2, 0x5B89, 0xB0B3, 0x4FFA, + 0xB0B4, 0x6309, 0xB0B5, 0x6697, 0xB0B6, 0x5CB8, 0xB0B7, 0x80FA, 0xB0B8, 0x6848, 0xB0B9, 0x80AE, 0xB0BA, 0x6602, 0xB0BB, 0x76CE, + 0xB0BC, 0x51F9, 0xB0BD, 0x6556, 0xB0BE, 0x71AC, 0xB0BF, 0x7FF1, 0xB0C0, 0x8884, 0xB0C1, 0x50B2, 0xB0C2, 0x5965, 0xB0C3, 0x61CA, + 0xB0C4, 0x6FB3, 0xB0C5, 0x82AD, 0xB0C6, 0x634C, 0xB0C7, 0x6252, 0xB0C8, 0x53ED, 0xB0C9, 0x5427, 0xB0CA, 0x7B06, 0xB0CB, 0x516B, + 0xB0CC, 0x75A4, 0xB0CD, 0x5DF4, 0xB0CE, 0x62D4, 0xB0CF, 0x8DCB, 0xB0D0, 0x9776, 0xB0D1, 0x628A, 0xB0D2, 0x8019, 0xB0D3, 0x575D, + 0xB0D4, 0x9738, 0xB0D5, 0x7F62, 0xB0D6, 0x7238, 0xB0D7, 0x767D, 0xB0D8, 0x67CF, 0xB0D9, 0x767E, 0xB0DA, 0x6446, 0xB0DB, 0x4F70, + 0xB0DC, 0x8D25, 0xB0DD, 0x62DC, 0xB0DE, 0x7A17, 0xB0DF, 0x6591, 0xB0E0, 0x73ED, 0xB0E1, 0x642C, 0xB0E2, 0x6273, 0xB0E3, 0x822C, + 0xB0E4, 0x9881, 0xB0E5, 0x677F, 0xB0E6, 0x7248, 0xB0E7, 0x626E, 0xB0E8, 0x62CC, 0xB0E9, 0x4F34, 0xB0EA, 0x74E3, 0xB0EB, 0x534A, + 0xB0EC, 0x529E, 0xB0ED, 0x7ECA, 0xB0EE, 0x90A6, 0xB0EF, 0x5E2E, 0xB0F0, 0x6886, 0xB0F1, 0x699C, 0xB0F2, 0x8180, 0xB0F3, 0x7ED1, + 0xB0F4, 0x68D2, 0xB0F5, 0x78C5, 0xB0F6, 0x868C, 0xB0F7, 0x9551, 0xB0F8, 0x508D, 0xB0F9, 0x8C24, 0xB0FA, 0x82DE, 0xB0FB, 0x80DE, + 0xB0FC, 0x5305, 0xB0FD, 0x8912, 0xB0FE, 0x5265, 0xB140, 0x76C4, 0xB141, 0x76C7, 0xB142, 0x76C9, 0xB143, 0x76CB, 0xB144, 0x76CC, + 0xB145, 0x76D3, 0xB146, 0x76D5, 0xB147, 0x76D9, 0xB148, 0x76DA, 0xB149, 0x76DC, 0xB14A, 0x76DD, 0xB14B, 0x76DE, 0xB14C, 0x76E0, + 0xB14D, 0x76E1, 0xB14E, 0x76E2, 0xB14F, 0x76E3, 0xB150, 0x76E4, 0xB151, 0x76E6, 0xB152, 0x76E7, 0xB153, 0x76E8, 0xB154, 0x76E9, + 0xB155, 0x76EA, 0xB156, 0x76EB, 0xB157, 0x76EC, 0xB158, 0x76ED, 0xB159, 0x76F0, 0xB15A, 0x76F3, 0xB15B, 0x76F5, 0xB15C, 0x76F6, + 0xB15D, 0x76F7, 0xB15E, 0x76FA, 0xB15F, 0x76FB, 0xB160, 0x76FD, 0xB161, 0x76FF, 0xB162, 0x7700, 0xB163, 0x7702, 0xB164, 0x7703, + 0xB165, 0x7705, 0xB166, 0x7706, 0xB167, 0x770A, 0xB168, 0x770C, 0xB169, 0x770E, 0xB16A, 0x770F, 0xB16B, 0x7710, 0xB16C, 0x7711, + 0xB16D, 0x7712, 0xB16E, 0x7713, 0xB16F, 0x7714, 0xB170, 0x7715, 0xB171, 0x7716, 0xB172, 0x7717, 0xB173, 0x7718, 0xB174, 0x771B, + 0xB175, 0x771C, 0xB176, 0x771D, 0xB177, 0x771E, 0xB178, 0x7721, 0xB179, 0x7723, 0xB17A, 0x7724, 0xB17B, 0x7725, 0xB17C, 0x7727, + 0xB17D, 0x772A, 0xB17E, 0x772B, 0xB180, 0x772C, 0xB181, 0x772E, 0xB182, 0x7730, 0xB183, 0x7731, 0xB184, 0x7732, 0xB185, 0x7733, + 0xB186, 0x7734, 0xB187, 0x7739, 0xB188, 0x773B, 0xB189, 0x773D, 0xB18A, 0x773E, 0xB18B, 0x773F, 0xB18C, 0x7742, 0xB18D, 0x7744, + 0xB18E, 0x7745, 0xB18F, 0x7746, 0xB190, 0x7748, 0xB191, 0x7749, 0xB192, 0x774A, 0xB193, 0x774B, 0xB194, 0x774C, 0xB195, 0x774D, + 0xB196, 0x774E, 0xB197, 0x774F, 0xB198, 0x7752, 0xB199, 0x7753, 0xB19A, 0x7754, 0xB19B, 0x7755, 0xB19C, 0x7756, 0xB19D, 0x7757, + 0xB19E, 0x7758, 0xB19F, 0x7759, 0xB1A0, 0x775C, 0xB1A1, 0x8584, 0xB1A2, 0x96F9, 0xB1A3, 0x4FDD, 0xB1A4, 0x5821, 0xB1A5, 0x9971, + 0xB1A6, 0x5B9D, 0xB1A7, 0x62B1, 0xB1A8, 0x62A5, 0xB1A9, 0x66B4, 0xB1AA, 0x8C79, 0xB1AB, 0x9C8D, 0xB1AC, 0x7206, 0xB1AD, 0x676F, + 0xB1AE, 0x7891, 0xB1AF, 0x60B2, 0xB1B0, 0x5351, 0xB1B1, 0x5317, 0xB1B2, 0x8F88, 0xB1B3, 0x80CC, 0xB1B4, 0x8D1D, 0xB1B5, 0x94A1, + 0xB1B6, 0x500D, 0xB1B7, 0x72C8, 0xB1B8, 0x5907, 0xB1B9, 0x60EB, 0xB1BA, 0x7119, 0xB1BB, 0x88AB, 0xB1BC, 0x5954, 0xB1BD, 0x82EF, + 0xB1BE, 0x672C, 0xB1BF, 0x7B28, 0xB1C0, 0x5D29, 0xB1C1, 0x7EF7, 0xB1C2, 0x752D, 0xB1C3, 0x6CF5, 0xB1C4, 0x8E66, 0xB1C5, 0x8FF8, + 0xB1C6, 0x903C, 0xB1C7, 0x9F3B, 0xB1C8, 0x6BD4, 0xB1C9, 0x9119, 0xB1CA, 0x7B14, 0xB1CB, 0x5F7C, 0xB1CC, 0x78A7, 0xB1CD, 0x84D6, + 0xB1CE, 0x853D, 0xB1CF, 0x6BD5, 0xB1D0, 0x6BD9, 0xB1D1, 0x6BD6, 0xB1D2, 0x5E01, 0xB1D3, 0x5E87, 0xB1D4, 0x75F9, 0xB1D5, 0x95ED, + 0xB1D6, 0x655D, 0xB1D7, 0x5F0A, 0xB1D8, 0x5FC5, 0xB1D9, 0x8F9F, 0xB1DA, 0x58C1, 0xB1DB, 0x81C2, 0xB1DC, 0x907F, 0xB1DD, 0x965B, + 0xB1DE, 0x97AD, 0xB1DF, 0x8FB9, 0xB1E0, 0x7F16, 0xB1E1, 0x8D2C, 0xB1E2, 0x6241, 0xB1E3, 0x4FBF, 0xB1E4, 0x53D8, 0xB1E5, 0x535E, + 0xB1E6, 0x8FA8, 0xB1E7, 0x8FA9, 0xB1E8, 0x8FAB, 0xB1E9, 0x904D, 0xB1EA, 0x6807, 0xB1EB, 0x5F6A, 0xB1EC, 0x8198, 0xB1ED, 0x8868, + 0xB1EE, 0x9CD6, 0xB1EF, 0x618B, 0xB1F0, 0x522B, 0xB1F1, 0x762A, 0xB1F2, 0x5F6C, 0xB1F3, 0x658C, 0xB1F4, 0x6FD2, 0xB1F5, 0x6EE8, + 0xB1F6, 0x5BBE, 0xB1F7, 0x6448, 0xB1F8, 0x5175, 0xB1F9, 0x51B0, 0xB1FA, 0x67C4, 0xB1FB, 0x4E19, 0xB1FC, 0x79C9, 0xB1FD, 0x997C, + 0xB1FE, 0x70B3, 0xB240, 0x775D, 0xB241, 0x775E, 0xB242, 0x775F, 0xB243, 0x7760, 0xB244, 0x7764, 0xB245, 0x7767, 0xB246, 0x7769, + 0xB247, 0x776A, 0xB248, 0x776D, 0xB249, 0x776E, 0xB24A, 0x776F, 0xB24B, 0x7770, 0xB24C, 0x7771, 0xB24D, 0x7772, 0xB24E, 0x7773, + 0xB24F, 0x7774, 0xB250, 0x7775, 0xB251, 0x7776, 0xB252, 0x7777, 0xB253, 0x7778, 0xB254, 0x777A, 0xB255, 0x777B, 0xB256, 0x777C, + 0xB257, 0x7781, 0xB258, 0x7782, 0xB259, 0x7783, 0xB25A, 0x7786, 0xB25B, 0x7787, 0xB25C, 0x7788, 0xB25D, 0x7789, 0xB25E, 0x778A, + 0xB25F, 0x778B, 0xB260, 0x778F, 0xB261, 0x7790, 0xB262, 0x7793, 0xB263, 0x7794, 0xB264, 0x7795, 0xB265, 0x7796, 0xB266, 0x7797, + 0xB267, 0x7798, 0xB268, 0x7799, 0xB269, 0x779A, 0xB26A, 0x779B, 0xB26B, 0x779C, 0xB26C, 0x779D, 0xB26D, 0x779E, 0xB26E, 0x77A1, + 0xB26F, 0x77A3, 0xB270, 0x77A4, 0xB271, 0x77A6, 0xB272, 0x77A8, 0xB273, 0x77AB, 0xB274, 0x77AD, 0xB275, 0x77AE, 0xB276, 0x77AF, + 0xB277, 0x77B1, 0xB278, 0x77B2, 0xB279, 0x77B4, 0xB27A, 0x77B6, 0xB27B, 0x77B7, 0xB27C, 0x77B8, 0xB27D, 0x77B9, 0xB27E, 0x77BA, + 0xB280, 0x77BC, 0xB281, 0x77BE, 0xB282, 0x77C0, 0xB283, 0x77C1, 0xB284, 0x77C2, 0xB285, 0x77C3, 0xB286, 0x77C4, 0xB287, 0x77C5, + 0xB288, 0x77C6, 0xB289, 0x77C7, 0xB28A, 0x77C8, 0xB28B, 0x77C9, 0xB28C, 0x77CA, 0xB28D, 0x77CB, 0xB28E, 0x77CC, 0xB28F, 0x77CE, + 0xB290, 0x77CF, 0xB291, 0x77D0, 0xB292, 0x77D1, 0xB293, 0x77D2, 0xB294, 0x77D3, 0xB295, 0x77D4, 0xB296, 0x77D5, 0xB297, 0x77D6, + 0xB298, 0x77D8, 0xB299, 0x77D9, 0xB29A, 0x77DA, 0xB29B, 0x77DD, 0xB29C, 0x77DE, 0xB29D, 0x77DF, 0xB29E, 0x77E0, 0xB29F, 0x77E1, + 0xB2A0, 0x77E4, 0xB2A1, 0x75C5, 0xB2A2, 0x5E76, 0xB2A3, 0x73BB, 0xB2A4, 0x83E0, 0xB2A5, 0x64AD, 0xB2A6, 0x62E8, 0xB2A7, 0x94B5, + 0xB2A8, 0x6CE2, 0xB2A9, 0x535A, 0xB2AA, 0x52C3, 0xB2AB, 0x640F, 0xB2AC, 0x94C2, 0xB2AD, 0x7B94, 0xB2AE, 0x4F2F, 0xB2AF, 0x5E1B, + 0xB2B0, 0x8236, 0xB2B1, 0x8116, 0xB2B2, 0x818A, 0xB2B3, 0x6E24, 0xB2B4, 0x6CCA, 0xB2B5, 0x9A73, 0xB2B6, 0x6355, 0xB2B7, 0x535C, + 0xB2B8, 0x54FA, 0xB2B9, 0x8865, 0xB2BA, 0x57E0, 0xB2BB, 0x4E0D, 0xB2BC, 0x5E03, 0xB2BD, 0x6B65, 0xB2BE, 0x7C3F, 0xB2BF, 0x90E8, + 0xB2C0, 0x6016, 0xB2C1, 0x64E6, 0xB2C2, 0x731C, 0xB2C3, 0x88C1, 0xB2C4, 0x6750, 0xB2C5, 0x624D, 0xB2C6, 0x8D22, 0xB2C7, 0x776C, + 0xB2C8, 0x8E29, 0xB2C9, 0x91C7, 0xB2CA, 0x5F69, 0xB2CB, 0x83DC, 0xB2CC, 0x8521, 0xB2CD, 0x9910, 0xB2CE, 0x53C2, 0xB2CF, 0x8695, + 0xB2D0, 0x6B8B, 0xB2D1, 0x60ED, 0xB2D2, 0x60E8, 0xB2D3, 0x707F, 0xB2D4, 0x82CD, 0xB2D5, 0x8231, 0xB2D6, 0x4ED3, 0xB2D7, 0x6CA7, + 0xB2D8, 0x85CF, 0xB2D9, 0x64CD, 0xB2DA, 0x7CD9, 0xB2DB, 0x69FD, 0xB2DC, 0x66F9, 0xB2DD, 0x8349, 0xB2DE, 0x5395, 0xB2DF, 0x7B56, + 0xB2E0, 0x4FA7, 0xB2E1, 0x518C, 0xB2E2, 0x6D4B, 0xB2E3, 0x5C42, 0xB2E4, 0x8E6D, 0xB2E5, 0x63D2, 0xB2E6, 0x53C9, 0xB2E7, 0x832C, + 0xB2E8, 0x8336, 0xB2E9, 0x67E5, 0xB2EA, 0x78B4, 0xB2EB, 0x643D, 0xB2EC, 0x5BDF, 0xB2ED, 0x5C94, 0xB2EE, 0x5DEE, 0xB2EF, 0x8BE7, + 0xB2F0, 0x62C6, 0xB2F1, 0x67F4, 0xB2F2, 0x8C7A, 0xB2F3, 0x6400, 0xB2F4, 0x63BA, 0xB2F5, 0x8749, 0xB2F6, 0x998B, 0xB2F7, 0x8C17, + 0xB2F8, 0x7F20, 0xB2F9, 0x94F2, 0xB2FA, 0x4EA7, 0xB2FB, 0x9610, 0xB2FC, 0x98A4, 0xB2FD, 0x660C, 0xB2FE, 0x7316, 0xB340, 0x77E6, + 0xB341, 0x77E8, 0xB342, 0x77EA, 0xB343, 0x77EF, 0xB344, 0x77F0, 0xB345, 0x77F1, 0xB346, 0x77F2, 0xB347, 0x77F4, 0xB348, 0x77F5, + 0xB349, 0x77F7, 0xB34A, 0x77F9, 0xB34B, 0x77FA, 0xB34C, 0x77FB, 0xB34D, 0x77FC, 0xB34E, 0x7803, 0xB34F, 0x7804, 0xB350, 0x7805, + 0xB351, 0x7806, 0xB352, 0x7807, 0xB353, 0x7808, 0xB354, 0x780A, 0xB355, 0x780B, 0xB356, 0x780E, 0xB357, 0x780F, 0xB358, 0x7810, + 0xB359, 0x7813, 0xB35A, 0x7815, 0xB35B, 0x7819, 0xB35C, 0x781B, 0xB35D, 0x781E, 0xB35E, 0x7820, 0xB35F, 0x7821, 0xB360, 0x7822, + 0xB361, 0x7824, 0xB362, 0x7828, 0xB363, 0x782A, 0xB364, 0x782B, 0xB365, 0x782E, 0xB366, 0x782F, 0xB367, 0x7831, 0xB368, 0x7832, + 0xB369, 0x7833, 0xB36A, 0x7835, 0xB36B, 0x7836, 0xB36C, 0x783D, 0xB36D, 0x783F, 0xB36E, 0x7841, 0xB36F, 0x7842, 0xB370, 0x7843, + 0xB371, 0x7844, 0xB372, 0x7846, 0xB373, 0x7848, 0xB374, 0x7849, 0xB375, 0x784A, 0xB376, 0x784B, 0xB377, 0x784D, 0xB378, 0x784F, + 0xB379, 0x7851, 0xB37A, 0x7853, 0xB37B, 0x7854, 0xB37C, 0x7858, 0xB37D, 0x7859, 0xB37E, 0x785A, 0xB380, 0x785B, 0xB381, 0x785C, + 0xB382, 0x785E, 0xB383, 0x785F, 0xB384, 0x7860, 0xB385, 0x7861, 0xB386, 0x7862, 0xB387, 0x7863, 0xB388, 0x7864, 0xB389, 0x7865, + 0xB38A, 0x7866, 0xB38B, 0x7867, 0xB38C, 0x7868, 0xB38D, 0x7869, 0xB38E, 0x786F, 0xB38F, 0x7870, 0xB390, 0x7871, 0xB391, 0x7872, + 0xB392, 0x7873, 0xB393, 0x7874, 0xB394, 0x7875, 0xB395, 0x7876, 0xB396, 0x7878, 0xB397, 0x7879, 0xB398, 0x787A, 0xB399, 0x787B, + 0xB39A, 0x787D, 0xB39B, 0x787E, 0xB39C, 0x787F, 0xB39D, 0x7880, 0xB39E, 0x7881, 0xB39F, 0x7882, 0xB3A0, 0x7883, 0xB3A1, 0x573A, + 0xB3A2, 0x5C1D, 0xB3A3, 0x5E38, 0xB3A4, 0x957F, 0xB3A5, 0x507F, 0xB3A6, 0x80A0, 0xB3A7, 0x5382, 0xB3A8, 0x655E, 0xB3A9, 0x7545, + 0xB3AA, 0x5531, 0xB3AB, 0x5021, 0xB3AC, 0x8D85, 0xB3AD, 0x6284, 0xB3AE, 0x949E, 0xB3AF, 0x671D, 0xB3B0, 0x5632, 0xB3B1, 0x6F6E, + 0xB3B2, 0x5DE2, 0xB3B3, 0x5435, 0xB3B4, 0x7092, 0xB3B5, 0x8F66, 0xB3B6, 0x626F, 0xB3B7, 0x64A4, 0xB3B8, 0x63A3, 0xB3B9, 0x5F7B, + 0xB3BA, 0x6F88, 0xB3BB, 0x90F4, 0xB3BC, 0x81E3, 0xB3BD, 0x8FB0, 0xB3BE, 0x5C18, 0xB3BF, 0x6668, 0xB3C0, 0x5FF1, 0xB3C1, 0x6C89, + 0xB3C2, 0x9648, 0xB3C3, 0x8D81, 0xB3C4, 0x886C, 0xB3C5, 0x6491, 0xB3C6, 0x79F0, 0xB3C7, 0x57CE, 0xB3C8, 0x6A59, 0xB3C9, 0x6210, + 0xB3CA, 0x5448, 0xB3CB, 0x4E58, 0xB3CC, 0x7A0B, 0xB3CD, 0x60E9, 0xB3CE, 0x6F84, 0xB3CF, 0x8BDA, 0xB3D0, 0x627F, 0xB3D1, 0x901E, + 0xB3D2, 0x9A8B, 0xB3D3, 0x79E4, 0xB3D4, 0x5403, 0xB3D5, 0x75F4, 0xB3D6, 0x6301, 0xB3D7, 0x5319, 0xB3D8, 0x6C60, 0xB3D9, 0x8FDF, + 0xB3DA, 0x5F1B, 0xB3DB, 0x9A70, 0xB3DC, 0x803B, 0xB3DD, 0x9F7F, 0xB3DE, 0x4F88, 0xB3DF, 0x5C3A, 0xB3E0, 0x8D64, 0xB3E1, 0x7FC5, + 0xB3E2, 0x65A5, 0xB3E3, 0x70BD, 0xB3E4, 0x5145, 0xB3E5, 0x51B2, 0xB3E6, 0x866B, 0xB3E7, 0x5D07, 0xB3E8, 0x5BA0, 0xB3E9, 0x62BD, + 0xB3EA, 0x916C, 0xB3EB, 0x7574, 0xB3EC, 0x8E0C, 0xB3ED, 0x7A20, 0xB3EE, 0x6101, 0xB3EF, 0x7B79, 0xB3F0, 0x4EC7, 0xB3F1, 0x7EF8, + 0xB3F2, 0x7785, 0xB3F3, 0x4E11, 0xB3F4, 0x81ED, 0xB3F5, 0x521D, 0xB3F6, 0x51FA, 0xB3F7, 0x6A71, 0xB3F8, 0x53A8, 0xB3F9, 0x8E87, + 0xB3FA, 0x9504, 0xB3FB, 0x96CF, 0xB3FC, 0x6EC1, 0xB3FD, 0x9664, 0xB3FE, 0x695A, 0xB440, 0x7884, 0xB441, 0x7885, 0xB442, 0x7886, + 0xB443, 0x7888, 0xB444, 0x788A, 0xB445, 0x788B, 0xB446, 0x788F, 0xB447, 0x7890, 0xB448, 0x7892, 0xB449, 0x7894, 0xB44A, 0x7895, + 0xB44B, 0x7896, 0xB44C, 0x7899, 0xB44D, 0x789D, 0xB44E, 0x789E, 0xB44F, 0x78A0, 0xB450, 0x78A2, 0xB451, 0x78A4, 0xB452, 0x78A6, + 0xB453, 0x78A8, 0xB454, 0x78A9, 0xB455, 0x78AA, 0xB456, 0x78AB, 0xB457, 0x78AC, 0xB458, 0x78AD, 0xB459, 0x78AE, 0xB45A, 0x78AF, + 0xB45B, 0x78B5, 0xB45C, 0x78B6, 0xB45D, 0x78B7, 0xB45E, 0x78B8, 0xB45F, 0x78BA, 0xB460, 0x78BB, 0xB461, 0x78BC, 0xB462, 0x78BD, + 0xB463, 0x78BF, 0xB464, 0x78C0, 0xB465, 0x78C2, 0xB466, 0x78C3, 0xB467, 0x78C4, 0xB468, 0x78C6, 0xB469, 0x78C7, 0xB46A, 0x78C8, + 0xB46B, 0x78CC, 0xB46C, 0x78CD, 0xB46D, 0x78CE, 0xB46E, 0x78CF, 0xB46F, 0x78D1, 0xB470, 0x78D2, 0xB471, 0x78D3, 0xB472, 0x78D6, + 0xB473, 0x78D7, 0xB474, 0x78D8, 0xB475, 0x78DA, 0xB476, 0x78DB, 0xB477, 0x78DC, 0xB478, 0x78DD, 0xB479, 0x78DE, 0xB47A, 0x78DF, + 0xB47B, 0x78E0, 0xB47C, 0x78E1, 0xB47D, 0x78E2, 0xB47E, 0x78E3, 0xB480, 0x78E4, 0xB481, 0x78E5, 0xB482, 0x78E6, 0xB483, 0x78E7, + 0xB484, 0x78E9, 0xB485, 0x78EA, 0xB486, 0x78EB, 0xB487, 0x78ED, 0xB488, 0x78EE, 0xB489, 0x78EF, 0xB48A, 0x78F0, 0xB48B, 0x78F1, + 0xB48C, 0x78F3, 0xB48D, 0x78F5, 0xB48E, 0x78F6, 0xB48F, 0x78F8, 0xB490, 0x78F9, 0xB491, 0x78FB, 0xB492, 0x78FC, 0xB493, 0x78FD, + 0xB494, 0x78FE, 0xB495, 0x78FF, 0xB496, 0x7900, 0xB497, 0x7902, 0xB498, 0x7903, 0xB499, 0x7904, 0xB49A, 0x7906, 0xB49B, 0x7907, + 0xB49C, 0x7908, 0xB49D, 0x7909, 0xB49E, 0x790A, 0xB49F, 0x790B, 0xB4A0, 0x790C, 0xB4A1, 0x7840, 0xB4A2, 0x50A8, 0xB4A3, 0x77D7, + 0xB4A4, 0x6410, 0xB4A5, 0x89E6, 0xB4A6, 0x5904, 0xB4A7, 0x63E3, 0xB4A8, 0x5DDD, 0xB4A9, 0x7A7F, 0xB4AA, 0x693D, 0xB4AB, 0x4F20, + 0xB4AC, 0x8239, 0xB4AD, 0x5598, 0xB4AE, 0x4E32, 0xB4AF, 0x75AE, 0xB4B0, 0x7A97, 0xB4B1, 0x5E62, 0xB4B2, 0x5E8A, 0xB4B3, 0x95EF, + 0xB4B4, 0x521B, 0xB4B5, 0x5439, 0xB4B6, 0x708A, 0xB4B7, 0x6376, 0xB4B8, 0x9524, 0xB4B9, 0x5782, 0xB4BA, 0x6625, 0xB4BB, 0x693F, + 0xB4BC, 0x9187, 0xB4BD, 0x5507, 0xB4BE, 0x6DF3, 0xB4BF, 0x7EAF, 0xB4C0, 0x8822, 0xB4C1, 0x6233, 0xB4C2, 0x7EF0, 0xB4C3, 0x75B5, + 0xB4C4, 0x8328, 0xB4C5, 0x78C1, 0xB4C6, 0x96CC, 0xB4C7, 0x8F9E, 0xB4C8, 0x6148, 0xB4C9, 0x74F7, 0xB4CA, 0x8BCD, 0xB4CB, 0x6B64, + 0xB4CC, 0x523A, 0xB4CD, 0x8D50, 0xB4CE, 0x6B21, 0xB4CF, 0x806A, 0xB4D0, 0x8471, 0xB4D1, 0x56F1, 0xB4D2, 0x5306, 0xB4D3, 0x4ECE, + 0xB4D4, 0x4E1B, 0xB4D5, 0x51D1, 0xB4D6, 0x7C97, 0xB4D7, 0x918B, 0xB4D8, 0x7C07, 0xB4D9, 0x4FC3, 0xB4DA, 0x8E7F, 0xB4DB, 0x7BE1, + 0xB4DC, 0x7A9C, 0xB4DD, 0x6467, 0xB4DE, 0x5D14, 0xB4DF, 0x50AC, 0xB4E0, 0x8106, 0xB4E1, 0x7601, 0xB4E2, 0x7CB9, 0xB4E3, 0x6DEC, + 0xB4E4, 0x7FE0, 0xB4E5, 0x6751, 0xB4E6, 0x5B58, 0xB4E7, 0x5BF8, 0xB4E8, 0x78CB, 0xB4E9, 0x64AE, 0xB4EA, 0x6413, 0xB4EB, 0x63AA, + 0xB4EC, 0x632B, 0xB4ED, 0x9519, 0xB4EE, 0x642D, 0xB4EF, 0x8FBE, 0xB4F0, 0x7B54, 0xB4F1, 0x7629, 0xB4F2, 0x6253, 0xB4F3, 0x5927, + 0xB4F4, 0x5446, 0xB4F5, 0x6B79, 0xB4F6, 0x50A3, 0xB4F7, 0x6234, 0xB4F8, 0x5E26, 0xB4F9, 0x6B86, 0xB4FA, 0x4EE3, 0xB4FB, 0x8D37, + 0xB4FC, 0x888B, 0xB4FD, 0x5F85, 0xB4FE, 0x902E, 0xB540, 0x790D, 0xB541, 0x790E, 0xB542, 0x790F, 0xB543, 0x7910, 0xB544, 0x7911, + 0xB545, 0x7912, 0xB546, 0x7914, 0xB547, 0x7915, 0xB548, 0x7916, 0xB549, 0x7917, 0xB54A, 0x7918, 0xB54B, 0x7919, 0xB54C, 0x791A, + 0xB54D, 0x791B, 0xB54E, 0x791C, 0xB54F, 0x791D, 0xB550, 0x791F, 0xB551, 0x7920, 0xB552, 0x7921, 0xB553, 0x7922, 0xB554, 0x7923, + 0xB555, 0x7925, 0xB556, 0x7926, 0xB557, 0x7927, 0xB558, 0x7928, 0xB559, 0x7929, 0xB55A, 0x792A, 0xB55B, 0x792B, 0xB55C, 0x792C, + 0xB55D, 0x792D, 0xB55E, 0x792E, 0xB55F, 0x792F, 0xB560, 0x7930, 0xB561, 0x7931, 0xB562, 0x7932, 0xB563, 0x7933, 0xB564, 0x7935, + 0xB565, 0x7936, 0xB566, 0x7937, 0xB567, 0x7938, 0xB568, 0x7939, 0xB569, 0x793D, 0xB56A, 0x793F, 0xB56B, 0x7942, 0xB56C, 0x7943, + 0xB56D, 0x7944, 0xB56E, 0x7945, 0xB56F, 0x7947, 0xB570, 0x794A, 0xB571, 0x794B, 0xB572, 0x794C, 0xB573, 0x794D, 0xB574, 0x794E, + 0xB575, 0x794F, 0xB576, 0x7950, 0xB577, 0x7951, 0xB578, 0x7952, 0xB579, 0x7954, 0xB57A, 0x7955, 0xB57B, 0x7958, 0xB57C, 0x7959, + 0xB57D, 0x7961, 0xB57E, 0x7963, 0xB580, 0x7964, 0xB581, 0x7966, 0xB582, 0x7969, 0xB583, 0x796A, 0xB584, 0x796B, 0xB585, 0x796C, + 0xB586, 0x796E, 0xB587, 0x7970, 0xB588, 0x7971, 0xB589, 0x7972, 0xB58A, 0x7973, 0xB58B, 0x7974, 0xB58C, 0x7975, 0xB58D, 0x7976, + 0xB58E, 0x7979, 0xB58F, 0x797B, 0xB590, 0x797C, 0xB591, 0x797D, 0xB592, 0x797E, 0xB593, 0x797F, 0xB594, 0x7982, 0xB595, 0x7983, + 0xB596, 0x7986, 0xB597, 0x7987, 0xB598, 0x7988, 0xB599, 0x7989, 0xB59A, 0x798B, 0xB59B, 0x798C, 0xB59C, 0x798D, 0xB59D, 0x798E, + 0xB59E, 0x7990, 0xB59F, 0x7991, 0xB5A0, 0x7992, 0xB5A1, 0x6020, 0xB5A2, 0x803D, 0xB5A3, 0x62C5, 0xB5A4, 0x4E39, 0xB5A5, 0x5355, + 0xB5A6, 0x90F8, 0xB5A7, 0x63B8, 0xB5A8, 0x80C6, 0xB5A9, 0x65E6, 0xB5AA, 0x6C2E, 0xB5AB, 0x4F46, 0xB5AC, 0x60EE, 0xB5AD, 0x6DE1, + 0xB5AE, 0x8BDE, 0xB5AF, 0x5F39, 0xB5B0, 0x86CB, 0xB5B1, 0x5F53, 0xB5B2, 0x6321, 0xB5B3, 0x515A, 0xB5B4, 0x8361, 0xB5B5, 0x6863, + 0xB5B6, 0x5200, 0xB5B7, 0x6363, 0xB5B8, 0x8E48, 0xB5B9, 0x5012, 0xB5BA, 0x5C9B, 0xB5BB, 0x7977, 0xB5BC, 0x5BFC, 0xB5BD, 0x5230, + 0xB5BE, 0x7A3B, 0xB5BF, 0x60BC, 0xB5C0, 0x9053, 0xB5C1, 0x76D7, 0xB5C2, 0x5FB7, 0xB5C3, 0x5F97, 0xB5C4, 0x7684, 0xB5C5, 0x8E6C, + 0xB5C6, 0x706F, 0xB5C7, 0x767B, 0xB5C8, 0x7B49, 0xB5C9, 0x77AA, 0xB5CA, 0x51F3, 0xB5CB, 0x9093, 0xB5CC, 0x5824, 0xB5CD, 0x4F4E, + 0xB5CE, 0x6EF4, 0xB5CF, 0x8FEA, 0xB5D0, 0x654C, 0xB5D1, 0x7B1B, 0xB5D2, 0x72C4, 0xB5D3, 0x6DA4, 0xB5D4, 0x7FDF, 0xB5D5, 0x5AE1, + 0xB5D6, 0x62B5, 0xB5D7, 0x5E95, 0xB5D8, 0x5730, 0xB5D9, 0x8482, 0xB5DA, 0x7B2C, 0xB5DB, 0x5E1D, 0xB5DC, 0x5F1F, 0xB5DD, 0x9012, + 0xB5DE, 0x7F14, 0xB5DF, 0x98A0, 0xB5E0, 0x6382, 0xB5E1, 0x6EC7, 0xB5E2, 0x7898, 0xB5E3, 0x70B9, 0xB5E4, 0x5178, 0xB5E5, 0x975B, + 0xB5E6, 0x57AB, 0xB5E7, 0x7535, 0xB5E8, 0x4F43, 0xB5E9, 0x7538, 0xB5EA, 0x5E97, 0xB5EB, 0x60E6, 0xB5EC, 0x5960, 0xB5ED, 0x6DC0, + 0xB5EE, 0x6BBF, 0xB5EF, 0x7889, 0xB5F0, 0x53FC, 0xB5F1, 0x96D5, 0xB5F2, 0x51CB, 0xB5F3, 0x5201, 0xB5F4, 0x6389, 0xB5F5, 0x540A, + 0xB5F6, 0x9493, 0xB5F7, 0x8C03, 0xB5F8, 0x8DCC, 0xB5F9, 0x7239, 0xB5FA, 0x789F, 0xB5FB, 0x8776, 0xB5FC, 0x8FED, 0xB5FD, 0x8C0D, + 0xB5FE, 0x53E0, 0xB640, 0x7993, 0xB641, 0x7994, 0xB642, 0x7995, 0xB643, 0x7996, 0xB644, 0x7997, 0xB645, 0x7998, 0xB646, 0x7999, + 0xB647, 0x799B, 0xB648, 0x799C, 0xB649, 0x799D, 0xB64A, 0x799E, 0xB64B, 0x799F, 0xB64C, 0x79A0, 0xB64D, 0x79A1, 0xB64E, 0x79A2, + 0xB64F, 0x79A3, 0xB650, 0x79A4, 0xB651, 0x79A5, 0xB652, 0x79A6, 0xB653, 0x79A8, 0xB654, 0x79A9, 0xB655, 0x79AA, 0xB656, 0x79AB, + 0xB657, 0x79AC, 0xB658, 0x79AD, 0xB659, 0x79AE, 0xB65A, 0x79AF, 0xB65B, 0x79B0, 0xB65C, 0x79B1, 0xB65D, 0x79B2, 0xB65E, 0x79B4, + 0xB65F, 0x79B5, 0xB660, 0x79B6, 0xB661, 0x79B7, 0xB662, 0x79B8, 0xB663, 0x79BC, 0xB664, 0x79BF, 0xB665, 0x79C2, 0xB666, 0x79C4, + 0xB667, 0x79C5, 0xB668, 0x79C7, 0xB669, 0x79C8, 0xB66A, 0x79CA, 0xB66B, 0x79CC, 0xB66C, 0x79CE, 0xB66D, 0x79CF, 0xB66E, 0x79D0, + 0xB66F, 0x79D3, 0xB670, 0x79D4, 0xB671, 0x79D6, 0xB672, 0x79D7, 0xB673, 0x79D9, 0xB674, 0x79DA, 0xB675, 0x79DB, 0xB676, 0x79DC, + 0xB677, 0x79DD, 0xB678, 0x79DE, 0xB679, 0x79E0, 0xB67A, 0x79E1, 0xB67B, 0x79E2, 0xB67C, 0x79E5, 0xB67D, 0x79E8, 0xB67E, 0x79EA, + 0xB680, 0x79EC, 0xB681, 0x79EE, 0xB682, 0x79F1, 0xB683, 0x79F2, 0xB684, 0x79F3, 0xB685, 0x79F4, 0xB686, 0x79F5, 0xB687, 0x79F6, + 0xB688, 0x79F7, 0xB689, 0x79F9, 0xB68A, 0x79FA, 0xB68B, 0x79FC, 0xB68C, 0x79FE, 0xB68D, 0x79FF, 0xB68E, 0x7A01, 0xB68F, 0x7A04, + 0xB690, 0x7A05, 0xB691, 0x7A07, 0xB692, 0x7A08, 0xB693, 0x7A09, 0xB694, 0x7A0A, 0xB695, 0x7A0C, 0xB696, 0x7A0F, 0xB697, 0x7A10, + 0xB698, 0x7A11, 0xB699, 0x7A12, 0xB69A, 0x7A13, 0xB69B, 0x7A15, 0xB69C, 0x7A16, 0xB69D, 0x7A18, 0xB69E, 0x7A19, 0xB69F, 0x7A1B, + 0xB6A0, 0x7A1C, 0xB6A1, 0x4E01, 0xB6A2, 0x76EF, 0xB6A3, 0x53EE, 0xB6A4, 0x9489, 0xB6A5, 0x9876, 0xB6A6, 0x9F0E, 0xB6A7, 0x952D, + 0xB6A8, 0x5B9A, 0xB6A9, 0x8BA2, 0xB6AA, 0x4E22, 0xB6AB, 0x4E1C, 0xB6AC, 0x51AC, 0xB6AD, 0x8463, 0xB6AE, 0x61C2, 0xB6AF, 0x52A8, + 0xB6B0, 0x680B, 0xB6B1, 0x4F97, 0xB6B2, 0x606B, 0xB6B3, 0x51BB, 0xB6B4, 0x6D1E, 0xB6B5, 0x515C, 0xB6B6, 0x6296, 0xB6B7, 0x6597, + 0xB6B8, 0x9661, 0xB6B9, 0x8C46, 0xB6BA, 0x9017, 0xB6BB, 0x75D8, 0xB6BC, 0x90FD, 0xB6BD, 0x7763, 0xB6BE, 0x6BD2, 0xB6BF, 0x728A, + 0xB6C0, 0x72EC, 0xB6C1, 0x8BFB, 0xB6C2, 0x5835, 0xB6C3, 0x7779, 0xB6C4, 0x8D4C, 0xB6C5, 0x675C, 0xB6C6, 0x9540, 0xB6C7, 0x809A, + 0xB6C8, 0x5EA6, 0xB6C9, 0x6E21, 0xB6CA, 0x5992, 0xB6CB, 0x7AEF, 0xB6CC, 0x77ED, 0xB6CD, 0x953B, 0xB6CE, 0x6BB5, 0xB6CF, 0x65AD, + 0xB6D0, 0x7F0E, 0xB6D1, 0x5806, 0xB6D2, 0x5151, 0xB6D3, 0x961F, 0xB6D4, 0x5BF9, 0xB6D5, 0x58A9, 0xB6D6, 0x5428, 0xB6D7, 0x8E72, + 0xB6D8, 0x6566, 0xB6D9, 0x987F, 0xB6DA, 0x56E4, 0xB6DB, 0x949D, 0xB6DC, 0x76FE, 0xB6DD, 0x9041, 0xB6DE, 0x6387, 0xB6DF, 0x54C6, + 0xB6E0, 0x591A, 0xB6E1, 0x593A, 0xB6E2, 0x579B, 0xB6E3, 0x8EB2, 0xB6E4, 0x6735, 0xB6E5, 0x8DFA, 0xB6E6, 0x8235, 0xB6E7, 0x5241, + 0xB6E8, 0x60F0, 0xB6E9, 0x5815, 0xB6EA, 0x86FE, 0xB6EB, 0x5CE8, 0xB6EC, 0x9E45, 0xB6ED, 0x4FC4, 0xB6EE, 0x989D, 0xB6EF, 0x8BB9, + 0xB6F0, 0x5A25, 0xB6F1, 0x6076, 0xB6F2, 0x5384, 0xB6F3, 0x627C, 0xB6F4, 0x904F, 0xB6F5, 0x9102, 0xB6F6, 0x997F, 0xB6F7, 0x6069, + 0xB6F8, 0x800C, 0xB6F9, 0x513F, 0xB6FA, 0x8033, 0xB6FB, 0x5C14, 0xB6FC, 0x9975, 0xB6FD, 0x6D31, 0xB6FE, 0x4E8C, 0xB740, 0x7A1D, + 0xB741, 0x7A1F, 0xB742, 0x7A21, 0xB743, 0x7A22, 0xB744, 0x7A24, 0xB745, 0x7A25, 0xB746, 0x7A26, 0xB747, 0x7A27, 0xB748, 0x7A28, + 0xB749, 0x7A29, 0xB74A, 0x7A2A, 0xB74B, 0x7A2B, 0xB74C, 0x7A2C, 0xB74D, 0x7A2D, 0xB74E, 0x7A2E, 0xB74F, 0x7A2F, 0xB750, 0x7A30, + 0xB751, 0x7A31, 0xB752, 0x7A32, 0xB753, 0x7A34, 0xB754, 0x7A35, 0xB755, 0x7A36, 0xB756, 0x7A38, 0xB757, 0x7A3A, 0xB758, 0x7A3E, + 0xB759, 0x7A40, 0xB75A, 0x7A41, 0xB75B, 0x7A42, 0xB75C, 0x7A43, 0xB75D, 0x7A44, 0xB75E, 0x7A45, 0xB75F, 0x7A47, 0xB760, 0x7A48, + 0xB761, 0x7A49, 0xB762, 0x7A4A, 0xB763, 0x7A4B, 0xB764, 0x7A4C, 0xB765, 0x7A4D, 0xB766, 0x7A4E, 0xB767, 0x7A4F, 0xB768, 0x7A50, + 0xB769, 0x7A52, 0xB76A, 0x7A53, 0xB76B, 0x7A54, 0xB76C, 0x7A55, 0xB76D, 0x7A56, 0xB76E, 0x7A58, 0xB76F, 0x7A59, 0xB770, 0x7A5A, + 0xB771, 0x7A5B, 0xB772, 0x7A5C, 0xB773, 0x7A5D, 0xB774, 0x7A5E, 0xB775, 0x7A5F, 0xB776, 0x7A60, 0xB777, 0x7A61, 0xB778, 0x7A62, + 0xB779, 0x7A63, 0xB77A, 0x7A64, 0xB77B, 0x7A65, 0xB77C, 0x7A66, 0xB77D, 0x7A67, 0xB77E, 0x7A68, 0xB780, 0x7A69, 0xB781, 0x7A6A, + 0xB782, 0x7A6B, 0xB783, 0x7A6C, 0xB784, 0x7A6D, 0xB785, 0x7A6E, 0xB786, 0x7A6F, 0xB787, 0x7A71, 0xB788, 0x7A72, 0xB789, 0x7A73, + 0xB78A, 0x7A75, 0xB78B, 0x7A7B, 0xB78C, 0x7A7C, 0xB78D, 0x7A7D, 0xB78E, 0x7A7E, 0xB78F, 0x7A82, 0xB790, 0x7A85, 0xB791, 0x7A87, + 0xB792, 0x7A89, 0xB793, 0x7A8A, 0xB794, 0x7A8B, 0xB795, 0x7A8C, 0xB796, 0x7A8E, 0xB797, 0x7A8F, 0xB798, 0x7A90, 0xB799, 0x7A93, + 0xB79A, 0x7A94, 0xB79B, 0x7A99, 0xB79C, 0x7A9A, 0xB79D, 0x7A9B, 0xB79E, 0x7A9E, 0xB79F, 0x7AA1, 0xB7A0, 0x7AA2, 0xB7A1, 0x8D30, + 0xB7A2, 0x53D1, 0xB7A3, 0x7F5A, 0xB7A4, 0x7B4F, 0xB7A5, 0x4F10, 0xB7A6, 0x4E4F, 0xB7A7, 0x9600, 0xB7A8, 0x6CD5, 0xB7A9, 0x73D0, + 0xB7AA, 0x85E9, 0xB7AB, 0x5E06, 0xB7AC, 0x756A, 0xB7AD, 0x7FFB, 0xB7AE, 0x6A0A, 0xB7AF, 0x77FE, 0xB7B0, 0x9492, 0xB7B1, 0x7E41, + 0xB7B2, 0x51E1, 0xB7B3, 0x70E6, 0xB7B4, 0x53CD, 0xB7B5, 0x8FD4, 0xB7B6, 0x8303, 0xB7B7, 0x8D29, 0xB7B8, 0x72AF, 0xB7B9, 0x996D, + 0xB7BA, 0x6CDB, 0xB7BB, 0x574A, 0xB7BC, 0x82B3, 0xB7BD, 0x65B9, 0xB7BE, 0x80AA, 0xB7BF, 0x623F, 0xB7C0, 0x9632, 0xB7C1, 0x59A8, + 0xB7C2, 0x4EFF, 0xB7C3, 0x8BBF, 0xB7C4, 0x7EBA, 0xB7C5, 0x653E, 0xB7C6, 0x83F2, 0xB7C7, 0x975E, 0xB7C8, 0x5561, 0xB7C9, 0x98DE, + 0xB7CA, 0x80A5, 0xB7CB, 0x532A, 0xB7CC, 0x8BFD, 0xB7CD, 0x5420, 0xB7CE, 0x80BA, 0xB7CF, 0x5E9F, 0xB7D0, 0x6CB8, 0xB7D1, 0x8D39, + 0xB7D2, 0x82AC, 0xB7D3, 0x915A, 0xB7D4, 0x5429, 0xB7D5, 0x6C1B, 0xB7D6, 0x5206, 0xB7D7, 0x7EB7, 0xB7D8, 0x575F, 0xB7D9, 0x711A, + 0xB7DA, 0x6C7E, 0xB7DB, 0x7C89, 0xB7DC, 0x594B, 0xB7DD, 0x4EFD, 0xB7DE, 0x5FFF, 0xB7DF, 0x6124, 0xB7E0, 0x7CAA, 0xB7E1, 0x4E30, + 0xB7E2, 0x5C01, 0xB7E3, 0x67AB, 0xB7E4, 0x8702, 0xB7E5, 0x5CF0, 0xB7E6, 0x950B, 0xB7E7, 0x98CE, 0xB7E8, 0x75AF, 0xB7E9, 0x70FD, + 0xB7EA, 0x9022, 0xB7EB, 0x51AF, 0xB7EC, 0x7F1D, 0xB7ED, 0x8BBD, 0xB7EE, 0x5949, 0xB7EF, 0x51E4, 0xB7F0, 0x4F5B, 0xB7F1, 0x5426, + 0xB7F2, 0x592B, 0xB7F3, 0x6577, 0xB7F4, 0x80A4, 0xB7F5, 0x5B75, 0xB7F6, 0x6276, 0xB7F7, 0x62C2, 0xB7F8, 0x8F90, 0xB7F9, 0x5E45, + 0xB7FA, 0x6C1F, 0xB7FB, 0x7B26, 0xB7FC, 0x4F0F, 0xB7FD, 0x4FD8, 0xB7FE, 0x670D, 0xB840, 0x7AA3, 0xB841, 0x7AA4, 0xB842, 0x7AA7, + 0xB843, 0x7AA9, 0xB844, 0x7AAA, 0xB845, 0x7AAB, 0xB846, 0x7AAE, 0xB847, 0x7AAF, 0xB848, 0x7AB0, 0xB849, 0x7AB1, 0xB84A, 0x7AB2, + 0xB84B, 0x7AB4, 0xB84C, 0x7AB5, 0xB84D, 0x7AB6, 0xB84E, 0x7AB7, 0xB84F, 0x7AB8, 0xB850, 0x7AB9, 0xB851, 0x7ABA, 0xB852, 0x7ABB, + 0xB853, 0x7ABC, 0xB854, 0x7ABD, 0xB855, 0x7ABE, 0xB856, 0x7AC0, 0xB857, 0x7AC1, 0xB858, 0x7AC2, 0xB859, 0x7AC3, 0xB85A, 0x7AC4, + 0xB85B, 0x7AC5, 0xB85C, 0x7AC6, 0xB85D, 0x7AC7, 0xB85E, 0x7AC8, 0xB85F, 0x7AC9, 0xB860, 0x7ACA, 0xB861, 0x7ACC, 0xB862, 0x7ACD, + 0xB863, 0x7ACE, 0xB864, 0x7ACF, 0xB865, 0x7AD0, 0xB866, 0x7AD1, 0xB867, 0x7AD2, 0xB868, 0x7AD3, 0xB869, 0x7AD4, 0xB86A, 0x7AD5, + 0xB86B, 0x7AD7, 0xB86C, 0x7AD8, 0xB86D, 0x7ADA, 0xB86E, 0x7ADB, 0xB86F, 0x7ADC, 0xB870, 0x7ADD, 0xB871, 0x7AE1, 0xB872, 0x7AE2, + 0xB873, 0x7AE4, 0xB874, 0x7AE7, 0xB875, 0x7AE8, 0xB876, 0x7AE9, 0xB877, 0x7AEA, 0xB878, 0x7AEB, 0xB879, 0x7AEC, 0xB87A, 0x7AEE, + 0xB87B, 0x7AF0, 0xB87C, 0x7AF1, 0xB87D, 0x7AF2, 0xB87E, 0x7AF3, 0xB880, 0x7AF4, 0xB881, 0x7AF5, 0xB882, 0x7AF6, 0xB883, 0x7AF7, + 0xB884, 0x7AF8, 0xB885, 0x7AFB, 0xB886, 0x7AFC, 0xB887, 0x7AFE, 0xB888, 0x7B00, 0xB889, 0x7B01, 0xB88A, 0x7B02, 0xB88B, 0x7B05, + 0xB88C, 0x7B07, 0xB88D, 0x7B09, 0xB88E, 0x7B0C, 0xB88F, 0x7B0D, 0xB890, 0x7B0E, 0xB891, 0x7B10, 0xB892, 0x7B12, 0xB893, 0x7B13, + 0xB894, 0x7B16, 0xB895, 0x7B17, 0xB896, 0x7B18, 0xB897, 0x7B1A, 0xB898, 0x7B1C, 0xB899, 0x7B1D, 0xB89A, 0x7B1F, 0xB89B, 0x7B21, + 0xB89C, 0x7B22, 0xB89D, 0x7B23, 0xB89E, 0x7B27, 0xB89F, 0x7B29, 0xB8A0, 0x7B2D, 0xB8A1, 0x6D6E, 0xB8A2, 0x6DAA, 0xB8A3, 0x798F, + 0xB8A4, 0x88B1, 0xB8A5, 0x5F17, 0xB8A6, 0x752B, 0xB8A7, 0x629A, 0xB8A8, 0x8F85, 0xB8A9, 0x4FEF, 0xB8AA, 0x91DC, 0xB8AB, 0x65A7, + 0xB8AC, 0x812F, 0xB8AD, 0x8151, 0xB8AE, 0x5E9C, 0xB8AF, 0x8150, 0xB8B0, 0x8D74, 0xB8B1, 0x526F, 0xB8B2, 0x8986, 0xB8B3, 0x8D4B, + 0xB8B4, 0x590D, 0xB8B5, 0x5085, 0xB8B6, 0x4ED8, 0xB8B7, 0x961C, 0xB8B8, 0x7236, 0xB8B9, 0x8179, 0xB8BA, 0x8D1F, 0xB8BB, 0x5BCC, + 0xB8BC, 0x8BA3, 0xB8BD, 0x9644, 0xB8BE, 0x5987, 0xB8BF, 0x7F1A, 0xB8C0, 0x5490, 0xB8C1, 0x5676, 0xB8C2, 0x560E, 0xB8C3, 0x8BE5, + 0xB8C4, 0x6539, 0xB8C5, 0x6982, 0xB8C6, 0x9499, 0xB8C7, 0x76D6, 0xB8C8, 0x6E89, 0xB8C9, 0x5E72, 0xB8CA, 0x7518, 0xB8CB, 0x6746, + 0xB8CC, 0x67D1, 0xB8CD, 0x7AFF, 0xB8CE, 0x809D, 0xB8CF, 0x8D76, 0xB8D0, 0x611F, 0xB8D1, 0x79C6, 0xB8D2, 0x6562, 0xB8D3, 0x8D63, + 0xB8D4, 0x5188, 0xB8D5, 0x521A, 0xB8D6, 0x94A2, 0xB8D7, 0x7F38, 0xB8D8, 0x809B, 0xB8D9, 0x7EB2, 0xB8DA, 0x5C97, 0xB8DB, 0x6E2F, + 0xB8DC, 0x6760, 0xB8DD, 0x7BD9, 0xB8DE, 0x768B, 0xB8DF, 0x9AD8, 0xB8E0, 0x818F, 0xB8E1, 0x7F94, 0xB8E2, 0x7CD5, 0xB8E3, 0x641E, + 0xB8E4, 0x9550, 0xB8E5, 0x7A3F, 0xB8E6, 0x544A, 0xB8E7, 0x54E5, 0xB8E8, 0x6B4C, 0xB8E9, 0x6401, 0xB8EA, 0x6208, 0xB8EB, 0x9E3D, + 0xB8EC, 0x80F3, 0xB8ED, 0x7599, 0xB8EE, 0x5272, 0xB8EF, 0x9769, 0xB8F0, 0x845B, 0xB8F1, 0x683C, 0xB8F2, 0x86E4, 0xB8F3, 0x9601, + 0xB8F4, 0x9694, 0xB8F5, 0x94EC, 0xB8F6, 0x4E2A, 0xB8F7, 0x5404, 0xB8F8, 0x7ED9, 0xB8F9, 0x6839, 0xB8FA, 0x8DDF, 0xB8FB, 0x8015, + 0xB8FC, 0x66F4, 0xB8FD, 0x5E9A, 0xB8FE, 0x7FB9, 0xB940, 0x7B2F, 0xB941, 0x7B30, 0xB942, 0x7B32, 0xB943, 0x7B34, 0xB944, 0x7B35, + 0xB945, 0x7B36, 0xB946, 0x7B37, 0xB947, 0x7B39, 0xB948, 0x7B3B, 0xB949, 0x7B3D, 0xB94A, 0x7B3F, 0xB94B, 0x7B40, 0xB94C, 0x7B41, + 0xB94D, 0x7B42, 0xB94E, 0x7B43, 0xB94F, 0x7B44, 0xB950, 0x7B46, 0xB951, 0x7B48, 0xB952, 0x7B4A, 0xB953, 0x7B4D, 0xB954, 0x7B4E, + 0xB955, 0x7B53, 0xB956, 0x7B55, 0xB957, 0x7B57, 0xB958, 0x7B59, 0xB959, 0x7B5C, 0xB95A, 0x7B5E, 0xB95B, 0x7B5F, 0xB95C, 0x7B61, + 0xB95D, 0x7B63, 0xB95E, 0x7B64, 0xB95F, 0x7B65, 0xB960, 0x7B66, 0xB961, 0x7B67, 0xB962, 0x7B68, 0xB963, 0x7B69, 0xB964, 0x7B6A, + 0xB965, 0x7B6B, 0xB966, 0x7B6C, 0xB967, 0x7B6D, 0xB968, 0x7B6F, 0xB969, 0x7B70, 0xB96A, 0x7B73, 0xB96B, 0x7B74, 0xB96C, 0x7B76, + 0xB96D, 0x7B78, 0xB96E, 0x7B7A, 0xB96F, 0x7B7C, 0xB970, 0x7B7D, 0xB971, 0x7B7F, 0xB972, 0x7B81, 0xB973, 0x7B82, 0xB974, 0x7B83, + 0xB975, 0x7B84, 0xB976, 0x7B86, 0xB977, 0x7B87, 0xB978, 0x7B88, 0xB979, 0x7B89, 0xB97A, 0x7B8A, 0xB97B, 0x7B8B, 0xB97C, 0x7B8C, + 0xB97D, 0x7B8E, 0xB97E, 0x7B8F, 0xB980, 0x7B91, 0xB981, 0x7B92, 0xB982, 0x7B93, 0xB983, 0x7B96, 0xB984, 0x7B98, 0xB985, 0x7B99, + 0xB986, 0x7B9A, 0xB987, 0x7B9B, 0xB988, 0x7B9E, 0xB989, 0x7B9F, 0xB98A, 0x7BA0, 0xB98B, 0x7BA3, 0xB98C, 0x7BA4, 0xB98D, 0x7BA5, + 0xB98E, 0x7BAE, 0xB98F, 0x7BAF, 0xB990, 0x7BB0, 0xB991, 0x7BB2, 0xB992, 0x7BB3, 0xB993, 0x7BB5, 0xB994, 0x7BB6, 0xB995, 0x7BB7, + 0xB996, 0x7BB9, 0xB997, 0x7BBA, 0xB998, 0x7BBB, 0xB999, 0x7BBC, 0xB99A, 0x7BBD, 0xB99B, 0x7BBE, 0xB99C, 0x7BBF, 0xB99D, 0x7BC0, + 0xB99E, 0x7BC2, 0xB99F, 0x7BC3, 0xB9A0, 0x7BC4, 0xB9A1, 0x57C2, 0xB9A2, 0x803F, 0xB9A3, 0x6897, 0xB9A4, 0x5DE5, 0xB9A5, 0x653B, + 0xB9A6, 0x529F, 0xB9A7, 0x606D, 0xB9A8, 0x9F9A, 0xB9A9, 0x4F9B, 0xB9AA, 0x8EAC, 0xB9AB, 0x516C, 0xB9AC, 0x5BAB, 0xB9AD, 0x5F13, + 0xB9AE, 0x5DE9, 0xB9AF, 0x6C5E, 0xB9B0, 0x62F1, 0xB9B1, 0x8D21, 0xB9B2, 0x5171, 0xB9B3, 0x94A9, 0xB9B4, 0x52FE, 0xB9B5, 0x6C9F, + 0xB9B6, 0x82DF, 0xB9B7, 0x72D7, 0xB9B8, 0x57A2, 0xB9B9, 0x6784, 0xB9BA, 0x8D2D, 0xB9BB, 0x591F, 0xB9BC, 0x8F9C, 0xB9BD, 0x83C7, + 0xB9BE, 0x5495, 0xB9BF, 0x7B8D, 0xB9C0, 0x4F30, 0xB9C1, 0x6CBD, 0xB9C2, 0x5B64, 0xB9C3, 0x59D1, 0xB9C4, 0x9F13, 0xB9C5, 0x53E4, + 0xB9C6, 0x86CA, 0xB9C7, 0x9AA8, 0xB9C8, 0x8C37, 0xB9C9, 0x80A1, 0xB9CA, 0x6545, 0xB9CB, 0x987E, 0xB9CC, 0x56FA, 0xB9CD, 0x96C7, + 0xB9CE, 0x522E, 0xB9CF, 0x74DC, 0xB9D0, 0x5250, 0xB9D1, 0x5BE1, 0xB9D2, 0x6302, 0xB9D3, 0x8902, 0xB9D4, 0x4E56, 0xB9D5, 0x62D0, + 0xB9D6, 0x602A, 0xB9D7, 0x68FA, 0xB9D8, 0x5173, 0xB9D9, 0x5B98, 0xB9DA, 0x51A0, 0xB9DB, 0x89C2, 0xB9DC, 0x7BA1, 0xB9DD, 0x9986, + 0xB9DE, 0x7F50, 0xB9DF, 0x60EF, 0xB9E0, 0x704C, 0xB9E1, 0x8D2F, 0xB9E2, 0x5149, 0xB9E3, 0x5E7F, 0xB9E4, 0x901B, 0xB9E5, 0x7470, + 0xB9E6, 0x89C4, 0xB9E7, 0x572D, 0xB9E8, 0x7845, 0xB9E9, 0x5F52, 0xB9EA, 0x9F9F, 0xB9EB, 0x95FA, 0xB9EC, 0x8F68, 0xB9ED, 0x9B3C, + 0xB9EE, 0x8BE1, 0xB9EF, 0x7678, 0xB9F0, 0x6842, 0xB9F1, 0x67DC, 0xB9F2, 0x8DEA, 0xB9F3, 0x8D35, 0xB9F4, 0x523D, 0xB9F5, 0x8F8A, + 0xB9F6, 0x6EDA, 0xB9F7, 0x68CD, 0xB9F8, 0x9505, 0xB9F9, 0x90ED, 0xB9FA, 0x56FD, 0xB9FB, 0x679C, 0xB9FC, 0x88F9, 0xB9FD, 0x8FC7, + 0xB9FE, 0x54C8, 0xBA40, 0x7BC5, 0xBA41, 0x7BC8, 0xBA42, 0x7BC9, 0xBA43, 0x7BCA, 0xBA44, 0x7BCB, 0xBA45, 0x7BCD, 0xBA46, 0x7BCE, + 0xBA47, 0x7BCF, 0xBA48, 0x7BD0, 0xBA49, 0x7BD2, 0xBA4A, 0x7BD4, 0xBA4B, 0x7BD5, 0xBA4C, 0x7BD6, 0xBA4D, 0x7BD7, 0xBA4E, 0x7BD8, + 0xBA4F, 0x7BDB, 0xBA50, 0x7BDC, 0xBA51, 0x7BDE, 0xBA52, 0x7BDF, 0xBA53, 0x7BE0, 0xBA54, 0x7BE2, 0xBA55, 0x7BE3, 0xBA56, 0x7BE4, + 0xBA57, 0x7BE7, 0xBA58, 0x7BE8, 0xBA59, 0x7BE9, 0xBA5A, 0x7BEB, 0xBA5B, 0x7BEC, 0xBA5C, 0x7BED, 0xBA5D, 0x7BEF, 0xBA5E, 0x7BF0, + 0xBA5F, 0x7BF2, 0xBA60, 0x7BF3, 0xBA61, 0x7BF4, 0xBA62, 0x7BF5, 0xBA63, 0x7BF6, 0xBA64, 0x7BF8, 0xBA65, 0x7BF9, 0xBA66, 0x7BFA, + 0xBA67, 0x7BFB, 0xBA68, 0x7BFD, 0xBA69, 0x7BFF, 0xBA6A, 0x7C00, 0xBA6B, 0x7C01, 0xBA6C, 0x7C02, 0xBA6D, 0x7C03, 0xBA6E, 0x7C04, + 0xBA6F, 0x7C05, 0xBA70, 0x7C06, 0xBA71, 0x7C08, 0xBA72, 0x7C09, 0xBA73, 0x7C0A, 0xBA74, 0x7C0D, 0xBA75, 0x7C0E, 0xBA76, 0x7C10, + 0xBA77, 0x7C11, 0xBA78, 0x7C12, 0xBA79, 0x7C13, 0xBA7A, 0x7C14, 0xBA7B, 0x7C15, 0xBA7C, 0x7C17, 0xBA7D, 0x7C18, 0xBA7E, 0x7C19, + 0xBA80, 0x7C1A, 0xBA81, 0x7C1B, 0xBA82, 0x7C1C, 0xBA83, 0x7C1D, 0xBA84, 0x7C1E, 0xBA85, 0x7C20, 0xBA86, 0x7C21, 0xBA87, 0x7C22, + 0xBA88, 0x7C23, 0xBA89, 0x7C24, 0xBA8A, 0x7C25, 0xBA8B, 0x7C28, 0xBA8C, 0x7C29, 0xBA8D, 0x7C2B, 0xBA8E, 0x7C2C, 0xBA8F, 0x7C2D, + 0xBA90, 0x7C2E, 0xBA91, 0x7C2F, 0xBA92, 0x7C30, 0xBA93, 0x7C31, 0xBA94, 0x7C32, 0xBA95, 0x7C33, 0xBA96, 0x7C34, 0xBA97, 0x7C35, + 0xBA98, 0x7C36, 0xBA99, 0x7C37, 0xBA9A, 0x7C39, 0xBA9B, 0x7C3A, 0xBA9C, 0x7C3B, 0xBA9D, 0x7C3C, 0xBA9E, 0x7C3D, 0xBA9F, 0x7C3E, + 0xBAA0, 0x7C42, 0xBAA1, 0x9AB8, 0xBAA2, 0x5B69, 0xBAA3, 0x6D77, 0xBAA4, 0x6C26, 0xBAA5, 0x4EA5, 0xBAA6, 0x5BB3, 0xBAA7, 0x9A87, + 0xBAA8, 0x9163, 0xBAA9, 0x61A8, 0xBAAA, 0x90AF, 0xBAAB, 0x97E9, 0xBAAC, 0x542B, 0xBAAD, 0x6DB5, 0xBAAE, 0x5BD2, 0xBAAF, 0x51FD, + 0xBAB0, 0x558A, 0xBAB1, 0x7F55, 0xBAB2, 0x7FF0, 0xBAB3, 0x64BC, 0xBAB4, 0x634D, 0xBAB5, 0x65F1, 0xBAB6, 0x61BE, 0xBAB7, 0x608D, + 0xBAB8, 0x710A, 0xBAB9, 0x6C57, 0xBABA, 0x6C49, 0xBABB, 0x592F, 0xBABC, 0x676D, 0xBABD, 0x822A, 0xBABE, 0x58D5, 0xBABF, 0x568E, + 0xBAC0, 0x8C6A, 0xBAC1, 0x6BEB, 0xBAC2, 0x90DD, 0xBAC3, 0x597D, 0xBAC4, 0x8017, 0xBAC5, 0x53F7, 0xBAC6, 0x6D69, 0xBAC7, 0x5475, + 0xBAC8, 0x559D, 0xBAC9, 0x8377, 0xBACA, 0x83CF, 0xBACB, 0x6838, 0xBACC, 0x79BE, 0xBACD, 0x548C, 0xBACE, 0x4F55, 0xBACF, 0x5408, + 0xBAD0, 0x76D2, 0xBAD1, 0x8C89, 0xBAD2, 0x9602, 0xBAD3, 0x6CB3, 0xBAD4, 0x6DB8, 0xBAD5, 0x8D6B, 0xBAD6, 0x8910, 0xBAD7, 0x9E64, + 0xBAD8, 0x8D3A, 0xBAD9, 0x563F, 0xBADA, 0x9ED1, 0xBADB, 0x75D5, 0xBADC, 0x5F88, 0xBADD, 0x72E0, 0xBADE, 0x6068, 0xBADF, 0x54FC, + 0xBAE0, 0x4EA8, 0xBAE1, 0x6A2A, 0xBAE2, 0x8861, 0xBAE3, 0x6052, 0xBAE4, 0x8F70, 0xBAE5, 0x54C4, 0xBAE6, 0x70D8, 0xBAE7, 0x8679, + 0xBAE8, 0x9E3F, 0xBAE9, 0x6D2A, 0xBAEA, 0x5B8F, 0xBAEB, 0x5F18, 0xBAEC, 0x7EA2, 0xBAED, 0x5589, 0xBAEE, 0x4FAF, 0xBAEF, 0x7334, + 0xBAF0, 0x543C, 0xBAF1, 0x539A, 0xBAF2, 0x5019, 0xBAF3, 0x540E, 0xBAF4, 0x547C, 0xBAF5, 0x4E4E, 0xBAF6, 0x5FFD, 0xBAF7, 0x745A, + 0xBAF8, 0x58F6, 0xBAF9, 0x846B, 0xBAFA, 0x80E1, 0xBAFB, 0x8774, 0xBAFC, 0x72D0, 0xBAFD, 0x7CCA, 0xBAFE, 0x6E56, 0xBB40, 0x7C43, + 0xBB41, 0x7C44, 0xBB42, 0x7C45, 0xBB43, 0x7C46, 0xBB44, 0x7C47, 0xBB45, 0x7C48, 0xBB46, 0x7C49, 0xBB47, 0x7C4A, 0xBB48, 0x7C4B, + 0xBB49, 0x7C4C, 0xBB4A, 0x7C4E, 0xBB4B, 0x7C4F, 0xBB4C, 0x7C50, 0xBB4D, 0x7C51, 0xBB4E, 0x7C52, 0xBB4F, 0x7C53, 0xBB50, 0x7C54, + 0xBB51, 0x7C55, 0xBB52, 0x7C56, 0xBB53, 0x7C57, 0xBB54, 0x7C58, 0xBB55, 0x7C59, 0xBB56, 0x7C5A, 0xBB57, 0x7C5B, 0xBB58, 0x7C5C, + 0xBB59, 0x7C5D, 0xBB5A, 0x7C5E, 0xBB5B, 0x7C5F, 0xBB5C, 0x7C60, 0xBB5D, 0x7C61, 0xBB5E, 0x7C62, 0xBB5F, 0x7C63, 0xBB60, 0x7C64, + 0xBB61, 0x7C65, 0xBB62, 0x7C66, 0xBB63, 0x7C67, 0xBB64, 0x7C68, 0xBB65, 0x7C69, 0xBB66, 0x7C6A, 0xBB67, 0x7C6B, 0xBB68, 0x7C6C, + 0xBB69, 0x7C6D, 0xBB6A, 0x7C6E, 0xBB6B, 0x7C6F, 0xBB6C, 0x7C70, 0xBB6D, 0x7C71, 0xBB6E, 0x7C72, 0xBB6F, 0x7C75, 0xBB70, 0x7C76, + 0xBB71, 0x7C77, 0xBB72, 0x7C78, 0xBB73, 0x7C79, 0xBB74, 0x7C7A, 0xBB75, 0x7C7E, 0xBB76, 0x7C7F, 0xBB77, 0x7C80, 0xBB78, 0x7C81, + 0xBB79, 0x7C82, 0xBB7A, 0x7C83, 0xBB7B, 0x7C84, 0xBB7C, 0x7C85, 0xBB7D, 0x7C86, 0xBB7E, 0x7C87, 0xBB80, 0x7C88, 0xBB81, 0x7C8A, + 0xBB82, 0x7C8B, 0xBB83, 0x7C8C, 0xBB84, 0x7C8D, 0xBB85, 0x7C8E, 0xBB86, 0x7C8F, 0xBB87, 0x7C90, 0xBB88, 0x7C93, 0xBB89, 0x7C94, + 0xBB8A, 0x7C96, 0xBB8B, 0x7C99, 0xBB8C, 0x7C9A, 0xBB8D, 0x7C9B, 0xBB8E, 0x7CA0, 0xBB8F, 0x7CA1, 0xBB90, 0x7CA3, 0xBB91, 0x7CA6, + 0xBB92, 0x7CA7, 0xBB93, 0x7CA8, 0xBB94, 0x7CA9, 0xBB95, 0x7CAB, 0xBB96, 0x7CAC, 0xBB97, 0x7CAD, 0xBB98, 0x7CAF, 0xBB99, 0x7CB0, + 0xBB9A, 0x7CB4, 0xBB9B, 0x7CB5, 0xBB9C, 0x7CB6, 0xBB9D, 0x7CB7, 0xBB9E, 0x7CB8, 0xBB9F, 0x7CBA, 0xBBA0, 0x7CBB, 0xBBA1, 0x5F27, + 0xBBA2, 0x864E, 0xBBA3, 0x552C, 0xBBA4, 0x62A4, 0xBBA5, 0x4E92, 0xBBA6, 0x6CAA, 0xBBA7, 0x6237, 0xBBA8, 0x82B1, 0xBBA9, 0x54D7, + 0xBBAA, 0x534E, 0xBBAB, 0x733E, 0xBBAC, 0x6ED1, 0xBBAD, 0x753B, 0xBBAE, 0x5212, 0xBBAF, 0x5316, 0xBBB0, 0x8BDD, 0xBBB1, 0x69D0, + 0xBBB2, 0x5F8A, 0xBBB3, 0x6000, 0xBBB4, 0x6DEE, 0xBBB5, 0x574F, 0xBBB6, 0x6B22, 0xBBB7, 0x73AF, 0xBBB8, 0x6853, 0xBBB9, 0x8FD8, + 0xBBBA, 0x7F13, 0xBBBB, 0x6362, 0xBBBC, 0x60A3, 0xBBBD, 0x5524, 0xBBBE, 0x75EA, 0xBBBF, 0x8C62, 0xBBC0, 0x7115, 0xBBC1, 0x6DA3, + 0xBBC2, 0x5BA6, 0xBBC3, 0x5E7B, 0xBBC4, 0x8352, 0xBBC5, 0x614C, 0xBBC6, 0x9EC4, 0xBBC7, 0x78FA, 0xBBC8, 0x8757, 0xBBC9, 0x7C27, + 0xBBCA, 0x7687, 0xBBCB, 0x51F0, 0xBBCC, 0x60F6, 0xBBCD, 0x714C, 0xBBCE, 0x6643, 0xBBCF, 0x5E4C, 0xBBD0, 0x604D, 0xBBD1, 0x8C0E, + 0xBBD2, 0x7070, 0xBBD3, 0x6325, 0xBBD4, 0x8F89, 0xBBD5, 0x5FBD, 0xBBD6, 0x6062, 0xBBD7, 0x86D4, 0xBBD8, 0x56DE, 0xBBD9, 0x6BC1, + 0xBBDA, 0x6094, 0xBBDB, 0x6167, 0xBBDC, 0x5349, 0xBBDD, 0x60E0, 0xBBDE, 0x6666, 0xBBDF, 0x8D3F, 0xBBE0, 0x79FD, 0xBBE1, 0x4F1A, + 0xBBE2, 0x70E9, 0xBBE3, 0x6C47, 0xBBE4, 0x8BB3, 0xBBE5, 0x8BF2, 0xBBE6, 0x7ED8, 0xBBE7, 0x8364, 0xBBE8, 0x660F, 0xBBE9, 0x5A5A, + 0xBBEA, 0x9B42, 0xBBEB, 0x6D51, 0xBBEC, 0x6DF7, 0xBBED, 0x8C41, 0xBBEE, 0x6D3B, 0xBBEF, 0x4F19, 0xBBF0, 0x706B, 0xBBF1, 0x83B7, + 0xBBF2, 0x6216, 0xBBF3, 0x60D1, 0xBBF4, 0x970D, 0xBBF5, 0x8D27, 0xBBF6, 0x7978, 0xBBF7, 0x51FB, 0xBBF8, 0x573E, 0xBBF9, 0x57FA, + 0xBBFA, 0x673A, 0xBBFB, 0x7578, 0xBBFC, 0x7A3D, 0xBBFD, 0x79EF, 0xBBFE, 0x7B95, 0xBC40, 0x7CBF, 0xBC41, 0x7CC0, 0xBC42, 0x7CC2, + 0xBC43, 0x7CC3, 0xBC44, 0x7CC4, 0xBC45, 0x7CC6, 0xBC46, 0x7CC9, 0xBC47, 0x7CCB, 0xBC48, 0x7CCE, 0xBC49, 0x7CCF, 0xBC4A, 0x7CD0, + 0xBC4B, 0x7CD1, 0xBC4C, 0x7CD2, 0xBC4D, 0x7CD3, 0xBC4E, 0x7CD4, 0xBC4F, 0x7CD8, 0xBC50, 0x7CDA, 0xBC51, 0x7CDB, 0xBC52, 0x7CDD, + 0xBC53, 0x7CDE, 0xBC54, 0x7CE1, 0xBC55, 0x7CE2, 0xBC56, 0x7CE3, 0xBC57, 0x7CE4, 0xBC58, 0x7CE5, 0xBC59, 0x7CE6, 0xBC5A, 0x7CE7, + 0xBC5B, 0x7CE9, 0xBC5C, 0x7CEA, 0xBC5D, 0x7CEB, 0xBC5E, 0x7CEC, 0xBC5F, 0x7CED, 0xBC60, 0x7CEE, 0xBC61, 0x7CF0, 0xBC62, 0x7CF1, + 0xBC63, 0x7CF2, 0xBC64, 0x7CF3, 0xBC65, 0x7CF4, 0xBC66, 0x7CF5, 0xBC67, 0x7CF6, 0xBC68, 0x7CF7, 0xBC69, 0x7CF9, 0xBC6A, 0x7CFA, + 0xBC6B, 0x7CFC, 0xBC6C, 0x7CFD, 0xBC6D, 0x7CFE, 0xBC6E, 0x7CFF, 0xBC6F, 0x7D00, 0xBC70, 0x7D01, 0xBC71, 0x7D02, 0xBC72, 0x7D03, + 0xBC73, 0x7D04, 0xBC74, 0x7D05, 0xBC75, 0x7D06, 0xBC76, 0x7D07, 0xBC77, 0x7D08, 0xBC78, 0x7D09, 0xBC79, 0x7D0B, 0xBC7A, 0x7D0C, + 0xBC7B, 0x7D0D, 0xBC7C, 0x7D0E, 0xBC7D, 0x7D0F, 0xBC7E, 0x7D10, 0xBC80, 0x7D11, 0xBC81, 0x7D12, 0xBC82, 0x7D13, 0xBC83, 0x7D14, + 0xBC84, 0x7D15, 0xBC85, 0x7D16, 0xBC86, 0x7D17, 0xBC87, 0x7D18, 0xBC88, 0x7D19, 0xBC89, 0x7D1A, 0xBC8A, 0x7D1B, 0xBC8B, 0x7D1C, + 0xBC8C, 0x7D1D, 0xBC8D, 0x7D1E, 0xBC8E, 0x7D1F, 0xBC8F, 0x7D21, 0xBC90, 0x7D23, 0xBC91, 0x7D24, 0xBC92, 0x7D25, 0xBC93, 0x7D26, + 0xBC94, 0x7D28, 0xBC95, 0x7D29, 0xBC96, 0x7D2A, 0xBC97, 0x7D2C, 0xBC98, 0x7D2D, 0xBC99, 0x7D2E, 0xBC9A, 0x7D30, 0xBC9B, 0x7D31, + 0xBC9C, 0x7D32, 0xBC9D, 0x7D33, 0xBC9E, 0x7D34, 0xBC9F, 0x7D35, 0xBCA0, 0x7D36, 0xBCA1, 0x808C, 0xBCA2, 0x9965, 0xBCA3, 0x8FF9, + 0xBCA4, 0x6FC0, 0xBCA5, 0x8BA5, 0xBCA6, 0x9E21, 0xBCA7, 0x59EC, 0xBCA8, 0x7EE9, 0xBCA9, 0x7F09, 0xBCAA, 0x5409, 0xBCAB, 0x6781, + 0xBCAC, 0x68D8, 0xBCAD, 0x8F91, 0xBCAE, 0x7C4D, 0xBCAF, 0x96C6, 0xBCB0, 0x53CA, 0xBCB1, 0x6025, 0xBCB2, 0x75BE, 0xBCB3, 0x6C72, + 0xBCB4, 0x5373, 0xBCB5, 0x5AC9, 0xBCB6, 0x7EA7, 0xBCB7, 0x6324, 0xBCB8, 0x51E0, 0xBCB9, 0x810A, 0xBCBA, 0x5DF1, 0xBCBB, 0x84DF, + 0xBCBC, 0x6280, 0xBCBD, 0x5180, 0xBCBE, 0x5B63, 0xBCBF, 0x4F0E, 0xBCC0, 0x796D, 0xBCC1, 0x5242, 0xBCC2, 0x60B8, 0xBCC3, 0x6D4E, + 0xBCC4, 0x5BC4, 0xBCC5, 0x5BC2, 0xBCC6, 0x8BA1, 0xBCC7, 0x8BB0, 0xBCC8, 0x65E2, 0xBCC9, 0x5FCC, 0xBCCA, 0x9645, 0xBCCB, 0x5993, + 0xBCCC, 0x7EE7, 0xBCCD, 0x7EAA, 0xBCCE, 0x5609, 0xBCCF, 0x67B7, 0xBCD0, 0x5939, 0xBCD1, 0x4F73, 0xBCD2, 0x5BB6, 0xBCD3, 0x52A0, + 0xBCD4, 0x835A, 0xBCD5, 0x988A, 0xBCD6, 0x8D3E, 0xBCD7, 0x7532, 0xBCD8, 0x94BE, 0xBCD9, 0x5047, 0xBCDA, 0x7A3C, 0xBCDB, 0x4EF7, + 0xBCDC, 0x67B6, 0xBCDD, 0x9A7E, 0xBCDE, 0x5AC1, 0xBCDF, 0x6B7C, 0xBCE0, 0x76D1, 0xBCE1, 0x575A, 0xBCE2, 0x5C16, 0xBCE3, 0x7B3A, + 0xBCE4, 0x95F4, 0xBCE5, 0x714E, 0xBCE6, 0x517C, 0xBCE7, 0x80A9, 0xBCE8, 0x8270, 0xBCE9, 0x5978, 0xBCEA, 0x7F04, 0xBCEB, 0x8327, + 0xBCEC, 0x68C0, 0xBCED, 0x67EC, 0xBCEE, 0x78B1, 0xBCEF, 0x7877, 0xBCF0, 0x62E3, 0xBCF1, 0x6361, 0xBCF2, 0x7B80, 0xBCF3, 0x4FED, + 0xBCF4, 0x526A, 0xBCF5, 0x51CF, 0xBCF6, 0x8350, 0xBCF7, 0x69DB, 0xBCF8, 0x9274, 0xBCF9, 0x8DF5, 0xBCFA, 0x8D31, 0xBCFB, 0x89C1, + 0xBCFC, 0x952E, 0xBCFD, 0x7BAD, 0xBCFE, 0x4EF6, 0xBD40, 0x7D37, 0xBD41, 0x7D38, 0xBD42, 0x7D39, 0xBD43, 0x7D3A, 0xBD44, 0x7D3B, + 0xBD45, 0x7D3C, 0xBD46, 0x7D3D, 0xBD47, 0x7D3E, 0xBD48, 0x7D3F, 0xBD49, 0x7D40, 0xBD4A, 0x7D41, 0xBD4B, 0x7D42, 0xBD4C, 0x7D43, + 0xBD4D, 0x7D44, 0xBD4E, 0x7D45, 0xBD4F, 0x7D46, 0xBD50, 0x7D47, 0xBD51, 0x7D48, 0xBD52, 0x7D49, 0xBD53, 0x7D4A, 0xBD54, 0x7D4B, + 0xBD55, 0x7D4C, 0xBD56, 0x7D4D, 0xBD57, 0x7D4E, 0xBD58, 0x7D4F, 0xBD59, 0x7D50, 0xBD5A, 0x7D51, 0xBD5B, 0x7D52, 0xBD5C, 0x7D53, + 0xBD5D, 0x7D54, 0xBD5E, 0x7D55, 0xBD5F, 0x7D56, 0xBD60, 0x7D57, 0xBD61, 0x7D58, 0xBD62, 0x7D59, 0xBD63, 0x7D5A, 0xBD64, 0x7D5B, + 0xBD65, 0x7D5C, 0xBD66, 0x7D5D, 0xBD67, 0x7D5E, 0xBD68, 0x7D5F, 0xBD69, 0x7D60, 0xBD6A, 0x7D61, 0xBD6B, 0x7D62, 0xBD6C, 0x7D63, + 0xBD6D, 0x7D64, 0xBD6E, 0x7D65, 0xBD6F, 0x7D66, 0xBD70, 0x7D67, 0xBD71, 0x7D68, 0xBD72, 0x7D69, 0xBD73, 0x7D6A, 0xBD74, 0x7D6B, + 0xBD75, 0x7D6C, 0xBD76, 0x7D6D, 0xBD77, 0x7D6F, 0xBD78, 0x7D70, 0xBD79, 0x7D71, 0xBD7A, 0x7D72, 0xBD7B, 0x7D73, 0xBD7C, 0x7D74, + 0xBD7D, 0x7D75, 0xBD7E, 0x7D76, 0xBD80, 0x7D78, 0xBD81, 0x7D79, 0xBD82, 0x7D7A, 0xBD83, 0x7D7B, 0xBD84, 0x7D7C, 0xBD85, 0x7D7D, + 0xBD86, 0x7D7E, 0xBD87, 0x7D7F, 0xBD88, 0x7D80, 0xBD89, 0x7D81, 0xBD8A, 0x7D82, 0xBD8B, 0x7D83, 0xBD8C, 0x7D84, 0xBD8D, 0x7D85, + 0xBD8E, 0x7D86, 0xBD8F, 0x7D87, 0xBD90, 0x7D88, 0xBD91, 0x7D89, 0xBD92, 0x7D8A, 0xBD93, 0x7D8B, 0xBD94, 0x7D8C, 0xBD95, 0x7D8D, + 0xBD96, 0x7D8E, 0xBD97, 0x7D8F, 0xBD98, 0x7D90, 0xBD99, 0x7D91, 0xBD9A, 0x7D92, 0xBD9B, 0x7D93, 0xBD9C, 0x7D94, 0xBD9D, 0x7D95, + 0xBD9E, 0x7D96, 0xBD9F, 0x7D97, 0xBDA0, 0x7D98, 0xBDA1, 0x5065, 0xBDA2, 0x8230, 0xBDA3, 0x5251, 0xBDA4, 0x996F, 0xBDA5, 0x6E10, + 0xBDA6, 0x6E85, 0xBDA7, 0x6DA7, 0xBDA8, 0x5EFA, 0xBDA9, 0x50F5, 0xBDAA, 0x59DC, 0xBDAB, 0x5C06, 0xBDAC, 0x6D46, 0xBDAD, 0x6C5F, + 0xBDAE, 0x7586, 0xBDAF, 0x848B, 0xBDB0, 0x6868, 0xBDB1, 0x5956, 0xBDB2, 0x8BB2, 0xBDB3, 0x5320, 0xBDB4, 0x9171, 0xBDB5, 0x964D, + 0xBDB6, 0x8549, 0xBDB7, 0x6912, 0xBDB8, 0x7901, 0xBDB9, 0x7126, 0xBDBA, 0x80F6, 0xBDBB, 0x4EA4, 0xBDBC, 0x90CA, 0xBDBD, 0x6D47, + 0xBDBE, 0x9A84, 0xBDBF, 0x5A07, 0xBDC0, 0x56BC, 0xBDC1, 0x6405, 0xBDC2, 0x94F0, 0xBDC3, 0x77EB, 0xBDC4, 0x4FA5, 0xBDC5, 0x811A, + 0xBDC6, 0x72E1, 0xBDC7, 0x89D2, 0xBDC8, 0x997A, 0xBDC9, 0x7F34, 0xBDCA, 0x7EDE, 0xBDCB, 0x527F, 0xBDCC, 0x6559, 0xBDCD, 0x9175, + 0xBDCE, 0x8F7F, 0xBDCF, 0x8F83, 0xBDD0, 0x53EB, 0xBDD1, 0x7A96, 0xBDD2, 0x63ED, 0xBDD3, 0x63A5, 0xBDD4, 0x7686, 0xBDD5, 0x79F8, + 0xBDD6, 0x8857, 0xBDD7, 0x9636, 0xBDD8, 0x622A, 0xBDD9, 0x52AB, 0xBDDA, 0x8282, 0xBDDB, 0x6854, 0xBDDC, 0x6770, 0xBDDD, 0x6377, + 0xBDDE, 0x776B, 0xBDDF, 0x7AED, 0xBDE0, 0x6D01, 0xBDE1, 0x7ED3, 0xBDE2, 0x89E3, 0xBDE3, 0x59D0, 0xBDE4, 0x6212, 0xBDE5, 0x85C9, + 0xBDE6, 0x82A5, 0xBDE7, 0x754C, 0xBDE8, 0x501F, 0xBDE9, 0x4ECB, 0xBDEA, 0x75A5, 0xBDEB, 0x8BEB, 0xBDEC, 0x5C4A, 0xBDED, 0x5DFE, + 0xBDEE, 0x7B4B, 0xBDEF, 0x65A4, 0xBDF0, 0x91D1, 0xBDF1, 0x4ECA, 0xBDF2, 0x6D25, 0xBDF3, 0x895F, 0xBDF4, 0x7D27, 0xBDF5, 0x9526, + 0xBDF6, 0x4EC5, 0xBDF7, 0x8C28, 0xBDF8, 0x8FDB, 0xBDF9, 0x9773, 0xBDFA, 0x664B, 0xBDFB, 0x7981, 0xBDFC, 0x8FD1, 0xBDFD, 0x70EC, + 0xBDFE, 0x6D78, 0xBE40, 0x7D99, 0xBE41, 0x7D9A, 0xBE42, 0x7D9B, 0xBE43, 0x7D9C, 0xBE44, 0x7D9D, 0xBE45, 0x7D9E, 0xBE46, 0x7D9F, + 0xBE47, 0x7DA0, 0xBE48, 0x7DA1, 0xBE49, 0x7DA2, 0xBE4A, 0x7DA3, 0xBE4B, 0x7DA4, 0xBE4C, 0x7DA5, 0xBE4D, 0x7DA7, 0xBE4E, 0x7DA8, + 0xBE4F, 0x7DA9, 0xBE50, 0x7DAA, 0xBE51, 0x7DAB, 0xBE52, 0x7DAC, 0xBE53, 0x7DAD, 0xBE54, 0x7DAF, 0xBE55, 0x7DB0, 0xBE56, 0x7DB1, + 0xBE57, 0x7DB2, 0xBE58, 0x7DB3, 0xBE59, 0x7DB4, 0xBE5A, 0x7DB5, 0xBE5B, 0x7DB6, 0xBE5C, 0x7DB7, 0xBE5D, 0x7DB8, 0xBE5E, 0x7DB9, + 0xBE5F, 0x7DBA, 0xBE60, 0x7DBB, 0xBE61, 0x7DBC, 0xBE62, 0x7DBD, 0xBE63, 0x7DBE, 0xBE64, 0x7DBF, 0xBE65, 0x7DC0, 0xBE66, 0x7DC1, + 0xBE67, 0x7DC2, 0xBE68, 0x7DC3, 0xBE69, 0x7DC4, 0xBE6A, 0x7DC5, 0xBE6B, 0x7DC6, 0xBE6C, 0x7DC7, 0xBE6D, 0x7DC8, 0xBE6E, 0x7DC9, + 0xBE6F, 0x7DCA, 0xBE70, 0x7DCB, 0xBE71, 0x7DCC, 0xBE72, 0x7DCD, 0xBE73, 0x7DCE, 0xBE74, 0x7DCF, 0xBE75, 0x7DD0, 0xBE76, 0x7DD1, + 0xBE77, 0x7DD2, 0xBE78, 0x7DD3, 0xBE79, 0x7DD4, 0xBE7A, 0x7DD5, 0xBE7B, 0x7DD6, 0xBE7C, 0x7DD7, 0xBE7D, 0x7DD8, 0xBE7E, 0x7DD9, + 0xBE80, 0x7DDA, 0xBE81, 0x7DDB, 0xBE82, 0x7DDC, 0xBE83, 0x7DDD, 0xBE84, 0x7DDE, 0xBE85, 0x7DDF, 0xBE86, 0x7DE0, 0xBE87, 0x7DE1, + 0xBE88, 0x7DE2, 0xBE89, 0x7DE3, 0xBE8A, 0x7DE4, 0xBE8B, 0x7DE5, 0xBE8C, 0x7DE6, 0xBE8D, 0x7DE7, 0xBE8E, 0x7DE8, 0xBE8F, 0x7DE9, + 0xBE90, 0x7DEA, 0xBE91, 0x7DEB, 0xBE92, 0x7DEC, 0xBE93, 0x7DED, 0xBE94, 0x7DEE, 0xBE95, 0x7DEF, 0xBE96, 0x7DF0, 0xBE97, 0x7DF1, + 0xBE98, 0x7DF2, 0xBE99, 0x7DF3, 0xBE9A, 0x7DF4, 0xBE9B, 0x7DF5, 0xBE9C, 0x7DF6, 0xBE9D, 0x7DF7, 0xBE9E, 0x7DF8, 0xBE9F, 0x7DF9, + 0xBEA0, 0x7DFA, 0xBEA1, 0x5C3D, 0xBEA2, 0x52B2, 0xBEA3, 0x8346, 0xBEA4, 0x5162, 0xBEA5, 0x830E, 0xBEA6, 0x775B, 0xBEA7, 0x6676, + 0xBEA8, 0x9CB8, 0xBEA9, 0x4EAC, 0xBEAA, 0x60CA, 0xBEAB, 0x7CBE, 0xBEAC, 0x7CB3, 0xBEAD, 0x7ECF, 0xBEAE, 0x4E95, 0xBEAF, 0x8B66, + 0xBEB0, 0x666F, 0xBEB1, 0x9888, 0xBEB2, 0x9759, 0xBEB3, 0x5883, 0xBEB4, 0x656C, 0xBEB5, 0x955C, 0xBEB6, 0x5F84, 0xBEB7, 0x75C9, + 0xBEB8, 0x9756, 0xBEB9, 0x7ADF, 0xBEBA, 0x7ADE, 0xBEBB, 0x51C0, 0xBEBC, 0x70AF, 0xBEBD, 0x7A98, 0xBEBE, 0x63EA, 0xBEBF, 0x7A76, + 0xBEC0, 0x7EA0, 0xBEC1, 0x7396, 0xBEC2, 0x97ED, 0xBEC3, 0x4E45, 0xBEC4, 0x7078, 0xBEC5, 0x4E5D, 0xBEC6, 0x9152, 0xBEC7, 0x53A9, + 0xBEC8, 0x6551, 0xBEC9, 0x65E7, 0xBECA, 0x81FC, 0xBECB, 0x8205, 0xBECC, 0x548E, 0xBECD, 0x5C31, 0xBECE, 0x759A, 0xBECF, 0x97A0, + 0xBED0, 0x62D8, 0xBED1, 0x72D9, 0xBED2, 0x75BD, 0xBED3, 0x5C45, 0xBED4, 0x9A79, 0xBED5, 0x83CA, 0xBED6, 0x5C40, 0xBED7, 0x5480, + 0xBED8, 0x77E9, 0xBED9, 0x4E3E, 0xBEDA, 0x6CAE, 0xBEDB, 0x805A, 0xBEDC, 0x62D2, 0xBEDD, 0x636E, 0xBEDE, 0x5DE8, 0xBEDF, 0x5177, + 0xBEE0, 0x8DDD, 0xBEE1, 0x8E1E, 0xBEE2, 0x952F, 0xBEE3, 0x4FF1, 0xBEE4, 0x53E5, 0xBEE5, 0x60E7, 0xBEE6, 0x70AC, 0xBEE7, 0x5267, + 0xBEE8, 0x6350, 0xBEE9, 0x9E43, 0xBEEA, 0x5A1F, 0xBEEB, 0x5026, 0xBEEC, 0x7737, 0xBEED, 0x5377, 0xBEEE, 0x7EE2, 0xBEEF, 0x6485, + 0xBEF0, 0x652B, 0xBEF1, 0x6289, 0xBEF2, 0x6398, 0xBEF3, 0x5014, 0xBEF4, 0x7235, 0xBEF5, 0x89C9, 0xBEF6, 0x51B3, 0xBEF7, 0x8BC0, + 0xBEF8, 0x7EDD, 0xBEF9, 0x5747, 0xBEFA, 0x83CC, 0xBEFB, 0x94A7, 0xBEFC, 0x519B, 0xBEFD, 0x541B, 0xBEFE, 0x5CFB, 0xBF40, 0x7DFB, + 0xBF41, 0x7DFC, 0xBF42, 0x7DFD, 0xBF43, 0x7DFE, 0xBF44, 0x7DFF, 0xBF45, 0x7E00, 0xBF46, 0x7E01, 0xBF47, 0x7E02, 0xBF48, 0x7E03, + 0xBF49, 0x7E04, 0xBF4A, 0x7E05, 0xBF4B, 0x7E06, 0xBF4C, 0x7E07, 0xBF4D, 0x7E08, 0xBF4E, 0x7E09, 0xBF4F, 0x7E0A, 0xBF50, 0x7E0B, + 0xBF51, 0x7E0C, 0xBF52, 0x7E0D, 0xBF53, 0x7E0E, 0xBF54, 0x7E0F, 0xBF55, 0x7E10, 0xBF56, 0x7E11, 0xBF57, 0x7E12, 0xBF58, 0x7E13, + 0xBF59, 0x7E14, 0xBF5A, 0x7E15, 0xBF5B, 0x7E16, 0xBF5C, 0x7E17, 0xBF5D, 0x7E18, 0xBF5E, 0x7E19, 0xBF5F, 0x7E1A, 0xBF60, 0x7E1B, + 0xBF61, 0x7E1C, 0xBF62, 0x7E1D, 0xBF63, 0x7E1E, 0xBF64, 0x7E1F, 0xBF65, 0x7E20, 0xBF66, 0x7E21, 0xBF67, 0x7E22, 0xBF68, 0x7E23, + 0xBF69, 0x7E24, 0xBF6A, 0x7E25, 0xBF6B, 0x7E26, 0xBF6C, 0x7E27, 0xBF6D, 0x7E28, 0xBF6E, 0x7E29, 0xBF6F, 0x7E2A, 0xBF70, 0x7E2B, + 0xBF71, 0x7E2C, 0xBF72, 0x7E2D, 0xBF73, 0x7E2E, 0xBF74, 0x7E2F, 0xBF75, 0x7E30, 0xBF76, 0x7E31, 0xBF77, 0x7E32, 0xBF78, 0x7E33, + 0xBF79, 0x7E34, 0xBF7A, 0x7E35, 0xBF7B, 0x7E36, 0xBF7C, 0x7E37, 0xBF7D, 0x7E38, 0xBF7E, 0x7E39, 0xBF80, 0x7E3A, 0xBF81, 0x7E3C, + 0xBF82, 0x7E3D, 0xBF83, 0x7E3E, 0xBF84, 0x7E3F, 0xBF85, 0x7E40, 0xBF86, 0x7E42, 0xBF87, 0x7E43, 0xBF88, 0x7E44, 0xBF89, 0x7E45, + 0xBF8A, 0x7E46, 0xBF8B, 0x7E48, 0xBF8C, 0x7E49, 0xBF8D, 0x7E4A, 0xBF8E, 0x7E4B, 0xBF8F, 0x7E4C, 0xBF90, 0x7E4D, 0xBF91, 0x7E4E, + 0xBF92, 0x7E4F, 0xBF93, 0x7E50, 0xBF94, 0x7E51, 0xBF95, 0x7E52, 0xBF96, 0x7E53, 0xBF97, 0x7E54, 0xBF98, 0x7E55, 0xBF99, 0x7E56, + 0xBF9A, 0x7E57, 0xBF9B, 0x7E58, 0xBF9C, 0x7E59, 0xBF9D, 0x7E5A, 0xBF9E, 0x7E5B, 0xBF9F, 0x7E5C, 0xBFA0, 0x7E5D, 0xBFA1, 0x4FCA, + 0xBFA2, 0x7AE3, 0xBFA3, 0x6D5A, 0xBFA4, 0x90E1, 0xBFA5, 0x9A8F, 0xBFA6, 0x5580, 0xBFA7, 0x5496, 0xBFA8, 0x5361, 0xBFA9, 0x54AF, + 0xBFAA, 0x5F00, 0xBFAB, 0x63E9, 0xBFAC, 0x6977, 0xBFAD, 0x51EF, 0xBFAE, 0x6168, 0xBFAF, 0x520A, 0xBFB0, 0x582A, 0xBFB1, 0x52D8, + 0xBFB2, 0x574E, 0xBFB3, 0x780D, 0xBFB4, 0x770B, 0xBFB5, 0x5EB7, 0xBFB6, 0x6177, 0xBFB7, 0x7CE0, 0xBFB8, 0x625B, 0xBFB9, 0x6297, + 0xBFBA, 0x4EA2, 0xBFBB, 0x7095, 0xBFBC, 0x8003, 0xBFBD, 0x62F7, 0xBFBE, 0x70E4, 0xBFBF, 0x9760, 0xBFC0, 0x5777, 0xBFC1, 0x82DB, + 0xBFC2, 0x67EF, 0xBFC3, 0x68F5, 0xBFC4, 0x78D5, 0xBFC5, 0x9897, 0xBFC6, 0x79D1, 0xBFC7, 0x58F3, 0xBFC8, 0x54B3, 0xBFC9, 0x53EF, + 0xBFCA, 0x6E34, 0xBFCB, 0x514B, 0xBFCC, 0x523B, 0xBFCD, 0x5BA2, 0xBFCE, 0x8BFE, 0xBFCF, 0x80AF, 0xBFD0, 0x5543, 0xBFD1, 0x57A6, + 0xBFD2, 0x6073, 0xBFD3, 0x5751, 0xBFD4, 0x542D, 0xBFD5, 0x7A7A, 0xBFD6, 0x6050, 0xBFD7, 0x5B54, 0xBFD8, 0x63A7, 0xBFD9, 0x62A0, + 0xBFDA, 0x53E3, 0xBFDB, 0x6263, 0xBFDC, 0x5BC7, 0xBFDD, 0x67AF, 0xBFDE, 0x54ED, 0xBFDF, 0x7A9F, 0xBFE0, 0x82E6, 0xBFE1, 0x9177, + 0xBFE2, 0x5E93, 0xBFE3, 0x88E4, 0xBFE4, 0x5938, 0xBFE5, 0x57AE, 0xBFE6, 0x630E, 0xBFE7, 0x8DE8, 0xBFE8, 0x80EF, 0xBFE9, 0x5757, + 0xBFEA, 0x7B77, 0xBFEB, 0x4FA9, 0xBFEC, 0x5FEB, 0xBFED, 0x5BBD, 0xBFEE, 0x6B3E, 0xBFEF, 0x5321, 0xBFF0, 0x7B50, 0xBFF1, 0x72C2, + 0xBFF2, 0x6846, 0xBFF3, 0x77FF, 0xBFF4, 0x7736, 0xBFF5, 0x65F7, 0xBFF6, 0x51B5, 0xBFF7, 0x4E8F, 0xBFF8, 0x76D4, 0xBFF9, 0x5CBF, + 0xBFFA, 0x7AA5, 0xBFFB, 0x8475, 0xBFFC, 0x594E, 0xBFFD, 0x9B41, 0xBFFE, 0x5080, 0xC040, 0x7E5E, 0xC041, 0x7E5F, 0xC042, 0x7E60, + 0xC043, 0x7E61, 0xC044, 0x7E62, 0xC045, 0x7E63, 0xC046, 0x7E64, 0xC047, 0x7E65, 0xC048, 0x7E66, 0xC049, 0x7E67, 0xC04A, 0x7E68, + 0xC04B, 0x7E69, 0xC04C, 0x7E6A, 0xC04D, 0x7E6B, 0xC04E, 0x7E6C, 0xC04F, 0x7E6D, 0xC050, 0x7E6E, 0xC051, 0x7E6F, 0xC052, 0x7E70, + 0xC053, 0x7E71, 0xC054, 0x7E72, 0xC055, 0x7E73, 0xC056, 0x7E74, 0xC057, 0x7E75, 0xC058, 0x7E76, 0xC059, 0x7E77, 0xC05A, 0x7E78, + 0xC05B, 0x7E79, 0xC05C, 0x7E7A, 0xC05D, 0x7E7B, 0xC05E, 0x7E7C, 0xC05F, 0x7E7D, 0xC060, 0x7E7E, 0xC061, 0x7E7F, 0xC062, 0x7E80, + 0xC063, 0x7E81, 0xC064, 0x7E83, 0xC065, 0x7E84, 0xC066, 0x7E85, 0xC067, 0x7E86, 0xC068, 0x7E87, 0xC069, 0x7E88, 0xC06A, 0x7E89, + 0xC06B, 0x7E8A, 0xC06C, 0x7E8B, 0xC06D, 0x7E8C, 0xC06E, 0x7E8D, 0xC06F, 0x7E8E, 0xC070, 0x7E8F, 0xC071, 0x7E90, 0xC072, 0x7E91, + 0xC073, 0x7E92, 0xC074, 0x7E93, 0xC075, 0x7E94, 0xC076, 0x7E95, 0xC077, 0x7E96, 0xC078, 0x7E97, 0xC079, 0x7E98, 0xC07A, 0x7E99, + 0xC07B, 0x7E9A, 0xC07C, 0x7E9C, 0xC07D, 0x7E9D, 0xC07E, 0x7E9E, 0xC080, 0x7EAE, 0xC081, 0x7EB4, 0xC082, 0x7EBB, 0xC083, 0x7EBC, + 0xC084, 0x7ED6, 0xC085, 0x7EE4, 0xC086, 0x7EEC, 0xC087, 0x7EF9, 0xC088, 0x7F0A, 0xC089, 0x7F10, 0xC08A, 0x7F1E, 0xC08B, 0x7F37, + 0xC08C, 0x7F39, 0xC08D, 0x7F3B, 0xC08E, 0x7F3C, 0xC08F, 0x7F3D, 0xC090, 0x7F3E, 0xC091, 0x7F3F, 0xC092, 0x7F40, 0xC093, 0x7F41, + 0xC094, 0x7F43, 0xC095, 0x7F46, 0xC096, 0x7F47, 0xC097, 0x7F48, 0xC098, 0x7F49, 0xC099, 0x7F4A, 0xC09A, 0x7F4B, 0xC09B, 0x7F4C, + 0xC09C, 0x7F4D, 0xC09D, 0x7F4E, 0xC09E, 0x7F4F, 0xC09F, 0x7F52, 0xC0A0, 0x7F53, 0xC0A1, 0x9988, 0xC0A2, 0x6127, 0xC0A3, 0x6E83, + 0xC0A4, 0x5764, 0xC0A5, 0x6606, 0xC0A6, 0x6346, 0xC0A7, 0x56F0, 0xC0A8, 0x62EC, 0xC0A9, 0x6269, 0xC0AA, 0x5ED3, 0xC0AB, 0x9614, + 0xC0AC, 0x5783, 0xC0AD, 0x62C9, 0xC0AE, 0x5587, 0xC0AF, 0x8721, 0xC0B0, 0x814A, 0xC0B1, 0x8FA3, 0xC0B2, 0x5566, 0xC0B3, 0x83B1, + 0xC0B4, 0x6765, 0xC0B5, 0x8D56, 0xC0B6, 0x84DD, 0xC0B7, 0x5A6A, 0xC0B8, 0x680F, 0xC0B9, 0x62E6, 0xC0BA, 0x7BEE, 0xC0BB, 0x9611, + 0xC0BC, 0x5170, 0xC0BD, 0x6F9C, 0xC0BE, 0x8C30, 0xC0BF, 0x63FD, 0xC0C0, 0x89C8, 0xC0C1, 0x61D2, 0xC0C2, 0x7F06, 0xC0C3, 0x70C2, + 0xC0C4, 0x6EE5, 0xC0C5, 0x7405, 0xC0C6, 0x6994, 0xC0C7, 0x72FC, 0xC0C8, 0x5ECA, 0xC0C9, 0x90CE, 0xC0CA, 0x6717, 0xC0CB, 0x6D6A, + 0xC0CC, 0x635E, 0xC0CD, 0x52B3, 0xC0CE, 0x7262, 0xC0CF, 0x8001, 0xC0D0, 0x4F6C, 0xC0D1, 0x59E5, 0xC0D2, 0x916A, 0xC0D3, 0x70D9, + 0xC0D4, 0x6D9D, 0xC0D5, 0x52D2, 0xC0D6, 0x4E50, 0xC0D7, 0x96F7, 0xC0D8, 0x956D, 0xC0D9, 0x857E, 0xC0DA, 0x78CA, 0xC0DB, 0x7D2F, + 0xC0DC, 0x5121, 0xC0DD, 0x5792, 0xC0DE, 0x64C2, 0xC0DF, 0x808B, 0xC0E0, 0x7C7B, 0xC0E1, 0x6CEA, 0xC0E2, 0x68F1, 0xC0E3, 0x695E, + 0xC0E4, 0x51B7, 0xC0E5, 0x5398, 0xC0E6, 0x68A8, 0xC0E7, 0x7281, 0xC0E8, 0x9ECE, 0xC0E9, 0x7BF1, 0xC0EA, 0x72F8, 0xC0EB, 0x79BB, + 0xC0EC, 0x6F13, 0xC0ED, 0x7406, 0xC0EE, 0x674E, 0xC0EF, 0x91CC, 0xC0F0, 0x9CA4, 0xC0F1, 0x793C, 0xC0F2, 0x8389, 0xC0F3, 0x8354, + 0xC0F4, 0x540F, 0xC0F5, 0x6817, 0xC0F6, 0x4E3D, 0xC0F7, 0x5389, 0xC0F8, 0x52B1, 0xC0F9, 0x783E, 0xC0FA, 0x5386, 0xC0FB, 0x5229, + 0xC0FC, 0x5088, 0xC0FD, 0x4F8B, 0xC0FE, 0x4FD0, 0xC140, 0x7F56, 0xC141, 0x7F59, 0xC142, 0x7F5B, 0xC143, 0x7F5C, 0xC144, 0x7F5D, + 0xC145, 0x7F5E, 0xC146, 0x7F60, 0xC147, 0x7F63, 0xC148, 0x7F64, 0xC149, 0x7F65, 0xC14A, 0x7F66, 0xC14B, 0x7F67, 0xC14C, 0x7F6B, + 0xC14D, 0x7F6C, 0xC14E, 0x7F6D, 0xC14F, 0x7F6F, 0xC150, 0x7F70, 0xC151, 0x7F73, 0xC152, 0x7F75, 0xC153, 0x7F76, 0xC154, 0x7F77, + 0xC155, 0x7F78, 0xC156, 0x7F7A, 0xC157, 0x7F7B, 0xC158, 0x7F7C, 0xC159, 0x7F7D, 0xC15A, 0x7F7F, 0xC15B, 0x7F80, 0xC15C, 0x7F82, + 0xC15D, 0x7F83, 0xC15E, 0x7F84, 0xC15F, 0x7F85, 0xC160, 0x7F86, 0xC161, 0x7F87, 0xC162, 0x7F88, 0xC163, 0x7F89, 0xC164, 0x7F8B, + 0xC165, 0x7F8D, 0xC166, 0x7F8F, 0xC167, 0x7F90, 0xC168, 0x7F91, 0xC169, 0x7F92, 0xC16A, 0x7F93, 0xC16B, 0x7F95, 0xC16C, 0x7F96, + 0xC16D, 0x7F97, 0xC16E, 0x7F98, 0xC16F, 0x7F99, 0xC170, 0x7F9B, 0xC171, 0x7F9C, 0xC172, 0x7FA0, 0xC173, 0x7FA2, 0xC174, 0x7FA3, + 0xC175, 0x7FA5, 0xC176, 0x7FA6, 0xC177, 0x7FA8, 0xC178, 0x7FA9, 0xC179, 0x7FAA, 0xC17A, 0x7FAB, 0xC17B, 0x7FAC, 0xC17C, 0x7FAD, + 0xC17D, 0x7FAE, 0xC17E, 0x7FB1, 0xC180, 0x7FB3, 0xC181, 0x7FB4, 0xC182, 0x7FB5, 0xC183, 0x7FB6, 0xC184, 0x7FB7, 0xC185, 0x7FBA, + 0xC186, 0x7FBB, 0xC187, 0x7FBE, 0xC188, 0x7FC0, 0xC189, 0x7FC2, 0xC18A, 0x7FC3, 0xC18B, 0x7FC4, 0xC18C, 0x7FC6, 0xC18D, 0x7FC7, + 0xC18E, 0x7FC8, 0xC18F, 0x7FC9, 0xC190, 0x7FCB, 0xC191, 0x7FCD, 0xC192, 0x7FCF, 0xC193, 0x7FD0, 0xC194, 0x7FD1, 0xC195, 0x7FD2, + 0xC196, 0x7FD3, 0xC197, 0x7FD6, 0xC198, 0x7FD7, 0xC199, 0x7FD9, 0xC19A, 0x7FDA, 0xC19B, 0x7FDB, 0xC19C, 0x7FDC, 0xC19D, 0x7FDD, + 0xC19E, 0x7FDE, 0xC19F, 0x7FE2, 0xC1A0, 0x7FE3, 0xC1A1, 0x75E2, 0xC1A2, 0x7ACB, 0xC1A3, 0x7C92, 0xC1A4, 0x6CA5, 0xC1A5, 0x96B6, + 0xC1A6, 0x529B, 0xC1A7, 0x7483, 0xC1A8, 0x54E9, 0xC1A9, 0x4FE9, 0xC1AA, 0x8054, 0xC1AB, 0x83B2, 0xC1AC, 0x8FDE, 0xC1AD, 0x9570, + 0xC1AE, 0x5EC9, 0xC1AF, 0x601C, 0xC1B0, 0x6D9F, 0xC1B1, 0x5E18, 0xC1B2, 0x655B, 0xC1B3, 0x8138, 0xC1B4, 0x94FE, 0xC1B5, 0x604B, + 0xC1B6, 0x70BC, 0xC1B7, 0x7EC3, 0xC1B8, 0x7CAE, 0xC1B9, 0x51C9, 0xC1BA, 0x6881, 0xC1BB, 0x7CB1, 0xC1BC, 0x826F, 0xC1BD, 0x4E24, + 0xC1BE, 0x8F86, 0xC1BF, 0x91CF, 0xC1C0, 0x667E, 0xC1C1, 0x4EAE, 0xC1C2, 0x8C05, 0xC1C3, 0x64A9, 0xC1C4, 0x804A, 0xC1C5, 0x50DA, + 0xC1C6, 0x7597, 0xC1C7, 0x71CE, 0xC1C8, 0x5BE5, 0xC1C9, 0x8FBD, 0xC1CA, 0x6F66, 0xC1CB, 0x4E86, 0xC1CC, 0x6482, 0xC1CD, 0x9563, + 0xC1CE, 0x5ED6, 0xC1CF, 0x6599, 0xC1D0, 0x5217, 0xC1D1, 0x88C2, 0xC1D2, 0x70C8, 0xC1D3, 0x52A3, 0xC1D4, 0x730E, 0xC1D5, 0x7433, + 0xC1D6, 0x6797, 0xC1D7, 0x78F7, 0xC1D8, 0x9716, 0xC1D9, 0x4E34, 0xC1DA, 0x90BB, 0xC1DB, 0x9CDE, 0xC1DC, 0x6DCB, 0xC1DD, 0x51DB, + 0xC1DE, 0x8D41, 0xC1DF, 0x541D, 0xC1E0, 0x62CE, 0xC1E1, 0x73B2, 0xC1E2, 0x83F1, 0xC1E3, 0x96F6, 0xC1E4, 0x9F84, 0xC1E5, 0x94C3, + 0xC1E6, 0x4F36, 0xC1E7, 0x7F9A, 0xC1E8, 0x51CC, 0xC1E9, 0x7075, 0xC1EA, 0x9675, 0xC1EB, 0x5CAD, 0xC1EC, 0x9886, 0xC1ED, 0x53E6, + 0xC1EE, 0x4EE4, 0xC1EF, 0x6E9C, 0xC1F0, 0x7409, 0xC1F1, 0x69B4, 0xC1F2, 0x786B, 0xC1F3, 0x998F, 0xC1F4, 0x7559, 0xC1F5, 0x5218, + 0xC1F6, 0x7624, 0xC1F7, 0x6D41, 0xC1F8, 0x67F3, 0xC1F9, 0x516D, 0xC1FA, 0x9F99, 0xC1FB, 0x804B, 0xC1FC, 0x5499, 0xC1FD, 0x7B3C, + 0xC1FE, 0x7ABF, 0xC240, 0x7FE4, 0xC241, 0x7FE7, 0xC242, 0x7FE8, 0xC243, 0x7FEA, 0xC244, 0x7FEB, 0xC245, 0x7FEC, 0xC246, 0x7FED, + 0xC247, 0x7FEF, 0xC248, 0x7FF2, 0xC249, 0x7FF4, 0xC24A, 0x7FF5, 0xC24B, 0x7FF6, 0xC24C, 0x7FF7, 0xC24D, 0x7FF8, 0xC24E, 0x7FF9, + 0xC24F, 0x7FFA, 0xC250, 0x7FFD, 0xC251, 0x7FFE, 0xC252, 0x7FFF, 0xC253, 0x8002, 0xC254, 0x8007, 0xC255, 0x8008, 0xC256, 0x8009, + 0xC257, 0x800A, 0xC258, 0x800E, 0xC259, 0x800F, 0xC25A, 0x8011, 0xC25B, 0x8013, 0xC25C, 0x801A, 0xC25D, 0x801B, 0xC25E, 0x801D, + 0xC25F, 0x801E, 0xC260, 0x801F, 0xC261, 0x8021, 0xC262, 0x8023, 0xC263, 0x8024, 0xC264, 0x802B, 0xC265, 0x802C, 0xC266, 0x802D, + 0xC267, 0x802E, 0xC268, 0x802F, 0xC269, 0x8030, 0xC26A, 0x8032, 0xC26B, 0x8034, 0xC26C, 0x8039, 0xC26D, 0x803A, 0xC26E, 0x803C, + 0xC26F, 0x803E, 0xC270, 0x8040, 0xC271, 0x8041, 0xC272, 0x8044, 0xC273, 0x8045, 0xC274, 0x8047, 0xC275, 0x8048, 0xC276, 0x8049, + 0xC277, 0x804E, 0xC278, 0x804F, 0xC279, 0x8050, 0xC27A, 0x8051, 0xC27B, 0x8053, 0xC27C, 0x8055, 0xC27D, 0x8056, 0xC27E, 0x8057, + 0xC280, 0x8059, 0xC281, 0x805B, 0xC282, 0x805C, 0xC283, 0x805D, 0xC284, 0x805E, 0xC285, 0x805F, 0xC286, 0x8060, 0xC287, 0x8061, + 0xC288, 0x8062, 0xC289, 0x8063, 0xC28A, 0x8064, 0xC28B, 0x8065, 0xC28C, 0x8066, 0xC28D, 0x8067, 0xC28E, 0x8068, 0xC28F, 0x806B, + 0xC290, 0x806C, 0xC291, 0x806D, 0xC292, 0x806E, 0xC293, 0x806F, 0xC294, 0x8070, 0xC295, 0x8072, 0xC296, 0x8073, 0xC297, 0x8074, + 0xC298, 0x8075, 0xC299, 0x8076, 0xC29A, 0x8077, 0xC29B, 0x8078, 0xC29C, 0x8079, 0xC29D, 0x807A, 0xC29E, 0x807B, 0xC29F, 0x807C, + 0xC2A0, 0x807D, 0xC2A1, 0x9686, 0xC2A2, 0x5784, 0xC2A3, 0x62E2, 0xC2A4, 0x9647, 0xC2A5, 0x697C, 0xC2A6, 0x5A04, 0xC2A7, 0x6402, + 0xC2A8, 0x7BD3, 0xC2A9, 0x6F0F, 0xC2AA, 0x964B, 0xC2AB, 0x82A6, 0xC2AC, 0x5362, 0xC2AD, 0x9885, 0xC2AE, 0x5E90, 0xC2AF, 0x7089, + 0xC2B0, 0x63B3, 0xC2B1, 0x5364, 0xC2B2, 0x864F, 0xC2B3, 0x9C81, 0xC2B4, 0x9E93, 0xC2B5, 0x788C, 0xC2B6, 0x9732, 0xC2B7, 0x8DEF, + 0xC2B8, 0x8D42, 0xC2B9, 0x9E7F, 0xC2BA, 0x6F5E, 0xC2BB, 0x7984, 0xC2BC, 0x5F55, 0xC2BD, 0x9646, 0xC2BE, 0x622E, 0xC2BF, 0x9A74, + 0xC2C0, 0x5415, 0xC2C1, 0x94DD, 0xC2C2, 0x4FA3, 0xC2C3, 0x65C5, 0xC2C4, 0x5C65, 0xC2C5, 0x5C61, 0xC2C6, 0x7F15, 0xC2C7, 0x8651, + 0xC2C8, 0x6C2F, 0xC2C9, 0x5F8B, 0xC2CA, 0x7387, 0xC2CB, 0x6EE4, 0xC2CC, 0x7EFF, 0xC2CD, 0x5CE6, 0xC2CE, 0x631B, 0xC2CF, 0x5B6A, + 0xC2D0, 0x6EE6, 0xC2D1, 0x5375, 0xC2D2, 0x4E71, 0xC2D3, 0x63A0, 0xC2D4, 0x7565, 0xC2D5, 0x62A1, 0xC2D6, 0x8F6E, 0xC2D7, 0x4F26, + 0xC2D8, 0x4ED1, 0xC2D9, 0x6CA6, 0xC2DA, 0x7EB6, 0xC2DB, 0x8BBA, 0xC2DC, 0x841D, 0xC2DD, 0x87BA, 0xC2DE, 0x7F57, 0xC2DF, 0x903B, + 0xC2E0, 0x9523, 0xC2E1, 0x7BA9, 0xC2E2, 0x9AA1, 0xC2E3, 0x88F8, 0xC2E4, 0x843D, 0xC2E5, 0x6D1B, 0xC2E6, 0x9A86, 0xC2E7, 0x7EDC, + 0xC2E8, 0x5988, 0xC2E9, 0x9EBB, 0xC2EA, 0x739B, 0xC2EB, 0x7801, 0xC2EC, 0x8682, 0xC2ED, 0x9A6C, 0xC2EE, 0x9A82, 0xC2EF, 0x561B, + 0xC2F0, 0x5417, 0xC2F1, 0x57CB, 0xC2F2, 0x4E70, 0xC2F3, 0x9EA6, 0xC2F4, 0x5356, 0xC2F5, 0x8FC8, 0xC2F6, 0x8109, 0xC2F7, 0x7792, + 0xC2F8, 0x9992, 0xC2F9, 0x86EE, 0xC2FA, 0x6EE1, 0xC2FB, 0x8513, 0xC2FC, 0x66FC, 0xC2FD, 0x6162, 0xC2FE, 0x6F2B, 0xC340, 0x807E, + 0xC341, 0x8081, 0xC342, 0x8082, 0xC343, 0x8085, 0xC344, 0x8088, 0xC345, 0x808A, 0xC346, 0x808D, 0xC347, 0x808E, 0xC348, 0x808F, + 0xC349, 0x8090, 0xC34A, 0x8091, 0xC34B, 0x8092, 0xC34C, 0x8094, 0xC34D, 0x8095, 0xC34E, 0x8097, 0xC34F, 0x8099, 0xC350, 0x809E, + 0xC351, 0x80A3, 0xC352, 0x80A6, 0xC353, 0x80A7, 0xC354, 0x80A8, 0xC355, 0x80AC, 0xC356, 0x80B0, 0xC357, 0x80B3, 0xC358, 0x80B5, + 0xC359, 0x80B6, 0xC35A, 0x80B8, 0xC35B, 0x80B9, 0xC35C, 0x80BB, 0xC35D, 0x80C5, 0xC35E, 0x80C7, 0xC35F, 0x80C8, 0xC360, 0x80C9, + 0xC361, 0x80CA, 0xC362, 0x80CB, 0xC363, 0x80CF, 0xC364, 0x80D0, 0xC365, 0x80D1, 0xC366, 0x80D2, 0xC367, 0x80D3, 0xC368, 0x80D4, + 0xC369, 0x80D5, 0xC36A, 0x80D8, 0xC36B, 0x80DF, 0xC36C, 0x80E0, 0xC36D, 0x80E2, 0xC36E, 0x80E3, 0xC36F, 0x80E6, 0xC370, 0x80EE, + 0xC371, 0x80F5, 0xC372, 0x80F7, 0xC373, 0x80F9, 0xC374, 0x80FB, 0xC375, 0x80FE, 0xC376, 0x80FF, 0xC377, 0x8100, 0xC378, 0x8101, + 0xC379, 0x8103, 0xC37A, 0x8104, 0xC37B, 0x8105, 0xC37C, 0x8107, 0xC37D, 0x8108, 0xC37E, 0x810B, 0xC380, 0x810C, 0xC381, 0x8115, + 0xC382, 0x8117, 0xC383, 0x8119, 0xC384, 0x811B, 0xC385, 0x811C, 0xC386, 0x811D, 0xC387, 0x811F, 0xC388, 0x8120, 0xC389, 0x8121, + 0xC38A, 0x8122, 0xC38B, 0x8123, 0xC38C, 0x8124, 0xC38D, 0x8125, 0xC38E, 0x8126, 0xC38F, 0x8127, 0xC390, 0x8128, 0xC391, 0x8129, + 0xC392, 0x812A, 0xC393, 0x812B, 0xC394, 0x812D, 0xC395, 0x812E, 0xC396, 0x8130, 0xC397, 0x8133, 0xC398, 0x8134, 0xC399, 0x8135, + 0xC39A, 0x8137, 0xC39B, 0x8139, 0xC39C, 0x813A, 0xC39D, 0x813B, 0xC39E, 0x813C, 0xC39F, 0x813D, 0xC3A0, 0x813F, 0xC3A1, 0x8C29, + 0xC3A2, 0x8292, 0xC3A3, 0x832B, 0xC3A4, 0x76F2, 0xC3A5, 0x6C13, 0xC3A6, 0x5FD9, 0xC3A7, 0x83BD, 0xC3A8, 0x732B, 0xC3A9, 0x8305, + 0xC3AA, 0x951A, 0xC3AB, 0x6BDB, 0xC3AC, 0x77DB, 0xC3AD, 0x94C6, 0xC3AE, 0x536F, 0xC3AF, 0x8302, 0xC3B0, 0x5192, 0xC3B1, 0x5E3D, + 0xC3B2, 0x8C8C, 0xC3B3, 0x8D38, 0xC3B4, 0x4E48, 0xC3B5, 0x73AB, 0xC3B6, 0x679A, 0xC3B7, 0x6885, 0xC3B8, 0x9176, 0xC3B9, 0x9709, + 0xC3BA, 0x7164, 0xC3BB, 0x6CA1, 0xC3BC, 0x7709, 0xC3BD, 0x5A92, 0xC3BE, 0x9541, 0xC3BF, 0x6BCF, 0xC3C0, 0x7F8E, 0xC3C1, 0x6627, + 0xC3C2, 0x5BD0, 0xC3C3, 0x59B9, 0xC3C4, 0x5A9A, 0xC3C5, 0x95E8, 0xC3C6, 0x95F7, 0xC3C7, 0x4EEC, 0xC3C8, 0x840C, 0xC3C9, 0x8499, + 0xC3CA, 0x6AAC, 0xC3CB, 0x76DF, 0xC3CC, 0x9530, 0xC3CD, 0x731B, 0xC3CE, 0x68A6, 0xC3CF, 0x5B5F, 0xC3D0, 0x772F, 0xC3D1, 0x919A, + 0xC3D2, 0x9761, 0xC3D3, 0x7CDC, 0xC3D4, 0x8FF7, 0xC3D5, 0x8C1C, 0xC3D6, 0x5F25, 0xC3D7, 0x7C73, 0xC3D8, 0x79D8, 0xC3D9, 0x89C5, + 0xC3DA, 0x6CCC, 0xC3DB, 0x871C, 0xC3DC, 0x5BC6, 0xC3DD, 0x5E42, 0xC3DE, 0x68C9, 0xC3DF, 0x7720, 0xC3E0, 0x7EF5, 0xC3E1, 0x5195, + 0xC3E2, 0x514D, 0xC3E3, 0x52C9, 0xC3E4, 0x5A29, 0xC3E5, 0x7F05, 0xC3E6, 0x9762, 0xC3E7, 0x82D7, 0xC3E8, 0x63CF, 0xC3E9, 0x7784, + 0xC3EA, 0x85D0, 0xC3EB, 0x79D2, 0xC3EC, 0x6E3A, 0xC3ED, 0x5E99, 0xC3EE, 0x5999, 0xC3EF, 0x8511, 0xC3F0, 0x706D, 0xC3F1, 0x6C11, + 0xC3F2, 0x62BF, 0xC3F3, 0x76BF, 0xC3F4, 0x654F, 0xC3F5, 0x60AF, 0xC3F6, 0x95FD, 0xC3F7, 0x660E, 0xC3F8, 0x879F, 0xC3F9, 0x9E23, + 0xC3FA, 0x94ED, 0xC3FB, 0x540D, 0xC3FC, 0x547D, 0xC3FD, 0x8C2C, 0xC3FE, 0x6478, 0xC440, 0x8140, 0xC441, 0x8141, 0xC442, 0x8142, + 0xC443, 0x8143, 0xC444, 0x8144, 0xC445, 0x8145, 0xC446, 0x8147, 0xC447, 0x8149, 0xC448, 0x814D, 0xC449, 0x814E, 0xC44A, 0x814F, + 0xC44B, 0x8152, 0xC44C, 0x8156, 0xC44D, 0x8157, 0xC44E, 0x8158, 0xC44F, 0x815B, 0xC450, 0x815C, 0xC451, 0x815D, 0xC452, 0x815E, + 0xC453, 0x815F, 0xC454, 0x8161, 0xC455, 0x8162, 0xC456, 0x8163, 0xC457, 0x8164, 0xC458, 0x8166, 0xC459, 0x8168, 0xC45A, 0x816A, + 0xC45B, 0x816B, 0xC45C, 0x816C, 0xC45D, 0x816F, 0xC45E, 0x8172, 0xC45F, 0x8173, 0xC460, 0x8175, 0xC461, 0x8176, 0xC462, 0x8177, + 0xC463, 0x8178, 0xC464, 0x8181, 0xC465, 0x8183, 0xC466, 0x8184, 0xC467, 0x8185, 0xC468, 0x8186, 0xC469, 0x8187, 0xC46A, 0x8189, + 0xC46B, 0x818B, 0xC46C, 0x818C, 0xC46D, 0x818D, 0xC46E, 0x818E, 0xC46F, 0x8190, 0xC470, 0x8192, 0xC471, 0x8193, 0xC472, 0x8194, + 0xC473, 0x8195, 0xC474, 0x8196, 0xC475, 0x8197, 0xC476, 0x8199, 0xC477, 0x819A, 0xC478, 0x819E, 0xC479, 0x819F, 0xC47A, 0x81A0, + 0xC47B, 0x81A1, 0xC47C, 0x81A2, 0xC47D, 0x81A4, 0xC47E, 0x81A5, 0xC480, 0x81A7, 0xC481, 0x81A9, 0xC482, 0x81AB, 0xC483, 0x81AC, + 0xC484, 0x81AD, 0xC485, 0x81AE, 0xC486, 0x81AF, 0xC487, 0x81B0, 0xC488, 0x81B1, 0xC489, 0x81B2, 0xC48A, 0x81B4, 0xC48B, 0x81B5, + 0xC48C, 0x81B6, 0xC48D, 0x81B7, 0xC48E, 0x81B8, 0xC48F, 0x81B9, 0xC490, 0x81BC, 0xC491, 0x81BD, 0xC492, 0x81BE, 0xC493, 0x81BF, + 0xC494, 0x81C4, 0xC495, 0x81C5, 0xC496, 0x81C7, 0xC497, 0x81C8, 0xC498, 0x81C9, 0xC499, 0x81CB, 0xC49A, 0x81CD, 0xC49B, 0x81CE, + 0xC49C, 0x81CF, 0xC49D, 0x81D0, 0xC49E, 0x81D1, 0xC49F, 0x81D2, 0xC4A0, 0x81D3, 0xC4A1, 0x6479, 0xC4A2, 0x8611, 0xC4A3, 0x6A21, + 0xC4A4, 0x819C, 0xC4A5, 0x78E8, 0xC4A6, 0x6469, 0xC4A7, 0x9B54, 0xC4A8, 0x62B9, 0xC4A9, 0x672B, 0xC4AA, 0x83AB, 0xC4AB, 0x58A8, + 0xC4AC, 0x9ED8, 0xC4AD, 0x6CAB, 0xC4AE, 0x6F20, 0xC4AF, 0x5BDE, 0xC4B0, 0x964C, 0xC4B1, 0x8C0B, 0xC4B2, 0x725F, 0xC4B3, 0x67D0, + 0xC4B4, 0x62C7, 0xC4B5, 0x7261, 0xC4B6, 0x4EA9, 0xC4B7, 0x59C6, 0xC4B8, 0x6BCD, 0xC4B9, 0x5893, 0xC4BA, 0x66AE, 0xC4BB, 0x5E55, + 0xC4BC, 0x52DF, 0xC4BD, 0x6155, 0xC4BE, 0x6728, 0xC4BF, 0x76EE, 0xC4C0, 0x7766, 0xC4C1, 0x7267, 0xC4C2, 0x7A46, 0xC4C3, 0x62FF, + 0xC4C4, 0x54EA, 0xC4C5, 0x5450, 0xC4C6, 0x94A0, 0xC4C7, 0x90A3, 0xC4C8, 0x5A1C, 0xC4C9, 0x7EB3, 0xC4CA, 0x6C16, 0xC4CB, 0x4E43, + 0xC4CC, 0x5976, 0xC4CD, 0x8010, 0xC4CE, 0x5948, 0xC4CF, 0x5357, 0xC4D0, 0x7537, 0xC4D1, 0x96BE, 0xC4D2, 0x56CA, 0xC4D3, 0x6320, + 0xC4D4, 0x8111, 0xC4D5, 0x607C, 0xC4D6, 0x95F9, 0xC4D7, 0x6DD6, 0xC4D8, 0x5462, 0xC4D9, 0x9981, 0xC4DA, 0x5185, 0xC4DB, 0x5AE9, + 0xC4DC, 0x80FD, 0xC4DD, 0x59AE, 0xC4DE, 0x9713, 0xC4DF, 0x502A, 0xC4E0, 0x6CE5, 0xC4E1, 0x5C3C, 0xC4E2, 0x62DF, 0xC4E3, 0x4F60, + 0xC4E4, 0x533F, 0xC4E5, 0x817B, 0xC4E6, 0x9006, 0xC4E7, 0x6EBA, 0xC4E8, 0x852B, 0xC4E9, 0x62C8, 0xC4EA, 0x5E74, 0xC4EB, 0x78BE, + 0xC4EC, 0x64B5, 0xC4ED, 0x637B, 0xC4EE, 0x5FF5, 0xC4EF, 0x5A18, 0xC4F0, 0x917F, 0xC4F1, 0x9E1F, 0xC4F2, 0x5C3F, 0xC4F3, 0x634F, + 0xC4F4, 0x8042, 0xC4F5, 0x5B7D, 0xC4F6, 0x556E, 0xC4F7, 0x954A, 0xC4F8, 0x954D, 0xC4F9, 0x6D85, 0xC4FA, 0x60A8, 0xC4FB, 0x67E0, + 0xC4FC, 0x72DE, 0xC4FD, 0x51DD, 0xC4FE, 0x5B81, 0xC540, 0x81D4, 0xC541, 0x81D5, 0xC542, 0x81D6, 0xC543, 0x81D7, 0xC544, 0x81D8, + 0xC545, 0x81D9, 0xC546, 0x81DA, 0xC547, 0x81DB, 0xC548, 0x81DC, 0xC549, 0x81DD, 0xC54A, 0x81DE, 0xC54B, 0x81DF, 0xC54C, 0x81E0, + 0xC54D, 0x81E1, 0xC54E, 0x81E2, 0xC54F, 0x81E4, 0xC550, 0x81E5, 0xC551, 0x81E6, 0xC552, 0x81E8, 0xC553, 0x81E9, 0xC554, 0x81EB, + 0xC555, 0x81EE, 0xC556, 0x81EF, 0xC557, 0x81F0, 0xC558, 0x81F1, 0xC559, 0x81F2, 0xC55A, 0x81F5, 0xC55B, 0x81F6, 0xC55C, 0x81F7, + 0xC55D, 0x81F8, 0xC55E, 0x81F9, 0xC55F, 0x81FA, 0xC560, 0x81FD, 0xC561, 0x81FF, 0xC562, 0x8203, 0xC563, 0x8207, 0xC564, 0x8208, + 0xC565, 0x8209, 0xC566, 0x820A, 0xC567, 0x820B, 0xC568, 0x820E, 0xC569, 0x820F, 0xC56A, 0x8211, 0xC56B, 0x8213, 0xC56C, 0x8215, + 0xC56D, 0x8216, 0xC56E, 0x8217, 0xC56F, 0x8218, 0xC570, 0x8219, 0xC571, 0x821A, 0xC572, 0x821D, 0xC573, 0x8220, 0xC574, 0x8224, + 0xC575, 0x8225, 0xC576, 0x8226, 0xC577, 0x8227, 0xC578, 0x8229, 0xC579, 0x822E, 0xC57A, 0x8232, 0xC57B, 0x823A, 0xC57C, 0x823C, + 0xC57D, 0x823D, 0xC57E, 0x823F, 0xC580, 0x8240, 0xC581, 0x8241, 0xC582, 0x8242, 0xC583, 0x8243, 0xC584, 0x8245, 0xC585, 0x8246, + 0xC586, 0x8248, 0xC587, 0x824A, 0xC588, 0x824C, 0xC589, 0x824D, 0xC58A, 0x824E, 0xC58B, 0x8250, 0xC58C, 0x8251, 0xC58D, 0x8252, + 0xC58E, 0x8253, 0xC58F, 0x8254, 0xC590, 0x8255, 0xC591, 0x8256, 0xC592, 0x8257, 0xC593, 0x8259, 0xC594, 0x825B, 0xC595, 0x825C, + 0xC596, 0x825D, 0xC597, 0x825E, 0xC598, 0x8260, 0xC599, 0x8261, 0xC59A, 0x8262, 0xC59B, 0x8263, 0xC59C, 0x8264, 0xC59D, 0x8265, + 0xC59E, 0x8266, 0xC59F, 0x8267, 0xC5A0, 0x8269, 0xC5A1, 0x62E7, 0xC5A2, 0x6CDE, 0xC5A3, 0x725B, 0xC5A4, 0x626D, 0xC5A5, 0x94AE, + 0xC5A6, 0x7EBD, 0xC5A7, 0x8113, 0xC5A8, 0x6D53, 0xC5A9, 0x519C, 0xC5AA, 0x5F04, 0xC5AB, 0x5974, 0xC5AC, 0x52AA, 0xC5AD, 0x6012, + 0xC5AE, 0x5973, 0xC5AF, 0x6696, 0xC5B0, 0x8650, 0xC5B1, 0x759F, 0xC5B2, 0x632A, 0xC5B3, 0x61E6, 0xC5B4, 0x7CEF, 0xC5B5, 0x8BFA, + 0xC5B6, 0x54E6, 0xC5B7, 0x6B27, 0xC5B8, 0x9E25, 0xC5B9, 0x6BB4, 0xC5BA, 0x85D5, 0xC5BB, 0x5455, 0xC5BC, 0x5076, 0xC5BD, 0x6CA4, + 0xC5BE, 0x556A, 0xC5BF, 0x8DB4, 0xC5C0, 0x722C, 0xC5C1, 0x5E15, 0xC5C2, 0x6015, 0xC5C3, 0x7436, 0xC5C4, 0x62CD, 0xC5C5, 0x6392, + 0xC5C6, 0x724C, 0xC5C7, 0x5F98, 0xC5C8, 0x6E43, 0xC5C9, 0x6D3E, 0xC5CA, 0x6500, 0xC5CB, 0x6F58, 0xC5CC, 0x76D8, 0xC5CD, 0x78D0, + 0xC5CE, 0x76FC, 0xC5CF, 0x7554, 0xC5D0, 0x5224, 0xC5D1, 0x53DB, 0xC5D2, 0x4E53, 0xC5D3, 0x5E9E, 0xC5D4, 0x65C1, 0xC5D5, 0x802A, + 0xC5D6, 0x80D6, 0xC5D7, 0x629B, 0xC5D8, 0x5486, 0xC5D9, 0x5228, 0xC5DA, 0x70AE, 0xC5DB, 0x888D, 0xC5DC, 0x8DD1, 0xC5DD, 0x6CE1, + 0xC5DE, 0x5478, 0xC5DF, 0x80DA, 0xC5E0, 0x57F9, 0xC5E1, 0x88F4, 0xC5E2, 0x8D54, 0xC5E3, 0x966A, 0xC5E4, 0x914D, 0xC5E5, 0x4F69, + 0xC5E6, 0x6C9B, 0xC5E7, 0x55B7, 0xC5E8, 0x76C6, 0xC5E9, 0x7830, 0xC5EA, 0x62A8, 0xC5EB, 0x70F9, 0xC5EC, 0x6F8E, 0xC5ED, 0x5F6D, + 0xC5EE, 0x84EC, 0xC5EF, 0x68DA, 0xC5F0, 0x787C, 0xC5F1, 0x7BF7, 0xC5F2, 0x81A8, 0xC5F3, 0x670B, 0xC5F4, 0x9E4F, 0xC5F5, 0x6367, + 0xC5F6, 0x78B0, 0xC5F7, 0x576F, 0xC5F8, 0x7812, 0xC5F9, 0x9739, 0xC5FA, 0x6279, 0xC5FB, 0x62AB, 0xC5FC, 0x5288, 0xC5FD, 0x7435, + 0xC5FE, 0x6BD7, 0xC640, 0x826A, 0xC641, 0x826B, 0xC642, 0x826C, 0xC643, 0x826D, 0xC644, 0x8271, 0xC645, 0x8275, 0xC646, 0x8276, + 0xC647, 0x8277, 0xC648, 0x8278, 0xC649, 0x827B, 0xC64A, 0x827C, 0xC64B, 0x8280, 0xC64C, 0x8281, 0xC64D, 0x8283, 0xC64E, 0x8285, + 0xC64F, 0x8286, 0xC650, 0x8287, 0xC651, 0x8289, 0xC652, 0x828C, 0xC653, 0x8290, 0xC654, 0x8293, 0xC655, 0x8294, 0xC656, 0x8295, + 0xC657, 0x8296, 0xC658, 0x829A, 0xC659, 0x829B, 0xC65A, 0x829E, 0xC65B, 0x82A0, 0xC65C, 0x82A2, 0xC65D, 0x82A3, 0xC65E, 0x82A7, + 0xC65F, 0x82B2, 0xC660, 0x82B5, 0xC661, 0x82B6, 0xC662, 0x82BA, 0xC663, 0x82BB, 0xC664, 0x82BC, 0xC665, 0x82BF, 0xC666, 0x82C0, + 0xC667, 0x82C2, 0xC668, 0x82C3, 0xC669, 0x82C5, 0xC66A, 0x82C6, 0xC66B, 0x82C9, 0xC66C, 0x82D0, 0xC66D, 0x82D6, 0xC66E, 0x82D9, + 0xC66F, 0x82DA, 0xC670, 0x82DD, 0xC671, 0x82E2, 0xC672, 0x82E7, 0xC673, 0x82E8, 0xC674, 0x82E9, 0xC675, 0x82EA, 0xC676, 0x82EC, + 0xC677, 0x82ED, 0xC678, 0x82EE, 0xC679, 0x82F0, 0xC67A, 0x82F2, 0xC67B, 0x82F3, 0xC67C, 0x82F5, 0xC67D, 0x82F6, 0xC67E, 0x82F8, + 0xC680, 0x82FA, 0xC681, 0x82FC, 0xC682, 0x82FD, 0xC683, 0x82FE, 0xC684, 0x82FF, 0xC685, 0x8300, 0xC686, 0x830A, 0xC687, 0x830B, + 0xC688, 0x830D, 0xC689, 0x8310, 0xC68A, 0x8312, 0xC68B, 0x8313, 0xC68C, 0x8316, 0xC68D, 0x8318, 0xC68E, 0x8319, 0xC68F, 0x831D, + 0xC690, 0x831E, 0xC691, 0x831F, 0xC692, 0x8320, 0xC693, 0x8321, 0xC694, 0x8322, 0xC695, 0x8323, 0xC696, 0x8324, 0xC697, 0x8325, + 0xC698, 0x8326, 0xC699, 0x8329, 0xC69A, 0x832A, 0xC69B, 0x832E, 0xC69C, 0x8330, 0xC69D, 0x8332, 0xC69E, 0x8337, 0xC69F, 0x833B, + 0xC6A0, 0x833D, 0xC6A1, 0x5564, 0xC6A2, 0x813E, 0xC6A3, 0x75B2, 0xC6A4, 0x76AE, 0xC6A5, 0x5339, 0xC6A6, 0x75DE, 0xC6A7, 0x50FB, + 0xC6A8, 0x5C41, 0xC6A9, 0x8B6C, 0xC6AA, 0x7BC7, 0xC6AB, 0x504F, 0xC6AC, 0x7247, 0xC6AD, 0x9A97, 0xC6AE, 0x98D8, 0xC6AF, 0x6F02, + 0xC6B0, 0x74E2, 0xC6B1, 0x7968, 0xC6B2, 0x6487, 0xC6B3, 0x77A5, 0xC6B4, 0x62FC, 0xC6B5, 0x9891, 0xC6B6, 0x8D2B, 0xC6B7, 0x54C1, + 0xC6B8, 0x8058, 0xC6B9, 0x4E52, 0xC6BA, 0x576A, 0xC6BB, 0x82F9, 0xC6BC, 0x840D, 0xC6BD, 0x5E73, 0xC6BE, 0x51ED, 0xC6BF, 0x74F6, + 0xC6C0, 0x8BC4, 0xC6C1, 0x5C4F, 0xC6C2, 0x5761, 0xC6C3, 0x6CFC, 0xC6C4, 0x9887, 0xC6C5, 0x5A46, 0xC6C6, 0x7834, 0xC6C7, 0x9B44, + 0xC6C8, 0x8FEB, 0xC6C9, 0x7C95, 0xC6CA, 0x5256, 0xC6CB, 0x6251, 0xC6CC, 0x94FA, 0xC6CD, 0x4EC6, 0xC6CE, 0x8386, 0xC6CF, 0x8461, + 0xC6D0, 0x83E9, 0xC6D1, 0x84B2, 0xC6D2, 0x57D4, 0xC6D3, 0x6734, 0xC6D4, 0x5703, 0xC6D5, 0x666E, 0xC6D6, 0x6D66, 0xC6D7, 0x8C31, + 0xC6D8, 0x66DD, 0xC6D9, 0x7011, 0xC6DA, 0x671F, 0xC6DB, 0x6B3A, 0xC6DC, 0x6816, 0xC6DD, 0x621A, 0xC6DE, 0x59BB, 0xC6DF, 0x4E03, + 0xC6E0, 0x51C4, 0xC6E1, 0x6F06, 0xC6E2, 0x67D2, 0xC6E3, 0x6C8F, 0xC6E4, 0x5176, 0xC6E5, 0x68CB, 0xC6E6, 0x5947, 0xC6E7, 0x6B67, + 0xC6E8, 0x7566, 0xC6E9, 0x5D0E, 0xC6EA, 0x8110, 0xC6EB, 0x9F50, 0xC6EC, 0x65D7, 0xC6ED, 0x7948, 0xC6EE, 0x7941, 0xC6EF, 0x9A91, + 0xC6F0, 0x8D77, 0xC6F1, 0x5C82, 0xC6F2, 0x4E5E, 0xC6F3, 0x4F01, 0xC6F4, 0x542F, 0xC6F5, 0x5951, 0xC6F6, 0x780C, 0xC6F7, 0x5668, + 0xC6F8, 0x6C14, 0xC6F9, 0x8FC4, 0xC6FA, 0x5F03, 0xC6FB, 0x6C7D, 0xC6FC, 0x6CE3, 0xC6FD, 0x8BAB, 0xC6FE, 0x6390, 0xC740, 0x833E, + 0xC741, 0x833F, 0xC742, 0x8341, 0xC743, 0x8342, 0xC744, 0x8344, 0xC745, 0x8345, 0xC746, 0x8348, 0xC747, 0x834A, 0xC748, 0x834B, + 0xC749, 0x834C, 0xC74A, 0x834D, 0xC74B, 0x834E, 0xC74C, 0x8353, 0xC74D, 0x8355, 0xC74E, 0x8356, 0xC74F, 0x8357, 0xC750, 0x8358, + 0xC751, 0x8359, 0xC752, 0x835D, 0xC753, 0x8362, 0xC754, 0x8370, 0xC755, 0x8371, 0xC756, 0x8372, 0xC757, 0x8373, 0xC758, 0x8374, + 0xC759, 0x8375, 0xC75A, 0x8376, 0xC75B, 0x8379, 0xC75C, 0x837A, 0xC75D, 0x837E, 0xC75E, 0x837F, 0xC75F, 0x8380, 0xC760, 0x8381, + 0xC761, 0x8382, 0xC762, 0x8383, 0xC763, 0x8384, 0xC764, 0x8387, 0xC765, 0x8388, 0xC766, 0x838A, 0xC767, 0x838B, 0xC768, 0x838C, + 0xC769, 0x838D, 0xC76A, 0x838F, 0xC76B, 0x8390, 0xC76C, 0x8391, 0xC76D, 0x8394, 0xC76E, 0x8395, 0xC76F, 0x8396, 0xC770, 0x8397, + 0xC771, 0x8399, 0xC772, 0x839A, 0xC773, 0x839D, 0xC774, 0x839F, 0xC775, 0x83A1, 0xC776, 0x83A2, 0xC777, 0x83A3, 0xC778, 0x83A4, + 0xC779, 0x83A5, 0xC77A, 0x83A6, 0xC77B, 0x83A7, 0xC77C, 0x83AC, 0xC77D, 0x83AD, 0xC77E, 0x83AE, 0xC780, 0x83AF, 0xC781, 0x83B5, + 0xC782, 0x83BB, 0xC783, 0x83BE, 0xC784, 0x83BF, 0xC785, 0x83C2, 0xC786, 0x83C3, 0xC787, 0x83C4, 0xC788, 0x83C6, 0xC789, 0x83C8, + 0xC78A, 0x83C9, 0xC78B, 0x83CB, 0xC78C, 0x83CD, 0xC78D, 0x83CE, 0xC78E, 0x83D0, 0xC78F, 0x83D1, 0xC790, 0x83D2, 0xC791, 0x83D3, + 0xC792, 0x83D5, 0xC793, 0x83D7, 0xC794, 0x83D9, 0xC795, 0x83DA, 0xC796, 0x83DB, 0xC797, 0x83DE, 0xC798, 0x83E2, 0xC799, 0x83E3, + 0xC79A, 0x83E4, 0xC79B, 0x83E6, 0xC79C, 0x83E7, 0xC79D, 0x83E8, 0xC79E, 0x83EB, 0xC79F, 0x83EC, 0xC7A0, 0x83ED, 0xC7A1, 0x6070, + 0xC7A2, 0x6D3D, 0xC7A3, 0x7275, 0xC7A4, 0x6266, 0xC7A5, 0x948E, 0xC7A6, 0x94C5, 0xC7A7, 0x5343, 0xC7A8, 0x8FC1, 0xC7A9, 0x7B7E, + 0xC7AA, 0x4EDF, 0xC7AB, 0x8C26, 0xC7AC, 0x4E7E, 0xC7AD, 0x9ED4, 0xC7AE, 0x94B1, 0xC7AF, 0x94B3, 0xC7B0, 0x524D, 0xC7B1, 0x6F5C, + 0xC7B2, 0x9063, 0xC7B3, 0x6D45, 0xC7B4, 0x8C34, 0xC7B5, 0x5811, 0xC7B6, 0x5D4C, 0xC7B7, 0x6B20, 0xC7B8, 0x6B49, 0xC7B9, 0x67AA, + 0xC7BA, 0x545B, 0xC7BB, 0x8154, 0xC7BC, 0x7F8C, 0xC7BD, 0x5899, 0xC7BE, 0x8537, 0xC7BF, 0x5F3A, 0xC7C0, 0x62A2, 0xC7C1, 0x6A47, + 0xC7C2, 0x9539, 0xC7C3, 0x6572, 0xC7C4, 0x6084, 0xC7C5, 0x6865, 0xC7C6, 0x77A7, 0xC7C7, 0x4E54, 0xC7C8, 0x4FA8, 0xC7C9, 0x5DE7, + 0xC7CA, 0x9798, 0xC7CB, 0x64AC, 0xC7CC, 0x7FD8, 0xC7CD, 0x5CED, 0xC7CE, 0x4FCF, 0xC7CF, 0x7A8D, 0xC7D0, 0x5207, 0xC7D1, 0x8304, + 0xC7D2, 0x4E14, 0xC7D3, 0x602F, 0xC7D4, 0x7A83, 0xC7D5, 0x94A6, 0xC7D6, 0x4FB5, 0xC7D7, 0x4EB2, 0xC7D8, 0x79E6, 0xC7D9, 0x7434, + 0xC7DA, 0x52E4, 0xC7DB, 0x82B9, 0xC7DC, 0x64D2, 0xC7DD, 0x79BD, 0xC7DE, 0x5BDD, 0xC7DF, 0x6C81, 0xC7E0, 0x9752, 0xC7E1, 0x8F7B, + 0xC7E2, 0x6C22, 0xC7E3, 0x503E, 0xC7E4, 0x537F, 0xC7E5, 0x6E05, 0xC7E6, 0x64CE, 0xC7E7, 0x6674, 0xC7E8, 0x6C30, 0xC7E9, 0x60C5, + 0xC7EA, 0x9877, 0xC7EB, 0x8BF7, 0xC7EC, 0x5E86, 0xC7ED, 0x743C, 0xC7EE, 0x7A77, 0xC7EF, 0x79CB, 0xC7F0, 0x4E18, 0xC7F1, 0x90B1, + 0xC7F2, 0x7403, 0xC7F3, 0x6C42, 0xC7F4, 0x56DA, 0xC7F5, 0x914B, 0xC7F6, 0x6CC5, 0xC7F7, 0x8D8B, 0xC7F8, 0x533A, 0xC7F9, 0x86C6, + 0xC7FA, 0x66F2, 0xC7FB, 0x8EAF, 0xC7FC, 0x5C48, 0xC7FD, 0x9A71, 0xC7FE, 0x6E20, 0xC840, 0x83EE, 0xC841, 0x83EF, 0xC842, 0x83F3, + 0xC843, 0x83F4, 0xC844, 0x83F5, 0xC845, 0x83F6, 0xC846, 0x83F7, 0xC847, 0x83FA, 0xC848, 0x83FB, 0xC849, 0x83FC, 0xC84A, 0x83FE, + 0xC84B, 0x83FF, 0xC84C, 0x8400, 0xC84D, 0x8402, 0xC84E, 0x8405, 0xC84F, 0x8407, 0xC850, 0x8408, 0xC851, 0x8409, 0xC852, 0x840A, + 0xC853, 0x8410, 0xC854, 0x8412, 0xC855, 0x8413, 0xC856, 0x8414, 0xC857, 0x8415, 0xC858, 0x8416, 0xC859, 0x8417, 0xC85A, 0x8419, + 0xC85B, 0x841A, 0xC85C, 0x841B, 0xC85D, 0x841E, 0xC85E, 0x841F, 0xC85F, 0x8420, 0xC860, 0x8421, 0xC861, 0x8422, 0xC862, 0x8423, + 0xC863, 0x8429, 0xC864, 0x842A, 0xC865, 0x842B, 0xC866, 0x842C, 0xC867, 0x842D, 0xC868, 0x842E, 0xC869, 0x842F, 0xC86A, 0x8430, + 0xC86B, 0x8432, 0xC86C, 0x8433, 0xC86D, 0x8434, 0xC86E, 0x8435, 0xC86F, 0x8436, 0xC870, 0x8437, 0xC871, 0x8439, 0xC872, 0x843A, + 0xC873, 0x843B, 0xC874, 0x843E, 0xC875, 0x843F, 0xC876, 0x8440, 0xC877, 0x8441, 0xC878, 0x8442, 0xC879, 0x8443, 0xC87A, 0x8444, + 0xC87B, 0x8445, 0xC87C, 0x8447, 0xC87D, 0x8448, 0xC87E, 0x8449, 0xC880, 0x844A, 0xC881, 0x844B, 0xC882, 0x844C, 0xC883, 0x844D, + 0xC884, 0x844E, 0xC885, 0x844F, 0xC886, 0x8450, 0xC887, 0x8452, 0xC888, 0x8453, 0xC889, 0x8454, 0xC88A, 0x8455, 0xC88B, 0x8456, + 0xC88C, 0x8458, 0xC88D, 0x845D, 0xC88E, 0x845E, 0xC88F, 0x845F, 0xC890, 0x8460, 0xC891, 0x8462, 0xC892, 0x8464, 0xC893, 0x8465, + 0xC894, 0x8466, 0xC895, 0x8467, 0xC896, 0x8468, 0xC897, 0x846A, 0xC898, 0x846E, 0xC899, 0x846F, 0xC89A, 0x8470, 0xC89B, 0x8472, + 0xC89C, 0x8474, 0xC89D, 0x8477, 0xC89E, 0x8479, 0xC89F, 0x847B, 0xC8A0, 0x847C, 0xC8A1, 0x53D6, 0xC8A2, 0x5A36, 0xC8A3, 0x9F8B, + 0xC8A4, 0x8DA3, 0xC8A5, 0x53BB, 0xC8A6, 0x5708, 0xC8A7, 0x98A7, 0xC8A8, 0x6743, 0xC8A9, 0x919B, 0xC8AA, 0x6CC9, 0xC8AB, 0x5168, + 0xC8AC, 0x75CA, 0xC8AD, 0x62F3, 0xC8AE, 0x72AC, 0xC8AF, 0x5238, 0xC8B0, 0x529D, 0xC8B1, 0x7F3A, 0xC8B2, 0x7094, 0xC8B3, 0x7638, + 0xC8B4, 0x5374, 0xC8B5, 0x9E4A, 0xC8B6, 0x69B7, 0xC8B7, 0x786E, 0xC8B8, 0x96C0, 0xC8B9, 0x88D9, 0xC8BA, 0x7FA4, 0xC8BB, 0x7136, + 0xC8BC, 0x71C3, 0xC8BD, 0x5189, 0xC8BE, 0x67D3, 0xC8BF, 0x74E4, 0xC8C0, 0x58E4, 0xC8C1, 0x6518, 0xC8C2, 0x56B7, 0xC8C3, 0x8BA9, + 0xC8C4, 0x9976, 0xC8C5, 0x6270, 0xC8C6, 0x7ED5, 0xC8C7, 0x60F9, 0xC8C8, 0x70ED, 0xC8C9, 0x58EC, 0xC8CA, 0x4EC1, 0xC8CB, 0x4EBA, + 0xC8CC, 0x5FCD, 0xC8CD, 0x97E7, 0xC8CE, 0x4EFB, 0xC8CF, 0x8BA4, 0xC8D0, 0x5203, 0xC8D1, 0x598A, 0xC8D2, 0x7EAB, 0xC8D3, 0x6254, + 0xC8D4, 0x4ECD, 0xC8D5, 0x65E5, 0xC8D6, 0x620E, 0xC8D7, 0x8338, 0xC8D8, 0x84C9, 0xC8D9, 0x8363, 0xC8DA, 0x878D, 0xC8DB, 0x7194, + 0xC8DC, 0x6EB6, 0xC8DD, 0x5BB9, 0xC8DE, 0x7ED2, 0xC8DF, 0x5197, 0xC8E0, 0x63C9, 0xC8E1, 0x67D4, 0xC8E2, 0x8089, 0xC8E3, 0x8339, + 0xC8E4, 0x8815, 0xC8E5, 0x5112, 0xC8E6, 0x5B7A, 0xC8E7, 0x5982, 0xC8E8, 0x8FB1, 0xC8E9, 0x4E73, 0xC8EA, 0x6C5D, 0xC8EB, 0x5165, + 0xC8EC, 0x8925, 0xC8ED, 0x8F6F, 0xC8EE, 0x962E, 0xC8EF, 0x854A, 0xC8F0, 0x745E, 0xC8F1, 0x9510, 0xC8F2, 0x95F0, 0xC8F3, 0x6DA6, + 0xC8F4, 0x82E5, 0xC8F5, 0x5F31, 0xC8F6, 0x6492, 0xC8F7, 0x6D12, 0xC8F8, 0x8428, 0xC8F9, 0x816E, 0xC8FA, 0x9CC3, 0xC8FB, 0x585E, + 0xC8FC, 0x8D5B, 0xC8FD, 0x4E09, 0xC8FE, 0x53C1, 0xC940, 0x847D, 0xC941, 0x847E, 0xC942, 0x847F, 0xC943, 0x8480, 0xC944, 0x8481, + 0xC945, 0x8483, 0xC946, 0x8484, 0xC947, 0x8485, 0xC948, 0x8486, 0xC949, 0x848A, 0xC94A, 0x848D, 0xC94B, 0x848F, 0xC94C, 0x8490, + 0xC94D, 0x8491, 0xC94E, 0x8492, 0xC94F, 0x8493, 0xC950, 0x8494, 0xC951, 0x8495, 0xC952, 0x8496, 0xC953, 0x8498, 0xC954, 0x849A, + 0xC955, 0x849B, 0xC956, 0x849D, 0xC957, 0x849E, 0xC958, 0x849F, 0xC959, 0x84A0, 0xC95A, 0x84A2, 0xC95B, 0x84A3, 0xC95C, 0x84A4, + 0xC95D, 0x84A5, 0xC95E, 0x84A6, 0xC95F, 0x84A7, 0xC960, 0x84A8, 0xC961, 0x84A9, 0xC962, 0x84AA, 0xC963, 0x84AB, 0xC964, 0x84AC, + 0xC965, 0x84AD, 0xC966, 0x84AE, 0xC967, 0x84B0, 0xC968, 0x84B1, 0xC969, 0x84B3, 0xC96A, 0x84B5, 0xC96B, 0x84B6, 0xC96C, 0x84B7, + 0xC96D, 0x84BB, 0xC96E, 0x84BC, 0xC96F, 0x84BE, 0xC970, 0x84C0, 0xC971, 0x84C2, 0xC972, 0x84C3, 0xC973, 0x84C5, 0xC974, 0x84C6, + 0xC975, 0x84C7, 0xC976, 0x84C8, 0xC977, 0x84CB, 0xC978, 0x84CC, 0xC979, 0x84CE, 0xC97A, 0x84CF, 0xC97B, 0x84D2, 0xC97C, 0x84D4, + 0xC97D, 0x84D5, 0xC97E, 0x84D7, 0xC980, 0x84D8, 0xC981, 0x84D9, 0xC982, 0x84DA, 0xC983, 0x84DB, 0xC984, 0x84DC, 0xC985, 0x84DE, + 0xC986, 0x84E1, 0xC987, 0x84E2, 0xC988, 0x84E4, 0xC989, 0x84E7, 0xC98A, 0x84E8, 0xC98B, 0x84E9, 0xC98C, 0x84EA, 0xC98D, 0x84EB, + 0xC98E, 0x84ED, 0xC98F, 0x84EE, 0xC990, 0x84EF, 0xC991, 0x84F1, 0xC992, 0x84F2, 0xC993, 0x84F3, 0xC994, 0x84F4, 0xC995, 0x84F5, + 0xC996, 0x84F6, 0xC997, 0x84F7, 0xC998, 0x84F8, 0xC999, 0x84F9, 0xC99A, 0x84FA, 0xC99B, 0x84FB, 0xC99C, 0x84FD, 0xC99D, 0x84FE, + 0xC99E, 0x8500, 0xC99F, 0x8501, 0xC9A0, 0x8502, 0xC9A1, 0x4F1E, 0xC9A2, 0x6563, 0xC9A3, 0x6851, 0xC9A4, 0x55D3, 0xC9A5, 0x4E27, + 0xC9A6, 0x6414, 0xC9A7, 0x9A9A, 0xC9A8, 0x626B, 0xC9A9, 0x5AC2, 0xC9AA, 0x745F, 0xC9AB, 0x8272, 0xC9AC, 0x6DA9, 0xC9AD, 0x68EE, + 0xC9AE, 0x50E7, 0xC9AF, 0x838E, 0xC9B0, 0x7802, 0xC9B1, 0x6740, 0xC9B2, 0x5239, 0xC9B3, 0x6C99, 0xC9B4, 0x7EB1, 0xC9B5, 0x50BB, + 0xC9B6, 0x5565, 0xC9B7, 0x715E, 0xC9B8, 0x7B5B, 0xC9B9, 0x6652, 0xC9BA, 0x73CA, 0xC9BB, 0x82EB, 0xC9BC, 0x6749, 0xC9BD, 0x5C71, + 0xC9BE, 0x5220, 0xC9BF, 0x717D, 0xC9C0, 0x886B, 0xC9C1, 0x95EA, 0xC9C2, 0x9655, 0xC9C3, 0x64C5, 0xC9C4, 0x8D61, 0xC9C5, 0x81B3, + 0xC9C6, 0x5584, 0xC9C7, 0x6C55, 0xC9C8, 0x6247, 0xC9C9, 0x7F2E, 0xC9CA, 0x5892, 0xC9CB, 0x4F24, 0xC9CC, 0x5546, 0xC9CD, 0x8D4F, + 0xC9CE, 0x664C, 0xC9CF, 0x4E0A, 0xC9D0, 0x5C1A, 0xC9D1, 0x88F3, 0xC9D2, 0x68A2, 0xC9D3, 0x634E, 0xC9D4, 0x7A0D, 0xC9D5, 0x70E7, + 0xC9D6, 0x828D, 0xC9D7, 0x52FA, 0xC9D8, 0x97F6, 0xC9D9, 0x5C11, 0xC9DA, 0x54E8, 0xC9DB, 0x90B5, 0xC9DC, 0x7ECD, 0xC9DD, 0x5962, + 0xC9DE, 0x8D4A, 0xC9DF, 0x86C7, 0xC9E0, 0x820C, 0xC9E1, 0x820D, 0xC9E2, 0x8D66, 0xC9E3, 0x6444, 0xC9E4, 0x5C04, 0xC9E5, 0x6151, + 0xC9E6, 0x6D89, 0xC9E7, 0x793E, 0xC9E8, 0x8BBE, 0xC9E9, 0x7837, 0xC9EA, 0x7533, 0xC9EB, 0x547B, 0xC9EC, 0x4F38, 0xC9ED, 0x8EAB, + 0xC9EE, 0x6DF1, 0xC9EF, 0x5A20, 0xC9F0, 0x7EC5, 0xC9F1, 0x795E, 0xC9F2, 0x6C88, 0xC9F3, 0x5BA1, 0xC9F4, 0x5A76, 0xC9F5, 0x751A, + 0xC9F6, 0x80BE, 0xC9F7, 0x614E, 0xC9F8, 0x6E17, 0xC9F9, 0x58F0, 0xC9FA, 0x751F, 0xC9FB, 0x7525, 0xC9FC, 0x7272, 0xC9FD, 0x5347, + 0xC9FE, 0x7EF3, 0xCA40, 0x8503, 0xCA41, 0x8504, 0xCA42, 0x8505, 0xCA43, 0x8506, 0xCA44, 0x8507, 0xCA45, 0x8508, 0xCA46, 0x8509, + 0xCA47, 0x850A, 0xCA48, 0x850B, 0xCA49, 0x850D, 0xCA4A, 0x850E, 0xCA4B, 0x850F, 0xCA4C, 0x8510, 0xCA4D, 0x8512, 0xCA4E, 0x8514, + 0xCA4F, 0x8515, 0xCA50, 0x8516, 0xCA51, 0x8518, 0xCA52, 0x8519, 0xCA53, 0x851B, 0xCA54, 0x851C, 0xCA55, 0x851D, 0xCA56, 0x851E, + 0xCA57, 0x8520, 0xCA58, 0x8522, 0xCA59, 0x8523, 0xCA5A, 0x8524, 0xCA5B, 0x8525, 0xCA5C, 0x8526, 0xCA5D, 0x8527, 0xCA5E, 0x8528, + 0xCA5F, 0x8529, 0xCA60, 0x852A, 0xCA61, 0x852D, 0xCA62, 0x852E, 0xCA63, 0x852F, 0xCA64, 0x8530, 0xCA65, 0x8531, 0xCA66, 0x8532, + 0xCA67, 0x8533, 0xCA68, 0x8534, 0xCA69, 0x8535, 0xCA6A, 0x8536, 0xCA6B, 0x853E, 0xCA6C, 0x853F, 0xCA6D, 0x8540, 0xCA6E, 0x8541, + 0xCA6F, 0x8542, 0xCA70, 0x8544, 0xCA71, 0x8545, 0xCA72, 0x8546, 0xCA73, 0x8547, 0xCA74, 0x854B, 0xCA75, 0x854C, 0xCA76, 0x854D, + 0xCA77, 0x854E, 0xCA78, 0x854F, 0xCA79, 0x8550, 0xCA7A, 0x8551, 0xCA7B, 0x8552, 0xCA7C, 0x8553, 0xCA7D, 0x8554, 0xCA7E, 0x8555, + 0xCA80, 0x8557, 0xCA81, 0x8558, 0xCA82, 0x855A, 0xCA83, 0x855B, 0xCA84, 0x855C, 0xCA85, 0x855D, 0xCA86, 0x855F, 0xCA87, 0x8560, + 0xCA88, 0x8561, 0xCA89, 0x8562, 0xCA8A, 0x8563, 0xCA8B, 0x8565, 0xCA8C, 0x8566, 0xCA8D, 0x8567, 0xCA8E, 0x8569, 0xCA8F, 0x856A, + 0xCA90, 0x856B, 0xCA91, 0x856C, 0xCA92, 0x856D, 0xCA93, 0x856E, 0xCA94, 0x856F, 0xCA95, 0x8570, 0xCA96, 0x8571, 0xCA97, 0x8573, + 0xCA98, 0x8575, 0xCA99, 0x8576, 0xCA9A, 0x8577, 0xCA9B, 0x8578, 0xCA9C, 0x857C, 0xCA9D, 0x857D, 0xCA9E, 0x857F, 0xCA9F, 0x8580, + 0xCAA0, 0x8581, 0xCAA1, 0x7701, 0xCAA2, 0x76DB, 0xCAA3, 0x5269, 0xCAA4, 0x80DC, 0xCAA5, 0x5723, 0xCAA6, 0x5E08, 0xCAA7, 0x5931, + 0xCAA8, 0x72EE, 0xCAA9, 0x65BD, 0xCAAA, 0x6E7F, 0xCAAB, 0x8BD7, 0xCAAC, 0x5C38, 0xCAAD, 0x8671, 0xCAAE, 0x5341, 0xCAAF, 0x77F3, + 0xCAB0, 0x62FE, 0xCAB1, 0x65F6, 0xCAB2, 0x4EC0, 0xCAB3, 0x98DF, 0xCAB4, 0x8680, 0xCAB5, 0x5B9E, 0xCAB6, 0x8BC6, 0xCAB7, 0x53F2, + 0xCAB8, 0x77E2, 0xCAB9, 0x4F7F, 0xCABA, 0x5C4E, 0xCABB, 0x9A76, 0xCABC, 0x59CB, 0xCABD, 0x5F0F, 0xCABE, 0x793A, 0xCABF, 0x58EB, + 0xCAC0, 0x4E16, 0xCAC1, 0x67FF, 0xCAC2, 0x4E8B, 0xCAC3, 0x62ED, 0xCAC4, 0x8A93, 0xCAC5, 0x901D, 0xCAC6, 0x52BF, 0xCAC7, 0x662F, + 0xCAC8, 0x55DC, 0xCAC9, 0x566C, 0xCACA, 0x9002, 0xCACB, 0x4ED5, 0xCACC, 0x4F8D, 0xCACD, 0x91CA, 0xCACE, 0x9970, 0xCACF, 0x6C0F, + 0xCAD0, 0x5E02, 0xCAD1, 0x6043, 0xCAD2, 0x5BA4, 0xCAD3, 0x89C6, 0xCAD4, 0x8BD5, 0xCAD5, 0x6536, 0xCAD6, 0x624B, 0xCAD7, 0x9996, + 0xCAD8, 0x5B88, 0xCAD9, 0x5BFF, 0xCADA, 0x6388, 0xCADB, 0x552E, 0xCADC, 0x53D7, 0xCADD, 0x7626, 0xCADE, 0x517D, 0xCADF, 0x852C, + 0xCAE0, 0x67A2, 0xCAE1, 0x68B3, 0xCAE2, 0x6B8A, 0xCAE3, 0x6292, 0xCAE4, 0x8F93, 0xCAE5, 0x53D4, 0xCAE6, 0x8212, 0xCAE7, 0x6DD1, + 0xCAE8, 0x758F, 0xCAE9, 0x4E66, 0xCAEA, 0x8D4E, 0xCAEB, 0x5B70, 0xCAEC, 0x719F, 0xCAED, 0x85AF, 0xCAEE, 0x6691, 0xCAEF, 0x66D9, + 0xCAF0, 0x7F72, 0xCAF1, 0x8700, 0xCAF2, 0x9ECD, 0xCAF3, 0x9F20, 0xCAF4, 0x5C5E, 0xCAF5, 0x672F, 0xCAF6, 0x8FF0, 0xCAF7, 0x6811, + 0xCAF8, 0x675F, 0xCAF9, 0x620D, 0xCAFA, 0x7AD6, 0xCAFB, 0x5885, 0xCAFC, 0x5EB6, 0xCAFD, 0x6570, 0xCAFE, 0x6F31, 0xCB40, 0x8582, + 0xCB41, 0x8583, 0xCB42, 0x8586, 0xCB43, 0x8588, 0xCB44, 0x8589, 0xCB45, 0x858A, 0xCB46, 0x858B, 0xCB47, 0x858C, 0xCB48, 0x858D, + 0xCB49, 0x858E, 0xCB4A, 0x8590, 0xCB4B, 0x8591, 0xCB4C, 0x8592, 0xCB4D, 0x8593, 0xCB4E, 0x8594, 0xCB4F, 0x8595, 0xCB50, 0x8596, + 0xCB51, 0x8597, 0xCB52, 0x8598, 0xCB53, 0x8599, 0xCB54, 0x859A, 0xCB55, 0x859D, 0xCB56, 0x859E, 0xCB57, 0x859F, 0xCB58, 0x85A0, + 0xCB59, 0x85A1, 0xCB5A, 0x85A2, 0xCB5B, 0x85A3, 0xCB5C, 0x85A5, 0xCB5D, 0x85A6, 0xCB5E, 0x85A7, 0xCB5F, 0x85A9, 0xCB60, 0x85AB, + 0xCB61, 0x85AC, 0xCB62, 0x85AD, 0xCB63, 0x85B1, 0xCB64, 0x85B2, 0xCB65, 0x85B3, 0xCB66, 0x85B4, 0xCB67, 0x85B5, 0xCB68, 0x85B6, + 0xCB69, 0x85B8, 0xCB6A, 0x85BA, 0xCB6B, 0x85BB, 0xCB6C, 0x85BC, 0xCB6D, 0x85BD, 0xCB6E, 0x85BE, 0xCB6F, 0x85BF, 0xCB70, 0x85C0, + 0xCB71, 0x85C2, 0xCB72, 0x85C3, 0xCB73, 0x85C4, 0xCB74, 0x85C5, 0xCB75, 0x85C6, 0xCB76, 0x85C7, 0xCB77, 0x85C8, 0xCB78, 0x85CA, + 0xCB79, 0x85CB, 0xCB7A, 0x85CC, 0xCB7B, 0x85CD, 0xCB7C, 0x85CE, 0xCB7D, 0x85D1, 0xCB7E, 0x85D2, 0xCB80, 0x85D4, 0xCB81, 0x85D6, + 0xCB82, 0x85D7, 0xCB83, 0x85D8, 0xCB84, 0x85D9, 0xCB85, 0x85DA, 0xCB86, 0x85DB, 0xCB87, 0x85DD, 0xCB88, 0x85DE, 0xCB89, 0x85DF, + 0xCB8A, 0x85E0, 0xCB8B, 0x85E1, 0xCB8C, 0x85E2, 0xCB8D, 0x85E3, 0xCB8E, 0x85E5, 0xCB8F, 0x85E6, 0xCB90, 0x85E7, 0xCB91, 0x85E8, + 0xCB92, 0x85EA, 0xCB93, 0x85EB, 0xCB94, 0x85EC, 0xCB95, 0x85ED, 0xCB96, 0x85EE, 0xCB97, 0x85EF, 0xCB98, 0x85F0, 0xCB99, 0x85F1, + 0xCB9A, 0x85F2, 0xCB9B, 0x85F3, 0xCB9C, 0x85F4, 0xCB9D, 0x85F5, 0xCB9E, 0x85F6, 0xCB9F, 0x85F7, 0xCBA0, 0x85F8, 0xCBA1, 0x6055, + 0xCBA2, 0x5237, 0xCBA3, 0x800D, 0xCBA4, 0x6454, 0xCBA5, 0x8870, 0xCBA6, 0x7529, 0xCBA7, 0x5E05, 0xCBA8, 0x6813, 0xCBA9, 0x62F4, + 0xCBAA, 0x971C, 0xCBAB, 0x53CC, 0xCBAC, 0x723D, 0xCBAD, 0x8C01, 0xCBAE, 0x6C34, 0xCBAF, 0x7761, 0xCBB0, 0x7A0E, 0xCBB1, 0x542E, + 0xCBB2, 0x77AC, 0xCBB3, 0x987A, 0xCBB4, 0x821C, 0xCBB5, 0x8BF4, 0xCBB6, 0x7855, 0xCBB7, 0x6714, 0xCBB8, 0x70C1, 0xCBB9, 0x65AF, + 0xCBBA, 0x6495, 0xCBBB, 0x5636, 0xCBBC, 0x601D, 0xCBBD, 0x79C1, 0xCBBE, 0x53F8, 0xCBBF, 0x4E1D, 0xCBC0, 0x6B7B, 0xCBC1, 0x8086, + 0xCBC2, 0x5BFA, 0xCBC3, 0x55E3, 0xCBC4, 0x56DB, 0xCBC5, 0x4F3A, 0xCBC6, 0x4F3C, 0xCBC7, 0x9972, 0xCBC8, 0x5DF3, 0xCBC9, 0x677E, + 0xCBCA, 0x8038, 0xCBCB, 0x6002, 0xCBCC, 0x9882, 0xCBCD, 0x9001, 0xCBCE, 0x5B8B, 0xCBCF, 0x8BBC, 0xCBD0, 0x8BF5, 0xCBD1, 0x641C, + 0xCBD2, 0x8258, 0xCBD3, 0x64DE, 0xCBD4, 0x55FD, 0xCBD5, 0x82CF, 0xCBD6, 0x9165, 0xCBD7, 0x4FD7, 0xCBD8, 0x7D20, 0xCBD9, 0x901F, + 0xCBDA, 0x7C9F, 0xCBDB, 0x50F3, 0xCBDC, 0x5851, 0xCBDD, 0x6EAF, 0xCBDE, 0x5BBF, 0xCBDF, 0x8BC9, 0xCBE0, 0x8083, 0xCBE1, 0x9178, + 0xCBE2, 0x849C, 0xCBE3, 0x7B97, 0xCBE4, 0x867D, 0xCBE5, 0x968B, 0xCBE6, 0x968F, 0xCBE7, 0x7EE5, 0xCBE8, 0x9AD3, 0xCBE9, 0x788E, + 0xCBEA, 0x5C81, 0xCBEB, 0x7A57, 0xCBEC, 0x9042, 0xCBED, 0x96A7, 0xCBEE, 0x795F, 0xCBEF, 0x5B59, 0xCBF0, 0x635F, 0xCBF1, 0x7B0B, + 0xCBF2, 0x84D1, 0xCBF3, 0x68AD, 0xCBF4, 0x5506, 0xCBF5, 0x7F29, 0xCBF6, 0x7410, 0xCBF7, 0x7D22, 0xCBF8, 0x9501, 0xCBF9, 0x6240, + 0xCBFA, 0x584C, 0xCBFB, 0x4ED6, 0xCBFC, 0x5B83, 0xCBFD, 0x5979, 0xCBFE, 0x5854, 0xCC40, 0x85F9, 0xCC41, 0x85FA, 0xCC42, 0x85FC, + 0xCC43, 0x85FD, 0xCC44, 0x85FE, 0xCC45, 0x8600, 0xCC46, 0x8601, 0xCC47, 0x8602, 0xCC48, 0x8603, 0xCC49, 0x8604, 0xCC4A, 0x8606, + 0xCC4B, 0x8607, 0xCC4C, 0x8608, 0xCC4D, 0x8609, 0xCC4E, 0x860A, 0xCC4F, 0x860B, 0xCC50, 0x860C, 0xCC51, 0x860D, 0xCC52, 0x860E, + 0xCC53, 0x860F, 0xCC54, 0x8610, 0xCC55, 0x8612, 0xCC56, 0x8613, 0xCC57, 0x8614, 0xCC58, 0x8615, 0xCC59, 0x8617, 0xCC5A, 0x8618, + 0xCC5B, 0x8619, 0xCC5C, 0x861A, 0xCC5D, 0x861B, 0xCC5E, 0x861C, 0xCC5F, 0x861D, 0xCC60, 0x861E, 0xCC61, 0x861F, 0xCC62, 0x8620, + 0xCC63, 0x8621, 0xCC64, 0x8622, 0xCC65, 0x8623, 0xCC66, 0x8624, 0xCC67, 0x8625, 0xCC68, 0x8626, 0xCC69, 0x8628, 0xCC6A, 0x862A, + 0xCC6B, 0x862B, 0xCC6C, 0x862C, 0xCC6D, 0x862D, 0xCC6E, 0x862E, 0xCC6F, 0x862F, 0xCC70, 0x8630, 0xCC71, 0x8631, 0xCC72, 0x8632, + 0xCC73, 0x8633, 0xCC74, 0x8634, 0xCC75, 0x8635, 0xCC76, 0x8636, 0xCC77, 0x8637, 0xCC78, 0x8639, 0xCC79, 0x863A, 0xCC7A, 0x863B, + 0xCC7B, 0x863D, 0xCC7C, 0x863E, 0xCC7D, 0x863F, 0xCC7E, 0x8640, 0xCC80, 0x8641, 0xCC81, 0x8642, 0xCC82, 0x8643, 0xCC83, 0x8644, + 0xCC84, 0x8645, 0xCC85, 0x8646, 0xCC86, 0x8647, 0xCC87, 0x8648, 0xCC88, 0x8649, 0xCC89, 0x864A, 0xCC8A, 0x864B, 0xCC8B, 0x864C, + 0xCC8C, 0x8652, 0xCC8D, 0x8653, 0xCC8E, 0x8655, 0xCC8F, 0x8656, 0xCC90, 0x8657, 0xCC91, 0x8658, 0xCC92, 0x8659, 0xCC93, 0x865B, + 0xCC94, 0x865C, 0xCC95, 0x865D, 0xCC96, 0x865F, 0xCC97, 0x8660, 0xCC98, 0x8661, 0xCC99, 0x8663, 0xCC9A, 0x8664, 0xCC9B, 0x8665, + 0xCC9C, 0x8666, 0xCC9D, 0x8667, 0xCC9E, 0x8668, 0xCC9F, 0x8669, 0xCCA0, 0x866A, 0xCCA1, 0x736D, 0xCCA2, 0x631E, 0xCCA3, 0x8E4B, + 0xCCA4, 0x8E0F, 0xCCA5, 0x80CE, 0xCCA6, 0x82D4, 0xCCA7, 0x62AC, 0xCCA8, 0x53F0, 0xCCA9, 0x6CF0, 0xCCAA, 0x915E, 0xCCAB, 0x592A, + 0xCCAC, 0x6001, 0xCCAD, 0x6C70, 0xCCAE, 0x574D, 0xCCAF, 0x644A, 0xCCB0, 0x8D2A, 0xCCB1, 0x762B, 0xCCB2, 0x6EE9, 0xCCB3, 0x575B, + 0xCCB4, 0x6A80, 0xCCB5, 0x75F0, 0xCCB6, 0x6F6D, 0xCCB7, 0x8C2D, 0xCCB8, 0x8C08, 0xCCB9, 0x5766, 0xCCBA, 0x6BEF, 0xCCBB, 0x8892, + 0xCCBC, 0x78B3, 0xCCBD, 0x63A2, 0xCCBE, 0x53F9, 0xCCBF, 0x70AD, 0xCCC0, 0x6C64, 0xCCC1, 0x5858, 0xCCC2, 0x642A, 0xCCC3, 0x5802, + 0xCCC4, 0x68E0, 0xCCC5, 0x819B, 0xCCC6, 0x5510, 0xCCC7, 0x7CD6, 0xCCC8, 0x5018, 0xCCC9, 0x8EBA, 0xCCCA, 0x6DCC, 0xCCCB, 0x8D9F, + 0xCCCC, 0x70EB, 0xCCCD, 0x638F, 0xCCCE, 0x6D9B, 0xCCCF, 0x6ED4, 0xCCD0, 0x7EE6, 0xCCD1, 0x8404, 0xCCD2, 0x6843, 0xCCD3, 0x9003, + 0xCCD4, 0x6DD8, 0xCCD5, 0x9676, 0xCCD6, 0x8BA8, 0xCCD7, 0x5957, 0xCCD8, 0x7279, 0xCCD9, 0x85E4, 0xCCDA, 0x817E, 0xCCDB, 0x75BC, + 0xCCDC, 0x8A8A, 0xCCDD, 0x68AF, 0xCCDE, 0x5254, 0xCCDF, 0x8E22, 0xCCE0, 0x9511, 0xCCE1, 0x63D0, 0xCCE2, 0x9898, 0xCCE3, 0x8E44, + 0xCCE4, 0x557C, 0xCCE5, 0x4F53, 0xCCE6, 0x66FF, 0xCCE7, 0x568F, 0xCCE8, 0x60D5, 0xCCE9, 0x6D95, 0xCCEA, 0x5243, 0xCCEB, 0x5C49, + 0xCCEC, 0x5929, 0xCCED, 0x6DFB, 0xCCEE, 0x586B, 0xCCEF, 0x7530, 0xCCF0, 0x751C, 0xCCF1, 0x606C, 0xCCF2, 0x8214, 0xCCF3, 0x8146, + 0xCCF4, 0x6311, 0xCCF5, 0x6761, 0xCCF6, 0x8FE2, 0xCCF7, 0x773A, 0xCCF8, 0x8DF3, 0xCCF9, 0x8D34, 0xCCFA, 0x94C1, 0xCCFB, 0x5E16, + 0xCCFC, 0x5385, 0xCCFD, 0x542C, 0xCCFE, 0x70C3, 0xCD40, 0x866D, 0xCD41, 0x866F, 0xCD42, 0x8670, 0xCD43, 0x8672, 0xCD44, 0x8673, + 0xCD45, 0x8674, 0xCD46, 0x8675, 0xCD47, 0x8676, 0xCD48, 0x8677, 0xCD49, 0x8678, 0xCD4A, 0x8683, 0xCD4B, 0x8684, 0xCD4C, 0x8685, + 0xCD4D, 0x8686, 0xCD4E, 0x8687, 0xCD4F, 0x8688, 0xCD50, 0x8689, 0xCD51, 0x868E, 0xCD52, 0x868F, 0xCD53, 0x8690, 0xCD54, 0x8691, + 0xCD55, 0x8692, 0xCD56, 0x8694, 0xCD57, 0x8696, 0xCD58, 0x8697, 0xCD59, 0x8698, 0xCD5A, 0x8699, 0xCD5B, 0x869A, 0xCD5C, 0x869B, + 0xCD5D, 0x869E, 0xCD5E, 0x869F, 0xCD5F, 0x86A0, 0xCD60, 0x86A1, 0xCD61, 0x86A2, 0xCD62, 0x86A5, 0xCD63, 0x86A6, 0xCD64, 0x86AB, + 0xCD65, 0x86AD, 0xCD66, 0x86AE, 0xCD67, 0x86B2, 0xCD68, 0x86B3, 0xCD69, 0x86B7, 0xCD6A, 0x86B8, 0xCD6B, 0x86B9, 0xCD6C, 0x86BB, + 0xCD6D, 0x86BC, 0xCD6E, 0x86BD, 0xCD6F, 0x86BE, 0xCD70, 0x86BF, 0xCD71, 0x86C1, 0xCD72, 0x86C2, 0xCD73, 0x86C3, 0xCD74, 0x86C5, + 0xCD75, 0x86C8, 0xCD76, 0x86CC, 0xCD77, 0x86CD, 0xCD78, 0x86D2, 0xCD79, 0x86D3, 0xCD7A, 0x86D5, 0xCD7B, 0x86D6, 0xCD7C, 0x86D7, + 0xCD7D, 0x86DA, 0xCD7E, 0x86DC, 0xCD80, 0x86DD, 0xCD81, 0x86E0, 0xCD82, 0x86E1, 0xCD83, 0x86E2, 0xCD84, 0x86E3, 0xCD85, 0x86E5, + 0xCD86, 0x86E6, 0xCD87, 0x86E7, 0xCD88, 0x86E8, 0xCD89, 0x86EA, 0xCD8A, 0x86EB, 0xCD8B, 0x86EC, 0xCD8C, 0x86EF, 0xCD8D, 0x86F5, + 0xCD8E, 0x86F6, 0xCD8F, 0x86F7, 0xCD90, 0x86FA, 0xCD91, 0x86FB, 0xCD92, 0x86FC, 0xCD93, 0x86FD, 0xCD94, 0x86FF, 0xCD95, 0x8701, + 0xCD96, 0x8704, 0xCD97, 0x8705, 0xCD98, 0x8706, 0xCD99, 0x870B, 0xCD9A, 0x870C, 0xCD9B, 0x870E, 0xCD9C, 0x870F, 0xCD9D, 0x8710, + 0xCD9E, 0x8711, 0xCD9F, 0x8714, 0xCDA0, 0x8716, 0xCDA1, 0x6C40, 0xCDA2, 0x5EF7, 0xCDA3, 0x505C, 0xCDA4, 0x4EAD, 0xCDA5, 0x5EAD, + 0xCDA6, 0x633A, 0xCDA7, 0x8247, 0xCDA8, 0x901A, 0xCDA9, 0x6850, 0xCDAA, 0x916E, 0xCDAB, 0x77B3, 0xCDAC, 0x540C, 0xCDAD, 0x94DC, + 0xCDAE, 0x5F64, 0xCDAF, 0x7AE5, 0xCDB0, 0x6876, 0xCDB1, 0x6345, 0xCDB2, 0x7B52, 0xCDB3, 0x7EDF, 0xCDB4, 0x75DB, 0xCDB5, 0x5077, + 0xCDB6, 0x6295, 0xCDB7, 0x5934, 0xCDB8, 0x900F, 0xCDB9, 0x51F8, 0xCDBA, 0x79C3, 0xCDBB, 0x7A81, 0xCDBC, 0x56FE, 0xCDBD, 0x5F92, + 0xCDBE, 0x9014, 0xCDBF, 0x6D82, 0xCDC0, 0x5C60, 0xCDC1, 0x571F, 0xCDC2, 0x5410, 0xCDC3, 0x5154, 0xCDC4, 0x6E4D, 0xCDC5, 0x56E2, + 0xCDC6, 0x63A8, 0xCDC7, 0x9893, 0xCDC8, 0x817F, 0xCDC9, 0x8715, 0xCDCA, 0x892A, 0xCDCB, 0x9000, 0xCDCC, 0x541E, 0xCDCD, 0x5C6F, + 0xCDCE, 0x81C0, 0xCDCF, 0x62D6, 0xCDD0, 0x6258, 0xCDD1, 0x8131, 0xCDD2, 0x9E35, 0xCDD3, 0x9640, 0xCDD4, 0x9A6E, 0xCDD5, 0x9A7C, + 0xCDD6, 0x692D, 0xCDD7, 0x59A5, 0xCDD8, 0x62D3, 0xCDD9, 0x553E, 0xCDDA, 0x6316, 0xCDDB, 0x54C7, 0xCDDC, 0x86D9, 0xCDDD, 0x6D3C, + 0xCDDE, 0x5A03, 0xCDDF, 0x74E6, 0xCDE0, 0x889C, 0xCDE1, 0x6B6A, 0xCDE2, 0x5916, 0xCDE3, 0x8C4C, 0xCDE4, 0x5F2F, 0xCDE5, 0x6E7E, + 0xCDE6, 0x73A9, 0xCDE7, 0x987D, 0xCDE8, 0x4E38, 0xCDE9, 0x70F7, 0xCDEA, 0x5B8C, 0xCDEB, 0x7897, 0xCDEC, 0x633D, 0xCDED, 0x665A, + 0xCDEE, 0x7696, 0xCDEF, 0x60CB, 0xCDF0, 0x5B9B, 0xCDF1, 0x5A49, 0xCDF2, 0x4E07, 0xCDF3, 0x8155, 0xCDF4, 0x6C6A, 0xCDF5, 0x738B, + 0xCDF6, 0x4EA1, 0xCDF7, 0x6789, 0xCDF8, 0x7F51, 0xCDF9, 0x5F80, 0xCDFA, 0x65FA, 0xCDFB, 0x671B, 0xCDFC, 0x5FD8, 0xCDFD, 0x5984, + 0xCDFE, 0x5A01, 0xCE40, 0x8719, 0xCE41, 0x871B, 0xCE42, 0x871D, 0xCE43, 0x871F, 0xCE44, 0x8720, 0xCE45, 0x8724, 0xCE46, 0x8726, + 0xCE47, 0x8727, 0xCE48, 0x8728, 0xCE49, 0x872A, 0xCE4A, 0x872B, 0xCE4B, 0x872C, 0xCE4C, 0x872D, 0xCE4D, 0x872F, 0xCE4E, 0x8730, + 0xCE4F, 0x8732, 0xCE50, 0x8733, 0xCE51, 0x8735, 0xCE52, 0x8736, 0xCE53, 0x8738, 0xCE54, 0x8739, 0xCE55, 0x873A, 0xCE56, 0x873C, + 0xCE57, 0x873D, 0xCE58, 0x8740, 0xCE59, 0x8741, 0xCE5A, 0x8742, 0xCE5B, 0x8743, 0xCE5C, 0x8744, 0xCE5D, 0x8745, 0xCE5E, 0x8746, + 0xCE5F, 0x874A, 0xCE60, 0x874B, 0xCE61, 0x874D, 0xCE62, 0x874F, 0xCE63, 0x8750, 0xCE64, 0x8751, 0xCE65, 0x8752, 0xCE66, 0x8754, + 0xCE67, 0x8755, 0xCE68, 0x8756, 0xCE69, 0x8758, 0xCE6A, 0x875A, 0xCE6B, 0x875B, 0xCE6C, 0x875C, 0xCE6D, 0x875D, 0xCE6E, 0x875E, + 0xCE6F, 0x875F, 0xCE70, 0x8761, 0xCE71, 0x8762, 0xCE72, 0x8766, 0xCE73, 0x8767, 0xCE74, 0x8768, 0xCE75, 0x8769, 0xCE76, 0x876A, + 0xCE77, 0x876B, 0xCE78, 0x876C, 0xCE79, 0x876D, 0xCE7A, 0x876F, 0xCE7B, 0x8771, 0xCE7C, 0x8772, 0xCE7D, 0x8773, 0xCE7E, 0x8775, + 0xCE80, 0x8777, 0xCE81, 0x8778, 0xCE82, 0x8779, 0xCE83, 0x877A, 0xCE84, 0x877F, 0xCE85, 0x8780, 0xCE86, 0x8781, 0xCE87, 0x8784, + 0xCE88, 0x8786, 0xCE89, 0x8787, 0xCE8A, 0x8789, 0xCE8B, 0x878A, 0xCE8C, 0x878C, 0xCE8D, 0x878E, 0xCE8E, 0x878F, 0xCE8F, 0x8790, + 0xCE90, 0x8791, 0xCE91, 0x8792, 0xCE92, 0x8794, 0xCE93, 0x8795, 0xCE94, 0x8796, 0xCE95, 0x8798, 0xCE96, 0x8799, 0xCE97, 0x879A, + 0xCE98, 0x879B, 0xCE99, 0x879C, 0xCE9A, 0x879D, 0xCE9B, 0x879E, 0xCE9C, 0x87A0, 0xCE9D, 0x87A1, 0xCE9E, 0x87A2, 0xCE9F, 0x87A3, + 0xCEA0, 0x87A4, 0xCEA1, 0x5DCD, 0xCEA2, 0x5FAE, 0xCEA3, 0x5371, 0xCEA4, 0x97E6, 0xCEA5, 0x8FDD, 0xCEA6, 0x6845, 0xCEA7, 0x56F4, + 0xCEA8, 0x552F, 0xCEA9, 0x60DF, 0xCEAA, 0x4E3A, 0xCEAB, 0x6F4D, 0xCEAC, 0x7EF4, 0xCEAD, 0x82C7, 0xCEAE, 0x840E, 0xCEAF, 0x59D4, + 0xCEB0, 0x4F1F, 0xCEB1, 0x4F2A, 0xCEB2, 0x5C3E, 0xCEB3, 0x7EAC, 0xCEB4, 0x672A, 0xCEB5, 0x851A, 0xCEB6, 0x5473, 0xCEB7, 0x754F, + 0xCEB8, 0x80C3, 0xCEB9, 0x5582, 0xCEBA, 0x9B4F, 0xCEBB, 0x4F4D, 0xCEBC, 0x6E2D, 0xCEBD, 0x8C13, 0xCEBE, 0x5C09, 0xCEBF, 0x6170, + 0xCEC0, 0x536B, 0xCEC1, 0x761F, 0xCEC2, 0x6E29, 0xCEC3, 0x868A, 0xCEC4, 0x6587, 0xCEC5, 0x95FB, 0xCEC6, 0x7EB9, 0xCEC7, 0x543B, + 0xCEC8, 0x7A33, 0xCEC9, 0x7D0A, 0xCECA, 0x95EE, 0xCECB, 0x55E1, 0xCECC, 0x7FC1, 0xCECD, 0x74EE, 0xCECE, 0x631D, 0xCECF, 0x8717, + 0xCED0, 0x6DA1, 0xCED1, 0x7A9D, 0xCED2, 0x6211, 0xCED3, 0x65A1, 0xCED4, 0x5367, 0xCED5, 0x63E1, 0xCED6, 0x6C83, 0xCED7, 0x5DEB, + 0xCED8, 0x545C, 0xCED9, 0x94A8, 0xCEDA, 0x4E4C, 0xCEDB, 0x6C61, 0xCEDC, 0x8BEC, 0xCEDD, 0x5C4B, 0xCEDE, 0x65E0, 0xCEDF, 0x829C, + 0xCEE0, 0x68A7, 0xCEE1, 0x543E, 0xCEE2, 0x5434, 0xCEE3, 0x6BCB, 0xCEE4, 0x6B66, 0xCEE5, 0x4E94, 0xCEE6, 0x6342, 0xCEE7, 0x5348, + 0xCEE8, 0x821E, 0xCEE9, 0x4F0D, 0xCEEA, 0x4FAE, 0xCEEB, 0x575E, 0xCEEC, 0x620A, 0xCEED, 0x96FE, 0xCEEE, 0x6664, 0xCEEF, 0x7269, + 0xCEF0, 0x52FF, 0xCEF1, 0x52A1, 0xCEF2, 0x609F, 0xCEF3, 0x8BEF, 0xCEF4, 0x6614, 0xCEF5, 0x7199, 0xCEF6, 0x6790, 0xCEF7, 0x897F, + 0xCEF8, 0x7852, 0xCEF9, 0x77FD, 0xCEFA, 0x6670, 0xCEFB, 0x563B, 0xCEFC, 0x5438, 0xCEFD, 0x9521, 0xCEFE, 0x727A, 0xCF40, 0x87A5, + 0xCF41, 0x87A6, 0xCF42, 0x87A7, 0xCF43, 0x87A9, 0xCF44, 0x87AA, 0xCF45, 0x87AE, 0xCF46, 0x87B0, 0xCF47, 0x87B1, 0xCF48, 0x87B2, + 0xCF49, 0x87B4, 0xCF4A, 0x87B6, 0xCF4B, 0x87B7, 0xCF4C, 0x87B8, 0xCF4D, 0x87B9, 0xCF4E, 0x87BB, 0xCF4F, 0x87BC, 0xCF50, 0x87BE, + 0xCF51, 0x87BF, 0xCF52, 0x87C1, 0xCF53, 0x87C2, 0xCF54, 0x87C3, 0xCF55, 0x87C4, 0xCF56, 0x87C5, 0xCF57, 0x87C7, 0xCF58, 0x87C8, + 0xCF59, 0x87C9, 0xCF5A, 0x87CC, 0xCF5B, 0x87CD, 0xCF5C, 0x87CE, 0xCF5D, 0x87CF, 0xCF5E, 0x87D0, 0xCF5F, 0x87D4, 0xCF60, 0x87D5, + 0xCF61, 0x87D6, 0xCF62, 0x87D7, 0xCF63, 0x87D8, 0xCF64, 0x87D9, 0xCF65, 0x87DA, 0xCF66, 0x87DC, 0xCF67, 0x87DD, 0xCF68, 0x87DE, + 0xCF69, 0x87DF, 0xCF6A, 0x87E1, 0xCF6B, 0x87E2, 0xCF6C, 0x87E3, 0xCF6D, 0x87E4, 0xCF6E, 0x87E6, 0xCF6F, 0x87E7, 0xCF70, 0x87E8, + 0xCF71, 0x87E9, 0xCF72, 0x87EB, 0xCF73, 0x87EC, 0xCF74, 0x87ED, 0xCF75, 0x87EF, 0xCF76, 0x87F0, 0xCF77, 0x87F1, 0xCF78, 0x87F2, + 0xCF79, 0x87F3, 0xCF7A, 0x87F4, 0xCF7B, 0x87F5, 0xCF7C, 0x87F6, 0xCF7D, 0x87F7, 0xCF7E, 0x87F8, 0xCF80, 0x87FA, 0xCF81, 0x87FB, + 0xCF82, 0x87FC, 0xCF83, 0x87FD, 0xCF84, 0x87FF, 0xCF85, 0x8800, 0xCF86, 0x8801, 0xCF87, 0x8802, 0xCF88, 0x8804, 0xCF89, 0x8805, + 0xCF8A, 0x8806, 0xCF8B, 0x8807, 0xCF8C, 0x8808, 0xCF8D, 0x8809, 0xCF8E, 0x880B, 0xCF8F, 0x880C, 0xCF90, 0x880D, 0xCF91, 0x880E, + 0xCF92, 0x880F, 0xCF93, 0x8810, 0xCF94, 0x8811, 0xCF95, 0x8812, 0xCF96, 0x8814, 0xCF97, 0x8817, 0xCF98, 0x8818, 0xCF99, 0x8819, + 0xCF9A, 0x881A, 0xCF9B, 0x881C, 0xCF9C, 0x881D, 0xCF9D, 0x881E, 0xCF9E, 0x881F, 0xCF9F, 0x8820, 0xCFA0, 0x8823, 0xCFA1, 0x7A00, + 0xCFA2, 0x606F, 0xCFA3, 0x5E0C, 0xCFA4, 0x6089, 0xCFA5, 0x819D, 0xCFA6, 0x5915, 0xCFA7, 0x60DC, 0xCFA8, 0x7184, 0xCFA9, 0x70EF, + 0xCFAA, 0x6EAA, 0xCFAB, 0x6C50, 0xCFAC, 0x7280, 0xCFAD, 0x6A84, 0xCFAE, 0x88AD, 0xCFAF, 0x5E2D, 0xCFB0, 0x4E60, 0xCFB1, 0x5AB3, + 0xCFB2, 0x559C, 0xCFB3, 0x94E3, 0xCFB4, 0x6D17, 0xCFB5, 0x7CFB, 0xCFB6, 0x9699, 0xCFB7, 0x620F, 0xCFB8, 0x7EC6, 0xCFB9, 0x778E, + 0xCFBA, 0x867E, 0xCFBB, 0x5323, 0xCFBC, 0x971E, 0xCFBD, 0x8F96, 0xCFBE, 0x6687, 0xCFBF, 0x5CE1, 0xCFC0, 0x4FA0, 0xCFC1, 0x72ED, + 0xCFC2, 0x4E0B, 0xCFC3, 0x53A6, 0xCFC4, 0x590F, 0xCFC5, 0x5413, 0xCFC6, 0x6380, 0xCFC7, 0x9528, 0xCFC8, 0x5148, 0xCFC9, 0x4ED9, + 0xCFCA, 0x9C9C, 0xCFCB, 0x7EA4, 0xCFCC, 0x54B8, 0xCFCD, 0x8D24, 0xCFCE, 0x8854, 0xCFCF, 0x8237, 0xCFD0, 0x95F2, 0xCFD1, 0x6D8E, + 0xCFD2, 0x5F26, 0xCFD3, 0x5ACC, 0xCFD4, 0x663E, 0xCFD5, 0x9669, 0xCFD6, 0x73B0, 0xCFD7, 0x732E, 0xCFD8, 0x53BF, 0xCFD9, 0x817A, + 0xCFDA, 0x9985, 0xCFDB, 0x7FA1, 0xCFDC, 0x5BAA, 0xCFDD, 0x9677, 0xCFDE, 0x9650, 0xCFDF, 0x7EBF, 0xCFE0, 0x76F8, 0xCFE1, 0x53A2, + 0xCFE2, 0x9576, 0xCFE3, 0x9999, 0xCFE4, 0x7BB1, 0xCFE5, 0x8944, 0xCFE6, 0x6E58, 0xCFE7, 0x4E61, 0xCFE8, 0x7FD4, 0xCFE9, 0x7965, + 0xCFEA, 0x8BE6, 0xCFEB, 0x60F3, 0xCFEC, 0x54CD, 0xCFED, 0x4EAB, 0xCFEE, 0x9879, 0xCFEF, 0x5DF7, 0xCFF0, 0x6A61, 0xCFF1, 0x50CF, + 0xCFF2, 0x5411, 0xCFF3, 0x8C61, 0xCFF4, 0x8427, 0xCFF5, 0x785D, 0xCFF6, 0x9704, 0xCFF7, 0x524A, 0xCFF8, 0x54EE, 0xCFF9, 0x56A3, + 0xCFFA, 0x9500, 0xCFFB, 0x6D88, 0xCFFC, 0x5BB5, 0xCFFD, 0x6DC6, 0xCFFE, 0x6653, 0xD040, 0x8824, 0xD041, 0x8825, 0xD042, 0x8826, + 0xD043, 0x8827, 0xD044, 0x8828, 0xD045, 0x8829, 0xD046, 0x882A, 0xD047, 0x882B, 0xD048, 0x882C, 0xD049, 0x882D, 0xD04A, 0x882E, + 0xD04B, 0x882F, 0xD04C, 0x8830, 0xD04D, 0x8831, 0xD04E, 0x8833, 0xD04F, 0x8834, 0xD050, 0x8835, 0xD051, 0x8836, 0xD052, 0x8837, + 0xD053, 0x8838, 0xD054, 0x883A, 0xD055, 0x883B, 0xD056, 0x883D, 0xD057, 0x883E, 0xD058, 0x883F, 0xD059, 0x8841, 0xD05A, 0x8842, + 0xD05B, 0x8843, 0xD05C, 0x8846, 0xD05D, 0x8847, 0xD05E, 0x8848, 0xD05F, 0x8849, 0xD060, 0x884A, 0xD061, 0x884B, 0xD062, 0x884E, + 0xD063, 0x884F, 0xD064, 0x8850, 0xD065, 0x8851, 0xD066, 0x8852, 0xD067, 0x8853, 0xD068, 0x8855, 0xD069, 0x8856, 0xD06A, 0x8858, + 0xD06B, 0x885A, 0xD06C, 0x885B, 0xD06D, 0x885C, 0xD06E, 0x885D, 0xD06F, 0x885E, 0xD070, 0x885F, 0xD071, 0x8860, 0xD072, 0x8866, + 0xD073, 0x8867, 0xD074, 0x886A, 0xD075, 0x886D, 0xD076, 0x886F, 0xD077, 0x8871, 0xD078, 0x8873, 0xD079, 0x8874, 0xD07A, 0x8875, + 0xD07B, 0x8876, 0xD07C, 0x8878, 0xD07D, 0x8879, 0xD07E, 0x887A, 0xD080, 0x887B, 0xD081, 0x887C, 0xD082, 0x8880, 0xD083, 0x8883, + 0xD084, 0x8886, 0xD085, 0x8887, 0xD086, 0x8889, 0xD087, 0x888A, 0xD088, 0x888C, 0xD089, 0x888E, 0xD08A, 0x888F, 0xD08B, 0x8890, + 0xD08C, 0x8891, 0xD08D, 0x8893, 0xD08E, 0x8894, 0xD08F, 0x8895, 0xD090, 0x8897, 0xD091, 0x8898, 0xD092, 0x8899, 0xD093, 0x889A, + 0xD094, 0x889B, 0xD095, 0x889D, 0xD096, 0x889E, 0xD097, 0x889F, 0xD098, 0x88A0, 0xD099, 0x88A1, 0xD09A, 0x88A3, 0xD09B, 0x88A5, + 0xD09C, 0x88A6, 0xD09D, 0x88A7, 0xD09E, 0x88A8, 0xD09F, 0x88A9, 0xD0A0, 0x88AA, 0xD0A1, 0x5C0F, 0xD0A2, 0x5B5D, 0xD0A3, 0x6821, + 0xD0A4, 0x8096, 0xD0A5, 0x5578, 0xD0A6, 0x7B11, 0xD0A7, 0x6548, 0xD0A8, 0x6954, 0xD0A9, 0x4E9B, 0xD0AA, 0x6B47, 0xD0AB, 0x874E, + 0xD0AC, 0x978B, 0xD0AD, 0x534F, 0xD0AE, 0x631F, 0xD0AF, 0x643A, 0xD0B0, 0x90AA, 0xD0B1, 0x659C, 0xD0B2, 0x80C1, 0xD0B3, 0x8C10, + 0xD0B4, 0x5199, 0xD0B5, 0x68B0, 0xD0B6, 0x5378, 0xD0B7, 0x87F9, 0xD0B8, 0x61C8, 0xD0B9, 0x6CC4, 0xD0BA, 0x6CFB, 0xD0BB, 0x8C22, + 0xD0BC, 0x5C51, 0xD0BD, 0x85AA, 0xD0BE, 0x82AF, 0xD0BF, 0x950C, 0xD0C0, 0x6B23, 0xD0C1, 0x8F9B, 0xD0C2, 0x65B0, 0xD0C3, 0x5FFB, + 0xD0C4, 0x5FC3, 0xD0C5, 0x4FE1, 0xD0C6, 0x8845, 0xD0C7, 0x661F, 0xD0C8, 0x8165, 0xD0C9, 0x7329, 0xD0CA, 0x60FA, 0xD0CB, 0x5174, + 0xD0CC, 0x5211, 0xD0CD, 0x578B, 0xD0CE, 0x5F62, 0xD0CF, 0x90A2, 0xD0D0, 0x884C, 0xD0D1, 0x9192, 0xD0D2, 0x5E78, 0xD0D3, 0x674F, + 0xD0D4, 0x6027, 0xD0D5, 0x59D3, 0xD0D6, 0x5144, 0xD0D7, 0x51F6, 0xD0D8, 0x80F8, 0xD0D9, 0x5308, 0xD0DA, 0x6C79, 0xD0DB, 0x96C4, + 0xD0DC, 0x718A, 0xD0DD, 0x4F11, 0xD0DE, 0x4FEE, 0xD0DF, 0x7F9E, 0xD0E0, 0x673D, 0xD0E1, 0x55C5, 0xD0E2, 0x9508, 0xD0E3, 0x79C0, + 0xD0E4, 0x8896, 0xD0E5, 0x7EE3, 0xD0E6, 0x589F, 0xD0E7, 0x620C, 0xD0E8, 0x9700, 0xD0E9, 0x865A, 0xD0EA, 0x5618, 0xD0EB, 0x987B, + 0xD0EC, 0x5F90, 0xD0ED, 0x8BB8, 0xD0EE, 0x84C4, 0xD0EF, 0x9157, 0xD0F0, 0x53D9, 0xD0F1, 0x65ED, 0xD0F2, 0x5E8F, 0xD0F3, 0x755C, + 0xD0F4, 0x6064, 0xD0F5, 0x7D6E, 0xD0F6, 0x5A7F, 0xD0F7, 0x7EEA, 0xD0F8, 0x7EED, 0xD0F9, 0x8F69, 0xD0FA, 0x55A7, 0xD0FB, 0x5BA3, + 0xD0FC, 0x60AC, 0xD0FD, 0x65CB, 0xD0FE, 0x7384, 0xD140, 0x88AC, 0xD141, 0x88AE, 0xD142, 0x88AF, 0xD143, 0x88B0, 0xD144, 0x88B2, + 0xD145, 0x88B3, 0xD146, 0x88B4, 0xD147, 0x88B5, 0xD148, 0x88B6, 0xD149, 0x88B8, 0xD14A, 0x88B9, 0xD14B, 0x88BA, 0xD14C, 0x88BB, + 0xD14D, 0x88BD, 0xD14E, 0x88BE, 0xD14F, 0x88BF, 0xD150, 0x88C0, 0xD151, 0x88C3, 0xD152, 0x88C4, 0xD153, 0x88C7, 0xD154, 0x88C8, + 0xD155, 0x88CA, 0xD156, 0x88CB, 0xD157, 0x88CC, 0xD158, 0x88CD, 0xD159, 0x88CF, 0xD15A, 0x88D0, 0xD15B, 0x88D1, 0xD15C, 0x88D3, + 0xD15D, 0x88D6, 0xD15E, 0x88D7, 0xD15F, 0x88DA, 0xD160, 0x88DB, 0xD161, 0x88DC, 0xD162, 0x88DD, 0xD163, 0x88DE, 0xD164, 0x88E0, + 0xD165, 0x88E1, 0xD166, 0x88E6, 0xD167, 0x88E7, 0xD168, 0x88E9, 0xD169, 0x88EA, 0xD16A, 0x88EB, 0xD16B, 0x88EC, 0xD16C, 0x88ED, + 0xD16D, 0x88EE, 0xD16E, 0x88EF, 0xD16F, 0x88F2, 0xD170, 0x88F5, 0xD171, 0x88F6, 0xD172, 0x88F7, 0xD173, 0x88FA, 0xD174, 0x88FB, + 0xD175, 0x88FD, 0xD176, 0x88FF, 0xD177, 0x8900, 0xD178, 0x8901, 0xD179, 0x8903, 0xD17A, 0x8904, 0xD17B, 0x8905, 0xD17C, 0x8906, + 0xD17D, 0x8907, 0xD17E, 0x8908, 0xD180, 0x8909, 0xD181, 0x890B, 0xD182, 0x890C, 0xD183, 0x890D, 0xD184, 0x890E, 0xD185, 0x890F, + 0xD186, 0x8911, 0xD187, 0x8914, 0xD188, 0x8915, 0xD189, 0x8916, 0xD18A, 0x8917, 0xD18B, 0x8918, 0xD18C, 0x891C, 0xD18D, 0x891D, + 0xD18E, 0x891E, 0xD18F, 0x891F, 0xD190, 0x8920, 0xD191, 0x8922, 0xD192, 0x8923, 0xD193, 0x8924, 0xD194, 0x8926, 0xD195, 0x8927, + 0xD196, 0x8928, 0xD197, 0x8929, 0xD198, 0x892C, 0xD199, 0x892D, 0xD19A, 0x892E, 0xD19B, 0x892F, 0xD19C, 0x8931, 0xD19D, 0x8932, + 0xD19E, 0x8933, 0xD19F, 0x8935, 0xD1A0, 0x8937, 0xD1A1, 0x9009, 0xD1A2, 0x7663, 0xD1A3, 0x7729, 0xD1A4, 0x7EDA, 0xD1A5, 0x9774, + 0xD1A6, 0x859B, 0xD1A7, 0x5B66, 0xD1A8, 0x7A74, 0xD1A9, 0x96EA, 0xD1AA, 0x8840, 0xD1AB, 0x52CB, 0xD1AC, 0x718F, 0xD1AD, 0x5FAA, + 0xD1AE, 0x65EC, 0xD1AF, 0x8BE2, 0xD1B0, 0x5BFB, 0xD1B1, 0x9A6F, 0xD1B2, 0x5DE1, 0xD1B3, 0x6B89, 0xD1B4, 0x6C5B, 0xD1B5, 0x8BAD, + 0xD1B6, 0x8BAF, 0xD1B7, 0x900A, 0xD1B8, 0x8FC5, 0xD1B9, 0x538B, 0xD1BA, 0x62BC, 0xD1BB, 0x9E26, 0xD1BC, 0x9E2D, 0xD1BD, 0x5440, + 0xD1BE, 0x4E2B, 0xD1BF, 0x82BD, 0xD1C0, 0x7259, 0xD1C1, 0x869C, 0xD1C2, 0x5D16, 0xD1C3, 0x8859, 0xD1C4, 0x6DAF, 0xD1C5, 0x96C5, + 0xD1C6, 0x54D1, 0xD1C7, 0x4E9A, 0xD1C8, 0x8BB6, 0xD1C9, 0x7109, 0xD1CA, 0x54BD, 0xD1CB, 0x9609, 0xD1CC, 0x70DF, 0xD1CD, 0x6DF9, + 0xD1CE, 0x76D0, 0xD1CF, 0x4E25, 0xD1D0, 0x7814, 0xD1D1, 0x8712, 0xD1D2, 0x5CA9, 0xD1D3, 0x5EF6, 0xD1D4, 0x8A00, 0xD1D5, 0x989C, + 0xD1D6, 0x960E, 0xD1D7, 0x708E, 0xD1D8, 0x6CBF, 0xD1D9, 0x5944, 0xD1DA, 0x63A9, 0xD1DB, 0x773C, 0xD1DC, 0x884D, 0xD1DD, 0x6F14, + 0xD1DE, 0x8273, 0xD1DF, 0x5830, 0xD1E0, 0x71D5, 0xD1E1, 0x538C, 0xD1E2, 0x781A, 0xD1E3, 0x96C1, 0xD1E4, 0x5501, 0xD1E5, 0x5F66, + 0xD1E6, 0x7130, 0xD1E7, 0x5BB4, 0xD1E8, 0x8C1A, 0xD1E9, 0x9A8C, 0xD1EA, 0x6B83, 0xD1EB, 0x592E, 0xD1EC, 0x9E2F, 0xD1ED, 0x79E7, + 0xD1EE, 0x6768, 0xD1EF, 0x626C, 0xD1F0, 0x4F6F, 0xD1F1, 0x75A1, 0xD1F2, 0x7F8A, 0xD1F3, 0x6D0B, 0xD1F4, 0x9633, 0xD1F5, 0x6C27, + 0xD1F6, 0x4EF0, 0xD1F7, 0x75D2, 0xD1F8, 0x517B, 0xD1F9, 0x6837, 0xD1FA, 0x6F3E, 0xD1FB, 0x9080, 0xD1FC, 0x8170, 0xD1FD, 0x5996, + 0xD1FE, 0x7476, 0xD240, 0x8938, 0xD241, 0x8939, 0xD242, 0x893A, 0xD243, 0x893B, 0xD244, 0x893C, 0xD245, 0x893D, 0xD246, 0x893E, + 0xD247, 0x893F, 0xD248, 0x8940, 0xD249, 0x8942, 0xD24A, 0x8943, 0xD24B, 0x8945, 0xD24C, 0x8946, 0xD24D, 0x8947, 0xD24E, 0x8948, + 0xD24F, 0x8949, 0xD250, 0x894A, 0xD251, 0x894B, 0xD252, 0x894C, 0xD253, 0x894D, 0xD254, 0x894E, 0xD255, 0x894F, 0xD256, 0x8950, + 0xD257, 0x8951, 0xD258, 0x8952, 0xD259, 0x8953, 0xD25A, 0x8954, 0xD25B, 0x8955, 0xD25C, 0x8956, 0xD25D, 0x8957, 0xD25E, 0x8958, + 0xD25F, 0x8959, 0xD260, 0x895A, 0xD261, 0x895B, 0xD262, 0x895C, 0xD263, 0x895D, 0xD264, 0x8960, 0xD265, 0x8961, 0xD266, 0x8962, + 0xD267, 0x8963, 0xD268, 0x8964, 0xD269, 0x8965, 0xD26A, 0x8967, 0xD26B, 0x8968, 0xD26C, 0x8969, 0xD26D, 0x896A, 0xD26E, 0x896B, + 0xD26F, 0x896C, 0xD270, 0x896D, 0xD271, 0x896E, 0xD272, 0x896F, 0xD273, 0x8970, 0xD274, 0x8971, 0xD275, 0x8972, 0xD276, 0x8973, + 0xD277, 0x8974, 0xD278, 0x8975, 0xD279, 0x8976, 0xD27A, 0x8977, 0xD27B, 0x8978, 0xD27C, 0x8979, 0xD27D, 0x897A, 0xD27E, 0x897C, + 0xD280, 0x897D, 0xD281, 0x897E, 0xD282, 0x8980, 0xD283, 0x8982, 0xD284, 0x8984, 0xD285, 0x8985, 0xD286, 0x8987, 0xD287, 0x8988, + 0xD288, 0x8989, 0xD289, 0x898A, 0xD28A, 0x898B, 0xD28B, 0x898C, 0xD28C, 0x898D, 0xD28D, 0x898E, 0xD28E, 0x898F, 0xD28F, 0x8990, + 0xD290, 0x8991, 0xD291, 0x8992, 0xD292, 0x8993, 0xD293, 0x8994, 0xD294, 0x8995, 0xD295, 0x8996, 0xD296, 0x8997, 0xD297, 0x8998, + 0xD298, 0x8999, 0xD299, 0x899A, 0xD29A, 0x899B, 0xD29B, 0x899C, 0xD29C, 0x899D, 0xD29D, 0x899E, 0xD29E, 0x899F, 0xD29F, 0x89A0, + 0xD2A0, 0x89A1, 0xD2A1, 0x6447, 0xD2A2, 0x5C27, 0xD2A3, 0x9065, 0xD2A4, 0x7A91, 0xD2A5, 0x8C23, 0xD2A6, 0x59DA, 0xD2A7, 0x54AC, + 0xD2A8, 0x8200, 0xD2A9, 0x836F, 0xD2AA, 0x8981, 0xD2AB, 0x8000, 0xD2AC, 0x6930, 0xD2AD, 0x564E, 0xD2AE, 0x8036, 0xD2AF, 0x7237, + 0xD2B0, 0x91CE, 0xD2B1, 0x51B6, 0xD2B2, 0x4E5F, 0xD2B3, 0x9875, 0xD2B4, 0x6396, 0xD2B5, 0x4E1A, 0xD2B6, 0x53F6, 0xD2B7, 0x66F3, + 0xD2B8, 0x814B, 0xD2B9, 0x591C, 0xD2BA, 0x6DB2, 0xD2BB, 0x4E00, 0xD2BC, 0x58F9, 0xD2BD, 0x533B, 0xD2BE, 0x63D6, 0xD2BF, 0x94F1, + 0xD2C0, 0x4F9D, 0xD2C1, 0x4F0A, 0xD2C2, 0x8863, 0xD2C3, 0x9890, 0xD2C4, 0x5937, 0xD2C5, 0x9057, 0xD2C6, 0x79FB, 0xD2C7, 0x4EEA, + 0xD2C8, 0x80F0, 0xD2C9, 0x7591, 0xD2CA, 0x6C82, 0xD2CB, 0x5B9C, 0xD2CC, 0x59E8, 0xD2CD, 0x5F5D, 0xD2CE, 0x6905, 0xD2CF, 0x8681, + 0xD2D0, 0x501A, 0xD2D1, 0x5DF2, 0xD2D2, 0x4E59, 0xD2D3, 0x77E3, 0xD2D4, 0x4EE5, 0xD2D5, 0x827A, 0xD2D6, 0x6291, 0xD2D7, 0x6613, + 0xD2D8, 0x9091, 0xD2D9, 0x5C79, 0xD2DA, 0x4EBF, 0xD2DB, 0x5F79, 0xD2DC, 0x81C6, 0xD2DD, 0x9038, 0xD2DE, 0x8084, 0xD2DF, 0x75AB, + 0xD2E0, 0x4EA6, 0xD2E1, 0x88D4, 0xD2E2, 0x610F, 0xD2E3, 0x6BC5, 0xD2E4, 0x5FC6, 0xD2E5, 0x4E49, 0xD2E6, 0x76CA, 0xD2E7, 0x6EA2, + 0xD2E8, 0x8BE3, 0xD2E9, 0x8BAE, 0xD2EA, 0x8C0A, 0xD2EB, 0x8BD1, 0xD2EC, 0x5F02, 0xD2ED, 0x7FFC, 0xD2EE, 0x7FCC, 0xD2EF, 0x7ECE, + 0xD2F0, 0x8335, 0xD2F1, 0x836B, 0xD2F2, 0x56E0, 0xD2F3, 0x6BB7, 0xD2F4, 0x97F3, 0xD2F5, 0x9634, 0xD2F6, 0x59FB, 0xD2F7, 0x541F, + 0xD2F8, 0x94F6, 0xD2F9, 0x6DEB, 0xD2FA, 0x5BC5, 0xD2FB, 0x996E, 0xD2FC, 0x5C39, 0xD2FD, 0x5F15, 0xD2FE, 0x9690, 0xD340, 0x89A2, + 0xD341, 0x89A3, 0xD342, 0x89A4, 0xD343, 0x89A5, 0xD344, 0x89A6, 0xD345, 0x89A7, 0xD346, 0x89A8, 0xD347, 0x89A9, 0xD348, 0x89AA, + 0xD349, 0x89AB, 0xD34A, 0x89AC, 0xD34B, 0x89AD, 0xD34C, 0x89AE, 0xD34D, 0x89AF, 0xD34E, 0x89B0, 0xD34F, 0x89B1, 0xD350, 0x89B2, + 0xD351, 0x89B3, 0xD352, 0x89B4, 0xD353, 0x89B5, 0xD354, 0x89B6, 0xD355, 0x89B7, 0xD356, 0x89B8, 0xD357, 0x89B9, 0xD358, 0x89BA, + 0xD359, 0x89BB, 0xD35A, 0x89BC, 0xD35B, 0x89BD, 0xD35C, 0x89BE, 0xD35D, 0x89BF, 0xD35E, 0x89C0, 0xD35F, 0x89C3, 0xD360, 0x89CD, + 0xD361, 0x89D3, 0xD362, 0x89D4, 0xD363, 0x89D5, 0xD364, 0x89D7, 0xD365, 0x89D8, 0xD366, 0x89D9, 0xD367, 0x89DB, 0xD368, 0x89DD, + 0xD369, 0x89DF, 0xD36A, 0x89E0, 0xD36B, 0x89E1, 0xD36C, 0x89E2, 0xD36D, 0x89E4, 0xD36E, 0x89E7, 0xD36F, 0x89E8, 0xD370, 0x89E9, + 0xD371, 0x89EA, 0xD372, 0x89EC, 0xD373, 0x89ED, 0xD374, 0x89EE, 0xD375, 0x89F0, 0xD376, 0x89F1, 0xD377, 0x89F2, 0xD378, 0x89F4, + 0xD379, 0x89F5, 0xD37A, 0x89F6, 0xD37B, 0x89F7, 0xD37C, 0x89F8, 0xD37D, 0x89F9, 0xD37E, 0x89FA, 0xD380, 0x89FB, 0xD381, 0x89FC, + 0xD382, 0x89FD, 0xD383, 0x89FE, 0xD384, 0x89FF, 0xD385, 0x8A01, 0xD386, 0x8A02, 0xD387, 0x8A03, 0xD388, 0x8A04, 0xD389, 0x8A05, + 0xD38A, 0x8A06, 0xD38B, 0x8A08, 0xD38C, 0x8A09, 0xD38D, 0x8A0A, 0xD38E, 0x8A0B, 0xD38F, 0x8A0C, 0xD390, 0x8A0D, 0xD391, 0x8A0E, + 0xD392, 0x8A0F, 0xD393, 0x8A10, 0xD394, 0x8A11, 0xD395, 0x8A12, 0xD396, 0x8A13, 0xD397, 0x8A14, 0xD398, 0x8A15, 0xD399, 0x8A16, + 0xD39A, 0x8A17, 0xD39B, 0x8A18, 0xD39C, 0x8A19, 0xD39D, 0x8A1A, 0xD39E, 0x8A1B, 0xD39F, 0x8A1C, 0xD3A0, 0x8A1D, 0xD3A1, 0x5370, + 0xD3A2, 0x82F1, 0xD3A3, 0x6A31, 0xD3A4, 0x5A74, 0xD3A5, 0x9E70, 0xD3A6, 0x5E94, 0xD3A7, 0x7F28, 0xD3A8, 0x83B9, 0xD3A9, 0x8424, + 0xD3AA, 0x8425, 0xD3AB, 0x8367, 0xD3AC, 0x8747, 0xD3AD, 0x8FCE, 0xD3AE, 0x8D62, 0xD3AF, 0x76C8, 0xD3B0, 0x5F71, 0xD3B1, 0x9896, + 0xD3B2, 0x786C, 0xD3B3, 0x6620, 0xD3B4, 0x54DF, 0xD3B5, 0x62E5, 0xD3B6, 0x4F63, 0xD3B7, 0x81C3, 0xD3B8, 0x75C8, 0xD3B9, 0x5EB8, + 0xD3BA, 0x96CD, 0xD3BB, 0x8E0A, 0xD3BC, 0x86F9, 0xD3BD, 0x548F, 0xD3BE, 0x6CF3, 0xD3BF, 0x6D8C, 0xD3C0, 0x6C38, 0xD3C1, 0x607F, + 0xD3C2, 0x52C7, 0xD3C3, 0x7528, 0xD3C4, 0x5E7D, 0xD3C5, 0x4F18, 0xD3C6, 0x60A0, 0xD3C7, 0x5FE7, 0xD3C8, 0x5C24, 0xD3C9, 0x7531, + 0xD3CA, 0x90AE, 0xD3CB, 0x94C0, 0xD3CC, 0x72B9, 0xD3CD, 0x6CB9, 0xD3CE, 0x6E38, 0xD3CF, 0x9149, 0xD3D0, 0x6709, 0xD3D1, 0x53CB, + 0xD3D2, 0x53F3, 0xD3D3, 0x4F51, 0xD3D4, 0x91C9, 0xD3D5, 0x8BF1, 0xD3D6, 0x53C8, 0xD3D7, 0x5E7C, 0xD3D8, 0x8FC2, 0xD3D9, 0x6DE4, + 0xD3DA, 0x4E8E, 0xD3DB, 0x76C2, 0xD3DC, 0x6986, 0xD3DD, 0x865E, 0xD3DE, 0x611A, 0xD3DF, 0x8206, 0xD3E0, 0x4F59, 0xD3E1, 0x4FDE, + 0xD3E2, 0x903E, 0xD3E3, 0x9C7C, 0xD3E4, 0x6109, 0xD3E5, 0x6E1D, 0xD3E6, 0x6E14, 0xD3E7, 0x9685, 0xD3E8, 0x4E88, 0xD3E9, 0x5A31, + 0xD3EA, 0x96E8, 0xD3EB, 0x4E0E, 0xD3EC, 0x5C7F, 0xD3ED, 0x79B9, 0xD3EE, 0x5B87, 0xD3EF, 0x8BED, 0xD3F0, 0x7FBD, 0xD3F1, 0x7389, + 0xD3F2, 0x57DF, 0xD3F3, 0x828B, 0xD3F4, 0x90C1, 0xD3F5, 0x5401, 0xD3F6, 0x9047, 0xD3F7, 0x55BB, 0xD3F8, 0x5CEA, 0xD3F9, 0x5FA1, + 0xD3FA, 0x6108, 0xD3FB, 0x6B32, 0xD3FC, 0x72F1, 0xD3FD, 0x80B2, 0xD3FE, 0x8A89, 0xD440, 0x8A1E, 0xD441, 0x8A1F, 0xD442, 0x8A20, + 0xD443, 0x8A21, 0xD444, 0x8A22, 0xD445, 0x8A23, 0xD446, 0x8A24, 0xD447, 0x8A25, 0xD448, 0x8A26, 0xD449, 0x8A27, 0xD44A, 0x8A28, + 0xD44B, 0x8A29, 0xD44C, 0x8A2A, 0xD44D, 0x8A2B, 0xD44E, 0x8A2C, 0xD44F, 0x8A2D, 0xD450, 0x8A2E, 0xD451, 0x8A2F, 0xD452, 0x8A30, + 0xD453, 0x8A31, 0xD454, 0x8A32, 0xD455, 0x8A33, 0xD456, 0x8A34, 0xD457, 0x8A35, 0xD458, 0x8A36, 0xD459, 0x8A37, 0xD45A, 0x8A38, + 0xD45B, 0x8A39, 0xD45C, 0x8A3A, 0xD45D, 0x8A3B, 0xD45E, 0x8A3C, 0xD45F, 0x8A3D, 0xD460, 0x8A3F, 0xD461, 0x8A40, 0xD462, 0x8A41, + 0xD463, 0x8A42, 0xD464, 0x8A43, 0xD465, 0x8A44, 0xD466, 0x8A45, 0xD467, 0x8A46, 0xD468, 0x8A47, 0xD469, 0x8A49, 0xD46A, 0x8A4A, + 0xD46B, 0x8A4B, 0xD46C, 0x8A4C, 0xD46D, 0x8A4D, 0xD46E, 0x8A4E, 0xD46F, 0x8A4F, 0xD470, 0x8A50, 0xD471, 0x8A51, 0xD472, 0x8A52, + 0xD473, 0x8A53, 0xD474, 0x8A54, 0xD475, 0x8A55, 0xD476, 0x8A56, 0xD477, 0x8A57, 0xD478, 0x8A58, 0xD479, 0x8A59, 0xD47A, 0x8A5A, + 0xD47B, 0x8A5B, 0xD47C, 0x8A5C, 0xD47D, 0x8A5D, 0xD47E, 0x8A5E, 0xD480, 0x8A5F, 0xD481, 0x8A60, 0xD482, 0x8A61, 0xD483, 0x8A62, + 0xD484, 0x8A63, 0xD485, 0x8A64, 0xD486, 0x8A65, 0xD487, 0x8A66, 0xD488, 0x8A67, 0xD489, 0x8A68, 0xD48A, 0x8A69, 0xD48B, 0x8A6A, + 0xD48C, 0x8A6B, 0xD48D, 0x8A6C, 0xD48E, 0x8A6D, 0xD48F, 0x8A6E, 0xD490, 0x8A6F, 0xD491, 0x8A70, 0xD492, 0x8A71, 0xD493, 0x8A72, + 0xD494, 0x8A73, 0xD495, 0x8A74, 0xD496, 0x8A75, 0xD497, 0x8A76, 0xD498, 0x8A77, 0xD499, 0x8A78, 0xD49A, 0x8A7A, 0xD49B, 0x8A7B, + 0xD49C, 0x8A7C, 0xD49D, 0x8A7D, 0xD49E, 0x8A7E, 0xD49F, 0x8A7F, 0xD4A0, 0x8A80, 0xD4A1, 0x6D74, 0xD4A2, 0x5BD3, 0xD4A3, 0x88D5, + 0xD4A4, 0x9884, 0xD4A5, 0x8C6B, 0xD4A6, 0x9A6D, 0xD4A7, 0x9E33, 0xD4A8, 0x6E0A, 0xD4A9, 0x51A4, 0xD4AA, 0x5143, 0xD4AB, 0x57A3, + 0xD4AC, 0x8881, 0xD4AD, 0x539F, 0xD4AE, 0x63F4, 0xD4AF, 0x8F95, 0xD4B0, 0x56ED, 0xD4B1, 0x5458, 0xD4B2, 0x5706, 0xD4B3, 0x733F, + 0xD4B4, 0x6E90, 0xD4B5, 0x7F18, 0xD4B6, 0x8FDC, 0xD4B7, 0x82D1, 0xD4B8, 0x613F, 0xD4B9, 0x6028, 0xD4BA, 0x9662, 0xD4BB, 0x66F0, + 0xD4BC, 0x7EA6, 0xD4BD, 0x8D8A, 0xD4BE, 0x8DC3, 0xD4BF, 0x94A5, 0xD4C0, 0x5CB3, 0xD4C1, 0x7CA4, 0xD4C2, 0x6708, 0xD4C3, 0x60A6, + 0xD4C4, 0x9605, 0xD4C5, 0x8018, 0xD4C6, 0x4E91, 0xD4C7, 0x90E7, 0xD4C8, 0x5300, 0xD4C9, 0x9668, 0xD4CA, 0x5141, 0xD4CB, 0x8FD0, + 0xD4CC, 0x8574, 0xD4CD, 0x915D, 0xD4CE, 0x6655, 0xD4CF, 0x97F5, 0xD4D0, 0x5B55, 0xD4D1, 0x531D, 0xD4D2, 0x7838, 0xD4D3, 0x6742, + 0xD4D4, 0x683D, 0xD4D5, 0x54C9, 0xD4D6, 0x707E, 0xD4D7, 0x5BB0, 0xD4D8, 0x8F7D, 0xD4D9, 0x518D, 0xD4DA, 0x5728, 0xD4DB, 0x54B1, + 0xD4DC, 0x6512, 0xD4DD, 0x6682, 0xD4DE, 0x8D5E, 0xD4DF, 0x8D43, 0xD4E0, 0x810F, 0xD4E1, 0x846C, 0xD4E2, 0x906D, 0xD4E3, 0x7CDF, + 0xD4E4, 0x51FF, 0xD4E5, 0x85FB, 0xD4E6, 0x67A3, 0xD4E7, 0x65E9, 0xD4E8, 0x6FA1, 0xD4E9, 0x86A4, 0xD4EA, 0x8E81, 0xD4EB, 0x566A, + 0xD4EC, 0x9020, 0xD4ED, 0x7682, 0xD4EE, 0x7076, 0xD4EF, 0x71E5, 0xD4F0, 0x8D23, 0xD4F1, 0x62E9, 0xD4F2, 0x5219, 0xD4F3, 0x6CFD, + 0xD4F4, 0x8D3C, 0xD4F5, 0x600E, 0xD4F6, 0x589E, 0xD4F7, 0x618E, 0xD4F8, 0x66FE, 0xD4F9, 0x8D60, 0xD4FA, 0x624E, 0xD4FB, 0x55B3, + 0xD4FC, 0x6E23, 0xD4FD, 0x672D, 0xD4FE, 0x8F67, 0xD540, 0x8A81, 0xD541, 0x8A82, 0xD542, 0x8A83, 0xD543, 0x8A84, 0xD544, 0x8A85, + 0xD545, 0x8A86, 0xD546, 0x8A87, 0xD547, 0x8A88, 0xD548, 0x8A8B, 0xD549, 0x8A8C, 0xD54A, 0x8A8D, 0xD54B, 0x8A8E, 0xD54C, 0x8A8F, + 0xD54D, 0x8A90, 0xD54E, 0x8A91, 0xD54F, 0x8A92, 0xD550, 0x8A94, 0xD551, 0x8A95, 0xD552, 0x8A96, 0xD553, 0x8A97, 0xD554, 0x8A98, + 0xD555, 0x8A99, 0xD556, 0x8A9A, 0xD557, 0x8A9B, 0xD558, 0x8A9C, 0xD559, 0x8A9D, 0xD55A, 0x8A9E, 0xD55B, 0x8A9F, 0xD55C, 0x8AA0, + 0xD55D, 0x8AA1, 0xD55E, 0x8AA2, 0xD55F, 0x8AA3, 0xD560, 0x8AA4, 0xD561, 0x8AA5, 0xD562, 0x8AA6, 0xD563, 0x8AA7, 0xD564, 0x8AA8, + 0xD565, 0x8AA9, 0xD566, 0x8AAA, 0xD567, 0x8AAB, 0xD568, 0x8AAC, 0xD569, 0x8AAD, 0xD56A, 0x8AAE, 0xD56B, 0x8AAF, 0xD56C, 0x8AB0, + 0xD56D, 0x8AB1, 0xD56E, 0x8AB2, 0xD56F, 0x8AB3, 0xD570, 0x8AB4, 0xD571, 0x8AB5, 0xD572, 0x8AB6, 0xD573, 0x8AB7, 0xD574, 0x8AB8, + 0xD575, 0x8AB9, 0xD576, 0x8ABA, 0xD577, 0x8ABB, 0xD578, 0x8ABC, 0xD579, 0x8ABD, 0xD57A, 0x8ABE, 0xD57B, 0x8ABF, 0xD57C, 0x8AC0, + 0xD57D, 0x8AC1, 0xD57E, 0x8AC2, 0xD580, 0x8AC3, 0xD581, 0x8AC4, 0xD582, 0x8AC5, 0xD583, 0x8AC6, 0xD584, 0x8AC7, 0xD585, 0x8AC8, + 0xD586, 0x8AC9, 0xD587, 0x8ACA, 0xD588, 0x8ACB, 0xD589, 0x8ACC, 0xD58A, 0x8ACD, 0xD58B, 0x8ACE, 0xD58C, 0x8ACF, 0xD58D, 0x8AD0, + 0xD58E, 0x8AD1, 0xD58F, 0x8AD2, 0xD590, 0x8AD3, 0xD591, 0x8AD4, 0xD592, 0x8AD5, 0xD593, 0x8AD6, 0xD594, 0x8AD7, 0xD595, 0x8AD8, + 0xD596, 0x8AD9, 0xD597, 0x8ADA, 0xD598, 0x8ADB, 0xD599, 0x8ADC, 0xD59A, 0x8ADD, 0xD59B, 0x8ADE, 0xD59C, 0x8ADF, 0xD59D, 0x8AE0, + 0xD59E, 0x8AE1, 0xD59F, 0x8AE2, 0xD5A0, 0x8AE3, 0xD5A1, 0x94E1, 0xD5A2, 0x95F8, 0xD5A3, 0x7728, 0xD5A4, 0x6805, 0xD5A5, 0x69A8, + 0xD5A6, 0x548B, 0xD5A7, 0x4E4D, 0xD5A8, 0x70B8, 0xD5A9, 0x8BC8, 0xD5AA, 0x6458, 0xD5AB, 0x658B, 0xD5AC, 0x5B85, 0xD5AD, 0x7A84, + 0xD5AE, 0x503A, 0xD5AF, 0x5BE8, 0xD5B0, 0x77BB, 0xD5B1, 0x6BE1, 0xD5B2, 0x8A79, 0xD5B3, 0x7C98, 0xD5B4, 0x6CBE, 0xD5B5, 0x76CF, + 0xD5B6, 0x65A9, 0xD5B7, 0x8F97, 0xD5B8, 0x5D2D, 0xD5B9, 0x5C55, 0xD5BA, 0x8638, 0xD5BB, 0x6808, 0xD5BC, 0x5360, 0xD5BD, 0x6218, + 0xD5BE, 0x7AD9, 0xD5BF, 0x6E5B, 0xD5C0, 0x7EFD, 0xD5C1, 0x6A1F, 0xD5C2, 0x7AE0, 0xD5C3, 0x5F70, 0xD5C4, 0x6F33, 0xD5C5, 0x5F20, + 0xD5C6, 0x638C, 0xD5C7, 0x6DA8, 0xD5C8, 0x6756, 0xD5C9, 0x4E08, 0xD5CA, 0x5E10, 0xD5CB, 0x8D26, 0xD5CC, 0x4ED7, 0xD5CD, 0x80C0, + 0xD5CE, 0x7634, 0xD5CF, 0x969C, 0xD5D0, 0x62DB, 0xD5D1, 0x662D, 0xD5D2, 0x627E, 0xD5D3, 0x6CBC, 0xD5D4, 0x8D75, 0xD5D5, 0x7167, + 0xD5D6, 0x7F69, 0xD5D7, 0x5146, 0xD5D8, 0x8087, 0xD5D9, 0x53EC, 0xD5DA, 0x906E, 0xD5DB, 0x6298, 0xD5DC, 0x54F2, 0xD5DD, 0x86F0, + 0xD5DE, 0x8F99, 0xD5DF, 0x8005, 0xD5E0, 0x9517, 0xD5E1, 0x8517, 0xD5E2, 0x8FD9, 0xD5E3, 0x6D59, 0xD5E4, 0x73CD, 0xD5E5, 0x659F, + 0xD5E6, 0x771F, 0xD5E7, 0x7504, 0xD5E8, 0x7827, 0xD5E9, 0x81FB, 0xD5EA, 0x8D1E, 0xD5EB, 0x9488, 0xD5EC, 0x4FA6, 0xD5ED, 0x6795, + 0xD5EE, 0x75B9, 0xD5EF, 0x8BCA, 0xD5F0, 0x9707, 0xD5F1, 0x632F, 0xD5F2, 0x9547, 0xD5F3, 0x9635, 0xD5F4, 0x84B8, 0xD5F5, 0x6323, + 0xD5F6, 0x7741, 0xD5F7, 0x5F81, 0xD5F8, 0x72F0, 0xD5F9, 0x4E89, 0xD5FA, 0x6014, 0xD5FB, 0x6574, 0xD5FC, 0x62EF, 0xD5FD, 0x6B63, + 0xD5FE, 0x653F, 0xD640, 0x8AE4, 0xD641, 0x8AE5, 0xD642, 0x8AE6, 0xD643, 0x8AE7, 0xD644, 0x8AE8, 0xD645, 0x8AE9, 0xD646, 0x8AEA, + 0xD647, 0x8AEB, 0xD648, 0x8AEC, 0xD649, 0x8AED, 0xD64A, 0x8AEE, 0xD64B, 0x8AEF, 0xD64C, 0x8AF0, 0xD64D, 0x8AF1, 0xD64E, 0x8AF2, + 0xD64F, 0x8AF3, 0xD650, 0x8AF4, 0xD651, 0x8AF5, 0xD652, 0x8AF6, 0xD653, 0x8AF7, 0xD654, 0x8AF8, 0xD655, 0x8AF9, 0xD656, 0x8AFA, + 0xD657, 0x8AFB, 0xD658, 0x8AFC, 0xD659, 0x8AFD, 0xD65A, 0x8AFE, 0xD65B, 0x8AFF, 0xD65C, 0x8B00, 0xD65D, 0x8B01, 0xD65E, 0x8B02, + 0xD65F, 0x8B03, 0xD660, 0x8B04, 0xD661, 0x8B05, 0xD662, 0x8B06, 0xD663, 0x8B08, 0xD664, 0x8B09, 0xD665, 0x8B0A, 0xD666, 0x8B0B, + 0xD667, 0x8B0C, 0xD668, 0x8B0D, 0xD669, 0x8B0E, 0xD66A, 0x8B0F, 0xD66B, 0x8B10, 0xD66C, 0x8B11, 0xD66D, 0x8B12, 0xD66E, 0x8B13, + 0xD66F, 0x8B14, 0xD670, 0x8B15, 0xD671, 0x8B16, 0xD672, 0x8B17, 0xD673, 0x8B18, 0xD674, 0x8B19, 0xD675, 0x8B1A, 0xD676, 0x8B1B, + 0xD677, 0x8B1C, 0xD678, 0x8B1D, 0xD679, 0x8B1E, 0xD67A, 0x8B1F, 0xD67B, 0x8B20, 0xD67C, 0x8B21, 0xD67D, 0x8B22, 0xD67E, 0x8B23, + 0xD680, 0x8B24, 0xD681, 0x8B25, 0xD682, 0x8B27, 0xD683, 0x8B28, 0xD684, 0x8B29, 0xD685, 0x8B2A, 0xD686, 0x8B2B, 0xD687, 0x8B2C, + 0xD688, 0x8B2D, 0xD689, 0x8B2E, 0xD68A, 0x8B2F, 0xD68B, 0x8B30, 0xD68C, 0x8B31, 0xD68D, 0x8B32, 0xD68E, 0x8B33, 0xD68F, 0x8B34, + 0xD690, 0x8B35, 0xD691, 0x8B36, 0xD692, 0x8B37, 0xD693, 0x8B38, 0xD694, 0x8B39, 0xD695, 0x8B3A, 0xD696, 0x8B3B, 0xD697, 0x8B3C, + 0xD698, 0x8B3D, 0xD699, 0x8B3E, 0xD69A, 0x8B3F, 0xD69B, 0x8B40, 0xD69C, 0x8B41, 0xD69D, 0x8B42, 0xD69E, 0x8B43, 0xD69F, 0x8B44, + 0xD6A0, 0x8B45, 0xD6A1, 0x5E27, 0xD6A2, 0x75C7, 0xD6A3, 0x90D1, 0xD6A4, 0x8BC1, 0xD6A5, 0x829D, 0xD6A6, 0x679D, 0xD6A7, 0x652F, + 0xD6A8, 0x5431, 0xD6A9, 0x8718, 0xD6AA, 0x77E5, 0xD6AB, 0x80A2, 0xD6AC, 0x8102, 0xD6AD, 0x6C41, 0xD6AE, 0x4E4B, 0xD6AF, 0x7EC7, + 0xD6B0, 0x804C, 0xD6B1, 0x76F4, 0xD6B2, 0x690D, 0xD6B3, 0x6B96, 0xD6B4, 0x6267, 0xD6B5, 0x503C, 0xD6B6, 0x4F84, 0xD6B7, 0x5740, + 0xD6B8, 0x6307, 0xD6B9, 0x6B62, 0xD6BA, 0x8DBE, 0xD6BB, 0x53EA, 0xD6BC, 0x65E8, 0xD6BD, 0x7EB8, 0xD6BE, 0x5FD7, 0xD6BF, 0x631A, + 0xD6C0, 0x63B7, 0xD6C1, 0x81F3, 0xD6C2, 0x81F4, 0xD6C3, 0x7F6E, 0xD6C4, 0x5E1C, 0xD6C5, 0x5CD9, 0xD6C6, 0x5236, 0xD6C7, 0x667A, + 0xD6C8, 0x79E9, 0xD6C9, 0x7A1A, 0xD6CA, 0x8D28, 0xD6CB, 0x7099, 0xD6CC, 0x75D4, 0xD6CD, 0x6EDE, 0xD6CE, 0x6CBB, 0xD6CF, 0x7A92, + 0xD6D0, 0x4E2D, 0xD6D1, 0x76C5, 0xD6D2, 0x5FE0, 0xD6D3, 0x949F, 0xD6D4, 0x8877, 0xD6D5, 0x7EC8, 0xD6D6, 0x79CD, 0xD6D7, 0x80BF, + 0xD6D8, 0x91CD, 0xD6D9, 0x4EF2, 0xD6DA, 0x4F17, 0xD6DB, 0x821F, 0xD6DC, 0x5468, 0xD6DD, 0x5DDE, 0xD6DE, 0x6D32, 0xD6DF, 0x8BCC, + 0xD6E0, 0x7CA5, 0xD6E1, 0x8F74, 0xD6E2, 0x8098, 0xD6E3, 0x5E1A, 0xD6E4, 0x5492, 0xD6E5, 0x76B1, 0xD6E6, 0x5B99, 0xD6E7, 0x663C, + 0xD6E8, 0x9AA4, 0xD6E9, 0x73E0, 0xD6EA, 0x682A, 0xD6EB, 0x86DB, 0xD6EC, 0x6731, 0xD6ED, 0x732A, 0xD6EE, 0x8BF8, 0xD6EF, 0x8BDB, + 0xD6F0, 0x9010, 0xD6F1, 0x7AF9, 0xD6F2, 0x70DB, 0xD6F3, 0x716E, 0xD6F4, 0x62C4, 0xD6F5, 0x77A9, 0xD6F6, 0x5631, 0xD6F7, 0x4E3B, + 0xD6F8, 0x8457, 0xD6F9, 0x67F1, 0xD6FA, 0x52A9, 0xD6FB, 0x86C0, 0xD6FC, 0x8D2E, 0xD6FD, 0x94F8, 0xD6FE, 0x7B51, 0xD740, 0x8B46, + 0xD741, 0x8B47, 0xD742, 0x8B48, 0xD743, 0x8B49, 0xD744, 0x8B4A, 0xD745, 0x8B4B, 0xD746, 0x8B4C, 0xD747, 0x8B4D, 0xD748, 0x8B4E, + 0xD749, 0x8B4F, 0xD74A, 0x8B50, 0xD74B, 0x8B51, 0xD74C, 0x8B52, 0xD74D, 0x8B53, 0xD74E, 0x8B54, 0xD74F, 0x8B55, 0xD750, 0x8B56, + 0xD751, 0x8B57, 0xD752, 0x8B58, 0xD753, 0x8B59, 0xD754, 0x8B5A, 0xD755, 0x8B5B, 0xD756, 0x8B5C, 0xD757, 0x8B5D, 0xD758, 0x8B5E, + 0xD759, 0x8B5F, 0xD75A, 0x8B60, 0xD75B, 0x8B61, 0xD75C, 0x8B62, 0xD75D, 0x8B63, 0xD75E, 0x8B64, 0xD75F, 0x8B65, 0xD760, 0x8B67, + 0xD761, 0x8B68, 0xD762, 0x8B69, 0xD763, 0x8B6A, 0xD764, 0x8B6B, 0xD765, 0x8B6D, 0xD766, 0x8B6E, 0xD767, 0x8B6F, 0xD768, 0x8B70, + 0xD769, 0x8B71, 0xD76A, 0x8B72, 0xD76B, 0x8B73, 0xD76C, 0x8B74, 0xD76D, 0x8B75, 0xD76E, 0x8B76, 0xD76F, 0x8B77, 0xD770, 0x8B78, + 0xD771, 0x8B79, 0xD772, 0x8B7A, 0xD773, 0x8B7B, 0xD774, 0x8B7C, 0xD775, 0x8B7D, 0xD776, 0x8B7E, 0xD777, 0x8B7F, 0xD778, 0x8B80, + 0xD779, 0x8B81, 0xD77A, 0x8B82, 0xD77B, 0x8B83, 0xD77C, 0x8B84, 0xD77D, 0x8B85, 0xD77E, 0x8B86, 0xD780, 0x8B87, 0xD781, 0x8B88, + 0xD782, 0x8B89, 0xD783, 0x8B8A, 0xD784, 0x8B8B, 0xD785, 0x8B8C, 0xD786, 0x8B8D, 0xD787, 0x8B8E, 0xD788, 0x8B8F, 0xD789, 0x8B90, + 0xD78A, 0x8B91, 0xD78B, 0x8B92, 0xD78C, 0x8B93, 0xD78D, 0x8B94, 0xD78E, 0x8B95, 0xD78F, 0x8B96, 0xD790, 0x8B97, 0xD791, 0x8B98, + 0xD792, 0x8B99, 0xD793, 0x8B9A, 0xD794, 0x8B9B, 0xD795, 0x8B9C, 0xD796, 0x8B9D, 0xD797, 0x8B9E, 0xD798, 0x8B9F, 0xD799, 0x8BAC, + 0xD79A, 0x8BB1, 0xD79B, 0x8BBB, 0xD79C, 0x8BC7, 0xD79D, 0x8BD0, 0xD79E, 0x8BEA, 0xD79F, 0x8C09, 0xD7A0, 0x8C1E, 0xD7A1, 0x4F4F, + 0xD7A2, 0x6CE8, 0xD7A3, 0x795D, 0xD7A4, 0x9A7B, 0xD7A5, 0x6293, 0xD7A6, 0x722A, 0xD7A7, 0x62FD, 0xD7A8, 0x4E13, 0xD7A9, 0x7816, + 0xD7AA, 0x8F6C, 0xD7AB, 0x64B0, 0xD7AC, 0x8D5A, 0xD7AD, 0x7BC6, 0xD7AE, 0x6869, 0xD7AF, 0x5E84, 0xD7B0, 0x88C5, 0xD7B1, 0x5986, + 0xD7B2, 0x649E, 0xD7B3, 0x58EE, 0xD7B4, 0x72B6, 0xD7B5, 0x690E, 0xD7B6, 0x9525, 0xD7B7, 0x8FFD, 0xD7B8, 0x8D58, 0xD7B9, 0x5760, + 0xD7BA, 0x7F00, 0xD7BB, 0x8C06, 0xD7BC, 0x51C6, 0xD7BD, 0x6349, 0xD7BE, 0x62D9, 0xD7BF, 0x5353, 0xD7C0, 0x684C, 0xD7C1, 0x7422, + 0xD7C2, 0x8301, 0xD7C3, 0x914C, 0xD7C4, 0x5544, 0xD7C5, 0x7740, 0xD7C6, 0x707C, 0xD7C7, 0x6D4A, 0xD7C8, 0x5179, 0xD7C9, 0x54A8, + 0xD7CA, 0x8D44, 0xD7CB, 0x59FF, 0xD7CC, 0x6ECB, 0xD7CD, 0x6DC4, 0xD7CE, 0x5B5C, 0xD7CF, 0x7D2B, 0xD7D0, 0x4ED4, 0xD7D1, 0x7C7D, + 0xD7D2, 0x6ED3, 0xD7D3, 0x5B50, 0xD7D4, 0x81EA, 0xD7D5, 0x6E0D, 0xD7D6, 0x5B57, 0xD7D7, 0x9B03, 0xD7D8, 0x68D5, 0xD7D9, 0x8E2A, + 0xD7DA, 0x5B97, 0xD7DB, 0x7EFC, 0xD7DC, 0x603B, 0xD7DD, 0x7EB5, 0xD7DE, 0x90B9, 0xD7DF, 0x8D70, 0xD7E0, 0x594F, 0xD7E1, 0x63CD, + 0xD7E2, 0x79DF, 0xD7E3, 0x8DB3, 0xD7E4, 0x5352, 0xD7E5, 0x65CF, 0xD7E6, 0x7956, 0xD7E7, 0x8BC5, 0xD7E8, 0x963B, 0xD7E9, 0x7EC4, + 0xD7EA, 0x94BB, 0xD7EB, 0x7E82, 0xD7EC, 0x5634, 0xD7ED, 0x9189, 0xD7EE, 0x6700, 0xD7EF, 0x7F6A, 0xD7F0, 0x5C0A, 0xD7F1, 0x9075, + 0xD7F2, 0x6628, 0xD7F3, 0x5DE6, 0xD7F4, 0x4F50, 0xD7F5, 0x67DE, 0xD7F6, 0x505A, 0xD7F7, 0x4F5C, 0xD7F8, 0x5750, 0xD7F9, 0x5EA7, + 0xD840, 0x8C38, 0xD841, 0x8C39, 0xD842, 0x8C3A, 0xD843, 0x8C3B, 0xD844, 0x8C3C, 0xD845, 0x8C3D, 0xD846, 0x8C3E, 0xD847, 0x8C3F, + 0xD848, 0x8C40, 0xD849, 0x8C42, 0xD84A, 0x8C43, 0xD84B, 0x8C44, 0xD84C, 0x8C45, 0xD84D, 0x8C48, 0xD84E, 0x8C4A, 0xD84F, 0x8C4B, + 0xD850, 0x8C4D, 0xD851, 0x8C4E, 0xD852, 0x8C4F, 0xD853, 0x8C50, 0xD854, 0x8C51, 0xD855, 0x8C52, 0xD856, 0x8C53, 0xD857, 0x8C54, + 0xD858, 0x8C56, 0xD859, 0x8C57, 0xD85A, 0x8C58, 0xD85B, 0x8C59, 0xD85C, 0x8C5B, 0xD85D, 0x8C5C, 0xD85E, 0x8C5D, 0xD85F, 0x8C5E, + 0xD860, 0x8C5F, 0xD861, 0x8C60, 0xD862, 0x8C63, 0xD863, 0x8C64, 0xD864, 0x8C65, 0xD865, 0x8C66, 0xD866, 0x8C67, 0xD867, 0x8C68, + 0xD868, 0x8C69, 0xD869, 0x8C6C, 0xD86A, 0x8C6D, 0xD86B, 0x8C6E, 0xD86C, 0x8C6F, 0xD86D, 0x8C70, 0xD86E, 0x8C71, 0xD86F, 0x8C72, + 0xD870, 0x8C74, 0xD871, 0x8C75, 0xD872, 0x8C76, 0xD873, 0x8C77, 0xD874, 0x8C7B, 0xD875, 0x8C7C, 0xD876, 0x8C7D, 0xD877, 0x8C7E, + 0xD878, 0x8C7F, 0xD879, 0x8C80, 0xD87A, 0x8C81, 0xD87B, 0x8C83, 0xD87C, 0x8C84, 0xD87D, 0x8C86, 0xD87E, 0x8C87, 0xD880, 0x8C88, + 0xD881, 0x8C8B, 0xD882, 0x8C8D, 0xD883, 0x8C8E, 0xD884, 0x8C8F, 0xD885, 0x8C90, 0xD886, 0x8C91, 0xD887, 0x8C92, 0xD888, 0x8C93, + 0xD889, 0x8C95, 0xD88A, 0x8C96, 0xD88B, 0x8C97, 0xD88C, 0x8C99, 0xD88D, 0x8C9A, 0xD88E, 0x8C9B, 0xD88F, 0x8C9C, 0xD890, 0x8C9D, + 0xD891, 0x8C9E, 0xD892, 0x8C9F, 0xD893, 0x8CA0, 0xD894, 0x8CA1, 0xD895, 0x8CA2, 0xD896, 0x8CA3, 0xD897, 0x8CA4, 0xD898, 0x8CA5, + 0xD899, 0x8CA6, 0xD89A, 0x8CA7, 0xD89B, 0x8CA8, 0xD89C, 0x8CA9, 0xD89D, 0x8CAA, 0xD89E, 0x8CAB, 0xD89F, 0x8CAC, 0xD8A0, 0x8CAD, + 0xD8A1, 0x4E8D, 0xD8A2, 0x4E0C, 0xD8A3, 0x5140, 0xD8A4, 0x4E10, 0xD8A5, 0x5EFF, 0xD8A6, 0x5345, 0xD8A7, 0x4E15, 0xD8A8, 0x4E98, + 0xD8A9, 0x4E1E, 0xD8AA, 0x9B32, 0xD8AB, 0x5B6C, 0xD8AC, 0x5669, 0xD8AD, 0x4E28, 0xD8AE, 0x79BA, 0xD8AF, 0x4E3F, 0xD8B0, 0x5315, + 0xD8B1, 0x4E47, 0xD8B2, 0x592D, 0xD8B3, 0x723B, 0xD8B4, 0x536E, 0xD8B5, 0x6C10, 0xD8B6, 0x56DF, 0xD8B7, 0x80E4, 0xD8B8, 0x9997, + 0xD8B9, 0x6BD3, 0xD8BA, 0x777E, 0xD8BB, 0x9F17, 0xD8BC, 0x4E36, 0xD8BD, 0x4E9F, 0xD8BE, 0x9F10, 0xD8BF, 0x4E5C, 0xD8C0, 0x4E69, + 0xD8C1, 0x4E93, 0xD8C2, 0x8288, 0xD8C3, 0x5B5B, 0xD8C4, 0x556C, 0xD8C5, 0x560F, 0xD8C6, 0x4EC4, 0xD8C7, 0x538D, 0xD8C8, 0x539D, + 0xD8C9, 0x53A3, 0xD8CA, 0x53A5, 0xD8CB, 0x53AE, 0xD8CC, 0x9765, 0xD8CD, 0x8D5D, 0xD8CE, 0x531A, 0xD8CF, 0x53F5, 0xD8D0, 0x5326, + 0xD8D1, 0x532E, 0xD8D2, 0x533E, 0xD8D3, 0x8D5C, 0xD8D4, 0x5366, 0xD8D5, 0x5363, 0xD8D6, 0x5202, 0xD8D7, 0x5208, 0xD8D8, 0x520E, + 0xD8D9, 0x522D, 0xD8DA, 0x5233, 0xD8DB, 0x523F, 0xD8DC, 0x5240, 0xD8DD, 0x524C, 0xD8DE, 0x525E, 0xD8DF, 0x5261, 0xD8E0, 0x525C, + 0xD8E1, 0x84AF, 0xD8E2, 0x527D, 0xD8E3, 0x5282, 0xD8E4, 0x5281, 0xD8E5, 0x5290, 0xD8E6, 0x5293, 0xD8E7, 0x5182, 0xD8E8, 0x7F54, + 0xD8E9, 0x4EBB, 0xD8EA, 0x4EC3, 0xD8EB, 0x4EC9, 0xD8EC, 0x4EC2, 0xD8ED, 0x4EE8, 0xD8EE, 0x4EE1, 0xD8EF, 0x4EEB, 0xD8F0, 0x4EDE, + 0xD8F1, 0x4F1B, 0xD8F2, 0x4EF3, 0xD8F3, 0x4F22, 0xD8F4, 0x4F64, 0xD8F5, 0x4EF5, 0xD8F6, 0x4F25, 0xD8F7, 0x4F27, 0xD8F8, 0x4F09, + 0xD8F9, 0x4F2B, 0xD8FA, 0x4F5E, 0xD8FB, 0x4F67, 0xD8FC, 0x6538, 0xD8FD, 0x4F5A, 0xD8FE, 0x4F5D, 0xD940, 0x8CAE, 0xD941, 0x8CAF, + 0xD942, 0x8CB0, 0xD943, 0x8CB1, 0xD944, 0x8CB2, 0xD945, 0x8CB3, 0xD946, 0x8CB4, 0xD947, 0x8CB5, 0xD948, 0x8CB6, 0xD949, 0x8CB7, + 0xD94A, 0x8CB8, 0xD94B, 0x8CB9, 0xD94C, 0x8CBA, 0xD94D, 0x8CBB, 0xD94E, 0x8CBC, 0xD94F, 0x8CBD, 0xD950, 0x8CBE, 0xD951, 0x8CBF, + 0xD952, 0x8CC0, 0xD953, 0x8CC1, 0xD954, 0x8CC2, 0xD955, 0x8CC3, 0xD956, 0x8CC4, 0xD957, 0x8CC5, 0xD958, 0x8CC6, 0xD959, 0x8CC7, + 0xD95A, 0x8CC8, 0xD95B, 0x8CC9, 0xD95C, 0x8CCA, 0xD95D, 0x8CCB, 0xD95E, 0x8CCC, 0xD95F, 0x8CCD, 0xD960, 0x8CCE, 0xD961, 0x8CCF, + 0xD962, 0x8CD0, 0xD963, 0x8CD1, 0xD964, 0x8CD2, 0xD965, 0x8CD3, 0xD966, 0x8CD4, 0xD967, 0x8CD5, 0xD968, 0x8CD6, 0xD969, 0x8CD7, + 0xD96A, 0x8CD8, 0xD96B, 0x8CD9, 0xD96C, 0x8CDA, 0xD96D, 0x8CDB, 0xD96E, 0x8CDC, 0xD96F, 0x8CDD, 0xD970, 0x8CDE, 0xD971, 0x8CDF, + 0xD972, 0x8CE0, 0xD973, 0x8CE1, 0xD974, 0x8CE2, 0xD975, 0x8CE3, 0xD976, 0x8CE4, 0xD977, 0x8CE5, 0xD978, 0x8CE6, 0xD979, 0x8CE7, + 0xD97A, 0x8CE8, 0xD97B, 0x8CE9, 0xD97C, 0x8CEA, 0xD97D, 0x8CEB, 0xD97E, 0x8CEC, 0xD980, 0x8CED, 0xD981, 0x8CEE, 0xD982, 0x8CEF, + 0xD983, 0x8CF0, 0xD984, 0x8CF1, 0xD985, 0x8CF2, 0xD986, 0x8CF3, 0xD987, 0x8CF4, 0xD988, 0x8CF5, 0xD989, 0x8CF6, 0xD98A, 0x8CF7, + 0xD98B, 0x8CF8, 0xD98C, 0x8CF9, 0xD98D, 0x8CFA, 0xD98E, 0x8CFB, 0xD98F, 0x8CFC, 0xD990, 0x8CFD, 0xD991, 0x8CFE, 0xD992, 0x8CFF, + 0xD993, 0x8D00, 0xD994, 0x8D01, 0xD995, 0x8D02, 0xD996, 0x8D03, 0xD997, 0x8D04, 0xD998, 0x8D05, 0xD999, 0x8D06, 0xD99A, 0x8D07, + 0xD99B, 0x8D08, 0xD99C, 0x8D09, 0xD99D, 0x8D0A, 0xD99E, 0x8D0B, 0xD99F, 0x8D0C, 0xD9A0, 0x8D0D, 0xD9A1, 0x4F5F, 0xD9A2, 0x4F57, + 0xD9A3, 0x4F32, 0xD9A4, 0x4F3D, 0xD9A5, 0x4F76, 0xD9A6, 0x4F74, 0xD9A7, 0x4F91, 0xD9A8, 0x4F89, 0xD9A9, 0x4F83, 0xD9AA, 0x4F8F, + 0xD9AB, 0x4F7E, 0xD9AC, 0x4F7B, 0xD9AD, 0x4FAA, 0xD9AE, 0x4F7C, 0xD9AF, 0x4FAC, 0xD9B0, 0x4F94, 0xD9B1, 0x4FE6, 0xD9B2, 0x4FE8, + 0xD9B3, 0x4FEA, 0xD9B4, 0x4FC5, 0xD9B5, 0x4FDA, 0xD9B6, 0x4FE3, 0xD9B7, 0x4FDC, 0xD9B8, 0x4FD1, 0xD9B9, 0x4FDF, 0xD9BA, 0x4FF8, + 0xD9BB, 0x5029, 0xD9BC, 0x504C, 0xD9BD, 0x4FF3, 0xD9BE, 0x502C, 0xD9BF, 0x500F, 0xD9C0, 0x502E, 0xD9C1, 0x502D, 0xD9C2, 0x4FFE, + 0xD9C3, 0x501C, 0xD9C4, 0x500C, 0xD9C5, 0x5025, 0xD9C6, 0x5028, 0xD9C7, 0x507E, 0xD9C8, 0x5043, 0xD9C9, 0x5055, 0xD9CA, 0x5048, + 0xD9CB, 0x504E, 0xD9CC, 0x506C, 0xD9CD, 0x507B, 0xD9CE, 0x50A5, 0xD9CF, 0x50A7, 0xD9D0, 0x50A9, 0xD9D1, 0x50BA, 0xD9D2, 0x50D6, + 0xD9D3, 0x5106, 0xD9D4, 0x50ED, 0xD9D5, 0x50EC, 0xD9D6, 0x50E6, 0xD9D7, 0x50EE, 0xD9D8, 0x5107, 0xD9D9, 0x510B, 0xD9DA, 0x4EDD, + 0xD9DB, 0x6C3D, 0xD9DC, 0x4F58, 0xD9DD, 0x4F65, 0xD9DE, 0x4FCE, 0xD9DF, 0x9FA0, 0xD9E0, 0x6C46, 0xD9E1, 0x7C74, 0xD9E2, 0x516E, + 0xD9E3, 0x5DFD, 0xD9E4, 0x9EC9, 0xD9E5, 0x9998, 0xD9E6, 0x5181, 0xD9E7, 0x5914, 0xD9E8, 0x52F9, 0xD9E9, 0x530D, 0xD9EA, 0x8A07, + 0xD9EB, 0x5310, 0xD9EC, 0x51EB, 0xD9ED, 0x5919, 0xD9EE, 0x5155, 0xD9EF, 0x4EA0, 0xD9F0, 0x5156, 0xD9F1, 0x4EB3, 0xD9F2, 0x886E, + 0xD9F3, 0x88A4, 0xD9F4, 0x4EB5, 0xD9F5, 0x8114, 0xD9F6, 0x88D2, 0xD9F7, 0x7980, 0xD9F8, 0x5B34, 0xD9F9, 0x8803, 0xD9FA, 0x7FB8, + 0xD9FB, 0x51AB, 0xD9FC, 0x51B1, 0xD9FD, 0x51BD, 0xD9FE, 0x51BC, 0xDA40, 0x8D0E, 0xDA41, 0x8D0F, 0xDA42, 0x8D10, 0xDA43, 0x8D11, + 0xDA44, 0x8D12, 0xDA45, 0x8D13, 0xDA46, 0x8D14, 0xDA47, 0x8D15, 0xDA48, 0x8D16, 0xDA49, 0x8D17, 0xDA4A, 0x8D18, 0xDA4B, 0x8D19, + 0xDA4C, 0x8D1A, 0xDA4D, 0x8D1B, 0xDA4E, 0x8D1C, 0xDA4F, 0x8D20, 0xDA50, 0x8D51, 0xDA51, 0x8D52, 0xDA52, 0x8D57, 0xDA53, 0x8D5F, + 0xDA54, 0x8D65, 0xDA55, 0x8D68, 0xDA56, 0x8D69, 0xDA57, 0x8D6A, 0xDA58, 0x8D6C, 0xDA59, 0x8D6E, 0xDA5A, 0x8D6F, 0xDA5B, 0x8D71, + 0xDA5C, 0x8D72, 0xDA5D, 0x8D78, 0xDA5E, 0x8D79, 0xDA5F, 0x8D7A, 0xDA60, 0x8D7B, 0xDA61, 0x8D7C, 0xDA62, 0x8D7D, 0xDA63, 0x8D7E, + 0xDA64, 0x8D7F, 0xDA65, 0x8D80, 0xDA66, 0x8D82, 0xDA67, 0x8D83, 0xDA68, 0x8D86, 0xDA69, 0x8D87, 0xDA6A, 0x8D88, 0xDA6B, 0x8D89, + 0xDA6C, 0x8D8C, 0xDA6D, 0x8D8D, 0xDA6E, 0x8D8E, 0xDA6F, 0x8D8F, 0xDA70, 0x8D90, 0xDA71, 0x8D92, 0xDA72, 0x8D93, 0xDA73, 0x8D95, + 0xDA74, 0x8D96, 0xDA75, 0x8D97, 0xDA76, 0x8D98, 0xDA77, 0x8D99, 0xDA78, 0x8D9A, 0xDA79, 0x8D9B, 0xDA7A, 0x8D9C, 0xDA7B, 0x8D9D, + 0xDA7C, 0x8D9E, 0xDA7D, 0x8DA0, 0xDA7E, 0x8DA1, 0xDA80, 0x8DA2, 0xDA81, 0x8DA4, 0xDA82, 0x8DA5, 0xDA83, 0x8DA6, 0xDA84, 0x8DA7, + 0xDA85, 0x8DA8, 0xDA86, 0x8DA9, 0xDA87, 0x8DAA, 0xDA88, 0x8DAB, 0xDA89, 0x8DAC, 0xDA8A, 0x8DAD, 0xDA8B, 0x8DAE, 0xDA8C, 0x8DAF, + 0xDA8D, 0x8DB0, 0xDA8E, 0x8DB2, 0xDA8F, 0x8DB6, 0xDA90, 0x8DB7, 0xDA91, 0x8DB9, 0xDA92, 0x8DBB, 0xDA93, 0x8DBD, 0xDA94, 0x8DC0, + 0xDA95, 0x8DC1, 0xDA96, 0x8DC2, 0xDA97, 0x8DC5, 0xDA98, 0x8DC7, 0xDA99, 0x8DC8, 0xDA9A, 0x8DC9, 0xDA9B, 0x8DCA, 0xDA9C, 0x8DCD, + 0xDA9D, 0x8DD0, 0xDA9E, 0x8DD2, 0xDA9F, 0x8DD3, 0xDAA0, 0x8DD4, 0xDAA1, 0x51C7, 0xDAA2, 0x5196, 0xDAA3, 0x51A2, 0xDAA4, 0x51A5, + 0xDAA5, 0x8BA0, 0xDAA6, 0x8BA6, 0xDAA7, 0x8BA7, 0xDAA8, 0x8BAA, 0xDAA9, 0x8BB4, 0xDAAA, 0x8BB5, 0xDAAB, 0x8BB7, 0xDAAC, 0x8BC2, + 0xDAAD, 0x8BC3, 0xDAAE, 0x8BCB, 0xDAAF, 0x8BCF, 0xDAB0, 0x8BCE, 0xDAB1, 0x8BD2, 0xDAB2, 0x8BD3, 0xDAB3, 0x8BD4, 0xDAB4, 0x8BD6, + 0xDAB5, 0x8BD8, 0xDAB6, 0x8BD9, 0xDAB7, 0x8BDC, 0xDAB8, 0x8BDF, 0xDAB9, 0x8BE0, 0xDABA, 0x8BE4, 0xDABB, 0x8BE8, 0xDABC, 0x8BE9, + 0xDABD, 0x8BEE, 0xDABE, 0x8BF0, 0xDABF, 0x8BF3, 0xDAC0, 0x8BF6, 0xDAC1, 0x8BF9, 0xDAC2, 0x8BFC, 0xDAC3, 0x8BFF, 0xDAC4, 0x8C00, + 0xDAC5, 0x8C02, 0xDAC6, 0x8C04, 0xDAC7, 0x8C07, 0xDAC8, 0x8C0C, 0xDAC9, 0x8C0F, 0xDACA, 0x8C11, 0xDACB, 0x8C12, 0xDACC, 0x8C14, + 0xDACD, 0x8C15, 0xDACE, 0x8C16, 0xDACF, 0x8C19, 0xDAD0, 0x8C1B, 0xDAD1, 0x8C18, 0xDAD2, 0x8C1D, 0xDAD3, 0x8C1F, 0xDAD4, 0x8C20, + 0xDAD5, 0x8C21, 0xDAD6, 0x8C25, 0xDAD7, 0x8C27, 0xDAD8, 0x8C2A, 0xDAD9, 0x8C2B, 0xDADA, 0x8C2E, 0xDADB, 0x8C2F, 0xDADC, 0x8C32, + 0xDADD, 0x8C33, 0xDADE, 0x8C35, 0xDADF, 0x8C36, 0xDAE0, 0x5369, 0xDAE1, 0x537A, 0xDAE2, 0x961D, 0xDAE3, 0x9622, 0xDAE4, 0x9621, + 0xDAE5, 0x9631, 0xDAE6, 0x962A, 0xDAE7, 0x963D, 0xDAE8, 0x963C, 0xDAE9, 0x9642, 0xDAEA, 0x9649, 0xDAEB, 0x9654, 0xDAEC, 0x965F, + 0xDAED, 0x9667, 0xDAEE, 0x966C, 0xDAEF, 0x9672, 0xDAF0, 0x9674, 0xDAF1, 0x9688, 0xDAF2, 0x968D, 0xDAF3, 0x9697, 0xDAF4, 0x96B0, + 0xDAF5, 0x9097, 0xDAF6, 0x909B, 0xDAF7, 0x909D, 0xDAF8, 0x9099, 0xDAF9, 0x90AC, 0xDAFA, 0x90A1, 0xDAFB, 0x90B4, 0xDAFC, 0x90B3, + 0xDAFD, 0x90B6, 0xDAFE, 0x90BA, 0xDB40, 0x8DD5, 0xDB41, 0x8DD8, 0xDB42, 0x8DD9, 0xDB43, 0x8DDC, 0xDB44, 0x8DE0, 0xDB45, 0x8DE1, + 0xDB46, 0x8DE2, 0xDB47, 0x8DE5, 0xDB48, 0x8DE6, 0xDB49, 0x8DE7, 0xDB4A, 0x8DE9, 0xDB4B, 0x8DED, 0xDB4C, 0x8DEE, 0xDB4D, 0x8DF0, + 0xDB4E, 0x8DF1, 0xDB4F, 0x8DF2, 0xDB50, 0x8DF4, 0xDB51, 0x8DF6, 0xDB52, 0x8DFC, 0xDB53, 0x8DFE, 0xDB54, 0x8DFF, 0xDB55, 0x8E00, + 0xDB56, 0x8E01, 0xDB57, 0x8E02, 0xDB58, 0x8E03, 0xDB59, 0x8E04, 0xDB5A, 0x8E06, 0xDB5B, 0x8E07, 0xDB5C, 0x8E08, 0xDB5D, 0x8E0B, + 0xDB5E, 0x8E0D, 0xDB5F, 0x8E0E, 0xDB60, 0x8E10, 0xDB61, 0x8E11, 0xDB62, 0x8E12, 0xDB63, 0x8E13, 0xDB64, 0x8E15, 0xDB65, 0x8E16, + 0xDB66, 0x8E17, 0xDB67, 0x8E18, 0xDB68, 0x8E19, 0xDB69, 0x8E1A, 0xDB6A, 0x8E1B, 0xDB6B, 0x8E1C, 0xDB6C, 0x8E20, 0xDB6D, 0x8E21, + 0xDB6E, 0x8E24, 0xDB6F, 0x8E25, 0xDB70, 0x8E26, 0xDB71, 0x8E27, 0xDB72, 0x8E28, 0xDB73, 0x8E2B, 0xDB74, 0x8E2D, 0xDB75, 0x8E30, + 0xDB76, 0x8E32, 0xDB77, 0x8E33, 0xDB78, 0x8E34, 0xDB79, 0x8E36, 0xDB7A, 0x8E37, 0xDB7B, 0x8E38, 0xDB7C, 0x8E3B, 0xDB7D, 0x8E3C, + 0xDB7E, 0x8E3E, 0xDB80, 0x8E3F, 0xDB81, 0x8E43, 0xDB82, 0x8E45, 0xDB83, 0x8E46, 0xDB84, 0x8E4C, 0xDB85, 0x8E4D, 0xDB86, 0x8E4E, + 0xDB87, 0x8E4F, 0xDB88, 0x8E50, 0xDB89, 0x8E53, 0xDB8A, 0x8E54, 0xDB8B, 0x8E55, 0xDB8C, 0x8E56, 0xDB8D, 0x8E57, 0xDB8E, 0x8E58, + 0xDB8F, 0x8E5A, 0xDB90, 0x8E5B, 0xDB91, 0x8E5C, 0xDB92, 0x8E5D, 0xDB93, 0x8E5E, 0xDB94, 0x8E5F, 0xDB95, 0x8E60, 0xDB96, 0x8E61, + 0xDB97, 0x8E62, 0xDB98, 0x8E63, 0xDB99, 0x8E64, 0xDB9A, 0x8E65, 0xDB9B, 0x8E67, 0xDB9C, 0x8E68, 0xDB9D, 0x8E6A, 0xDB9E, 0x8E6B, + 0xDB9F, 0x8E6E, 0xDBA0, 0x8E71, 0xDBA1, 0x90B8, 0xDBA2, 0x90B0, 0xDBA3, 0x90CF, 0xDBA4, 0x90C5, 0xDBA5, 0x90BE, 0xDBA6, 0x90D0, + 0xDBA7, 0x90C4, 0xDBA8, 0x90C7, 0xDBA9, 0x90D3, 0xDBAA, 0x90E6, 0xDBAB, 0x90E2, 0xDBAC, 0x90DC, 0xDBAD, 0x90D7, 0xDBAE, 0x90DB, + 0xDBAF, 0x90EB, 0xDBB0, 0x90EF, 0xDBB1, 0x90FE, 0xDBB2, 0x9104, 0xDBB3, 0x9122, 0xDBB4, 0x911E, 0xDBB5, 0x9123, 0xDBB6, 0x9131, + 0xDBB7, 0x912F, 0xDBB8, 0x9139, 0xDBB9, 0x9143, 0xDBBA, 0x9146, 0xDBBB, 0x520D, 0xDBBC, 0x5942, 0xDBBD, 0x52A2, 0xDBBE, 0x52AC, + 0xDBBF, 0x52AD, 0xDBC0, 0x52BE, 0xDBC1, 0x54FF, 0xDBC2, 0x52D0, 0xDBC3, 0x52D6, 0xDBC4, 0x52F0, 0xDBC5, 0x53DF, 0xDBC6, 0x71EE, + 0xDBC7, 0x77CD, 0xDBC8, 0x5EF4, 0xDBC9, 0x51F5, 0xDBCA, 0x51FC, 0xDBCB, 0x9B2F, 0xDBCC, 0x53B6, 0xDBCD, 0x5F01, 0xDBCE, 0x755A, + 0xDBCF, 0x5DEF, 0xDBD0, 0x574C, 0xDBD1, 0x57A9, 0xDBD2, 0x57A1, 0xDBD3, 0x587E, 0xDBD4, 0x58BC, 0xDBD5, 0x58C5, 0xDBD6, 0x58D1, + 0xDBD7, 0x5729, 0xDBD8, 0x572C, 0xDBD9, 0x572A, 0xDBDA, 0x5733, 0xDBDB, 0x5739, 0xDBDC, 0x572E, 0xDBDD, 0x572F, 0xDBDE, 0x575C, + 0xDBDF, 0x573B, 0xDBE0, 0x5742, 0xDBE1, 0x5769, 0xDBE2, 0x5785, 0xDBE3, 0x576B, 0xDBE4, 0x5786, 0xDBE5, 0x577C, 0xDBE6, 0x577B, + 0xDBE7, 0x5768, 0xDBE8, 0x576D, 0xDBE9, 0x5776, 0xDBEA, 0x5773, 0xDBEB, 0x57AD, 0xDBEC, 0x57A4, 0xDBED, 0x578C, 0xDBEE, 0x57B2, + 0xDBEF, 0x57CF, 0xDBF0, 0x57A7, 0xDBF1, 0x57B4, 0xDBF2, 0x5793, 0xDBF3, 0x57A0, 0xDBF4, 0x57D5, 0xDBF5, 0x57D8, 0xDBF6, 0x57DA, + 0xDBF7, 0x57D9, 0xDBF8, 0x57D2, 0xDBF9, 0x57B8, 0xDBFA, 0x57F4, 0xDBFB, 0x57EF, 0xDBFC, 0x57F8, 0xDBFD, 0x57E4, 0xDBFE, 0x57DD, + 0xDC40, 0x8E73, 0xDC41, 0x8E75, 0xDC42, 0x8E77, 0xDC43, 0x8E78, 0xDC44, 0x8E79, 0xDC45, 0x8E7A, 0xDC46, 0x8E7B, 0xDC47, 0x8E7D, + 0xDC48, 0x8E7E, 0xDC49, 0x8E80, 0xDC4A, 0x8E82, 0xDC4B, 0x8E83, 0xDC4C, 0x8E84, 0xDC4D, 0x8E86, 0xDC4E, 0x8E88, 0xDC4F, 0x8E89, + 0xDC50, 0x8E8A, 0xDC51, 0x8E8B, 0xDC52, 0x8E8C, 0xDC53, 0x8E8D, 0xDC54, 0x8E8E, 0xDC55, 0x8E91, 0xDC56, 0x8E92, 0xDC57, 0x8E93, + 0xDC58, 0x8E95, 0xDC59, 0x8E96, 0xDC5A, 0x8E97, 0xDC5B, 0x8E98, 0xDC5C, 0x8E99, 0xDC5D, 0x8E9A, 0xDC5E, 0x8E9B, 0xDC5F, 0x8E9D, + 0xDC60, 0x8E9F, 0xDC61, 0x8EA0, 0xDC62, 0x8EA1, 0xDC63, 0x8EA2, 0xDC64, 0x8EA3, 0xDC65, 0x8EA4, 0xDC66, 0x8EA5, 0xDC67, 0x8EA6, + 0xDC68, 0x8EA7, 0xDC69, 0x8EA8, 0xDC6A, 0x8EA9, 0xDC6B, 0x8EAA, 0xDC6C, 0x8EAD, 0xDC6D, 0x8EAE, 0xDC6E, 0x8EB0, 0xDC6F, 0x8EB1, + 0xDC70, 0x8EB3, 0xDC71, 0x8EB4, 0xDC72, 0x8EB5, 0xDC73, 0x8EB6, 0xDC74, 0x8EB7, 0xDC75, 0x8EB8, 0xDC76, 0x8EB9, 0xDC77, 0x8EBB, + 0xDC78, 0x8EBC, 0xDC79, 0x8EBD, 0xDC7A, 0x8EBE, 0xDC7B, 0x8EBF, 0xDC7C, 0x8EC0, 0xDC7D, 0x8EC1, 0xDC7E, 0x8EC2, 0xDC80, 0x8EC3, + 0xDC81, 0x8EC4, 0xDC82, 0x8EC5, 0xDC83, 0x8EC6, 0xDC84, 0x8EC7, 0xDC85, 0x8EC8, 0xDC86, 0x8EC9, 0xDC87, 0x8ECA, 0xDC88, 0x8ECB, + 0xDC89, 0x8ECC, 0xDC8A, 0x8ECD, 0xDC8B, 0x8ECF, 0xDC8C, 0x8ED0, 0xDC8D, 0x8ED1, 0xDC8E, 0x8ED2, 0xDC8F, 0x8ED3, 0xDC90, 0x8ED4, + 0xDC91, 0x8ED5, 0xDC92, 0x8ED6, 0xDC93, 0x8ED7, 0xDC94, 0x8ED8, 0xDC95, 0x8ED9, 0xDC96, 0x8EDA, 0xDC97, 0x8EDB, 0xDC98, 0x8EDC, + 0xDC99, 0x8EDD, 0xDC9A, 0x8EDE, 0xDC9B, 0x8EDF, 0xDC9C, 0x8EE0, 0xDC9D, 0x8EE1, 0xDC9E, 0x8EE2, 0xDC9F, 0x8EE3, 0xDCA0, 0x8EE4, + 0xDCA1, 0x580B, 0xDCA2, 0x580D, 0xDCA3, 0x57FD, 0xDCA4, 0x57ED, 0xDCA5, 0x5800, 0xDCA6, 0x581E, 0xDCA7, 0x5819, 0xDCA8, 0x5844, + 0xDCA9, 0x5820, 0xDCAA, 0x5865, 0xDCAB, 0x586C, 0xDCAC, 0x5881, 0xDCAD, 0x5889, 0xDCAE, 0x589A, 0xDCAF, 0x5880, 0xDCB0, 0x99A8, + 0xDCB1, 0x9F19, 0xDCB2, 0x61FF, 0xDCB3, 0x8279, 0xDCB4, 0x827D, 0xDCB5, 0x827F, 0xDCB6, 0x828F, 0xDCB7, 0x828A, 0xDCB8, 0x82A8, + 0xDCB9, 0x8284, 0xDCBA, 0x828E, 0xDCBB, 0x8291, 0xDCBC, 0x8297, 0xDCBD, 0x8299, 0xDCBE, 0x82AB, 0xDCBF, 0x82B8, 0xDCC0, 0x82BE, + 0xDCC1, 0x82B0, 0xDCC2, 0x82C8, 0xDCC3, 0x82CA, 0xDCC4, 0x82E3, 0xDCC5, 0x8298, 0xDCC6, 0x82B7, 0xDCC7, 0x82AE, 0xDCC8, 0x82CB, + 0xDCC9, 0x82CC, 0xDCCA, 0x82C1, 0xDCCB, 0x82A9, 0xDCCC, 0x82B4, 0xDCCD, 0x82A1, 0xDCCE, 0x82AA, 0xDCCF, 0x829F, 0xDCD0, 0x82C4, + 0xDCD1, 0x82CE, 0xDCD2, 0x82A4, 0xDCD3, 0x82E1, 0xDCD4, 0x8309, 0xDCD5, 0x82F7, 0xDCD6, 0x82E4, 0xDCD7, 0x830F, 0xDCD8, 0x8307, + 0xDCD9, 0x82DC, 0xDCDA, 0x82F4, 0xDCDB, 0x82D2, 0xDCDC, 0x82D8, 0xDCDD, 0x830C, 0xDCDE, 0x82FB, 0xDCDF, 0x82D3, 0xDCE0, 0x8311, + 0xDCE1, 0x831A, 0xDCE2, 0x8306, 0xDCE3, 0x8314, 0xDCE4, 0x8315, 0xDCE5, 0x82E0, 0xDCE6, 0x82D5, 0xDCE7, 0x831C, 0xDCE8, 0x8351, + 0xDCE9, 0x835B, 0xDCEA, 0x835C, 0xDCEB, 0x8308, 0xDCEC, 0x8392, 0xDCED, 0x833C, 0xDCEE, 0x8334, 0xDCEF, 0x8331, 0xDCF0, 0x839B, + 0xDCF1, 0x835E, 0xDCF2, 0x832F, 0xDCF3, 0x834F, 0xDCF4, 0x8347, 0xDCF5, 0x8343, 0xDCF6, 0x835F, 0xDCF7, 0x8340, 0xDCF8, 0x8317, + 0xDCF9, 0x8360, 0xDCFA, 0x832D, 0xDCFB, 0x833A, 0xDCFC, 0x8333, 0xDCFD, 0x8366, 0xDCFE, 0x8365, 0xDD40, 0x8EE5, 0xDD41, 0x8EE6, + 0xDD42, 0x8EE7, 0xDD43, 0x8EE8, 0xDD44, 0x8EE9, 0xDD45, 0x8EEA, 0xDD46, 0x8EEB, 0xDD47, 0x8EEC, 0xDD48, 0x8EED, 0xDD49, 0x8EEE, + 0xDD4A, 0x8EEF, 0xDD4B, 0x8EF0, 0xDD4C, 0x8EF1, 0xDD4D, 0x8EF2, 0xDD4E, 0x8EF3, 0xDD4F, 0x8EF4, 0xDD50, 0x8EF5, 0xDD51, 0x8EF6, + 0xDD52, 0x8EF7, 0xDD53, 0x8EF8, 0xDD54, 0x8EF9, 0xDD55, 0x8EFA, 0xDD56, 0x8EFB, 0xDD57, 0x8EFC, 0xDD58, 0x8EFD, 0xDD59, 0x8EFE, + 0xDD5A, 0x8EFF, 0xDD5B, 0x8F00, 0xDD5C, 0x8F01, 0xDD5D, 0x8F02, 0xDD5E, 0x8F03, 0xDD5F, 0x8F04, 0xDD60, 0x8F05, 0xDD61, 0x8F06, + 0xDD62, 0x8F07, 0xDD63, 0x8F08, 0xDD64, 0x8F09, 0xDD65, 0x8F0A, 0xDD66, 0x8F0B, 0xDD67, 0x8F0C, 0xDD68, 0x8F0D, 0xDD69, 0x8F0E, + 0xDD6A, 0x8F0F, 0xDD6B, 0x8F10, 0xDD6C, 0x8F11, 0xDD6D, 0x8F12, 0xDD6E, 0x8F13, 0xDD6F, 0x8F14, 0xDD70, 0x8F15, 0xDD71, 0x8F16, + 0xDD72, 0x8F17, 0xDD73, 0x8F18, 0xDD74, 0x8F19, 0xDD75, 0x8F1A, 0xDD76, 0x8F1B, 0xDD77, 0x8F1C, 0xDD78, 0x8F1D, 0xDD79, 0x8F1E, + 0xDD7A, 0x8F1F, 0xDD7B, 0x8F20, 0xDD7C, 0x8F21, 0xDD7D, 0x8F22, 0xDD7E, 0x8F23, 0xDD80, 0x8F24, 0xDD81, 0x8F25, 0xDD82, 0x8F26, + 0xDD83, 0x8F27, 0xDD84, 0x8F28, 0xDD85, 0x8F29, 0xDD86, 0x8F2A, 0xDD87, 0x8F2B, 0xDD88, 0x8F2C, 0xDD89, 0x8F2D, 0xDD8A, 0x8F2E, + 0xDD8B, 0x8F2F, 0xDD8C, 0x8F30, 0xDD8D, 0x8F31, 0xDD8E, 0x8F32, 0xDD8F, 0x8F33, 0xDD90, 0x8F34, 0xDD91, 0x8F35, 0xDD92, 0x8F36, + 0xDD93, 0x8F37, 0xDD94, 0x8F38, 0xDD95, 0x8F39, 0xDD96, 0x8F3A, 0xDD97, 0x8F3B, 0xDD98, 0x8F3C, 0xDD99, 0x8F3D, 0xDD9A, 0x8F3E, + 0xDD9B, 0x8F3F, 0xDD9C, 0x8F40, 0xDD9D, 0x8F41, 0xDD9E, 0x8F42, 0xDD9F, 0x8F43, 0xDDA0, 0x8F44, 0xDDA1, 0x8368, 0xDDA2, 0x831B, + 0xDDA3, 0x8369, 0xDDA4, 0x836C, 0xDDA5, 0x836A, 0xDDA6, 0x836D, 0xDDA7, 0x836E, 0xDDA8, 0x83B0, 0xDDA9, 0x8378, 0xDDAA, 0x83B3, + 0xDDAB, 0x83B4, 0xDDAC, 0x83A0, 0xDDAD, 0x83AA, 0xDDAE, 0x8393, 0xDDAF, 0x839C, 0xDDB0, 0x8385, 0xDDB1, 0x837C, 0xDDB2, 0x83B6, + 0xDDB3, 0x83A9, 0xDDB4, 0x837D, 0xDDB5, 0x83B8, 0xDDB6, 0x837B, 0xDDB7, 0x8398, 0xDDB8, 0x839E, 0xDDB9, 0x83A8, 0xDDBA, 0x83BA, + 0xDDBB, 0x83BC, 0xDDBC, 0x83C1, 0xDDBD, 0x8401, 0xDDBE, 0x83E5, 0xDDBF, 0x83D8, 0xDDC0, 0x5807, 0xDDC1, 0x8418, 0xDDC2, 0x840B, + 0xDDC3, 0x83DD, 0xDDC4, 0x83FD, 0xDDC5, 0x83D6, 0xDDC6, 0x841C, 0xDDC7, 0x8438, 0xDDC8, 0x8411, 0xDDC9, 0x8406, 0xDDCA, 0x83D4, + 0xDDCB, 0x83DF, 0xDDCC, 0x840F, 0xDDCD, 0x8403, 0xDDCE, 0x83F8, 0xDDCF, 0x83F9, 0xDDD0, 0x83EA, 0xDDD1, 0x83C5, 0xDDD2, 0x83C0, + 0xDDD3, 0x8426, 0xDDD4, 0x83F0, 0xDDD5, 0x83E1, 0xDDD6, 0x845C, 0xDDD7, 0x8451, 0xDDD8, 0x845A, 0xDDD9, 0x8459, 0xDDDA, 0x8473, + 0xDDDB, 0x8487, 0xDDDC, 0x8488, 0xDDDD, 0x847A, 0xDDDE, 0x8489, 0xDDDF, 0x8478, 0xDDE0, 0x843C, 0xDDE1, 0x8446, 0xDDE2, 0x8469, + 0xDDE3, 0x8476, 0xDDE4, 0x848C, 0xDDE5, 0x848E, 0xDDE6, 0x8431, 0xDDE7, 0x846D, 0xDDE8, 0x84C1, 0xDDE9, 0x84CD, 0xDDEA, 0x84D0, + 0xDDEB, 0x84E6, 0xDDEC, 0x84BD, 0xDDED, 0x84D3, 0xDDEE, 0x84CA, 0xDDEF, 0x84BF, 0xDDF0, 0x84BA, 0xDDF1, 0x84E0, 0xDDF2, 0x84A1, + 0xDDF3, 0x84B9, 0xDDF4, 0x84B4, 0xDDF5, 0x8497, 0xDDF6, 0x84E5, 0xDDF7, 0x84E3, 0xDDF8, 0x850C, 0xDDF9, 0x750D, 0xDDFA, 0x8538, + 0xDDFB, 0x84F0, 0xDDFC, 0x8539, 0xDDFD, 0x851F, 0xDDFE, 0x853A, 0xDE40, 0x8F45, 0xDE41, 0x8F46, 0xDE42, 0x8F47, 0xDE43, 0x8F48, + 0xDE44, 0x8F49, 0xDE45, 0x8F4A, 0xDE46, 0x8F4B, 0xDE47, 0x8F4C, 0xDE48, 0x8F4D, 0xDE49, 0x8F4E, 0xDE4A, 0x8F4F, 0xDE4B, 0x8F50, + 0xDE4C, 0x8F51, 0xDE4D, 0x8F52, 0xDE4E, 0x8F53, 0xDE4F, 0x8F54, 0xDE50, 0x8F55, 0xDE51, 0x8F56, 0xDE52, 0x8F57, 0xDE53, 0x8F58, + 0xDE54, 0x8F59, 0xDE55, 0x8F5A, 0xDE56, 0x8F5B, 0xDE57, 0x8F5C, 0xDE58, 0x8F5D, 0xDE59, 0x8F5E, 0xDE5A, 0x8F5F, 0xDE5B, 0x8F60, + 0xDE5C, 0x8F61, 0xDE5D, 0x8F62, 0xDE5E, 0x8F63, 0xDE5F, 0x8F64, 0xDE60, 0x8F65, 0xDE61, 0x8F6A, 0xDE62, 0x8F80, 0xDE63, 0x8F8C, + 0xDE64, 0x8F92, 0xDE65, 0x8F9D, 0xDE66, 0x8FA0, 0xDE67, 0x8FA1, 0xDE68, 0x8FA2, 0xDE69, 0x8FA4, 0xDE6A, 0x8FA5, 0xDE6B, 0x8FA6, + 0xDE6C, 0x8FA7, 0xDE6D, 0x8FAA, 0xDE6E, 0x8FAC, 0xDE6F, 0x8FAD, 0xDE70, 0x8FAE, 0xDE71, 0x8FAF, 0xDE72, 0x8FB2, 0xDE73, 0x8FB3, + 0xDE74, 0x8FB4, 0xDE75, 0x8FB5, 0xDE76, 0x8FB7, 0xDE77, 0x8FB8, 0xDE78, 0x8FBA, 0xDE79, 0x8FBB, 0xDE7A, 0x8FBC, 0xDE7B, 0x8FBF, + 0xDE7C, 0x8FC0, 0xDE7D, 0x8FC3, 0xDE7E, 0x8FC6, 0xDE80, 0x8FC9, 0xDE81, 0x8FCA, 0xDE82, 0x8FCB, 0xDE83, 0x8FCC, 0xDE84, 0x8FCD, + 0xDE85, 0x8FCF, 0xDE86, 0x8FD2, 0xDE87, 0x8FD6, 0xDE88, 0x8FD7, 0xDE89, 0x8FDA, 0xDE8A, 0x8FE0, 0xDE8B, 0x8FE1, 0xDE8C, 0x8FE3, + 0xDE8D, 0x8FE7, 0xDE8E, 0x8FEC, 0xDE8F, 0x8FEF, 0xDE90, 0x8FF1, 0xDE91, 0x8FF2, 0xDE92, 0x8FF4, 0xDE93, 0x8FF5, 0xDE94, 0x8FF6, + 0xDE95, 0x8FFA, 0xDE96, 0x8FFB, 0xDE97, 0x8FFC, 0xDE98, 0x8FFE, 0xDE99, 0x8FFF, 0xDE9A, 0x9007, 0xDE9B, 0x9008, 0xDE9C, 0x900C, + 0xDE9D, 0x900E, 0xDE9E, 0x9013, 0xDE9F, 0x9015, 0xDEA0, 0x9018, 0xDEA1, 0x8556, 0xDEA2, 0x853B, 0xDEA3, 0x84FF, 0xDEA4, 0x84FC, + 0xDEA5, 0x8559, 0xDEA6, 0x8548, 0xDEA7, 0x8568, 0xDEA8, 0x8564, 0xDEA9, 0x855E, 0xDEAA, 0x857A, 0xDEAB, 0x77A2, 0xDEAC, 0x8543, + 0xDEAD, 0x8572, 0xDEAE, 0x857B, 0xDEAF, 0x85A4, 0xDEB0, 0x85A8, 0xDEB1, 0x8587, 0xDEB2, 0x858F, 0xDEB3, 0x8579, 0xDEB4, 0x85AE, + 0xDEB5, 0x859C, 0xDEB6, 0x8585, 0xDEB7, 0x85B9, 0xDEB8, 0x85B7, 0xDEB9, 0x85B0, 0xDEBA, 0x85D3, 0xDEBB, 0x85C1, 0xDEBC, 0x85DC, + 0xDEBD, 0x85FF, 0xDEBE, 0x8627, 0xDEBF, 0x8605, 0xDEC0, 0x8629, 0xDEC1, 0x8616, 0xDEC2, 0x863C, 0xDEC3, 0x5EFE, 0xDEC4, 0x5F08, + 0xDEC5, 0x593C, 0xDEC6, 0x5941, 0xDEC7, 0x8037, 0xDEC8, 0x5955, 0xDEC9, 0x595A, 0xDECA, 0x5958, 0xDECB, 0x530F, 0xDECC, 0x5C22, + 0xDECD, 0x5C25, 0xDECE, 0x5C2C, 0xDECF, 0x5C34, 0xDED0, 0x624C, 0xDED1, 0x626A, 0xDED2, 0x629F, 0xDED3, 0x62BB, 0xDED4, 0x62CA, + 0xDED5, 0x62DA, 0xDED6, 0x62D7, 0xDED7, 0x62EE, 0xDED8, 0x6322, 0xDED9, 0x62F6, 0xDEDA, 0x6339, 0xDEDB, 0x634B, 0xDEDC, 0x6343, + 0xDEDD, 0x63AD, 0xDEDE, 0x63F6, 0xDEDF, 0x6371, 0xDEE0, 0x637A, 0xDEE1, 0x638E, 0xDEE2, 0x63B4, 0xDEE3, 0x636D, 0xDEE4, 0x63AC, + 0xDEE5, 0x638A, 0xDEE6, 0x6369, 0xDEE7, 0x63AE, 0xDEE8, 0x63BC, 0xDEE9, 0x63F2, 0xDEEA, 0x63F8, 0xDEEB, 0x63E0, 0xDEEC, 0x63FF, + 0xDEED, 0x63C4, 0xDEEE, 0x63DE, 0xDEEF, 0x63CE, 0xDEF0, 0x6452, 0xDEF1, 0x63C6, 0xDEF2, 0x63BE, 0xDEF3, 0x6445, 0xDEF4, 0x6441, + 0xDEF5, 0x640B, 0xDEF6, 0x641B, 0xDEF7, 0x6420, 0xDEF8, 0x640C, 0xDEF9, 0x6426, 0xDEFA, 0x6421, 0xDEFB, 0x645E, 0xDEFC, 0x6484, + 0xDEFD, 0x646D, 0xDEFE, 0x6496, 0xDF40, 0x9019, 0xDF41, 0x901C, 0xDF42, 0x9023, 0xDF43, 0x9024, 0xDF44, 0x9025, 0xDF45, 0x9027, + 0xDF46, 0x9028, 0xDF47, 0x9029, 0xDF48, 0x902A, 0xDF49, 0x902B, 0xDF4A, 0x902C, 0xDF4B, 0x9030, 0xDF4C, 0x9031, 0xDF4D, 0x9032, + 0xDF4E, 0x9033, 0xDF4F, 0x9034, 0xDF50, 0x9037, 0xDF51, 0x9039, 0xDF52, 0x903A, 0xDF53, 0x903D, 0xDF54, 0x903F, 0xDF55, 0x9040, + 0xDF56, 0x9043, 0xDF57, 0x9045, 0xDF58, 0x9046, 0xDF59, 0x9048, 0xDF5A, 0x9049, 0xDF5B, 0x904A, 0xDF5C, 0x904B, 0xDF5D, 0x904C, + 0xDF5E, 0x904E, 0xDF5F, 0x9054, 0xDF60, 0x9055, 0xDF61, 0x9056, 0xDF62, 0x9059, 0xDF63, 0x905A, 0xDF64, 0x905C, 0xDF65, 0x905D, + 0xDF66, 0x905E, 0xDF67, 0x905F, 0xDF68, 0x9060, 0xDF69, 0x9061, 0xDF6A, 0x9064, 0xDF6B, 0x9066, 0xDF6C, 0x9067, 0xDF6D, 0x9069, + 0xDF6E, 0x906A, 0xDF6F, 0x906B, 0xDF70, 0x906C, 0xDF71, 0x906F, 0xDF72, 0x9070, 0xDF73, 0x9071, 0xDF74, 0x9072, 0xDF75, 0x9073, + 0xDF76, 0x9076, 0xDF77, 0x9077, 0xDF78, 0x9078, 0xDF79, 0x9079, 0xDF7A, 0x907A, 0xDF7B, 0x907B, 0xDF7C, 0x907C, 0xDF7D, 0x907E, + 0xDF7E, 0x9081, 0xDF80, 0x9084, 0xDF81, 0x9085, 0xDF82, 0x9086, 0xDF83, 0x9087, 0xDF84, 0x9089, 0xDF85, 0x908A, 0xDF86, 0x908C, + 0xDF87, 0x908D, 0xDF88, 0x908E, 0xDF89, 0x908F, 0xDF8A, 0x9090, 0xDF8B, 0x9092, 0xDF8C, 0x9094, 0xDF8D, 0x9096, 0xDF8E, 0x9098, + 0xDF8F, 0x909A, 0xDF90, 0x909C, 0xDF91, 0x909E, 0xDF92, 0x909F, 0xDF93, 0x90A0, 0xDF94, 0x90A4, 0xDF95, 0x90A5, 0xDF96, 0x90A7, + 0xDF97, 0x90A8, 0xDF98, 0x90A9, 0xDF99, 0x90AB, 0xDF9A, 0x90AD, 0xDF9B, 0x90B2, 0xDF9C, 0x90B7, 0xDF9D, 0x90BC, 0xDF9E, 0x90BD, + 0xDF9F, 0x90BF, 0xDFA0, 0x90C0, 0xDFA1, 0x647A, 0xDFA2, 0x64B7, 0xDFA3, 0x64B8, 0xDFA4, 0x6499, 0xDFA5, 0x64BA, 0xDFA6, 0x64C0, + 0xDFA7, 0x64D0, 0xDFA8, 0x64D7, 0xDFA9, 0x64E4, 0xDFAA, 0x64E2, 0xDFAB, 0x6509, 0xDFAC, 0x6525, 0xDFAD, 0x652E, 0xDFAE, 0x5F0B, + 0xDFAF, 0x5FD2, 0xDFB0, 0x7519, 0xDFB1, 0x5F11, 0xDFB2, 0x535F, 0xDFB3, 0x53F1, 0xDFB4, 0x53FD, 0xDFB5, 0x53E9, 0xDFB6, 0x53E8, + 0xDFB7, 0x53FB, 0xDFB8, 0x5412, 0xDFB9, 0x5416, 0xDFBA, 0x5406, 0xDFBB, 0x544B, 0xDFBC, 0x5452, 0xDFBD, 0x5453, 0xDFBE, 0x5454, + 0xDFBF, 0x5456, 0xDFC0, 0x5443, 0xDFC1, 0x5421, 0xDFC2, 0x5457, 0xDFC3, 0x5459, 0xDFC4, 0x5423, 0xDFC5, 0x5432, 0xDFC6, 0x5482, + 0xDFC7, 0x5494, 0xDFC8, 0x5477, 0xDFC9, 0x5471, 0xDFCA, 0x5464, 0xDFCB, 0x549A, 0xDFCC, 0x549B, 0xDFCD, 0x5484, 0xDFCE, 0x5476, + 0xDFCF, 0x5466, 0xDFD0, 0x549D, 0xDFD1, 0x54D0, 0xDFD2, 0x54AD, 0xDFD3, 0x54C2, 0xDFD4, 0x54B4, 0xDFD5, 0x54D2, 0xDFD6, 0x54A7, + 0xDFD7, 0x54A6, 0xDFD8, 0x54D3, 0xDFD9, 0x54D4, 0xDFDA, 0x5472, 0xDFDB, 0x54A3, 0xDFDC, 0x54D5, 0xDFDD, 0x54BB, 0xDFDE, 0x54BF, + 0xDFDF, 0x54CC, 0xDFE0, 0x54D9, 0xDFE1, 0x54DA, 0xDFE2, 0x54DC, 0xDFE3, 0x54A9, 0xDFE4, 0x54AA, 0xDFE5, 0x54A4, 0xDFE6, 0x54DD, + 0xDFE7, 0x54CF, 0xDFE8, 0x54DE, 0xDFE9, 0x551B, 0xDFEA, 0x54E7, 0xDFEB, 0x5520, 0xDFEC, 0x54FD, 0xDFED, 0x5514, 0xDFEE, 0x54F3, + 0xDFEF, 0x5522, 0xDFF0, 0x5523, 0xDFF1, 0x550F, 0xDFF2, 0x5511, 0xDFF3, 0x5527, 0xDFF4, 0x552A, 0xDFF5, 0x5567, 0xDFF6, 0x558F, + 0xDFF7, 0x55B5, 0xDFF8, 0x5549, 0xDFF9, 0x556D, 0xDFFA, 0x5541, 0xDFFB, 0x5555, 0xDFFC, 0x553F, 0xDFFD, 0x5550, 0xDFFE, 0x553C, + 0xE040, 0x90C2, 0xE041, 0x90C3, 0xE042, 0x90C6, 0xE043, 0x90C8, 0xE044, 0x90C9, 0xE045, 0x90CB, 0xE046, 0x90CC, 0xE047, 0x90CD, + 0xE048, 0x90D2, 0xE049, 0x90D4, 0xE04A, 0x90D5, 0xE04B, 0x90D6, 0xE04C, 0x90D8, 0xE04D, 0x90D9, 0xE04E, 0x90DA, 0xE04F, 0x90DE, + 0xE050, 0x90DF, 0xE051, 0x90E0, 0xE052, 0x90E3, 0xE053, 0x90E4, 0xE054, 0x90E5, 0xE055, 0x90E9, 0xE056, 0x90EA, 0xE057, 0x90EC, + 0xE058, 0x90EE, 0xE059, 0x90F0, 0xE05A, 0x90F1, 0xE05B, 0x90F2, 0xE05C, 0x90F3, 0xE05D, 0x90F5, 0xE05E, 0x90F6, 0xE05F, 0x90F7, + 0xE060, 0x90F9, 0xE061, 0x90FA, 0xE062, 0x90FB, 0xE063, 0x90FC, 0xE064, 0x90FF, 0xE065, 0x9100, 0xE066, 0x9101, 0xE067, 0x9103, + 0xE068, 0x9105, 0xE069, 0x9106, 0xE06A, 0x9107, 0xE06B, 0x9108, 0xE06C, 0x9109, 0xE06D, 0x910A, 0xE06E, 0x910B, 0xE06F, 0x910C, + 0xE070, 0x910D, 0xE071, 0x910E, 0xE072, 0x910F, 0xE073, 0x9110, 0xE074, 0x9111, 0xE075, 0x9112, 0xE076, 0x9113, 0xE077, 0x9114, + 0xE078, 0x9115, 0xE079, 0x9116, 0xE07A, 0x9117, 0xE07B, 0x9118, 0xE07C, 0x911A, 0xE07D, 0x911B, 0xE07E, 0x911C, 0xE080, 0x911D, + 0xE081, 0x911F, 0xE082, 0x9120, 0xE083, 0x9121, 0xE084, 0x9124, 0xE085, 0x9125, 0xE086, 0x9126, 0xE087, 0x9127, 0xE088, 0x9128, + 0xE089, 0x9129, 0xE08A, 0x912A, 0xE08B, 0x912B, 0xE08C, 0x912C, 0xE08D, 0x912D, 0xE08E, 0x912E, 0xE08F, 0x9130, 0xE090, 0x9132, + 0xE091, 0x9133, 0xE092, 0x9134, 0xE093, 0x9135, 0xE094, 0x9136, 0xE095, 0x9137, 0xE096, 0x9138, 0xE097, 0x913A, 0xE098, 0x913B, + 0xE099, 0x913C, 0xE09A, 0x913D, 0xE09B, 0x913E, 0xE09C, 0x913F, 0xE09D, 0x9140, 0xE09E, 0x9141, 0xE09F, 0x9142, 0xE0A0, 0x9144, + 0xE0A1, 0x5537, 0xE0A2, 0x5556, 0xE0A3, 0x5575, 0xE0A4, 0x5576, 0xE0A5, 0x5577, 0xE0A6, 0x5533, 0xE0A7, 0x5530, 0xE0A8, 0x555C, + 0xE0A9, 0x558B, 0xE0AA, 0x55D2, 0xE0AB, 0x5583, 0xE0AC, 0x55B1, 0xE0AD, 0x55B9, 0xE0AE, 0x5588, 0xE0AF, 0x5581, 0xE0B0, 0x559F, + 0xE0B1, 0x557E, 0xE0B2, 0x55D6, 0xE0B3, 0x5591, 0xE0B4, 0x557B, 0xE0B5, 0x55DF, 0xE0B6, 0x55BD, 0xE0B7, 0x55BE, 0xE0B8, 0x5594, + 0xE0B9, 0x5599, 0xE0BA, 0x55EA, 0xE0BB, 0x55F7, 0xE0BC, 0x55C9, 0xE0BD, 0x561F, 0xE0BE, 0x55D1, 0xE0BF, 0x55EB, 0xE0C0, 0x55EC, + 0xE0C1, 0x55D4, 0xE0C2, 0x55E6, 0xE0C3, 0x55DD, 0xE0C4, 0x55C4, 0xE0C5, 0x55EF, 0xE0C6, 0x55E5, 0xE0C7, 0x55F2, 0xE0C8, 0x55F3, + 0xE0C9, 0x55CC, 0xE0CA, 0x55CD, 0xE0CB, 0x55E8, 0xE0CC, 0x55F5, 0xE0CD, 0x55E4, 0xE0CE, 0x8F94, 0xE0CF, 0x561E, 0xE0D0, 0x5608, + 0xE0D1, 0x560C, 0xE0D2, 0x5601, 0xE0D3, 0x5624, 0xE0D4, 0x5623, 0xE0D5, 0x55FE, 0xE0D6, 0x5600, 0xE0D7, 0x5627, 0xE0D8, 0x562D, + 0xE0D9, 0x5658, 0xE0DA, 0x5639, 0xE0DB, 0x5657, 0xE0DC, 0x562C, 0xE0DD, 0x564D, 0xE0DE, 0x5662, 0xE0DF, 0x5659, 0xE0E0, 0x565C, + 0xE0E1, 0x564C, 0xE0E2, 0x5654, 0xE0E3, 0x5686, 0xE0E4, 0x5664, 0xE0E5, 0x5671, 0xE0E6, 0x566B, 0xE0E7, 0x567B, 0xE0E8, 0x567C, + 0xE0E9, 0x5685, 0xE0EA, 0x5693, 0xE0EB, 0x56AF, 0xE0EC, 0x56D4, 0xE0ED, 0x56D7, 0xE0EE, 0x56DD, 0xE0EF, 0x56E1, 0xE0F0, 0x56F5, + 0xE0F1, 0x56EB, 0xE0F2, 0x56F9, 0xE0F3, 0x56FF, 0xE0F4, 0x5704, 0xE0F5, 0x570A, 0xE0F6, 0x5709, 0xE0F7, 0x571C, 0xE0F8, 0x5E0F, + 0xE0F9, 0x5E19, 0xE0FA, 0x5E14, 0xE0FB, 0x5E11, 0xE0FC, 0x5E31, 0xE0FD, 0x5E3B, 0xE0FE, 0x5E3C, 0xE140, 0x9145, 0xE141, 0x9147, + 0xE142, 0x9148, 0xE143, 0x9151, 0xE144, 0x9153, 0xE145, 0x9154, 0xE146, 0x9155, 0xE147, 0x9156, 0xE148, 0x9158, 0xE149, 0x9159, + 0xE14A, 0x915B, 0xE14B, 0x915C, 0xE14C, 0x915F, 0xE14D, 0x9160, 0xE14E, 0x9166, 0xE14F, 0x9167, 0xE150, 0x9168, 0xE151, 0x916B, + 0xE152, 0x916D, 0xE153, 0x9173, 0xE154, 0x917A, 0xE155, 0x917B, 0xE156, 0x917C, 0xE157, 0x9180, 0xE158, 0x9181, 0xE159, 0x9182, + 0xE15A, 0x9183, 0xE15B, 0x9184, 0xE15C, 0x9186, 0xE15D, 0x9188, 0xE15E, 0x918A, 0xE15F, 0x918E, 0xE160, 0x918F, 0xE161, 0x9193, + 0xE162, 0x9194, 0xE163, 0x9195, 0xE164, 0x9196, 0xE165, 0x9197, 0xE166, 0x9198, 0xE167, 0x9199, 0xE168, 0x919C, 0xE169, 0x919D, + 0xE16A, 0x919E, 0xE16B, 0x919F, 0xE16C, 0x91A0, 0xE16D, 0x91A1, 0xE16E, 0x91A4, 0xE16F, 0x91A5, 0xE170, 0x91A6, 0xE171, 0x91A7, + 0xE172, 0x91A8, 0xE173, 0x91A9, 0xE174, 0x91AB, 0xE175, 0x91AC, 0xE176, 0x91B0, 0xE177, 0x91B1, 0xE178, 0x91B2, 0xE179, 0x91B3, + 0xE17A, 0x91B6, 0xE17B, 0x91B7, 0xE17C, 0x91B8, 0xE17D, 0x91B9, 0xE17E, 0x91BB, 0xE180, 0x91BC, 0xE181, 0x91BD, 0xE182, 0x91BE, + 0xE183, 0x91BF, 0xE184, 0x91C0, 0xE185, 0x91C1, 0xE186, 0x91C2, 0xE187, 0x91C3, 0xE188, 0x91C4, 0xE189, 0x91C5, 0xE18A, 0x91C6, + 0xE18B, 0x91C8, 0xE18C, 0x91CB, 0xE18D, 0x91D0, 0xE18E, 0x91D2, 0xE18F, 0x91D3, 0xE190, 0x91D4, 0xE191, 0x91D5, 0xE192, 0x91D6, + 0xE193, 0x91D7, 0xE194, 0x91D8, 0xE195, 0x91D9, 0xE196, 0x91DA, 0xE197, 0x91DB, 0xE198, 0x91DD, 0xE199, 0x91DE, 0xE19A, 0x91DF, + 0xE19B, 0x91E0, 0xE19C, 0x91E1, 0xE19D, 0x91E2, 0xE19E, 0x91E3, 0xE19F, 0x91E4, 0xE1A0, 0x91E5, 0xE1A1, 0x5E37, 0xE1A2, 0x5E44, + 0xE1A3, 0x5E54, 0xE1A4, 0x5E5B, 0xE1A5, 0x5E5E, 0xE1A6, 0x5E61, 0xE1A7, 0x5C8C, 0xE1A8, 0x5C7A, 0xE1A9, 0x5C8D, 0xE1AA, 0x5C90, + 0xE1AB, 0x5C96, 0xE1AC, 0x5C88, 0xE1AD, 0x5C98, 0xE1AE, 0x5C99, 0xE1AF, 0x5C91, 0xE1B0, 0x5C9A, 0xE1B1, 0x5C9C, 0xE1B2, 0x5CB5, + 0xE1B3, 0x5CA2, 0xE1B4, 0x5CBD, 0xE1B5, 0x5CAC, 0xE1B6, 0x5CAB, 0xE1B7, 0x5CB1, 0xE1B8, 0x5CA3, 0xE1B9, 0x5CC1, 0xE1BA, 0x5CB7, + 0xE1BB, 0x5CC4, 0xE1BC, 0x5CD2, 0xE1BD, 0x5CE4, 0xE1BE, 0x5CCB, 0xE1BF, 0x5CE5, 0xE1C0, 0x5D02, 0xE1C1, 0x5D03, 0xE1C2, 0x5D27, + 0xE1C3, 0x5D26, 0xE1C4, 0x5D2E, 0xE1C5, 0x5D24, 0xE1C6, 0x5D1E, 0xE1C7, 0x5D06, 0xE1C8, 0x5D1B, 0xE1C9, 0x5D58, 0xE1CA, 0x5D3E, + 0xE1CB, 0x5D34, 0xE1CC, 0x5D3D, 0xE1CD, 0x5D6C, 0xE1CE, 0x5D5B, 0xE1CF, 0x5D6F, 0xE1D0, 0x5D5D, 0xE1D1, 0x5D6B, 0xE1D2, 0x5D4B, + 0xE1D3, 0x5D4A, 0xE1D4, 0x5D69, 0xE1D5, 0x5D74, 0xE1D6, 0x5D82, 0xE1D7, 0x5D99, 0xE1D8, 0x5D9D, 0xE1D9, 0x8C73, 0xE1DA, 0x5DB7, + 0xE1DB, 0x5DC5, 0xE1DC, 0x5F73, 0xE1DD, 0x5F77, 0xE1DE, 0x5F82, 0xE1DF, 0x5F87, 0xE1E0, 0x5F89, 0xE1E1, 0x5F8C, 0xE1E2, 0x5F95, + 0xE1E3, 0x5F99, 0xE1E4, 0x5F9C, 0xE1E5, 0x5FA8, 0xE1E6, 0x5FAD, 0xE1E7, 0x5FB5, 0xE1E8, 0x5FBC, 0xE1E9, 0x8862, 0xE1EA, 0x5F61, + 0xE1EB, 0x72AD, 0xE1EC, 0x72B0, 0xE1ED, 0x72B4, 0xE1EE, 0x72B7, 0xE1EF, 0x72B8, 0xE1F0, 0x72C3, 0xE1F1, 0x72C1, 0xE1F2, 0x72CE, + 0xE1F3, 0x72CD, 0xE1F4, 0x72D2, 0xE1F5, 0x72E8, 0xE1F6, 0x72EF, 0xE1F7, 0x72E9, 0xE1F8, 0x72F2, 0xE1F9, 0x72F4, 0xE1FA, 0x72F7, + 0xE1FB, 0x7301, 0xE1FC, 0x72F3, 0xE1FD, 0x7303, 0xE1FE, 0x72FA, 0xE240, 0x91E6, 0xE241, 0x91E7, 0xE242, 0x91E8, 0xE243, 0x91E9, + 0xE244, 0x91EA, 0xE245, 0x91EB, 0xE246, 0x91EC, 0xE247, 0x91ED, 0xE248, 0x91EE, 0xE249, 0x91EF, 0xE24A, 0x91F0, 0xE24B, 0x91F1, + 0xE24C, 0x91F2, 0xE24D, 0x91F3, 0xE24E, 0x91F4, 0xE24F, 0x91F5, 0xE250, 0x91F6, 0xE251, 0x91F7, 0xE252, 0x91F8, 0xE253, 0x91F9, + 0xE254, 0x91FA, 0xE255, 0x91FB, 0xE256, 0x91FC, 0xE257, 0x91FD, 0xE258, 0x91FE, 0xE259, 0x91FF, 0xE25A, 0x9200, 0xE25B, 0x9201, + 0xE25C, 0x9202, 0xE25D, 0x9203, 0xE25E, 0x9204, 0xE25F, 0x9205, 0xE260, 0x9206, 0xE261, 0x9207, 0xE262, 0x9208, 0xE263, 0x9209, + 0xE264, 0x920A, 0xE265, 0x920B, 0xE266, 0x920C, 0xE267, 0x920D, 0xE268, 0x920E, 0xE269, 0x920F, 0xE26A, 0x9210, 0xE26B, 0x9211, + 0xE26C, 0x9212, 0xE26D, 0x9213, 0xE26E, 0x9214, 0xE26F, 0x9215, 0xE270, 0x9216, 0xE271, 0x9217, 0xE272, 0x9218, 0xE273, 0x9219, + 0xE274, 0x921A, 0xE275, 0x921B, 0xE276, 0x921C, 0xE277, 0x921D, 0xE278, 0x921E, 0xE279, 0x921F, 0xE27A, 0x9220, 0xE27B, 0x9221, + 0xE27C, 0x9222, 0xE27D, 0x9223, 0xE27E, 0x9224, 0xE280, 0x9225, 0xE281, 0x9226, 0xE282, 0x9227, 0xE283, 0x9228, 0xE284, 0x9229, + 0xE285, 0x922A, 0xE286, 0x922B, 0xE287, 0x922C, 0xE288, 0x922D, 0xE289, 0x922E, 0xE28A, 0x922F, 0xE28B, 0x9230, 0xE28C, 0x9231, + 0xE28D, 0x9232, 0xE28E, 0x9233, 0xE28F, 0x9234, 0xE290, 0x9235, 0xE291, 0x9236, 0xE292, 0x9237, 0xE293, 0x9238, 0xE294, 0x9239, + 0xE295, 0x923A, 0xE296, 0x923B, 0xE297, 0x923C, 0xE298, 0x923D, 0xE299, 0x923E, 0xE29A, 0x923F, 0xE29B, 0x9240, 0xE29C, 0x9241, + 0xE29D, 0x9242, 0xE29E, 0x9243, 0xE29F, 0x9244, 0xE2A0, 0x9245, 0xE2A1, 0x72FB, 0xE2A2, 0x7317, 0xE2A3, 0x7313, 0xE2A4, 0x7321, + 0xE2A5, 0x730A, 0xE2A6, 0x731E, 0xE2A7, 0x731D, 0xE2A8, 0x7315, 0xE2A9, 0x7322, 0xE2AA, 0x7339, 0xE2AB, 0x7325, 0xE2AC, 0x732C, + 0xE2AD, 0x7338, 0xE2AE, 0x7331, 0xE2AF, 0x7350, 0xE2B0, 0x734D, 0xE2B1, 0x7357, 0xE2B2, 0x7360, 0xE2B3, 0x736C, 0xE2B4, 0x736F, + 0xE2B5, 0x737E, 0xE2B6, 0x821B, 0xE2B7, 0x5925, 0xE2B8, 0x98E7, 0xE2B9, 0x5924, 0xE2BA, 0x5902, 0xE2BB, 0x9963, 0xE2BC, 0x9967, + 0xE2BD, 0x9968, 0xE2BE, 0x9969, 0xE2BF, 0x996A, 0xE2C0, 0x996B, 0xE2C1, 0x996C, 0xE2C2, 0x9974, 0xE2C3, 0x9977, 0xE2C4, 0x997D, + 0xE2C5, 0x9980, 0xE2C6, 0x9984, 0xE2C7, 0x9987, 0xE2C8, 0x998A, 0xE2C9, 0x998D, 0xE2CA, 0x9990, 0xE2CB, 0x9991, 0xE2CC, 0x9993, + 0xE2CD, 0x9994, 0xE2CE, 0x9995, 0xE2CF, 0x5E80, 0xE2D0, 0x5E91, 0xE2D1, 0x5E8B, 0xE2D2, 0x5E96, 0xE2D3, 0x5EA5, 0xE2D4, 0x5EA0, + 0xE2D5, 0x5EB9, 0xE2D6, 0x5EB5, 0xE2D7, 0x5EBE, 0xE2D8, 0x5EB3, 0xE2D9, 0x8D53, 0xE2DA, 0x5ED2, 0xE2DB, 0x5ED1, 0xE2DC, 0x5EDB, + 0xE2DD, 0x5EE8, 0xE2DE, 0x5EEA, 0xE2DF, 0x81BA, 0xE2E0, 0x5FC4, 0xE2E1, 0x5FC9, 0xE2E2, 0x5FD6, 0xE2E3, 0x5FCF, 0xE2E4, 0x6003, + 0xE2E5, 0x5FEE, 0xE2E6, 0x6004, 0xE2E7, 0x5FE1, 0xE2E8, 0x5FE4, 0xE2E9, 0x5FFE, 0xE2EA, 0x6005, 0xE2EB, 0x6006, 0xE2EC, 0x5FEA, + 0xE2ED, 0x5FED, 0xE2EE, 0x5FF8, 0xE2EF, 0x6019, 0xE2F0, 0x6035, 0xE2F1, 0x6026, 0xE2F2, 0x601B, 0xE2F3, 0x600F, 0xE2F4, 0x600D, + 0xE2F5, 0x6029, 0xE2F6, 0x602B, 0xE2F7, 0x600A, 0xE2F8, 0x603F, 0xE2F9, 0x6021, 0xE2FA, 0x6078, 0xE2FB, 0x6079, 0xE2FC, 0x607B, + 0xE2FD, 0x607A, 0xE2FE, 0x6042, 0xE340, 0x9246, 0xE341, 0x9247, 0xE342, 0x9248, 0xE343, 0x9249, 0xE344, 0x924A, 0xE345, 0x924B, + 0xE346, 0x924C, 0xE347, 0x924D, 0xE348, 0x924E, 0xE349, 0x924F, 0xE34A, 0x9250, 0xE34B, 0x9251, 0xE34C, 0x9252, 0xE34D, 0x9253, + 0xE34E, 0x9254, 0xE34F, 0x9255, 0xE350, 0x9256, 0xE351, 0x9257, 0xE352, 0x9258, 0xE353, 0x9259, 0xE354, 0x925A, 0xE355, 0x925B, + 0xE356, 0x925C, 0xE357, 0x925D, 0xE358, 0x925E, 0xE359, 0x925F, 0xE35A, 0x9260, 0xE35B, 0x9261, 0xE35C, 0x9262, 0xE35D, 0x9263, + 0xE35E, 0x9264, 0xE35F, 0x9265, 0xE360, 0x9266, 0xE361, 0x9267, 0xE362, 0x9268, 0xE363, 0x9269, 0xE364, 0x926A, 0xE365, 0x926B, + 0xE366, 0x926C, 0xE367, 0x926D, 0xE368, 0x926E, 0xE369, 0x926F, 0xE36A, 0x9270, 0xE36B, 0x9271, 0xE36C, 0x9272, 0xE36D, 0x9273, + 0xE36E, 0x9275, 0xE36F, 0x9276, 0xE370, 0x9277, 0xE371, 0x9278, 0xE372, 0x9279, 0xE373, 0x927A, 0xE374, 0x927B, 0xE375, 0x927C, + 0xE376, 0x927D, 0xE377, 0x927E, 0xE378, 0x927F, 0xE379, 0x9280, 0xE37A, 0x9281, 0xE37B, 0x9282, 0xE37C, 0x9283, 0xE37D, 0x9284, + 0xE37E, 0x9285, 0xE380, 0x9286, 0xE381, 0x9287, 0xE382, 0x9288, 0xE383, 0x9289, 0xE384, 0x928A, 0xE385, 0x928B, 0xE386, 0x928C, + 0xE387, 0x928D, 0xE388, 0x928F, 0xE389, 0x9290, 0xE38A, 0x9291, 0xE38B, 0x9292, 0xE38C, 0x9293, 0xE38D, 0x9294, 0xE38E, 0x9295, + 0xE38F, 0x9296, 0xE390, 0x9297, 0xE391, 0x9298, 0xE392, 0x9299, 0xE393, 0x929A, 0xE394, 0x929B, 0xE395, 0x929C, 0xE396, 0x929D, + 0xE397, 0x929E, 0xE398, 0x929F, 0xE399, 0x92A0, 0xE39A, 0x92A1, 0xE39B, 0x92A2, 0xE39C, 0x92A3, 0xE39D, 0x92A4, 0xE39E, 0x92A5, + 0xE39F, 0x92A6, 0xE3A0, 0x92A7, 0xE3A1, 0x606A, 0xE3A2, 0x607D, 0xE3A3, 0x6096, 0xE3A4, 0x609A, 0xE3A5, 0x60AD, 0xE3A6, 0x609D, + 0xE3A7, 0x6083, 0xE3A8, 0x6092, 0xE3A9, 0x608C, 0xE3AA, 0x609B, 0xE3AB, 0x60EC, 0xE3AC, 0x60BB, 0xE3AD, 0x60B1, 0xE3AE, 0x60DD, + 0xE3AF, 0x60D8, 0xE3B0, 0x60C6, 0xE3B1, 0x60DA, 0xE3B2, 0x60B4, 0xE3B3, 0x6120, 0xE3B4, 0x6126, 0xE3B5, 0x6115, 0xE3B6, 0x6123, + 0xE3B7, 0x60F4, 0xE3B8, 0x6100, 0xE3B9, 0x610E, 0xE3BA, 0x612B, 0xE3BB, 0x614A, 0xE3BC, 0x6175, 0xE3BD, 0x61AC, 0xE3BE, 0x6194, + 0xE3BF, 0x61A7, 0xE3C0, 0x61B7, 0xE3C1, 0x61D4, 0xE3C2, 0x61F5, 0xE3C3, 0x5FDD, 0xE3C4, 0x96B3, 0xE3C5, 0x95E9, 0xE3C6, 0x95EB, + 0xE3C7, 0x95F1, 0xE3C8, 0x95F3, 0xE3C9, 0x95F5, 0xE3CA, 0x95F6, 0xE3CB, 0x95FC, 0xE3CC, 0x95FE, 0xE3CD, 0x9603, 0xE3CE, 0x9604, + 0xE3CF, 0x9606, 0xE3D0, 0x9608, 0xE3D1, 0x960A, 0xE3D2, 0x960B, 0xE3D3, 0x960C, 0xE3D4, 0x960D, 0xE3D5, 0x960F, 0xE3D6, 0x9612, + 0xE3D7, 0x9615, 0xE3D8, 0x9616, 0xE3D9, 0x9617, 0xE3DA, 0x9619, 0xE3DB, 0x961A, 0xE3DC, 0x4E2C, 0xE3DD, 0x723F, 0xE3DE, 0x6215, + 0xE3DF, 0x6C35, 0xE3E0, 0x6C54, 0xE3E1, 0x6C5C, 0xE3E2, 0x6C4A, 0xE3E3, 0x6CA3, 0xE3E4, 0x6C85, 0xE3E5, 0x6C90, 0xE3E6, 0x6C94, + 0xE3E7, 0x6C8C, 0xE3E8, 0x6C68, 0xE3E9, 0x6C69, 0xE3EA, 0x6C74, 0xE3EB, 0x6C76, 0xE3EC, 0x6C86, 0xE3ED, 0x6CA9, 0xE3EE, 0x6CD0, + 0xE3EF, 0x6CD4, 0xE3F0, 0x6CAD, 0xE3F1, 0x6CF7, 0xE3F2, 0x6CF8, 0xE3F3, 0x6CF1, 0xE3F4, 0x6CD7, 0xE3F5, 0x6CB2, 0xE3F6, 0x6CE0, + 0xE3F7, 0x6CD6, 0xE3F8, 0x6CFA, 0xE3F9, 0x6CEB, 0xE3FA, 0x6CEE, 0xE3FB, 0x6CB1, 0xE3FC, 0x6CD3, 0xE3FD, 0x6CEF, 0xE3FE, 0x6CFE, + 0xE440, 0x92A8, 0xE441, 0x92A9, 0xE442, 0x92AA, 0xE443, 0x92AB, 0xE444, 0x92AC, 0xE445, 0x92AD, 0xE446, 0x92AF, 0xE447, 0x92B0, + 0xE448, 0x92B1, 0xE449, 0x92B2, 0xE44A, 0x92B3, 0xE44B, 0x92B4, 0xE44C, 0x92B5, 0xE44D, 0x92B6, 0xE44E, 0x92B7, 0xE44F, 0x92B8, + 0xE450, 0x92B9, 0xE451, 0x92BA, 0xE452, 0x92BB, 0xE453, 0x92BC, 0xE454, 0x92BD, 0xE455, 0x92BE, 0xE456, 0x92BF, 0xE457, 0x92C0, + 0xE458, 0x92C1, 0xE459, 0x92C2, 0xE45A, 0x92C3, 0xE45B, 0x92C4, 0xE45C, 0x92C5, 0xE45D, 0x92C6, 0xE45E, 0x92C7, 0xE45F, 0x92C9, + 0xE460, 0x92CA, 0xE461, 0x92CB, 0xE462, 0x92CC, 0xE463, 0x92CD, 0xE464, 0x92CE, 0xE465, 0x92CF, 0xE466, 0x92D0, 0xE467, 0x92D1, + 0xE468, 0x92D2, 0xE469, 0x92D3, 0xE46A, 0x92D4, 0xE46B, 0x92D5, 0xE46C, 0x92D6, 0xE46D, 0x92D7, 0xE46E, 0x92D8, 0xE46F, 0x92D9, + 0xE470, 0x92DA, 0xE471, 0x92DB, 0xE472, 0x92DC, 0xE473, 0x92DD, 0xE474, 0x92DE, 0xE475, 0x92DF, 0xE476, 0x92E0, 0xE477, 0x92E1, + 0xE478, 0x92E2, 0xE479, 0x92E3, 0xE47A, 0x92E4, 0xE47B, 0x92E5, 0xE47C, 0x92E6, 0xE47D, 0x92E7, 0xE47E, 0x92E8, 0xE480, 0x92E9, + 0xE481, 0x92EA, 0xE482, 0x92EB, 0xE483, 0x92EC, 0xE484, 0x92ED, 0xE485, 0x92EE, 0xE486, 0x92EF, 0xE487, 0x92F0, 0xE488, 0x92F1, + 0xE489, 0x92F2, 0xE48A, 0x92F3, 0xE48B, 0x92F4, 0xE48C, 0x92F5, 0xE48D, 0x92F6, 0xE48E, 0x92F7, 0xE48F, 0x92F8, 0xE490, 0x92F9, + 0xE491, 0x92FA, 0xE492, 0x92FB, 0xE493, 0x92FC, 0xE494, 0x92FD, 0xE495, 0x92FE, 0xE496, 0x92FF, 0xE497, 0x9300, 0xE498, 0x9301, + 0xE499, 0x9302, 0xE49A, 0x9303, 0xE49B, 0x9304, 0xE49C, 0x9305, 0xE49D, 0x9306, 0xE49E, 0x9307, 0xE49F, 0x9308, 0xE4A0, 0x9309, + 0xE4A1, 0x6D39, 0xE4A2, 0x6D27, 0xE4A3, 0x6D0C, 0xE4A4, 0x6D43, 0xE4A5, 0x6D48, 0xE4A6, 0x6D07, 0xE4A7, 0x6D04, 0xE4A8, 0x6D19, + 0xE4A9, 0x6D0E, 0xE4AA, 0x6D2B, 0xE4AB, 0x6D4D, 0xE4AC, 0x6D2E, 0xE4AD, 0x6D35, 0xE4AE, 0x6D1A, 0xE4AF, 0x6D4F, 0xE4B0, 0x6D52, + 0xE4B1, 0x6D54, 0xE4B2, 0x6D33, 0xE4B3, 0x6D91, 0xE4B4, 0x6D6F, 0xE4B5, 0x6D9E, 0xE4B6, 0x6DA0, 0xE4B7, 0x6D5E, 0xE4B8, 0x6D93, + 0xE4B9, 0x6D94, 0xE4BA, 0x6D5C, 0xE4BB, 0x6D60, 0xE4BC, 0x6D7C, 0xE4BD, 0x6D63, 0xE4BE, 0x6E1A, 0xE4BF, 0x6DC7, 0xE4C0, 0x6DC5, + 0xE4C1, 0x6DDE, 0xE4C2, 0x6E0E, 0xE4C3, 0x6DBF, 0xE4C4, 0x6DE0, 0xE4C5, 0x6E11, 0xE4C6, 0x6DE6, 0xE4C7, 0x6DDD, 0xE4C8, 0x6DD9, + 0xE4C9, 0x6E16, 0xE4CA, 0x6DAB, 0xE4CB, 0x6E0C, 0xE4CC, 0x6DAE, 0xE4CD, 0x6E2B, 0xE4CE, 0x6E6E, 0xE4CF, 0x6E4E, 0xE4D0, 0x6E6B, + 0xE4D1, 0x6EB2, 0xE4D2, 0x6E5F, 0xE4D3, 0x6E86, 0xE4D4, 0x6E53, 0xE4D5, 0x6E54, 0xE4D6, 0x6E32, 0xE4D7, 0x6E25, 0xE4D8, 0x6E44, + 0xE4D9, 0x6EDF, 0xE4DA, 0x6EB1, 0xE4DB, 0x6E98, 0xE4DC, 0x6EE0, 0xE4DD, 0x6F2D, 0xE4DE, 0x6EE2, 0xE4DF, 0x6EA5, 0xE4E0, 0x6EA7, + 0xE4E1, 0x6EBD, 0xE4E2, 0x6EBB, 0xE4E3, 0x6EB7, 0xE4E4, 0x6ED7, 0xE4E5, 0x6EB4, 0xE4E6, 0x6ECF, 0xE4E7, 0x6E8F, 0xE4E8, 0x6EC2, + 0xE4E9, 0x6E9F, 0xE4EA, 0x6F62, 0xE4EB, 0x6F46, 0xE4EC, 0x6F47, 0xE4ED, 0x6F24, 0xE4EE, 0x6F15, 0xE4EF, 0x6EF9, 0xE4F0, 0x6F2F, + 0xE4F1, 0x6F36, 0xE4F2, 0x6F4B, 0xE4F3, 0x6F74, 0xE4F4, 0x6F2A, 0xE4F5, 0x6F09, 0xE4F6, 0x6F29, 0xE4F7, 0x6F89, 0xE4F8, 0x6F8D, + 0xE4F9, 0x6F8C, 0xE4FA, 0x6F78, 0xE4FB, 0x6F72, 0xE4FC, 0x6F7C, 0xE4FD, 0x6F7A, 0xE4FE, 0x6FD1, 0xE540, 0x930A, 0xE541, 0x930B, + 0xE542, 0x930C, 0xE543, 0x930D, 0xE544, 0x930E, 0xE545, 0x930F, 0xE546, 0x9310, 0xE547, 0x9311, 0xE548, 0x9312, 0xE549, 0x9313, + 0xE54A, 0x9314, 0xE54B, 0x9315, 0xE54C, 0x9316, 0xE54D, 0x9317, 0xE54E, 0x9318, 0xE54F, 0x9319, 0xE550, 0x931A, 0xE551, 0x931B, + 0xE552, 0x931C, 0xE553, 0x931D, 0xE554, 0x931E, 0xE555, 0x931F, 0xE556, 0x9320, 0xE557, 0x9321, 0xE558, 0x9322, 0xE559, 0x9323, + 0xE55A, 0x9324, 0xE55B, 0x9325, 0xE55C, 0x9326, 0xE55D, 0x9327, 0xE55E, 0x9328, 0xE55F, 0x9329, 0xE560, 0x932A, 0xE561, 0x932B, + 0xE562, 0x932C, 0xE563, 0x932D, 0xE564, 0x932E, 0xE565, 0x932F, 0xE566, 0x9330, 0xE567, 0x9331, 0xE568, 0x9332, 0xE569, 0x9333, + 0xE56A, 0x9334, 0xE56B, 0x9335, 0xE56C, 0x9336, 0xE56D, 0x9337, 0xE56E, 0x9338, 0xE56F, 0x9339, 0xE570, 0x933A, 0xE571, 0x933B, + 0xE572, 0x933C, 0xE573, 0x933D, 0xE574, 0x933F, 0xE575, 0x9340, 0xE576, 0x9341, 0xE577, 0x9342, 0xE578, 0x9343, 0xE579, 0x9344, + 0xE57A, 0x9345, 0xE57B, 0x9346, 0xE57C, 0x9347, 0xE57D, 0x9348, 0xE57E, 0x9349, 0xE580, 0x934A, 0xE581, 0x934B, 0xE582, 0x934C, + 0xE583, 0x934D, 0xE584, 0x934E, 0xE585, 0x934F, 0xE586, 0x9350, 0xE587, 0x9351, 0xE588, 0x9352, 0xE589, 0x9353, 0xE58A, 0x9354, + 0xE58B, 0x9355, 0xE58C, 0x9356, 0xE58D, 0x9357, 0xE58E, 0x9358, 0xE58F, 0x9359, 0xE590, 0x935A, 0xE591, 0x935B, 0xE592, 0x935C, + 0xE593, 0x935D, 0xE594, 0x935E, 0xE595, 0x935F, 0xE596, 0x9360, 0xE597, 0x9361, 0xE598, 0x9362, 0xE599, 0x9363, 0xE59A, 0x9364, + 0xE59B, 0x9365, 0xE59C, 0x9366, 0xE59D, 0x9367, 0xE59E, 0x9368, 0xE59F, 0x9369, 0xE5A0, 0x936B, 0xE5A1, 0x6FC9, 0xE5A2, 0x6FA7, + 0xE5A3, 0x6FB9, 0xE5A4, 0x6FB6, 0xE5A5, 0x6FC2, 0xE5A6, 0x6FE1, 0xE5A7, 0x6FEE, 0xE5A8, 0x6FDE, 0xE5A9, 0x6FE0, 0xE5AA, 0x6FEF, + 0xE5AB, 0x701A, 0xE5AC, 0x7023, 0xE5AD, 0x701B, 0xE5AE, 0x7039, 0xE5AF, 0x7035, 0xE5B0, 0x704F, 0xE5B1, 0x705E, 0xE5B2, 0x5B80, + 0xE5B3, 0x5B84, 0xE5B4, 0x5B95, 0xE5B5, 0x5B93, 0xE5B6, 0x5BA5, 0xE5B7, 0x5BB8, 0xE5B8, 0x752F, 0xE5B9, 0x9A9E, 0xE5BA, 0x6434, + 0xE5BB, 0x5BE4, 0xE5BC, 0x5BEE, 0xE5BD, 0x8930, 0xE5BE, 0x5BF0, 0xE5BF, 0x8E47, 0xE5C0, 0x8B07, 0xE5C1, 0x8FB6, 0xE5C2, 0x8FD3, + 0xE5C3, 0x8FD5, 0xE5C4, 0x8FE5, 0xE5C5, 0x8FEE, 0xE5C6, 0x8FE4, 0xE5C7, 0x8FE9, 0xE5C8, 0x8FE6, 0xE5C9, 0x8FF3, 0xE5CA, 0x8FE8, + 0xE5CB, 0x9005, 0xE5CC, 0x9004, 0xE5CD, 0x900B, 0xE5CE, 0x9026, 0xE5CF, 0x9011, 0xE5D0, 0x900D, 0xE5D1, 0x9016, 0xE5D2, 0x9021, + 0xE5D3, 0x9035, 0xE5D4, 0x9036, 0xE5D5, 0x902D, 0xE5D6, 0x902F, 0xE5D7, 0x9044, 0xE5D8, 0x9051, 0xE5D9, 0x9052, 0xE5DA, 0x9050, + 0xE5DB, 0x9068, 0xE5DC, 0x9058, 0xE5DD, 0x9062, 0xE5DE, 0x905B, 0xE5DF, 0x66B9, 0xE5E0, 0x9074, 0xE5E1, 0x907D, 0xE5E2, 0x9082, + 0xE5E3, 0x9088, 0xE5E4, 0x9083, 0xE5E5, 0x908B, 0xE5E6, 0x5F50, 0xE5E7, 0x5F57, 0xE5E8, 0x5F56, 0xE5E9, 0x5F58, 0xE5EA, 0x5C3B, + 0xE5EB, 0x54AB, 0xE5EC, 0x5C50, 0xE5ED, 0x5C59, 0xE5EE, 0x5B71, 0xE5EF, 0x5C63, 0xE5F0, 0x5C66, 0xE5F1, 0x7FBC, 0xE5F2, 0x5F2A, + 0xE5F3, 0x5F29, 0xE5F4, 0x5F2D, 0xE5F5, 0x8274, 0xE5F6, 0x5F3C, 0xE5F7, 0x9B3B, 0xE5F8, 0x5C6E, 0xE5F9, 0x5981, 0xE5FA, 0x5983, + 0xE5FB, 0x598D, 0xE5FC, 0x59A9, 0xE5FD, 0x59AA, 0xE5FE, 0x59A3, 0xE640, 0x936C, 0xE641, 0x936D, 0xE642, 0x936E, 0xE643, 0x936F, + 0xE644, 0x9370, 0xE645, 0x9371, 0xE646, 0x9372, 0xE647, 0x9373, 0xE648, 0x9374, 0xE649, 0x9375, 0xE64A, 0x9376, 0xE64B, 0x9377, + 0xE64C, 0x9378, 0xE64D, 0x9379, 0xE64E, 0x937A, 0xE64F, 0x937B, 0xE650, 0x937C, 0xE651, 0x937D, 0xE652, 0x937E, 0xE653, 0x937F, + 0xE654, 0x9380, 0xE655, 0x9381, 0xE656, 0x9382, 0xE657, 0x9383, 0xE658, 0x9384, 0xE659, 0x9385, 0xE65A, 0x9386, 0xE65B, 0x9387, + 0xE65C, 0x9388, 0xE65D, 0x9389, 0xE65E, 0x938A, 0xE65F, 0x938B, 0xE660, 0x938C, 0xE661, 0x938D, 0xE662, 0x938E, 0xE663, 0x9390, + 0xE664, 0x9391, 0xE665, 0x9392, 0xE666, 0x9393, 0xE667, 0x9394, 0xE668, 0x9395, 0xE669, 0x9396, 0xE66A, 0x9397, 0xE66B, 0x9398, + 0xE66C, 0x9399, 0xE66D, 0x939A, 0xE66E, 0x939B, 0xE66F, 0x939C, 0xE670, 0x939D, 0xE671, 0x939E, 0xE672, 0x939F, 0xE673, 0x93A0, + 0xE674, 0x93A1, 0xE675, 0x93A2, 0xE676, 0x93A3, 0xE677, 0x93A4, 0xE678, 0x93A5, 0xE679, 0x93A6, 0xE67A, 0x93A7, 0xE67B, 0x93A8, + 0xE67C, 0x93A9, 0xE67D, 0x93AA, 0xE67E, 0x93AB, 0xE680, 0x93AC, 0xE681, 0x93AD, 0xE682, 0x93AE, 0xE683, 0x93AF, 0xE684, 0x93B0, + 0xE685, 0x93B1, 0xE686, 0x93B2, 0xE687, 0x93B3, 0xE688, 0x93B4, 0xE689, 0x93B5, 0xE68A, 0x93B6, 0xE68B, 0x93B7, 0xE68C, 0x93B8, + 0xE68D, 0x93B9, 0xE68E, 0x93BA, 0xE68F, 0x93BB, 0xE690, 0x93BC, 0xE691, 0x93BD, 0xE692, 0x93BE, 0xE693, 0x93BF, 0xE694, 0x93C0, + 0xE695, 0x93C1, 0xE696, 0x93C2, 0xE697, 0x93C3, 0xE698, 0x93C4, 0xE699, 0x93C5, 0xE69A, 0x93C6, 0xE69B, 0x93C7, 0xE69C, 0x93C8, + 0xE69D, 0x93C9, 0xE69E, 0x93CB, 0xE69F, 0x93CC, 0xE6A0, 0x93CD, 0xE6A1, 0x5997, 0xE6A2, 0x59CA, 0xE6A3, 0x59AB, 0xE6A4, 0x599E, + 0xE6A5, 0x59A4, 0xE6A6, 0x59D2, 0xE6A7, 0x59B2, 0xE6A8, 0x59AF, 0xE6A9, 0x59D7, 0xE6AA, 0x59BE, 0xE6AB, 0x5A05, 0xE6AC, 0x5A06, + 0xE6AD, 0x59DD, 0xE6AE, 0x5A08, 0xE6AF, 0x59E3, 0xE6B0, 0x59D8, 0xE6B1, 0x59F9, 0xE6B2, 0x5A0C, 0xE6B3, 0x5A09, 0xE6B4, 0x5A32, + 0xE6B5, 0x5A34, 0xE6B6, 0x5A11, 0xE6B7, 0x5A23, 0xE6B8, 0x5A13, 0xE6B9, 0x5A40, 0xE6BA, 0x5A67, 0xE6BB, 0x5A4A, 0xE6BC, 0x5A55, + 0xE6BD, 0x5A3C, 0xE6BE, 0x5A62, 0xE6BF, 0x5A75, 0xE6C0, 0x80EC, 0xE6C1, 0x5AAA, 0xE6C2, 0x5A9B, 0xE6C3, 0x5A77, 0xE6C4, 0x5A7A, + 0xE6C5, 0x5ABE, 0xE6C6, 0x5AEB, 0xE6C7, 0x5AB2, 0xE6C8, 0x5AD2, 0xE6C9, 0x5AD4, 0xE6CA, 0x5AB8, 0xE6CB, 0x5AE0, 0xE6CC, 0x5AE3, + 0xE6CD, 0x5AF1, 0xE6CE, 0x5AD6, 0xE6CF, 0x5AE6, 0xE6D0, 0x5AD8, 0xE6D1, 0x5ADC, 0xE6D2, 0x5B09, 0xE6D3, 0x5B17, 0xE6D4, 0x5B16, + 0xE6D5, 0x5B32, 0xE6D6, 0x5B37, 0xE6D7, 0x5B40, 0xE6D8, 0x5C15, 0xE6D9, 0x5C1C, 0xE6DA, 0x5B5A, 0xE6DB, 0x5B65, 0xE6DC, 0x5B73, + 0xE6DD, 0x5B51, 0xE6DE, 0x5B53, 0xE6DF, 0x5B62, 0xE6E0, 0x9A75, 0xE6E1, 0x9A77, 0xE6E2, 0x9A78, 0xE6E3, 0x9A7A, 0xE6E4, 0x9A7F, + 0xE6E5, 0x9A7D, 0xE6E6, 0x9A80, 0xE6E7, 0x9A81, 0xE6E8, 0x9A85, 0xE6E9, 0x9A88, 0xE6EA, 0x9A8A, 0xE6EB, 0x9A90, 0xE6EC, 0x9A92, + 0xE6ED, 0x9A93, 0xE6EE, 0x9A96, 0xE6EF, 0x9A98, 0xE6F0, 0x9A9B, 0xE6F1, 0x9A9C, 0xE6F2, 0x9A9D, 0xE6F3, 0x9A9F, 0xE6F4, 0x9AA0, + 0xE6F5, 0x9AA2, 0xE6F6, 0x9AA3, 0xE6F7, 0x9AA5, 0xE6F8, 0x9AA7, 0xE6F9, 0x7E9F, 0xE6FA, 0x7EA1, 0xE6FB, 0x7EA3, 0xE6FC, 0x7EA5, + 0xE6FD, 0x7EA8, 0xE6FE, 0x7EA9, 0xE740, 0x93CE, 0xE741, 0x93CF, 0xE742, 0x93D0, 0xE743, 0x93D1, 0xE744, 0x93D2, 0xE745, 0x93D3, + 0xE746, 0x93D4, 0xE747, 0x93D5, 0xE748, 0x93D7, 0xE749, 0x93D8, 0xE74A, 0x93D9, 0xE74B, 0x93DA, 0xE74C, 0x93DB, 0xE74D, 0x93DC, + 0xE74E, 0x93DD, 0xE74F, 0x93DE, 0xE750, 0x93DF, 0xE751, 0x93E0, 0xE752, 0x93E1, 0xE753, 0x93E2, 0xE754, 0x93E3, 0xE755, 0x93E4, + 0xE756, 0x93E5, 0xE757, 0x93E6, 0xE758, 0x93E7, 0xE759, 0x93E8, 0xE75A, 0x93E9, 0xE75B, 0x93EA, 0xE75C, 0x93EB, 0xE75D, 0x93EC, + 0xE75E, 0x93ED, 0xE75F, 0x93EE, 0xE760, 0x93EF, 0xE761, 0x93F0, 0xE762, 0x93F1, 0xE763, 0x93F2, 0xE764, 0x93F3, 0xE765, 0x93F4, + 0xE766, 0x93F5, 0xE767, 0x93F6, 0xE768, 0x93F7, 0xE769, 0x93F8, 0xE76A, 0x93F9, 0xE76B, 0x93FA, 0xE76C, 0x93FB, 0xE76D, 0x93FC, + 0xE76E, 0x93FD, 0xE76F, 0x93FE, 0xE770, 0x93FF, 0xE771, 0x9400, 0xE772, 0x9401, 0xE773, 0x9402, 0xE774, 0x9403, 0xE775, 0x9404, + 0xE776, 0x9405, 0xE777, 0x9406, 0xE778, 0x9407, 0xE779, 0x9408, 0xE77A, 0x9409, 0xE77B, 0x940A, 0xE77C, 0x940B, 0xE77D, 0x940C, + 0xE77E, 0x940D, 0xE780, 0x940E, 0xE781, 0x940F, 0xE782, 0x9410, 0xE783, 0x9411, 0xE784, 0x9412, 0xE785, 0x9413, 0xE786, 0x9414, + 0xE787, 0x9415, 0xE788, 0x9416, 0xE789, 0x9417, 0xE78A, 0x9418, 0xE78B, 0x9419, 0xE78C, 0x941A, 0xE78D, 0x941B, 0xE78E, 0x941C, + 0xE78F, 0x941D, 0xE790, 0x941E, 0xE791, 0x941F, 0xE792, 0x9420, 0xE793, 0x9421, 0xE794, 0x9422, 0xE795, 0x9423, 0xE796, 0x9424, + 0xE797, 0x9425, 0xE798, 0x9426, 0xE799, 0x9427, 0xE79A, 0x9428, 0xE79B, 0x9429, 0xE79C, 0x942A, 0xE79D, 0x942B, 0xE79E, 0x942C, + 0xE79F, 0x942D, 0xE7A0, 0x942E, 0xE7A1, 0x7EAD, 0xE7A2, 0x7EB0, 0xE7A3, 0x7EBE, 0xE7A4, 0x7EC0, 0xE7A5, 0x7EC1, 0xE7A6, 0x7EC2, + 0xE7A7, 0x7EC9, 0xE7A8, 0x7ECB, 0xE7A9, 0x7ECC, 0xE7AA, 0x7ED0, 0xE7AB, 0x7ED4, 0xE7AC, 0x7ED7, 0xE7AD, 0x7EDB, 0xE7AE, 0x7EE0, + 0xE7AF, 0x7EE1, 0xE7B0, 0x7EE8, 0xE7B1, 0x7EEB, 0xE7B2, 0x7EEE, 0xE7B3, 0x7EEF, 0xE7B4, 0x7EF1, 0xE7B5, 0x7EF2, 0xE7B6, 0x7F0D, + 0xE7B7, 0x7EF6, 0xE7B8, 0x7EFA, 0xE7B9, 0x7EFB, 0xE7BA, 0x7EFE, 0xE7BB, 0x7F01, 0xE7BC, 0x7F02, 0xE7BD, 0x7F03, 0xE7BE, 0x7F07, + 0xE7BF, 0x7F08, 0xE7C0, 0x7F0B, 0xE7C1, 0x7F0C, 0xE7C2, 0x7F0F, 0xE7C3, 0x7F11, 0xE7C4, 0x7F12, 0xE7C5, 0x7F17, 0xE7C6, 0x7F19, + 0xE7C7, 0x7F1C, 0xE7C8, 0x7F1B, 0xE7C9, 0x7F1F, 0xE7CA, 0x7F21, 0xE7CB, 0x7F22, 0xE7CC, 0x7F23, 0xE7CD, 0x7F24, 0xE7CE, 0x7F25, + 0xE7CF, 0x7F26, 0xE7D0, 0x7F27, 0xE7D1, 0x7F2A, 0xE7D2, 0x7F2B, 0xE7D3, 0x7F2C, 0xE7D4, 0x7F2D, 0xE7D5, 0x7F2F, 0xE7D6, 0x7F30, + 0xE7D7, 0x7F31, 0xE7D8, 0x7F32, 0xE7D9, 0x7F33, 0xE7DA, 0x7F35, 0xE7DB, 0x5E7A, 0xE7DC, 0x757F, 0xE7DD, 0x5DDB, 0xE7DE, 0x753E, + 0xE7DF, 0x9095, 0xE7E0, 0x738E, 0xE7E1, 0x7391, 0xE7E2, 0x73AE, 0xE7E3, 0x73A2, 0xE7E4, 0x739F, 0xE7E5, 0x73CF, 0xE7E6, 0x73C2, + 0xE7E7, 0x73D1, 0xE7E8, 0x73B7, 0xE7E9, 0x73B3, 0xE7EA, 0x73C0, 0xE7EB, 0x73C9, 0xE7EC, 0x73C8, 0xE7ED, 0x73E5, 0xE7EE, 0x73D9, + 0xE7EF, 0x987C, 0xE7F0, 0x740A, 0xE7F1, 0x73E9, 0xE7F2, 0x73E7, 0xE7F3, 0x73DE, 0xE7F4, 0x73BA, 0xE7F5, 0x73F2, 0xE7F6, 0x740F, + 0xE7F7, 0x742A, 0xE7F8, 0x745B, 0xE7F9, 0x7426, 0xE7FA, 0x7425, 0xE7FB, 0x7428, 0xE7FC, 0x7430, 0xE7FD, 0x742E, 0xE7FE, 0x742C, + 0xE840, 0x942F, 0xE841, 0x9430, 0xE842, 0x9431, 0xE843, 0x9432, 0xE844, 0x9433, 0xE845, 0x9434, 0xE846, 0x9435, 0xE847, 0x9436, + 0xE848, 0x9437, 0xE849, 0x9438, 0xE84A, 0x9439, 0xE84B, 0x943A, 0xE84C, 0x943B, 0xE84D, 0x943C, 0xE84E, 0x943D, 0xE84F, 0x943F, + 0xE850, 0x9440, 0xE851, 0x9441, 0xE852, 0x9442, 0xE853, 0x9443, 0xE854, 0x9444, 0xE855, 0x9445, 0xE856, 0x9446, 0xE857, 0x9447, + 0xE858, 0x9448, 0xE859, 0x9449, 0xE85A, 0x944A, 0xE85B, 0x944B, 0xE85C, 0x944C, 0xE85D, 0x944D, 0xE85E, 0x944E, 0xE85F, 0x944F, + 0xE860, 0x9450, 0xE861, 0x9451, 0xE862, 0x9452, 0xE863, 0x9453, 0xE864, 0x9454, 0xE865, 0x9455, 0xE866, 0x9456, 0xE867, 0x9457, + 0xE868, 0x9458, 0xE869, 0x9459, 0xE86A, 0x945A, 0xE86B, 0x945B, 0xE86C, 0x945C, 0xE86D, 0x945D, 0xE86E, 0x945E, 0xE86F, 0x945F, + 0xE870, 0x9460, 0xE871, 0x9461, 0xE872, 0x9462, 0xE873, 0x9463, 0xE874, 0x9464, 0xE875, 0x9465, 0xE876, 0x9466, 0xE877, 0x9467, + 0xE878, 0x9468, 0xE879, 0x9469, 0xE87A, 0x946A, 0xE87B, 0x946C, 0xE87C, 0x946D, 0xE87D, 0x946E, 0xE87E, 0x946F, 0xE880, 0x9470, + 0xE881, 0x9471, 0xE882, 0x9472, 0xE883, 0x9473, 0xE884, 0x9474, 0xE885, 0x9475, 0xE886, 0x9476, 0xE887, 0x9477, 0xE888, 0x9478, + 0xE889, 0x9479, 0xE88A, 0x947A, 0xE88B, 0x947B, 0xE88C, 0x947C, 0xE88D, 0x947D, 0xE88E, 0x947E, 0xE88F, 0x947F, 0xE890, 0x9480, + 0xE891, 0x9481, 0xE892, 0x9482, 0xE893, 0x9483, 0xE894, 0x9484, 0xE895, 0x9491, 0xE896, 0x9496, 0xE897, 0x9498, 0xE898, 0x94C7, + 0xE899, 0x94CF, 0xE89A, 0x94D3, 0xE89B, 0x94D4, 0xE89C, 0x94DA, 0xE89D, 0x94E6, 0xE89E, 0x94FB, 0xE89F, 0x951C, 0xE8A0, 0x9520, + 0xE8A1, 0x741B, 0xE8A2, 0x741A, 0xE8A3, 0x7441, 0xE8A4, 0x745C, 0xE8A5, 0x7457, 0xE8A6, 0x7455, 0xE8A7, 0x7459, 0xE8A8, 0x7477, + 0xE8A9, 0x746D, 0xE8AA, 0x747E, 0xE8AB, 0x749C, 0xE8AC, 0x748E, 0xE8AD, 0x7480, 0xE8AE, 0x7481, 0xE8AF, 0x7487, 0xE8B0, 0x748B, + 0xE8B1, 0x749E, 0xE8B2, 0x74A8, 0xE8B3, 0x74A9, 0xE8B4, 0x7490, 0xE8B5, 0x74A7, 0xE8B6, 0x74D2, 0xE8B7, 0x74BA, 0xE8B8, 0x97EA, + 0xE8B9, 0x97EB, 0xE8BA, 0x97EC, 0xE8BB, 0x674C, 0xE8BC, 0x6753, 0xE8BD, 0x675E, 0xE8BE, 0x6748, 0xE8BF, 0x6769, 0xE8C0, 0x67A5, + 0xE8C1, 0x6787, 0xE8C2, 0x676A, 0xE8C3, 0x6773, 0xE8C4, 0x6798, 0xE8C5, 0x67A7, 0xE8C6, 0x6775, 0xE8C7, 0x67A8, 0xE8C8, 0x679E, + 0xE8C9, 0x67AD, 0xE8CA, 0x678B, 0xE8CB, 0x6777, 0xE8CC, 0x677C, 0xE8CD, 0x67F0, 0xE8CE, 0x6809, 0xE8CF, 0x67D8, 0xE8D0, 0x680A, + 0xE8D1, 0x67E9, 0xE8D2, 0x67B0, 0xE8D3, 0x680C, 0xE8D4, 0x67D9, 0xE8D5, 0x67B5, 0xE8D6, 0x67DA, 0xE8D7, 0x67B3, 0xE8D8, 0x67DD, + 0xE8D9, 0x6800, 0xE8DA, 0x67C3, 0xE8DB, 0x67B8, 0xE8DC, 0x67E2, 0xE8DD, 0x680E, 0xE8DE, 0x67C1, 0xE8DF, 0x67FD, 0xE8E0, 0x6832, + 0xE8E1, 0x6833, 0xE8E2, 0x6860, 0xE8E3, 0x6861, 0xE8E4, 0x684E, 0xE8E5, 0x6862, 0xE8E6, 0x6844, 0xE8E7, 0x6864, 0xE8E8, 0x6883, + 0xE8E9, 0x681D, 0xE8EA, 0x6855, 0xE8EB, 0x6866, 0xE8EC, 0x6841, 0xE8ED, 0x6867, 0xE8EE, 0x6840, 0xE8EF, 0x683E, 0xE8F0, 0x684A, + 0xE8F1, 0x6849, 0xE8F2, 0x6829, 0xE8F3, 0x68B5, 0xE8F4, 0x688F, 0xE8F5, 0x6874, 0xE8F6, 0x6877, 0xE8F7, 0x6893, 0xE8F8, 0x686B, + 0xE8F9, 0x68C2, 0xE8FA, 0x696E, 0xE8FB, 0x68FC, 0xE8FC, 0x691F, 0xE8FD, 0x6920, 0xE8FE, 0x68F9, 0xE940, 0x9527, 0xE941, 0x9533, + 0xE942, 0x953D, 0xE943, 0x9543, 0xE944, 0x9548, 0xE945, 0x954B, 0xE946, 0x9555, 0xE947, 0x955A, 0xE948, 0x9560, 0xE949, 0x956E, + 0xE94A, 0x9574, 0xE94B, 0x9575, 0xE94C, 0x9577, 0xE94D, 0x9578, 0xE94E, 0x9579, 0xE94F, 0x957A, 0xE950, 0x957B, 0xE951, 0x957C, + 0xE952, 0x957D, 0xE953, 0x957E, 0xE954, 0x9580, 0xE955, 0x9581, 0xE956, 0x9582, 0xE957, 0x9583, 0xE958, 0x9584, 0xE959, 0x9585, + 0xE95A, 0x9586, 0xE95B, 0x9587, 0xE95C, 0x9588, 0xE95D, 0x9589, 0xE95E, 0x958A, 0xE95F, 0x958B, 0xE960, 0x958C, 0xE961, 0x958D, + 0xE962, 0x958E, 0xE963, 0x958F, 0xE964, 0x9590, 0xE965, 0x9591, 0xE966, 0x9592, 0xE967, 0x9593, 0xE968, 0x9594, 0xE969, 0x9595, + 0xE96A, 0x9596, 0xE96B, 0x9597, 0xE96C, 0x9598, 0xE96D, 0x9599, 0xE96E, 0x959A, 0xE96F, 0x959B, 0xE970, 0x959C, 0xE971, 0x959D, + 0xE972, 0x959E, 0xE973, 0x959F, 0xE974, 0x95A0, 0xE975, 0x95A1, 0xE976, 0x95A2, 0xE977, 0x95A3, 0xE978, 0x95A4, 0xE979, 0x95A5, + 0xE97A, 0x95A6, 0xE97B, 0x95A7, 0xE97C, 0x95A8, 0xE97D, 0x95A9, 0xE97E, 0x95AA, 0xE980, 0x95AB, 0xE981, 0x95AC, 0xE982, 0x95AD, + 0xE983, 0x95AE, 0xE984, 0x95AF, 0xE985, 0x95B0, 0xE986, 0x95B1, 0xE987, 0x95B2, 0xE988, 0x95B3, 0xE989, 0x95B4, 0xE98A, 0x95B5, + 0xE98B, 0x95B6, 0xE98C, 0x95B7, 0xE98D, 0x95B8, 0xE98E, 0x95B9, 0xE98F, 0x95BA, 0xE990, 0x95BB, 0xE991, 0x95BC, 0xE992, 0x95BD, + 0xE993, 0x95BE, 0xE994, 0x95BF, 0xE995, 0x95C0, 0xE996, 0x95C1, 0xE997, 0x95C2, 0xE998, 0x95C3, 0xE999, 0x95C4, 0xE99A, 0x95C5, + 0xE99B, 0x95C6, 0xE99C, 0x95C7, 0xE99D, 0x95C8, 0xE99E, 0x95C9, 0xE99F, 0x95CA, 0xE9A0, 0x95CB, 0xE9A1, 0x6924, 0xE9A2, 0x68F0, + 0xE9A3, 0x690B, 0xE9A4, 0x6901, 0xE9A5, 0x6957, 0xE9A6, 0x68E3, 0xE9A7, 0x6910, 0xE9A8, 0x6971, 0xE9A9, 0x6939, 0xE9AA, 0x6960, + 0xE9AB, 0x6942, 0xE9AC, 0x695D, 0xE9AD, 0x6984, 0xE9AE, 0x696B, 0xE9AF, 0x6980, 0xE9B0, 0x6998, 0xE9B1, 0x6978, 0xE9B2, 0x6934, + 0xE9B3, 0x69CC, 0xE9B4, 0x6987, 0xE9B5, 0x6988, 0xE9B6, 0x69CE, 0xE9B7, 0x6989, 0xE9B8, 0x6966, 0xE9B9, 0x6963, 0xE9BA, 0x6979, + 0xE9BB, 0x699B, 0xE9BC, 0x69A7, 0xE9BD, 0x69BB, 0xE9BE, 0x69AB, 0xE9BF, 0x69AD, 0xE9C0, 0x69D4, 0xE9C1, 0x69B1, 0xE9C2, 0x69C1, + 0xE9C3, 0x69CA, 0xE9C4, 0x69DF, 0xE9C5, 0x6995, 0xE9C6, 0x69E0, 0xE9C7, 0x698D, 0xE9C8, 0x69FF, 0xE9C9, 0x6A2F, 0xE9CA, 0x69ED, + 0xE9CB, 0x6A17, 0xE9CC, 0x6A18, 0xE9CD, 0x6A65, 0xE9CE, 0x69F2, 0xE9CF, 0x6A44, 0xE9D0, 0x6A3E, 0xE9D1, 0x6AA0, 0xE9D2, 0x6A50, + 0xE9D3, 0x6A5B, 0xE9D4, 0x6A35, 0xE9D5, 0x6A8E, 0xE9D6, 0x6A79, 0xE9D7, 0x6A3D, 0xE9D8, 0x6A28, 0xE9D9, 0x6A58, 0xE9DA, 0x6A7C, + 0xE9DB, 0x6A91, 0xE9DC, 0x6A90, 0xE9DD, 0x6AA9, 0xE9DE, 0x6A97, 0xE9DF, 0x6AAB, 0xE9E0, 0x7337, 0xE9E1, 0x7352, 0xE9E2, 0x6B81, + 0xE9E3, 0x6B82, 0xE9E4, 0x6B87, 0xE9E5, 0x6B84, 0xE9E6, 0x6B92, 0xE9E7, 0x6B93, 0xE9E8, 0x6B8D, 0xE9E9, 0x6B9A, 0xE9EA, 0x6B9B, + 0xE9EB, 0x6BA1, 0xE9EC, 0x6BAA, 0xE9ED, 0x8F6B, 0xE9EE, 0x8F6D, 0xE9EF, 0x8F71, 0xE9F0, 0x8F72, 0xE9F1, 0x8F73, 0xE9F2, 0x8F75, + 0xE9F3, 0x8F76, 0xE9F4, 0x8F78, 0xE9F5, 0x8F77, 0xE9F6, 0x8F79, 0xE9F7, 0x8F7A, 0xE9F8, 0x8F7C, 0xE9F9, 0x8F7E, 0xE9FA, 0x8F81, + 0xE9FB, 0x8F82, 0xE9FC, 0x8F84, 0xE9FD, 0x8F87, 0xE9FE, 0x8F8B, 0xEA40, 0x95CC, 0xEA41, 0x95CD, 0xEA42, 0x95CE, 0xEA43, 0x95CF, + 0xEA44, 0x95D0, 0xEA45, 0x95D1, 0xEA46, 0x95D2, 0xEA47, 0x95D3, 0xEA48, 0x95D4, 0xEA49, 0x95D5, 0xEA4A, 0x95D6, 0xEA4B, 0x95D7, + 0xEA4C, 0x95D8, 0xEA4D, 0x95D9, 0xEA4E, 0x95DA, 0xEA4F, 0x95DB, 0xEA50, 0x95DC, 0xEA51, 0x95DD, 0xEA52, 0x95DE, 0xEA53, 0x95DF, + 0xEA54, 0x95E0, 0xEA55, 0x95E1, 0xEA56, 0x95E2, 0xEA57, 0x95E3, 0xEA58, 0x95E4, 0xEA59, 0x95E5, 0xEA5A, 0x95E6, 0xEA5B, 0x95E7, + 0xEA5C, 0x95EC, 0xEA5D, 0x95FF, 0xEA5E, 0x9607, 0xEA5F, 0x9613, 0xEA60, 0x9618, 0xEA61, 0x961B, 0xEA62, 0x961E, 0xEA63, 0x9620, + 0xEA64, 0x9623, 0xEA65, 0x9624, 0xEA66, 0x9625, 0xEA67, 0x9626, 0xEA68, 0x9627, 0xEA69, 0x9628, 0xEA6A, 0x9629, 0xEA6B, 0x962B, + 0xEA6C, 0x962C, 0xEA6D, 0x962D, 0xEA6E, 0x962F, 0xEA6F, 0x9630, 0xEA70, 0x9637, 0xEA71, 0x9638, 0xEA72, 0x9639, 0xEA73, 0x963A, + 0xEA74, 0x963E, 0xEA75, 0x9641, 0xEA76, 0x9643, 0xEA77, 0x964A, 0xEA78, 0x964E, 0xEA79, 0x964F, 0xEA7A, 0x9651, 0xEA7B, 0x9652, + 0xEA7C, 0x9653, 0xEA7D, 0x9656, 0xEA7E, 0x9657, 0xEA80, 0x9658, 0xEA81, 0x9659, 0xEA82, 0x965A, 0xEA83, 0x965C, 0xEA84, 0x965D, + 0xEA85, 0x965E, 0xEA86, 0x9660, 0xEA87, 0x9663, 0xEA88, 0x9665, 0xEA89, 0x9666, 0xEA8A, 0x966B, 0xEA8B, 0x966D, 0xEA8C, 0x966E, + 0xEA8D, 0x966F, 0xEA8E, 0x9670, 0xEA8F, 0x9671, 0xEA90, 0x9673, 0xEA91, 0x9678, 0xEA92, 0x9679, 0xEA93, 0x967A, 0xEA94, 0x967B, + 0xEA95, 0x967C, 0xEA96, 0x967D, 0xEA97, 0x967E, 0xEA98, 0x967F, 0xEA99, 0x9680, 0xEA9A, 0x9681, 0xEA9B, 0x9682, 0xEA9C, 0x9683, + 0xEA9D, 0x9684, 0xEA9E, 0x9687, 0xEA9F, 0x9689, 0xEAA0, 0x968A, 0xEAA1, 0x8F8D, 0xEAA2, 0x8F8E, 0xEAA3, 0x8F8F, 0xEAA4, 0x8F98, + 0xEAA5, 0x8F9A, 0xEAA6, 0x8ECE, 0xEAA7, 0x620B, 0xEAA8, 0x6217, 0xEAA9, 0x621B, 0xEAAA, 0x621F, 0xEAAB, 0x6222, 0xEAAC, 0x6221, + 0xEAAD, 0x6225, 0xEAAE, 0x6224, 0xEAAF, 0x622C, 0xEAB0, 0x81E7, 0xEAB1, 0x74EF, 0xEAB2, 0x74F4, 0xEAB3, 0x74FF, 0xEAB4, 0x750F, + 0xEAB5, 0x7511, 0xEAB6, 0x7513, 0xEAB7, 0x6534, 0xEAB8, 0x65EE, 0xEAB9, 0x65EF, 0xEABA, 0x65F0, 0xEABB, 0x660A, 0xEABC, 0x6619, + 0xEABD, 0x6772, 0xEABE, 0x6603, 0xEABF, 0x6615, 0xEAC0, 0x6600, 0xEAC1, 0x7085, 0xEAC2, 0x66F7, 0xEAC3, 0x661D, 0xEAC4, 0x6634, + 0xEAC5, 0x6631, 0xEAC6, 0x6636, 0xEAC7, 0x6635, 0xEAC8, 0x8006, 0xEAC9, 0x665F, 0xEACA, 0x6654, 0xEACB, 0x6641, 0xEACC, 0x664F, + 0xEACD, 0x6656, 0xEACE, 0x6661, 0xEACF, 0x6657, 0xEAD0, 0x6677, 0xEAD1, 0x6684, 0xEAD2, 0x668C, 0xEAD3, 0x66A7, 0xEAD4, 0x669D, + 0xEAD5, 0x66BE, 0xEAD6, 0x66DB, 0xEAD7, 0x66DC, 0xEAD8, 0x66E6, 0xEAD9, 0x66E9, 0xEADA, 0x8D32, 0xEADB, 0x8D33, 0xEADC, 0x8D36, + 0xEADD, 0x8D3B, 0xEADE, 0x8D3D, 0xEADF, 0x8D40, 0xEAE0, 0x8D45, 0xEAE1, 0x8D46, 0xEAE2, 0x8D48, 0xEAE3, 0x8D49, 0xEAE4, 0x8D47, + 0xEAE5, 0x8D4D, 0xEAE6, 0x8D55, 0xEAE7, 0x8D59, 0xEAE8, 0x89C7, 0xEAE9, 0x89CA, 0xEAEA, 0x89CB, 0xEAEB, 0x89CC, 0xEAEC, 0x89CE, + 0xEAED, 0x89CF, 0xEAEE, 0x89D0, 0xEAEF, 0x89D1, 0xEAF0, 0x726E, 0xEAF1, 0x729F, 0xEAF2, 0x725D, 0xEAF3, 0x7266, 0xEAF4, 0x726F, + 0xEAF5, 0x727E, 0xEAF6, 0x727F, 0xEAF7, 0x7284, 0xEAF8, 0x728B, 0xEAF9, 0x728D, 0xEAFA, 0x728F, 0xEAFB, 0x7292, 0xEAFC, 0x6308, + 0xEAFD, 0x6332, 0xEAFE, 0x63B0, 0xEB40, 0x968C, 0xEB41, 0x968E, 0xEB42, 0x9691, 0xEB43, 0x9692, 0xEB44, 0x9693, 0xEB45, 0x9695, + 0xEB46, 0x9696, 0xEB47, 0x969A, 0xEB48, 0x969B, 0xEB49, 0x969D, 0xEB4A, 0x969E, 0xEB4B, 0x969F, 0xEB4C, 0x96A0, 0xEB4D, 0x96A1, + 0xEB4E, 0x96A2, 0xEB4F, 0x96A3, 0xEB50, 0x96A4, 0xEB51, 0x96A5, 0xEB52, 0x96A6, 0xEB53, 0x96A8, 0xEB54, 0x96A9, 0xEB55, 0x96AA, + 0xEB56, 0x96AB, 0xEB57, 0x96AC, 0xEB58, 0x96AD, 0xEB59, 0x96AE, 0xEB5A, 0x96AF, 0xEB5B, 0x96B1, 0xEB5C, 0x96B2, 0xEB5D, 0x96B4, + 0xEB5E, 0x96B5, 0xEB5F, 0x96B7, 0xEB60, 0x96B8, 0xEB61, 0x96BA, 0xEB62, 0x96BB, 0xEB63, 0x96BF, 0xEB64, 0x96C2, 0xEB65, 0x96C3, + 0xEB66, 0x96C8, 0xEB67, 0x96CA, 0xEB68, 0x96CB, 0xEB69, 0x96D0, 0xEB6A, 0x96D1, 0xEB6B, 0x96D3, 0xEB6C, 0x96D4, 0xEB6D, 0x96D6, + 0xEB6E, 0x96D7, 0xEB6F, 0x96D8, 0xEB70, 0x96D9, 0xEB71, 0x96DA, 0xEB72, 0x96DB, 0xEB73, 0x96DC, 0xEB74, 0x96DD, 0xEB75, 0x96DE, + 0xEB76, 0x96DF, 0xEB77, 0x96E1, 0xEB78, 0x96E2, 0xEB79, 0x96E3, 0xEB7A, 0x96E4, 0xEB7B, 0x96E5, 0xEB7C, 0x96E6, 0xEB7D, 0x96E7, + 0xEB7E, 0x96EB, 0xEB80, 0x96EC, 0xEB81, 0x96ED, 0xEB82, 0x96EE, 0xEB83, 0x96F0, 0xEB84, 0x96F1, 0xEB85, 0x96F2, 0xEB86, 0x96F4, + 0xEB87, 0x96F5, 0xEB88, 0x96F8, 0xEB89, 0x96FA, 0xEB8A, 0x96FB, 0xEB8B, 0x96FC, 0xEB8C, 0x96FD, 0xEB8D, 0x96FF, 0xEB8E, 0x9702, + 0xEB8F, 0x9703, 0xEB90, 0x9705, 0xEB91, 0x970A, 0xEB92, 0x970B, 0xEB93, 0x970C, 0xEB94, 0x9710, 0xEB95, 0x9711, 0xEB96, 0x9712, + 0xEB97, 0x9714, 0xEB98, 0x9715, 0xEB99, 0x9717, 0xEB9A, 0x9718, 0xEB9B, 0x9719, 0xEB9C, 0x971A, 0xEB9D, 0x971B, 0xEB9E, 0x971D, + 0xEB9F, 0x971F, 0xEBA0, 0x9720, 0xEBA1, 0x643F, 0xEBA2, 0x64D8, 0xEBA3, 0x8004, 0xEBA4, 0x6BEA, 0xEBA5, 0x6BF3, 0xEBA6, 0x6BFD, + 0xEBA7, 0x6BF5, 0xEBA8, 0x6BF9, 0xEBA9, 0x6C05, 0xEBAA, 0x6C07, 0xEBAB, 0x6C06, 0xEBAC, 0x6C0D, 0xEBAD, 0x6C15, 0xEBAE, 0x6C18, + 0xEBAF, 0x6C19, 0xEBB0, 0x6C1A, 0xEBB1, 0x6C21, 0xEBB2, 0x6C29, 0xEBB3, 0x6C24, 0xEBB4, 0x6C2A, 0xEBB5, 0x6C32, 0xEBB6, 0x6535, + 0xEBB7, 0x6555, 0xEBB8, 0x656B, 0xEBB9, 0x724D, 0xEBBA, 0x7252, 0xEBBB, 0x7256, 0xEBBC, 0x7230, 0xEBBD, 0x8662, 0xEBBE, 0x5216, + 0xEBBF, 0x809F, 0xEBC0, 0x809C, 0xEBC1, 0x8093, 0xEBC2, 0x80BC, 0xEBC3, 0x670A, 0xEBC4, 0x80BD, 0xEBC5, 0x80B1, 0xEBC6, 0x80AB, + 0xEBC7, 0x80AD, 0xEBC8, 0x80B4, 0xEBC9, 0x80B7, 0xEBCA, 0x80E7, 0xEBCB, 0x80E8, 0xEBCC, 0x80E9, 0xEBCD, 0x80EA, 0xEBCE, 0x80DB, + 0xEBCF, 0x80C2, 0xEBD0, 0x80C4, 0xEBD1, 0x80D9, 0xEBD2, 0x80CD, 0xEBD3, 0x80D7, 0xEBD4, 0x6710, 0xEBD5, 0x80DD, 0xEBD6, 0x80EB, + 0xEBD7, 0x80F1, 0xEBD8, 0x80F4, 0xEBD9, 0x80ED, 0xEBDA, 0x810D, 0xEBDB, 0x810E, 0xEBDC, 0x80F2, 0xEBDD, 0x80FC, 0xEBDE, 0x6715, + 0xEBDF, 0x8112, 0xEBE0, 0x8C5A, 0xEBE1, 0x8136, 0xEBE2, 0x811E, 0xEBE3, 0x812C, 0xEBE4, 0x8118, 0xEBE5, 0x8132, 0xEBE6, 0x8148, + 0xEBE7, 0x814C, 0xEBE8, 0x8153, 0xEBE9, 0x8174, 0xEBEA, 0x8159, 0xEBEB, 0x815A, 0xEBEC, 0x8171, 0xEBED, 0x8160, 0xEBEE, 0x8169, + 0xEBEF, 0x817C, 0xEBF0, 0x817D, 0xEBF1, 0x816D, 0xEBF2, 0x8167, 0xEBF3, 0x584D, 0xEBF4, 0x5AB5, 0xEBF5, 0x8188, 0xEBF6, 0x8182, + 0xEBF7, 0x8191, 0xEBF8, 0x6ED5, 0xEBF9, 0x81A3, 0xEBFA, 0x81AA, 0xEBFB, 0x81CC, 0xEBFC, 0x6726, 0xEBFD, 0x81CA, 0xEBFE, 0x81BB, + 0xEC40, 0x9721, 0xEC41, 0x9722, 0xEC42, 0x9723, 0xEC43, 0x9724, 0xEC44, 0x9725, 0xEC45, 0x9726, 0xEC46, 0x9727, 0xEC47, 0x9728, + 0xEC48, 0x9729, 0xEC49, 0x972B, 0xEC4A, 0x972C, 0xEC4B, 0x972E, 0xEC4C, 0x972F, 0xEC4D, 0x9731, 0xEC4E, 0x9733, 0xEC4F, 0x9734, + 0xEC50, 0x9735, 0xEC51, 0x9736, 0xEC52, 0x9737, 0xEC53, 0x973A, 0xEC54, 0x973B, 0xEC55, 0x973C, 0xEC56, 0x973D, 0xEC57, 0x973F, + 0xEC58, 0x9740, 0xEC59, 0x9741, 0xEC5A, 0x9742, 0xEC5B, 0x9743, 0xEC5C, 0x9744, 0xEC5D, 0x9745, 0xEC5E, 0x9746, 0xEC5F, 0x9747, + 0xEC60, 0x9748, 0xEC61, 0x9749, 0xEC62, 0x974A, 0xEC63, 0x974B, 0xEC64, 0x974C, 0xEC65, 0x974D, 0xEC66, 0x974E, 0xEC67, 0x974F, + 0xEC68, 0x9750, 0xEC69, 0x9751, 0xEC6A, 0x9754, 0xEC6B, 0x9755, 0xEC6C, 0x9757, 0xEC6D, 0x9758, 0xEC6E, 0x975A, 0xEC6F, 0x975C, + 0xEC70, 0x975D, 0xEC71, 0x975F, 0xEC72, 0x9763, 0xEC73, 0x9764, 0xEC74, 0x9766, 0xEC75, 0x9767, 0xEC76, 0x9768, 0xEC77, 0x976A, + 0xEC78, 0x976B, 0xEC79, 0x976C, 0xEC7A, 0x976D, 0xEC7B, 0x976E, 0xEC7C, 0x976F, 0xEC7D, 0x9770, 0xEC7E, 0x9771, 0xEC80, 0x9772, + 0xEC81, 0x9775, 0xEC82, 0x9777, 0xEC83, 0x9778, 0xEC84, 0x9779, 0xEC85, 0x977A, 0xEC86, 0x977B, 0xEC87, 0x977D, 0xEC88, 0x977E, + 0xEC89, 0x977F, 0xEC8A, 0x9780, 0xEC8B, 0x9781, 0xEC8C, 0x9782, 0xEC8D, 0x9783, 0xEC8E, 0x9784, 0xEC8F, 0x9786, 0xEC90, 0x9787, + 0xEC91, 0x9788, 0xEC92, 0x9789, 0xEC93, 0x978A, 0xEC94, 0x978C, 0xEC95, 0x978E, 0xEC96, 0x978F, 0xEC97, 0x9790, 0xEC98, 0x9793, + 0xEC99, 0x9795, 0xEC9A, 0x9796, 0xEC9B, 0x9797, 0xEC9C, 0x9799, 0xEC9D, 0x979A, 0xEC9E, 0x979B, 0xEC9F, 0x979C, 0xECA0, 0x979D, + 0xECA1, 0x81C1, 0xECA2, 0x81A6, 0xECA3, 0x6B24, 0xECA4, 0x6B37, 0xECA5, 0x6B39, 0xECA6, 0x6B43, 0xECA7, 0x6B46, 0xECA8, 0x6B59, + 0xECA9, 0x98D1, 0xECAA, 0x98D2, 0xECAB, 0x98D3, 0xECAC, 0x98D5, 0xECAD, 0x98D9, 0xECAE, 0x98DA, 0xECAF, 0x6BB3, 0xECB0, 0x5F40, + 0xECB1, 0x6BC2, 0xECB2, 0x89F3, 0xECB3, 0x6590, 0xECB4, 0x9F51, 0xECB5, 0x6593, 0xECB6, 0x65BC, 0xECB7, 0x65C6, 0xECB8, 0x65C4, + 0xECB9, 0x65C3, 0xECBA, 0x65CC, 0xECBB, 0x65CE, 0xECBC, 0x65D2, 0xECBD, 0x65D6, 0xECBE, 0x7080, 0xECBF, 0x709C, 0xECC0, 0x7096, + 0xECC1, 0x709D, 0xECC2, 0x70BB, 0xECC3, 0x70C0, 0xECC4, 0x70B7, 0xECC5, 0x70AB, 0xECC6, 0x70B1, 0xECC7, 0x70E8, 0xECC8, 0x70CA, + 0xECC9, 0x7110, 0xECCA, 0x7113, 0xECCB, 0x7116, 0xECCC, 0x712F, 0xECCD, 0x7131, 0xECCE, 0x7173, 0xECCF, 0x715C, 0xECD0, 0x7168, + 0xECD1, 0x7145, 0xECD2, 0x7172, 0xECD3, 0x714A, 0xECD4, 0x7178, 0xECD5, 0x717A, 0xECD6, 0x7198, 0xECD7, 0x71B3, 0xECD8, 0x71B5, + 0xECD9, 0x71A8, 0xECDA, 0x71A0, 0xECDB, 0x71E0, 0xECDC, 0x71D4, 0xECDD, 0x71E7, 0xECDE, 0x71F9, 0xECDF, 0x721D, 0xECE0, 0x7228, + 0xECE1, 0x706C, 0xECE2, 0x7118, 0xECE3, 0x7166, 0xECE4, 0x71B9, 0xECE5, 0x623E, 0xECE6, 0x623D, 0xECE7, 0x6243, 0xECE8, 0x6248, + 0xECE9, 0x6249, 0xECEA, 0x793B, 0xECEB, 0x7940, 0xECEC, 0x7946, 0xECED, 0x7949, 0xECEE, 0x795B, 0xECEF, 0x795C, 0xECF0, 0x7953, + 0xECF1, 0x795A, 0xECF2, 0x7962, 0xECF3, 0x7957, 0xECF4, 0x7960, 0xECF5, 0x796F, 0xECF6, 0x7967, 0xECF7, 0x797A, 0xECF8, 0x7985, + 0xECF9, 0x798A, 0xECFA, 0x799A, 0xECFB, 0x79A7, 0xECFC, 0x79B3, 0xECFD, 0x5FD1, 0xECFE, 0x5FD0, 0xED40, 0x979E, 0xED41, 0x979F, + 0xED42, 0x97A1, 0xED43, 0x97A2, 0xED44, 0x97A4, 0xED45, 0x97A5, 0xED46, 0x97A6, 0xED47, 0x97A7, 0xED48, 0x97A8, 0xED49, 0x97A9, + 0xED4A, 0x97AA, 0xED4B, 0x97AC, 0xED4C, 0x97AE, 0xED4D, 0x97B0, 0xED4E, 0x97B1, 0xED4F, 0x97B3, 0xED50, 0x97B5, 0xED51, 0x97B6, + 0xED52, 0x97B7, 0xED53, 0x97B8, 0xED54, 0x97B9, 0xED55, 0x97BA, 0xED56, 0x97BB, 0xED57, 0x97BC, 0xED58, 0x97BD, 0xED59, 0x97BE, + 0xED5A, 0x97BF, 0xED5B, 0x97C0, 0xED5C, 0x97C1, 0xED5D, 0x97C2, 0xED5E, 0x97C3, 0xED5F, 0x97C4, 0xED60, 0x97C5, 0xED61, 0x97C6, + 0xED62, 0x97C7, 0xED63, 0x97C8, 0xED64, 0x97C9, 0xED65, 0x97CA, 0xED66, 0x97CB, 0xED67, 0x97CC, 0xED68, 0x97CD, 0xED69, 0x97CE, + 0xED6A, 0x97CF, 0xED6B, 0x97D0, 0xED6C, 0x97D1, 0xED6D, 0x97D2, 0xED6E, 0x97D3, 0xED6F, 0x97D4, 0xED70, 0x97D5, 0xED71, 0x97D6, + 0xED72, 0x97D7, 0xED73, 0x97D8, 0xED74, 0x97D9, 0xED75, 0x97DA, 0xED76, 0x97DB, 0xED77, 0x97DC, 0xED78, 0x97DD, 0xED79, 0x97DE, + 0xED7A, 0x97DF, 0xED7B, 0x97E0, 0xED7C, 0x97E1, 0xED7D, 0x97E2, 0xED7E, 0x97E3, 0xED80, 0x97E4, 0xED81, 0x97E5, 0xED82, 0x97E8, + 0xED83, 0x97EE, 0xED84, 0x97EF, 0xED85, 0x97F0, 0xED86, 0x97F1, 0xED87, 0x97F2, 0xED88, 0x97F4, 0xED89, 0x97F7, 0xED8A, 0x97F8, + 0xED8B, 0x97F9, 0xED8C, 0x97FA, 0xED8D, 0x97FB, 0xED8E, 0x97FC, 0xED8F, 0x97FD, 0xED90, 0x97FE, 0xED91, 0x97FF, 0xED92, 0x9800, + 0xED93, 0x9801, 0xED94, 0x9802, 0xED95, 0x9803, 0xED96, 0x9804, 0xED97, 0x9805, 0xED98, 0x9806, 0xED99, 0x9807, 0xED9A, 0x9808, + 0xED9B, 0x9809, 0xED9C, 0x980A, 0xED9D, 0x980B, 0xED9E, 0x980C, 0xED9F, 0x980D, 0xEDA0, 0x980E, 0xEDA1, 0x603C, 0xEDA2, 0x605D, + 0xEDA3, 0x605A, 0xEDA4, 0x6067, 0xEDA5, 0x6041, 0xEDA6, 0x6059, 0xEDA7, 0x6063, 0xEDA8, 0x60AB, 0xEDA9, 0x6106, 0xEDAA, 0x610D, + 0xEDAB, 0x615D, 0xEDAC, 0x61A9, 0xEDAD, 0x619D, 0xEDAE, 0x61CB, 0xEDAF, 0x61D1, 0xEDB0, 0x6206, 0xEDB1, 0x8080, 0xEDB2, 0x807F, + 0xEDB3, 0x6C93, 0xEDB4, 0x6CF6, 0xEDB5, 0x6DFC, 0xEDB6, 0x77F6, 0xEDB7, 0x77F8, 0xEDB8, 0x7800, 0xEDB9, 0x7809, 0xEDBA, 0x7817, + 0xEDBB, 0x7818, 0xEDBC, 0x7811, 0xEDBD, 0x65AB, 0xEDBE, 0x782D, 0xEDBF, 0x781C, 0xEDC0, 0x781D, 0xEDC1, 0x7839, 0xEDC2, 0x783A, + 0xEDC3, 0x783B, 0xEDC4, 0x781F, 0xEDC5, 0x783C, 0xEDC6, 0x7825, 0xEDC7, 0x782C, 0xEDC8, 0x7823, 0xEDC9, 0x7829, 0xEDCA, 0x784E, + 0xEDCB, 0x786D, 0xEDCC, 0x7856, 0xEDCD, 0x7857, 0xEDCE, 0x7826, 0xEDCF, 0x7850, 0xEDD0, 0x7847, 0xEDD1, 0x784C, 0xEDD2, 0x786A, + 0xEDD3, 0x789B, 0xEDD4, 0x7893, 0xEDD5, 0x789A, 0xEDD6, 0x7887, 0xEDD7, 0x789C, 0xEDD8, 0x78A1, 0xEDD9, 0x78A3, 0xEDDA, 0x78B2, + 0xEDDB, 0x78B9, 0xEDDC, 0x78A5, 0xEDDD, 0x78D4, 0xEDDE, 0x78D9, 0xEDDF, 0x78C9, 0xEDE0, 0x78EC, 0xEDE1, 0x78F2, 0xEDE2, 0x7905, + 0xEDE3, 0x78F4, 0xEDE4, 0x7913, 0xEDE5, 0x7924, 0xEDE6, 0x791E, 0xEDE7, 0x7934, 0xEDE8, 0x9F9B, 0xEDE9, 0x9EF9, 0xEDEA, 0x9EFB, + 0xEDEB, 0x9EFC, 0xEDEC, 0x76F1, 0xEDED, 0x7704, 0xEDEE, 0x770D, 0xEDEF, 0x76F9, 0xEDF0, 0x7707, 0xEDF1, 0x7708, 0xEDF2, 0x771A, + 0xEDF3, 0x7722, 0xEDF4, 0x7719, 0xEDF5, 0x772D, 0xEDF6, 0x7726, 0xEDF7, 0x7735, 0xEDF8, 0x7738, 0xEDF9, 0x7750, 0xEDFA, 0x7751, + 0xEDFB, 0x7747, 0xEDFC, 0x7743, 0xEDFD, 0x775A, 0xEDFE, 0x7768, 0xEE40, 0x980F, 0xEE41, 0x9810, 0xEE42, 0x9811, 0xEE43, 0x9812, + 0xEE44, 0x9813, 0xEE45, 0x9814, 0xEE46, 0x9815, 0xEE47, 0x9816, 0xEE48, 0x9817, 0xEE49, 0x9818, 0xEE4A, 0x9819, 0xEE4B, 0x981A, + 0xEE4C, 0x981B, 0xEE4D, 0x981C, 0xEE4E, 0x981D, 0xEE4F, 0x981E, 0xEE50, 0x981F, 0xEE51, 0x9820, 0xEE52, 0x9821, 0xEE53, 0x9822, + 0xEE54, 0x9823, 0xEE55, 0x9824, 0xEE56, 0x9825, 0xEE57, 0x9826, 0xEE58, 0x9827, 0xEE59, 0x9828, 0xEE5A, 0x9829, 0xEE5B, 0x982A, + 0xEE5C, 0x982B, 0xEE5D, 0x982C, 0xEE5E, 0x982D, 0xEE5F, 0x982E, 0xEE60, 0x982F, 0xEE61, 0x9830, 0xEE62, 0x9831, 0xEE63, 0x9832, + 0xEE64, 0x9833, 0xEE65, 0x9834, 0xEE66, 0x9835, 0xEE67, 0x9836, 0xEE68, 0x9837, 0xEE69, 0x9838, 0xEE6A, 0x9839, 0xEE6B, 0x983A, + 0xEE6C, 0x983B, 0xEE6D, 0x983C, 0xEE6E, 0x983D, 0xEE6F, 0x983E, 0xEE70, 0x983F, 0xEE71, 0x9840, 0xEE72, 0x9841, 0xEE73, 0x9842, + 0xEE74, 0x9843, 0xEE75, 0x9844, 0xEE76, 0x9845, 0xEE77, 0x9846, 0xEE78, 0x9847, 0xEE79, 0x9848, 0xEE7A, 0x9849, 0xEE7B, 0x984A, + 0xEE7C, 0x984B, 0xEE7D, 0x984C, 0xEE7E, 0x984D, 0xEE80, 0x984E, 0xEE81, 0x984F, 0xEE82, 0x9850, 0xEE83, 0x9851, 0xEE84, 0x9852, + 0xEE85, 0x9853, 0xEE86, 0x9854, 0xEE87, 0x9855, 0xEE88, 0x9856, 0xEE89, 0x9857, 0xEE8A, 0x9858, 0xEE8B, 0x9859, 0xEE8C, 0x985A, + 0xEE8D, 0x985B, 0xEE8E, 0x985C, 0xEE8F, 0x985D, 0xEE90, 0x985E, 0xEE91, 0x985F, 0xEE92, 0x9860, 0xEE93, 0x9861, 0xEE94, 0x9862, + 0xEE95, 0x9863, 0xEE96, 0x9864, 0xEE97, 0x9865, 0xEE98, 0x9866, 0xEE99, 0x9867, 0xEE9A, 0x9868, 0xEE9B, 0x9869, 0xEE9C, 0x986A, + 0xEE9D, 0x986B, 0xEE9E, 0x986C, 0xEE9F, 0x986D, 0xEEA0, 0x986E, 0xEEA1, 0x7762, 0xEEA2, 0x7765, 0xEEA3, 0x777F, 0xEEA4, 0x778D, + 0xEEA5, 0x777D, 0xEEA6, 0x7780, 0xEEA7, 0x778C, 0xEEA8, 0x7791, 0xEEA9, 0x779F, 0xEEAA, 0x77A0, 0xEEAB, 0x77B0, 0xEEAC, 0x77B5, + 0xEEAD, 0x77BD, 0xEEAE, 0x753A, 0xEEAF, 0x7540, 0xEEB0, 0x754E, 0xEEB1, 0x754B, 0xEEB2, 0x7548, 0xEEB3, 0x755B, 0xEEB4, 0x7572, + 0xEEB5, 0x7579, 0xEEB6, 0x7583, 0xEEB7, 0x7F58, 0xEEB8, 0x7F61, 0xEEB9, 0x7F5F, 0xEEBA, 0x8A48, 0xEEBB, 0x7F68, 0xEEBC, 0x7F74, + 0xEEBD, 0x7F71, 0xEEBE, 0x7F79, 0xEEBF, 0x7F81, 0xEEC0, 0x7F7E, 0xEEC1, 0x76CD, 0xEEC2, 0x76E5, 0xEEC3, 0x8832, 0xEEC4, 0x9485, + 0xEEC5, 0x9486, 0xEEC6, 0x9487, 0xEEC7, 0x948B, 0xEEC8, 0x948A, 0xEEC9, 0x948C, 0xEECA, 0x948D, 0xEECB, 0x948F, 0xEECC, 0x9490, + 0xEECD, 0x9494, 0xEECE, 0x9497, 0xEECF, 0x9495, 0xEED0, 0x949A, 0xEED1, 0x949B, 0xEED2, 0x949C, 0xEED3, 0x94A3, 0xEED4, 0x94A4, + 0xEED5, 0x94AB, 0xEED6, 0x94AA, 0xEED7, 0x94AD, 0xEED8, 0x94AC, 0xEED9, 0x94AF, 0xEEDA, 0x94B0, 0xEEDB, 0x94B2, 0xEEDC, 0x94B4, + 0xEEDD, 0x94B6, 0xEEDE, 0x94B7, 0xEEDF, 0x94B8, 0xEEE0, 0x94B9, 0xEEE1, 0x94BA, 0xEEE2, 0x94BC, 0xEEE3, 0x94BD, 0xEEE4, 0x94BF, + 0xEEE5, 0x94C4, 0xEEE6, 0x94C8, 0xEEE7, 0x94C9, 0xEEE8, 0x94CA, 0xEEE9, 0x94CB, 0xEEEA, 0x94CC, 0xEEEB, 0x94CD, 0xEEEC, 0x94CE, + 0xEEED, 0x94D0, 0xEEEE, 0x94D1, 0xEEEF, 0x94D2, 0xEEF0, 0x94D5, 0xEEF1, 0x94D6, 0xEEF2, 0x94D7, 0xEEF3, 0x94D9, 0xEEF4, 0x94D8, + 0xEEF5, 0x94DB, 0xEEF6, 0x94DE, 0xEEF7, 0x94DF, 0xEEF8, 0x94E0, 0xEEF9, 0x94E2, 0xEEFA, 0x94E4, 0xEEFB, 0x94E5, 0xEEFC, 0x94E7, + 0xEEFD, 0x94E8, 0xEEFE, 0x94EA, 0xEF40, 0x986F, 0xEF41, 0x9870, 0xEF42, 0x9871, 0xEF43, 0x9872, 0xEF44, 0x9873, 0xEF45, 0x9874, + 0xEF46, 0x988B, 0xEF47, 0x988E, 0xEF48, 0x9892, 0xEF49, 0x9895, 0xEF4A, 0x9899, 0xEF4B, 0x98A3, 0xEF4C, 0x98A8, 0xEF4D, 0x98A9, + 0xEF4E, 0x98AA, 0xEF4F, 0x98AB, 0xEF50, 0x98AC, 0xEF51, 0x98AD, 0xEF52, 0x98AE, 0xEF53, 0x98AF, 0xEF54, 0x98B0, 0xEF55, 0x98B1, + 0xEF56, 0x98B2, 0xEF57, 0x98B3, 0xEF58, 0x98B4, 0xEF59, 0x98B5, 0xEF5A, 0x98B6, 0xEF5B, 0x98B7, 0xEF5C, 0x98B8, 0xEF5D, 0x98B9, + 0xEF5E, 0x98BA, 0xEF5F, 0x98BB, 0xEF60, 0x98BC, 0xEF61, 0x98BD, 0xEF62, 0x98BE, 0xEF63, 0x98BF, 0xEF64, 0x98C0, 0xEF65, 0x98C1, + 0xEF66, 0x98C2, 0xEF67, 0x98C3, 0xEF68, 0x98C4, 0xEF69, 0x98C5, 0xEF6A, 0x98C6, 0xEF6B, 0x98C7, 0xEF6C, 0x98C8, 0xEF6D, 0x98C9, + 0xEF6E, 0x98CA, 0xEF6F, 0x98CB, 0xEF70, 0x98CC, 0xEF71, 0x98CD, 0xEF72, 0x98CF, 0xEF73, 0x98D0, 0xEF74, 0x98D4, 0xEF75, 0x98D6, + 0xEF76, 0x98D7, 0xEF77, 0x98DB, 0xEF78, 0x98DC, 0xEF79, 0x98DD, 0xEF7A, 0x98E0, 0xEF7B, 0x98E1, 0xEF7C, 0x98E2, 0xEF7D, 0x98E3, + 0xEF7E, 0x98E4, 0xEF80, 0x98E5, 0xEF81, 0x98E6, 0xEF82, 0x98E9, 0xEF83, 0x98EA, 0xEF84, 0x98EB, 0xEF85, 0x98EC, 0xEF86, 0x98ED, + 0xEF87, 0x98EE, 0xEF88, 0x98EF, 0xEF89, 0x98F0, 0xEF8A, 0x98F1, 0xEF8B, 0x98F2, 0xEF8C, 0x98F3, 0xEF8D, 0x98F4, 0xEF8E, 0x98F5, + 0xEF8F, 0x98F6, 0xEF90, 0x98F7, 0xEF91, 0x98F8, 0xEF92, 0x98F9, 0xEF93, 0x98FA, 0xEF94, 0x98FB, 0xEF95, 0x98FC, 0xEF96, 0x98FD, + 0xEF97, 0x98FE, 0xEF98, 0x98FF, 0xEF99, 0x9900, 0xEF9A, 0x9901, 0xEF9B, 0x9902, 0xEF9C, 0x9903, 0xEF9D, 0x9904, 0xEF9E, 0x9905, + 0xEF9F, 0x9906, 0xEFA0, 0x9907, 0xEFA1, 0x94E9, 0xEFA2, 0x94EB, 0xEFA3, 0x94EE, 0xEFA4, 0x94EF, 0xEFA5, 0x94F3, 0xEFA6, 0x94F4, + 0xEFA7, 0x94F5, 0xEFA8, 0x94F7, 0xEFA9, 0x94F9, 0xEFAA, 0x94FC, 0xEFAB, 0x94FD, 0xEFAC, 0x94FF, 0xEFAD, 0x9503, 0xEFAE, 0x9502, + 0xEFAF, 0x9506, 0xEFB0, 0x9507, 0xEFB1, 0x9509, 0xEFB2, 0x950A, 0xEFB3, 0x950D, 0xEFB4, 0x950E, 0xEFB5, 0x950F, 0xEFB6, 0x9512, + 0xEFB7, 0x9513, 0xEFB8, 0x9514, 0xEFB9, 0x9515, 0xEFBA, 0x9516, 0xEFBB, 0x9518, 0xEFBC, 0x951B, 0xEFBD, 0x951D, 0xEFBE, 0x951E, + 0xEFBF, 0x951F, 0xEFC0, 0x9522, 0xEFC1, 0x952A, 0xEFC2, 0x952B, 0xEFC3, 0x9529, 0xEFC4, 0x952C, 0xEFC5, 0x9531, 0xEFC6, 0x9532, + 0xEFC7, 0x9534, 0xEFC8, 0x9536, 0xEFC9, 0x9537, 0xEFCA, 0x9538, 0xEFCB, 0x953C, 0xEFCC, 0x953E, 0xEFCD, 0x953F, 0xEFCE, 0x9542, + 0xEFCF, 0x9535, 0xEFD0, 0x9544, 0xEFD1, 0x9545, 0xEFD2, 0x9546, 0xEFD3, 0x9549, 0xEFD4, 0x954C, 0xEFD5, 0x954E, 0xEFD6, 0x954F, + 0xEFD7, 0x9552, 0xEFD8, 0x9553, 0xEFD9, 0x9554, 0xEFDA, 0x9556, 0xEFDB, 0x9557, 0xEFDC, 0x9558, 0xEFDD, 0x9559, 0xEFDE, 0x955B, + 0xEFDF, 0x955E, 0xEFE0, 0x955F, 0xEFE1, 0x955D, 0xEFE2, 0x9561, 0xEFE3, 0x9562, 0xEFE4, 0x9564, 0xEFE5, 0x9565, 0xEFE6, 0x9566, + 0xEFE7, 0x9567, 0xEFE8, 0x9568, 0xEFE9, 0x9569, 0xEFEA, 0x956A, 0xEFEB, 0x956B, 0xEFEC, 0x956C, 0xEFED, 0x956F, 0xEFEE, 0x9571, + 0xEFEF, 0x9572, 0xEFF0, 0x9573, 0xEFF1, 0x953A, 0xEFF2, 0x77E7, 0xEFF3, 0x77EC, 0xEFF4, 0x96C9, 0xEFF5, 0x79D5, 0xEFF6, 0x79ED, + 0xEFF7, 0x79E3, 0xEFF8, 0x79EB, 0xEFF9, 0x7A06, 0xEFFA, 0x5D47, 0xEFFB, 0x7A03, 0xEFFC, 0x7A02, 0xEFFD, 0x7A1E, 0xEFFE, 0x7A14, + 0xF040, 0x9908, 0xF041, 0x9909, 0xF042, 0x990A, 0xF043, 0x990B, 0xF044, 0x990C, 0xF045, 0x990E, 0xF046, 0x990F, 0xF047, 0x9911, + 0xF048, 0x9912, 0xF049, 0x9913, 0xF04A, 0x9914, 0xF04B, 0x9915, 0xF04C, 0x9916, 0xF04D, 0x9917, 0xF04E, 0x9918, 0xF04F, 0x9919, + 0xF050, 0x991A, 0xF051, 0x991B, 0xF052, 0x991C, 0xF053, 0x991D, 0xF054, 0x991E, 0xF055, 0x991F, 0xF056, 0x9920, 0xF057, 0x9921, + 0xF058, 0x9922, 0xF059, 0x9923, 0xF05A, 0x9924, 0xF05B, 0x9925, 0xF05C, 0x9926, 0xF05D, 0x9927, 0xF05E, 0x9928, 0xF05F, 0x9929, + 0xF060, 0x992A, 0xF061, 0x992B, 0xF062, 0x992C, 0xF063, 0x992D, 0xF064, 0x992F, 0xF065, 0x9930, 0xF066, 0x9931, 0xF067, 0x9932, + 0xF068, 0x9933, 0xF069, 0x9934, 0xF06A, 0x9935, 0xF06B, 0x9936, 0xF06C, 0x9937, 0xF06D, 0x9938, 0xF06E, 0x9939, 0xF06F, 0x993A, + 0xF070, 0x993B, 0xF071, 0x993C, 0xF072, 0x993D, 0xF073, 0x993E, 0xF074, 0x993F, 0xF075, 0x9940, 0xF076, 0x9941, 0xF077, 0x9942, + 0xF078, 0x9943, 0xF079, 0x9944, 0xF07A, 0x9945, 0xF07B, 0x9946, 0xF07C, 0x9947, 0xF07D, 0x9948, 0xF07E, 0x9949, 0xF080, 0x994A, + 0xF081, 0x994B, 0xF082, 0x994C, 0xF083, 0x994D, 0xF084, 0x994E, 0xF085, 0x994F, 0xF086, 0x9950, 0xF087, 0x9951, 0xF088, 0x9952, + 0xF089, 0x9953, 0xF08A, 0x9956, 0xF08B, 0x9957, 0xF08C, 0x9958, 0xF08D, 0x9959, 0xF08E, 0x995A, 0xF08F, 0x995B, 0xF090, 0x995C, + 0xF091, 0x995D, 0xF092, 0x995E, 0xF093, 0x995F, 0xF094, 0x9960, 0xF095, 0x9961, 0xF096, 0x9962, 0xF097, 0x9964, 0xF098, 0x9966, + 0xF099, 0x9973, 0xF09A, 0x9978, 0xF09B, 0x9979, 0xF09C, 0x997B, 0xF09D, 0x997E, 0xF09E, 0x9982, 0xF09F, 0x9983, 0xF0A0, 0x9989, + 0xF0A1, 0x7A39, 0xF0A2, 0x7A37, 0xF0A3, 0x7A51, 0xF0A4, 0x9ECF, 0xF0A5, 0x99A5, 0xF0A6, 0x7A70, 0xF0A7, 0x7688, 0xF0A8, 0x768E, + 0xF0A9, 0x7693, 0xF0AA, 0x7699, 0xF0AB, 0x76A4, 0xF0AC, 0x74DE, 0xF0AD, 0x74E0, 0xF0AE, 0x752C, 0xF0AF, 0x9E20, 0xF0B0, 0x9E22, + 0xF0B1, 0x9E28, 0xF0B2, 0x9E29, 0xF0B3, 0x9E2A, 0xF0B4, 0x9E2B, 0xF0B5, 0x9E2C, 0xF0B6, 0x9E32, 0xF0B7, 0x9E31, 0xF0B8, 0x9E36, + 0xF0B9, 0x9E38, 0xF0BA, 0x9E37, 0xF0BB, 0x9E39, 0xF0BC, 0x9E3A, 0xF0BD, 0x9E3E, 0xF0BE, 0x9E41, 0xF0BF, 0x9E42, 0xF0C0, 0x9E44, + 0xF0C1, 0x9E46, 0xF0C2, 0x9E47, 0xF0C3, 0x9E48, 0xF0C4, 0x9E49, 0xF0C5, 0x9E4B, 0xF0C6, 0x9E4C, 0xF0C7, 0x9E4E, 0xF0C8, 0x9E51, + 0xF0C9, 0x9E55, 0xF0CA, 0x9E57, 0xF0CB, 0x9E5A, 0xF0CC, 0x9E5B, 0xF0CD, 0x9E5C, 0xF0CE, 0x9E5E, 0xF0CF, 0x9E63, 0xF0D0, 0x9E66, + 0xF0D1, 0x9E67, 0xF0D2, 0x9E68, 0xF0D3, 0x9E69, 0xF0D4, 0x9E6A, 0xF0D5, 0x9E6B, 0xF0D6, 0x9E6C, 0xF0D7, 0x9E71, 0xF0D8, 0x9E6D, + 0xF0D9, 0x9E73, 0xF0DA, 0x7592, 0xF0DB, 0x7594, 0xF0DC, 0x7596, 0xF0DD, 0x75A0, 0xF0DE, 0x759D, 0xF0DF, 0x75AC, 0xF0E0, 0x75A3, + 0xF0E1, 0x75B3, 0xF0E2, 0x75B4, 0xF0E3, 0x75B8, 0xF0E4, 0x75C4, 0xF0E5, 0x75B1, 0xF0E6, 0x75B0, 0xF0E7, 0x75C3, 0xF0E8, 0x75C2, + 0xF0E9, 0x75D6, 0xF0EA, 0x75CD, 0xF0EB, 0x75E3, 0xF0EC, 0x75E8, 0xF0ED, 0x75E6, 0xF0EE, 0x75E4, 0xF0EF, 0x75EB, 0xF0F0, 0x75E7, + 0xF0F1, 0x7603, 0xF0F2, 0x75F1, 0xF0F3, 0x75FC, 0xF0F4, 0x75FF, 0xF0F5, 0x7610, 0xF0F6, 0x7600, 0xF0F7, 0x7605, 0xF0F8, 0x760C, + 0xF0F9, 0x7617, 0xF0FA, 0x760A, 0xF0FB, 0x7625, 0xF0FC, 0x7618, 0xF0FD, 0x7615, 0xF0FE, 0x7619, 0xF140, 0x998C, 0xF141, 0x998E, + 0xF142, 0x999A, 0xF143, 0x999B, 0xF144, 0x999C, 0xF145, 0x999D, 0xF146, 0x999E, 0xF147, 0x999F, 0xF148, 0x99A0, 0xF149, 0x99A1, + 0xF14A, 0x99A2, 0xF14B, 0x99A3, 0xF14C, 0x99A4, 0xF14D, 0x99A6, 0xF14E, 0x99A7, 0xF14F, 0x99A9, 0xF150, 0x99AA, 0xF151, 0x99AB, + 0xF152, 0x99AC, 0xF153, 0x99AD, 0xF154, 0x99AE, 0xF155, 0x99AF, 0xF156, 0x99B0, 0xF157, 0x99B1, 0xF158, 0x99B2, 0xF159, 0x99B3, + 0xF15A, 0x99B4, 0xF15B, 0x99B5, 0xF15C, 0x99B6, 0xF15D, 0x99B7, 0xF15E, 0x99B8, 0xF15F, 0x99B9, 0xF160, 0x99BA, 0xF161, 0x99BB, + 0xF162, 0x99BC, 0xF163, 0x99BD, 0xF164, 0x99BE, 0xF165, 0x99BF, 0xF166, 0x99C0, 0xF167, 0x99C1, 0xF168, 0x99C2, 0xF169, 0x99C3, + 0xF16A, 0x99C4, 0xF16B, 0x99C5, 0xF16C, 0x99C6, 0xF16D, 0x99C7, 0xF16E, 0x99C8, 0xF16F, 0x99C9, 0xF170, 0x99CA, 0xF171, 0x99CB, + 0xF172, 0x99CC, 0xF173, 0x99CD, 0xF174, 0x99CE, 0xF175, 0x99CF, 0xF176, 0x99D0, 0xF177, 0x99D1, 0xF178, 0x99D2, 0xF179, 0x99D3, + 0xF17A, 0x99D4, 0xF17B, 0x99D5, 0xF17C, 0x99D6, 0xF17D, 0x99D7, 0xF17E, 0x99D8, 0xF180, 0x99D9, 0xF181, 0x99DA, 0xF182, 0x99DB, + 0xF183, 0x99DC, 0xF184, 0x99DD, 0xF185, 0x99DE, 0xF186, 0x99DF, 0xF187, 0x99E0, 0xF188, 0x99E1, 0xF189, 0x99E2, 0xF18A, 0x99E3, + 0xF18B, 0x99E4, 0xF18C, 0x99E5, 0xF18D, 0x99E6, 0xF18E, 0x99E7, 0xF18F, 0x99E8, 0xF190, 0x99E9, 0xF191, 0x99EA, 0xF192, 0x99EB, + 0xF193, 0x99EC, 0xF194, 0x99ED, 0xF195, 0x99EE, 0xF196, 0x99EF, 0xF197, 0x99F0, 0xF198, 0x99F1, 0xF199, 0x99F2, 0xF19A, 0x99F3, + 0xF19B, 0x99F4, 0xF19C, 0x99F5, 0xF19D, 0x99F6, 0xF19E, 0x99F7, 0xF19F, 0x99F8, 0xF1A0, 0x99F9, 0xF1A1, 0x761B, 0xF1A2, 0x763C, + 0xF1A3, 0x7622, 0xF1A4, 0x7620, 0xF1A5, 0x7640, 0xF1A6, 0x762D, 0xF1A7, 0x7630, 0xF1A8, 0x763F, 0xF1A9, 0x7635, 0xF1AA, 0x7643, + 0xF1AB, 0x763E, 0xF1AC, 0x7633, 0xF1AD, 0x764D, 0xF1AE, 0x765E, 0xF1AF, 0x7654, 0xF1B0, 0x765C, 0xF1B1, 0x7656, 0xF1B2, 0x766B, + 0xF1B3, 0x766F, 0xF1B4, 0x7FCA, 0xF1B5, 0x7AE6, 0xF1B6, 0x7A78, 0xF1B7, 0x7A79, 0xF1B8, 0x7A80, 0xF1B9, 0x7A86, 0xF1BA, 0x7A88, + 0xF1BB, 0x7A95, 0xF1BC, 0x7AA6, 0xF1BD, 0x7AA0, 0xF1BE, 0x7AAC, 0xF1BF, 0x7AA8, 0xF1C0, 0x7AAD, 0xF1C1, 0x7AB3, 0xF1C2, 0x8864, + 0xF1C3, 0x8869, 0xF1C4, 0x8872, 0xF1C5, 0x887D, 0xF1C6, 0x887F, 0xF1C7, 0x8882, 0xF1C8, 0x88A2, 0xF1C9, 0x88C6, 0xF1CA, 0x88B7, + 0xF1CB, 0x88BC, 0xF1CC, 0x88C9, 0xF1CD, 0x88E2, 0xF1CE, 0x88CE, 0xF1CF, 0x88E3, 0xF1D0, 0x88E5, 0xF1D1, 0x88F1, 0xF1D2, 0x891A, + 0xF1D3, 0x88FC, 0xF1D4, 0x88E8, 0xF1D5, 0x88FE, 0xF1D6, 0x88F0, 0xF1D7, 0x8921, 0xF1D8, 0x8919, 0xF1D9, 0x8913, 0xF1DA, 0x891B, + 0xF1DB, 0x890A, 0xF1DC, 0x8934, 0xF1DD, 0x892B, 0xF1DE, 0x8936, 0xF1DF, 0x8941, 0xF1E0, 0x8966, 0xF1E1, 0x897B, 0xF1E2, 0x758B, + 0xF1E3, 0x80E5, 0xF1E4, 0x76B2, 0xF1E5, 0x76B4, 0xF1E6, 0x77DC, 0xF1E7, 0x8012, 0xF1E8, 0x8014, 0xF1E9, 0x8016, 0xF1EA, 0x801C, + 0xF1EB, 0x8020, 0xF1EC, 0x8022, 0xF1ED, 0x8025, 0xF1EE, 0x8026, 0xF1EF, 0x8027, 0xF1F0, 0x8029, 0xF1F1, 0x8028, 0xF1F2, 0x8031, + 0xF1F3, 0x800B, 0xF1F4, 0x8035, 0xF1F5, 0x8043, 0xF1F6, 0x8046, 0xF1F7, 0x804D, 0xF1F8, 0x8052, 0xF1F9, 0x8069, 0xF1FA, 0x8071, + 0xF1FB, 0x8983, 0xF1FC, 0x9878, 0xF1FD, 0x9880, 0xF1FE, 0x9883, 0xF240, 0x99FA, 0xF241, 0x99FB, 0xF242, 0x99FC, 0xF243, 0x99FD, + 0xF244, 0x99FE, 0xF245, 0x99FF, 0xF246, 0x9A00, 0xF247, 0x9A01, 0xF248, 0x9A02, 0xF249, 0x9A03, 0xF24A, 0x9A04, 0xF24B, 0x9A05, + 0xF24C, 0x9A06, 0xF24D, 0x9A07, 0xF24E, 0x9A08, 0xF24F, 0x9A09, 0xF250, 0x9A0A, 0xF251, 0x9A0B, 0xF252, 0x9A0C, 0xF253, 0x9A0D, + 0xF254, 0x9A0E, 0xF255, 0x9A0F, 0xF256, 0x9A10, 0xF257, 0x9A11, 0xF258, 0x9A12, 0xF259, 0x9A13, 0xF25A, 0x9A14, 0xF25B, 0x9A15, + 0xF25C, 0x9A16, 0xF25D, 0x9A17, 0xF25E, 0x9A18, 0xF25F, 0x9A19, 0xF260, 0x9A1A, 0xF261, 0x9A1B, 0xF262, 0x9A1C, 0xF263, 0x9A1D, + 0xF264, 0x9A1E, 0xF265, 0x9A1F, 0xF266, 0x9A20, 0xF267, 0x9A21, 0xF268, 0x9A22, 0xF269, 0x9A23, 0xF26A, 0x9A24, 0xF26B, 0x9A25, + 0xF26C, 0x9A26, 0xF26D, 0x9A27, 0xF26E, 0x9A28, 0xF26F, 0x9A29, 0xF270, 0x9A2A, 0xF271, 0x9A2B, 0xF272, 0x9A2C, 0xF273, 0x9A2D, + 0xF274, 0x9A2E, 0xF275, 0x9A2F, 0xF276, 0x9A30, 0xF277, 0x9A31, 0xF278, 0x9A32, 0xF279, 0x9A33, 0xF27A, 0x9A34, 0xF27B, 0x9A35, + 0xF27C, 0x9A36, 0xF27D, 0x9A37, 0xF27E, 0x9A38, 0xF280, 0x9A39, 0xF281, 0x9A3A, 0xF282, 0x9A3B, 0xF283, 0x9A3C, 0xF284, 0x9A3D, + 0xF285, 0x9A3E, 0xF286, 0x9A3F, 0xF287, 0x9A40, 0xF288, 0x9A41, 0xF289, 0x9A42, 0xF28A, 0x9A43, 0xF28B, 0x9A44, 0xF28C, 0x9A45, + 0xF28D, 0x9A46, 0xF28E, 0x9A47, 0xF28F, 0x9A48, 0xF290, 0x9A49, 0xF291, 0x9A4A, 0xF292, 0x9A4B, 0xF293, 0x9A4C, 0xF294, 0x9A4D, + 0xF295, 0x9A4E, 0xF296, 0x9A4F, 0xF297, 0x9A50, 0xF298, 0x9A51, 0xF299, 0x9A52, 0xF29A, 0x9A53, 0xF29B, 0x9A54, 0xF29C, 0x9A55, + 0xF29D, 0x9A56, 0xF29E, 0x9A57, 0xF29F, 0x9A58, 0xF2A0, 0x9A59, 0xF2A1, 0x9889, 0xF2A2, 0x988C, 0xF2A3, 0x988D, 0xF2A4, 0x988F, + 0xF2A5, 0x9894, 0xF2A6, 0x989A, 0xF2A7, 0x989B, 0xF2A8, 0x989E, 0xF2A9, 0x989F, 0xF2AA, 0x98A1, 0xF2AB, 0x98A2, 0xF2AC, 0x98A5, + 0xF2AD, 0x98A6, 0xF2AE, 0x864D, 0xF2AF, 0x8654, 0xF2B0, 0x866C, 0xF2B1, 0x866E, 0xF2B2, 0x867F, 0xF2B3, 0x867A, 0xF2B4, 0x867C, + 0xF2B5, 0x867B, 0xF2B6, 0x86A8, 0xF2B7, 0x868D, 0xF2B8, 0x868B, 0xF2B9, 0x86AC, 0xF2BA, 0x869D, 0xF2BB, 0x86A7, 0xF2BC, 0x86A3, + 0xF2BD, 0x86AA, 0xF2BE, 0x8693, 0xF2BF, 0x86A9, 0xF2C0, 0x86B6, 0xF2C1, 0x86C4, 0xF2C2, 0x86B5, 0xF2C3, 0x86CE, 0xF2C4, 0x86B0, + 0xF2C5, 0x86BA, 0xF2C6, 0x86B1, 0xF2C7, 0x86AF, 0xF2C8, 0x86C9, 0xF2C9, 0x86CF, 0xF2CA, 0x86B4, 0xF2CB, 0x86E9, 0xF2CC, 0x86F1, + 0xF2CD, 0x86F2, 0xF2CE, 0x86ED, 0xF2CF, 0x86F3, 0xF2D0, 0x86D0, 0xF2D1, 0x8713, 0xF2D2, 0x86DE, 0xF2D3, 0x86F4, 0xF2D4, 0x86DF, + 0xF2D5, 0x86D8, 0xF2D6, 0x86D1, 0xF2D7, 0x8703, 0xF2D8, 0x8707, 0xF2D9, 0x86F8, 0xF2DA, 0x8708, 0xF2DB, 0x870A, 0xF2DC, 0x870D, + 0xF2DD, 0x8709, 0xF2DE, 0x8723, 0xF2DF, 0x873B, 0xF2E0, 0x871E, 0xF2E1, 0x8725, 0xF2E2, 0x872E, 0xF2E3, 0x871A, 0xF2E4, 0x873E, + 0xF2E5, 0x8748, 0xF2E6, 0x8734, 0xF2E7, 0x8731, 0xF2E8, 0x8729, 0xF2E9, 0x8737, 0xF2EA, 0x873F, 0xF2EB, 0x8782, 0xF2EC, 0x8722, + 0xF2ED, 0x877D, 0xF2EE, 0x877E, 0xF2EF, 0x877B, 0xF2F0, 0x8760, 0xF2F1, 0x8770, 0xF2F2, 0x874C, 0xF2F3, 0x876E, 0xF2F4, 0x878B, + 0xF2F5, 0x8753, 0xF2F6, 0x8763, 0xF2F7, 0x877C, 0xF2F8, 0x8764, 0xF2F9, 0x8759, 0xF2FA, 0x8765, 0xF2FB, 0x8793, 0xF2FC, 0x87AF, + 0xF2FD, 0x87A8, 0xF2FE, 0x87D2, 0xF340, 0x9A5A, 0xF341, 0x9A5B, 0xF342, 0x9A5C, 0xF343, 0x9A5D, 0xF344, 0x9A5E, 0xF345, 0x9A5F, + 0xF346, 0x9A60, 0xF347, 0x9A61, 0xF348, 0x9A62, 0xF349, 0x9A63, 0xF34A, 0x9A64, 0xF34B, 0x9A65, 0xF34C, 0x9A66, 0xF34D, 0x9A67, + 0xF34E, 0x9A68, 0xF34F, 0x9A69, 0xF350, 0x9A6A, 0xF351, 0x9A6B, 0xF352, 0x9A72, 0xF353, 0x9A83, 0xF354, 0x9A89, 0xF355, 0x9A8D, + 0xF356, 0x9A8E, 0xF357, 0x9A94, 0xF358, 0x9A95, 0xF359, 0x9A99, 0xF35A, 0x9AA6, 0xF35B, 0x9AA9, 0xF35C, 0x9AAA, 0xF35D, 0x9AAB, + 0xF35E, 0x9AAC, 0xF35F, 0x9AAD, 0xF360, 0x9AAE, 0xF361, 0x9AAF, 0xF362, 0x9AB2, 0xF363, 0x9AB3, 0xF364, 0x9AB4, 0xF365, 0x9AB5, + 0xF366, 0x9AB9, 0xF367, 0x9ABB, 0xF368, 0x9ABD, 0xF369, 0x9ABE, 0xF36A, 0x9ABF, 0xF36B, 0x9AC3, 0xF36C, 0x9AC4, 0xF36D, 0x9AC6, + 0xF36E, 0x9AC7, 0xF36F, 0x9AC8, 0xF370, 0x9AC9, 0xF371, 0x9ACA, 0xF372, 0x9ACD, 0xF373, 0x9ACE, 0xF374, 0x9ACF, 0xF375, 0x9AD0, + 0xF376, 0x9AD2, 0xF377, 0x9AD4, 0xF378, 0x9AD5, 0xF379, 0x9AD6, 0xF37A, 0x9AD7, 0xF37B, 0x9AD9, 0xF37C, 0x9ADA, 0xF37D, 0x9ADB, + 0xF37E, 0x9ADC, 0xF380, 0x9ADD, 0xF381, 0x9ADE, 0xF382, 0x9AE0, 0xF383, 0x9AE2, 0xF384, 0x9AE3, 0xF385, 0x9AE4, 0xF386, 0x9AE5, + 0xF387, 0x9AE7, 0xF388, 0x9AE8, 0xF389, 0x9AE9, 0xF38A, 0x9AEA, 0xF38B, 0x9AEC, 0xF38C, 0x9AEE, 0xF38D, 0x9AF0, 0xF38E, 0x9AF1, + 0xF38F, 0x9AF2, 0xF390, 0x9AF3, 0xF391, 0x9AF4, 0xF392, 0x9AF5, 0xF393, 0x9AF6, 0xF394, 0x9AF7, 0xF395, 0x9AF8, 0xF396, 0x9AFA, + 0xF397, 0x9AFC, 0xF398, 0x9AFD, 0xF399, 0x9AFE, 0xF39A, 0x9AFF, 0xF39B, 0x9B00, 0xF39C, 0x9B01, 0xF39D, 0x9B02, 0xF39E, 0x9B04, + 0xF39F, 0x9B05, 0xF3A0, 0x9B06, 0xF3A1, 0x87C6, 0xF3A2, 0x8788, 0xF3A3, 0x8785, 0xF3A4, 0x87AD, 0xF3A5, 0x8797, 0xF3A6, 0x8783, + 0xF3A7, 0x87AB, 0xF3A8, 0x87E5, 0xF3A9, 0x87AC, 0xF3AA, 0x87B5, 0xF3AB, 0x87B3, 0xF3AC, 0x87CB, 0xF3AD, 0x87D3, 0xF3AE, 0x87BD, + 0xF3AF, 0x87D1, 0xF3B0, 0x87C0, 0xF3B1, 0x87CA, 0xF3B2, 0x87DB, 0xF3B3, 0x87EA, 0xF3B4, 0x87E0, 0xF3B5, 0x87EE, 0xF3B6, 0x8816, + 0xF3B7, 0x8813, 0xF3B8, 0x87FE, 0xF3B9, 0x880A, 0xF3BA, 0x881B, 0xF3BB, 0x8821, 0xF3BC, 0x8839, 0xF3BD, 0x883C, 0xF3BE, 0x7F36, + 0xF3BF, 0x7F42, 0xF3C0, 0x7F44, 0xF3C1, 0x7F45, 0xF3C2, 0x8210, 0xF3C3, 0x7AFA, 0xF3C4, 0x7AFD, 0xF3C5, 0x7B08, 0xF3C6, 0x7B03, + 0xF3C7, 0x7B04, 0xF3C8, 0x7B15, 0xF3C9, 0x7B0A, 0xF3CA, 0x7B2B, 0xF3CB, 0x7B0F, 0xF3CC, 0x7B47, 0xF3CD, 0x7B38, 0xF3CE, 0x7B2A, + 0xF3CF, 0x7B19, 0xF3D0, 0x7B2E, 0xF3D1, 0x7B31, 0xF3D2, 0x7B20, 0xF3D3, 0x7B25, 0xF3D4, 0x7B24, 0xF3D5, 0x7B33, 0xF3D6, 0x7B3E, + 0xF3D7, 0x7B1E, 0xF3D8, 0x7B58, 0xF3D9, 0x7B5A, 0xF3DA, 0x7B45, 0xF3DB, 0x7B75, 0xF3DC, 0x7B4C, 0xF3DD, 0x7B5D, 0xF3DE, 0x7B60, + 0xF3DF, 0x7B6E, 0xF3E0, 0x7B7B, 0xF3E1, 0x7B62, 0xF3E2, 0x7B72, 0xF3E3, 0x7B71, 0xF3E4, 0x7B90, 0xF3E5, 0x7BA6, 0xF3E6, 0x7BA7, + 0xF3E7, 0x7BB8, 0xF3E8, 0x7BAC, 0xF3E9, 0x7B9D, 0xF3EA, 0x7BA8, 0xF3EB, 0x7B85, 0xF3EC, 0x7BAA, 0xF3ED, 0x7B9C, 0xF3EE, 0x7BA2, + 0xF3EF, 0x7BAB, 0xF3F0, 0x7BB4, 0xF3F1, 0x7BD1, 0xF3F2, 0x7BC1, 0xF3F3, 0x7BCC, 0xF3F4, 0x7BDD, 0xF3F5, 0x7BDA, 0xF3F6, 0x7BE5, + 0xF3F7, 0x7BE6, 0xF3F8, 0x7BEA, 0xF3F9, 0x7C0C, 0xF3FA, 0x7BFE, 0xF3FB, 0x7BFC, 0xF3FC, 0x7C0F, 0xF3FD, 0x7C16, 0xF3FE, 0x7C0B, + 0xF440, 0x9B07, 0xF441, 0x9B09, 0xF442, 0x9B0A, 0xF443, 0x9B0B, 0xF444, 0x9B0C, 0xF445, 0x9B0D, 0xF446, 0x9B0E, 0xF447, 0x9B10, + 0xF448, 0x9B11, 0xF449, 0x9B12, 0xF44A, 0x9B14, 0xF44B, 0x9B15, 0xF44C, 0x9B16, 0xF44D, 0x9B17, 0xF44E, 0x9B18, 0xF44F, 0x9B19, + 0xF450, 0x9B1A, 0xF451, 0x9B1B, 0xF452, 0x9B1C, 0xF453, 0x9B1D, 0xF454, 0x9B1E, 0xF455, 0x9B20, 0xF456, 0x9B21, 0xF457, 0x9B22, + 0xF458, 0x9B24, 0xF459, 0x9B25, 0xF45A, 0x9B26, 0xF45B, 0x9B27, 0xF45C, 0x9B28, 0xF45D, 0x9B29, 0xF45E, 0x9B2A, 0xF45F, 0x9B2B, + 0xF460, 0x9B2C, 0xF461, 0x9B2D, 0xF462, 0x9B2E, 0xF463, 0x9B30, 0xF464, 0x9B31, 0xF465, 0x9B33, 0xF466, 0x9B34, 0xF467, 0x9B35, + 0xF468, 0x9B36, 0xF469, 0x9B37, 0xF46A, 0x9B38, 0xF46B, 0x9B39, 0xF46C, 0x9B3A, 0xF46D, 0x9B3D, 0xF46E, 0x9B3E, 0xF46F, 0x9B3F, + 0xF470, 0x9B40, 0xF471, 0x9B46, 0xF472, 0x9B4A, 0xF473, 0x9B4B, 0xF474, 0x9B4C, 0xF475, 0x9B4E, 0xF476, 0x9B50, 0xF477, 0x9B52, + 0xF478, 0x9B53, 0xF479, 0x9B55, 0xF47A, 0x9B56, 0xF47B, 0x9B57, 0xF47C, 0x9B58, 0xF47D, 0x9B59, 0xF47E, 0x9B5A, 0xF480, 0x9B5B, + 0xF481, 0x9B5C, 0xF482, 0x9B5D, 0xF483, 0x9B5E, 0xF484, 0x9B5F, 0xF485, 0x9B60, 0xF486, 0x9B61, 0xF487, 0x9B62, 0xF488, 0x9B63, + 0xF489, 0x9B64, 0xF48A, 0x9B65, 0xF48B, 0x9B66, 0xF48C, 0x9B67, 0xF48D, 0x9B68, 0xF48E, 0x9B69, 0xF48F, 0x9B6A, 0xF490, 0x9B6B, + 0xF491, 0x9B6C, 0xF492, 0x9B6D, 0xF493, 0x9B6E, 0xF494, 0x9B6F, 0xF495, 0x9B70, 0xF496, 0x9B71, 0xF497, 0x9B72, 0xF498, 0x9B73, + 0xF499, 0x9B74, 0xF49A, 0x9B75, 0xF49B, 0x9B76, 0xF49C, 0x9B77, 0xF49D, 0x9B78, 0xF49E, 0x9B79, 0xF49F, 0x9B7A, 0xF4A0, 0x9B7B, + 0xF4A1, 0x7C1F, 0xF4A2, 0x7C2A, 0xF4A3, 0x7C26, 0xF4A4, 0x7C38, 0xF4A5, 0x7C41, 0xF4A6, 0x7C40, 0xF4A7, 0x81FE, 0xF4A8, 0x8201, + 0xF4A9, 0x8202, 0xF4AA, 0x8204, 0xF4AB, 0x81EC, 0xF4AC, 0x8844, 0xF4AD, 0x8221, 0xF4AE, 0x8222, 0xF4AF, 0x8223, 0xF4B0, 0x822D, + 0xF4B1, 0x822F, 0xF4B2, 0x8228, 0xF4B3, 0x822B, 0xF4B4, 0x8238, 0xF4B5, 0x823B, 0xF4B6, 0x8233, 0xF4B7, 0x8234, 0xF4B8, 0x823E, + 0xF4B9, 0x8244, 0xF4BA, 0x8249, 0xF4BB, 0x824B, 0xF4BC, 0x824F, 0xF4BD, 0x825A, 0xF4BE, 0x825F, 0xF4BF, 0x8268, 0xF4C0, 0x887E, + 0xF4C1, 0x8885, 0xF4C2, 0x8888, 0xF4C3, 0x88D8, 0xF4C4, 0x88DF, 0xF4C5, 0x895E, 0xF4C6, 0x7F9D, 0xF4C7, 0x7F9F, 0xF4C8, 0x7FA7, + 0xF4C9, 0x7FAF, 0xF4CA, 0x7FB0, 0xF4CB, 0x7FB2, 0xF4CC, 0x7C7C, 0xF4CD, 0x6549, 0xF4CE, 0x7C91, 0xF4CF, 0x7C9D, 0xF4D0, 0x7C9C, + 0xF4D1, 0x7C9E, 0xF4D2, 0x7CA2, 0xF4D3, 0x7CB2, 0xF4D4, 0x7CBC, 0xF4D5, 0x7CBD, 0xF4D6, 0x7CC1, 0xF4D7, 0x7CC7, 0xF4D8, 0x7CCC, + 0xF4D9, 0x7CCD, 0xF4DA, 0x7CC8, 0xF4DB, 0x7CC5, 0xF4DC, 0x7CD7, 0xF4DD, 0x7CE8, 0xF4DE, 0x826E, 0xF4DF, 0x66A8, 0xF4E0, 0x7FBF, + 0xF4E1, 0x7FCE, 0xF4E2, 0x7FD5, 0xF4E3, 0x7FE5, 0xF4E4, 0x7FE1, 0xF4E5, 0x7FE6, 0xF4E6, 0x7FE9, 0xF4E7, 0x7FEE, 0xF4E8, 0x7FF3, + 0xF4E9, 0x7CF8, 0xF4EA, 0x7D77, 0xF4EB, 0x7DA6, 0xF4EC, 0x7DAE, 0xF4ED, 0x7E47, 0xF4EE, 0x7E9B, 0xF4EF, 0x9EB8, 0xF4F0, 0x9EB4, + 0xF4F1, 0x8D73, 0xF4F2, 0x8D84, 0xF4F3, 0x8D94, 0xF4F4, 0x8D91, 0xF4F5, 0x8DB1, 0xF4F6, 0x8D67, 0xF4F7, 0x8D6D, 0xF4F8, 0x8C47, + 0xF4F9, 0x8C49, 0xF4FA, 0x914A, 0xF4FB, 0x9150, 0xF4FC, 0x914E, 0xF4FD, 0x914F, 0xF4FE, 0x9164, 0xF540, 0x9B7C, 0xF541, 0x9B7D, + 0xF542, 0x9B7E, 0xF543, 0x9B7F, 0xF544, 0x9B80, 0xF545, 0x9B81, 0xF546, 0x9B82, 0xF547, 0x9B83, 0xF548, 0x9B84, 0xF549, 0x9B85, + 0xF54A, 0x9B86, 0xF54B, 0x9B87, 0xF54C, 0x9B88, 0xF54D, 0x9B89, 0xF54E, 0x9B8A, 0xF54F, 0x9B8B, 0xF550, 0x9B8C, 0xF551, 0x9B8D, + 0xF552, 0x9B8E, 0xF553, 0x9B8F, 0xF554, 0x9B90, 0xF555, 0x9B91, 0xF556, 0x9B92, 0xF557, 0x9B93, 0xF558, 0x9B94, 0xF559, 0x9B95, + 0xF55A, 0x9B96, 0xF55B, 0x9B97, 0xF55C, 0x9B98, 0xF55D, 0x9B99, 0xF55E, 0x9B9A, 0xF55F, 0x9B9B, 0xF560, 0x9B9C, 0xF561, 0x9B9D, + 0xF562, 0x9B9E, 0xF563, 0x9B9F, 0xF564, 0x9BA0, 0xF565, 0x9BA1, 0xF566, 0x9BA2, 0xF567, 0x9BA3, 0xF568, 0x9BA4, 0xF569, 0x9BA5, + 0xF56A, 0x9BA6, 0xF56B, 0x9BA7, 0xF56C, 0x9BA8, 0xF56D, 0x9BA9, 0xF56E, 0x9BAA, 0xF56F, 0x9BAB, 0xF570, 0x9BAC, 0xF571, 0x9BAD, + 0xF572, 0x9BAE, 0xF573, 0x9BAF, 0xF574, 0x9BB0, 0xF575, 0x9BB1, 0xF576, 0x9BB2, 0xF577, 0x9BB3, 0xF578, 0x9BB4, 0xF579, 0x9BB5, + 0xF57A, 0x9BB6, 0xF57B, 0x9BB7, 0xF57C, 0x9BB8, 0xF57D, 0x9BB9, 0xF57E, 0x9BBA, 0xF580, 0x9BBB, 0xF581, 0x9BBC, 0xF582, 0x9BBD, + 0xF583, 0x9BBE, 0xF584, 0x9BBF, 0xF585, 0x9BC0, 0xF586, 0x9BC1, 0xF587, 0x9BC2, 0xF588, 0x9BC3, 0xF589, 0x9BC4, 0xF58A, 0x9BC5, + 0xF58B, 0x9BC6, 0xF58C, 0x9BC7, 0xF58D, 0x9BC8, 0xF58E, 0x9BC9, 0xF58F, 0x9BCA, 0xF590, 0x9BCB, 0xF591, 0x9BCC, 0xF592, 0x9BCD, + 0xF593, 0x9BCE, 0xF594, 0x9BCF, 0xF595, 0x9BD0, 0xF596, 0x9BD1, 0xF597, 0x9BD2, 0xF598, 0x9BD3, 0xF599, 0x9BD4, 0xF59A, 0x9BD5, + 0xF59B, 0x9BD6, 0xF59C, 0x9BD7, 0xF59D, 0x9BD8, 0xF59E, 0x9BD9, 0xF59F, 0x9BDA, 0xF5A0, 0x9BDB, 0xF5A1, 0x9162, 0xF5A2, 0x9161, + 0xF5A3, 0x9170, 0xF5A4, 0x9169, 0xF5A5, 0x916F, 0xF5A6, 0x917D, 0xF5A7, 0x917E, 0xF5A8, 0x9172, 0xF5A9, 0x9174, 0xF5AA, 0x9179, + 0xF5AB, 0x918C, 0xF5AC, 0x9185, 0xF5AD, 0x9190, 0xF5AE, 0x918D, 0xF5AF, 0x9191, 0xF5B0, 0x91A2, 0xF5B1, 0x91A3, 0xF5B2, 0x91AA, + 0xF5B3, 0x91AD, 0xF5B4, 0x91AE, 0xF5B5, 0x91AF, 0xF5B6, 0x91B5, 0xF5B7, 0x91B4, 0xF5B8, 0x91BA, 0xF5B9, 0x8C55, 0xF5BA, 0x9E7E, + 0xF5BB, 0x8DB8, 0xF5BC, 0x8DEB, 0xF5BD, 0x8E05, 0xF5BE, 0x8E59, 0xF5BF, 0x8E69, 0xF5C0, 0x8DB5, 0xF5C1, 0x8DBF, 0xF5C2, 0x8DBC, + 0xF5C3, 0x8DBA, 0xF5C4, 0x8DC4, 0xF5C5, 0x8DD6, 0xF5C6, 0x8DD7, 0xF5C7, 0x8DDA, 0xF5C8, 0x8DDE, 0xF5C9, 0x8DCE, 0xF5CA, 0x8DCF, + 0xF5CB, 0x8DDB, 0xF5CC, 0x8DC6, 0xF5CD, 0x8DEC, 0xF5CE, 0x8DF7, 0xF5CF, 0x8DF8, 0xF5D0, 0x8DE3, 0xF5D1, 0x8DF9, 0xF5D2, 0x8DFB, + 0xF5D3, 0x8DE4, 0xF5D4, 0x8E09, 0xF5D5, 0x8DFD, 0xF5D6, 0x8E14, 0xF5D7, 0x8E1D, 0xF5D8, 0x8E1F, 0xF5D9, 0x8E2C, 0xF5DA, 0x8E2E, + 0xF5DB, 0x8E23, 0xF5DC, 0x8E2F, 0xF5DD, 0x8E3A, 0xF5DE, 0x8E40, 0xF5DF, 0x8E39, 0xF5E0, 0x8E35, 0xF5E1, 0x8E3D, 0xF5E2, 0x8E31, + 0xF5E3, 0x8E49, 0xF5E4, 0x8E41, 0xF5E5, 0x8E42, 0xF5E6, 0x8E51, 0xF5E7, 0x8E52, 0xF5E8, 0x8E4A, 0xF5E9, 0x8E70, 0xF5EA, 0x8E76, + 0xF5EB, 0x8E7C, 0xF5EC, 0x8E6F, 0xF5ED, 0x8E74, 0xF5EE, 0x8E85, 0xF5EF, 0x8E8F, 0xF5F0, 0x8E94, 0xF5F1, 0x8E90, 0xF5F2, 0x8E9C, + 0xF5F3, 0x8E9E, 0xF5F4, 0x8C78, 0xF5F5, 0x8C82, 0xF5F6, 0x8C8A, 0xF5F7, 0x8C85, 0xF5F8, 0x8C98, 0xF5F9, 0x8C94, 0xF5FA, 0x659B, + 0xF5FB, 0x89D6, 0xF5FC, 0x89DE, 0xF5FD, 0x89DA, 0xF5FE, 0x89DC, 0xF640, 0x9BDC, 0xF641, 0x9BDD, 0xF642, 0x9BDE, 0xF643, 0x9BDF, + 0xF644, 0x9BE0, 0xF645, 0x9BE1, 0xF646, 0x9BE2, 0xF647, 0x9BE3, 0xF648, 0x9BE4, 0xF649, 0x9BE5, 0xF64A, 0x9BE6, 0xF64B, 0x9BE7, + 0xF64C, 0x9BE8, 0xF64D, 0x9BE9, 0xF64E, 0x9BEA, 0xF64F, 0x9BEB, 0xF650, 0x9BEC, 0xF651, 0x9BED, 0xF652, 0x9BEE, 0xF653, 0x9BEF, + 0xF654, 0x9BF0, 0xF655, 0x9BF1, 0xF656, 0x9BF2, 0xF657, 0x9BF3, 0xF658, 0x9BF4, 0xF659, 0x9BF5, 0xF65A, 0x9BF6, 0xF65B, 0x9BF7, + 0xF65C, 0x9BF8, 0xF65D, 0x9BF9, 0xF65E, 0x9BFA, 0xF65F, 0x9BFB, 0xF660, 0x9BFC, 0xF661, 0x9BFD, 0xF662, 0x9BFE, 0xF663, 0x9BFF, + 0xF664, 0x9C00, 0xF665, 0x9C01, 0xF666, 0x9C02, 0xF667, 0x9C03, 0xF668, 0x9C04, 0xF669, 0x9C05, 0xF66A, 0x9C06, 0xF66B, 0x9C07, + 0xF66C, 0x9C08, 0xF66D, 0x9C09, 0xF66E, 0x9C0A, 0xF66F, 0x9C0B, 0xF670, 0x9C0C, 0xF671, 0x9C0D, 0xF672, 0x9C0E, 0xF673, 0x9C0F, + 0xF674, 0x9C10, 0xF675, 0x9C11, 0xF676, 0x9C12, 0xF677, 0x9C13, 0xF678, 0x9C14, 0xF679, 0x9C15, 0xF67A, 0x9C16, 0xF67B, 0x9C17, + 0xF67C, 0x9C18, 0xF67D, 0x9C19, 0xF67E, 0x9C1A, 0xF680, 0x9C1B, 0xF681, 0x9C1C, 0xF682, 0x9C1D, 0xF683, 0x9C1E, 0xF684, 0x9C1F, + 0xF685, 0x9C20, 0xF686, 0x9C21, 0xF687, 0x9C22, 0xF688, 0x9C23, 0xF689, 0x9C24, 0xF68A, 0x9C25, 0xF68B, 0x9C26, 0xF68C, 0x9C27, + 0xF68D, 0x9C28, 0xF68E, 0x9C29, 0xF68F, 0x9C2A, 0xF690, 0x9C2B, 0xF691, 0x9C2C, 0xF692, 0x9C2D, 0xF693, 0x9C2E, 0xF694, 0x9C2F, + 0xF695, 0x9C30, 0xF696, 0x9C31, 0xF697, 0x9C32, 0xF698, 0x9C33, 0xF699, 0x9C34, 0xF69A, 0x9C35, 0xF69B, 0x9C36, 0xF69C, 0x9C37, + 0xF69D, 0x9C38, 0xF69E, 0x9C39, 0xF69F, 0x9C3A, 0xF6A0, 0x9C3B, 0xF6A1, 0x89E5, 0xF6A2, 0x89EB, 0xF6A3, 0x89EF, 0xF6A4, 0x8A3E, + 0xF6A5, 0x8B26, 0xF6A6, 0x9753, 0xF6A7, 0x96E9, 0xF6A8, 0x96F3, 0xF6A9, 0x96EF, 0xF6AA, 0x9706, 0xF6AB, 0x9701, 0xF6AC, 0x9708, + 0xF6AD, 0x970F, 0xF6AE, 0x970E, 0xF6AF, 0x972A, 0xF6B0, 0x972D, 0xF6B1, 0x9730, 0xF6B2, 0x973E, 0xF6B3, 0x9F80, 0xF6B4, 0x9F83, + 0xF6B5, 0x9F85, 0xF6B6, 0x9F86, 0xF6B7, 0x9F87, 0xF6B8, 0x9F88, 0xF6B9, 0x9F89, 0xF6BA, 0x9F8A, 0xF6BB, 0x9F8C, 0xF6BC, 0x9EFE, + 0xF6BD, 0x9F0B, 0xF6BE, 0x9F0D, 0xF6BF, 0x96B9, 0xF6C0, 0x96BC, 0xF6C1, 0x96BD, 0xF6C2, 0x96CE, 0xF6C3, 0x96D2, 0xF6C4, 0x77BF, + 0xF6C5, 0x96E0, 0xF6C6, 0x928E, 0xF6C7, 0x92AE, 0xF6C8, 0x92C8, 0xF6C9, 0x933E, 0xF6CA, 0x936A, 0xF6CB, 0x93CA, 0xF6CC, 0x938F, + 0xF6CD, 0x943E, 0xF6CE, 0x946B, 0xF6CF, 0x9C7F, 0xF6D0, 0x9C82, 0xF6D1, 0x9C85, 0xF6D2, 0x9C86, 0xF6D3, 0x9C87, 0xF6D4, 0x9C88, + 0xF6D5, 0x7A23, 0xF6D6, 0x9C8B, 0xF6D7, 0x9C8E, 0xF6D8, 0x9C90, 0xF6D9, 0x9C91, 0xF6DA, 0x9C92, 0xF6DB, 0x9C94, 0xF6DC, 0x9C95, + 0xF6DD, 0x9C9A, 0xF6DE, 0x9C9B, 0xF6DF, 0x9C9E, 0xF6E0, 0x9C9F, 0xF6E1, 0x9CA0, 0xF6E2, 0x9CA1, 0xF6E3, 0x9CA2, 0xF6E4, 0x9CA3, + 0xF6E5, 0x9CA5, 0xF6E6, 0x9CA6, 0xF6E7, 0x9CA7, 0xF6E8, 0x9CA8, 0xF6E9, 0x9CA9, 0xF6EA, 0x9CAB, 0xF6EB, 0x9CAD, 0xF6EC, 0x9CAE, + 0xF6ED, 0x9CB0, 0xF6EE, 0x9CB1, 0xF6EF, 0x9CB2, 0xF6F0, 0x9CB3, 0xF6F1, 0x9CB4, 0xF6F2, 0x9CB5, 0xF6F3, 0x9CB6, 0xF6F4, 0x9CB7, + 0xF6F5, 0x9CBA, 0xF6F6, 0x9CBB, 0xF6F7, 0x9CBC, 0xF6F8, 0x9CBD, 0xF6F9, 0x9CC4, 0xF6FA, 0x9CC5, 0xF6FB, 0x9CC6, 0xF6FC, 0x9CC7, + 0xF6FD, 0x9CCA, 0xF6FE, 0x9CCB, 0xF740, 0x9C3C, 0xF741, 0x9C3D, 0xF742, 0x9C3E, 0xF743, 0x9C3F, 0xF744, 0x9C40, 0xF745, 0x9C41, + 0xF746, 0x9C42, 0xF747, 0x9C43, 0xF748, 0x9C44, 0xF749, 0x9C45, 0xF74A, 0x9C46, 0xF74B, 0x9C47, 0xF74C, 0x9C48, 0xF74D, 0x9C49, + 0xF74E, 0x9C4A, 0xF74F, 0x9C4B, 0xF750, 0x9C4C, 0xF751, 0x9C4D, 0xF752, 0x9C4E, 0xF753, 0x9C4F, 0xF754, 0x9C50, 0xF755, 0x9C51, + 0xF756, 0x9C52, 0xF757, 0x9C53, 0xF758, 0x9C54, 0xF759, 0x9C55, 0xF75A, 0x9C56, 0xF75B, 0x9C57, 0xF75C, 0x9C58, 0xF75D, 0x9C59, + 0xF75E, 0x9C5A, 0xF75F, 0x9C5B, 0xF760, 0x9C5C, 0xF761, 0x9C5D, 0xF762, 0x9C5E, 0xF763, 0x9C5F, 0xF764, 0x9C60, 0xF765, 0x9C61, + 0xF766, 0x9C62, 0xF767, 0x9C63, 0xF768, 0x9C64, 0xF769, 0x9C65, 0xF76A, 0x9C66, 0xF76B, 0x9C67, 0xF76C, 0x9C68, 0xF76D, 0x9C69, + 0xF76E, 0x9C6A, 0xF76F, 0x9C6B, 0xF770, 0x9C6C, 0xF771, 0x9C6D, 0xF772, 0x9C6E, 0xF773, 0x9C6F, 0xF774, 0x9C70, 0xF775, 0x9C71, + 0xF776, 0x9C72, 0xF777, 0x9C73, 0xF778, 0x9C74, 0xF779, 0x9C75, 0xF77A, 0x9C76, 0xF77B, 0x9C77, 0xF77C, 0x9C78, 0xF77D, 0x9C79, + 0xF77E, 0x9C7A, 0xF780, 0x9C7B, 0xF781, 0x9C7D, 0xF782, 0x9C7E, 0xF783, 0x9C80, 0xF784, 0x9C83, 0xF785, 0x9C84, 0xF786, 0x9C89, + 0xF787, 0x9C8A, 0xF788, 0x9C8C, 0xF789, 0x9C8F, 0xF78A, 0x9C93, 0xF78B, 0x9C96, 0xF78C, 0x9C97, 0xF78D, 0x9C98, 0xF78E, 0x9C99, + 0xF78F, 0x9C9D, 0xF790, 0x9CAA, 0xF791, 0x9CAC, 0xF792, 0x9CAF, 0xF793, 0x9CB9, 0xF794, 0x9CBE, 0xF795, 0x9CBF, 0xF796, 0x9CC0, + 0xF797, 0x9CC1, 0xF798, 0x9CC2, 0xF799, 0x9CC8, 0xF79A, 0x9CC9, 0xF79B, 0x9CD1, 0xF79C, 0x9CD2, 0xF79D, 0x9CDA, 0xF79E, 0x9CDB, + 0xF79F, 0x9CE0, 0xF7A0, 0x9CE1, 0xF7A1, 0x9CCC, 0xF7A2, 0x9CCD, 0xF7A3, 0x9CCE, 0xF7A4, 0x9CCF, 0xF7A5, 0x9CD0, 0xF7A6, 0x9CD3, + 0xF7A7, 0x9CD4, 0xF7A8, 0x9CD5, 0xF7A9, 0x9CD7, 0xF7AA, 0x9CD8, 0xF7AB, 0x9CD9, 0xF7AC, 0x9CDC, 0xF7AD, 0x9CDD, 0xF7AE, 0x9CDF, + 0xF7AF, 0x9CE2, 0xF7B0, 0x977C, 0xF7B1, 0x9785, 0xF7B2, 0x9791, 0xF7B3, 0x9792, 0xF7B4, 0x9794, 0xF7B5, 0x97AF, 0xF7B6, 0x97AB, + 0xF7B7, 0x97A3, 0xF7B8, 0x97B2, 0xF7B9, 0x97B4, 0xF7BA, 0x9AB1, 0xF7BB, 0x9AB0, 0xF7BC, 0x9AB7, 0xF7BD, 0x9E58, 0xF7BE, 0x9AB6, + 0xF7BF, 0x9ABA, 0xF7C0, 0x9ABC, 0xF7C1, 0x9AC1, 0xF7C2, 0x9AC0, 0xF7C3, 0x9AC5, 0xF7C4, 0x9AC2, 0xF7C5, 0x9ACB, 0xF7C6, 0x9ACC, + 0xF7C7, 0x9AD1, 0xF7C8, 0x9B45, 0xF7C9, 0x9B43, 0xF7CA, 0x9B47, 0xF7CB, 0x9B49, 0xF7CC, 0x9B48, 0xF7CD, 0x9B4D, 0xF7CE, 0x9B51, + 0xF7CF, 0x98E8, 0xF7D0, 0x990D, 0xF7D1, 0x992E, 0xF7D2, 0x9955, 0xF7D3, 0x9954, 0xF7D4, 0x9ADF, 0xF7D5, 0x9AE1, 0xF7D6, 0x9AE6, + 0xF7D7, 0x9AEF, 0xF7D8, 0x9AEB, 0xF7D9, 0x9AFB, 0xF7DA, 0x9AED, 0xF7DB, 0x9AF9, 0xF7DC, 0x9B08, 0xF7DD, 0x9B0F, 0xF7DE, 0x9B13, + 0xF7DF, 0x9B1F, 0xF7E0, 0x9B23, 0xF7E1, 0x9EBD, 0xF7E2, 0x9EBE, 0xF7E3, 0x7E3B, 0xF7E4, 0x9E82, 0xF7E5, 0x9E87, 0xF7E6, 0x9E88, + 0xF7E7, 0x9E8B, 0xF7E8, 0x9E92, 0xF7E9, 0x93D6, 0xF7EA, 0x9E9D, 0xF7EB, 0x9E9F, 0xF7EC, 0x9EDB, 0xF7ED, 0x9EDC, 0xF7EE, 0x9EDD, + 0xF7EF, 0x9EE0, 0xF7F0, 0x9EDF, 0xF7F1, 0x9EE2, 0xF7F2, 0x9EE9, 0xF7F3, 0x9EE7, 0xF7F4, 0x9EE5, 0xF7F5, 0x9EEA, 0xF7F6, 0x9EEF, + 0xF7F7, 0x9F22, 0xF7F8, 0x9F2C, 0xF7F9, 0x9F2F, 0xF7FA, 0x9F39, 0xF7FB, 0x9F37, 0xF7FC, 0x9F3D, 0xF7FD, 0x9F3E, 0xF7FE, 0x9F44, + 0xF840, 0x9CE3, 0xF841, 0x9CE4, 0xF842, 0x9CE5, 0xF843, 0x9CE6, 0xF844, 0x9CE7, 0xF845, 0x9CE8, 0xF846, 0x9CE9, 0xF847, 0x9CEA, + 0xF848, 0x9CEB, 0xF849, 0x9CEC, 0xF84A, 0x9CED, 0xF84B, 0x9CEE, 0xF84C, 0x9CEF, 0xF84D, 0x9CF0, 0xF84E, 0x9CF1, 0xF84F, 0x9CF2, + 0xF850, 0x9CF3, 0xF851, 0x9CF4, 0xF852, 0x9CF5, 0xF853, 0x9CF6, 0xF854, 0x9CF7, 0xF855, 0x9CF8, 0xF856, 0x9CF9, 0xF857, 0x9CFA, + 0xF858, 0x9CFB, 0xF859, 0x9CFC, 0xF85A, 0x9CFD, 0xF85B, 0x9CFE, 0xF85C, 0x9CFF, 0xF85D, 0x9D00, 0xF85E, 0x9D01, 0xF85F, 0x9D02, + 0xF860, 0x9D03, 0xF861, 0x9D04, 0xF862, 0x9D05, 0xF863, 0x9D06, 0xF864, 0x9D07, 0xF865, 0x9D08, 0xF866, 0x9D09, 0xF867, 0x9D0A, + 0xF868, 0x9D0B, 0xF869, 0x9D0C, 0xF86A, 0x9D0D, 0xF86B, 0x9D0E, 0xF86C, 0x9D0F, 0xF86D, 0x9D10, 0xF86E, 0x9D11, 0xF86F, 0x9D12, + 0xF870, 0x9D13, 0xF871, 0x9D14, 0xF872, 0x9D15, 0xF873, 0x9D16, 0xF874, 0x9D17, 0xF875, 0x9D18, 0xF876, 0x9D19, 0xF877, 0x9D1A, + 0xF878, 0x9D1B, 0xF879, 0x9D1C, 0xF87A, 0x9D1D, 0xF87B, 0x9D1E, 0xF87C, 0x9D1F, 0xF87D, 0x9D20, 0xF87E, 0x9D21, 0xF880, 0x9D22, + 0xF881, 0x9D23, 0xF882, 0x9D24, 0xF883, 0x9D25, 0xF884, 0x9D26, 0xF885, 0x9D27, 0xF886, 0x9D28, 0xF887, 0x9D29, 0xF888, 0x9D2A, + 0xF889, 0x9D2B, 0xF88A, 0x9D2C, 0xF88B, 0x9D2D, 0xF88C, 0x9D2E, 0xF88D, 0x9D2F, 0xF88E, 0x9D30, 0xF88F, 0x9D31, 0xF890, 0x9D32, + 0xF891, 0x9D33, 0xF892, 0x9D34, 0xF893, 0x9D35, 0xF894, 0x9D36, 0xF895, 0x9D37, 0xF896, 0x9D38, 0xF897, 0x9D39, 0xF898, 0x9D3A, + 0xF899, 0x9D3B, 0xF89A, 0x9D3C, 0xF89B, 0x9D3D, 0xF89C, 0x9D3E, 0xF89D, 0x9D3F, 0xF89E, 0x9D40, 0xF89F, 0x9D41, 0xF8A0, 0x9D42, + 0xF940, 0x9D43, 0xF941, 0x9D44, 0xF942, 0x9D45, 0xF943, 0x9D46, 0xF944, 0x9D47, 0xF945, 0x9D48, 0xF946, 0x9D49, 0xF947, 0x9D4A, + 0xF948, 0x9D4B, 0xF949, 0x9D4C, 0xF94A, 0x9D4D, 0xF94B, 0x9D4E, 0xF94C, 0x9D4F, 0xF94D, 0x9D50, 0xF94E, 0x9D51, 0xF94F, 0x9D52, + 0xF950, 0x9D53, 0xF951, 0x9D54, 0xF952, 0x9D55, 0xF953, 0x9D56, 0xF954, 0x9D57, 0xF955, 0x9D58, 0xF956, 0x9D59, 0xF957, 0x9D5A, + 0xF958, 0x9D5B, 0xF959, 0x9D5C, 0xF95A, 0x9D5D, 0xF95B, 0x9D5E, 0xF95C, 0x9D5F, 0xF95D, 0x9D60, 0xF95E, 0x9D61, 0xF95F, 0x9D62, + 0xF960, 0x9D63, 0xF961, 0x9D64, 0xF962, 0x9D65, 0xF963, 0x9D66, 0xF964, 0x9D67, 0xF965, 0x9D68, 0xF966, 0x9D69, 0xF967, 0x9D6A, + 0xF968, 0x9D6B, 0xF969, 0x9D6C, 0xF96A, 0x9D6D, 0xF96B, 0x9D6E, 0xF96C, 0x9D6F, 0xF96D, 0x9D70, 0xF96E, 0x9D71, 0xF96F, 0x9D72, + 0xF970, 0x9D73, 0xF971, 0x9D74, 0xF972, 0x9D75, 0xF973, 0x9D76, 0xF974, 0x9D77, 0xF975, 0x9D78, 0xF976, 0x9D79, 0xF977, 0x9D7A, + 0xF978, 0x9D7B, 0xF979, 0x9D7C, 0xF97A, 0x9D7D, 0xF97B, 0x9D7E, 0xF97C, 0x9D7F, 0xF97D, 0x9D80, 0xF97E, 0x9D81, 0xF980, 0x9D82, + 0xF981, 0x9D83, 0xF982, 0x9D84, 0xF983, 0x9D85, 0xF984, 0x9D86, 0xF985, 0x9D87, 0xF986, 0x9D88, 0xF987, 0x9D89, 0xF988, 0x9D8A, + 0xF989, 0x9D8B, 0xF98A, 0x9D8C, 0xF98B, 0x9D8D, 0xF98C, 0x9D8E, 0xF98D, 0x9D8F, 0xF98E, 0x9D90, 0xF98F, 0x9D91, 0xF990, 0x9D92, + 0xF991, 0x9D93, 0xF992, 0x9D94, 0xF993, 0x9D95, 0xF994, 0x9D96, 0xF995, 0x9D97, 0xF996, 0x9D98, 0xF997, 0x9D99, 0xF998, 0x9D9A, + 0xF999, 0x9D9B, 0xF99A, 0x9D9C, 0xF99B, 0x9D9D, 0xF99C, 0x9D9E, 0xF99D, 0x9D9F, 0xF99E, 0x9DA0, 0xF99F, 0x9DA1, 0xF9A0, 0x9DA2, + 0xFA40, 0x9DA3, 0xFA41, 0x9DA4, 0xFA42, 0x9DA5, 0xFA43, 0x9DA6, 0xFA44, 0x9DA7, 0xFA45, 0x9DA8, 0xFA46, 0x9DA9, 0xFA47, 0x9DAA, + 0xFA48, 0x9DAB, 0xFA49, 0x9DAC, 0xFA4A, 0x9DAD, 0xFA4B, 0x9DAE, 0xFA4C, 0x9DAF, 0xFA4D, 0x9DB0, 0xFA4E, 0x9DB1, 0xFA4F, 0x9DB2, + 0xFA50, 0x9DB3, 0xFA51, 0x9DB4, 0xFA52, 0x9DB5, 0xFA53, 0x9DB6, 0xFA54, 0x9DB7, 0xFA55, 0x9DB8, 0xFA56, 0x9DB9, 0xFA57, 0x9DBA, + 0xFA58, 0x9DBB, 0xFA59, 0x9DBC, 0xFA5A, 0x9DBD, 0xFA5B, 0x9DBE, 0xFA5C, 0x9DBF, 0xFA5D, 0x9DC0, 0xFA5E, 0x9DC1, 0xFA5F, 0x9DC2, + 0xFA60, 0x9DC3, 0xFA61, 0x9DC4, 0xFA62, 0x9DC5, 0xFA63, 0x9DC6, 0xFA64, 0x9DC7, 0xFA65, 0x9DC8, 0xFA66, 0x9DC9, 0xFA67, 0x9DCA, + 0xFA68, 0x9DCB, 0xFA69, 0x9DCC, 0xFA6A, 0x9DCD, 0xFA6B, 0x9DCE, 0xFA6C, 0x9DCF, 0xFA6D, 0x9DD0, 0xFA6E, 0x9DD1, 0xFA6F, 0x9DD2, + 0xFA70, 0x9DD3, 0xFA71, 0x9DD4, 0xFA72, 0x9DD5, 0xFA73, 0x9DD6, 0xFA74, 0x9DD7, 0xFA75, 0x9DD8, 0xFA76, 0x9DD9, 0xFA77, 0x9DDA, + 0xFA78, 0x9DDB, 0xFA79, 0x9DDC, 0xFA7A, 0x9DDD, 0xFA7B, 0x9DDE, 0xFA7C, 0x9DDF, 0xFA7D, 0x9DE0, 0xFA7E, 0x9DE1, 0xFA80, 0x9DE2, + 0xFA81, 0x9DE3, 0xFA82, 0x9DE4, 0xFA83, 0x9DE5, 0xFA84, 0x9DE6, 0xFA85, 0x9DE7, 0xFA86, 0x9DE8, 0xFA87, 0x9DE9, 0xFA88, 0x9DEA, + 0xFA89, 0x9DEB, 0xFA8A, 0x9DEC, 0xFA8B, 0x9DED, 0xFA8C, 0x9DEE, 0xFA8D, 0x9DEF, 0xFA8E, 0x9DF0, 0xFA8F, 0x9DF1, 0xFA90, 0x9DF2, + 0xFA91, 0x9DF3, 0xFA92, 0x9DF4, 0xFA93, 0x9DF5, 0xFA94, 0x9DF6, 0xFA95, 0x9DF7, 0xFA96, 0x9DF8, 0xFA97, 0x9DF9, 0xFA98, 0x9DFA, + 0xFA99, 0x9DFB, 0xFA9A, 0x9DFC, 0xFA9B, 0x9DFD, 0xFA9C, 0x9DFE, 0xFA9D, 0x9DFF, 0xFA9E, 0x9E00, 0xFA9F, 0x9E01, 0xFAA0, 0x9E02, + 0xFB40, 0x9E03, 0xFB41, 0x9E04, 0xFB42, 0x9E05, 0xFB43, 0x9E06, 0xFB44, 0x9E07, 0xFB45, 0x9E08, 0xFB46, 0x9E09, 0xFB47, 0x9E0A, + 0xFB48, 0x9E0B, 0xFB49, 0x9E0C, 0xFB4A, 0x9E0D, 0xFB4B, 0x9E0E, 0xFB4C, 0x9E0F, 0xFB4D, 0x9E10, 0xFB4E, 0x9E11, 0xFB4F, 0x9E12, + 0xFB50, 0x9E13, 0xFB51, 0x9E14, 0xFB52, 0x9E15, 0xFB53, 0x9E16, 0xFB54, 0x9E17, 0xFB55, 0x9E18, 0xFB56, 0x9E19, 0xFB57, 0x9E1A, + 0xFB58, 0x9E1B, 0xFB59, 0x9E1C, 0xFB5A, 0x9E1D, 0xFB5B, 0x9E1E, 0xFB5C, 0x9E24, 0xFB5D, 0x9E27, 0xFB5E, 0x9E2E, 0xFB5F, 0x9E30, + 0xFB60, 0x9E34, 0xFB61, 0x9E3B, 0xFB62, 0x9E3C, 0xFB63, 0x9E40, 0xFB64, 0x9E4D, 0xFB65, 0x9E50, 0xFB66, 0x9E52, 0xFB67, 0x9E53, + 0xFB68, 0x9E54, 0xFB69, 0x9E56, 0xFB6A, 0x9E59, 0xFB6B, 0x9E5D, 0xFB6C, 0x9E5F, 0xFB6D, 0x9E60, 0xFB6E, 0x9E61, 0xFB6F, 0x9E62, + 0xFB70, 0x9E65, 0xFB71, 0x9E6E, 0xFB72, 0x9E6F, 0xFB73, 0x9E72, 0xFB74, 0x9E74, 0xFB75, 0x9E75, 0xFB76, 0x9E76, 0xFB77, 0x9E77, + 0xFB78, 0x9E78, 0xFB79, 0x9E79, 0xFB7A, 0x9E7A, 0xFB7B, 0x9E7B, 0xFB7C, 0x9E7C, 0xFB7D, 0x9E7D, 0xFB7E, 0x9E80, 0xFB80, 0x9E81, + 0xFB81, 0x9E83, 0xFB82, 0x9E84, 0xFB83, 0x9E85, 0xFB84, 0x9E86, 0xFB85, 0x9E89, 0xFB86, 0x9E8A, 0xFB87, 0x9E8C, 0xFB88, 0x9E8D, + 0xFB89, 0x9E8E, 0xFB8A, 0x9E8F, 0xFB8B, 0x9E90, 0xFB8C, 0x9E91, 0xFB8D, 0x9E94, 0xFB8E, 0x9E95, 0xFB8F, 0x9E96, 0xFB90, 0x9E97, + 0xFB91, 0x9E98, 0xFB92, 0x9E99, 0xFB93, 0x9E9A, 0xFB94, 0x9E9B, 0xFB95, 0x9E9C, 0xFB96, 0x9E9E, 0xFB97, 0x9EA0, 0xFB98, 0x9EA1, + 0xFB99, 0x9EA2, 0xFB9A, 0x9EA3, 0xFB9B, 0x9EA4, 0xFB9C, 0x9EA5, 0xFB9D, 0x9EA7, 0xFB9E, 0x9EA8, 0xFB9F, 0x9EA9, 0xFBA0, 0x9EAA, + 0xFC40, 0x9EAB, 0xFC41, 0x9EAC, 0xFC42, 0x9EAD, 0xFC43, 0x9EAE, 0xFC44, 0x9EAF, 0xFC45, 0x9EB0, 0xFC46, 0x9EB1, 0xFC47, 0x9EB2, + 0xFC48, 0x9EB3, 0xFC49, 0x9EB5, 0xFC4A, 0x9EB6, 0xFC4B, 0x9EB7, 0xFC4C, 0x9EB9, 0xFC4D, 0x9EBA, 0xFC4E, 0x9EBC, 0xFC4F, 0x9EBF, + 0xFC50, 0x9EC0, 0xFC51, 0x9EC1, 0xFC52, 0x9EC2, 0xFC53, 0x9EC3, 0xFC54, 0x9EC5, 0xFC55, 0x9EC6, 0xFC56, 0x9EC7, 0xFC57, 0x9EC8, + 0xFC58, 0x9ECA, 0xFC59, 0x9ECB, 0xFC5A, 0x9ECC, 0xFC5B, 0x9ED0, 0xFC5C, 0x9ED2, 0xFC5D, 0x9ED3, 0xFC5E, 0x9ED5, 0xFC5F, 0x9ED6, + 0xFC60, 0x9ED7, 0xFC61, 0x9ED9, 0xFC62, 0x9EDA, 0xFC63, 0x9EDE, 0xFC64, 0x9EE1, 0xFC65, 0x9EE3, 0xFC66, 0x9EE4, 0xFC67, 0x9EE6, + 0xFC68, 0x9EE8, 0xFC69, 0x9EEB, 0xFC6A, 0x9EEC, 0xFC6B, 0x9EED, 0xFC6C, 0x9EEE, 0xFC6D, 0x9EF0, 0xFC6E, 0x9EF1, 0xFC6F, 0x9EF2, + 0xFC70, 0x9EF3, 0xFC71, 0x9EF4, 0xFC72, 0x9EF5, 0xFC73, 0x9EF6, 0xFC74, 0x9EF7, 0xFC75, 0x9EF8, 0xFC76, 0x9EFA, 0xFC77, 0x9EFD, + 0xFC78, 0x9EFF, 0xFC79, 0x9F00, 0xFC7A, 0x9F01, 0xFC7B, 0x9F02, 0xFC7C, 0x9F03, 0xFC7D, 0x9F04, 0xFC7E, 0x9F05, 0xFC80, 0x9F06, + 0xFC81, 0x9F07, 0xFC82, 0x9F08, 0xFC83, 0x9F09, 0xFC84, 0x9F0A, 0xFC85, 0x9F0C, 0xFC86, 0x9F0F, 0xFC87, 0x9F11, 0xFC88, 0x9F12, + 0xFC89, 0x9F14, 0xFC8A, 0x9F15, 0xFC8B, 0x9F16, 0xFC8C, 0x9F18, 0xFC8D, 0x9F1A, 0xFC8E, 0x9F1B, 0xFC8F, 0x9F1C, 0xFC90, 0x9F1D, + 0xFC91, 0x9F1E, 0xFC92, 0x9F1F, 0xFC93, 0x9F21, 0xFC94, 0x9F23, 0xFC95, 0x9F24, 0xFC96, 0x9F25, 0xFC97, 0x9F26, 0xFC98, 0x9F27, + 0xFC99, 0x9F28, 0xFC9A, 0x9F29, 0xFC9B, 0x9F2A, 0xFC9C, 0x9F2B, 0xFC9D, 0x9F2D, 0xFC9E, 0x9F2E, 0xFC9F, 0x9F30, 0xFCA0, 0x9F31, + 0xFD40, 0x9F32, 0xFD41, 0x9F33, 0xFD42, 0x9F34, 0xFD43, 0x9F35, 0xFD44, 0x9F36, 0xFD45, 0x9F38, 0xFD46, 0x9F3A, 0xFD47, 0x9F3C, + 0xFD48, 0x9F3F, 0xFD49, 0x9F40, 0xFD4A, 0x9F41, 0xFD4B, 0x9F42, 0xFD4C, 0x9F43, 0xFD4D, 0x9F45, 0xFD4E, 0x9F46, 0xFD4F, 0x9F47, + 0xFD50, 0x9F48, 0xFD51, 0x9F49, 0xFD52, 0x9F4A, 0xFD53, 0x9F4B, 0xFD54, 0x9F4C, 0xFD55, 0x9F4D, 0xFD56, 0x9F4E, 0xFD57, 0x9F4F, + 0xFD58, 0x9F52, 0xFD59, 0x9F53, 0xFD5A, 0x9F54, 0xFD5B, 0x9F55, 0xFD5C, 0x9F56, 0xFD5D, 0x9F57, 0xFD5E, 0x9F58, 0xFD5F, 0x9F59, + 0xFD60, 0x9F5A, 0xFD61, 0x9F5B, 0xFD62, 0x9F5C, 0xFD63, 0x9F5D, 0xFD64, 0x9F5E, 0xFD65, 0x9F5F, 0xFD66, 0x9F60, 0xFD67, 0x9F61, + 0xFD68, 0x9F62, 0xFD69, 0x9F63, 0xFD6A, 0x9F64, 0xFD6B, 0x9F65, 0xFD6C, 0x9F66, 0xFD6D, 0x9F67, 0xFD6E, 0x9F68, 0xFD6F, 0x9F69, + 0xFD70, 0x9F6A, 0xFD71, 0x9F6B, 0xFD72, 0x9F6C, 0xFD73, 0x9F6D, 0xFD74, 0x9F6E, 0xFD75, 0x9F6F, 0xFD76, 0x9F70, 0xFD77, 0x9F71, + 0xFD78, 0x9F72, 0xFD79, 0x9F73, 0xFD7A, 0x9F74, 0xFD7B, 0x9F75, 0xFD7C, 0x9F76, 0xFD7D, 0x9F77, 0xFD7E, 0x9F78, 0xFD80, 0x9F79, + 0xFD81, 0x9F7A, 0xFD82, 0x9F7B, 0xFD83, 0x9F7C, 0xFD84, 0x9F7D, 0xFD85, 0x9F7E, 0xFD86, 0x9F81, 0xFD87, 0x9F82, 0xFD88, 0x9F8D, + 0xFD89, 0x9F8E, 0xFD8A, 0x9F8F, 0xFD8B, 0x9F90, 0xFD8C, 0x9F91, 0xFD8D, 0x9F92, 0xFD8E, 0x9F93, 0xFD8F, 0x9F94, 0xFD90, 0x9F95, + 0xFD91, 0x9F96, 0xFD92, 0x9F97, 0xFD93, 0x9F98, 0xFD94, 0x9F9C, 0xFD95, 0x9F9D, 0xFD96, 0x9F9E, 0xFD97, 0x9FA1, 0xFD98, 0x9FA2, + 0xFD99, 0x9FA3, 0xFD9A, 0x9FA4, 0xFD9B, 0x9FA5, 0xFD9C, 0xF92C, 0xFD9D, 0xF979, 0xFD9E, 0xF995, 0xFD9F, 0xF9E7, 0xFDA0, 0xF9F1, + 0xFE40, 0xFA0C, 0xFE41, 0xFA0D, 0xFE42, 0xFA0E, 0xFE43, 0xFA0F, 0xFE44, 0xFA11, 0xFE45, 0xFA13, 0xFE46, 0xFA14, 0xFE47, 0xFA18, + 0xFE48, 0xFA1F, 0xFE49, 0xFA20, 0xFE4A, 0xFA21, 0xFE4B, 0xFA23, 0xFE4C, 0xFA24, 0xFE4D, 0xFA27, 0xFE4E, 0xFA28, 0xFE4F, 0xFA29, + 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 949 || FF_CODE_PAGE == 0 /* Korean */ +static const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */ + 0x00A1, 0xA2AE, 0x00A4, 0xA2B4, 0x00A7, 0xA1D7, 0x00A8, 0xA1A7, 0x00AA, 0xA8A3, 0x00AD, 0xA1A9, 0x00AE, 0xA2E7, 0x00B0, 0xA1C6, + 0x00B1, 0xA1BE, 0x00B2, 0xA9F7, 0x00B3, 0xA9F8, 0x00B4, 0xA2A5, 0x00B6, 0xA2D2, 0x00B7, 0xA1A4, 0x00B8, 0xA2AC, 0x00B9, 0xA9F6, + 0x00BA, 0xA8AC, 0x00BC, 0xA8F9, 0x00BD, 0xA8F6, 0x00BE, 0xA8FA, 0x00BF, 0xA2AF, 0x00C6, 0xA8A1, 0x00D0, 0xA8A2, 0x00D7, 0xA1BF, + 0x00D8, 0xA8AA, 0x00DE, 0xA8AD, 0x00DF, 0xA9AC, 0x00E6, 0xA9A1, 0x00F0, 0xA9A3, 0x00F7, 0xA1C0, 0x00F8, 0xA9AA, 0x00FE, 0xA9AD, + 0x0111, 0xA9A2, 0x0126, 0xA8A4, 0x0127, 0xA9A4, 0x0131, 0xA9A5, 0x0132, 0xA8A6, 0x0133, 0xA9A6, 0x0138, 0xA9A7, 0x013F, 0xA8A8, + 0x0140, 0xA9A8, 0x0141, 0xA8A9, 0x0142, 0xA9A9, 0x0149, 0xA9B0, 0x014A, 0xA8AF, 0x014B, 0xA9AF, 0x0152, 0xA8AB, 0x0153, 0xA9AB, + 0x0166, 0xA8AE, 0x0167, 0xA9AE, 0x02C7, 0xA2A7, 0x02D0, 0xA2B0, 0x02D8, 0xA2A8, 0x02D9, 0xA2AB, 0x02DA, 0xA2AA, 0x02DB, 0xA2AD, + 0x02DD, 0xA2A9, 0x0391, 0xA5C1, 0x0392, 0xA5C2, 0x0393, 0xA5C3, 0x0394, 0xA5C4, 0x0395, 0xA5C5, 0x0396, 0xA5C6, 0x0397, 0xA5C7, + 0x0398, 0xA5C8, 0x0399, 0xA5C9, 0x039A, 0xA5CA, 0x039B, 0xA5CB, 0x039C, 0xA5CC, 0x039D, 0xA5CD, 0x039E, 0xA5CE, 0x039F, 0xA5CF, + 0x03A0, 0xA5D0, 0x03A1, 0xA5D1, 0x03A3, 0xA5D2, 0x03A4, 0xA5D3, 0x03A5, 0xA5D4, 0x03A6, 0xA5D5, 0x03A7, 0xA5D6, 0x03A8, 0xA5D7, + 0x03A9, 0xA5D8, 0x03B1, 0xA5E1, 0x03B2, 0xA5E2, 0x03B3, 0xA5E3, 0x03B4, 0xA5E4, 0x03B5, 0xA5E5, 0x03B6, 0xA5E6, 0x03B7, 0xA5E7, + 0x03B8, 0xA5E8, 0x03B9, 0xA5E9, 0x03BA, 0xA5EA, 0x03BB, 0xA5EB, 0x03BC, 0xA5EC, 0x03BD, 0xA5ED, 0x03BE, 0xA5EE, 0x03BF, 0xA5EF, + 0x03C0, 0xA5F0, 0x03C1, 0xA5F1, 0x03C3, 0xA5F2, 0x03C4, 0xA5F3, 0x03C5, 0xA5F4, 0x03C6, 0xA5F5, 0x03C7, 0xA5F6, 0x03C8, 0xA5F7, + 0x03C9, 0xA5F8, 0x0401, 0xACA7, 0x0410, 0xACA1, 0x0411, 0xACA2, 0x0412, 0xACA3, 0x0413, 0xACA4, 0x0414, 0xACA5, 0x0415, 0xACA6, + 0x0416, 0xACA8, 0x0417, 0xACA9, 0x0418, 0xACAA, 0x0419, 0xACAB, 0x041A, 0xACAC, 0x041B, 0xACAD, 0x041C, 0xACAE, 0x041D, 0xACAF, + 0x041E, 0xACB0, 0x041F, 0xACB1, 0x0420, 0xACB2, 0x0421, 0xACB3, 0x0422, 0xACB4, 0x0423, 0xACB5, 0x0424, 0xACB6, 0x0425, 0xACB7, + 0x0426, 0xACB8, 0x0427, 0xACB9, 0x0428, 0xACBA, 0x0429, 0xACBB, 0x042A, 0xACBC, 0x042B, 0xACBD, 0x042C, 0xACBE, 0x042D, 0xACBF, + 0x042E, 0xACC0, 0x042F, 0xACC1, 0x0430, 0xACD1, 0x0431, 0xACD2, 0x0432, 0xACD3, 0x0433, 0xACD4, 0x0434, 0xACD5, 0x0435, 0xACD6, + 0x0436, 0xACD8, 0x0437, 0xACD9, 0x0438, 0xACDA, 0x0439, 0xACDB, 0x043A, 0xACDC, 0x043B, 0xACDD, 0x043C, 0xACDE, 0x043D, 0xACDF, + 0x043E, 0xACE0, 0x043F, 0xACE1, 0x0440, 0xACE2, 0x0441, 0xACE3, 0x0442, 0xACE4, 0x0443, 0xACE5, 0x0444, 0xACE6, 0x0445, 0xACE7, + 0x0446, 0xACE8, 0x0447, 0xACE9, 0x0448, 0xACEA, 0x0449, 0xACEB, 0x044A, 0xACEC, 0x044B, 0xACED, 0x044C, 0xACEE, 0x044D, 0xACEF, + 0x044E, 0xACF0, 0x044F, 0xACF1, 0x0451, 0xACD7, 0x2015, 0xA1AA, 0x2018, 0xA1AE, 0x2019, 0xA1AF, 0x201C, 0xA1B0, 0x201D, 0xA1B1, + 0x2020, 0xA2D3, 0x2021, 0xA2D4, 0x2025, 0xA1A5, 0x2026, 0xA1A6, 0x2030, 0xA2B6, 0x2032, 0xA1C7, 0x2033, 0xA1C8, 0x203B, 0xA1D8, + 0x2074, 0xA9F9, 0x207F, 0xA9FA, 0x2081, 0xA9FB, 0x2082, 0xA9FC, 0x2083, 0xA9FD, 0x2084, 0xA9FE, 0x20AC, 0xA2E6, 0x2103, 0xA1C9, + 0x2109, 0xA2B5, 0x2113, 0xA7A4, 0x2116, 0xA2E0, 0x2121, 0xA2E5, 0x2122, 0xA2E2, 0x2126, 0xA7D9, 0x212B, 0xA1CA, 0x2153, 0xA8F7, + 0x2154, 0xA8F8, 0x215B, 0xA8FB, 0x215C, 0xA8FC, 0x215D, 0xA8FD, 0x215E, 0xA8FE, 0x2160, 0xA5B0, 0x2161, 0xA5B1, 0x2162, 0xA5B2, + 0x2163, 0xA5B3, 0x2164, 0xA5B4, 0x2165, 0xA5B5, 0x2166, 0xA5B6, 0x2167, 0xA5B7, 0x2168, 0xA5B8, 0x2169, 0xA5B9, 0x2170, 0xA5A1, + 0x2171, 0xA5A2, 0x2172, 0xA5A3, 0x2173, 0xA5A4, 0x2174, 0xA5A5, 0x2175, 0xA5A6, 0x2176, 0xA5A7, 0x2177, 0xA5A8, 0x2178, 0xA5A9, + 0x2179, 0xA5AA, 0x2190, 0xA1E7, 0x2191, 0xA1E8, 0x2192, 0xA1E6, 0x2193, 0xA1E9, 0x2194, 0xA1EA, 0x2195, 0xA2D5, 0x2196, 0xA2D8, + 0x2197, 0xA2D6, 0x2198, 0xA2D9, 0x2199, 0xA2D7, 0x21D2, 0xA2A1, 0x21D4, 0xA2A2, 0x2200, 0xA2A3, 0x2202, 0xA1D3, 0x2203, 0xA2A4, + 0x2207, 0xA1D4, 0x2208, 0xA1F4, 0x220B, 0xA1F5, 0x220F, 0xA2B3, 0x2211, 0xA2B2, 0x221A, 0xA1EE, 0x221D, 0xA1F0, 0x221E, 0xA1C4, + 0x2220, 0xA1D0, 0x2225, 0xA1AB, 0x2227, 0xA1FC, 0x2228, 0xA1FD, 0x2229, 0xA1FB, 0x222A, 0xA1FA, 0x222B, 0xA1F2, 0x222C, 0xA1F3, + 0x222E, 0xA2B1, 0x2234, 0xA1C5, 0x2235, 0xA1F1, 0x223C, 0xA1AD, 0x223D, 0xA1EF, 0x2252, 0xA1D6, 0x2260, 0xA1C1, 0x2261, 0xA1D5, + 0x2264, 0xA1C2, 0x2265, 0xA1C3, 0x226A, 0xA1EC, 0x226B, 0xA1ED, 0x2282, 0xA1F8, 0x2283, 0xA1F9, 0x2286, 0xA1F6, 0x2287, 0xA1F7, + 0x2299, 0xA2C1, 0x22A5, 0xA1D1, 0x2312, 0xA1D2, 0x2460, 0xA8E7, 0x2461, 0xA8E8, 0x2462, 0xA8E9, 0x2463, 0xA8EA, 0x2464, 0xA8EB, + 0x2465, 0xA8EC, 0x2466, 0xA8ED, 0x2467, 0xA8EE, 0x2468, 0xA8EF, 0x2469, 0xA8F0, 0x246A, 0xA8F1, 0x246B, 0xA8F2, 0x246C, 0xA8F3, + 0x246D, 0xA8F4, 0x246E, 0xA8F5, 0x2474, 0xA9E7, 0x2475, 0xA9E8, 0x2476, 0xA9E9, 0x2477, 0xA9EA, 0x2478, 0xA9EB, 0x2479, 0xA9EC, + 0x247A, 0xA9ED, 0x247B, 0xA9EE, 0x247C, 0xA9EF, 0x247D, 0xA9F0, 0x247E, 0xA9F1, 0x247F, 0xA9F2, 0x2480, 0xA9F3, 0x2481, 0xA9F4, + 0x2482, 0xA9F5, 0x249C, 0xA9CD, 0x249D, 0xA9CE, 0x249E, 0xA9CF, 0x249F, 0xA9D0, 0x24A0, 0xA9D1, 0x24A1, 0xA9D2, 0x24A2, 0xA9D3, + 0x24A3, 0xA9D4, 0x24A4, 0xA9D5, 0x24A5, 0xA9D6, 0x24A6, 0xA9D7, 0x24A7, 0xA9D8, 0x24A8, 0xA9D9, 0x24A9, 0xA9DA, 0x24AA, 0xA9DB, + 0x24AB, 0xA9DC, 0x24AC, 0xA9DD, 0x24AD, 0xA9DE, 0x24AE, 0xA9DF, 0x24AF, 0xA9E0, 0x24B0, 0xA9E1, 0x24B1, 0xA9E2, 0x24B2, 0xA9E3, + 0x24B3, 0xA9E4, 0x24B4, 0xA9E5, 0x24B5, 0xA9E6, 0x24D0, 0xA8CD, 0x24D1, 0xA8CE, 0x24D2, 0xA8CF, 0x24D3, 0xA8D0, 0x24D4, 0xA8D1, + 0x24D5, 0xA8D2, 0x24D6, 0xA8D3, 0x24D7, 0xA8D4, 0x24D8, 0xA8D5, 0x24D9, 0xA8D6, 0x24DA, 0xA8D7, 0x24DB, 0xA8D8, 0x24DC, 0xA8D9, + 0x24DD, 0xA8DA, 0x24DE, 0xA8DB, 0x24DF, 0xA8DC, 0x24E0, 0xA8DD, 0x24E1, 0xA8DE, 0x24E2, 0xA8DF, 0x24E3, 0xA8E0, 0x24E4, 0xA8E1, + 0x24E5, 0xA8E2, 0x24E6, 0xA8E3, 0x24E7, 0xA8E4, 0x24E8, 0xA8E5, 0x24E9, 0xA8E6, 0x2500, 0xA6A1, 0x2501, 0xA6AC, 0x2502, 0xA6A2, + 0x2503, 0xA6AD, 0x250C, 0xA6A3, 0x250D, 0xA6C8, 0x250E, 0xA6C7, 0x250F, 0xA6AE, 0x2510, 0xA6A4, 0x2511, 0xA6C2, 0x2512, 0xA6C1, + 0x2513, 0xA6AF, 0x2514, 0xA6A6, 0x2515, 0xA6C6, 0x2516, 0xA6C5, 0x2517, 0xA6B1, 0x2518, 0xA6A5, 0x2519, 0xA6C4, 0x251A, 0xA6C3, + 0x251B, 0xA6B0, 0x251C, 0xA6A7, 0x251D, 0xA6BC, 0x251E, 0xA6C9, 0x251F, 0xA6CA, 0x2520, 0xA6B7, 0x2521, 0xA6CB, 0x2522, 0xA6CC, + 0x2523, 0xA6B2, 0x2524, 0xA6A9, 0x2525, 0xA6BE, 0x2526, 0xA6CD, 0x2527, 0xA6CE, 0x2528, 0xA6B9, 0x2529, 0xA6CF, 0x252A, 0xA6D0, + 0x252B, 0xA6B4, 0x252C, 0xA6A8, 0x252D, 0xA6D1, 0x252E, 0xA6D2, 0x252F, 0xA6B8, 0x2530, 0xA6BD, 0x2531, 0xA6D3, 0x2532, 0xA6D4, + 0x2533, 0xA6B3, 0x2534, 0xA6AA, 0x2535, 0xA6D5, 0x2536, 0xA6D6, 0x2537, 0xA6BA, 0x2538, 0xA6BF, 0x2539, 0xA6D7, 0x253A, 0xA6D8, + 0x253B, 0xA6B5, 0x253C, 0xA6AB, 0x253D, 0xA6D9, 0x253E, 0xA6DA, 0x253F, 0xA6BB, 0x2540, 0xA6DB, 0x2541, 0xA6DC, 0x2542, 0xA6C0, + 0x2543, 0xA6DD, 0x2544, 0xA6DE, 0x2545, 0xA6DF, 0x2546, 0xA6E0, 0x2547, 0xA6E1, 0x2548, 0xA6E2, 0x2549, 0xA6E3, 0x254A, 0xA6E4, + 0x254B, 0xA6B6, 0x2592, 0xA2C6, 0x25A0, 0xA1E1, 0x25A1, 0xA1E0, 0x25A3, 0xA2C3, 0x25A4, 0xA2C7, 0x25A5, 0xA2C8, 0x25A6, 0xA2CB, + 0x25A7, 0xA2CA, 0x25A8, 0xA2C9, 0x25A9, 0xA2CC, 0x25B2, 0xA1E3, 0x25B3, 0xA1E2, 0x25B6, 0xA2BA, 0x25B7, 0xA2B9, 0x25BC, 0xA1E5, + 0x25BD, 0xA1E4, 0x25C0, 0xA2B8, 0x25C1, 0xA2B7, 0x25C6, 0xA1DF, 0x25C7, 0xA1DE, 0x25C8, 0xA2C2, 0x25CB, 0xA1DB, 0x25CE, 0xA1DD, + 0x25CF, 0xA1DC, 0x25D0, 0xA2C4, 0x25D1, 0xA2C5, 0x2605, 0xA1DA, 0x2606, 0xA1D9, 0x260E, 0xA2CF, 0x260F, 0xA2CE, 0x261C, 0xA2D0, + 0x261E, 0xA2D1, 0x2640, 0xA1CF, 0x2642, 0xA1CE, 0x2660, 0xA2BC, 0x2661, 0xA2BD, 0x2663, 0xA2C0, 0x2664, 0xA2BB, 0x2665, 0xA2BE, + 0x2667, 0xA2BF, 0x2668, 0xA2CD, 0x2669, 0xA2DB, 0x266A, 0xA2DC, 0x266C, 0xA2DD, 0x266D, 0xA2DA, 0x3000, 0xA1A1, 0x3001, 0xA1A2, + 0x3002, 0xA1A3, 0x3003, 0xA1A8, 0x3008, 0xA1B4, 0x3009, 0xA1B5, 0x300A, 0xA1B6, 0x300B, 0xA1B7, 0x300C, 0xA1B8, 0x300D, 0xA1B9, + 0x300E, 0xA1BA, 0x300F, 0xA1BB, 0x3010, 0xA1BC, 0x3011, 0xA1BD, 0x3013, 0xA1EB, 0x3014, 0xA1B2, 0x3015, 0xA1B3, 0x3041, 0xAAA1, + 0x3042, 0xAAA2, 0x3043, 0xAAA3, 0x3044, 0xAAA4, 0x3045, 0xAAA5, 0x3046, 0xAAA6, 0x3047, 0xAAA7, 0x3048, 0xAAA8, 0x3049, 0xAAA9, + 0x304A, 0xAAAA, 0x304B, 0xAAAB, 0x304C, 0xAAAC, 0x304D, 0xAAAD, 0x304E, 0xAAAE, 0x304F, 0xAAAF, 0x3050, 0xAAB0, 0x3051, 0xAAB1, + 0x3052, 0xAAB2, 0x3053, 0xAAB3, 0x3054, 0xAAB4, 0x3055, 0xAAB5, 0x3056, 0xAAB6, 0x3057, 0xAAB7, 0x3058, 0xAAB8, 0x3059, 0xAAB9, + 0x305A, 0xAABA, 0x305B, 0xAABB, 0x305C, 0xAABC, 0x305D, 0xAABD, 0x305E, 0xAABE, 0x305F, 0xAABF, 0x3060, 0xAAC0, 0x3061, 0xAAC1, + 0x3062, 0xAAC2, 0x3063, 0xAAC3, 0x3064, 0xAAC4, 0x3065, 0xAAC5, 0x3066, 0xAAC6, 0x3067, 0xAAC7, 0x3068, 0xAAC8, 0x3069, 0xAAC9, + 0x306A, 0xAACA, 0x306B, 0xAACB, 0x306C, 0xAACC, 0x306D, 0xAACD, 0x306E, 0xAACE, 0x306F, 0xAACF, 0x3070, 0xAAD0, 0x3071, 0xAAD1, + 0x3072, 0xAAD2, 0x3073, 0xAAD3, 0x3074, 0xAAD4, 0x3075, 0xAAD5, 0x3076, 0xAAD6, 0x3077, 0xAAD7, 0x3078, 0xAAD8, 0x3079, 0xAAD9, + 0x307A, 0xAADA, 0x307B, 0xAADB, 0x307C, 0xAADC, 0x307D, 0xAADD, 0x307E, 0xAADE, 0x307F, 0xAADF, 0x3080, 0xAAE0, 0x3081, 0xAAE1, + 0x3082, 0xAAE2, 0x3083, 0xAAE3, 0x3084, 0xAAE4, 0x3085, 0xAAE5, 0x3086, 0xAAE6, 0x3087, 0xAAE7, 0x3088, 0xAAE8, 0x3089, 0xAAE9, + 0x308A, 0xAAEA, 0x308B, 0xAAEB, 0x308C, 0xAAEC, 0x308D, 0xAAED, 0x308E, 0xAAEE, 0x308F, 0xAAEF, 0x3090, 0xAAF0, 0x3091, 0xAAF1, + 0x3092, 0xAAF2, 0x3093, 0xAAF3, 0x30A1, 0xABA1, 0x30A2, 0xABA2, 0x30A3, 0xABA3, 0x30A4, 0xABA4, 0x30A5, 0xABA5, 0x30A6, 0xABA6, + 0x30A7, 0xABA7, 0x30A8, 0xABA8, 0x30A9, 0xABA9, 0x30AA, 0xABAA, 0x30AB, 0xABAB, 0x30AC, 0xABAC, 0x30AD, 0xABAD, 0x30AE, 0xABAE, + 0x30AF, 0xABAF, 0x30B0, 0xABB0, 0x30B1, 0xABB1, 0x30B2, 0xABB2, 0x30B3, 0xABB3, 0x30B4, 0xABB4, 0x30B5, 0xABB5, 0x30B6, 0xABB6, + 0x30B7, 0xABB7, 0x30B8, 0xABB8, 0x30B9, 0xABB9, 0x30BA, 0xABBA, 0x30BB, 0xABBB, 0x30BC, 0xABBC, 0x30BD, 0xABBD, 0x30BE, 0xABBE, + 0x30BF, 0xABBF, 0x30C0, 0xABC0, 0x30C1, 0xABC1, 0x30C2, 0xABC2, 0x30C3, 0xABC3, 0x30C4, 0xABC4, 0x30C5, 0xABC5, 0x30C6, 0xABC6, + 0x30C7, 0xABC7, 0x30C8, 0xABC8, 0x30C9, 0xABC9, 0x30CA, 0xABCA, 0x30CB, 0xABCB, 0x30CC, 0xABCC, 0x30CD, 0xABCD, 0x30CE, 0xABCE, + 0x30CF, 0xABCF, 0x30D0, 0xABD0, 0x30D1, 0xABD1, 0x30D2, 0xABD2, 0x30D3, 0xABD3, 0x30D4, 0xABD4, 0x30D5, 0xABD5, 0x30D6, 0xABD6, + 0x30D7, 0xABD7, 0x30D8, 0xABD8, 0x30D9, 0xABD9, 0x30DA, 0xABDA, 0x30DB, 0xABDB, 0x30DC, 0xABDC, 0x30DD, 0xABDD, 0x30DE, 0xABDE, + 0x30DF, 0xABDF, 0x30E0, 0xABE0, 0x30E1, 0xABE1, 0x30E2, 0xABE2, 0x30E3, 0xABE3, 0x30E4, 0xABE4, 0x30E5, 0xABE5, 0x30E6, 0xABE6, + 0x30E7, 0xABE7, 0x30E8, 0xABE8, 0x30E9, 0xABE9, 0x30EA, 0xABEA, 0x30EB, 0xABEB, 0x30EC, 0xABEC, 0x30ED, 0xABED, 0x30EE, 0xABEE, + 0x30EF, 0xABEF, 0x30F0, 0xABF0, 0x30F1, 0xABF1, 0x30F2, 0xABF2, 0x30F3, 0xABF3, 0x30F4, 0xABF4, 0x30F5, 0xABF5, 0x30F6, 0xABF6, + 0x3131, 0xA4A1, 0x3132, 0xA4A2, 0x3133, 0xA4A3, 0x3134, 0xA4A4, 0x3135, 0xA4A5, 0x3136, 0xA4A6, 0x3137, 0xA4A7, 0x3138, 0xA4A8, + 0x3139, 0xA4A9, 0x313A, 0xA4AA, 0x313B, 0xA4AB, 0x313C, 0xA4AC, 0x313D, 0xA4AD, 0x313E, 0xA4AE, 0x313F, 0xA4AF, 0x3140, 0xA4B0, + 0x3141, 0xA4B1, 0x3142, 0xA4B2, 0x3143, 0xA4B3, 0x3144, 0xA4B4, 0x3145, 0xA4B5, 0x3146, 0xA4B6, 0x3147, 0xA4B7, 0x3148, 0xA4B8, + 0x3149, 0xA4B9, 0x314A, 0xA4BA, 0x314B, 0xA4BB, 0x314C, 0xA4BC, 0x314D, 0xA4BD, 0x314E, 0xA4BE, 0x314F, 0xA4BF, 0x3150, 0xA4C0, + 0x3151, 0xA4C1, 0x3152, 0xA4C2, 0x3153, 0xA4C3, 0x3154, 0xA4C4, 0x3155, 0xA4C5, 0x3156, 0xA4C6, 0x3157, 0xA4C7, 0x3158, 0xA4C8, + 0x3159, 0xA4C9, 0x315A, 0xA4CA, 0x315B, 0xA4CB, 0x315C, 0xA4CC, 0x315D, 0xA4CD, 0x315E, 0xA4CE, 0x315F, 0xA4CF, 0x3160, 0xA4D0, + 0x3161, 0xA4D1, 0x3162, 0xA4D2, 0x3163, 0xA4D3, 0x3164, 0xA4D4, 0x3165, 0xA4D5, 0x3166, 0xA4D6, 0x3167, 0xA4D7, 0x3168, 0xA4D8, + 0x3169, 0xA4D9, 0x316A, 0xA4DA, 0x316B, 0xA4DB, 0x316C, 0xA4DC, 0x316D, 0xA4DD, 0x316E, 0xA4DE, 0x316F, 0xA4DF, 0x3170, 0xA4E0, + 0x3171, 0xA4E1, 0x3172, 0xA4E2, 0x3173, 0xA4E3, 0x3174, 0xA4E4, 0x3175, 0xA4E5, 0x3176, 0xA4E6, 0x3177, 0xA4E7, 0x3178, 0xA4E8, + 0x3179, 0xA4E9, 0x317A, 0xA4EA, 0x317B, 0xA4EB, 0x317C, 0xA4EC, 0x317D, 0xA4ED, 0x317E, 0xA4EE, 0x317F, 0xA4EF, 0x3180, 0xA4F0, + 0x3181, 0xA4F1, 0x3182, 0xA4F2, 0x3183, 0xA4F3, 0x3184, 0xA4F4, 0x3185, 0xA4F5, 0x3186, 0xA4F6, 0x3187, 0xA4F7, 0x3188, 0xA4F8, + 0x3189, 0xA4F9, 0x318A, 0xA4FA, 0x318B, 0xA4FB, 0x318C, 0xA4FC, 0x318D, 0xA4FD, 0x318E, 0xA4FE, 0x3200, 0xA9B1, 0x3201, 0xA9B2, + 0x3202, 0xA9B3, 0x3203, 0xA9B4, 0x3204, 0xA9B5, 0x3205, 0xA9B6, 0x3206, 0xA9B7, 0x3207, 0xA9B8, 0x3208, 0xA9B9, 0x3209, 0xA9BA, + 0x320A, 0xA9BB, 0x320B, 0xA9BC, 0x320C, 0xA9BD, 0x320D, 0xA9BE, 0x320E, 0xA9BF, 0x320F, 0xA9C0, 0x3210, 0xA9C1, 0x3211, 0xA9C2, + 0x3212, 0xA9C3, 0x3213, 0xA9C4, 0x3214, 0xA9C5, 0x3215, 0xA9C6, 0x3216, 0xA9C7, 0x3217, 0xA9C8, 0x3218, 0xA9C9, 0x3219, 0xA9CA, + 0x321A, 0xA9CB, 0x321B, 0xA9CC, 0x321C, 0xA2DF, 0x3260, 0xA8B1, 0x3261, 0xA8B2, 0x3262, 0xA8B3, 0x3263, 0xA8B4, 0x3264, 0xA8B5, + 0x3265, 0xA8B6, 0x3266, 0xA8B7, 0x3267, 0xA8B8, 0x3268, 0xA8B9, 0x3269, 0xA8BA, 0x326A, 0xA8BB, 0x326B, 0xA8BC, 0x326C, 0xA8BD, + 0x326D, 0xA8BE, 0x326E, 0xA8BF, 0x326F, 0xA8C0, 0x3270, 0xA8C1, 0x3271, 0xA8C2, 0x3272, 0xA8C3, 0x3273, 0xA8C4, 0x3274, 0xA8C5, + 0x3275, 0xA8C6, 0x3276, 0xA8C7, 0x3277, 0xA8C8, 0x3278, 0xA8C9, 0x3279, 0xA8CA, 0x327A, 0xA8CB, 0x327B, 0xA8CC, 0x327F, 0xA2DE, + 0x3380, 0xA7C9, 0x3381, 0xA7CA, 0x3382, 0xA7CB, 0x3383, 0xA7CC, 0x3384, 0xA7CD, 0x3388, 0xA7BA, 0x3389, 0xA7BB, 0x338A, 0xA7DC, + 0x338B, 0xA7DD, 0x338C, 0xA7DE, 0x338D, 0xA7B6, 0x338E, 0xA7B7, 0x338F, 0xA7B8, 0x3390, 0xA7D4, 0x3391, 0xA7D5, 0x3392, 0xA7D6, + 0x3393, 0xA7D7, 0x3394, 0xA7D8, 0x3395, 0xA7A1, 0x3396, 0xA7A2, 0x3397, 0xA7A3, 0x3398, 0xA7A5, 0x3399, 0xA7AB, 0x339A, 0xA7AC, + 0x339B, 0xA7AD, 0x339C, 0xA7AE, 0x339D, 0xA7AF, 0x339E, 0xA7B0, 0x339F, 0xA7B1, 0x33A0, 0xA7B2, 0x33A1, 0xA7B3, 0x33A2, 0xA7B4, + 0x33A3, 0xA7A7, 0x33A4, 0xA7A8, 0x33A5, 0xA7A9, 0x33A6, 0xA7AA, 0x33A7, 0xA7BD, 0x33A8, 0xA7BE, 0x33A9, 0xA7E5, 0x33AA, 0xA7E6, + 0x33AB, 0xA7E7, 0x33AC, 0xA7E8, 0x33AD, 0xA7E1, 0x33AE, 0xA7E2, 0x33AF, 0xA7E3, 0x33B0, 0xA7BF, 0x33B1, 0xA7C0, 0x33B2, 0xA7C1, + 0x33B3, 0xA7C2, 0x33B4, 0xA7C3, 0x33B5, 0xA7C4, 0x33B6, 0xA7C5, 0x33B7, 0xA7C6, 0x33B8, 0xA7C7, 0x33B9, 0xA7C8, 0x33BA, 0xA7CE, + 0x33BB, 0xA7CF, 0x33BC, 0xA7D0, 0x33BD, 0xA7D1, 0x33BE, 0xA7D2, 0x33BF, 0xA7D3, 0x33C0, 0xA7DA, 0x33C1, 0xA7DB, 0x33C2, 0xA2E3, + 0x33C3, 0xA7EC, 0x33C4, 0xA7A6, 0x33C5, 0xA7E0, 0x33C6, 0xA7EF, 0x33C7, 0xA2E1, 0x33C8, 0xA7BC, 0x33C9, 0xA7ED, 0x33CA, 0xA7B5, + 0x33CF, 0xA7B9, 0x33D0, 0xA7EA, 0x33D3, 0xA7EB, 0x33D6, 0xA7DF, 0x33D8, 0xA2E4, 0x33DB, 0xA7E4, 0x33DC, 0xA7EE, 0x33DD, 0xA7E9, + 0x4E00, 0xECE9, 0x4E01, 0xEFCB, 0x4E03, 0xF6D2, 0x4E07, 0xD8B2, 0x4E08, 0xEDDB, 0x4E09, 0xDFB2, 0x4E0A, 0xDFBE, 0x4E0B, 0xF9BB, + 0x4E0D, 0xDCF4, 0x4E11, 0xF5E4, 0x4E14, 0xF3A6, 0x4E15, 0xDDE0, 0x4E16, 0xE1A6, 0x4E18, 0xCEF8, 0x4E19, 0xDCB0, 0x4E1E, 0xE3AA, + 0x4E2D, 0xF1E9, 0x4E32, 0xCDFA, 0x4E38, 0xFCAF, 0x4E39, 0xD3A1, 0x4E3B, 0xF1AB, 0x4E42, 0xE7D1, 0x4E43, 0xD2AC, 0x4E45, 0xCEF9, + 0x4E4B, 0xF1FD, 0x4E4D, 0xDEBF, 0x4E4E, 0xFBBA, 0x4E4F, 0xF9B9, 0x4E56, 0xCED2, 0x4E58, 0xE3AB, 0x4E59, 0xEBE0, 0x4E5D, 0xCEFA, + 0x4E5E, 0xCBF7, 0x4E5F, 0xE5A5, 0x4E6B, 0xCAE1, 0x4E6D, 0xD4CC, 0x4E73, 0xEAE1, 0x4E76, 0xDCE3, 0x4E77, 0xDFAD, 0x4E7E, 0xCBEB, + 0x4E82, 0xD5AF, 0x4E86, 0xD6F5, 0x4E88, 0xE5F8, 0x4E8B, 0xDEC0, 0x4E8C, 0xECA3, 0x4E8E, 0xE9CD, 0x4E90, 0xEAA7, 0x4E91, 0xE9F6, + 0x4E92, 0xFBBB, 0x4E94, 0xE7E9, 0x4E95, 0xEFCC, 0x4E98, 0xD0E6, 0x4E9B, 0xDEC1, 0x4E9E, 0xE4AC, 0x4EA1, 0xD8CC, 0x4EA2, 0xF9F1, + 0x4EA4, 0xCEDF, 0x4EA5, 0xFAA4, 0x4EA6, 0xE6B2, 0x4EA8, 0xFAFB, 0x4EAB, 0xFABD, 0x4EAC, 0xCCC8, 0x4EAD, 0xEFCD, 0x4EAE, 0xD5D5, + 0x4EB6, 0xD3A2, 0x4EBA, 0xECD1, 0x4EC0, 0xE4A7, 0x4EC1, 0xECD2, 0x4EC4, 0xF6B1, 0x4EC7, 0xCEFB, 0x4ECA, 0xD0D1, 0x4ECB, 0xCBBF, + 0x4ECD, 0xEDA4, 0x4ED4, 0xEDA8, 0x4ED5, 0xDEC2, 0x4ED6, 0xF6E2, 0x4ED7, 0xEDDC, 0x4ED8, 0xDCF5, 0x4ED9, 0xE0B9, 0x4EDD, 0xD4CE, + 0x4EDF, 0xF4B5, 0x4EE3, 0xD3DB, 0x4EE4, 0xD6B5, 0x4EE5, 0xECA4, 0x4EF0, 0xE4E6, 0x4EF2, 0xF1EA, 0x4EF6, 0xCBEC, 0x4EF7, 0xCBC0, + 0x4EFB, 0xECF2, 0x4F01, 0xD0EA, 0x4F09, 0xF9F2, 0x4F0A, 0xECA5, 0x4F0B, 0xD0DF, 0x4F0D, 0xE7EA, 0x4F0E, 0xD0EB, 0x4F0F, 0xDCD1, + 0x4F10, 0xDBE9, 0x4F11, 0xFDCC, 0x4F2F, 0xDBD7, 0x4F34, 0xDAE1, 0x4F36, 0xD6B6, 0x4F38, 0xE3DF, 0x4F3A, 0xDEC3, 0x4F3C, 0xDEC4, + 0x4F3D, 0xCAA1, 0x4F43, 0xEEEC, 0x4F46, 0xD3A3, 0x4F47, 0xEEB7, 0x4F48, 0xF8CF, 0x4F4D, 0xEAC8, 0x4F4E, 0xEEB8, 0x4F4F, 0xF1AC, + 0x4F50, 0xF1A5, 0x4F51, 0xE9CE, 0x4F55, 0xF9BC, 0x4F59, 0xE5F9, 0x4F5A, 0xECEA, 0x4F5B, 0xDDD6, 0x4F5C, 0xEDC2, 0x4F69, 0xF8A5, + 0x4F6F, 0xE5BA, 0x4F70, 0xDBD8, 0x4F73, 0xCAA2, 0x4F76, 0xD1CD, 0x4F7A, 0xEEED, 0x4F7E, 0xECEB, 0x4F7F, 0xDEC5, 0x4F81, 0xE3E0, + 0x4F83, 0xCAC9, 0x4F84, 0xF2E9, 0x4F86, 0xD5CE, 0x4F88, 0xF6B6, 0x4F8A, 0xCEC2, 0x4F8B, 0xD6C7, 0x4F8D, 0xE3B4, 0x4F8F, 0xF1AD, + 0x4F91, 0xEAE2, 0x4F96, 0xD7C2, 0x4F98, 0xF3A7, 0x4F9B, 0xCDEA, 0x4F9D, 0xEBEE, 0x4FAE, 0xD9B2, 0x4FAF, 0xFDA5, 0x4FB5, 0xF6D5, + 0x4FB6, 0xD5E2, 0x4FBF, 0xF8B5, 0x4FC2, 0xCCF5, 0x4FC3, 0xF5B5, 0x4FC4, 0xE4AD, 0x4FC9, 0xE7EB, 0x4FCA, 0xF1D5, 0x4FCE, 0xF0BB, + 0x4FD1, 0xE9B5, 0x4FD3, 0xCCC9, 0x4FD4, 0xFAD5, 0x4FD7, 0xE1D4, 0x4FDA, 0xD7D6, 0x4FDD, 0xDCC1, 0x4FDF, 0xDEC6, 0x4FE0, 0xFAEF, + 0x4FE1, 0xE3E1, 0x4FEE, 0xE1F3, 0x4FEF, 0xDCF6, 0x4FF1, 0xCEFC, 0x4FF3, 0xDBC4, 0x4FF5, 0xF8F1, 0x4FF8, 0xDCE4, 0x4FFA, 0xE5EF, + 0x5002, 0xDCB1, 0x5006, 0xD5D6, 0x5009, 0xF3DA, 0x500B, 0xCBC1, 0x500D, 0xDBC3, 0x5011, 0xD9FA, 0x5012, 0xD3EE, 0x5016, 0xFAB8, + 0x5019, 0xFDA6, 0x501A, 0xEBEF, 0x501C, 0xF4A6, 0x501E, 0xCCCA, 0x501F, 0xF3A8, 0x5021, 0xF3DB, 0x5023, 0xDBA7, 0x5024, 0xF6B7, + 0x5026, 0xCFE6, 0x5027, 0xF0F2, 0x5028, 0xCBDA, 0x502A, 0xE7D2, 0x502B, 0xD7C3, 0x502C, 0xF6F0, 0x502D, 0xE8DE, 0x503B, 0xE5A6, + 0x5043, 0xE5E7, 0x5047, 0xCAA3, 0x5048, 0xCCA7, 0x5049, 0xEAC9, 0x504F, 0xF8B6, 0x5055, 0xFAA5, 0x505A, 0xF1AE, 0x505C, 0xEFCE, + 0x5065, 0xCBED, 0x5074, 0xF6B0, 0x5075, 0xEFCF, 0x5076, 0xE9CF, 0x5078, 0xF7DE, 0x5080, 0xCED3, 0x5085, 0xDCF7, 0x508D, 0xDBA8, + 0x5091, 0xCBF8, 0x5098, 0xDFA1, 0x5099, 0xDDE1, 0x50AC, 0xF5CA, 0x50AD, 0xE9B6, 0x50B2, 0xE7EC, 0x50B3, 0xEEEE, 0x50B5, 0xF3F0, + 0x50B7, 0xDFBF, 0x50BE, 0xCCCB, 0x50C5, 0xD0C1, 0x50C9, 0xF4D2, 0x50CA, 0xE0BA, 0x50CF, 0xDFC0, 0x50D1, 0xCEE0, 0x50D5, 0xDCD2, + 0x50D6, 0xFDEA, 0x50DA, 0xD6F6, 0x50DE, 0xEACA, 0x50E5, 0xE8E9, 0x50E7, 0xE3AC, 0x50ED, 0xF3D0, 0x50F9, 0xCAA4, 0x50FB, 0xDBF8, + 0x50FF, 0xDEC7, 0x5100, 0xEBF0, 0x5101, 0xF1D6, 0x5104, 0xE5E2, 0x5106, 0xCCCC, 0x5109, 0xCBFB, 0x5112, 0xEAE3, 0x511F, 0xDFC1, + 0x5121, 0xD6ED, 0x512A, 0xE9D0, 0x5132, 0xEEB9, 0x5137, 0xD5E3, 0x513A, 0xD1D3, 0x513C, 0xE5F0, 0x5140, 0xE8B4, 0x5141, 0xEBC3, + 0x5143, 0xEAAA, 0x5144, 0xFAFC, 0x5145, 0xF5F6, 0x5146, 0xF0BC, 0x5147, 0xFDD4, 0x5148, 0xE0BB, 0x5149, 0xCEC3, 0x514B, 0xD0BA, + 0x514C, 0xF7BA, 0x514D, 0xD8F3, 0x514E, 0xF7CD, 0x5152, 0xE4AE, 0x515C, 0xD4DF, 0x5162, 0xD0E7, 0x5165, 0xECFD, 0x5167, 0xD2AE, + 0x5168, 0xEEEF, 0x5169, 0xD5D7, 0x516A, 0xEAE4, 0x516B, 0xF8A2, 0x516C, 0xCDEB, 0x516D, 0xD7BF, 0x516E, 0xFBB1, 0x5171, 0xCDEC, + 0x5175, 0xDCB2, 0x5176, 0xD0EC, 0x5177, 0xCEFD, 0x5178, 0xEEF0, 0x517C, 0xCCC2, 0x5180, 0xD0ED, 0x5186, 0xE5F7, 0x518A, 0xF3FC, + 0x518D, 0xEEA2, 0x5192, 0xD9B3, 0x5195, 0xD8F4, 0x5197, 0xE9B7, 0x51A0, 0xCEAE, 0x51A5, 0xD9A2, 0x51AA, 0xD8F1, 0x51AC, 0xD4CF, + 0x51B6, 0xE5A7, 0x51B7, 0xD5D2, 0x51BD, 0xD6A9, 0x51C4, 0xF4A2, 0x51C6, 0xF1D7, 0x51C9, 0xD5D8, 0x51CB, 0xF0BD, 0x51CC, 0xD7D0, + 0x51CD, 0xD4D0, 0x51DC, 0xD7CF, 0x51DD, 0xEBEA, 0x51DE, 0xFDEB, 0x51E1, 0xDBED, 0x51F0, 0xFCC5, 0x51F1, 0xCBC2, 0x51F6, 0xFDD5, + 0x51F8, 0xF4C8, 0x51F9, 0xE8EA, 0x51FA, 0xF5F3, 0x51FD, 0xF9DE, 0x5200, 0xD3EF, 0x5203, 0xECD3, 0x5206, 0xDDC2, 0x5207, 0xEFB7, + 0x5208, 0xE7D4, 0x520A, 0xCACA, 0x520E, 0xD9FB, 0x5211, 0xFAFD, 0x5217, 0xD6AA, 0x521D, 0xF4F8, 0x5224, 0xF7F7, 0x5225, 0xDCAC, + 0x5229, 0xD7D7, 0x522A, 0xDFA2, 0x522E, 0xCEBE, 0x5230, 0xD3F0, 0x5236, 0xF0A4, 0x5237, 0xE1EC, 0x5238, 0xCFE7, 0x5239, 0xF3CB, + 0x523A, 0xEDA9, 0x523B, 0xCABE, 0x5243, 0xF4EF, 0x5247, 0xF6CE, 0x524A, 0xDEFB, 0x524B, 0xD0BB, 0x524C, 0xD5B7, 0x524D, 0xEEF1, + 0x5254, 0xF4A8, 0x5256, 0xDCF8, 0x525B, 0xCBA7, 0x525D, 0xDACE, 0x5261, 0xE0E6, 0x5269, 0xEDA5, 0x526A, 0xEEF2, 0x526F, 0xDCF9, + 0x5272, 0xF9DC, 0x5275, 0xF3DC, 0x527D, 0xF8F2, 0x527F, 0xF4F9, 0x5283, 0xFCF1, 0x5287, 0xD0BC, 0x5288, 0xDBF9, 0x5289, 0xD7B1, + 0x528D, 0xCBFC, 0x5291, 0xF0A5, 0x5292, 0xCBFD, 0x529B, 0xD5F4, 0x529F, 0xCDED, 0x52A0, 0xCAA5, 0x52A3, 0xD6AB, 0x52A4, 0xD0C2, + 0x52A9, 0xF0BE, 0x52AA, 0xD2BD, 0x52AB, 0xCCA4, 0x52BE, 0xFAB6, 0x52C1, 0xCCCD, 0x52C3, 0xDAFA, 0x52C5, 0xF6CF, 0x52C7, 0xE9B8, + 0x52C9, 0xD8F5, 0x52CD, 0xCCCE, 0x52D2, 0xD7CD, 0x52D5, 0xD4D1, 0x52D6, 0xE9ED, 0x52D8, 0xCAEB, 0x52D9, 0xD9E2, 0x52DB, 0xFDB2, + 0x52DD, 0xE3AD, 0x52DE, 0xD6CC, 0x52DF, 0xD9B4, 0x52E2, 0xE1A7, 0x52E3, 0xEED3, 0x52E4, 0xD0C3, 0x52F3, 0xFDB3, 0x52F5, 0xD5E4, + 0x52F8, 0xCFE8, 0x52FA, 0xEDC3, 0x52FB, 0xD0B2, 0x52FE, 0xCEFE, 0x52FF, 0xDAA8, 0x5305, 0xF8D0, 0x5308, 0xFDD6, 0x530D, 0xF8D1, + 0x530F, 0xF8D2, 0x5310, 0xDCD3, 0x5315, 0xDDE2, 0x5316, 0xFBF9, 0x5317, 0xDDC1, 0x5319, 0xE3B5, 0x5320, 0xEDDD, 0x5321, 0xCEC4, + 0x5323, 0xCBA1, 0x532A, 0xDDE3, 0x532F, 0xFCDD, 0x5339, 0xF9AF, 0x533F, 0xD2FB, 0x5340, 0xCFA1, 0x5341, 0xE4A8, 0x5343, 0xF4B6, + 0x5344, 0xECFE, 0x5347, 0xE3AE, 0x5348, 0xE7ED, 0x5349, 0xFDC1, 0x534A, 0xDAE2, 0x534D, 0xD8B3, 0x5351, 0xDDE4, 0x5352, 0xF0EF, + 0x5353, 0xF6F1, 0x5354, 0xFAF0, 0x5357, 0xD1F5, 0x535A, 0xDACF, 0x535C, 0xDCD4, 0x535E, 0xDCA6, 0x5360, 0xEFBF, 0x5366, 0xCECF, + 0x5368, 0xE0D9, 0x536F, 0xD9D6, 0x5370, 0xECD4, 0x5371, 0xEACB, 0x5374, 0xCABF, 0x5375, 0xD5B0, 0x5377, 0xCFE9, 0x537D, 0xF1ED, + 0x537F, 0xCCCF, 0x5384, 0xE4F8, 0x5393, 0xE4ED, 0x5398, 0xD7D8, 0x539A, 0xFDA7, 0x539F, 0xEAAB, 0x53A0, 0xF6B2, 0x53A5, 0xCFF0, + 0x53A6, 0xF9BD, 0x53AD, 0xE6F4, 0x53BB, 0xCBDB, 0x53C3, 0xF3D1, 0x53C8, 0xE9D1, 0x53C9, 0xF3A9, 0x53CA, 0xD0E0, 0x53CB, 0xE9D2, + 0x53CD, 0xDAE3, 0x53D4, 0xE2D2, 0x53D6, 0xF6A2, 0x53D7, 0xE1F4, 0x53DB, 0xDAE4, 0x53E1, 0xE7D5, 0x53E2, 0xF5BF, 0x53E3, 0xCFA2, + 0x53E4, 0xCDAF, 0x53E5, 0xCFA3, 0x53E9, 0xCDB0, 0x53EA, 0xF1FE, 0x53EB, 0xD0A3, 0x53EC, 0xE1AF, 0x53ED, 0xF8A3, 0x53EF, 0xCAA6, + 0x53F0, 0xF7BB, 0x53F1, 0xF2EA, 0x53F2, 0xDEC8, 0x53F3, 0xE9D3, 0x53F8, 0xDEC9, 0x5403, 0xFDDE, 0x5404, 0xCAC0, 0x5408, 0xF9EA, + 0x5409, 0xD1CE, 0x540A, 0xEED4, 0x540C, 0xD4D2, 0x540D, 0xD9A3, 0x540E, 0xFDA8, 0x540F, 0xD7D9, 0x5410, 0xF7CE, 0x5411, 0xFABE, + 0x541B, 0xCFD6, 0x541D, 0xD7F0, 0x541F, 0xEBE1, 0x5420, 0xF8C5, 0x5426, 0xDCFA, 0x5429, 0xDDC3, 0x542B, 0xF9DF, 0x5433, 0xE7EF, + 0x5438, 0xFDE5, 0x5439, 0xF6A3, 0x543B, 0xD9FC, 0x543C, 0xFDA9, 0x543E, 0xE7EE, 0x5442, 0xD5E5, 0x5448, 0xEFD0, 0x544A, 0xCDB1, + 0x5451, 0xF7A2, 0x5468, 0xF1B2, 0x546A, 0xF1B1, 0x5471, 0xCDB2, 0x5473, 0xDAAB, 0x5475, 0xCAA7, 0x547B, 0xE3E2, 0x547C, 0xFBBC, + 0x547D, 0xD9A4, 0x5480, 0xEEBA, 0x5486, 0xF8D3, 0x548C, 0xFBFA, 0x548E, 0xCFA4, 0x5490, 0xDCFB, 0x54A4, 0xF6E3, 0x54A8, 0xEDAA, + 0x54AB, 0xF2A1, 0x54AC, 0xCEE1, 0x54B3, 0xFAA6, 0x54B8, 0xF9E0, 0x54BD, 0xECD6, 0x54C0, 0xE4EE, 0x54C1, 0xF9A1, 0x54C4, 0xFBEF, + 0x54C8, 0xF9EB, 0x54C9, 0xEEA3, 0x54E1, 0xEAAC, 0x54E5, 0xCAA8, 0x54E8, 0xF4FA, 0x54ED, 0xCDD6, 0x54EE, 0xFCF6, 0x54F2, 0xF4C9, + 0x54FA, 0xF8D4, 0x5504, 0xF8A6, 0x5506, 0xDECA, 0x5507, 0xF2C6, 0x550E, 0xD7DA, 0x5510, 0xD3D0, 0x551C, 0xD8C5, 0x552F, 0xEAE6, + 0x5531, 0xF3DD, 0x5535, 0xE4DA, 0x553E, 0xF6E4, 0x5544, 0xF6F2, 0x5546, 0xDFC2, 0x554F, 0xD9FD, 0x5553, 0xCCF6, 0x5556, 0xD3BA, + 0x555E, 0xE4AF, 0x5563, 0xF9E1, 0x557C, 0xF0A6, 0x5580, 0xCBD3, 0x5584, 0xE0BC, 0x5586, 0xF4CA, 0x5587, 0xD4FA, 0x5589, 0xFDAA, + 0x558A, 0xF9E2, 0x5598, 0xF4B7, 0x5599, 0xFDC2, 0x559A, 0xFCB0, 0x559C, 0xFDEC, 0x559D, 0xCAE2, 0x55A7, 0xFDBD, 0x55A9, 0xEAE7, + 0x55AA, 0xDFC3, 0x55AB, 0xD1D2, 0x55AC, 0xCEE2, 0x55AE, 0xD3A4, 0x55C5, 0xFDAB, 0x55C7, 0xDFE0, 0x55D4, 0xF2C7, 0x55DA, 0xE7F0, + 0x55DC, 0xD0EE, 0x55DF, 0xF3AA, 0x55E3, 0xDECB, 0x55E4, 0xF6B8, 0x55FD, 0xE1F5, 0x55FE, 0xF1B3, 0x5606, 0xF7A3, 0x5609, 0xCAA9, + 0x5614, 0xCFA5, 0x5617, 0xDFC4, 0x562F, 0xE1B0, 0x5632, 0xF0BF, 0x5634, 0xF6A4, 0x5636, 0xE3B6, 0x5653, 0xFAC6, 0x5668, 0xD0EF, + 0x566B, 0xFDED, 0x5674, 0xDDC4, 0x5686, 0xFCF7, 0x56A5, 0xE6BF, 0x56AC, 0xDEAD, 0x56AE, 0xFABF, 0x56B4, 0xE5F1, 0x56BC, 0xEDC4, + 0x56CA, 0xD2A5, 0x56CD, 0xFDEE, 0x56D1, 0xF5B6, 0x56DA, 0xE1F6, 0x56DB, 0xDECC, 0x56DE, 0xFCDE, 0x56E0, 0xECD7, 0x56F0, 0xCDDD, + 0x56F9, 0xD6B7, 0x56FA, 0xCDB3, 0x5703, 0xF8D5, 0x5704, 0xE5D8, 0x5708, 0xCFEA, 0x570B, 0xCFD0, 0x570D, 0xEACC, 0x5712, 0xEAAE, + 0x5713, 0xEAAD, 0x5716, 0xD3F1, 0x5718, 0xD3A5, 0x571F, 0xF7CF, 0x5728, 0xEEA4, 0x572D, 0xD0A4, 0x5730, 0xF2A2, 0x573B, 0xD0F0, + 0x5740, 0xF2A3, 0x5742, 0xF7F8, 0x5747, 0xD0B3, 0x574A, 0xDBA9, 0x574D, 0xD3BB, 0x574E, 0xCAEC, 0x5750, 0xF1A6, 0x5751, 0xCBD5, + 0x5761, 0xF7E7, 0x5764, 0xCDDE, 0x5766, 0xF7A4, 0x576A, 0xF8C0, 0x576E, 0xD3DD, 0x5770, 0xCCD0, 0x5775, 0xCFA6, 0x577C, 0xF6F3, + 0x5782, 0xE1F7, 0x5788, 0xD3DC, 0x578B, 0xFAFE, 0x5793, 0xFAA7, 0x57A0, 0xEBD9, 0x57A2, 0xCFA7, 0x57A3, 0xEAAF, 0x57C3, 0xE4EF, + 0x57C7, 0xE9B9, 0x57C8, 0xF1D8, 0x57CB, 0xD8D8, 0x57CE, 0xE0F2, 0x57DF, 0xE6B4, 0x57E0, 0xDCFC, 0x57F0, 0xF3F1, 0x57F4, 0xE3D0, + 0x57F7, 0xF2FB, 0x57F9, 0xDBC6, 0x57FA, 0xD0F1, 0x57FC, 0xD0F2, 0x5800, 0xCFDC, 0x5802, 0xD3D1, 0x5805, 0xCCB1, 0x5806, 0xF7D8, + 0x5808, 0xCBA8, 0x5809, 0xEBBC, 0x580A, 0xE4BE, 0x581E, 0xF4DC, 0x5821, 0xDCC2, 0x5824, 0xF0A7, 0x5827, 0xE6C0, 0x582A, 0xCAED, + 0x582F, 0xE8EB, 0x5830, 0xE5E8, 0x5831, 0xDCC3, 0x5834, 0xEDDE, 0x5835, 0xD3F2, 0x583A, 0xCCF7, 0x584A, 0xCED4, 0x584B, 0xE7AB, + 0x584F, 0xCBC3, 0x5851, 0xE1B1, 0x5854, 0xF7B2, 0x5857, 0xD3F3, 0x5858, 0xD3D2, 0x585A, 0xF5C0, 0x585E, 0xDFDD, 0x5861, 0xEEF3, + 0x5862, 0xE7F1, 0x5864, 0xFDB4, 0x5875, 0xF2C8, 0x5879, 0xF3D2, 0x587C, 0xEEF4, 0x587E, 0xE2D3, 0x5883, 0xCCD1, 0x5885, 0xDFEA, + 0x5889, 0xE9BA, 0x5893, 0xD9D7, 0x589C, 0xF5CD, 0x589E, 0xF1F2, 0x589F, 0xFAC7, 0x58A8, 0xD9F8, 0x58A9, 0xD4C2, 0x58AE, 0xF6E5, + 0x58B3, 0xDDC5, 0x58BA, 0xE7F2, 0x58BB, 0xEDDF, 0x58BE, 0xCACB, 0x58C1, 0xDBFA, 0x58C5, 0xE8B5, 0x58C7, 0xD3A6, 0x58CE, 0xFDB5, + 0x58D1, 0xF9C9, 0x58D3, 0xE4E2, 0x58D5, 0xFBBD, 0x58D8, 0xD7A4, 0x58D9, 0xCEC5, 0x58DE, 0xCED5, 0x58DF, 0xD6E6, 0x58E4, 0xE5BD, + 0x58EB, 0xDECD, 0x58EC, 0xECF3, 0x58EF, 0xEDE0, 0x58F9, 0xECEC, 0x58FA, 0xFBBE, 0x58FB, 0xDFEB, 0x58FD, 0xE1F8, 0x590F, 0xF9BE, + 0x5914, 0xD0F3, 0x5915, 0xE0AA, 0x5916, 0xE8E2, 0x5919, 0xE2D4, 0x591A, 0xD2FD, 0x591C, 0xE5A8, 0x5922, 0xD9D3, 0x5927, 0xD3DE, + 0x5929, 0xF4B8, 0x592A, 0xF7BC, 0x592B, 0xDCFD, 0x592D, 0xE8EC, 0x592E, 0xE4E7, 0x5931, 0xE3F7, 0x5937, 0xECA8, 0x593E, 0xFAF1, + 0x5944, 0xE5F2, 0x5947, 0xD0F4, 0x5948, 0xD2AF, 0x5949, 0xDCE5, 0x594E, 0xD0A5, 0x594F, 0xF1B4, 0x5950, 0xFCB1, 0x5951, 0xCCF8, + 0x5954, 0xDDC6, 0x5955, 0xFAD1, 0x5957, 0xF7DF, 0x595A, 0xFAA8, 0x5960, 0xEEF5, 0x5962, 0xDECE, 0x5967, 0xE7F3, 0x596A, 0xF7AC, + 0x596B, 0xEBC4, 0x596C, 0xEDE1, 0x596D, 0xE0AB, 0x596E, 0xDDC7, 0x5973, 0xD2B3, 0x5974, 0xD2BF, 0x5978, 0xCACC, 0x597D, 0xFBBF, + 0x5982, 0xE5FD, 0x5983, 0xDDE5, 0x5984, 0xD8CD, 0x598A, 0xECF4, 0x5993, 0xD0F5, 0x5996, 0xE8ED, 0x5997, 0xD0D2, 0x5999, 0xD9D8, + 0x59A5, 0xF6E6, 0x59A8, 0xDBAA, 0x59AC, 0xF7E0, 0x59B9, 0xD8D9, 0x59BB, 0xF4A3, 0x59BE, 0xF4DD, 0x59C3, 0xEFD1, 0x59C6, 0xD9B5, + 0x59C9, 0xEDAB, 0x59CB, 0xE3B7, 0x59D0, 0xEEBB, 0x59D1, 0xCDB4, 0x59D3, 0xE0F3, 0x59D4, 0xEACD, 0x59D9, 0xECF5, 0x59DA, 0xE8EE, + 0x59DC, 0xCBA9, 0x59DD, 0xF1AF, 0x59E6, 0xCACD, 0x59E8, 0xECA9, 0x59EA, 0xF2EB, 0x59EC, 0xFDEF, 0x59EE, 0xF9F3, 0x59F8, 0xE6C1, + 0x59FB, 0xECD8, 0x59FF, 0xEDAC, 0x5A01, 0xEACE, 0x5A03, 0xE8DF, 0x5A11, 0xDECF, 0x5A18, 0xD2A6, 0x5A1B, 0xE7F4, 0x5A1C, 0xD1D6, + 0x5A1F, 0xE6C2, 0x5A20, 0xE3E3, 0x5A25, 0xE4B0, 0x5A29, 0xD8B4, 0x5A36, 0xF6A5, 0x5A3C, 0xF3DE, 0x5A41, 0xD7A5, 0x5A46, 0xF7E8, + 0x5A49, 0xE8C6, 0x5A5A, 0xFBE6, 0x5A62, 0xDDE6, 0x5A66, 0xDCFE, 0x5A92, 0xD8DA, 0x5A9A, 0xDAAC, 0x5A9B, 0xEAB0, 0x5AA4, 0xE3B8, + 0x5AC1, 0xCAAA, 0x5AC2, 0xE1F9, 0x5AC4, 0xEAB1, 0x5AC9, 0xF2EC, 0x5ACC, 0xFAEE, 0x5AE1, 0xEED5, 0x5AE6, 0xF9F4, 0x5AE9, 0xD2EC, + 0x5B05, 0xFBFB, 0x5B09, 0xFDF0, 0x5B0B, 0xE0BD, 0x5B0C, 0xCEE3, 0x5B16, 0xF8C6, 0x5B2A, 0xDEAE, 0x5B40, 0xDFC5, 0x5B43, 0xE5BE, + 0x5B50, 0xEDAD, 0x5B51, 0xFAEA, 0x5B54, 0xCDEE, 0x5B55, 0xEDA6, 0x5B57, 0xEDAE, 0x5B58, 0xF0ED, 0x5B5A, 0xDDA1, 0x5B5C, 0xEDAF, + 0x5B5D, 0xFCF8, 0x5B5F, 0xD8EB, 0x5B63, 0xCCF9, 0x5B64, 0xCDB5, 0x5B69, 0xFAA9, 0x5B6B, 0xE1DD, 0x5B70, 0xE2D5, 0x5B71, 0xEDCF, + 0x5B75, 0xDDA2, 0x5B78, 0xF9CA, 0x5B7A, 0xEAE8, 0x5B7C, 0xE5ED, 0x5B85, 0xD3EB, 0x5B87, 0xE9D4, 0x5B88, 0xE1FA, 0x5B89, 0xE4CC, + 0x5B8B, 0xE1E4, 0x5B8C, 0xE8C7, 0x5B8F, 0xCEDB, 0x5B93, 0xDCD5, 0x5B95, 0xF7B5, 0x5B96, 0xFCF3, 0x5B97, 0xF0F3, 0x5B98, 0xCEAF, + 0x5B99, 0xF1B5, 0x5B9A, 0xEFD2, 0x5B9B, 0xE8C8, 0x5B9C, 0xEBF1, 0x5BA2, 0xCBD4, 0x5BA3, 0xE0BE, 0x5BA4, 0xE3F8, 0x5BA5, 0xEAE9, + 0x5BA6, 0xFCB2, 0x5BAC, 0xE0F4, 0x5BAE, 0xCFE0, 0x5BB0, 0xEEA5, 0x5BB3, 0xFAAA, 0x5BB4, 0xE6C3, 0x5BB5, 0xE1B2, 0x5BB6, 0xCAAB, + 0x5BB8, 0xE3E4, 0x5BB9, 0xE9BB, 0x5BBF, 0xE2D6, 0x5BC0, 0xF3F2, 0x5BC2, 0xEED6, 0x5BC3, 0xEAB2, 0x5BC4, 0xD0F6, 0x5BC5, 0xECD9, + 0x5BC6, 0xDACB, 0x5BC7, 0xCFA8, 0x5BCC, 0xDDA3, 0x5BD0, 0xD8DB, 0x5BD2, 0xF9CE, 0x5BD3, 0xE9D5, 0x5BD4, 0xE3D1, 0x5BD7, 0xD2BC, + 0x5BDE, 0xD8AC, 0x5BDF, 0xF3CC, 0x5BE1, 0xCDFB, 0x5BE2, 0xF6D6, 0x5BE4, 0xE7F5, 0x5BE5, 0xE8EF, 0x5BE6, 0xE3F9, 0x5BE7, 0xD2BB, + 0x5BE8, 0xF3F3, 0x5BE9, 0xE3FB, 0x5BEB, 0xDED0, 0x5BEC, 0xCEB0, 0x5BEE, 0xD6F7, 0x5BEF, 0xF1D9, 0x5BF5, 0xF5C1, 0x5BF6, 0xDCC4, + 0x5BF8, 0xF5BB, 0x5BFA, 0xDED1, 0x5C01, 0xDCE6, 0x5C04, 0xDED2, 0x5C07, 0xEDE2, 0x5C08, 0xEEF6, 0x5C09, 0xEACF, 0x5C0A, 0xF0EE, + 0x5C0B, 0xE3FC, 0x5C0D, 0xD3DF, 0x5C0E, 0xD3F4, 0x5C0F, 0xE1B3, 0x5C11, 0xE1B4, 0x5C16, 0xF4D3, 0x5C19, 0xDFC6, 0x5C24, 0xE9D6, + 0x5C28, 0xDBAB, 0x5C31, 0xF6A6, 0x5C38, 0xE3B9, 0x5C39, 0xEBC5, 0x5C3A, 0xF4A9, 0x5C3B, 0xCDB6, 0x5C3C, 0xD2F9, 0x5C3E, 0xDAAD, + 0x5C3F, 0xD2E3, 0x5C40, 0xCFD1, 0x5C45, 0xCBDC, 0x5C46, 0xCCFA, 0x5C48, 0xCFDD, 0x5C4B, 0xE8A9, 0x5C4D, 0xE3BB, 0x5C4E, 0xE3BA, + 0x5C51, 0xE0DA, 0x5C55, 0xEEF7, 0x5C5B, 0xDCB3, 0x5C60, 0xD3F5, 0x5C62, 0xD7A6, 0x5C64, 0xF6B5, 0x5C65, 0xD7DB, 0x5C6C, 0xE1D5, + 0x5C6F, 0xD4EA, 0x5C71, 0xDFA3, 0x5C79, 0xFDDF, 0x5C90, 0xD0F7, 0x5C91, 0xEDD4, 0x5CA1, 0xCBAA, 0x5CA9, 0xE4DB, 0x5CAB, 0xE1FB, + 0x5CAC, 0xCBA2, 0x5CB1, 0xD3E0, 0x5CB3, 0xE4BF, 0x5CB5, 0xFBC0, 0x5CB7, 0xDABE, 0x5CB8, 0xE4CD, 0x5CBA, 0xD6B9, 0x5CBE, 0xEFC0, + 0x5CC0, 0xE1FC, 0x5CD9, 0xF6B9, 0x5CE0, 0xDFC7, 0x5CE8, 0xE4B1, 0x5CEF, 0xDCE7, 0x5CF0, 0xDCE8, 0x5CF4, 0xFAD6, 0x5CF6, 0xD3F6, + 0x5CFB, 0xF1DA, 0x5CFD, 0xFAF2, 0x5D07, 0xE2FD, 0x5D0D, 0xD5CF, 0x5D0E, 0xD0F8, 0x5D11, 0xCDDF, 0x5D14, 0xF5CB, 0x5D16, 0xE4F0, + 0x5D17, 0xCBAB, 0x5D19, 0xD7C4, 0x5D27, 0xE2FE, 0x5D29, 0xDDDA, 0x5D4B, 0xDAAE, 0x5D4C, 0xCAEE, 0x5D50, 0xD5B9, 0x5D69, 0xE3A1, + 0x5D6C, 0xE8E3, 0x5D6F, 0xF3AB, 0x5D87, 0xCFA9, 0x5D8B, 0xD3F7, 0x5D9D, 0xD4F1, 0x5DA0, 0xCEE4, 0x5DA2, 0xE8F2, 0x5DAA, 0xE5F5, + 0x5DB8, 0xE7AE, 0x5DBA, 0xD6BA, 0x5DBC, 0xDFEC, 0x5DBD, 0xE4C0, 0x5DCD, 0xE8E4, 0x5DD2, 0xD8B5, 0x5DD6, 0xE4DC, 0x5DDD, 0xF4B9, + 0x5DDE, 0xF1B6, 0x5DE1, 0xE2DE, 0x5DE2, 0xE1B5, 0x5DE5, 0xCDEF, 0x5DE6, 0xF1A7, 0x5DE7, 0xCEE5, 0x5DE8, 0xCBDD, 0x5DEB, 0xD9E3, + 0x5DEE, 0xF3AC, 0x5DF1, 0xD0F9, 0x5DF2, 0xECAB, 0x5DF3, 0xDED3, 0x5DF4, 0xF7E9, 0x5DF7, 0xF9F5, 0x5DFD, 0xE1DE, 0x5DFE, 0xCBEE, + 0x5E02, 0xE3BC, 0x5E03, 0xF8D6, 0x5E06, 0xDBEE, 0x5E0C, 0xFDF1, 0x5E11, 0xF7B6, 0x5E16, 0xF4DE, 0x5E19, 0xF2ED, 0x5E1B, 0xDBD9, + 0x5E1D, 0xF0A8, 0x5E25, 0xE1FD, 0x5E2B, 0xDED4, 0x5E2D, 0xE0AC, 0x5E33, 0xEDE3, 0x5E36, 0xD3E1, 0x5E38, 0xDFC8, 0x5E3D, 0xD9B6, + 0x5E3F, 0xFDAC, 0x5E40, 0xEFD3, 0x5E44, 0xE4C1, 0x5E45, 0xF8EB, 0x5E47, 0xDBAC, 0x5E4C, 0xFCC6, 0x5E55, 0xD8AD, 0x5E5F, 0xF6BA, + 0x5E61, 0xDBDF, 0x5E62, 0xD3D3, 0x5E63, 0xF8C7, 0x5E72, 0xCACE, 0x5E73, 0xF8C1, 0x5E74, 0xD2B4, 0x5E77, 0xDCB4, 0x5E78, 0xFAB9, + 0x5E79, 0xCACF, 0x5E7B, 0xFCB3, 0x5E7C, 0xEAEA, 0x5E7D, 0xEAEB, 0x5E7E, 0xD0FA, 0x5E84, 0xEDE4, 0x5E87, 0xDDE7, 0x5E8A, 0xDFC9, + 0x5E8F, 0xDFED, 0x5E95, 0xEEBC, 0x5E97, 0xEFC1, 0x5E9A, 0xCCD2, 0x5E9C, 0xDDA4, 0x5EA0, 0xDFCA, 0x5EA6, 0xD3F8, 0x5EA7, 0xF1A8, + 0x5EAB, 0xCDB7, 0x5EAD, 0xEFD4, 0x5EB5, 0xE4DD, 0x5EB6, 0xDFEE, 0x5EB7, 0xCBAC, 0x5EB8, 0xE9BC, 0x5EBE, 0xEAEC, 0x5EC2, 0xDFCB, + 0x5EC8, 0xF9BF, 0x5EC9, 0xD6AF, 0x5ECA, 0xD5C6, 0x5ED0, 0xCFAA, 0x5ED3, 0xCEA9, 0x5ED6, 0xD6F8, 0x5EDA, 0xF1B7, 0x5EDB, 0xEEF8, + 0x5EDF, 0xD9D9, 0x5EE0, 0xF3DF, 0x5EE2, 0xF8C8, 0x5EE3, 0xCEC6, 0x5EEC, 0xD5E6, 0x5EF3, 0xF4E6, 0x5EF6, 0xE6C5, 0x5EF7, 0xEFD5, + 0x5EFA, 0xCBEF, 0x5EFB, 0xFCDF, 0x5F01, 0xDCA7, 0x5F04, 0xD6E7, 0x5F0A, 0xF8C9, 0x5F0F, 0xE3D2, 0x5F11, 0xE3BD, 0x5F13, 0xCFE1, + 0x5F14, 0xF0C0, 0x5F15, 0xECDA, 0x5F17, 0xDDD7, 0x5F18, 0xFBF0, 0x5F1B, 0xECAC, 0x5F1F, 0xF0A9, 0x5F26, 0xFAD7, 0x5F27, 0xFBC1, + 0x5F29, 0xD2C0, 0x5F31, 0xE5B0, 0x5F35, 0xEDE5, 0x5F3A, 0xCBAD, 0x5F3C, 0xF9B0, 0x5F48, 0xF7A5, 0x5F4A, 0xCBAE, 0x5F4C, 0xDAAF, + 0x5F4E, 0xD8B6, 0x5F56, 0xD3A7, 0x5F57, 0xFBB2, 0x5F59, 0xFDC4, 0x5F5B, 0xECAD, 0x5F62, 0xFBA1, 0x5F66, 0xE5E9, 0x5F67, 0xE9EE, + 0x5F69, 0xF3F4, 0x5F6A, 0xF8F3, 0x5F6B, 0xF0C1, 0x5F6C, 0xDEAF, 0x5F6D, 0xF8B0, 0x5F70, 0xF3E0, 0x5F71, 0xE7AF, 0x5F77, 0xDBAD, + 0x5F79, 0xE6B5, 0x5F7C, 0xF9A8, 0x5F7F, 0xDDD8, 0x5F80, 0xE8D9, 0x5F81, 0xEFD6, 0x5F85, 0xD3E2, 0x5F87, 0xE2DF, 0x5F8A, 0xFCE0, + 0x5F8B, 0xD7C8, 0x5F8C, 0xFDAD, 0x5F90, 0xDFEF, 0x5F91, 0xCCD3, 0x5F92, 0xD3F9, 0x5F97, 0xD4F0, 0x5F98, 0xDBC7, 0x5F99, 0xDED5, + 0x5F9E, 0xF0F4, 0x5FA0, 0xD5D0, 0x5FA1, 0xE5D9, 0x5FA8, 0xFCC7, 0x5FA9, 0xDCD6, 0x5FAA, 0xE2E0, 0x5FAE, 0xDAB0, 0x5FB5, 0xF3A3, + 0x5FB7, 0xD3EC, 0x5FB9, 0xF4CB, 0x5FBD, 0xFDC5, 0x5FC3, 0xE3FD, 0x5FC5, 0xF9B1, 0x5FCC, 0xD0FB, 0x5FCD, 0xECDB, 0x5FD6, 0xF5BC, + 0x5FD7, 0xF2A4, 0x5FD8, 0xD8CE, 0x5FD9, 0xD8CF, 0x5FE0, 0xF5F7, 0x5FEB, 0xF6E1, 0x5FF5, 0xD2B7, 0x5FFD, 0xFBEC, 0x5FFF, 0xDDC8, + 0x600F, 0xE4E8, 0x6012, 0xD2C1, 0x6016, 0xF8D7, 0x601C, 0xD6BB, 0x601D, 0xDED6, 0x6020, 0xF7BD, 0x6021, 0xECAE, 0x6025, 0xD0E1, + 0x6027, 0xE0F5, 0x6028, 0xEAB3, 0x602A, 0xCED6, 0x602F, 0xCCA5, 0x6041, 0xECF6, 0x6042, 0xE2E1, 0x6043, 0xE3BE, 0x604D, 0xFCC8, + 0x6050, 0xCDF0, 0x6052, 0xF9F6, 0x6055, 0xDFF0, 0x6059, 0xE5BF, 0x605D, 0xCEBF, 0x6062, 0xFCE1, 0x6063, 0xEDB0, 0x6064, 0xFDD1, + 0x6065, 0xF6BB, 0x6068, 0xF9CF, 0x6069, 0xEBDA, 0x606A, 0xCAC1, 0x606C, 0xD2B8, 0x606D, 0xCDF1, 0x606F, 0xE3D3, 0x6070, 0xFDE6, + 0x6085, 0xE6ED, 0x6089, 0xE3FA, 0x608C, 0xF0AA, 0x608D, 0xF9D0, 0x6094, 0xFCE2, 0x6096, 0xF8A7, 0x609A, 0xE1E5, 0x609B, 0xEEF9, + 0x609F, 0xE7F6, 0x60A0, 0xEAED, 0x60A3, 0xFCB4, 0x60A4, 0xF5C2, 0x60A7, 0xD7DC, 0x60B0, 0xF0F5, 0x60B2, 0xDDE8, 0x60B3, 0xD3ED, + 0x60B4, 0xF5FC, 0x60B6, 0xDABF, 0x60B8, 0xCCFB, 0x60BC, 0xD3FA, 0x60BD, 0xF4A4, 0x60C5, 0xEFD7, 0x60C7, 0xD4C3, 0x60D1, 0xFBE3, + 0x60DA, 0xFBED, 0x60DC, 0xE0AD, 0x60DF, 0xEAEE, 0x60E0, 0xFBB3, 0x60E1, 0xE4C2, 0x60F0, 0xF6E7, 0x60F1, 0xD2DD, 0x60F3, 0xDFCC, + 0x60F6, 0xFCC9, 0x60F9, 0xE5A9, 0x60FA, 0xE0F6, 0x60FB, 0xF6B3, 0x6101, 0xE1FE, 0x6106, 0xCBF0, 0x6108, 0xEAEF, 0x6109, 0xEAF0, + 0x610D, 0xDAC0, 0x610E, 0xF8B4, 0x610F, 0xEBF2, 0x6115, 0xE4C3, 0x611A, 0xE9D7, 0x611B, 0xE4F1, 0x611F, 0xCAEF, 0x6127, 0xCED7, + 0x6130, 0xFCCA, 0x6134, 0xF3E1, 0x6137, 0xCBC4, 0x613C, 0xE3E5, 0x613E, 0xCBC5, 0x613F, 0xEAB4, 0x6142, 0xE9BD, 0x6144, 0xD7C9, + 0x6147, 0xEBDB, 0x6148, 0xEDB1, 0x614A, 0xCCC3, 0x614B, 0xF7BE, 0x614C, 0xFCCB, 0x6153, 0xF8F4, 0x6155, 0xD9B7, 0x6158, 0xF3D3, + 0x6159, 0xF3D4, 0x615D, 0xF7E4, 0x615F, 0xF7D1, 0x6162, 0xD8B7, 0x6163, 0xCEB1, 0x6164, 0xCAC2, 0x6167, 0xFBB4, 0x6168, 0xCBC6, + 0x616B, 0xF0F6, 0x616E, 0xD5E7, 0x6170, 0xEAD0, 0x6176, 0xCCD4, 0x6177, 0xCBAF, 0x617D, 0xF4AA, 0x617E, 0xE9AF, 0x6181, 0xF5C3, + 0x6182, 0xE9D8, 0x618A, 0xDDE9, 0x618E, 0xF1F3, 0x6190, 0xD5FB, 0x6191, 0xDEBB, 0x6194, 0xF4FB, 0x6198, 0xFDF3, 0x6199, 0xFDF2, + 0x619A, 0xF7A6, 0x61A4, 0xDDC9, 0x61A7, 0xD4D3, 0x61A9, 0xCCA8, 0x61AB, 0xDAC1, 0x61AC, 0xCCD5, 0x61AE, 0xD9E4, 0x61B2, 0xFACA, + 0x61B6, 0xE5E3, 0x61BA, 0xD3BC, 0x61BE, 0xCAF0, 0x61C3, 0xD0C4, 0x61C7, 0xCAD0, 0x61C8, 0xFAAB, 0x61C9, 0xEBEB, 0x61CA, 0xE7F8, + 0x61CB, 0xD9E5, 0x61E6, 0xD1D7, 0x61F2, 0xF3A4, 0x61F6, 0xD4FB, 0x61F7, 0xFCE3, 0x61F8, 0xFAD8, 0x61FA, 0xF3D5, 0x61FC, 0xCFAB, + 0x61FF, 0xEBF3, 0x6200, 0xD5FC, 0x6207, 0xD3D4, 0x6208, 0xCDFC, 0x620A, 0xD9E6, 0x620C, 0xE2F9, 0x620D, 0xE2A1, 0x620E, 0xEBD4, + 0x6210, 0xE0F7, 0x6211, 0xE4B2, 0x6212, 0xCCFC, 0x6216, 0xFBE4, 0x621A, 0xF4AB, 0x621F, 0xD0BD, 0x6221, 0xCAF1, 0x622A, 0xEFB8, + 0x622E, 0xD7C0, 0x6230, 0xEEFA, 0x6231, 0xFDF4, 0x6234, 0xD3E3, 0x6236, 0xFBC2, 0x623E, 0xD5E8, 0x623F, 0xDBAE, 0x6240, 0xE1B6, + 0x6241, 0xF8B7, 0x6247, 0xE0BF, 0x6248, 0xFBC3, 0x6249, 0xDDEA, 0x624B, 0xE2A2, 0x624D, 0xEEA6, 0x6253, 0xF6E8, 0x6258, 0xF6F5, + 0x626E, 0xDDCA, 0x6271, 0xD0E2, 0x6276, 0xDDA6, 0x6279, 0xDDEB, 0x627C, 0xE4F9, 0x627F, 0xE3AF, 0x6280, 0xD0FC, 0x6284, 0xF4FC, + 0x6289, 0xCCBC, 0x628A, 0xF7EA, 0x6291, 0xE5E4, 0x6292, 0xDFF1, 0x6295, 0xF7E1, 0x6297, 0xF9F7, 0x6298, 0xEFB9, 0x629B, 0xF8D8, + 0x62AB, 0xF9A9, 0x62B1, 0xF8D9, 0x62B5, 0xEEBD, 0x62B9, 0xD8C6, 0x62BC, 0xE4E3, 0x62BD, 0xF5CE, 0x62C2, 0xDDD9, 0x62C7, 0xD9E7, + 0x62C8, 0xD2B9, 0x62C9, 0xD5C3, 0x62CC, 0xDAE5, 0x62CD, 0xDAD0, 0x62CF, 0xD1D9, 0x62D0, 0xCED8, 0x62D2, 0xCBDE, 0x62D3, 0xF4AC, + 0x62D4, 0xDAFB, 0x62D6, 0xF6E9, 0x62D7, 0xE8F3, 0x62D8, 0xCFAC, 0x62D9, 0xF0F0, 0x62DB, 0xF4FD, 0x62DC, 0xDBC8, 0x62EC, 0xCEC0, + 0x62ED, 0xE3D4, 0x62EE, 0xD1CF, 0x62EF, 0xF1F5, 0x62F1, 0xCDF2, 0x62F3, 0xCFEB, 0x62F7, 0xCDB8, 0x62FE, 0xE3A6, 0x62FF, 0xD1DA, + 0x6301, 0xF2A5, 0x6307, 0xF2A6, 0x6309, 0xE4CE, 0x6311, 0xD3FB, 0x632B, 0xF1A9, 0x632F, 0xF2C9, 0x633A, 0xEFD8, 0x633B, 0xE6C9, + 0x633D, 0xD8B8, 0x633E, 0xFAF3, 0x6349, 0xF3B5, 0x634C, 0xF8A4, 0x634F, 0xD1F3, 0x6350, 0xE6C8, 0x6355, 0xF8DA, 0x6367, 0xDCE9, + 0x6368, 0xDED7, 0x636E, 0xCBDF, 0x6372, 0xCFEC, 0x6377, 0xF4DF, 0x637A, 0xD1F4, 0x637B, 0xD2BA, 0x637F, 0xDFF2, 0x6383, 0xE1B7, + 0x6388, 0xE2A3, 0x6389, 0xD3FC, 0x638C, 0xEDE6, 0x6392, 0xDBC9, 0x6396, 0xE4FA, 0x6398, 0xCFDE, 0x639B, 0xCED0, 0x63A0, 0xD5D3, + 0x63A1, 0xF3F5, 0x63A2, 0xF7AE, 0x63A5, 0xEFC8, 0x63A7, 0xCDF3, 0x63A8, 0xF5CF, 0x63A9, 0xE5F3, 0x63AA, 0xF0C2, 0x63C0, 0xCAD1, + 0x63C4, 0xEAF1, 0x63C6, 0xD0A6, 0x63CF, 0xD9DA, 0x63D0, 0xF0AB, 0x63D6, 0xEBE7, 0x63DA, 0xE5C0, 0x63DB, 0xFCB5, 0x63E1, 0xE4C4, + 0x63ED, 0xCCA9, 0x63EE, 0xFDC6, 0x63F4, 0xEAB5, 0x63F6, 0xE5AA, 0x63F7, 0xDFBA, 0x640D, 0xE1DF, 0x640F, 0xDAD1, 0x6414, 0xE1B8, + 0x6416, 0xE8F4, 0x6417, 0xD3FD, 0x641C, 0xE2A4, 0x6422, 0xF2CA, 0x642C, 0xDAE6, 0x642D, 0xF7B3, 0x643A, 0xFDCD, 0x643E, 0xF3B6, + 0x6458, 0xEED7, 0x6460, 0xF5C4, 0x6469, 0xD8A4, 0x646F, 0xF2A7, 0x6478, 0xD9B8, 0x6479, 0xD9B9, 0x647A, 0xEFC9, 0x6488, 0xD6CE, + 0x6491, 0xF7CB, 0x6492, 0xDFAE, 0x6493, 0xE8F5, 0x649A, 0xD2B5, 0x649E, 0xD3D5, 0x64A4, 0xF4CC, 0x64A5, 0xDAFC, 0x64AB, 0xD9E8, + 0x64AD, 0xF7EB, 0x64AE, 0xF5C9, 0x64B0, 0xF3BC, 0x64B2, 0xDAD2, 0x64BB, 0xD3B5, 0x64C1, 0xE8B6, 0x64C4, 0xD6CF, 0x64C5, 0xF4BA, + 0x64C7, 0xF7C9, 0x64CA, 0xCCAA, 0x64CD, 0xF0C3, 0x64CE, 0xCCD6, 0x64D2, 0xD0D3, 0x64D4, 0xD3BD, 0x64D8, 0xDBFB, 0x64DA, 0xCBE0, + 0x64E1, 0xD3E4, 0x64E2, 0xF6F7, 0x64E5, 0xD5BA, 0x64E6, 0xF3CD, 0x64E7, 0xCBE1, 0x64EC, 0xEBF4, 0x64F2, 0xF4AD, 0x64F4, 0xFCAA, + 0x64FA, 0xF7EC, 0x64FE, 0xE8F6, 0x6500, 0xDAE7, 0x6504, 0xF7CC, 0x6518, 0xE5C1, 0x651D, 0xE0EE, 0x6523, 0xD5FD, 0x652A, 0xCEE6, + 0x652B, 0xFCAB, 0x652C, 0xD5BB, 0x652F, 0xF2A8, 0x6536, 0xE2A5, 0x6537, 0xCDB9, 0x6538, 0xEAF2, 0x6539, 0xCBC7, 0x653B, 0xCDF4, + 0x653E, 0xDBAF, 0x653F, 0xEFD9, 0x6545, 0xCDBA, 0x6548, 0xFCF9, 0x654D, 0xDFF3, 0x654E, 0xCEE7, 0x654F, 0xDAC2, 0x6551, 0xCFAD, + 0x6556, 0xE7F9, 0x6557, 0xF8A8, 0x655E, 0xF3E2, 0x6562, 0xCAF2, 0x6563, 0xDFA4, 0x6566, 0xD4C4, 0x656C, 0xCCD7, 0x656D, 0xE5C2, + 0x6572, 0xCDBB, 0x6574, 0xEFDA, 0x6575, 0xEED8, 0x6577, 0xDDA7, 0x6578, 0xE2A6, 0x657E, 0xE0C0, 0x6582, 0xD6B0, 0x6583, 0xF8CA, + 0x6585, 0xFCFA, 0x6587, 0xD9FE, 0x658C, 0xDEB0, 0x6590, 0xDDEC, 0x6591, 0xDAE8, 0x6597, 0xD4E0, 0x6599, 0xD6F9, 0x659B, 0xCDD7, + 0x659C, 0xDED8, 0x659F, 0xF2F8, 0x65A1, 0xE4D6, 0x65A4, 0xD0C5, 0x65A5, 0xF4AE, 0x65A7, 0xDDA8, 0x65AB, 0xEDC5, 0x65AC, 0xF3D6, + 0x65AF, 0xDED9, 0x65B0, 0xE3E6, 0x65B7, 0xD3A8, 0x65B9, 0xDBB0, 0x65BC, 0xE5DA, 0x65BD, 0xE3BF, 0x65C1, 0xDBB1, 0x65C5, 0xD5E9, + 0x65CB, 0xE0C1, 0x65CC, 0xEFDB, 0x65CF, 0xF0E9, 0x65D2, 0xD7B2, 0x65D7, 0xD0FD, 0x65E0, 0xD9E9, 0x65E3, 0xD0FE, 0x65E5, 0xECED, + 0x65E6, 0xD3A9, 0x65E8, 0xF2A9, 0x65E9, 0xF0C4, 0x65EC, 0xE2E2, 0x65ED, 0xE9EF, 0x65F1, 0xF9D1, 0x65F4, 0xE9D9, 0x65FA, 0xE8DA, + 0x65FB, 0xDAC3, 0x65FC, 0xDAC4, 0x65FD, 0xD4C5, 0x65FF, 0xE7FA, 0x6606, 0xCDE0, 0x6607, 0xE3B0, 0x6609, 0xDBB2, 0x660A, 0xFBC4, + 0x660C, 0xF3E3, 0x660E, 0xD9A5, 0x660F, 0xFBE7, 0x6610, 0xDDCB, 0x6611, 0xD0D4, 0x6613, 0xE6B6, 0x6614, 0xE0AE, 0x6615, 0xFDDA, + 0x661E, 0xDCB5, 0x661F, 0xE0F8, 0x6620, 0xE7B1, 0x6625, 0xF5F0, 0x6627, 0xD8DC, 0x6628, 0xEDC6, 0x662D, 0xE1B9, 0x662F, 0xE3C0, + 0x6630, 0xF9C0, 0x6631, 0xE9F0, 0x6634, 0xD9DB, 0x6636, 0xF3E4, 0x663A, 0xDCB6, 0x663B, 0xE4E9, 0x6641, 0xF0C5, 0x6642, 0xE3C1, + 0x6643, 0xFCCC, 0x6644, 0xFCCD, 0x6649, 0xF2CB, 0x664B, 0xF2CC, 0x664F, 0xE4CF, 0x6659, 0xF1DB, 0x665B, 0xFAD9, 0x665D, 0xF1B8, + 0x665E, 0xFDF5, 0x665F, 0xE0F9, 0x6664, 0xE7FB, 0x6665, 0xFCB7, 0x6666, 0xFCE4, 0x6667, 0xFBC5, 0x6668, 0xE3E7, 0x6669, 0xD8B9, + 0x666B, 0xF6F8, 0x666E, 0xDCC5, 0x666F, 0xCCD8, 0x6673, 0xE0AF, 0x6674, 0xF4E7, 0x6676, 0xEFDC, 0x6677, 0xCFFC, 0x6678, 0xEFDD, + 0x667A, 0xF2AA, 0x6684, 0xFDBE, 0x6687, 0xCAAC, 0x6688, 0xFDBB, 0x6689, 0xFDC7, 0x668E, 0xE7B2, 0x6690, 0xEAD1, 0x6691, 0xDFF4, + 0x6696, 0xD1EC, 0x6697, 0xE4DE, 0x6698, 0xE5C3, 0x669D, 0xD9A6, 0x66A0, 0xCDBC, 0x66A2, 0xF3E5, 0x66AB, 0xEDD5, 0x66AE, 0xD9BA, + 0x66B2, 0xEDE7, 0x66B3, 0xFBB5, 0x66B4, 0xF8EC, 0x66B9, 0xE0E7, 0x66BB, 0xCCD9, 0x66BE, 0xD4C6, 0x66C4, 0xE7A5, 0x66C6, 0xD5F5, + 0x66C7, 0xD3BE, 0x66C9, 0xFCFB, 0x66D6, 0xE4F2, 0x66D9, 0xDFF5, 0x66DC, 0xE8F8, 0x66DD, 0xF8ED, 0x66E0, 0xCEC7, 0x66E6, 0xFDF6, + 0x66F0, 0xE8D8, 0x66F2, 0xCDD8, 0x66F3, 0xE7D6, 0x66F4, 0xCCDA, 0x66F7, 0xCAE3, 0x66F8, 0xDFF6, 0x66F9, 0xF0C7, 0x66FA, 0xF0C6, + 0x66FC, 0xD8BA, 0x66FE, 0xF1F4, 0x66FF, 0xF4F0, 0x6700, 0xF5CC, 0x6703, 0xFCE5, 0x6708, 0xEAC5, 0x6709, 0xEAF3, 0x670B, 0xDDDB, + 0x670D, 0xDCD7, 0x6714, 0xDEFD, 0x6715, 0xF2F9, 0x6717, 0xD5C7, 0x671B, 0xD8D0, 0x671D, 0xF0C8, 0x671E, 0xD1A1, 0x671F, 0xD1A2, + 0x6726, 0xD9D4, 0x6727, 0xD6E8, 0x6728, 0xD9CA, 0x672A, 0xDAB1, 0x672B, 0xD8C7, 0x672C, 0xDCE2, 0x672D, 0xF3CE, 0x672E, 0xF5F4, + 0x6731, 0xF1B9, 0x6734, 0xDAD3, 0x6736, 0xF6EA, 0x673A, 0xCFF5, 0x673D, 0xFDAE, 0x6746, 0xCAD2, 0x6749, 0xDFB4, 0x674E, 0xD7DD, + 0x674F, 0xFABA, 0x6750, 0xEEA7, 0x6751, 0xF5BD, 0x6753, 0xF8F5, 0x6756, 0xEDE8, 0x675C, 0xD4E1, 0x675E, 0xD1A3, 0x675F, 0xE1D6, + 0x676D, 0xF9F8, 0x676F, 0xDBCA, 0x6770, 0xCBF9, 0x6771, 0xD4D4, 0x6773, 0xD9DC, 0x6775, 0xEEBE, 0x6777, 0xF7ED, 0x677B, 0xD2EE, + 0x677E, 0xE1E6, 0x677F, 0xF7F9, 0x6787, 0xDDED, 0x6789, 0xE8DB, 0x678B, 0xDBB3, 0x678F, 0xD1F7, 0x6790, 0xE0B0, 0x6793, 0xD4E2, + 0x6795, 0xF6D7, 0x6797, 0xD7F9, 0x679A, 0xD8DD, 0x679C, 0xCDFD, 0x679D, 0xF2AB, 0x67AF, 0xCDBD, 0x67B0, 0xF8C2, 0x67B3, 0xF2AC, + 0x67B6, 0xCAAD, 0x67B7, 0xCAAE, 0x67B8, 0xCFAE, 0x67BE, 0xE3C2, 0x67C4, 0xDCB7, 0x67CF, 0xDBDA, 0x67D0, 0xD9BB, 0x67D1, 0xCAF3, + 0x67D2, 0xF6D3, 0x67D3, 0xE6F8, 0x67D4, 0xEAF5, 0x67DA, 0xEAF6, 0x67DD, 0xF6F9, 0x67E9, 0xCFAF, 0x67EC, 0xCAD3, 0x67EF, 0xCAAF, + 0x67F0, 0xD2B0, 0x67F1, 0xF1BA, 0x67F3, 0xD7B3, 0x67F4, 0xE3C3, 0x67F5, 0xF3FD, 0x67F6, 0xDEDA, 0x67FB, 0xDEDB, 0x67FE, 0xEFDE, + 0x6812, 0xE2E3, 0x6813, 0xEEFB, 0x6816, 0xDFF7, 0x6817, 0xD7CA, 0x6821, 0xCEE8, 0x6822, 0xDBDB, 0x682A, 0xF1BB, 0x682F, 0xE9F1, + 0x6838, 0xFAB7, 0x6839, 0xD0C6, 0x683C, 0xCCAB, 0x683D, 0xEEA8, 0x6840, 0xCBFA, 0x6841, 0xF9F9, 0x6842, 0xCCFD, 0x6843, 0xD3FE, + 0x6848, 0xE4D0, 0x684E, 0xF2EE, 0x6850, 0xD4D5, 0x6851, 0xDFCD, 0x6853, 0xFCB8, 0x6854, 0xD1D0, 0x686D, 0xF2CD, 0x6876, 0xF7D2, + 0x687F, 0xCAD4, 0x6881, 0xD5D9, 0x6885, 0xD8DE, 0x688F, 0xCDD9, 0x6893, 0xEEA9, 0x6894, 0xF6BC, 0x6897, 0xCCDB, 0x689D, 0xF0C9, + 0x689F, 0xFCFC, 0x68A1, 0xE8C9, 0x68A2, 0xF4FE, 0x68A7, 0xE7FC, 0x68A8, 0xD7DE, 0x68AD, 0xDEDC, 0x68AF, 0xF0AC, 0x68B0, 0xCCFE, + 0x68B1, 0xCDE1, 0x68B3, 0xE1BA, 0x68B5, 0xDBEF, 0x68B6, 0xDAB2, 0x68C4, 0xD1A5, 0x68C5, 0xDCB8, 0x68C9, 0xD8F6, 0x68CB, 0xD1A4, + 0x68CD, 0xCDE2, 0x68D2, 0xDCEA, 0x68D5, 0xF0F7, 0x68D7, 0xF0CA, 0x68D8, 0xD0BE, 0x68DA, 0xDDDC, 0x68DF, 0xD4D6, 0x68E0, 0xD3D6, + 0x68E7, 0xEDD0, 0x68E8, 0xCDA1, 0x68EE, 0xDFB5, 0x68F2, 0xDFF8, 0x68F9, 0xD4A1, 0x68FA, 0xCEB2, 0x6900, 0xE8CA, 0x6905, 0xEBF5, + 0x690D, 0xE3D5, 0x690E, 0xF5D0, 0x6912, 0xF5A1, 0x6927, 0xD9A7, 0x6930, 0xE5AB, 0x693D, 0xE6CB, 0x693F, 0xF5F1, 0x694A, 0xE5C5, + 0x6953, 0xF9A3, 0x6954, 0xE0DB, 0x6955, 0xF6EB, 0x6957, 0xCBF1, 0x6959, 0xD9EA, 0x695A, 0xF5A2, 0x695E, 0xD7D1, 0x6960, 0xD1F8, + 0x6961, 0xEAF8, 0x6962, 0xEAF9, 0x6963, 0xDAB3, 0x6968, 0xEFDF, 0x696B, 0xF1EF, 0x696D, 0xE5F6, 0x696E, 0xEEBF, 0x696F, 0xE2E4, + 0x6975, 0xD0BF, 0x6977, 0xFAAC, 0x6978, 0xF5D1, 0x6979, 0xE7B3, 0x6995, 0xE9BE, 0x699B, 0xF2CE, 0x699C, 0xDBB4, 0x69A5, 0xFCCE, + 0x69A7, 0xDDEE, 0x69AE, 0xE7B4, 0x69B4, 0xD7B4, 0x69BB, 0xF7B4, 0x69C1, 0xCDBE, 0x69C3, 0xDAE9, 0x69CB, 0xCFB0, 0x69CC, 0xF7D9, + 0x69CD, 0xF3E6, 0x69D0, 0xCED9, 0x69E8, 0xCEAA, 0x69EA, 0xCBC8, 0x69FB, 0xD0A7, 0x69FD, 0xF0CB, 0x69FF, 0xD0C7, 0x6A02, 0xE4C5, + 0x6A0A, 0xDBE0, 0x6A11, 0xD5DA, 0x6A13, 0xD7A7, 0x6A17, 0xEEC0, 0x6A19, 0xF8F6, 0x6A1E, 0xF5D2, 0x6A1F, 0xEDE9, 0x6A21, 0xD9BC, + 0x6A23, 0xE5C6, 0x6A35, 0xF5A3, 0x6A38, 0xDAD4, 0x6A39, 0xE2A7, 0x6A3A, 0xFBFC, 0x6A3D, 0xF1DC, 0x6A44, 0xCAF4, 0x6A48, 0xE8FA, + 0x6A4B, 0xCEE9, 0x6A52, 0xE9F8, 0x6A53, 0xE2E5, 0x6A58, 0xD0B9, 0x6A59, 0xD4F2, 0x6A5F, 0xD1A6, 0x6A61, 0xDFCE, 0x6A6B, 0xFCF4, + 0x6A80, 0xD3AA, 0x6A84, 0xCCAC, 0x6A89, 0xEFE0, 0x6A8D, 0xE5E5, 0x6A8E, 0xD0D5, 0x6A97, 0xDBFC, 0x6A9C, 0xFCE6, 0x6AA2, 0xCBFE, + 0x6AA3, 0xEDEA, 0x6AB3, 0xDEB1, 0x6ABB, 0xF9E3, 0x6AC2, 0xD4A2, 0x6AC3, 0xCFF6, 0x6AD3, 0xD6D0, 0x6ADA, 0xD5EA, 0x6ADB, 0xF1EE, + 0x6AF6, 0xFACB, 0x6AFB, 0xE5A1, 0x6B04, 0xD5B1, 0x6B0A, 0xCFED, 0x6B0C, 0xEDEB, 0x6B12, 0xD5B2, 0x6B16, 0xD5BC, 0x6B20, 0xFDE2, + 0x6B21, 0xF3AD, 0x6B23, 0xFDDB, 0x6B32, 0xE9B0, 0x6B3A, 0xD1A7, 0x6B3D, 0xFDE3, 0x6B3E, 0xCEB3, 0x6B46, 0xFDE4, 0x6B47, 0xFACE, + 0x6B4C, 0xCAB0, 0x6B4E, 0xF7A7, 0x6B50, 0xCFB1, 0x6B5F, 0xE6A2, 0x6B61, 0xFCB6, 0x6B62, 0xF2AD, 0x6B63, 0xEFE1, 0x6B64, 0xF3AE, + 0x6B65, 0xDCC6, 0x6B66, 0xD9EB, 0x6B6A, 0xE8E0, 0x6B72, 0xE1A8, 0x6B77, 0xD5F6, 0x6B78, 0xCFFD, 0x6B7B, 0xDEDD, 0x6B7F, 0xD9D1, + 0x6B83, 0xE4EA, 0x6B84, 0xF2CF, 0x6B86, 0xF7BF, 0x6B89, 0xE2E6, 0x6B8A, 0xE2A8, 0x6B96, 0xE3D6, 0x6B98, 0xEDD1, 0x6B9E, 0xE9F9, + 0x6BAE, 0xD6B1, 0x6BAF, 0xDEB2, 0x6BB2, 0xE0E8, 0x6BB5, 0xD3AB, 0x6BB7, 0xEBDC, 0x6BBA, 0xDFAF, 0x6BBC, 0xCAC3, 0x6BBF, 0xEEFC, + 0x6BC1, 0xFDC3, 0x6BC5, 0xEBF6, 0x6BC6, 0xCFB2, 0x6BCB, 0xD9EC, 0x6BCD, 0xD9BD, 0x6BCF, 0xD8DF, 0x6BD2, 0xD4B8, 0x6BD3, 0xEBBE, + 0x6BD4, 0xDDEF, 0x6BD6, 0xDDF0, 0x6BD7, 0xDDF1, 0x6BD8, 0xDDF2, 0x6BDB, 0xD9BE, 0x6BEB, 0xFBC6, 0x6BEC, 0xCFB3, 0x6C08, 0xEEFD, + 0x6C0F, 0xE4AB, 0x6C11, 0xDAC5, 0x6C13, 0xD8EC, 0x6C23, 0xD1A8, 0x6C34, 0xE2A9, 0x6C37, 0xDEBC, 0x6C38, 0xE7B5, 0x6C3E, 0xDBF0, + 0x6C40, 0xEFE2, 0x6C41, 0xF1F0, 0x6C42, 0xCFB4, 0x6C4E, 0xDBF1, 0x6C50, 0xE0B1, 0x6C55, 0xDFA5, 0x6C57, 0xF9D2, 0x6C5A, 0xE7FD, + 0x6C5D, 0xE6A3, 0x6C5E, 0xFBF1, 0x6C5F, 0xCBB0, 0x6C60, 0xF2AE, 0x6C68, 0xCDE7, 0x6C6A, 0xE8DC, 0x6C6D, 0xE7D7, 0x6C70, 0xF7C0, + 0x6C72, 0xD0E3, 0x6C76, 0xDAA1, 0x6C7A, 0xCCBD, 0x6C7D, 0xD1A9, 0x6C7E, 0xDDCC, 0x6C81, 0xE3FE, 0x6C82, 0xD1AA, 0x6C83, 0xE8AA, + 0x6C85, 0xEAB6, 0x6C86, 0xF9FA, 0x6C87, 0xE6CC, 0x6C88, 0xF6D8, 0x6C8C, 0xD4C7, 0x6C90, 0xD9CB, 0x6C92, 0xD9D2, 0x6C93, 0xD3CB, + 0x6C94, 0xD8F7, 0x6C95, 0xDAA9, 0x6C96, 0xF5F8, 0x6C99, 0xDEDE, 0x6C9A, 0xF2AF, 0x6C9B, 0xF8A9, 0x6CAB, 0xD8C8, 0x6CAE, 0xEEC1, + 0x6CB3, 0xF9C1, 0x6CB8, 0xDDF3, 0x6CB9, 0xEAFA, 0x6CBB, 0xF6BD, 0x6CBC, 0xE1BB, 0x6CBD, 0xCDBF, 0x6CBE, 0xF4D4, 0x6CBF, 0xE6CD, + 0x6CC1, 0xFCCF, 0x6CC2, 0xFBA2, 0x6CC4, 0xE0DC, 0x6CC9, 0xF4BB, 0x6CCA, 0xDAD5, 0x6CCC, 0xF9B2, 0x6CD3, 0xFBF2, 0x6CD5, 0xDBF6, + 0x6CD7, 0xDEDF, 0x6CDB, 0xDBF2, 0x6CE1, 0xF8DC, 0x6CE2, 0xF7EE, 0x6CE3, 0xEBE8, 0x6CE5, 0xD2FA, 0x6CE8, 0xF1BC, 0x6CEB, 0xFADA, + 0x6CEE, 0xDAEA, 0x6CEF, 0xDAC6, 0x6CF0, 0xF7C1, 0x6CF3, 0xE7B6, 0x6D0B, 0xE5C7, 0x6D0C, 0xD6AC, 0x6D11, 0xDCC7, 0x6D17, 0xE1A9, + 0x6D19, 0xE2AA, 0x6D1B, 0xD5A6, 0x6D1E, 0xD4D7, 0x6D25, 0xF2D0, 0x6D27, 0xEAFB, 0x6D29, 0xE0DD, 0x6D2A, 0xFBF3, 0x6D32, 0xF1BD, + 0x6D35, 0xE2E7, 0x6D36, 0xFDD7, 0x6D38, 0xCEC8, 0x6D39, 0xEAB7, 0x6D3B, 0xFCC0, 0x6D3D, 0xFDE7, 0x6D3E, 0xF7EF, 0x6D41, 0xD7B5, + 0x6D59, 0xEFBA, 0x6D5A, 0xF1DD, 0x6D5C, 0xDEB3, 0x6D63, 0xE8CB, 0x6D66, 0xF8DD, 0x6D69, 0xFBC7, 0x6D6A, 0xD5C8, 0x6D6C, 0xD7DF, + 0x6D6E, 0xDDA9, 0x6D74, 0xE9B1, 0x6D77, 0xFAAD, 0x6D78, 0xF6D9, 0x6D79, 0xFAF4, 0x6D7F, 0xF8AA, 0x6D85, 0xE6EE, 0x6D87, 0xCCDC, + 0x6D88, 0xE1BC, 0x6D89, 0xE0EF, 0x6D8C, 0xE9BF, 0x6D8D, 0xFCFD, 0x6D8E, 0xE6CE, 0x6D91, 0xE1D7, 0x6D93, 0xE6CF, 0x6D95, 0xF4F1, + 0x6DAF, 0xE4F3, 0x6DB2, 0xE4FB, 0x6DB5, 0xF9E4, 0x6DC0, 0xEFE3, 0x6DC3, 0xCFEE, 0x6DC4, 0xF6BE, 0x6DC5, 0xE0B2, 0x6DC6, 0xFCFE, + 0x6DC7, 0xD1AB, 0x6DCB, 0xD7FA, 0x6DCF, 0xFBC8, 0x6DD1, 0xE2D7, 0x6DD8, 0xD4A3, 0x6DD9, 0xF0F8, 0x6DDA, 0xD7A8, 0x6DDE, 0xE1E7, + 0x6DE1, 0xD3BF, 0x6DE8, 0xEFE4, 0x6DEA, 0xD7C5, 0x6DEB, 0xEBE2, 0x6DEE, 0xFCE7, 0x6DF1, 0xE4A2, 0x6DF3, 0xE2E8, 0x6DF5, 0xE6D0, + 0x6DF7, 0xFBE8, 0x6DF8, 0xF4E8, 0x6DF9, 0xE5F4, 0x6DFA, 0xF4BC, 0x6DFB, 0xF4D5, 0x6E17, 0xDFB6, 0x6E19, 0xFCB9, 0x6E1A, 0xEEC2, + 0x6E1B, 0xCAF5, 0x6E1F, 0xEFE5, 0x6E20, 0xCBE2, 0x6E21, 0xD4A4, 0x6E23, 0xDEE0, 0x6E24, 0xDAFD, 0x6E25, 0xE4C6, 0x6E26, 0xE8BE, + 0x6E2B, 0xE0DE, 0x6E2C, 0xF6B4, 0x6E2D, 0xEAD2, 0x6E2F, 0xF9FB, 0x6E32, 0xE0C2, 0x6E34, 0xCAE4, 0x6E36, 0xE7B7, 0x6E38, 0xEAFD, + 0x6E3A, 0xD9DD, 0x6E3C, 0xDAB4, 0x6E3D, 0xEEAA, 0x6E3E, 0xFBE9, 0x6E43, 0xDBCB, 0x6E44, 0xDAB5, 0x6E4A, 0xF1BE, 0x6E4D, 0xD3AC, + 0x6E56, 0xFBC9, 0x6E58, 0xDFCF, 0x6E5B, 0xD3C0, 0x6E5C, 0xE3D7, 0x6E5E, 0xEFE6, 0x6E5F, 0xFCD0, 0x6E67, 0xE9C0, 0x6E6B, 0xF5D3, + 0x6E6E, 0xECDC, 0x6E6F, 0xF7B7, 0x6E72, 0xEAB8, 0x6E73, 0xD1F9, 0x6E7A, 0xDCC8, 0x6E90, 0xEAB9, 0x6E96, 0xF1DE, 0x6E9C, 0xD7B6, + 0x6E9D, 0xCFB5, 0x6E9F, 0xD9A8, 0x6EA2, 0xECEE, 0x6EA5, 0xDDAA, 0x6EAA, 0xCDA2, 0x6EAB, 0xE8AE, 0x6EAF, 0xE1BD, 0x6EB1, 0xF2D1, + 0x6EB6, 0xE9C1, 0x6EBA, 0xD2FC, 0x6EC2, 0xDBB5, 0x6EC4, 0xF3E7, 0x6EC5, 0xD8FE, 0x6EC9, 0xFCD1, 0x6ECB, 0xEDB2, 0x6ECC, 0xF4AF, + 0x6ECE, 0xFBA3, 0x6ED1, 0xFCC1, 0x6ED3, 0xEEAB, 0x6ED4, 0xD4A5, 0x6EEF, 0xF4F2, 0x6EF4, 0xEED9, 0x6EF8, 0xFBCA, 0x6EFE, 0xCDE3, + 0x6EFF, 0xD8BB, 0x6F01, 0xE5DB, 0x6F02, 0xF8F7, 0x6F06, 0xF6D4, 0x6F0F, 0xD7A9, 0x6F11, 0xCBC9, 0x6F14, 0xE6D1, 0x6F15, 0xF0CC, + 0x6F20, 0xD8AE, 0x6F22, 0xF9D3, 0x6F23, 0xD5FE, 0x6F2B, 0xD8BC, 0x6F2C, 0xF2B0, 0x6F31, 0xE2AB, 0x6F32, 0xF3E8, 0x6F38, 0xEFC2, + 0x6F3F, 0xEDEC, 0x6F41, 0xE7B8, 0x6F51, 0xDAFE, 0x6F54, 0xCCBE, 0x6F57, 0xF2FC, 0x6F58, 0xDAEB, 0x6F5A, 0xE2D8, 0x6F5B, 0xEDD6, + 0x6F5E, 0xD6D1, 0x6F5F, 0xE0B3, 0x6F62, 0xFCD2, 0x6F64, 0xEBC8, 0x6F6D, 0xD3C1, 0x6F6E, 0xF0CD, 0x6F70, 0xCFF7, 0x6F7A, 0xEDD2, + 0x6F7C, 0xD4D8, 0x6F7D, 0xDCC9, 0x6F7E, 0xD7F1, 0x6F81, 0xDFBB, 0x6F84, 0xF3A5, 0x6F88, 0xF4CD, 0x6F8D, 0xF1BF, 0x6F8E, 0xF8B1, + 0x6F90, 0xE9FA, 0x6F94, 0xFBCB, 0x6F97, 0xCAD5, 0x6FA3, 0xF9D4, 0x6FA4, 0xF7CA, 0x6FA7, 0xD6C8, 0x6FAE, 0xFCE8, 0x6FAF, 0xF3BD, + 0x6FB1, 0xEEFE, 0x6FB3, 0xE7FE, 0x6FB9, 0xD3C2, 0x6FBE, 0xD3B6, 0x6FC0, 0xCCAD, 0x6FC1, 0xF6FA, 0x6FC2, 0xD6B2, 0x6FC3, 0xD2D8, + 0x6FCA, 0xE7D8, 0x6FD5, 0xE3A5, 0x6FDA, 0xE7B9, 0x6FDF, 0xF0AD, 0x6FE0, 0xFBCC, 0x6FE1, 0xEBA1, 0x6FE4, 0xD4A6, 0x6FE9, 0xFBCD, + 0x6FEB, 0xD5BD, 0x6FEC, 0xF1DF, 0x6FEF, 0xF6FB, 0x6FF1, 0xDEB4, 0x6FFE, 0xD5EB, 0x7001, 0xE5C8, 0x7005, 0xFBA4, 0x7006, 0xD4B9, + 0x7009, 0xDEE1, 0x700B, 0xE4A3, 0x700F, 0xD7B7, 0x7011, 0xF8EE, 0x7015, 0xDEB5, 0x7018, 0xD6D2, 0x701A, 0xF9D5, 0x701B, 0xE7BA, + 0x701C, 0xEBD5, 0x701D, 0xD5F7, 0x701E, 0xEFE7, 0x701F, 0xE1BE, 0x7023, 0xFAAE, 0x7027, 0xD6E9, 0x7028, 0xD6EE, 0x702F, 0xE7BB, + 0x7037, 0xECCB, 0x703E, 0xD5B3, 0x704C, 0xCEB4, 0x7050, 0xFBA5, 0x7051, 0xE1EE, 0x7058, 0xF7A8, 0x705D, 0xFBCE, 0x7063, 0xD8BD, + 0x706B, 0xFBFD, 0x7070, 0xFCE9, 0x7078, 0xCFB6, 0x707C, 0xEDC7, 0x707D, 0xEEAC, 0x7085, 0xCCDD, 0x708A, 0xF6A7, 0x708E, 0xE6FA, + 0x7092, 0xF5A4, 0x7098, 0xFDDC, 0x7099, 0xEDB3, 0x709A, 0xCEC9, 0x70A1, 0xEFE8, 0x70A4, 0xE1BF, 0x70AB, 0xFADB, 0x70AC, 0xCBE3, + 0x70AD, 0xF7A9, 0x70AF, 0xFBA6, 0x70B3, 0xDCB9, 0x70B7, 0xF1C0, 0x70B8, 0xEDC8, 0x70B9, 0xEFC3, 0x70C8, 0xD6AD, 0x70CB, 0xFDCE, + 0x70CF, 0xE8A1, 0x70D8, 0xFBF4, 0x70D9, 0xD5A7, 0x70DD, 0xF1F6, 0x70DF, 0xE6D3, 0x70F1, 0xCCDE, 0x70F9, 0xF8B2, 0x70FD, 0xDCEB, + 0x7104, 0xFDB6, 0x7109, 0xE5EA, 0x710C, 0xF1E0, 0x7119, 0xDBCC, 0x711A, 0xDDCD, 0x711E, 0xD4C8, 0x7121, 0xD9ED, 0x7126, 0xF5A5, + 0x7130, 0xE6FB, 0x7136, 0xE6D4, 0x7147, 0xFDC8, 0x7149, 0xD6A1, 0x714A, 0xFDBF, 0x714C, 0xFCD3, 0x714E, 0xEFA1, 0x7150, 0xE7BC, + 0x7156, 0xD1EE, 0x7159, 0xE6D5, 0x715C, 0xE9F2, 0x715E, 0xDFB0, 0x7164, 0xD8E0, 0x7165, 0xFCBA, 0x7166, 0xFDAF, 0x7167, 0xF0CE, + 0x7169, 0xDBE1, 0x716C, 0xE5C9, 0x716E, 0xEDB4, 0x717D, 0xE0C3, 0x7184, 0xE3D8, 0x7189, 0xE9FB, 0x718A, 0xEAA8, 0x718F, 0xFDB7, + 0x7192, 0xFBA7, 0x7194, 0xE9C2, 0x7199, 0xFDF7, 0x719F, 0xE2D9, 0x71A2, 0xDCEC, 0x71AC, 0xE8A2, 0x71B1, 0xE6F0, 0x71B9, 0xFDF8, + 0x71BA, 0xFDF9, 0x71BE, 0xF6BF, 0x71C1, 0xE7A7, 0x71C3, 0xE6D7, 0x71C8, 0xD4F3, 0x71C9, 0xD4C9, 0x71CE, 0xD6FA, 0x71D0, 0xD7F2, + 0x71D2, 0xE1C0, 0x71D4, 0xDBE2, 0x71D5, 0xE6D8, 0x71DF, 0xE7BD, 0x71E5, 0xF0CF, 0x71E6, 0xF3BE, 0x71E7, 0xE2AC, 0x71ED, 0xF5B7, + 0x71EE, 0xE0F0, 0x71FB, 0xFDB8, 0x71FC, 0xE3E8, 0x71FE, 0xD4A7, 0x71FF, 0xE8FC, 0x7200, 0xFAD2, 0x7206, 0xF8EF, 0x7210, 0xD6D3, + 0x721B, 0xD5B4, 0x722A, 0xF0D0, 0x722C, 0xF7F0, 0x722D, 0xEEB3, 0x7230, 0xEABA, 0x7232, 0xEAD3, 0x7235, 0xEDC9, 0x7236, 0xDDAB, + 0x723A, 0xE5AC, 0x723B, 0xFDA1, 0x723D, 0xDFD0, 0x723E, 0xECB3, 0x7240, 0xDFD1, 0x7246, 0xEDED, 0x7247, 0xF8B8, 0x7248, 0xF7FA, + 0x724C, 0xF8AB, 0x7252, 0xF4E0, 0x7258, 0xD4BA, 0x7259, 0xE4B3, 0x725B, 0xE9DA, 0x725D, 0xDEB6, 0x725F, 0xD9BF, 0x7261, 0xD9C0, + 0x7262, 0xD6EF, 0x7267, 0xD9CC, 0x7269, 0xDAAA, 0x7272, 0xDFE5, 0x7279, 0xF7E5, 0x727D, 0xCCB2, 0x7280, 0xDFF9, 0x7281, 0xD7E0, + 0x72A2, 0xD4BB, 0x72A7, 0xFDFA, 0x72AC, 0xCCB3, 0x72AF, 0xDBF3, 0x72C0, 0xDFD2, 0x72C2, 0xCECA, 0x72C4, 0xEEDA, 0x72CE, 0xE4E4, + 0x72D0, 0xFBCF, 0x72D7, 0xCFB7, 0x72D9, 0xEEC3, 0x72E1, 0xCEEA, 0x72E9, 0xE2AD, 0x72F8, 0xD7E1, 0x72F9, 0xFAF5, 0x72FC, 0xD5C9, + 0x72FD, 0xF8AC, 0x730A, 0xE7D9, 0x7316, 0xF3E9, 0x731B, 0xD8ED, 0x731C, 0xE3C4, 0x731D, 0xF0F1, 0x7325, 0xE8E5, 0x7329, 0xE0FA, + 0x732A, 0xEEC4, 0x732B, 0xD9DE, 0x7336, 0xEBA2, 0x7337, 0xEBA3, 0x733E, 0xFCC2, 0x733F, 0xEABB, 0x7344, 0xE8AB, 0x7345, 0xDEE2, + 0x7350, 0xEDEF, 0x7352, 0xE8A3, 0x7357, 0xCFF1, 0x7368, 0xD4BC, 0x736A, 0xFCEA, 0x7370, 0xE7BE, 0x7372, 0xFCF2, 0x7375, 0xD6B4, + 0x7378, 0xE2AE, 0x737A, 0xD3B7, 0x737B, 0xFACC, 0x7384, 0xFADC, 0x7386, 0xEDB5, 0x7387, 0xE1E3, 0x7389, 0xE8AC, 0x738B, 0xE8DD, + 0x738E, 0xEFE9, 0x7394, 0xF4BD, 0x7396, 0xCFB8, 0x7397, 0xE9DB, 0x7398, 0xD1AC, 0x739F, 0xDAC7, 0x73A7, 0xEBC9, 0x73A9, 0xE8CC, + 0x73AD, 0xDEB7, 0x73B2, 0xD6BC, 0x73B3, 0xD3E5, 0x73B9, 0xFADD, 0x73C0, 0xDAD6, 0x73C2, 0xCAB1, 0x73C9, 0xDAC8, 0x73CA, 0xDFA6, + 0x73CC, 0xF9B3, 0x73CD, 0xF2D2, 0x73CF, 0xCAC4, 0x73D6, 0xCECB, 0x73D9, 0xCDF5, 0x73DD, 0xFDB0, 0x73DE, 0xD5A8, 0x73E0, 0xF1C1, + 0x73E3, 0xE2E9, 0x73E4, 0xDCCA, 0x73E5, 0xECB4, 0x73E6, 0xFAC0, 0x73E9, 0xFBA8, 0x73EA, 0xD0A8, 0x73ED, 0xDAEC, 0x73F7, 0xD9EE, + 0x73F9, 0xE0FB, 0x73FD, 0xEFEA, 0x73FE, 0xFADE, 0x7401, 0xE0C4, 0x7403, 0xCFB9, 0x7405, 0xD5CA, 0x7406, 0xD7E2, 0x7407, 0xE2AF, + 0x7409, 0xD7B8, 0x7413, 0xE8CD, 0x741B, 0xF6DA, 0x7420, 0xEFA2, 0x7421, 0xE2DA, 0x7422, 0xF6FC, 0x7425, 0xFBD0, 0x7426, 0xD1AD, + 0x7428, 0xCDE4, 0x742A, 0xD1AE, 0x742B, 0xDCED, 0x742C, 0xE8CE, 0x742E, 0xF0F9, 0x742F, 0xCEB5, 0x7430, 0xE6FC, 0x7433, 0xD7FB, + 0x7434, 0xD0D6, 0x7435, 0xDDF5, 0x7436, 0xF7F1, 0x7438, 0xF6FD, 0x743A, 0xDBF7, 0x743F, 0xFBEA, 0x7440, 0xE9DC, 0x7441, 0xD9C1, + 0x7443, 0xF5F2, 0x7444, 0xE0C5, 0x744B, 0xEAD4, 0x7455, 0xF9C2, 0x7457, 0xEABC, 0x7459, 0xD2C5, 0x745A, 0xFBD1, 0x745B, 0xE7C0, + 0x745C, 0xEBA5, 0x745E, 0xDFFA, 0x745F, 0xE3A2, 0x7460, 0xD7B9, 0x7462, 0xE9C3, 0x7464, 0xE8FD, 0x7465, 0xE8AF, 0x7468, 0xF2D3, + 0x7469, 0xFBA9, 0x746A, 0xD8A5, 0x746F, 0xD5CB, 0x747E, 0xD0C8, 0x7482, 0xD1AF, 0x7483, 0xD7E3, 0x7487, 0xE0C6, 0x7489, 0xD6A2, + 0x748B, 0xEDF0, 0x7498, 0xD7F3, 0x749C, 0xFCD4, 0x749E, 0xDAD7, 0x749F, 0xCCDF, 0x74A1, 0xF2D4, 0x74A3, 0xD1B0, 0x74A5, 0xCCE0, + 0x74A7, 0xDBFD, 0x74A8, 0xF3BF, 0x74AA, 0xF0D1, 0x74B0, 0xFCBB, 0x74B2, 0xE2B0, 0x74B5, 0xE6A5, 0x74B9, 0xE2DB, 0x74BD, 0xDFDE, + 0x74BF, 0xE0C7, 0x74C6, 0xF2EF, 0x74CA, 0xCCE1, 0x74CF, 0xD6EA, 0x74D4, 0xE7C2, 0x74D8, 0xCEB6, 0x74DA, 0xF3C0, 0x74DC, 0xCDFE, + 0x74E0, 0xFBD2, 0x74E2, 0xF8F8, 0x74E3, 0xF7FB, 0x74E6, 0xE8BF, 0x74EE, 0xE8B7, 0x74F7, 0xEDB6, 0x7501, 0xDCBA, 0x7504, 0xCCB4, + 0x7511, 0xF1F7, 0x7515, 0xE8B8, 0x7518, 0xCAF6, 0x751A, 0xE4A4, 0x751B, 0xF4D6, 0x751F, 0xDFE6, 0x7523, 0xDFA7, 0x7525, 0xDFE7, + 0x7526, 0xE1C1, 0x7528, 0xE9C4, 0x752B, 0xDCCB, 0x752C, 0xE9C5, 0x7530, 0xEFA3, 0x7531, 0xEBA6, 0x7532, 0xCBA3, 0x7533, 0xE3E9, + 0x7537, 0xD1FB, 0x7538, 0xEFA4, 0x753A, 0xEFEB, 0x7547, 0xD0B4, 0x754C, 0xCDA3, 0x754F, 0xE8E6, 0x7551, 0xEFA5, 0x7553, 0xD3CC, + 0x7554, 0xDAED, 0x7559, 0xD7BA, 0x755B, 0xF2D5, 0x755C, 0xF5E5, 0x755D, 0xD9EF, 0x7562, 0xF9B4, 0x7565, 0xD5D4, 0x7566, 0xFDCF, + 0x756A, 0xDBE3, 0x756F, 0xF1E1, 0x7570, 0xECB6, 0x7575, 0xFBFE, 0x7576, 0xD3D7, 0x7578, 0xD1B1, 0x757A, 0xCBB1, 0x757F, 0xD1B2, + 0x7586, 0xCBB2, 0x7587, 0xF1C2, 0x758A, 0xF4E1, 0x758B, 0xF9B5, 0x758E, 0xE1C3, 0x758F, 0xE1C2, 0x7591, 0xEBF7, 0x759D, 0xDFA8, + 0x75A5, 0xCBCA, 0x75AB, 0xE6B9, 0x75B1, 0xF8DE, 0x75B2, 0xF9AA, 0x75B3, 0xCAF7, 0x75B5, 0xEDB7, 0x75B8, 0xD3B8, 0x75B9, 0xF2D6, + 0x75BC, 0xD4D9, 0x75BD, 0xEEC5, 0x75BE, 0xF2F0, 0x75C2, 0xCAB2, 0x75C5, 0xDCBB, 0x75C7, 0xF1F8, 0x75CD, 0xECB7, 0x75D2, 0xE5CA, + 0x75D4, 0xF6C0, 0x75D5, 0xFDDD, 0x75D8, 0xD4E3, 0x75D9, 0xCCE2, 0x75DB, 0xF7D4, 0x75E2, 0xD7E5, 0x75F0, 0xD3C3, 0x75F2, 0xD8A6, + 0x75F4, 0xF6C1, 0x75FA, 0xDDF6, 0x75FC, 0xCDC0, 0x7600, 0xE5DC, 0x760D, 0xE5CB, 0x7619, 0xE1C4, 0x761F, 0xE8B0, 0x7620, 0xF4B0, + 0x7621, 0xF3EA, 0x7622, 0xDAEE, 0x7624, 0xD7BB, 0x7626, 0xE2B1, 0x763B, 0xD7AA, 0x7642, 0xD6FB, 0x764C, 0xE4DF, 0x764E, 0xCAD6, + 0x7652, 0xEBA8, 0x7656, 0xDBFE, 0x7661, 0xF6C2, 0x7664, 0xEFBB, 0x7669, 0xD4FD, 0x766C, 0xE0C8, 0x7670, 0xE8B9, 0x7672, 0xEFA6, + 0x7678, 0xCDA4, 0x767B, 0xD4F4, 0x767C, 0xDBA1, 0x767D, 0xDBDC, 0x767E, 0xDBDD, 0x7684, 0xEEDC, 0x7686, 0xCBCB, 0x7687, 0xFCD5, + 0x768E, 0xCEEB, 0x7690, 0xCDC1, 0x7693, 0xFBD3, 0x76AE, 0xF9AB, 0x76BA, 0xF5D4, 0x76BF, 0xD9A9, 0x76C2, 0xE9DD, 0x76C3, 0xDBCD, + 0x76C6, 0xDDCE, 0x76C8, 0xE7C3, 0x76CA, 0xECCC, 0x76D2, 0xF9EC, 0x76D6, 0xCBCC, 0x76DB, 0xE0FC, 0x76DC, 0xD4A8, 0x76DE, 0xEDD3, + 0x76DF, 0xD8EF, 0x76E1, 0xF2D7, 0x76E3, 0xCAF8, 0x76E4, 0xDAEF, 0x76E7, 0xD6D4, 0x76EE, 0xD9CD, 0x76F2, 0xD8EE, 0x76F4, 0xF2C1, + 0x76F8, 0xDFD3, 0x76FC, 0xDAF0, 0x76FE, 0xE2EA, 0x7701, 0xE0FD, 0x7704, 0xD8F8, 0x7708, 0xF7AF, 0x7709, 0xDAB6, 0x770B, 0xCAD7, + 0x771E, 0xF2D8, 0x7720, 0xD8F9, 0x7729, 0xFADF, 0x7737, 0xCFEF, 0x7738, 0xD9C2, 0x773A, 0xF0D2, 0x773C, 0xE4D1, 0x7740, 0xF3B7, + 0x774D, 0xFAE0, 0x775B, 0xEFEC, 0x7761, 0xE2B2, 0x7763, 0xD4BD, 0x7766, 0xD9CE, 0x776B, 0xF4E2, 0x7779, 0xD4A9, 0x777E, 0xCDC2, + 0x777F, 0xE7DA, 0x778B, 0xF2D9, 0x7791, 0xD9AA, 0x779E, 0xD8BE, 0x77A5, 0xDCAD, 0x77AC, 0xE2EB, 0x77AD, 0xD6FC, 0x77B0, 0xCAF9, + 0x77B3, 0xD4DA, 0x77BB, 0xF4D7, 0x77BC, 0xCCA1, 0x77BF, 0xCFBA, 0x77D7, 0xF5B8, 0x77DB, 0xD9C3, 0x77DC, 0xD0E8, 0x77E2, 0xE3C5, + 0x77E3, 0xEBF8, 0x77E5, 0xF2B1, 0x77E9, 0xCFBB, 0x77ED, 0xD3AD, 0x77EE, 0xE8E1, 0x77EF, 0xCEEC, 0x77F3, 0xE0B4, 0x7802, 0xDEE3, + 0x7812, 0xDDF7, 0x7825, 0xF2B2, 0x7826, 0xF3F6, 0x7827, 0xF6DB, 0x782C, 0xD7FE, 0x7832, 0xF8DF, 0x7834, 0xF7F2, 0x7845, 0xD0A9, + 0x784F, 0xE6DA, 0x785D, 0xF5A6, 0x786B, 0xD7BC, 0x786C, 0xCCE3, 0x786F, 0xE6DB, 0x787C, 0xDDDD, 0x7881, 0xD1B3, 0x7887, 0xEFED, + 0x788C, 0xD6DE, 0x788D, 0xE4F4, 0x788E, 0xE1EF, 0x7891, 0xDDF8, 0x7897, 0xE8CF, 0x78A3, 0xCAE5, 0x78A7, 0xDCA1, 0x78A9, 0xE0B5, + 0x78BA, 0xFCAC, 0x78BB, 0xFCAD, 0x78BC, 0xD8A7, 0x78C1, 0xEDB8, 0x78C5, 0xDBB6, 0x78CA, 0xD6F0, 0x78CB, 0xF3AF, 0x78CE, 0xCDA5, + 0x78D0, 0xDAF1, 0x78E8, 0xD8A8, 0x78EC, 0xCCE4, 0x78EF, 0xD1B4, 0x78F5, 0xCAD8, 0x78FB, 0xDAF2, 0x7901, 0xF5A7, 0x790E, 0xF5A8, + 0x7916, 0xE6A6, 0x792A, 0xD5EC, 0x792B, 0xD5F8, 0x792C, 0xDAF3, 0x793A, 0xE3C6, 0x793E, 0xDEE4, 0x7940, 0xDEE5, 0x7941, 0xD1B5, + 0x7947, 0xD1B6, 0x7948, 0xD1B7, 0x7949, 0xF2B3, 0x7950, 0xE9DE, 0x7956, 0xF0D3, 0x7957, 0xF2B4, 0x795A, 0xF0D4, 0x795B, 0xCBE4, + 0x795C, 0xFBD4, 0x795D, 0xF5E6, 0x795E, 0xE3EA, 0x7960, 0xDEE6, 0x7965, 0xDFD4, 0x7968, 0xF8F9, 0x796D, 0xF0AE, 0x797A, 0xD1B8, + 0x797F, 0xD6DF, 0x7981, 0xD0D7, 0x798D, 0xFCA1, 0x798E, 0xEFEE, 0x798F, 0xDCD8, 0x7991, 0xE9DF, 0x79A6, 0xE5DD, 0x79A7, 0xFDFB, + 0x79AA, 0xE0C9, 0x79AE, 0xD6C9, 0x79B1, 0xD4AA, 0x79B3, 0xE5CC, 0x79B9, 0xE9E0, 0x79BD, 0xD0D8, 0x79BE, 0xFCA2, 0x79BF, 0xD4BE, + 0x79C0, 0xE2B3, 0x79C1, 0xDEE7, 0x79C9, 0xDCBC, 0x79CA, 0xD2B6, 0x79CB, 0xF5D5, 0x79D1, 0xCEA1, 0x79D2, 0xF5A9, 0x79D5, 0xDDF9, + 0x79D8, 0xDDFA, 0x79DF, 0xF0D5, 0x79E4, 0xF6DF, 0x79E6, 0xF2DA, 0x79E7, 0xE4EB, 0x79E9, 0xF2F1, 0x79FB, 0xECB9, 0x7A00, 0xFDFC, + 0x7A05, 0xE1AA, 0x7A08, 0xCAD9, 0x7A0B, 0xEFEF, 0x7A0D, 0xF5AA, 0x7A14, 0xECF9, 0x7A17, 0xF8AD, 0x7A19, 0xF2C2, 0x7A1A, 0xF6C3, + 0x7A1C, 0xD7D2, 0x7A1F, 0xF9A2, 0x7A20, 0xF0D6, 0x7A2E, 0xF0FA, 0x7A31, 0xF6E0, 0x7A36, 0xE9F3, 0x7A37, 0xF2C3, 0x7A3B, 0xD4AB, + 0x7A3C, 0xCAB3, 0x7A3D, 0xCDA6, 0x7A3F, 0xCDC3, 0x7A40, 0xCDDA, 0x7A46, 0xD9CF, 0x7A49, 0xF6C4, 0x7A4D, 0xEEDD, 0x7A4E, 0xE7C4, + 0x7A57, 0xE2B4, 0x7A61, 0xDFE2, 0x7A62, 0xE7DB, 0x7A69, 0xE8B1, 0x7A6B, 0xFCAE, 0x7A70, 0xE5CD, 0x7A74, 0xFAEB, 0x7A76, 0xCFBC, + 0x7A79, 0xCFE2, 0x7A7A, 0xCDF6, 0x7A7D, 0xEFF0, 0x7A7F, 0xF4BE, 0x7A81, 0xD4CD, 0x7A84, 0xF3B8, 0x7A88, 0xE9A1, 0x7A92, 0xF2F2, + 0x7A93, 0xF3EB, 0x7A95, 0xF0D7, 0x7A98, 0xCFD7, 0x7A9F, 0xCFDF, 0x7AA9, 0xE8C0, 0x7AAA, 0xE8C1, 0x7AAE, 0xCFE3, 0x7AAF, 0xE9A2, + 0x7ABA, 0xD0AA, 0x7AC4, 0xF3C1, 0x7AC5, 0xD0AB, 0x7AC7, 0xD4E4, 0x7ACA, 0xEFBC, 0x7ACB, 0xD8A1, 0x7AD7, 0xD9DF, 0x7AD9, 0xF3D7, + 0x7ADD, 0xDCBD, 0x7ADF, 0xCCE5, 0x7AE0, 0xEDF1, 0x7AE3, 0xF1E2, 0x7AE5, 0xD4DB, 0x7AEA, 0xE2B5, 0x7AED, 0xCAE6, 0x7AEF, 0xD3AE, + 0x7AF6, 0xCCE6, 0x7AF9, 0xF1D3, 0x7AFA, 0xF5E7, 0x7AFF, 0xCADA, 0x7B0F, 0xFBEE, 0x7B11, 0xE1C5, 0x7B19, 0xDFE9, 0x7B1B, 0xEEDE, + 0x7B1E, 0xF7C2, 0x7B20, 0xD8A2, 0x7B26, 0xDDAC, 0x7B2C, 0xF0AF, 0x7B2D, 0xD6BD, 0x7B39, 0xE1AB, 0x7B46, 0xF9B6, 0x7B49, 0xD4F5, + 0x7B4B, 0xD0C9, 0x7B4C, 0xEFA7, 0x7B4D, 0xE2EC, 0x7B4F, 0xDBEA, 0x7B50, 0xCECC, 0x7B51, 0xF5E8, 0x7B52, 0xF7D5, 0x7B54, 0xD3CD, + 0x7B56, 0xF3FE, 0x7B60, 0xD0B5, 0x7B6C, 0xE0FE, 0x7B6E, 0xDFFB, 0x7B75, 0xE6DD, 0x7B7D, 0xE8A4, 0x7B87, 0xCBCD, 0x7B8B, 0xEFA8, + 0x7B8F, 0xEEB4, 0x7B94, 0xDAD8, 0x7B95, 0xD1B9, 0x7B97, 0xDFA9, 0x7B9A, 0xF3B0, 0x7B9D, 0xCCC4, 0x7BA1, 0xCEB7, 0x7BAD, 0xEFA9, + 0x7BB1, 0xDFD5, 0x7BB4, 0xEDD7, 0x7BB8, 0xEEC6, 0x7BC0, 0xEFBD, 0x7BC1, 0xFCD6, 0x7BC4, 0xDBF4, 0x7BC6, 0xEFAA, 0x7BC7, 0xF8B9, + 0x7BC9, 0xF5E9, 0x7BD2, 0xE3D9, 0x7BE0, 0xE1C6, 0x7BE4, 0xD4BF, 0x7BE9, 0xDEE8, 0x7C07, 0xF0EA, 0x7C12, 0xF3C2, 0x7C1E, 0xD3AF, + 0x7C21, 0xCADB, 0x7C27, 0xFCD7, 0x7C2A, 0xEDD8, 0x7C2B, 0xE1C7, 0x7C3D, 0xF4D8, 0x7C3E, 0xD6B3, 0x7C3F, 0xDDAD, 0x7C43, 0xD5BE, + 0x7C4C, 0xF1C3, 0x7C4D, 0xEEDF, 0x7C60, 0xD6EB, 0x7C64, 0xF4D9, 0x7C6C, 0xD7E6, 0x7C73, 0xDAB7, 0x7C83, 0xDDFB, 0x7C89, 0xDDCF, + 0x7C92, 0xD8A3, 0x7C95, 0xDAD9, 0x7C97, 0xF0D8, 0x7C98, 0xEFC4, 0x7C9F, 0xE1D8, 0x7CA5, 0xF1D4, 0x7CA7, 0xEDF2, 0x7CAE, 0xD5DB, + 0x7CB1, 0xD5DC, 0x7CB2, 0xF3C4, 0x7CB3, 0xCBD7, 0x7CB9, 0xE2B6, 0x7CBE, 0xEFF1, 0x7CCA, 0xFBD5, 0x7CD6, 0xD3D8, 0x7CDE, 0xDDD0, + 0x7CDF, 0xF0D9, 0x7CE0, 0xCBB3, 0x7CE7, 0xD5DD, 0x7CFB, 0xCDA7, 0x7CFE, 0xD0AC, 0x7D00, 0xD1BA, 0x7D02, 0xF1C4, 0x7D04, 0xE5B3, + 0x7D05, 0xFBF5, 0x7D06, 0xE9E1, 0x7D07, 0xFDE0, 0x7D08, 0xFCBC, 0x7D0A, 0xDAA2, 0x7D0B, 0xDAA3, 0x7D0D, 0xD2A1, 0x7D10, 0xD2EF, + 0x7D14, 0xE2ED, 0x7D17, 0xDEE9, 0x7D18, 0xCEDC, 0x7D19, 0xF2B5, 0x7D1A, 0xD0E4, 0x7D1B, 0xDDD1, 0x7D20, 0xE1C8, 0x7D21, 0xDBB7, + 0x7D22, 0xDFE3, 0x7D2B, 0xEDB9, 0x7D2C, 0xF1C5, 0x7D2E, 0xF3CF, 0x7D2F, 0xD7AB, 0x7D30, 0xE1AC, 0x7D33, 0xE3EB, 0x7D35, 0xEEC7, + 0x7D39, 0xE1C9, 0x7D3A, 0xCAFA, 0x7D42, 0xF0FB, 0x7D43, 0xFAE1, 0x7D44, 0xF0DA, 0x7D45, 0xCCE7, 0x7D46, 0xDAF4, 0x7D50, 0xCCBF, + 0x7D5E, 0xCEED, 0x7D61, 0xD5A9, 0x7D62, 0xFAE2, 0x7D66, 0xD0E5, 0x7D68, 0xEBD6, 0x7D6A, 0xECDF, 0x7D6E, 0xDFFC, 0x7D71, 0xF7D6, + 0x7D72, 0xDEEA, 0x7D73, 0xCBB4, 0x7D76, 0xEFBE, 0x7D79, 0xCCB5, 0x7D7F, 0xCFBD, 0x7D8E, 0xEFF2, 0x7D8F, 0xE2B7, 0x7D93, 0xCCE8, + 0x7D9C, 0xF0FC, 0x7DA0, 0xD6E0, 0x7DA2, 0xF1C6, 0x7DAC, 0xE2B8, 0x7DAD, 0xEBAB, 0x7DB1, 0xCBB5, 0x7DB2, 0xD8D1, 0x7DB4, 0xF4CE, + 0x7DB5, 0xF3F7, 0x7DB8, 0xD7C6, 0x7DBA, 0xD1BB, 0x7DBB, 0xF7AA, 0x7DBD, 0xEDCA, 0x7DBE, 0xD7D3, 0x7DBF, 0xD8FA, 0x7DC7, 0xF6C5, + 0x7DCA, 0xD1CC, 0x7DCB, 0xDDFC, 0x7DD6, 0xDFFD, 0x7DD8, 0xF9E5, 0x7DDA, 0xE0CA, 0x7DDD, 0xF2FD, 0x7DDE, 0xD3B0, 0x7DE0, 0xF4F3, + 0x7DE1, 0xDAC9, 0x7DE3, 0xE6DE, 0x7DE8, 0xF8BA, 0x7DE9, 0xE8D0, 0x7DEC, 0xD8FB, 0x7DEF, 0xEAD5, 0x7DF4, 0xD6A3, 0x7DFB, 0xF6C6, + 0x7E09, 0xF2DB, 0x7E0A, 0xE4FC, 0x7E15, 0xE8B2, 0x7E1B, 0xDADA, 0x7E1D, 0xF2DC, 0x7E1E, 0xFBD6, 0x7E1F, 0xE9B2, 0x7E21, 0xEEAD, + 0x7E23, 0xFAE3, 0x7E2B, 0xDCEE, 0x7E2E, 0xF5EA, 0x7E2F, 0xE6E0, 0x7E31, 0xF0FD, 0x7E37, 0xD7AC, 0x7E3D, 0xF5C5, 0x7E3E, 0xEEE0, + 0x7E41, 0xDBE5, 0x7E43, 0xDDDE, 0x7E46, 0xD9F0, 0x7E47, 0xE9A3, 0x7E52, 0xF1F9, 0x7E54, 0xF2C4, 0x7E55, 0xE0CB, 0x7E5E, 0xE9A4, + 0x7E61, 0xE2B9, 0x7E69, 0xE3B1, 0x7E6A, 0xFCEB, 0x7E6B, 0xCDA8, 0x7E6D, 0xCCB6, 0x7E70, 0xF0DB, 0x7E79, 0xE6BA, 0x7E7C, 0xCDA9, + 0x7E82, 0xF3C3, 0x7E8C, 0xE1D9, 0x7E8F, 0xEFAB, 0x7E93, 0xE7C5, 0x7E96, 0xE0E9, 0x7E98, 0xF3C5, 0x7E9B, 0xD4C0, 0x7E9C, 0xD5BF, + 0x7F36, 0xDDAE, 0x7F38, 0xF9FC, 0x7F3A, 0xCCC0, 0x7F4C, 0xE5A2, 0x7F50, 0xCEB8, 0x7F54, 0xD8D2, 0x7F55, 0xF9D6, 0x7F6A, 0xF1AA, + 0x7F6B, 0xCED1, 0x7F6E, 0xF6C7, 0x7F70, 0xDBEB, 0x7F72, 0xDFFE, 0x7F75, 0xD8E1, 0x7F77, 0xF7F3, 0x7F79, 0xD7E7, 0x7F85, 0xD4FE, + 0x7F88, 0xD1BC, 0x7F8A, 0xE5CF, 0x7F8C, 0xCBB6, 0x7F8E, 0xDAB8, 0x7F94, 0xCDC4, 0x7F9A, 0xD6BE, 0x7F9E, 0xE2BA, 0x7FA4, 0xCFD8, + 0x7FA8, 0xE0CC, 0x7FA9, 0xEBF9, 0x7FB2, 0xFDFD, 0x7FB8, 0xD7E8, 0x7FB9, 0xCBD8, 0x7FBD, 0xE9E2, 0x7FC1, 0xE8BA, 0x7FC5, 0xE3C7, + 0x7FCA, 0xECCD, 0x7FCC, 0xECCE, 0x7FCE, 0xD6BF, 0x7FD2, 0xE3A7, 0x7FD4, 0xDFD6, 0x7FD5, 0xFDE8, 0x7FDF, 0xEEE1, 0x7FE0, 0xF6A8, + 0x7FE1, 0xDDFD, 0x7FE9, 0xF8BB, 0x7FEB, 0xE8D1, 0x7FF0, 0xF9D7, 0x7FF9, 0xCEEE, 0x7FFC, 0xECCF, 0x8000, 0xE9A5, 0x8001, 0xD6D5, + 0x8003, 0xCDC5, 0x8005, 0xEDBA, 0x8006, 0xD1BD, 0x8009, 0xCFBE, 0x800C, 0xECBB, 0x8010, 0xD2B1, 0x8015, 0xCCE9, 0x8017, 0xD9C4, + 0x8018, 0xE9FC, 0x802D, 0xD1BE, 0x8033, 0xECBC, 0x8036, 0xE5AD, 0x803D, 0xF7B0, 0x803F, 0xCCEA, 0x8043, 0xD3C4, 0x8046, 0xD6C0, + 0x804A, 0xD6FD, 0x8056, 0xE1A1, 0x8058, 0xDEBD, 0x805A, 0xF6A9, 0x805E, 0xDAA4, 0x806F, 0xD6A4, 0x8070, 0xF5C6, 0x8072, 0xE1A2, + 0x8073, 0xE9C6, 0x8077, 0xF2C5, 0x807D, 0xF4E9, 0x807E, 0xD6EC, 0x807F, 0xEBD3, 0x8084, 0xECBD, 0x8085, 0xE2DC, 0x8086, 0xDEEB, + 0x8087, 0xF0DC, 0x8089, 0xEBBF, 0x808B, 0xD7CE, 0x808C, 0xD1BF, 0x8096, 0xF5AB, 0x809B, 0xF9FD, 0x809D, 0xCADC, 0x80A1, 0xCDC6, + 0x80A2, 0xF2B6, 0x80A5, 0xDDFE, 0x80A9, 0xCCB7, 0x80AA, 0xDBB8, 0x80AF, 0xD0E9, 0x80B1, 0xCEDD, 0x80B2, 0xEBC0, 0x80B4, 0xFDA2, + 0x80BA, 0xF8CB, 0x80C3, 0xEAD6, 0x80C4, 0xF1B0, 0x80CC, 0xDBCE, 0x80CE, 0xF7C3, 0x80DA, 0xDBCF, 0x80DB, 0xCBA4, 0x80DE, 0xF8E0, + 0x80E1, 0xFBD7, 0x80E4, 0xEBCA, 0x80E5, 0xE0A1, 0x80F1, 0xCECD, 0x80F4, 0xD4DC, 0x80F8, 0xFDD8, 0x80FD, 0xD2F6, 0x8102, 0xF2B7, + 0x8105, 0xFAF6, 0x8106, 0xF6AA, 0x8107, 0xFAF7, 0x8108, 0xD8E6, 0x810A, 0xF4B1, 0x8118, 0xE8D2, 0x811A, 0xCAC5, 0x811B, 0xCCEB, + 0x8123, 0xE2EE, 0x8129, 0xE2BB, 0x812B, 0xF7AD, 0x812F, 0xF8E1, 0x8139, 0xF3EC, 0x813E, 0xDEA1, 0x814B, 0xE4FD, 0x814E, 0xE3EC, + 0x8150, 0xDDAF, 0x8151, 0xDDB0, 0x8154, 0xCBB7, 0x8155, 0xE8D3, 0x8165, 0xE1A3, 0x8166, 0xD2E0, 0x816B, 0xF0FE, 0x8170, 0xE9A6, + 0x8171, 0xCBF2, 0x8178, 0xEDF3, 0x8179, 0xDCD9, 0x817A, 0xE0CD, 0x817F, 0xF7DA, 0x8180, 0xDBB9, 0x8188, 0xCCAE, 0x818A, 0xDADB, + 0x818F, 0xCDC7, 0x819A, 0xDDB1, 0x819C, 0xD8AF, 0x819D, 0xE3A3, 0x81A0, 0xCEEF, 0x81A3, 0xF2F3, 0x81A8, 0xF8B3, 0x81B3, 0xE0CE, + 0x81B5, 0xF5FD, 0x81BA, 0xEBEC, 0x81BD, 0xD3C5, 0x81BE, 0xFCEC, 0x81BF, 0xD2DB, 0x81C0, 0xD4EB, 0x81C2, 0xDEA2, 0x81C6, 0xE5E6, + 0x81CD, 0xF0B0, 0x81D8, 0xD5C4, 0x81DF, 0xEDF4, 0x81E3, 0xE3ED, 0x81E5, 0xE8C2, 0x81E7, 0xEDF5, 0x81E8, 0xD7FC, 0x81EA, 0xEDBB, + 0x81ED, 0xF6AB, 0x81F3, 0xF2B8, 0x81F4, 0xF6C8, 0x81FA, 0xD3E6, 0x81FB, 0xF2DD, 0x81FC, 0xCFBF, 0x81FE, 0xEBAC, 0x8205, 0xCFC0, + 0x8207, 0xE6A8, 0x8208, 0xFDE9, 0x820A, 0xCFC1, 0x820C, 0xE0DF, 0x820D, 0xDEEC, 0x8212, 0xE0A2, 0x821B, 0xF4BF, 0x821C, 0xE2EF, + 0x821E, 0xD9F1, 0x821F, 0xF1C7, 0x8221, 0xCBB8, 0x822A, 0xF9FE, 0x822B, 0xDBBA, 0x822C, 0xDAF5, 0x8235, 0xF6EC, 0x8236, 0xDADC, + 0x8237, 0xFAE4, 0x8239, 0xE0CF, 0x8240, 0xDDB2, 0x8245, 0xE6A9, 0x8247, 0xEFF3, 0x8259, 0xF3ED, 0x8264, 0xEBFA, 0x8266, 0xF9E6, + 0x826E, 0xCADD, 0x826F, 0xD5DE, 0x8271, 0xCADE, 0x8272, 0xDFE4, 0x8276, 0xE6FD, 0x8278, 0xF5AC, 0x827E, 0xE4F5, 0x828B, 0xE9E3, + 0x828D, 0xEDCB, 0x828E, 0xCFE4, 0x8292, 0xD8D3, 0x8299, 0xDDB3, 0x829A, 0xD4EC, 0x829D, 0xF2B9, 0x829F, 0xDFB7, 0x82A5, 0xCBCE, + 0x82A6, 0xFBD8, 0x82A9, 0xD0D9, 0x82AC, 0xDDD2, 0x82AD, 0xF7F4, 0x82AE, 0xE7DC, 0x82AF, 0xE4A5, 0x82B1, 0xFCA3, 0x82B3, 0xDBBB, + 0x82B7, 0xF2BA, 0x82B8, 0xE9FD, 0x82B9, 0xD0CA, 0x82BB, 0xF5D6, 0x82BC, 0xD9C5, 0x82BD, 0xE4B4, 0x82BF, 0xEDA7, 0x82D1, 0xEABD, + 0x82D2, 0xE6FE, 0x82D4, 0xF7C4, 0x82D5, 0xF5AD, 0x82D7, 0xD9E0, 0x82DB, 0xCAB4, 0x82DE, 0xF8E2, 0x82DF, 0xCFC2, 0x82E1, 0xECBE, + 0x82E5, 0xE5B4, 0x82E6, 0xCDC8, 0x82E7, 0xEEC8, 0x82F1, 0xE7C8, 0x82FD, 0xCDC9, 0x82FE, 0xF9B7, 0x8301, 0xF1E8, 0x8302, 0xD9F2, + 0x8303, 0xDBF5, 0x8304, 0xCAB5, 0x8305, 0xD9C6, 0x8309, 0xD8C9, 0x8317, 0xD9AB, 0x8328, 0xEDBC, 0x832B, 0xD8D4, 0x832F, 0xDCDA, + 0x8331, 0xE2BC, 0x8334, 0xFCED, 0x8335, 0xECE0, 0x8336, 0xD2FE, 0x8338, 0xE9C7, 0x8339, 0xE6AA, 0x8340, 0xE2F0, 0x8347, 0xFABB, + 0x8349, 0xF5AE, 0x834A, 0xFBAA, 0x834F, 0xECFB, 0x8351, 0xECBF, 0x8352, 0xFCD8, 0x8373, 0xD4E5, 0x8377, 0xF9C3, 0x837B, 0xEEE2, + 0x8389, 0xD7E9, 0x838A, 0xEDF6, 0x838E, 0xDEED, 0x8396, 0xCCEC, 0x8398, 0xE3EE, 0x839E, 0xE8D4, 0x83A2, 0xFAF8, 0x83A9, 0xDDB4, + 0x83AA, 0xE4B5, 0x83AB, 0xD8B0, 0x83BD, 0xD8D5, 0x83C1, 0xF4EA, 0x83C5, 0xCEB9, 0x83C9, 0xD6E1, 0x83CA, 0xCFD2, 0x83CC, 0xD0B6, + 0x83D3, 0xCEA2, 0x83D6, 0xF3EE, 0x83DC, 0xF3F8, 0x83E9, 0xDCCC, 0x83EB, 0xD0CB, 0x83EF, 0xFCA4, 0x83F0, 0xCDCA, 0x83F1, 0xD7D4, + 0x83F2, 0xDEA3, 0x83F4, 0xE4E0, 0x83F9, 0xEEC9, 0x83FD, 0xE2DD, 0x8403, 0xF5FE, 0x8404, 0xD4AC, 0x840A, 0xD5D1, 0x840C, 0xD8F0, + 0x840D, 0xF8C3, 0x840E, 0xEAD7, 0x8429, 0xF5D7, 0x842C, 0xD8BF, 0x8431, 0xFDC0, 0x8438, 0xEBAD, 0x843D, 0xD5AA, 0x8449, 0xE7A8, + 0x8457, 0xEECA, 0x845B, 0xCAE7, 0x8461, 0xF8E3, 0x8463, 0xD4DD, 0x8466, 0xEAD8, 0x846B, 0xFBD9, 0x846C, 0xEDF7, 0x846F, 0xE5B5, + 0x8475, 0xD0AD, 0x847A, 0xF1F1, 0x8490, 0xE2BD, 0x8494, 0xE3C8, 0x8499, 0xD9D5, 0x849C, 0xDFAA, 0x84A1, 0xDBBC, 0x84B2, 0xF8E4, + 0x84B8, 0xF1FA, 0x84BB, 0xE5B6, 0x84BC, 0xF3EF, 0x84BF, 0xFBDA, 0x84C0, 0xE1E0, 0x84C2, 0xD9AC, 0x84C4, 0xF5EB, 0x84C6, 0xE0B6, + 0x84C9, 0xE9C8, 0x84CB, 0xCBCF, 0x84CD, 0xE3C9, 0x84D1, 0xDEEE, 0x84DA, 0xE2BE, 0x84EC, 0xDCEF, 0x84EE, 0xD6A5, 0x84F4, 0xE2F1, + 0x84FC, 0xD6FE, 0x8511, 0xD9A1, 0x8513, 0xD8C0, 0x8514, 0xDCDB, 0x8517, 0xEDBD, 0x8518, 0xDFB8, 0x851A, 0xEAA5, 0x851E, 0xD7AD, + 0x8521, 0xF3F9, 0x8523, 0xEDF8, 0x8525, 0xF5C7, 0x852C, 0xE1CA, 0x852D, 0xEBE3, 0x852F, 0xF2DE, 0x853D, 0xF8CC, 0x853F, 0xEAD9, + 0x8541, 0xD3C6, 0x8543, 0xDBE6, 0x8549, 0xF5AF, 0x854E, 0xCEF0, 0x8553, 0xE9FE, 0x8559, 0xFBB6, 0x8563, 0xE2F2, 0x8568, 0xCFF2, + 0x8569, 0xF7B9, 0x856A, 0xD9F3, 0x856D, 0xE1CB, 0x8584, 0xDADD, 0x8587, 0xDAB9, 0x858F, 0xEBFB, 0x8591, 0xCBB9, 0x8594, 0xEDF9, + 0x859B, 0xE0E0, 0x85A6, 0xF4C0, 0x85A8, 0xFDBC, 0x85A9, 0xDFB1, 0x85AA, 0xE3EF, 0x85AF, 0xE0A3, 0x85B0, 0xFDB9, 0x85BA, 0xF0B1, + 0x85C1, 0xCDCB, 0x85C9, 0xEDBE, 0x85CD, 0xD5C0, 0x85CE, 0xE3F0, 0x85CF, 0xEDFA, 0x85D5, 0xE9E4, 0x85DC, 0xD5ED, 0x85DD, 0xE7DD, + 0x85E4, 0xD4F6, 0x85E5, 0xE5B7, 0x85E9, 0xDBE7, 0x85EA, 0xE2BF, 0x85F7, 0xEECB, 0x85FA, 0xD7F4, 0x85FB, 0xF0DD, 0x85FF, 0xCEAB, + 0x8602, 0xE7DE, 0x8606, 0xD6D6, 0x8607, 0xE1CC, 0x860A, 0xE8B3, 0x8616, 0xE5EE, 0x8617, 0xDCA2, 0x861A, 0xE0D0, 0x862D, 0xD5B5, + 0x863F, 0xD5A1, 0x864E, 0xFBDB, 0x8650, 0xF9CB, 0x8654, 0xCBF3, 0x8655, 0xF4A5, 0x865B, 0xFAC8, 0x865C, 0xD6D7, 0x865E, 0xE9E5, + 0x865F, 0xFBDC, 0x8667, 0xFDD0, 0x8679, 0xFBF6, 0x868A, 0xDAA5, 0x868C, 0xDBBD, 0x8693, 0xECE2, 0x86A3, 0xCDF7, 0x86A4, 0xF0DE, + 0x86A9, 0xF6C9, 0x86C7, 0xDEEF, 0x86CB, 0xD3B1, 0x86D4, 0xFCEE, 0x86D9, 0xE8C3, 0x86DB, 0xF1C8, 0x86DF, 0xCEF1, 0x86E4, 0xF9ED, + 0x86ED, 0xF2F4, 0x86FE, 0xE4B6, 0x8700, 0xF5B9, 0x8702, 0xDCF0, 0x8703, 0xE3F1, 0x8708, 0xE8A5, 0x8718, 0xF2BB, 0x871A, 0xDEA4, + 0x871C, 0xDACC, 0x874E, 0xCAE9, 0x8755, 0xE3DA, 0x8757, 0xFCD9, 0x875F, 0xEADA, 0x8766, 0xF9C4, 0x8768, 0xE3A4, 0x8774, 0xFBDD, + 0x8776, 0xEFCA, 0x8778, 0xE8C4, 0x8782, 0xD5CC, 0x878D, 0xEBD7, 0x879F, 0xD9AD, 0x87A2, 0xFBAB, 0x87B3, 0xD3D9, 0x87BA, 0xD5A2, + 0x87C4, 0xF6DE, 0x87E0, 0xDAF6, 0x87EC, 0xE0D1, 0x87EF, 0xE9A8, 0x87F2, 0xF5F9, 0x87F9, 0xFAAF, 0x87FB, 0xEBFC, 0x87FE, 0xE0EA, + 0x8805, 0xE3B2, 0x881F, 0xD5C5, 0x8822, 0xF1E3, 0x8823, 0xD5EE, 0x8831, 0xCDCC, 0x8836, 0xEDD9, 0x883B, 0xD8C1, 0x8840, 0xFAEC, + 0x8846, 0xF1EB, 0x884C, 0xFABC, 0x884D, 0xE6E2, 0x8852, 0xFAE5, 0x8853, 0xE2FA, 0x8857, 0xCAB6, 0x8859, 0xE4B7, 0x885B, 0xEADB, + 0x885D, 0xF5FA, 0x8861, 0xFBAC, 0x8862, 0xCFC3, 0x8863, 0xEBFD, 0x8868, 0xF8FA, 0x886B, 0xDFB9, 0x8870, 0xE1F1, 0x8872, 0xD2A4, + 0x8877, 0xF5FB, 0x887E, 0xD0DA, 0x887F, 0xD0DB, 0x8881, 0xEABE, 0x8882, 0xD9B1, 0x8888, 0xCAB7, 0x888B, 0xD3E7, 0x888D, 0xF8E5, + 0x8892, 0xD3B2, 0x8896, 0xE2C0, 0x8897, 0xF2DF, 0x889E, 0xCDE5, 0x88AB, 0xF9AC, 0x88B4, 0xCDCD, 0x88C1, 0xEEAE, 0x88C2, 0xD6AE, + 0x88CF, 0xD7EA, 0x88D4, 0xE7E0, 0x88D5, 0xEBAE, 0x88D9, 0xCFD9, 0x88DC, 0xDCCD, 0x88DD, 0xEDFB, 0x88DF, 0xDEF0, 0x88E1, 0xD7EB, + 0x88E8, 0xDEA5, 0x88F3, 0xDFD7, 0x88F4, 0xDBD0, 0x88F5, 0xDBD1, 0x88F8, 0xD5A3, 0x88FD, 0xF0B2, 0x8907, 0xDCDC, 0x8910, 0xCAE8, + 0x8912, 0xF8E6, 0x8913, 0xDCCE, 0x8918, 0xEADC, 0x8919, 0xDBD2, 0x8925, 0xE9B3, 0x892A, 0xF7DB, 0x8936, 0xE3A8, 0x8938, 0xD7AE, + 0x893B, 0xE0E1, 0x8941, 0xCBBA, 0x8944, 0xE5D1, 0x895F, 0xD0DC, 0x8964, 0xD5C1, 0x896A, 0xD8CA, 0x8972, 0xE3A9, 0x897F, 0xE0A4, + 0x8981, 0xE9A9, 0x8983, 0xD3C7, 0x8986, 0xDCDD, 0x8987, 0xF8AE, 0x898B, 0xCCB8, 0x898F, 0xD0AE, 0x8993, 0xD8F2, 0x8996, 0xE3CA, + 0x89A1, 0xCCAF, 0x89A9, 0xD4AD, 0x89AA, 0xF6D1, 0x89B2, 0xD0CC, 0x89BA, 0xCAC6, 0x89BD, 0xD5C2, 0x89C0, 0xCEBA, 0x89D2, 0xCAC7, + 0x89E3, 0xFAB0, 0x89F4, 0xDFD8, 0x89F8, 0xF5BA, 0x8A00, 0xE5EB, 0x8A02, 0xEFF4, 0x8A03, 0xDDB5, 0x8A08, 0xCDAA, 0x8A0A, 0xE3F2, + 0x8A0C, 0xFBF7, 0x8A0E, 0xF7D0, 0x8A13, 0xFDBA, 0x8A16, 0xFDE1, 0x8A17, 0xF6FE, 0x8A18, 0xD1C0, 0x8A1B, 0xE8C5, 0x8A1D, 0xE4B8, + 0x8A1F, 0xE1E8, 0x8A23, 0xCCC1, 0x8A25, 0xD2ED, 0x8A2A, 0xDBBE, 0x8A2D, 0xE0E2, 0x8A31, 0xFAC9, 0x8A34, 0xE1CD, 0x8A36, 0xCAB8, + 0x8A3A, 0xF2E0, 0x8A3B, 0xF1C9, 0x8A50, 0xDEF1, 0x8A54, 0xF0DF, 0x8A55, 0xF8C4, 0x8A5B, 0xEECC, 0x8A5E, 0xDEF2, 0x8A60, 0xE7C9, + 0x8A62, 0xE2F3, 0x8A63, 0xE7E1, 0x8A66, 0xE3CB, 0x8A69, 0xE3CC, 0x8A6D, 0xCFF8, 0x8A6E, 0xEFAC, 0x8A70, 0xFDFE, 0x8A71, 0xFCA5, + 0x8A72, 0xFAB1, 0x8A73, 0xDFD9, 0x8A75, 0xE0D2, 0x8A79, 0xF4DA, 0x8A85, 0xF1CA, 0x8A87, 0xCEA3, 0x8A8C, 0xF2BC, 0x8A8D, 0xECE3, + 0x8A93, 0xE0A5, 0x8A95, 0xF7AB, 0x8A98, 0xEBAF, 0x8A9E, 0xE5DE, 0x8AA0, 0xE1A4, 0x8AA1, 0xCDAB, 0x8AA3, 0xD9F4, 0x8AA4, 0xE8A6, + 0x8AA5, 0xCDCE, 0x8AA6, 0xE1E9, 0x8AA8, 0xFCEF, 0x8AAA, 0xE0E3, 0x8AB0, 0xE2C1, 0x8AB2, 0xCEA4, 0x8AB9, 0xDEA6, 0x8ABC, 0xEBFE, + 0x8ABE, 0xEBDD, 0x8ABF, 0xF0E0, 0x8AC2, 0xF4DB, 0x8AC4, 0xE2F4, 0x8AC7, 0xD3C8, 0x8ACB, 0xF4EB, 0x8ACD, 0xEEB5, 0x8ACF, 0xF5D8, + 0x8AD2, 0xD5DF, 0x8AD6, 0xD6E5, 0x8ADB, 0xEBB0, 0x8ADC, 0xF4E3, 0x8AE1, 0xE3CD, 0x8AE6, 0xF4F4, 0x8AE7, 0xFAB2, 0x8AEA, 0xEFF5, + 0x8AEB, 0xCADF, 0x8AED, 0xEBB1, 0x8AEE, 0xEDBF, 0x8AF1, 0xFDC9, 0x8AF6, 0xE4A6, 0x8AF7, 0xF9A4, 0x8AF8, 0xF0B3, 0x8AFA, 0xE5EC, + 0x8AFE, 0xD1E7, 0x8B00, 0xD9C7, 0x8B01, 0xE4D7, 0x8B02, 0xEADD, 0x8B04, 0xD4F7, 0x8B0E, 0xDABA, 0x8B10, 0xDACD, 0x8B14, 0xF9CC, + 0x8B16, 0xE1DA, 0x8B17, 0xDBBF, 0x8B19, 0xCCC5, 0x8B1A, 0xECD0, 0x8B1B, 0xCBBB, 0x8B1D, 0xDEF3, 0x8B20, 0xE9AA, 0x8B28, 0xD9C8, + 0x8B2B, 0xEEE3, 0x8B2C, 0xD7BD, 0x8B33, 0xCFC4, 0x8B39, 0xD0CD, 0x8B41, 0xFCA6, 0x8B49, 0xF1FB, 0x8B4E, 0xFDD2, 0x8B4F, 0xD1C1, + 0x8B58, 0xE3DB, 0x8B5A, 0xD3C9, 0x8B5C, 0xDCCF, 0x8B66, 0xCCED, 0x8B6C, 0xDEA7, 0x8B6F, 0xE6BB, 0x8B70, 0xECA1, 0x8B74, 0xCCB9, + 0x8B77, 0xFBDE, 0x8B7D, 0xE7E2, 0x8B80, 0xD4C1, 0x8B8A, 0xDCA8, 0x8B90, 0xE2C2, 0x8B92, 0xF3D8, 0x8B93, 0xE5D3, 0x8B96, 0xF3D9, + 0x8B9A, 0xF3C6, 0x8C37, 0xCDDB, 0x8C3F, 0xCDAC, 0x8C41, 0xFCC3, 0x8C46, 0xD4E7, 0x8C48, 0xD1C2, 0x8C4A, 0xF9A5, 0x8C4C, 0xE8D5, + 0x8C55, 0xE3CE, 0x8C5A, 0xD4CA, 0x8C61, 0xDFDA, 0x8C6A, 0xFBDF, 0x8C6B, 0xE7E3, 0x8C79, 0xF8FB, 0x8C7A, 0xE3CF, 0x8C82, 0xF5B0, + 0x8C8A, 0xD8E7, 0x8C8C, 0xD9C9, 0x8C9D, 0xF8AF, 0x8C9E, 0xEFF6, 0x8CA0, 0xDDB6, 0x8CA1, 0xEEAF, 0x8CA2, 0xCDF8, 0x8CA7, 0xDEB8, + 0x8CA8, 0xFCA7, 0x8CA9, 0xF7FC, 0x8CAA, 0xF7B1, 0x8CAB, 0xCEBB, 0x8CAC, 0xF4A1, 0x8CAF, 0xEECD, 0x8CB0, 0xE1AE, 0x8CB3, 0xECC3, + 0x8CB4, 0xCFFE, 0x8CB6, 0xF8BF, 0x8CB7, 0xD8E2, 0x8CB8, 0xD3E8, 0x8CBB, 0xDEA8, 0x8CBC, 0xF4E4, 0x8CBD, 0xECC2, 0x8CBF, 0xD9F5, + 0x8CC0, 0xF9C5, 0x8CC1, 0xDDD3, 0x8CC2, 0xD6F1, 0x8CC3, 0xECFC, 0x8CC4, 0xFCF0, 0x8CC7, 0xEDC0, 0x8CC8, 0xCAB9, 0x8CCA, 0xEEE4, + 0x8CD1, 0xF2E1, 0x8CD3, 0xDEB9, 0x8CDA, 0xD6F2, 0x8CDC, 0xDEF4, 0x8CDE, 0xDFDB, 0x8CE0, 0xDBD3, 0x8CE2, 0xFAE7, 0x8CE3, 0xD8E3, + 0x8CE4, 0xF4C1, 0x8CE6, 0xDDB7, 0x8CEA, 0xF2F5, 0x8CED, 0xD4AE, 0x8CF4, 0xD6F3, 0x8CFB, 0xDDB8, 0x8CFC, 0xCFC5, 0x8CFD, 0xDFDF, + 0x8D04, 0xF2BE, 0x8D05, 0xF6A1, 0x8D07, 0xEBCB, 0x8D08, 0xF1FC, 0x8D0A, 0xF3C7, 0x8D0D, 0xE0EB, 0x8D13, 0xEDFC, 0x8D16, 0xE1DB, + 0x8D64, 0xEEE5, 0x8D66, 0xDEF5, 0x8D6B, 0xFAD3, 0x8D70, 0xF1CB, 0x8D73, 0xD0AF, 0x8D74, 0xDDB9, 0x8D77, 0xD1C3, 0x8D85, 0xF5B1, + 0x8D8A, 0xEAC6, 0x8D99, 0xF0E1, 0x8DA3, 0xF6AC, 0x8DA8, 0xF5D9, 0x8DB3, 0xF0EB, 0x8DBA, 0xDDBA, 0x8DBE, 0xF2BF, 0x8DC6, 0xF7C5, + 0x8DCB, 0xDBA2, 0x8DCC, 0xF2F6, 0x8DCF, 0xCABA, 0x8DDB, 0xF7F5, 0x8DDD, 0xCBE5, 0x8DE1, 0xEEE6, 0x8DE3, 0xE0D3, 0x8DE8, 0xCEA5, + 0x8DEF, 0xD6D8, 0x8DF3, 0xD4AF, 0x8E0A, 0xE9C9, 0x8E0F, 0xD3CE, 0x8E10, 0xF4C2, 0x8E1E, 0xCBE6, 0x8E2A, 0xF1A1, 0x8E30, 0xEBB2, + 0x8E35, 0xF1A2, 0x8E42, 0xEBB3, 0x8E44, 0xF0B4, 0x8E47, 0xCBF4, 0x8E48, 0xD4B0, 0x8E49, 0xF3B2, 0x8E4A, 0xFBB7, 0x8E59, 0xF5EC, + 0x8E5F, 0xEEE7, 0x8E60, 0xF4B2, 0x8E74, 0xF5ED, 0x8E76, 0xCFF3, 0x8E81, 0xF0E2, 0x8E87, 0xEECE, 0x8E8A, 0xF1CC, 0x8E8D, 0xE5B8, + 0x8EAA, 0xD7F5, 0x8EAB, 0xE3F3, 0x8EAC, 0xCFE5, 0x8EC0, 0xCFC6, 0x8ECA, 0xF3B3, 0x8ECB, 0xE4D8, 0x8ECC, 0xCFF9, 0x8ECD, 0xCFDA, + 0x8ED2, 0xFACD, 0x8EDF, 0xE6E3, 0x8EEB, 0xF2E2, 0x8EF8, 0xF5EE, 0x8EFB, 0xCABB, 0x8EFE, 0xE3DC, 0x8F03, 0xCEF2, 0x8F05, 0xD6D9, + 0x8F09, 0xEEB0, 0x8F12, 0xF4E5, 0x8F13, 0xD8C2, 0x8F14, 0xDCD0, 0x8F15, 0xCCEE, 0x8F1B, 0xD5E0, 0x8F1C, 0xF6CA, 0x8F1D, 0xFDCA, + 0x8F1E, 0xD8D6, 0x8F1F, 0xF4CF, 0x8F26, 0xD6A6, 0x8F27, 0xDCBE, 0x8F29, 0xDBD4, 0x8F2A, 0xD7C7, 0x8F2F, 0xF2FE, 0x8F33, 0xF1CD, + 0x8F38, 0xE2C3, 0x8F39, 0xDCDE, 0x8F3B, 0xDCDF, 0x8F3E, 0xEFAD, 0x8F3F, 0xE6AB, 0x8F44, 0xF9DD, 0x8F45, 0xEABF, 0x8F49, 0xEFAE, + 0x8F4D, 0xF4D0, 0x8F4E, 0xCEF3, 0x8F5D, 0xE6AC, 0x8F5F, 0xCEDE, 0x8F62, 0xD5F9, 0x8F9B, 0xE3F4, 0x8F9C, 0xCDD0, 0x8FA3, 0xD5B8, + 0x8FA6, 0xF7FD, 0x8FA8, 0xDCA9, 0x8FAD, 0xDEF6, 0x8FAF, 0xDCAA, 0x8FB0, 0xF2E3, 0x8FB1, 0xE9B4, 0x8FB2, 0xD2DC, 0x8FC2, 0xE9E6, + 0x8FC5, 0xE3F6, 0x8FCE, 0xE7CA, 0x8FD1, 0xD0CE, 0x8FD4, 0xDAF7, 0x8FE6, 0xCABC, 0x8FEA, 0xEEE8, 0x8FEB, 0xDADE, 0x8FED, 0xF2F7, + 0x8FF0, 0xE2FB, 0x8FF2, 0xCCA6, 0x8FF7, 0xDABB, 0x8FF9, 0xEEE9, 0x8FFD, 0xF5DA, 0x9000, 0xF7DC, 0x9001, 0xE1EA, 0x9002, 0xCEC1, + 0x9003, 0xD4B1, 0x9005, 0xFDB1, 0x9006, 0xE6BD, 0x9008, 0xFBAD, 0x900B, 0xF8E7, 0x900D, 0xE1CE, 0x900F, 0xF7E2, 0x9010, 0xF5EF, + 0x9011, 0xCFC7, 0x9014, 0xD4B2, 0x9015, 0xCCEF, 0x9017, 0xD4E8, 0x9019, 0xEECF, 0x901A, 0xF7D7, 0x901D, 0xE0A6, 0x901E, 0xD6C1, + 0x901F, 0xE1DC, 0x9020, 0xF0E3, 0x9021, 0xF1E4, 0x9022, 0xDCF1, 0x9023, 0xD6A7, 0x902E, 0xF4F5, 0x9031, 0xF1CE, 0x9032, 0xF2E4, + 0x9035, 0xD0B0, 0x9038, 0xECEF, 0x903C, 0xF9BA, 0x903E, 0xEBB5, 0x9041, 0xD4ED, 0x9042, 0xE2C4, 0x9047, 0xE9E7, 0x904A, 0xEBB4, + 0x904B, 0xEAA1, 0x904D, 0xF8BC, 0x904E, 0xCEA6, 0x9050, 0xF9C6, 0x9051, 0xFCDA, 0x9053, 0xD4B3, 0x9054, 0xD3B9, 0x9055, 0xEADE, + 0x9059, 0xE9AB, 0x905C, 0xE1E1, 0x905D, 0xD3CF, 0x905E, 0xF4F6, 0x9060, 0xEAC0, 0x9061, 0xE1CF, 0x9063, 0xCCBA, 0x9069, 0xEEEA, + 0x906D, 0xF0E4, 0x906E, 0xF3B4, 0x906F, 0xD4EE, 0x9072, 0xF2C0, 0x9075, 0xF1E5, 0x9077, 0xF4C3, 0x9078, 0xE0D4, 0x907A, 0xEBB6, + 0x907C, 0xD7A1, 0x907D, 0xCBE8, 0x907F, 0xF9AD, 0x9080, 0xE9AD, 0x9081, 0xD8E4, 0x9082, 0xFAB3, 0x9083, 0xE2C5, 0x9084, 0xFCBD, + 0x9087, 0xECC4, 0x9088, 0xD8B1, 0x908A, 0xDCAB, 0x908F, 0xD5A4, 0x9091, 0xEBE9, 0x9095, 0xE8BB, 0x9099, 0xD8D7, 0x90A2, 0xFBAE, + 0x90A3, 0xD1E1, 0x90A6, 0xDBC0, 0x90A8, 0xF5BE, 0x90AA, 0xDEF7, 0x90AF, 0xCAFB, 0x90B0, 0xF7C6, 0x90B1, 0xCFC8, 0x90B5, 0xE1D0, + 0x90B8, 0xEED0, 0x90C1, 0xE9F4, 0x90CA, 0xCEF4, 0x90DE, 0xD5CD, 0x90E1, 0xCFDB, 0x90E8, 0xDDBB, 0x90ED, 0xCEAC, 0x90F5, 0xE9E8, + 0x90FD, 0xD4B4, 0x9102, 0xE4C7, 0x9112, 0xF5DB, 0x9115, 0xFAC1, 0x9119, 0xDEA9, 0x9127, 0xD4F8, 0x912D, 0xEFF7, 0x9132, 0xD3B3, + 0x9149, 0xEBB7, 0x914A, 0xEFF8, 0x914B, 0xF5DC, 0x914C, 0xEDCC, 0x914D, 0xDBD5, 0x914E, 0xF1CF, 0x9152, 0xF1D0, 0x9162, 0xF5B2, + 0x9169, 0xD9AE, 0x916A, 0xD5AC, 0x916C, 0xE2C6, 0x9175, 0xFDA3, 0x9177, 0xFBE5, 0x9178, 0xDFAB, 0x9187, 0xE2F5, 0x9189, 0xF6AD, + 0x918B, 0xF5B3, 0x918D, 0xF0B5, 0x9192, 0xE1A5, 0x919C, 0xF5DD, 0x91AB, 0xECA2, 0x91AC, 0xEDFD, 0x91AE, 0xF5B4, 0x91AF, 0xFBB8, + 0x91B1, 0xDBA3, 0x91B4, 0xD6CA, 0x91B5, 0xCBD9, 0x91C0, 0xE5D4, 0x91C7, 0xF3FA, 0x91C9, 0xEBB8, 0x91CB, 0xE0B7, 0x91CC, 0xD7EC, + 0x91CD, 0xF1EC, 0x91CE, 0xE5AF, 0x91CF, 0xD5E1, 0x91D0, 0xD7ED, 0x91D1, 0xD1D1, 0x91D7, 0xE1F2, 0x91D8, 0xEFF9, 0x91DC, 0xDDBC, + 0x91DD, 0xF6DC, 0x91E3, 0xF0E5, 0x91E7, 0xF4C4, 0x91EA, 0xE9E9, 0x91F5, 0xF3FB, 0x920D, 0xD4EF, 0x9210, 0xCCA2, 0x9211, 0xF7FE, + 0x9212, 0xDFBC, 0x9217, 0xEBCD, 0x921E, 0xD0B7, 0x9234, 0xD6C2, 0x923A, 0xE8AD, 0x923F, 0xEFAF, 0x9240, 0xCBA5, 0x9245, 0xCBE9, + 0x9249, 0xFAE8, 0x9257, 0xCCC6, 0x925B, 0xE6E7, 0x925E, 0xEAC7, 0x9262, 0xDBA4, 0x9264, 0xCFC9, 0x9265, 0xE2FC, 0x9266, 0xEFFA, + 0x9280, 0xEBDE, 0x9283, 0xF5C8, 0x9285, 0xD4DE, 0x9291, 0xE0D5, 0x9293, 0xEFB0, 0x9296, 0xE2C7, 0x9298, 0xD9AF, 0x929C, 0xF9E7, + 0x92B3, 0xE7E5, 0x92B6, 0xCFCA, 0x92B7, 0xE1D1, 0x92B9, 0xE2C8, 0x92CC, 0xEFFB, 0x92CF, 0xFAF9, 0x92D2, 0xDCF2, 0x92E4, 0xE0A7, + 0x92EA, 0xF8E8, 0x92F8, 0xCBEA, 0x92FC, 0xCBBC, 0x9304, 0xD6E2, 0x9310, 0xF5DE, 0x9318, 0xF5DF, 0x931A, 0xEEB6, 0x931E, 0xE2F6, + 0x931F, 0xD3CA, 0x9320, 0xEFFC, 0x9321, 0xD1C4, 0x9322, 0xEFB1, 0x9324, 0xD1C5, 0x9326, 0xD0DE, 0x9328, 0xD9E1, 0x932B, 0xE0B8, + 0x932E, 0xCDD1, 0x932F, 0xF3B9, 0x9348, 0xE7CC, 0x934A, 0xD6A8, 0x934B, 0xCEA7, 0x934D, 0xD4B5, 0x9354, 0xE4C8, 0x935B, 0xD3B4, + 0x936E, 0xEBB9, 0x9375, 0xCBF5, 0x937C, 0xF6DD, 0x937E, 0xF1A3, 0x938C, 0xCCC7, 0x9394, 0xE9CA, 0x9396, 0xE1F0, 0x939A, 0xF5E0, + 0x93A3, 0xFBAF, 0x93A7, 0xCBD1, 0x93AC, 0xFBE0, 0x93AD, 0xF2E5, 0x93B0, 0xECF0, 0x93C3, 0xF0EC, 0x93D1, 0xEEEB, 0x93DE, 0xE9CB, + 0x93E1, 0xCCF0, 0x93E4, 0xD7AF, 0x93F6, 0xF3A1, 0x9404, 0xFCF5, 0x9418, 0xF1A4, 0x9425, 0xE0D6, 0x942B, 0xEFB2, 0x9435, 0xF4D1, + 0x9438, 0xF7A1, 0x9444, 0xF1D1, 0x9451, 0xCAFC, 0x9452, 0xCAFD, 0x945B, 0xCECE, 0x947D, 0xF3C8, 0x947F, 0xF3BA, 0x9577, 0xEDFE, + 0x9580, 0xDAA6, 0x9583, 0xE0EC, 0x9589, 0xF8CD, 0x958B, 0xCBD2, 0x958F, 0xEBCE, 0x9591, 0xF9D8, 0x9592, 0xF9D9, 0x9593, 0xCAE0, + 0x9594, 0xDACA, 0x9598, 0xCBA6, 0x95A3, 0xCAC8, 0x95A4, 0xF9EE, 0x95A5, 0xDBEC, 0x95A8, 0xD0B1, 0x95AD, 0xD5EF, 0x95B1, 0xE6F3, + 0x95BB, 0xE7A2, 0x95BC, 0xE4D9, 0x95C7, 0xE4E1, 0x95CA, 0xFCC4, 0x95D4, 0xF9EF, 0x95D5, 0xCFF4, 0x95D6, 0xF7E6, 0x95DC, 0xCEBC, + 0x95E1, 0xF4C5, 0x95E2, 0xDCA3, 0x961C, 0xDDBD, 0x9621, 0xF4C6, 0x962A, 0xF8A1, 0x962E, 0xE8D6, 0x9632, 0xDBC1, 0x963B, 0xF0E6, + 0x963F, 0xE4B9, 0x9640, 0xF6ED, 0x9642, 0xF9AE, 0x9644, 0xDDBE, 0x964B, 0xD7B0, 0x964C, 0xD8E8, 0x964D, 0xCBBD, 0x9650, 0xF9DA, + 0x965B, 0xF8CE, 0x965C, 0xF9F0, 0x965D, 0xE0ED, 0x965E, 0xE3B3, 0x965F, 0xF4B3, 0x9662, 0xEAC2, 0x9663, 0xF2E6, 0x9664, 0xF0B6, + 0x966A, 0xDBD6, 0x9670, 0xEBE4, 0x9673, 0xF2E7, 0x9675, 0xD7D5, 0x9676, 0xD4B6, 0x9677, 0xF9E8, 0x9678, 0xD7C1, 0x967D, 0xE5D5, + 0x9685, 0xE9EA, 0x9686, 0xD7CC, 0x968A, 0xD3E9, 0x968B, 0xE2C9, 0x968D, 0xFCDB, 0x968E, 0xCDAD, 0x9694, 0xCCB0, 0x9695, 0xEAA2, + 0x9698, 0xE4F6, 0x9699, 0xD0C0, 0x969B, 0xF0B7, 0x969C, 0xEEA1, 0x96A3, 0xD7F6, 0x96A7, 0xE2CA, 0x96A8, 0xE2CB, 0x96AA, 0xFACF, + 0x96B1, 0xEBDF, 0x96B7, 0xD6CB, 0x96BB, 0xF4B4, 0x96C0, 0xEDCD, 0x96C1, 0xE4D2, 0x96C4, 0xEAA9, 0x96C5, 0xE4BA, 0x96C6, 0xF3A2, + 0x96C7, 0xCDD2, 0x96C9, 0xF6CB, 0x96CB, 0xF1E6, 0x96CC, 0xEDC1, 0x96CD, 0xE8BC, 0x96CE, 0xEED1, 0x96D5, 0xF0E7, 0x96D6, 0xE2CC, + 0x96D9, 0xE4AA, 0x96DB, 0xF5E1, 0x96DC, 0xEDDA, 0x96E2, 0xD7EE, 0x96E3, 0xD1F1, 0x96E8, 0xE9EB, 0x96E9, 0xE9EC, 0x96EA, 0xE0E4, + 0x96EF, 0xDAA7, 0x96F0, 0xDDD4, 0x96F2, 0xEAA3, 0x96F6, 0xD6C3, 0x96F7, 0xD6F4, 0x96F9, 0xDADF, 0x96FB, 0xEFB3, 0x9700, 0xE2CD, + 0x9706, 0xEFFD, 0x9707, 0xF2E8, 0x9711, 0xEFC5, 0x9713, 0xE7E7, 0x9716, 0xD7FD, 0x9719, 0xE7CE, 0x971C, 0xDFDC, 0x971E, 0xF9C7, + 0x9727, 0xD9F6, 0x9730, 0xDFAC, 0x9732, 0xD6DA, 0x9739, 0xDCA4, 0x973D, 0xF0B8, 0x9742, 0xD5FA, 0x9744, 0xE4F7, 0x9748, 0xD6C4, + 0x9751, 0xF4EC, 0x9756, 0xEFFE, 0x975C, 0xF0A1, 0x975E, 0xDEAA, 0x9761, 0xDABC, 0x9762, 0xD8FC, 0x9769, 0xFAD4, 0x976D, 0xECE5, + 0x9774, 0xFCA8, 0x9777, 0xECE6, 0x977A, 0xD8CB, 0x978B, 0xFBB9, 0x978D, 0xE4D3, 0x978F, 0xCDF9, 0x97A0, 0xCFD3, 0x97A8, 0xCAEA, + 0x97AB, 0xCFD4, 0x97AD, 0xF8BD, 0x97C6, 0xF4C7, 0x97CB, 0xEADF, 0x97D3, 0xF9DB, 0x97DC, 0xD4B7, 0x97F3, 0xEBE5, 0x97F6, 0xE1D2, + 0x97FB, 0xEAA4, 0x97FF, 0xFAC2, 0x9800, 0xFBE1, 0x9801, 0xFAED, 0x9802, 0xF0A2, 0x9803, 0xCCF1, 0x9805, 0xFAA3, 0x9806, 0xE2F7, + 0x9808, 0xE2CE, 0x980A, 0xE9F5, 0x980C, 0xE1EB, 0x9810, 0xE7E8, 0x9811, 0xE8D7, 0x9812, 0xDAF8, 0x9813, 0xD4CB, 0x9817, 0xF7F6, + 0x9818, 0xD6C5, 0x982D, 0xD4E9, 0x9830, 0xFAFA, 0x9838, 0xCCF2, 0x9839, 0xF7DD, 0x983B, 0xDEBA, 0x9846, 0xCEA8, 0x984C, 0xF0B9, + 0x984D, 0xE4FE, 0x984E, 0xE4C9, 0x9854, 0xE4D4, 0x9858, 0xEAC3, 0x985A, 0xEFB4, 0x985E, 0xD7BE, 0x9865, 0xFBE2, 0x9867, 0xCDD3, + 0x986B, 0xEFB5, 0x986F, 0xFAE9, 0x98A8, 0xF9A6, 0x98AF, 0xDFBD, 0x98B1, 0xF7C7, 0x98C4, 0xF8FD, 0x98C7, 0xF8FC, 0x98DB, 0xDEAB, + 0x98DC, 0xDBE8, 0x98DF, 0xE3DD, 0x98E1, 0xE1E2, 0x98E2, 0xD1C6, 0x98ED, 0xF6D0, 0x98EE, 0xEBE6, 0x98EF, 0xDAF9, 0x98F4, 0xECC7, + 0x98FC, 0xDEF8, 0x98FD, 0xF8E9, 0x98FE, 0xE3DE, 0x9903, 0xCEF5, 0x9909, 0xFAC3, 0x990A, 0xE5D7, 0x990C, 0xECC8, 0x9910, 0xF3C9, + 0x9913, 0xE4BB, 0x9918, 0xE6AE, 0x991E, 0xEFB6, 0x9920, 0xDCBF, 0x9928, 0xCEBD, 0x9945, 0xD8C3, 0x9949, 0xD0CF, 0x994B, 0xCFFA, + 0x994C, 0xF3CA, 0x994D, 0xE0D7, 0x9951, 0xD1C7, 0x9952, 0xE9AE, 0x9954, 0xE8BD, 0x9957, 0xFAC4, 0x9996, 0xE2CF, 0x9999, 0xFAC5, + 0x999D, 0xF9B8, 0x99A5, 0xDCE0, 0x99A8, 0xFBB0, 0x99AC, 0xD8A9, 0x99AD, 0xE5DF, 0x99AE, 0xF9A7, 0x99B1, 0xF6EE, 0x99B3, 0xF6CC, + 0x99B4, 0xE2F8, 0x99B9, 0xECF1, 0x99C1, 0xDAE0, 0x99D0, 0xF1D2, 0x99D1, 0xD2CC, 0x99D2, 0xCFCB, 0x99D5, 0xCABD, 0x99D9, 0xDDBF, + 0x99DD, 0xF6EF, 0x99DF, 0xDEF9, 0x99ED, 0xFAB4, 0x99F1, 0xD5AD, 0x99FF, 0xF1E7, 0x9A01, 0xDEBE, 0x9A08, 0xDCC0, 0x9A0E, 0xD1C8, + 0x9A0F, 0xD1C9, 0x9A19, 0xF8BE, 0x9A2B, 0xCBF6, 0x9A30, 0xD4F9, 0x9A36, 0xF5E2, 0x9A37, 0xE1D3, 0x9A40, 0xD8E9, 0x9A43, 0xF8FE, + 0x9A45, 0xCFCC, 0x9A4D, 0xFDA4, 0x9A55, 0xCEF6, 0x9A57, 0xFAD0, 0x9A5A, 0xCCF3, 0x9A5B, 0xE6BE, 0x9A5F, 0xF6AE, 0x9A62, 0xD5F0, + 0x9A65, 0xD1CA, 0x9A69, 0xFCBE, 0x9A6A, 0xD5F1, 0x9AA8, 0xCDE9, 0x9AB8, 0xFAB5, 0x9AD3, 0xE2D0, 0x9AD4, 0xF4F7, 0x9AD8, 0xCDD4, + 0x9AE5, 0xE7A3, 0x9AEE, 0xDBA5, 0x9B1A, 0xE2D1, 0x9B27, 0xD7A2, 0x9B2A, 0xF7E3, 0x9B31, 0xEAA6, 0x9B3C, 0xD0A1, 0x9B41, 0xCEDA, + 0x9B42, 0xFBEB, 0x9B43, 0xDBA6, 0x9B44, 0xDBDE, 0x9B45, 0xD8E5, 0x9B4F, 0xEAE0, 0x9B54, 0xD8AA, 0x9B5A, 0xE5E0, 0x9B6F, 0xD6DB, + 0x9B8E, 0xEFC6, 0x9B91, 0xF8EA, 0x9B9F, 0xE4D5, 0x9BAB, 0xCEF7, 0x9BAE, 0xE0D8, 0x9BC9, 0xD7EF, 0x9BD6, 0xF4ED, 0x9BE4, 0xCDE6, + 0x9BE8, 0xCCF4, 0x9C0D, 0xF5E3, 0x9C10, 0xE4CA, 0x9C12, 0xDCE1, 0x9C15, 0xF9C8, 0x9C25, 0xFCBF, 0x9C32, 0xE8A7, 0x9C3B, 0xD8C4, + 0x9C47, 0xCBBE, 0x9C49, 0xDCAE, 0x9C57, 0xD7F7, 0x9CE5, 0xF0E8, 0x9CE7, 0xDDC0, 0x9CE9, 0xCFCD, 0x9CF3, 0xDCF3, 0x9CF4, 0xD9B0, + 0x9CF6, 0xE6E9, 0x9D09, 0xE4BC, 0x9D1B, 0xEAC4, 0x9D26, 0xE4EC, 0x9D28, 0xE4E5, 0x9D3B, 0xFBF8, 0x9D51, 0xCCBB, 0x9D5D, 0xE4BD, + 0x9D60, 0xCDDC, 0x9D61, 0xD9F7, 0x9D6C, 0xDDDF, 0x9D72, 0xEDCE, 0x9DA9, 0xD9D0, 0x9DAF, 0xE5A3, 0x9DB4, 0xF9CD, 0x9DC4, 0xCDAE, + 0x9DD7, 0xCFCE, 0x9DF2, 0xF6AF, 0x9DF8, 0xFDD3, 0x9DF9, 0xEBED, 0x9DFA, 0xD6DC, 0x9E1A, 0xE5A4, 0x9E1E, 0xD5B6, 0x9E75, 0xD6DD, + 0x9E79, 0xF9E9, 0x9E7D, 0xE7A4, 0x9E7F, 0xD6E3, 0x9E92, 0xD1CB, 0x9E93, 0xD6E4, 0x9E97, 0xD5F2, 0x9E9D, 0xDEFA, 0x9E9F, 0xD7F8, + 0x9EA5, 0xD8EA, 0x9EB4, 0xCFD5, 0x9EB5, 0xD8FD, 0x9EBB, 0xD8AB, 0x9EBE, 0xFDCB, 0x9EC3, 0xFCDC, 0x9ECD, 0xE0A8, 0x9ECE, 0xD5F3, + 0x9ED1, 0xFDD9, 0x9ED4, 0xCCA3, 0x9ED8, 0xD9F9, 0x9EDB, 0xD3EA, 0x9EDC, 0xF5F5, 0x9EDE, 0xEFC7, 0x9EE8, 0xD3DA, 0x9EF4, 0xDABD, + 0x9F07, 0xE8A8, 0x9F08, 0xDCAF, 0x9F0E, 0xF0A3, 0x9F13, 0xCDD5, 0x9F20, 0xE0A9, 0x9F3B, 0xDEAC, 0x9F4A, 0xF0BA, 0x9F4B, 0xEEB1, + 0x9F4E, 0xEEB2, 0x9F52, 0xF6CD, 0x9F5F, 0xEED2, 0x9F61, 0xD6C6, 0x9F67, 0xE0E5, 0x9F6A, 0xF3BB, 0x9F6C, 0xE5E1, 0x9F77, 0xE4CB, + 0x9F8D, 0xD7A3, 0x9F90, 0xDBC2, 0x9F95, 0xCAFE, 0x9F9C, 0xCFCF, 0xAC00, 0xB0A1, 0xAC01, 0xB0A2, 0xAC02, 0x8141, 0xAC03, 0x8142, + 0xAC04, 0xB0A3, 0xAC05, 0x8143, 0xAC06, 0x8144, 0xAC07, 0xB0A4, 0xAC08, 0xB0A5, 0xAC09, 0xB0A6, 0xAC0A, 0xB0A7, 0xAC0B, 0x8145, + 0xAC0C, 0x8146, 0xAC0D, 0x8147, 0xAC0E, 0x8148, 0xAC0F, 0x8149, 0xAC10, 0xB0A8, 0xAC11, 0xB0A9, 0xAC12, 0xB0AA, 0xAC13, 0xB0AB, + 0xAC14, 0xB0AC, 0xAC15, 0xB0AD, 0xAC16, 0xB0AE, 0xAC17, 0xB0AF, 0xAC18, 0x814A, 0xAC19, 0xB0B0, 0xAC1A, 0xB0B1, 0xAC1B, 0xB0B2, + 0xAC1C, 0xB0B3, 0xAC1D, 0xB0B4, 0xAC1E, 0x814B, 0xAC1F, 0x814C, 0xAC20, 0xB0B5, 0xAC21, 0x814D, 0xAC22, 0x814E, 0xAC23, 0x814F, + 0xAC24, 0xB0B6, 0xAC25, 0x8150, 0xAC26, 0x8151, 0xAC27, 0x8152, 0xAC28, 0x8153, 0xAC29, 0x8154, 0xAC2A, 0x8155, 0xAC2B, 0x8156, + 0xAC2C, 0xB0B7, 0xAC2D, 0xB0B8, 0xAC2E, 0x8157, 0xAC2F, 0xB0B9, 0xAC30, 0xB0BA, 0xAC31, 0xB0BB, 0xAC32, 0x8158, 0xAC33, 0x8159, + 0xAC34, 0x815A, 0xAC35, 0x8161, 0xAC36, 0x8162, 0xAC37, 0x8163, 0xAC38, 0xB0BC, 0xAC39, 0xB0BD, 0xAC3A, 0x8164, 0xAC3B, 0x8165, + 0xAC3C, 0xB0BE, 0xAC3D, 0x8166, 0xAC3E, 0x8167, 0xAC3F, 0x8168, 0xAC40, 0xB0BF, 0xAC41, 0x8169, 0xAC42, 0x816A, 0xAC43, 0x816B, + 0xAC44, 0x816C, 0xAC45, 0x816D, 0xAC46, 0x816E, 0xAC47, 0x816F, 0xAC48, 0x8170, 0xAC49, 0x8171, 0xAC4A, 0x8172, 0xAC4B, 0xB0C0, + 0xAC4C, 0x8173, 0xAC4D, 0xB0C1, 0xAC4E, 0x8174, 0xAC4F, 0x8175, 0xAC50, 0x8176, 0xAC51, 0x8177, 0xAC52, 0x8178, 0xAC53, 0x8179, + 0xAC54, 0xB0C2, 0xAC55, 0x817A, 0xAC56, 0x8181, 0xAC57, 0x8182, 0xAC58, 0xB0C3, 0xAC59, 0x8183, 0xAC5A, 0x8184, 0xAC5B, 0x8185, + 0xAC5C, 0xB0C4, 0xAC5D, 0x8186, 0xAC5E, 0x8187, 0xAC5F, 0x8188, 0xAC60, 0x8189, 0xAC61, 0x818A, 0xAC62, 0x818B, 0xAC63, 0x818C, + 0xAC64, 0x818D, 0xAC65, 0x818E, 0xAC66, 0x818F, 0xAC67, 0x8190, 0xAC68, 0x8191, 0xAC69, 0x8192, 0xAC6A, 0x8193, 0xAC6B, 0x8194, + 0xAC6C, 0x8195, 0xAC6D, 0x8196, 0xAC6E, 0x8197, 0xAC6F, 0x8198, 0xAC70, 0xB0C5, 0xAC71, 0xB0C6, 0xAC72, 0x8199, 0xAC73, 0x819A, + 0xAC74, 0xB0C7, 0xAC75, 0x819B, 0xAC76, 0x819C, 0xAC77, 0xB0C8, 0xAC78, 0xB0C9, 0xAC79, 0x819D, 0xAC7A, 0xB0CA, 0xAC7B, 0x819E, + 0xAC7C, 0x819F, 0xAC7D, 0x81A0, 0xAC7E, 0x81A1, 0xAC7F, 0x81A2, 0xAC80, 0xB0CB, 0xAC81, 0xB0CC, 0xAC82, 0x81A3, 0xAC83, 0xB0CD, + 0xAC84, 0xB0CE, 0xAC85, 0xB0CF, 0xAC86, 0xB0D0, 0xAC87, 0x81A4, 0xAC88, 0x81A5, 0xAC89, 0xB0D1, 0xAC8A, 0xB0D2, 0xAC8B, 0xB0D3, + 0xAC8C, 0xB0D4, 0xAC8D, 0x81A6, 0xAC8E, 0x81A7, 0xAC8F, 0x81A8, 0xAC90, 0xB0D5, 0xAC91, 0x81A9, 0xAC92, 0x81AA, 0xAC93, 0x81AB, + 0xAC94, 0xB0D6, 0xAC95, 0x81AC, 0xAC96, 0x81AD, 0xAC97, 0x81AE, 0xAC98, 0x81AF, 0xAC99, 0x81B0, 0xAC9A, 0x81B1, 0xAC9B, 0x81B2, + 0xAC9C, 0xB0D7, 0xAC9D, 0xB0D8, 0xAC9E, 0x81B3, 0xAC9F, 0xB0D9, 0xACA0, 0xB0DA, 0xACA1, 0xB0DB, 0xACA2, 0x81B4, 0xACA3, 0x81B5, + 0xACA4, 0x81B6, 0xACA5, 0x81B7, 0xACA6, 0x81B8, 0xACA7, 0x81B9, 0xACA8, 0xB0DC, 0xACA9, 0xB0DD, 0xACAA, 0xB0DE, 0xACAB, 0x81BA, + 0xACAC, 0xB0DF, 0xACAD, 0x81BB, 0xACAE, 0x81BC, 0xACAF, 0xB0E0, 0xACB0, 0xB0E1, 0xACB1, 0x81BD, 0xACB2, 0x81BE, 0xACB3, 0x81BF, + 0xACB4, 0x81C0, 0xACB5, 0x81C1, 0xACB6, 0x81C2, 0xACB7, 0x81C3, 0xACB8, 0xB0E2, 0xACB9, 0xB0E3, 0xACBA, 0x81C4, 0xACBB, 0xB0E4, + 0xACBC, 0xB0E5, 0xACBD, 0xB0E6, 0xACBE, 0x81C5, 0xACBF, 0x81C6, 0xACC0, 0x81C7, 0xACC1, 0xB0E7, 0xACC2, 0x81C8, 0xACC3, 0x81C9, + 0xACC4, 0xB0E8, 0xACC5, 0x81CA, 0xACC6, 0x81CB, 0xACC7, 0x81CC, 0xACC8, 0xB0E9, 0xACC9, 0x81CD, 0xACCA, 0x81CE, 0xACCB, 0x81CF, + 0xACCC, 0xB0EA, 0xACCD, 0x81D0, 0xACCE, 0x81D1, 0xACCF, 0x81D2, 0xACD0, 0x81D3, 0xACD1, 0x81D4, 0xACD2, 0x81D5, 0xACD3, 0x81D6, + 0xACD4, 0x81D7, 0xACD5, 0xB0EB, 0xACD6, 0x81D8, 0xACD7, 0xB0EC, 0xACD8, 0x81D9, 0xACD9, 0x81DA, 0xACDA, 0x81DB, 0xACDB, 0x81DC, + 0xACDC, 0x81DD, 0xACDD, 0x81DE, 0xACDE, 0x81DF, 0xACDF, 0x81E0, 0xACE0, 0xB0ED, 0xACE1, 0xB0EE, 0xACE2, 0x81E1, 0xACE3, 0x81E2, + 0xACE4, 0xB0EF, 0xACE5, 0x81E3, 0xACE6, 0x81E4, 0xACE7, 0xB0F0, 0xACE8, 0xB0F1, 0xACE9, 0x81E5, 0xACEA, 0xB0F2, 0xACEB, 0x81E6, + 0xACEC, 0xB0F3, 0xACED, 0x81E7, 0xACEE, 0x81E8, 0xACEF, 0xB0F4, 0xACF0, 0xB0F5, 0xACF1, 0xB0F6, 0xACF2, 0x81E9, 0xACF3, 0xB0F7, + 0xACF4, 0x81EA, 0xACF5, 0xB0F8, 0xACF6, 0xB0F9, 0xACF7, 0x81EB, 0xACF8, 0x81EC, 0xACF9, 0x81ED, 0xACFA, 0x81EE, 0xACFB, 0x81EF, + 0xACFC, 0xB0FA, 0xACFD, 0xB0FB, 0xACFE, 0x81F0, 0xACFF, 0x81F1, 0xAD00, 0xB0FC, 0xAD01, 0x81F2, 0xAD02, 0x81F3, 0xAD03, 0x81F4, + 0xAD04, 0xB0FD, 0xAD05, 0x81F5, 0xAD06, 0xB0FE, 0xAD07, 0x81F6, 0xAD08, 0x81F7, 0xAD09, 0x81F8, 0xAD0A, 0x81F9, 0xAD0B, 0x81FA, + 0xAD0C, 0xB1A1, 0xAD0D, 0xB1A2, 0xAD0E, 0x81FB, 0xAD0F, 0xB1A3, 0xAD10, 0x81FC, 0xAD11, 0xB1A4, 0xAD12, 0x81FD, 0xAD13, 0x81FE, + 0xAD14, 0x8241, 0xAD15, 0x8242, 0xAD16, 0x8243, 0xAD17, 0x8244, 0xAD18, 0xB1A5, 0xAD19, 0x8245, 0xAD1A, 0x8246, 0xAD1B, 0x8247, + 0xAD1C, 0xB1A6, 0xAD1D, 0x8248, 0xAD1E, 0x8249, 0xAD1F, 0x824A, 0xAD20, 0xB1A7, 0xAD21, 0x824B, 0xAD22, 0x824C, 0xAD23, 0x824D, + 0xAD24, 0x824E, 0xAD25, 0x824F, 0xAD26, 0x8250, 0xAD27, 0x8251, 0xAD28, 0x8252, 0xAD29, 0xB1A8, 0xAD2A, 0x8253, 0xAD2B, 0x8254, + 0xAD2C, 0xB1A9, 0xAD2D, 0xB1AA, 0xAD2E, 0x8255, 0xAD2F, 0x8256, 0xAD30, 0x8257, 0xAD31, 0x8258, 0xAD32, 0x8259, 0xAD33, 0x825A, + 0xAD34, 0xB1AB, 0xAD35, 0xB1AC, 0xAD36, 0x8261, 0xAD37, 0x8262, 0xAD38, 0xB1AD, 0xAD39, 0x8263, 0xAD3A, 0x8264, 0xAD3B, 0x8265, + 0xAD3C, 0xB1AE, 0xAD3D, 0x8266, 0xAD3E, 0x8267, 0xAD3F, 0x8268, 0xAD40, 0x8269, 0xAD41, 0x826A, 0xAD42, 0x826B, 0xAD43, 0x826C, + 0xAD44, 0xB1AF, 0xAD45, 0xB1B0, 0xAD46, 0x826D, 0xAD47, 0xB1B1, 0xAD48, 0x826E, 0xAD49, 0xB1B2, 0xAD4A, 0x826F, 0xAD4B, 0x8270, + 0xAD4C, 0x8271, 0xAD4D, 0x8272, 0xAD4E, 0x8273, 0xAD4F, 0x8274, 0xAD50, 0xB1B3, 0xAD51, 0x8275, 0xAD52, 0x8276, 0xAD53, 0x8277, + 0xAD54, 0xB1B4, 0xAD55, 0x8278, 0xAD56, 0x8279, 0xAD57, 0x827A, 0xAD58, 0xB1B5, 0xAD59, 0x8281, 0xAD5A, 0x8282, 0xAD5B, 0x8283, + 0xAD5C, 0x8284, 0xAD5D, 0x8285, 0xAD5E, 0x8286, 0xAD5F, 0x8287, 0xAD60, 0x8288, 0xAD61, 0xB1B6, 0xAD62, 0x8289, 0xAD63, 0xB1B7, + 0xAD64, 0x828A, 0xAD65, 0x828B, 0xAD66, 0x828C, 0xAD67, 0x828D, 0xAD68, 0x828E, 0xAD69, 0x828F, 0xAD6A, 0x8290, 0xAD6B, 0x8291, + 0xAD6C, 0xB1B8, 0xAD6D, 0xB1B9, 0xAD6E, 0x8292, 0xAD6F, 0x8293, 0xAD70, 0xB1BA, 0xAD71, 0x8294, 0xAD72, 0x8295, 0xAD73, 0xB1BB, + 0xAD74, 0xB1BC, 0xAD75, 0xB1BD, 0xAD76, 0xB1BE, 0xAD77, 0x8296, 0xAD78, 0x8297, 0xAD79, 0x8298, 0xAD7A, 0x8299, 0xAD7B, 0xB1BF, + 0xAD7C, 0xB1C0, 0xAD7D, 0xB1C1, 0xAD7E, 0x829A, 0xAD7F, 0xB1C2, 0xAD80, 0x829B, 0xAD81, 0xB1C3, 0xAD82, 0xB1C4, 0xAD83, 0x829C, + 0xAD84, 0x829D, 0xAD85, 0x829E, 0xAD86, 0x829F, 0xAD87, 0x82A0, 0xAD88, 0xB1C5, 0xAD89, 0xB1C6, 0xAD8A, 0x82A1, 0xAD8B, 0x82A2, + 0xAD8C, 0xB1C7, 0xAD8D, 0x82A3, 0xAD8E, 0x82A4, 0xAD8F, 0x82A5, 0xAD90, 0xB1C8, 0xAD91, 0x82A6, 0xAD92, 0x82A7, 0xAD93, 0x82A8, + 0xAD94, 0x82A9, 0xAD95, 0x82AA, 0xAD96, 0x82AB, 0xAD97, 0x82AC, 0xAD98, 0x82AD, 0xAD99, 0x82AE, 0xAD9A, 0x82AF, 0xAD9B, 0x82B0, + 0xAD9C, 0xB1C9, 0xAD9D, 0xB1CA, 0xAD9E, 0x82B1, 0xAD9F, 0x82B2, 0xADA0, 0x82B3, 0xADA1, 0x82B4, 0xADA2, 0x82B5, 0xADA3, 0x82B6, + 0xADA4, 0xB1CB, 0xADA5, 0x82B7, 0xADA6, 0x82B8, 0xADA7, 0x82B9, 0xADA8, 0x82BA, 0xADA9, 0x82BB, 0xADAA, 0x82BC, 0xADAB, 0x82BD, + 0xADAC, 0x82BE, 0xADAD, 0x82BF, 0xADAE, 0x82C0, 0xADAF, 0x82C1, 0xADB0, 0x82C2, 0xADB1, 0x82C3, 0xADB2, 0x82C4, 0xADB3, 0x82C5, + 0xADB4, 0x82C6, 0xADB5, 0x82C7, 0xADB6, 0x82C8, 0xADB7, 0xB1CC, 0xADB8, 0x82C9, 0xADB9, 0x82CA, 0xADBA, 0x82CB, 0xADBB, 0x82CC, + 0xADBC, 0x82CD, 0xADBD, 0x82CE, 0xADBE, 0x82CF, 0xADBF, 0x82D0, 0xADC0, 0xB1CD, 0xADC1, 0xB1CE, 0xADC2, 0x82D1, 0xADC3, 0x82D2, + 0xADC4, 0xB1CF, 0xADC5, 0x82D3, 0xADC6, 0x82D4, 0xADC7, 0x82D5, 0xADC8, 0xB1D0, 0xADC9, 0x82D6, 0xADCA, 0x82D7, 0xADCB, 0x82D8, + 0xADCC, 0x82D9, 0xADCD, 0x82DA, 0xADCE, 0x82DB, 0xADCF, 0x82DC, 0xADD0, 0xB1D1, 0xADD1, 0xB1D2, 0xADD2, 0x82DD, 0xADD3, 0xB1D3, + 0xADD4, 0x82DE, 0xADD5, 0x82DF, 0xADD6, 0x82E0, 0xADD7, 0x82E1, 0xADD8, 0x82E2, 0xADD9, 0x82E3, 0xADDA, 0x82E4, 0xADDB, 0x82E5, + 0xADDC, 0xB1D4, 0xADDD, 0x82E6, 0xADDE, 0x82E7, 0xADDF, 0x82E8, 0xADE0, 0xB1D5, 0xADE1, 0x82E9, 0xADE2, 0x82EA, 0xADE3, 0x82EB, + 0xADE4, 0xB1D6, 0xADE5, 0x82EC, 0xADE6, 0x82ED, 0xADE7, 0x82EE, 0xADE8, 0x82EF, 0xADE9, 0x82F0, 0xADEA, 0x82F1, 0xADEB, 0x82F2, + 0xADEC, 0x82F3, 0xADED, 0x82F4, 0xADEE, 0x82F5, 0xADEF, 0x82F6, 0xADF0, 0x82F7, 0xADF1, 0x82F8, 0xADF2, 0x82F9, 0xADF3, 0x82FA, + 0xADF4, 0x82FB, 0xADF5, 0x82FC, 0xADF6, 0x82FD, 0xADF7, 0x82FE, 0xADF8, 0xB1D7, 0xADF9, 0xB1D8, 0xADFA, 0x8341, 0xADFB, 0x8342, + 0xADFC, 0xB1D9, 0xADFD, 0x8343, 0xADFE, 0x8344, 0xADFF, 0xB1DA, 0xAE00, 0xB1DB, 0xAE01, 0xB1DC, 0xAE02, 0x8345, 0xAE03, 0x8346, + 0xAE04, 0x8347, 0xAE05, 0x8348, 0xAE06, 0x8349, 0xAE07, 0x834A, 0xAE08, 0xB1DD, 0xAE09, 0xB1DE, 0xAE0A, 0x834B, 0xAE0B, 0xB1DF, + 0xAE0C, 0x834C, 0xAE0D, 0xB1E0, 0xAE0E, 0x834D, 0xAE0F, 0x834E, 0xAE10, 0x834F, 0xAE11, 0x8350, 0xAE12, 0x8351, 0xAE13, 0x8352, + 0xAE14, 0xB1E1, 0xAE15, 0x8353, 0xAE16, 0x8354, 0xAE17, 0x8355, 0xAE18, 0x8356, 0xAE19, 0x8357, 0xAE1A, 0x8358, 0xAE1B, 0x8359, + 0xAE1C, 0x835A, 0xAE1D, 0x8361, 0xAE1E, 0x8362, 0xAE1F, 0x8363, 0xAE20, 0x8364, 0xAE21, 0x8365, 0xAE22, 0x8366, 0xAE23, 0x8367, + 0xAE24, 0x8368, 0xAE25, 0x8369, 0xAE26, 0x836A, 0xAE27, 0x836B, 0xAE28, 0x836C, 0xAE29, 0x836D, 0xAE2A, 0x836E, 0xAE2B, 0x836F, + 0xAE2C, 0x8370, 0xAE2D, 0x8371, 0xAE2E, 0x8372, 0xAE2F, 0x8373, 0xAE30, 0xB1E2, 0xAE31, 0xB1E3, 0xAE32, 0x8374, 0xAE33, 0x8375, + 0xAE34, 0xB1E4, 0xAE35, 0x8376, 0xAE36, 0x8377, 0xAE37, 0xB1E5, 0xAE38, 0xB1E6, 0xAE39, 0x8378, 0xAE3A, 0xB1E7, 0xAE3B, 0x8379, + 0xAE3C, 0x837A, 0xAE3D, 0x8381, 0xAE3E, 0x8382, 0xAE3F, 0x8383, 0xAE40, 0xB1E8, 0xAE41, 0xB1E9, 0xAE42, 0x8384, 0xAE43, 0xB1EA, + 0xAE44, 0x8385, 0xAE45, 0xB1EB, 0xAE46, 0xB1EC, 0xAE47, 0x8386, 0xAE48, 0x8387, 0xAE49, 0x8388, 0xAE4A, 0xB1ED, 0xAE4B, 0x8389, + 0xAE4C, 0xB1EE, 0xAE4D, 0xB1EF, 0xAE4E, 0xB1F0, 0xAE4F, 0x838A, 0xAE50, 0xB1F1, 0xAE51, 0x838B, 0xAE52, 0x838C, 0xAE53, 0x838D, + 0xAE54, 0xB1F2, 0xAE55, 0x838E, 0xAE56, 0xB1F3, 0xAE57, 0x838F, 0xAE58, 0x8390, 0xAE59, 0x8391, 0xAE5A, 0x8392, 0xAE5B, 0x8393, + 0xAE5C, 0xB1F4, 0xAE5D, 0xB1F5, 0xAE5E, 0x8394, 0xAE5F, 0xB1F6, 0xAE60, 0xB1F7, 0xAE61, 0xB1F8, 0xAE62, 0x8395, 0xAE63, 0x8396, + 0xAE64, 0x8397, 0xAE65, 0xB1F9, 0xAE66, 0x8398, 0xAE67, 0x8399, 0xAE68, 0xB1FA, 0xAE69, 0xB1FB, 0xAE6A, 0x839A, 0xAE6B, 0x839B, + 0xAE6C, 0xB1FC, 0xAE6D, 0x839C, 0xAE6E, 0x839D, 0xAE6F, 0x839E, 0xAE70, 0xB1FD, 0xAE71, 0x839F, 0xAE72, 0x83A0, 0xAE73, 0x83A1, + 0xAE74, 0x83A2, 0xAE75, 0x83A3, 0xAE76, 0x83A4, 0xAE77, 0x83A5, 0xAE78, 0xB1FE, 0xAE79, 0xB2A1, 0xAE7A, 0x83A6, 0xAE7B, 0xB2A2, + 0xAE7C, 0xB2A3, 0xAE7D, 0xB2A4, 0xAE7E, 0x83A7, 0xAE7F, 0x83A8, 0xAE80, 0x83A9, 0xAE81, 0x83AA, 0xAE82, 0x83AB, 0xAE83, 0x83AC, + 0xAE84, 0xB2A5, 0xAE85, 0xB2A6, 0xAE86, 0x83AD, 0xAE87, 0x83AE, 0xAE88, 0x83AF, 0xAE89, 0x83B0, 0xAE8A, 0x83B1, 0xAE8B, 0x83B2, + 0xAE8C, 0xB2A7, 0xAE8D, 0x83B3, 0xAE8E, 0x83B4, 0xAE8F, 0x83B5, 0xAE90, 0x83B6, 0xAE91, 0x83B7, 0xAE92, 0x83B8, 0xAE93, 0x83B9, + 0xAE94, 0x83BA, 0xAE95, 0x83BB, 0xAE96, 0x83BC, 0xAE97, 0x83BD, 0xAE98, 0x83BE, 0xAE99, 0x83BF, 0xAE9A, 0x83C0, 0xAE9B, 0x83C1, + 0xAE9C, 0x83C2, 0xAE9D, 0x83C3, 0xAE9E, 0x83C4, 0xAE9F, 0x83C5, 0xAEA0, 0x83C6, 0xAEA1, 0x83C7, 0xAEA2, 0x83C8, 0xAEA3, 0x83C9, + 0xAEA4, 0x83CA, 0xAEA5, 0x83CB, 0xAEA6, 0x83CC, 0xAEA7, 0x83CD, 0xAEA8, 0x83CE, 0xAEA9, 0x83CF, 0xAEAA, 0x83D0, 0xAEAB, 0x83D1, + 0xAEAC, 0x83D2, 0xAEAD, 0x83D3, 0xAEAE, 0x83D4, 0xAEAF, 0x83D5, 0xAEB0, 0x83D6, 0xAEB1, 0x83D7, 0xAEB2, 0x83D8, 0xAEB3, 0x83D9, + 0xAEB4, 0x83DA, 0xAEB5, 0x83DB, 0xAEB6, 0x83DC, 0xAEB7, 0x83DD, 0xAEB8, 0x83DE, 0xAEB9, 0x83DF, 0xAEBA, 0x83E0, 0xAEBB, 0x83E1, + 0xAEBC, 0xB2A8, 0xAEBD, 0xB2A9, 0xAEBE, 0xB2AA, 0xAEBF, 0x83E2, 0xAEC0, 0xB2AB, 0xAEC1, 0x83E3, 0xAEC2, 0x83E4, 0xAEC3, 0x83E5, + 0xAEC4, 0xB2AC, 0xAEC5, 0x83E6, 0xAEC6, 0x83E7, 0xAEC7, 0x83E8, 0xAEC8, 0x83E9, 0xAEC9, 0x83EA, 0xAECA, 0x83EB, 0xAECB, 0x83EC, + 0xAECC, 0xB2AD, 0xAECD, 0xB2AE, 0xAECE, 0x83ED, 0xAECF, 0xB2AF, 0xAED0, 0xB2B0, 0xAED1, 0xB2B1, 0xAED2, 0x83EE, 0xAED3, 0x83EF, + 0xAED4, 0x83F0, 0xAED5, 0x83F1, 0xAED6, 0x83F2, 0xAED7, 0x83F3, 0xAED8, 0xB2B2, 0xAED9, 0xB2B3, 0xAEDA, 0x83F4, 0xAEDB, 0x83F5, + 0xAEDC, 0xB2B4, 0xAEDD, 0x83F6, 0xAEDE, 0x83F7, 0xAEDF, 0x83F8, 0xAEE0, 0x83F9, 0xAEE1, 0x83FA, 0xAEE2, 0x83FB, 0xAEE3, 0x83FC, + 0xAEE4, 0x83FD, 0xAEE5, 0x83FE, 0xAEE6, 0x8441, 0xAEE7, 0x8442, 0xAEE8, 0xB2B5, 0xAEE9, 0x8443, 0xAEEA, 0x8444, 0xAEEB, 0xB2B6, + 0xAEEC, 0x8445, 0xAEED, 0xB2B7, 0xAEEE, 0x8446, 0xAEEF, 0x8447, 0xAEF0, 0x8448, 0xAEF1, 0x8449, 0xAEF2, 0x844A, 0xAEF3, 0x844B, + 0xAEF4, 0xB2B8, 0xAEF5, 0x844C, 0xAEF6, 0x844D, 0xAEF7, 0x844E, 0xAEF8, 0xB2B9, 0xAEF9, 0x844F, 0xAEFA, 0x8450, 0xAEFB, 0x8451, + 0xAEFC, 0xB2BA, 0xAEFD, 0x8452, 0xAEFE, 0x8453, 0xAEFF, 0x8454, 0xAF00, 0x8455, 0xAF01, 0x8456, 0xAF02, 0x8457, 0xAF03, 0x8458, + 0xAF04, 0x8459, 0xAF05, 0x845A, 0xAF06, 0x8461, 0xAF07, 0xB2BB, 0xAF08, 0xB2BC, 0xAF09, 0x8462, 0xAF0A, 0x8463, 0xAF0B, 0x8464, + 0xAF0C, 0x8465, 0xAF0D, 0xB2BD, 0xAF0E, 0x8466, 0xAF0F, 0x8467, 0xAF10, 0xB2BE, 0xAF11, 0x8468, 0xAF12, 0x8469, 0xAF13, 0x846A, + 0xAF14, 0x846B, 0xAF15, 0x846C, 0xAF16, 0x846D, 0xAF17, 0x846E, 0xAF18, 0x846F, 0xAF19, 0x8470, 0xAF1A, 0x8471, 0xAF1B, 0x8472, + 0xAF1C, 0x8473, 0xAF1D, 0x8474, 0xAF1E, 0x8475, 0xAF1F, 0x8476, 0xAF20, 0x8477, 0xAF21, 0x8478, 0xAF22, 0x8479, 0xAF23, 0x847A, + 0xAF24, 0x8481, 0xAF25, 0x8482, 0xAF26, 0x8483, 0xAF27, 0x8484, 0xAF28, 0x8485, 0xAF29, 0x8486, 0xAF2A, 0x8487, 0xAF2B, 0x8488, + 0xAF2C, 0xB2BF, 0xAF2D, 0xB2C0, 0xAF2E, 0x8489, 0xAF2F, 0x848A, 0xAF30, 0xB2C1, 0xAF31, 0x848B, 0xAF32, 0xB2C2, 0xAF33, 0x848C, + 0xAF34, 0xB2C3, 0xAF35, 0x848D, 0xAF36, 0x848E, 0xAF37, 0x848F, 0xAF38, 0x8490, 0xAF39, 0x8491, 0xAF3A, 0x8492, 0xAF3B, 0x8493, + 0xAF3C, 0xB2C4, 0xAF3D, 0xB2C5, 0xAF3E, 0x8494, 0xAF3F, 0xB2C6, 0xAF40, 0x8495, 0xAF41, 0xB2C7, 0xAF42, 0xB2C8, 0xAF43, 0xB2C9, + 0xAF44, 0x8496, 0xAF45, 0x8497, 0xAF46, 0x8498, 0xAF47, 0x8499, 0xAF48, 0xB2CA, 0xAF49, 0xB2CB, 0xAF4A, 0x849A, 0xAF4B, 0x849B, + 0xAF4C, 0x849C, 0xAF4D, 0x849D, 0xAF4E, 0x849E, 0xAF4F, 0x849F, 0xAF50, 0xB2CC, 0xAF51, 0x84A0, 0xAF52, 0x84A1, 0xAF53, 0x84A2, + 0xAF54, 0x84A3, 0xAF55, 0x84A4, 0xAF56, 0x84A5, 0xAF57, 0x84A6, 0xAF58, 0x84A7, 0xAF59, 0x84A8, 0xAF5A, 0x84A9, 0xAF5B, 0x84AA, + 0xAF5C, 0xB2CD, 0xAF5D, 0xB2CE, 0xAF5E, 0x84AB, 0xAF5F, 0x84AC, 0xAF60, 0x84AD, 0xAF61, 0x84AE, 0xAF62, 0x84AF, 0xAF63, 0x84B0, + 0xAF64, 0xB2CF, 0xAF65, 0xB2D0, 0xAF66, 0x84B1, 0xAF67, 0x84B2, 0xAF68, 0x84B3, 0xAF69, 0x84B4, 0xAF6A, 0x84B5, 0xAF6B, 0x84B6, + 0xAF6C, 0x84B7, 0xAF6D, 0x84B8, 0xAF6E, 0x84B9, 0xAF6F, 0x84BA, 0xAF70, 0x84BB, 0xAF71, 0x84BC, 0xAF72, 0x84BD, 0xAF73, 0x84BE, + 0xAF74, 0x84BF, 0xAF75, 0x84C0, 0xAF76, 0x84C1, 0xAF77, 0x84C2, 0xAF78, 0x84C3, 0xAF79, 0xB2D1, 0xAF7A, 0x84C4, 0xAF7B, 0x84C5, + 0xAF7C, 0x84C6, 0xAF7D, 0x84C7, 0xAF7E, 0x84C8, 0xAF7F, 0x84C9, 0xAF80, 0xB2D2, 0xAF81, 0x84CA, 0xAF82, 0x84CB, 0xAF83, 0x84CC, + 0xAF84, 0xB2D3, 0xAF85, 0x84CD, 0xAF86, 0x84CE, 0xAF87, 0x84CF, 0xAF88, 0xB2D4, 0xAF89, 0x84D0, 0xAF8A, 0x84D1, 0xAF8B, 0x84D2, + 0xAF8C, 0x84D3, 0xAF8D, 0x84D4, 0xAF8E, 0x84D5, 0xAF8F, 0x84D6, 0xAF90, 0xB2D5, 0xAF91, 0xB2D6, 0xAF92, 0x84D7, 0xAF93, 0x84D8, + 0xAF94, 0x84D9, 0xAF95, 0xB2D7, 0xAF96, 0x84DA, 0xAF97, 0x84DB, 0xAF98, 0x84DC, 0xAF99, 0x84DD, 0xAF9A, 0x84DE, 0xAF9B, 0x84DF, + 0xAF9C, 0xB2D8, 0xAF9D, 0x84E0, 0xAF9E, 0x84E1, 0xAF9F, 0x84E2, 0xAFA0, 0x84E3, 0xAFA1, 0x84E4, 0xAFA2, 0x84E5, 0xAFA3, 0x84E6, + 0xAFA4, 0x84E7, 0xAFA5, 0x84E8, 0xAFA6, 0x84E9, 0xAFA7, 0x84EA, 0xAFA8, 0x84EB, 0xAFA9, 0x84EC, 0xAFAA, 0x84ED, 0xAFAB, 0x84EE, + 0xAFAC, 0x84EF, 0xAFAD, 0x84F0, 0xAFAE, 0x84F1, 0xAFAF, 0x84F2, 0xAFB0, 0x84F3, 0xAFB1, 0x84F4, 0xAFB2, 0x84F5, 0xAFB3, 0x84F6, + 0xAFB4, 0x84F7, 0xAFB5, 0x84F8, 0xAFB6, 0x84F9, 0xAFB7, 0x84FA, 0xAFB8, 0xB2D9, 0xAFB9, 0xB2DA, 0xAFBA, 0x84FB, 0xAFBB, 0x84FC, + 0xAFBC, 0xB2DB, 0xAFBD, 0x84FD, 0xAFBE, 0x84FE, 0xAFBF, 0x8541, 0xAFC0, 0xB2DC, 0xAFC1, 0x8542, 0xAFC2, 0x8543, 0xAFC3, 0x8544, + 0xAFC4, 0x8545, 0xAFC5, 0x8546, 0xAFC6, 0x8547, 0xAFC7, 0xB2DD, 0xAFC8, 0xB2DE, 0xAFC9, 0xB2DF, 0xAFCA, 0x8548, 0xAFCB, 0xB2E0, + 0xAFCC, 0x8549, 0xAFCD, 0xB2E1, 0xAFCE, 0xB2E2, 0xAFCF, 0x854A, 0xAFD0, 0x854B, 0xAFD1, 0x854C, 0xAFD2, 0x854D, 0xAFD3, 0x854E, + 0xAFD4, 0xB2E3, 0xAFD5, 0x854F, 0xAFD6, 0x8550, 0xAFD7, 0x8551, 0xAFD8, 0x8552, 0xAFD9, 0x8553, 0xAFDA, 0x8554, 0xAFDB, 0x8555, + 0xAFDC, 0xB2E4, 0xAFDD, 0x8556, 0xAFDE, 0x8557, 0xAFDF, 0x8558, 0xAFE0, 0x8559, 0xAFE1, 0x855A, 0xAFE2, 0x8561, 0xAFE3, 0x8562, + 0xAFE4, 0x8563, 0xAFE5, 0x8564, 0xAFE6, 0x8565, 0xAFE7, 0x8566, 0xAFE8, 0xB2E5, 0xAFE9, 0xB2E6, 0xAFEA, 0x8567, 0xAFEB, 0x8568, + 0xAFEC, 0x8569, 0xAFED, 0x856A, 0xAFEE, 0x856B, 0xAFEF, 0x856C, 0xAFF0, 0xB2E7, 0xAFF1, 0xB2E8, 0xAFF2, 0x856D, 0xAFF3, 0x856E, + 0xAFF4, 0xB2E9, 0xAFF5, 0x856F, 0xAFF6, 0x8570, 0xAFF7, 0x8571, 0xAFF8, 0xB2EA, 0xAFF9, 0x8572, 0xAFFA, 0x8573, 0xAFFB, 0x8574, + 0xAFFC, 0x8575, 0xAFFD, 0x8576, 0xAFFE, 0x8577, 0xAFFF, 0x8578, 0xB000, 0xB2EB, 0xB001, 0xB2EC, 0xB002, 0x8579, 0xB003, 0x857A, + 0xB004, 0xB2ED, 0xB005, 0x8581, 0xB006, 0x8582, 0xB007, 0x8583, 0xB008, 0x8584, 0xB009, 0x8585, 0xB00A, 0x8586, 0xB00B, 0x8587, + 0xB00C, 0xB2EE, 0xB00D, 0x8588, 0xB00E, 0x8589, 0xB00F, 0x858A, 0xB010, 0xB2EF, 0xB011, 0x858B, 0xB012, 0x858C, 0xB013, 0x858D, + 0xB014, 0xB2F0, 0xB015, 0x858E, 0xB016, 0x858F, 0xB017, 0x8590, 0xB018, 0x8591, 0xB019, 0x8592, 0xB01A, 0x8593, 0xB01B, 0x8594, + 0xB01C, 0xB2F1, 0xB01D, 0xB2F2, 0xB01E, 0x8595, 0xB01F, 0x8596, 0xB020, 0x8597, 0xB021, 0x8598, 0xB022, 0x8599, 0xB023, 0x859A, + 0xB024, 0x859B, 0xB025, 0x859C, 0xB026, 0x859D, 0xB027, 0x859E, 0xB028, 0xB2F3, 0xB029, 0x859F, 0xB02A, 0x85A0, 0xB02B, 0x85A1, + 0xB02C, 0x85A2, 0xB02D, 0x85A3, 0xB02E, 0x85A4, 0xB02F, 0x85A5, 0xB030, 0x85A6, 0xB031, 0x85A7, 0xB032, 0x85A8, 0xB033, 0x85A9, + 0xB034, 0x85AA, 0xB035, 0x85AB, 0xB036, 0x85AC, 0xB037, 0x85AD, 0xB038, 0x85AE, 0xB039, 0x85AF, 0xB03A, 0x85B0, 0xB03B, 0x85B1, + 0xB03C, 0x85B2, 0xB03D, 0x85B3, 0xB03E, 0x85B4, 0xB03F, 0x85B5, 0xB040, 0x85B6, 0xB041, 0x85B7, 0xB042, 0x85B8, 0xB043, 0x85B9, + 0xB044, 0xB2F4, 0xB045, 0xB2F5, 0xB046, 0x85BA, 0xB047, 0x85BB, 0xB048, 0xB2F6, 0xB049, 0x85BC, 0xB04A, 0xB2F7, 0xB04B, 0x85BD, + 0xB04C, 0xB2F8, 0xB04D, 0x85BE, 0xB04E, 0xB2F9, 0xB04F, 0x85BF, 0xB050, 0x85C0, 0xB051, 0x85C1, 0xB052, 0x85C2, 0xB053, 0xB2FA, + 0xB054, 0xB2FB, 0xB055, 0xB2FC, 0xB056, 0x85C3, 0xB057, 0xB2FD, 0xB058, 0x85C4, 0xB059, 0xB2FE, 0xB05A, 0x85C5, 0xB05B, 0x85C6, + 0xB05C, 0x85C7, 0xB05D, 0xB3A1, 0xB05E, 0x85C8, 0xB05F, 0x85C9, 0xB060, 0x85CA, 0xB061, 0x85CB, 0xB062, 0x85CC, 0xB063, 0x85CD, + 0xB064, 0x85CE, 0xB065, 0x85CF, 0xB066, 0x85D0, 0xB067, 0x85D1, 0xB068, 0x85D2, 0xB069, 0x85D3, 0xB06A, 0x85D4, 0xB06B, 0x85D5, + 0xB06C, 0x85D6, 0xB06D, 0x85D7, 0xB06E, 0x85D8, 0xB06F, 0x85D9, 0xB070, 0x85DA, 0xB071, 0x85DB, 0xB072, 0x85DC, 0xB073, 0x85DD, + 0xB074, 0x85DE, 0xB075, 0x85DF, 0xB076, 0x85E0, 0xB077, 0x85E1, 0xB078, 0x85E2, 0xB079, 0x85E3, 0xB07A, 0x85E4, 0xB07B, 0x85E5, + 0xB07C, 0xB3A2, 0xB07D, 0xB3A3, 0xB07E, 0x85E6, 0xB07F, 0x85E7, 0xB080, 0xB3A4, 0xB081, 0x85E8, 0xB082, 0x85E9, 0xB083, 0x85EA, + 0xB084, 0xB3A5, 0xB085, 0x85EB, 0xB086, 0x85EC, 0xB087, 0x85ED, 0xB088, 0x85EE, 0xB089, 0x85EF, 0xB08A, 0x85F0, 0xB08B, 0x85F1, + 0xB08C, 0xB3A6, 0xB08D, 0xB3A7, 0xB08E, 0x85F2, 0xB08F, 0xB3A8, 0xB090, 0x85F3, 0xB091, 0xB3A9, 0xB092, 0x85F4, 0xB093, 0x85F5, + 0xB094, 0x85F6, 0xB095, 0x85F7, 0xB096, 0x85F8, 0xB097, 0x85F9, 0xB098, 0xB3AA, 0xB099, 0xB3AB, 0xB09A, 0xB3AC, 0xB09B, 0x85FA, + 0xB09C, 0xB3AD, 0xB09D, 0x85FB, 0xB09E, 0x85FC, 0xB09F, 0xB3AE, 0xB0A0, 0xB3AF, 0xB0A1, 0xB3B0, 0xB0A2, 0xB3B1, 0xB0A3, 0x85FD, + 0xB0A4, 0x85FE, 0xB0A5, 0x8641, 0xB0A6, 0x8642, 0xB0A7, 0x8643, 0xB0A8, 0xB3B2, 0xB0A9, 0xB3B3, 0xB0AA, 0x8644, 0xB0AB, 0xB3B4, + 0xB0AC, 0xB3B5, 0xB0AD, 0xB3B6, 0xB0AE, 0xB3B7, 0xB0AF, 0xB3B8, 0xB0B0, 0x8645, 0xB0B1, 0xB3B9, 0xB0B2, 0x8646, 0xB0B3, 0xB3BA, + 0xB0B4, 0xB3BB, 0xB0B5, 0xB3BC, 0xB0B6, 0x8647, 0xB0B7, 0x8648, 0xB0B8, 0xB3BD, 0xB0B9, 0x8649, 0xB0BA, 0x864A, 0xB0BB, 0x864B, + 0xB0BC, 0xB3BE, 0xB0BD, 0x864C, 0xB0BE, 0x864D, 0xB0BF, 0x864E, 0xB0C0, 0x864F, 0xB0C1, 0x8650, 0xB0C2, 0x8651, 0xB0C3, 0x8652, + 0xB0C4, 0xB3BF, 0xB0C5, 0xB3C0, 0xB0C6, 0x8653, 0xB0C7, 0xB3C1, 0xB0C8, 0xB3C2, 0xB0C9, 0xB3C3, 0xB0CA, 0x8654, 0xB0CB, 0x8655, + 0xB0CC, 0x8656, 0xB0CD, 0x8657, 0xB0CE, 0x8658, 0xB0CF, 0x8659, 0xB0D0, 0xB3C4, 0xB0D1, 0xB3C5, 0xB0D2, 0x865A, 0xB0D3, 0x8661, + 0xB0D4, 0xB3C6, 0xB0D5, 0x8662, 0xB0D6, 0x8663, 0xB0D7, 0x8664, 0xB0D8, 0xB3C7, 0xB0D9, 0x8665, 0xB0DA, 0x8666, 0xB0DB, 0x8667, + 0xB0DC, 0x8668, 0xB0DD, 0x8669, 0xB0DE, 0x866A, 0xB0DF, 0x866B, 0xB0E0, 0xB3C8, 0xB0E1, 0x866C, 0xB0E2, 0x866D, 0xB0E3, 0x866E, + 0xB0E4, 0x866F, 0xB0E5, 0xB3C9, 0xB0E6, 0x8670, 0xB0E7, 0x8671, 0xB0E8, 0x8672, 0xB0E9, 0x8673, 0xB0EA, 0x8674, 0xB0EB, 0x8675, + 0xB0EC, 0x8676, 0xB0ED, 0x8677, 0xB0EE, 0x8678, 0xB0EF, 0x8679, 0xB0F0, 0x867A, 0xB0F1, 0x8681, 0xB0F2, 0x8682, 0xB0F3, 0x8683, + 0xB0F4, 0x8684, 0xB0F5, 0x8685, 0xB0F6, 0x8686, 0xB0F7, 0x8687, 0xB0F8, 0x8688, 0xB0F9, 0x8689, 0xB0FA, 0x868A, 0xB0FB, 0x868B, + 0xB0FC, 0x868C, 0xB0FD, 0x868D, 0xB0FE, 0x868E, 0xB0FF, 0x868F, 0xB100, 0x8690, 0xB101, 0x8691, 0xB102, 0x8692, 0xB103, 0x8693, + 0xB104, 0x8694, 0xB105, 0x8695, 0xB106, 0x8696, 0xB107, 0x8697, 0xB108, 0xB3CA, 0xB109, 0xB3CB, 0xB10A, 0x8698, 0xB10B, 0xB3CC, + 0xB10C, 0xB3CD, 0xB10D, 0x8699, 0xB10E, 0x869A, 0xB10F, 0x869B, 0xB110, 0xB3CE, 0xB111, 0x869C, 0xB112, 0xB3CF, 0xB113, 0xB3D0, + 0xB114, 0x869D, 0xB115, 0x869E, 0xB116, 0x869F, 0xB117, 0x86A0, 0xB118, 0xB3D1, 0xB119, 0xB3D2, 0xB11A, 0x86A1, 0xB11B, 0xB3D3, + 0xB11C, 0xB3D4, 0xB11D, 0xB3D5, 0xB11E, 0x86A2, 0xB11F, 0x86A3, 0xB120, 0x86A4, 0xB121, 0x86A5, 0xB122, 0x86A6, 0xB123, 0xB3D6, + 0xB124, 0xB3D7, 0xB125, 0xB3D8, 0xB126, 0x86A7, 0xB127, 0x86A8, 0xB128, 0xB3D9, 0xB129, 0x86A9, 0xB12A, 0x86AA, 0xB12B, 0x86AB, + 0xB12C, 0xB3DA, 0xB12D, 0x86AC, 0xB12E, 0x86AD, 0xB12F, 0x86AE, 0xB130, 0x86AF, 0xB131, 0x86B0, 0xB132, 0x86B1, 0xB133, 0x86B2, + 0xB134, 0xB3DB, 0xB135, 0xB3DC, 0xB136, 0x86B3, 0xB137, 0xB3DD, 0xB138, 0xB3DE, 0xB139, 0xB3DF, 0xB13A, 0x86B4, 0xB13B, 0x86B5, + 0xB13C, 0x86B6, 0xB13D, 0x86B7, 0xB13E, 0x86B8, 0xB13F, 0x86B9, 0xB140, 0xB3E0, 0xB141, 0xB3E1, 0xB142, 0x86BA, 0xB143, 0x86BB, + 0xB144, 0xB3E2, 0xB145, 0x86BC, 0xB146, 0x86BD, 0xB147, 0x86BE, 0xB148, 0xB3E3, 0xB149, 0x86BF, 0xB14A, 0x86C0, 0xB14B, 0x86C1, + 0xB14C, 0x86C2, 0xB14D, 0x86C3, 0xB14E, 0x86C4, 0xB14F, 0x86C5, 0xB150, 0xB3E4, 0xB151, 0xB3E5, 0xB152, 0x86C6, 0xB153, 0x86C7, + 0xB154, 0xB3E6, 0xB155, 0xB3E7, 0xB156, 0x86C8, 0xB157, 0x86C9, 0xB158, 0xB3E8, 0xB159, 0x86CA, 0xB15A, 0x86CB, 0xB15B, 0x86CC, + 0xB15C, 0xB3E9, 0xB15D, 0x86CD, 0xB15E, 0x86CE, 0xB15F, 0x86CF, 0xB160, 0xB3EA, 0xB161, 0x86D0, 0xB162, 0x86D1, 0xB163, 0x86D2, + 0xB164, 0x86D3, 0xB165, 0x86D4, 0xB166, 0x86D5, 0xB167, 0x86D6, 0xB168, 0x86D7, 0xB169, 0x86D8, 0xB16A, 0x86D9, 0xB16B, 0x86DA, + 0xB16C, 0x86DB, 0xB16D, 0x86DC, 0xB16E, 0x86DD, 0xB16F, 0x86DE, 0xB170, 0x86DF, 0xB171, 0x86E0, 0xB172, 0x86E1, 0xB173, 0x86E2, + 0xB174, 0x86E3, 0xB175, 0x86E4, 0xB176, 0x86E5, 0xB177, 0x86E6, 0xB178, 0xB3EB, 0xB179, 0xB3EC, 0xB17A, 0x86E7, 0xB17B, 0x86E8, + 0xB17C, 0xB3ED, 0xB17D, 0x86E9, 0xB17E, 0x86EA, 0xB17F, 0x86EB, 0xB180, 0xB3EE, 0xB181, 0x86EC, 0xB182, 0xB3EF, 0xB183, 0x86ED, + 0xB184, 0x86EE, 0xB185, 0x86EF, 0xB186, 0x86F0, 0xB187, 0x86F1, 0xB188, 0xB3F0, 0xB189, 0xB3F1, 0xB18A, 0x86F2, 0xB18B, 0xB3F2, + 0xB18C, 0x86F3, 0xB18D, 0xB3F3, 0xB18E, 0x86F4, 0xB18F, 0x86F5, 0xB190, 0x86F6, 0xB191, 0x86F7, 0xB192, 0xB3F4, 0xB193, 0xB3F5, + 0xB194, 0xB3F6, 0xB195, 0x86F8, 0xB196, 0x86F9, 0xB197, 0x86FA, 0xB198, 0xB3F7, 0xB199, 0x86FB, 0xB19A, 0x86FC, 0xB19B, 0x86FD, + 0xB19C, 0xB3F8, 0xB19D, 0x86FE, 0xB19E, 0x8741, 0xB19F, 0x8742, 0xB1A0, 0x8743, 0xB1A1, 0x8744, 0xB1A2, 0x8745, 0xB1A3, 0x8746, + 0xB1A4, 0x8747, 0xB1A5, 0x8748, 0xB1A6, 0x8749, 0xB1A7, 0x874A, 0xB1A8, 0xB3F9, 0xB1A9, 0x874B, 0xB1AA, 0x874C, 0xB1AB, 0x874D, + 0xB1AC, 0x874E, 0xB1AD, 0x874F, 0xB1AE, 0x8750, 0xB1AF, 0x8751, 0xB1B0, 0x8752, 0xB1B1, 0x8753, 0xB1B2, 0x8754, 0xB1B3, 0x8755, + 0xB1B4, 0x8756, 0xB1B5, 0x8757, 0xB1B6, 0x8758, 0xB1B7, 0x8759, 0xB1B8, 0x875A, 0xB1B9, 0x8761, 0xB1BA, 0x8762, 0xB1BB, 0x8763, + 0xB1BC, 0x8764, 0xB1BD, 0x8765, 0xB1BE, 0x8766, 0xB1BF, 0x8767, 0xB1C0, 0x8768, 0xB1C1, 0x8769, 0xB1C2, 0x876A, 0xB1C3, 0x876B, + 0xB1C4, 0x876C, 0xB1C5, 0x876D, 0xB1C6, 0x876E, 0xB1C7, 0x876F, 0xB1C8, 0x8770, 0xB1C9, 0x8771, 0xB1CA, 0x8772, 0xB1CB, 0x8773, + 0xB1CC, 0xB3FA, 0xB1CD, 0x8774, 0xB1CE, 0x8775, 0xB1CF, 0x8776, 0xB1D0, 0xB3FB, 0xB1D1, 0x8777, 0xB1D2, 0x8778, 0xB1D3, 0x8779, + 0xB1D4, 0xB3FC, 0xB1D5, 0x877A, 0xB1D6, 0x8781, 0xB1D7, 0x8782, 0xB1D8, 0x8783, 0xB1D9, 0x8784, 0xB1DA, 0x8785, 0xB1DB, 0x8786, + 0xB1DC, 0xB3FD, 0xB1DD, 0xB3FE, 0xB1DE, 0x8787, 0xB1DF, 0xB4A1, 0xB1E0, 0x8788, 0xB1E1, 0x8789, 0xB1E2, 0x878A, 0xB1E3, 0x878B, + 0xB1E4, 0x878C, 0xB1E5, 0x878D, 0xB1E6, 0x878E, 0xB1E7, 0x878F, 0xB1E8, 0xB4A2, 0xB1E9, 0xB4A3, 0xB1EA, 0x8790, 0xB1EB, 0x8791, + 0xB1EC, 0xB4A4, 0xB1ED, 0x8792, 0xB1EE, 0x8793, 0xB1EF, 0x8794, 0xB1F0, 0xB4A5, 0xB1F1, 0x8795, 0xB1F2, 0x8796, 0xB1F3, 0x8797, + 0xB1F4, 0x8798, 0xB1F5, 0x8799, 0xB1F6, 0x879A, 0xB1F7, 0x879B, 0xB1F8, 0x879C, 0xB1F9, 0xB4A6, 0xB1FA, 0x879D, 0xB1FB, 0xB4A7, + 0xB1FC, 0x879E, 0xB1FD, 0xB4A8, 0xB1FE, 0x879F, 0xB1FF, 0x87A0, 0xB200, 0x87A1, 0xB201, 0x87A2, 0xB202, 0x87A3, 0xB203, 0x87A4, + 0xB204, 0xB4A9, 0xB205, 0xB4AA, 0xB206, 0x87A5, 0xB207, 0x87A6, 0xB208, 0xB4AB, 0xB209, 0x87A7, 0xB20A, 0x87A8, 0xB20B, 0xB4AC, + 0xB20C, 0xB4AD, 0xB20D, 0x87A9, 0xB20E, 0x87AA, 0xB20F, 0x87AB, 0xB210, 0x87AC, 0xB211, 0x87AD, 0xB212, 0x87AE, 0xB213, 0x87AF, + 0xB214, 0xB4AE, 0xB215, 0xB4AF, 0xB216, 0x87B0, 0xB217, 0xB4B0, 0xB218, 0x87B1, 0xB219, 0xB4B1, 0xB21A, 0x87B2, 0xB21B, 0x87B3, + 0xB21C, 0x87B4, 0xB21D, 0x87B5, 0xB21E, 0x87B6, 0xB21F, 0x87B7, 0xB220, 0xB4B2, 0xB221, 0x87B8, 0xB222, 0x87B9, 0xB223, 0x87BA, + 0xB224, 0x87BB, 0xB225, 0x87BC, 0xB226, 0x87BD, 0xB227, 0x87BE, 0xB228, 0x87BF, 0xB229, 0x87C0, 0xB22A, 0x87C1, 0xB22B, 0x87C2, + 0xB22C, 0x87C3, 0xB22D, 0x87C4, 0xB22E, 0x87C5, 0xB22F, 0x87C6, 0xB230, 0x87C7, 0xB231, 0x87C8, 0xB232, 0x87C9, 0xB233, 0x87CA, + 0xB234, 0xB4B3, 0xB235, 0x87CB, 0xB236, 0x87CC, 0xB237, 0x87CD, 0xB238, 0x87CE, 0xB239, 0x87CF, 0xB23A, 0x87D0, 0xB23B, 0x87D1, + 0xB23C, 0xB4B4, 0xB23D, 0x87D2, 0xB23E, 0x87D3, 0xB23F, 0x87D4, 0xB240, 0x87D5, 0xB241, 0x87D6, 0xB242, 0x87D7, 0xB243, 0x87D8, + 0xB244, 0x87D9, 0xB245, 0x87DA, 0xB246, 0x87DB, 0xB247, 0x87DC, 0xB248, 0x87DD, 0xB249, 0x87DE, 0xB24A, 0x87DF, 0xB24B, 0x87E0, + 0xB24C, 0x87E1, 0xB24D, 0x87E2, 0xB24E, 0x87E3, 0xB24F, 0x87E4, 0xB250, 0x87E5, 0xB251, 0x87E6, 0xB252, 0x87E7, 0xB253, 0x87E8, + 0xB254, 0x87E9, 0xB255, 0x87EA, 0xB256, 0x87EB, 0xB257, 0x87EC, 0xB258, 0xB4B5, 0xB259, 0x87ED, 0xB25A, 0x87EE, 0xB25B, 0x87EF, + 0xB25C, 0xB4B6, 0xB25D, 0x87F0, 0xB25E, 0x87F1, 0xB25F, 0x87F2, 0xB260, 0xB4B7, 0xB261, 0x87F3, 0xB262, 0x87F4, 0xB263, 0x87F5, + 0xB264, 0x87F6, 0xB265, 0x87F7, 0xB266, 0x87F8, 0xB267, 0x87F9, 0xB268, 0xB4B8, 0xB269, 0xB4B9, 0xB26A, 0x87FA, 0xB26B, 0x87FB, + 0xB26C, 0x87FC, 0xB26D, 0x87FD, 0xB26E, 0x87FE, 0xB26F, 0x8841, 0xB270, 0x8842, 0xB271, 0x8843, 0xB272, 0x8844, 0xB273, 0x8845, + 0xB274, 0xB4BA, 0xB275, 0xB4BB, 0xB276, 0x8846, 0xB277, 0x8847, 0xB278, 0x8848, 0xB279, 0x8849, 0xB27A, 0x884A, 0xB27B, 0x884B, + 0xB27C, 0xB4BC, 0xB27D, 0x884C, 0xB27E, 0x884D, 0xB27F, 0x884E, 0xB280, 0x884F, 0xB281, 0x8850, 0xB282, 0x8851, 0xB283, 0x8852, + 0xB284, 0xB4BD, 0xB285, 0xB4BE, 0xB286, 0x8853, 0xB287, 0x8854, 0xB288, 0x8855, 0xB289, 0xB4BF, 0xB28A, 0x8856, 0xB28B, 0x8857, + 0xB28C, 0x8858, 0xB28D, 0x8859, 0xB28E, 0x885A, 0xB28F, 0x8861, 0xB290, 0xB4C0, 0xB291, 0xB4C1, 0xB292, 0x8862, 0xB293, 0x8863, + 0xB294, 0xB4C2, 0xB295, 0x8864, 0xB296, 0x8865, 0xB297, 0x8866, 0xB298, 0xB4C3, 0xB299, 0xB4C4, 0xB29A, 0xB4C5, 0xB29B, 0x8867, + 0xB29C, 0x8868, 0xB29D, 0x8869, 0xB29E, 0x886A, 0xB29F, 0x886B, 0xB2A0, 0xB4C6, 0xB2A1, 0xB4C7, 0xB2A2, 0x886C, 0xB2A3, 0xB4C8, + 0xB2A4, 0x886D, 0xB2A5, 0xB4C9, 0xB2A6, 0xB4CA, 0xB2A7, 0x886E, 0xB2A8, 0x886F, 0xB2A9, 0x8870, 0xB2AA, 0xB4CB, 0xB2AB, 0x8871, + 0xB2AC, 0xB4CC, 0xB2AD, 0x8872, 0xB2AE, 0x8873, 0xB2AF, 0x8874, 0xB2B0, 0xB4CD, 0xB2B1, 0x8875, 0xB2B2, 0x8876, 0xB2B3, 0x8877, + 0xB2B4, 0xB4CE, 0xB2B5, 0x8878, 0xB2B6, 0x8879, 0xB2B7, 0x887A, 0xB2B8, 0x8881, 0xB2B9, 0x8882, 0xB2BA, 0x8883, 0xB2BB, 0x8884, + 0xB2BC, 0x8885, 0xB2BD, 0x8886, 0xB2BE, 0x8887, 0xB2BF, 0x8888, 0xB2C0, 0x8889, 0xB2C1, 0x888A, 0xB2C2, 0x888B, 0xB2C3, 0x888C, + 0xB2C4, 0x888D, 0xB2C5, 0x888E, 0xB2C6, 0x888F, 0xB2C7, 0x8890, 0xB2C8, 0xB4CF, 0xB2C9, 0xB4D0, 0xB2CA, 0x8891, 0xB2CB, 0x8892, + 0xB2CC, 0xB4D1, 0xB2CD, 0x8893, 0xB2CE, 0x8894, 0xB2CF, 0x8895, 0xB2D0, 0xB4D2, 0xB2D1, 0x8896, 0xB2D2, 0xB4D3, 0xB2D3, 0x8897, + 0xB2D4, 0x8898, 0xB2D5, 0x8899, 0xB2D6, 0x889A, 0xB2D7, 0x889B, 0xB2D8, 0xB4D4, 0xB2D9, 0xB4D5, 0xB2DA, 0x889C, 0xB2DB, 0xB4D6, + 0xB2DC, 0x889D, 0xB2DD, 0xB4D7, 0xB2DE, 0x889E, 0xB2DF, 0x889F, 0xB2E0, 0x88A0, 0xB2E1, 0x88A1, 0xB2E2, 0xB4D8, 0xB2E3, 0x88A2, + 0xB2E4, 0xB4D9, 0xB2E5, 0xB4DA, 0xB2E6, 0xB4DB, 0xB2E7, 0x88A3, 0xB2E8, 0xB4DC, 0xB2E9, 0x88A4, 0xB2EA, 0x88A5, 0xB2EB, 0xB4DD, + 0xB2EC, 0xB4DE, 0xB2ED, 0xB4DF, 0xB2EE, 0xB4E0, 0xB2EF, 0xB4E1, 0xB2F0, 0x88A6, 0xB2F1, 0x88A7, 0xB2F2, 0x88A8, 0xB2F3, 0xB4E2, + 0xB2F4, 0xB4E3, 0xB2F5, 0xB4E4, 0xB2F6, 0x88A9, 0xB2F7, 0xB4E5, 0xB2F8, 0xB4E6, 0xB2F9, 0xB4E7, 0xB2FA, 0xB4E8, 0xB2FB, 0xB4E9, + 0xB2FC, 0x88AA, 0xB2FD, 0x88AB, 0xB2FE, 0x88AC, 0xB2FF, 0xB4EA, 0xB300, 0xB4EB, 0xB301, 0xB4EC, 0xB302, 0x88AD, 0xB303, 0x88AE, + 0xB304, 0xB4ED, 0xB305, 0x88AF, 0xB306, 0x88B0, 0xB307, 0x88B1, 0xB308, 0xB4EE, 0xB309, 0x88B2, 0xB30A, 0x88B3, 0xB30B, 0x88B4, + 0xB30C, 0x88B5, 0xB30D, 0x88B6, 0xB30E, 0x88B7, 0xB30F, 0x88B8, 0xB310, 0xB4EF, 0xB311, 0xB4F0, 0xB312, 0x88B9, 0xB313, 0xB4F1, + 0xB314, 0xB4F2, 0xB315, 0xB4F3, 0xB316, 0x88BA, 0xB317, 0x88BB, 0xB318, 0x88BC, 0xB319, 0x88BD, 0xB31A, 0x88BE, 0xB31B, 0x88BF, + 0xB31C, 0xB4F4, 0xB31D, 0x88C0, 0xB31E, 0x88C1, 0xB31F, 0x88C2, 0xB320, 0x88C3, 0xB321, 0x88C4, 0xB322, 0x88C5, 0xB323, 0x88C6, + 0xB324, 0x88C7, 0xB325, 0x88C8, 0xB326, 0x88C9, 0xB327, 0x88CA, 0xB328, 0x88CB, 0xB329, 0x88CC, 0xB32A, 0x88CD, 0xB32B, 0x88CE, + 0xB32C, 0x88CF, 0xB32D, 0x88D0, 0xB32E, 0x88D1, 0xB32F, 0x88D2, 0xB330, 0x88D3, 0xB331, 0x88D4, 0xB332, 0x88D5, 0xB333, 0x88D6, + 0xB334, 0x88D7, 0xB335, 0x88D8, 0xB336, 0x88D9, 0xB337, 0x88DA, 0xB338, 0x88DB, 0xB339, 0x88DC, 0xB33A, 0x88DD, 0xB33B, 0x88DE, + 0xB33C, 0x88DF, 0xB33D, 0x88E0, 0xB33E, 0x88E1, 0xB33F, 0x88E2, 0xB340, 0x88E3, 0xB341, 0x88E4, 0xB342, 0x88E5, 0xB343, 0x88E6, + 0xB344, 0x88E7, 0xB345, 0x88E8, 0xB346, 0x88E9, 0xB347, 0x88EA, 0xB348, 0x88EB, 0xB349, 0x88EC, 0xB34A, 0x88ED, 0xB34B, 0x88EE, + 0xB34C, 0x88EF, 0xB34D, 0x88F0, 0xB34E, 0x88F1, 0xB34F, 0x88F2, 0xB350, 0x88F3, 0xB351, 0x88F4, 0xB352, 0x88F5, 0xB353, 0x88F6, + 0xB354, 0xB4F5, 0xB355, 0xB4F6, 0xB356, 0xB4F7, 0xB357, 0x88F7, 0xB358, 0xB4F8, 0xB359, 0x88F8, 0xB35A, 0x88F9, 0xB35B, 0xB4F9, + 0xB35C, 0xB4FA, 0xB35D, 0x88FA, 0xB35E, 0xB4FB, 0xB35F, 0xB4FC, 0xB360, 0x88FB, 0xB361, 0x88FC, 0xB362, 0x88FD, 0xB363, 0x88FE, + 0xB364, 0xB4FD, 0xB365, 0xB4FE, 0xB366, 0x8941, 0xB367, 0xB5A1, 0xB368, 0x8942, 0xB369, 0xB5A2, 0xB36A, 0x8943, 0xB36B, 0xB5A3, + 0xB36C, 0x8944, 0xB36D, 0x8945, 0xB36E, 0xB5A4, 0xB36F, 0x8946, 0xB370, 0xB5A5, 0xB371, 0xB5A6, 0xB372, 0x8947, 0xB373, 0x8948, + 0xB374, 0xB5A7, 0xB375, 0x8949, 0xB376, 0x894A, 0xB377, 0x894B, 0xB378, 0xB5A8, 0xB379, 0x894C, 0xB37A, 0x894D, 0xB37B, 0x894E, + 0xB37C, 0x894F, 0xB37D, 0x8950, 0xB37E, 0x8951, 0xB37F, 0x8952, 0xB380, 0xB5A9, 0xB381, 0xB5AA, 0xB382, 0x8953, 0xB383, 0xB5AB, + 0xB384, 0xB5AC, 0xB385, 0xB5AD, 0xB386, 0x8954, 0xB387, 0x8955, 0xB388, 0x8956, 0xB389, 0x8957, 0xB38A, 0x8958, 0xB38B, 0x8959, + 0xB38C, 0xB5AE, 0xB38D, 0x895A, 0xB38E, 0x8961, 0xB38F, 0x8962, 0xB390, 0xB5AF, 0xB391, 0x8963, 0xB392, 0x8964, 0xB393, 0x8965, + 0xB394, 0xB5B0, 0xB395, 0x8966, 0xB396, 0x8967, 0xB397, 0x8968, 0xB398, 0x8969, 0xB399, 0x896A, 0xB39A, 0x896B, 0xB39B, 0x896C, + 0xB39C, 0x896D, 0xB39D, 0x896E, 0xB39E, 0x896F, 0xB39F, 0x8970, 0xB3A0, 0xB5B1, 0xB3A1, 0xB5B2, 0xB3A2, 0x8971, 0xB3A3, 0x8972, + 0xB3A4, 0x8973, 0xB3A5, 0x8974, 0xB3A6, 0x8975, 0xB3A7, 0x8976, 0xB3A8, 0xB5B3, 0xB3A9, 0x8977, 0xB3AA, 0x8978, 0xB3AB, 0x8979, + 0xB3AC, 0xB5B4, 0xB3AD, 0x897A, 0xB3AE, 0x8981, 0xB3AF, 0x8982, 0xB3B0, 0x8983, 0xB3B1, 0x8984, 0xB3B2, 0x8985, 0xB3B3, 0x8986, + 0xB3B4, 0x8987, 0xB3B5, 0x8988, 0xB3B6, 0x8989, 0xB3B7, 0x898A, 0xB3B8, 0x898B, 0xB3B9, 0x898C, 0xB3BA, 0x898D, 0xB3BB, 0x898E, + 0xB3BC, 0x898F, 0xB3BD, 0x8990, 0xB3BE, 0x8991, 0xB3BF, 0x8992, 0xB3C0, 0x8993, 0xB3C1, 0x8994, 0xB3C2, 0x8995, 0xB3C3, 0x8996, + 0xB3C4, 0xB5B5, 0xB3C5, 0xB5B6, 0xB3C6, 0x8997, 0xB3C7, 0x8998, 0xB3C8, 0xB5B7, 0xB3C9, 0x8999, 0xB3CA, 0x899A, 0xB3CB, 0xB5B8, + 0xB3CC, 0xB5B9, 0xB3CD, 0x899B, 0xB3CE, 0xB5BA, 0xB3CF, 0x899C, 0xB3D0, 0xB5BB, 0xB3D1, 0x899D, 0xB3D2, 0x899E, 0xB3D3, 0x899F, + 0xB3D4, 0xB5BC, 0xB3D5, 0xB5BD, 0xB3D6, 0x89A0, 0xB3D7, 0xB5BE, 0xB3D8, 0x89A1, 0xB3D9, 0xB5BF, 0xB3DA, 0x89A2, 0xB3DB, 0xB5C0, + 0xB3DC, 0x89A3, 0xB3DD, 0xB5C1, 0xB3DE, 0x89A4, 0xB3DF, 0x89A5, 0xB3E0, 0xB5C2, 0xB3E1, 0x89A6, 0xB3E2, 0x89A7, 0xB3E3, 0x89A8, + 0xB3E4, 0xB5C3, 0xB3E5, 0x89A9, 0xB3E6, 0x89AA, 0xB3E7, 0x89AB, 0xB3E8, 0xB5C4, 0xB3E9, 0x89AC, 0xB3EA, 0x89AD, 0xB3EB, 0x89AE, + 0xB3EC, 0x89AF, 0xB3ED, 0x89B0, 0xB3EE, 0x89B1, 0xB3EF, 0x89B2, 0xB3F0, 0x89B3, 0xB3F1, 0x89B4, 0xB3F2, 0x89B5, 0xB3F3, 0x89B6, + 0xB3F4, 0x89B7, 0xB3F5, 0x89B8, 0xB3F6, 0x89B9, 0xB3F7, 0x89BA, 0xB3F8, 0x89BB, 0xB3F9, 0x89BC, 0xB3FA, 0x89BD, 0xB3FB, 0x89BE, + 0xB3FC, 0xB5C5, 0xB3FD, 0x89BF, 0xB3FE, 0x89C0, 0xB3FF, 0x89C1, 0xB400, 0x89C2, 0xB401, 0x89C3, 0xB402, 0x89C4, 0xB403, 0x89C5, + 0xB404, 0x89C6, 0xB405, 0x89C7, 0xB406, 0x89C8, 0xB407, 0x89C9, 0xB408, 0x89CA, 0xB409, 0x89CB, 0xB40A, 0x89CC, 0xB40B, 0x89CD, + 0xB40C, 0x89CE, 0xB40D, 0x89CF, 0xB40E, 0x89D0, 0xB40F, 0x89D1, 0xB410, 0xB5C6, 0xB411, 0x89D2, 0xB412, 0x89D3, 0xB413, 0x89D4, + 0xB414, 0x89D5, 0xB415, 0x89D6, 0xB416, 0x89D7, 0xB417, 0x89D8, 0xB418, 0xB5C7, 0xB419, 0x89D9, 0xB41A, 0x89DA, 0xB41B, 0x89DB, + 0xB41C, 0xB5C8, 0xB41D, 0x89DC, 0xB41E, 0x89DD, 0xB41F, 0x89DE, 0xB420, 0xB5C9, 0xB421, 0x89DF, 0xB422, 0x89E0, 0xB423, 0x89E1, + 0xB424, 0x89E2, 0xB425, 0x89E3, 0xB426, 0x89E4, 0xB427, 0x89E5, 0xB428, 0xB5CA, 0xB429, 0xB5CB, 0xB42A, 0x89E6, 0xB42B, 0xB5CC, + 0xB42C, 0x89E7, 0xB42D, 0x89E8, 0xB42E, 0x89E9, 0xB42F, 0x89EA, 0xB430, 0x89EB, 0xB431, 0x89EC, 0xB432, 0x89ED, 0xB433, 0x89EE, + 0xB434, 0xB5CD, 0xB435, 0x89EF, 0xB436, 0x89F0, 0xB437, 0x89F1, 0xB438, 0x89F2, 0xB439, 0x89F3, 0xB43A, 0x89F4, 0xB43B, 0x89F5, + 0xB43C, 0x89F6, 0xB43D, 0x89F7, 0xB43E, 0x89F8, 0xB43F, 0x89F9, 0xB440, 0x89FA, 0xB441, 0x89FB, 0xB442, 0x89FC, 0xB443, 0x89FD, + 0xB444, 0x89FE, 0xB445, 0x8A41, 0xB446, 0x8A42, 0xB447, 0x8A43, 0xB448, 0x8A44, 0xB449, 0x8A45, 0xB44A, 0x8A46, 0xB44B, 0x8A47, + 0xB44C, 0x8A48, 0xB44D, 0x8A49, 0xB44E, 0x8A4A, 0xB44F, 0x8A4B, 0xB450, 0xB5CE, 0xB451, 0xB5CF, 0xB452, 0x8A4C, 0xB453, 0x8A4D, + 0xB454, 0xB5D0, 0xB455, 0x8A4E, 0xB456, 0x8A4F, 0xB457, 0x8A50, 0xB458, 0xB5D1, 0xB459, 0x8A51, 0xB45A, 0x8A52, 0xB45B, 0x8A53, + 0xB45C, 0x8A54, 0xB45D, 0x8A55, 0xB45E, 0x8A56, 0xB45F, 0x8A57, 0xB460, 0xB5D2, 0xB461, 0xB5D3, 0xB462, 0x8A58, 0xB463, 0xB5D4, + 0xB464, 0x8A59, 0xB465, 0xB5D5, 0xB466, 0x8A5A, 0xB467, 0x8A61, 0xB468, 0x8A62, 0xB469, 0x8A63, 0xB46A, 0x8A64, 0xB46B, 0x8A65, + 0xB46C, 0xB5D6, 0xB46D, 0x8A66, 0xB46E, 0x8A67, 0xB46F, 0x8A68, 0xB470, 0x8A69, 0xB471, 0x8A6A, 0xB472, 0x8A6B, 0xB473, 0x8A6C, + 0xB474, 0x8A6D, 0xB475, 0x8A6E, 0xB476, 0x8A6F, 0xB477, 0x8A70, 0xB478, 0x8A71, 0xB479, 0x8A72, 0xB47A, 0x8A73, 0xB47B, 0x8A74, + 0xB47C, 0x8A75, 0xB47D, 0x8A76, 0xB47E, 0x8A77, 0xB47F, 0x8A78, 0xB480, 0xB5D7, 0xB481, 0x8A79, 0xB482, 0x8A7A, 0xB483, 0x8A81, + 0xB484, 0x8A82, 0xB485, 0x8A83, 0xB486, 0x8A84, 0xB487, 0x8A85, 0xB488, 0xB5D8, 0xB489, 0x8A86, 0xB48A, 0x8A87, 0xB48B, 0x8A88, + 0xB48C, 0x8A89, 0xB48D, 0x8A8A, 0xB48E, 0x8A8B, 0xB48F, 0x8A8C, 0xB490, 0x8A8D, 0xB491, 0x8A8E, 0xB492, 0x8A8F, 0xB493, 0x8A90, + 0xB494, 0x8A91, 0xB495, 0x8A92, 0xB496, 0x8A93, 0xB497, 0x8A94, 0xB498, 0x8A95, 0xB499, 0x8A96, 0xB49A, 0x8A97, 0xB49B, 0x8A98, + 0xB49C, 0x8A99, 0xB49D, 0xB5D9, 0xB49E, 0x8A9A, 0xB49F, 0x8A9B, 0xB4A0, 0x8A9C, 0xB4A1, 0x8A9D, 0xB4A2, 0x8A9E, 0xB4A3, 0x8A9F, + 0xB4A4, 0xB5DA, 0xB4A5, 0x8AA0, 0xB4A6, 0x8AA1, 0xB4A7, 0x8AA2, 0xB4A8, 0xB5DB, 0xB4A9, 0x8AA3, 0xB4AA, 0x8AA4, 0xB4AB, 0x8AA5, + 0xB4AC, 0xB5DC, 0xB4AD, 0x8AA6, 0xB4AE, 0x8AA7, 0xB4AF, 0x8AA8, 0xB4B0, 0x8AA9, 0xB4B1, 0x8AAA, 0xB4B2, 0x8AAB, 0xB4B3, 0x8AAC, + 0xB4B4, 0x8AAD, 0xB4B5, 0xB5DD, 0xB4B6, 0x8AAE, 0xB4B7, 0xB5DE, 0xB4B8, 0x8AAF, 0xB4B9, 0xB5DF, 0xB4BA, 0x8AB0, 0xB4BB, 0x8AB1, + 0xB4BC, 0x8AB2, 0xB4BD, 0x8AB3, 0xB4BE, 0x8AB4, 0xB4BF, 0x8AB5, 0xB4C0, 0xB5E0, 0xB4C1, 0x8AB6, 0xB4C2, 0x8AB7, 0xB4C3, 0x8AB8, + 0xB4C4, 0xB5E1, 0xB4C5, 0x8AB9, 0xB4C6, 0x8ABA, 0xB4C7, 0x8ABB, 0xB4C8, 0xB5E2, 0xB4C9, 0x8ABC, 0xB4CA, 0x8ABD, 0xB4CB, 0x8ABE, + 0xB4CC, 0x8ABF, 0xB4CD, 0x8AC0, 0xB4CE, 0x8AC1, 0xB4CF, 0x8AC2, 0xB4D0, 0xB5E3, 0xB4D1, 0x8AC3, 0xB4D2, 0x8AC4, 0xB4D3, 0x8AC5, + 0xB4D4, 0x8AC6, 0xB4D5, 0xB5E4, 0xB4D6, 0x8AC7, 0xB4D7, 0x8AC8, 0xB4D8, 0x8AC9, 0xB4D9, 0x8ACA, 0xB4DA, 0x8ACB, 0xB4DB, 0x8ACC, + 0xB4DC, 0xB5E5, 0xB4DD, 0xB5E6, 0xB4DE, 0x8ACD, 0xB4DF, 0x8ACE, 0xB4E0, 0xB5E7, 0xB4E1, 0x8ACF, 0xB4E2, 0x8AD0, 0xB4E3, 0xB5E8, + 0xB4E4, 0xB5E9, 0xB4E5, 0x8AD1, 0xB4E6, 0xB5EA, 0xB4E7, 0x8AD2, 0xB4E8, 0x8AD3, 0xB4E9, 0x8AD4, 0xB4EA, 0x8AD5, 0xB4EB, 0x8AD6, + 0xB4EC, 0xB5EB, 0xB4ED, 0xB5EC, 0xB4EE, 0x8AD7, 0xB4EF, 0xB5ED, 0xB4F0, 0x8AD8, 0xB4F1, 0xB5EE, 0xB4F2, 0x8AD9, 0xB4F3, 0x8ADA, + 0xB4F4, 0x8ADB, 0xB4F5, 0x8ADC, 0xB4F6, 0x8ADD, 0xB4F7, 0x8ADE, 0xB4F8, 0xB5EF, 0xB4F9, 0x8ADF, 0xB4FA, 0x8AE0, 0xB4FB, 0x8AE1, + 0xB4FC, 0x8AE2, 0xB4FD, 0x8AE3, 0xB4FE, 0x8AE4, 0xB4FF, 0x8AE5, 0xB500, 0x8AE6, 0xB501, 0x8AE7, 0xB502, 0x8AE8, 0xB503, 0x8AE9, + 0xB504, 0x8AEA, 0xB505, 0x8AEB, 0xB506, 0x8AEC, 0xB507, 0x8AED, 0xB508, 0x8AEE, 0xB509, 0x8AEF, 0xB50A, 0x8AF0, 0xB50B, 0x8AF1, + 0xB50C, 0x8AF2, 0xB50D, 0x8AF3, 0xB50E, 0x8AF4, 0xB50F, 0x8AF5, 0xB510, 0x8AF6, 0xB511, 0x8AF7, 0xB512, 0x8AF8, 0xB513, 0x8AF9, + 0xB514, 0xB5F0, 0xB515, 0xB5F1, 0xB516, 0x8AFA, 0xB517, 0x8AFB, 0xB518, 0xB5F2, 0xB519, 0x8AFC, 0xB51A, 0x8AFD, 0xB51B, 0xB5F3, + 0xB51C, 0xB5F4, 0xB51D, 0x8AFE, 0xB51E, 0x8B41, 0xB51F, 0x8B42, 0xB520, 0x8B43, 0xB521, 0x8B44, 0xB522, 0x8B45, 0xB523, 0x8B46, + 0xB524, 0xB5F5, 0xB525, 0xB5F6, 0xB526, 0x8B47, 0xB527, 0xB5F7, 0xB528, 0xB5F8, 0xB529, 0xB5F9, 0xB52A, 0xB5FA, 0xB52B, 0x8B48, + 0xB52C, 0x8B49, 0xB52D, 0x8B4A, 0xB52E, 0x8B4B, 0xB52F, 0x8B4C, 0xB530, 0xB5FB, 0xB531, 0xB5FC, 0xB532, 0x8B4D, 0xB533, 0x8B4E, + 0xB534, 0xB5FD, 0xB535, 0x8B4F, 0xB536, 0x8B50, 0xB537, 0x8B51, 0xB538, 0xB5FE, 0xB539, 0x8B52, 0xB53A, 0x8B53, 0xB53B, 0x8B54, + 0xB53C, 0x8B55, 0xB53D, 0x8B56, 0xB53E, 0x8B57, 0xB53F, 0x8B58, 0xB540, 0xB6A1, 0xB541, 0xB6A2, 0xB542, 0x8B59, 0xB543, 0xB6A3, + 0xB544, 0xB6A4, 0xB545, 0xB6A5, 0xB546, 0x8B5A, 0xB547, 0x8B61, 0xB548, 0x8B62, 0xB549, 0x8B63, 0xB54A, 0x8B64, 0xB54B, 0xB6A6, + 0xB54C, 0xB6A7, 0xB54D, 0xB6A8, 0xB54E, 0x8B65, 0xB54F, 0x8B66, 0xB550, 0xB6A9, 0xB551, 0x8B67, 0xB552, 0x8B68, 0xB553, 0x8B69, + 0xB554, 0xB6AA, 0xB555, 0x8B6A, 0xB556, 0x8B6B, 0xB557, 0x8B6C, 0xB558, 0x8B6D, 0xB559, 0x8B6E, 0xB55A, 0x8B6F, 0xB55B, 0x8B70, + 0xB55C, 0xB6AB, 0xB55D, 0xB6AC, 0xB55E, 0x8B71, 0xB55F, 0xB6AD, 0xB560, 0xB6AE, 0xB561, 0xB6AF, 0xB562, 0x8B72, 0xB563, 0x8B73, + 0xB564, 0x8B74, 0xB565, 0x8B75, 0xB566, 0x8B76, 0xB567, 0x8B77, 0xB568, 0x8B78, 0xB569, 0x8B79, 0xB56A, 0x8B7A, 0xB56B, 0x8B81, + 0xB56C, 0x8B82, 0xB56D, 0x8B83, 0xB56E, 0x8B84, 0xB56F, 0x8B85, 0xB570, 0x8B86, 0xB571, 0x8B87, 0xB572, 0x8B88, 0xB573, 0x8B89, + 0xB574, 0x8B8A, 0xB575, 0x8B8B, 0xB576, 0x8B8C, 0xB577, 0x8B8D, 0xB578, 0x8B8E, 0xB579, 0x8B8F, 0xB57A, 0x8B90, 0xB57B, 0x8B91, + 0xB57C, 0x8B92, 0xB57D, 0x8B93, 0xB57E, 0x8B94, 0xB57F, 0x8B95, 0xB580, 0x8B96, 0xB581, 0x8B97, 0xB582, 0x8B98, 0xB583, 0x8B99, + 0xB584, 0x8B9A, 0xB585, 0x8B9B, 0xB586, 0x8B9C, 0xB587, 0x8B9D, 0xB588, 0x8B9E, 0xB589, 0x8B9F, 0xB58A, 0x8BA0, 0xB58B, 0x8BA1, + 0xB58C, 0x8BA2, 0xB58D, 0x8BA3, 0xB58E, 0x8BA4, 0xB58F, 0x8BA5, 0xB590, 0x8BA6, 0xB591, 0x8BA7, 0xB592, 0x8BA8, 0xB593, 0x8BA9, + 0xB594, 0x8BAA, 0xB595, 0x8BAB, 0xB596, 0x8BAC, 0xB597, 0x8BAD, 0xB598, 0x8BAE, 0xB599, 0x8BAF, 0xB59A, 0x8BB0, 0xB59B, 0x8BB1, + 0xB59C, 0x8BB2, 0xB59D, 0x8BB3, 0xB59E, 0x8BB4, 0xB59F, 0x8BB5, 0xB5A0, 0xB6B0, 0xB5A1, 0xB6B1, 0xB5A2, 0x8BB6, 0xB5A3, 0x8BB7, + 0xB5A4, 0xB6B2, 0xB5A5, 0x8BB8, 0xB5A6, 0x8BB9, 0xB5A7, 0x8BBA, 0xB5A8, 0xB6B3, 0xB5A9, 0x8BBB, 0xB5AA, 0xB6B4, 0xB5AB, 0xB6B5, + 0xB5AC, 0x8BBC, 0xB5AD, 0x8BBD, 0xB5AE, 0x8BBE, 0xB5AF, 0x8BBF, 0xB5B0, 0xB6B6, 0xB5B1, 0xB6B7, 0xB5B2, 0x8BC0, 0xB5B3, 0xB6B8, + 0xB5B4, 0xB6B9, 0xB5B5, 0xB6BA, 0xB5B6, 0x8BC1, 0xB5B7, 0x8BC2, 0xB5B8, 0x8BC3, 0xB5B9, 0x8BC4, 0xB5BA, 0x8BC5, 0xB5BB, 0xB6BB, + 0xB5BC, 0xB6BC, 0xB5BD, 0xB6BD, 0xB5BE, 0x8BC6, 0xB5BF, 0x8BC7, 0xB5C0, 0xB6BE, 0xB5C1, 0x8BC8, 0xB5C2, 0x8BC9, 0xB5C3, 0x8BCA, + 0xB5C4, 0xB6BF, 0xB5C5, 0x8BCB, 0xB5C6, 0x8BCC, 0xB5C7, 0x8BCD, 0xB5C8, 0x8BCE, 0xB5C9, 0x8BCF, 0xB5CA, 0x8BD0, 0xB5CB, 0x8BD1, + 0xB5CC, 0xB6C0, 0xB5CD, 0xB6C1, 0xB5CE, 0x8BD2, 0xB5CF, 0xB6C2, 0xB5D0, 0xB6C3, 0xB5D1, 0xB6C4, 0xB5D2, 0x8BD3, 0xB5D3, 0x8BD4, + 0xB5D4, 0x8BD5, 0xB5D5, 0x8BD6, 0xB5D6, 0x8BD7, 0xB5D7, 0x8BD8, 0xB5D8, 0xB6C5, 0xB5D9, 0x8BD9, 0xB5DA, 0x8BDA, 0xB5DB, 0x8BDB, + 0xB5DC, 0x8BDC, 0xB5DD, 0x8BDD, 0xB5DE, 0x8BDE, 0xB5DF, 0x8BDF, 0xB5E0, 0x8BE0, 0xB5E1, 0x8BE1, 0xB5E2, 0x8BE2, 0xB5E3, 0x8BE3, + 0xB5E4, 0x8BE4, 0xB5E5, 0x8BE5, 0xB5E6, 0x8BE6, 0xB5E7, 0x8BE7, 0xB5E8, 0x8BE8, 0xB5E9, 0x8BE9, 0xB5EA, 0x8BEA, 0xB5EB, 0x8BEB, + 0xB5EC, 0xB6C6, 0xB5ED, 0x8BEC, 0xB5EE, 0x8BED, 0xB5EF, 0x8BEE, 0xB5F0, 0x8BEF, 0xB5F1, 0x8BF0, 0xB5F2, 0x8BF1, 0xB5F3, 0x8BF2, + 0xB5F4, 0x8BF3, 0xB5F5, 0x8BF4, 0xB5F6, 0x8BF5, 0xB5F7, 0x8BF6, 0xB5F8, 0x8BF7, 0xB5F9, 0x8BF8, 0xB5FA, 0x8BF9, 0xB5FB, 0x8BFA, + 0xB5FC, 0x8BFB, 0xB5FD, 0x8BFC, 0xB5FE, 0x8BFD, 0xB5FF, 0x8BFE, 0xB600, 0x8C41, 0xB601, 0x8C42, 0xB602, 0x8C43, 0xB603, 0x8C44, + 0xB604, 0x8C45, 0xB605, 0x8C46, 0xB606, 0x8C47, 0xB607, 0x8C48, 0xB608, 0x8C49, 0xB609, 0x8C4A, 0xB60A, 0x8C4B, 0xB60B, 0x8C4C, + 0xB60C, 0x8C4D, 0xB60D, 0x8C4E, 0xB60E, 0x8C4F, 0xB60F, 0x8C50, 0xB610, 0xB6C7, 0xB611, 0xB6C8, 0xB612, 0x8C51, 0xB613, 0x8C52, + 0xB614, 0xB6C9, 0xB615, 0x8C53, 0xB616, 0x8C54, 0xB617, 0x8C55, 0xB618, 0xB6CA, 0xB619, 0x8C56, 0xB61A, 0x8C57, 0xB61B, 0x8C58, + 0xB61C, 0x8C59, 0xB61D, 0x8C5A, 0xB61E, 0x8C61, 0xB61F, 0x8C62, 0xB620, 0x8C63, 0xB621, 0x8C64, 0xB622, 0x8C65, 0xB623, 0x8C66, + 0xB624, 0x8C67, 0xB625, 0xB6CB, 0xB626, 0x8C68, 0xB627, 0x8C69, 0xB628, 0x8C6A, 0xB629, 0x8C6B, 0xB62A, 0x8C6C, 0xB62B, 0x8C6D, + 0xB62C, 0xB6CC, 0xB62D, 0x8C6E, 0xB62E, 0x8C6F, 0xB62F, 0x8C70, 0xB630, 0x8C71, 0xB631, 0x8C72, 0xB632, 0x8C73, 0xB633, 0x8C74, + 0xB634, 0xB6CD, 0xB635, 0x8C75, 0xB636, 0x8C76, 0xB637, 0x8C77, 0xB638, 0x8C78, 0xB639, 0x8C79, 0xB63A, 0x8C7A, 0xB63B, 0x8C81, + 0xB63C, 0x8C82, 0xB63D, 0x8C83, 0xB63E, 0x8C84, 0xB63F, 0x8C85, 0xB640, 0x8C86, 0xB641, 0x8C87, 0xB642, 0x8C88, 0xB643, 0x8C89, + 0xB644, 0x8C8A, 0xB645, 0x8C8B, 0xB646, 0x8C8C, 0xB647, 0x8C8D, 0xB648, 0xB6CE, 0xB649, 0x8C8E, 0xB64A, 0x8C8F, 0xB64B, 0x8C90, + 0xB64C, 0x8C91, 0xB64D, 0x8C92, 0xB64E, 0x8C93, 0xB64F, 0x8C94, 0xB650, 0x8C95, 0xB651, 0x8C96, 0xB652, 0x8C97, 0xB653, 0x8C98, + 0xB654, 0x8C99, 0xB655, 0x8C9A, 0xB656, 0x8C9B, 0xB657, 0x8C9C, 0xB658, 0x8C9D, 0xB659, 0x8C9E, 0xB65A, 0x8C9F, 0xB65B, 0x8CA0, + 0xB65C, 0x8CA1, 0xB65D, 0x8CA2, 0xB65E, 0x8CA3, 0xB65F, 0x8CA4, 0xB660, 0x8CA5, 0xB661, 0x8CA6, 0xB662, 0x8CA7, 0xB663, 0x8CA8, + 0xB664, 0xB6CF, 0xB665, 0x8CA9, 0xB666, 0x8CAA, 0xB667, 0x8CAB, 0xB668, 0xB6D0, 0xB669, 0x8CAC, 0xB66A, 0x8CAD, 0xB66B, 0x8CAE, + 0xB66C, 0x8CAF, 0xB66D, 0x8CB0, 0xB66E, 0x8CB1, 0xB66F, 0x8CB2, 0xB670, 0x8CB3, 0xB671, 0x8CB4, 0xB672, 0x8CB5, 0xB673, 0x8CB6, + 0xB674, 0x8CB7, 0xB675, 0x8CB8, 0xB676, 0x8CB9, 0xB677, 0x8CBA, 0xB678, 0x8CBB, 0xB679, 0x8CBC, 0xB67A, 0x8CBD, 0xB67B, 0x8CBE, + 0xB67C, 0x8CBF, 0xB67D, 0x8CC0, 0xB67E, 0x8CC1, 0xB67F, 0x8CC2, 0xB680, 0x8CC3, 0xB681, 0x8CC4, 0xB682, 0x8CC5, 0xB683, 0x8CC6, + 0xB684, 0x8CC7, 0xB685, 0x8CC8, 0xB686, 0x8CC9, 0xB687, 0x8CCA, 0xB688, 0x8CCB, 0xB689, 0x8CCC, 0xB68A, 0x8CCD, 0xB68B, 0x8CCE, + 0xB68C, 0x8CCF, 0xB68D, 0x8CD0, 0xB68E, 0x8CD1, 0xB68F, 0x8CD2, 0xB690, 0x8CD3, 0xB691, 0x8CD4, 0xB692, 0x8CD5, 0xB693, 0x8CD6, + 0xB694, 0x8CD7, 0xB695, 0x8CD8, 0xB696, 0x8CD9, 0xB697, 0x8CDA, 0xB698, 0x8CDB, 0xB699, 0x8CDC, 0xB69A, 0x8CDD, 0xB69B, 0x8CDE, + 0xB69C, 0xB6D1, 0xB69D, 0xB6D2, 0xB69E, 0x8CDF, 0xB69F, 0x8CE0, 0xB6A0, 0xB6D3, 0xB6A1, 0x8CE1, 0xB6A2, 0x8CE2, 0xB6A3, 0x8CE3, + 0xB6A4, 0xB6D4, 0xB6A5, 0x8CE4, 0xB6A6, 0x8CE5, 0xB6A7, 0x8CE6, 0xB6A8, 0x8CE7, 0xB6A9, 0x8CE8, 0xB6AA, 0x8CE9, 0xB6AB, 0xB6D5, + 0xB6AC, 0xB6D6, 0xB6AD, 0x8CEA, 0xB6AE, 0x8CEB, 0xB6AF, 0x8CEC, 0xB6B0, 0x8CED, 0xB6B1, 0xB6D7, 0xB6B2, 0x8CEE, 0xB6B3, 0x8CEF, + 0xB6B4, 0x8CF0, 0xB6B5, 0x8CF1, 0xB6B6, 0x8CF2, 0xB6B7, 0x8CF3, 0xB6B8, 0x8CF4, 0xB6B9, 0x8CF5, 0xB6BA, 0x8CF6, 0xB6BB, 0x8CF7, + 0xB6BC, 0x8CF8, 0xB6BD, 0x8CF9, 0xB6BE, 0x8CFA, 0xB6BF, 0x8CFB, 0xB6C0, 0x8CFC, 0xB6C1, 0x8CFD, 0xB6C2, 0x8CFE, 0xB6C3, 0x8D41, + 0xB6C4, 0x8D42, 0xB6C5, 0x8D43, 0xB6C6, 0x8D44, 0xB6C7, 0x8D45, 0xB6C8, 0x8D46, 0xB6C9, 0x8D47, 0xB6CA, 0x8D48, 0xB6CB, 0x8D49, + 0xB6CC, 0x8D4A, 0xB6CD, 0x8D4B, 0xB6CE, 0x8D4C, 0xB6CF, 0x8D4D, 0xB6D0, 0x8D4E, 0xB6D1, 0x8D4F, 0xB6D2, 0x8D50, 0xB6D3, 0x8D51, + 0xB6D4, 0xB6D8, 0xB6D5, 0x8D52, 0xB6D6, 0x8D53, 0xB6D7, 0x8D54, 0xB6D8, 0x8D55, 0xB6D9, 0x8D56, 0xB6DA, 0x8D57, 0xB6DB, 0x8D58, + 0xB6DC, 0x8D59, 0xB6DD, 0x8D5A, 0xB6DE, 0x8D61, 0xB6DF, 0x8D62, 0xB6E0, 0x8D63, 0xB6E1, 0x8D64, 0xB6E2, 0x8D65, 0xB6E3, 0x8D66, + 0xB6E4, 0x8D67, 0xB6E5, 0x8D68, 0xB6E6, 0x8D69, 0xB6E7, 0x8D6A, 0xB6E8, 0x8D6B, 0xB6E9, 0x8D6C, 0xB6EA, 0x8D6D, 0xB6EB, 0x8D6E, + 0xB6EC, 0x8D6F, 0xB6ED, 0x8D70, 0xB6EE, 0x8D71, 0xB6EF, 0x8D72, 0xB6F0, 0xB6D9, 0xB6F1, 0x8D73, 0xB6F2, 0x8D74, 0xB6F3, 0x8D75, + 0xB6F4, 0xB6DA, 0xB6F5, 0x8D76, 0xB6F6, 0x8D77, 0xB6F7, 0x8D78, 0xB6F8, 0xB6DB, 0xB6F9, 0x8D79, 0xB6FA, 0x8D7A, 0xB6FB, 0x8D81, + 0xB6FC, 0x8D82, 0xB6FD, 0x8D83, 0xB6FE, 0x8D84, 0xB6FF, 0x8D85, 0xB700, 0xB6DC, 0xB701, 0xB6DD, 0xB702, 0x8D86, 0xB703, 0x8D87, + 0xB704, 0x8D88, 0xB705, 0xB6DE, 0xB706, 0x8D89, 0xB707, 0x8D8A, 0xB708, 0x8D8B, 0xB709, 0x8D8C, 0xB70A, 0x8D8D, 0xB70B, 0x8D8E, + 0xB70C, 0x8D8F, 0xB70D, 0x8D90, 0xB70E, 0x8D91, 0xB70F, 0x8D92, 0xB710, 0x8D93, 0xB711, 0x8D94, 0xB712, 0x8D95, 0xB713, 0x8D96, + 0xB714, 0x8D97, 0xB715, 0x8D98, 0xB716, 0x8D99, 0xB717, 0x8D9A, 0xB718, 0x8D9B, 0xB719, 0x8D9C, 0xB71A, 0x8D9D, 0xB71B, 0x8D9E, + 0xB71C, 0x8D9F, 0xB71D, 0x8DA0, 0xB71E, 0x8DA1, 0xB71F, 0x8DA2, 0xB720, 0x8DA3, 0xB721, 0x8DA4, 0xB722, 0x8DA5, 0xB723, 0x8DA6, + 0xB724, 0x8DA7, 0xB725, 0x8DA8, 0xB726, 0x8DA9, 0xB727, 0x8DAA, 0xB728, 0xB6DF, 0xB729, 0xB6E0, 0xB72A, 0x8DAB, 0xB72B, 0x8DAC, + 0xB72C, 0xB6E1, 0xB72D, 0x8DAD, 0xB72E, 0x8DAE, 0xB72F, 0xB6E2, 0xB730, 0xB6E3, 0xB731, 0x8DAF, 0xB732, 0x8DB0, 0xB733, 0x8DB1, + 0xB734, 0x8DB2, 0xB735, 0x8DB3, 0xB736, 0x8DB4, 0xB737, 0x8DB5, 0xB738, 0xB6E4, 0xB739, 0xB6E5, 0xB73A, 0x8DB6, 0xB73B, 0xB6E6, + 0xB73C, 0x8DB7, 0xB73D, 0x8DB8, 0xB73E, 0x8DB9, 0xB73F, 0x8DBA, 0xB740, 0x8DBB, 0xB741, 0x8DBC, 0xB742, 0x8DBD, 0xB743, 0x8DBE, + 0xB744, 0xB6E7, 0xB745, 0x8DBF, 0xB746, 0x8DC0, 0xB747, 0x8DC1, 0xB748, 0xB6E8, 0xB749, 0x8DC2, 0xB74A, 0x8DC3, 0xB74B, 0x8DC4, + 0xB74C, 0xB6E9, 0xB74D, 0x8DC5, 0xB74E, 0x8DC6, 0xB74F, 0x8DC7, 0xB750, 0x8DC8, 0xB751, 0x8DC9, 0xB752, 0x8DCA, 0xB753, 0x8DCB, + 0xB754, 0xB6EA, 0xB755, 0xB6EB, 0xB756, 0x8DCC, 0xB757, 0x8DCD, 0xB758, 0x8DCE, 0xB759, 0x8DCF, 0xB75A, 0x8DD0, 0xB75B, 0x8DD1, + 0xB75C, 0x8DD2, 0xB75D, 0x8DD3, 0xB75E, 0x8DD4, 0xB75F, 0x8DD5, 0xB760, 0xB6EC, 0xB761, 0x8DD6, 0xB762, 0x8DD7, 0xB763, 0x8DD8, + 0xB764, 0xB6ED, 0xB765, 0x8DD9, 0xB766, 0x8DDA, 0xB767, 0x8DDB, 0xB768, 0xB6EE, 0xB769, 0x8DDC, 0xB76A, 0x8DDD, 0xB76B, 0x8DDE, + 0xB76C, 0x8DDF, 0xB76D, 0x8DE0, 0xB76E, 0x8DE1, 0xB76F, 0x8DE2, 0xB770, 0xB6EF, 0xB771, 0xB6F0, 0xB772, 0x8DE3, 0xB773, 0xB6F1, + 0xB774, 0x8DE4, 0xB775, 0xB6F2, 0xB776, 0x8DE5, 0xB777, 0x8DE6, 0xB778, 0x8DE7, 0xB779, 0x8DE8, 0xB77A, 0x8DE9, 0xB77B, 0x8DEA, + 0xB77C, 0xB6F3, 0xB77D, 0xB6F4, 0xB77E, 0x8DEB, 0xB77F, 0x8DEC, 0xB780, 0xB6F5, 0xB781, 0x8DED, 0xB782, 0x8DEE, 0xB783, 0x8DEF, + 0xB784, 0xB6F6, 0xB785, 0x8DF0, 0xB786, 0x8DF1, 0xB787, 0x8DF2, 0xB788, 0x8DF3, 0xB789, 0x8DF4, 0xB78A, 0x8DF5, 0xB78B, 0x8DF6, + 0xB78C, 0xB6F7, 0xB78D, 0xB6F8, 0xB78E, 0x8DF7, 0xB78F, 0xB6F9, 0xB790, 0xB6FA, 0xB791, 0xB6FB, 0xB792, 0xB6FC, 0xB793, 0x8DF8, + 0xB794, 0x8DF9, 0xB795, 0x8DFA, 0xB796, 0xB6FD, 0xB797, 0xB6FE, 0xB798, 0xB7A1, 0xB799, 0xB7A2, 0xB79A, 0x8DFB, 0xB79B, 0x8DFC, + 0xB79C, 0xB7A3, 0xB79D, 0x8DFD, 0xB79E, 0x8DFE, 0xB79F, 0x8E41, 0xB7A0, 0xB7A4, 0xB7A1, 0x8E42, 0xB7A2, 0x8E43, 0xB7A3, 0x8E44, + 0xB7A4, 0x8E45, 0xB7A5, 0x8E46, 0xB7A6, 0x8E47, 0xB7A7, 0x8E48, 0xB7A8, 0xB7A5, 0xB7A9, 0xB7A6, 0xB7AA, 0x8E49, 0xB7AB, 0xB7A7, + 0xB7AC, 0xB7A8, 0xB7AD, 0xB7A9, 0xB7AE, 0x8E4A, 0xB7AF, 0x8E4B, 0xB7B0, 0x8E4C, 0xB7B1, 0x8E4D, 0xB7B2, 0x8E4E, 0xB7B3, 0x8E4F, + 0xB7B4, 0xB7AA, 0xB7B5, 0xB7AB, 0xB7B6, 0x8E50, 0xB7B7, 0x8E51, 0xB7B8, 0xB7AC, 0xB7B9, 0x8E52, 0xB7BA, 0x8E53, 0xB7BB, 0x8E54, + 0xB7BC, 0x8E55, 0xB7BD, 0x8E56, 0xB7BE, 0x8E57, 0xB7BF, 0x8E58, 0xB7C0, 0x8E59, 0xB7C1, 0x8E5A, 0xB7C2, 0x8E61, 0xB7C3, 0x8E62, + 0xB7C4, 0x8E63, 0xB7C5, 0x8E64, 0xB7C6, 0x8E65, 0xB7C7, 0xB7AD, 0xB7C8, 0x8E66, 0xB7C9, 0xB7AE, 0xB7CA, 0x8E67, 0xB7CB, 0x8E68, + 0xB7CC, 0x8E69, 0xB7CD, 0x8E6A, 0xB7CE, 0x8E6B, 0xB7CF, 0x8E6C, 0xB7D0, 0x8E6D, 0xB7D1, 0x8E6E, 0xB7D2, 0x8E6F, 0xB7D3, 0x8E70, + 0xB7D4, 0x8E71, 0xB7D5, 0x8E72, 0xB7D6, 0x8E73, 0xB7D7, 0x8E74, 0xB7D8, 0x8E75, 0xB7D9, 0x8E76, 0xB7DA, 0x8E77, 0xB7DB, 0x8E78, + 0xB7DC, 0x8E79, 0xB7DD, 0x8E7A, 0xB7DE, 0x8E81, 0xB7DF, 0x8E82, 0xB7E0, 0x8E83, 0xB7E1, 0x8E84, 0xB7E2, 0x8E85, 0xB7E3, 0x8E86, + 0xB7E4, 0x8E87, 0xB7E5, 0x8E88, 0xB7E6, 0x8E89, 0xB7E7, 0x8E8A, 0xB7E8, 0x8E8B, 0xB7E9, 0x8E8C, 0xB7EA, 0x8E8D, 0xB7EB, 0x8E8E, + 0xB7EC, 0xB7AF, 0xB7ED, 0xB7B0, 0xB7EE, 0x8E8F, 0xB7EF, 0x8E90, 0xB7F0, 0xB7B1, 0xB7F1, 0x8E91, 0xB7F2, 0x8E92, 0xB7F3, 0x8E93, + 0xB7F4, 0xB7B2, 0xB7F5, 0x8E94, 0xB7F6, 0x8E95, 0xB7F7, 0x8E96, 0xB7F8, 0x8E97, 0xB7F9, 0x8E98, 0xB7FA, 0x8E99, 0xB7FB, 0x8E9A, + 0xB7FC, 0xB7B3, 0xB7FD, 0xB7B4, 0xB7FE, 0x8E9B, 0xB7FF, 0xB7B5, 0xB800, 0xB7B6, 0xB801, 0xB7B7, 0xB802, 0x8E9C, 0xB803, 0x8E9D, + 0xB804, 0x8E9E, 0xB805, 0x8E9F, 0xB806, 0x8EA0, 0xB807, 0xB7B8, 0xB808, 0xB7B9, 0xB809, 0xB7BA, 0xB80A, 0x8EA1, 0xB80B, 0x8EA2, + 0xB80C, 0xB7BB, 0xB80D, 0x8EA3, 0xB80E, 0x8EA4, 0xB80F, 0x8EA5, 0xB810, 0xB7BC, 0xB811, 0x8EA6, 0xB812, 0x8EA7, 0xB813, 0x8EA8, + 0xB814, 0x8EA9, 0xB815, 0x8EAA, 0xB816, 0x8EAB, 0xB817, 0x8EAC, 0xB818, 0xB7BD, 0xB819, 0xB7BE, 0xB81A, 0x8EAD, 0xB81B, 0xB7BF, + 0xB81C, 0x8EAE, 0xB81D, 0xB7C0, 0xB81E, 0x8EAF, 0xB81F, 0x8EB0, 0xB820, 0x8EB1, 0xB821, 0x8EB2, 0xB822, 0x8EB3, 0xB823, 0x8EB4, + 0xB824, 0xB7C1, 0xB825, 0xB7C2, 0xB826, 0x8EB5, 0xB827, 0x8EB6, 0xB828, 0xB7C3, 0xB829, 0x8EB7, 0xB82A, 0x8EB8, 0xB82B, 0x8EB9, + 0xB82C, 0xB7C4, 0xB82D, 0x8EBA, 0xB82E, 0x8EBB, 0xB82F, 0x8EBC, 0xB830, 0x8EBD, 0xB831, 0x8EBE, 0xB832, 0x8EBF, 0xB833, 0x8EC0, + 0xB834, 0xB7C5, 0xB835, 0xB7C6, 0xB836, 0x8EC1, 0xB837, 0xB7C7, 0xB838, 0xB7C8, 0xB839, 0xB7C9, 0xB83A, 0x8EC2, 0xB83B, 0x8EC3, + 0xB83C, 0x8EC4, 0xB83D, 0x8EC5, 0xB83E, 0x8EC6, 0xB83F, 0x8EC7, 0xB840, 0xB7CA, 0xB841, 0x8EC8, 0xB842, 0x8EC9, 0xB843, 0x8ECA, + 0xB844, 0xB7CB, 0xB845, 0x8ECB, 0xB846, 0x8ECC, 0xB847, 0x8ECD, 0xB848, 0x8ECE, 0xB849, 0x8ECF, 0xB84A, 0x8ED0, 0xB84B, 0x8ED1, + 0xB84C, 0x8ED2, 0xB84D, 0x8ED3, 0xB84E, 0x8ED4, 0xB84F, 0x8ED5, 0xB850, 0x8ED6, 0xB851, 0xB7CC, 0xB852, 0x8ED7, 0xB853, 0xB7CD, + 0xB854, 0x8ED8, 0xB855, 0x8ED9, 0xB856, 0x8EDA, 0xB857, 0x8EDB, 0xB858, 0x8EDC, 0xB859, 0x8EDD, 0xB85A, 0x8EDE, 0xB85B, 0x8EDF, + 0xB85C, 0xB7CE, 0xB85D, 0xB7CF, 0xB85E, 0x8EE0, 0xB85F, 0x8EE1, 0xB860, 0xB7D0, 0xB861, 0x8EE2, 0xB862, 0x8EE3, 0xB863, 0x8EE4, + 0xB864, 0xB7D1, 0xB865, 0x8EE5, 0xB866, 0x8EE6, 0xB867, 0x8EE7, 0xB868, 0x8EE8, 0xB869, 0x8EE9, 0xB86A, 0x8EEA, 0xB86B, 0x8EEB, + 0xB86C, 0xB7D2, 0xB86D, 0xB7D3, 0xB86E, 0x8EEC, 0xB86F, 0xB7D4, 0xB870, 0x8EED, 0xB871, 0xB7D5, 0xB872, 0x8EEE, 0xB873, 0x8EEF, + 0xB874, 0x8EF0, 0xB875, 0x8EF1, 0xB876, 0x8EF2, 0xB877, 0x8EF3, 0xB878, 0xB7D6, 0xB879, 0x8EF4, 0xB87A, 0x8EF5, 0xB87B, 0x8EF6, + 0xB87C, 0xB7D7, 0xB87D, 0x8EF7, 0xB87E, 0x8EF8, 0xB87F, 0x8EF9, 0xB880, 0x8EFA, 0xB881, 0x8EFB, 0xB882, 0x8EFC, 0xB883, 0x8EFD, + 0xB884, 0x8EFE, 0xB885, 0x8F41, 0xB886, 0x8F42, 0xB887, 0x8F43, 0xB888, 0x8F44, 0xB889, 0x8F45, 0xB88A, 0x8F46, 0xB88B, 0x8F47, + 0xB88C, 0x8F48, 0xB88D, 0xB7D8, 0xB88E, 0x8F49, 0xB88F, 0x8F4A, 0xB890, 0x8F4B, 0xB891, 0x8F4C, 0xB892, 0x8F4D, 0xB893, 0x8F4E, + 0xB894, 0x8F4F, 0xB895, 0x8F50, 0xB896, 0x8F51, 0xB897, 0x8F52, 0xB898, 0x8F53, 0xB899, 0x8F54, 0xB89A, 0x8F55, 0xB89B, 0x8F56, + 0xB89C, 0x8F57, 0xB89D, 0x8F58, 0xB89E, 0x8F59, 0xB89F, 0x8F5A, 0xB8A0, 0x8F61, 0xB8A1, 0x8F62, 0xB8A2, 0x8F63, 0xB8A3, 0x8F64, + 0xB8A4, 0x8F65, 0xB8A5, 0x8F66, 0xB8A6, 0x8F67, 0xB8A7, 0x8F68, 0xB8A8, 0xB7D9, 0xB8A9, 0x8F69, 0xB8AA, 0x8F6A, 0xB8AB, 0x8F6B, + 0xB8AC, 0x8F6C, 0xB8AD, 0x8F6D, 0xB8AE, 0x8F6E, 0xB8AF, 0x8F6F, 0xB8B0, 0xB7DA, 0xB8B1, 0x8F70, 0xB8B2, 0x8F71, 0xB8B3, 0x8F72, + 0xB8B4, 0xB7DB, 0xB8B5, 0x8F73, 0xB8B6, 0x8F74, 0xB8B7, 0x8F75, 0xB8B8, 0xB7DC, 0xB8B9, 0x8F76, 0xB8BA, 0x8F77, 0xB8BB, 0x8F78, + 0xB8BC, 0x8F79, 0xB8BD, 0x8F7A, 0xB8BE, 0x8F81, 0xB8BF, 0x8F82, 0xB8C0, 0xB7DD, 0xB8C1, 0xB7DE, 0xB8C2, 0x8F83, 0xB8C3, 0xB7DF, + 0xB8C4, 0x8F84, 0xB8C5, 0xB7E0, 0xB8C6, 0x8F85, 0xB8C7, 0x8F86, 0xB8C8, 0x8F87, 0xB8C9, 0x8F88, 0xB8CA, 0x8F89, 0xB8CB, 0x8F8A, + 0xB8CC, 0xB7E1, 0xB8CD, 0x8F8B, 0xB8CE, 0x8F8C, 0xB8CF, 0x8F8D, 0xB8D0, 0xB7E2, 0xB8D1, 0x8F8E, 0xB8D2, 0x8F8F, 0xB8D3, 0x8F90, + 0xB8D4, 0xB7E3, 0xB8D5, 0x8F91, 0xB8D6, 0x8F92, 0xB8D7, 0x8F93, 0xB8D8, 0x8F94, 0xB8D9, 0x8F95, 0xB8DA, 0x8F96, 0xB8DB, 0x8F97, + 0xB8DC, 0x8F98, 0xB8DD, 0xB7E4, 0xB8DE, 0x8F99, 0xB8DF, 0xB7E5, 0xB8E0, 0x8F9A, 0xB8E1, 0xB7E6, 0xB8E2, 0x8F9B, 0xB8E3, 0x8F9C, + 0xB8E4, 0x8F9D, 0xB8E5, 0x8F9E, 0xB8E6, 0x8F9F, 0xB8E7, 0x8FA0, 0xB8E8, 0xB7E7, 0xB8E9, 0xB7E8, 0xB8EA, 0x8FA1, 0xB8EB, 0x8FA2, + 0xB8EC, 0xB7E9, 0xB8ED, 0x8FA3, 0xB8EE, 0x8FA4, 0xB8EF, 0x8FA5, 0xB8F0, 0xB7EA, 0xB8F1, 0x8FA6, 0xB8F2, 0x8FA7, 0xB8F3, 0x8FA8, + 0xB8F4, 0x8FA9, 0xB8F5, 0x8FAA, 0xB8F6, 0x8FAB, 0xB8F7, 0x8FAC, 0xB8F8, 0xB7EB, 0xB8F9, 0xB7EC, 0xB8FA, 0x8FAD, 0xB8FB, 0xB7ED, + 0xB8FC, 0x8FAE, 0xB8FD, 0xB7EE, 0xB8FE, 0x8FAF, 0xB8FF, 0x8FB0, 0xB900, 0x8FB1, 0xB901, 0x8FB2, 0xB902, 0x8FB3, 0xB903, 0x8FB4, + 0xB904, 0xB7EF, 0xB905, 0x8FB5, 0xB906, 0x8FB6, 0xB907, 0x8FB7, 0xB908, 0x8FB8, 0xB909, 0x8FB9, 0xB90A, 0x8FBA, 0xB90B, 0x8FBB, + 0xB90C, 0x8FBC, 0xB90D, 0x8FBD, 0xB90E, 0x8FBE, 0xB90F, 0x8FBF, 0xB910, 0x8FC0, 0xB911, 0x8FC1, 0xB912, 0x8FC2, 0xB913, 0x8FC3, + 0xB914, 0x8FC4, 0xB915, 0x8FC5, 0xB916, 0x8FC6, 0xB917, 0x8FC7, 0xB918, 0xB7F0, 0xB919, 0x8FC8, 0xB91A, 0x8FC9, 0xB91B, 0x8FCA, + 0xB91C, 0x8FCB, 0xB91D, 0x8FCC, 0xB91E, 0x8FCD, 0xB91F, 0x8FCE, 0xB920, 0xB7F1, 0xB921, 0x8FCF, 0xB922, 0x8FD0, 0xB923, 0x8FD1, + 0xB924, 0x8FD2, 0xB925, 0x8FD3, 0xB926, 0x8FD4, 0xB927, 0x8FD5, 0xB928, 0x8FD6, 0xB929, 0x8FD7, 0xB92A, 0x8FD8, 0xB92B, 0x8FD9, + 0xB92C, 0x8FDA, 0xB92D, 0x8FDB, 0xB92E, 0x8FDC, 0xB92F, 0x8FDD, 0xB930, 0x8FDE, 0xB931, 0x8FDF, 0xB932, 0x8FE0, 0xB933, 0x8FE1, + 0xB934, 0x8FE2, 0xB935, 0x8FE3, 0xB936, 0x8FE4, 0xB937, 0x8FE5, 0xB938, 0x8FE6, 0xB939, 0x8FE7, 0xB93A, 0x8FE8, 0xB93B, 0x8FE9, + 0xB93C, 0xB7F2, 0xB93D, 0xB7F3, 0xB93E, 0x8FEA, 0xB93F, 0x8FEB, 0xB940, 0xB7F4, 0xB941, 0x8FEC, 0xB942, 0x8FED, 0xB943, 0x8FEE, + 0xB944, 0xB7F5, 0xB945, 0x8FEF, 0xB946, 0x8FF0, 0xB947, 0x8FF1, 0xB948, 0x8FF2, 0xB949, 0x8FF3, 0xB94A, 0x8FF4, 0xB94B, 0x8FF5, + 0xB94C, 0xB7F6, 0xB94D, 0x8FF6, 0xB94E, 0x8FF7, 0xB94F, 0xB7F7, 0xB950, 0x8FF8, 0xB951, 0xB7F8, 0xB952, 0x8FF9, 0xB953, 0x8FFA, + 0xB954, 0x8FFB, 0xB955, 0x8FFC, 0xB956, 0x8FFD, 0xB957, 0x8FFE, 0xB958, 0xB7F9, 0xB959, 0xB7FA, 0xB95A, 0x9041, 0xB95B, 0x9042, + 0xB95C, 0xB7FB, 0xB95D, 0x9043, 0xB95E, 0x9044, 0xB95F, 0x9045, 0xB960, 0xB7FC, 0xB961, 0x9046, 0xB962, 0x9047, 0xB963, 0x9048, + 0xB964, 0x9049, 0xB965, 0x904A, 0xB966, 0x904B, 0xB967, 0x904C, 0xB968, 0xB7FD, 0xB969, 0xB7FE, 0xB96A, 0x904D, 0xB96B, 0xB8A1, + 0xB96C, 0x904E, 0xB96D, 0xB8A2, 0xB96E, 0x904F, 0xB96F, 0x9050, 0xB970, 0x9051, 0xB971, 0x9052, 0xB972, 0x9053, 0xB973, 0x9054, + 0xB974, 0xB8A3, 0xB975, 0xB8A4, 0xB976, 0x9055, 0xB977, 0x9056, 0xB978, 0xB8A5, 0xB979, 0x9057, 0xB97A, 0x9058, 0xB97B, 0x9059, + 0xB97C, 0xB8A6, 0xB97D, 0x905A, 0xB97E, 0x9061, 0xB97F, 0x9062, 0xB980, 0x9063, 0xB981, 0x9064, 0xB982, 0x9065, 0xB983, 0x9066, + 0xB984, 0xB8A7, 0xB985, 0xB8A8, 0xB986, 0x9067, 0xB987, 0xB8A9, 0xB988, 0x9068, 0xB989, 0xB8AA, 0xB98A, 0xB8AB, 0xB98B, 0x9069, + 0xB98C, 0x906A, 0xB98D, 0xB8AC, 0xB98E, 0xB8AD, 0xB98F, 0x906B, 0xB990, 0x906C, 0xB991, 0x906D, 0xB992, 0x906E, 0xB993, 0x906F, + 0xB994, 0x9070, 0xB995, 0x9071, 0xB996, 0x9072, 0xB997, 0x9073, 0xB998, 0x9074, 0xB999, 0x9075, 0xB99A, 0x9076, 0xB99B, 0x9077, + 0xB99C, 0x9078, 0xB99D, 0x9079, 0xB99E, 0x907A, 0xB99F, 0x9081, 0xB9A0, 0x9082, 0xB9A1, 0x9083, 0xB9A2, 0x9084, 0xB9A3, 0x9085, + 0xB9A4, 0x9086, 0xB9A5, 0x9087, 0xB9A6, 0x9088, 0xB9A7, 0x9089, 0xB9A8, 0x908A, 0xB9A9, 0x908B, 0xB9AA, 0x908C, 0xB9AB, 0x908D, + 0xB9AC, 0xB8AE, 0xB9AD, 0xB8AF, 0xB9AE, 0x908E, 0xB9AF, 0x908F, 0xB9B0, 0xB8B0, 0xB9B1, 0x9090, 0xB9B2, 0x9091, 0xB9B3, 0x9092, + 0xB9B4, 0xB8B1, 0xB9B5, 0x9093, 0xB9B6, 0x9094, 0xB9B7, 0x9095, 0xB9B8, 0x9096, 0xB9B9, 0x9097, 0xB9BA, 0x9098, 0xB9BB, 0x9099, + 0xB9BC, 0xB8B2, 0xB9BD, 0xB8B3, 0xB9BE, 0x909A, 0xB9BF, 0xB8B4, 0xB9C0, 0x909B, 0xB9C1, 0xB8B5, 0xB9C2, 0x909C, 0xB9C3, 0x909D, + 0xB9C4, 0x909E, 0xB9C5, 0x909F, 0xB9C6, 0x90A0, 0xB9C7, 0x90A1, 0xB9C8, 0xB8B6, 0xB9C9, 0xB8B7, 0xB9CA, 0x90A2, 0xB9CB, 0x90A3, + 0xB9CC, 0xB8B8, 0xB9CD, 0x90A4, 0xB9CE, 0xB8B9, 0xB9CF, 0xB8BA, 0xB9D0, 0xB8BB, 0xB9D1, 0xB8BC, 0xB9D2, 0xB8BD, 0xB9D3, 0x90A5, + 0xB9D4, 0x90A6, 0xB9D5, 0x90A7, 0xB9D6, 0x90A8, 0xB9D7, 0x90A9, 0xB9D8, 0xB8BE, 0xB9D9, 0xB8BF, 0xB9DA, 0x90AA, 0xB9DB, 0xB8C0, + 0xB9DC, 0x90AB, 0xB9DD, 0xB8C1, 0xB9DE, 0xB8C2, 0xB9DF, 0x90AC, 0xB9E0, 0x90AD, 0xB9E1, 0xB8C3, 0xB9E2, 0x90AE, 0xB9E3, 0xB8C4, + 0xB9E4, 0xB8C5, 0xB9E5, 0xB8C6, 0xB9E6, 0x90AF, 0xB9E7, 0x90B0, 0xB9E8, 0xB8C7, 0xB9E9, 0x90B1, 0xB9EA, 0x90B2, 0xB9EB, 0x90B3, + 0xB9EC, 0xB8C8, 0xB9ED, 0x90B4, 0xB9EE, 0x90B5, 0xB9EF, 0x90B6, 0xB9F0, 0x90B7, 0xB9F1, 0x90B8, 0xB9F2, 0x90B9, 0xB9F3, 0x90BA, + 0xB9F4, 0xB8C9, 0xB9F5, 0xB8CA, 0xB9F6, 0x90BB, 0xB9F7, 0xB8CB, 0xB9F8, 0xB8CC, 0xB9F9, 0xB8CD, 0xB9FA, 0xB8CE, 0xB9FB, 0x90BC, + 0xB9FC, 0x90BD, 0xB9FD, 0x90BE, 0xB9FE, 0x90BF, 0xB9FF, 0x90C0, 0xBA00, 0xB8CF, 0xBA01, 0xB8D0, 0xBA02, 0x90C1, 0xBA03, 0x90C2, + 0xBA04, 0x90C3, 0xBA05, 0x90C4, 0xBA06, 0x90C5, 0xBA07, 0x90C6, 0xBA08, 0xB8D1, 0xBA09, 0x90C7, 0xBA0A, 0x90C8, 0xBA0B, 0x90C9, + 0xBA0C, 0x90CA, 0xBA0D, 0x90CB, 0xBA0E, 0x90CC, 0xBA0F, 0x90CD, 0xBA10, 0x90CE, 0xBA11, 0x90CF, 0xBA12, 0x90D0, 0xBA13, 0x90D1, + 0xBA14, 0x90D2, 0xBA15, 0xB8D2, 0xBA16, 0x90D3, 0xBA17, 0x90D4, 0xBA18, 0x90D5, 0xBA19, 0x90D6, 0xBA1A, 0x90D7, 0xBA1B, 0x90D8, + 0xBA1C, 0x90D9, 0xBA1D, 0x90DA, 0xBA1E, 0x90DB, 0xBA1F, 0x90DC, 0xBA20, 0x90DD, 0xBA21, 0x90DE, 0xBA22, 0x90DF, 0xBA23, 0x90E0, + 0xBA24, 0x90E1, 0xBA25, 0x90E2, 0xBA26, 0x90E3, 0xBA27, 0x90E4, 0xBA28, 0x90E5, 0xBA29, 0x90E6, 0xBA2A, 0x90E7, 0xBA2B, 0x90E8, + 0xBA2C, 0x90E9, 0xBA2D, 0x90EA, 0xBA2E, 0x90EB, 0xBA2F, 0x90EC, 0xBA30, 0x90ED, 0xBA31, 0x90EE, 0xBA32, 0x90EF, 0xBA33, 0x90F0, + 0xBA34, 0x90F1, 0xBA35, 0x90F2, 0xBA36, 0x90F3, 0xBA37, 0x90F4, 0xBA38, 0xB8D3, 0xBA39, 0xB8D4, 0xBA3A, 0x90F5, 0xBA3B, 0x90F6, + 0xBA3C, 0xB8D5, 0xBA3D, 0x90F7, 0xBA3E, 0x90F8, 0xBA3F, 0x90F9, 0xBA40, 0xB8D6, 0xBA41, 0x90FA, 0xBA42, 0xB8D7, 0xBA43, 0x90FB, + 0xBA44, 0x90FC, 0xBA45, 0x90FD, 0xBA46, 0x90FE, 0xBA47, 0x9141, 0xBA48, 0xB8D8, 0xBA49, 0xB8D9, 0xBA4A, 0x9142, 0xBA4B, 0xB8DA, + 0xBA4C, 0x9143, 0xBA4D, 0xB8DB, 0xBA4E, 0xB8DC, 0xBA4F, 0x9144, 0xBA50, 0x9145, 0xBA51, 0x9146, 0xBA52, 0x9147, 0xBA53, 0xB8DD, + 0xBA54, 0xB8DE, 0xBA55, 0xB8DF, 0xBA56, 0x9148, 0xBA57, 0x9149, 0xBA58, 0xB8E0, 0xBA59, 0x914A, 0xBA5A, 0x914B, 0xBA5B, 0x914C, + 0xBA5C, 0xB8E1, 0xBA5D, 0x914D, 0xBA5E, 0x914E, 0xBA5F, 0x914F, 0xBA60, 0x9150, 0xBA61, 0x9151, 0xBA62, 0x9152, 0xBA63, 0x9153, + 0xBA64, 0xB8E2, 0xBA65, 0xB8E3, 0xBA66, 0x9154, 0xBA67, 0xB8E4, 0xBA68, 0xB8E5, 0xBA69, 0xB8E6, 0xBA6A, 0x9155, 0xBA6B, 0x9156, + 0xBA6C, 0x9157, 0xBA6D, 0x9158, 0xBA6E, 0x9159, 0xBA6F, 0x915A, 0xBA70, 0xB8E7, 0xBA71, 0xB8E8, 0xBA72, 0x9161, 0xBA73, 0x9162, + 0xBA74, 0xB8E9, 0xBA75, 0x9163, 0xBA76, 0x9164, 0xBA77, 0x9165, 0xBA78, 0xB8EA, 0xBA79, 0x9166, 0xBA7A, 0x9167, 0xBA7B, 0x9168, + 0xBA7C, 0x9169, 0xBA7D, 0x916A, 0xBA7E, 0x916B, 0xBA7F, 0x916C, 0xBA80, 0x916D, 0xBA81, 0x916E, 0xBA82, 0x916F, 0xBA83, 0xB8EB, + 0xBA84, 0xB8EC, 0xBA85, 0xB8ED, 0xBA86, 0x9170, 0xBA87, 0xB8EE, 0xBA88, 0x9171, 0xBA89, 0x9172, 0xBA8A, 0x9173, 0xBA8B, 0x9174, + 0xBA8C, 0xB8EF, 0xBA8D, 0x9175, 0xBA8E, 0x9176, 0xBA8F, 0x9177, 0xBA90, 0x9178, 0xBA91, 0x9179, 0xBA92, 0x917A, 0xBA93, 0x9181, + 0xBA94, 0x9182, 0xBA95, 0x9183, 0xBA96, 0x9184, 0xBA97, 0x9185, 0xBA98, 0x9186, 0xBA99, 0x9187, 0xBA9A, 0x9188, 0xBA9B, 0x9189, + 0xBA9C, 0x918A, 0xBA9D, 0x918B, 0xBA9E, 0x918C, 0xBA9F, 0x918D, 0xBAA0, 0x918E, 0xBAA1, 0x918F, 0xBAA2, 0x9190, 0xBAA3, 0x9191, + 0xBAA4, 0x9192, 0xBAA5, 0x9193, 0xBAA6, 0x9194, 0xBAA7, 0x9195, 0xBAA8, 0xB8F0, 0xBAA9, 0xB8F1, 0xBAAA, 0x9196, 0xBAAB, 0xB8F2, + 0xBAAC, 0xB8F3, 0xBAAD, 0x9197, 0xBAAE, 0x9198, 0xBAAF, 0x9199, 0xBAB0, 0xB8F4, 0xBAB1, 0x919A, 0xBAB2, 0xB8F5, 0xBAB3, 0x919B, + 0xBAB4, 0x919C, 0xBAB5, 0x919D, 0xBAB6, 0x919E, 0xBAB7, 0x919F, 0xBAB8, 0xB8F6, 0xBAB9, 0xB8F7, 0xBABA, 0x91A0, 0xBABB, 0xB8F8, + 0xBABC, 0x91A1, 0xBABD, 0xB8F9, 0xBABE, 0x91A2, 0xBABF, 0x91A3, 0xBAC0, 0x91A4, 0xBAC1, 0x91A5, 0xBAC2, 0x91A6, 0xBAC3, 0x91A7, + 0xBAC4, 0xB8FA, 0xBAC5, 0x91A8, 0xBAC6, 0x91A9, 0xBAC7, 0x91AA, 0xBAC8, 0xB8FB, 0xBAC9, 0x91AB, 0xBACA, 0x91AC, 0xBACB, 0x91AD, + 0xBACC, 0x91AE, 0xBACD, 0x91AF, 0xBACE, 0x91B0, 0xBACF, 0x91B1, 0xBAD0, 0x91B2, 0xBAD1, 0x91B3, 0xBAD2, 0x91B4, 0xBAD3, 0x91B5, + 0xBAD4, 0x91B6, 0xBAD5, 0x91B7, 0xBAD6, 0x91B8, 0xBAD7, 0x91B9, 0xBAD8, 0xB8FC, 0xBAD9, 0xB8FD, 0xBADA, 0x91BA, 0xBADB, 0x91BB, + 0xBADC, 0x91BC, 0xBADD, 0x91BD, 0xBADE, 0x91BE, 0xBADF, 0x91BF, 0xBAE0, 0x91C0, 0xBAE1, 0x91C1, 0xBAE2, 0x91C2, 0xBAE3, 0x91C3, + 0xBAE4, 0x91C4, 0xBAE5, 0x91C5, 0xBAE6, 0x91C6, 0xBAE7, 0x91C7, 0xBAE8, 0x91C8, 0xBAE9, 0x91C9, 0xBAEA, 0x91CA, 0xBAEB, 0x91CB, + 0xBAEC, 0x91CC, 0xBAED, 0x91CD, 0xBAEE, 0x91CE, 0xBAEF, 0x91CF, 0xBAF0, 0x91D0, 0xBAF1, 0x91D1, 0xBAF2, 0x91D2, 0xBAF3, 0x91D3, + 0xBAF4, 0x91D4, 0xBAF5, 0x91D5, 0xBAF6, 0x91D6, 0xBAF7, 0x91D7, 0xBAF8, 0x91D8, 0xBAF9, 0x91D9, 0xBAFA, 0x91DA, 0xBAFB, 0x91DB, + 0xBAFC, 0xB8FE, 0xBAFD, 0x91DC, 0xBAFE, 0x91DD, 0xBAFF, 0x91DE, 0xBB00, 0xB9A1, 0xBB01, 0x91DF, 0xBB02, 0x91E0, 0xBB03, 0x91E1, + 0xBB04, 0xB9A2, 0xBB05, 0x91E2, 0xBB06, 0x91E3, 0xBB07, 0x91E4, 0xBB08, 0x91E5, 0xBB09, 0x91E6, 0xBB0A, 0x91E7, 0xBB0B, 0x91E8, + 0xBB0C, 0x91E9, 0xBB0D, 0xB9A3, 0xBB0E, 0x91EA, 0xBB0F, 0xB9A4, 0xBB10, 0x91EB, 0xBB11, 0xB9A5, 0xBB12, 0x91EC, 0xBB13, 0x91ED, + 0xBB14, 0x91EE, 0xBB15, 0x91EF, 0xBB16, 0x91F0, 0xBB17, 0x91F1, 0xBB18, 0xB9A6, 0xBB19, 0x91F2, 0xBB1A, 0x91F3, 0xBB1B, 0x91F4, + 0xBB1C, 0xB9A7, 0xBB1D, 0x91F5, 0xBB1E, 0x91F6, 0xBB1F, 0x91F7, 0xBB20, 0xB9A8, 0xBB21, 0x91F8, 0xBB22, 0x91F9, 0xBB23, 0x91FA, + 0xBB24, 0x91FB, 0xBB25, 0x91FC, 0xBB26, 0x91FD, 0xBB27, 0x91FE, 0xBB28, 0x9241, 0xBB29, 0xB9A9, 0xBB2A, 0x9242, 0xBB2B, 0xB9AA, + 0xBB2C, 0x9243, 0xBB2D, 0x9244, 0xBB2E, 0x9245, 0xBB2F, 0x9246, 0xBB30, 0x9247, 0xBB31, 0x9248, 0xBB32, 0x9249, 0xBB33, 0x924A, + 0xBB34, 0xB9AB, 0xBB35, 0xB9AC, 0xBB36, 0xB9AD, 0xBB37, 0x924B, 0xBB38, 0xB9AE, 0xBB39, 0x924C, 0xBB3A, 0x924D, 0xBB3B, 0xB9AF, + 0xBB3C, 0xB9B0, 0xBB3D, 0xB9B1, 0xBB3E, 0xB9B2, 0xBB3F, 0x924E, 0xBB40, 0x924F, 0xBB41, 0x9250, 0xBB42, 0x9251, 0xBB43, 0x9252, + 0xBB44, 0xB9B3, 0xBB45, 0xB9B4, 0xBB46, 0x9253, 0xBB47, 0xB9B5, 0xBB48, 0x9254, 0xBB49, 0xB9B6, 0xBB4A, 0x9255, 0xBB4B, 0x9256, + 0xBB4C, 0x9257, 0xBB4D, 0xB9B7, 0xBB4E, 0x9258, 0xBB4F, 0xB9B8, 0xBB50, 0xB9B9, 0xBB51, 0x9259, 0xBB52, 0x925A, 0xBB53, 0x9261, + 0xBB54, 0xB9BA, 0xBB55, 0x9262, 0xBB56, 0x9263, 0xBB57, 0x9264, 0xBB58, 0xB9BB, 0xBB59, 0x9265, 0xBB5A, 0x9266, 0xBB5B, 0x9267, + 0xBB5C, 0x9268, 0xBB5D, 0x9269, 0xBB5E, 0x926A, 0xBB5F, 0x926B, 0xBB60, 0x926C, 0xBB61, 0xB9BC, 0xBB62, 0x926D, 0xBB63, 0xB9BD, + 0xBB64, 0x926E, 0xBB65, 0x926F, 0xBB66, 0x9270, 0xBB67, 0x9271, 0xBB68, 0x9272, 0xBB69, 0x9273, 0xBB6A, 0x9274, 0xBB6B, 0x9275, + 0xBB6C, 0xB9BE, 0xBB6D, 0x9276, 0xBB6E, 0x9277, 0xBB6F, 0x9278, 0xBB70, 0x9279, 0xBB71, 0x927A, 0xBB72, 0x9281, 0xBB73, 0x9282, + 0xBB74, 0x9283, 0xBB75, 0x9284, 0xBB76, 0x9285, 0xBB77, 0x9286, 0xBB78, 0x9287, 0xBB79, 0x9288, 0xBB7A, 0x9289, 0xBB7B, 0x928A, + 0xBB7C, 0x928B, 0xBB7D, 0x928C, 0xBB7E, 0x928D, 0xBB7F, 0x928E, 0xBB80, 0x928F, 0xBB81, 0x9290, 0xBB82, 0x9291, 0xBB83, 0x9292, + 0xBB84, 0x9293, 0xBB85, 0x9294, 0xBB86, 0x9295, 0xBB87, 0x9296, 0xBB88, 0xB9BF, 0xBB89, 0x9297, 0xBB8A, 0x9298, 0xBB8B, 0x9299, + 0xBB8C, 0xB9C0, 0xBB8D, 0x929A, 0xBB8E, 0x929B, 0xBB8F, 0x929C, 0xBB90, 0xB9C1, 0xBB91, 0x929D, 0xBB92, 0x929E, 0xBB93, 0x929F, + 0xBB94, 0x92A0, 0xBB95, 0x92A1, 0xBB96, 0x92A2, 0xBB97, 0x92A3, 0xBB98, 0x92A4, 0xBB99, 0x92A5, 0xBB9A, 0x92A6, 0xBB9B, 0x92A7, + 0xBB9C, 0x92A8, 0xBB9D, 0x92A9, 0xBB9E, 0x92AA, 0xBB9F, 0x92AB, 0xBBA0, 0x92AC, 0xBBA1, 0x92AD, 0xBBA2, 0x92AE, 0xBBA3, 0x92AF, + 0xBBA4, 0xB9C2, 0xBBA5, 0x92B0, 0xBBA6, 0x92B1, 0xBBA7, 0x92B2, 0xBBA8, 0xB9C3, 0xBBA9, 0x92B3, 0xBBAA, 0x92B4, 0xBBAB, 0x92B5, + 0xBBAC, 0xB9C4, 0xBBAD, 0x92B6, 0xBBAE, 0x92B7, 0xBBAF, 0x92B8, 0xBBB0, 0x92B9, 0xBBB1, 0x92BA, 0xBBB2, 0x92BB, 0xBBB3, 0x92BC, + 0xBBB4, 0xB9C5, 0xBBB5, 0x92BD, 0xBBB6, 0x92BE, 0xBBB7, 0xB9C6, 0xBBB8, 0x92BF, 0xBBB9, 0x92C0, 0xBBBA, 0x92C1, 0xBBBB, 0x92C2, + 0xBBBC, 0x92C3, 0xBBBD, 0x92C4, 0xBBBE, 0x92C5, 0xBBBF, 0x92C6, 0xBBC0, 0xB9C7, 0xBBC1, 0x92C7, 0xBBC2, 0x92C8, 0xBBC3, 0x92C9, + 0xBBC4, 0xB9C8, 0xBBC5, 0x92CA, 0xBBC6, 0x92CB, 0xBBC7, 0x92CC, 0xBBC8, 0xB9C9, 0xBBC9, 0x92CD, 0xBBCA, 0x92CE, 0xBBCB, 0x92CF, + 0xBBCC, 0x92D0, 0xBBCD, 0x92D1, 0xBBCE, 0x92D2, 0xBBCF, 0x92D3, 0xBBD0, 0xB9CA, 0xBBD1, 0x92D4, 0xBBD2, 0x92D5, 0xBBD3, 0xB9CB, + 0xBBD4, 0x92D6, 0xBBD5, 0x92D7, 0xBBD6, 0x92D8, 0xBBD7, 0x92D9, 0xBBD8, 0x92DA, 0xBBD9, 0x92DB, 0xBBDA, 0x92DC, 0xBBDB, 0x92DD, + 0xBBDC, 0x92DE, 0xBBDD, 0x92DF, 0xBBDE, 0x92E0, 0xBBDF, 0x92E1, 0xBBE0, 0x92E2, 0xBBE1, 0x92E3, 0xBBE2, 0x92E4, 0xBBE3, 0x92E5, + 0xBBE4, 0x92E6, 0xBBE5, 0x92E7, 0xBBE6, 0x92E8, 0xBBE7, 0x92E9, 0xBBE8, 0x92EA, 0xBBE9, 0x92EB, 0xBBEA, 0x92EC, 0xBBEB, 0x92ED, + 0xBBEC, 0x92EE, 0xBBED, 0x92EF, 0xBBEE, 0x92F0, 0xBBEF, 0x92F1, 0xBBF0, 0x92F2, 0xBBF1, 0x92F3, 0xBBF2, 0x92F4, 0xBBF3, 0x92F5, + 0xBBF4, 0x92F6, 0xBBF5, 0x92F7, 0xBBF6, 0x92F8, 0xBBF7, 0x92F9, 0xBBF8, 0xB9CC, 0xBBF9, 0xB9CD, 0xBBFA, 0x92FA, 0xBBFB, 0x92FB, + 0xBBFC, 0xB9CE, 0xBBFD, 0x92FC, 0xBBFE, 0x92FD, 0xBBFF, 0xB9CF, 0xBC00, 0xB9D0, 0xBC01, 0x92FE, 0xBC02, 0xB9D1, 0xBC03, 0x9341, + 0xBC04, 0x9342, 0xBC05, 0x9343, 0xBC06, 0x9344, 0xBC07, 0x9345, 0xBC08, 0xB9D2, 0xBC09, 0xB9D3, 0xBC0A, 0x9346, 0xBC0B, 0xB9D4, + 0xBC0C, 0xB9D5, 0xBC0D, 0xB9D6, 0xBC0E, 0x9347, 0xBC0F, 0xB9D7, 0xBC10, 0x9348, 0xBC11, 0xB9D8, 0xBC12, 0x9349, 0xBC13, 0x934A, + 0xBC14, 0xB9D9, 0xBC15, 0xB9DA, 0xBC16, 0xB9DB, 0xBC17, 0xB9DC, 0xBC18, 0xB9DD, 0xBC19, 0x934B, 0xBC1A, 0x934C, 0xBC1B, 0xB9DE, + 0xBC1C, 0xB9DF, 0xBC1D, 0xB9E0, 0xBC1E, 0xB9E1, 0xBC1F, 0xB9E2, 0xBC20, 0x934D, 0xBC21, 0x934E, 0xBC22, 0x934F, 0xBC23, 0x9350, + 0xBC24, 0xB9E3, 0xBC25, 0xB9E4, 0xBC26, 0x9351, 0xBC27, 0xB9E5, 0xBC28, 0x9352, 0xBC29, 0xB9E6, 0xBC2A, 0x9353, 0xBC2B, 0x9354, + 0xBC2C, 0x9355, 0xBC2D, 0xB9E7, 0xBC2E, 0x9356, 0xBC2F, 0x9357, 0xBC30, 0xB9E8, 0xBC31, 0xB9E9, 0xBC32, 0x9358, 0xBC33, 0x9359, + 0xBC34, 0xB9EA, 0xBC35, 0x935A, 0xBC36, 0x9361, 0xBC37, 0x9362, 0xBC38, 0xB9EB, 0xBC39, 0x9363, 0xBC3A, 0x9364, 0xBC3B, 0x9365, + 0xBC3C, 0x9366, 0xBC3D, 0x9367, 0xBC3E, 0x9368, 0xBC3F, 0x9369, 0xBC40, 0xB9EC, 0xBC41, 0xB9ED, 0xBC42, 0x936A, 0xBC43, 0xB9EE, + 0xBC44, 0xB9EF, 0xBC45, 0xB9F0, 0xBC46, 0x936B, 0xBC47, 0x936C, 0xBC48, 0x936D, 0xBC49, 0xB9F1, 0xBC4A, 0x936E, 0xBC4B, 0x936F, + 0xBC4C, 0xB9F2, 0xBC4D, 0xB9F3, 0xBC4E, 0x9370, 0xBC4F, 0x9371, 0xBC50, 0xB9F4, 0xBC51, 0x9372, 0xBC52, 0x9373, 0xBC53, 0x9374, + 0xBC54, 0x9375, 0xBC55, 0x9376, 0xBC56, 0x9377, 0xBC57, 0x9378, 0xBC58, 0x9379, 0xBC59, 0x937A, 0xBC5A, 0x9381, 0xBC5B, 0x9382, + 0xBC5C, 0x9383, 0xBC5D, 0xB9F5, 0xBC5E, 0x9384, 0xBC5F, 0x9385, 0xBC60, 0x9386, 0xBC61, 0x9387, 0xBC62, 0x9388, 0xBC63, 0x9389, + 0xBC64, 0x938A, 0xBC65, 0x938B, 0xBC66, 0x938C, 0xBC67, 0x938D, 0xBC68, 0x938E, 0xBC69, 0x938F, 0xBC6A, 0x9390, 0xBC6B, 0x9391, + 0xBC6C, 0x9392, 0xBC6D, 0x9393, 0xBC6E, 0x9394, 0xBC6F, 0x9395, 0xBC70, 0x9396, 0xBC71, 0x9397, 0xBC72, 0x9398, 0xBC73, 0x9399, + 0xBC74, 0x939A, 0xBC75, 0x939B, 0xBC76, 0x939C, 0xBC77, 0x939D, 0xBC78, 0x939E, 0xBC79, 0x939F, 0xBC7A, 0x93A0, 0xBC7B, 0x93A1, + 0xBC7C, 0x93A2, 0xBC7D, 0x93A3, 0xBC7E, 0x93A4, 0xBC7F, 0x93A5, 0xBC80, 0x93A6, 0xBC81, 0x93A7, 0xBC82, 0x93A8, 0xBC83, 0x93A9, + 0xBC84, 0xB9F6, 0xBC85, 0xB9F7, 0xBC86, 0x93AA, 0xBC87, 0x93AB, 0xBC88, 0xB9F8, 0xBC89, 0x93AC, 0xBC8A, 0x93AD, 0xBC8B, 0xB9F9, + 0xBC8C, 0xB9FA, 0xBC8D, 0x93AE, 0xBC8E, 0xB9FB, 0xBC8F, 0x93AF, 0xBC90, 0x93B0, 0xBC91, 0x93B1, 0xBC92, 0x93B2, 0xBC93, 0x93B3, + 0xBC94, 0xB9FC, 0xBC95, 0xB9FD, 0xBC96, 0x93B4, 0xBC97, 0xB9FE, 0xBC98, 0x93B5, 0xBC99, 0xBAA1, 0xBC9A, 0xBAA2, 0xBC9B, 0x93B6, + 0xBC9C, 0x93B7, 0xBC9D, 0x93B8, 0xBC9E, 0x93B9, 0xBC9F, 0x93BA, 0xBCA0, 0xBAA3, 0xBCA1, 0xBAA4, 0xBCA2, 0x93BB, 0xBCA3, 0x93BC, + 0xBCA4, 0xBAA5, 0xBCA5, 0x93BD, 0xBCA6, 0x93BE, 0xBCA7, 0xBAA6, 0xBCA8, 0xBAA7, 0xBCA9, 0x93BF, 0xBCAA, 0x93C0, 0xBCAB, 0x93C1, + 0xBCAC, 0x93C2, 0xBCAD, 0x93C3, 0xBCAE, 0x93C4, 0xBCAF, 0x93C5, 0xBCB0, 0xBAA8, 0xBCB1, 0xBAA9, 0xBCB2, 0x93C6, 0xBCB3, 0xBAAA, + 0xBCB4, 0xBAAB, 0xBCB5, 0xBAAC, 0xBCB6, 0x93C7, 0xBCB7, 0x93C8, 0xBCB8, 0x93C9, 0xBCB9, 0x93CA, 0xBCBA, 0x93CB, 0xBCBB, 0x93CC, + 0xBCBC, 0xBAAD, 0xBCBD, 0xBAAE, 0xBCBE, 0x93CD, 0xBCBF, 0x93CE, 0xBCC0, 0xBAAF, 0xBCC1, 0x93CF, 0xBCC2, 0x93D0, 0xBCC3, 0x93D1, + 0xBCC4, 0xBAB0, 0xBCC5, 0x93D2, 0xBCC6, 0x93D3, 0xBCC7, 0x93D4, 0xBCC8, 0x93D5, 0xBCC9, 0x93D6, 0xBCCA, 0x93D7, 0xBCCB, 0x93D8, + 0xBCCC, 0x93D9, 0xBCCD, 0xBAB1, 0xBCCE, 0x93DA, 0xBCCF, 0xBAB2, 0xBCD0, 0xBAB3, 0xBCD1, 0xBAB4, 0xBCD2, 0x93DB, 0xBCD3, 0x93DC, + 0xBCD4, 0x93DD, 0xBCD5, 0xBAB5, 0xBCD6, 0x93DE, 0xBCD7, 0x93DF, 0xBCD8, 0xBAB6, 0xBCD9, 0x93E0, 0xBCDA, 0x93E1, 0xBCDB, 0x93E2, + 0xBCDC, 0xBAB7, 0xBCDD, 0x93E3, 0xBCDE, 0x93E4, 0xBCDF, 0x93E5, 0xBCE0, 0x93E6, 0xBCE1, 0x93E7, 0xBCE2, 0x93E8, 0xBCE3, 0x93E9, + 0xBCE4, 0x93EA, 0xBCE5, 0x93EB, 0xBCE6, 0x93EC, 0xBCE7, 0x93ED, 0xBCE8, 0x93EE, 0xBCE9, 0x93EF, 0xBCEA, 0x93F0, 0xBCEB, 0x93F1, + 0xBCEC, 0x93F2, 0xBCED, 0x93F3, 0xBCEE, 0x93F4, 0xBCEF, 0x93F5, 0xBCF0, 0x93F6, 0xBCF1, 0x93F7, 0xBCF2, 0x93F8, 0xBCF3, 0x93F9, + 0xBCF4, 0xBAB8, 0xBCF5, 0xBAB9, 0xBCF6, 0xBABA, 0xBCF7, 0x93FA, 0xBCF8, 0xBABB, 0xBCF9, 0x93FB, 0xBCFA, 0x93FC, 0xBCFB, 0x93FD, + 0xBCFC, 0xBABC, 0xBCFD, 0x93FE, 0xBCFE, 0x9441, 0xBCFF, 0x9442, 0xBD00, 0x9443, 0xBD01, 0x9444, 0xBD02, 0x9445, 0xBD03, 0x9446, + 0xBD04, 0xBABD, 0xBD05, 0xBABE, 0xBD06, 0x9447, 0xBD07, 0xBABF, 0xBD08, 0x9448, 0xBD09, 0xBAC0, 0xBD0A, 0x9449, 0xBD0B, 0x944A, + 0xBD0C, 0x944B, 0xBD0D, 0x944C, 0xBD0E, 0x944D, 0xBD0F, 0x944E, 0xBD10, 0xBAC1, 0xBD11, 0x944F, 0xBD12, 0x9450, 0xBD13, 0x9451, + 0xBD14, 0xBAC2, 0xBD15, 0x9452, 0xBD16, 0x9453, 0xBD17, 0x9454, 0xBD18, 0x9455, 0xBD19, 0x9456, 0xBD1A, 0x9457, 0xBD1B, 0x9458, + 0xBD1C, 0x9459, 0xBD1D, 0x945A, 0xBD1E, 0x9461, 0xBD1F, 0x9462, 0xBD20, 0x9463, 0xBD21, 0x9464, 0xBD22, 0x9465, 0xBD23, 0x9466, + 0xBD24, 0xBAC3, 0xBD25, 0x9467, 0xBD26, 0x9468, 0xBD27, 0x9469, 0xBD28, 0x946A, 0xBD29, 0x946B, 0xBD2A, 0x946C, 0xBD2B, 0x946D, + 0xBD2C, 0xBAC4, 0xBD2D, 0x946E, 0xBD2E, 0x946F, 0xBD2F, 0x9470, 0xBD30, 0x9471, 0xBD31, 0x9472, 0xBD32, 0x9473, 0xBD33, 0x9474, + 0xBD34, 0x9475, 0xBD35, 0x9476, 0xBD36, 0x9477, 0xBD37, 0x9478, 0xBD38, 0x9479, 0xBD39, 0x947A, 0xBD3A, 0x9481, 0xBD3B, 0x9482, + 0xBD3C, 0x9483, 0xBD3D, 0x9484, 0xBD3E, 0x9485, 0xBD3F, 0x9486, 0xBD40, 0xBAC5, 0xBD41, 0x9487, 0xBD42, 0x9488, 0xBD43, 0x9489, + 0xBD44, 0x948A, 0xBD45, 0x948B, 0xBD46, 0x948C, 0xBD47, 0x948D, 0xBD48, 0xBAC6, 0xBD49, 0xBAC7, 0xBD4A, 0x948E, 0xBD4B, 0x948F, + 0xBD4C, 0xBAC8, 0xBD4D, 0x9490, 0xBD4E, 0x9491, 0xBD4F, 0x9492, 0xBD50, 0xBAC9, 0xBD51, 0x9493, 0xBD52, 0x9494, 0xBD53, 0x9495, + 0xBD54, 0x9496, 0xBD55, 0x9497, 0xBD56, 0x9498, 0xBD57, 0x9499, 0xBD58, 0xBACA, 0xBD59, 0xBACB, 0xBD5A, 0x949A, 0xBD5B, 0x949B, + 0xBD5C, 0x949C, 0xBD5D, 0x949D, 0xBD5E, 0x949E, 0xBD5F, 0x949F, 0xBD60, 0x94A0, 0xBD61, 0x94A1, 0xBD62, 0x94A2, 0xBD63, 0x94A3, + 0xBD64, 0xBACC, 0xBD65, 0x94A4, 0xBD66, 0x94A5, 0xBD67, 0x94A6, 0xBD68, 0xBACD, 0xBD69, 0x94A7, 0xBD6A, 0x94A8, 0xBD6B, 0x94A9, + 0xBD6C, 0x94AA, 0xBD6D, 0x94AB, 0xBD6E, 0x94AC, 0xBD6F, 0x94AD, 0xBD70, 0x94AE, 0xBD71, 0x94AF, 0xBD72, 0x94B0, 0xBD73, 0x94B1, + 0xBD74, 0x94B2, 0xBD75, 0x94B3, 0xBD76, 0x94B4, 0xBD77, 0x94B5, 0xBD78, 0x94B6, 0xBD79, 0x94B7, 0xBD7A, 0x94B8, 0xBD7B, 0x94B9, + 0xBD7C, 0x94BA, 0xBD7D, 0x94BB, 0xBD7E, 0x94BC, 0xBD7F, 0x94BD, 0xBD80, 0xBACE, 0xBD81, 0xBACF, 0xBD82, 0x94BE, 0xBD83, 0x94BF, + 0xBD84, 0xBAD0, 0xBD85, 0x94C0, 0xBD86, 0x94C1, 0xBD87, 0xBAD1, 0xBD88, 0xBAD2, 0xBD89, 0xBAD3, 0xBD8A, 0xBAD4, 0xBD8B, 0x94C2, + 0xBD8C, 0x94C3, 0xBD8D, 0x94C4, 0xBD8E, 0x94C5, 0xBD8F, 0x94C6, 0xBD90, 0xBAD5, 0xBD91, 0xBAD6, 0xBD92, 0x94C7, 0xBD93, 0xBAD7, + 0xBD94, 0x94C8, 0xBD95, 0xBAD8, 0xBD96, 0x94C9, 0xBD97, 0x94CA, 0xBD98, 0x94CB, 0xBD99, 0xBAD9, 0xBD9A, 0xBADA, 0xBD9B, 0x94CC, + 0xBD9C, 0xBADB, 0xBD9D, 0x94CD, 0xBD9E, 0x94CE, 0xBD9F, 0x94CF, 0xBDA0, 0x94D0, 0xBDA1, 0x94D1, 0xBDA2, 0x94D2, 0xBDA3, 0x94D3, + 0xBDA4, 0xBADC, 0xBDA5, 0x94D4, 0xBDA6, 0x94D5, 0xBDA7, 0x94D6, 0xBDA8, 0x94D7, 0xBDA9, 0x94D8, 0xBDAA, 0x94D9, 0xBDAB, 0x94DA, + 0xBDAC, 0x94DB, 0xBDAD, 0x94DC, 0xBDAE, 0x94DD, 0xBDAF, 0x94DE, 0xBDB0, 0xBADD, 0xBDB1, 0x94DF, 0xBDB2, 0x94E0, 0xBDB3, 0x94E1, + 0xBDB4, 0x94E2, 0xBDB5, 0x94E3, 0xBDB6, 0x94E4, 0xBDB7, 0x94E5, 0xBDB8, 0xBADE, 0xBDB9, 0x94E6, 0xBDBA, 0x94E7, 0xBDBB, 0x94E8, + 0xBDBC, 0x94E9, 0xBDBD, 0x94EA, 0xBDBE, 0x94EB, 0xBDBF, 0x94EC, 0xBDC0, 0x94ED, 0xBDC1, 0x94EE, 0xBDC2, 0x94EF, 0xBDC3, 0x94F0, + 0xBDC4, 0x94F1, 0xBDC5, 0x94F2, 0xBDC6, 0x94F3, 0xBDC7, 0x94F4, 0xBDC8, 0x94F5, 0xBDC9, 0x94F6, 0xBDCA, 0x94F7, 0xBDCB, 0x94F8, + 0xBDCC, 0x94F9, 0xBDCD, 0x94FA, 0xBDCE, 0x94FB, 0xBDCF, 0x94FC, 0xBDD0, 0x94FD, 0xBDD1, 0x94FE, 0xBDD2, 0x9541, 0xBDD3, 0x9542, + 0xBDD4, 0xBADF, 0xBDD5, 0xBAE0, 0xBDD6, 0x9543, 0xBDD7, 0x9544, 0xBDD8, 0xBAE1, 0xBDD9, 0x9545, 0xBDDA, 0x9546, 0xBDDB, 0x9547, + 0xBDDC, 0xBAE2, 0xBDDD, 0x9548, 0xBDDE, 0x9549, 0xBDDF, 0x954A, 0xBDE0, 0x954B, 0xBDE1, 0x954C, 0xBDE2, 0x954D, 0xBDE3, 0x954E, + 0xBDE4, 0x954F, 0xBDE5, 0x9550, 0xBDE6, 0x9551, 0xBDE7, 0x9552, 0xBDE8, 0x9553, 0xBDE9, 0xBAE3, 0xBDEA, 0x9554, 0xBDEB, 0x9555, + 0xBDEC, 0x9556, 0xBDED, 0x9557, 0xBDEE, 0x9558, 0xBDEF, 0x9559, 0xBDF0, 0xBAE4, 0xBDF1, 0x955A, 0xBDF2, 0x9561, 0xBDF3, 0x9562, + 0xBDF4, 0xBAE5, 0xBDF5, 0x9563, 0xBDF6, 0x9564, 0xBDF7, 0x9565, 0xBDF8, 0xBAE6, 0xBDF9, 0x9566, 0xBDFA, 0x9567, 0xBDFB, 0x9568, + 0xBDFC, 0x9569, 0xBDFD, 0x956A, 0xBDFE, 0x956B, 0xBDFF, 0x956C, 0xBE00, 0xBAE7, 0xBE01, 0x956D, 0xBE02, 0x956E, 0xBE03, 0xBAE8, + 0xBE04, 0x956F, 0xBE05, 0xBAE9, 0xBE06, 0x9570, 0xBE07, 0x9571, 0xBE08, 0x9572, 0xBE09, 0x9573, 0xBE0A, 0x9574, 0xBE0B, 0x9575, + 0xBE0C, 0xBAEA, 0xBE0D, 0xBAEB, 0xBE0E, 0x9576, 0xBE0F, 0x9577, 0xBE10, 0xBAEC, 0xBE11, 0x9578, 0xBE12, 0x9579, 0xBE13, 0x957A, + 0xBE14, 0xBAED, 0xBE15, 0x9581, 0xBE16, 0x9582, 0xBE17, 0x9583, 0xBE18, 0x9584, 0xBE19, 0x9585, 0xBE1A, 0x9586, 0xBE1B, 0x9587, + 0xBE1C, 0xBAEE, 0xBE1D, 0xBAEF, 0xBE1E, 0x9588, 0xBE1F, 0xBAF0, 0xBE20, 0x9589, 0xBE21, 0x958A, 0xBE22, 0x958B, 0xBE23, 0x958C, + 0xBE24, 0x958D, 0xBE25, 0x958E, 0xBE26, 0x958F, 0xBE27, 0x9590, 0xBE28, 0x9591, 0xBE29, 0x9592, 0xBE2A, 0x9593, 0xBE2B, 0x9594, + 0xBE2C, 0x9595, 0xBE2D, 0x9596, 0xBE2E, 0x9597, 0xBE2F, 0x9598, 0xBE30, 0x9599, 0xBE31, 0x959A, 0xBE32, 0x959B, 0xBE33, 0x959C, + 0xBE34, 0x959D, 0xBE35, 0x959E, 0xBE36, 0x959F, 0xBE37, 0x95A0, 0xBE38, 0x95A1, 0xBE39, 0x95A2, 0xBE3A, 0x95A3, 0xBE3B, 0x95A4, + 0xBE3C, 0x95A5, 0xBE3D, 0x95A6, 0xBE3E, 0x95A7, 0xBE3F, 0x95A8, 0xBE40, 0x95A9, 0xBE41, 0x95AA, 0xBE42, 0x95AB, 0xBE43, 0x95AC, + 0xBE44, 0xBAF1, 0xBE45, 0xBAF2, 0xBE46, 0x95AD, 0xBE47, 0x95AE, 0xBE48, 0xBAF3, 0xBE49, 0x95AF, 0xBE4A, 0x95B0, 0xBE4B, 0x95B1, + 0xBE4C, 0xBAF4, 0xBE4D, 0x95B2, 0xBE4E, 0xBAF5, 0xBE4F, 0x95B3, 0xBE50, 0x95B4, 0xBE51, 0x95B5, 0xBE52, 0x95B6, 0xBE53, 0x95B7, + 0xBE54, 0xBAF6, 0xBE55, 0xBAF7, 0xBE56, 0x95B8, 0xBE57, 0xBAF8, 0xBE58, 0x95B9, 0xBE59, 0xBAF9, 0xBE5A, 0xBAFA, 0xBE5B, 0xBAFB, + 0xBE5C, 0x95BA, 0xBE5D, 0x95BB, 0xBE5E, 0x95BC, 0xBE5F, 0x95BD, 0xBE60, 0xBAFC, 0xBE61, 0xBAFD, 0xBE62, 0x95BE, 0xBE63, 0x95BF, + 0xBE64, 0xBAFE, 0xBE65, 0x95C0, 0xBE66, 0x95C1, 0xBE67, 0x95C2, 0xBE68, 0xBBA1, 0xBE69, 0x95C3, 0xBE6A, 0xBBA2, 0xBE6B, 0x95C4, + 0xBE6C, 0x95C5, 0xBE6D, 0x95C6, 0xBE6E, 0x95C7, 0xBE6F, 0x95C8, 0xBE70, 0xBBA3, 0xBE71, 0xBBA4, 0xBE72, 0x95C9, 0xBE73, 0xBBA5, + 0xBE74, 0xBBA6, 0xBE75, 0xBBA7, 0xBE76, 0x95CA, 0xBE77, 0x95CB, 0xBE78, 0x95CC, 0xBE79, 0x95CD, 0xBE7A, 0x95CE, 0xBE7B, 0xBBA8, + 0xBE7C, 0xBBA9, 0xBE7D, 0xBBAA, 0xBE7E, 0x95CF, 0xBE7F, 0x95D0, 0xBE80, 0xBBAB, 0xBE81, 0x95D1, 0xBE82, 0x95D2, 0xBE83, 0x95D3, + 0xBE84, 0xBBAC, 0xBE85, 0x95D4, 0xBE86, 0x95D5, 0xBE87, 0x95D6, 0xBE88, 0x95D7, 0xBE89, 0x95D8, 0xBE8A, 0x95D9, 0xBE8B, 0x95DA, + 0xBE8C, 0xBBAD, 0xBE8D, 0xBBAE, 0xBE8E, 0x95DB, 0xBE8F, 0xBBAF, 0xBE90, 0xBBB0, 0xBE91, 0xBBB1, 0xBE92, 0x95DC, 0xBE93, 0x95DD, + 0xBE94, 0x95DE, 0xBE95, 0x95DF, 0xBE96, 0x95E0, 0xBE97, 0x95E1, 0xBE98, 0xBBB2, 0xBE99, 0xBBB3, 0xBE9A, 0x95E2, 0xBE9B, 0x95E3, + 0xBE9C, 0x95E4, 0xBE9D, 0x95E5, 0xBE9E, 0x95E6, 0xBE9F, 0x95E7, 0xBEA0, 0x95E8, 0xBEA1, 0x95E9, 0xBEA2, 0x95EA, 0xBEA3, 0x95EB, + 0xBEA4, 0x95EC, 0xBEA5, 0x95ED, 0xBEA6, 0x95EE, 0xBEA7, 0x95EF, 0xBEA8, 0xBBB4, 0xBEA9, 0x95F0, 0xBEAA, 0x95F1, 0xBEAB, 0x95F2, + 0xBEAC, 0x95F3, 0xBEAD, 0x95F4, 0xBEAE, 0x95F5, 0xBEAF, 0x95F6, 0xBEB0, 0x95F7, 0xBEB1, 0x95F8, 0xBEB2, 0x95F9, 0xBEB3, 0x95FA, + 0xBEB4, 0x95FB, 0xBEB5, 0x95FC, 0xBEB6, 0x95FD, 0xBEB7, 0x95FE, 0xBEB8, 0x9641, 0xBEB9, 0x9642, 0xBEBA, 0x9643, 0xBEBB, 0x9644, + 0xBEBC, 0x9645, 0xBEBD, 0x9646, 0xBEBE, 0x9647, 0xBEBF, 0x9648, 0xBEC0, 0x9649, 0xBEC1, 0x964A, 0xBEC2, 0x964B, 0xBEC3, 0x964C, + 0xBEC4, 0x964D, 0xBEC5, 0x964E, 0xBEC6, 0x964F, 0xBEC7, 0x9650, 0xBEC8, 0x9651, 0xBEC9, 0x9652, 0xBECA, 0x9653, 0xBECB, 0x9654, + 0xBECC, 0x9655, 0xBECD, 0x9656, 0xBECE, 0x9657, 0xBECF, 0x9658, 0xBED0, 0xBBB5, 0xBED1, 0xBBB6, 0xBED2, 0x9659, 0xBED3, 0x965A, + 0xBED4, 0xBBB7, 0xBED5, 0x9661, 0xBED6, 0x9662, 0xBED7, 0xBBB8, 0xBED8, 0xBBB9, 0xBED9, 0x9663, 0xBEDA, 0x9664, 0xBEDB, 0x9665, + 0xBEDC, 0x9666, 0xBEDD, 0x9667, 0xBEDE, 0x9668, 0xBEDF, 0x9669, 0xBEE0, 0xBBBA, 0xBEE1, 0x966A, 0xBEE2, 0x966B, 0xBEE3, 0xBBBB, + 0xBEE4, 0xBBBC, 0xBEE5, 0xBBBD, 0xBEE6, 0x966C, 0xBEE7, 0x966D, 0xBEE8, 0x966E, 0xBEE9, 0x966F, 0xBEEA, 0x9670, 0xBEEB, 0x9671, + 0xBEEC, 0xBBBE, 0xBEED, 0x9672, 0xBEEE, 0x9673, 0xBEEF, 0x9674, 0xBEF0, 0x9675, 0xBEF1, 0x9676, 0xBEF2, 0x9677, 0xBEF3, 0x9678, + 0xBEF4, 0x9679, 0xBEF5, 0x967A, 0xBEF6, 0x9681, 0xBEF7, 0x9682, 0xBEF8, 0x9683, 0xBEF9, 0x9684, 0xBEFA, 0x9685, 0xBEFB, 0x9686, + 0xBEFC, 0x9687, 0xBEFD, 0x9688, 0xBEFE, 0x9689, 0xBEFF, 0x968A, 0xBF00, 0x968B, 0xBF01, 0xBBBF, 0xBF02, 0x968C, 0xBF03, 0x968D, + 0xBF04, 0x968E, 0xBF05, 0x968F, 0xBF06, 0x9690, 0xBF07, 0x9691, 0xBF08, 0xBBC0, 0xBF09, 0xBBC1, 0xBF0A, 0x9692, 0xBF0B, 0x9693, + 0xBF0C, 0x9694, 0xBF0D, 0x9695, 0xBF0E, 0x9696, 0xBF0F, 0x9697, 0xBF10, 0x9698, 0xBF11, 0x9699, 0xBF12, 0x969A, 0xBF13, 0x969B, + 0xBF14, 0x969C, 0xBF15, 0x969D, 0xBF16, 0x969E, 0xBF17, 0x969F, 0xBF18, 0xBBC2, 0xBF19, 0xBBC3, 0xBF1A, 0x96A0, 0xBF1B, 0xBBC4, + 0xBF1C, 0xBBC5, 0xBF1D, 0xBBC6, 0xBF1E, 0x96A1, 0xBF1F, 0x96A2, 0xBF20, 0x96A3, 0xBF21, 0x96A4, 0xBF22, 0x96A5, 0xBF23, 0x96A6, + 0xBF24, 0x96A7, 0xBF25, 0x96A8, 0xBF26, 0x96A9, 0xBF27, 0x96AA, 0xBF28, 0x96AB, 0xBF29, 0x96AC, 0xBF2A, 0x96AD, 0xBF2B, 0x96AE, + 0xBF2C, 0x96AF, 0xBF2D, 0x96B0, 0xBF2E, 0x96B1, 0xBF2F, 0x96B2, 0xBF30, 0x96B3, 0xBF31, 0x96B4, 0xBF32, 0x96B5, 0xBF33, 0x96B6, + 0xBF34, 0x96B7, 0xBF35, 0x96B8, 0xBF36, 0x96B9, 0xBF37, 0x96BA, 0xBF38, 0x96BB, 0xBF39, 0x96BC, 0xBF3A, 0x96BD, 0xBF3B, 0x96BE, + 0xBF3C, 0x96BF, 0xBF3D, 0x96C0, 0xBF3E, 0x96C1, 0xBF3F, 0x96C2, 0xBF40, 0xBBC7, 0xBF41, 0xBBC8, 0xBF42, 0x96C3, 0xBF43, 0x96C4, + 0xBF44, 0xBBC9, 0xBF45, 0x96C5, 0xBF46, 0x96C6, 0xBF47, 0x96C7, 0xBF48, 0xBBCA, 0xBF49, 0x96C8, 0xBF4A, 0x96C9, 0xBF4B, 0x96CA, + 0xBF4C, 0x96CB, 0xBF4D, 0x96CC, 0xBF4E, 0x96CD, 0xBF4F, 0x96CE, 0xBF50, 0xBBCB, 0xBF51, 0xBBCC, 0xBF52, 0x96CF, 0xBF53, 0x96D0, + 0xBF54, 0x96D1, 0xBF55, 0xBBCD, 0xBF56, 0x96D2, 0xBF57, 0x96D3, 0xBF58, 0x96D4, 0xBF59, 0x96D5, 0xBF5A, 0x96D6, 0xBF5B, 0x96D7, + 0xBF5C, 0x96D8, 0xBF5D, 0x96D9, 0xBF5E, 0x96DA, 0xBF5F, 0x96DB, 0xBF60, 0x96DC, 0xBF61, 0x96DD, 0xBF62, 0x96DE, 0xBF63, 0x96DF, + 0xBF64, 0x96E0, 0xBF65, 0x96E1, 0xBF66, 0x96E2, 0xBF67, 0x96E3, 0xBF68, 0x96E4, 0xBF69, 0x96E5, 0xBF6A, 0x96E6, 0xBF6B, 0x96E7, + 0xBF6C, 0x96E8, 0xBF6D, 0x96E9, 0xBF6E, 0x96EA, 0xBF6F, 0x96EB, 0xBF70, 0x96EC, 0xBF71, 0x96ED, 0xBF72, 0x96EE, 0xBF73, 0x96EF, + 0xBF74, 0x96F0, 0xBF75, 0x96F1, 0xBF76, 0x96F2, 0xBF77, 0x96F3, 0xBF78, 0x96F4, 0xBF79, 0x96F5, 0xBF7A, 0x96F6, 0xBF7B, 0x96F7, + 0xBF7C, 0x96F8, 0xBF7D, 0x96F9, 0xBF7E, 0x96FA, 0xBF7F, 0x96FB, 0xBF80, 0x96FC, 0xBF81, 0x96FD, 0xBF82, 0x96FE, 0xBF83, 0x9741, + 0xBF84, 0x9742, 0xBF85, 0x9743, 0xBF86, 0x9744, 0xBF87, 0x9745, 0xBF88, 0x9746, 0xBF89, 0x9747, 0xBF8A, 0x9748, 0xBF8B, 0x9749, + 0xBF8C, 0x974A, 0xBF8D, 0x974B, 0xBF8E, 0x974C, 0xBF8F, 0x974D, 0xBF90, 0x974E, 0xBF91, 0x974F, 0xBF92, 0x9750, 0xBF93, 0x9751, + 0xBF94, 0xBBCE, 0xBF95, 0x9752, 0xBF96, 0x9753, 0xBF97, 0x9754, 0xBF98, 0x9755, 0xBF99, 0x9756, 0xBF9A, 0x9757, 0xBF9B, 0x9758, + 0xBF9C, 0x9759, 0xBF9D, 0x975A, 0xBF9E, 0x9761, 0xBF9F, 0x9762, 0xBFA0, 0x9763, 0xBFA1, 0x9764, 0xBFA2, 0x9765, 0xBFA3, 0x9766, + 0xBFA4, 0x9767, 0xBFA5, 0x9768, 0xBFA6, 0x9769, 0xBFA7, 0x976A, 0xBFA8, 0x976B, 0xBFA9, 0x976C, 0xBFAA, 0x976D, 0xBFAB, 0x976E, + 0xBFAC, 0x976F, 0xBFAD, 0x9770, 0xBFAE, 0x9771, 0xBFAF, 0x9772, 0xBFB0, 0xBBCF, 0xBFB1, 0x9773, 0xBFB2, 0x9774, 0xBFB3, 0x9775, + 0xBFB4, 0x9776, 0xBFB5, 0x9777, 0xBFB6, 0x9778, 0xBFB7, 0x9779, 0xBFB8, 0x977A, 0xBFB9, 0x9781, 0xBFBA, 0x9782, 0xBFBB, 0x9783, + 0xBFBC, 0x9784, 0xBFBD, 0x9785, 0xBFBE, 0x9786, 0xBFBF, 0x9787, 0xBFC0, 0x9788, 0xBFC1, 0x9789, 0xBFC2, 0x978A, 0xBFC3, 0x978B, + 0xBFC4, 0x978C, 0xBFC5, 0xBBD0, 0xBFC6, 0x978D, 0xBFC7, 0x978E, 0xBFC8, 0x978F, 0xBFC9, 0x9790, 0xBFCA, 0x9791, 0xBFCB, 0x9792, + 0xBFCC, 0xBBD1, 0xBFCD, 0xBBD2, 0xBFCE, 0x9793, 0xBFCF, 0x9794, 0xBFD0, 0xBBD3, 0xBFD1, 0x9795, 0xBFD2, 0x9796, 0xBFD3, 0x9797, + 0xBFD4, 0xBBD4, 0xBFD5, 0x9798, 0xBFD6, 0x9799, 0xBFD7, 0x979A, 0xBFD8, 0x979B, 0xBFD9, 0x979C, 0xBFDA, 0x979D, 0xBFDB, 0x979E, + 0xBFDC, 0xBBD5, 0xBFDD, 0x979F, 0xBFDE, 0x97A0, 0xBFDF, 0xBBD6, 0xBFE0, 0x97A1, 0xBFE1, 0xBBD7, 0xBFE2, 0x97A2, 0xBFE3, 0x97A3, + 0xBFE4, 0x97A4, 0xBFE5, 0x97A5, 0xBFE6, 0x97A6, 0xBFE7, 0x97A7, 0xBFE8, 0x97A8, 0xBFE9, 0x97A9, 0xBFEA, 0x97AA, 0xBFEB, 0x97AB, + 0xBFEC, 0x97AC, 0xBFED, 0x97AD, 0xBFEE, 0x97AE, 0xBFEF, 0x97AF, 0xBFF0, 0x97B0, 0xBFF1, 0x97B1, 0xBFF2, 0x97B2, 0xBFF3, 0x97B3, + 0xBFF4, 0x97B4, 0xBFF5, 0x97B5, 0xBFF6, 0x97B6, 0xBFF7, 0x97B7, 0xBFF8, 0x97B8, 0xBFF9, 0x97B9, 0xBFFA, 0x97BA, 0xBFFB, 0x97BB, + 0xBFFC, 0x97BC, 0xBFFD, 0x97BD, 0xBFFE, 0x97BE, 0xBFFF, 0x97BF, 0xC000, 0x97C0, 0xC001, 0x97C1, 0xC002, 0x97C2, 0xC003, 0x97C3, + 0xC004, 0x97C4, 0xC005, 0x97C5, 0xC006, 0x97C6, 0xC007, 0x97C7, 0xC008, 0x97C8, 0xC009, 0x97C9, 0xC00A, 0x97CA, 0xC00B, 0x97CB, + 0xC00C, 0x97CC, 0xC00D, 0x97CD, 0xC00E, 0x97CE, 0xC00F, 0x97CF, 0xC010, 0x97D0, 0xC011, 0x97D1, 0xC012, 0x97D2, 0xC013, 0x97D3, + 0xC014, 0x97D4, 0xC015, 0x97D5, 0xC016, 0x97D6, 0xC017, 0x97D7, 0xC018, 0x97D8, 0xC019, 0x97D9, 0xC01A, 0x97DA, 0xC01B, 0x97DB, + 0xC01C, 0x97DC, 0xC01D, 0x97DD, 0xC01E, 0x97DE, 0xC01F, 0x97DF, 0xC020, 0x97E0, 0xC021, 0x97E1, 0xC022, 0x97E2, 0xC023, 0x97E3, + 0xC024, 0x97E4, 0xC025, 0x97E5, 0xC026, 0x97E6, 0xC027, 0x97E7, 0xC028, 0x97E8, 0xC029, 0x97E9, 0xC02A, 0x97EA, 0xC02B, 0x97EB, + 0xC02C, 0x97EC, 0xC02D, 0x97ED, 0xC02E, 0x97EE, 0xC02F, 0x97EF, 0xC030, 0x97F0, 0xC031, 0x97F1, 0xC032, 0x97F2, 0xC033, 0x97F3, + 0xC034, 0x97F4, 0xC035, 0x97F5, 0xC036, 0x97F6, 0xC037, 0x97F7, 0xC038, 0x97F8, 0xC039, 0x97F9, 0xC03A, 0x97FA, 0xC03B, 0x97FB, + 0xC03C, 0xBBD8, 0xC03D, 0x97FC, 0xC03E, 0x97FD, 0xC03F, 0x97FE, 0xC040, 0x9841, 0xC041, 0x9842, 0xC042, 0x9843, 0xC043, 0x9844, + 0xC044, 0x9845, 0xC045, 0x9846, 0xC046, 0x9847, 0xC047, 0x9848, 0xC048, 0x9849, 0xC049, 0x984A, 0xC04A, 0x984B, 0xC04B, 0x984C, + 0xC04C, 0x984D, 0xC04D, 0x984E, 0xC04E, 0x984F, 0xC04F, 0x9850, 0xC050, 0x9851, 0xC051, 0xBBD9, 0xC052, 0x9852, 0xC053, 0x9853, + 0xC054, 0x9854, 0xC055, 0x9855, 0xC056, 0x9856, 0xC057, 0x9857, 0xC058, 0xBBDA, 0xC059, 0x9858, 0xC05A, 0x9859, 0xC05B, 0x985A, + 0xC05C, 0xBBDB, 0xC05D, 0x9861, 0xC05E, 0x9862, 0xC05F, 0x9863, 0xC060, 0xBBDC, 0xC061, 0x9864, 0xC062, 0x9865, 0xC063, 0x9866, + 0xC064, 0x9867, 0xC065, 0x9868, 0xC066, 0x9869, 0xC067, 0x986A, 0xC068, 0xBBDD, 0xC069, 0xBBDE, 0xC06A, 0x986B, 0xC06B, 0x986C, + 0xC06C, 0x986D, 0xC06D, 0x986E, 0xC06E, 0x986F, 0xC06F, 0x9870, 0xC070, 0x9871, 0xC071, 0x9872, 0xC072, 0x9873, 0xC073, 0x9874, + 0xC074, 0x9875, 0xC075, 0x9876, 0xC076, 0x9877, 0xC077, 0x9878, 0xC078, 0x9879, 0xC079, 0x987A, 0xC07A, 0x9881, 0xC07B, 0x9882, + 0xC07C, 0x9883, 0xC07D, 0x9884, 0xC07E, 0x9885, 0xC07F, 0x9886, 0xC080, 0x9887, 0xC081, 0x9888, 0xC082, 0x9889, 0xC083, 0x988A, + 0xC084, 0x988B, 0xC085, 0x988C, 0xC086, 0x988D, 0xC087, 0x988E, 0xC088, 0x988F, 0xC089, 0x9890, 0xC08A, 0x9891, 0xC08B, 0x9892, + 0xC08C, 0x9893, 0xC08D, 0x9894, 0xC08E, 0x9895, 0xC08F, 0x9896, 0xC090, 0xBBDF, 0xC091, 0xBBE0, 0xC092, 0x9897, 0xC093, 0x9898, + 0xC094, 0xBBE1, 0xC095, 0x9899, 0xC096, 0x989A, 0xC097, 0x989B, 0xC098, 0xBBE2, 0xC099, 0x989C, 0xC09A, 0x989D, 0xC09B, 0x989E, + 0xC09C, 0x989F, 0xC09D, 0x98A0, 0xC09E, 0x98A1, 0xC09F, 0x98A2, 0xC0A0, 0xBBE3, 0xC0A1, 0xBBE4, 0xC0A2, 0x98A3, 0xC0A3, 0xBBE5, + 0xC0A4, 0x98A4, 0xC0A5, 0xBBE6, 0xC0A6, 0x98A5, 0xC0A7, 0x98A6, 0xC0A8, 0x98A7, 0xC0A9, 0x98A8, 0xC0AA, 0x98A9, 0xC0AB, 0x98AA, + 0xC0AC, 0xBBE7, 0xC0AD, 0xBBE8, 0xC0AE, 0x98AB, 0xC0AF, 0xBBE9, 0xC0B0, 0xBBEA, 0xC0B1, 0x98AC, 0xC0B2, 0x98AD, 0xC0B3, 0xBBEB, + 0xC0B4, 0xBBEC, 0xC0B5, 0xBBED, 0xC0B6, 0xBBEE, 0xC0B7, 0x98AE, 0xC0B8, 0x98AF, 0xC0B9, 0x98B0, 0xC0BA, 0x98B1, 0xC0BB, 0x98B2, + 0xC0BC, 0xBBEF, 0xC0BD, 0xBBF0, 0xC0BE, 0x98B3, 0xC0BF, 0xBBF1, 0xC0C0, 0xBBF2, 0xC0C1, 0xBBF3, 0xC0C2, 0x98B4, 0xC0C3, 0x98B5, + 0xC0C4, 0x98B6, 0xC0C5, 0xBBF4, 0xC0C6, 0x98B7, 0xC0C7, 0x98B8, 0xC0C8, 0xBBF5, 0xC0C9, 0xBBF6, 0xC0CA, 0x98B9, 0xC0CB, 0x98BA, + 0xC0CC, 0xBBF7, 0xC0CD, 0x98BB, 0xC0CE, 0x98BC, 0xC0CF, 0x98BD, 0xC0D0, 0xBBF8, 0xC0D1, 0x98BE, 0xC0D2, 0x98BF, 0xC0D3, 0x98C0, + 0xC0D4, 0x98C1, 0xC0D5, 0x98C2, 0xC0D6, 0x98C3, 0xC0D7, 0x98C4, 0xC0D8, 0xBBF9, 0xC0D9, 0xBBFA, 0xC0DA, 0x98C5, 0xC0DB, 0xBBFB, + 0xC0DC, 0xBBFC, 0xC0DD, 0xBBFD, 0xC0DE, 0x98C6, 0xC0DF, 0x98C7, 0xC0E0, 0x98C8, 0xC0E1, 0x98C9, 0xC0E2, 0x98CA, 0xC0E3, 0x98CB, + 0xC0E4, 0xBBFE, 0xC0E5, 0xBCA1, 0xC0E6, 0x98CC, 0xC0E7, 0x98CD, 0xC0E8, 0xBCA2, 0xC0E9, 0x98CE, 0xC0EA, 0x98CF, 0xC0EB, 0x98D0, + 0xC0EC, 0xBCA3, 0xC0ED, 0x98D1, 0xC0EE, 0x98D2, 0xC0EF, 0x98D3, 0xC0F0, 0x98D4, 0xC0F1, 0x98D5, 0xC0F2, 0x98D6, 0xC0F3, 0x98D7, + 0xC0F4, 0xBCA4, 0xC0F5, 0xBCA5, 0xC0F6, 0x98D8, 0xC0F7, 0xBCA6, 0xC0F8, 0x98D9, 0xC0F9, 0xBCA7, 0xC0FA, 0x98DA, 0xC0FB, 0x98DB, + 0xC0FC, 0x98DC, 0xC0FD, 0x98DD, 0xC0FE, 0x98DE, 0xC0FF, 0x98DF, 0xC100, 0xBCA8, 0xC101, 0x98E0, 0xC102, 0x98E1, 0xC103, 0x98E2, + 0xC104, 0xBCA9, 0xC105, 0x98E3, 0xC106, 0x98E4, 0xC107, 0x98E5, 0xC108, 0xBCAA, 0xC109, 0x98E6, 0xC10A, 0x98E7, 0xC10B, 0x98E8, + 0xC10C, 0x98E9, 0xC10D, 0x98EA, 0xC10E, 0x98EB, 0xC10F, 0x98EC, 0xC110, 0xBCAB, 0xC111, 0x98ED, 0xC112, 0x98EE, 0xC113, 0x98EF, + 0xC114, 0x98F0, 0xC115, 0xBCAC, 0xC116, 0x98F1, 0xC117, 0x98F2, 0xC118, 0x98F3, 0xC119, 0x98F4, 0xC11A, 0x98F5, 0xC11B, 0x98F6, + 0xC11C, 0xBCAD, 0xC11D, 0xBCAE, 0xC11E, 0xBCAF, 0xC11F, 0xBCB0, 0xC120, 0xBCB1, 0xC121, 0x98F7, 0xC122, 0x98F8, 0xC123, 0xBCB2, + 0xC124, 0xBCB3, 0xC125, 0x98F9, 0xC126, 0xBCB4, 0xC127, 0xBCB5, 0xC128, 0x98FA, 0xC129, 0x98FB, 0xC12A, 0x98FC, 0xC12B, 0x98FD, + 0xC12C, 0xBCB6, 0xC12D, 0xBCB7, 0xC12E, 0x98FE, 0xC12F, 0xBCB8, 0xC130, 0xBCB9, 0xC131, 0xBCBA, 0xC132, 0x9941, 0xC133, 0x9942, + 0xC134, 0x9943, 0xC135, 0x9944, 0xC136, 0xBCBB, 0xC137, 0x9945, 0xC138, 0xBCBC, 0xC139, 0xBCBD, 0xC13A, 0x9946, 0xC13B, 0x9947, + 0xC13C, 0xBCBE, 0xC13D, 0x9948, 0xC13E, 0x9949, 0xC13F, 0x994A, 0xC140, 0xBCBF, 0xC141, 0x994B, 0xC142, 0x994C, 0xC143, 0x994D, + 0xC144, 0x994E, 0xC145, 0x994F, 0xC146, 0x9950, 0xC147, 0x9951, 0xC148, 0xBCC0, 0xC149, 0xBCC1, 0xC14A, 0x9952, 0xC14B, 0xBCC2, + 0xC14C, 0xBCC3, 0xC14D, 0xBCC4, 0xC14E, 0x9953, 0xC14F, 0x9954, 0xC150, 0x9955, 0xC151, 0x9956, 0xC152, 0x9957, 0xC153, 0x9958, + 0xC154, 0xBCC5, 0xC155, 0xBCC6, 0xC156, 0x9959, 0xC157, 0x995A, 0xC158, 0xBCC7, 0xC159, 0x9961, 0xC15A, 0x9962, 0xC15B, 0x9963, + 0xC15C, 0xBCC8, 0xC15D, 0x9964, 0xC15E, 0x9965, 0xC15F, 0x9966, 0xC160, 0x9967, 0xC161, 0x9968, 0xC162, 0x9969, 0xC163, 0x996A, + 0xC164, 0xBCC9, 0xC165, 0xBCCA, 0xC166, 0x996B, 0xC167, 0xBCCB, 0xC168, 0xBCCC, 0xC169, 0xBCCD, 0xC16A, 0x996C, 0xC16B, 0x996D, + 0xC16C, 0x996E, 0xC16D, 0x996F, 0xC16E, 0x9970, 0xC16F, 0x9971, 0xC170, 0xBCCE, 0xC171, 0x9972, 0xC172, 0x9973, 0xC173, 0x9974, + 0xC174, 0xBCCF, 0xC175, 0x9975, 0xC176, 0x9976, 0xC177, 0x9977, 0xC178, 0xBCD0, 0xC179, 0x9978, 0xC17A, 0x9979, 0xC17B, 0x997A, + 0xC17C, 0x9981, 0xC17D, 0x9982, 0xC17E, 0x9983, 0xC17F, 0x9984, 0xC180, 0x9985, 0xC181, 0x9986, 0xC182, 0x9987, 0xC183, 0x9988, + 0xC184, 0x9989, 0xC185, 0xBCD1, 0xC186, 0x998A, 0xC187, 0x998B, 0xC188, 0x998C, 0xC189, 0x998D, 0xC18A, 0x998E, 0xC18B, 0x998F, + 0xC18C, 0xBCD2, 0xC18D, 0xBCD3, 0xC18E, 0xBCD4, 0xC18F, 0x9990, 0xC190, 0xBCD5, 0xC191, 0x9991, 0xC192, 0x9992, 0xC193, 0x9993, + 0xC194, 0xBCD6, 0xC195, 0x9994, 0xC196, 0xBCD7, 0xC197, 0x9995, 0xC198, 0x9996, 0xC199, 0x9997, 0xC19A, 0x9998, 0xC19B, 0x9999, + 0xC19C, 0xBCD8, 0xC19D, 0xBCD9, 0xC19E, 0x999A, 0xC19F, 0xBCDA, 0xC1A0, 0x999B, 0xC1A1, 0xBCDB, 0xC1A2, 0x999C, 0xC1A3, 0x999D, + 0xC1A4, 0x999E, 0xC1A5, 0xBCDC, 0xC1A6, 0x999F, 0xC1A7, 0x99A0, 0xC1A8, 0xBCDD, 0xC1A9, 0xBCDE, 0xC1AA, 0x99A1, 0xC1AB, 0x99A2, + 0xC1AC, 0xBCDF, 0xC1AD, 0x99A3, 0xC1AE, 0x99A4, 0xC1AF, 0x99A5, 0xC1B0, 0xBCE0, 0xC1B1, 0x99A6, 0xC1B2, 0x99A7, 0xC1B3, 0x99A8, + 0xC1B4, 0x99A9, 0xC1B5, 0x99AA, 0xC1B6, 0x99AB, 0xC1B7, 0x99AC, 0xC1B8, 0x99AD, 0xC1B9, 0x99AE, 0xC1BA, 0x99AF, 0xC1BB, 0x99B0, + 0xC1BC, 0x99B1, 0xC1BD, 0xBCE1, 0xC1BE, 0x99B2, 0xC1BF, 0x99B3, 0xC1C0, 0x99B4, 0xC1C1, 0x99B5, 0xC1C2, 0x99B6, 0xC1C3, 0x99B7, + 0xC1C4, 0xBCE2, 0xC1C5, 0x99B8, 0xC1C6, 0x99B9, 0xC1C7, 0x99BA, 0xC1C8, 0xBCE3, 0xC1C9, 0x99BB, 0xC1CA, 0x99BC, 0xC1CB, 0x99BD, + 0xC1CC, 0xBCE4, 0xC1CD, 0x99BE, 0xC1CE, 0x99BF, 0xC1CF, 0x99C0, 0xC1D0, 0x99C1, 0xC1D1, 0x99C2, 0xC1D2, 0x99C3, 0xC1D3, 0x99C4, + 0xC1D4, 0xBCE5, 0xC1D5, 0x99C5, 0xC1D6, 0x99C6, 0xC1D7, 0xBCE6, 0xC1D8, 0xBCE7, 0xC1D9, 0x99C7, 0xC1DA, 0x99C8, 0xC1DB, 0x99C9, + 0xC1DC, 0x99CA, 0xC1DD, 0x99CB, 0xC1DE, 0x99CC, 0xC1DF, 0x99CD, 0xC1E0, 0xBCE8, 0xC1E1, 0x99CE, 0xC1E2, 0x99CF, 0xC1E3, 0x99D0, + 0xC1E4, 0xBCE9, 0xC1E5, 0x99D1, 0xC1E6, 0x99D2, 0xC1E7, 0x99D3, 0xC1E8, 0xBCEA, 0xC1E9, 0x99D4, 0xC1EA, 0x99D5, 0xC1EB, 0x99D6, + 0xC1EC, 0x99D7, 0xC1ED, 0x99D8, 0xC1EE, 0x99D9, 0xC1EF, 0x99DA, 0xC1F0, 0xBCEB, 0xC1F1, 0xBCEC, 0xC1F2, 0x99DB, 0xC1F3, 0xBCED, + 0xC1F4, 0x99DC, 0xC1F5, 0x99DD, 0xC1F6, 0x99DE, 0xC1F7, 0x99DF, 0xC1F8, 0x99E0, 0xC1F9, 0x99E1, 0xC1FA, 0x99E2, 0xC1FB, 0x99E3, + 0xC1FC, 0xBCEE, 0xC1FD, 0xBCEF, 0xC1FE, 0x99E4, 0xC1FF, 0x99E5, 0xC200, 0xBCF0, 0xC201, 0x99E6, 0xC202, 0x99E7, 0xC203, 0x99E8, + 0xC204, 0xBCF1, 0xC205, 0x99E9, 0xC206, 0x99EA, 0xC207, 0x99EB, 0xC208, 0x99EC, 0xC209, 0x99ED, 0xC20A, 0x99EE, 0xC20B, 0x99EF, + 0xC20C, 0xBCF2, 0xC20D, 0xBCF3, 0xC20E, 0x99F0, 0xC20F, 0xBCF4, 0xC210, 0x99F1, 0xC211, 0xBCF5, 0xC212, 0x99F2, 0xC213, 0x99F3, + 0xC214, 0x99F4, 0xC215, 0x99F5, 0xC216, 0x99F6, 0xC217, 0x99F7, 0xC218, 0xBCF6, 0xC219, 0xBCF7, 0xC21A, 0x99F8, 0xC21B, 0x99F9, + 0xC21C, 0xBCF8, 0xC21D, 0x99FA, 0xC21E, 0x99FB, 0xC21F, 0xBCF9, 0xC220, 0xBCFA, 0xC221, 0x99FC, 0xC222, 0x99FD, 0xC223, 0x99FE, + 0xC224, 0x9A41, 0xC225, 0x9A42, 0xC226, 0x9A43, 0xC227, 0x9A44, 0xC228, 0xBCFB, 0xC229, 0xBCFC, 0xC22A, 0x9A45, 0xC22B, 0xBCFD, + 0xC22C, 0x9A46, 0xC22D, 0xBCFE, 0xC22E, 0x9A47, 0xC22F, 0xBDA1, 0xC230, 0x9A48, 0xC231, 0xBDA2, 0xC232, 0xBDA3, 0xC233, 0x9A49, + 0xC234, 0xBDA4, 0xC235, 0x9A4A, 0xC236, 0x9A4B, 0xC237, 0x9A4C, 0xC238, 0x9A4D, 0xC239, 0x9A4E, 0xC23A, 0x9A4F, 0xC23B, 0x9A50, + 0xC23C, 0x9A51, 0xC23D, 0x9A52, 0xC23E, 0x9A53, 0xC23F, 0x9A54, 0xC240, 0x9A55, 0xC241, 0x9A56, 0xC242, 0x9A57, 0xC243, 0x9A58, + 0xC244, 0x9A59, 0xC245, 0x9A5A, 0xC246, 0x9A61, 0xC247, 0x9A62, 0xC248, 0xBDA5, 0xC249, 0x9A63, 0xC24A, 0x9A64, 0xC24B, 0x9A65, + 0xC24C, 0x9A66, 0xC24D, 0x9A67, 0xC24E, 0x9A68, 0xC24F, 0x9A69, 0xC250, 0xBDA6, 0xC251, 0xBDA7, 0xC252, 0x9A6A, 0xC253, 0x9A6B, + 0xC254, 0xBDA8, 0xC255, 0x9A6C, 0xC256, 0x9A6D, 0xC257, 0x9A6E, 0xC258, 0xBDA9, 0xC259, 0x9A6F, 0xC25A, 0x9A70, 0xC25B, 0x9A71, + 0xC25C, 0x9A72, 0xC25D, 0x9A73, 0xC25E, 0x9A74, 0xC25F, 0x9A75, 0xC260, 0xBDAA, 0xC261, 0x9A76, 0xC262, 0x9A77, 0xC263, 0x9A78, + 0xC264, 0x9A79, 0xC265, 0xBDAB, 0xC266, 0x9A7A, 0xC267, 0x9A81, 0xC268, 0x9A82, 0xC269, 0x9A83, 0xC26A, 0x9A84, 0xC26B, 0x9A85, + 0xC26C, 0xBDAC, 0xC26D, 0xBDAD, 0xC26E, 0x9A86, 0xC26F, 0x9A87, 0xC270, 0xBDAE, 0xC271, 0x9A88, 0xC272, 0x9A89, 0xC273, 0x9A8A, + 0xC274, 0xBDAF, 0xC275, 0x9A8B, 0xC276, 0x9A8C, 0xC277, 0x9A8D, 0xC278, 0x9A8E, 0xC279, 0x9A8F, 0xC27A, 0x9A90, 0xC27B, 0x9A91, + 0xC27C, 0xBDB0, 0xC27D, 0xBDB1, 0xC27E, 0x9A92, 0xC27F, 0xBDB2, 0xC280, 0x9A93, 0xC281, 0xBDB3, 0xC282, 0x9A94, 0xC283, 0x9A95, + 0xC284, 0x9A96, 0xC285, 0x9A97, 0xC286, 0x9A98, 0xC287, 0x9A99, 0xC288, 0xBDB4, 0xC289, 0xBDB5, 0xC28A, 0x9A9A, 0xC28B, 0x9A9B, + 0xC28C, 0x9A9C, 0xC28D, 0x9A9D, 0xC28E, 0x9A9E, 0xC28F, 0x9A9F, 0xC290, 0xBDB6, 0xC291, 0x9AA0, 0xC292, 0x9AA1, 0xC293, 0x9AA2, + 0xC294, 0x9AA3, 0xC295, 0x9AA4, 0xC296, 0x9AA5, 0xC297, 0x9AA6, 0xC298, 0xBDB7, 0xC299, 0x9AA7, 0xC29A, 0x9AA8, 0xC29B, 0xBDB8, + 0xC29C, 0x9AA9, 0xC29D, 0xBDB9, 0xC29E, 0x9AAA, 0xC29F, 0x9AAB, 0xC2A0, 0x9AAC, 0xC2A1, 0x9AAD, 0xC2A2, 0x9AAE, 0xC2A3, 0x9AAF, + 0xC2A4, 0xBDBA, 0xC2A5, 0xBDBB, 0xC2A6, 0x9AB0, 0xC2A7, 0x9AB1, 0xC2A8, 0xBDBC, 0xC2A9, 0x9AB2, 0xC2AA, 0x9AB3, 0xC2AB, 0x9AB4, + 0xC2AC, 0xBDBD, 0xC2AD, 0xBDBE, 0xC2AE, 0x9AB5, 0xC2AF, 0x9AB6, 0xC2B0, 0x9AB7, 0xC2B1, 0x9AB8, 0xC2B2, 0x9AB9, 0xC2B3, 0x9ABA, + 0xC2B4, 0xBDBF, 0xC2B5, 0xBDC0, 0xC2B6, 0x9ABB, 0xC2B7, 0xBDC1, 0xC2B8, 0x9ABC, 0xC2B9, 0xBDC2, 0xC2BA, 0x9ABD, 0xC2BB, 0x9ABE, + 0xC2BC, 0x9ABF, 0xC2BD, 0x9AC0, 0xC2BE, 0x9AC1, 0xC2BF, 0x9AC2, 0xC2C0, 0x9AC3, 0xC2C1, 0x9AC4, 0xC2C2, 0x9AC5, 0xC2C3, 0x9AC6, + 0xC2C4, 0x9AC7, 0xC2C5, 0x9AC8, 0xC2C6, 0x9AC9, 0xC2C7, 0x9ACA, 0xC2C8, 0x9ACB, 0xC2C9, 0x9ACC, 0xC2CA, 0x9ACD, 0xC2CB, 0x9ACE, + 0xC2CC, 0x9ACF, 0xC2CD, 0x9AD0, 0xC2CE, 0x9AD1, 0xC2CF, 0x9AD2, 0xC2D0, 0x9AD3, 0xC2D1, 0x9AD4, 0xC2D2, 0x9AD5, 0xC2D3, 0x9AD6, + 0xC2D4, 0x9AD7, 0xC2D5, 0x9AD8, 0xC2D6, 0x9AD9, 0xC2D7, 0x9ADA, 0xC2D8, 0x9ADB, 0xC2D9, 0x9ADC, 0xC2DA, 0x9ADD, 0xC2DB, 0x9ADE, + 0xC2DC, 0xBDC3, 0xC2DD, 0xBDC4, 0xC2DE, 0x9ADF, 0xC2DF, 0x9AE0, 0xC2E0, 0xBDC5, 0xC2E1, 0x9AE1, 0xC2E2, 0x9AE2, 0xC2E3, 0xBDC6, + 0xC2E4, 0xBDC7, 0xC2E5, 0x9AE3, 0xC2E6, 0x9AE4, 0xC2E7, 0x9AE5, 0xC2E8, 0x9AE6, 0xC2E9, 0x9AE7, 0xC2EA, 0x9AE8, 0xC2EB, 0xBDC8, + 0xC2EC, 0xBDC9, 0xC2ED, 0xBDCA, 0xC2EE, 0x9AE9, 0xC2EF, 0xBDCB, 0xC2F0, 0x9AEA, 0xC2F1, 0xBDCC, 0xC2F2, 0x9AEB, 0xC2F3, 0x9AEC, + 0xC2F4, 0x9AED, 0xC2F5, 0x9AEE, 0xC2F6, 0xBDCD, 0xC2F7, 0x9AEF, 0xC2F8, 0xBDCE, 0xC2F9, 0xBDCF, 0xC2FA, 0x9AF0, 0xC2FB, 0xBDD0, + 0xC2FC, 0xBDD1, 0xC2FD, 0x9AF1, 0xC2FE, 0x9AF2, 0xC2FF, 0x9AF3, 0xC300, 0xBDD2, 0xC301, 0x9AF4, 0xC302, 0x9AF5, 0xC303, 0x9AF6, + 0xC304, 0x9AF7, 0xC305, 0x9AF8, 0xC306, 0x9AF9, 0xC307, 0x9AFA, 0xC308, 0xBDD3, 0xC309, 0xBDD4, 0xC30A, 0x9AFB, 0xC30B, 0x9AFC, + 0xC30C, 0xBDD5, 0xC30D, 0xBDD6, 0xC30E, 0x9AFD, 0xC30F, 0x9AFE, 0xC310, 0x9B41, 0xC311, 0x9B42, 0xC312, 0x9B43, 0xC313, 0xBDD7, + 0xC314, 0xBDD8, 0xC315, 0xBDD9, 0xC316, 0x9B44, 0xC317, 0x9B45, 0xC318, 0xBDDA, 0xC319, 0x9B46, 0xC31A, 0x9B47, 0xC31B, 0x9B48, + 0xC31C, 0xBDDB, 0xC31D, 0x9B49, 0xC31E, 0x9B4A, 0xC31F, 0x9B4B, 0xC320, 0x9B4C, 0xC321, 0x9B4D, 0xC322, 0x9B4E, 0xC323, 0x9B4F, + 0xC324, 0xBDDC, 0xC325, 0xBDDD, 0xC326, 0x9B50, 0xC327, 0x9B51, 0xC328, 0xBDDE, 0xC329, 0xBDDF, 0xC32A, 0x9B52, 0xC32B, 0x9B53, + 0xC32C, 0x9B54, 0xC32D, 0x9B55, 0xC32E, 0x9B56, 0xC32F, 0x9B57, 0xC330, 0x9B58, 0xC331, 0x9B59, 0xC332, 0x9B5A, 0xC333, 0x9B61, + 0xC334, 0x9B62, 0xC335, 0x9B63, 0xC336, 0x9B64, 0xC337, 0x9B65, 0xC338, 0x9B66, 0xC339, 0x9B67, 0xC33A, 0x9B68, 0xC33B, 0x9B69, + 0xC33C, 0x9B6A, 0xC33D, 0x9B6B, 0xC33E, 0x9B6C, 0xC33F, 0x9B6D, 0xC340, 0x9B6E, 0xC341, 0x9B6F, 0xC342, 0x9B70, 0xC343, 0x9B71, + 0xC344, 0x9B72, 0xC345, 0xBDE0, 0xC346, 0x9B73, 0xC347, 0x9B74, 0xC348, 0x9B75, 0xC349, 0x9B76, 0xC34A, 0x9B77, 0xC34B, 0x9B78, + 0xC34C, 0x9B79, 0xC34D, 0x9B7A, 0xC34E, 0x9B81, 0xC34F, 0x9B82, 0xC350, 0x9B83, 0xC351, 0x9B84, 0xC352, 0x9B85, 0xC353, 0x9B86, + 0xC354, 0x9B87, 0xC355, 0x9B88, 0xC356, 0x9B89, 0xC357, 0x9B8A, 0xC358, 0x9B8B, 0xC359, 0x9B8C, 0xC35A, 0x9B8D, 0xC35B, 0x9B8E, + 0xC35C, 0x9B8F, 0xC35D, 0x9B90, 0xC35E, 0x9B91, 0xC35F, 0x9B92, 0xC360, 0x9B93, 0xC361, 0x9B94, 0xC362, 0x9B95, 0xC363, 0x9B96, + 0xC364, 0x9B97, 0xC365, 0x9B98, 0xC366, 0x9B99, 0xC367, 0x9B9A, 0xC368, 0xBDE1, 0xC369, 0xBDE2, 0xC36A, 0x9B9B, 0xC36B, 0x9B9C, + 0xC36C, 0xBDE3, 0xC36D, 0x9B9D, 0xC36E, 0x9B9E, 0xC36F, 0x9B9F, 0xC370, 0xBDE4, 0xC371, 0x9BA0, 0xC372, 0xBDE5, 0xC373, 0x9BA1, + 0xC374, 0x9BA2, 0xC375, 0x9BA3, 0xC376, 0x9BA4, 0xC377, 0x9BA5, 0xC378, 0xBDE6, 0xC379, 0xBDE7, 0xC37A, 0x9BA6, 0xC37B, 0x9BA7, + 0xC37C, 0xBDE8, 0xC37D, 0xBDE9, 0xC37E, 0x9BA8, 0xC37F, 0x9BA9, 0xC380, 0x9BAA, 0xC381, 0x9BAB, 0xC382, 0x9BAC, 0xC383, 0x9BAD, + 0xC384, 0xBDEA, 0xC385, 0x9BAE, 0xC386, 0x9BAF, 0xC387, 0x9BB0, 0xC388, 0xBDEB, 0xC389, 0x9BB1, 0xC38A, 0x9BB2, 0xC38B, 0x9BB3, + 0xC38C, 0xBDEC, 0xC38D, 0x9BB4, 0xC38E, 0x9BB5, 0xC38F, 0x9BB6, 0xC390, 0x9BB7, 0xC391, 0x9BB8, 0xC392, 0x9BB9, 0xC393, 0x9BBA, + 0xC394, 0x9BBB, 0xC395, 0x9BBC, 0xC396, 0x9BBD, 0xC397, 0x9BBE, 0xC398, 0x9BBF, 0xC399, 0x9BC0, 0xC39A, 0x9BC1, 0xC39B, 0x9BC2, + 0xC39C, 0x9BC3, 0xC39D, 0x9BC4, 0xC39E, 0x9BC5, 0xC39F, 0x9BC6, 0xC3A0, 0x9BC7, 0xC3A1, 0x9BC8, 0xC3A2, 0x9BC9, 0xC3A3, 0x9BCA, + 0xC3A4, 0x9BCB, 0xC3A5, 0x9BCC, 0xC3A6, 0x9BCD, 0xC3A7, 0x9BCE, 0xC3A8, 0x9BCF, 0xC3A9, 0x9BD0, 0xC3AA, 0x9BD1, 0xC3AB, 0x9BD2, + 0xC3AC, 0x9BD3, 0xC3AD, 0x9BD4, 0xC3AE, 0x9BD5, 0xC3AF, 0x9BD6, 0xC3B0, 0x9BD7, 0xC3B1, 0x9BD8, 0xC3B2, 0x9BD9, 0xC3B3, 0x9BDA, + 0xC3B4, 0x9BDB, 0xC3B5, 0x9BDC, 0xC3B6, 0x9BDD, 0xC3B7, 0x9BDE, 0xC3B8, 0x9BDF, 0xC3B9, 0x9BE0, 0xC3BA, 0x9BE1, 0xC3BB, 0x9BE2, + 0xC3BC, 0x9BE3, 0xC3BD, 0x9BE4, 0xC3BE, 0x9BE5, 0xC3BF, 0x9BE6, 0xC3C0, 0xBDED, 0xC3C1, 0x9BE7, 0xC3C2, 0x9BE8, 0xC3C3, 0x9BE9, + 0xC3C4, 0x9BEA, 0xC3C5, 0x9BEB, 0xC3C6, 0x9BEC, 0xC3C7, 0x9BED, 0xC3C8, 0x9BEE, 0xC3C9, 0x9BEF, 0xC3CA, 0x9BF0, 0xC3CB, 0x9BF1, + 0xC3CC, 0x9BF2, 0xC3CD, 0x9BF3, 0xC3CE, 0x9BF4, 0xC3CF, 0x9BF5, 0xC3D0, 0x9BF6, 0xC3D1, 0x9BF7, 0xC3D2, 0x9BF8, 0xC3D3, 0x9BF9, + 0xC3D4, 0x9BFA, 0xC3D5, 0x9BFB, 0xC3D6, 0x9BFC, 0xC3D7, 0x9BFD, 0xC3D8, 0xBDEE, 0xC3D9, 0xBDEF, 0xC3DA, 0x9BFE, 0xC3DB, 0x9C41, + 0xC3DC, 0xBDF0, 0xC3DD, 0x9C42, 0xC3DE, 0x9C43, 0xC3DF, 0xBDF1, 0xC3E0, 0xBDF2, 0xC3E1, 0x9C44, 0xC3E2, 0xBDF3, 0xC3E3, 0x9C45, + 0xC3E4, 0x9C46, 0xC3E5, 0x9C47, 0xC3E6, 0x9C48, 0xC3E7, 0x9C49, 0xC3E8, 0xBDF4, 0xC3E9, 0xBDF5, 0xC3EA, 0x9C4A, 0xC3EB, 0x9C4B, + 0xC3EC, 0x9C4C, 0xC3ED, 0xBDF6, 0xC3EE, 0x9C4D, 0xC3EF, 0x9C4E, 0xC3F0, 0x9C4F, 0xC3F1, 0x9C50, 0xC3F2, 0x9C51, 0xC3F3, 0x9C52, + 0xC3F4, 0xBDF7, 0xC3F5, 0xBDF8, 0xC3F6, 0x9C53, 0xC3F7, 0x9C54, 0xC3F8, 0xBDF9, 0xC3F9, 0x9C55, 0xC3FA, 0x9C56, 0xC3FB, 0x9C57, + 0xC3FC, 0x9C58, 0xC3FD, 0x9C59, 0xC3FE, 0x9C5A, 0xC3FF, 0x9C61, 0xC400, 0x9C62, 0xC401, 0x9C63, 0xC402, 0x9C64, 0xC403, 0x9C65, + 0xC404, 0x9C66, 0xC405, 0x9C67, 0xC406, 0x9C68, 0xC407, 0x9C69, 0xC408, 0xBDFA, 0xC409, 0x9C6A, 0xC40A, 0x9C6B, 0xC40B, 0x9C6C, + 0xC40C, 0x9C6D, 0xC40D, 0x9C6E, 0xC40E, 0x9C6F, 0xC40F, 0x9C70, 0xC410, 0xBDFB, 0xC411, 0x9C71, 0xC412, 0x9C72, 0xC413, 0x9C73, + 0xC414, 0x9C74, 0xC415, 0x9C75, 0xC416, 0x9C76, 0xC417, 0x9C77, 0xC418, 0x9C78, 0xC419, 0x9C79, 0xC41A, 0x9C7A, 0xC41B, 0x9C81, + 0xC41C, 0x9C82, 0xC41D, 0x9C83, 0xC41E, 0x9C84, 0xC41F, 0x9C85, 0xC420, 0x9C86, 0xC421, 0x9C87, 0xC422, 0x9C88, 0xC423, 0x9C89, + 0xC424, 0xBDFC, 0xC425, 0x9C8A, 0xC426, 0x9C8B, 0xC427, 0x9C8C, 0xC428, 0x9C8D, 0xC429, 0x9C8E, 0xC42A, 0x9C8F, 0xC42B, 0x9C90, + 0xC42C, 0xBDFD, 0xC42D, 0x9C91, 0xC42E, 0x9C92, 0xC42F, 0x9C93, 0xC430, 0xBDFE, 0xC431, 0x9C94, 0xC432, 0x9C95, 0xC433, 0x9C96, + 0xC434, 0xBEA1, 0xC435, 0x9C97, 0xC436, 0x9C98, 0xC437, 0x9C99, 0xC438, 0x9C9A, 0xC439, 0x9C9B, 0xC43A, 0x9C9C, 0xC43B, 0x9C9D, + 0xC43C, 0xBEA2, 0xC43D, 0xBEA3, 0xC43E, 0x9C9E, 0xC43F, 0x9C9F, 0xC440, 0x9CA0, 0xC441, 0x9CA1, 0xC442, 0x9CA2, 0xC443, 0x9CA3, + 0xC444, 0x9CA4, 0xC445, 0x9CA5, 0xC446, 0x9CA6, 0xC447, 0x9CA7, 0xC448, 0xBEA4, 0xC449, 0x9CA8, 0xC44A, 0x9CA9, 0xC44B, 0x9CAA, + 0xC44C, 0x9CAB, 0xC44D, 0x9CAC, 0xC44E, 0x9CAD, 0xC44F, 0x9CAE, 0xC450, 0x9CAF, 0xC451, 0x9CB0, 0xC452, 0x9CB1, 0xC453, 0x9CB2, + 0xC454, 0x9CB3, 0xC455, 0x9CB4, 0xC456, 0x9CB5, 0xC457, 0x9CB6, 0xC458, 0x9CB7, 0xC459, 0x9CB8, 0xC45A, 0x9CB9, 0xC45B, 0x9CBA, + 0xC45C, 0x9CBB, 0xC45D, 0x9CBC, 0xC45E, 0x9CBD, 0xC45F, 0x9CBE, 0xC460, 0x9CBF, 0xC461, 0x9CC0, 0xC462, 0x9CC1, 0xC463, 0x9CC2, + 0xC464, 0xBEA5, 0xC465, 0xBEA6, 0xC466, 0x9CC3, 0xC467, 0x9CC4, 0xC468, 0xBEA7, 0xC469, 0x9CC5, 0xC46A, 0x9CC6, 0xC46B, 0x9CC7, + 0xC46C, 0xBEA8, 0xC46D, 0x9CC8, 0xC46E, 0x9CC9, 0xC46F, 0x9CCA, 0xC470, 0x9CCB, 0xC471, 0x9CCC, 0xC472, 0x9CCD, 0xC473, 0x9CCE, + 0xC474, 0xBEA9, 0xC475, 0xBEAA, 0xC476, 0x9CCF, 0xC477, 0x9CD0, 0xC478, 0x9CD1, 0xC479, 0xBEAB, 0xC47A, 0x9CD2, 0xC47B, 0x9CD3, + 0xC47C, 0x9CD4, 0xC47D, 0x9CD5, 0xC47E, 0x9CD6, 0xC47F, 0x9CD7, 0xC480, 0xBEAC, 0xC481, 0x9CD8, 0xC482, 0x9CD9, 0xC483, 0x9CDA, + 0xC484, 0x9CDB, 0xC485, 0x9CDC, 0xC486, 0x9CDD, 0xC487, 0x9CDE, 0xC488, 0x9CDF, 0xC489, 0x9CE0, 0xC48A, 0x9CE1, 0xC48B, 0x9CE2, + 0xC48C, 0x9CE3, 0xC48D, 0x9CE4, 0xC48E, 0x9CE5, 0xC48F, 0x9CE6, 0xC490, 0x9CE7, 0xC491, 0x9CE8, 0xC492, 0x9CE9, 0xC493, 0x9CEA, + 0xC494, 0xBEAD, 0xC495, 0x9CEB, 0xC496, 0x9CEC, 0xC497, 0x9CED, 0xC498, 0x9CEE, 0xC499, 0x9CEF, 0xC49A, 0x9CF0, 0xC49B, 0x9CF1, + 0xC49C, 0xBEAE, 0xC49D, 0x9CF2, 0xC49E, 0x9CF3, 0xC49F, 0x9CF4, 0xC4A0, 0x9CF5, 0xC4A1, 0x9CF6, 0xC4A2, 0x9CF7, 0xC4A3, 0x9CF8, + 0xC4A4, 0x9CF9, 0xC4A5, 0x9CFA, 0xC4A6, 0x9CFB, 0xC4A7, 0x9CFC, 0xC4A8, 0x9CFD, 0xC4A9, 0x9CFE, 0xC4AA, 0x9D41, 0xC4AB, 0x9D42, + 0xC4AC, 0x9D43, 0xC4AD, 0x9D44, 0xC4AE, 0x9D45, 0xC4AF, 0x9D46, 0xC4B0, 0x9D47, 0xC4B1, 0x9D48, 0xC4B2, 0x9D49, 0xC4B3, 0x9D4A, + 0xC4B4, 0x9D4B, 0xC4B5, 0x9D4C, 0xC4B6, 0x9D4D, 0xC4B7, 0x9D4E, 0xC4B8, 0xBEAF, 0xC4B9, 0x9D4F, 0xC4BA, 0x9D50, 0xC4BB, 0x9D51, + 0xC4BC, 0xBEB0, 0xC4BD, 0x9D52, 0xC4BE, 0x9D53, 0xC4BF, 0x9D54, 0xC4C0, 0x9D55, 0xC4C1, 0x9D56, 0xC4C2, 0x9D57, 0xC4C3, 0x9D58, + 0xC4C4, 0x9D59, 0xC4C5, 0x9D5A, 0xC4C6, 0x9D61, 0xC4C7, 0x9D62, 0xC4C8, 0x9D63, 0xC4C9, 0x9D64, 0xC4CA, 0x9D65, 0xC4CB, 0x9D66, + 0xC4CC, 0x9D67, 0xC4CD, 0x9D68, 0xC4CE, 0x9D69, 0xC4CF, 0x9D6A, 0xC4D0, 0x9D6B, 0xC4D1, 0x9D6C, 0xC4D2, 0x9D6D, 0xC4D3, 0x9D6E, + 0xC4D4, 0x9D6F, 0xC4D5, 0x9D70, 0xC4D6, 0x9D71, 0xC4D7, 0x9D72, 0xC4D8, 0x9D73, 0xC4D9, 0x9D74, 0xC4DA, 0x9D75, 0xC4DB, 0x9D76, + 0xC4DC, 0x9D77, 0xC4DD, 0x9D78, 0xC4DE, 0x9D79, 0xC4DF, 0x9D7A, 0xC4E0, 0x9D81, 0xC4E1, 0x9D82, 0xC4E2, 0x9D83, 0xC4E3, 0x9D84, + 0xC4E4, 0x9D85, 0xC4E5, 0x9D86, 0xC4E6, 0x9D87, 0xC4E7, 0x9D88, 0xC4E8, 0x9D89, 0xC4E9, 0xBEB1, 0xC4EA, 0x9D8A, 0xC4EB, 0x9D8B, + 0xC4EC, 0x9D8C, 0xC4ED, 0x9D8D, 0xC4EE, 0x9D8E, 0xC4EF, 0x9D8F, 0xC4F0, 0xBEB2, 0xC4F1, 0xBEB3, 0xC4F2, 0x9D90, 0xC4F3, 0x9D91, + 0xC4F4, 0xBEB4, 0xC4F5, 0x9D92, 0xC4F6, 0x9D93, 0xC4F7, 0x9D94, 0xC4F8, 0xBEB5, 0xC4F9, 0x9D95, 0xC4FA, 0xBEB6, 0xC4FB, 0x9D96, + 0xC4FC, 0x9D97, 0xC4FD, 0x9D98, 0xC4FE, 0x9D99, 0xC4FF, 0xBEB7, 0xC500, 0xBEB8, 0xC501, 0xBEB9, 0xC502, 0x9D9A, 0xC503, 0x9D9B, + 0xC504, 0x9D9C, 0xC505, 0x9D9D, 0xC506, 0x9D9E, 0xC507, 0x9D9F, 0xC508, 0x9DA0, 0xC509, 0x9DA1, 0xC50A, 0x9DA2, 0xC50B, 0x9DA3, + 0xC50C, 0xBEBA, 0xC50D, 0x9DA4, 0xC50E, 0x9DA5, 0xC50F, 0x9DA6, 0xC510, 0xBEBB, 0xC511, 0x9DA7, 0xC512, 0x9DA8, 0xC513, 0x9DA9, + 0xC514, 0xBEBC, 0xC515, 0x9DAA, 0xC516, 0x9DAB, 0xC517, 0x9DAC, 0xC518, 0x9DAD, 0xC519, 0x9DAE, 0xC51A, 0x9DAF, 0xC51B, 0x9DB0, + 0xC51C, 0xBEBD, 0xC51D, 0x9DB1, 0xC51E, 0x9DB2, 0xC51F, 0x9DB3, 0xC520, 0x9DB4, 0xC521, 0x9DB5, 0xC522, 0x9DB6, 0xC523, 0x9DB7, + 0xC524, 0x9DB8, 0xC525, 0x9DB9, 0xC526, 0x9DBA, 0xC527, 0x9DBB, 0xC528, 0xBEBE, 0xC529, 0xBEBF, 0xC52A, 0x9DBC, 0xC52B, 0x9DBD, + 0xC52C, 0xBEC0, 0xC52D, 0x9DBE, 0xC52E, 0x9DBF, 0xC52F, 0x9DC0, 0xC530, 0xBEC1, 0xC531, 0x9DC1, 0xC532, 0x9DC2, 0xC533, 0x9DC3, + 0xC534, 0x9DC4, 0xC535, 0x9DC5, 0xC536, 0x9DC6, 0xC537, 0x9DC7, 0xC538, 0xBEC2, 0xC539, 0xBEC3, 0xC53A, 0x9DC8, 0xC53B, 0xBEC4, + 0xC53C, 0x9DC9, 0xC53D, 0xBEC5, 0xC53E, 0x9DCA, 0xC53F, 0x9DCB, 0xC540, 0x9DCC, 0xC541, 0x9DCD, 0xC542, 0x9DCE, 0xC543, 0x9DCF, + 0xC544, 0xBEC6, 0xC545, 0xBEC7, 0xC546, 0x9DD0, 0xC547, 0x9DD1, 0xC548, 0xBEC8, 0xC549, 0xBEC9, 0xC54A, 0xBECA, 0xC54B, 0x9DD2, + 0xC54C, 0xBECB, 0xC54D, 0xBECC, 0xC54E, 0xBECD, 0xC54F, 0x9DD3, 0xC550, 0x9DD4, 0xC551, 0x9DD5, 0xC552, 0x9DD6, 0xC553, 0xBECE, + 0xC554, 0xBECF, 0xC555, 0xBED0, 0xC556, 0x9DD7, 0xC557, 0xBED1, 0xC558, 0xBED2, 0xC559, 0xBED3, 0xC55A, 0x9DD8, 0xC55B, 0x9DD9, + 0xC55C, 0x9DDA, 0xC55D, 0xBED4, 0xC55E, 0xBED5, 0xC55F, 0x9DDB, 0xC560, 0xBED6, 0xC561, 0xBED7, 0xC562, 0x9DDC, 0xC563, 0x9DDD, + 0xC564, 0xBED8, 0xC565, 0x9DDE, 0xC566, 0x9DDF, 0xC567, 0x9DE0, 0xC568, 0xBED9, 0xC569, 0x9DE1, 0xC56A, 0x9DE2, 0xC56B, 0x9DE3, + 0xC56C, 0x9DE4, 0xC56D, 0x9DE5, 0xC56E, 0x9DE6, 0xC56F, 0x9DE7, 0xC570, 0xBEDA, 0xC571, 0xBEDB, 0xC572, 0x9DE8, 0xC573, 0xBEDC, + 0xC574, 0xBEDD, 0xC575, 0xBEDE, 0xC576, 0x9DE9, 0xC577, 0x9DEA, 0xC578, 0x9DEB, 0xC579, 0x9DEC, 0xC57A, 0x9DED, 0xC57B, 0x9DEE, + 0xC57C, 0xBEDF, 0xC57D, 0xBEE0, 0xC57E, 0x9DEF, 0xC57F, 0x9DF0, 0xC580, 0xBEE1, 0xC581, 0x9DF1, 0xC582, 0x9DF2, 0xC583, 0x9DF3, + 0xC584, 0xBEE2, 0xC585, 0x9DF4, 0xC586, 0x9DF5, 0xC587, 0xBEE3, 0xC588, 0x9DF6, 0xC589, 0x9DF7, 0xC58A, 0x9DF8, 0xC58B, 0x9DF9, + 0xC58C, 0xBEE4, 0xC58D, 0xBEE5, 0xC58E, 0x9DFA, 0xC58F, 0xBEE6, 0xC590, 0x9DFB, 0xC591, 0xBEE7, 0xC592, 0x9DFC, 0xC593, 0x9DFD, + 0xC594, 0x9DFE, 0xC595, 0xBEE8, 0xC596, 0x9E41, 0xC597, 0xBEE9, 0xC598, 0xBEEA, 0xC599, 0x9E42, 0xC59A, 0x9E43, 0xC59B, 0x9E44, + 0xC59C, 0xBEEB, 0xC59D, 0x9E45, 0xC59E, 0x9E46, 0xC59F, 0x9E47, 0xC5A0, 0xBEEC, 0xC5A1, 0x9E48, 0xC5A2, 0x9E49, 0xC5A3, 0x9E4A, + 0xC5A4, 0x9E4B, 0xC5A5, 0x9E4C, 0xC5A6, 0x9E4D, 0xC5A7, 0x9E4E, 0xC5A8, 0x9E4F, 0xC5A9, 0xBEED, 0xC5AA, 0x9E50, 0xC5AB, 0x9E51, + 0xC5AC, 0x9E52, 0xC5AD, 0x9E53, 0xC5AE, 0x9E54, 0xC5AF, 0x9E55, 0xC5B0, 0x9E56, 0xC5B1, 0x9E57, 0xC5B2, 0x9E58, 0xC5B3, 0x9E59, + 0xC5B4, 0xBEEE, 0xC5B5, 0xBEEF, 0xC5B6, 0x9E5A, 0xC5B7, 0x9E61, 0xC5B8, 0xBEF0, 0xC5B9, 0xBEF1, 0xC5BA, 0x9E62, 0xC5BB, 0xBEF2, + 0xC5BC, 0xBEF3, 0xC5BD, 0xBEF4, 0xC5BE, 0xBEF5, 0xC5BF, 0x9E63, 0xC5C0, 0x9E64, 0xC5C1, 0x9E65, 0xC5C2, 0x9E66, 0xC5C3, 0x9E67, + 0xC5C4, 0xBEF6, 0xC5C5, 0xBEF7, 0xC5C6, 0xBEF8, 0xC5C7, 0xBEF9, 0xC5C8, 0xBEFA, 0xC5C9, 0xBEFB, 0xC5CA, 0xBEFC, 0xC5CB, 0x9E68, + 0xC5CC, 0xBEFD, 0xC5CD, 0x9E69, 0xC5CE, 0xBEFE, 0xC5CF, 0x9E6A, 0xC5D0, 0xBFA1, 0xC5D1, 0xBFA2, 0xC5D2, 0x9E6B, 0xC5D3, 0x9E6C, + 0xC5D4, 0xBFA3, 0xC5D5, 0x9E6D, 0xC5D6, 0x9E6E, 0xC5D7, 0x9E6F, 0xC5D8, 0xBFA4, 0xC5D9, 0x9E70, 0xC5DA, 0x9E71, 0xC5DB, 0x9E72, + 0xC5DC, 0x9E73, 0xC5DD, 0x9E74, 0xC5DE, 0x9E75, 0xC5DF, 0x9E76, 0xC5E0, 0xBFA5, 0xC5E1, 0xBFA6, 0xC5E2, 0x9E77, 0xC5E3, 0xBFA7, + 0xC5E4, 0x9E78, 0xC5E5, 0xBFA8, 0xC5E6, 0x9E79, 0xC5E7, 0x9E7A, 0xC5E8, 0x9E81, 0xC5E9, 0x9E82, 0xC5EA, 0x9E83, 0xC5EB, 0x9E84, + 0xC5EC, 0xBFA9, 0xC5ED, 0xBFAA, 0xC5EE, 0xBFAB, 0xC5EF, 0x9E85, 0xC5F0, 0xBFAC, 0xC5F1, 0x9E86, 0xC5F2, 0x9E87, 0xC5F3, 0x9E88, + 0xC5F4, 0xBFAD, 0xC5F5, 0x9E89, 0xC5F6, 0xBFAE, 0xC5F7, 0xBFAF, 0xC5F8, 0x9E8A, 0xC5F9, 0x9E8B, 0xC5FA, 0x9E8C, 0xC5FB, 0x9E8D, + 0xC5FC, 0xBFB0, 0xC5FD, 0xBFB1, 0xC5FE, 0xBFB2, 0xC5FF, 0xBFB3, 0xC600, 0xBFB4, 0xC601, 0xBFB5, 0xC602, 0x9E8E, 0xC603, 0x9E8F, + 0xC604, 0x9E90, 0xC605, 0xBFB6, 0xC606, 0xBFB7, 0xC607, 0xBFB8, 0xC608, 0xBFB9, 0xC609, 0x9E91, 0xC60A, 0x9E92, 0xC60B, 0x9E93, + 0xC60C, 0xBFBA, 0xC60D, 0x9E94, 0xC60E, 0x9E95, 0xC60F, 0x9E96, 0xC610, 0xBFBB, 0xC611, 0x9E97, 0xC612, 0x9E98, 0xC613, 0x9E99, + 0xC614, 0x9E9A, 0xC615, 0x9E9B, 0xC616, 0x9E9C, 0xC617, 0x9E9D, 0xC618, 0xBFBC, 0xC619, 0xBFBD, 0xC61A, 0x9E9E, 0xC61B, 0xBFBE, + 0xC61C, 0xBFBF, 0xC61D, 0x9E9F, 0xC61E, 0x9EA0, 0xC61F, 0x9EA1, 0xC620, 0x9EA2, 0xC621, 0x9EA3, 0xC622, 0x9EA4, 0xC623, 0x9EA5, + 0xC624, 0xBFC0, 0xC625, 0xBFC1, 0xC626, 0x9EA6, 0xC627, 0x9EA7, 0xC628, 0xBFC2, 0xC629, 0x9EA8, 0xC62A, 0x9EA9, 0xC62B, 0x9EAA, + 0xC62C, 0xBFC3, 0xC62D, 0xBFC4, 0xC62E, 0xBFC5, 0xC62F, 0x9EAB, 0xC630, 0xBFC6, 0xC631, 0x9EAC, 0xC632, 0x9EAD, 0xC633, 0xBFC7, + 0xC634, 0xBFC8, 0xC635, 0xBFC9, 0xC636, 0x9EAE, 0xC637, 0xBFCA, 0xC638, 0x9EAF, 0xC639, 0xBFCB, 0xC63A, 0x9EB0, 0xC63B, 0xBFCC, + 0xC63C, 0x9EB1, 0xC63D, 0x9EB2, 0xC63E, 0x9EB3, 0xC63F, 0x9EB4, 0xC640, 0xBFCD, 0xC641, 0xBFCE, 0xC642, 0x9EB5, 0xC643, 0x9EB6, + 0xC644, 0xBFCF, 0xC645, 0x9EB7, 0xC646, 0x9EB8, 0xC647, 0x9EB9, 0xC648, 0xBFD0, 0xC649, 0x9EBA, 0xC64A, 0x9EBB, 0xC64B, 0x9EBC, + 0xC64C, 0x9EBD, 0xC64D, 0x9EBE, 0xC64E, 0x9EBF, 0xC64F, 0x9EC0, 0xC650, 0xBFD1, 0xC651, 0xBFD2, 0xC652, 0x9EC1, 0xC653, 0xBFD3, + 0xC654, 0xBFD4, 0xC655, 0xBFD5, 0xC656, 0x9EC2, 0xC657, 0x9EC3, 0xC658, 0x9EC4, 0xC659, 0x9EC5, 0xC65A, 0x9EC6, 0xC65B, 0x9EC7, + 0xC65C, 0xBFD6, 0xC65D, 0xBFD7, 0xC65E, 0x9EC8, 0xC65F, 0x9EC9, 0xC660, 0xBFD8, 0xC661, 0x9ECA, 0xC662, 0x9ECB, 0xC663, 0x9ECC, + 0xC664, 0x9ECD, 0xC665, 0x9ECE, 0xC666, 0x9ECF, 0xC667, 0x9ED0, 0xC668, 0x9ED1, 0xC669, 0x9ED2, 0xC66A, 0x9ED3, 0xC66B, 0x9ED4, + 0xC66C, 0xBFD9, 0xC66D, 0x9ED5, 0xC66E, 0x9ED6, 0xC66F, 0xBFDA, 0xC670, 0x9ED7, 0xC671, 0xBFDB, 0xC672, 0x9ED8, 0xC673, 0x9ED9, + 0xC674, 0x9EDA, 0xC675, 0x9EDB, 0xC676, 0x9EDC, 0xC677, 0x9EDD, 0xC678, 0xBFDC, 0xC679, 0xBFDD, 0xC67A, 0x9EDE, 0xC67B, 0x9EDF, + 0xC67C, 0xBFDE, 0xC67D, 0x9EE0, 0xC67E, 0x9EE1, 0xC67F, 0x9EE2, 0xC680, 0xBFDF, 0xC681, 0x9EE3, 0xC682, 0x9EE4, 0xC683, 0x9EE5, + 0xC684, 0x9EE6, 0xC685, 0x9EE7, 0xC686, 0x9EE8, 0xC687, 0x9EE9, 0xC688, 0xBFE0, 0xC689, 0xBFE1, 0xC68A, 0x9EEA, 0xC68B, 0xBFE2, + 0xC68C, 0x9EEB, 0xC68D, 0xBFE3, 0xC68E, 0x9EEC, 0xC68F, 0x9EED, 0xC690, 0x9EEE, 0xC691, 0x9EEF, 0xC692, 0x9EF0, 0xC693, 0x9EF1, + 0xC694, 0xBFE4, 0xC695, 0xBFE5, 0xC696, 0x9EF2, 0xC697, 0x9EF3, 0xC698, 0xBFE6, 0xC699, 0x9EF4, 0xC69A, 0x9EF5, 0xC69B, 0x9EF6, + 0xC69C, 0xBFE7, 0xC69D, 0x9EF7, 0xC69E, 0x9EF8, 0xC69F, 0x9EF9, 0xC6A0, 0x9EFA, 0xC6A1, 0x9EFB, 0xC6A2, 0x9EFC, 0xC6A3, 0x9EFD, + 0xC6A4, 0xBFE8, 0xC6A5, 0xBFE9, 0xC6A6, 0x9EFE, 0xC6A7, 0xBFEA, 0xC6A8, 0x9F41, 0xC6A9, 0xBFEB, 0xC6AA, 0x9F42, 0xC6AB, 0x9F43, + 0xC6AC, 0x9F44, 0xC6AD, 0x9F45, 0xC6AE, 0x9F46, 0xC6AF, 0x9F47, 0xC6B0, 0xBFEC, 0xC6B1, 0xBFED, 0xC6B2, 0x9F48, 0xC6B3, 0x9F49, + 0xC6B4, 0xBFEE, 0xC6B5, 0x9F4A, 0xC6B6, 0x9F4B, 0xC6B7, 0x9F4C, 0xC6B8, 0xBFEF, 0xC6B9, 0xBFF0, 0xC6BA, 0xBFF1, 0xC6BB, 0x9F4D, + 0xC6BC, 0x9F4E, 0xC6BD, 0x9F4F, 0xC6BE, 0x9F50, 0xC6BF, 0x9F51, 0xC6C0, 0xBFF2, 0xC6C1, 0xBFF3, 0xC6C2, 0x9F52, 0xC6C3, 0xBFF4, + 0xC6C4, 0x9F53, 0xC6C5, 0xBFF5, 0xC6C6, 0x9F54, 0xC6C7, 0x9F55, 0xC6C8, 0x9F56, 0xC6C9, 0x9F57, 0xC6CA, 0x9F58, 0xC6CB, 0x9F59, + 0xC6CC, 0xBFF6, 0xC6CD, 0xBFF7, 0xC6CE, 0x9F5A, 0xC6CF, 0x9F61, 0xC6D0, 0xBFF8, 0xC6D1, 0x9F62, 0xC6D2, 0x9F63, 0xC6D3, 0x9F64, + 0xC6D4, 0xBFF9, 0xC6D5, 0x9F65, 0xC6D6, 0x9F66, 0xC6D7, 0x9F67, 0xC6D8, 0x9F68, 0xC6D9, 0x9F69, 0xC6DA, 0x9F6A, 0xC6DB, 0x9F6B, + 0xC6DC, 0xBFFA, 0xC6DD, 0xBFFB, 0xC6DE, 0x9F6C, 0xC6DF, 0x9F6D, 0xC6E0, 0xBFFC, 0xC6E1, 0xBFFD, 0xC6E2, 0x9F6E, 0xC6E3, 0x9F6F, + 0xC6E4, 0x9F70, 0xC6E5, 0x9F71, 0xC6E6, 0x9F72, 0xC6E7, 0x9F73, 0xC6E8, 0xBFFE, 0xC6E9, 0xC0A1, 0xC6EA, 0x9F74, 0xC6EB, 0x9F75, + 0xC6EC, 0xC0A2, 0xC6ED, 0x9F76, 0xC6EE, 0x9F77, 0xC6EF, 0x9F78, 0xC6F0, 0xC0A3, 0xC6F1, 0x9F79, 0xC6F2, 0x9F7A, 0xC6F3, 0x9F81, + 0xC6F4, 0x9F82, 0xC6F5, 0x9F83, 0xC6F6, 0x9F84, 0xC6F7, 0x9F85, 0xC6F8, 0xC0A4, 0xC6F9, 0xC0A5, 0xC6FA, 0x9F86, 0xC6FB, 0x9F87, + 0xC6FC, 0x9F88, 0xC6FD, 0xC0A6, 0xC6FE, 0x9F89, 0xC6FF, 0x9F8A, 0xC700, 0x9F8B, 0xC701, 0x9F8C, 0xC702, 0x9F8D, 0xC703, 0x9F8E, + 0xC704, 0xC0A7, 0xC705, 0xC0A8, 0xC706, 0x9F8F, 0xC707, 0x9F90, 0xC708, 0xC0A9, 0xC709, 0x9F91, 0xC70A, 0x9F92, 0xC70B, 0x9F93, + 0xC70C, 0xC0AA, 0xC70D, 0x9F94, 0xC70E, 0x9F95, 0xC70F, 0x9F96, 0xC710, 0x9F97, 0xC711, 0x9F98, 0xC712, 0x9F99, 0xC713, 0x9F9A, + 0xC714, 0xC0AB, 0xC715, 0xC0AC, 0xC716, 0x9F9B, 0xC717, 0xC0AD, 0xC718, 0x9F9C, 0xC719, 0xC0AE, 0xC71A, 0x9F9D, 0xC71B, 0x9F9E, + 0xC71C, 0x9F9F, 0xC71D, 0x9FA0, 0xC71E, 0x9FA1, 0xC71F, 0x9FA2, 0xC720, 0xC0AF, 0xC721, 0xC0B0, 0xC722, 0x9FA3, 0xC723, 0x9FA4, + 0xC724, 0xC0B1, 0xC725, 0x9FA5, 0xC726, 0x9FA6, 0xC727, 0x9FA7, 0xC728, 0xC0B2, 0xC729, 0x9FA8, 0xC72A, 0x9FA9, 0xC72B, 0x9FAA, + 0xC72C, 0x9FAB, 0xC72D, 0x9FAC, 0xC72E, 0x9FAD, 0xC72F, 0x9FAE, 0xC730, 0xC0B3, 0xC731, 0xC0B4, 0xC732, 0x9FAF, 0xC733, 0xC0B5, + 0xC734, 0x9FB0, 0xC735, 0xC0B6, 0xC736, 0x9FB1, 0xC737, 0xC0B7, 0xC738, 0x9FB2, 0xC739, 0x9FB3, 0xC73A, 0x9FB4, 0xC73B, 0x9FB5, + 0xC73C, 0xC0B8, 0xC73D, 0xC0B9, 0xC73E, 0x9FB6, 0xC73F, 0x9FB7, 0xC740, 0xC0BA, 0xC741, 0x9FB8, 0xC742, 0x9FB9, 0xC743, 0x9FBA, + 0xC744, 0xC0BB, 0xC745, 0x9FBB, 0xC746, 0x9FBC, 0xC747, 0x9FBD, 0xC748, 0x9FBE, 0xC749, 0x9FBF, 0xC74A, 0xC0BC, 0xC74B, 0x9FC0, + 0xC74C, 0xC0BD, 0xC74D, 0xC0BE, 0xC74E, 0x9FC1, 0xC74F, 0xC0BF, 0xC750, 0x9FC2, 0xC751, 0xC0C0, 0xC752, 0xC0C1, 0xC753, 0xC0C2, + 0xC754, 0xC0C3, 0xC755, 0xC0C4, 0xC756, 0xC0C5, 0xC757, 0xC0C6, 0xC758, 0xC0C7, 0xC759, 0x9FC3, 0xC75A, 0x9FC4, 0xC75B, 0x9FC5, + 0xC75C, 0xC0C8, 0xC75D, 0x9FC6, 0xC75E, 0x9FC7, 0xC75F, 0x9FC8, 0xC760, 0xC0C9, 0xC761, 0x9FC9, 0xC762, 0x9FCA, 0xC763, 0x9FCB, + 0xC764, 0x9FCC, 0xC765, 0x9FCD, 0xC766, 0x9FCE, 0xC767, 0x9FCF, 0xC768, 0xC0CA, 0xC769, 0x9FD0, 0xC76A, 0x9FD1, 0xC76B, 0xC0CB, + 0xC76C, 0x9FD2, 0xC76D, 0x9FD3, 0xC76E, 0x9FD4, 0xC76F, 0x9FD5, 0xC770, 0x9FD6, 0xC771, 0x9FD7, 0xC772, 0x9FD8, 0xC773, 0x9FD9, + 0xC774, 0xC0CC, 0xC775, 0xC0CD, 0xC776, 0x9FDA, 0xC777, 0x9FDB, 0xC778, 0xC0CE, 0xC779, 0x9FDC, 0xC77A, 0x9FDD, 0xC77B, 0x9FDE, + 0xC77C, 0xC0CF, 0xC77D, 0xC0D0, 0xC77E, 0xC0D1, 0xC77F, 0x9FDF, 0xC780, 0x9FE0, 0xC781, 0x9FE1, 0xC782, 0x9FE2, 0xC783, 0xC0D2, + 0xC784, 0xC0D3, 0xC785, 0xC0D4, 0xC786, 0x9FE3, 0xC787, 0xC0D5, 0xC788, 0xC0D6, 0xC789, 0xC0D7, 0xC78A, 0xC0D8, 0xC78B, 0x9FE4, + 0xC78C, 0x9FE5, 0xC78D, 0x9FE6, 0xC78E, 0xC0D9, 0xC78F, 0x9FE7, 0xC790, 0xC0DA, 0xC791, 0xC0DB, 0xC792, 0x9FE8, 0xC793, 0x9FE9, + 0xC794, 0xC0DC, 0xC795, 0x9FEA, 0xC796, 0xC0DD, 0xC797, 0xC0DE, 0xC798, 0xC0DF, 0xC799, 0x9FEB, 0xC79A, 0xC0E0, 0xC79B, 0x9FEC, + 0xC79C, 0x9FED, 0xC79D, 0x9FEE, 0xC79E, 0x9FEF, 0xC79F, 0x9FF0, 0xC7A0, 0xC0E1, 0xC7A1, 0xC0E2, 0xC7A2, 0x9FF1, 0xC7A3, 0xC0E3, + 0xC7A4, 0xC0E4, 0xC7A5, 0xC0E5, 0xC7A6, 0xC0E6, 0xC7A7, 0x9FF2, 0xC7A8, 0x9FF3, 0xC7A9, 0x9FF4, 0xC7AA, 0x9FF5, 0xC7AB, 0x9FF6, + 0xC7AC, 0xC0E7, 0xC7AD, 0xC0E8, 0xC7AE, 0x9FF7, 0xC7AF, 0x9FF8, 0xC7B0, 0xC0E9, 0xC7B1, 0x9FF9, 0xC7B2, 0x9FFA, 0xC7B3, 0x9FFB, + 0xC7B4, 0xC0EA, 0xC7B5, 0x9FFC, 0xC7B6, 0x9FFD, 0xC7B7, 0x9FFE, 0xC7B8, 0xA041, 0xC7B9, 0xA042, 0xC7BA, 0xA043, 0xC7BB, 0xA044, + 0xC7BC, 0xC0EB, 0xC7BD, 0xC0EC, 0xC7BE, 0xA045, 0xC7BF, 0xC0ED, 0xC7C0, 0xC0EE, 0xC7C1, 0xC0EF, 0xC7C2, 0xA046, 0xC7C3, 0xA047, + 0xC7C4, 0xA048, 0xC7C5, 0xA049, 0xC7C6, 0xA04A, 0xC7C7, 0xA04B, 0xC7C8, 0xC0F0, 0xC7C9, 0xC0F1, 0xC7CA, 0xA04C, 0xC7CB, 0xA04D, + 0xC7CC, 0xC0F2, 0xC7CD, 0xA04E, 0xC7CE, 0xC0F3, 0xC7CF, 0xA04F, 0xC7D0, 0xC0F4, 0xC7D1, 0xA050, 0xC7D2, 0xA051, 0xC7D3, 0xA052, + 0xC7D4, 0xA053, 0xC7D5, 0xA054, 0xC7D6, 0xA055, 0xC7D7, 0xA056, 0xC7D8, 0xC0F5, 0xC7D9, 0xA057, 0xC7DA, 0xA058, 0xC7DB, 0xA059, + 0xC7DC, 0xA05A, 0xC7DD, 0xC0F6, 0xC7DE, 0xA061, 0xC7DF, 0xA062, 0xC7E0, 0xA063, 0xC7E1, 0xA064, 0xC7E2, 0xA065, 0xC7E3, 0xA066, + 0xC7E4, 0xC0F7, 0xC7E5, 0xA067, 0xC7E6, 0xA068, 0xC7E7, 0xA069, 0xC7E8, 0xC0F8, 0xC7E9, 0xA06A, 0xC7EA, 0xA06B, 0xC7EB, 0xA06C, + 0xC7EC, 0xC0F9, 0xC7ED, 0xA06D, 0xC7EE, 0xA06E, 0xC7EF, 0xA06F, 0xC7F0, 0xA070, 0xC7F1, 0xA071, 0xC7F2, 0xA072, 0xC7F3, 0xA073, + 0xC7F4, 0xA074, 0xC7F5, 0xA075, 0xC7F6, 0xA076, 0xC7F7, 0xA077, 0xC7F8, 0xA078, 0xC7F9, 0xA079, 0xC7FA, 0xA07A, 0xC7FB, 0xA081, + 0xC7FC, 0xA082, 0xC7FD, 0xA083, 0xC7FE, 0xA084, 0xC7FF, 0xA085, 0xC800, 0xC0FA, 0xC801, 0xC0FB, 0xC802, 0xA086, 0xC803, 0xA087, + 0xC804, 0xC0FC, 0xC805, 0xA088, 0xC806, 0xA089, 0xC807, 0xA08A, 0xC808, 0xC0FD, 0xC809, 0xA08B, 0xC80A, 0xC0FE, 0xC80B, 0xA08C, + 0xC80C, 0xA08D, 0xC80D, 0xA08E, 0xC80E, 0xA08F, 0xC80F, 0xA090, 0xC810, 0xC1A1, 0xC811, 0xC1A2, 0xC812, 0xA091, 0xC813, 0xC1A3, + 0xC814, 0xA092, 0xC815, 0xC1A4, 0xC816, 0xC1A5, 0xC817, 0xA093, 0xC818, 0xA094, 0xC819, 0xA095, 0xC81A, 0xA096, 0xC81B, 0xA097, + 0xC81C, 0xC1A6, 0xC81D, 0xC1A7, 0xC81E, 0xA098, 0xC81F, 0xA099, 0xC820, 0xC1A8, 0xC821, 0xA09A, 0xC822, 0xA09B, 0xC823, 0xA09C, + 0xC824, 0xC1A9, 0xC825, 0xA09D, 0xC826, 0xA09E, 0xC827, 0xA09F, 0xC828, 0xA0A0, 0xC829, 0xA0A1, 0xC82A, 0xA0A2, 0xC82B, 0xA0A3, + 0xC82C, 0xC1AA, 0xC82D, 0xC1AB, 0xC82E, 0xA0A4, 0xC82F, 0xC1AC, 0xC830, 0xA0A5, 0xC831, 0xC1AD, 0xC832, 0xA0A6, 0xC833, 0xA0A7, + 0xC834, 0xA0A8, 0xC835, 0xA0A9, 0xC836, 0xA0AA, 0xC837, 0xA0AB, 0xC838, 0xC1AE, 0xC839, 0xA0AC, 0xC83A, 0xA0AD, 0xC83B, 0xA0AE, + 0xC83C, 0xC1AF, 0xC83D, 0xA0AF, 0xC83E, 0xA0B0, 0xC83F, 0xA0B1, 0xC840, 0xC1B0, 0xC841, 0xA0B2, 0xC842, 0xA0B3, 0xC843, 0xA0B4, + 0xC844, 0xA0B5, 0xC845, 0xA0B6, 0xC846, 0xA0B7, 0xC847, 0xA0B8, 0xC848, 0xC1B1, 0xC849, 0xC1B2, 0xC84A, 0xA0B9, 0xC84B, 0xA0BA, + 0xC84C, 0xC1B3, 0xC84D, 0xC1B4, 0xC84E, 0xA0BB, 0xC84F, 0xA0BC, 0xC850, 0xA0BD, 0xC851, 0xA0BE, 0xC852, 0xA0BF, 0xC853, 0xA0C0, + 0xC854, 0xC1B5, 0xC855, 0xA0C1, 0xC856, 0xA0C2, 0xC857, 0xA0C3, 0xC858, 0xA0C4, 0xC859, 0xA0C5, 0xC85A, 0xA0C6, 0xC85B, 0xA0C7, + 0xC85C, 0xA0C8, 0xC85D, 0xA0C9, 0xC85E, 0xA0CA, 0xC85F, 0xA0CB, 0xC860, 0xA0CC, 0xC861, 0xA0CD, 0xC862, 0xA0CE, 0xC863, 0xA0CF, + 0xC864, 0xA0D0, 0xC865, 0xA0D1, 0xC866, 0xA0D2, 0xC867, 0xA0D3, 0xC868, 0xA0D4, 0xC869, 0xA0D5, 0xC86A, 0xA0D6, 0xC86B, 0xA0D7, + 0xC86C, 0xA0D8, 0xC86D, 0xA0D9, 0xC86E, 0xA0DA, 0xC86F, 0xA0DB, 0xC870, 0xC1B6, 0xC871, 0xC1B7, 0xC872, 0xA0DC, 0xC873, 0xA0DD, + 0xC874, 0xC1B8, 0xC875, 0xA0DE, 0xC876, 0xA0DF, 0xC877, 0xA0E0, 0xC878, 0xC1B9, 0xC879, 0xA0E1, 0xC87A, 0xC1BA, 0xC87B, 0xA0E2, + 0xC87C, 0xA0E3, 0xC87D, 0xA0E4, 0xC87E, 0xA0E5, 0xC87F, 0xA0E6, 0xC880, 0xC1BB, 0xC881, 0xC1BC, 0xC882, 0xA0E7, 0xC883, 0xC1BD, + 0xC884, 0xA0E8, 0xC885, 0xC1BE, 0xC886, 0xC1BF, 0xC887, 0xC1C0, 0xC888, 0xA0E9, 0xC889, 0xA0EA, 0xC88A, 0xA0EB, 0xC88B, 0xC1C1, + 0xC88C, 0xC1C2, 0xC88D, 0xC1C3, 0xC88E, 0xA0EC, 0xC88F, 0xA0ED, 0xC890, 0xA0EE, 0xC891, 0xA0EF, 0xC892, 0xA0F0, 0xC893, 0xA0F1, + 0xC894, 0xC1C4, 0xC895, 0xA0F2, 0xC896, 0xA0F3, 0xC897, 0xA0F4, 0xC898, 0xA0F5, 0xC899, 0xA0F6, 0xC89A, 0xA0F7, 0xC89B, 0xA0F8, + 0xC89C, 0xA0F9, 0xC89D, 0xC1C5, 0xC89E, 0xA0FA, 0xC89F, 0xC1C6, 0xC8A0, 0xA0FB, 0xC8A1, 0xC1C7, 0xC8A2, 0xA0FC, 0xC8A3, 0xA0FD, + 0xC8A4, 0xA0FE, 0xC8A5, 0xA141, 0xC8A6, 0xA142, 0xC8A7, 0xA143, 0xC8A8, 0xC1C8, 0xC8A9, 0xA144, 0xC8AA, 0xA145, 0xC8AB, 0xA146, + 0xC8AC, 0xA147, 0xC8AD, 0xA148, 0xC8AE, 0xA149, 0xC8AF, 0xA14A, 0xC8B0, 0xA14B, 0xC8B1, 0xA14C, 0xC8B2, 0xA14D, 0xC8B3, 0xA14E, + 0xC8B4, 0xA14F, 0xC8B5, 0xA150, 0xC8B6, 0xA151, 0xC8B7, 0xA152, 0xC8B8, 0xA153, 0xC8B9, 0xA154, 0xC8BA, 0xA155, 0xC8BB, 0xA156, + 0xC8BC, 0xC1C9, 0xC8BD, 0xC1CA, 0xC8BE, 0xA157, 0xC8BF, 0xA158, 0xC8C0, 0xA159, 0xC8C1, 0xA15A, 0xC8C2, 0xA161, 0xC8C3, 0xA162, + 0xC8C4, 0xC1CB, 0xC8C5, 0xA163, 0xC8C6, 0xA164, 0xC8C7, 0xA165, 0xC8C8, 0xC1CC, 0xC8C9, 0xA166, 0xC8CA, 0xA167, 0xC8CB, 0xA168, + 0xC8CC, 0xC1CD, 0xC8CD, 0xA169, 0xC8CE, 0xA16A, 0xC8CF, 0xA16B, 0xC8D0, 0xA16C, 0xC8D1, 0xA16D, 0xC8D2, 0xA16E, 0xC8D3, 0xA16F, + 0xC8D4, 0xC1CE, 0xC8D5, 0xC1CF, 0xC8D6, 0xA170, 0xC8D7, 0xC1D0, 0xC8D8, 0xA171, 0xC8D9, 0xC1D1, 0xC8DA, 0xA172, 0xC8DB, 0xA173, + 0xC8DC, 0xA174, 0xC8DD, 0xA175, 0xC8DE, 0xA176, 0xC8DF, 0xA177, 0xC8E0, 0xC1D2, 0xC8E1, 0xC1D3, 0xC8E2, 0xA178, 0xC8E3, 0xA179, + 0xC8E4, 0xC1D4, 0xC8E5, 0xA17A, 0xC8E6, 0xA181, 0xC8E7, 0xA182, 0xC8E8, 0xA183, 0xC8E9, 0xA184, 0xC8EA, 0xA185, 0xC8EB, 0xA186, + 0xC8EC, 0xA187, 0xC8ED, 0xA188, 0xC8EE, 0xA189, 0xC8EF, 0xA18A, 0xC8F0, 0xA18B, 0xC8F1, 0xA18C, 0xC8F2, 0xA18D, 0xC8F3, 0xA18E, + 0xC8F4, 0xA18F, 0xC8F5, 0xC1D5, 0xC8F6, 0xA190, 0xC8F7, 0xA191, 0xC8F8, 0xA192, 0xC8F9, 0xA193, 0xC8FA, 0xA194, 0xC8FB, 0xA195, + 0xC8FC, 0xC1D6, 0xC8FD, 0xC1D7, 0xC8FE, 0xA196, 0xC8FF, 0xA197, 0xC900, 0xC1D8, 0xC901, 0xA198, 0xC902, 0xA199, 0xC903, 0xA19A, + 0xC904, 0xC1D9, 0xC905, 0xC1DA, 0xC906, 0xC1DB, 0xC907, 0xA19B, 0xC908, 0xA19C, 0xC909, 0xA19D, 0xC90A, 0xA19E, 0xC90B, 0xA19F, + 0xC90C, 0xC1DC, 0xC90D, 0xC1DD, 0xC90E, 0xA1A0, 0xC90F, 0xC1DE, 0xC910, 0xA241, 0xC911, 0xC1DF, 0xC912, 0xA242, 0xC913, 0xA243, + 0xC914, 0xA244, 0xC915, 0xA245, 0xC916, 0xA246, 0xC917, 0xA247, 0xC918, 0xC1E0, 0xC919, 0xA248, 0xC91A, 0xA249, 0xC91B, 0xA24A, + 0xC91C, 0xA24B, 0xC91D, 0xA24C, 0xC91E, 0xA24D, 0xC91F, 0xA24E, 0xC920, 0xA24F, 0xC921, 0xA250, 0xC922, 0xA251, 0xC923, 0xA252, + 0xC924, 0xA253, 0xC925, 0xA254, 0xC926, 0xA255, 0xC927, 0xA256, 0xC928, 0xA257, 0xC929, 0xA258, 0xC92A, 0xA259, 0xC92B, 0xA25A, + 0xC92C, 0xC1E1, 0xC92D, 0xA261, 0xC92E, 0xA262, 0xC92F, 0xA263, 0xC930, 0xA264, 0xC931, 0xA265, 0xC932, 0xA266, 0xC933, 0xA267, + 0xC934, 0xC1E2, 0xC935, 0xA268, 0xC936, 0xA269, 0xC937, 0xA26A, 0xC938, 0xA26B, 0xC939, 0xA26C, 0xC93A, 0xA26D, 0xC93B, 0xA26E, + 0xC93C, 0xA26F, 0xC93D, 0xA270, 0xC93E, 0xA271, 0xC93F, 0xA272, 0xC940, 0xA273, 0xC941, 0xA274, 0xC942, 0xA275, 0xC943, 0xA276, + 0xC944, 0xA277, 0xC945, 0xA278, 0xC946, 0xA279, 0xC947, 0xA27A, 0xC948, 0xA281, 0xC949, 0xA282, 0xC94A, 0xA283, 0xC94B, 0xA284, + 0xC94C, 0xA285, 0xC94D, 0xA286, 0xC94E, 0xA287, 0xC94F, 0xA288, 0xC950, 0xC1E3, 0xC951, 0xC1E4, 0xC952, 0xA289, 0xC953, 0xA28A, + 0xC954, 0xC1E5, 0xC955, 0xA28B, 0xC956, 0xA28C, 0xC957, 0xA28D, 0xC958, 0xC1E6, 0xC959, 0xA28E, 0xC95A, 0xA28F, 0xC95B, 0xA290, + 0xC95C, 0xA291, 0xC95D, 0xA292, 0xC95E, 0xA293, 0xC95F, 0xA294, 0xC960, 0xC1E7, 0xC961, 0xC1E8, 0xC962, 0xA295, 0xC963, 0xC1E9, + 0xC964, 0xA296, 0xC965, 0xA297, 0xC966, 0xA298, 0xC967, 0xA299, 0xC968, 0xA29A, 0xC969, 0xA29B, 0xC96A, 0xA29C, 0xC96B, 0xA29D, + 0xC96C, 0xC1EA, 0xC96D, 0xA29E, 0xC96E, 0xA29F, 0xC96F, 0xA2A0, 0xC970, 0xC1EB, 0xC971, 0xA341, 0xC972, 0xA342, 0xC973, 0xA343, + 0xC974, 0xC1EC, 0xC975, 0xA344, 0xC976, 0xA345, 0xC977, 0xA346, 0xC978, 0xA347, 0xC979, 0xA348, 0xC97A, 0xA349, 0xC97B, 0xA34A, + 0xC97C, 0xC1ED, 0xC97D, 0xA34B, 0xC97E, 0xA34C, 0xC97F, 0xA34D, 0xC980, 0xA34E, 0xC981, 0xA34F, 0xC982, 0xA350, 0xC983, 0xA351, + 0xC984, 0xA352, 0xC985, 0xA353, 0xC986, 0xA354, 0xC987, 0xA355, 0xC988, 0xC1EE, 0xC989, 0xC1EF, 0xC98A, 0xA356, 0xC98B, 0xA357, + 0xC98C, 0xC1F0, 0xC98D, 0xA358, 0xC98E, 0xA359, 0xC98F, 0xA35A, 0xC990, 0xC1F1, 0xC991, 0xA361, 0xC992, 0xA362, 0xC993, 0xA363, + 0xC994, 0xA364, 0xC995, 0xA365, 0xC996, 0xA366, 0xC997, 0xA367, 0xC998, 0xC1F2, 0xC999, 0xC1F3, 0xC99A, 0xA368, 0xC99B, 0xC1F4, + 0xC99C, 0xA369, 0xC99D, 0xC1F5, 0xC99E, 0xA36A, 0xC99F, 0xA36B, 0xC9A0, 0xA36C, 0xC9A1, 0xA36D, 0xC9A2, 0xA36E, 0xC9A3, 0xA36F, + 0xC9A4, 0xA370, 0xC9A5, 0xA371, 0xC9A6, 0xA372, 0xC9A7, 0xA373, 0xC9A8, 0xA374, 0xC9A9, 0xA375, 0xC9AA, 0xA376, 0xC9AB, 0xA377, + 0xC9AC, 0xA378, 0xC9AD, 0xA379, 0xC9AE, 0xA37A, 0xC9AF, 0xA381, 0xC9B0, 0xA382, 0xC9B1, 0xA383, 0xC9B2, 0xA384, 0xC9B3, 0xA385, + 0xC9B4, 0xA386, 0xC9B5, 0xA387, 0xC9B6, 0xA388, 0xC9B7, 0xA389, 0xC9B8, 0xA38A, 0xC9B9, 0xA38B, 0xC9BA, 0xA38C, 0xC9BB, 0xA38D, + 0xC9BC, 0xA38E, 0xC9BD, 0xA38F, 0xC9BE, 0xA390, 0xC9BF, 0xA391, 0xC9C0, 0xC1F6, 0xC9C1, 0xC1F7, 0xC9C2, 0xA392, 0xC9C3, 0xA393, + 0xC9C4, 0xC1F8, 0xC9C5, 0xA394, 0xC9C6, 0xA395, 0xC9C7, 0xC1F9, 0xC9C8, 0xC1FA, 0xC9C9, 0xA396, 0xC9CA, 0xC1FB, 0xC9CB, 0xA397, + 0xC9CC, 0xA398, 0xC9CD, 0xA399, 0xC9CE, 0xA39A, 0xC9CF, 0xA39B, 0xC9D0, 0xC1FC, 0xC9D1, 0xC1FD, 0xC9D2, 0xA39C, 0xC9D3, 0xC1FE, + 0xC9D4, 0xA39D, 0xC9D5, 0xC2A1, 0xC9D6, 0xC2A2, 0xC9D7, 0xA39E, 0xC9D8, 0xA39F, 0xC9D9, 0xC2A3, 0xC9DA, 0xC2A4, 0xC9DB, 0xA3A0, + 0xC9DC, 0xC2A5, 0xC9DD, 0xC2A6, 0xC9DE, 0xA441, 0xC9DF, 0xA442, 0xC9E0, 0xC2A7, 0xC9E1, 0xA443, 0xC9E2, 0xC2A8, 0xC9E3, 0xA444, + 0xC9E4, 0xC2A9, 0xC9E5, 0xA445, 0xC9E6, 0xA446, 0xC9E7, 0xC2AA, 0xC9E8, 0xA447, 0xC9E9, 0xA448, 0xC9EA, 0xA449, 0xC9EB, 0xA44A, + 0xC9EC, 0xC2AB, 0xC9ED, 0xC2AC, 0xC9EE, 0xA44B, 0xC9EF, 0xC2AD, 0xC9F0, 0xC2AE, 0xC9F1, 0xC2AF, 0xC9F2, 0xA44C, 0xC9F3, 0xA44D, + 0xC9F4, 0xA44E, 0xC9F5, 0xA44F, 0xC9F6, 0xA450, 0xC9F7, 0xA451, 0xC9F8, 0xC2B0, 0xC9F9, 0xC2B1, 0xC9FA, 0xA452, 0xC9FB, 0xA453, + 0xC9FC, 0xC2B2, 0xC9FD, 0xA454, 0xC9FE, 0xA455, 0xC9FF, 0xA456, 0xCA00, 0xC2B3, 0xCA01, 0xA457, 0xCA02, 0xA458, 0xCA03, 0xA459, + 0xCA04, 0xA45A, 0xCA05, 0xA461, 0xCA06, 0xA462, 0xCA07, 0xA463, 0xCA08, 0xC2B4, 0xCA09, 0xC2B5, 0xCA0A, 0xA464, 0xCA0B, 0xC2B6, + 0xCA0C, 0xC2B7, 0xCA0D, 0xC2B8, 0xCA0E, 0xA465, 0xCA0F, 0xA466, 0xCA10, 0xA467, 0xCA11, 0xA468, 0xCA12, 0xA469, 0xCA13, 0xA46A, + 0xCA14, 0xC2B9, 0xCA15, 0xA46B, 0xCA16, 0xA46C, 0xCA17, 0xA46D, 0xCA18, 0xC2BA, 0xCA19, 0xA46E, 0xCA1A, 0xA46F, 0xCA1B, 0xA470, + 0xCA1C, 0xA471, 0xCA1D, 0xA472, 0xCA1E, 0xA473, 0xCA1F, 0xA474, 0xCA20, 0xA475, 0xCA21, 0xA476, 0xCA22, 0xA477, 0xCA23, 0xA478, + 0xCA24, 0xA479, 0xCA25, 0xA47A, 0xCA26, 0xA481, 0xCA27, 0xA482, 0xCA28, 0xA483, 0xCA29, 0xC2BB, 0xCA2A, 0xA484, 0xCA2B, 0xA485, + 0xCA2C, 0xA486, 0xCA2D, 0xA487, 0xCA2E, 0xA488, 0xCA2F, 0xA489, 0xCA30, 0xA48A, 0xCA31, 0xA48B, 0xCA32, 0xA48C, 0xCA33, 0xA48D, + 0xCA34, 0xA48E, 0xCA35, 0xA48F, 0xCA36, 0xA490, 0xCA37, 0xA491, 0xCA38, 0xA492, 0xCA39, 0xA493, 0xCA3A, 0xA494, 0xCA3B, 0xA495, + 0xCA3C, 0xA496, 0xCA3D, 0xA497, 0xCA3E, 0xA498, 0xCA3F, 0xA499, 0xCA40, 0xA49A, 0xCA41, 0xA49B, 0xCA42, 0xA49C, 0xCA43, 0xA49D, + 0xCA44, 0xA49E, 0xCA45, 0xA49F, 0xCA46, 0xA4A0, 0xCA47, 0xA541, 0xCA48, 0xA542, 0xCA49, 0xA543, 0xCA4A, 0xA544, 0xCA4B, 0xA545, + 0xCA4C, 0xC2BC, 0xCA4D, 0xC2BD, 0xCA4E, 0xA546, 0xCA4F, 0xA547, 0xCA50, 0xC2BE, 0xCA51, 0xA548, 0xCA52, 0xA549, 0xCA53, 0xA54A, + 0xCA54, 0xC2BF, 0xCA55, 0xA54B, 0xCA56, 0xA54C, 0xCA57, 0xA54D, 0xCA58, 0xA54E, 0xCA59, 0xA54F, 0xCA5A, 0xA550, 0xCA5B, 0xA551, + 0xCA5C, 0xC2C0, 0xCA5D, 0xC2C1, 0xCA5E, 0xA552, 0xCA5F, 0xC2C2, 0xCA60, 0xC2C3, 0xCA61, 0xC2C4, 0xCA62, 0xA553, 0xCA63, 0xA554, + 0xCA64, 0xA555, 0xCA65, 0xA556, 0xCA66, 0xA557, 0xCA67, 0xA558, 0xCA68, 0xC2C5, 0xCA69, 0xA559, 0xCA6A, 0xA55A, 0xCA6B, 0xA561, + 0xCA6C, 0xA562, 0xCA6D, 0xA563, 0xCA6E, 0xA564, 0xCA6F, 0xA565, 0xCA70, 0xA566, 0xCA71, 0xA567, 0xCA72, 0xA568, 0xCA73, 0xA569, + 0xCA74, 0xA56A, 0xCA75, 0xA56B, 0xCA76, 0xA56C, 0xCA77, 0xA56D, 0xCA78, 0xA56E, 0xCA79, 0xA56F, 0xCA7A, 0xA570, 0xCA7B, 0xA571, + 0xCA7C, 0xA572, 0xCA7D, 0xC2C6, 0xCA7E, 0xA573, 0xCA7F, 0xA574, 0xCA80, 0xA575, 0xCA81, 0xA576, 0xCA82, 0xA577, 0xCA83, 0xA578, + 0xCA84, 0xC2C7, 0xCA85, 0xA579, 0xCA86, 0xA57A, 0xCA87, 0xA581, 0xCA88, 0xA582, 0xCA89, 0xA583, 0xCA8A, 0xA584, 0xCA8B, 0xA585, + 0xCA8C, 0xA586, 0xCA8D, 0xA587, 0xCA8E, 0xA588, 0xCA8F, 0xA589, 0xCA90, 0xA58A, 0xCA91, 0xA58B, 0xCA92, 0xA58C, 0xCA93, 0xA58D, + 0xCA94, 0xA58E, 0xCA95, 0xA58F, 0xCA96, 0xA590, 0xCA97, 0xA591, 0xCA98, 0xC2C8, 0xCA99, 0xA592, 0xCA9A, 0xA593, 0xCA9B, 0xA594, + 0xCA9C, 0xA595, 0xCA9D, 0xA596, 0xCA9E, 0xA597, 0xCA9F, 0xA598, 0xCAA0, 0xA599, 0xCAA1, 0xA59A, 0xCAA2, 0xA59B, 0xCAA3, 0xA59C, + 0xCAA4, 0xA59D, 0xCAA5, 0xA59E, 0xCAA6, 0xA59F, 0xCAA7, 0xA5A0, 0xCAA8, 0xA641, 0xCAA9, 0xA642, 0xCAAA, 0xA643, 0xCAAB, 0xA644, + 0xCAAC, 0xA645, 0xCAAD, 0xA646, 0xCAAE, 0xA647, 0xCAAF, 0xA648, 0xCAB0, 0xA649, 0xCAB1, 0xA64A, 0xCAB2, 0xA64B, 0xCAB3, 0xA64C, + 0xCAB4, 0xA64D, 0xCAB5, 0xA64E, 0xCAB6, 0xA64F, 0xCAB7, 0xA650, 0xCAB8, 0xA651, 0xCAB9, 0xA652, 0xCABA, 0xA653, 0xCABB, 0xA654, + 0xCABC, 0xC2C9, 0xCABD, 0xC2CA, 0xCABE, 0xA655, 0xCABF, 0xA656, 0xCAC0, 0xC2CB, 0xCAC1, 0xA657, 0xCAC2, 0xA658, 0xCAC3, 0xA659, + 0xCAC4, 0xC2CC, 0xCAC5, 0xA65A, 0xCAC6, 0xA661, 0xCAC7, 0xA662, 0xCAC8, 0xA663, 0xCAC9, 0xA664, 0xCACA, 0xA665, 0xCACB, 0xA666, + 0xCACC, 0xC2CD, 0xCACD, 0xC2CE, 0xCACE, 0xA667, 0xCACF, 0xC2CF, 0xCAD0, 0xA668, 0xCAD1, 0xC2D0, 0xCAD2, 0xA669, 0xCAD3, 0xC2D1, + 0xCAD4, 0xA66A, 0xCAD5, 0xA66B, 0xCAD6, 0xA66C, 0xCAD7, 0xA66D, 0xCAD8, 0xC2D2, 0xCAD9, 0xC2D3, 0xCADA, 0xA66E, 0xCADB, 0xA66F, + 0xCADC, 0xA670, 0xCADD, 0xA671, 0xCADE, 0xA672, 0xCADF, 0xA673, 0xCAE0, 0xC2D4, 0xCAE1, 0xA674, 0xCAE2, 0xA675, 0xCAE3, 0xA676, + 0xCAE4, 0xA677, 0xCAE5, 0xA678, 0xCAE6, 0xA679, 0xCAE7, 0xA67A, 0xCAE8, 0xA681, 0xCAE9, 0xA682, 0xCAEA, 0xA683, 0xCAEB, 0xA684, + 0xCAEC, 0xC2D5, 0xCAED, 0xA685, 0xCAEE, 0xA686, 0xCAEF, 0xA687, 0xCAF0, 0xA688, 0xCAF1, 0xA689, 0xCAF2, 0xA68A, 0xCAF3, 0xA68B, + 0xCAF4, 0xC2D6, 0xCAF5, 0xA68C, 0xCAF6, 0xA68D, 0xCAF7, 0xA68E, 0xCAF8, 0xA68F, 0xCAF9, 0xA690, 0xCAFA, 0xA691, 0xCAFB, 0xA692, + 0xCAFC, 0xA693, 0xCAFD, 0xA694, 0xCAFE, 0xA695, 0xCAFF, 0xA696, 0xCB00, 0xA697, 0xCB01, 0xA698, 0xCB02, 0xA699, 0xCB03, 0xA69A, + 0xCB04, 0xA69B, 0xCB05, 0xA69C, 0xCB06, 0xA69D, 0xCB07, 0xA69E, 0xCB08, 0xC2D7, 0xCB09, 0xA69F, 0xCB0A, 0xA6A0, 0xCB0B, 0xA741, + 0xCB0C, 0xA742, 0xCB0D, 0xA743, 0xCB0E, 0xA744, 0xCB0F, 0xA745, 0xCB10, 0xC2D8, 0xCB11, 0xA746, 0xCB12, 0xA747, 0xCB13, 0xA748, + 0xCB14, 0xC2D9, 0xCB15, 0xA749, 0xCB16, 0xA74A, 0xCB17, 0xA74B, 0xCB18, 0xC2DA, 0xCB19, 0xA74C, 0xCB1A, 0xA74D, 0xCB1B, 0xA74E, + 0xCB1C, 0xA74F, 0xCB1D, 0xA750, 0xCB1E, 0xA751, 0xCB1F, 0xA752, 0xCB20, 0xC2DB, 0xCB21, 0xC2DC, 0xCB22, 0xA753, 0xCB23, 0xA754, + 0xCB24, 0xA755, 0xCB25, 0xA756, 0xCB26, 0xA757, 0xCB27, 0xA758, 0xCB28, 0xA759, 0xCB29, 0xA75A, 0xCB2A, 0xA761, 0xCB2B, 0xA762, + 0xCB2C, 0xA763, 0xCB2D, 0xA764, 0xCB2E, 0xA765, 0xCB2F, 0xA766, 0xCB30, 0xA767, 0xCB31, 0xA768, 0xCB32, 0xA769, 0xCB33, 0xA76A, + 0xCB34, 0xA76B, 0xCB35, 0xA76C, 0xCB36, 0xA76D, 0xCB37, 0xA76E, 0xCB38, 0xA76F, 0xCB39, 0xA770, 0xCB3A, 0xA771, 0xCB3B, 0xA772, + 0xCB3C, 0xA773, 0xCB3D, 0xA774, 0xCB3E, 0xA775, 0xCB3F, 0xA776, 0xCB40, 0xA777, 0xCB41, 0xC2DD, 0xCB42, 0xA778, 0xCB43, 0xA779, + 0xCB44, 0xA77A, 0xCB45, 0xA781, 0xCB46, 0xA782, 0xCB47, 0xA783, 0xCB48, 0xC2DE, 0xCB49, 0xC2DF, 0xCB4A, 0xA784, 0xCB4B, 0xA785, + 0xCB4C, 0xC2E0, 0xCB4D, 0xA786, 0xCB4E, 0xA787, 0xCB4F, 0xA788, 0xCB50, 0xC2E1, 0xCB51, 0xA789, 0xCB52, 0xA78A, 0xCB53, 0xA78B, + 0xCB54, 0xA78C, 0xCB55, 0xA78D, 0xCB56, 0xA78E, 0xCB57, 0xA78F, 0xCB58, 0xC2E2, 0xCB59, 0xC2E3, 0xCB5A, 0xA790, 0xCB5B, 0xA791, + 0xCB5C, 0xA792, 0xCB5D, 0xC2E4, 0xCB5E, 0xA793, 0xCB5F, 0xA794, 0xCB60, 0xA795, 0xCB61, 0xA796, 0xCB62, 0xA797, 0xCB63, 0xA798, + 0xCB64, 0xC2E5, 0xCB65, 0xA799, 0xCB66, 0xA79A, 0xCB67, 0xA79B, 0xCB68, 0xA79C, 0xCB69, 0xA79D, 0xCB6A, 0xA79E, 0xCB6B, 0xA79F, + 0xCB6C, 0xA7A0, 0xCB6D, 0xA841, 0xCB6E, 0xA842, 0xCB6F, 0xA843, 0xCB70, 0xA844, 0xCB71, 0xA845, 0xCB72, 0xA846, 0xCB73, 0xA847, + 0xCB74, 0xA848, 0xCB75, 0xA849, 0xCB76, 0xA84A, 0xCB77, 0xA84B, 0xCB78, 0xC2E6, 0xCB79, 0xC2E7, 0xCB7A, 0xA84C, 0xCB7B, 0xA84D, + 0xCB7C, 0xA84E, 0xCB7D, 0xA84F, 0xCB7E, 0xA850, 0xCB7F, 0xA851, 0xCB80, 0xA852, 0xCB81, 0xA853, 0xCB82, 0xA854, 0xCB83, 0xA855, + 0xCB84, 0xA856, 0xCB85, 0xA857, 0xCB86, 0xA858, 0xCB87, 0xA859, 0xCB88, 0xA85A, 0xCB89, 0xA861, 0xCB8A, 0xA862, 0xCB8B, 0xA863, + 0xCB8C, 0xA864, 0xCB8D, 0xA865, 0xCB8E, 0xA866, 0xCB8F, 0xA867, 0xCB90, 0xA868, 0xCB91, 0xA869, 0xCB92, 0xA86A, 0xCB93, 0xA86B, + 0xCB94, 0xA86C, 0xCB95, 0xA86D, 0xCB96, 0xA86E, 0xCB97, 0xA86F, 0xCB98, 0xA870, 0xCB99, 0xA871, 0xCB9A, 0xA872, 0xCB9B, 0xA873, + 0xCB9C, 0xC2E8, 0xCB9D, 0xA874, 0xCB9E, 0xA875, 0xCB9F, 0xA876, 0xCBA0, 0xA877, 0xCBA1, 0xA878, 0xCBA2, 0xA879, 0xCBA3, 0xA87A, + 0xCBA4, 0xA881, 0xCBA5, 0xA882, 0xCBA6, 0xA883, 0xCBA7, 0xA884, 0xCBA8, 0xA885, 0xCBA9, 0xA886, 0xCBAA, 0xA887, 0xCBAB, 0xA888, + 0xCBAC, 0xA889, 0xCBAD, 0xA88A, 0xCBAE, 0xA88B, 0xCBAF, 0xA88C, 0xCBB0, 0xA88D, 0xCBB1, 0xA88E, 0xCBB2, 0xA88F, 0xCBB3, 0xA890, + 0xCBB4, 0xA891, 0xCBB5, 0xA892, 0xCBB6, 0xA893, 0xCBB7, 0xA894, 0xCBB8, 0xC2E9, 0xCBB9, 0xA895, 0xCBBA, 0xA896, 0xCBBB, 0xA897, + 0xCBBC, 0xA898, 0xCBBD, 0xA899, 0xCBBE, 0xA89A, 0xCBBF, 0xA89B, 0xCBC0, 0xA89C, 0xCBC1, 0xA89D, 0xCBC2, 0xA89E, 0xCBC3, 0xA89F, + 0xCBC4, 0xA8A0, 0xCBC5, 0xA941, 0xCBC6, 0xA942, 0xCBC7, 0xA943, 0xCBC8, 0xA944, 0xCBC9, 0xA945, 0xCBCA, 0xA946, 0xCBCB, 0xA947, + 0xCBCC, 0xA948, 0xCBCD, 0xA949, 0xCBCE, 0xA94A, 0xCBCF, 0xA94B, 0xCBD0, 0xA94C, 0xCBD1, 0xA94D, 0xCBD2, 0xA94E, 0xCBD3, 0xA94F, + 0xCBD4, 0xC2EA, 0xCBD5, 0xA950, 0xCBD6, 0xA951, 0xCBD7, 0xA952, 0xCBD8, 0xA953, 0xCBD9, 0xA954, 0xCBDA, 0xA955, 0xCBDB, 0xA956, + 0xCBDC, 0xA957, 0xCBDD, 0xA958, 0xCBDE, 0xA959, 0xCBDF, 0xA95A, 0xCBE0, 0xA961, 0xCBE1, 0xA962, 0xCBE2, 0xA963, 0xCBE3, 0xA964, + 0xCBE4, 0xC2EB, 0xCBE5, 0xA965, 0xCBE6, 0xA966, 0xCBE7, 0xC2EC, 0xCBE8, 0xA967, 0xCBE9, 0xC2ED, 0xCBEA, 0xA968, 0xCBEB, 0xA969, + 0xCBEC, 0xA96A, 0xCBED, 0xA96B, 0xCBEE, 0xA96C, 0xCBEF, 0xA96D, 0xCBF0, 0xA96E, 0xCBF1, 0xA96F, 0xCBF2, 0xA970, 0xCBF3, 0xA971, + 0xCBF4, 0xA972, 0xCBF5, 0xA973, 0xCBF6, 0xA974, 0xCBF7, 0xA975, 0xCBF8, 0xA976, 0xCBF9, 0xA977, 0xCBFA, 0xA978, 0xCBFB, 0xA979, + 0xCBFC, 0xA97A, 0xCBFD, 0xA981, 0xCBFE, 0xA982, 0xCBFF, 0xA983, 0xCC00, 0xA984, 0xCC01, 0xA985, 0xCC02, 0xA986, 0xCC03, 0xA987, + 0xCC04, 0xA988, 0xCC05, 0xA989, 0xCC06, 0xA98A, 0xCC07, 0xA98B, 0xCC08, 0xA98C, 0xCC09, 0xA98D, 0xCC0A, 0xA98E, 0xCC0B, 0xA98F, + 0xCC0C, 0xC2EE, 0xCC0D, 0xC2EF, 0xCC0E, 0xA990, 0xCC0F, 0xA991, 0xCC10, 0xC2F0, 0xCC11, 0xA992, 0xCC12, 0xA993, 0xCC13, 0xA994, + 0xCC14, 0xC2F1, 0xCC15, 0xA995, 0xCC16, 0xA996, 0xCC17, 0xA997, 0xCC18, 0xA998, 0xCC19, 0xA999, 0xCC1A, 0xA99A, 0xCC1B, 0xA99B, + 0xCC1C, 0xC2F2, 0xCC1D, 0xC2F3, 0xCC1E, 0xA99C, 0xCC1F, 0xA99D, 0xCC20, 0xA99E, 0xCC21, 0xC2F4, 0xCC22, 0xC2F5, 0xCC23, 0xA99F, + 0xCC24, 0xA9A0, 0xCC25, 0xAA41, 0xCC26, 0xAA42, 0xCC27, 0xC2F6, 0xCC28, 0xC2F7, 0xCC29, 0xC2F8, 0xCC2A, 0xAA43, 0xCC2B, 0xAA44, + 0xCC2C, 0xC2F9, 0xCC2D, 0xAA45, 0xCC2E, 0xC2FA, 0xCC2F, 0xAA46, 0xCC30, 0xC2FB, 0xCC31, 0xAA47, 0xCC32, 0xAA48, 0xCC33, 0xAA49, + 0xCC34, 0xAA4A, 0xCC35, 0xAA4B, 0xCC36, 0xAA4C, 0xCC37, 0xAA4D, 0xCC38, 0xC2FC, 0xCC39, 0xC2FD, 0xCC3A, 0xAA4E, 0xCC3B, 0xC2FE, + 0xCC3C, 0xC3A1, 0xCC3D, 0xC3A2, 0xCC3E, 0xC3A3, 0xCC3F, 0xAA4F, 0xCC40, 0xAA50, 0xCC41, 0xAA51, 0xCC42, 0xAA52, 0xCC43, 0xAA53, + 0xCC44, 0xC3A4, 0xCC45, 0xC3A5, 0xCC46, 0xAA54, 0xCC47, 0xAA55, 0xCC48, 0xC3A6, 0xCC49, 0xAA56, 0xCC4A, 0xAA57, 0xCC4B, 0xAA58, + 0xCC4C, 0xC3A7, 0xCC4D, 0xAA59, 0xCC4E, 0xAA5A, 0xCC4F, 0xAA61, 0xCC50, 0xAA62, 0xCC51, 0xAA63, 0xCC52, 0xAA64, 0xCC53, 0xAA65, + 0xCC54, 0xC3A8, 0xCC55, 0xC3A9, 0xCC56, 0xAA66, 0xCC57, 0xC3AA, 0xCC58, 0xC3AB, 0xCC59, 0xC3AC, 0xCC5A, 0xAA67, 0xCC5B, 0xAA68, + 0xCC5C, 0xAA69, 0xCC5D, 0xAA6A, 0xCC5E, 0xAA6B, 0xCC5F, 0xAA6C, 0xCC60, 0xC3AD, 0xCC61, 0xAA6D, 0xCC62, 0xAA6E, 0xCC63, 0xAA6F, + 0xCC64, 0xC3AE, 0xCC65, 0xAA70, 0xCC66, 0xC3AF, 0xCC67, 0xAA71, 0xCC68, 0xC3B0, 0xCC69, 0xAA72, 0xCC6A, 0xAA73, 0xCC6B, 0xAA74, + 0xCC6C, 0xAA75, 0xCC6D, 0xAA76, 0xCC6E, 0xAA77, 0xCC6F, 0xAA78, 0xCC70, 0xC3B1, 0xCC71, 0xAA79, 0xCC72, 0xAA7A, 0xCC73, 0xAA81, + 0xCC74, 0xAA82, 0xCC75, 0xC3B2, 0xCC76, 0xAA83, 0xCC77, 0xAA84, 0xCC78, 0xAA85, 0xCC79, 0xAA86, 0xCC7A, 0xAA87, 0xCC7B, 0xAA88, + 0xCC7C, 0xAA89, 0xCC7D, 0xAA8A, 0xCC7E, 0xAA8B, 0xCC7F, 0xAA8C, 0xCC80, 0xAA8D, 0xCC81, 0xAA8E, 0xCC82, 0xAA8F, 0xCC83, 0xAA90, + 0xCC84, 0xAA91, 0xCC85, 0xAA92, 0xCC86, 0xAA93, 0xCC87, 0xAA94, 0xCC88, 0xAA95, 0xCC89, 0xAA96, 0xCC8A, 0xAA97, 0xCC8B, 0xAA98, + 0xCC8C, 0xAA99, 0xCC8D, 0xAA9A, 0xCC8E, 0xAA9B, 0xCC8F, 0xAA9C, 0xCC90, 0xAA9D, 0xCC91, 0xAA9E, 0xCC92, 0xAA9F, 0xCC93, 0xAAA0, + 0xCC94, 0xAB41, 0xCC95, 0xAB42, 0xCC96, 0xAB43, 0xCC97, 0xAB44, 0xCC98, 0xC3B3, 0xCC99, 0xC3B4, 0xCC9A, 0xAB45, 0xCC9B, 0xAB46, + 0xCC9C, 0xC3B5, 0xCC9D, 0xAB47, 0xCC9E, 0xAB48, 0xCC9F, 0xAB49, 0xCCA0, 0xC3B6, 0xCCA1, 0xAB4A, 0xCCA2, 0xAB4B, 0xCCA3, 0xAB4C, + 0xCCA4, 0xAB4D, 0xCCA5, 0xAB4E, 0xCCA6, 0xAB4F, 0xCCA7, 0xAB50, 0xCCA8, 0xC3B7, 0xCCA9, 0xC3B8, 0xCCAA, 0xAB51, 0xCCAB, 0xC3B9, + 0xCCAC, 0xC3BA, 0xCCAD, 0xC3BB, 0xCCAE, 0xAB52, 0xCCAF, 0xAB53, 0xCCB0, 0xAB54, 0xCCB1, 0xAB55, 0xCCB2, 0xAB56, 0xCCB3, 0xAB57, + 0xCCB4, 0xC3BC, 0xCCB5, 0xC3BD, 0xCCB6, 0xAB58, 0xCCB7, 0xAB59, 0xCCB8, 0xC3BE, 0xCCB9, 0xAB5A, 0xCCBA, 0xAB61, 0xCCBB, 0xAB62, + 0xCCBC, 0xC3BF, 0xCCBD, 0xAB63, 0xCCBE, 0xAB64, 0xCCBF, 0xAB65, 0xCCC0, 0xAB66, 0xCCC1, 0xAB67, 0xCCC2, 0xAB68, 0xCCC3, 0xAB69, + 0xCCC4, 0xC3C0, 0xCCC5, 0xC3C1, 0xCCC6, 0xAB6A, 0xCCC7, 0xC3C2, 0xCCC8, 0xAB6B, 0xCCC9, 0xC3C3, 0xCCCA, 0xAB6C, 0xCCCB, 0xAB6D, + 0xCCCC, 0xAB6E, 0xCCCD, 0xAB6F, 0xCCCE, 0xAB70, 0xCCCF, 0xAB71, 0xCCD0, 0xC3C4, 0xCCD1, 0xAB72, 0xCCD2, 0xAB73, 0xCCD3, 0xAB74, + 0xCCD4, 0xC3C5, 0xCCD5, 0xAB75, 0xCCD6, 0xAB76, 0xCCD7, 0xAB77, 0xCCD8, 0xAB78, 0xCCD9, 0xAB79, 0xCCDA, 0xAB7A, 0xCCDB, 0xAB81, + 0xCCDC, 0xAB82, 0xCCDD, 0xAB83, 0xCCDE, 0xAB84, 0xCCDF, 0xAB85, 0xCCE0, 0xAB86, 0xCCE1, 0xAB87, 0xCCE2, 0xAB88, 0xCCE3, 0xAB89, + 0xCCE4, 0xC3C6, 0xCCE5, 0xAB8A, 0xCCE6, 0xAB8B, 0xCCE7, 0xAB8C, 0xCCE8, 0xAB8D, 0xCCE9, 0xAB8E, 0xCCEA, 0xAB8F, 0xCCEB, 0xAB90, + 0xCCEC, 0xC3C7, 0xCCED, 0xAB91, 0xCCEE, 0xAB92, 0xCCEF, 0xAB93, 0xCCF0, 0xC3C8, 0xCCF1, 0xAB94, 0xCCF2, 0xAB95, 0xCCF3, 0xAB96, + 0xCCF4, 0xAB97, 0xCCF5, 0xAB98, 0xCCF6, 0xAB99, 0xCCF7, 0xAB9A, 0xCCF8, 0xAB9B, 0xCCF9, 0xAB9C, 0xCCFA, 0xAB9D, 0xCCFB, 0xAB9E, + 0xCCFC, 0xAB9F, 0xCCFD, 0xABA0, 0xCCFE, 0xAC41, 0xCCFF, 0xAC42, 0xCD00, 0xAC43, 0xCD01, 0xC3C9, 0xCD02, 0xAC44, 0xCD03, 0xAC45, + 0xCD04, 0xAC46, 0xCD05, 0xAC47, 0xCD06, 0xAC48, 0xCD07, 0xAC49, 0xCD08, 0xC3CA, 0xCD09, 0xC3CB, 0xCD0A, 0xAC4A, 0xCD0B, 0xAC4B, + 0xCD0C, 0xC3CC, 0xCD0D, 0xAC4C, 0xCD0E, 0xAC4D, 0xCD0F, 0xAC4E, 0xCD10, 0xC3CD, 0xCD11, 0xAC4F, 0xCD12, 0xAC50, 0xCD13, 0xAC51, + 0xCD14, 0xAC52, 0xCD15, 0xAC53, 0xCD16, 0xAC54, 0xCD17, 0xAC55, 0xCD18, 0xC3CE, 0xCD19, 0xC3CF, 0xCD1A, 0xAC56, 0xCD1B, 0xC3D0, + 0xCD1C, 0xAC57, 0xCD1D, 0xC3D1, 0xCD1E, 0xAC58, 0xCD1F, 0xAC59, 0xCD20, 0xAC5A, 0xCD21, 0xAC61, 0xCD22, 0xAC62, 0xCD23, 0xAC63, + 0xCD24, 0xC3D2, 0xCD25, 0xAC64, 0xCD26, 0xAC65, 0xCD27, 0xAC66, 0xCD28, 0xC3D3, 0xCD29, 0xAC67, 0xCD2A, 0xAC68, 0xCD2B, 0xAC69, + 0xCD2C, 0xC3D4, 0xCD2D, 0xAC6A, 0xCD2E, 0xAC6B, 0xCD2F, 0xAC6C, 0xCD30, 0xAC6D, 0xCD31, 0xAC6E, 0xCD32, 0xAC6F, 0xCD33, 0xAC70, + 0xCD34, 0xAC71, 0xCD35, 0xAC72, 0xCD36, 0xAC73, 0xCD37, 0xAC74, 0xCD38, 0xAC75, 0xCD39, 0xC3D5, 0xCD3A, 0xAC76, 0xCD3B, 0xAC77, + 0xCD3C, 0xAC78, 0xCD3D, 0xAC79, 0xCD3E, 0xAC7A, 0xCD3F, 0xAC81, 0xCD40, 0xAC82, 0xCD41, 0xAC83, 0xCD42, 0xAC84, 0xCD43, 0xAC85, + 0xCD44, 0xAC86, 0xCD45, 0xAC87, 0xCD46, 0xAC88, 0xCD47, 0xAC89, 0xCD48, 0xAC8A, 0xCD49, 0xAC8B, 0xCD4A, 0xAC8C, 0xCD4B, 0xAC8D, + 0xCD4C, 0xAC8E, 0xCD4D, 0xAC8F, 0xCD4E, 0xAC90, 0xCD4F, 0xAC91, 0xCD50, 0xAC92, 0xCD51, 0xAC93, 0xCD52, 0xAC94, 0xCD53, 0xAC95, + 0xCD54, 0xAC96, 0xCD55, 0xAC97, 0xCD56, 0xAC98, 0xCD57, 0xAC99, 0xCD58, 0xAC9A, 0xCD59, 0xAC9B, 0xCD5A, 0xAC9C, 0xCD5B, 0xAC9D, + 0xCD5C, 0xC3D6, 0xCD5D, 0xAC9E, 0xCD5E, 0xAC9F, 0xCD5F, 0xACA0, 0xCD60, 0xC3D7, 0xCD61, 0xAD41, 0xCD62, 0xAD42, 0xCD63, 0xAD43, + 0xCD64, 0xC3D8, 0xCD65, 0xAD44, 0xCD66, 0xAD45, 0xCD67, 0xAD46, 0xCD68, 0xAD47, 0xCD69, 0xAD48, 0xCD6A, 0xAD49, 0xCD6B, 0xAD4A, + 0xCD6C, 0xC3D9, 0xCD6D, 0xC3DA, 0xCD6E, 0xAD4B, 0xCD6F, 0xC3DB, 0xCD70, 0xAD4C, 0xCD71, 0xC3DC, 0xCD72, 0xAD4D, 0xCD73, 0xAD4E, + 0xCD74, 0xAD4F, 0xCD75, 0xAD50, 0xCD76, 0xAD51, 0xCD77, 0xAD52, 0xCD78, 0xC3DD, 0xCD79, 0xAD53, 0xCD7A, 0xAD54, 0xCD7B, 0xAD55, + 0xCD7C, 0xAD56, 0xCD7D, 0xAD57, 0xCD7E, 0xAD58, 0xCD7F, 0xAD59, 0xCD80, 0xAD5A, 0xCD81, 0xAD61, 0xCD82, 0xAD62, 0xCD83, 0xAD63, + 0xCD84, 0xAD64, 0xCD85, 0xAD65, 0xCD86, 0xAD66, 0xCD87, 0xAD67, 0xCD88, 0xC3DE, 0xCD89, 0xAD68, 0xCD8A, 0xAD69, 0xCD8B, 0xAD6A, + 0xCD8C, 0xAD6B, 0xCD8D, 0xAD6C, 0xCD8E, 0xAD6D, 0xCD8F, 0xAD6E, 0xCD90, 0xAD6F, 0xCD91, 0xAD70, 0xCD92, 0xAD71, 0xCD93, 0xAD72, + 0xCD94, 0xC3DF, 0xCD95, 0xC3E0, 0xCD96, 0xAD73, 0xCD97, 0xAD74, 0xCD98, 0xC3E1, 0xCD99, 0xAD75, 0xCD9A, 0xAD76, 0xCD9B, 0xAD77, + 0xCD9C, 0xC3E2, 0xCD9D, 0xAD78, 0xCD9E, 0xAD79, 0xCD9F, 0xAD7A, 0xCDA0, 0xAD81, 0xCDA1, 0xAD82, 0xCDA2, 0xAD83, 0xCDA3, 0xAD84, + 0xCDA4, 0xC3E3, 0xCDA5, 0xC3E4, 0xCDA6, 0xAD85, 0xCDA7, 0xC3E5, 0xCDA8, 0xAD86, 0xCDA9, 0xC3E6, 0xCDAA, 0xAD87, 0xCDAB, 0xAD88, + 0xCDAC, 0xAD89, 0xCDAD, 0xAD8A, 0xCDAE, 0xAD8B, 0xCDAF, 0xAD8C, 0xCDB0, 0xC3E7, 0xCDB1, 0xAD8D, 0xCDB2, 0xAD8E, 0xCDB3, 0xAD8F, + 0xCDB4, 0xAD90, 0xCDB5, 0xAD91, 0xCDB6, 0xAD92, 0xCDB7, 0xAD93, 0xCDB8, 0xAD94, 0xCDB9, 0xAD95, 0xCDBA, 0xAD96, 0xCDBB, 0xAD97, + 0xCDBC, 0xAD98, 0xCDBD, 0xAD99, 0xCDBE, 0xAD9A, 0xCDBF, 0xAD9B, 0xCDC0, 0xAD9C, 0xCDC1, 0xAD9D, 0xCDC2, 0xAD9E, 0xCDC3, 0xAD9F, + 0xCDC4, 0xC3E8, 0xCDC5, 0xADA0, 0xCDC6, 0xAE41, 0xCDC7, 0xAE42, 0xCDC8, 0xAE43, 0xCDC9, 0xAE44, 0xCDCA, 0xAE45, 0xCDCB, 0xAE46, + 0xCDCC, 0xC3E9, 0xCDCD, 0xAE47, 0xCDCE, 0xAE48, 0xCDCF, 0xAE49, 0xCDD0, 0xC3EA, 0xCDD1, 0xAE4A, 0xCDD2, 0xAE4B, 0xCDD3, 0xAE4C, + 0xCDD4, 0xAE4D, 0xCDD5, 0xAE4E, 0xCDD6, 0xAE4F, 0xCDD7, 0xAE50, 0xCDD8, 0xAE51, 0xCDD9, 0xAE52, 0xCDDA, 0xAE53, 0xCDDB, 0xAE54, + 0xCDDC, 0xAE55, 0xCDDD, 0xAE56, 0xCDDE, 0xAE57, 0xCDDF, 0xAE58, 0xCDE0, 0xAE59, 0xCDE1, 0xAE5A, 0xCDE2, 0xAE61, 0xCDE3, 0xAE62, + 0xCDE4, 0xAE63, 0xCDE5, 0xAE64, 0xCDE6, 0xAE65, 0xCDE7, 0xAE66, 0xCDE8, 0xC3EB, 0xCDE9, 0xAE67, 0xCDEA, 0xAE68, 0xCDEB, 0xAE69, + 0xCDEC, 0xC3EC, 0xCDED, 0xAE6A, 0xCDEE, 0xAE6B, 0xCDEF, 0xAE6C, 0xCDF0, 0xC3ED, 0xCDF1, 0xAE6D, 0xCDF2, 0xAE6E, 0xCDF3, 0xAE6F, + 0xCDF4, 0xAE70, 0xCDF5, 0xAE71, 0xCDF6, 0xAE72, 0xCDF7, 0xAE73, 0xCDF8, 0xC3EE, 0xCDF9, 0xC3EF, 0xCDFA, 0xAE74, 0xCDFB, 0xC3F0, + 0xCDFC, 0xAE75, 0xCDFD, 0xC3F1, 0xCDFE, 0xAE76, 0xCDFF, 0xAE77, 0xCE00, 0xAE78, 0xCE01, 0xAE79, 0xCE02, 0xAE7A, 0xCE03, 0xAE81, + 0xCE04, 0xC3F2, 0xCE05, 0xAE82, 0xCE06, 0xAE83, 0xCE07, 0xAE84, 0xCE08, 0xC3F3, 0xCE09, 0xAE85, 0xCE0A, 0xAE86, 0xCE0B, 0xAE87, + 0xCE0C, 0xC3F4, 0xCE0D, 0xAE88, 0xCE0E, 0xAE89, 0xCE0F, 0xAE8A, 0xCE10, 0xAE8B, 0xCE11, 0xAE8C, 0xCE12, 0xAE8D, 0xCE13, 0xAE8E, + 0xCE14, 0xC3F5, 0xCE15, 0xAE8F, 0xCE16, 0xAE90, 0xCE17, 0xAE91, 0xCE18, 0xAE92, 0xCE19, 0xC3F6, 0xCE1A, 0xAE93, 0xCE1B, 0xAE94, + 0xCE1C, 0xAE95, 0xCE1D, 0xAE96, 0xCE1E, 0xAE97, 0xCE1F, 0xAE98, 0xCE20, 0xC3F7, 0xCE21, 0xC3F8, 0xCE22, 0xAE99, 0xCE23, 0xAE9A, + 0xCE24, 0xC3F9, 0xCE25, 0xAE9B, 0xCE26, 0xAE9C, 0xCE27, 0xAE9D, 0xCE28, 0xC3FA, 0xCE29, 0xAE9E, 0xCE2A, 0xAE9F, 0xCE2B, 0xAEA0, + 0xCE2C, 0xAF41, 0xCE2D, 0xAF42, 0xCE2E, 0xAF43, 0xCE2F, 0xAF44, 0xCE30, 0xC3FB, 0xCE31, 0xC3FC, 0xCE32, 0xAF45, 0xCE33, 0xC3FD, + 0xCE34, 0xAF46, 0xCE35, 0xC3FE, 0xCE36, 0xAF47, 0xCE37, 0xAF48, 0xCE38, 0xAF49, 0xCE39, 0xAF4A, 0xCE3A, 0xAF4B, 0xCE3B, 0xAF4C, + 0xCE3C, 0xAF4D, 0xCE3D, 0xAF4E, 0xCE3E, 0xAF4F, 0xCE3F, 0xAF50, 0xCE40, 0xAF51, 0xCE41, 0xAF52, 0xCE42, 0xAF53, 0xCE43, 0xAF54, + 0xCE44, 0xAF55, 0xCE45, 0xAF56, 0xCE46, 0xAF57, 0xCE47, 0xAF58, 0xCE48, 0xAF59, 0xCE49, 0xAF5A, 0xCE4A, 0xAF61, 0xCE4B, 0xAF62, + 0xCE4C, 0xAF63, 0xCE4D, 0xAF64, 0xCE4E, 0xAF65, 0xCE4F, 0xAF66, 0xCE50, 0xAF67, 0xCE51, 0xAF68, 0xCE52, 0xAF69, 0xCE53, 0xAF6A, + 0xCE54, 0xAF6B, 0xCE55, 0xAF6C, 0xCE56, 0xAF6D, 0xCE57, 0xAF6E, 0xCE58, 0xC4A1, 0xCE59, 0xC4A2, 0xCE5A, 0xAF6F, 0xCE5B, 0xAF70, + 0xCE5C, 0xC4A3, 0xCE5D, 0xAF71, 0xCE5E, 0xAF72, 0xCE5F, 0xC4A4, 0xCE60, 0xC4A5, 0xCE61, 0xC4A6, 0xCE62, 0xAF73, 0xCE63, 0xAF74, + 0xCE64, 0xAF75, 0xCE65, 0xAF76, 0xCE66, 0xAF77, 0xCE67, 0xAF78, 0xCE68, 0xC4A7, 0xCE69, 0xC4A8, 0xCE6A, 0xAF79, 0xCE6B, 0xC4A9, + 0xCE6C, 0xAF7A, 0xCE6D, 0xC4AA, 0xCE6E, 0xAF81, 0xCE6F, 0xAF82, 0xCE70, 0xAF83, 0xCE71, 0xAF84, 0xCE72, 0xAF85, 0xCE73, 0xAF86, + 0xCE74, 0xC4AB, 0xCE75, 0xC4AC, 0xCE76, 0xAF87, 0xCE77, 0xAF88, 0xCE78, 0xC4AD, 0xCE79, 0xAF89, 0xCE7A, 0xAF8A, 0xCE7B, 0xAF8B, + 0xCE7C, 0xC4AE, 0xCE7D, 0xAF8C, 0xCE7E, 0xAF8D, 0xCE7F, 0xAF8E, 0xCE80, 0xAF8F, 0xCE81, 0xAF90, 0xCE82, 0xAF91, 0xCE83, 0xAF92, + 0xCE84, 0xC4AF, 0xCE85, 0xC4B0, 0xCE86, 0xAF93, 0xCE87, 0xC4B1, 0xCE88, 0xAF94, 0xCE89, 0xC4B2, 0xCE8A, 0xAF95, 0xCE8B, 0xAF96, + 0xCE8C, 0xAF97, 0xCE8D, 0xAF98, 0xCE8E, 0xAF99, 0xCE8F, 0xAF9A, 0xCE90, 0xC4B3, 0xCE91, 0xC4B4, 0xCE92, 0xAF9B, 0xCE93, 0xAF9C, + 0xCE94, 0xC4B5, 0xCE95, 0xAF9D, 0xCE96, 0xAF9E, 0xCE97, 0xAF9F, 0xCE98, 0xC4B6, 0xCE99, 0xAFA0, 0xCE9A, 0xB041, 0xCE9B, 0xB042, + 0xCE9C, 0xB043, 0xCE9D, 0xB044, 0xCE9E, 0xB045, 0xCE9F, 0xB046, 0xCEA0, 0xC4B7, 0xCEA1, 0xC4B8, 0xCEA2, 0xB047, 0xCEA3, 0xC4B9, + 0xCEA4, 0xC4BA, 0xCEA5, 0xC4BB, 0xCEA6, 0xB048, 0xCEA7, 0xB049, 0xCEA8, 0xB04A, 0xCEA9, 0xB04B, 0xCEAA, 0xB04C, 0xCEAB, 0xB04D, + 0xCEAC, 0xC4BC, 0xCEAD, 0xC4BD, 0xCEAE, 0xB04E, 0xCEAF, 0xB04F, 0xCEB0, 0xB050, 0xCEB1, 0xB051, 0xCEB2, 0xB052, 0xCEB3, 0xB053, + 0xCEB4, 0xB054, 0xCEB5, 0xB055, 0xCEB6, 0xB056, 0xCEB7, 0xB057, 0xCEB8, 0xB058, 0xCEB9, 0xB059, 0xCEBA, 0xB05A, 0xCEBB, 0xB061, + 0xCEBC, 0xB062, 0xCEBD, 0xB063, 0xCEBE, 0xB064, 0xCEBF, 0xB065, 0xCEC0, 0xB066, 0xCEC1, 0xC4BE, 0xCEC2, 0xB067, 0xCEC3, 0xB068, + 0xCEC4, 0xB069, 0xCEC5, 0xB06A, 0xCEC6, 0xB06B, 0xCEC7, 0xB06C, 0xCEC8, 0xB06D, 0xCEC9, 0xB06E, 0xCECA, 0xB06F, 0xCECB, 0xB070, + 0xCECC, 0xB071, 0xCECD, 0xB072, 0xCECE, 0xB073, 0xCECF, 0xB074, 0xCED0, 0xB075, 0xCED1, 0xB076, 0xCED2, 0xB077, 0xCED3, 0xB078, + 0xCED4, 0xB079, 0xCED5, 0xB07A, 0xCED6, 0xB081, 0xCED7, 0xB082, 0xCED8, 0xB083, 0xCED9, 0xB084, 0xCEDA, 0xB085, 0xCEDB, 0xB086, + 0xCEDC, 0xB087, 0xCEDD, 0xB088, 0xCEDE, 0xB089, 0xCEDF, 0xB08A, 0xCEE0, 0xB08B, 0xCEE1, 0xB08C, 0xCEE2, 0xB08D, 0xCEE3, 0xB08E, + 0xCEE4, 0xC4BF, 0xCEE5, 0xC4C0, 0xCEE6, 0xB08F, 0xCEE7, 0xB090, 0xCEE8, 0xC4C1, 0xCEE9, 0xB091, 0xCEEA, 0xB092, 0xCEEB, 0xC4C2, + 0xCEEC, 0xC4C3, 0xCEED, 0xB093, 0xCEEE, 0xB094, 0xCEEF, 0xB095, 0xCEF0, 0xB096, 0xCEF1, 0xB097, 0xCEF2, 0xB098, 0xCEF3, 0xB099, + 0xCEF4, 0xC4C4, 0xCEF5, 0xC4C5, 0xCEF6, 0xB09A, 0xCEF7, 0xC4C6, 0xCEF8, 0xC4C7, 0xCEF9, 0xC4C8, 0xCEFA, 0xB09B, 0xCEFB, 0xB09C, + 0xCEFC, 0xB09D, 0xCEFD, 0xB09E, 0xCEFE, 0xB09F, 0xCEFF, 0xB0A0, 0xCF00, 0xC4C9, 0xCF01, 0xC4CA, 0xCF02, 0xB141, 0xCF03, 0xB142, + 0xCF04, 0xC4CB, 0xCF05, 0xB143, 0xCF06, 0xB144, 0xCF07, 0xB145, 0xCF08, 0xC4CC, 0xCF09, 0xB146, 0xCF0A, 0xB147, 0xCF0B, 0xB148, + 0xCF0C, 0xB149, 0xCF0D, 0xB14A, 0xCF0E, 0xB14B, 0xCF0F, 0xB14C, 0xCF10, 0xC4CD, 0xCF11, 0xC4CE, 0xCF12, 0xB14D, 0xCF13, 0xC4CF, + 0xCF14, 0xB14E, 0xCF15, 0xC4D0, 0xCF16, 0xB14F, 0xCF17, 0xB150, 0xCF18, 0xB151, 0xCF19, 0xB152, 0xCF1A, 0xB153, 0xCF1B, 0xB154, + 0xCF1C, 0xC4D1, 0xCF1D, 0xB155, 0xCF1E, 0xB156, 0xCF1F, 0xB157, 0xCF20, 0xC4D2, 0xCF21, 0xB158, 0xCF22, 0xB159, 0xCF23, 0xB15A, + 0xCF24, 0xC4D3, 0xCF25, 0xB161, 0xCF26, 0xB162, 0xCF27, 0xB163, 0xCF28, 0xB164, 0xCF29, 0xB165, 0xCF2A, 0xB166, 0xCF2B, 0xB167, + 0xCF2C, 0xC4D4, 0xCF2D, 0xC4D5, 0xCF2E, 0xB168, 0xCF2F, 0xC4D6, 0xCF30, 0xC4D7, 0xCF31, 0xC4D8, 0xCF32, 0xB169, 0xCF33, 0xB16A, + 0xCF34, 0xB16B, 0xCF35, 0xB16C, 0xCF36, 0xB16D, 0xCF37, 0xB16E, 0xCF38, 0xC4D9, 0xCF39, 0xB16F, 0xCF3A, 0xB170, 0xCF3B, 0xB171, + 0xCF3C, 0xB172, 0xCF3D, 0xB173, 0xCF3E, 0xB174, 0xCF3F, 0xB175, 0xCF40, 0xB176, 0xCF41, 0xB177, 0xCF42, 0xB178, 0xCF43, 0xB179, + 0xCF44, 0xB17A, 0xCF45, 0xB181, 0xCF46, 0xB182, 0xCF47, 0xB183, 0xCF48, 0xB184, 0xCF49, 0xB185, 0xCF4A, 0xB186, 0xCF4B, 0xB187, + 0xCF4C, 0xB188, 0xCF4D, 0xB189, 0xCF4E, 0xB18A, 0xCF4F, 0xB18B, 0xCF50, 0xB18C, 0xCF51, 0xB18D, 0xCF52, 0xB18E, 0xCF53, 0xB18F, + 0xCF54, 0xC4DA, 0xCF55, 0xC4DB, 0xCF56, 0xB190, 0xCF57, 0xB191, 0xCF58, 0xC4DC, 0xCF59, 0xB192, 0xCF5A, 0xB193, 0xCF5B, 0xB194, + 0xCF5C, 0xC4DD, 0xCF5D, 0xB195, 0xCF5E, 0xB196, 0xCF5F, 0xB197, 0xCF60, 0xB198, 0xCF61, 0xB199, 0xCF62, 0xB19A, 0xCF63, 0xB19B, + 0xCF64, 0xC4DE, 0xCF65, 0xC4DF, 0xCF66, 0xB19C, 0xCF67, 0xC4E0, 0xCF68, 0xB19D, 0xCF69, 0xC4E1, 0xCF6A, 0xB19E, 0xCF6B, 0xB19F, + 0xCF6C, 0xB1A0, 0xCF6D, 0xB241, 0xCF6E, 0xB242, 0xCF6F, 0xB243, 0xCF70, 0xC4E2, 0xCF71, 0xC4E3, 0xCF72, 0xB244, 0xCF73, 0xB245, + 0xCF74, 0xC4E4, 0xCF75, 0xB246, 0xCF76, 0xB247, 0xCF77, 0xB248, 0xCF78, 0xC4E5, 0xCF79, 0xB249, 0xCF7A, 0xB24A, 0xCF7B, 0xB24B, + 0xCF7C, 0xB24C, 0xCF7D, 0xB24D, 0xCF7E, 0xB24E, 0xCF7F, 0xB24F, 0xCF80, 0xC4E6, 0xCF81, 0xB250, 0xCF82, 0xB251, 0xCF83, 0xB252, + 0xCF84, 0xB253, 0xCF85, 0xC4E7, 0xCF86, 0xB254, 0xCF87, 0xB255, 0xCF88, 0xB256, 0xCF89, 0xB257, 0xCF8A, 0xB258, 0xCF8B, 0xB259, + 0xCF8C, 0xC4E8, 0xCF8D, 0xB25A, 0xCF8E, 0xB261, 0xCF8F, 0xB262, 0xCF90, 0xB263, 0xCF91, 0xB264, 0xCF92, 0xB265, 0xCF93, 0xB266, + 0xCF94, 0xB267, 0xCF95, 0xB268, 0xCF96, 0xB269, 0xCF97, 0xB26A, 0xCF98, 0xB26B, 0xCF99, 0xB26C, 0xCF9A, 0xB26D, 0xCF9B, 0xB26E, + 0xCF9C, 0xB26F, 0xCF9D, 0xB270, 0xCF9E, 0xB271, 0xCF9F, 0xB272, 0xCFA0, 0xB273, 0xCFA1, 0xC4E9, 0xCFA2, 0xB274, 0xCFA3, 0xB275, + 0xCFA4, 0xB276, 0xCFA5, 0xB277, 0xCFA6, 0xB278, 0xCFA7, 0xB279, 0xCFA8, 0xC4EA, 0xCFA9, 0xB27A, 0xCFAA, 0xB281, 0xCFAB, 0xB282, + 0xCFAC, 0xB283, 0xCFAD, 0xB284, 0xCFAE, 0xB285, 0xCFAF, 0xB286, 0xCFB0, 0xC4EB, 0xCFB1, 0xB287, 0xCFB2, 0xB288, 0xCFB3, 0xB289, + 0xCFB4, 0xB28A, 0xCFB5, 0xB28B, 0xCFB6, 0xB28C, 0xCFB7, 0xB28D, 0xCFB8, 0xB28E, 0xCFB9, 0xB28F, 0xCFBA, 0xB290, 0xCFBB, 0xB291, + 0xCFBC, 0xB292, 0xCFBD, 0xB293, 0xCFBE, 0xB294, 0xCFBF, 0xB295, 0xCFC0, 0xB296, 0xCFC1, 0xB297, 0xCFC2, 0xB298, 0xCFC3, 0xB299, + 0xCFC4, 0xC4EC, 0xCFC5, 0xB29A, 0xCFC6, 0xB29B, 0xCFC7, 0xB29C, 0xCFC8, 0xB29D, 0xCFC9, 0xB29E, 0xCFCA, 0xB29F, 0xCFCB, 0xB2A0, + 0xCFCC, 0xB341, 0xCFCD, 0xB342, 0xCFCE, 0xB343, 0xCFCF, 0xB344, 0xCFD0, 0xB345, 0xCFD1, 0xB346, 0xCFD2, 0xB347, 0xCFD3, 0xB348, + 0xCFD4, 0xB349, 0xCFD5, 0xB34A, 0xCFD6, 0xB34B, 0xCFD7, 0xB34C, 0xCFD8, 0xB34D, 0xCFD9, 0xB34E, 0xCFDA, 0xB34F, 0xCFDB, 0xB350, + 0xCFDC, 0xB351, 0xCFDD, 0xB352, 0xCFDE, 0xB353, 0xCFDF, 0xB354, 0xCFE0, 0xC4ED, 0xCFE1, 0xC4EE, 0xCFE2, 0xB355, 0xCFE3, 0xB356, + 0xCFE4, 0xC4EF, 0xCFE5, 0xB357, 0xCFE6, 0xB358, 0xCFE7, 0xB359, 0xCFE8, 0xC4F0, 0xCFE9, 0xB35A, 0xCFEA, 0xB361, 0xCFEB, 0xB362, + 0xCFEC, 0xB363, 0xCFED, 0xB364, 0xCFEE, 0xB365, 0xCFEF, 0xB366, 0xCFF0, 0xC4F1, 0xCFF1, 0xC4F2, 0xCFF2, 0xB367, 0xCFF3, 0xC4F3, + 0xCFF4, 0xB368, 0xCFF5, 0xC4F4, 0xCFF6, 0xB369, 0xCFF7, 0xB36A, 0xCFF8, 0xB36B, 0xCFF9, 0xB36C, 0xCFFA, 0xB36D, 0xCFFB, 0xB36E, + 0xCFFC, 0xC4F5, 0xCFFD, 0xB36F, 0xCFFE, 0xB370, 0xCFFF, 0xB371, 0xD000, 0xC4F6, 0xD001, 0xB372, 0xD002, 0xB373, 0xD003, 0xB374, + 0xD004, 0xC4F7, 0xD005, 0xB375, 0xD006, 0xB376, 0xD007, 0xB377, 0xD008, 0xB378, 0xD009, 0xB379, 0xD00A, 0xB37A, 0xD00B, 0xB381, + 0xD00C, 0xB382, 0xD00D, 0xB383, 0xD00E, 0xB384, 0xD00F, 0xB385, 0xD010, 0xB386, 0xD011, 0xC4F8, 0xD012, 0xB387, 0xD013, 0xB388, + 0xD014, 0xB389, 0xD015, 0xB38A, 0xD016, 0xB38B, 0xD017, 0xB38C, 0xD018, 0xC4F9, 0xD019, 0xB38D, 0xD01A, 0xB38E, 0xD01B, 0xB38F, + 0xD01C, 0xB390, 0xD01D, 0xB391, 0xD01E, 0xB392, 0xD01F, 0xB393, 0xD020, 0xB394, 0xD021, 0xB395, 0xD022, 0xB396, 0xD023, 0xB397, + 0xD024, 0xB398, 0xD025, 0xB399, 0xD026, 0xB39A, 0xD027, 0xB39B, 0xD028, 0xB39C, 0xD029, 0xB39D, 0xD02A, 0xB39E, 0xD02B, 0xB39F, + 0xD02C, 0xB3A0, 0xD02D, 0xC4FA, 0xD02E, 0xB441, 0xD02F, 0xB442, 0xD030, 0xB443, 0xD031, 0xB444, 0xD032, 0xB445, 0xD033, 0xB446, + 0xD034, 0xC4FB, 0xD035, 0xC4FC, 0xD036, 0xB447, 0xD037, 0xB448, 0xD038, 0xC4FD, 0xD039, 0xB449, 0xD03A, 0xB44A, 0xD03B, 0xB44B, + 0xD03C, 0xC4FE, 0xD03D, 0xB44C, 0xD03E, 0xB44D, 0xD03F, 0xB44E, 0xD040, 0xB44F, 0xD041, 0xB450, 0xD042, 0xB451, 0xD043, 0xB452, + 0xD044, 0xC5A1, 0xD045, 0xC5A2, 0xD046, 0xB453, 0xD047, 0xC5A3, 0xD048, 0xB454, 0xD049, 0xC5A4, 0xD04A, 0xB455, 0xD04B, 0xB456, + 0xD04C, 0xB457, 0xD04D, 0xB458, 0xD04E, 0xB459, 0xD04F, 0xB45A, 0xD050, 0xC5A5, 0xD051, 0xB461, 0xD052, 0xB462, 0xD053, 0xB463, + 0xD054, 0xC5A6, 0xD055, 0xB464, 0xD056, 0xB465, 0xD057, 0xB466, 0xD058, 0xC5A7, 0xD059, 0xB467, 0xD05A, 0xB468, 0xD05B, 0xB469, + 0xD05C, 0xB46A, 0xD05D, 0xB46B, 0xD05E, 0xB46C, 0xD05F, 0xB46D, 0xD060, 0xC5A8, 0xD061, 0xB46E, 0xD062, 0xB46F, 0xD063, 0xB470, + 0xD064, 0xB471, 0xD065, 0xB472, 0xD066, 0xB473, 0xD067, 0xB474, 0xD068, 0xB475, 0xD069, 0xB476, 0xD06A, 0xB477, 0xD06B, 0xB478, + 0xD06C, 0xC5A9, 0xD06D, 0xC5AA, 0xD06E, 0xB479, 0xD06F, 0xB47A, 0xD070, 0xC5AB, 0xD071, 0xB481, 0xD072, 0xB482, 0xD073, 0xB483, + 0xD074, 0xC5AC, 0xD075, 0xB484, 0xD076, 0xB485, 0xD077, 0xB486, 0xD078, 0xB487, 0xD079, 0xB488, 0xD07A, 0xB489, 0xD07B, 0xB48A, + 0xD07C, 0xC5AD, 0xD07D, 0xC5AE, 0xD07E, 0xB48B, 0xD07F, 0xB48C, 0xD080, 0xB48D, 0xD081, 0xC5AF, 0xD082, 0xB48E, 0xD083, 0xB48F, + 0xD084, 0xB490, 0xD085, 0xB491, 0xD086, 0xB492, 0xD087, 0xB493, 0xD088, 0xB494, 0xD089, 0xB495, 0xD08A, 0xB496, 0xD08B, 0xB497, + 0xD08C, 0xB498, 0xD08D, 0xB499, 0xD08E, 0xB49A, 0xD08F, 0xB49B, 0xD090, 0xB49C, 0xD091, 0xB49D, 0xD092, 0xB49E, 0xD093, 0xB49F, + 0xD094, 0xB4A0, 0xD095, 0xB541, 0xD096, 0xB542, 0xD097, 0xB543, 0xD098, 0xB544, 0xD099, 0xB545, 0xD09A, 0xB546, 0xD09B, 0xB547, + 0xD09C, 0xB548, 0xD09D, 0xB549, 0xD09E, 0xB54A, 0xD09F, 0xB54B, 0xD0A0, 0xB54C, 0xD0A1, 0xB54D, 0xD0A2, 0xB54E, 0xD0A3, 0xB54F, + 0xD0A4, 0xC5B0, 0xD0A5, 0xC5B1, 0xD0A6, 0xB550, 0xD0A7, 0xB551, 0xD0A8, 0xC5B2, 0xD0A9, 0xB552, 0xD0AA, 0xB553, 0xD0AB, 0xB554, + 0xD0AC, 0xC5B3, 0xD0AD, 0xB555, 0xD0AE, 0xB556, 0xD0AF, 0xB557, 0xD0B0, 0xB558, 0xD0B1, 0xB559, 0xD0B2, 0xB55A, 0xD0B3, 0xB561, + 0xD0B4, 0xC5B4, 0xD0B5, 0xC5B5, 0xD0B6, 0xB562, 0xD0B7, 0xC5B6, 0xD0B8, 0xB563, 0xD0B9, 0xC5B7, 0xD0BA, 0xB564, 0xD0BB, 0xB565, + 0xD0BC, 0xB566, 0xD0BD, 0xB567, 0xD0BE, 0xB568, 0xD0BF, 0xB569, 0xD0C0, 0xC5B8, 0xD0C1, 0xC5B9, 0xD0C2, 0xB56A, 0xD0C3, 0xB56B, + 0xD0C4, 0xC5BA, 0xD0C5, 0xB56C, 0xD0C6, 0xB56D, 0xD0C7, 0xB56E, 0xD0C8, 0xC5BB, 0xD0C9, 0xC5BC, 0xD0CA, 0xB56F, 0xD0CB, 0xB570, + 0xD0CC, 0xB571, 0xD0CD, 0xB572, 0xD0CE, 0xB573, 0xD0CF, 0xB574, 0xD0D0, 0xC5BD, 0xD0D1, 0xC5BE, 0xD0D2, 0xB575, 0xD0D3, 0xC5BF, + 0xD0D4, 0xC5C0, 0xD0D5, 0xC5C1, 0xD0D6, 0xB576, 0xD0D7, 0xB577, 0xD0D8, 0xB578, 0xD0D9, 0xB579, 0xD0DA, 0xB57A, 0xD0DB, 0xB581, + 0xD0DC, 0xC5C2, 0xD0DD, 0xC5C3, 0xD0DE, 0xB582, 0xD0DF, 0xB583, 0xD0E0, 0xC5C4, 0xD0E1, 0xB584, 0xD0E2, 0xB585, 0xD0E3, 0xB586, + 0xD0E4, 0xC5C5, 0xD0E5, 0xB587, 0xD0E6, 0xB588, 0xD0E7, 0xB589, 0xD0E8, 0xB58A, 0xD0E9, 0xB58B, 0xD0EA, 0xB58C, 0xD0EB, 0xB58D, + 0xD0EC, 0xC5C6, 0xD0ED, 0xC5C7, 0xD0EE, 0xB58E, 0xD0EF, 0xC5C8, 0xD0F0, 0xC5C9, 0xD0F1, 0xC5CA, 0xD0F2, 0xB58F, 0xD0F3, 0xB590, + 0xD0F4, 0xB591, 0xD0F5, 0xB592, 0xD0F6, 0xB593, 0xD0F7, 0xB594, 0xD0F8, 0xC5CB, 0xD0F9, 0xB595, 0xD0FA, 0xB596, 0xD0FB, 0xB597, + 0xD0FC, 0xB598, 0xD0FD, 0xB599, 0xD0FE, 0xB59A, 0xD0FF, 0xB59B, 0xD100, 0xB59C, 0xD101, 0xB59D, 0xD102, 0xB59E, 0xD103, 0xB59F, + 0xD104, 0xB5A0, 0xD105, 0xB641, 0xD106, 0xB642, 0xD107, 0xB643, 0xD108, 0xB644, 0xD109, 0xB645, 0xD10A, 0xB646, 0xD10B, 0xB647, + 0xD10C, 0xB648, 0xD10D, 0xC5CC, 0xD10E, 0xB649, 0xD10F, 0xB64A, 0xD110, 0xB64B, 0xD111, 0xB64C, 0xD112, 0xB64D, 0xD113, 0xB64E, + 0xD114, 0xB64F, 0xD115, 0xB650, 0xD116, 0xB651, 0xD117, 0xB652, 0xD118, 0xB653, 0xD119, 0xB654, 0xD11A, 0xB655, 0xD11B, 0xB656, + 0xD11C, 0xB657, 0xD11D, 0xB658, 0xD11E, 0xB659, 0xD11F, 0xB65A, 0xD120, 0xB661, 0xD121, 0xB662, 0xD122, 0xB663, 0xD123, 0xB664, + 0xD124, 0xB665, 0xD125, 0xB666, 0xD126, 0xB667, 0xD127, 0xB668, 0xD128, 0xB669, 0xD129, 0xB66A, 0xD12A, 0xB66B, 0xD12B, 0xB66C, + 0xD12C, 0xB66D, 0xD12D, 0xB66E, 0xD12E, 0xB66F, 0xD12F, 0xB670, 0xD130, 0xC5CD, 0xD131, 0xC5CE, 0xD132, 0xB671, 0xD133, 0xB672, + 0xD134, 0xC5CF, 0xD135, 0xB673, 0xD136, 0xB674, 0xD137, 0xB675, 0xD138, 0xC5D0, 0xD139, 0xB676, 0xD13A, 0xC5D1, 0xD13B, 0xB677, + 0xD13C, 0xB678, 0xD13D, 0xB679, 0xD13E, 0xB67A, 0xD13F, 0xB681, 0xD140, 0xC5D2, 0xD141, 0xC5D3, 0xD142, 0xB682, 0xD143, 0xC5D4, + 0xD144, 0xC5D5, 0xD145, 0xC5D6, 0xD146, 0xB683, 0xD147, 0xB684, 0xD148, 0xB685, 0xD149, 0xB686, 0xD14A, 0xB687, 0xD14B, 0xB688, + 0xD14C, 0xC5D7, 0xD14D, 0xC5D8, 0xD14E, 0xB689, 0xD14F, 0xB68A, 0xD150, 0xC5D9, 0xD151, 0xB68B, 0xD152, 0xB68C, 0xD153, 0xB68D, + 0xD154, 0xC5DA, 0xD155, 0xB68E, 0xD156, 0xB68F, 0xD157, 0xB690, 0xD158, 0xB691, 0xD159, 0xB692, 0xD15A, 0xB693, 0xD15B, 0xB694, + 0xD15C, 0xC5DB, 0xD15D, 0xC5DC, 0xD15E, 0xB695, 0xD15F, 0xC5DD, 0xD160, 0xB696, 0xD161, 0xC5DE, 0xD162, 0xB697, 0xD163, 0xB698, + 0xD164, 0xB699, 0xD165, 0xB69A, 0xD166, 0xB69B, 0xD167, 0xB69C, 0xD168, 0xC5DF, 0xD169, 0xB69D, 0xD16A, 0xB69E, 0xD16B, 0xB69F, + 0xD16C, 0xC5E0, 0xD16D, 0xB6A0, 0xD16E, 0xB741, 0xD16F, 0xB742, 0xD170, 0xB743, 0xD171, 0xB744, 0xD172, 0xB745, 0xD173, 0xB746, + 0xD174, 0xB747, 0xD175, 0xB748, 0xD176, 0xB749, 0xD177, 0xB74A, 0xD178, 0xB74B, 0xD179, 0xB74C, 0xD17A, 0xB74D, 0xD17B, 0xB74E, + 0xD17C, 0xC5E1, 0xD17D, 0xB74F, 0xD17E, 0xB750, 0xD17F, 0xB751, 0xD180, 0xB752, 0xD181, 0xB753, 0xD182, 0xB754, 0xD183, 0xB755, + 0xD184, 0xC5E2, 0xD185, 0xB756, 0xD186, 0xB757, 0xD187, 0xB758, 0xD188, 0xC5E3, 0xD189, 0xB759, 0xD18A, 0xB75A, 0xD18B, 0xB761, + 0xD18C, 0xB762, 0xD18D, 0xB763, 0xD18E, 0xB764, 0xD18F, 0xB765, 0xD190, 0xB766, 0xD191, 0xB767, 0xD192, 0xB768, 0xD193, 0xB769, + 0xD194, 0xB76A, 0xD195, 0xB76B, 0xD196, 0xB76C, 0xD197, 0xB76D, 0xD198, 0xB76E, 0xD199, 0xB76F, 0xD19A, 0xB770, 0xD19B, 0xB771, + 0xD19C, 0xB772, 0xD19D, 0xB773, 0xD19E, 0xB774, 0xD19F, 0xB775, 0xD1A0, 0xC5E4, 0xD1A1, 0xC5E5, 0xD1A2, 0xB776, 0xD1A3, 0xB777, + 0xD1A4, 0xC5E6, 0xD1A5, 0xB778, 0xD1A6, 0xB779, 0xD1A7, 0xB77A, 0xD1A8, 0xC5E7, 0xD1A9, 0xB781, 0xD1AA, 0xB782, 0xD1AB, 0xB783, + 0xD1AC, 0xB784, 0xD1AD, 0xB785, 0xD1AE, 0xB786, 0xD1AF, 0xB787, 0xD1B0, 0xC5E8, 0xD1B1, 0xC5E9, 0xD1B2, 0xB788, 0xD1B3, 0xC5EA, + 0xD1B4, 0xB789, 0xD1B5, 0xC5EB, 0xD1B6, 0xB78A, 0xD1B7, 0xB78B, 0xD1B8, 0xB78C, 0xD1B9, 0xB78D, 0xD1BA, 0xC5EC, 0xD1BB, 0xB78E, + 0xD1BC, 0xC5ED, 0xD1BD, 0xB78F, 0xD1BE, 0xB790, 0xD1BF, 0xB791, 0xD1C0, 0xC5EE, 0xD1C1, 0xB792, 0xD1C2, 0xB793, 0xD1C3, 0xB794, + 0xD1C4, 0xB795, 0xD1C5, 0xB796, 0xD1C6, 0xB797, 0xD1C7, 0xB798, 0xD1C8, 0xB799, 0xD1C9, 0xB79A, 0xD1CA, 0xB79B, 0xD1CB, 0xB79C, + 0xD1CC, 0xB79D, 0xD1CD, 0xB79E, 0xD1CE, 0xB79F, 0xD1CF, 0xB7A0, 0xD1D0, 0xB841, 0xD1D1, 0xB842, 0xD1D2, 0xB843, 0xD1D3, 0xB844, + 0xD1D4, 0xB845, 0xD1D5, 0xB846, 0xD1D6, 0xB847, 0xD1D7, 0xB848, 0xD1D8, 0xC5EF, 0xD1D9, 0xB849, 0xD1DA, 0xB84A, 0xD1DB, 0xB84B, + 0xD1DC, 0xB84C, 0xD1DD, 0xB84D, 0xD1DE, 0xB84E, 0xD1DF, 0xB84F, 0xD1E0, 0xB850, 0xD1E1, 0xB851, 0xD1E2, 0xB852, 0xD1E3, 0xB853, + 0xD1E4, 0xB854, 0xD1E5, 0xB855, 0xD1E6, 0xB856, 0xD1E7, 0xB857, 0xD1E8, 0xB858, 0xD1E9, 0xB859, 0xD1EA, 0xB85A, 0xD1EB, 0xB861, + 0xD1EC, 0xB862, 0xD1ED, 0xB863, 0xD1EE, 0xB864, 0xD1EF, 0xB865, 0xD1F0, 0xB866, 0xD1F1, 0xB867, 0xD1F2, 0xB868, 0xD1F3, 0xB869, + 0xD1F4, 0xC5F0, 0xD1F5, 0xB86A, 0xD1F6, 0xB86B, 0xD1F7, 0xB86C, 0xD1F8, 0xC5F1, 0xD1F9, 0xB86D, 0xD1FA, 0xB86E, 0xD1FB, 0xB86F, + 0xD1FC, 0xB870, 0xD1FD, 0xB871, 0xD1FE, 0xB872, 0xD1FF, 0xB873, 0xD200, 0xB874, 0xD201, 0xB875, 0xD202, 0xB876, 0xD203, 0xB877, + 0xD204, 0xB878, 0xD205, 0xB879, 0xD206, 0xB87A, 0xD207, 0xC5F2, 0xD208, 0xB881, 0xD209, 0xC5F3, 0xD20A, 0xB882, 0xD20B, 0xB883, + 0xD20C, 0xB884, 0xD20D, 0xB885, 0xD20E, 0xB886, 0xD20F, 0xB887, 0xD210, 0xC5F4, 0xD211, 0xB888, 0xD212, 0xB889, 0xD213, 0xB88A, + 0xD214, 0xB88B, 0xD215, 0xB88C, 0xD216, 0xB88D, 0xD217, 0xB88E, 0xD218, 0xB88F, 0xD219, 0xB890, 0xD21A, 0xB891, 0xD21B, 0xB892, + 0xD21C, 0xB893, 0xD21D, 0xB894, 0xD21E, 0xB895, 0xD21F, 0xB896, 0xD220, 0xB897, 0xD221, 0xB898, 0xD222, 0xB899, 0xD223, 0xB89A, + 0xD224, 0xB89B, 0xD225, 0xB89C, 0xD226, 0xB89D, 0xD227, 0xB89E, 0xD228, 0xB89F, 0xD229, 0xB8A0, 0xD22A, 0xB941, 0xD22B, 0xB942, + 0xD22C, 0xC5F5, 0xD22D, 0xC5F6, 0xD22E, 0xB943, 0xD22F, 0xB944, 0xD230, 0xC5F7, 0xD231, 0xB945, 0xD232, 0xB946, 0xD233, 0xB947, + 0xD234, 0xC5F8, 0xD235, 0xB948, 0xD236, 0xB949, 0xD237, 0xB94A, 0xD238, 0xB94B, 0xD239, 0xB94C, 0xD23A, 0xB94D, 0xD23B, 0xB94E, + 0xD23C, 0xC5F9, 0xD23D, 0xC5FA, 0xD23E, 0xB94F, 0xD23F, 0xC5FB, 0xD240, 0xB950, 0xD241, 0xC5FC, 0xD242, 0xB951, 0xD243, 0xB952, + 0xD244, 0xB953, 0xD245, 0xB954, 0xD246, 0xB955, 0xD247, 0xB956, 0xD248, 0xC5FD, 0xD249, 0xB957, 0xD24A, 0xB958, 0xD24B, 0xB959, + 0xD24C, 0xB95A, 0xD24D, 0xB961, 0xD24E, 0xB962, 0xD24F, 0xB963, 0xD250, 0xB964, 0xD251, 0xB965, 0xD252, 0xB966, 0xD253, 0xB967, + 0xD254, 0xB968, 0xD255, 0xB969, 0xD256, 0xB96A, 0xD257, 0xB96B, 0xD258, 0xB96C, 0xD259, 0xB96D, 0xD25A, 0xB96E, 0xD25B, 0xB96F, + 0xD25C, 0xC5FE, 0xD25D, 0xB970, 0xD25E, 0xB971, 0xD25F, 0xB972, 0xD260, 0xB973, 0xD261, 0xB974, 0xD262, 0xB975, 0xD263, 0xB976, + 0xD264, 0xC6A1, 0xD265, 0xB977, 0xD266, 0xB978, 0xD267, 0xB979, 0xD268, 0xB97A, 0xD269, 0xB981, 0xD26A, 0xB982, 0xD26B, 0xB983, + 0xD26C, 0xB984, 0xD26D, 0xB985, 0xD26E, 0xB986, 0xD26F, 0xB987, 0xD270, 0xB988, 0xD271, 0xB989, 0xD272, 0xB98A, 0xD273, 0xB98B, + 0xD274, 0xB98C, 0xD275, 0xB98D, 0xD276, 0xB98E, 0xD277, 0xB98F, 0xD278, 0xB990, 0xD279, 0xB991, 0xD27A, 0xB992, 0xD27B, 0xB993, + 0xD27C, 0xB994, 0xD27D, 0xB995, 0xD27E, 0xB996, 0xD27F, 0xB997, 0xD280, 0xC6A2, 0xD281, 0xC6A3, 0xD282, 0xB998, 0xD283, 0xB999, + 0xD284, 0xC6A4, 0xD285, 0xB99A, 0xD286, 0xB99B, 0xD287, 0xB99C, 0xD288, 0xC6A5, 0xD289, 0xB99D, 0xD28A, 0xB99E, 0xD28B, 0xB99F, + 0xD28C, 0xB9A0, 0xD28D, 0xBA41, 0xD28E, 0xBA42, 0xD28F, 0xBA43, 0xD290, 0xC6A6, 0xD291, 0xC6A7, 0xD292, 0xBA44, 0xD293, 0xBA45, + 0xD294, 0xBA46, 0xD295, 0xC6A8, 0xD296, 0xBA47, 0xD297, 0xBA48, 0xD298, 0xBA49, 0xD299, 0xBA4A, 0xD29A, 0xBA4B, 0xD29B, 0xBA4C, + 0xD29C, 0xC6A9, 0xD29D, 0xBA4D, 0xD29E, 0xBA4E, 0xD29F, 0xBA4F, 0xD2A0, 0xC6AA, 0xD2A1, 0xBA50, 0xD2A2, 0xBA51, 0xD2A3, 0xBA52, + 0xD2A4, 0xC6AB, 0xD2A5, 0xBA53, 0xD2A6, 0xBA54, 0xD2A7, 0xBA55, 0xD2A8, 0xBA56, 0xD2A9, 0xBA57, 0xD2AA, 0xBA58, 0xD2AB, 0xBA59, + 0xD2AC, 0xC6AC, 0xD2AD, 0xBA5A, 0xD2AE, 0xBA61, 0xD2AF, 0xBA62, 0xD2B0, 0xBA63, 0xD2B1, 0xC6AD, 0xD2B2, 0xBA64, 0xD2B3, 0xBA65, + 0xD2B4, 0xBA66, 0xD2B5, 0xBA67, 0xD2B6, 0xBA68, 0xD2B7, 0xBA69, 0xD2B8, 0xC6AE, 0xD2B9, 0xC6AF, 0xD2BA, 0xBA6A, 0xD2BB, 0xBA6B, + 0xD2BC, 0xC6B0, 0xD2BD, 0xBA6C, 0xD2BE, 0xBA6D, 0xD2BF, 0xC6B1, 0xD2C0, 0xC6B2, 0xD2C1, 0xBA6E, 0xD2C2, 0xC6B3, 0xD2C3, 0xBA6F, + 0xD2C4, 0xBA70, 0xD2C5, 0xBA71, 0xD2C6, 0xBA72, 0xD2C7, 0xBA73, 0xD2C8, 0xC6B4, 0xD2C9, 0xC6B5, 0xD2CA, 0xBA74, 0xD2CB, 0xC6B6, + 0xD2CC, 0xBA75, 0xD2CD, 0xBA76, 0xD2CE, 0xBA77, 0xD2CF, 0xBA78, 0xD2D0, 0xBA79, 0xD2D1, 0xBA7A, 0xD2D2, 0xBA81, 0xD2D3, 0xBA82, + 0xD2D4, 0xC6B7, 0xD2D5, 0xBA83, 0xD2D6, 0xBA84, 0xD2D7, 0xBA85, 0xD2D8, 0xC6B8, 0xD2D9, 0xBA86, 0xD2DA, 0xBA87, 0xD2DB, 0xBA88, + 0xD2DC, 0xC6B9, 0xD2DD, 0xBA89, 0xD2DE, 0xBA8A, 0xD2DF, 0xBA8B, 0xD2E0, 0xBA8C, 0xD2E1, 0xBA8D, 0xD2E2, 0xBA8E, 0xD2E3, 0xBA8F, + 0xD2E4, 0xC6BA, 0xD2E5, 0xC6BB, 0xD2E6, 0xBA90, 0xD2E7, 0xBA91, 0xD2E8, 0xBA92, 0xD2E9, 0xBA93, 0xD2EA, 0xBA94, 0xD2EB, 0xBA95, + 0xD2EC, 0xBA96, 0xD2ED, 0xBA97, 0xD2EE, 0xBA98, 0xD2EF, 0xBA99, 0xD2F0, 0xC6BC, 0xD2F1, 0xC6BD, 0xD2F2, 0xBA9A, 0xD2F3, 0xBA9B, + 0xD2F4, 0xC6BE, 0xD2F5, 0xBA9C, 0xD2F6, 0xBA9D, 0xD2F7, 0xBA9E, 0xD2F8, 0xC6BF, 0xD2F9, 0xBA9F, 0xD2FA, 0xBAA0, 0xD2FB, 0xBB41, + 0xD2FC, 0xBB42, 0xD2FD, 0xBB43, 0xD2FE, 0xBB44, 0xD2FF, 0xBB45, 0xD300, 0xC6C0, 0xD301, 0xC6C1, 0xD302, 0xBB46, 0xD303, 0xC6C2, + 0xD304, 0xBB47, 0xD305, 0xC6C3, 0xD306, 0xBB48, 0xD307, 0xBB49, 0xD308, 0xBB4A, 0xD309, 0xBB4B, 0xD30A, 0xBB4C, 0xD30B, 0xBB4D, + 0xD30C, 0xC6C4, 0xD30D, 0xC6C5, 0xD30E, 0xC6C6, 0xD30F, 0xBB4E, 0xD310, 0xC6C7, 0xD311, 0xBB4F, 0xD312, 0xBB50, 0xD313, 0xBB51, + 0xD314, 0xC6C8, 0xD315, 0xBB52, 0xD316, 0xC6C9, 0xD317, 0xBB53, 0xD318, 0xBB54, 0xD319, 0xBB55, 0xD31A, 0xBB56, 0xD31B, 0xBB57, + 0xD31C, 0xC6CA, 0xD31D, 0xC6CB, 0xD31E, 0xBB58, 0xD31F, 0xC6CC, 0xD320, 0xC6CD, 0xD321, 0xC6CE, 0xD322, 0xBB59, 0xD323, 0xBB5A, + 0xD324, 0xBB61, 0xD325, 0xC6CF, 0xD326, 0xBB62, 0xD327, 0xBB63, 0xD328, 0xC6D0, 0xD329, 0xC6D1, 0xD32A, 0xBB64, 0xD32B, 0xBB65, + 0xD32C, 0xC6D2, 0xD32D, 0xBB66, 0xD32E, 0xBB67, 0xD32F, 0xBB68, 0xD330, 0xC6D3, 0xD331, 0xBB69, 0xD332, 0xBB6A, 0xD333, 0xBB6B, + 0xD334, 0xBB6C, 0xD335, 0xBB6D, 0xD336, 0xBB6E, 0xD337, 0xBB6F, 0xD338, 0xC6D4, 0xD339, 0xC6D5, 0xD33A, 0xBB70, 0xD33B, 0xC6D6, + 0xD33C, 0xC6D7, 0xD33D, 0xC6D8, 0xD33E, 0xBB71, 0xD33F, 0xBB72, 0xD340, 0xBB73, 0xD341, 0xBB74, 0xD342, 0xBB75, 0xD343, 0xBB76, + 0xD344, 0xC6D9, 0xD345, 0xC6DA, 0xD346, 0xBB77, 0xD347, 0xBB78, 0xD348, 0xBB79, 0xD349, 0xBB7A, 0xD34A, 0xBB81, 0xD34B, 0xBB82, + 0xD34C, 0xBB83, 0xD34D, 0xBB84, 0xD34E, 0xBB85, 0xD34F, 0xBB86, 0xD350, 0xBB87, 0xD351, 0xBB88, 0xD352, 0xBB89, 0xD353, 0xBB8A, + 0xD354, 0xBB8B, 0xD355, 0xBB8C, 0xD356, 0xBB8D, 0xD357, 0xBB8E, 0xD358, 0xBB8F, 0xD359, 0xBB90, 0xD35A, 0xBB91, 0xD35B, 0xBB92, + 0xD35C, 0xBB93, 0xD35D, 0xBB94, 0xD35E, 0xBB95, 0xD35F, 0xBB96, 0xD360, 0xBB97, 0xD361, 0xBB98, 0xD362, 0xBB99, 0xD363, 0xBB9A, + 0xD364, 0xBB9B, 0xD365, 0xBB9C, 0xD366, 0xBB9D, 0xD367, 0xBB9E, 0xD368, 0xBB9F, 0xD369, 0xBBA0, 0xD36A, 0xBC41, 0xD36B, 0xBC42, + 0xD36C, 0xBC43, 0xD36D, 0xBC44, 0xD36E, 0xBC45, 0xD36F, 0xBC46, 0xD370, 0xBC47, 0xD371, 0xBC48, 0xD372, 0xBC49, 0xD373, 0xBC4A, + 0xD374, 0xBC4B, 0xD375, 0xBC4C, 0xD376, 0xBC4D, 0xD377, 0xBC4E, 0xD378, 0xBC4F, 0xD379, 0xBC50, 0xD37A, 0xBC51, 0xD37B, 0xBC52, + 0xD37C, 0xC6DB, 0xD37D, 0xC6DC, 0xD37E, 0xBC53, 0xD37F, 0xBC54, 0xD380, 0xC6DD, 0xD381, 0xBC55, 0xD382, 0xBC56, 0xD383, 0xBC57, + 0xD384, 0xC6DE, 0xD385, 0xBC58, 0xD386, 0xBC59, 0xD387, 0xBC5A, 0xD388, 0xBC61, 0xD389, 0xBC62, 0xD38A, 0xBC63, 0xD38B, 0xBC64, + 0xD38C, 0xC6DF, 0xD38D, 0xC6E0, 0xD38E, 0xBC65, 0xD38F, 0xC6E1, 0xD390, 0xC6E2, 0xD391, 0xC6E3, 0xD392, 0xBC66, 0xD393, 0xBC67, + 0xD394, 0xBC68, 0xD395, 0xBC69, 0xD396, 0xBC6A, 0xD397, 0xBC6B, 0xD398, 0xC6E4, 0xD399, 0xC6E5, 0xD39A, 0xBC6C, 0xD39B, 0xBC6D, + 0xD39C, 0xC6E6, 0xD39D, 0xBC6E, 0xD39E, 0xBC6F, 0xD39F, 0xBC70, 0xD3A0, 0xC6E7, 0xD3A1, 0xBC71, 0xD3A2, 0xBC72, 0xD3A3, 0xBC73, + 0xD3A4, 0xBC74, 0xD3A5, 0xBC75, 0xD3A6, 0xBC76, 0xD3A7, 0xBC77, 0xD3A8, 0xC6E8, 0xD3A9, 0xC6E9, 0xD3AA, 0xBC78, 0xD3AB, 0xC6EA, + 0xD3AC, 0xBC79, 0xD3AD, 0xC6EB, 0xD3AE, 0xBC7A, 0xD3AF, 0xBC81, 0xD3B0, 0xBC82, 0xD3B1, 0xBC83, 0xD3B2, 0xBC84, 0xD3B3, 0xBC85, + 0xD3B4, 0xC6EC, 0xD3B5, 0xBC86, 0xD3B6, 0xBC87, 0xD3B7, 0xBC88, 0xD3B8, 0xC6ED, 0xD3B9, 0xBC89, 0xD3BA, 0xBC8A, 0xD3BB, 0xBC8B, + 0xD3BC, 0xC6EE, 0xD3BD, 0xBC8C, 0xD3BE, 0xBC8D, 0xD3BF, 0xBC8E, 0xD3C0, 0xBC8F, 0xD3C1, 0xBC90, 0xD3C2, 0xBC91, 0xD3C3, 0xBC92, + 0xD3C4, 0xC6EF, 0xD3C5, 0xC6F0, 0xD3C6, 0xBC93, 0xD3C7, 0xBC94, 0xD3C8, 0xC6F1, 0xD3C9, 0xC6F2, 0xD3CA, 0xBC95, 0xD3CB, 0xBC96, + 0xD3CC, 0xBC97, 0xD3CD, 0xBC98, 0xD3CE, 0xBC99, 0xD3CF, 0xBC9A, 0xD3D0, 0xC6F3, 0xD3D1, 0xBC9B, 0xD3D2, 0xBC9C, 0xD3D3, 0xBC9D, + 0xD3D4, 0xBC9E, 0xD3D5, 0xBC9F, 0xD3D6, 0xBCA0, 0xD3D7, 0xBD41, 0xD3D8, 0xC6F4, 0xD3D9, 0xBD42, 0xD3DA, 0xBD43, 0xD3DB, 0xBD44, + 0xD3DC, 0xBD45, 0xD3DD, 0xBD46, 0xD3DE, 0xBD47, 0xD3DF, 0xBD48, 0xD3E0, 0xBD49, 0xD3E1, 0xC6F5, 0xD3E2, 0xBD4A, 0xD3E3, 0xC6F6, + 0xD3E4, 0xBD4B, 0xD3E5, 0xBD4C, 0xD3E6, 0xBD4D, 0xD3E7, 0xBD4E, 0xD3E8, 0xBD4F, 0xD3E9, 0xBD50, 0xD3EA, 0xBD51, 0xD3EB, 0xBD52, + 0xD3EC, 0xC6F7, 0xD3ED, 0xC6F8, 0xD3EE, 0xBD53, 0xD3EF, 0xBD54, 0xD3F0, 0xC6F9, 0xD3F1, 0xBD55, 0xD3F2, 0xBD56, 0xD3F3, 0xBD57, + 0xD3F4, 0xC6FA, 0xD3F5, 0xBD58, 0xD3F6, 0xBD59, 0xD3F7, 0xBD5A, 0xD3F8, 0xBD61, 0xD3F9, 0xBD62, 0xD3FA, 0xBD63, 0xD3FB, 0xBD64, + 0xD3FC, 0xC6FB, 0xD3FD, 0xC6FC, 0xD3FE, 0xBD65, 0xD3FF, 0xC6FD, 0xD400, 0xBD66, 0xD401, 0xC6FE, 0xD402, 0xBD67, 0xD403, 0xBD68, + 0xD404, 0xBD69, 0xD405, 0xBD6A, 0xD406, 0xBD6B, 0xD407, 0xBD6C, 0xD408, 0xC7A1, 0xD409, 0xBD6D, 0xD40A, 0xBD6E, 0xD40B, 0xBD6F, + 0xD40C, 0xBD70, 0xD40D, 0xBD71, 0xD40E, 0xBD72, 0xD40F, 0xBD73, 0xD410, 0xBD74, 0xD411, 0xBD75, 0xD412, 0xBD76, 0xD413, 0xBD77, + 0xD414, 0xBD78, 0xD415, 0xBD79, 0xD416, 0xBD7A, 0xD417, 0xBD81, 0xD418, 0xBD82, 0xD419, 0xBD83, 0xD41A, 0xBD84, 0xD41B, 0xBD85, + 0xD41C, 0xBD86, 0xD41D, 0xC7A2, 0xD41E, 0xBD87, 0xD41F, 0xBD88, 0xD420, 0xBD89, 0xD421, 0xBD8A, 0xD422, 0xBD8B, 0xD423, 0xBD8C, + 0xD424, 0xBD8D, 0xD425, 0xBD8E, 0xD426, 0xBD8F, 0xD427, 0xBD90, 0xD428, 0xBD91, 0xD429, 0xBD92, 0xD42A, 0xBD93, 0xD42B, 0xBD94, + 0xD42C, 0xBD95, 0xD42D, 0xBD96, 0xD42E, 0xBD97, 0xD42F, 0xBD98, 0xD430, 0xBD99, 0xD431, 0xBD9A, 0xD432, 0xBD9B, 0xD433, 0xBD9C, + 0xD434, 0xBD9D, 0xD435, 0xBD9E, 0xD436, 0xBD9F, 0xD437, 0xBDA0, 0xD438, 0xBE41, 0xD439, 0xBE42, 0xD43A, 0xBE43, 0xD43B, 0xBE44, + 0xD43C, 0xBE45, 0xD43D, 0xBE46, 0xD43E, 0xBE47, 0xD43F, 0xBE48, 0xD440, 0xC7A3, 0xD441, 0xBE49, 0xD442, 0xBE4A, 0xD443, 0xBE4B, + 0xD444, 0xC7A4, 0xD445, 0xBE4C, 0xD446, 0xBE4D, 0xD447, 0xBE4E, 0xD448, 0xBE4F, 0xD449, 0xBE50, 0xD44A, 0xBE51, 0xD44B, 0xBE52, + 0xD44C, 0xBE53, 0xD44D, 0xBE54, 0xD44E, 0xBE55, 0xD44F, 0xBE56, 0xD450, 0xBE57, 0xD451, 0xBE58, 0xD452, 0xBE59, 0xD453, 0xBE5A, + 0xD454, 0xBE61, 0xD455, 0xBE62, 0xD456, 0xBE63, 0xD457, 0xBE64, 0xD458, 0xBE65, 0xD459, 0xBE66, 0xD45A, 0xBE67, 0xD45B, 0xBE68, + 0xD45C, 0xC7A5, 0xD45D, 0xBE69, 0xD45E, 0xBE6A, 0xD45F, 0xBE6B, 0xD460, 0xC7A6, 0xD461, 0xBE6C, 0xD462, 0xBE6D, 0xD463, 0xBE6E, + 0xD464, 0xC7A7, 0xD465, 0xBE6F, 0xD466, 0xBE70, 0xD467, 0xBE71, 0xD468, 0xBE72, 0xD469, 0xBE73, 0xD46A, 0xBE74, 0xD46B, 0xBE75, + 0xD46C, 0xBE76, 0xD46D, 0xC7A8, 0xD46E, 0xBE77, 0xD46F, 0xC7A9, 0xD470, 0xBE78, 0xD471, 0xBE79, 0xD472, 0xBE7A, 0xD473, 0xBE81, + 0xD474, 0xBE82, 0xD475, 0xBE83, 0xD476, 0xBE84, 0xD477, 0xBE85, 0xD478, 0xC7AA, 0xD479, 0xC7AB, 0xD47A, 0xBE86, 0xD47B, 0xBE87, + 0xD47C, 0xC7AC, 0xD47D, 0xBE88, 0xD47E, 0xBE89, 0xD47F, 0xC7AD, 0xD480, 0xC7AE, 0xD481, 0xBE8A, 0xD482, 0xC7AF, 0xD483, 0xBE8B, + 0xD484, 0xBE8C, 0xD485, 0xBE8D, 0xD486, 0xBE8E, 0xD487, 0xBE8F, 0xD488, 0xC7B0, 0xD489, 0xC7B1, 0xD48A, 0xBE90, 0xD48B, 0xC7B2, + 0xD48C, 0xBE91, 0xD48D, 0xC7B3, 0xD48E, 0xBE92, 0xD48F, 0xBE93, 0xD490, 0xBE94, 0xD491, 0xBE95, 0xD492, 0xBE96, 0xD493, 0xBE97, + 0xD494, 0xC7B4, 0xD495, 0xBE98, 0xD496, 0xBE99, 0xD497, 0xBE9A, 0xD498, 0xBE9B, 0xD499, 0xBE9C, 0xD49A, 0xBE9D, 0xD49B, 0xBE9E, + 0xD49C, 0xBE9F, 0xD49D, 0xBEA0, 0xD49E, 0xBF41, 0xD49F, 0xBF42, 0xD4A0, 0xBF43, 0xD4A1, 0xBF44, 0xD4A2, 0xBF45, 0xD4A3, 0xBF46, + 0xD4A4, 0xBF47, 0xD4A5, 0xBF48, 0xD4A6, 0xBF49, 0xD4A7, 0xBF4A, 0xD4A8, 0xBF4B, 0xD4A9, 0xC7B5, 0xD4AA, 0xBF4C, 0xD4AB, 0xBF4D, + 0xD4AC, 0xBF4E, 0xD4AD, 0xBF4F, 0xD4AE, 0xBF50, 0xD4AF, 0xBF51, 0xD4B0, 0xBF52, 0xD4B1, 0xBF53, 0xD4B2, 0xBF54, 0xD4B3, 0xBF55, + 0xD4B4, 0xBF56, 0xD4B5, 0xBF57, 0xD4B6, 0xBF58, 0xD4B7, 0xBF59, 0xD4B8, 0xBF5A, 0xD4B9, 0xBF61, 0xD4BA, 0xBF62, 0xD4BB, 0xBF63, + 0xD4BC, 0xBF64, 0xD4BD, 0xBF65, 0xD4BE, 0xBF66, 0xD4BF, 0xBF67, 0xD4C0, 0xBF68, 0xD4C1, 0xBF69, 0xD4C2, 0xBF6A, 0xD4C3, 0xBF6B, + 0xD4C4, 0xBF6C, 0xD4C5, 0xBF6D, 0xD4C6, 0xBF6E, 0xD4C7, 0xBF6F, 0xD4C8, 0xBF70, 0xD4C9, 0xBF71, 0xD4CA, 0xBF72, 0xD4CB, 0xBF73, + 0xD4CC, 0xC7B6, 0xD4CD, 0xBF74, 0xD4CE, 0xBF75, 0xD4CF, 0xBF76, 0xD4D0, 0xC7B7, 0xD4D1, 0xBF77, 0xD4D2, 0xBF78, 0xD4D3, 0xBF79, + 0xD4D4, 0xC7B8, 0xD4D5, 0xBF7A, 0xD4D6, 0xBF81, 0xD4D7, 0xBF82, 0xD4D8, 0xBF83, 0xD4D9, 0xBF84, 0xD4DA, 0xBF85, 0xD4DB, 0xBF86, + 0xD4DC, 0xC7B9, 0xD4DD, 0xBF87, 0xD4DE, 0xBF88, 0xD4DF, 0xC7BA, 0xD4E0, 0xBF89, 0xD4E1, 0xBF8A, 0xD4E2, 0xBF8B, 0xD4E3, 0xBF8C, + 0xD4E4, 0xBF8D, 0xD4E5, 0xBF8E, 0xD4E6, 0xBF8F, 0xD4E7, 0xBF90, 0xD4E8, 0xC7BB, 0xD4E9, 0xBF91, 0xD4EA, 0xBF92, 0xD4EB, 0xBF93, + 0xD4EC, 0xC7BC, 0xD4ED, 0xBF94, 0xD4EE, 0xBF95, 0xD4EF, 0xBF96, 0xD4F0, 0xC7BD, 0xD4F1, 0xBF97, 0xD4F2, 0xBF98, 0xD4F3, 0xBF99, + 0xD4F4, 0xBF9A, 0xD4F5, 0xBF9B, 0xD4F6, 0xBF9C, 0xD4F7, 0xBF9D, 0xD4F8, 0xC7BE, 0xD4F9, 0xBF9E, 0xD4FA, 0xBF9F, 0xD4FB, 0xC7BF, + 0xD4FC, 0xBFA0, 0xD4FD, 0xC7C0, 0xD4FE, 0xC041, 0xD4FF, 0xC042, 0xD500, 0xC043, 0xD501, 0xC044, 0xD502, 0xC045, 0xD503, 0xC046, + 0xD504, 0xC7C1, 0xD505, 0xC047, 0xD506, 0xC048, 0xD507, 0xC049, 0xD508, 0xC7C2, 0xD509, 0xC04A, 0xD50A, 0xC04B, 0xD50B, 0xC04C, + 0xD50C, 0xC7C3, 0xD50D, 0xC04D, 0xD50E, 0xC04E, 0xD50F, 0xC04F, 0xD510, 0xC050, 0xD511, 0xC051, 0xD512, 0xC052, 0xD513, 0xC053, + 0xD514, 0xC7C4, 0xD515, 0xC7C5, 0xD516, 0xC054, 0xD517, 0xC7C6, 0xD518, 0xC055, 0xD519, 0xC056, 0xD51A, 0xC057, 0xD51B, 0xC058, + 0xD51C, 0xC059, 0xD51D, 0xC05A, 0xD51E, 0xC061, 0xD51F, 0xC062, 0xD520, 0xC063, 0xD521, 0xC064, 0xD522, 0xC065, 0xD523, 0xC066, + 0xD524, 0xC067, 0xD525, 0xC068, 0xD526, 0xC069, 0xD527, 0xC06A, 0xD528, 0xC06B, 0xD529, 0xC06C, 0xD52A, 0xC06D, 0xD52B, 0xC06E, + 0xD52C, 0xC06F, 0xD52D, 0xC070, 0xD52E, 0xC071, 0xD52F, 0xC072, 0xD530, 0xC073, 0xD531, 0xC074, 0xD532, 0xC075, 0xD533, 0xC076, + 0xD534, 0xC077, 0xD535, 0xC078, 0xD536, 0xC079, 0xD537, 0xC07A, 0xD538, 0xC081, 0xD539, 0xC082, 0xD53A, 0xC083, 0xD53B, 0xC084, + 0xD53C, 0xC7C7, 0xD53D, 0xC7C8, 0xD53E, 0xC085, 0xD53F, 0xC086, 0xD540, 0xC7C9, 0xD541, 0xC087, 0xD542, 0xC088, 0xD543, 0xC089, + 0xD544, 0xC7CA, 0xD545, 0xC08A, 0xD546, 0xC08B, 0xD547, 0xC08C, 0xD548, 0xC08D, 0xD549, 0xC08E, 0xD54A, 0xC08F, 0xD54B, 0xC090, + 0xD54C, 0xC7CB, 0xD54D, 0xC7CC, 0xD54E, 0xC091, 0xD54F, 0xC7CD, 0xD550, 0xC092, 0xD551, 0xC7CE, 0xD552, 0xC093, 0xD553, 0xC094, + 0xD554, 0xC095, 0xD555, 0xC096, 0xD556, 0xC097, 0xD557, 0xC098, 0xD558, 0xC7CF, 0xD559, 0xC7D0, 0xD55A, 0xC099, 0xD55B, 0xC09A, + 0xD55C, 0xC7D1, 0xD55D, 0xC09B, 0xD55E, 0xC09C, 0xD55F, 0xC09D, 0xD560, 0xC7D2, 0xD561, 0xC09E, 0xD562, 0xC09F, 0xD563, 0xC0A0, + 0xD564, 0xC141, 0xD565, 0xC7D3, 0xD566, 0xC142, 0xD567, 0xC143, 0xD568, 0xC7D4, 0xD569, 0xC7D5, 0xD56A, 0xC144, 0xD56B, 0xC7D6, + 0xD56C, 0xC145, 0xD56D, 0xC7D7, 0xD56E, 0xC146, 0xD56F, 0xC147, 0xD570, 0xC148, 0xD571, 0xC149, 0xD572, 0xC14A, 0xD573, 0xC14B, + 0xD574, 0xC7D8, 0xD575, 0xC7D9, 0xD576, 0xC14C, 0xD577, 0xC14D, 0xD578, 0xC7DA, 0xD579, 0xC14E, 0xD57A, 0xC14F, 0xD57B, 0xC150, + 0xD57C, 0xC7DB, 0xD57D, 0xC151, 0xD57E, 0xC152, 0xD57F, 0xC153, 0xD580, 0xC154, 0xD581, 0xC155, 0xD582, 0xC156, 0xD583, 0xC157, + 0xD584, 0xC7DC, 0xD585, 0xC7DD, 0xD586, 0xC158, 0xD587, 0xC7DE, 0xD588, 0xC7DF, 0xD589, 0xC7E0, 0xD58A, 0xC159, 0xD58B, 0xC15A, + 0xD58C, 0xC161, 0xD58D, 0xC162, 0xD58E, 0xC163, 0xD58F, 0xC164, 0xD590, 0xC7E1, 0xD591, 0xC165, 0xD592, 0xC166, 0xD593, 0xC167, + 0xD594, 0xC168, 0xD595, 0xC169, 0xD596, 0xC16A, 0xD597, 0xC16B, 0xD598, 0xC16C, 0xD599, 0xC16D, 0xD59A, 0xC16E, 0xD59B, 0xC16F, + 0xD59C, 0xC170, 0xD59D, 0xC171, 0xD59E, 0xC172, 0xD59F, 0xC173, 0xD5A0, 0xC174, 0xD5A1, 0xC175, 0xD5A2, 0xC176, 0xD5A3, 0xC177, + 0xD5A4, 0xC178, 0xD5A5, 0xC7E2, 0xD5A6, 0xC179, 0xD5A7, 0xC17A, 0xD5A8, 0xC181, 0xD5A9, 0xC182, 0xD5AA, 0xC183, 0xD5AB, 0xC184, + 0xD5AC, 0xC185, 0xD5AD, 0xC186, 0xD5AE, 0xC187, 0xD5AF, 0xC188, 0xD5B0, 0xC189, 0xD5B1, 0xC18A, 0xD5B2, 0xC18B, 0xD5B3, 0xC18C, + 0xD5B4, 0xC18D, 0xD5B5, 0xC18E, 0xD5B6, 0xC18F, 0xD5B7, 0xC190, 0xD5B8, 0xC191, 0xD5B9, 0xC192, 0xD5BA, 0xC193, 0xD5BB, 0xC194, + 0xD5BC, 0xC195, 0xD5BD, 0xC196, 0xD5BE, 0xC197, 0xD5BF, 0xC198, 0xD5C0, 0xC199, 0xD5C1, 0xC19A, 0xD5C2, 0xC19B, 0xD5C3, 0xC19C, + 0xD5C4, 0xC19D, 0xD5C5, 0xC19E, 0xD5C6, 0xC19F, 0xD5C7, 0xC1A0, 0xD5C8, 0xC7E3, 0xD5C9, 0xC7E4, 0xD5CA, 0xC241, 0xD5CB, 0xC242, + 0xD5CC, 0xC7E5, 0xD5CD, 0xC243, 0xD5CE, 0xC244, 0xD5CF, 0xC245, 0xD5D0, 0xC7E6, 0xD5D1, 0xC246, 0xD5D2, 0xC7E7, 0xD5D3, 0xC247, + 0xD5D4, 0xC248, 0xD5D5, 0xC249, 0xD5D6, 0xC24A, 0xD5D7, 0xC24B, 0xD5D8, 0xC7E8, 0xD5D9, 0xC7E9, 0xD5DA, 0xC24C, 0xD5DB, 0xC7EA, + 0xD5DC, 0xC24D, 0xD5DD, 0xC7EB, 0xD5DE, 0xC24E, 0xD5DF, 0xC24F, 0xD5E0, 0xC250, 0xD5E1, 0xC251, 0xD5E2, 0xC252, 0xD5E3, 0xC253, + 0xD5E4, 0xC7EC, 0xD5E5, 0xC7ED, 0xD5E6, 0xC254, 0xD5E7, 0xC255, 0xD5E8, 0xC7EE, 0xD5E9, 0xC256, 0xD5EA, 0xC257, 0xD5EB, 0xC258, + 0xD5EC, 0xC7EF, 0xD5ED, 0xC259, 0xD5EE, 0xC25A, 0xD5EF, 0xC261, 0xD5F0, 0xC262, 0xD5F1, 0xC263, 0xD5F2, 0xC264, 0xD5F3, 0xC265, + 0xD5F4, 0xC7F0, 0xD5F5, 0xC7F1, 0xD5F6, 0xC266, 0xD5F7, 0xC7F2, 0xD5F8, 0xC267, 0xD5F9, 0xC7F3, 0xD5FA, 0xC268, 0xD5FB, 0xC269, + 0xD5FC, 0xC26A, 0xD5FD, 0xC26B, 0xD5FE, 0xC26C, 0xD5FF, 0xC26D, 0xD600, 0xC7F4, 0xD601, 0xC7F5, 0xD602, 0xC26E, 0xD603, 0xC26F, + 0xD604, 0xC7F6, 0xD605, 0xC270, 0xD606, 0xC271, 0xD607, 0xC272, 0xD608, 0xC7F7, 0xD609, 0xC273, 0xD60A, 0xC274, 0xD60B, 0xC275, + 0xD60C, 0xC276, 0xD60D, 0xC277, 0xD60E, 0xC278, 0xD60F, 0xC279, 0xD610, 0xC7F8, 0xD611, 0xC7F9, 0xD612, 0xC27A, 0xD613, 0xC7FA, + 0xD614, 0xC7FB, 0xD615, 0xC7FC, 0xD616, 0xC281, 0xD617, 0xC282, 0xD618, 0xC283, 0xD619, 0xC284, 0xD61A, 0xC285, 0xD61B, 0xC286, + 0xD61C, 0xC7FD, 0xD61D, 0xC287, 0xD61E, 0xC288, 0xD61F, 0xC289, 0xD620, 0xC7FE, 0xD621, 0xC28A, 0xD622, 0xC28B, 0xD623, 0xC28C, + 0xD624, 0xC8A1, 0xD625, 0xC28D, 0xD626, 0xC28E, 0xD627, 0xC28F, 0xD628, 0xC290, 0xD629, 0xC291, 0xD62A, 0xC292, 0xD62B, 0xC293, + 0xD62C, 0xC294, 0xD62D, 0xC8A2, 0xD62E, 0xC295, 0xD62F, 0xC296, 0xD630, 0xC297, 0xD631, 0xC298, 0xD632, 0xC299, 0xD633, 0xC29A, + 0xD634, 0xC29B, 0xD635, 0xC29C, 0xD636, 0xC29D, 0xD637, 0xC29E, 0xD638, 0xC8A3, 0xD639, 0xC8A4, 0xD63A, 0xC29F, 0xD63B, 0xC2A0, + 0xD63C, 0xC8A5, 0xD63D, 0xC341, 0xD63E, 0xC342, 0xD63F, 0xC343, 0xD640, 0xC8A6, 0xD641, 0xC344, 0xD642, 0xC345, 0xD643, 0xC346, + 0xD644, 0xC347, 0xD645, 0xC8A7, 0xD646, 0xC348, 0xD647, 0xC349, 0xD648, 0xC8A8, 0xD649, 0xC8A9, 0xD64A, 0xC34A, 0xD64B, 0xC8AA, + 0xD64C, 0xC34B, 0xD64D, 0xC8AB, 0xD64E, 0xC34C, 0xD64F, 0xC34D, 0xD650, 0xC34E, 0xD651, 0xC8AC, 0xD652, 0xC34F, 0xD653, 0xC350, + 0xD654, 0xC8AD, 0xD655, 0xC8AE, 0xD656, 0xC351, 0xD657, 0xC352, 0xD658, 0xC8AF, 0xD659, 0xC353, 0xD65A, 0xC354, 0xD65B, 0xC355, + 0xD65C, 0xC8B0, 0xD65D, 0xC356, 0xD65E, 0xC357, 0xD65F, 0xC358, 0xD660, 0xC359, 0xD661, 0xC35A, 0xD662, 0xC361, 0xD663, 0xC362, + 0xD664, 0xC363, 0xD665, 0xC364, 0xD666, 0xC365, 0xD667, 0xC8B1, 0xD668, 0xC366, 0xD669, 0xC8B2, 0xD66A, 0xC367, 0xD66B, 0xC368, + 0xD66C, 0xC369, 0xD66D, 0xC36A, 0xD66E, 0xC36B, 0xD66F, 0xC36C, 0xD670, 0xC8B3, 0xD671, 0xC8B4, 0xD672, 0xC36D, 0xD673, 0xC36E, + 0xD674, 0xC8B5, 0xD675, 0xC36F, 0xD676, 0xC370, 0xD677, 0xC371, 0xD678, 0xC372, 0xD679, 0xC373, 0xD67A, 0xC374, 0xD67B, 0xC375, + 0xD67C, 0xC376, 0xD67D, 0xC377, 0xD67E, 0xC378, 0xD67F, 0xC379, 0xD680, 0xC37A, 0xD681, 0xC381, 0xD682, 0xC382, 0xD683, 0xC8B6, + 0xD684, 0xC383, 0xD685, 0xC8B7, 0xD686, 0xC384, 0xD687, 0xC385, 0xD688, 0xC386, 0xD689, 0xC387, 0xD68A, 0xC388, 0xD68B, 0xC389, + 0xD68C, 0xC8B8, 0xD68D, 0xC8B9, 0xD68E, 0xC38A, 0xD68F, 0xC38B, 0xD690, 0xC8BA, 0xD691, 0xC38C, 0xD692, 0xC38D, 0xD693, 0xC38E, + 0xD694, 0xC8BB, 0xD695, 0xC38F, 0xD696, 0xC390, 0xD697, 0xC391, 0xD698, 0xC392, 0xD699, 0xC393, 0xD69A, 0xC394, 0xD69B, 0xC395, + 0xD69C, 0xC396, 0xD69D, 0xC8BC, 0xD69E, 0xC397, 0xD69F, 0xC8BD, 0xD6A0, 0xC398, 0xD6A1, 0xC8BE, 0xD6A2, 0xC399, 0xD6A3, 0xC39A, + 0xD6A4, 0xC39B, 0xD6A5, 0xC39C, 0xD6A6, 0xC39D, 0xD6A7, 0xC39E, 0xD6A8, 0xC8BF, 0xD6A9, 0xC39F, 0xD6AA, 0xC3A0, 0xD6AB, 0xC441, + 0xD6AC, 0xC8C0, 0xD6AD, 0xC442, 0xD6AE, 0xC443, 0xD6AF, 0xC444, 0xD6B0, 0xC8C1, 0xD6B1, 0xC445, 0xD6B2, 0xC446, 0xD6B3, 0xC447, + 0xD6B4, 0xC448, 0xD6B5, 0xC449, 0xD6B6, 0xC44A, 0xD6B7, 0xC44B, 0xD6B8, 0xC44C, 0xD6B9, 0xC8C2, 0xD6BA, 0xC44D, 0xD6BB, 0xC8C3, + 0xD6BC, 0xC44E, 0xD6BD, 0xC44F, 0xD6BE, 0xC450, 0xD6BF, 0xC451, 0xD6C0, 0xC452, 0xD6C1, 0xC453, 0xD6C2, 0xC454, 0xD6C3, 0xC455, + 0xD6C4, 0xC8C4, 0xD6C5, 0xC8C5, 0xD6C6, 0xC456, 0xD6C7, 0xC457, 0xD6C8, 0xC8C6, 0xD6C9, 0xC458, 0xD6CA, 0xC459, 0xD6CB, 0xC45A, + 0xD6CC, 0xC8C7, 0xD6CD, 0xC461, 0xD6CE, 0xC462, 0xD6CF, 0xC463, 0xD6D0, 0xC464, 0xD6D1, 0xC8C8, 0xD6D2, 0xC465, 0xD6D3, 0xC466, + 0xD6D4, 0xC8C9, 0xD6D5, 0xC467, 0xD6D6, 0xC468, 0xD6D7, 0xC8CA, 0xD6D8, 0xC469, 0xD6D9, 0xC8CB, 0xD6DA, 0xC46A, 0xD6DB, 0xC46B, + 0xD6DC, 0xC46C, 0xD6DD, 0xC46D, 0xD6DE, 0xC46E, 0xD6DF, 0xC46F, 0xD6E0, 0xC8CC, 0xD6E1, 0xC470, 0xD6E2, 0xC471, 0xD6E3, 0xC472, + 0xD6E4, 0xC8CD, 0xD6E5, 0xC473, 0xD6E6, 0xC474, 0xD6E7, 0xC475, 0xD6E8, 0xC8CE, 0xD6E9, 0xC476, 0xD6EA, 0xC477, 0xD6EB, 0xC478, + 0xD6EC, 0xC479, 0xD6ED, 0xC47A, 0xD6EE, 0xC481, 0xD6EF, 0xC482, 0xD6F0, 0xC8CF, 0xD6F1, 0xC483, 0xD6F2, 0xC484, 0xD6F3, 0xC485, + 0xD6F4, 0xC486, 0xD6F5, 0xC8D0, 0xD6F6, 0xC487, 0xD6F7, 0xC488, 0xD6F8, 0xC489, 0xD6F9, 0xC48A, 0xD6FA, 0xC48B, 0xD6FB, 0xC48C, + 0xD6FC, 0xC8D1, 0xD6FD, 0xC8D2, 0xD6FE, 0xC48D, 0xD6FF, 0xC48E, 0xD700, 0xC8D3, 0xD701, 0xC48F, 0xD702, 0xC490, 0xD703, 0xC491, + 0xD704, 0xC8D4, 0xD705, 0xC492, 0xD706, 0xC493, 0xD707, 0xC494, 0xD708, 0xC495, 0xD709, 0xC496, 0xD70A, 0xC497, 0xD70B, 0xC498, + 0xD70C, 0xC499, 0xD70D, 0xC49A, 0xD70E, 0xC49B, 0xD70F, 0xC49C, 0xD710, 0xC49D, 0xD711, 0xC8D5, 0xD712, 0xC49E, 0xD713, 0xC49F, + 0xD714, 0xC4A0, 0xD715, 0xC541, 0xD716, 0xC542, 0xD717, 0xC543, 0xD718, 0xC8D6, 0xD719, 0xC8D7, 0xD71A, 0xC544, 0xD71B, 0xC545, + 0xD71C, 0xC8D8, 0xD71D, 0xC546, 0xD71E, 0xC547, 0xD71F, 0xC548, 0xD720, 0xC8D9, 0xD721, 0xC549, 0xD722, 0xC54A, 0xD723, 0xC54B, + 0xD724, 0xC54C, 0xD725, 0xC54D, 0xD726, 0xC54E, 0xD727, 0xC54F, 0xD728, 0xC8DA, 0xD729, 0xC8DB, 0xD72A, 0xC550, 0xD72B, 0xC8DC, + 0xD72C, 0xC551, 0xD72D, 0xC8DD, 0xD72E, 0xC552, 0xD72F, 0xC553, 0xD730, 0xC554, 0xD731, 0xC555, 0xD732, 0xC556, 0xD733, 0xC557, + 0xD734, 0xC8DE, 0xD735, 0xC8DF, 0xD736, 0xC558, 0xD737, 0xC559, 0xD738, 0xC8E0, 0xD739, 0xC55A, 0xD73A, 0xC561, 0xD73B, 0xC562, + 0xD73C, 0xC8E1, 0xD73D, 0xC563, 0xD73E, 0xC564, 0xD73F, 0xC565, 0xD740, 0xC566, 0xD741, 0xC567, 0xD742, 0xC568, 0xD743, 0xC569, + 0xD744, 0xC8E2, 0xD745, 0xC56A, 0xD746, 0xC56B, 0xD747, 0xC8E3, 0xD748, 0xC56C, 0xD749, 0xC8E4, 0xD74A, 0xC56D, 0xD74B, 0xC56E, + 0xD74C, 0xC56F, 0xD74D, 0xC570, 0xD74E, 0xC571, 0xD74F, 0xC572, 0xD750, 0xC8E5, 0xD751, 0xC8E6, 0xD752, 0xC573, 0xD753, 0xC574, + 0xD754, 0xC8E7, 0xD755, 0xC575, 0xD756, 0xC8E8, 0xD757, 0xC8E9, 0xD758, 0xC8EA, 0xD759, 0xC8EB, 0xD75A, 0xC576, 0xD75B, 0xC577, + 0xD75C, 0xC578, 0xD75D, 0xC579, 0xD75E, 0xC57A, 0xD75F, 0xC581, 0xD760, 0xC8EC, 0xD761, 0xC8ED, 0xD762, 0xC582, 0xD763, 0xC8EE, + 0xD764, 0xC583, 0xD765, 0xC8EF, 0xD766, 0xC584, 0xD767, 0xC585, 0xD768, 0xC586, 0xD769, 0xC8F0, 0xD76A, 0xC587, 0xD76B, 0xC588, + 0xD76C, 0xC8F1, 0xD76D, 0xC589, 0xD76E, 0xC58A, 0xD76F, 0xC58B, 0xD770, 0xC8F2, 0xD771, 0xC58C, 0xD772, 0xC58D, 0xD773, 0xC58E, + 0xD774, 0xC8F3, 0xD775, 0xC58F, 0xD776, 0xC590, 0xD777, 0xC591, 0xD778, 0xC592, 0xD779, 0xC593, 0xD77A, 0xC594, 0xD77B, 0xC595, + 0xD77C, 0xC8F4, 0xD77D, 0xC8F5, 0xD77E, 0xC596, 0xD77F, 0xC597, 0xD780, 0xC598, 0xD781, 0xC8F6, 0xD782, 0xC599, 0xD783, 0xC59A, + 0xD784, 0xC59B, 0xD785, 0xC59C, 0xD786, 0xC59D, 0xD787, 0xC59E, 0xD788, 0xC8F7, 0xD789, 0xC8F8, 0xD78A, 0xC59F, 0xD78B, 0xC5A0, + 0xD78C, 0xC8F9, 0xD78D, 0xC641, 0xD78E, 0xC642, 0xD78F, 0xC643, 0xD790, 0xC8FA, 0xD791, 0xC644, 0xD792, 0xC645, 0xD793, 0xC646, + 0xD794, 0xC647, 0xD795, 0xC648, 0xD796, 0xC649, 0xD797, 0xC64A, 0xD798, 0xC8FB, 0xD799, 0xC8FC, 0xD79A, 0xC64B, 0xD79B, 0xC8FD, + 0xD79C, 0xC64C, 0xD79D, 0xC8FE, 0xD79E, 0xC64D, 0xD79F, 0xC64E, 0xD7A0, 0xC64F, 0xD7A1, 0xC650, 0xD7A2, 0xC651, 0xD7A3, 0xC652, + 0xF900, 0xCBD0, 0xF901, 0xCBD6, 0xF902, 0xCBE7, 0xF903, 0xCDCF, 0xF904, 0xCDE8, 0xF905, 0xCEAD, 0xF906, 0xCFFB, 0xF907, 0xD0A2, + 0xF908, 0xD0B8, 0xF909, 0xD0D0, 0xF90A, 0xD0DD, 0xF90B, 0xD1D4, 0xF90C, 0xD1D5, 0xF90D, 0xD1D8, 0xF90E, 0xD1DB, 0xF90F, 0xD1DC, + 0xF910, 0xD1DD, 0xF911, 0xD1DE, 0xF912, 0xD1DF, 0xF913, 0xD1E0, 0xF914, 0xD1E2, 0xF915, 0xD1E3, 0xF916, 0xD1E4, 0xF917, 0xD1E5, + 0xF918, 0xD1E6, 0xF919, 0xD1E8, 0xF91A, 0xD1E9, 0xF91B, 0xD1EA, 0xF91C, 0xD1EB, 0xF91D, 0xD1ED, 0xF91E, 0xD1EF, 0xF91F, 0xD1F0, + 0xF920, 0xD1F2, 0xF921, 0xD1F6, 0xF922, 0xD1FA, 0xF923, 0xD1FC, 0xF924, 0xD1FD, 0xF925, 0xD1FE, 0xF926, 0xD2A2, 0xF927, 0xD2A3, + 0xF928, 0xD2A7, 0xF929, 0xD2A8, 0xF92A, 0xD2A9, 0xF92B, 0xD2AA, 0xF92C, 0xD2AB, 0xF92D, 0xD2AD, 0xF92E, 0xD2B2, 0xF92F, 0xD2BE, + 0xF930, 0xD2C2, 0xF931, 0xD2C3, 0xF932, 0xD2C4, 0xF933, 0xD2C6, 0xF934, 0xD2C7, 0xF935, 0xD2C8, 0xF936, 0xD2C9, 0xF937, 0xD2CA, + 0xF938, 0xD2CB, 0xF939, 0xD2CD, 0xF93A, 0xD2CE, 0xF93B, 0xD2CF, 0xF93C, 0xD2D0, 0xF93D, 0xD2D1, 0xF93E, 0xD2D2, 0xF93F, 0xD2D3, + 0xF940, 0xD2D4, 0xF941, 0xD2D5, 0xF942, 0xD2D6, 0xF943, 0xD2D7, 0xF944, 0xD2D9, 0xF945, 0xD2DA, 0xF946, 0xD2DE, 0xF947, 0xD2DF, + 0xF948, 0xD2E1, 0xF949, 0xD2E2, 0xF94A, 0xD2E4, 0xF94B, 0xD2E5, 0xF94C, 0xD2E6, 0xF94D, 0xD2E7, 0xF94E, 0xD2E8, 0xF94F, 0xD2E9, + 0xF950, 0xD2EA, 0xF951, 0xD2EB, 0xF952, 0xD2F0, 0xF953, 0xD2F1, 0xF954, 0xD2F2, 0xF955, 0xD2F3, 0xF956, 0xD2F4, 0xF957, 0xD2F5, + 0xF958, 0xD2F7, 0xF959, 0xD2F8, 0xF95A, 0xD4E6, 0xF95B, 0xD4FC, 0xF95C, 0xD5A5, 0xF95D, 0xD5AB, 0xF95E, 0xD5AE, 0xF95F, 0xD6B8, + 0xF960, 0xD6CD, 0xF961, 0xD7CB, 0xF962, 0xD7E4, 0xF963, 0xDBC5, 0xF964, 0xDBE4, 0xF965, 0xDCA5, 0xF966, 0xDDA5, 0xF967, 0xDDD5, + 0xF968, 0xDDF4, 0xF969, 0xDEFC, 0xF96A, 0xDEFE, 0xF96B, 0xDFB3, 0xF96C, 0xDFE1, 0xF96D, 0xDFE8, 0xF96E, 0xE0F1, 0xF96F, 0xE1AD, + 0xF970, 0xE1ED, 0xF971, 0xE3F5, 0xF972, 0xE4A1, 0xF973, 0xE4A9, 0xF974, 0xE5AE, 0xF975, 0xE5B1, 0xF976, 0xE5B2, 0xF977, 0xE5B9, + 0xF978, 0xE5BB, 0xF979, 0xE5BC, 0xF97A, 0xE5C4, 0xF97B, 0xE5CE, 0xF97C, 0xE5D0, 0xF97D, 0xE5D2, 0xF97E, 0xE5D6, 0xF97F, 0xE5FA, + 0xF980, 0xE5FB, 0xF981, 0xE5FC, 0xF982, 0xE5FE, 0xF983, 0xE6A1, 0xF984, 0xE6A4, 0xF985, 0xE6A7, 0xF986, 0xE6AD, 0xF987, 0xE6AF, + 0xF988, 0xE6B0, 0xF989, 0xE6B1, 0xF98A, 0xE6B3, 0xF98B, 0xE6B7, 0xF98C, 0xE6B8, 0xF98D, 0xE6BC, 0xF98E, 0xE6C4, 0xF98F, 0xE6C6, + 0xF990, 0xE6C7, 0xF991, 0xE6CA, 0xF992, 0xE6D2, 0xF993, 0xE6D6, 0xF994, 0xE6D9, 0xF995, 0xE6DC, 0xF996, 0xE6DF, 0xF997, 0xE6E1, + 0xF998, 0xE6E4, 0xF999, 0xE6E5, 0xF99A, 0xE6E6, 0xF99B, 0xE6E8, 0xF99C, 0xE6EA, 0xF99D, 0xE6EB, 0xF99E, 0xE6EC, 0xF99F, 0xE6EF, + 0xF9A0, 0xE6F1, 0xF9A1, 0xE6F2, 0xF9A2, 0xE6F5, 0xF9A3, 0xE6F6, 0xF9A4, 0xE6F7, 0xF9A5, 0xE6F9, 0xF9A6, 0xE7A1, 0xF9A7, 0xE7A6, + 0xF9A8, 0xE7A9, 0xF9A9, 0xE7AA, 0xF9AA, 0xE7AC, 0xF9AB, 0xE7AD, 0xF9AC, 0xE7B0, 0xF9AD, 0xE7BF, 0xF9AE, 0xE7C1, 0xF9AF, 0xE7C6, + 0xF9B0, 0xE7C7, 0xF9B1, 0xE7CB, 0xF9B2, 0xE7CD, 0xF9B3, 0xE7CF, 0xF9B4, 0xE7D0, 0xF9B5, 0xE7D3, 0xF9B6, 0xE7DF, 0xF9B7, 0xE7E4, + 0xF9B8, 0xE7E6, 0xF9B9, 0xE7F7, 0xF9BA, 0xE8E7, 0xF9BB, 0xE8E8, 0xF9BC, 0xE8F0, 0xF9BD, 0xE8F1, 0xF9BE, 0xE8F7, 0xF9BF, 0xE8F9, + 0xF9C0, 0xE8FB, 0xF9C1, 0xE8FE, 0xF9C2, 0xE9A7, 0xF9C3, 0xE9AC, 0xF9C4, 0xE9CC, 0xF9C5, 0xE9F7, 0xF9C6, 0xEAC1, 0xF9C7, 0xEAE5, + 0xF9C8, 0xEAF4, 0xF9C9, 0xEAF7, 0xF9CA, 0xEAFC, 0xF9CB, 0xEAFE, 0xF9CC, 0xEBA4, 0xF9CD, 0xEBA7, 0xF9CE, 0xEBA9, 0xF9CF, 0xEBAA, + 0xF9D0, 0xEBBA, 0xF9D1, 0xEBBB, 0xF9D2, 0xEBBD, 0xF9D3, 0xEBC1, 0xF9D4, 0xEBC2, 0xF9D5, 0xEBC6, 0xF9D6, 0xEBC7, 0xF9D7, 0xEBCC, + 0xF9D8, 0xEBCF, 0xF9D9, 0xEBD0, 0xF9DA, 0xEBD1, 0xF9DB, 0xEBD2, 0xF9DC, 0xEBD8, 0xF9DD, 0xECA6, 0xF9DE, 0xECA7, 0xF9DF, 0xECAA, + 0xF9E0, 0xECAF, 0xF9E1, 0xECB0, 0xF9E2, 0xECB1, 0xF9E3, 0xECB2, 0xF9E4, 0xECB5, 0xF9E5, 0xECB8, 0xF9E6, 0xECBA, 0xF9E7, 0xECC0, + 0xF9E8, 0xECC1, 0xF9E9, 0xECC5, 0xF9EA, 0xECC6, 0xF9EB, 0xECC9, 0xF9EC, 0xECCA, 0xF9ED, 0xECD5, 0xF9EE, 0xECDD, 0xF9EF, 0xECDE, + 0xF9F0, 0xECE1, 0xF9F1, 0xECE4, 0xF9F2, 0xECE7, 0xF9F3, 0xECE8, 0xF9F4, 0xECF7, 0xF9F5, 0xECF8, 0xF9F6, 0xECFA, 0xF9F7, 0xEDA1, + 0xF9F8, 0xEDA2, 0xF9F9, 0xEDA3, 0xF9FA, 0xEDEE, 0xF9FB, 0xEEDB, 0xF9FC, 0xF2BD, 0xF9FD, 0xF2FA, 0xF9FE, 0xF3B1, 0xF9FF, 0xF4A7, + 0xFA00, 0xF4EE, 0xFA01, 0xF6F4, 0xFA02, 0xF6F6, 0xFA03, 0xF7B8, 0xFA04, 0xF7C8, 0xFA05, 0xF7D3, 0xFA06, 0xF8DB, 0xFA07, 0xF8F0, + 0xFA08, 0xFAA1, 0xFA09, 0xFAA2, 0xFA0A, 0xFAE6, 0xFA0B, 0xFCA9, 0xFF01, 0xA3A1, 0xFF02, 0xA3A2, 0xFF03, 0xA3A3, 0xFF04, 0xA3A4, + 0xFF05, 0xA3A5, 0xFF06, 0xA3A6, 0xFF07, 0xA3A7, 0xFF08, 0xA3A8, 0xFF09, 0xA3A9, 0xFF0A, 0xA3AA, 0xFF0B, 0xA3AB, 0xFF0C, 0xA3AC, + 0xFF0D, 0xA3AD, 0xFF0E, 0xA3AE, 0xFF0F, 0xA3AF, 0xFF10, 0xA3B0, 0xFF11, 0xA3B1, 0xFF12, 0xA3B2, 0xFF13, 0xA3B3, 0xFF14, 0xA3B4, + 0xFF15, 0xA3B5, 0xFF16, 0xA3B6, 0xFF17, 0xA3B7, 0xFF18, 0xA3B8, 0xFF19, 0xA3B9, 0xFF1A, 0xA3BA, 0xFF1B, 0xA3BB, 0xFF1C, 0xA3BC, + 0xFF1D, 0xA3BD, 0xFF1E, 0xA3BE, 0xFF1F, 0xA3BF, 0xFF20, 0xA3C0, 0xFF21, 0xA3C1, 0xFF22, 0xA3C2, 0xFF23, 0xA3C3, 0xFF24, 0xA3C4, + 0xFF25, 0xA3C5, 0xFF26, 0xA3C6, 0xFF27, 0xA3C7, 0xFF28, 0xA3C8, 0xFF29, 0xA3C9, 0xFF2A, 0xA3CA, 0xFF2B, 0xA3CB, 0xFF2C, 0xA3CC, + 0xFF2D, 0xA3CD, 0xFF2E, 0xA3CE, 0xFF2F, 0xA3CF, 0xFF30, 0xA3D0, 0xFF31, 0xA3D1, 0xFF32, 0xA3D2, 0xFF33, 0xA3D3, 0xFF34, 0xA3D4, + 0xFF35, 0xA3D5, 0xFF36, 0xA3D6, 0xFF37, 0xA3D7, 0xFF38, 0xA3D8, 0xFF39, 0xA3D9, 0xFF3A, 0xA3DA, 0xFF3B, 0xA3DB, 0xFF3C, 0xA1AC, + 0xFF3D, 0xA3DD, 0xFF3E, 0xA3DE, 0xFF3F, 0xA3DF, 0xFF40, 0xA3E0, 0xFF41, 0xA3E1, 0xFF42, 0xA3E2, 0xFF43, 0xA3E3, 0xFF44, 0xA3E4, + 0xFF45, 0xA3E5, 0xFF46, 0xA3E6, 0xFF47, 0xA3E7, 0xFF48, 0xA3E8, 0xFF49, 0xA3E9, 0xFF4A, 0xA3EA, 0xFF4B, 0xA3EB, 0xFF4C, 0xA3EC, + 0xFF4D, 0xA3ED, 0xFF4E, 0xA3EE, 0xFF4F, 0xA3EF, 0xFF50, 0xA3F0, 0xFF51, 0xA3F1, 0xFF52, 0xA3F2, 0xFF53, 0xA3F3, 0xFF54, 0xA3F4, + 0xFF55, 0xA3F5, 0xFF56, 0xA3F6, 0xFF57, 0xA3F7, 0xFF58, 0xA3F8, 0xFF59, 0xA3F9, 0xFF5A, 0xA3FA, 0xFF5B, 0xA3FB, 0xFF5C, 0xA3FC, + 0xFF5D, 0xA3FD, 0xFF5E, 0xA2A6, 0xFFE0, 0xA1CB, 0xFFE1, 0xA1CC, 0xFFE2, 0xA1FE, 0xFFE3, 0xA3FE, 0xFFE5, 0xA1CD, 0xFFE6, 0xA3DC, + 0, 0 +}; + +static const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */ + 0x8141, 0xAC02, 0x8142, 0xAC03, 0x8143, 0xAC05, 0x8144, 0xAC06, 0x8145, 0xAC0B, 0x8146, 0xAC0C, 0x8147, 0xAC0D, 0x8148, 0xAC0E, + 0x8149, 0xAC0F, 0x814A, 0xAC18, 0x814B, 0xAC1E, 0x814C, 0xAC1F, 0x814D, 0xAC21, 0x814E, 0xAC22, 0x814F, 0xAC23, 0x8150, 0xAC25, + 0x8151, 0xAC26, 0x8152, 0xAC27, 0x8153, 0xAC28, 0x8154, 0xAC29, 0x8155, 0xAC2A, 0x8156, 0xAC2B, 0x8157, 0xAC2E, 0x8158, 0xAC32, + 0x8159, 0xAC33, 0x815A, 0xAC34, 0x8161, 0xAC35, 0x8162, 0xAC36, 0x8163, 0xAC37, 0x8164, 0xAC3A, 0x8165, 0xAC3B, 0x8166, 0xAC3D, + 0x8167, 0xAC3E, 0x8168, 0xAC3F, 0x8169, 0xAC41, 0x816A, 0xAC42, 0x816B, 0xAC43, 0x816C, 0xAC44, 0x816D, 0xAC45, 0x816E, 0xAC46, + 0x816F, 0xAC47, 0x8170, 0xAC48, 0x8171, 0xAC49, 0x8172, 0xAC4A, 0x8173, 0xAC4C, 0x8174, 0xAC4E, 0x8175, 0xAC4F, 0x8176, 0xAC50, + 0x8177, 0xAC51, 0x8178, 0xAC52, 0x8179, 0xAC53, 0x817A, 0xAC55, 0x8181, 0xAC56, 0x8182, 0xAC57, 0x8183, 0xAC59, 0x8184, 0xAC5A, + 0x8185, 0xAC5B, 0x8186, 0xAC5D, 0x8187, 0xAC5E, 0x8188, 0xAC5F, 0x8189, 0xAC60, 0x818A, 0xAC61, 0x818B, 0xAC62, 0x818C, 0xAC63, + 0x818D, 0xAC64, 0x818E, 0xAC65, 0x818F, 0xAC66, 0x8190, 0xAC67, 0x8191, 0xAC68, 0x8192, 0xAC69, 0x8193, 0xAC6A, 0x8194, 0xAC6B, + 0x8195, 0xAC6C, 0x8196, 0xAC6D, 0x8197, 0xAC6E, 0x8198, 0xAC6F, 0x8199, 0xAC72, 0x819A, 0xAC73, 0x819B, 0xAC75, 0x819C, 0xAC76, + 0x819D, 0xAC79, 0x819E, 0xAC7B, 0x819F, 0xAC7C, 0x81A0, 0xAC7D, 0x81A1, 0xAC7E, 0x81A2, 0xAC7F, 0x81A3, 0xAC82, 0x81A4, 0xAC87, + 0x81A5, 0xAC88, 0x81A6, 0xAC8D, 0x81A7, 0xAC8E, 0x81A8, 0xAC8F, 0x81A9, 0xAC91, 0x81AA, 0xAC92, 0x81AB, 0xAC93, 0x81AC, 0xAC95, + 0x81AD, 0xAC96, 0x81AE, 0xAC97, 0x81AF, 0xAC98, 0x81B0, 0xAC99, 0x81B1, 0xAC9A, 0x81B2, 0xAC9B, 0x81B3, 0xAC9E, 0x81B4, 0xACA2, + 0x81B5, 0xACA3, 0x81B6, 0xACA4, 0x81B7, 0xACA5, 0x81B8, 0xACA6, 0x81B9, 0xACA7, 0x81BA, 0xACAB, 0x81BB, 0xACAD, 0x81BC, 0xACAE, + 0x81BD, 0xACB1, 0x81BE, 0xACB2, 0x81BF, 0xACB3, 0x81C0, 0xACB4, 0x81C1, 0xACB5, 0x81C2, 0xACB6, 0x81C3, 0xACB7, 0x81C4, 0xACBA, + 0x81C5, 0xACBE, 0x81C6, 0xACBF, 0x81C7, 0xACC0, 0x81C8, 0xACC2, 0x81C9, 0xACC3, 0x81CA, 0xACC5, 0x81CB, 0xACC6, 0x81CC, 0xACC7, + 0x81CD, 0xACC9, 0x81CE, 0xACCA, 0x81CF, 0xACCB, 0x81D0, 0xACCD, 0x81D1, 0xACCE, 0x81D2, 0xACCF, 0x81D3, 0xACD0, 0x81D4, 0xACD1, + 0x81D5, 0xACD2, 0x81D6, 0xACD3, 0x81D7, 0xACD4, 0x81D8, 0xACD6, 0x81D9, 0xACD8, 0x81DA, 0xACD9, 0x81DB, 0xACDA, 0x81DC, 0xACDB, + 0x81DD, 0xACDC, 0x81DE, 0xACDD, 0x81DF, 0xACDE, 0x81E0, 0xACDF, 0x81E1, 0xACE2, 0x81E2, 0xACE3, 0x81E3, 0xACE5, 0x81E4, 0xACE6, + 0x81E5, 0xACE9, 0x81E6, 0xACEB, 0x81E7, 0xACED, 0x81E8, 0xACEE, 0x81E9, 0xACF2, 0x81EA, 0xACF4, 0x81EB, 0xACF7, 0x81EC, 0xACF8, + 0x81ED, 0xACF9, 0x81EE, 0xACFA, 0x81EF, 0xACFB, 0x81F0, 0xACFE, 0x81F1, 0xACFF, 0x81F2, 0xAD01, 0x81F3, 0xAD02, 0x81F4, 0xAD03, + 0x81F5, 0xAD05, 0x81F6, 0xAD07, 0x81F7, 0xAD08, 0x81F8, 0xAD09, 0x81F9, 0xAD0A, 0x81FA, 0xAD0B, 0x81FB, 0xAD0E, 0x81FC, 0xAD10, + 0x81FD, 0xAD12, 0x81FE, 0xAD13, 0x8241, 0xAD14, 0x8242, 0xAD15, 0x8243, 0xAD16, 0x8244, 0xAD17, 0x8245, 0xAD19, 0x8246, 0xAD1A, + 0x8247, 0xAD1B, 0x8248, 0xAD1D, 0x8249, 0xAD1E, 0x824A, 0xAD1F, 0x824B, 0xAD21, 0x824C, 0xAD22, 0x824D, 0xAD23, 0x824E, 0xAD24, + 0x824F, 0xAD25, 0x8250, 0xAD26, 0x8251, 0xAD27, 0x8252, 0xAD28, 0x8253, 0xAD2A, 0x8254, 0xAD2B, 0x8255, 0xAD2E, 0x8256, 0xAD2F, + 0x8257, 0xAD30, 0x8258, 0xAD31, 0x8259, 0xAD32, 0x825A, 0xAD33, 0x8261, 0xAD36, 0x8262, 0xAD37, 0x8263, 0xAD39, 0x8264, 0xAD3A, + 0x8265, 0xAD3B, 0x8266, 0xAD3D, 0x8267, 0xAD3E, 0x8268, 0xAD3F, 0x8269, 0xAD40, 0x826A, 0xAD41, 0x826B, 0xAD42, 0x826C, 0xAD43, + 0x826D, 0xAD46, 0x826E, 0xAD48, 0x826F, 0xAD4A, 0x8270, 0xAD4B, 0x8271, 0xAD4C, 0x8272, 0xAD4D, 0x8273, 0xAD4E, 0x8274, 0xAD4F, + 0x8275, 0xAD51, 0x8276, 0xAD52, 0x8277, 0xAD53, 0x8278, 0xAD55, 0x8279, 0xAD56, 0x827A, 0xAD57, 0x8281, 0xAD59, 0x8282, 0xAD5A, + 0x8283, 0xAD5B, 0x8284, 0xAD5C, 0x8285, 0xAD5D, 0x8286, 0xAD5E, 0x8287, 0xAD5F, 0x8288, 0xAD60, 0x8289, 0xAD62, 0x828A, 0xAD64, + 0x828B, 0xAD65, 0x828C, 0xAD66, 0x828D, 0xAD67, 0x828E, 0xAD68, 0x828F, 0xAD69, 0x8290, 0xAD6A, 0x8291, 0xAD6B, 0x8292, 0xAD6E, + 0x8293, 0xAD6F, 0x8294, 0xAD71, 0x8295, 0xAD72, 0x8296, 0xAD77, 0x8297, 0xAD78, 0x8298, 0xAD79, 0x8299, 0xAD7A, 0x829A, 0xAD7E, + 0x829B, 0xAD80, 0x829C, 0xAD83, 0x829D, 0xAD84, 0x829E, 0xAD85, 0x829F, 0xAD86, 0x82A0, 0xAD87, 0x82A1, 0xAD8A, 0x82A2, 0xAD8B, + 0x82A3, 0xAD8D, 0x82A4, 0xAD8E, 0x82A5, 0xAD8F, 0x82A6, 0xAD91, 0x82A7, 0xAD92, 0x82A8, 0xAD93, 0x82A9, 0xAD94, 0x82AA, 0xAD95, + 0x82AB, 0xAD96, 0x82AC, 0xAD97, 0x82AD, 0xAD98, 0x82AE, 0xAD99, 0x82AF, 0xAD9A, 0x82B0, 0xAD9B, 0x82B1, 0xAD9E, 0x82B2, 0xAD9F, + 0x82B3, 0xADA0, 0x82B4, 0xADA1, 0x82B5, 0xADA2, 0x82B6, 0xADA3, 0x82B7, 0xADA5, 0x82B8, 0xADA6, 0x82B9, 0xADA7, 0x82BA, 0xADA8, + 0x82BB, 0xADA9, 0x82BC, 0xADAA, 0x82BD, 0xADAB, 0x82BE, 0xADAC, 0x82BF, 0xADAD, 0x82C0, 0xADAE, 0x82C1, 0xADAF, 0x82C2, 0xADB0, + 0x82C3, 0xADB1, 0x82C4, 0xADB2, 0x82C5, 0xADB3, 0x82C6, 0xADB4, 0x82C7, 0xADB5, 0x82C8, 0xADB6, 0x82C9, 0xADB8, 0x82CA, 0xADB9, + 0x82CB, 0xADBA, 0x82CC, 0xADBB, 0x82CD, 0xADBC, 0x82CE, 0xADBD, 0x82CF, 0xADBE, 0x82D0, 0xADBF, 0x82D1, 0xADC2, 0x82D2, 0xADC3, + 0x82D3, 0xADC5, 0x82D4, 0xADC6, 0x82D5, 0xADC7, 0x82D6, 0xADC9, 0x82D7, 0xADCA, 0x82D8, 0xADCB, 0x82D9, 0xADCC, 0x82DA, 0xADCD, + 0x82DB, 0xADCE, 0x82DC, 0xADCF, 0x82DD, 0xADD2, 0x82DE, 0xADD4, 0x82DF, 0xADD5, 0x82E0, 0xADD6, 0x82E1, 0xADD7, 0x82E2, 0xADD8, + 0x82E3, 0xADD9, 0x82E4, 0xADDA, 0x82E5, 0xADDB, 0x82E6, 0xADDD, 0x82E7, 0xADDE, 0x82E8, 0xADDF, 0x82E9, 0xADE1, 0x82EA, 0xADE2, + 0x82EB, 0xADE3, 0x82EC, 0xADE5, 0x82ED, 0xADE6, 0x82EE, 0xADE7, 0x82EF, 0xADE8, 0x82F0, 0xADE9, 0x82F1, 0xADEA, 0x82F2, 0xADEB, + 0x82F3, 0xADEC, 0x82F4, 0xADED, 0x82F5, 0xADEE, 0x82F6, 0xADEF, 0x82F7, 0xADF0, 0x82F8, 0xADF1, 0x82F9, 0xADF2, 0x82FA, 0xADF3, + 0x82FB, 0xADF4, 0x82FC, 0xADF5, 0x82FD, 0xADF6, 0x82FE, 0xADF7, 0x8341, 0xADFA, 0x8342, 0xADFB, 0x8343, 0xADFD, 0x8344, 0xADFE, + 0x8345, 0xAE02, 0x8346, 0xAE03, 0x8347, 0xAE04, 0x8348, 0xAE05, 0x8349, 0xAE06, 0x834A, 0xAE07, 0x834B, 0xAE0A, 0x834C, 0xAE0C, + 0x834D, 0xAE0E, 0x834E, 0xAE0F, 0x834F, 0xAE10, 0x8350, 0xAE11, 0x8351, 0xAE12, 0x8352, 0xAE13, 0x8353, 0xAE15, 0x8354, 0xAE16, + 0x8355, 0xAE17, 0x8356, 0xAE18, 0x8357, 0xAE19, 0x8358, 0xAE1A, 0x8359, 0xAE1B, 0x835A, 0xAE1C, 0x8361, 0xAE1D, 0x8362, 0xAE1E, + 0x8363, 0xAE1F, 0x8364, 0xAE20, 0x8365, 0xAE21, 0x8366, 0xAE22, 0x8367, 0xAE23, 0x8368, 0xAE24, 0x8369, 0xAE25, 0x836A, 0xAE26, + 0x836B, 0xAE27, 0x836C, 0xAE28, 0x836D, 0xAE29, 0x836E, 0xAE2A, 0x836F, 0xAE2B, 0x8370, 0xAE2C, 0x8371, 0xAE2D, 0x8372, 0xAE2E, + 0x8373, 0xAE2F, 0x8374, 0xAE32, 0x8375, 0xAE33, 0x8376, 0xAE35, 0x8377, 0xAE36, 0x8378, 0xAE39, 0x8379, 0xAE3B, 0x837A, 0xAE3C, + 0x8381, 0xAE3D, 0x8382, 0xAE3E, 0x8383, 0xAE3F, 0x8384, 0xAE42, 0x8385, 0xAE44, 0x8386, 0xAE47, 0x8387, 0xAE48, 0x8388, 0xAE49, + 0x8389, 0xAE4B, 0x838A, 0xAE4F, 0x838B, 0xAE51, 0x838C, 0xAE52, 0x838D, 0xAE53, 0x838E, 0xAE55, 0x838F, 0xAE57, 0x8390, 0xAE58, + 0x8391, 0xAE59, 0x8392, 0xAE5A, 0x8393, 0xAE5B, 0x8394, 0xAE5E, 0x8395, 0xAE62, 0x8396, 0xAE63, 0x8397, 0xAE64, 0x8398, 0xAE66, + 0x8399, 0xAE67, 0x839A, 0xAE6A, 0x839B, 0xAE6B, 0x839C, 0xAE6D, 0x839D, 0xAE6E, 0x839E, 0xAE6F, 0x839F, 0xAE71, 0x83A0, 0xAE72, + 0x83A1, 0xAE73, 0x83A2, 0xAE74, 0x83A3, 0xAE75, 0x83A4, 0xAE76, 0x83A5, 0xAE77, 0x83A6, 0xAE7A, 0x83A7, 0xAE7E, 0x83A8, 0xAE7F, + 0x83A9, 0xAE80, 0x83AA, 0xAE81, 0x83AB, 0xAE82, 0x83AC, 0xAE83, 0x83AD, 0xAE86, 0x83AE, 0xAE87, 0x83AF, 0xAE88, 0x83B0, 0xAE89, + 0x83B1, 0xAE8A, 0x83B2, 0xAE8B, 0x83B3, 0xAE8D, 0x83B4, 0xAE8E, 0x83B5, 0xAE8F, 0x83B6, 0xAE90, 0x83B7, 0xAE91, 0x83B8, 0xAE92, + 0x83B9, 0xAE93, 0x83BA, 0xAE94, 0x83BB, 0xAE95, 0x83BC, 0xAE96, 0x83BD, 0xAE97, 0x83BE, 0xAE98, 0x83BF, 0xAE99, 0x83C0, 0xAE9A, + 0x83C1, 0xAE9B, 0x83C2, 0xAE9C, 0x83C3, 0xAE9D, 0x83C4, 0xAE9E, 0x83C5, 0xAE9F, 0x83C6, 0xAEA0, 0x83C7, 0xAEA1, 0x83C8, 0xAEA2, + 0x83C9, 0xAEA3, 0x83CA, 0xAEA4, 0x83CB, 0xAEA5, 0x83CC, 0xAEA6, 0x83CD, 0xAEA7, 0x83CE, 0xAEA8, 0x83CF, 0xAEA9, 0x83D0, 0xAEAA, + 0x83D1, 0xAEAB, 0x83D2, 0xAEAC, 0x83D3, 0xAEAD, 0x83D4, 0xAEAE, 0x83D5, 0xAEAF, 0x83D6, 0xAEB0, 0x83D7, 0xAEB1, 0x83D8, 0xAEB2, + 0x83D9, 0xAEB3, 0x83DA, 0xAEB4, 0x83DB, 0xAEB5, 0x83DC, 0xAEB6, 0x83DD, 0xAEB7, 0x83DE, 0xAEB8, 0x83DF, 0xAEB9, 0x83E0, 0xAEBA, + 0x83E1, 0xAEBB, 0x83E2, 0xAEBF, 0x83E3, 0xAEC1, 0x83E4, 0xAEC2, 0x83E5, 0xAEC3, 0x83E6, 0xAEC5, 0x83E7, 0xAEC6, 0x83E8, 0xAEC7, + 0x83E9, 0xAEC8, 0x83EA, 0xAEC9, 0x83EB, 0xAECA, 0x83EC, 0xAECB, 0x83ED, 0xAECE, 0x83EE, 0xAED2, 0x83EF, 0xAED3, 0x83F0, 0xAED4, + 0x83F1, 0xAED5, 0x83F2, 0xAED6, 0x83F3, 0xAED7, 0x83F4, 0xAEDA, 0x83F5, 0xAEDB, 0x83F6, 0xAEDD, 0x83F7, 0xAEDE, 0x83F8, 0xAEDF, + 0x83F9, 0xAEE0, 0x83FA, 0xAEE1, 0x83FB, 0xAEE2, 0x83FC, 0xAEE3, 0x83FD, 0xAEE4, 0x83FE, 0xAEE5, 0x8441, 0xAEE6, 0x8442, 0xAEE7, + 0x8443, 0xAEE9, 0x8444, 0xAEEA, 0x8445, 0xAEEC, 0x8446, 0xAEEE, 0x8447, 0xAEEF, 0x8448, 0xAEF0, 0x8449, 0xAEF1, 0x844A, 0xAEF2, + 0x844B, 0xAEF3, 0x844C, 0xAEF5, 0x844D, 0xAEF6, 0x844E, 0xAEF7, 0x844F, 0xAEF9, 0x8450, 0xAEFA, 0x8451, 0xAEFB, 0x8452, 0xAEFD, + 0x8453, 0xAEFE, 0x8454, 0xAEFF, 0x8455, 0xAF00, 0x8456, 0xAF01, 0x8457, 0xAF02, 0x8458, 0xAF03, 0x8459, 0xAF04, 0x845A, 0xAF05, + 0x8461, 0xAF06, 0x8462, 0xAF09, 0x8463, 0xAF0A, 0x8464, 0xAF0B, 0x8465, 0xAF0C, 0x8466, 0xAF0E, 0x8467, 0xAF0F, 0x8468, 0xAF11, + 0x8469, 0xAF12, 0x846A, 0xAF13, 0x846B, 0xAF14, 0x846C, 0xAF15, 0x846D, 0xAF16, 0x846E, 0xAF17, 0x846F, 0xAF18, 0x8470, 0xAF19, + 0x8471, 0xAF1A, 0x8472, 0xAF1B, 0x8473, 0xAF1C, 0x8474, 0xAF1D, 0x8475, 0xAF1E, 0x8476, 0xAF1F, 0x8477, 0xAF20, 0x8478, 0xAF21, + 0x8479, 0xAF22, 0x847A, 0xAF23, 0x8481, 0xAF24, 0x8482, 0xAF25, 0x8483, 0xAF26, 0x8484, 0xAF27, 0x8485, 0xAF28, 0x8486, 0xAF29, + 0x8487, 0xAF2A, 0x8488, 0xAF2B, 0x8489, 0xAF2E, 0x848A, 0xAF2F, 0x848B, 0xAF31, 0x848C, 0xAF33, 0x848D, 0xAF35, 0x848E, 0xAF36, + 0x848F, 0xAF37, 0x8490, 0xAF38, 0x8491, 0xAF39, 0x8492, 0xAF3A, 0x8493, 0xAF3B, 0x8494, 0xAF3E, 0x8495, 0xAF40, 0x8496, 0xAF44, + 0x8497, 0xAF45, 0x8498, 0xAF46, 0x8499, 0xAF47, 0x849A, 0xAF4A, 0x849B, 0xAF4B, 0x849C, 0xAF4C, 0x849D, 0xAF4D, 0x849E, 0xAF4E, + 0x849F, 0xAF4F, 0x84A0, 0xAF51, 0x84A1, 0xAF52, 0x84A2, 0xAF53, 0x84A3, 0xAF54, 0x84A4, 0xAF55, 0x84A5, 0xAF56, 0x84A6, 0xAF57, + 0x84A7, 0xAF58, 0x84A8, 0xAF59, 0x84A9, 0xAF5A, 0x84AA, 0xAF5B, 0x84AB, 0xAF5E, 0x84AC, 0xAF5F, 0x84AD, 0xAF60, 0x84AE, 0xAF61, + 0x84AF, 0xAF62, 0x84B0, 0xAF63, 0x84B1, 0xAF66, 0x84B2, 0xAF67, 0x84B3, 0xAF68, 0x84B4, 0xAF69, 0x84B5, 0xAF6A, 0x84B6, 0xAF6B, + 0x84B7, 0xAF6C, 0x84B8, 0xAF6D, 0x84B9, 0xAF6E, 0x84BA, 0xAF6F, 0x84BB, 0xAF70, 0x84BC, 0xAF71, 0x84BD, 0xAF72, 0x84BE, 0xAF73, + 0x84BF, 0xAF74, 0x84C0, 0xAF75, 0x84C1, 0xAF76, 0x84C2, 0xAF77, 0x84C3, 0xAF78, 0x84C4, 0xAF7A, 0x84C5, 0xAF7B, 0x84C6, 0xAF7C, + 0x84C7, 0xAF7D, 0x84C8, 0xAF7E, 0x84C9, 0xAF7F, 0x84CA, 0xAF81, 0x84CB, 0xAF82, 0x84CC, 0xAF83, 0x84CD, 0xAF85, 0x84CE, 0xAF86, + 0x84CF, 0xAF87, 0x84D0, 0xAF89, 0x84D1, 0xAF8A, 0x84D2, 0xAF8B, 0x84D3, 0xAF8C, 0x84D4, 0xAF8D, 0x84D5, 0xAF8E, 0x84D6, 0xAF8F, + 0x84D7, 0xAF92, 0x84D8, 0xAF93, 0x84D9, 0xAF94, 0x84DA, 0xAF96, 0x84DB, 0xAF97, 0x84DC, 0xAF98, 0x84DD, 0xAF99, 0x84DE, 0xAF9A, + 0x84DF, 0xAF9B, 0x84E0, 0xAF9D, 0x84E1, 0xAF9E, 0x84E2, 0xAF9F, 0x84E3, 0xAFA0, 0x84E4, 0xAFA1, 0x84E5, 0xAFA2, 0x84E6, 0xAFA3, + 0x84E7, 0xAFA4, 0x84E8, 0xAFA5, 0x84E9, 0xAFA6, 0x84EA, 0xAFA7, 0x84EB, 0xAFA8, 0x84EC, 0xAFA9, 0x84ED, 0xAFAA, 0x84EE, 0xAFAB, + 0x84EF, 0xAFAC, 0x84F0, 0xAFAD, 0x84F1, 0xAFAE, 0x84F2, 0xAFAF, 0x84F3, 0xAFB0, 0x84F4, 0xAFB1, 0x84F5, 0xAFB2, 0x84F6, 0xAFB3, + 0x84F7, 0xAFB4, 0x84F8, 0xAFB5, 0x84F9, 0xAFB6, 0x84FA, 0xAFB7, 0x84FB, 0xAFBA, 0x84FC, 0xAFBB, 0x84FD, 0xAFBD, 0x84FE, 0xAFBE, + 0x8541, 0xAFBF, 0x8542, 0xAFC1, 0x8543, 0xAFC2, 0x8544, 0xAFC3, 0x8545, 0xAFC4, 0x8546, 0xAFC5, 0x8547, 0xAFC6, 0x8548, 0xAFCA, + 0x8549, 0xAFCC, 0x854A, 0xAFCF, 0x854B, 0xAFD0, 0x854C, 0xAFD1, 0x854D, 0xAFD2, 0x854E, 0xAFD3, 0x854F, 0xAFD5, 0x8550, 0xAFD6, + 0x8551, 0xAFD7, 0x8552, 0xAFD8, 0x8553, 0xAFD9, 0x8554, 0xAFDA, 0x8555, 0xAFDB, 0x8556, 0xAFDD, 0x8557, 0xAFDE, 0x8558, 0xAFDF, + 0x8559, 0xAFE0, 0x855A, 0xAFE1, 0x8561, 0xAFE2, 0x8562, 0xAFE3, 0x8563, 0xAFE4, 0x8564, 0xAFE5, 0x8565, 0xAFE6, 0x8566, 0xAFE7, + 0x8567, 0xAFEA, 0x8568, 0xAFEB, 0x8569, 0xAFEC, 0x856A, 0xAFED, 0x856B, 0xAFEE, 0x856C, 0xAFEF, 0x856D, 0xAFF2, 0x856E, 0xAFF3, + 0x856F, 0xAFF5, 0x8570, 0xAFF6, 0x8571, 0xAFF7, 0x8572, 0xAFF9, 0x8573, 0xAFFA, 0x8574, 0xAFFB, 0x8575, 0xAFFC, 0x8576, 0xAFFD, + 0x8577, 0xAFFE, 0x8578, 0xAFFF, 0x8579, 0xB002, 0x857A, 0xB003, 0x8581, 0xB005, 0x8582, 0xB006, 0x8583, 0xB007, 0x8584, 0xB008, + 0x8585, 0xB009, 0x8586, 0xB00A, 0x8587, 0xB00B, 0x8588, 0xB00D, 0x8589, 0xB00E, 0x858A, 0xB00F, 0x858B, 0xB011, 0x858C, 0xB012, + 0x858D, 0xB013, 0x858E, 0xB015, 0x858F, 0xB016, 0x8590, 0xB017, 0x8591, 0xB018, 0x8592, 0xB019, 0x8593, 0xB01A, 0x8594, 0xB01B, + 0x8595, 0xB01E, 0x8596, 0xB01F, 0x8597, 0xB020, 0x8598, 0xB021, 0x8599, 0xB022, 0x859A, 0xB023, 0x859B, 0xB024, 0x859C, 0xB025, + 0x859D, 0xB026, 0x859E, 0xB027, 0x859F, 0xB029, 0x85A0, 0xB02A, 0x85A1, 0xB02B, 0x85A2, 0xB02C, 0x85A3, 0xB02D, 0x85A4, 0xB02E, + 0x85A5, 0xB02F, 0x85A6, 0xB030, 0x85A7, 0xB031, 0x85A8, 0xB032, 0x85A9, 0xB033, 0x85AA, 0xB034, 0x85AB, 0xB035, 0x85AC, 0xB036, + 0x85AD, 0xB037, 0x85AE, 0xB038, 0x85AF, 0xB039, 0x85B0, 0xB03A, 0x85B1, 0xB03B, 0x85B2, 0xB03C, 0x85B3, 0xB03D, 0x85B4, 0xB03E, + 0x85B5, 0xB03F, 0x85B6, 0xB040, 0x85B7, 0xB041, 0x85B8, 0xB042, 0x85B9, 0xB043, 0x85BA, 0xB046, 0x85BB, 0xB047, 0x85BC, 0xB049, + 0x85BD, 0xB04B, 0x85BE, 0xB04D, 0x85BF, 0xB04F, 0x85C0, 0xB050, 0x85C1, 0xB051, 0x85C2, 0xB052, 0x85C3, 0xB056, 0x85C4, 0xB058, + 0x85C5, 0xB05A, 0x85C6, 0xB05B, 0x85C7, 0xB05C, 0x85C8, 0xB05E, 0x85C9, 0xB05F, 0x85CA, 0xB060, 0x85CB, 0xB061, 0x85CC, 0xB062, + 0x85CD, 0xB063, 0x85CE, 0xB064, 0x85CF, 0xB065, 0x85D0, 0xB066, 0x85D1, 0xB067, 0x85D2, 0xB068, 0x85D3, 0xB069, 0x85D4, 0xB06A, + 0x85D5, 0xB06B, 0x85D6, 0xB06C, 0x85D7, 0xB06D, 0x85D8, 0xB06E, 0x85D9, 0xB06F, 0x85DA, 0xB070, 0x85DB, 0xB071, 0x85DC, 0xB072, + 0x85DD, 0xB073, 0x85DE, 0xB074, 0x85DF, 0xB075, 0x85E0, 0xB076, 0x85E1, 0xB077, 0x85E2, 0xB078, 0x85E3, 0xB079, 0x85E4, 0xB07A, + 0x85E5, 0xB07B, 0x85E6, 0xB07E, 0x85E7, 0xB07F, 0x85E8, 0xB081, 0x85E9, 0xB082, 0x85EA, 0xB083, 0x85EB, 0xB085, 0x85EC, 0xB086, + 0x85ED, 0xB087, 0x85EE, 0xB088, 0x85EF, 0xB089, 0x85F0, 0xB08A, 0x85F1, 0xB08B, 0x85F2, 0xB08E, 0x85F3, 0xB090, 0x85F4, 0xB092, + 0x85F5, 0xB093, 0x85F6, 0xB094, 0x85F7, 0xB095, 0x85F8, 0xB096, 0x85F9, 0xB097, 0x85FA, 0xB09B, 0x85FB, 0xB09D, 0x85FC, 0xB09E, + 0x85FD, 0xB0A3, 0x85FE, 0xB0A4, 0x8641, 0xB0A5, 0x8642, 0xB0A6, 0x8643, 0xB0A7, 0x8644, 0xB0AA, 0x8645, 0xB0B0, 0x8646, 0xB0B2, + 0x8647, 0xB0B6, 0x8648, 0xB0B7, 0x8649, 0xB0B9, 0x864A, 0xB0BA, 0x864B, 0xB0BB, 0x864C, 0xB0BD, 0x864D, 0xB0BE, 0x864E, 0xB0BF, + 0x864F, 0xB0C0, 0x8650, 0xB0C1, 0x8651, 0xB0C2, 0x8652, 0xB0C3, 0x8653, 0xB0C6, 0x8654, 0xB0CA, 0x8655, 0xB0CB, 0x8656, 0xB0CC, + 0x8657, 0xB0CD, 0x8658, 0xB0CE, 0x8659, 0xB0CF, 0x865A, 0xB0D2, 0x8661, 0xB0D3, 0x8662, 0xB0D5, 0x8663, 0xB0D6, 0x8664, 0xB0D7, + 0x8665, 0xB0D9, 0x8666, 0xB0DA, 0x8667, 0xB0DB, 0x8668, 0xB0DC, 0x8669, 0xB0DD, 0x866A, 0xB0DE, 0x866B, 0xB0DF, 0x866C, 0xB0E1, + 0x866D, 0xB0E2, 0x866E, 0xB0E3, 0x866F, 0xB0E4, 0x8670, 0xB0E6, 0x8671, 0xB0E7, 0x8672, 0xB0E8, 0x8673, 0xB0E9, 0x8674, 0xB0EA, + 0x8675, 0xB0EB, 0x8676, 0xB0EC, 0x8677, 0xB0ED, 0x8678, 0xB0EE, 0x8679, 0xB0EF, 0x867A, 0xB0F0, 0x8681, 0xB0F1, 0x8682, 0xB0F2, + 0x8683, 0xB0F3, 0x8684, 0xB0F4, 0x8685, 0xB0F5, 0x8686, 0xB0F6, 0x8687, 0xB0F7, 0x8688, 0xB0F8, 0x8689, 0xB0F9, 0x868A, 0xB0FA, + 0x868B, 0xB0FB, 0x868C, 0xB0FC, 0x868D, 0xB0FD, 0x868E, 0xB0FE, 0x868F, 0xB0FF, 0x8690, 0xB100, 0x8691, 0xB101, 0x8692, 0xB102, + 0x8693, 0xB103, 0x8694, 0xB104, 0x8695, 0xB105, 0x8696, 0xB106, 0x8697, 0xB107, 0x8698, 0xB10A, 0x8699, 0xB10D, 0x869A, 0xB10E, + 0x869B, 0xB10F, 0x869C, 0xB111, 0x869D, 0xB114, 0x869E, 0xB115, 0x869F, 0xB116, 0x86A0, 0xB117, 0x86A1, 0xB11A, 0x86A2, 0xB11E, + 0x86A3, 0xB11F, 0x86A4, 0xB120, 0x86A5, 0xB121, 0x86A6, 0xB122, 0x86A7, 0xB126, 0x86A8, 0xB127, 0x86A9, 0xB129, 0x86AA, 0xB12A, + 0x86AB, 0xB12B, 0x86AC, 0xB12D, 0x86AD, 0xB12E, 0x86AE, 0xB12F, 0x86AF, 0xB130, 0x86B0, 0xB131, 0x86B1, 0xB132, 0x86B2, 0xB133, + 0x86B3, 0xB136, 0x86B4, 0xB13A, 0x86B5, 0xB13B, 0x86B6, 0xB13C, 0x86B7, 0xB13D, 0x86B8, 0xB13E, 0x86B9, 0xB13F, 0x86BA, 0xB142, + 0x86BB, 0xB143, 0x86BC, 0xB145, 0x86BD, 0xB146, 0x86BE, 0xB147, 0x86BF, 0xB149, 0x86C0, 0xB14A, 0x86C1, 0xB14B, 0x86C2, 0xB14C, + 0x86C3, 0xB14D, 0x86C4, 0xB14E, 0x86C5, 0xB14F, 0x86C6, 0xB152, 0x86C7, 0xB153, 0x86C8, 0xB156, 0x86C9, 0xB157, 0x86CA, 0xB159, + 0x86CB, 0xB15A, 0x86CC, 0xB15B, 0x86CD, 0xB15D, 0x86CE, 0xB15E, 0x86CF, 0xB15F, 0x86D0, 0xB161, 0x86D1, 0xB162, 0x86D2, 0xB163, + 0x86D3, 0xB164, 0x86D4, 0xB165, 0x86D5, 0xB166, 0x86D6, 0xB167, 0x86D7, 0xB168, 0x86D8, 0xB169, 0x86D9, 0xB16A, 0x86DA, 0xB16B, + 0x86DB, 0xB16C, 0x86DC, 0xB16D, 0x86DD, 0xB16E, 0x86DE, 0xB16F, 0x86DF, 0xB170, 0x86E0, 0xB171, 0x86E1, 0xB172, 0x86E2, 0xB173, + 0x86E3, 0xB174, 0x86E4, 0xB175, 0x86E5, 0xB176, 0x86E6, 0xB177, 0x86E7, 0xB17A, 0x86E8, 0xB17B, 0x86E9, 0xB17D, 0x86EA, 0xB17E, + 0x86EB, 0xB17F, 0x86EC, 0xB181, 0x86ED, 0xB183, 0x86EE, 0xB184, 0x86EF, 0xB185, 0x86F0, 0xB186, 0x86F1, 0xB187, 0x86F2, 0xB18A, + 0x86F3, 0xB18C, 0x86F4, 0xB18E, 0x86F5, 0xB18F, 0x86F6, 0xB190, 0x86F7, 0xB191, 0x86F8, 0xB195, 0x86F9, 0xB196, 0x86FA, 0xB197, + 0x86FB, 0xB199, 0x86FC, 0xB19A, 0x86FD, 0xB19B, 0x86FE, 0xB19D, 0x8741, 0xB19E, 0x8742, 0xB19F, 0x8743, 0xB1A0, 0x8744, 0xB1A1, + 0x8745, 0xB1A2, 0x8746, 0xB1A3, 0x8747, 0xB1A4, 0x8748, 0xB1A5, 0x8749, 0xB1A6, 0x874A, 0xB1A7, 0x874B, 0xB1A9, 0x874C, 0xB1AA, + 0x874D, 0xB1AB, 0x874E, 0xB1AC, 0x874F, 0xB1AD, 0x8750, 0xB1AE, 0x8751, 0xB1AF, 0x8752, 0xB1B0, 0x8753, 0xB1B1, 0x8754, 0xB1B2, + 0x8755, 0xB1B3, 0x8756, 0xB1B4, 0x8757, 0xB1B5, 0x8758, 0xB1B6, 0x8759, 0xB1B7, 0x875A, 0xB1B8, 0x8761, 0xB1B9, 0x8762, 0xB1BA, + 0x8763, 0xB1BB, 0x8764, 0xB1BC, 0x8765, 0xB1BD, 0x8766, 0xB1BE, 0x8767, 0xB1BF, 0x8768, 0xB1C0, 0x8769, 0xB1C1, 0x876A, 0xB1C2, + 0x876B, 0xB1C3, 0x876C, 0xB1C4, 0x876D, 0xB1C5, 0x876E, 0xB1C6, 0x876F, 0xB1C7, 0x8770, 0xB1C8, 0x8771, 0xB1C9, 0x8772, 0xB1CA, + 0x8773, 0xB1CB, 0x8774, 0xB1CD, 0x8775, 0xB1CE, 0x8776, 0xB1CF, 0x8777, 0xB1D1, 0x8778, 0xB1D2, 0x8779, 0xB1D3, 0x877A, 0xB1D5, + 0x8781, 0xB1D6, 0x8782, 0xB1D7, 0x8783, 0xB1D8, 0x8784, 0xB1D9, 0x8785, 0xB1DA, 0x8786, 0xB1DB, 0x8787, 0xB1DE, 0x8788, 0xB1E0, + 0x8789, 0xB1E1, 0x878A, 0xB1E2, 0x878B, 0xB1E3, 0x878C, 0xB1E4, 0x878D, 0xB1E5, 0x878E, 0xB1E6, 0x878F, 0xB1E7, 0x8790, 0xB1EA, + 0x8791, 0xB1EB, 0x8792, 0xB1ED, 0x8793, 0xB1EE, 0x8794, 0xB1EF, 0x8795, 0xB1F1, 0x8796, 0xB1F2, 0x8797, 0xB1F3, 0x8798, 0xB1F4, + 0x8799, 0xB1F5, 0x879A, 0xB1F6, 0x879B, 0xB1F7, 0x879C, 0xB1F8, 0x879D, 0xB1FA, 0x879E, 0xB1FC, 0x879F, 0xB1FE, 0x87A0, 0xB1FF, + 0x87A1, 0xB200, 0x87A2, 0xB201, 0x87A3, 0xB202, 0x87A4, 0xB203, 0x87A5, 0xB206, 0x87A6, 0xB207, 0x87A7, 0xB209, 0x87A8, 0xB20A, + 0x87A9, 0xB20D, 0x87AA, 0xB20E, 0x87AB, 0xB20F, 0x87AC, 0xB210, 0x87AD, 0xB211, 0x87AE, 0xB212, 0x87AF, 0xB213, 0x87B0, 0xB216, + 0x87B1, 0xB218, 0x87B2, 0xB21A, 0x87B3, 0xB21B, 0x87B4, 0xB21C, 0x87B5, 0xB21D, 0x87B6, 0xB21E, 0x87B7, 0xB21F, 0x87B8, 0xB221, + 0x87B9, 0xB222, 0x87BA, 0xB223, 0x87BB, 0xB224, 0x87BC, 0xB225, 0x87BD, 0xB226, 0x87BE, 0xB227, 0x87BF, 0xB228, 0x87C0, 0xB229, + 0x87C1, 0xB22A, 0x87C2, 0xB22B, 0x87C3, 0xB22C, 0x87C4, 0xB22D, 0x87C5, 0xB22E, 0x87C6, 0xB22F, 0x87C7, 0xB230, 0x87C8, 0xB231, + 0x87C9, 0xB232, 0x87CA, 0xB233, 0x87CB, 0xB235, 0x87CC, 0xB236, 0x87CD, 0xB237, 0x87CE, 0xB238, 0x87CF, 0xB239, 0x87D0, 0xB23A, + 0x87D1, 0xB23B, 0x87D2, 0xB23D, 0x87D3, 0xB23E, 0x87D4, 0xB23F, 0x87D5, 0xB240, 0x87D6, 0xB241, 0x87D7, 0xB242, 0x87D8, 0xB243, + 0x87D9, 0xB244, 0x87DA, 0xB245, 0x87DB, 0xB246, 0x87DC, 0xB247, 0x87DD, 0xB248, 0x87DE, 0xB249, 0x87DF, 0xB24A, 0x87E0, 0xB24B, + 0x87E1, 0xB24C, 0x87E2, 0xB24D, 0x87E3, 0xB24E, 0x87E4, 0xB24F, 0x87E5, 0xB250, 0x87E6, 0xB251, 0x87E7, 0xB252, 0x87E8, 0xB253, + 0x87E9, 0xB254, 0x87EA, 0xB255, 0x87EB, 0xB256, 0x87EC, 0xB257, 0x87ED, 0xB259, 0x87EE, 0xB25A, 0x87EF, 0xB25B, 0x87F0, 0xB25D, + 0x87F1, 0xB25E, 0x87F2, 0xB25F, 0x87F3, 0xB261, 0x87F4, 0xB262, 0x87F5, 0xB263, 0x87F6, 0xB264, 0x87F7, 0xB265, 0x87F8, 0xB266, + 0x87F9, 0xB267, 0x87FA, 0xB26A, 0x87FB, 0xB26B, 0x87FC, 0xB26C, 0x87FD, 0xB26D, 0x87FE, 0xB26E, 0x8841, 0xB26F, 0x8842, 0xB270, + 0x8843, 0xB271, 0x8844, 0xB272, 0x8845, 0xB273, 0x8846, 0xB276, 0x8847, 0xB277, 0x8848, 0xB278, 0x8849, 0xB279, 0x884A, 0xB27A, + 0x884B, 0xB27B, 0x884C, 0xB27D, 0x884D, 0xB27E, 0x884E, 0xB27F, 0x884F, 0xB280, 0x8850, 0xB281, 0x8851, 0xB282, 0x8852, 0xB283, + 0x8853, 0xB286, 0x8854, 0xB287, 0x8855, 0xB288, 0x8856, 0xB28A, 0x8857, 0xB28B, 0x8858, 0xB28C, 0x8859, 0xB28D, 0x885A, 0xB28E, + 0x8861, 0xB28F, 0x8862, 0xB292, 0x8863, 0xB293, 0x8864, 0xB295, 0x8865, 0xB296, 0x8866, 0xB297, 0x8867, 0xB29B, 0x8868, 0xB29C, + 0x8869, 0xB29D, 0x886A, 0xB29E, 0x886B, 0xB29F, 0x886C, 0xB2A2, 0x886D, 0xB2A4, 0x886E, 0xB2A7, 0x886F, 0xB2A8, 0x8870, 0xB2A9, + 0x8871, 0xB2AB, 0x8872, 0xB2AD, 0x8873, 0xB2AE, 0x8874, 0xB2AF, 0x8875, 0xB2B1, 0x8876, 0xB2B2, 0x8877, 0xB2B3, 0x8878, 0xB2B5, + 0x8879, 0xB2B6, 0x887A, 0xB2B7, 0x8881, 0xB2B8, 0x8882, 0xB2B9, 0x8883, 0xB2BA, 0x8884, 0xB2BB, 0x8885, 0xB2BC, 0x8886, 0xB2BD, + 0x8887, 0xB2BE, 0x8888, 0xB2BF, 0x8889, 0xB2C0, 0x888A, 0xB2C1, 0x888B, 0xB2C2, 0x888C, 0xB2C3, 0x888D, 0xB2C4, 0x888E, 0xB2C5, + 0x888F, 0xB2C6, 0x8890, 0xB2C7, 0x8891, 0xB2CA, 0x8892, 0xB2CB, 0x8893, 0xB2CD, 0x8894, 0xB2CE, 0x8895, 0xB2CF, 0x8896, 0xB2D1, + 0x8897, 0xB2D3, 0x8898, 0xB2D4, 0x8899, 0xB2D5, 0x889A, 0xB2D6, 0x889B, 0xB2D7, 0x889C, 0xB2DA, 0x889D, 0xB2DC, 0x889E, 0xB2DE, + 0x889F, 0xB2DF, 0x88A0, 0xB2E0, 0x88A1, 0xB2E1, 0x88A2, 0xB2E3, 0x88A3, 0xB2E7, 0x88A4, 0xB2E9, 0x88A5, 0xB2EA, 0x88A6, 0xB2F0, + 0x88A7, 0xB2F1, 0x88A8, 0xB2F2, 0x88A9, 0xB2F6, 0x88AA, 0xB2FC, 0x88AB, 0xB2FD, 0x88AC, 0xB2FE, 0x88AD, 0xB302, 0x88AE, 0xB303, + 0x88AF, 0xB305, 0x88B0, 0xB306, 0x88B1, 0xB307, 0x88B2, 0xB309, 0x88B3, 0xB30A, 0x88B4, 0xB30B, 0x88B5, 0xB30C, 0x88B6, 0xB30D, + 0x88B7, 0xB30E, 0x88B8, 0xB30F, 0x88B9, 0xB312, 0x88BA, 0xB316, 0x88BB, 0xB317, 0x88BC, 0xB318, 0x88BD, 0xB319, 0x88BE, 0xB31A, + 0x88BF, 0xB31B, 0x88C0, 0xB31D, 0x88C1, 0xB31E, 0x88C2, 0xB31F, 0x88C3, 0xB320, 0x88C4, 0xB321, 0x88C5, 0xB322, 0x88C6, 0xB323, + 0x88C7, 0xB324, 0x88C8, 0xB325, 0x88C9, 0xB326, 0x88CA, 0xB327, 0x88CB, 0xB328, 0x88CC, 0xB329, 0x88CD, 0xB32A, 0x88CE, 0xB32B, + 0x88CF, 0xB32C, 0x88D0, 0xB32D, 0x88D1, 0xB32E, 0x88D2, 0xB32F, 0x88D3, 0xB330, 0x88D4, 0xB331, 0x88D5, 0xB332, 0x88D6, 0xB333, + 0x88D7, 0xB334, 0x88D8, 0xB335, 0x88D9, 0xB336, 0x88DA, 0xB337, 0x88DB, 0xB338, 0x88DC, 0xB339, 0x88DD, 0xB33A, 0x88DE, 0xB33B, + 0x88DF, 0xB33C, 0x88E0, 0xB33D, 0x88E1, 0xB33E, 0x88E2, 0xB33F, 0x88E3, 0xB340, 0x88E4, 0xB341, 0x88E5, 0xB342, 0x88E6, 0xB343, + 0x88E7, 0xB344, 0x88E8, 0xB345, 0x88E9, 0xB346, 0x88EA, 0xB347, 0x88EB, 0xB348, 0x88EC, 0xB349, 0x88ED, 0xB34A, 0x88EE, 0xB34B, + 0x88EF, 0xB34C, 0x88F0, 0xB34D, 0x88F1, 0xB34E, 0x88F2, 0xB34F, 0x88F3, 0xB350, 0x88F4, 0xB351, 0x88F5, 0xB352, 0x88F6, 0xB353, + 0x88F7, 0xB357, 0x88F8, 0xB359, 0x88F9, 0xB35A, 0x88FA, 0xB35D, 0x88FB, 0xB360, 0x88FC, 0xB361, 0x88FD, 0xB362, 0x88FE, 0xB363, + 0x8941, 0xB366, 0x8942, 0xB368, 0x8943, 0xB36A, 0x8944, 0xB36C, 0x8945, 0xB36D, 0x8946, 0xB36F, 0x8947, 0xB372, 0x8948, 0xB373, + 0x8949, 0xB375, 0x894A, 0xB376, 0x894B, 0xB377, 0x894C, 0xB379, 0x894D, 0xB37A, 0x894E, 0xB37B, 0x894F, 0xB37C, 0x8950, 0xB37D, + 0x8951, 0xB37E, 0x8952, 0xB37F, 0x8953, 0xB382, 0x8954, 0xB386, 0x8955, 0xB387, 0x8956, 0xB388, 0x8957, 0xB389, 0x8958, 0xB38A, + 0x8959, 0xB38B, 0x895A, 0xB38D, 0x8961, 0xB38E, 0x8962, 0xB38F, 0x8963, 0xB391, 0x8964, 0xB392, 0x8965, 0xB393, 0x8966, 0xB395, + 0x8967, 0xB396, 0x8968, 0xB397, 0x8969, 0xB398, 0x896A, 0xB399, 0x896B, 0xB39A, 0x896C, 0xB39B, 0x896D, 0xB39C, 0x896E, 0xB39D, + 0x896F, 0xB39E, 0x8970, 0xB39F, 0x8971, 0xB3A2, 0x8972, 0xB3A3, 0x8973, 0xB3A4, 0x8974, 0xB3A5, 0x8975, 0xB3A6, 0x8976, 0xB3A7, + 0x8977, 0xB3A9, 0x8978, 0xB3AA, 0x8979, 0xB3AB, 0x897A, 0xB3AD, 0x8981, 0xB3AE, 0x8982, 0xB3AF, 0x8983, 0xB3B0, 0x8984, 0xB3B1, + 0x8985, 0xB3B2, 0x8986, 0xB3B3, 0x8987, 0xB3B4, 0x8988, 0xB3B5, 0x8989, 0xB3B6, 0x898A, 0xB3B7, 0x898B, 0xB3B8, 0x898C, 0xB3B9, + 0x898D, 0xB3BA, 0x898E, 0xB3BB, 0x898F, 0xB3BC, 0x8990, 0xB3BD, 0x8991, 0xB3BE, 0x8992, 0xB3BF, 0x8993, 0xB3C0, 0x8994, 0xB3C1, + 0x8995, 0xB3C2, 0x8996, 0xB3C3, 0x8997, 0xB3C6, 0x8998, 0xB3C7, 0x8999, 0xB3C9, 0x899A, 0xB3CA, 0x899B, 0xB3CD, 0x899C, 0xB3CF, + 0x899D, 0xB3D1, 0x899E, 0xB3D2, 0x899F, 0xB3D3, 0x89A0, 0xB3D6, 0x89A1, 0xB3D8, 0x89A2, 0xB3DA, 0x89A3, 0xB3DC, 0x89A4, 0xB3DE, + 0x89A5, 0xB3DF, 0x89A6, 0xB3E1, 0x89A7, 0xB3E2, 0x89A8, 0xB3E3, 0x89A9, 0xB3E5, 0x89AA, 0xB3E6, 0x89AB, 0xB3E7, 0x89AC, 0xB3E9, + 0x89AD, 0xB3EA, 0x89AE, 0xB3EB, 0x89AF, 0xB3EC, 0x89B0, 0xB3ED, 0x89B1, 0xB3EE, 0x89B2, 0xB3EF, 0x89B3, 0xB3F0, 0x89B4, 0xB3F1, + 0x89B5, 0xB3F2, 0x89B6, 0xB3F3, 0x89B7, 0xB3F4, 0x89B8, 0xB3F5, 0x89B9, 0xB3F6, 0x89BA, 0xB3F7, 0x89BB, 0xB3F8, 0x89BC, 0xB3F9, + 0x89BD, 0xB3FA, 0x89BE, 0xB3FB, 0x89BF, 0xB3FD, 0x89C0, 0xB3FE, 0x89C1, 0xB3FF, 0x89C2, 0xB400, 0x89C3, 0xB401, 0x89C4, 0xB402, + 0x89C5, 0xB403, 0x89C6, 0xB404, 0x89C7, 0xB405, 0x89C8, 0xB406, 0x89C9, 0xB407, 0x89CA, 0xB408, 0x89CB, 0xB409, 0x89CC, 0xB40A, + 0x89CD, 0xB40B, 0x89CE, 0xB40C, 0x89CF, 0xB40D, 0x89D0, 0xB40E, 0x89D1, 0xB40F, 0x89D2, 0xB411, 0x89D3, 0xB412, 0x89D4, 0xB413, + 0x89D5, 0xB414, 0x89D6, 0xB415, 0x89D7, 0xB416, 0x89D8, 0xB417, 0x89D9, 0xB419, 0x89DA, 0xB41A, 0x89DB, 0xB41B, 0x89DC, 0xB41D, + 0x89DD, 0xB41E, 0x89DE, 0xB41F, 0x89DF, 0xB421, 0x89E0, 0xB422, 0x89E1, 0xB423, 0x89E2, 0xB424, 0x89E3, 0xB425, 0x89E4, 0xB426, + 0x89E5, 0xB427, 0x89E6, 0xB42A, 0x89E7, 0xB42C, 0x89E8, 0xB42D, 0x89E9, 0xB42E, 0x89EA, 0xB42F, 0x89EB, 0xB430, 0x89EC, 0xB431, + 0x89ED, 0xB432, 0x89EE, 0xB433, 0x89EF, 0xB435, 0x89F0, 0xB436, 0x89F1, 0xB437, 0x89F2, 0xB438, 0x89F3, 0xB439, 0x89F4, 0xB43A, + 0x89F5, 0xB43B, 0x89F6, 0xB43C, 0x89F7, 0xB43D, 0x89F8, 0xB43E, 0x89F9, 0xB43F, 0x89FA, 0xB440, 0x89FB, 0xB441, 0x89FC, 0xB442, + 0x89FD, 0xB443, 0x89FE, 0xB444, 0x8A41, 0xB445, 0x8A42, 0xB446, 0x8A43, 0xB447, 0x8A44, 0xB448, 0x8A45, 0xB449, 0x8A46, 0xB44A, + 0x8A47, 0xB44B, 0x8A48, 0xB44C, 0x8A49, 0xB44D, 0x8A4A, 0xB44E, 0x8A4B, 0xB44F, 0x8A4C, 0xB452, 0x8A4D, 0xB453, 0x8A4E, 0xB455, + 0x8A4F, 0xB456, 0x8A50, 0xB457, 0x8A51, 0xB459, 0x8A52, 0xB45A, 0x8A53, 0xB45B, 0x8A54, 0xB45C, 0x8A55, 0xB45D, 0x8A56, 0xB45E, + 0x8A57, 0xB45F, 0x8A58, 0xB462, 0x8A59, 0xB464, 0x8A5A, 0xB466, 0x8A61, 0xB467, 0x8A62, 0xB468, 0x8A63, 0xB469, 0x8A64, 0xB46A, + 0x8A65, 0xB46B, 0x8A66, 0xB46D, 0x8A67, 0xB46E, 0x8A68, 0xB46F, 0x8A69, 0xB470, 0x8A6A, 0xB471, 0x8A6B, 0xB472, 0x8A6C, 0xB473, + 0x8A6D, 0xB474, 0x8A6E, 0xB475, 0x8A6F, 0xB476, 0x8A70, 0xB477, 0x8A71, 0xB478, 0x8A72, 0xB479, 0x8A73, 0xB47A, 0x8A74, 0xB47B, + 0x8A75, 0xB47C, 0x8A76, 0xB47D, 0x8A77, 0xB47E, 0x8A78, 0xB47F, 0x8A79, 0xB481, 0x8A7A, 0xB482, 0x8A81, 0xB483, 0x8A82, 0xB484, + 0x8A83, 0xB485, 0x8A84, 0xB486, 0x8A85, 0xB487, 0x8A86, 0xB489, 0x8A87, 0xB48A, 0x8A88, 0xB48B, 0x8A89, 0xB48C, 0x8A8A, 0xB48D, + 0x8A8B, 0xB48E, 0x8A8C, 0xB48F, 0x8A8D, 0xB490, 0x8A8E, 0xB491, 0x8A8F, 0xB492, 0x8A90, 0xB493, 0x8A91, 0xB494, 0x8A92, 0xB495, + 0x8A93, 0xB496, 0x8A94, 0xB497, 0x8A95, 0xB498, 0x8A96, 0xB499, 0x8A97, 0xB49A, 0x8A98, 0xB49B, 0x8A99, 0xB49C, 0x8A9A, 0xB49E, + 0x8A9B, 0xB49F, 0x8A9C, 0xB4A0, 0x8A9D, 0xB4A1, 0x8A9E, 0xB4A2, 0x8A9F, 0xB4A3, 0x8AA0, 0xB4A5, 0x8AA1, 0xB4A6, 0x8AA2, 0xB4A7, + 0x8AA3, 0xB4A9, 0x8AA4, 0xB4AA, 0x8AA5, 0xB4AB, 0x8AA6, 0xB4AD, 0x8AA7, 0xB4AE, 0x8AA8, 0xB4AF, 0x8AA9, 0xB4B0, 0x8AAA, 0xB4B1, + 0x8AAB, 0xB4B2, 0x8AAC, 0xB4B3, 0x8AAD, 0xB4B4, 0x8AAE, 0xB4B6, 0x8AAF, 0xB4B8, 0x8AB0, 0xB4BA, 0x8AB1, 0xB4BB, 0x8AB2, 0xB4BC, + 0x8AB3, 0xB4BD, 0x8AB4, 0xB4BE, 0x8AB5, 0xB4BF, 0x8AB6, 0xB4C1, 0x8AB7, 0xB4C2, 0x8AB8, 0xB4C3, 0x8AB9, 0xB4C5, 0x8ABA, 0xB4C6, + 0x8ABB, 0xB4C7, 0x8ABC, 0xB4C9, 0x8ABD, 0xB4CA, 0x8ABE, 0xB4CB, 0x8ABF, 0xB4CC, 0x8AC0, 0xB4CD, 0x8AC1, 0xB4CE, 0x8AC2, 0xB4CF, + 0x8AC3, 0xB4D1, 0x8AC4, 0xB4D2, 0x8AC5, 0xB4D3, 0x8AC6, 0xB4D4, 0x8AC7, 0xB4D6, 0x8AC8, 0xB4D7, 0x8AC9, 0xB4D8, 0x8ACA, 0xB4D9, + 0x8ACB, 0xB4DA, 0x8ACC, 0xB4DB, 0x8ACD, 0xB4DE, 0x8ACE, 0xB4DF, 0x8ACF, 0xB4E1, 0x8AD0, 0xB4E2, 0x8AD1, 0xB4E5, 0x8AD2, 0xB4E7, + 0x8AD3, 0xB4E8, 0x8AD4, 0xB4E9, 0x8AD5, 0xB4EA, 0x8AD6, 0xB4EB, 0x8AD7, 0xB4EE, 0x8AD8, 0xB4F0, 0x8AD9, 0xB4F2, 0x8ADA, 0xB4F3, + 0x8ADB, 0xB4F4, 0x8ADC, 0xB4F5, 0x8ADD, 0xB4F6, 0x8ADE, 0xB4F7, 0x8ADF, 0xB4F9, 0x8AE0, 0xB4FA, 0x8AE1, 0xB4FB, 0x8AE2, 0xB4FC, + 0x8AE3, 0xB4FD, 0x8AE4, 0xB4FE, 0x8AE5, 0xB4FF, 0x8AE6, 0xB500, 0x8AE7, 0xB501, 0x8AE8, 0xB502, 0x8AE9, 0xB503, 0x8AEA, 0xB504, + 0x8AEB, 0xB505, 0x8AEC, 0xB506, 0x8AED, 0xB507, 0x8AEE, 0xB508, 0x8AEF, 0xB509, 0x8AF0, 0xB50A, 0x8AF1, 0xB50B, 0x8AF2, 0xB50C, + 0x8AF3, 0xB50D, 0x8AF4, 0xB50E, 0x8AF5, 0xB50F, 0x8AF6, 0xB510, 0x8AF7, 0xB511, 0x8AF8, 0xB512, 0x8AF9, 0xB513, 0x8AFA, 0xB516, + 0x8AFB, 0xB517, 0x8AFC, 0xB519, 0x8AFD, 0xB51A, 0x8AFE, 0xB51D, 0x8B41, 0xB51E, 0x8B42, 0xB51F, 0x8B43, 0xB520, 0x8B44, 0xB521, + 0x8B45, 0xB522, 0x8B46, 0xB523, 0x8B47, 0xB526, 0x8B48, 0xB52B, 0x8B49, 0xB52C, 0x8B4A, 0xB52D, 0x8B4B, 0xB52E, 0x8B4C, 0xB52F, + 0x8B4D, 0xB532, 0x8B4E, 0xB533, 0x8B4F, 0xB535, 0x8B50, 0xB536, 0x8B51, 0xB537, 0x8B52, 0xB539, 0x8B53, 0xB53A, 0x8B54, 0xB53B, + 0x8B55, 0xB53C, 0x8B56, 0xB53D, 0x8B57, 0xB53E, 0x8B58, 0xB53F, 0x8B59, 0xB542, 0x8B5A, 0xB546, 0x8B61, 0xB547, 0x8B62, 0xB548, + 0x8B63, 0xB549, 0x8B64, 0xB54A, 0x8B65, 0xB54E, 0x8B66, 0xB54F, 0x8B67, 0xB551, 0x8B68, 0xB552, 0x8B69, 0xB553, 0x8B6A, 0xB555, + 0x8B6B, 0xB556, 0x8B6C, 0xB557, 0x8B6D, 0xB558, 0x8B6E, 0xB559, 0x8B6F, 0xB55A, 0x8B70, 0xB55B, 0x8B71, 0xB55E, 0x8B72, 0xB562, + 0x8B73, 0xB563, 0x8B74, 0xB564, 0x8B75, 0xB565, 0x8B76, 0xB566, 0x8B77, 0xB567, 0x8B78, 0xB568, 0x8B79, 0xB569, 0x8B7A, 0xB56A, + 0x8B81, 0xB56B, 0x8B82, 0xB56C, 0x8B83, 0xB56D, 0x8B84, 0xB56E, 0x8B85, 0xB56F, 0x8B86, 0xB570, 0x8B87, 0xB571, 0x8B88, 0xB572, + 0x8B89, 0xB573, 0x8B8A, 0xB574, 0x8B8B, 0xB575, 0x8B8C, 0xB576, 0x8B8D, 0xB577, 0x8B8E, 0xB578, 0x8B8F, 0xB579, 0x8B90, 0xB57A, + 0x8B91, 0xB57B, 0x8B92, 0xB57C, 0x8B93, 0xB57D, 0x8B94, 0xB57E, 0x8B95, 0xB57F, 0x8B96, 0xB580, 0x8B97, 0xB581, 0x8B98, 0xB582, + 0x8B99, 0xB583, 0x8B9A, 0xB584, 0x8B9B, 0xB585, 0x8B9C, 0xB586, 0x8B9D, 0xB587, 0x8B9E, 0xB588, 0x8B9F, 0xB589, 0x8BA0, 0xB58A, + 0x8BA1, 0xB58B, 0x8BA2, 0xB58C, 0x8BA3, 0xB58D, 0x8BA4, 0xB58E, 0x8BA5, 0xB58F, 0x8BA6, 0xB590, 0x8BA7, 0xB591, 0x8BA8, 0xB592, + 0x8BA9, 0xB593, 0x8BAA, 0xB594, 0x8BAB, 0xB595, 0x8BAC, 0xB596, 0x8BAD, 0xB597, 0x8BAE, 0xB598, 0x8BAF, 0xB599, 0x8BB0, 0xB59A, + 0x8BB1, 0xB59B, 0x8BB2, 0xB59C, 0x8BB3, 0xB59D, 0x8BB4, 0xB59E, 0x8BB5, 0xB59F, 0x8BB6, 0xB5A2, 0x8BB7, 0xB5A3, 0x8BB8, 0xB5A5, + 0x8BB9, 0xB5A6, 0x8BBA, 0xB5A7, 0x8BBB, 0xB5A9, 0x8BBC, 0xB5AC, 0x8BBD, 0xB5AD, 0x8BBE, 0xB5AE, 0x8BBF, 0xB5AF, 0x8BC0, 0xB5B2, + 0x8BC1, 0xB5B6, 0x8BC2, 0xB5B7, 0x8BC3, 0xB5B8, 0x8BC4, 0xB5B9, 0x8BC5, 0xB5BA, 0x8BC6, 0xB5BE, 0x8BC7, 0xB5BF, 0x8BC8, 0xB5C1, + 0x8BC9, 0xB5C2, 0x8BCA, 0xB5C3, 0x8BCB, 0xB5C5, 0x8BCC, 0xB5C6, 0x8BCD, 0xB5C7, 0x8BCE, 0xB5C8, 0x8BCF, 0xB5C9, 0x8BD0, 0xB5CA, + 0x8BD1, 0xB5CB, 0x8BD2, 0xB5CE, 0x8BD3, 0xB5D2, 0x8BD4, 0xB5D3, 0x8BD5, 0xB5D4, 0x8BD6, 0xB5D5, 0x8BD7, 0xB5D6, 0x8BD8, 0xB5D7, + 0x8BD9, 0xB5D9, 0x8BDA, 0xB5DA, 0x8BDB, 0xB5DB, 0x8BDC, 0xB5DC, 0x8BDD, 0xB5DD, 0x8BDE, 0xB5DE, 0x8BDF, 0xB5DF, 0x8BE0, 0xB5E0, + 0x8BE1, 0xB5E1, 0x8BE2, 0xB5E2, 0x8BE3, 0xB5E3, 0x8BE4, 0xB5E4, 0x8BE5, 0xB5E5, 0x8BE6, 0xB5E6, 0x8BE7, 0xB5E7, 0x8BE8, 0xB5E8, + 0x8BE9, 0xB5E9, 0x8BEA, 0xB5EA, 0x8BEB, 0xB5EB, 0x8BEC, 0xB5ED, 0x8BED, 0xB5EE, 0x8BEE, 0xB5EF, 0x8BEF, 0xB5F0, 0x8BF0, 0xB5F1, + 0x8BF1, 0xB5F2, 0x8BF2, 0xB5F3, 0x8BF3, 0xB5F4, 0x8BF4, 0xB5F5, 0x8BF5, 0xB5F6, 0x8BF6, 0xB5F7, 0x8BF7, 0xB5F8, 0x8BF8, 0xB5F9, + 0x8BF9, 0xB5FA, 0x8BFA, 0xB5FB, 0x8BFB, 0xB5FC, 0x8BFC, 0xB5FD, 0x8BFD, 0xB5FE, 0x8BFE, 0xB5FF, 0x8C41, 0xB600, 0x8C42, 0xB601, + 0x8C43, 0xB602, 0x8C44, 0xB603, 0x8C45, 0xB604, 0x8C46, 0xB605, 0x8C47, 0xB606, 0x8C48, 0xB607, 0x8C49, 0xB608, 0x8C4A, 0xB609, + 0x8C4B, 0xB60A, 0x8C4C, 0xB60B, 0x8C4D, 0xB60C, 0x8C4E, 0xB60D, 0x8C4F, 0xB60E, 0x8C50, 0xB60F, 0x8C51, 0xB612, 0x8C52, 0xB613, + 0x8C53, 0xB615, 0x8C54, 0xB616, 0x8C55, 0xB617, 0x8C56, 0xB619, 0x8C57, 0xB61A, 0x8C58, 0xB61B, 0x8C59, 0xB61C, 0x8C5A, 0xB61D, + 0x8C61, 0xB61E, 0x8C62, 0xB61F, 0x8C63, 0xB620, 0x8C64, 0xB621, 0x8C65, 0xB622, 0x8C66, 0xB623, 0x8C67, 0xB624, 0x8C68, 0xB626, + 0x8C69, 0xB627, 0x8C6A, 0xB628, 0x8C6B, 0xB629, 0x8C6C, 0xB62A, 0x8C6D, 0xB62B, 0x8C6E, 0xB62D, 0x8C6F, 0xB62E, 0x8C70, 0xB62F, + 0x8C71, 0xB630, 0x8C72, 0xB631, 0x8C73, 0xB632, 0x8C74, 0xB633, 0x8C75, 0xB635, 0x8C76, 0xB636, 0x8C77, 0xB637, 0x8C78, 0xB638, + 0x8C79, 0xB639, 0x8C7A, 0xB63A, 0x8C81, 0xB63B, 0x8C82, 0xB63C, 0x8C83, 0xB63D, 0x8C84, 0xB63E, 0x8C85, 0xB63F, 0x8C86, 0xB640, + 0x8C87, 0xB641, 0x8C88, 0xB642, 0x8C89, 0xB643, 0x8C8A, 0xB644, 0x8C8B, 0xB645, 0x8C8C, 0xB646, 0x8C8D, 0xB647, 0x8C8E, 0xB649, + 0x8C8F, 0xB64A, 0x8C90, 0xB64B, 0x8C91, 0xB64C, 0x8C92, 0xB64D, 0x8C93, 0xB64E, 0x8C94, 0xB64F, 0x8C95, 0xB650, 0x8C96, 0xB651, + 0x8C97, 0xB652, 0x8C98, 0xB653, 0x8C99, 0xB654, 0x8C9A, 0xB655, 0x8C9B, 0xB656, 0x8C9C, 0xB657, 0x8C9D, 0xB658, 0x8C9E, 0xB659, + 0x8C9F, 0xB65A, 0x8CA0, 0xB65B, 0x8CA1, 0xB65C, 0x8CA2, 0xB65D, 0x8CA3, 0xB65E, 0x8CA4, 0xB65F, 0x8CA5, 0xB660, 0x8CA6, 0xB661, + 0x8CA7, 0xB662, 0x8CA8, 0xB663, 0x8CA9, 0xB665, 0x8CAA, 0xB666, 0x8CAB, 0xB667, 0x8CAC, 0xB669, 0x8CAD, 0xB66A, 0x8CAE, 0xB66B, + 0x8CAF, 0xB66C, 0x8CB0, 0xB66D, 0x8CB1, 0xB66E, 0x8CB2, 0xB66F, 0x8CB3, 0xB670, 0x8CB4, 0xB671, 0x8CB5, 0xB672, 0x8CB6, 0xB673, + 0x8CB7, 0xB674, 0x8CB8, 0xB675, 0x8CB9, 0xB676, 0x8CBA, 0xB677, 0x8CBB, 0xB678, 0x8CBC, 0xB679, 0x8CBD, 0xB67A, 0x8CBE, 0xB67B, + 0x8CBF, 0xB67C, 0x8CC0, 0xB67D, 0x8CC1, 0xB67E, 0x8CC2, 0xB67F, 0x8CC3, 0xB680, 0x8CC4, 0xB681, 0x8CC5, 0xB682, 0x8CC6, 0xB683, + 0x8CC7, 0xB684, 0x8CC8, 0xB685, 0x8CC9, 0xB686, 0x8CCA, 0xB687, 0x8CCB, 0xB688, 0x8CCC, 0xB689, 0x8CCD, 0xB68A, 0x8CCE, 0xB68B, + 0x8CCF, 0xB68C, 0x8CD0, 0xB68D, 0x8CD1, 0xB68E, 0x8CD2, 0xB68F, 0x8CD3, 0xB690, 0x8CD4, 0xB691, 0x8CD5, 0xB692, 0x8CD6, 0xB693, + 0x8CD7, 0xB694, 0x8CD8, 0xB695, 0x8CD9, 0xB696, 0x8CDA, 0xB697, 0x8CDB, 0xB698, 0x8CDC, 0xB699, 0x8CDD, 0xB69A, 0x8CDE, 0xB69B, + 0x8CDF, 0xB69E, 0x8CE0, 0xB69F, 0x8CE1, 0xB6A1, 0x8CE2, 0xB6A2, 0x8CE3, 0xB6A3, 0x8CE4, 0xB6A5, 0x8CE5, 0xB6A6, 0x8CE6, 0xB6A7, + 0x8CE7, 0xB6A8, 0x8CE8, 0xB6A9, 0x8CE9, 0xB6AA, 0x8CEA, 0xB6AD, 0x8CEB, 0xB6AE, 0x8CEC, 0xB6AF, 0x8CED, 0xB6B0, 0x8CEE, 0xB6B2, + 0x8CEF, 0xB6B3, 0x8CF0, 0xB6B4, 0x8CF1, 0xB6B5, 0x8CF2, 0xB6B6, 0x8CF3, 0xB6B7, 0x8CF4, 0xB6B8, 0x8CF5, 0xB6B9, 0x8CF6, 0xB6BA, + 0x8CF7, 0xB6BB, 0x8CF8, 0xB6BC, 0x8CF9, 0xB6BD, 0x8CFA, 0xB6BE, 0x8CFB, 0xB6BF, 0x8CFC, 0xB6C0, 0x8CFD, 0xB6C1, 0x8CFE, 0xB6C2, + 0x8D41, 0xB6C3, 0x8D42, 0xB6C4, 0x8D43, 0xB6C5, 0x8D44, 0xB6C6, 0x8D45, 0xB6C7, 0x8D46, 0xB6C8, 0x8D47, 0xB6C9, 0x8D48, 0xB6CA, + 0x8D49, 0xB6CB, 0x8D4A, 0xB6CC, 0x8D4B, 0xB6CD, 0x8D4C, 0xB6CE, 0x8D4D, 0xB6CF, 0x8D4E, 0xB6D0, 0x8D4F, 0xB6D1, 0x8D50, 0xB6D2, + 0x8D51, 0xB6D3, 0x8D52, 0xB6D5, 0x8D53, 0xB6D6, 0x8D54, 0xB6D7, 0x8D55, 0xB6D8, 0x8D56, 0xB6D9, 0x8D57, 0xB6DA, 0x8D58, 0xB6DB, + 0x8D59, 0xB6DC, 0x8D5A, 0xB6DD, 0x8D61, 0xB6DE, 0x8D62, 0xB6DF, 0x8D63, 0xB6E0, 0x8D64, 0xB6E1, 0x8D65, 0xB6E2, 0x8D66, 0xB6E3, + 0x8D67, 0xB6E4, 0x8D68, 0xB6E5, 0x8D69, 0xB6E6, 0x8D6A, 0xB6E7, 0x8D6B, 0xB6E8, 0x8D6C, 0xB6E9, 0x8D6D, 0xB6EA, 0x8D6E, 0xB6EB, + 0x8D6F, 0xB6EC, 0x8D70, 0xB6ED, 0x8D71, 0xB6EE, 0x8D72, 0xB6EF, 0x8D73, 0xB6F1, 0x8D74, 0xB6F2, 0x8D75, 0xB6F3, 0x8D76, 0xB6F5, + 0x8D77, 0xB6F6, 0x8D78, 0xB6F7, 0x8D79, 0xB6F9, 0x8D7A, 0xB6FA, 0x8D81, 0xB6FB, 0x8D82, 0xB6FC, 0x8D83, 0xB6FD, 0x8D84, 0xB6FE, + 0x8D85, 0xB6FF, 0x8D86, 0xB702, 0x8D87, 0xB703, 0x8D88, 0xB704, 0x8D89, 0xB706, 0x8D8A, 0xB707, 0x8D8B, 0xB708, 0x8D8C, 0xB709, + 0x8D8D, 0xB70A, 0x8D8E, 0xB70B, 0x8D8F, 0xB70C, 0x8D90, 0xB70D, 0x8D91, 0xB70E, 0x8D92, 0xB70F, 0x8D93, 0xB710, 0x8D94, 0xB711, + 0x8D95, 0xB712, 0x8D96, 0xB713, 0x8D97, 0xB714, 0x8D98, 0xB715, 0x8D99, 0xB716, 0x8D9A, 0xB717, 0x8D9B, 0xB718, 0x8D9C, 0xB719, + 0x8D9D, 0xB71A, 0x8D9E, 0xB71B, 0x8D9F, 0xB71C, 0x8DA0, 0xB71D, 0x8DA1, 0xB71E, 0x8DA2, 0xB71F, 0x8DA3, 0xB720, 0x8DA4, 0xB721, + 0x8DA5, 0xB722, 0x8DA6, 0xB723, 0x8DA7, 0xB724, 0x8DA8, 0xB725, 0x8DA9, 0xB726, 0x8DAA, 0xB727, 0x8DAB, 0xB72A, 0x8DAC, 0xB72B, + 0x8DAD, 0xB72D, 0x8DAE, 0xB72E, 0x8DAF, 0xB731, 0x8DB0, 0xB732, 0x8DB1, 0xB733, 0x8DB2, 0xB734, 0x8DB3, 0xB735, 0x8DB4, 0xB736, + 0x8DB5, 0xB737, 0x8DB6, 0xB73A, 0x8DB7, 0xB73C, 0x8DB8, 0xB73D, 0x8DB9, 0xB73E, 0x8DBA, 0xB73F, 0x8DBB, 0xB740, 0x8DBC, 0xB741, + 0x8DBD, 0xB742, 0x8DBE, 0xB743, 0x8DBF, 0xB745, 0x8DC0, 0xB746, 0x8DC1, 0xB747, 0x8DC2, 0xB749, 0x8DC3, 0xB74A, 0x8DC4, 0xB74B, + 0x8DC5, 0xB74D, 0x8DC6, 0xB74E, 0x8DC7, 0xB74F, 0x8DC8, 0xB750, 0x8DC9, 0xB751, 0x8DCA, 0xB752, 0x8DCB, 0xB753, 0x8DCC, 0xB756, + 0x8DCD, 0xB757, 0x8DCE, 0xB758, 0x8DCF, 0xB759, 0x8DD0, 0xB75A, 0x8DD1, 0xB75B, 0x8DD2, 0xB75C, 0x8DD3, 0xB75D, 0x8DD4, 0xB75E, + 0x8DD5, 0xB75F, 0x8DD6, 0xB761, 0x8DD7, 0xB762, 0x8DD8, 0xB763, 0x8DD9, 0xB765, 0x8DDA, 0xB766, 0x8DDB, 0xB767, 0x8DDC, 0xB769, + 0x8DDD, 0xB76A, 0x8DDE, 0xB76B, 0x8DDF, 0xB76C, 0x8DE0, 0xB76D, 0x8DE1, 0xB76E, 0x8DE2, 0xB76F, 0x8DE3, 0xB772, 0x8DE4, 0xB774, + 0x8DE5, 0xB776, 0x8DE6, 0xB777, 0x8DE7, 0xB778, 0x8DE8, 0xB779, 0x8DE9, 0xB77A, 0x8DEA, 0xB77B, 0x8DEB, 0xB77E, 0x8DEC, 0xB77F, + 0x8DED, 0xB781, 0x8DEE, 0xB782, 0x8DEF, 0xB783, 0x8DF0, 0xB785, 0x8DF1, 0xB786, 0x8DF2, 0xB787, 0x8DF3, 0xB788, 0x8DF4, 0xB789, + 0x8DF5, 0xB78A, 0x8DF6, 0xB78B, 0x8DF7, 0xB78E, 0x8DF8, 0xB793, 0x8DF9, 0xB794, 0x8DFA, 0xB795, 0x8DFB, 0xB79A, 0x8DFC, 0xB79B, + 0x8DFD, 0xB79D, 0x8DFE, 0xB79E, 0x8E41, 0xB79F, 0x8E42, 0xB7A1, 0x8E43, 0xB7A2, 0x8E44, 0xB7A3, 0x8E45, 0xB7A4, 0x8E46, 0xB7A5, + 0x8E47, 0xB7A6, 0x8E48, 0xB7A7, 0x8E49, 0xB7AA, 0x8E4A, 0xB7AE, 0x8E4B, 0xB7AF, 0x8E4C, 0xB7B0, 0x8E4D, 0xB7B1, 0x8E4E, 0xB7B2, + 0x8E4F, 0xB7B3, 0x8E50, 0xB7B6, 0x8E51, 0xB7B7, 0x8E52, 0xB7B9, 0x8E53, 0xB7BA, 0x8E54, 0xB7BB, 0x8E55, 0xB7BC, 0x8E56, 0xB7BD, + 0x8E57, 0xB7BE, 0x8E58, 0xB7BF, 0x8E59, 0xB7C0, 0x8E5A, 0xB7C1, 0x8E61, 0xB7C2, 0x8E62, 0xB7C3, 0x8E63, 0xB7C4, 0x8E64, 0xB7C5, + 0x8E65, 0xB7C6, 0x8E66, 0xB7C8, 0x8E67, 0xB7CA, 0x8E68, 0xB7CB, 0x8E69, 0xB7CC, 0x8E6A, 0xB7CD, 0x8E6B, 0xB7CE, 0x8E6C, 0xB7CF, + 0x8E6D, 0xB7D0, 0x8E6E, 0xB7D1, 0x8E6F, 0xB7D2, 0x8E70, 0xB7D3, 0x8E71, 0xB7D4, 0x8E72, 0xB7D5, 0x8E73, 0xB7D6, 0x8E74, 0xB7D7, + 0x8E75, 0xB7D8, 0x8E76, 0xB7D9, 0x8E77, 0xB7DA, 0x8E78, 0xB7DB, 0x8E79, 0xB7DC, 0x8E7A, 0xB7DD, 0x8E81, 0xB7DE, 0x8E82, 0xB7DF, + 0x8E83, 0xB7E0, 0x8E84, 0xB7E1, 0x8E85, 0xB7E2, 0x8E86, 0xB7E3, 0x8E87, 0xB7E4, 0x8E88, 0xB7E5, 0x8E89, 0xB7E6, 0x8E8A, 0xB7E7, + 0x8E8B, 0xB7E8, 0x8E8C, 0xB7E9, 0x8E8D, 0xB7EA, 0x8E8E, 0xB7EB, 0x8E8F, 0xB7EE, 0x8E90, 0xB7EF, 0x8E91, 0xB7F1, 0x8E92, 0xB7F2, + 0x8E93, 0xB7F3, 0x8E94, 0xB7F5, 0x8E95, 0xB7F6, 0x8E96, 0xB7F7, 0x8E97, 0xB7F8, 0x8E98, 0xB7F9, 0x8E99, 0xB7FA, 0x8E9A, 0xB7FB, + 0x8E9B, 0xB7FE, 0x8E9C, 0xB802, 0x8E9D, 0xB803, 0x8E9E, 0xB804, 0x8E9F, 0xB805, 0x8EA0, 0xB806, 0x8EA1, 0xB80A, 0x8EA2, 0xB80B, + 0x8EA3, 0xB80D, 0x8EA4, 0xB80E, 0x8EA5, 0xB80F, 0x8EA6, 0xB811, 0x8EA7, 0xB812, 0x8EA8, 0xB813, 0x8EA9, 0xB814, 0x8EAA, 0xB815, + 0x8EAB, 0xB816, 0x8EAC, 0xB817, 0x8EAD, 0xB81A, 0x8EAE, 0xB81C, 0x8EAF, 0xB81E, 0x8EB0, 0xB81F, 0x8EB1, 0xB820, 0x8EB2, 0xB821, + 0x8EB3, 0xB822, 0x8EB4, 0xB823, 0x8EB5, 0xB826, 0x8EB6, 0xB827, 0x8EB7, 0xB829, 0x8EB8, 0xB82A, 0x8EB9, 0xB82B, 0x8EBA, 0xB82D, + 0x8EBB, 0xB82E, 0x8EBC, 0xB82F, 0x8EBD, 0xB830, 0x8EBE, 0xB831, 0x8EBF, 0xB832, 0x8EC0, 0xB833, 0x8EC1, 0xB836, 0x8EC2, 0xB83A, + 0x8EC3, 0xB83B, 0x8EC4, 0xB83C, 0x8EC5, 0xB83D, 0x8EC6, 0xB83E, 0x8EC7, 0xB83F, 0x8EC8, 0xB841, 0x8EC9, 0xB842, 0x8ECA, 0xB843, + 0x8ECB, 0xB845, 0x8ECC, 0xB846, 0x8ECD, 0xB847, 0x8ECE, 0xB848, 0x8ECF, 0xB849, 0x8ED0, 0xB84A, 0x8ED1, 0xB84B, 0x8ED2, 0xB84C, + 0x8ED3, 0xB84D, 0x8ED4, 0xB84E, 0x8ED5, 0xB84F, 0x8ED6, 0xB850, 0x8ED7, 0xB852, 0x8ED8, 0xB854, 0x8ED9, 0xB855, 0x8EDA, 0xB856, + 0x8EDB, 0xB857, 0x8EDC, 0xB858, 0x8EDD, 0xB859, 0x8EDE, 0xB85A, 0x8EDF, 0xB85B, 0x8EE0, 0xB85E, 0x8EE1, 0xB85F, 0x8EE2, 0xB861, + 0x8EE3, 0xB862, 0x8EE4, 0xB863, 0x8EE5, 0xB865, 0x8EE6, 0xB866, 0x8EE7, 0xB867, 0x8EE8, 0xB868, 0x8EE9, 0xB869, 0x8EEA, 0xB86A, + 0x8EEB, 0xB86B, 0x8EEC, 0xB86E, 0x8EED, 0xB870, 0x8EEE, 0xB872, 0x8EEF, 0xB873, 0x8EF0, 0xB874, 0x8EF1, 0xB875, 0x8EF2, 0xB876, + 0x8EF3, 0xB877, 0x8EF4, 0xB879, 0x8EF5, 0xB87A, 0x8EF6, 0xB87B, 0x8EF7, 0xB87D, 0x8EF8, 0xB87E, 0x8EF9, 0xB87F, 0x8EFA, 0xB880, + 0x8EFB, 0xB881, 0x8EFC, 0xB882, 0x8EFD, 0xB883, 0x8EFE, 0xB884, 0x8F41, 0xB885, 0x8F42, 0xB886, 0x8F43, 0xB887, 0x8F44, 0xB888, + 0x8F45, 0xB889, 0x8F46, 0xB88A, 0x8F47, 0xB88B, 0x8F48, 0xB88C, 0x8F49, 0xB88E, 0x8F4A, 0xB88F, 0x8F4B, 0xB890, 0x8F4C, 0xB891, + 0x8F4D, 0xB892, 0x8F4E, 0xB893, 0x8F4F, 0xB894, 0x8F50, 0xB895, 0x8F51, 0xB896, 0x8F52, 0xB897, 0x8F53, 0xB898, 0x8F54, 0xB899, + 0x8F55, 0xB89A, 0x8F56, 0xB89B, 0x8F57, 0xB89C, 0x8F58, 0xB89D, 0x8F59, 0xB89E, 0x8F5A, 0xB89F, 0x8F61, 0xB8A0, 0x8F62, 0xB8A1, + 0x8F63, 0xB8A2, 0x8F64, 0xB8A3, 0x8F65, 0xB8A4, 0x8F66, 0xB8A5, 0x8F67, 0xB8A6, 0x8F68, 0xB8A7, 0x8F69, 0xB8A9, 0x8F6A, 0xB8AA, + 0x8F6B, 0xB8AB, 0x8F6C, 0xB8AC, 0x8F6D, 0xB8AD, 0x8F6E, 0xB8AE, 0x8F6F, 0xB8AF, 0x8F70, 0xB8B1, 0x8F71, 0xB8B2, 0x8F72, 0xB8B3, + 0x8F73, 0xB8B5, 0x8F74, 0xB8B6, 0x8F75, 0xB8B7, 0x8F76, 0xB8B9, 0x8F77, 0xB8BA, 0x8F78, 0xB8BB, 0x8F79, 0xB8BC, 0x8F7A, 0xB8BD, + 0x8F81, 0xB8BE, 0x8F82, 0xB8BF, 0x8F83, 0xB8C2, 0x8F84, 0xB8C4, 0x8F85, 0xB8C6, 0x8F86, 0xB8C7, 0x8F87, 0xB8C8, 0x8F88, 0xB8C9, + 0x8F89, 0xB8CA, 0x8F8A, 0xB8CB, 0x8F8B, 0xB8CD, 0x8F8C, 0xB8CE, 0x8F8D, 0xB8CF, 0x8F8E, 0xB8D1, 0x8F8F, 0xB8D2, 0x8F90, 0xB8D3, + 0x8F91, 0xB8D5, 0x8F92, 0xB8D6, 0x8F93, 0xB8D7, 0x8F94, 0xB8D8, 0x8F95, 0xB8D9, 0x8F96, 0xB8DA, 0x8F97, 0xB8DB, 0x8F98, 0xB8DC, + 0x8F99, 0xB8DE, 0x8F9A, 0xB8E0, 0x8F9B, 0xB8E2, 0x8F9C, 0xB8E3, 0x8F9D, 0xB8E4, 0x8F9E, 0xB8E5, 0x8F9F, 0xB8E6, 0x8FA0, 0xB8E7, + 0x8FA1, 0xB8EA, 0x8FA2, 0xB8EB, 0x8FA3, 0xB8ED, 0x8FA4, 0xB8EE, 0x8FA5, 0xB8EF, 0x8FA6, 0xB8F1, 0x8FA7, 0xB8F2, 0x8FA8, 0xB8F3, + 0x8FA9, 0xB8F4, 0x8FAA, 0xB8F5, 0x8FAB, 0xB8F6, 0x8FAC, 0xB8F7, 0x8FAD, 0xB8FA, 0x8FAE, 0xB8FC, 0x8FAF, 0xB8FE, 0x8FB0, 0xB8FF, + 0x8FB1, 0xB900, 0x8FB2, 0xB901, 0x8FB3, 0xB902, 0x8FB4, 0xB903, 0x8FB5, 0xB905, 0x8FB6, 0xB906, 0x8FB7, 0xB907, 0x8FB8, 0xB908, + 0x8FB9, 0xB909, 0x8FBA, 0xB90A, 0x8FBB, 0xB90B, 0x8FBC, 0xB90C, 0x8FBD, 0xB90D, 0x8FBE, 0xB90E, 0x8FBF, 0xB90F, 0x8FC0, 0xB910, + 0x8FC1, 0xB911, 0x8FC2, 0xB912, 0x8FC3, 0xB913, 0x8FC4, 0xB914, 0x8FC5, 0xB915, 0x8FC6, 0xB916, 0x8FC7, 0xB917, 0x8FC8, 0xB919, + 0x8FC9, 0xB91A, 0x8FCA, 0xB91B, 0x8FCB, 0xB91C, 0x8FCC, 0xB91D, 0x8FCD, 0xB91E, 0x8FCE, 0xB91F, 0x8FCF, 0xB921, 0x8FD0, 0xB922, + 0x8FD1, 0xB923, 0x8FD2, 0xB924, 0x8FD3, 0xB925, 0x8FD4, 0xB926, 0x8FD5, 0xB927, 0x8FD6, 0xB928, 0x8FD7, 0xB929, 0x8FD8, 0xB92A, + 0x8FD9, 0xB92B, 0x8FDA, 0xB92C, 0x8FDB, 0xB92D, 0x8FDC, 0xB92E, 0x8FDD, 0xB92F, 0x8FDE, 0xB930, 0x8FDF, 0xB931, 0x8FE0, 0xB932, + 0x8FE1, 0xB933, 0x8FE2, 0xB934, 0x8FE3, 0xB935, 0x8FE4, 0xB936, 0x8FE5, 0xB937, 0x8FE6, 0xB938, 0x8FE7, 0xB939, 0x8FE8, 0xB93A, + 0x8FE9, 0xB93B, 0x8FEA, 0xB93E, 0x8FEB, 0xB93F, 0x8FEC, 0xB941, 0x8FED, 0xB942, 0x8FEE, 0xB943, 0x8FEF, 0xB945, 0x8FF0, 0xB946, + 0x8FF1, 0xB947, 0x8FF2, 0xB948, 0x8FF3, 0xB949, 0x8FF4, 0xB94A, 0x8FF5, 0xB94B, 0x8FF6, 0xB94D, 0x8FF7, 0xB94E, 0x8FF8, 0xB950, + 0x8FF9, 0xB952, 0x8FFA, 0xB953, 0x8FFB, 0xB954, 0x8FFC, 0xB955, 0x8FFD, 0xB956, 0x8FFE, 0xB957, 0x9041, 0xB95A, 0x9042, 0xB95B, + 0x9043, 0xB95D, 0x9044, 0xB95E, 0x9045, 0xB95F, 0x9046, 0xB961, 0x9047, 0xB962, 0x9048, 0xB963, 0x9049, 0xB964, 0x904A, 0xB965, + 0x904B, 0xB966, 0x904C, 0xB967, 0x904D, 0xB96A, 0x904E, 0xB96C, 0x904F, 0xB96E, 0x9050, 0xB96F, 0x9051, 0xB970, 0x9052, 0xB971, + 0x9053, 0xB972, 0x9054, 0xB973, 0x9055, 0xB976, 0x9056, 0xB977, 0x9057, 0xB979, 0x9058, 0xB97A, 0x9059, 0xB97B, 0x905A, 0xB97D, + 0x9061, 0xB97E, 0x9062, 0xB97F, 0x9063, 0xB980, 0x9064, 0xB981, 0x9065, 0xB982, 0x9066, 0xB983, 0x9067, 0xB986, 0x9068, 0xB988, + 0x9069, 0xB98B, 0x906A, 0xB98C, 0x906B, 0xB98F, 0x906C, 0xB990, 0x906D, 0xB991, 0x906E, 0xB992, 0x906F, 0xB993, 0x9070, 0xB994, + 0x9071, 0xB995, 0x9072, 0xB996, 0x9073, 0xB997, 0x9074, 0xB998, 0x9075, 0xB999, 0x9076, 0xB99A, 0x9077, 0xB99B, 0x9078, 0xB99C, + 0x9079, 0xB99D, 0x907A, 0xB99E, 0x9081, 0xB99F, 0x9082, 0xB9A0, 0x9083, 0xB9A1, 0x9084, 0xB9A2, 0x9085, 0xB9A3, 0x9086, 0xB9A4, + 0x9087, 0xB9A5, 0x9088, 0xB9A6, 0x9089, 0xB9A7, 0x908A, 0xB9A8, 0x908B, 0xB9A9, 0x908C, 0xB9AA, 0x908D, 0xB9AB, 0x908E, 0xB9AE, + 0x908F, 0xB9AF, 0x9090, 0xB9B1, 0x9091, 0xB9B2, 0x9092, 0xB9B3, 0x9093, 0xB9B5, 0x9094, 0xB9B6, 0x9095, 0xB9B7, 0x9096, 0xB9B8, + 0x9097, 0xB9B9, 0x9098, 0xB9BA, 0x9099, 0xB9BB, 0x909A, 0xB9BE, 0x909B, 0xB9C0, 0x909C, 0xB9C2, 0x909D, 0xB9C3, 0x909E, 0xB9C4, + 0x909F, 0xB9C5, 0x90A0, 0xB9C6, 0x90A1, 0xB9C7, 0x90A2, 0xB9CA, 0x90A3, 0xB9CB, 0x90A4, 0xB9CD, 0x90A5, 0xB9D3, 0x90A6, 0xB9D4, + 0x90A7, 0xB9D5, 0x90A8, 0xB9D6, 0x90A9, 0xB9D7, 0x90AA, 0xB9DA, 0x90AB, 0xB9DC, 0x90AC, 0xB9DF, 0x90AD, 0xB9E0, 0x90AE, 0xB9E2, + 0x90AF, 0xB9E6, 0x90B0, 0xB9E7, 0x90B1, 0xB9E9, 0x90B2, 0xB9EA, 0x90B3, 0xB9EB, 0x90B4, 0xB9ED, 0x90B5, 0xB9EE, 0x90B6, 0xB9EF, + 0x90B7, 0xB9F0, 0x90B8, 0xB9F1, 0x90B9, 0xB9F2, 0x90BA, 0xB9F3, 0x90BB, 0xB9F6, 0x90BC, 0xB9FB, 0x90BD, 0xB9FC, 0x90BE, 0xB9FD, + 0x90BF, 0xB9FE, 0x90C0, 0xB9FF, 0x90C1, 0xBA02, 0x90C2, 0xBA03, 0x90C3, 0xBA04, 0x90C4, 0xBA05, 0x90C5, 0xBA06, 0x90C6, 0xBA07, + 0x90C7, 0xBA09, 0x90C8, 0xBA0A, 0x90C9, 0xBA0B, 0x90CA, 0xBA0C, 0x90CB, 0xBA0D, 0x90CC, 0xBA0E, 0x90CD, 0xBA0F, 0x90CE, 0xBA10, + 0x90CF, 0xBA11, 0x90D0, 0xBA12, 0x90D1, 0xBA13, 0x90D2, 0xBA14, 0x90D3, 0xBA16, 0x90D4, 0xBA17, 0x90D5, 0xBA18, 0x90D6, 0xBA19, + 0x90D7, 0xBA1A, 0x90D8, 0xBA1B, 0x90D9, 0xBA1C, 0x90DA, 0xBA1D, 0x90DB, 0xBA1E, 0x90DC, 0xBA1F, 0x90DD, 0xBA20, 0x90DE, 0xBA21, + 0x90DF, 0xBA22, 0x90E0, 0xBA23, 0x90E1, 0xBA24, 0x90E2, 0xBA25, 0x90E3, 0xBA26, 0x90E4, 0xBA27, 0x90E5, 0xBA28, 0x90E6, 0xBA29, + 0x90E7, 0xBA2A, 0x90E8, 0xBA2B, 0x90E9, 0xBA2C, 0x90EA, 0xBA2D, 0x90EB, 0xBA2E, 0x90EC, 0xBA2F, 0x90ED, 0xBA30, 0x90EE, 0xBA31, + 0x90EF, 0xBA32, 0x90F0, 0xBA33, 0x90F1, 0xBA34, 0x90F2, 0xBA35, 0x90F3, 0xBA36, 0x90F4, 0xBA37, 0x90F5, 0xBA3A, 0x90F6, 0xBA3B, + 0x90F7, 0xBA3D, 0x90F8, 0xBA3E, 0x90F9, 0xBA3F, 0x90FA, 0xBA41, 0x90FB, 0xBA43, 0x90FC, 0xBA44, 0x90FD, 0xBA45, 0x90FE, 0xBA46, + 0x9141, 0xBA47, 0x9142, 0xBA4A, 0x9143, 0xBA4C, 0x9144, 0xBA4F, 0x9145, 0xBA50, 0x9146, 0xBA51, 0x9147, 0xBA52, 0x9148, 0xBA56, + 0x9149, 0xBA57, 0x914A, 0xBA59, 0x914B, 0xBA5A, 0x914C, 0xBA5B, 0x914D, 0xBA5D, 0x914E, 0xBA5E, 0x914F, 0xBA5F, 0x9150, 0xBA60, + 0x9151, 0xBA61, 0x9152, 0xBA62, 0x9153, 0xBA63, 0x9154, 0xBA66, 0x9155, 0xBA6A, 0x9156, 0xBA6B, 0x9157, 0xBA6C, 0x9158, 0xBA6D, + 0x9159, 0xBA6E, 0x915A, 0xBA6F, 0x9161, 0xBA72, 0x9162, 0xBA73, 0x9163, 0xBA75, 0x9164, 0xBA76, 0x9165, 0xBA77, 0x9166, 0xBA79, + 0x9167, 0xBA7A, 0x9168, 0xBA7B, 0x9169, 0xBA7C, 0x916A, 0xBA7D, 0x916B, 0xBA7E, 0x916C, 0xBA7F, 0x916D, 0xBA80, 0x916E, 0xBA81, + 0x916F, 0xBA82, 0x9170, 0xBA86, 0x9171, 0xBA88, 0x9172, 0xBA89, 0x9173, 0xBA8A, 0x9174, 0xBA8B, 0x9175, 0xBA8D, 0x9176, 0xBA8E, + 0x9177, 0xBA8F, 0x9178, 0xBA90, 0x9179, 0xBA91, 0x917A, 0xBA92, 0x9181, 0xBA93, 0x9182, 0xBA94, 0x9183, 0xBA95, 0x9184, 0xBA96, + 0x9185, 0xBA97, 0x9186, 0xBA98, 0x9187, 0xBA99, 0x9188, 0xBA9A, 0x9189, 0xBA9B, 0x918A, 0xBA9C, 0x918B, 0xBA9D, 0x918C, 0xBA9E, + 0x918D, 0xBA9F, 0x918E, 0xBAA0, 0x918F, 0xBAA1, 0x9190, 0xBAA2, 0x9191, 0xBAA3, 0x9192, 0xBAA4, 0x9193, 0xBAA5, 0x9194, 0xBAA6, + 0x9195, 0xBAA7, 0x9196, 0xBAAA, 0x9197, 0xBAAD, 0x9198, 0xBAAE, 0x9199, 0xBAAF, 0x919A, 0xBAB1, 0x919B, 0xBAB3, 0x919C, 0xBAB4, + 0x919D, 0xBAB5, 0x919E, 0xBAB6, 0x919F, 0xBAB7, 0x91A0, 0xBABA, 0x91A1, 0xBABC, 0x91A2, 0xBABE, 0x91A3, 0xBABF, 0x91A4, 0xBAC0, + 0x91A5, 0xBAC1, 0x91A6, 0xBAC2, 0x91A7, 0xBAC3, 0x91A8, 0xBAC5, 0x91A9, 0xBAC6, 0x91AA, 0xBAC7, 0x91AB, 0xBAC9, 0x91AC, 0xBACA, + 0x91AD, 0xBACB, 0x91AE, 0xBACC, 0x91AF, 0xBACD, 0x91B0, 0xBACE, 0x91B1, 0xBACF, 0x91B2, 0xBAD0, 0x91B3, 0xBAD1, 0x91B4, 0xBAD2, + 0x91B5, 0xBAD3, 0x91B6, 0xBAD4, 0x91B7, 0xBAD5, 0x91B8, 0xBAD6, 0x91B9, 0xBAD7, 0x91BA, 0xBADA, 0x91BB, 0xBADB, 0x91BC, 0xBADC, + 0x91BD, 0xBADD, 0x91BE, 0xBADE, 0x91BF, 0xBADF, 0x91C0, 0xBAE0, 0x91C1, 0xBAE1, 0x91C2, 0xBAE2, 0x91C3, 0xBAE3, 0x91C4, 0xBAE4, + 0x91C5, 0xBAE5, 0x91C6, 0xBAE6, 0x91C7, 0xBAE7, 0x91C8, 0xBAE8, 0x91C9, 0xBAE9, 0x91CA, 0xBAEA, 0x91CB, 0xBAEB, 0x91CC, 0xBAEC, + 0x91CD, 0xBAED, 0x91CE, 0xBAEE, 0x91CF, 0xBAEF, 0x91D0, 0xBAF0, 0x91D1, 0xBAF1, 0x91D2, 0xBAF2, 0x91D3, 0xBAF3, 0x91D4, 0xBAF4, + 0x91D5, 0xBAF5, 0x91D6, 0xBAF6, 0x91D7, 0xBAF7, 0x91D8, 0xBAF8, 0x91D9, 0xBAF9, 0x91DA, 0xBAFA, 0x91DB, 0xBAFB, 0x91DC, 0xBAFD, + 0x91DD, 0xBAFE, 0x91DE, 0xBAFF, 0x91DF, 0xBB01, 0x91E0, 0xBB02, 0x91E1, 0xBB03, 0x91E2, 0xBB05, 0x91E3, 0xBB06, 0x91E4, 0xBB07, + 0x91E5, 0xBB08, 0x91E6, 0xBB09, 0x91E7, 0xBB0A, 0x91E8, 0xBB0B, 0x91E9, 0xBB0C, 0x91EA, 0xBB0E, 0x91EB, 0xBB10, 0x91EC, 0xBB12, + 0x91ED, 0xBB13, 0x91EE, 0xBB14, 0x91EF, 0xBB15, 0x91F0, 0xBB16, 0x91F1, 0xBB17, 0x91F2, 0xBB19, 0x91F3, 0xBB1A, 0x91F4, 0xBB1B, + 0x91F5, 0xBB1D, 0x91F6, 0xBB1E, 0x91F7, 0xBB1F, 0x91F8, 0xBB21, 0x91F9, 0xBB22, 0x91FA, 0xBB23, 0x91FB, 0xBB24, 0x91FC, 0xBB25, + 0x91FD, 0xBB26, 0x91FE, 0xBB27, 0x9241, 0xBB28, 0x9242, 0xBB2A, 0x9243, 0xBB2C, 0x9244, 0xBB2D, 0x9245, 0xBB2E, 0x9246, 0xBB2F, + 0x9247, 0xBB30, 0x9248, 0xBB31, 0x9249, 0xBB32, 0x924A, 0xBB33, 0x924B, 0xBB37, 0x924C, 0xBB39, 0x924D, 0xBB3A, 0x924E, 0xBB3F, + 0x924F, 0xBB40, 0x9250, 0xBB41, 0x9251, 0xBB42, 0x9252, 0xBB43, 0x9253, 0xBB46, 0x9254, 0xBB48, 0x9255, 0xBB4A, 0x9256, 0xBB4B, + 0x9257, 0xBB4C, 0x9258, 0xBB4E, 0x9259, 0xBB51, 0x925A, 0xBB52, 0x9261, 0xBB53, 0x9262, 0xBB55, 0x9263, 0xBB56, 0x9264, 0xBB57, + 0x9265, 0xBB59, 0x9266, 0xBB5A, 0x9267, 0xBB5B, 0x9268, 0xBB5C, 0x9269, 0xBB5D, 0x926A, 0xBB5E, 0x926B, 0xBB5F, 0x926C, 0xBB60, + 0x926D, 0xBB62, 0x926E, 0xBB64, 0x926F, 0xBB65, 0x9270, 0xBB66, 0x9271, 0xBB67, 0x9272, 0xBB68, 0x9273, 0xBB69, 0x9274, 0xBB6A, + 0x9275, 0xBB6B, 0x9276, 0xBB6D, 0x9277, 0xBB6E, 0x9278, 0xBB6F, 0x9279, 0xBB70, 0x927A, 0xBB71, 0x9281, 0xBB72, 0x9282, 0xBB73, + 0x9283, 0xBB74, 0x9284, 0xBB75, 0x9285, 0xBB76, 0x9286, 0xBB77, 0x9287, 0xBB78, 0x9288, 0xBB79, 0x9289, 0xBB7A, 0x928A, 0xBB7B, + 0x928B, 0xBB7C, 0x928C, 0xBB7D, 0x928D, 0xBB7E, 0x928E, 0xBB7F, 0x928F, 0xBB80, 0x9290, 0xBB81, 0x9291, 0xBB82, 0x9292, 0xBB83, + 0x9293, 0xBB84, 0x9294, 0xBB85, 0x9295, 0xBB86, 0x9296, 0xBB87, 0x9297, 0xBB89, 0x9298, 0xBB8A, 0x9299, 0xBB8B, 0x929A, 0xBB8D, + 0x929B, 0xBB8E, 0x929C, 0xBB8F, 0x929D, 0xBB91, 0x929E, 0xBB92, 0x929F, 0xBB93, 0x92A0, 0xBB94, 0x92A1, 0xBB95, 0x92A2, 0xBB96, + 0x92A3, 0xBB97, 0x92A4, 0xBB98, 0x92A5, 0xBB99, 0x92A6, 0xBB9A, 0x92A7, 0xBB9B, 0x92A8, 0xBB9C, 0x92A9, 0xBB9D, 0x92AA, 0xBB9E, + 0x92AB, 0xBB9F, 0x92AC, 0xBBA0, 0x92AD, 0xBBA1, 0x92AE, 0xBBA2, 0x92AF, 0xBBA3, 0x92B0, 0xBBA5, 0x92B1, 0xBBA6, 0x92B2, 0xBBA7, + 0x92B3, 0xBBA9, 0x92B4, 0xBBAA, 0x92B5, 0xBBAB, 0x92B6, 0xBBAD, 0x92B7, 0xBBAE, 0x92B8, 0xBBAF, 0x92B9, 0xBBB0, 0x92BA, 0xBBB1, + 0x92BB, 0xBBB2, 0x92BC, 0xBBB3, 0x92BD, 0xBBB5, 0x92BE, 0xBBB6, 0x92BF, 0xBBB8, 0x92C0, 0xBBB9, 0x92C1, 0xBBBA, 0x92C2, 0xBBBB, + 0x92C3, 0xBBBC, 0x92C4, 0xBBBD, 0x92C5, 0xBBBE, 0x92C6, 0xBBBF, 0x92C7, 0xBBC1, 0x92C8, 0xBBC2, 0x92C9, 0xBBC3, 0x92CA, 0xBBC5, + 0x92CB, 0xBBC6, 0x92CC, 0xBBC7, 0x92CD, 0xBBC9, 0x92CE, 0xBBCA, 0x92CF, 0xBBCB, 0x92D0, 0xBBCC, 0x92D1, 0xBBCD, 0x92D2, 0xBBCE, + 0x92D3, 0xBBCF, 0x92D4, 0xBBD1, 0x92D5, 0xBBD2, 0x92D6, 0xBBD4, 0x92D7, 0xBBD5, 0x92D8, 0xBBD6, 0x92D9, 0xBBD7, 0x92DA, 0xBBD8, + 0x92DB, 0xBBD9, 0x92DC, 0xBBDA, 0x92DD, 0xBBDB, 0x92DE, 0xBBDC, 0x92DF, 0xBBDD, 0x92E0, 0xBBDE, 0x92E1, 0xBBDF, 0x92E2, 0xBBE0, + 0x92E3, 0xBBE1, 0x92E4, 0xBBE2, 0x92E5, 0xBBE3, 0x92E6, 0xBBE4, 0x92E7, 0xBBE5, 0x92E8, 0xBBE6, 0x92E9, 0xBBE7, 0x92EA, 0xBBE8, + 0x92EB, 0xBBE9, 0x92EC, 0xBBEA, 0x92ED, 0xBBEB, 0x92EE, 0xBBEC, 0x92EF, 0xBBED, 0x92F0, 0xBBEE, 0x92F1, 0xBBEF, 0x92F2, 0xBBF0, + 0x92F3, 0xBBF1, 0x92F4, 0xBBF2, 0x92F5, 0xBBF3, 0x92F6, 0xBBF4, 0x92F7, 0xBBF5, 0x92F8, 0xBBF6, 0x92F9, 0xBBF7, 0x92FA, 0xBBFA, + 0x92FB, 0xBBFB, 0x92FC, 0xBBFD, 0x92FD, 0xBBFE, 0x92FE, 0xBC01, 0x9341, 0xBC03, 0x9342, 0xBC04, 0x9343, 0xBC05, 0x9344, 0xBC06, + 0x9345, 0xBC07, 0x9346, 0xBC0A, 0x9347, 0xBC0E, 0x9348, 0xBC10, 0x9349, 0xBC12, 0x934A, 0xBC13, 0x934B, 0xBC19, 0x934C, 0xBC1A, + 0x934D, 0xBC20, 0x934E, 0xBC21, 0x934F, 0xBC22, 0x9350, 0xBC23, 0x9351, 0xBC26, 0x9352, 0xBC28, 0x9353, 0xBC2A, 0x9354, 0xBC2B, + 0x9355, 0xBC2C, 0x9356, 0xBC2E, 0x9357, 0xBC2F, 0x9358, 0xBC32, 0x9359, 0xBC33, 0x935A, 0xBC35, 0x9361, 0xBC36, 0x9362, 0xBC37, + 0x9363, 0xBC39, 0x9364, 0xBC3A, 0x9365, 0xBC3B, 0x9366, 0xBC3C, 0x9367, 0xBC3D, 0x9368, 0xBC3E, 0x9369, 0xBC3F, 0x936A, 0xBC42, + 0x936B, 0xBC46, 0x936C, 0xBC47, 0x936D, 0xBC48, 0x936E, 0xBC4A, 0x936F, 0xBC4B, 0x9370, 0xBC4E, 0x9371, 0xBC4F, 0x9372, 0xBC51, + 0x9373, 0xBC52, 0x9374, 0xBC53, 0x9375, 0xBC54, 0x9376, 0xBC55, 0x9377, 0xBC56, 0x9378, 0xBC57, 0x9379, 0xBC58, 0x937A, 0xBC59, + 0x9381, 0xBC5A, 0x9382, 0xBC5B, 0x9383, 0xBC5C, 0x9384, 0xBC5E, 0x9385, 0xBC5F, 0x9386, 0xBC60, 0x9387, 0xBC61, 0x9388, 0xBC62, + 0x9389, 0xBC63, 0x938A, 0xBC64, 0x938B, 0xBC65, 0x938C, 0xBC66, 0x938D, 0xBC67, 0x938E, 0xBC68, 0x938F, 0xBC69, 0x9390, 0xBC6A, + 0x9391, 0xBC6B, 0x9392, 0xBC6C, 0x9393, 0xBC6D, 0x9394, 0xBC6E, 0x9395, 0xBC6F, 0x9396, 0xBC70, 0x9397, 0xBC71, 0x9398, 0xBC72, + 0x9399, 0xBC73, 0x939A, 0xBC74, 0x939B, 0xBC75, 0x939C, 0xBC76, 0x939D, 0xBC77, 0x939E, 0xBC78, 0x939F, 0xBC79, 0x93A0, 0xBC7A, + 0x93A1, 0xBC7B, 0x93A2, 0xBC7C, 0x93A3, 0xBC7D, 0x93A4, 0xBC7E, 0x93A5, 0xBC7F, 0x93A6, 0xBC80, 0x93A7, 0xBC81, 0x93A8, 0xBC82, + 0x93A9, 0xBC83, 0x93AA, 0xBC86, 0x93AB, 0xBC87, 0x93AC, 0xBC89, 0x93AD, 0xBC8A, 0x93AE, 0xBC8D, 0x93AF, 0xBC8F, 0x93B0, 0xBC90, + 0x93B1, 0xBC91, 0x93B2, 0xBC92, 0x93B3, 0xBC93, 0x93B4, 0xBC96, 0x93B5, 0xBC98, 0x93B6, 0xBC9B, 0x93B7, 0xBC9C, 0x93B8, 0xBC9D, + 0x93B9, 0xBC9E, 0x93BA, 0xBC9F, 0x93BB, 0xBCA2, 0x93BC, 0xBCA3, 0x93BD, 0xBCA5, 0x93BE, 0xBCA6, 0x93BF, 0xBCA9, 0x93C0, 0xBCAA, + 0x93C1, 0xBCAB, 0x93C2, 0xBCAC, 0x93C3, 0xBCAD, 0x93C4, 0xBCAE, 0x93C5, 0xBCAF, 0x93C6, 0xBCB2, 0x93C7, 0xBCB6, 0x93C8, 0xBCB7, + 0x93C9, 0xBCB8, 0x93CA, 0xBCB9, 0x93CB, 0xBCBA, 0x93CC, 0xBCBB, 0x93CD, 0xBCBE, 0x93CE, 0xBCBF, 0x93CF, 0xBCC1, 0x93D0, 0xBCC2, + 0x93D1, 0xBCC3, 0x93D2, 0xBCC5, 0x93D3, 0xBCC6, 0x93D4, 0xBCC7, 0x93D5, 0xBCC8, 0x93D6, 0xBCC9, 0x93D7, 0xBCCA, 0x93D8, 0xBCCB, + 0x93D9, 0xBCCC, 0x93DA, 0xBCCE, 0x93DB, 0xBCD2, 0x93DC, 0xBCD3, 0x93DD, 0xBCD4, 0x93DE, 0xBCD6, 0x93DF, 0xBCD7, 0x93E0, 0xBCD9, + 0x93E1, 0xBCDA, 0x93E2, 0xBCDB, 0x93E3, 0xBCDD, 0x93E4, 0xBCDE, 0x93E5, 0xBCDF, 0x93E6, 0xBCE0, 0x93E7, 0xBCE1, 0x93E8, 0xBCE2, + 0x93E9, 0xBCE3, 0x93EA, 0xBCE4, 0x93EB, 0xBCE5, 0x93EC, 0xBCE6, 0x93ED, 0xBCE7, 0x93EE, 0xBCE8, 0x93EF, 0xBCE9, 0x93F0, 0xBCEA, + 0x93F1, 0xBCEB, 0x93F2, 0xBCEC, 0x93F3, 0xBCED, 0x93F4, 0xBCEE, 0x93F5, 0xBCEF, 0x93F6, 0xBCF0, 0x93F7, 0xBCF1, 0x93F8, 0xBCF2, + 0x93F9, 0xBCF3, 0x93FA, 0xBCF7, 0x93FB, 0xBCF9, 0x93FC, 0xBCFA, 0x93FD, 0xBCFB, 0x93FE, 0xBCFD, 0x9441, 0xBCFE, 0x9442, 0xBCFF, + 0x9443, 0xBD00, 0x9444, 0xBD01, 0x9445, 0xBD02, 0x9446, 0xBD03, 0x9447, 0xBD06, 0x9448, 0xBD08, 0x9449, 0xBD0A, 0x944A, 0xBD0B, + 0x944B, 0xBD0C, 0x944C, 0xBD0D, 0x944D, 0xBD0E, 0x944E, 0xBD0F, 0x944F, 0xBD11, 0x9450, 0xBD12, 0x9451, 0xBD13, 0x9452, 0xBD15, + 0x9453, 0xBD16, 0x9454, 0xBD17, 0x9455, 0xBD18, 0x9456, 0xBD19, 0x9457, 0xBD1A, 0x9458, 0xBD1B, 0x9459, 0xBD1C, 0x945A, 0xBD1D, + 0x9461, 0xBD1E, 0x9462, 0xBD1F, 0x9463, 0xBD20, 0x9464, 0xBD21, 0x9465, 0xBD22, 0x9466, 0xBD23, 0x9467, 0xBD25, 0x9468, 0xBD26, + 0x9469, 0xBD27, 0x946A, 0xBD28, 0x946B, 0xBD29, 0x946C, 0xBD2A, 0x946D, 0xBD2B, 0x946E, 0xBD2D, 0x946F, 0xBD2E, 0x9470, 0xBD2F, + 0x9471, 0xBD30, 0x9472, 0xBD31, 0x9473, 0xBD32, 0x9474, 0xBD33, 0x9475, 0xBD34, 0x9476, 0xBD35, 0x9477, 0xBD36, 0x9478, 0xBD37, + 0x9479, 0xBD38, 0x947A, 0xBD39, 0x9481, 0xBD3A, 0x9482, 0xBD3B, 0x9483, 0xBD3C, 0x9484, 0xBD3D, 0x9485, 0xBD3E, 0x9486, 0xBD3F, + 0x9487, 0xBD41, 0x9488, 0xBD42, 0x9489, 0xBD43, 0x948A, 0xBD44, 0x948B, 0xBD45, 0x948C, 0xBD46, 0x948D, 0xBD47, 0x948E, 0xBD4A, + 0x948F, 0xBD4B, 0x9490, 0xBD4D, 0x9491, 0xBD4E, 0x9492, 0xBD4F, 0x9493, 0xBD51, 0x9494, 0xBD52, 0x9495, 0xBD53, 0x9496, 0xBD54, + 0x9497, 0xBD55, 0x9498, 0xBD56, 0x9499, 0xBD57, 0x949A, 0xBD5A, 0x949B, 0xBD5B, 0x949C, 0xBD5C, 0x949D, 0xBD5D, 0x949E, 0xBD5E, + 0x949F, 0xBD5F, 0x94A0, 0xBD60, 0x94A1, 0xBD61, 0x94A2, 0xBD62, 0x94A3, 0xBD63, 0x94A4, 0xBD65, 0x94A5, 0xBD66, 0x94A6, 0xBD67, + 0x94A7, 0xBD69, 0x94A8, 0xBD6A, 0x94A9, 0xBD6B, 0x94AA, 0xBD6C, 0x94AB, 0xBD6D, 0x94AC, 0xBD6E, 0x94AD, 0xBD6F, 0x94AE, 0xBD70, + 0x94AF, 0xBD71, 0x94B0, 0xBD72, 0x94B1, 0xBD73, 0x94B2, 0xBD74, 0x94B3, 0xBD75, 0x94B4, 0xBD76, 0x94B5, 0xBD77, 0x94B6, 0xBD78, + 0x94B7, 0xBD79, 0x94B8, 0xBD7A, 0x94B9, 0xBD7B, 0x94BA, 0xBD7C, 0x94BB, 0xBD7D, 0x94BC, 0xBD7E, 0x94BD, 0xBD7F, 0x94BE, 0xBD82, + 0x94BF, 0xBD83, 0x94C0, 0xBD85, 0x94C1, 0xBD86, 0x94C2, 0xBD8B, 0x94C3, 0xBD8C, 0x94C4, 0xBD8D, 0x94C5, 0xBD8E, 0x94C6, 0xBD8F, + 0x94C7, 0xBD92, 0x94C8, 0xBD94, 0x94C9, 0xBD96, 0x94CA, 0xBD97, 0x94CB, 0xBD98, 0x94CC, 0xBD9B, 0x94CD, 0xBD9D, 0x94CE, 0xBD9E, + 0x94CF, 0xBD9F, 0x94D0, 0xBDA0, 0x94D1, 0xBDA1, 0x94D2, 0xBDA2, 0x94D3, 0xBDA3, 0x94D4, 0xBDA5, 0x94D5, 0xBDA6, 0x94D6, 0xBDA7, + 0x94D7, 0xBDA8, 0x94D8, 0xBDA9, 0x94D9, 0xBDAA, 0x94DA, 0xBDAB, 0x94DB, 0xBDAC, 0x94DC, 0xBDAD, 0x94DD, 0xBDAE, 0x94DE, 0xBDAF, + 0x94DF, 0xBDB1, 0x94E0, 0xBDB2, 0x94E1, 0xBDB3, 0x94E2, 0xBDB4, 0x94E3, 0xBDB5, 0x94E4, 0xBDB6, 0x94E5, 0xBDB7, 0x94E6, 0xBDB9, + 0x94E7, 0xBDBA, 0x94E8, 0xBDBB, 0x94E9, 0xBDBC, 0x94EA, 0xBDBD, 0x94EB, 0xBDBE, 0x94EC, 0xBDBF, 0x94ED, 0xBDC0, 0x94EE, 0xBDC1, + 0x94EF, 0xBDC2, 0x94F0, 0xBDC3, 0x94F1, 0xBDC4, 0x94F2, 0xBDC5, 0x94F3, 0xBDC6, 0x94F4, 0xBDC7, 0x94F5, 0xBDC8, 0x94F6, 0xBDC9, + 0x94F7, 0xBDCA, 0x94F8, 0xBDCB, 0x94F9, 0xBDCC, 0x94FA, 0xBDCD, 0x94FB, 0xBDCE, 0x94FC, 0xBDCF, 0x94FD, 0xBDD0, 0x94FE, 0xBDD1, + 0x9541, 0xBDD2, 0x9542, 0xBDD3, 0x9543, 0xBDD6, 0x9544, 0xBDD7, 0x9545, 0xBDD9, 0x9546, 0xBDDA, 0x9547, 0xBDDB, 0x9548, 0xBDDD, + 0x9549, 0xBDDE, 0x954A, 0xBDDF, 0x954B, 0xBDE0, 0x954C, 0xBDE1, 0x954D, 0xBDE2, 0x954E, 0xBDE3, 0x954F, 0xBDE4, 0x9550, 0xBDE5, + 0x9551, 0xBDE6, 0x9552, 0xBDE7, 0x9553, 0xBDE8, 0x9554, 0xBDEA, 0x9555, 0xBDEB, 0x9556, 0xBDEC, 0x9557, 0xBDED, 0x9558, 0xBDEE, + 0x9559, 0xBDEF, 0x955A, 0xBDF1, 0x9561, 0xBDF2, 0x9562, 0xBDF3, 0x9563, 0xBDF5, 0x9564, 0xBDF6, 0x9565, 0xBDF7, 0x9566, 0xBDF9, + 0x9567, 0xBDFA, 0x9568, 0xBDFB, 0x9569, 0xBDFC, 0x956A, 0xBDFD, 0x956B, 0xBDFE, 0x956C, 0xBDFF, 0x956D, 0xBE01, 0x956E, 0xBE02, + 0x956F, 0xBE04, 0x9570, 0xBE06, 0x9571, 0xBE07, 0x9572, 0xBE08, 0x9573, 0xBE09, 0x9574, 0xBE0A, 0x9575, 0xBE0B, 0x9576, 0xBE0E, + 0x9577, 0xBE0F, 0x9578, 0xBE11, 0x9579, 0xBE12, 0x957A, 0xBE13, 0x9581, 0xBE15, 0x9582, 0xBE16, 0x9583, 0xBE17, 0x9584, 0xBE18, + 0x9585, 0xBE19, 0x9586, 0xBE1A, 0x9587, 0xBE1B, 0x9588, 0xBE1E, 0x9589, 0xBE20, 0x958A, 0xBE21, 0x958B, 0xBE22, 0x958C, 0xBE23, + 0x958D, 0xBE24, 0x958E, 0xBE25, 0x958F, 0xBE26, 0x9590, 0xBE27, 0x9591, 0xBE28, 0x9592, 0xBE29, 0x9593, 0xBE2A, 0x9594, 0xBE2B, + 0x9595, 0xBE2C, 0x9596, 0xBE2D, 0x9597, 0xBE2E, 0x9598, 0xBE2F, 0x9599, 0xBE30, 0x959A, 0xBE31, 0x959B, 0xBE32, 0x959C, 0xBE33, + 0x959D, 0xBE34, 0x959E, 0xBE35, 0x959F, 0xBE36, 0x95A0, 0xBE37, 0x95A1, 0xBE38, 0x95A2, 0xBE39, 0x95A3, 0xBE3A, 0x95A4, 0xBE3B, + 0x95A5, 0xBE3C, 0x95A6, 0xBE3D, 0x95A7, 0xBE3E, 0x95A8, 0xBE3F, 0x95A9, 0xBE40, 0x95AA, 0xBE41, 0x95AB, 0xBE42, 0x95AC, 0xBE43, + 0x95AD, 0xBE46, 0x95AE, 0xBE47, 0x95AF, 0xBE49, 0x95B0, 0xBE4A, 0x95B1, 0xBE4B, 0x95B2, 0xBE4D, 0x95B3, 0xBE4F, 0x95B4, 0xBE50, + 0x95B5, 0xBE51, 0x95B6, 0xBE52, 0x95B7, 0xBE53, 0x95B8, 0xBE56, 0x95B9, 0xBE58, 0x95BA, 0xBE5C, 0x95BB, 0xBE5D, 0x95BC, 0xBE5E, + 0x95BD, 0xBE5F, 0x95BE, 0xBE62, 0x95BF, 0xBE63, 0x95C0, 0xBE65, 0x95C1, 0xBE66, 0x95C2, 0xBE67, 0x95C3, 0xBE69, 0x95C4, 0xBE6B, + 0x95C5, 0xBE6C, 0x95C6, 0xBE6D, 0x95C7, 0xBE6E, 0x95C8, 0xBE6F, 0x95C9, 0xBE72, 0x95CA, 0xBE76, 0x95CB, 0xBE77, 0x95CC, 0xBE78, + 0x95CD, 0xBE79, 0x95CE, 0xBE7A, 0x95CF, 0xBE7E, 0x95D0, 0xBE7F, 0x95D1, 0xBE81, 0x95D2, 0xBE82, 0x95D3, 0xBE83, 0x95D4, 0xBE85, + 0x95D5, 0xBE86, 0x95D6, 0xBE87, 0x95D7, 0xBE88, 0x95D8, 0xBE89, 0x95D9, 0xBE8A, 0x95DA, 0xBE8B, 0x95DB, 0xBE8E, 0x95DC, 0xBE92, + 0x95DD, 0xBE93, 0x95DE, 0xBE94, 0x95DF, 0xBE95, 0x95E0, 0xBE96, 0x95E1, 0xBE97, 0x95E2, 0xBE9A, 0x95E3, 0xBE9B, 0x95E4, 0xBE9C, + 0x95E5, 0xBE9D, 0x95E6, 0xBE9E, 0x95E7, 0xBE9F, 0x95E8, 0xBEA0, 0x95E9, 0xBEA1, 0x95EA, 0xBEA2, 0x95EB, 0xBEA3, 0x95EC, 0xBEA4, + 0x95ED, 0xBEA5, 0x95EE, 0xBEA6, 0x95EF, 0xBEA7, 0x95F0, 0xBEA9, 0x95F1, 0xBEAA, 0x95F2, 0xBEAB, 0x95F3, 0xBEAC, 0x95F4, 0xBEAD, + 0x95F5, 0xBEAE, 0x95F6, 0xBEAF, 0x95F7, 0xBEB0, 0x95F8, 0xBEB1, 0x95F9, 0xBEB2, 0x95FA, 0xBEB3, 0x95FB, 0xBEB4, 0x95FC, 0xBEB5, + 0x95FD, 0xBEB6, 0x95FE, 0xBEB7, 0x9641, 0xBEB8, 0x9642, 0xBEB9, 0x9643, 0xBEBA, 0x9644, 0xBEBB, 0x9645, 0xBEBC, 0x9646, 0xBEBD, + 0x9647, 0xBEBE, 0x9648, 0xBEBF, 0x9649, 0xBEC0, 0x964A, 0xBEC1, 0x964B, 0xBEC2, 0x964C, 0xBEC3, 0x964D, 0xBEC4, 0x964E, 0xBEC5, + 0x964F, 0xBEC6, 0x9650, 0xBEC7, 0x9651, 0xBEC8, 0x9652, 0xBEC9, 0x9653, 0xBECA, 0x9654, 0xBECB, 0x9655, 0xBECC, 0x9656, 0xBECD, + 0x9657, 0xBECE, 0x9658, 0xBECF, 0x9659, 0xBED2, 0x965A, 0xBED3, 0x9661, 0xBED5, 0x9662, 0xBED6, 0x9663, 0xBED9, 0x9664, 0xBEDA, + 0x9665, 0xBEDB, 0x9666, 0xBEDC, 0x9667, 0xBEDD, 0x9668, 0xBEDE, 0x9669, 0xBEDF, 0x966A, 0xBEE1, 0x966B, 0xBEE2, 0x966C, 0xBEE6, + 0x966D, 0xBEE7, 0x966E, 0xBEE8, 0x966F, 0xBEE9, 0x9670, 0xBEEA, 0x9671, 0xBEEB, 0x9672, 0xBEED, 0x9673, 0xBEEE, 0x9674, 0xBEEF, + 0x9675, 0xBEF0, 0x9676, 0xBEF1, 0x9677, 0xBEF2, 0x9678, 0xBEF3, 0x9679, 0xBEF4, 0x967A, 0xBEF5, 0x9681, 0xBEF6, 0x9682, 0xBEF7, + 0x9683, 0xBEF8, 0x9684, 0xBEF9, 0x9685, 0xBEFA, 0x9686, 0xBEFB, 0x9687, 0xBEFC, 0x9688, 0xBEFD, 0x9689, 0xBEFE, 0x968A, 0xBEFF, + 0x968B, 0xBF00, 0x968C, 0xBF02, 0x968D, 0xBF03, 0x968E, 0xBF04, 0x968F, 0xBF05, 0x9690, 0xBF06, 0x9691, 0xBF07, 0x9692, 0xBF0A, + 0x9693, 0xBF0B, 0x9694, 0xBF0C, 0x9695, 0xBF0D, 0x9696, 0xBF0E, 0x9697, 0xBF0F, 0x9698, 0xBF10, 0x9699, 0xBF11, 0x969A, 0xBF12, + 0x969B, 0xBF13, 0x969C, 0xBF14, 0x969D, 0xBF15, 0x969E, 0xBF16, 0x969F, 0xBF17, 0x96A0, 0xBF1A, 0x96A1, 0xBF1E, 0x96A2, 0xBF1F, + 0x96A3, 0xBF20, 0x96A4, 0xBF21, 0x96A5, 0xBF22, 0x96A6, 0xBF23, 0x96A7, 0xBF24, 0x96A8, 0xBF25, 0x96A9, 0xBF26, 0x96AA, 0xBF27, + 0x96AB, 0xBF28, 0x96AC, 0xBF29, 0x96AD, 0xBF2A, 0x96AE, 0xBF2B, 0x96AF, 0xBF2C, 0x96B0, 0xBF2D, 0x96B1, 0xBF2E, 0x96B2, 0xBF2F, + 0x96B3, 0xBF30, 0x96B4, 0xBF31, 0x96B5, 0xBF32, 0x96B6, 0xBF33, 0x96B7, 0xBF34, 0x96B8, 0xBF35, 0x96B9, 0xBF36, 0x96BA, 0xBF37, + 0x96BB, 0xBF38, 0x96BC, 0xBF39, 0x96BD, 0xBF3A, 0x96BE, 0xBF3B, 0x96BF, 0xBF3C, 0x96C0, 0xBF3D, 0x96C1, 0xBF3E, 0x96C2, 0xBF3F, + 0x96C3, 0xBF42, 0x96C4, 0xBF43, 0x96C5, 0xBF45, 0x96C6, 0xBF46, 0x96C7, 0xBF47, 0x96C8, 0xBF49, 0x96C9, 0xBF4A, 0x96CA, 0xBF4B, + 0x96CB, 0xBF4C, 0x96CC, 0xBF4D, 0x96CD, 0xBF4E, 0x96CE, 0xBF4F, 0x96CF, 0xBF52, 0x96D0, 0xBF53, 0x96D1, 0xBF54, 0x96D2, 0xBF56, + 0x96D3, 0xBF57, 0x96D4, 0xBF58, 0x96D5, 0xBF59, 0x96D6, 0xBF5A, 0x96D7, 0xBF5B, 0x96D8, 0xBF5C, 0x96D9, 0xBF5D, 0x96DA, 0xBF5E, + 0x96DB, 0xBF5F, 0x96DC, 0xBF60, 0x96DD, 0xBF61, 0x96DE, 0xBF62, 0x96DF, 0xBF63, 0x96E0, 0xBF64, 0x96E1, 0xBF65, 0x96E2, 0xBF66, + 0x96E3, 0xBF67, 0x96E4, 0xBF68, 0x96E5, 0xBF69, 0x96E6, 0xBF6A, 0x96E7, 0xBF6B, 0x96E8, 0xBF6C, 0x96E9, 0xBF6D, 0x96EA, 0xBF6E, + 0x96EB, 0xBF6F, 0x96EC, 0xBF70, 0x96ED, 0xBF71, 0x96EE, 0xBF72, 0x96EF, 0xBF73, 0x96F0, 0xBF74, 0x96F1, 0xBF75, 0x96F2, 0xBF76, + 0x96F3, 0xBF77, 0x96F4, 0xBF78, 0x96F5, 0xBF79, 0x96F6, 0xBF7A, 0x96F7, 0xBF7B, 0x96F8, 0xBF7C, 0x96F9, 0xBF7D, 0x96FA, 0xBF7E, + 0x96FB, 0xBF7F, 0x96FC, 0xBF80, 0x96FD, 0xBF81, 0x96FE, 0xBF82, 0x9741, 0xBF83, 0x9742, 0xBF84, 0x9743, 0xBF85, 0x9744, 0xBF86, + 0x9745, 0xBF87, 0x9746, 0xBF88, 0x9747, 0xBF89, 0x9748, 0xBF8A, 0x9749, 0xBF8B, 0x974A, 0xBF8C, 0x974B, 0xBF8D, 0x974C, 0xBF8E, + 0x974D, 0xBF8F, 0x974E, 0xBF90, 0x974F, 0xBF91, 0x9750, 0xBF92, 0x9751, 0xBF93, 0x9752, 0xBF95, 0x9753, 0xBF96, 0x9754, 0xBF97, + 0x9755, 0xBF98, 0x9756, 0xBF99, 0x9757, 0xBF9A, 0x9758, 0xBF9B, 0x9759, 0xBF9C, 0x975A, 0xBF9D, 0x9761, 0xBF9E, 0x9762, 0xBF9F, + 0x9763, 0xBFA0, 0x9764, 0xBFA1, 0x9765, 0xBFA2, 0x9766, 0xBFA3, 0x9767, 0xBFA4, 0x9768, 0xBFA5, 0x9769, 0xBFA6, 0x976A, 0xBFA7, + 0x976B, 0xBFA8, 0x976C, 0xBFA9, 0x976D, 0xBFAA, 0x976E, 0xBFAB, 0x976F, 0xBFAC, 0x9770, 0xBFAD, 0x9771, 0xBFAE, 0x9772, 0xBFAF, + 0x9773, 0xBFB1, 0x9774, 0xBFB2, 0x9775, 0xBFB3, 0x9776, 0xBFB4, 0x9777, 0xBFB5, 0x9778, 0xBFB6, 0x9779, 0xBFB7, 0x977A, 0xBFB8, + 0x9781, 0xBFB9, 0x9782, 0xBFBA, 0x9783, 0xBFBB, 0x9784, 0xBFBC, 0x9785, 0xBFBD, 0x9786, 0xBFBE, 0x9787, 0xBFBF, 0x9788, 0xBFC0, + 0x9789, 0xBFC1, 0x978A, 0xBFC2, 0x978B, 0xBFC3, 0x978C, 0xBFC4, 0x978D, 0xBFC6, 0x978E, 0xBFC7, 0x978F, 0xBFC8, 0x9790, 0xBFC9, + 0x9791, 0xBFCA, 0x9792, 0xBFCB, 0x9793, 0xBFCE, 0x9794, 0xBFCF, 0x9795, 0xBFD1, 0x9796, 0xBFD2, 0x9797, 0xBFD3, 0x9798, 0xBFD5, + 0x9799, 0xBFD6, 0x979A, 0xBFD7, 0x979B, 0xBFD8, 0x979C, 0xBFD9, 0x979D, 0xBFDA, 0x979E, 0xBFDB, 0x979F, 0xBFDD, 0x97A0, 0xBFDE, + 0x97A1, 0xBFE0, 0x97A2, 0xBFE2, 0x97A3, 0xBFE3, 0x97A4, 0xBFE4, 0x97A5, 0xBFE5, 0x97A6, 0xBFE6, 0x97A7, 0xBFE7, 0x97A8, 0xBFE8, + 0x97A9, 0xBFE9, 0x97AA, 0xBFEA, 0x97AB, 0xBFEB, 0x97AC, 0xBFEC, 0x97AD, 0xBFED, 0x97AE, 0xBFEE, 0x97AF, 0xBFEF, 0x97B0, 0xBFF0, + 0x97B1, 0xBFF1, 0x97B2, 0xBFF2, 0x97B3, 0xBFF3, 0x97B4, 0xBFF4, 0x97B5, 0xBFF5, 0x97B6, 0xBFF6, 0x97B7, 0xBFF7, 0x97B8, 0xBFF8, + 0x97B9, 0xBFF9, 0x97BA, 0xBFFA, 0x97BB, 0xBFFB, 0x97BC, 0xBFFC, 0x97BD, 0xBFFD, 0x97BE, 0xBFFE, 0x97BF, 0xBFFF, 0x97C0, 0xC000, + 0x97C1, 0xC001, 0x97C2, 0xC002, 0x97C3, 0xC003, 0x97C4, 0xC004, 0x97C5, 0xC005, 0x97C6, 0xC006, 0x97C7, 0xC007, 0x97C8, 0xC008, + 0x97C9, 0xC009, 0x97CA, 0xC00A, 0x97CB, 0xC00B, 0x97CC, 0xC00C, 0x97CD, 0xC00D, 0x97CE, 0xC00E, 0x97CF, 0xC00F, 0x97D0, 0xC010, + 0x97D1, 0xC011, 0x97D2, 0xC012, 0x97D3, 0xC013, 0x97D4, 0xC014, 0x97D5, 0xC015, 0x97D6, 0xC016, 0x97D7, 0xC017, 0x97D8, 0xC018, + 0x97D9, 0xC019, 0x97DA, 0xC01A, 0x97DB, 0xC01B, 0x97DC, 0xC01C, 0x97DD, 0xC01D, 0x97DE, 0xC01E, 0x97DF, 0xC01F, 0x97E0, 0xC020, + 0x97E1, 0xC021, 0x97E2, 0xC022, 0x97E3, 0xC023, 0x97E4, 0xC024, 0x97E5, 0xC025, 0x97E6, 0xC026, 0x97E7, 0xC027, 0x97E8, 0xC028, + 0x97E9, 0xC029, 0x97EA, 0xC02A, 0x97EB, 0xC02B, 0x97EC, 0xC02C, 0x97ED, 0xC02D, 0x97EE, 0xC02E, 0x97EF, 0xC02F, 0x97F0, 0xC030, + 0x97F1, 0xC031, 0x97F2, 0xC032, 0x97F3, 0xC033, 0x97F4, 0xC034, 0x97F5, 0xC035, 0x97F6, 0xC036, 0x97F7, 0xC037, 0x97F8, 0xC038, + 0x97F9, 0xC039, 0x97FA, 0xC03A, 0x97FB, 0xC03B, 0x97FC, 0xC03D, 0x97FD, 0xC03E, 0x97FE, 0xC03F, 0x9841, 0xC040, 0x9842, 0xC041, + 0x9843, 0xC042, 0x9844, 0xC043, 0x9845, 0xC044, 0x9846, 0xC045, 0x9847, 0xC046, 0x9848, 0xC047, 0x9849, 0xC048, 0x984A, 0xC049, + 0x984B, 0xC04A, 0x984C, 0xC04B, 0x984D, 0xC04C, 0x984E, 0xC04D, 0x984F, 0xC04E, 0x9850, 0xC04F, 0x9851, 0xC050, 0x9852, 0xC052, + 0x9853, 0xC053, 0x9854, 0xC054, 0x9855, 0xC055, 0x9856, 0xC056, 0x9857, 0xC057, 0x9858, 0xC059, 0x9859, 0xC05A, 0x985A, 0xC05B, + 0x9861, 0xC05D, 0x9862, 0xC05E, 0x9863, 0xC05F, 0x9864, 0xC061, 0x9865, 0xC062, 0x9866, 0xC063, 0x9867, 0xC064, 0x9868, 0xC065, + 0x9869, 0xC066, 0x986A, 0xC067, 0x986B, 0xC06A, 0x986C, 0xC06B, 0x986D, 0xC06C, 0x986E, 0xC06D, 0x986F, 0xC06E, 0x9870, 0xC06F, + 0x9871, 0xC070, 0x9872, 0xC071, 0x9873, 0xC072, 0x9874, 0xC073, 0x9875, 0xC074, 0x9876, 0xC075, 0x9877, 0xC076, 0x9878, 0xC077, + 0x9879, 0xC078, 0x987A, 0xC079, 0x9881, 0xC07A, 0x9882, 0xC07B, 0x9883, 0xC07C, 0x9884, 0xC07D, 0x9885, 0xC07E, 0x9886, 0xC07F, + 0x9887, 0xC080, 0x9888, 0xC081, 0x9889, 0xC082, 0x988A, 0xC083, 0x988B, 0xC084, 0x988C, 0xC085, 0x988D, 0xC086, 0x988E, 0xC087, + 0x988F, 0xC088, 0x9890, 0xC089, 0x9891, 0xC08A, 0x9892, 0xC08B, 0x9893, 0xC08C, 0x9894, 0xC08D, 0x9895, 0xC08E, 0x9896, 0xC08F, + 0x9897, 0xC092, 0x9898, 0xC093, 0x9899, 0xC095, 0x989A, 0xC096, 0x989B, 0xC097, 0x989C, 0xC099, 0x989D, 0xC09A, 0x989E, 0xC09B, + 0x989F, 0xC09C, 0x98A0, 0xC09D, 0x98A1, 0xC09E, 0x98A2, 0xC09F, 0x98A3, 0xC0A2, 0x98A4, 0xC0A4, 0x98A5, 0xC0A6, 0x98A6, 0xC0A7, + 0x98A7, 0xC0A8, 0x98A8, 0xC0A9, 0x98A9, 0xC0AA, 0x98AA, 0xC0AB, 0x98AB, 0xC0AE, 0x98AC, 0xC0B1, 0x98AD, 0xC0B2, 0x98AE, 0xC0B7, + 0x98AF, 0xC0B8, 0x98B0, 0xC0B9, 0x98B1, 0xC0BA, 0x98B2, 0xC0BB, 0x98B3, 0xC0BE, 0x98B4, 0xC0C2, 0x98B5, 0xC0C3, 0x98B6, 0xC0C4, + 0x98B7, 0xC0C6, 0x98B8, 0xC0C7, 0x98B9, 0xC0CA, 0x98BA, 0xC0CB, 0x98BB, 0xC0CD, 0x98BC, 0xC0CE, 0x98BD, 0xC0CF, 0x98BE, 0xC0D1, + 0x98BF, 0xC0D2, 0x98C0, 0xC0D3, 0x98C1, 0xC0D4, 0x98C2, 0xC0D5, 0x98C3, 0xC0D6, 0x98C4, 0xC0D7, 0x98C5, 0xC0DA, 0x98C6, 0xC0DE, + 0x98C7, 0xC0DF, 0x98C8, 0xC0E0, 0x98C9, 0xC0E1, 0x98CA, 0xC0E2, 0x98CB, 0xC0E3, 0x98CC, 0xC0E6, 0x98CD, 0xC0E7, 0x98CE, 0xC0E9, + 0x98CF, 0xC0EA, 0x98D0, 0xC0EB, 0x98D1, 0xC0ED, 0x98D2, 0xC0EE, 0x98D3, 0xC0EF, 0x98D4, 0xC0F0, 0x98D5, 0xC0F1, 0x98D6, 0xC0F2, + 0x98D7, 0xC0F3, 0x98D8, 0xC0F6, 0x98D9, 0xC0F8, 0x98DA, 0xC0FA, 0x98DB, 0xC0FB, 0x98DC, 0xC0FC, 0x98DD, 0xC0FD, 0x98DE, 0xC0FE, + 0x98DF, 0xC0FF, 0x98E0, 0xC101, 0x98E1, 0xC102, 0x98E2, 0xC103, 0x98E3, 0xC105, 0x98E4, 0xC106, 0x98E5, 0xC107, 0x98E6, 0xC109, + 0x98E7, 0xC10A, 0x98E8, 0xC10B, 0x98E9, 0xC10C, 0x98EA, 0xC10D, 0x98EB, 0xC10E, 0x98EC, 0xC10F, 0x98ED, 0xC111, 0x98EE, 0xC112, + 0x98EF, 0xC113, 0x98F0, 0xC114, 0x98F1, 0xC116, 0x98F2, 0xC117, 0x98F3, 0xC118, 0x98F4, 0xC119, 0x98F5, 0xC11A, 0x98F6, 0xC11B, + 0x98F7, 0xC121, 0x98F8, 0xC122, 0x98F9, 0xC125, 0x98FA, 0xC128, 0x98FB, 0xC129, 0x98FC, 0xC12A, 0x98FD, 0xC12B, 0x98FE, 0xC12E, + 0x9941, 0xC132, 0x9942, 0xC133, 0x9943, 0xC134, 0x9944, 0xC135, 0x9945, 0xC137, 0x9946, 0xC13A, 0x9947, 0xC13B, 0x9948, 0xC13D, + 0x9949, 0xC13E, 0x994A, 0xC13F, 0x994B, 0xC141, 0x994C, 0xC142, 0x994D, 0xC143, 0x994E, 0xC144, 0x994F, 0xC145, 0x9950, 0xC146, + 0x9951, 0xC147, 0x9952, 0xC14A, 0x9953, 0xC14E, 0x9954, 0xC14F, 0x9955, 0xC150, 0x9956, 0xC151, 0x9957, 0xC152, 0x9958, 0xC153, + 0x9959, 0xC156, 0x995A, 0xC157, 0x9961, 0xC159, 0x9962, 0xC15A, 0x9963, 0xC15B, 0x9964, 0xC15D, 0x9965, 0xC15E, 0x9966, 0xC15F, + 0x9967, 0xC160, 0x9968, 0xC161, 0x9969, 0xC162, 0x996A, 0xC163, 0x996B, 0xC166, 0x996C, 0xC16A, 0x996D, 0xC16B, 0x996E, 0xC16C, + 0x996F, 0xC16D, 0x9970, 0xC16E, 0x9971, 0xC16F, 0x9972, 0xC171, 0x9973, 0xC172, 0x9974, 0xC173, 0x9975, 0xC175, 0x9976, 0xC176, + 0x9977, 0xC177, 0x9978, 0xC179, 0x9979, 0xC17A, 0x997A, 0xC17B, 0x9981, 0xC17C, 0x9982, 0xC17D, 0x9983, 0xC17E, 0x9984, 0xC17F, + 0x9985, 0xC180, 0x9986, 0xC181, 0x9987, 0xC182, 0x9988, 0xC183, 0x9989, 0xC184, 0x998A, 0xC186, 0x998B, 0xC187, 0x998C, 0xC188, + 0x998D, 0xC189, 0x998E, 0xC18A, 0x998F, 0xC18B, 0x9990, 0xC18F, 0x9991, 0xC191, 0x9992, 0xC192, 0x9993, 0xC193, 0x9994, 0xC195, + 0x9995, 0xC197, 0x9996, 0xC198, 0x9997, 0xC199, 0x9998, 0xC19A, 0x9999, 0xC19B, 0x999A, 0xC19E, 0x999B, 0xC1A0, 0x999C, 0xC1A2, + 0x999D, 0xC1A3, 0x999E, 0xC1A4, 0x999F, 0xC1A6, 0x99A0, 0xC1A7, 0x99A1, 0xC1AA, 0x99A2, 0xC1AB, 0x99A3, 0xC1AD, 0x99A4, 0xC1AE, + 0x99A5, 0xC1AF, 0x99A6, 0xC1B1, 0x99A7, 0xC1B2, 0x99A8, 0xC1B3, 0x99A9, 0xC1B4, 0x99AA, 0xC1B5, 0x99AB, 0xC1B6, 0x99AC, 0xC1B7, + 0x99AD, 0xC1B8, 0x99AE, 0xC1B9, 0x99AF, 0xC1BA, 0x99B0, 0xC1BB, 0x99B1, 0xC1BC, 0x99B2, 0xC1BE, 0x99B3, 0xC1BF, 0x99B4, 0xC1C0, + 0x99B5, 0xC1C1, 0x99B6, 0xC1C2, 0x99B7, 0xC1C3, 0x99B8, 0xC1C5, 0x99B9, 0xC1C6, 0x99BA, 0xC1C7, 0x99BB, 0xC1C9, 0x99BC, 0xC1CA, + 0x99BD, 0xC1CB, 0x99BE, 0xC1CD, 0x99BF, 0xC1CE, 0x99C0, 0xC1CF, 0x99C1, 0xC1D0, 0x99C2, 0xC1D1, 0x99C3, 0xC1D2, 0x99C4, 0xC1D3, + 0x99C5, 0xC1D5, 0x99C6, 0xC1D6, 0x99C7, 0xC1D9, 0x99C8, 0xC1DA, 0x99C9, 0xC1DB, 0x99CA, 0xC1DC, 0x99CB, 0xC1DD, 0x99CC, 0xC1DE, + 0x99CD, 0xC1DF, 0x99CE, 0xC1E1, 0x99CF, 0xC1E2, 0x99D0, 0xC1E3, 0x99D1, 0xC1E5, 0x99D2, 0xC1E6, 0x99D3, 0xC1E7, 0x99D4, 0xC1E9, + 0x99D5, 0xC1EA, 0x99D6, 0xC1EB, 0x99D7, 0xC1EC, 0x99D8, 0xC1ED, 0x99D9, 0xC1EE, 0x99DA, 0xC1EF, 0x99DB, 0xC1F2, 0x99DC, 0xC1F4, + 0x99DD, 0xC1F5, 0x99DE, 0xC1F6, 0x99DF, 0xC1F7, 0x99E0, 0xC1F8, 0x99E1, 0xC1F9, 0x99E2, 0xC1FA, 0x99E3, 0xC1FB, 0x99E4, 0xC1FE, + 0x99E5, 0xC1FF, 0x99E6, 0xC201, 0x99E7, 0xC202, 0x99E8, 0xC203, 0x99E9, 0xC205, 0x99EA, 0xC206, 0x99EB, 0xC207, 0x99EC, 0xC208, + 0x99ED, 0xC209, 0x99EE, 0xC20A, 0x99EF, 0xC20B, 0x99F0, 0xC20E, 0x99F1, 0xC210, 0x99F2, 0xC212, 0x99F3, 0xC213, 0x99F4, 0xC214, + 0x99F5, 0xC215, 0x99F6, 0xC216, 0x99F7, 0xC217, 0x99F8, 0xC21A, 0x99F9, 0xC21B, 0x99FA, 0xC21D, 0x99FB, 0xC21E, 0x99FC, 0xC221, + 0x99FD, 0xC222, 0x99FE, 0xC223, 0x9A41, 0xC224, 0x9A42, 0xC225, 0x9A43, 0xC226, 0x9A44, 0xC227, 0x9A45, 0xC22A, 0x9A46, 0xC22C, + 0x9A47, 0xC22E, 0x9A48, 0xC230, 0x9A49, 0xC233, 0x9A4A, 0xC235, 0x9A4B, 0xC236, 0x9A4C, 0xC237, 0x9A4D, 0xC238, 0x9A4E, 0xC239, + 0x9A4F, 0xC23A, 0x9A50, 0xC23B, 0x9A51, 0xC23C, 0x9A52, 0xC23D, 0x9A53, 0xC23E, 0x9A54, 0xC23F, 0x9A55, 0xC240, 0x9A56, 0xC241, + 0x9A57, 0xC242, 0x9A58, 0xC243, 0x9A59, 0xC244, 0x9A5A, 0xC245, 0x9A61, 0xC246, 0x9A62, 0xC247, 0x9A63, 0xC249, 0x9A64, 0xC24A, + 0x9A65, 0xC24B, 0x9A66, 0xC24C, 0x9A67, 0xC24D, 0x9A68, 0xC24E, 0x9A69, 0xC24F, 0x9A6A, 0xC252, 0x9A6B, 0xC253, 0x9A6C, 0xC255, + 0x9A6D, 0xC256, 0x9A6E, 0xC257, 0x9A6F, 0xC259, 0x9A70, 0xC25A, 0x9A71, 0xC25B, 0x9A72, 0xC25C, 0x9A73, 0xC25D, 0x9A74, 0xC25E, + 0x9A75, 0xC25F, 0x9A76, 0xC261, 0x9A77, 0xC262, 0x9A78, 0xC263, 0x9A79, 0xC264, 0x9A7A, 0xC266, 0x9A81, 0xC267, 0x9A82, 0xC268, + 0x9A83, 0xC269, 0x9A84, 0xC26A, 0x9A85, 0xC26B, 0x9A86, 0xC26E, 0x9A87, 0xC26F, 0x9A88, 0xC271, 0x9A89, 0xC272, 0x9A8A, 0xC273, + 0x9A8B, 0xC275, 0x9A8C, 0xC276, 0x9A8D, 0xC277, 0x9A8E, 0xC278, 0x9A8F, 0xC279, 0x9A90, 0xC27A, 0x9A91, 0xC27B, 0x9A92, 0xC27E, + 0x9A93, 0xC280, 0x9A94, 0xC282, 0x9A95, 0xC283, 0x9A96, 0xC284, 0x9A97, 0xC285, 0x9A98, 0xC286, 0x9A99, 0xC287, 0x9A9A, 0xC28A, + 0x9A9B, 0xC28B, 0x9A9C, 0xC28C, 0x9A9D, 0xC28D, 0x9A9E, 0xC28E, 0x9A9F, 0xC28F, 0x9AA0, 0xC291, 0x9AA1, 0xC292, 0x9AA2, 0xC293, + 0x9AA3, 0xC294, 0x9AA4, 0xC295, 0x9AA5, 0xC296, 0x9AA6, 0xC297, 0x9AA7, 0xC299, 0x9AA8, 0xC29A, 0x9AA9, 0xC29C, 0x9AAA, 0xC29E, + 0x9AAB, 0xC29F, 0x9AAC, 0xC2A0, 0x9AAD, 0xC2A1, 0x9AAE, 0xC2A2, 0x9AAF, 0xC2A3, 0x9AB0, 0xC2A6, 0x9AB1, 0xC2A7, 0x9AB2, 0xC2A9, + 0x9AB3, 0xC2AA, 0x9AB4, 0xC2AB, 0x9AB5, 0xC2AE, 0x9AB6, 0xC2AF, 0x9AB7, 0xC2B0, 0x9AB8, 0xC2B1, 0x9AB9, 0xC2B2, 0x9ABA, 0xC2B3, + 0x9ABB, 0xC2B6, 0x9ABC, 0xC2B8, 0x9ABD, 0xC2BA, 0x9ABE, 0xC2BB, 0x9ABF, 0xC2BC, 0x9AC0, 0xC2BD, 0x9AC1, 0xC2BE, 0x9AC2, 0xC2BF, + 0x9AC3, 0xC2C0, 0x9AC4, 0xC2C1, 0x9AC5, 0xC2C2, 0x9AC6, 0xC2C3, 0x9AC7, 0xC2C4, 0x9AC8, 0xC2C5, 0x9AC9, 0xC2C6, 0x9ACA, 0xC2C7, + 0x9ACB, 0xC2C8, 0x9ACC, 0xC2C9, 0x9ACD, 0xC2CA, 0x9ACE, 0xC2CB, 0x9ACF, 0xC2CC, 0x9AD0, 0xC2CD, 0x9AD1, 0xC2CE, 0x9AD2, 0xC2CF, + 0x9AD3, 0xC2D0, 0x9AD4, 0xC2D1, 0x9AD5, 0xC2D2, 0x9AD6, 0xC2D3, 0x9AD7, 0xC2D4, 0x9AD8, 0xC2D5, 0x9AD9, 0xC2D6, 0x9ADA, 0xC2D7, + 0x9ADB, 0xC2D8, 0x9ADC, 0xC2D9, 0x9ADD, 0xC2DA, 0x9ADE, 0xC2DB, 0x9ADF, 0xC2DE, 0x9AE0, 0xC2DF, 0x9AE1, 0xC2E1, 0x9AE2, 0xC2E2, + 0x9AE3, 0xC2E5, 0x9AE4, 0xC2E6, 0x9AE5, 0xC2E7, 0x9AE6, 0xC2E8, 0x9AE7, 0xC2E9, 0x9AE8, 0xC2EA, 0x9AE9, 0xC2EE, 0x9AEA, 0xC2F0, + 0x9AEB, 0xC2F2, 0x9AEC, 0xC2F3, 0x9AED, 0xC2F4, 0x9AEE, 0xC2F5, 0x9AEF, 0xC2F7, 0x9AF0, 0xC2FA, 0x9AF1, 0xC2FD, 0x9AF2, 0xC2FE, + 0x9AF3, 0xC2FF, 0x9AF4, 0xC301, 0x9AF5, 0xC302, 0x9AF6, 0xC303, 0x9AF7, 0xC304, 0x9AF8, 0xC305, 0x9AF9, 0xC306, 0x9AFA, 0xC307, + 0x9AFB, 0xC30A, 0x9AFC, 0xC30B, 0x9AFD, 0xC30E, 0x9AFE, 0xC30F, 0x9B41, 0xC310, 0x9B42, 0xC311, 0x9B43, 0xC312, 0x9B44, 0xC316, + 0x9B45, 0xC317, 0x9B46, 0xC319, 0x9B47, 0xC31A, 0x9B48, 0xC31B, 0x9B49, 0xC31D, 0x9B4A, 0xC31E, 0x9B4B, 0xC31F, 0x9B4C, 0xC320, + 0x9B4D, 0xC321, 0x9B4E, 0xC322, 0x9B4F, 0xC323, 0x9B50, 0xC326, 0x9B51, 0xC327, 0x9B52, 0xC32A, 0x9B53, 0xC32B, 0x9B54, 0xC32C, + 0x9B55, 0xC32D, 0x9B56, 0xC32E, 0x9B57, 0xC32F, 0x9B58, 0xC330, 0x9B59, 0xC331, 0x9B5A, 0xC332, 0x9B61, 0xC333, 0x9B62, 0xC334, + 0x9B63, 0xC335, 0x9B64, 0xC336, 0x9B65, 0xC337, 0x9B66, 0xC338, 0x9B67, 0xC339, 0x9B68, 0xC33A, 0x9B69, 0xC33B, 0x9B6A, 0xC33C, + 0x9B6B, 0xC33D, 0x9B6C, 0xC33E, 0x9B6D, 0xC33F, 0x9B6E, 0xC340, 0x9B6F, 0xC341, 0x9B70, 0xC342, 0x9B71, 0xC343, 0x9B72, 0xC344, + 0x9B73, 0xC346, 0x9B74, 0xC347, 0x9B75, 0xC348, 0x9B76, 0xC349, 0x9B77, 0xC34A, 0x9B78, 0xC34B, 0x9B79, 0xC34C, 0x9B7A, 0xC34D, + 0x9B81, 0xC34E, 0x9B82, 0xC34F, 0x9B83, 0xC350, 0x9B84, 0xC351, 0x9B85, 0xC352, 0x9B86, 0xC353, 0x9B87, 0xC354, 0x9B88, 0xC355, + 0x9B89, 0xC356, 0x9B8A, 0xC357, 0x9B8B, 0xC358, 0x9B8C, 0xC359, 0x9B8D, 0xC35A, 0x9B8E, 0xC35B, 0x9B8F, 0xC35C, 0x9B90, 0xC35D, + 0x9B91, 0xC35E, 0x9B92, 0xC35F, 0x9B93, 0xC360, 0x9B94, 0xC361, 0x9B95, 0xC362, 0x9B96, 0xC363, 0x9B97, 0xC364, 0x9B98, 0xC365, + 0x9B99, 0xC366, 0x9B9A, 0xC367, 0x9B9B, 0xC36A, 0x9B9C, 0xC36B, 0x9B9D, 0xC36D, 0x9B9E, 0xC36E, 0x9B9F, 0xC36F, 0x9BA0, 0xC371, + 0x9BA1, 0xC373, 0x9BA2, 0xC374, 0x9BA3, 0xC375, 0x9BA4, 0xC376, 0x9BA5, 0xC377, 0x9BA6, 0xC37A, 0x9BA7, 0xC37B, 0x9BA8, 0xC37E, + 0x9BA9, 0xC37F, 0x9BAA, 0xC380, 0x9BAB, 0xC381, 0x9BAC, 0xC382, 0x9BAD, 0xC383, 0x9BAE, 0xC385, 0x9BAF, 0xC386, 0x9BB0, 0xC387, + 0x9BB1, 0xC389, 0x9BB2, 0xC38A, 0x9BB3, 0xC38B, 0x9BB4, 0xC38D, 0x9BB5, 0xC38E, 0x9BB6, 0xC38F, 0x9BB7, 0xC390, 0x9BB8, 0xC391, + 0x9BB9, 0xC392, 0x9BBA, 0xC393, 0x9BBB, 0xC394, 0x9BBC, 0xC395, 0x9BBD, 0xC396, 0x9BBE, 0xC397, 0x9BBF, 0xC398, 0x9BC0, 0xC399, + 0x9BC1, 0xC39A, 0x9BC2, 0xC39B, 0x9BC3, 0xC39C, 0x9BC4, 0xC39D, 0x9BC5, 0xC39E, 0x9BC6, 0xC39F, 0x9BC7, 0xC3A0, 0x9BC8, 0xC3A1, + 0x9BC9, 0xC3A2, 0x9BCA, 0xC3A3, 0x9BCB, 0xC3A4, 0x9BCC, 0xC3A5, 0x9BCD, 0xC3A6, 0x9BCE, 0xC3A7, 0x9BCF, 0xC3A8, 0x9BD0, 0xC3A9, + 0x9BD1, 0xC3AA, 0x9BD2, 0xC3AB, 0x9BD3, 0xC3AC, 0x9BD4, 0xC3AD, 0x9BD5, 0xC3AE, 0x9BD6, 0xC3AF, 0x9BD7, 0xC3B0, 0x9BD8, 0xC3B1, + 0x9BD9, 0xC3B2, 0x9BDA, 0xC3B3, 0x9BDB, 0xC3B4, 0x9BDC, 0xC3B5, 0x9BDD, 0xC3B6, 0x9BDE, 0xC3B7, 0x9BDF, 0xC3B8, 0x9BE0, 0xC3B9, + 0x9BE1, 0xC3BA, 0x9BE2, 0xC3BB, 0x9BE3, 0xC3BC, 0x9BE4, 0xC3BD, 0x9BE5, 0xC3BE, 0x9BE6, 0xC3BF, 0x9BE7, 0xC3C1, 0x9BE8, 0xC3C2, + 0x9BE9, 0xC3C3, 0x9BEA, 0xC3C4, 0x9BEB, 0xC3C5, 0x9BEC, 0xC3C6, 0x9BED, 0xC3C7, 0x9BEE, 0xC3C8, 0x9BEF, 0xC3C9, 0x9BF0, 0xC3CA, + 0x9BF1, 0xC3CB, 0x9BF2, 0xC3CC, 0x9BF3, 0xC3CD, 0x9BF4, 0xC3CE, 0x9BF5, 0xC3CF, 0x9BF6, 0xC3D0, 0x9BF7, 0xC3D1, 0x9BF8, 0xC3D2, + 0x9BF9, 0xC3D3, 0x9BFA, 0xC3D4, 0x9BFB, 0xC3D5, 0x9BFC, 0xC3D6, 0x9BFD, 0xC3D7, 0x9BFE, 0xC3DA, 0x9C41, 0xC3DB, 0x9C42, 0xC3DD, + 0x9C43, 0xC3DE, 0x9C44, 0xC3E1, 0x9C45, 0xC3E3, 0x9C46, 0xC3E4, 0x9C47, 0xC3E5, 0x9C48, 0xC3E6, 0x9C49, 0xC3E7, 0x9C4A, 0xC3EA, + 0x9C4B, 0xC3EB, 0x9C4C, 0xC3EC, 0x9C4D, 0xC3EE, 0x9C4E, 0xC3EF, 0x9C4F, 0xC3F0, 0x9C50, 0xC3F1, 0x9C51, 0xC3F2, 0x9C52, 0xC3F3, + 0x9C53, 0xC3F6, 0x9C54, 0xC3F7, 0x9C55, 0xC3F9, 0x9C56, 0xC3FA, 0x9C57, 0xC3FB, 0x9C58, 0xC3FC, 0x9C59, 0xC3FD, 0x9C5A, 0xC3FE, + 0x9C61, 0xC3FF, 0x9C62, 0xC400, 0x9C63, 0xC401, 0x9C64, 0xC402, 0x9C65, 0xC403, 0x9C66, 0xC404, 0x9C67, 0xC405, 0x9C68, 0xC406, + 0x9C69, 0xC407, 0x9C6A, 0xC409, 0x9C6B, 0xC40A, 0x9C6C, 0xC40B, 0x9C6D, 0xC40C, 0x9C6E, 0xC40D, 0x9C6F, 0xC40E, 0x9C70, 0xC40F, + 0x9C71, 0xC411, 0x9C72, 0xC412, 0x9C73, 0xC413, 0x9C74, 0xC414, 0x9C75, 0xC415, 0x9C76, 0xC416, 0x9C77, 0xC417, 0x9C78, 0xC418, + 0x9C79, 0xC419, 0x9C7A, 0xC41A, 0x9C81, 0xC41B, 0x9C82, 0xC41C, 0x9C83, 0xC41D, 0x9C84, 0xC41E, 0x9C85, 0xC41F, 0x9C86, 0xC420, + 0x9C87, 0xC421, 0x9C88, 0xC422, 0x9C89, 0xC423, 0x9C8A, 0xC425, 0x9C8B, 0xC426, 0x9C8C, 0xC427, 0x9C8D, 0xC428, 0x9C8E, 0xC429, + 0x9C8F, 0xC42A, 0x9C90, 0xC42B, 0x9C91, 0xC42D, 0x9C92, 0xC42E, 0x9C93, 0xC42F, 0x9C94, 0xC431, 0x9C95, 0xC432, 0x9C96, 0xC433, + 0x9C97, 0xC435, 0x9C98, 0xC436, 0x9C99, 0xC437, 0x9C9A, 0xC438, 0x9C9B, 0xC439, 0x9C9C, 0xC43A, 0x9C9D, 0xC43B, 0x9C9E, 0xC43E, + 0x9C9F, 0xC43F, 0x9CA0, 0xC440, 0x9CA1, 0xC441, 0x9CA2, 0xC442, 0x9CA3, 0xC443, 0x9CA4, 0xC444, 0x9CA5, 0xC445, 0x9CA6, 0xC446, + 0x9CA7, 0xC447, 0x9CA8, 0xC449, 0x9CA9, 0xC44A, 0x9CAA, 0xC44B, 0x9CAB, 0xC44C, 0x9CAC, 0xC44D, 0x9CAD, 0xC44E, 0x9CAE, 0xC44F, + 0x9CAF, 0xC450, 0x9CB0, 0xC451, 0x9CB1, 0xC452, 0x9CB2, 0xC453, 0x9CB3, 0xC454, 0x9CB4, 0xC455, 0x9CB5, 0xC456, 0x9CB6, 0xC457, + 0x9CB7, 0xC458, 0x9CB8, 0xC459, 0x9CB9, 0xC45A, 0x9CBA, 0xC45B, 0x9CBB, 0xC45C, 0x9CBC, 0xC45D, 0x9CBD, 0xC45E, 0x9CBE, 0xC45F, + 0x9CBF, 0xC460, 0x9CC0, 0xC461, 0x9CC1, 0xC462, 0x9CC2, 0xC463, 0x9CC3, 0xC466, 0x9CC4, 0xC467, 0x9CC5, 0xC469, 0x9CC6, 0xC46A, + 0x9CC7, 0xC46B, 0x9CC8, 0xC46D, 0x9CC9, 0xC46E, 0x9CCA, 0xC46F, 0x9CCB, 0xC470, 0x9CCC, 0xC471, 0x9CCD, 0xC472, 0x9CCE, 0xC473, + 0x9CCF, 0xC476, 0x9CD0, 0xC477, 0x9CD1, 0xC478, 0x9CD2, 0xC47A, 0x9CD3, 0xC47B, 0x9CD4, 0xC47C, 0x9CD5, 0xC47D, 0x9CD6, 0xC47E, + 0x9CD7, 0xC47F, 0x9CD8, 0xC481, 0x9CD9, 0xC482, 0x9CDA, 0xC483, 0x9CDB, 0xC484, 0x9CDC, 0xC485, 0x9CDD, 0xC486, 0x9CDE, 0xC487, + 0x9CDF, 0xC488, 0x9CE0, 0xC489, 0x9CE1, 0xC48A, 0x9CE2, 0xC48B, 0x9CE3, 0xC48C, 0x9CE4, 0xC48D, 0x9CE5, 0xC48E, 0x9CE6, 0xC48F, + 0x9CE7, 0xC490, 0x9CE8, 0xC491, 0x9CE9, 0xC492, 0x9CEA, 0xC493, 0x9CEB, 0xC495, 0x9CEC, 0xC496, 0x9CED, 0xC497, 0x9CEE, 0xC498, + 0x9CEF, 0xC499, 0x9CF0, 0xC49A, 0x9CF1, 0xC49B, 0x9CF2, 0xC49D, 0x9CF3, 0xC49E, 0x9CF4, 0xC49F, 0x9CF5, 0xC4A0, 0x9CF6, 0xC4A1, + 0x9CF7, 0xC4A2, 0x9CF8, 0xC4A3, 0x9CF9, 0xC4A4, 0x9CFA, 0xC4A5, 0x9CFB, 0xC4A6, 0x9CFC, 0xC4A7, 0x9CFD, 0xC4A8, 0x9CFE, 0xC4A9, + 0x9D41, 0xC4AA, 0x9D42, 0xC4AB, 0x9D43, 0xC4AC, 0x9D44, 0xC4AD, 0x9D45, 0xC4AE, 0x9D46, 0xC4AF, 0x9D47, 0xC4B0, 0x9D48, 0xC4B1, + 0x9D49, 0xC4B2, 0x9D4A, 0xC4B3, 0x9D4B, 0xC4B4, 0x9D4C, 0xC4B5, 0x9D4D, 0xC4B6, 0x9D4E, 0xC4B7, 0x9D4F, 0xC4B9, 0x9D50, 0xC4BA, + 0x9D51, 0xC4BB, 0x9D52, 0xC4BD, 0x9D53, 0xC4BE, 0x9D54, 0xC4BF, 0x9D55, 0xC4C0, 0x9D56, 0xC4C1, 0x9D57, 0xC4C2, 0x9D58, 0xC4C3, + 0x9D59, 0xC4C4, 0x9D5A, 0xC4C5, 0x9D61, 0xC4C6, 0x9D62, 0xC4C7, 0x9D63, 0xC4C8, 0x9D64, 0xC4C9, 0x9D65, 0xC4CA, 0x9D66, 0xC4CB, + 0x9D67, 0xC4CC, 0x9D68, 0xC4CD, 0x9D69, 0xC4CE, 0x9D6A, 0xC4CF, 0x9D6B, 0xC4D0, 0x9D6C, 0xC4D1, 0x9D6D, 0xC4D2, 0x9D6E, 0xC4D3, + 0x9D6F, 0xC4D4, 0x9D70, 0xC4D5, 0x9D71, 0xC4D6, 0x9D72, 0xC4D7, 0x9D73, 0xC4D8, 0x9D74, 0xC4D9, 0x9D75, 0xC4DA, 0x9D76, 0xC4DB, + 0x9D77, 0xC4DC, 0x9D78, 0xC4DD, 0x9D79, 0xC4DE, 0x9D7A, 0xC4DF, 0x9D81, 0xC4E0, 0x9D82, 0xC4E1, 0x9D83, 0xC4E2, 0x9D84, 0xC4E3, + 0x9D85, 0xC4E4, 0x9D86, 0xC4E5, 0x9D87, 0xC4E6, 0x9D88, 0xC4E7, 0x9D89, 0xC4E8, 0x9D8A, 0xC4EA, 0x9D8B, 0xC4EB, 0x9D8C, 0xC4EC, + 0x9D8D, 0xC4ED, 0x9D8E, 0xC4EE, 0x9D8F, 0xC4EF, 0x9D90, 0xC4F2, 0x9D91, 0xC4F3, 0x9D92, 0xC4F5, 0x9D93, 0xC4F6, 0x9D94, 0xC4F7, + 0x9D95, 0xC4F9, 0x9D96, 0xC4FB, 0x9D97, 0xC4FC, 0x9D98, 0xC4FD, 0x9D99, 0xC4FE, 0x9D9A, 0xC502, 0x9D9B, 0xC503, 0x9D9C, 0xC504, + 0x9D9D, 0xC505, 0x9D9E, 0xC506, 0x9D9F, 0xC507, 0x9DA0, 0xC508, 0x9DA1, 0xC509, 0x9DA2, 0xC50A, 0x9DA3, 0xC50B, 0x9DA4, 0xC50D, + 0x9DA5, 0xC50E, 0x9DA6, 0xC50F, 0x9DA7, 0xC511, 0x9DA8, 0xC512, 0x9DA9, 0xC513, 0x9DAA, 0xC515, 0x9DAB, 0xC516, 0x9DAC, 0xC517, + 0x9DAD, 0xC518, 0x9DAE, 0xC519, 0x9DAF, 0xC51A, 0x9DB0, 0xC51B, 0x9DB1, 0xC51D, 0x9DB2, 0xC51E, 0x9DB3, 0xC51F, 0x9DB4, 0xC520, + 0x9DB5, 0xC521, 0x9DB6, 0xC522, 0x9DB7, 0xC523, 0x9DB8, 0xC524, 0x9DB9, 0xC525, 0x9DBA, 0xC526, 0x9DBB, 0xC527, 0x9DBC, 0xC52A, + 0x9DBD, 0xC52B, 0x9DBE, 0xC52D, 0x9DBF, 0xC52E, 0x9DC0, 0xC52F, 0x9DC1, 0xC531, 0x9DC2, 0xC532, 0x9DC3, 0xC533, 0x9DC4, 0xC534, + 0x9DC5, 0xC535, 0x9DC6, 0xC536, 0x9DC7, 0xC537, 0x9DC8, 0xC53A, 0x9DC9, 0xC53C, 0x9DCA, 0xC53E, 0x9DCB, 0xC53F, 0x9DCC, 0xC540, + 0x9DCD, 0xC541, 0x9DCE, 0xC542, 0x9DCF, 0xC543, 0x9DD0, 0xC546, 0x9DD1, 0xC547, 0x9DD2, 0xC54B, 0x9DD3, 0xC54F, 0x9DD4, 0xC550, + 0x9DD5, 0xC551, 0x9DD6, 0xC552, 0x9DD7, 0xC556, 0x9DD8, 0xC55A, 0x9DD9, 0xC55B, 0x9DDA, 0xC55C, 0x9DDB, 0xC55F, 0x9DDC, 0xC562, + 0x9DDD, 0xC563, 0x9DDE, 0xC565, 0x9DDF, 0xC566, 0x9DE0, 0xC567, 0x9DE1, 0xC569, 0x9DE2, 0xC56A, 0x9DE3, 0xC56B, 0x9DE4, 0xC56C, + 0x9DE5, 0xC56D, 0x9DE6, 0xC56E, 0x9DE7, 0xC56F, 0x9DE8, 0xC572, 0x9DE9, 0xC576, 0x9DEA, 0xC577, 0x9DEB, 0xC578, 0x9DEC, 0xC579, + 0x9DED, 0xC57A, 0x9DEE, 0xC57B, 0x9DEF, 0xC57E, 0x9DF0, 0xC57F, 0x9DF1, 0xC581, 0x9DF2, 0xC582, 0x9DF3, 0xC583, 0x9DF4, 0xC585, + 0x9DF5, 0xC586, 0x9DF6, 0xC588, 0x9DF7, 0xC589, 0x9DF8, 0xC58A, 0x9DF9, 0xC58B, 0x9DFA, 0xC58E, 0x9DFB, 0xC590, 0x9DFC, 0xC592, + 0x9DFD, 0xC593, 0x9DFE, 0xC594, 0x9E41, 0xC596, 0x9E42, 0xC599, 0x9E43, 0xC59A, 0x9E44, 0xC59B, 0x9E45, 0xC59D, 0x9E46, 0xC59E, + 0x9E47, 0xC59F, 0x9E48, 0xC5A1, 0x9E49, 0xC5A2, 0x9E4A, 0xC5A3, 0x9E4B, 0xC5A4, 0x9E4C, 0xC5A5, 0x9E4D, 0xC5A6, 0x9E4E, 0xC5A7, + 0x9E4F, 0xC5A8, 0x9E50, 0xC5AA, 0x9E51, 0xC5AB, 0x9E52, 0xC5AC, 0x9E53, 0xC5AD, 0x9E54, 0xC5AE, 0x9E55, 0xC5AF, 0x9E56, 0xC5B0, + 0x9E57, 0xC5B1, 0x9E58, 0xC5B2, 0x9E59, 0xC5B3, 0x9E5A, 0xC5B6, 0x9E61, 0xC5B7, 0x9E62, 0xC5BA, 0x9E63, 0xC5BF, 0x9E64, 0xC5C0, + 0x9E65, 0xC5C1, 0x9E66, 0xC5C2, 0x9E67, 0xC5C3, 0x9E68, 0xC5CB, 0x9E69, 0xC5CD, 0x9E6A, 0xC5CF, 0x9E6B, 0xC5D2, 0x9E6C, 0xC5D3, + 0x9E6D, 0xC5D5, 0x9E6E, 0xC5D6, 0x9E6F, 0xC5D7, 0x9E70, 0xC5D9, 0x9E71, 0xC5DA, 0x9E72, 0xC5DB, 0x9E73, 0xC5DC, 0x9E74, 0xC5DD, + 0x9E75, 0xC5DE, 0x9E76, 0xC5DF, 0x9E77, 0xC5E2, 0x9E78, 0xC5E4, 0x9E79, 0xC5E6, 0x9E7A, 0xC5E7, 0x9E81, 0xC5E8, 0x9E82, 0xC5E9, + 0x9E83, 0xC5EA, 0x9E84, 0xC5EB, 0x9E85, 0xC5EF, 0x9E86, 0xC5F1, 0x9E87, 0xC5F2, 0x9E88, 0xC5F3, 0x9E89, 0xC5F5, 0x9E8A, 0xC5F8, + 0x9E8B, 0xC5F9, 0x9E8C, 0xC5FA, 0x9E8D, 0xC5FB, 0x9E8E, 0xC602, 0x9E8F, 0xC603, 0x9E90, 0xC604, 0x9E91, 0xC609, 0x9E92, 0xC60A, + 0x9E93, 0xC60B, 0x9E94, 0xC60D, 0x9E95, 0xC60E, 0x9E96, 0xC60F, 0x9E97, 0xC611, 0x9E98, 0xC612, 0x9E99, 0xC613, 0x9E9A, 0xC614, + 0x9E9B, 0xC615, 0x9E9C, 0xC616, 0x9E9D, 0xC617, 0x9E9E, 0xC61A, 0x9E9F, 0xC61D, 0x9EA0, 0xC61E, 0x9EA1, 0xC61F, 0x9EA2, 0xC620, + 0x9EA3, 0xC621, 0x9EA4, 0xC622, 0x9EA5, 0xC623, 0x9EA6, 0xC626, 0x9EA7, 0xC627, 0x9EA8, 0xC629, 0x9EA9, 0xC62A, 0x9EAA, 0xC62B, + 0x9EAB, 0xC62F, 0x9EAC, 0xC631, 0x9EAD, 0xC632, 0x9EAE, 0xC636, 0x9EAF, 0xC638, 0x9EB0, 0xC63A, 0x9EB1, 0xC63C, 0x9EB2, 0xC63D, + 0x9EB3, 0xC63E, 0x9EB4, 0xC63F, 0x9EB5, 0xC642, 0x9EB6, 0xC643, 0x9EB7, 0xC645, 0x9EB8, 0xC646, 0x9EB9, 0xC647, 0x9EBA, 0xC649, + 0x9EBB, 0xC64A, 0x9EBC, 0xC64B, 0x9EBD, 0xC64C, 0x9EBE, 0xC64D, 0x9EBF, 0xC64E, 0x9EC0, 0xC64F, 0x9EC1, 0xC652, 0x9EC2, 0xC656, + 0x9EC3, 0xC657, 0x9EC4, 0xC658, 0x9EC5, 0xC659, 0x9EC6, 0xC65A, 0x9EC7, 0xC65B, 0x9EC8, 0xC65E, 0x9EC9, 0xC65F, 0x9ECA, 0xC661, + 0x9ECB, 0xC662, 0x9ECC, 0xC663, 0x9ECD, 0xC664, 0x9ECE, 0xC665, 0x9ECF, 0xC666, 0x9ED0, 0xC667, 0x9ED1, 0xC668, 0x9ED2, 0xC669, + 0x9ED3, 0xC66A, 0x9ED4, 0xC66B, 0x9ED5, 0xC66D, 0x9ED6, 0xC66E, 0x9ED7, 0xC670, 0x9ED8, 0xC672, 0x9ED9, 0xC673, 0x9EDA, 0xC674, + 0x9EDB, 0xC675, 0x9EDC, 0xC676, 0x9EDD, 0xC677, 0x9EDE, 0xC67A, 0x9EDF, 0xC67B, 0x9EE0, 0xC67D, 0x9EE1, 0xC67E, 0x9EE2, 0xC67F, + 0x9EE3, 0xC681, 0x9EE4, 0xC682, 0x9EE5, 0xC683, 0x9EE6, 0xC684, 0x9EE7, 0xC685, 0x9EE8, 0xC686, 0x9EE9, 0xC687, 0x9EEA, 0xC68A, + 0x9EEB, 0xC68C, 0x9EEC, 0xC68E, 0x9EED, 0xC68F, 0x9EEE, 0xC690, 0x9EEF, 0xC691, 0x9EF0, 0xC692, 0x9EF1, 0xC693, 0x9EF2, 0xC696, + 0x9EF3, 0xC697, 0x9EF4, 0xC699, 0x9EF5, 0xC69A, 0x9EF6, 0xC69B, 0x9EF7, 0xC69D, 0x9EF8, 0xC69E, 0x9EF9, 0xC69F, 0x9EFA, 0xC6A0, + 0x9EFB, 0xC6A1, 0x9EFC, 0xC6A2, 0x9EFD, 0xC6A3, 0x9EFE, 0xC6A6, 0x9F41, 0xC6A8, 0x9F42, 0xC6AA, 0x9F43, 0xC6AB, 0x9F44, 0xC6AC, + 0x9F45, 0xC6AD, 0x9F46, 0xC6AE, 0x9F47, 0xC6AF, 0x9F48, 0xC6B2, 0x9F49, 0xC6B3, 0x9F4A, 0xC6B5, 0x9F4B, 0xC6B6, 0x9F4C, 0xC6B7, + 0x9F4D, 0xC6BB, 0x9F4E, 0xC6BC, 0x9F4F, 0xC6BD, 0x9F50, 0xC6BE, 0x9F51, 0xC6BF, 0x9F52, 0xC6C2, 0x9F53, 0xC6C4, 0x9F54, 0xC6C6, + 0x9F55, 0xC6C7, 0x9F56, 0xC6C8, 0x9F57, 0xC6C9, 0x9F58, 0xC6CA, 0x9F59, 0xC6CB, 0x9F5A, 0xC6CE, 0x9F61, 0xC6CF, 0x9F62, 0xC6D1, + 0x9F63, 0xC6D2, 0x9F64, 0xC6D3, 0x9F65, 0xC6D5, 0x9F66, 0xC6D6, 0x9F67, 0xC6D7, 0x9F68, 0xC6D8, 0x9F69, 0xC6D9, 0x9F6A, 0xC6DA, + 0x9F6B, 0xC6DB, 0x9F6C, 0xC6DE, 0x9F6D, 0xC6DF, 0x9F6E, 0xC6E2, 0x9F6F, 0xC6E3, 0x9F70, 0xC6E4, 0x9F71, 0xC6E5, 0x9F72, 0xC6E6, + 0x9F73, 0xC6E7, 0x9F74, 0xC6EA, 0x9F75, 0xC6EB, 0x9F76, 0xC6ED, 0x9F77, 0xC6EE, 0x9F78, 0xC6EF, 0x9F79, 0xC6F1, 0x9F7A, 0xC6F2, + 0x9F81, 0xC6F3, 0x9F82, 0xC6F4, 0x9F83, 0xC6F5, 0x9F84, 0xC6F6, 0x9F85, 0xC6F7, 0x9F86, 0xC6FA, 0x9F87, 0xC6FB, 0x9F88, 0xC6FC, + 0x9F89, 0xC6FE, 0x9F8A, 0xC6FF, 0x9F8B, 0xC700, 0x9F8C, 0xC701, 0x9F8D, 0xC702, 0x9F8E, 0xC703, 0x9F8F, 0xC706, 0x9F90, 0xC707, + 0x9F91, 0xC709, 0x9F92, 0xC70A, 0x9F93, 0xC70B, 0x9F94, 0xC70D, 0x9F95, 0xC70E, 0x9F96, 0xC70F, 0x9F97, 0xC710, 0x9F98, 0xC711, + 0x9F99, 0xC712, 0x9F9A, 0xC713, 0x9F9B, 0xC716, 0x9F9C, 0xC718, 0x9F9D, 0xC71A, 0x9F9E, 0xC71B, 0x9F9F, 0xC71C, 0x9FA0, 0xC71D, + 0x9FA1, 0xC71E, 0x9FA2, 0xC71F, 0x9FA3, 0xC722, 0x9FA4, 0xC723, 0x9FA5, 0xC725, 0x9FA6, 0xC726, 0x9FA7, 0xC727, 0x9FA8, 0xC729, + 0x9FA9, 0xC72A, 0x9FAA, 0xC72B, 0x9FAB, 0xC72C, 0x9FAC, 0xC72D, 0x9FAD, 0xC72E, 0x9FAE, 0xC72F, 0x9FAF, 0xC732, 0x9FB0, 0xC734, + 0x9FB1, 0xC736, 0x9FB2, 0xC738, 0x9FB3, 0xC739, 0x9FB4, 0xC73A, 0x9FB5, 0xC73B, 0x9FB6, 0xC73E, 0x9FB7, 0xC73F, 0x9FB8, 0xC741, + 0x9FB9, 0xC742, 0x9FBA, 0xC743, 0x9FBB, 0xC745, 0x9FBC, 0xC746, 0x9FBD, 0xC747, 0x9FBE, 0xC748, 0x9FBF, 0xC749, 0x9FC0, 0xC74B, + 0x9FC1, 0xC74E, 0x9FC2, 0xC750, 0x9FC3, 0xC759, 0x9FC4, 0xC75A, 0x9FC5, 0xC75B, 0x9FC6, 0xC75D, 0x9FC7, 0xC75E, 0x9FC8, 0xC75F, + 0x9FC9, 0xC761, 0x9FCA, 0xC762, 0x9FCB, 0xC763, 0x9FCC, 0xC764, 0x9FCD, 0xC765, 0x9FCE, 0xC766, 0x9FCF, 0xC767, 0x9FD0, 0xC769, + 0x9FD1, 0xC76A, 0x9FD2, 0xC76C, 0x9FD3, 0xC76D, 0x9FD4, 0xC76E, 0x9FD5, 0xC76F, 0x9FD6, 0xC770, 0x9FD7, 0xC771, 0x9FD8, 0xC772, + 0x9FD9, 0xC773, 0x9FDA, 0xC776, 0x9FDB, 0xC777, 0x9FDC, 0xC779, 0x9FDD, 0xC77A, 0x9FDE, 0xC77B, 0x9FDF, 0xC77F, 0x9FE0, 0xC780, + 0x9FE1, 0xC781, 0x9FE2, 0xC782, 0x9FE3, 0xC786, 0x9FE4, 0xC78B, 0x9FE5, 0xC78C, 0x9FE6, 0xC78D, 0x9FE7, 0xC78F, 0x9FE8, 0xC792, + 0x9FE9, 0xC793, 0x9FEA, 0xC795, 0x9FEB, 0xC799, 0x9FEC, 0xC79B, 0x9FED, 0xC79C, 0x9FEE, 0xC79D, 0x9FEF, 0xC79E, 0x9FF0, 0xC79F, + 0x9FF1, 0xC7A2, 0x9FF2, 0xC7A7, 0x9FF3, 0xC7A8, 0x9FF4, 0xC7A9, 0x9FF5, 0xC7AA, 0x9FF6, 0xC7AB, 0x9FF7, 0xC7AE, 0x9FF8, 0xC7AF, + 0x9FF9, 0xC7B1, 0x9FFA, 0xC7B2, 0x9FFB, 0xC7B3, 0x9FFC, 0xC7B5, 0x9FFD, 0xC7B6, 0x9FFE, 0xC7B7, 0xA041, 0xC7B8, 0xA042, 0xC7B9, + 0xA043, 0xC7BA, 0xA044, 0xC7BB, 0xA045, 0xC7BE, 0xA046, 0xC7C2, 0xA047, 0xC7C3, 0xA048, 0xC7C4, 0xA049, 0xC7C5, 0xA04A, 0xC7C6, + 0xA04B, 0xC7C7, 0xA04C, 0xC7CA, 0xA04D, 0xC7CB, 0xA04E, 0xC7CD, 0xA04F, 0xC7CF, 0xA050, 0xC7D1, 0xA051, 0xC7D2, 0xA052, 0xC7D3, + 0xA053, 0xC7D4, 0xA054, 0xC7D5, 0xA055, 0xC7D6, 0xA056, 0xC7D7, 0xA057, 0xC7D9, 0xA058, 0xC7DA, 0xA059, 0xC7DB, 0xA05A, 0xC7DC, + 0xA061, 0xC7DE, 0xA062, 0xC7DF, 0xA063, 0xC7E0, 0xA064, 0xC7E1, 0xA065, 0xC7E2, 0xA066, 0xC7E3, 0xA067, 0xC7E5, 0xA068, 0xC7E6, + 0xA069, 0xC7E7, 0xA06A, 0xC7E9, 0xA06B, 0xC7EA, 0xA06C, 0xC7EB, 0xA06D, 0xC7ED, 0xA06E, 0xC7EE, 0xA06F, 0xC7EF, 0xA070, 0xC7F0, + 0xA071, 0xC7F1, 0xA072, 0xC7F2, 0xA073, 0xC7F3, 0xA074, 0xC7F4, 0xA075, 0xC7F5, 0xA076, 0xC7F6, 0xA077, 0xC7F7, 0xA078, 0xC7F8, + 0xA079, 0xC7F9, 0xA07A, 0xC7FA, 0xA081, 0xC7FB, 0xA082, 0xC7FC, 0xA083, 0xC7FD, 0xA084, 0xC7FE, 0xA085, 0xC7FF, 0xA086, 0xC802, + 0xA087, 0xC803, 0xA088, 0xC805, 0xA089, 0xC806, 0xA08A, 0xC807, 0xA08B, 0xC809, 0xA08C, 0xC80B, 0xA08D, 0xC80C, 0xA08E, 0xC80D, + 0xA08F, 0xC80E, 0xA090, 0xC80F, 0xA091, 0xC812, 0xA092, 0xC814, 0xA093, 0xC817, 0xA094, 0xC818, 0xA095, 0xC819, 0xA096, 0xC81A, + 0xA097, 0xC81B, 0xA098, 0xC81E, 0xA099, 0xC81F, 0xA09A, 0xC821, 0xA09B, 0xC822, 0xA09C, 0xC823, 0xA09D, 0xC825, 0xA09E, 0xC826, + 0xA09F, 0xC827, 0xA0A0, 0xC828, 0xA0A1, 0xC829, 0xA0A2, 0xC82A, 0xA0A3, 0xC82B, 0xA0A4, 0xC82E, 0xA0A5, 0xC830, 0xA0A6, 0xC832, + 0xA0A7, 0xC833, 0xA0A8, 0xC834, 0xA0A9, 0xC835, 0xA0AA, 0xC836, 0xA0AB, 0xC837, 0xA0AC, 0xC839, 0xA0AD, 0xC83A, 0xA0AE, 0xC83B, + 0xA0AF, 0xC83D, 0xA0B0, 0xC83E, 0xA0B1, 0xC83F, 0xA0B2, 0xC841, 0xA0B3, 0xC842, 0xA0B4, 0xC843, 0xA0B5, 0xC844, 0xA0B6, 0xC845, + 0xA0B7, 0xC846, 0xA0B8, 0xC847, 0xA0B9, 0xC84A, 0xA0BA, 0xC84B, 0xA0BB, 0xC84E, 0xA0BC, 0xC84F, 0xA0BD, 0xC850, 0xA0BE, 0xC851, + 0xA0BF, 0xC852, 0xA0C0, 0xC853, 0xA0C1, 0xC855, 0xA0C2, 0xC856, 0xA0C3, 0xC857, 0xA0C4, 0xC858, 0xA0C5, 0xC859, 0xA0C6, 0xC85A, + 0xA0C7, 0xC85B, 0xA0C8, 0xC85C, 0xA0C9, 0xC85D, 0xA0CA, 0xC85E, 0xA0CB, 0xC85F, 0xA0CC, 0xC860, 0xA0CD, 0xC861, 0xA0CE, 0xC862, + 0xA0CF, 0xC863, 0xA0D0, 0xC864, 0xA0D1, 0xC865, 0xA0D2, 0xC866, 0xA0D3, 0xC867, 0xA0D4, 0xC868, 0xA0D5, 0xC869, 0xA0D6, 0xC86A, + 0xA0D7, 0xC86B, 0xA0D8, 0xC86C, 0xA0D9, 0xC86D, 0xA0DA, 0xC86E, 0xA0DB, 0xC86F, 0xA0DC, 0xC872, 0xA0DD, 0xC873, 0xA0DE, 0xC875, + 0xA0DF, 0xC876, 0xA0E0, 0xC877, 0xA0E1, 0xC879, 0xA0E2, 0xC87B, 0xA0E3, 0xC87C, 0xA0E4, 0xC87D, 0xA0E5, 0xC87E, 0xA0E6, 0xC87F, + 0xA0E7, 0xC882, 0xA0E8, 0xC884, 0xA0E9, 0xC888, 0xA0EA, 0xC889, 0xA0EB, 0xC88A, 0xA0EC, 0xC88E, 0xA0ED, 0xC88F, 0xA0EE, 0xC890, + 0xA0EF, 0xC891, 0xA0F0, 0xC892, 0xA0F1, 0xC893, 0xA0F2, 0xC895, 0xA0F3, 0xC896, 0xA0F4, 0xC897, 0xA0F5, 0xC898, 0xA0F6, 0xC899, + 0xA0F7, 0xC89A, 0xA0F8, 0xC89B, 0xA0F9, 0xC89C, 0xA0FA, 0xC89E, 0xA0FB, 0xC8A0, 0xA0FC, 0xC8A2, 0xA0FD, 0xC8A3, 0xA0FE, 0xC8A4, + 0xA141, 0xC8A5, 0xA142, 0xC8A6, 0xA143, 0xC8A7, 0xA144, 0xC8A9, 0xA145, 0xC8AA, 0xA146, 0xC8AB, 0xA147, 0xC8AC, 0xA148, 0xC8AD, + 0xA149, 0xC8AE, 0xA14A, 0xC8AF, 0xA14B, 0xC8B0, 0xA14C, 0xC8B1, 0xA14D, 0xC8B2, 0xA14E, 0xC8B3, 0xA14F, 0xC8B4, 0xA150, 0xC8B5, + 0xA151, 0xC8B6, 0xA152, 0xC8B7, 0xA153, 0xC8B8, 0xA154, 0xC8B9, 0xA155, 0xC8BA, 0xA156, 0xC8BB, 0xA157, 0xC8BE, 0xA158, 0xC8BF, + 0xA159, 0xC8C0, 0xA15A, 0xC8C1, 0xA161, 0xC8C2, 0xA162, 0xC8C3, 0xA163, 0xC8C5, 0xA164, 0xC8C6, 0xA165, 0xC8C7, 0xA166, 0xC8C9, + 0xA167, 0xC8CA, 0xA168, 0xC8CB, 0xA169, 0xC8CD, 0xA16A, 0xC8CE, 0xA16B, 0xC8CF, 0xA16C, 0xC8D0, 0xA16D, 0xC8D1, 0xA16E, 0xC8D2, + 0xA16F, 0xC8D3, 0xA170, 0xC8D6, 0xA171, 0xC8D8, 0xA172, 0xC8DA, 0xA173, 0xC8DB, 0xA174, 0xC8DC, 0xA175, 0xC8DD, 0xA176, 0xC8DE, + 0xA177, 0xC8DF, 0xA178, 0xC8E2, 0xA179, 0xC8E3, 0xA17A, 0xC8E5, 0xA181, 0xC8E6, 0xA182, 0xC8E7, 0xA183, 0xC8E8, 0xA184, 0xC8E9, + 0xA185, 0xC8EA, 0xA186, 0xC8EB, 0xA187, 0xC8EC, 0xA188, 0xC8ED, 0xA189, 0xC8EE, 0xA18A, 0xC8EF, 0xA18B, 0xC8F0, 0xA18C, 0xC8F1, + 0xA18D, 0xC8F2, 0xA18E, 0xC8F3, 0xA18F, 0xC8F4, 0xA190, 0xC8F6, 0xA191, 0xC8F7, 0xA192, 0xC8F8, 0xA193, 0xC8F9, 0xA194, 0xC8FA, + 0xA195, 0xC8FB, 0xA196, 0xC8FE, 0xA197, 0xC8FF, 0xA198, 0xC901, 0xA199, 0xC902, 0xA19A, 0xC903, 0xA19B, 0xC907, 0xA19C, 0xC908, + 0xA19D, 0xC909, 0xA19E, 0xC90A, 0xA19F, 0xC90B, 0xA1A0, 0xC90E, 0xA1A1, 0x3000, 0xA1A2, 0x3001, 0xA1A3, 0x3002, 0xA1A4, 0x00B7, + 0xA1A5, 0x2025, 0xA1A6, 0x2026, 0xA1A7, 0x00A8, 0xA1A8, 0x3003, 0xA1A9, 0x00AD, 0xA1AA, 0x2015, 0xA1AB, 0x2225, 0xA1AC, 0xFF3C, + 0xA1AD, 0x223C, 0xA1AE, 0x2018, 0xA1AF, 0x2019, 0xA1B0, 0x201C, 0xA1B1, 0x201D, 0xA1B2, 0x3014, 0xA1B3, 0x3015, 0xA1B4, 0x3008, + 0xA1B5, 0x3009, 0xA1B6, 0x300A, 0xA1B7, 0x300B, 0xA1B8, 0x300C, 0xA1B9, 0x300D, 0xA1BA, 0x300E, 0xA1BB, 0x300F, 0xA1BC, 0x3010, + 0xA1BD, 0x3011, 0xA1BE, 0x00B1, 0xA1BF, 0x00D7, 0xA1C0, 0x00F7, 0xA1C1, 0x2260, 0xA1C2, 0x2264, 0xA1C3, 0x2265, 0xA1C4, 0x221E, + 0xA1C5, 0x2234, 0xA1C6, 0x00B0, 0xA1C7, 0x2032, 0xA1C8, 0x2033, 0xA1C9, 0x2103, 0xA1CA, 0x212B, 0xA1CB, 0xFFE0, 0xA1CC, 0xFFE1, + 0xA1CD, 0xFFE5, 0xA1CE, 0x2642, 0xA1CF, 0x2640, 0xA1D0, 0x2220, 0xA1D1, 0x22A5, 0xA1D2, 0x2312, 0xA1D3, 0x2202, 0xA1D4, 0x2207, + 0xA1D5, 0x2261, 0xA1D6, 0x2252, 0xA1D7, 0x00A7, 0xA1D8, 0x203B, 0xA1D9, 0x2606, 0xA1DA, 0x2605, 0xA1DB, 0x25CB, 0xA1DC, 0x25CF, + 0xA1DD, 0x25CE, 0xA1DE, 0x25C7, 0xA1DF, 0x25C6, 0xA1E0, 0x25A1, 0xA1E1, 0x25A0, 0xA1E2, 0x25B3, 0xA1E3, 0x25B2, 0xA1E4, 0x25BD, + 0xA1E5, 0x25BC, 0xA1E6, 0x2192, 0xA1E7, 0x2190, 0xA1E8, 0x2191, 0xA1E9, 0x2193, 0xA1EA, 0x2194, 0xA1EB, 0x3013, 0xA1EC, 0x226A, + 0xA1ED, 0x226B, 0xA1EE, 0x221A, 0xA1EF, 0x223D, 0xA1F0, 0x221D, 0xA1F1, 0x2235, 0xA1F2, 0x222B, 0xA1F3, 0x222C, 0xA1F4, 0x2208, + 0xA1F5, 0x220B, 0xA1F6, 0x2286, 0xA1F7, 0x2287, 0xA1F8, 0x2282, 0xA1F9, 0x2283, 0xA1FA, 0x222A, 0xA1FB, 0x2229, 0xA1FC, 0x2227, + 0xA1FD, 0x2228, 0xA1FE, 0xFFE2, 0xA241, 0xC910, 0xA242, 0xC912, 0xA243, 0xC913, 0xA244, 0xC914, 0xA245, 0xC915, 0xA246, 0xC916, + 0xA247, 0xC917, 0xA248, 0xC919, 0xA249, 0xC91A, 0xA24A, 0xC91B, 0xA24B, 0xC91C, 0xA24C, 0xC91D, 0xA24D, 0xC91E, 0xA24E, 0xC91F, + 0xA24F, 0xC920, 0xA250, 0xC921, 0xA251, 0xC922, 0xA252, 0xC923, 0xA253, 0xC924, 0xA254, 0xC925, 0xA255, 0xC926, 0xA256, 0xC927, + 0xA257, 0xC928, 0xA258, 0xC929, 0xA259, 0xC92A, 0xA25A, 0xC92B, 0xA261, 0xC92D, 0xA262, 0xC92E, 0xA263, 0xC92F, 0xA264, 0xC930, + 0xA265, 0xC931, 0xA266, 0xC932, 0xA267, 0xC933, 0xA268, 0xC935, 0xA269, 0xC936, 0xA26A, 0xC937, 0xA26B, 0xC938, 0xA26C, 0xC939, + 0xA26D, 0xC93A, 0xA26E, 0xC93B, 0xA26F, 0xC93C, 0xA270, 0xC93D, 0xA271, 0xC93E, 0xA272, 0xC93F, 0xA273, 0xC940, 0xA274, 0xC941, + 0xA275, 0xC942, 0xA276, 0xC943, 0xA277, 0xC944, 0xA278, 0xC945, 0xA279, 0xC946, 0xA27A, 0xC947, 0xA281, 0xC948, 0xA282, 0xC949, + 0xA283, 0xC94A, 0xA284, 0xC94B, 0xA285, 0xC94C, 0xA286, 0xC94D, 0xA287, 0xC94E, 0xA288, 0xC94F, 0xA289, 0xC952, 0xA28A, 0xC953, + 0xA28B, 0xC955, 0xA28C, 0xC956, 0xA28D, 0xC957, 0xA28E, 0xC959, 0xA28F, 0xC95A, 0xA290, 0xC95B, 0xA291, 0xC95C, 0xA292, 0xC95D, + 0xA293, 0xC95E, 0xA294, 0xC95F, 0xA295, 0xC962, 0xA296, 0xC964, 0xA297, 0xC965, 0xA298, 0xC966, 0xA299, 0xC967, 0xA29A, 0xC968, + 0xA29B, 0xC969, 0xA29C, 0xC96A, 0xA29D, 0xC96B, 0xA29E, 0xC96D, 0xA29F, 0xC96E, 0xA2A0, 0xC96F, 0xA2A1, 0x21D2, 0xA2A2, 0x21D4, + 0xA2A3, 0x2200, 0xA2A4, 0x2203, 0xA2A5, 0x00B4, 0xA2A6, 0xFF5E, 0xA2A7, 0x02C7, 0xA2A8, 0x02D8, 0xA2A9, 0x02DD, 0xA2AA, 0x02DA, + 0xA2AB, 0x02D9, 0xA2AC, 0x00B8, 0xA2AD, 0x02DB, 0xA2AE, 0x00A1, 0xA2AF, 0x00BF, 0xA2B0, 0x02D0, 0xA2B1, 0x222E, 0xA2B2, 0x2211, + 0xA2B3, 0x220F, 0xA2B4, 0x00A4, 0xA2B5, 0x2109, 0xA2B6, 0x2030, 0xA2B7, 0x25C1, 0xA2B8, 0x25C0, 0xA2B9, 0x25B7, 0xA2BA, 0x25B6, + 0xA2BB, 0x2664, 0xA2BC, 0x2660, 0xA2BD, 0x2661, 0xA2BE, 0x2665, 0xA2BF, 0x2667, 0xA2C0, 0x2663, 0xA2C1, 0x2299, 0xA2C2, 0x25C8, + 0xA2C3, 0x25A3, 0xA2C4, 0x25D0, 0xA2C5, 0x25D1, 0xA2C6, 0x2592, 0xA2C7, 0x25A4, 0xA2C8, 0x25A5, 0xA2C9, 0x25A8, 0xA2CA, 0x25A7, + 0xA2CB, 0x25A6, 0xA2CC, 0x25A9, 0xA2CD, 0x2668, 0xA2CE, 0x260F, 0xA2CF, 0x260E, 0xA2D0, 0x261C, 0xA2D1, 0x261E, 0xA2D2, 0x00B6, + 0xA2D3, 0x2020, 0xA2D4, 0x2021, 0xA2D5, 0x2195, 0xA2D6, 0x2197, 0xA2D7, 0x2199, 0xA2D8, 0x2196, 0xA2D9, 0x2198, 0xA2DA, 0x266D, + 0xA2DB, 0x2669, 0xA2DC, 0x266A, 0xA2DD, 0x266C, 0xA2DE, 0x327F, 0xA2DF, 0x321C, 0xA2E0, 0x2116, 0xA2E1, 0x33C7, 0xA2E2, 0x2122, + 0xA2E3, 0x33C2, 0xA2E4, 0x33D8, 0xA2E5, 0x2121, 0xA2E6, 0x20AC, 0xA2E7, 0x00AE, 0xA341, 0xC971, 0xA342, 0xC972, 0xA343, 0xC973, + 0xA344, 0xC975, 0xA345, 0xC976, 0xA346, 0xC977, 0xA347, 0xC978, 0xA348, 0xC979, 0xA349, 0xC97A, 0xA34A, 0xC97B, 0xA34B, 0xC97D, + 0xA34C, 0xC97E, 0xA34D, 0xC97F, 0xA34E, 0xC980, 0xA34F, 0xC981, 0xA350, 0xC982, 0xA351, 0xC983, 0xA352, 0xC984, 0xA353, 0xC985, + 0xA354, 0xC986, 0xA355, 0xC987, 0xA356, 0xC98A, 0xA357, 0xC98B, 0xA358, 0xC98D, 0xA359, 0xC98E, 0xA35A, 0xC98F, 0xA361, 0xC991, + 0xA362, 0xC992, 0xA363, 0xC993, 0xA364, 0xC994, 0xA365, 0xC995, 0xA366, 0xC996, 0xA367, 0xC997, 0xA368, 0xC99A, 0xA369, 0xC99C, + 0xA36A, 0xC99E, 0xA36B, 0xC99F, 0xA36C, 0xC9A0, 0xA36D, 0xC9A1, 0xA36E, 0xC9A2, 0xA36F, 0xC9A3, 0xA370, 0xC9A4, 0xA371, 0xC9A5, + 0xA372, 0xC9A6, 0xA373, 0xC9A7, 0xA374, 0xC9A8, 0xA375, 0xC9A9, 0xA376, 0xC9AA, 0xA377, 0xC9AB, 0xA378, 0xC9AC, 0xA379, 0xC9AD, + 0xA37A, 0xC9AE, 0xA381, 0xC9AF, 0xA382, 0xC9B0, 0xA383, 0xC9B1, 0xA384, 0xC9B2, 0xA385, 0xC9B3, 0xA386, 0xC9B4, 0xA387, 0xC9B5, + 0xA388, 0xC9B6, 0xA389, 0xC9B7, 0xA38A, 0xC9B8, 0xA38B, 0xC9B9, 0xA38C, 0xC9BA, 0xA38D, 0xC9BB, 0xA38E, 0xC9BC, 0xA38F, 0xC9BD, + 0xA390, 0xC9BE, 0xA391, 0xC9BF, 0xA392, 0xC9C2, 0xA393, 0xC9C3, 0xA394, 0xC9C5, 0xA395, 0xC9C6, 0xA396, 0xC9C9, 0xA397, 0xC9CB, + 0xA398, 0xC9CC, 0xA399, 0xC9CD, 0xA39A, 0xC9CE, 0xA39B, 0xC9CF, 0xA39C, 0xC9D2, 0xA39D, 0xC9D4, 0xA39E, 0xC9D7, 0xA39F, 0xC9D8, + 0xA3A0, 0xC9DB, 0xA3A1, 0xFF01, 0xA3A2, 0xFF02, 0xA3A3, 0xFF03, 0xA3A4, 0xFF04, 0xA3A5, 0xFF05, 0xA3A6, 0xFF06, 0xA3A7, 0xFF07, + 0xA3A8, 0xFF08, 0xA3A9, 0xFF09, 0xA3AA, 0xFF0A, 0xA3AB, 0xFF0B, 0xA3AC, 0xFF0C, 0xA3AD, 0xFF0D, 0xA3AE, 0xFF0E, 0xA3AF, 0xFF0F, + 0xA3B0, 0xFF10, 0xA3B1, 0xFF11, 0xA3B2, 0xFF12, 0xA3B3, 0xFF13, 0xA3B4, 0xFF14, 0xA3B5, 0xFF15, 0xA3B6, 0xFF16, 0xA3B7, 0xFF17, + 0xA3B8, 0xFF18, 0xA3B9, 0xFF19, 0xA3BA, 0xFF1A, 0xA3BB, 0xFF1B, 0xA3BC, 0xFF1C, 0xA3BD, 0xFF1D, 0xA3BE, 0xFF1E, 0xA3BF, 0xFF1F, + 0xA3C0, 0xFF20, 0xA3C1, 0xFF21, 0xA3C2, 0xFF22, 0xA3C3, 0xFF23, 0xA3C4, 0xFF24, 0xA3C5, 0xFF25, 0xA3C6, 0xFF26, 0xA3C7, 0xFF27, + 0xA3C8, 0xFF28, 0xA3C9, 0xFF29, 0xA3CA, 0xFF2A, 0xA3CB, 0xFF2B, 0xA3CC, 0xFF2C, 0xA3CD, 0xFF2D, 0xA3CE, 0xFF2E, 0xA3CF, 0xFF2F, + 0xA3D0, 0xFF30, 0xA3D1, 0xFF31, 0xA3D2, 0xFF32, 0xA3D3, 0xFF33, 0xA3D4, 0xFF34, 0xA3D5, 0xFF35, 0xA3D6, 0xFF36, 0xA3D7, 0xFF37, + 0xA3D8, 0xFF38, 0xA3D9, 0xFF39, 0xA3DA, 0xFF3A, 0xA3DB, 0xFF3B, 0xA3DC, 0xFFE6, 0xA3DD, 0xFF3D, 0xA3DE, 0xFF3E, 0xA3DF, 0xFF3F, + 0xA3E0, 0xFF40, 0xA3E1, 0xFF41, 0xA3E2, 0xFF42, 0xA3E3, 0xFF43, 0xA3E4, 0xFF44, 0xA3E5, 0xFF45, 0xA3E6, 0xFF46, 0xA3E7, 0xFF47, + 0xA3E8, 0xFF48, 0xA3E9, 0xFF49, 0xA3EA, 0xFF4A, 0xA3EB, 0xFF4B, 0xA3EC, 0xFF4C, 0xA3ED, 0xFF4D, 0xA3EE, 0xFF4E, 0xA3EF, 0xFF4F, + 0xA3F0, 0xFF50, 0xA3F1, 0xFF51, 0xA3F2, 0xFF52, 0xA3F3, 0xFF53, 0xA3F4, 0xFF54, 0xA3F5, 0xFF55, 0xA3F6, 0xFF56, 0xA3F7, 0xFF57, + 0xA3F8, 0xFF58, 0xA3F9, 0xFF59, 0xA3FA, 0xFF5A, 0xA3FB, 0xFF5B, 0xA3FC, 0xFF5C, 0xA3FD, 0xFF5D, 0xA3FE, 0xFFE3, 0xA441, 0xC9DE, + 0xA442, 0xC9DF, 0xA443, 0xC9E1, 0xA444, 0xC9E3, 0xA445, 0xC9E5, 0xA446, 0xC9E6, 0xA447, 0xC9E8, 0xA448, 0xC9E9, 0xA449, 0xC9EA, + 0xA44A, 0xC9EB, 0xA44B, 0xC9EE, 0xA44C, 0xC9F2, 0xA44D, 0xC9F3, 0xA44E, 0xC9F4, 0xA44F, 0xC9F5, 0xA450, 0xC9F6, 0xA451, 0xC9F7, + 0xA452, 0xC9FA, 0xA453, 0xC9FB, 0xA454, 0xC9FD, 0xA455, 0xC9FE, 0xA456, 0xC9FF, 0xA457, 0xCA01, 0xA458, 0xCA02, 0xA459, 0xCA03, + 0xA45A, 0xCA04, 0xA461, 0xCA05, 0xA462, 0xCA06, 0xA463, 0xCA07, 0xA464, 0xCA0A, 0xA465, 0xCA0E, 0xA466, 0xCA0F, 0xA467, 0xCA10, + 0xA468, 0xCA11, 0xA469, 0xCA12, 0xA46A, 0xCA13, 0xA46B, 0xCA15, 0xA46C, 0xCA16, 0xA46D, 0xCA17, 0xA46E, 0xCA19, 0xA46F, 0xCA1A, + 0xA470, 0xCA1B, 0xA471, 0xCA1C, 0xA472, 0xCA1D, 0xA473, 0xCA1E, 0xA474, 0xCA1F, 0xA475, 0xCA20, 0xA476, 0xCA21, 0xA477, 0xCA22, + 0xA478, 0xCA23, 0xA479, 0xCA24, 0xA47A, 0xCA25, 0xA481, 0xCA26, 0xA482, 0xCA27, 0xA483, 0xCA28, 0xA484, 0xCA2A, 0xA485, 0xCA2B, + 0xA486, 0xCA2C, 0xA487, 0xCA2D, 0xA488, 0xCA2E, 0xA489, 0xCA2F, 0xA48A, 0xCA30, 0xA48B, 0xCA31, 0xA48C, 0xCA32, 0xA48D, 0xCA33, + 0xA48E, 0xCA34, 0xA48F, 0xCA35, 0xA490, 0xCA36, 0xA491, 0xCA37, 0xA492, 0xCA38, 0xA493, 0xCA39, 0xA494, 0xCA3A, 0xA495, 0xCA3B, + 0xA496, 0xCA3C, 0xA497, 0xCA3D, 0xA498, 0xCA3E, 0xA499, 0xCA3F, 0xA49A, 0xCA40, 0xA49B, 0xCA41, 0xA49C, 0xCA42, 0xA49D, 0xCA43, + 0xA49E, 0xCA44, 0xA49F, 0xCA45, 0xA4A0, 0xCA46, 0xA4A1, 0x3131, 0xA4A2, 0x3132, 0xA4A3, 0x3133, 0xA4A4, 0x3134, 0xA4A5, 0x3135, + 0xA4A6, 0x3136, 0xA4A7, 0x3137, 0xA4A8, 0x3138, 0xA4A9, 0x3139, 0xA4AA, 0x313A, 0xA4AB, 0x313B, 0xA4AC, 0x313C, 0xA4AD, 0x313D, + 0xA4AE, 0x313E, 0xA4AF, 0x313F, 0xA4B0, 0x3140, 0xA4B1, 0x3141, 0xA4B2, 0x3142, 0xA4B3, 0x3143, 0xA4B4, 0x3144, 0xA4B5, 0x3145, + 0xA4B6, 0x3146, 0xA4B7, 0x3147, 0xA4B8, 0x3148, 0xA4B9, 0x3149, 0xA4BA, 0x314A, 0xA4BB, 0x314B, 0xA4BC, 0x314C, 0xA4BD, 0x314D, + 0xA4BE, 0x314E, 0xA4BF, 0x314F, 0xA4C0, 0x3150, 0xA4C1, 0x3151, 0xA4C2, 0x3152, 0xA4C3, 0x3153, 0xA4C4, 0x3154, 0xA4C5, 0x3155, + 0xA4C6, 0x3156, 0xA4C7, 0x3157, 0xA4C8, 0x3158, 0xA4C9, 0x3159, 0xA4CA, 0x315A, 0xA4CB, 0x315B, 0xA4CC, 0x315C, 0xA4CD, 0x315D, + 0xA4CE, 0x315E, 0xA4CF, 0x315F, 0xA4D0, 0x3160, 0xA4D1, 0x3161, 0xA4D2, 0x3162, 0xA4D3, 0x3163, 0xA4D4, 0x3164, 0xA4D5, 0x3165, + 0xA4D6, 0x3166, 0xA4D7, 0x3167, 0xA4D8, 0x3168, 0xA4D9, 0x3169, 0xA4DA, 0x316A, 0xA4DB, 0x316B, 0xA4DC, 0x316C, 0xA4DD, 0x316D, + 0xA4DE, 0x316E, 0xA4DF, 0x316F, 0xA4E0, 0x3170, 0xA4E1, 0x3171, 0xA4E2, 0x3172, 0xA4E3, 0x3173, 0xA4E4, 0x3174, 0xA4E5, 0x3175, + 0xA4E6, 0x3176, 0xA4E7, 0x3177, 0xA4E8, 0x3178, 0xA4E9, 0x3179, 0xA4EA, 0x317A, 0xA4EB, 0x317B, 0xA4EC, 0x317C, 0xA4ED, 0x317D, + 0xA4EE, 0x317E, 0xA4EF, 0x317F, 0xA4F0, 0x3180, 0xA4F1, 0x3181, 0xA4F2, 0x3182, 0xA4F3, 0x3183, 0xA4F4, 0x3184, 0xA4F5, 0x3185, + 0xA4F6, 0x3186, 0xA4F7, 0x3187, 0xA4F8, 0x3188, 0xA4F9, 0x3189, 0xA4FA, 0x318A, 0xA4FB, 0x318B, 0xA4FC, 0x318C, 0xA4FD, 0x318D, + 0xA4FE, 0x318E, 0xA541, 0xCA47, 0xA542, 0xCA48, 0xA543, 0xCA49, 0xA544, 0xCA4A, 0xA545, 0xCA4B, 0xA546, 0xCA4E, 0xA547, 0xCA4F, + 0xA548, 0xCA51, 0xA549, 0xCA52, 0xA54A, 0xCA53, 0xA54B, 0xCA55, 0xA54C, 0xCA56, 0xA54D, 0xCA57, 0xA54E, 0xCA58, 0xA54F, 0xCA59, + 0xA550, 0xCA5A, 0xA551, 0xCA5B, 0xA552, 0xCA5E, 0xA553, 0xCA62, 0xA554, 0xCA63, 0xA555, 0xCA64, 0xA556, 0xCA65, 0xA557, 0xCA66, + 0xA558, 0xCA67, 0xA559, 0xCA69, 0xA55A, 0xCA6A, 0xA561, 0xCA6B, 0xA562, 0xCA6C, 0xA563, 0xCA6D, 0xA564, 0xCA6E, 0xA565, 0xCA6F, + 0xA566, 0xCA70, 0xA567, 0xCA71, 0xA568, 0xCA72, 0xA569, 0xCA73, 0xA56A, 0xCA74, 0xA56B, 0xCA75, 0xA56C, 0xCA76, 0xA56D, 0xCA77, + 0xA56E, 0xCA78, 0xA56F, 0xCA79, 0xA570, 0xCA7A, 0xA571, 0xCA7B, 0xA572, 0xCA7C, 0xA573, 0xCA7E, 0xA574, 0xCA7F, 0xA575, 0xCA80, + 0xA576, 0xCA81, 0xA577, 0xCA82, 0xA578, 0xCA83, 0xA579, 0xCA85, 0xA57A, 0xCA86, 0xA581, 0xCA87, 0xA582, 0xCA88, 0xA583, 0xCA89, + 0xA584, 0xCA8A, 0xA585, 0xCA8B, 0xA586, 0xCA8C, 0xA587, 0xCA8D, 0xA588, 0xCA8E, 0xA589, 0xCA8F, 0xA58A, 0xCA90, 0xA58B, 0xCA91, + 0xA58C, 0xCA92, 0xA58D, 0xCA93, 0xA58E, 0xCA94, 0xA58F, 0xCA95, 0xA590, 0xCA96, 0xA591, 0xCA97, 0xA592, 0xCA99, 0xA593, 0xCA9A, + 0xA594, 0xCA9B, 0xA595, 0xCA9C, 0xA596, 0xCA9D, 0xA597, 0xCA9E, 0xA598, 0xCA9F, 0xA599, 0xCAA0, 0xA59A, 0xCAA1, 0xA59B, 0xCAA2, + 0xA59C, 0xCAA3, 0xA59D, 0xCAA4, 0xA59E, 0xCAA5, 0xA59F, 0xCAA6, 0xA5A0, 0xCAA7, 0xA5A1, 0x2170, 0xA5A2, 0x2171, 0xA5A3, 0x2172, + 0xA5A4, 0x2173, 0xA5A5, 0x2174, 0xA5A6, 0x2175, 0xA5A7, 0x2176, 0xA5A8, 0x2177, 0xA5A9, 0x2178, 0xA5AA, 0x2179, 0xA5B0, 0x2160, + 0xA5B1, 0x2161, 0xA5B2, 0x2162, 0xA5B3, 0x2163, 0xA5B4, 0x2164, 0xA5B5, 0x2165, 0xA5B6, 0x2166, 0xA5B7, 0x2167, 0xA5B8, 0x2168, + 0xA5B9, 0x2169, 0xA5C1, 0x0391, 0xA5C2, 0x0392, 0xA5C3, 0x0393, 0xA5C4, 0x0394, 0xA5C5, 0x0395, 0xA5C6, 0x0396, 0xA5C7, 0x0397, + 0xA5C8, 0x0398, 0xA5C9, 0x0399, 0xA5CA, 0x039A, 0xA5CB, 0x039B, 0xA5CC, 0x039C, 0xA5CD, 0x039D, 0xA5CE, 0x039E, 0xA5CF, 0x039F, + 0xA5D0, 0x03A0, 0xA5D1, 0x03A1, 0xA5D2, 0x03A3, 0xA5D3, 0x03A4, 0xA5D4, 0x03A5, 0xA5D5, 0x03A6, 0xA5D6, 0x03A7, 0xA5D7, 0x03A8, + 0xA5D8, 0x03A9, 0xA5E1, 0x03B1, 0xA5E2, 0x03B2, 0xA5E3, 0x03B3, 0xA5E4, 0x03B4, 0xA5E5, 0x03B5, 0xA5E6, 0x03B6, 0xA5E7, 0x03B7, + 0xA5E8, 0x03B8, 0xA5E9, 0x03B9, 0xA5EA, 0x03BA, 0xA5EB, 0x03BB, 0xA5EC, 0x03BC, 0xA5ED, 0x03BD, 0xA5EE, 0x03BE, 0xA5EF, 0x03BF, + 0xA5F0, 0x03C0, 0xA5F1, 0x03C1, 0xA5F2, 0x03C3, 0xA5F3, 0x03C4, 0xA5F4, 0x03C5, 0xA5F5, 0x03C6, 0xA5F6, 0x03C7, 0xA5F7, 0x03C8, + 0xA5F8, 0x03C9, 0xA641, 0xCAA8, 0xA642, 0xCAA9, 0xA643, 0xCAAA, 0xA644, 0xCAAB, 0xA645, 0xCAAC, 0xA646, 0xCAAD, 0xA647, 0xCAAE, + 0xA648, 0xCAAF, 0xA649, 0xCAB0, 0xA64A, 0xCAB1, 0xA64B, 0xCAB2, 0xA64C, 0xCAB3, 0xA64D, 0xCAB4, 0xA64E, 0xCAB5, 0xA64F, 0xCAB6, + 0xA650, 0xCAB7, 0xA651, 0xCAB8, 0xA652, 0xCAB9, 0xA653, 0xCABA, 0xA654, 0xCABB, 0xA655, 0xCABE, 0xA656, 0xCABF, 0xA657, 0xCAC1, + 0xA658, 0xCAC2, 0xA659, 0xCAC3, 0xA65A, 0xCAC5, 0xA661, 0xCAC6, 0xA662, 0xCAC7, 0xA663, 0xCAC8, 0xA664, 0xCAC9, 0xA665, 0xCACA, + 0xA666, 0xCACB, 0xA667, 0xCACE, 0xA668, 0xCAD0, 0xA669, 0xCAD2, 0xA66A, 0xCAD4, 0xA66B, 0xCAD5, 0xA66C, 0xCAD6, 0xA66D, 0xCAD7, + 0xA66E, 0xCADA, 0xA66F, 0xCADB, 0xA670, 0xCADC, 0xA671, 0xCADD, 0xA672, 0xCADE, 0xA673, 0xCADF, 0xA674, 0xCAE1, 0xA675, 0xCAE2, + 0xA676, 0xCAE3, 0xA677, 0xCAE4, 0xA678, 0xCAE5, 0xA679, 0xCAE6, 0xA67A, 0xCAE7, 0xA681, 0xCAE8, 0xA682, 0xCAE9, 0xA683, 0xCAEA, + 0xA684, 0xCAEB, 0xA685, 0xCAED, 0xA686, 0xCAEE, 0xA687, 0xCAEF, 0xA688, 0xCAF0, 0xA689, 0xCAF1, 0xA68A, 0xCAF2, 0xA68B, 0xCAF3, + 0xA68C, 0xCAF5, 0xA68D, 0xCAF6, 0xA68E, 0xCAF7, 0xA68F, 0xCAF8, 0xA690, 0xCAF9, 0xA691, 0xCAFA, 0xA692, 0xCAFB, 0xA693, 0xCAFC, + 0xA694, 0xCAFD, 0xA695, 0xCAFE, 0xA696, 0xCAFF, 0xA697, 0xCB00, 0xA698, 0xCB01, 0xA699, 0xCB02, 0xA69A, 0xCB03, 0xA69B, 0xCB04, + 0xA69C, 0xCB05, 0xA69D, 0xCB06, 0xA69E, 0xCB07, 0xA69F, 0xCB09, 0xA6A0, 0xCB0A, 0xA6A1, 0x2500, 0xA6A2, 0x2502, 0xA6A3, 0x250C, + 0xA6A4, 0x2510, 0xA6A5, 0x2518, 0xA6A6, 0x2514, 0xA6A7, 0x251C, 0xA6A8, 0x252C, 0xA6A9, 0x2524, 0xA6AA, 0x2534, 0xA6AB, 0x253C, + 0xA6AC, 0x2501, 0xA6AD, 0x2503, 0xA6AE, 0x250F, 0xA6AF, 0x2513, 0xA6B0, 0x251B, 0xA6B1, 0x2517, 0xA6B2, 0x2523, 0xA6B3, 0x2533, + 0xA6B4, 0x252B, 0xA6B5, 0x253B, 0xA6B6, 0x254B, 0xA6B7, 0x2520, 0xA6B8, 0x252F, 0xA6B9, 0x2528, 0xA6BA, 0x2537, 0xA6BB, 0x253F, + 0xA6BC, 0x251D, 0xA6BD, 0x2530, 0xA6BE, 0x2525, 0xA6BF, 0x2538, 0xA6C0, 0x2542, 0xA6C1, 0x2512, 0xA6C2, 0x2511, 0xA6C3, 0x251A, + 0xA6C4, 0x2519, 0xA6C5, 0x2516, 0xA6C6, 0x2515, 0xA6C7, 0x250E, 0xA6C8, 0x250D, 0xA6C9, 0x251E, 0xA6CA, 0x251F, 0xA6CB, 0x2521, + 0xA6CC, 0x2522, 0xA6CD, 0x2526, 0xA6CE, 0x2527, 0xA6CF, 0x2529, 0xA6D0, 0x252A, 0xA6D1, 0x252D, 0xA6D2, 0x252E, 0xA6D3, 0x2531, + 0xA6D4, 0x2532, 0xA6D5, 0x2535, 0xA6D6, 0x2536, 0xA6D7, 0x2539, 0xA6D8, 0x253A, 0xA6D9, 0x253D, 0xA6DA, 0x253E, 0xA6DB, 0x2540, + 0xA6DC, 0x2541, 0xA6DD, 0x2543, 0xA6DE, 0x2544, 0xA6DF, 0x2545, 0xA6E0, 0x2546, 0xA6E1, 0x2547, 0xA6E2, 0x2548, 0xA6E3, 0x2549, + 0xA6E4, 0x254A, 0xA741, 0xCB0B, 0xA742, 0xCB0C, 0xA743, 0xCB0D, 0xA744, 0xCB0E, 0xA745, 0xCB0F, 0xA746, 0xCB11, 0xA747, 0xCB12, + 0xA748, 0xCB13, 0xA749, 0xCB15, 0xA74A, 0xCB16, 0xA74B, 0xCB17, 0xA74C, 0xCB19, 0xA74D, 0xCB1A, 0xA74E, 0xCB1B, 0xA74F, 0xCB1C, + 0xA750, 0xCB1D, 0xA751, 0xCB1E, 0xA752, 0xCB1F, 0xA753, 0xCB22, 0xA754, 0xCB23, 0xA755, 0xCB24, 0xA756, 0xCB25, 0xA757, 0xCB26, + 0xA758, 0xCB27, 0xA759, 0xCB28, 0xA75A, 0xCB29, 0xA761, 0xCB2A, 0xA762, 0xCB2B, 0xA763, 0xCB2C, 0xA764, 0xCB2D, 0xA765, 0xCB2E, + 0xA766, 0xCB2F, 0xA767, 0xCB30, 0xA768, 0xCB31, 0xA769, 0xCB32, 0xA76A, 0xCB33, 0xA76B, 0xCB34, 0xA76C, 0xCB35, 0xA76D, 0xCB36, + 0xA76E, 0xCB37, 0xA76F, 0xCB38, 0xA770, 0xCB39, 0xA771, 0xCB3A, 0xA772, 0xCB3B, 0xA773, 0xCB3C, 0xA774, 0xCB3D, 0xA775, 0xCB3E, + 0xA776, 0xCB3F, 0xA777, 0xCB40, 0xA778, 0xCB42, 0xA779, 0xCB43, 0xA77A, 0xCB44, 0xA781, 0xCB45, 0xA782, 0xCB46, 0xA783, 0xCB47, + 0xA784, 0xCB4A, 0xA785, 0xCB4B, 0xA786, 0xCB4D, 0xA787, 0xCB4E, 0xA788, 0xCB4F, 0xA789, 0xCB51, 0xA78A, 0xCB52, 0xA78B, 0xCB53, + 0xA78C, 0xCB54, 0xA78D, 0xCB55, 0xA78E, 0xCB56, 0xA78F, 0xCB57, 0xA790, 0xCB5A, 0xA791, 0xCB5B, 0xA792, 0xCB5C, 0xA793, 0xCB5E, + 0xA794, 0xCB5F, 0xA795, 0xCB60, 0xA796, 0xCB61, 0xA797, 0xCB62, 0xA798, 0xCB63, 0xA799, 0xCB65, 0xA79A, 0xCB66, 0xA79B, 0xCB67, + 0xA79C, 0xCB68, 0xA79D, 0xCB69, 0xA79E, 0xCB6A, 0xA79F, 0xCB6B, 0xA7A0, 0xCB6C, 0xA7A1, 0x3395, 0xA7A2, 0x3396, 0xA7A3, 0x3397, + 0xA7A4, 0x2113, 0xA7A5, 0x3398, 0xA7A6, 0x33C4, 0xA7A7, 0x33A3, 0xA7A8, 0x33A4, 0xA7A9, 0x33A5, 0xA7AA, 0x33A6, 0xA7AB, 0x3399, + 0xA7AC, 0x339A, 0xA7AD, 0x339B, 0xA7AE, 0x339C, 0xA7AF, 0x339D, 0xA7B0, 0x339E, 0xA7B1, 0x339F, 0xA7B2, 0x33A0, 0xA7B3, 0x33A1, + 0xA7B4, 0x33A2, 0xA7B5, 0x33CA, 0xA7B6, 0x338D, 0xA7B7, 0x338E, 0xA7B8, 0x338F, 0xA7B9, 0x33CF, 0xA7BA, 0x3388, 0xA7BB, 0x3389, + 0xA7BC, 0x33C8, 0xA7BD, 0x33A7, 0xA7BE, 0x33A8, 0xA7BF, 0x33B0, 0xA7C0, 0x33B1, 0xA7C1, 0x33B2, 0xA7C2, 0x33B3, 0xA7C3, 0x33B4, + 0xA7C4, 0x33B5, 0xA7C5, 0x33B6, 0xA7C6, 0x33B7, 0xA7C7, 0x33B8, 0xA7C8, 0x33B9, 0xA7C9, 0x3380, 0xA7CA, 0x3381, 0xA7CB, 0x3382, + 0xA7CC, 0x3383, 0xA7CD, 0x3384, 0xA7CE, 0x33BA, 0xA7CF, 0x33BB, 0xA7D0, 0x33BC, 0xA7D1, 0x33BD, 0xA7D2, 0x33BE, 0xA7D3, 0x33BF, + 0xA7D4, 0x3390, 0xA7D5, 0x3391, 0xA7D6, 0x3392, 0xA7D7, 0x3393, 0xA7D8, 0x3394, 0xA7D9, 0x2126, 0xA7DA, 0x33C0, 0xA7DB, 0x33C1, + 0xA7DC, 0x338A, 0xA7DD, 0x338B, 0xA7DE, 0x338C, 0xA7DF, 0x33D6, 0xA7E0, 0x33C5, 0xA7E1, 0x33AD, 0xA7E2, 0x33AE, 0xA7E3, 0x33AF, + 0xA7E4, 0x33DB, 0xA7E5, 0x33A9, 0xA7E6, 0x33AA, 0xA7E7, 0x33AB, 0xA7E8, 0x33AC, 0xA7E9, 0x33DD, 0xA7EA, 0x33D0, 0xA7EB, 0x33D3, + 0xA7EC, 0x33C3, 0xA7ED, 0x33C9, 0xA7EE, 0x33DC, 0xA7EF, 0x33C6, 0xA841, 0xCB6D, 0xA842, 0xCB6E, 0xA843, 0xCB6F, 0xA844, 0xCB70, + 0xA845, 0xCB71, 0xA846, 0xCB72, 0xA847, 0xCB73, 0xA848, 0xCB74, 0xA849, 0xCB75, 0xA84A, 0xCB76, 0xA84B, 0xCB77, 0xA84C, 0xCB7A, + 0xA84D, 0xCB7B, 0xA84E, 0xCB7C, 0xA84F, 0xCB7D, 0xA850, 0xCB7E, 0xA851, 0xCB7F, 0xA852, 0xCB80, 0xA853, 0xCB81, 0xA854, 0xCB82, + 0xA855, 0xCB83, 0xA856, 0xCB84, 0xA857, 0xCB85, 0xA858, 0xCB86, 0xA859, 0xCB87, 0xA85A, 0xCB88, 0xA861, 0xCB89, 0xA862, 0xCB8A, + 0xA863, 0xCB8B, 0xA864, 0xCB8C, 0xA865, 0xCB8D, 0xA866, 0xCB8E, 0xA867, 0xCB8F, 0xA868, 0xCB90, 0xA869, 0xCB91, 0xA86A, 0xCB92, + 0xA86B, 0xCB93, 0xA86C, 0xCB94, 0xA86D, 0xCB95, 0xA86E, 0xCB96, 0xA86F, 0xCB97, 0xA870, 0xCB98, 0xA871, 0xCB99, 0xA872, 0xCB9A, + 0xA873, 0xCB9B, 0xA874, 0xCB9D, 0xA875, 0xCB9E, 0xA876, 0xCB9F, 0xA877, 0xCBA0, 0xA878, 0xCBA1, 0xA879, 0xCBA2, 0xA87A, 0xCBA3, + 0xA881, 0xCBA4, 0xA882, 0xCBA5, 0xA883, 0xCBA6, 0xA884, 0xCBA7, 0xA885, 0xCBA8, 0xA886, 0xCBA9, 0xA887, 0xCBAA, 0xA888, 0xCBAB, + 0xA889, 0xCBAC, 0xA88A, 0xCBAD, 0xA88B, 0xCBAE, 0xA88C, 0xCBAF, 0xA88D, 0xCBB0, 0xA88E, 0xCBB1, 0xA88F, 0xCBB2, 0xA890, 0xCBB3, + 0xA891, 0xCBB4, 0xA892, 0xCBB5, 0xA893, 0xCBB6, 0xA894, 0xCBB7, 0xA895, 0xCBB9, 0xA896, 0xCBBA, 0xA897, 0xCBBB, 0xA898, 0xCBBC, + 0xA899, 0xCBBD, 0xA89A, 0xCBBE, 0xA89B, 0xCBBF, 0xA89C, 0xCBC0, 0xA89D, 0xCBC1, 0xA89E, 0xCBC2, 0xA89F, 0xCBC3, 0xA8A0, 0xCBC4, + 0xA8A1, 0x00C6, 0xA8A2, 0x00D0, 0xA8A3, 0x00AA, 0xA8A4, 0x0126, 0xA8A6, 0x0132, 0xA8A8, 0x013F, 0xA8A9, 0x0141, 0xA8AA, 0x00D8, + 0xA8AB, 0x0152, 0xA8AC, 0x00BA, 0xA8AD, 0x00DE, 0xA8AE, 0x0166, 0xA8AF, 0x014A, 0xA8B1, 0x3260, 0xA8B2, 0x3261, 0xA8B3, 0x3262, + 0xA8B4, 0x3263, 0xA8B5, 0x3264, 0xA8B6, 0x3265, 0xA8B7, 0x3266, 0xA8B8, 0x3267, 0xA8B9, 0x3268, 0xA8BA, 0x3269, 0xA8BB, 0x326A, + 0xA8BC, 0x326B, 0xA8BD, 0x326C, 0xA8BE, 0x326D, 0xA8BF, 0x326E, 0xA8C0, 0x326F, 0xA8C1, 0x3270, 0xA8C2, 0x3271, 0xA8C3, 0x3272, + 0xA8C4, 0x3273, 0xA8C5, 0x3274, 0xA8C6, 0x3275, 0xA8C7, 0x3276, 0xA8C8, 0x3277, 0xA8C9, 0x3278, 0xA8CA, 0x3279, 0xA8CB, 0x327A, + 0xA8CC, 0x327B, 0xA8CD, 0x24D0, 0xA8CE, 0x24D1, 0xA8CF, 0x24D2, 0xA8D0, 0x24D3, 0xA8D1, 0x24D4, 0xA8D2, 0x24D5, 0xA8D3, 0x24D6, + 0xA8D4, 0x24D7, 0xA8D5, 0x24D8, 0xA8D6, 0x24D9, 0xA8D7, 0x24DA, 0xA8D8, 0x24DB, 0xA8D9, 0x24DC, 0xA8DA, 0x24DD, 0xA8DB, 0x24DE, + 0xA8DC, 0x24DF, 0xA8DD, 0x24E0, 0xA8DE, 0x24E1, 0xA8DF, 0x24E2, 0xA8E0, 0x24E3, 0xA8E1, 0x24E4, 0xA8E2, 0x24E5, 0xA8E3, 0x24E6, + 0xA8E4, 0x24E7, 0xA8E5, 0x24E8, 0xA8E6, 0x24E9, 0xA8E7, 0x2460, 0xA8E8, 0x2461, 0xA8E9, 0x2462, 0xA8EA, 0x2463, 0xA8EB, 0x2464, + 0xA8EC, 0x2465, 0xA8ED, 0x2466, 0xA8EE, 0x2467, 0xA8EF, 0x2468, 0xA8F0, 0x2469, 0xA8F1, 0x246A, 0xA8F2, 0x246B, 0xA8F3, 0x246C, + 0xA8F4, 0x246D, 0xA8F5, 0x246E, 0xA8F6, 0x00BD, 0xA8F7, 0x2153, 0xA8F8, 0x2154, 0xA8F9, 0x00BC, 0xA8FA, 0x00BE, 0xA8FB, 0x215B, + 0xA8FC, 0x215C, 0xA8FD, 0x215D, 0xA8FE, 0x215E, 0xA941, 0xCBC5, 0xA942, 0xCBC6, 0xA943, 0xCBC7, 0xA944, 0xCBC8, 0xA945, 0xCBC9, + 0xA946, 0xCBCA, 0xA947, 0xCBCB, 0xA948, 0xCBCC, 0xA949, 0xCBCD, 0xA94A, 0xCBCE, 0xA94B, 0xCBCF, 0xA94C, 0xCBD0, 0xA94D, 0xCBD1, + 0xA94E, 0xCBD2, 0xA94F, 0xCBD3, 0xA950, 0xCBD5, 0xA951, 0xCBD6, 0xA952, 0xCBD7, 0xA953, 0xCBD8, 0xA954, 0xCBD9, 0xA955, 0xCBDA, + 0xA956, 0xCBDB, 0xA957, 0xCBDC, 0xA958, 0xCBDD, 0xA959, 0xCBDE, 0xA95A, 0xCBDF, 0xA961, 0xCBE0, 0xA962, 0xCBE1, 0xA963, 0xCBE2, + 0xA964, 0xCBE3, 0xA965, 0xCBE5, 0xA966, 0xCBE6, 0xA967, 0xCBE8, 0xA968, 0xCBEA, 0xA969, 0xCBEB, 0xA96A, 0xCBEC, 0xA96B, 0xCBED, + 0xA96C, 0xCBEE, 0xA96D, 0xCBEF, 0xA96E, 0xCBF0, 0xA96F, 0xCBF1, 0xA970, 0xCBF2, 0xA971, 0xCBF3, 0xA972, 0xCBF4, 0xA973, 0xCBF5, + 0xA974, 0xCBF6, 0xA975, 0xCBF7, 0xA976, 0xCBF8, 0xA977, 0xCBF9, 0xA978, 0xCBFA, 0xA979, 0xCBFB, 0xA97A, 0xCBFC, 0xA981, 0xCBFD, + 0xA982, 0xCBFE, 0xA983, 0xCBFF, 0xA984, 0xCC00, 0xA985, 0xCC01, 0xA986, 0xCC02, 0xA987, 0xCC03, 0xA988, 0xCC04, 0xA989, 0xCC05, + 0xA98A, 0xCC06, 0xA98B, 0xCC07, 0xA98C, 0xCC08, 0xA98D, 0xCC09, 0xA98E, 0xCC0A, 0xA98F, 0xCC0B, 0xA990, 0xCC0E, 0xA991, 0xCC0F, + 0xA992, 0xCC11, 0xA993, 0xCC12, 0xA994, 0xCC13, 0xA995, 0xCC15, 0xA996, 0xCC16, 0xA997, 0xCC17, 0xA998, 0xCC18, 0xA999, 0xCC19, + 0xA99A, 0xCC1A, 0xA99B, 0xCC1B, 0xA99C, 0xCC1E, 0xA99D, 0xCC1F, 0xA99E, 0xCC20, 0xA99F, 0xCC23, 0xA9A0, 0xCC24, 0xA9A1, 0x00E6, + 0xA9A2, 0x0111, 0xA9A3, 0x00F0, 0xA9A4, 0x0127, 0xA9A5, 0x0131, 0xA9A6, 0x0133, 0xA9A7, 0x0138, 0xA9A8, 0x0140, 0xA9A9, 0x0142, + 0xA9AA, 0x00F8, 0xA9AB, 0x0153, 0xA9AC, 0x00DF, 0xA9AD, 0x00FE, 0xA9AE, 0x0167, 0xA9AF, 0x014B, 0xA9B0, 0x0149, 0xA9B1, 0x3200, + 0xA9B2, 0x3201, 0xA9B3, 0x3202, 0xA9B4, 0x3203, 0xA9B5, 0x3204, 0xA9B6, 0x3205, 0xA9B7, 0x3206, 0xA9B8, 0x3207, 0xA9B9, 0x3208, + 0xA9BA, 0x3209, 0xA9BB, 0x320A, 0xA9BC, 0x320B, 0xA9BD, 0x320C, 0xA9BE, 0x320D, 0xA9BF, 0x320E, 0xA9C0, 0x320F, 0xA9C1, 0x3210, + 0xA9C2, 0x3211, 0xA9C3, 0x3212, 0xA9C4, 0x3213, 0xA9C5, 0x3214, 0xA9C6, 0x3215, 0xA9C7, 0x3216, 0xA9C8, 0x3217, 0xA9C9, 0x3218, + 0xA9CA, 0x3219, 0xA9CB, 0x321A, 0xA9CC, 0x321B, 0xA9CD, 0x249C, 0xA9CE, 0x249D, 0xA9CF, 0x249E, 0xA9D0, 0x249F, 0xA9D1, 0x24A0, + 0xA9D2, 0x24A1, 0xA9D3, 0x24A2, 0xA9D4, 0x24A3, 0xA9D5, 0x24A4, 0xA9D6, 0x24A5, 0xA9D7, 0x24A6, 0xA9D8, 0x24A7, 0xA9D9, 0x24A8, + 0xA9DA, 0x24A9, 0xA9DB, 0x24AA, 0xA9DC, 0x24AB, 0xA9DD, 0x24AC, 0xA9DE, 0x24AD, 0xA9DF, 0x24AE, 0xA9E0, 0x24AF, 0xA9E1, 0x24B0, + 0xA9E2, 0x24B1, 0xA9E3, 0x24B2, 0xA9E4, 0x24B3, 0xA9E5, 0x24B4, 0xA9E6, 0x24B5, 0xA9E7, 0x2474, 0xA9E8, 0x2475, 0xA9E9, 0x2476, + 0xA9EA, 0x2477, 0xA9EB, 0x2478, 0xA9EC, 0x2479, 0xA9ED, 0x247A, 0xA9EE, 0x247B, 0xA9EF, 0x247C, 0xA9F0, 0x247D, 0xA9F1, 0x247E, + 0xA9F2, 0x247F, 0xA9F3, 0x2480, 0xA9F4, 0x2481, 0xA9F5, 0x2482, 0xA9F6, 0x00B9, 0xA9F7, 0x00B2, 0xA9F8, 0x00B3, 0xA9F9, 0x2074, + 0xA9FA, 0x207F, 0xA9FB, 0x2081, 0xA9FC, 0x2082, 0xA9FD, 0x2083, 0xA9FE, 0x2084, 0xAA41, 0xCC25, 0xAA42, 0xCC26, 0xAA43, 0xCC2A, + 0xAA44, 0xCC2B, 0xAA45, 0xCC2D, 0xAA46, 0xCC2F, 0xAA47, 0xCC31, 0xAA48, 0xCC32, 0xAA49, 0xCC33, 0xAA4A, 0xCC34, 0xAA4B, 0xCC35, + 0xAA4C, 0xCC36, 0xAA4D, 0xCC37, 0xAA4E, 0xCC3A, 0xAA4F, 0xCC3F, 0xAA50, 0xCC40, 0xAA51, 0xCC41, 0xAA52, 0xCC42, 0xAA53, 0xCC43, + 0xAA54, 0xCC46, 0xAA55, 0xCC47, 0xAA56, 0xCC49, 0xAA57, 0xCC4A, 0xAA58, 0xCC4B, 0xAA59, 0xCC4D, 0xAA5A, 0xCC4E, 0xAA61, 0xCC4F, + 0xAA62, 0xCC50, 0xAA63, 0xCC51, 0xAA64, 0xCC52, 0xAA65, 0xCC53, 0xAA66, 0xCC56, 0xAA67, 0xCC5A, 0xAA68, 0xCC5B, 0xAA69, 0xCC5C, + 0xAA6A, 0xCC5D, 0xAA6B, 0xCC5E, 0xAA6C, 0xCC5F, 0xAA6D, 0xCC61, 0xAA6E, 0xCC62, 0xAA6F, 0xCC63, 0xAA70, 0xCC65, 0xAA71, 0xCC67, + 0xAA72, 0xCC69, 0xAA73, 0xCC6A, 0xAA74, 0xCC6B, 0xAA75, 0xCC6C, 0xAA76, 0xCC6D, 0xAA77, 0xCC6E, 0xAA78, 0xCC6F, 0xAA79, 0xCC71, + 0xAA7A, 0xCC72, 0xAA81, 0xCC73, 0xAA82, 0xCC74, 0xAA83, 0xCC76, 0xAA84, 0xCC77, 0xAA85, 0xCC78, 0xAA86, 0xCC79, 0xAA87, 0xCC7A, + 0xAA88, 0xCC7B, 0xAA89, 0xCC7C, 0xAA8A, 0xCC7D, 0xAA8B, 0xCC7E, 0xAA8C, 0xCC7F, 0xAA8D, 0xCC80, 0xAA8E, 0xCC81, 0xAA8F, 0xCC82, + 0xAA90, 0xCC83, 0xAA91, 0xCC84, 0xAA92, 0xCC85, 0xAA93, 0xCC86, 0xAA94, 0xCC87, 0xAA95, 0xCC88, 0xAA96, 0xCC89, 0xAA97, 0xCC8A, + 0xAA98, 0xCC8B, 0xAA99, 0xCC8C, 0xAA9A, 0xCC8D, 0xAA9B, 0xCC8E, 0xAA9C, 0xCC8F, 0xAA9D, 0xCC90, 0xAA9E, 0xCC91, 0xAA9F, 0xCC92, + 0xAAA0, 0xCC93, 0xAAA1, 0x3041, 0xAAA2, 0x3042, 0xAAA3, 0x3043, 0xAAA4, 0x3044, 0xAAA5, 0x3045, 0xAAA6, 0x3046, 0xAAA7, 0x3047, + 0xAAA8, 0x3048, 0xAAA9, 0x3049, 0xAAAA, 0x304A, 0xAAAB, 0x304B, 0xAAAC, 0x304C, 0xAAAD, 0x304D, 0xAAAE, 0x304E, 0xAAAF, 0x304F, + 0xAAB0, 0x3050, 0xAAB1, 0x3051, 0xAAB2, 0x3052, 0xAAB3, 0x3053, 0xAAB4, 0x3054, 0xAAB5, 0x3055, 0xAAB6, 0x3056, 0xAAB7, 0x3057, + 0xAAB8, 0x3058, 0xAAB9, 0x3059, 0xAABA, 0x305A, 0xAABB, 0x305B, 0xAABC, 0x305C, 0xAABD, 0x305D, 0xAABE, 0x305E, 0xAABF, 0x305F, + 0xAAC0, 0x3060, 0xAAC1, 0x3061, 0xAAC2, 0x3062, 0xAAC3, 0x3063, 0xAAC4, 0x3064, 0xAAC5, 0x3065, 0xAAC6, 0x3066, 0xAAC7, 0x3067, + 0xAAC8, 0x3068, 0xAAC9, 0x3069, 0xAACA, 0x306A, 0xAACB, 0x306B, 0xAACC, 0x306C, 0xAACD, 0x306D, 0xAACE, 0x306E, 0xAACF, 0x306F, + 0xAAD0, 0x3070, 0xAAD1, 0x3071, 0xAAD2, 0x3072, 0xAAD3, 0x3073, 0xAAD4, 0x3074, 0xAAD5, 0x3075, 0xAAD6, 0x3076, 0xAAD7, 0x3077, + 0xAAD8, 0x3078, 0xAAD9, 0x3079, 0xAADA, 0x307A, 0xAADB, 0x307B, 0xAADC, 0x307C, 0xAADD, 0x307D, 0xAADE, 0x307E, 0xAADF, 0x307F, + 0xAAE0, 0x3080, 0xAAE1, 0x3081, 0xAAE2, 0x3082, 0xAAE3, 0x3083, 0xAAE4, 0x3084, 0xAAE5, 0x3085, 0xAAE6, 0x3086, 0xAAE7, 0x3087, + 0xAAE8, 0x3088, 0xAAE9, 0x3089, 0xAAEA, 0x308A, 0xAAEB, 0x308B, 0xAAEC, 0x308C, 0xAAED, 0x308D, 0xAAEE, 0x308E, 0xAAEF, 0x308F, + 0xAAF0, 0x3090, 0xAAF1, 0x3091, 0xAAF2, 0x3092, 0xAAF3, 0x3093, 0xAB41, 0xCC94, 0xAB42, 0xCC95, 0xAB43, 0xCC96, 0xAB44, 0xCC97, + 0xAB45, 0xCC9A, 0xAB46, 0xCC9B, 0xAB47, 0xCC9D, 0xAB48, 0xCC9E, 0xAB49, 0xCC9F, 0xAB4A, 0xCCA1, 0xAB4B, 0xCCA2, 0xAB4C, 0xCCA3, + 0xAB4D, 0xCCA4, 0xAB4E, 0xCCA5, 0xAB4F, 0xCCA6, 0xAB50, 0xCCA7, 0xAB51, 0xCCAA, 0xAB52, 0xCCAE, 0xAB53, 0xCCAF, 0xAB54, 0xCCB0, + 0xAB55, 0xCCB1, 0xAB56, 0xCCB2, 0xAB57, 0xCCB3, 0xAB58, 0xCCB6, 0xAB59, 0xCCB7, 0xAB5A, 0xCCB9, 0xAB61, 0xCCBA, 0xAB62, 0xCCBB, + 0xAB63, 0xCCBD, 0xAB64, 0xCCBE, 0xAB65, 0xCCBF, 0xAB66, 0xCCC0, 0xAB67, 0xCCC1, 0xAB68, 0xCCC2, 0xAB69, 0xCCC3, 0xAB6A, 0xCCC6, + 0xAB6B, 0xCCC8, 0xAB6C, 0xCCCA, 0xAB6D, 0xCCCB, 0xAB6E, 0xCCCC, 0xAB6F, 0xCCCD, 0xAB70, 0xCCCE, 0xAB71, 0xCCCF, 0xAB72, 0xCCD1, + 0xAB73, 0xCCD2, 0xAB74, 0xCCD3, 0xAB75, 0xCCD5, 0xAB76, 0xCCD6, 0xAB77, 0xCCD7, 0xAB78, 0xCCD8, 0xAB79, 0xCCD9, 0xAB7A, 0xCCDA, + 0xAB81, 0xCCDB, 0xAB82, 0xCCDC, 0xAB83, 0xCCDD, 0xAB84, 0xCCDE, 0xAB85, 0xCCDF, 0xAB86, 0xCCE0, 0xAB87, 0xCCE1, 0xAB88, 0xCCE2, + 0xAB89, 0xCCE3, 0xAB8A, 0xCCE5, 0xAB8B, 0xCCE6, 0xAB8C, 0xCCE7, 0xAB8D, 0xCCE8, 0xAB8E, 0xCCE9, 0xAB8F, 0xCCEA, 0xAB90, 0xCCEB, + 0xAB91, 0xCCED, 0xAB92, 0xCCEE, 0xAB93, 0xCCEF, 0xAB94, 0xCCF1, 0xAB95, 0xCCF2, 0xAB96, 0xCCF3, 0xAB97, 0xCCF4, 0xAB98, 0xCCF5, + 0xAB99, 0xCCF6, 0xAB9A, 0xCCF7, 0xAB9B, 0xCCF8, 0xAB9C, 0xCCF9, 0xAB9D, 0xCCFA, 0xAB9E, 0xCCFB, 0xAB9F, 0xCCFC, 0xABA0, 0xCCFD, + 0xABA1, 0x30A1, 0xABA2, 0x30A2, 0xABA3, 0x30A3, 0xABA4, 0x30A4, 0xABA5, 0x30A5, 0xABA6, 0x30A6, 0xABA7, 0x30A7, 0xABA8, 0x30A8, + 0xABA9, 0x30A9, 0xABAA, 0x30AA, 0xABAB, 0x30AB, 0xABAC, 0x30AC, 0xABAD, 0x30AD, 0xABAE, 0x30AE, 0xABAF, 0x30AF, 0xABB0, 0x30B0, + 0xABB1, 0x30B1, 0xABB2, 0x30B2, 0xABB3, 0x30B3, 0xABB4, 0x30B4, 0xABB5, 0x30B5, 0xABB6, 0x30B6, 0xABB7, 0x30B7, 0xABB8, 0x30B8, + 0xABB9, 0x30B9, 0xABBA, 0x30BA, 0xABBB, 0x30BB, 0xABBC, 0x30BC, 0xABBD, 0x30BD, 0xABBE, 0x30BE, 0xABBF, 0x30BF, 0xABC0, 0x30C0, + 0xABC1, 0x30C1, 0xABC2, 0x30C2, 0xABC3, 0x30C3, 0xABC4, 0x30C4, 0xABC5, 0x30C5, 0xABC6, 0x30C6, 0xABC7, 0x30C7, 0xABC8, 0x30C8, + 0xABC9, 0x30C9, 0xABCA, 0x30CA, 0xABCB, 0x30CB, 0xABCC, 0x30CC, 0xABCD, 0x30CD, 0xABCE, 0x30CE, 0xABCF, 0x30CF, 0xABD0, 0x30D0, + 0xABD1, 0x30D1, 0xABD2, 0x30D2, 0xABD3, 0x30D3, 0xABD4, 0x30D4, 0xABD5, 0x30D5, 0xABD6, 0x30D6, 0xABD7, 0x30D7, 0xABD8, 0x30D8, + 0xABD9, 0x30D9, 0xABDA, 0x30DA, 0xABDB, 0x30DB, 0xABDC, 0x30DC, 0xABDD, 0x30DD, 0xABDE, 0x30DE, 0xABDF, 0x30DF, 0xABE0, 0x30E0, + 0xABE1, 0x30E1, 0xABE2, 0x30E2, 0xABE3, 0x30E3, 0xABE4, 0x30E4, 0xABE5, 0x30E5, 0xABE6, 0x30E6, 0xABE7, 0x30E7, 0xABE8, 0x30E8, + 0xABE9, 0x30E9, 0xABEA, 0x30EA, 0xABEB, 0x30EB, 0xABEC, 0x30EC, 0xABED, 0x30ED, 0xABEE, 0x30EE, 0xABEF, 0x30EF, 0xABF0, 0x30F0, + 0xABF1, 0x30F1, 0xABF2, 0x30F2, 0xABF3, 0x30F3, 0xABF4, 0x30F4, 0xABF5, 0x30F5, 0xABF6, 0x30F6, 0xAC41, 0xCCFE, 0xAC42, 0xCCFF, + 0xAC43, 0xCD00, 0xAC44, 0xCD02, 0xAC45, 0xCD03, 0xAC46, 0xCD04, 0xAC47, 0xCD05, 0xAC48, 0xCD06, 0xAC49, 0xCD07, 0xAC4A, 0xCD0A, + 0xAC4B, 0xCD0B, 0xAC4C, 0xCD0D, 0xAC4D, 0xCD0E, 0xAC4E, 0xCD0F, 0xAC4F, 0xCD11, 0xAC50, 0xCD12, 0xAC51, 0xCD13, 0xAC52, 0xCD14, + 0xAC53, 0xCD15, 0xAC54, 0xCD16, 0xAC55, 0xCD17, 0xAC56, 0xCD1A, 0xAC57, 0xCD1C, 0xAC58, 0xCD1E, 0xAC59, 0xCD1F, 0xAC5A, 0xCD20, + 0xAC61, 0xCD21, 0xAC62, 0xCD22, 0xAC63, 0xCD23, 0xAC64, 0xCD25, 0xAC65, 0xCD26, 0xAC66, 0xCD27, 0xAC67, 0xCD29, 0xAC68, 0xCD2A, + 0xAC69, 0xCD2B, 0xAC6A, 0xCD2D, 0xAC6B, 0xCD2E, 0xAC6C, 0xCD2F, 0xAC6D, 0xCD30, 0xAC6E, 0xCD31, 0xAC6F, 0xCD32, 0xAC70, 0xCD33, + 0xAC71, 0xCD34, 0xAC72, 0xCD35, 0xAC73, 0xCD36, 0xAC74, 0xCD37, 0xAC75, 0xCD38, 0xAC76, 0xCD3A, 0xAC77, 0xCD3B, 0xAC78, 0xCD3C, + 0xAC79, 0xCD3D, 0xAC7A, 0xCD3E, 0xAC81, 0xCD3F, 0xAC82, 0xCD40, 0xAC83, 0xCD41, 0xAC84, 0xCD42, 0xAC85, 0xCD43, 0xAC86, 0xCD44, + 0xAC87, 0xCD45, 0xAC88, 0xCD46, 0xAC89, 0xCD47, 0xAC8A, 0xCD48, 0xAC8B, 0xCD49, 0xAC8C, 0xCD4A, 0xAC8D, 0xCD4B, 0xAC8E, 0xCD4C, + 0xAC8F, 0xCD4D, 0xAC90, 0xCD4E, 0xAC91, 0xCD4F, 0xAC92, 0xCD50, 0xAC93, 0xCD51, 0xAC94, 0xCD52, 0xAC95, 0xCD53, 0xAC96, 0xCD54, + 0xAC97, 0xCD55, 0xAC98, 0xCD56, 0xAC99, 0xCD57, 0xAC9A, 0xCD58, 0xAC9B, 0xCD59, 0xAC9C, 0xCD5A, 0xAC9D, 0xCD5B, 0xAC9E, 0xCD5D, + 0xAC9F, 0xCD5E, 0xACA0, 0xCD5F, 0xACA1, 0x0410, 0xACA2, 0x0411, 0xACA3, 0x0412, 0xACA4, 0x0413, 0xACA5, 0x0414, 0xACA6, 0x0415, + 0xACA7, 0x0401, 0xACA8, 0x0416, 0xACA9, 0x0417, 0xACAA, 0x0418, 0xACAB, 0x0419, 0xACAC, 0x041A, 0xACAD, 0x041B, 0xACAE, 0x041C, + 0xACAF, 0x041D, 0xACB0, 0x041E, 0xACB1, 0x041F, 0xACB2, 0x0420, 0xACB3, 0x0421, 0xACB4, 0x0422, 0xACB5, 0x0423, 0xACB6, 0x0424, + 0xACB7, 0x0425, 0xACB8, 0x0426, 0xACB9, 0x0427, 0xACBA, 0x0428, 0xACBB, 0x0429, 0xACBC, 0x042A, 0xACBD, 0x042B, 0xACBE, 0x042C, + 0xACBF, 0x042D, 0xACC0, 0x042E, 0xACC1, 0x042F, 0xACD1, 0x0430, 0xACD2, 0x0431, 0xACD3, 0x0432, 0xACD4, 0x0433, 0xACD5, 0x0434, + 0xACD6, 0x0435, 0xACD7, 0x0451, 0xACD8, 0x0436, 0xACD9, 0x0437, 0xACDA, 0x0438, 0xACDB, 0x0439, 0xACDC, 0x043A, 0xACDD, 0x043B, + 0xACDE, 0x043C, 0xACDF, 0x043D, 0xACE0, 0x043E, 0xACE1, 0x043F, 0xACE2, 0x0440, 0xACE3, 0x0441, 0xACE4, 0x0442, 0xACE5, 0x0443, + 0xACE6, 0x0444, 0xACE7, 0x0445, 0xACE8, 0x0446, 0xACE9, 0x0447, 0xACEA, 0x0448, 0xACEB, 0x0449, 0xACEC, 0x044A, 0xACED, 0x044B, + 0xACEE, 0x044C, 0xACEF, 0x044D, 0xACF0, 0x044E, 0xACF1, 0x044F, 0xAD41, 0xCD61, 0xAD42, 0xCD62, 0xAD43, 0xCD63, 0xAD44, 0xCD65, + 0xAD45, 0xCD66, 0xAD46, 0xCD67, 0xAD47, 0xCD68, 0xAD48, 0xCD69, 0xAD49, 0xCD6A, 0xAD4A, 0xCD6B, 0xAD4B, 0xCD6E, 0xAD4C, 0xCD70, + 0xAD4D, 0xCD72, 0xAD4E, 0xCD73, 0xAD4F, 0xCD74, 0xAD50, 0xCD75, 0xAD51, 0xCD76, 0xAD52, 0xCD77, 0xAD53, 0xCD79, 0xAD54, 0xCD7A, + 0xAD55, 0xCD7B, 0xAD56, 0xCD7C, 0xAD57, 0xCD7D, 0xAD58, 0xCD7E, 0xAD59, 0xCD7F, 0xAD5A, 0xCD80, 0xAD61, 0xCD81, 0xAD62, 0xCD82, + 0xAD63, 0xCD83, 0xAD64, 0xCD84, 0xAD65, 0xCD85, 0xAD66, 0xCD86, 0xAD67, 0xCD87, 0xAD68, 0xCD89, 0xAD69, 0xCD8A, 0xAD6A, 0xCD8B, + 0xAD6B, 0xCD8C, 0xAD6C, 0xCD8D, 0xAD6D, 0xCD8E, 0xAD6E, 0xCD8F, 0xAD6F, 0xCD90, 0xAD70, 0xCD91, 0xAD71, 0xCD92, 0xAD72, 0xCD93, + 0xAD73, 0xCD96, 0xAD74, 0xCD97, 0xAD75, 0xCD99, 0xAD76, 0xCD9A, 0xAD77, 0xCD9B, 0xAD78, 0xCD9D, 0xAD79, 0xCD9E, 0xAD7A, 0xCD9F, + 0xAD81, 0xCDA0, 0xAD82, 0xCDA1, 0xAD83, 0xCDA2, 0xAD84, 0xCDA3, 0xAD85, 0xCDA6, 0xAD86, 0xCDA8, 0xAD87, 0xCDAA, 0xAD88, 0xCDAB, + 0xAD89, 0xCDAC, 0xAD8A, 0xCDAD, 0xAD8B, 0xCDAE, 0xAD8C, 0xCDAF, 0xAD8D, 0xCDB1, 0xAD8E, 0xCDB2, 0xAD8F, 0xCDB3, 0xAD90, 0xCDB4, + 0xAD91, 0xCDB5, 0xAD92, 0xCDB6, 0xAD93, 0xCDB7, 0xAD94, 0xCDB8, 0xAD95, 0xCDB9, 0xAD96, 0xCDBA, 0xAD97, 0xCDBB, 0xAD98, 0xCDBC, + 0xAD99, 0xCDBD, 0xAD9A, 0xCDBE, 0xAD9B, 0xCDBF, 0xAD9C, 0xCDC0, 0xAD9D, 0xCDC1, 0xAD9E, 0xCDC2, 0xAD9F, 0xCDC3, 0xADA0, 0xCDC5, + 0xAE41, 0xCDC6, 0xAE42, 0xCDC7, 0xAE43, 0xCDC8, 0xAE44, 0xCDC9, 0xAE45, 0xCDCA, 0xAE46, 0xCDCB, 0xAE47, 0xCDCD, 0xAE48, 0xCDCE, + 0xAE49, 0xCDCF, 0xAE4A, 0xCDD1, 0xAE4B, 0xCDD2, 0xAE4C, 0xCDD3, 0xAE4D, 0xCDD4, 0xAE4E, 0xCDD5, 0xAE4F, 0xCDD6, 0xAE50, 0xCDD7, + 0xAE51, 0xCDD8, 0xAE52, 0xCDD9, 0xAE53, 0xCDDA, 0xAE54, 0xCDDB, 0xAE55, 0xCDDC, 0xAE56, 0xCDDD, 0xAE57, 0xCDDE, 0xAE58, 0xCDDF, + 0xAE59, 0xCDE0, 0xAE5A, 0xCDE1, 0xAE61, 0xCDE2, 0xAE62, 0xCDE3, 0xAE63, 0xCDE4, 0xAE64, 0xCDE5, 0xAE65, 0xCDE6, 0xAE66, 0xCDE7, + 0xAE67, 0xCDE9, 0xAE68, 0xCDEA, 0xAE69, 0xCDEB, 0xAE6A, 0xCDED, 0xAE6B, 0xCDEE, 0xAE6C, 0xCDEF, 0xAE6D, 0xCDF1, 0xAE6E, 0xCDF2, + 0xAE6F, 0xCDF3, 0xAE70, 0xCDF4, 0xAE71, 0xCDF5, 0xAE72, 0xCDF6, 0xAE73, 0xCDF7, 0xAE74, 0xCDFA, 0xAE75, 0xCDFC, 0xAE76, 0xCDFE, + 0xAE77, 0xCDFF, 0xAE78, 0xCE00, 0xAE79, 0xCE01, 0xAE7A, 0xCE02, 0xAE81, 0xCE03, 0xAE82, 0xCE05, 0xAE83, 0xCE06, 0xAE84, 0xCE07, + 0xAE85, 0xCE09, 0xAE86, 0xCE0A, 0xAE87, 0xCE0B, 0xAE88, 0xCE0D, 0xAE89, 0xCE0E, 0xAE8A, 0xCE0F, 0xAE8B, 0xCE10, 0xAE8C, 0xCE11, + 0xAE8D, 0xCE12, 0xAE8E, 0xCE13, 0xAE8F, 0xCE15, 0xAE90, 0xCE16, 0xAE91, 0xCE17, 0xAE92, 0xCE18, 0xAE93, 0xCE1A, 0xAE94, 0xCE1B, + 0xAE95, 0xCE1C, 0xAE96, 0xCE1D, 0xAE97, 0xCE1E, 0xAE98, 0xCE1F, 0xAE99, 0xCE22, 0xAE9A, 0xCE23, 0xAE9B, 0xCE25, 0xAE9C, 0xCE26, + 0xAE9D, 0xCE27, 0xAE9E, 0xCE29, 0xAE9F, 0xCE2A, 0xAEA0, 0xCE2B, 0xAF41, 0xCE2C, 0xAF42, 0xCE2D, 0xAF43, 0xCE2E, 0xAF44, 0xCE2F, + 0xAF45, 0xCE32, 0xAF46, 0xCE34, 0xAF47, 0xCE36, 0xAF48, 0xCE37, 0xAF49, 0xCE38, 0xAF4A, 0xCE39, 0xAF4B, 0xCE3A, 0xAF4C, 0xCE3B, + 0xAF4D, 0xCE3C, 0xAF4E, 0xCE3D, 0xAF4F, 0xCE3E, 0xAF50, 0xCE3F, 0xAF51, 0xCE40, 0xAF52, 0xCE41, 0xAF53, 0xCE42, 0xAF54, 0xCE43, + 0xAF55, 0xCE44, 0xAF56, 0xCE45, 0xAF57, 0xCE46, 0xAF58, 0xCE47, 0xAF59, 0xCE48, 0xAF5A, 0xCE49, 0xAF61, 0xCE4A, 0xAF62, 0xCE4B, + 0xAF63, 0xCE4C, 0xAF64, 0xCE4D, 0xAF65, 0xCE4E, 0xAF66, 0xCE4F, 0xAF67, 0xCE50, 0xAF68, 0xCE51, 0xAF69, 0xCE52, 0xAF6A, 0xCE53, + 0xAF6B, 0xCE54, 0xAF6C, 0xCE55, 0xAF6D, 0xCE56, 0xAF6E, 0xCE57, 0xAF6F, 0xCE5A, 0xAF70, 0xCE5B, 0xAF71, 0xCE5D, 0xAF72, 0xCE5E, + 0xAF73, 0xCE62, 0xAF74, 0xCE63, 0xAF75, 0xCE64, 0xAF76, 0xCE65, 0xAF77, 0xCE66, 0xAF78, 0xCE67, 0xAF79, 0xCE6A, 0xAF7A, 0xCE6C, + 0xAF81, 0xCE6E, 0xAF82, 0xCE6F, 0xAF83, 0xCE70, 0xAF84, 0xCE71, 0xAF85, 0xCE72, 0xAF86, 0xCE73, 0xAF87, 0xCE76, 0xAF88, 0xCE77, + 0xAF89, 0xCE79, 0xAF8A, 0xCE7A, 0xAF8B, 0xCE7B, 0xAF8C, 0xCE7D, 0xAF8D, 0xCE7E, 0xAF8E, 0xCE7F, 0xAF8F, 0xCE80, 0xAF90, 0xCE81, + 0xAF91, 0xCE82, 0xAF92, 0xCE83, 0xAF93, 0xCE86, 0xAF94, 0xCE88, 0xAF95, 0xCE8A, 0xAF96, 0xCE8B, 0xAF97, 0xCE8C, 0xAF98, 0xCE8D, + 0xAF99, 0xCE8E, 0xAF9A, 0xCE8F, 0xAF9B, 0xCE92, 0xAF9C, 0xCE93, 0xAF9D, 0xCE95, 0xAF9E, 0xCE96, 0xAF9F, 0xCE97, 0xAFA0, 0xCE99, + 0xB041, 0xCE9A, 0xB042, 0xCE9B, 0xB043, 0xCE9C, 0xB044, 0xCE9D, 0xB045, 0xCE9E, 0xB046, 0xCE9F, 0xB047, 0xCEA2, 0xB048, 0xCEA6, + 0xB049, 0xCEA7, 0xB04A, 0xCEA8, 0xB04B, 0xCEA9, 0xB04C, 0xCEAA, 0xB04D, 0xCEAB, 0xB04E, 0xCEAE, 0xB04F, 0xCEAF, 0xB050, 0xCEB0, + 0xB051, 0xCEB1, 0xB052, 0xCEB2, 0xB053, 0xCEB3, 0xB054, 0xCEB4, 0xB055, 0xCEB5, 0xB056, 0xCEB6, 0xB057, 0xCEB7, 0xB058, 0xCEB8, + 0xB059, 0xCEB9, 0xB05A, 0xCEBA, 0xB061, 0xCEBB, 0xB062, 0xCEBC, 0xB063, 0xCEBD, 0xB064, 0xCEBE, 0xB065, 0xCEBF, 0xB066, 0xCEC0, + 0xB067, 0xCEC2, 0xB068, 0xCEC3, 0xB069, 0xCEC4, 0xB06A, 0xCEC5, 0xB06B, 0xCEC6, 0xB06C, 0xCEC7, 0xB06D, 0xCEC8, 0xB06E, 0xCEC9, + 0xB06F, 0xCECA, 0xB070, 0xCECB, 0xB071, 0xCECC, 0xB072, 0xCECD, 0xB073, 0xCECE, 0xB074, 0xCECF, 0xB075, 0xCED0, 0xB076, 0xCED1, + 0xB077, 0xCED2, 0xB078, 0xCED3, 0xB079, 0xCED4, 0xB07A, 0xCED5, 0xB081, 0xCED6, 0xB082, 0xCED7, 0xB083, 0xCED8, 0xB084, 0xCED9, + 0xB085, 0xCEDA, 0xB086, 0xCEDB, 0xB087, 0xCEDC, 0xB088, 0xCEDD, 0xB089, 0xCEDE, 0xB08A, 0xCEDF, 0xB08B, 0xCEE0, 0xB08C, 0xCEE1, + 0xB08D, 0xCEE2, 0xB08E, 0xCEE3, 0xB08F, 0xCEE6, 0xB090, 0xCEE7, 0xB091, 0xCEE9, 0xB092, 0xCEEA, 0xB093, 0xCEED, 0xB094, 0xCEEE, + 0xB095, 0xCEEF, 0xB096, 0xCEF0, 0xB097, 0xCEF1, 0xB098, 0xCEF2, 0xB099, 0xCEF3, 0xB09A, 0xCEF6, 0xB09B, 0xCEFA, 0xB09C, 0xCEFB, + 0xB09D, 0xCEFC, 0xB09E, 0xCEFD, 0xB09F, 0xCEFE, 0xB0A0, 0xCEFF, 0xB0A1, 0xAC00, 0xB0A2, 0xAC01, 0xB0A3, 0xAC04, 0xB0A4, 0xAC07, + 0xB0A5, 0xAC08, 0xB0A6, 0xAC09, 0xB0A7, 0xAC0A, 0xB0A8, 0xAC10, 0xB0A9, 0xAC11, 0xB0AA, 0xAC12, 0xB0AB, 0xAC13, 0xB0AC, 0xAC14, + 0xB0AD, 0xAC15, 0xB0AE, 0xAC16, 0xB0AF, 0xAC17, 0xB0B0, 0xAC19, 0xB0B1, 0xAC1A, 0xB0B2, 0xAC1B, 0xB0B3, 0xAC1C, 0xB0B4, 0xAC1D, + 0xB0B5, 0xAC20, 0xB0B6, 0xAC24, 0xB0B7, 0xAC2C, 0xB0B8, 0xAC2D, 0xB0B9, 0xAC2F, 0xB0BA, 0xAC30, 0xB0BB, 0xAC31, 0xB0BC, 0xAC38, + 0xB0BD, 0xAC39, 0xB0BE, 0xAC3C, 0xB0BF, 0xAC40, 0xB0C0, 0xAC4B, 0xB0C1, 0xAC4D, 0xB0C2, 0xAC54, 0xB0C3, 0xAC58, 0xB0C4, 0xAC5C, + 0xB0C5, 0xAC70, 0xB0C6, 0xAC71, 0xB0C7, 0xAC74, 0xB0C8, 0xAC77, 0xB0C9, 0xAC78, 0xB0CA, 0xAC7A, 0xB0CB, 0xAC80, 0xB0CC, 0xAC81, + 0xB0CD, 0xAC83, 0xB0CE, 0xAC84, 0xB0CF, 0xAC85, 0xB0D0, 0xAC86, 0xB0D1, 0xAC89, 0xB0D2, 0xAC8A, 0xB0D3, 0xAC8B, 0xB0D4, 0xAC8C, + 0xB0D5, 0xAC90, 0xB0D6, 0xAC94, 0xB0D7, 0xAC9C, 0xB0D8, 0xAC9D, 0xB0D9, 0xAC9F, 0xB0DA, 0xACA0, 0xB0DB, 0xACA1, 0xB0DC, 0xACA8, + 0xB0DD, 0xACA9, 0xB0DE, 0xACAA, 0xB0DF, 0xACAC, 0xB0E0, 0xACAF, 0xB0E1, 0xACB0, 0xB0E2, 0xACB8, 0xB0E3, 0xACB9, 0xB0E4, 0xACBB, + 0xB0E5, 0xACBC, 0xB0E6, 0xACBD, 0xB0E7, 0xACC1, 0xB0E8, 0xACC4, 0xB0E9, 0xACC8, 0xB0EA, 0xACCC, 0xB0EB, 0xACD5, 0xB0EC, 0xACD7, + 0xB0ED, 0xACE0, 0xB0EE, 0xACE1, 0xB0EF, 0xACE4, 0xB0F0, 0xACE7, 0xB0F1, 0xACE8, 0xB0F2, 0xACEA, 0xB0F3, 0xACEC, 0xB0F4, 0xACEF, + 0xB0F5, 0xACF0, 0xB0F6, 0xACF1, 0xB0F7, 0xACF3, 0xB0F8, 0xACF5, 0xB0F9, 0xACF6, 0xB0FA, 0xACFC, 0xB0FB, 0xACFD, 0xB0FC, 0xAD00, + 0xB0FD, 0xAD04, 0xB0FE, 0xAD06, 0xB141, 0xCF02, 0xB142, 0xCF03, 0xB143, 0xCF05, 0xB144, 0xCF06, 0xB145, 0xCF07, 0xB146, 0xCF09, + 0xB147, 0xCF0A, 0xB148, 0xCF0B, 0xB149, 0xCF0C, 0xB14A, 0xCF0D, 0xB14B, 0xCF0E, 0xB14C, 0xCF0F, 0xB14D, 0xCF12, 0xB14E, 0xCF14, + 0xB14F, 0xCF16, 0xB150, 0xCF17, 0xB151, 0xCF18, 0xB152, 0xCF19, 0xB153, 0xCF1A, 0xB154, 0xCF1B, 0xB155, 0xCF1D, 0xB156, 0xCF1E, + 0xB157, 0xCF1F, 0xB158, 0xCF21, 0xB159, 0xCF22, 0xB15A, 0xCF23, 0xB161, 0xCF25, 0xB162, 0xCF26, 0xB163, 0xCF27, 0xB164, 0xCF28, + 0xB165, 0xCF29, 0xB166, 0xCF2A, 0xB167, 0xCF2B, 0xB168, 0xCF2E, 0xB169, 0xCF32, 0xB16A, 0xCF33, 0xB16B, 0xCF34, 0xB16C, 0xCF35, + 0xB16D, 0xCF36, 0xB16E, 0xCF37, 0xB16F, 0xCF39, 0xB170, 0xCF3A, 0xB171, 0xCF3B, 0xB172, 0xCF3C, 0xB173, 0xCF3D, 0xB174, 0xCF3E, + 0xB175, 0xCF3F, 0xB176, 0xCF40, 0xB177, 0xCF41, 0xB178, 0xCF42, 0xB179, 0xCF43, 0xB17A, 0xCF44, 0xB181, 0xCF45, 0xB182, 0xCF46, + 0xB183, 0xCF47, 0xB184, 0xCF48, 0xB185, 0xCF49, 0xB186, 0xCF4A, 0xB187, 0xCF4B, 0xB188, 0xCF4C, 0xB189, 0xCF4D, 0xB18A, 0xCF4E, + 0xB18B, 0xCF4F, 0xB18C, 0xCF50, 0xB18D, 0xCF51, 0xB18E, 0xCF52, 0xB18F, 0xCF53, 0xB190, 0xCF56, 0xB191, 0xCF57, 0xB192, 0xCF59, + 0xB193, 0xCF5A, 0xB194, 0xCF5B, 0xB195, 0xCF5D, 0xB196, 0xCF5E, 0xB197, 0xCF5F, 0xB198, 0xCF60, 0xB199, 0xCF61, 0xB19A, 0xCF62, + 0xB19B, 0xCF63, 0xB19C, 0xCF66, 0xB19D, 0xCF68, 0xB19E, 0xCF6A, 0xB19F, 0xCF6B, 0xB1A0, 0xCF6C, 0xB1A1, 0xAD0C, 0xB1A2, 0xAD0D, + 0xB1A3, 0xAD0F, 0xB1A4, 0xAD11, 0xB1A5, 0xAD18, 0xB1A6, 0xAD1C, 0xB1A7, 0xAD20, 0xB1A8, 0xAD29, 0xB1A9, 0xAD2C, 0xB1AA, 0xAD2D, + 0xB1AB, 0xAD34, 0xB1AC, 0xAD35, 0xB1AD, 0xAD38, 0xB1AE, 0xAD3C, 0xB1AF, 0xAD44, 0xB1B0, 0xAD45, 0xB1B1, 0xAD47, 0xB1B2, 0xAD49, + 0xB1B3, 0xAD50, 0xB1B4, 0xAD54, 0xB1B5, 0xAD58, 0xB1B6, 0xAD61, 0xB1B7, 0xAD63, 0xB1B8, 0xAD6C, 0xB1B9, 0xAD6D, 0xB1BA, 0xAD70, + 0xB1BB, 0xAD73, 0xB1BC, 0xAD74, 0xB1BD, 0xAD75, 0xB1BE, 0xAD76, 0xB1BF, 0xAD7B, 0xB1C0, 0xAD7C, 0xB1C1, 0xAD7D, 0xB1C2, 0xAD7F, + 0xB1C3, 0xAD81, 0xB1C4, 0xAD82, 0xB1C5, 0xAD88, 0xB1C6, 0xAD89, 0xB1C7, 0xAD8C, 0xB1C8, 0xAD90, 0xB1C9, 0xAD9C, 0xB1CA, 0xAD9D, + 0xB1CB, 0xADA4, 0xB1CC, 0xADB7, 0xB1CD, 0xADC0, 0xB1CE, 0xADC1, 0xB1CF, 0xADC4, 0xB1D0, 0xADC8, 0xB1D1, 0xADD0, 0xB1D2, 0xADD1, + 0xB1D3, 0xADD3, 0xB1D4, 0xADDC, 0xB1D5, 0xADE0, 0xB1D6, 0xADE4, 0xB1D7, 0xADF8, 0xB1D8, 0xADF9, 0xB1D9, 0xADFC, 0xB1DA, 0xADFF, + 0xB1DB, 0xAE00, 0xB1DC, 0xAE01, 0xB1DD, 0xAE08, 0xB1DE, 0xAE09, 0xB1DF, 0xAE0B, 0xB1E0, 0xAE0D, 0xB1E1, 0xAE14, 0xB1E2, 0xAE30, + 0xB1E3, 0xAE31, 0xB1E4, 0xAE34, 0xB1E5, 0xAE37, 0xB1E6, 0xAE38, 0xB1E7, 0xAE3A, 0xB1E8, 0xAE40, 0xB1E9, 0xAE41, 0xB1EA, 0xAE43, + 0xB1EB, 0xAE45, 0xB1EC, 0xAE46, 0xB1ED, 0xAE4A, 0xB1EE, 0xAE4C, 0xB1EF, 0xAE4D, 0xB1F0, 0xAE4E, 0xB1F1, 0xAE50, 0xB1F2, 0xAE54, + 0xB1F3, 0xAE56, 0xB1F4, 0xAE5C, 0xB1F5, 0xAE5D, 0xB1F6, 0xAE5F, 0xB1F7, 0xAE60, 0xB1F8, 0xAE61, 0xB1F9, 0xAE65, 0xB1FA, 0xAE68, + 0xB1FB, 0xAE69, 0xB1FC, 0xAE6C, 0xB1FD, 0xAE70, 0xB1FE, 0xAE78, 0xB241, 0xCF6D, 0xB242, 0xCF6E, 0xB243, 0xCF6F, 0xB244, 0xCF72, + 0xB245, 0xCF73, 0xB246, 0xCF75, 0xB247, 0xCF76, 0xB248, 0xCF77, 0xB249, 0xCF79, 0xB24A, 0xCF7A, 0xB24B, 0xCF7B, 0xB24C, 0xCF7C, + 0xB24D, 0xCF7D, 0xB24E, 0xCF7E, 0xB24F, 0xCF7F, 0xB250, 0xCF81, 0xB251, 0xCF82, 0xB252, 0xCF83, 0xB253, 0xCF84, 0xB254, 0xCF86, + 0xB255, 0xCF87, 0xB256, 0xCF88, 0xB257, 0xCF89, 0xB258, 0xCF8A, 0xB259, 0xCF8B, 0xB25A, 0xCF8D, 0xB261, 0xCF8E, 0xB262, 0xCF8F, + 0xB263, 0xCF90, 0xB264, 0xCF91, 0xB265, 0xCF92, 0xB266, 0xCF93, 0xB267, 0xCF94, 0xB268, 0xCF95, 0xB269, 0xCF96, 0xB26A, 0xCF97, + 0xB26B, 0xCF98, 0xB26C, 0xCF99, 0xB26D, 0xCF9A, 0xB26E, 0xCF9B, 0xB26F, 0xCF9C, 0xB270, 0xCF9D, 0xB271, 0xCF9E, 0xB272, 0xCF9F, + 0xB273, 0xCFA0, 0xB274, 0xCFA2, 0xB275, 0xCFA3, 0xB276, 0xCFA4, 0xB277, 0xCFA5, 0xB278, 0xCFA6, 0xB279, 0xCFA7, 0xB27A, 0xCFA9, + 0xB281, 0xCFAA, 0xB282, 0xCFAB, 0xB283, 0xCFAC, 0xB284, 0xCFAD, 0xB285, 0xCFAE, 0xB286, 0xCFAF, 0xB287, 0xCFB1, 0xB288, 0xCFB2, + 0xB289, 0xCFB3, 0xB28A, 0xCFB4, 0xB28B, 0xCFB5, 0xB28C, 0xCFB6, 0xB28D, 0xCFB7, 0xB28E, 0xCFB8, 0xB28F, 0xCFB9, 0xB290, 0xCFBA, + 0xB291, 0xCFBB, 0xB292, 0xCFBC, 0xB293, 0xCFBD, 0xB294, 0xCFBE, 0xB295, 0xCFBF, 0xB296, 0xCFC0, 0xB297, 0xCFC1, 0xB298, 0xCFC2, + 0xB299, 0xCFC3, 0xB29A, 0xCFC5, 0xB29B, 0xCFC6, 0xB29C, 0xCFC7, 0xB29D, 0xCFC8, 0xB29E, 0xCFC9, 0xB29F, 0xCFCA, 0xB2A0, 0xCFCB, + 0xB2A1, 0xAE79, 0xB2A2, 0xAE7B, 0xB2A3, 0xAE7C, 0xB2A4, 0xAE7D, 0xB2A5, 0xAE84, 0xB2A6, 0xAE85, 0xB2A7, 0xAE8C, 0xB2A8, 0xAEBC, + 0xB2A9, 0xAEBD, 0xB2AA, 0xAEBE, 0xB2AB, 0xAEC0, 0xB2AC, 0xAEC4, 0xB2AD, 0xAECC, 0xB2AE, 0xAECD, 0xB2AF, 0xAECF, 0xB2B0, 0xAED0, + 0xB2B1, 0xAED1, 0xB2B2, 0xAED8, 0xB2B3, 0xAED9, 0xB2B4, 0xAEDC, 0xB2B5, 0xAEE8, 0xB2B6, 0xAEEB, 0xB2B7, 0xAEED, 0xB2B8, 0xAEF4, + 0xB2B9, 0xAEF8, 0xB2BA, 0xAEFC, 0xB2BB, 0xAF07, 0xB2BC, 0xAF08, 0xB2BD, 0xAF0D, 0xB2BE, 0xAF10, 0xB2BF, 0xAF2C, 0xB2C0, 0xAF2D, + 0xB2C1, 0xAF30, 0xB2C2, 0xAF32, 0xB2C3, 0xAF34, 0xB2C4, 0xAF3C, 0xB2C5, 0xAF3D, 0xB2C6, 0xAF3F, 0xB2C7, 0xAF41, 0xB2C8, 0xAF42, + 0xB2C9, 0xAF43, 0xB2CA, 0xAF48, 0xB2CB, 0xAF49, 0xB2CC, 0xAF50, 0xB2CD, 0xAF5C, 0xB2CE, 0xAF5D, 0xB2CF, 0xAF64, 0xB2D0, 0xAF65, + 0xB2D1, 0xAF79, 0xB2D2, 0xAF80, 0xB2D3, 0xAF84, 0xB2D4, 0xAF88, 0xB2D5, 0xAF90, 0xB2D6, 0xAF91, 0xB2D7, 0xAF95, 0xB2D8, 0xAF9C, + 0xB2D9, 0xAFB8, 0xB2DA, 0xAFB9, 0xB2DB, 0xAFBC, 0xB2DC, 0xAFC0, 0xB2DD, 0xAFC7, 0xB2DE, 0xAFC8, 0xB2DF, 0xAFC9, 0xB2E0, 0xAFCB, + 0xB2E1, 0xAFCD, 0xB2E2, 0xAFCE, 0xB2E3, 0xAFD4, 0xB2E4, 0xAFDC, 0xB2E5, 0xAFE8, 0xB2E6, 0xAFE9, 0xB2E7, 0xAFF0, 0xB2E8, 0xAFF1, + 0xB2E9, 0xAFF4, 0xB2EA, 0xAFF8, 0xB2EB, 0xB000, 0xB2EC, 0xB001, 0xB2ED, 0xB004, 0xB2EE, 0xB00C, 0xB2EF, 0xB010, 0xB2F0, 0xB014, + 0xB2F1, 0xB01C, 0xB2F2, 0xB01D, 0xB2F3, 0xB028, 0xB2F4, 0xB044, 0xB2F5, 0xB045, 0xB2F6, 0xB048, 0xB2F7, 0xB04A, 0xB2F8, 0xB04C, + 0xB2F9, 0xB04E, 0xB2FA, 0xB053, 0xB2FB, 0xB054, 0xB2FC, 0xB055, 0xB2FD, 0xB057, 0xB2FE, 0xB059, 0xB341, 0xCFCC, 0xB342, 0xCFCD, + 0xB343, 0xCFCE, 0xB344, 0xCFCF, 0xB345, 0xCFD0, 0xB346, 0xCFD1, 0xB347, 0xCFD2, 0xB348, 0xCFD3, 0xB349, 0xCFD4, 0xB34A, 0xCFD5, + 0xB34B, 0xCFD6, 0xB34C, 0xCFD7, 0xB34D, 0xCFD8, 0xB34E, 0xCFD9, 0xB34F, 0xCFDA, 0xB350, 0xCFDB, 0xB351, 0xCFDC, 0xB352, 0xCFDD, + 0xB353, 0xCFDE, 0xB354, 0xCFDF, 0xB355, 0xCFE2, 0xB356, 0xCFE3, 0xB357, 0xCFE5, 0xB358, 0xCFE6, 0xB359, 0xCFE7, 0xB35A, 0xCFE9, + 0xB361, 0xCFEA, 0xB362, 0xCFEB, 0xB363, 0xCFEC, 0xB364, 0xCFED, 0xB365, 0xCFEE, 0xB366, 0xCFEF, 0xB367, 0xCFF2, 0xB368, 0xCFF4, + 0xB369, 0xCFF6, 0xB36A, 0xCFF7, 0xB36B, 0xCFF8, 0xB36C, 0xCFF9, 0xB36D, 0xCFFA, 0xB36E, 0xCFFB, 0xB36F, 0xCFFD, 0xB370, 0xCFFE, + 0xB371, 0xCFFF, 0xB372, 0xD001, 0xB373, 0xD002, 0xB374, 0xD003, 0xB375, 0xD005, 0xB376, 0xD006, 0xB377, 0xD007, 0xB378, 0xD008, + 0xB379, 0xD009, 0xB37A, 0xD00A, 0xB381, 0xD00B, 0xB382, 0xD00C, 0xB383, 0xD00D, 0xB384, 0xD00E, 0xB385, 0xD00F, 0xB386, 0xD010, + 0xB387, 0xD012, 0xB388, 0xD013, 0xB389, 0xD014, 0xB38A, 0xD015, 0xB38B, 0xD016, 0xB38C, 0xD017, 0xB38D, 0xD019, 0xB38E, 0xD01A, + 0xB38F, 0xD01B, 0xB390, 0xD01C, 0xB391, 0xD01D, 0xB392, 0xD01E, 0xB393, 0xD01F, 0xB394, 0xD020, 0xB395, 0xD021, 0xB396, 0xD022, + 0xB397, 0xD023, 0xB398, 0xD024, 0xB399, 0xD025, 0xB39A, 0xD026, 0xB39B, 0xD027, 0xB39C, 0xD028, 0xB39D, 0xD029, 0xB39E, 0xD02A, + 0xB39F, 0xD02B, 0xB3A0, 0xD02C, 0xB3A1, 0xB05D, 0xB3A2, 0xB07C, 0xB3A3, 0xB07D, 0xB3A4, 0xB080, 0xB3A5, 0xB084, 0xB3A6, 0xB08C, + 0xB3A7, 0xB08D, 0xB3A8, 0xB08F, 0xB3A9, 0xB091, 0xB3AA, 0xB098, 0xB3AB, 0xB099, 0xB3AC, 0xB09A, 0xB3AD, 0xB09C, 0xB3AE, 0xB09F, + 0xB3AF, 0xB0A0, 0xB3B0, 0xB0A1, 0xB3B1, 0xB0A2, 0xB3B2, 0xB0A8, 0xB3B3, 0xB0A9, 0xB3B4, 0xB0AB, 0xB3B5, 0xB0AC, 0xB3B6, 0xB0AD, + 0xB3B7, 0xB0AE, 0xB3B8, 0xB0AF, 0xB3B9, 0xB0B1, 0xB3BA, 0xB0B3, 0xB3BB, 0xB0B4, 0xB3BC, 0xB0B5, 0xB3BD, 0xB0B8, 0xB3BE, 0xB0BC, + 0xB3BF, 0xB0C4, 0xB3C0, 0xB0C5, 0xB3C1, 0xB0C7, 0xB3C2, 0xB0C8, 0xB3C3, 0xB0C9, 0xB3C4, 0xB0D0, 0xB3C5, 0xB0D1, 0xB3C6, 0xB0D4, + 0xB3C7, 0xB0D8, 0xB3C8, 0xB0E0, 0xB3C9, 0xB0E5, 0xB3CA, 0xB108, 0xB3CB, 0xB109, 0xB3CC, 0xB10B, 0xB3CD, 0xB10C, 0xB3CE, 0xB110, + 0xB3CF, 0xB112, 0xB3D0, 0xB113, 0xB3D1, 0xB118, 0xB3D2, 0xB119, 0xB3D3, 0xB11B, 0xB3D4, 0xB11C, 0xB3D5, 0xB11D, 0xB3D6, 0xB123, + 0xB3D7, 0xB124, 0xB3D8, 0xB125, 0xB3D9, 0xB128, 0xB3DA, 0xB12C, 0xB3DB, 0xB134, 0xB3DC, 0xB135, 0xB3DD, 0xB137, 0xB3DE, 0xB138, + 0xB3DF, 0xB139, 0xB3E0, 0xB140, 0xB3E1, 0xB141, 0xB3E2, 0xB144, 0xB3E3, 0xB148, 0xB3E4, 0xB150, 0xB3E5, 0xB151, 0xB3E6, 0xB154, + 0xB3E7, 0xB155, 0xB3E8, 0xB158, 0xB3E9, 0xB15C, 0xB3EA, 0xB160, 0xB3EB, 0xB178, 0xB3EC, 0xB179, 0xB3ED, 0xB17C, 0xB3EE, 0xB180, + 0xB3EF, 0xB182, 0xB3F0, 0xB188, 0xB3F1, 0xB189, 0xB3F2, 0xB18B, 0xB3F3, 0xB18D, 0xB3F4, 0xB192, 0xB3F5, 0xB193, 0xB3F6, 0xB194, + 0xB3F7, 0xB198, 0xB3F8, 0xB19C, 0xB3F9, 0xB1A8, 0xB3FA, 0xB1CC, 0xB3FB, 0xB1D0, 0xB3FC, 0xB1D4, 0xB3FD, 0xB1DC, 0xB3FE, 0xB1DD, + 0xB441, 0xD02E, 0xB442, 0xD02F, 0xB443, 0xD030, 0xB444, 0xD031, 0xB445, 0xD032, 0xB446, 0xD033, 0xB447, 0xD036, 0xB448, 0xD037, + 0xB449, 0xD039, 0xB44A, 0xD03A, 0xB44B, 0xD03B, 0xB44C, 0xD03D, 0xB44D, 0xD03E, 0xB44E, 0xD03F, 0xB44F, 0xD040, 0xB450, 0xD041, + 0xB451, 0xD042, 0xB452, 0xD043, 0xB453, 0xD046, 0xB454, 0xD048, 0xB455, 0xD04A, 0xB456, 0xD04B, 0xB457, 0xD04C, 0xB458, 0xD04D, + 0xB459, 0xD04E, 0xB45A, 0xD04F, 0xB461, 0xD051, 0xB462, 0xD052, 0xB463, 0xD053, 0xB464, 0xD055, 0xB465, 0xD056, 0xB466, 0xD057, + 0xB467, 0xD059, 0xB468, 0xD05A, 0xB469, 0xD05B, 0xB46A, 0xD05C, 0xB46B, 0xD05D, 0xB46C, 0xD05E, 0xB46D, 0xD05F, 0xB46E, 0xD061, + 0xB46F, 0xD062, 0xB470, 0xD063, 0xB471, 0xD064, 0xB472, 0xD065, 0xB473, 0xD066, 0xB474, 0xD067, 0xB475, 0xD068, 0xB476, 0xD069, + 0xB477, 0xD06A, 0xB478, 0xD06B, 0xB479, 0xD06E, 0xB47A, 0xD06F, 0xB481, 0xD071, 0xB482, 0xD072, 0xB483, 0xD073, 0xB484, 0xD075, + 0xB485, 0xD076, 0xB486, 0xD077, 0xB487, 0xD078, 0xB488, 0xD079, 0xB489, 0xD07A, 0xB48A, 0xD07B, 0xB48B, 0xD07E, 0xB48C, 0xD07F, + 0xB48D, 0xD080, 0xB48E, 0xD082, 0xB48F, 0xD083, 0xB490, 0xD084, 0xB491, 0xD085, 0xB492, 0xD086, 0xB493, 0xD087, 0xB494, 0xD088, + 0xB495, 0xD089, 0xB496, 0xD08A, 0xB497, 0xD08B, 0xB498, 0xD08C, 0xB499, 0xD08D, 0xB49A, 0xD08E, 0xB49B, 0xD08F, 0xB49C, 0xD090, + 0xB49D, 0xD091, 0xB49E, 0xD092, 0xB49F, 0xD093, 0xB4A0, 0xD094, 0xB4A1, 0xB1DF, 0xB4A2, 0xB1E8, 0xB4A3, 0xB1E9, 0xB4A4, 0xB1EC, + 0xB4A5, 0xB1F0, 0xB4A6, 0xB1F9, 0xB4A7, 0xB1FB, 0xB4A8, 0xB1FD, 0xB4A9, 0xB204, 0xB4AA, 0xB205, 0xB4AB, 0xB208, 0xB4AC, 0xB20B, + 0xB4AD, 0xB20C, 0xB4AE, 0xB214, 0xB4AF, 0xB215, 0xB4B0, 0xB217, 0xB4B1, 0xB219, 0xB4B2, 0xB220, 0xB4B3, 0xB234, 0xB4B4, 0xB23C, + 0xB4B5, 0xB258, 0xB4B6, 0xB25C, 0xB4B7, 0xB260, 0xB4B8, 0xB268, 0xB4B9, 0xB269, 0xB4BA, 0xB274, 0xB4BB, 0xB275, 0xB4BC, 0xB27C, + 0xB4BD, 0xB284, 0xB4BE, 0xB285, 0xB4BF, 0xB289, 0xB4C0, 0xB290, 0xB4C1, 0xB291, 0xB4C2, 0xB294, 0xB4C3, 0xB298, 0xB4C4, 0xB299, + 0xB4C5, 0xB29A, 0xB4C6, 0xB2A0, 0xB4C7, 0xB2A1, 0xB4C8, 0xB2A3, 0xB4C9, 0xB2A5, 0xB4CA, 0xB2A6, 0xB4CB, 0xB2AA, 0xB4CC, 0xB2AC, + 0xB4CD, 0xB2B0, 0xB4CE, 0xB2B4, 0xB4CF, 0xB2C8, 0xB4D0, 0xB2C9, 0xB4D1, 0xB2CC, 0xB4D2, 0xB2D0, 0xB4D3, 0xB2D2, 0xB4D4, 0xB2D8, + 0xB4D5, 0xB2D9, 0xB4D6, 0xB2DB, 0xB4D7, 0xB2DD, 0xB4D8, 0xB2E2, 0xB4D9, 0xB2E4, 0xB4DA, 0xB2E5, 0xB4DB, 0xB2E6, 0xB4DC, 0xB2E8, + 0xB4DD, 0xB2EB, 0xB4DE, 0xB2EC, 0xB4DF, 0xB2ED, 0xB4E0, 0xB2EE, 0xB4E1, 0xB2EF, 0xB4E2, 0xB2F3, 0xB4E3, 0xB2F4, 0xB4E4, 0xB2F5, + 0xB4E5, 0xB2F7, 0xB4E6, 0xB2F8, 0xB4E7, 0xB2F9, 0xB4E8, 0xB2FA, 0xB4E9, 0xB2FB, 0xB4EA, 0xB2FF, 0xB4EB, 0xB300, 0xB4EC, 0xB301, + 0xB4ED, 0xB304, 0xB4EE, 0xB308, 0xB4EF, 0xB310, 0xB4F0, 0xB311, 0xB4F1, 0xB313, 0xB4F2, 0xB314, 0xB4F3, 0xB315, 0xB4F4, 0xB31C, + 0xB4F5, 0xB354, 0xB4F6, 0xB355, 0xB4F7, 0xB356, 0xB4F8, 0xB358, 0xB4F9, 0xB35B, 0xB4FA, 0xB35C, 0xB4FB, 0xB35E, 0xB4FC, 0xB35F, + 0xB4FD, 0xB364, 0xB4FE, 0xB365, 0xB541, 0xD095, 0xB542, 0xD096, 0xB543, 0xD097, 0xB544, 0xD098, 0xB545, 0xD099, 0xB546, 0xD09A, + 0xB547, 0xD09B, 0xB548, 0xD09C, 0xB549, 0xD09D, 0xB54A, 0xD09E, 0xB54B, 0xD09F, 0xB54C, 0xD0A0, 0xB54D, 0xD0A1, 0xB54E, 0xD0A2, + 0xB54F, 0xD0A3, 0xB550, 0xD0A6, 0xB551, 0xD0A7, 0xB552, 0xD0A9, 0xB553, 0xD0AA, 0xB554, 0xD0AB, 0xB555, 0xD0AD, 0xB556, 0xD0AE, + 0xB557, 0xD0AF, 0xB558, 0xD0B0, 0xB559, 0xD0B1, 0xB55A, 0xD0B2, 0xB561, 0xD0B3, 0xB562, 0xD0B6, 0xB563, 0xD0B8, 0xB564, 0xD0BA, + 0xB565, 0xD0BB, 0xB566, 0xD0BC, 0xB567, 0xD0BD, 0xB568, 0xD0BE, 0xB569, 0xD0BF, 0xB56A, 0xD0C2, 0xB56B, 0xD0C3, 0xB56C, 0xD0C5, + 0xB56D, 0xD0C6, 0xB56E, 0xD0C7, 0xB56F, 0xD0CA, 0xB570, 0xD0CB, 0xB571, 0xD0CC, 0xB572, 0xD0CD, 0xB573, 0xD0CE, 0xB574, 0xD0CF, + 0xB575, 0xD0D2, 0xB576, 0xD0D6, 0xB577, 0xD0D7, 0xB578, 0xD0D8, 0xB579, 0xD0D9, 0xB57A, 0xD0DA, 0xB581, 0xD0DB, 0xB582, 0xD0DE, + 0xB583, 0xD0DF, 0xB584, 0xD0E1, 0xB585, 0xD0E2, 0xB586, 0xD0E3, 0xB587, 0xD0E5, 0xB588, 0xD0E6, 0xB589, 0xD0E7, 0xB58A, 0xD0E8, + 0xB58B, 0xD0E9, 0xB58C, 0xD0EA, 0xB58D, 0xD0EB, 0xB58E, 0xD0EE, 0xB58F, 0xD0F2, 0xB590, 0xD0F3, 0xB591, 0xD0F4, 0xB592, 0xD0F5, + 0xB593, 0xD0F6, 0xB594, 0xD0F7, 0xB595, 0xD0F9, 0xB596, 0xD0FA, 0xB597, 0xD0FB, 0xB598, 0xD0FC, 0xB599, 0xD0FD, 0xB59A, 0xD0FE, + 0xB59B, 0xD0FF, 0xB59C, 0xD100, 0xB59D, 0xD101, 0xB59E, 0xD102, 0xB59F, 0xD103, 0xB5A0, 0xD104, 0xB5A1, 0xB367, 0xB5A2, 0xB369, + 0xB5A3, 0xB36B, 0xB5A4, 0xB36E, 0xB5A5, 0xB370, 0xB5A6, 0xB371, 0xB5A7, 0xB374, 0xB5A8, 0xB378, 0xB5A9, 0xB380, 0xB5AA, 0xB381, + 0xB5AB, 0xB383, 0xB5AC, 0xB384, 0xB5AD, 0xB385, 0xB5AE, 0xB38C, 0xB5AF, 0xB390, 0xB5B0, 0xB394, 0xB5B1, 0xB3A0, 0xB5B2, 0xB3A1, + 0xB5B3, 0xB3A8, 0xB5B4, 0xB3AC, 0xB5B5, 0xB3C4, 0xB5B6, 0xB3C5, 0xB5B7, 0xB3C8, 0xB5B8, 0xB3CB, 0xB5B9, 0xB3CC, 0xB5BA, 0xB3CE, + 0xB5BB, 0xB3D0, 0xB5BC, 0xB3D4, 0xB5BD, 0xB3D5, 0xB5BE, 0xB3D7, 0xB5BF, 0xB3D9, 0xB5C0, 0xB3DB, 0xB5C1, 0xB3DD, 0xB5C2, 0xB3E0, + 0xB5C3, 0xB3E4, 0xB5C4, 0xB3E8, 0xB5C5, 0xB3FC, 0xB5C6, 0xB410, 0xB5C7, 0xB418, 0xB5C8, 0xB41C, 0xB5C9, 0xB420, 0xB5CA, 0xB428, + 0xB5CB, 0xB429, 0xB5CC, 0xB42B, 0xB5CD, 0xB434, 0xB5CE, 0xB450, 0xB5CF, 0xB451, 0xB5D0, 0xB454, 0xB5D1, 0xB458, 0xB5D2, 0xB460, + 0xB5D3, 0xB461, 0xB5D4, 0xB463, 0xB5D5, 0xB465, 0xB5D6, 0xB46C, 0xB5D7, 0xB480, 0xB5D8, 0xB488, 0xB5D9, 0xB49D, 0xB5DA, 0xB4A4, + 0xB5DB, 0xB4A8, 0xB5DC, 0xB4AC, 0xB5DD, 0xB4B5, 0xB5DE, 0xB4B7, 0xB5DF, 0xB4B9, 0xB5E0, 0xB4C0, 0xB5E1, 0xB4C4, 0xB5E2, 0xB4C8, + 0xB5E3, 0xB4D0, 0xB5E4, 0xB4D5, 0xB5E5, 0xB4DC, 0xB5E6, 0xB4DD, 0xB5E7, 0xB4E0, 0xB5E8, 0xB4E3, 0xB5E9, 0xB4E4, 0xB5EA, 0xB4E6, + 0xB5EB, 0xB4EC, 0xB5EC, 0xB4ED, 0xB5ED, 0xB4EF, 0xB5EE, 0xB4F1, 0xB5EF, 0xB4F8, 0xB5F0, 0xB514, 0xB5F1, 0xB515, 0xB5F2, 0xB518, + 0xB5F3, 0xB51B, 0xB5F4, 0xB51C, 0xB5F5, 0xB524, 0xB5F6, 0xB525, 0xB5F7, 0xB527, 0xB5F8, 0xB528, 0xB5F9, 0xB529, 0xB5FA, 0xB52A, + 0xB5FB, 0xB530, 0xB5FC, 0xB531, 0xB5FD, 0xB534, 0xB5FE, 0xB538, 0xB641, 0xD105, 0xB642, 0xD106, 0xB643, 0xD107, 0xB644, 0xD108, + 0xB645, 0xD109, 0xB646, 0xD10A, 0xB647, 0xD10B, 0xB648, 0xD10C, 0xB649, 0xD10E, 0xB64A, 0xD10F, 0xB64B, 0xD110, 0xB64C, 0xD111, + 0xB64D, 0xD112, 0xB64E, 0xD113, 0xB64F, 0xD114, 0xB650, 0xD115, 0xB651, 0xD116, 0xB652, 0xD117, 0xB653, 0xD118, 0xB654, 0xD119, + 0xB655, 0xD11A, 0xB656, 0xD11B, 0xB657, 0xD11C, 0xB658, 0xD11D, 0xB659, 0xD11E, 0xB65A, 0xD11F, 0xB661, 0xD120, 0xB662, 0xD121, + 0xB663, 0xD122, 0xB664, 0xD123, 0xB665, 0xD124, 0xB666, 0xD125, 0xB667, 0xD126, 0xB668, 0xD127, 0xB669, 0xD128, 0xB66A, 0xD129, + 0xB66B, 0xD12A, 0xB66C, 0xD12B, 0xB66D, 0xD12C, 0xB66E, 0xD12D, 0xB66F, 0xD12E, 0xB670, 0xD12F, 0xB671, 0xD132, 0xB672, 0xD133, + 0xB673, 0xD135, 0xB674, 0xD136, 0xB675, 0xD137, 0xB676, 0xD139, 0xB677, 0xD13B, 0xB678, 0xD13C, 0xB679, 0xD13D, 0xB67A, 0xD13E, + 0xB681, 0xD13F, 0xB682, 0xD142, 0xB683, 0xD146, 0xB684, 0xD147, 0xB685, 0xD148, 0xB686, 0xD149, 0xB687, 0xD14A, 0xB688, 0xD14B, + 0xB689, 0xD14E, 0xB68A, 0xD14F, 0xB68B, 0xD151, 0xB68C, 0xD152, 0xB68D, 0xD153, 0xB68E, 0xD155, 0xB68F, 0xD156, 0xB690, 0xD157, + 0xB691, 0xD158, 0xB692, 0xD159, 0xB693, 0xD15A, 0xB694, 0xD15B, 0xB695, 0xD15E, 0xB696, 0xD160, 0xB697, 0xD162, 0xB698, 0xD163, + 0xB699, 0xD164, 0xB69A, 0xD165, 0xB69B, 0xD166, 0xB69C, 0xD167, 0xB69D, 0xD169, 0xB69E, 0xD16A, 0xB69F, 0xD16B, 0xB6A0, 0xD16D, + 0xB6A1, 0xB540, 0xB6A2, 0xB541, 0xB6A3, 0xB543, 0xB6A4, 0xB544, 0xB6A5, 0xB545, 0xB6A6, 0xB54B, 0xB6A7, 0xB54C, 0xB6A8, 0xB54D, + 0xB6A9, 0xB550, 0xB6AA, 0xB554, 0xB6AB, 0xB55C, 0xB6AC, 0xB55D, 0xB6AD, 0xB55F, 0xB6AE, 0xB560, 0xB6AF, 0xB561, 0xB6B0, 0xB5A0, + 0xB6B1, 0xB5A1, 0xB6B2, 0xB5A4, 0xB6B3, 0xB5A8, 0xB6B4, 0xB5AA, 0xB6B5, 0xB5AB, 0xB6B6, 0xB5B0, 0xB6B7, 0xB5B1, 0xB6B8, 0xB5B3, + 0xB6B9, 0xB5B4, 0xB6BA, 0xB5B5, 0xB6BB, 0xB5BB, 0xB6BC, 0xB5BC, 0xB6BD, 0xB5BD, 0xB6BE, 0xB5C0, 0xB6BF, 0xB5C4, 0xB6C0, 0xB5CC, + 0xB6C1, 0xB5CD, 0xB6C2, 0xB5CF, 0xB6C3, 0xB5D0, 0xB6C4, 0xB5D1, 0xB6C5, 0xB5D8, 0xB6C6, 0xB5EC, 0xB6C7, 0xB610, 0xB6C8, 0xB611, + 0xB6C9, 0xB614, 0xB6CA, 0xB618, 0xB6CB, 0xB625, 0xB6CC, 0xB62C, 0xB6CD, 0xB634, 0xB6CE, 0xB648, 0xB6CF, 0xB664, 0xB6D0, 0xB668, + 0xB6D1, 0xB69C, 0xB6D2, 0xB69D, 0xB6D3, 0xB6A0, 0xB6D4, 0xB6A4, 0xB6D5, 0xB6AB, 0xB6D6, 0xB6AC, 0xB6D7, 0xB6B1, 0xB6D8, 0xB6D4, + 0xB6D9, 0xB6F0, 0xB6DA, 0xB6F4, 0xB6DB, 0xB6F8, 0xB6DC, 0xB700, 0xB6DD, 0xB701, 0xB6DE, 0xB705, 0xB6DF, 0xB728, 0xB6E0, 0xB729, + 0xB6E1, 0xB72C, 0xB6E2, 0xB72F, 0xB6E3, 0xB730, 0xB6E4, 0xB738, 0xB6E5, 0xB739, 0xB6E6, 0xB73B, 0xB6E7, 0xB744, 0xB6E8, 0xB748, + 0xB6E9, 0xB74C, 0xB6EA, 0xB754, 0xB6EB, 0xB755, 0xB6EC, 0xB760, 0xB6ED, 0xB764, 0xB6EE, 0xB768, 0xB6EF, 0xB770, 0xB6F0, 0xB771, + 0xB6F1, 0xB773, 0xB6F2, 0xB775, 0xB6F3, 0xB77C, 0xB6F4, 0xB77D, 0xB6F5, 0xB780, 0xB6F6, 0xB784, 0xB6F7, 0xB78C, 0xB6F8, 0xB78D, + 0xB6F9, 0xB78F, 0xB6FA, 0xB790, 0xB6FB, 0xB791, 0xB6FC, 0xB792, 0xB6FD, 0xB796, 0xB6FE, 0xB797, 0xB741, 0xD16E, 0xB742, 0xD16F, + 0xB743, 0xD170, 0xB744, 0xD171, 0xB745, 0xD172, 0xB746, 0xD173, 0xB747, 0xD174, 0xB748, 0xD175, 0xB749, 0xD176, 0xB74A, 0xD177, + 0xB74B, 0xD178, 0xB74C, 0xD179, 0xB74D, 0xD17A, 0xB74E, 0xD17B, 0xB74F, 0xD17D, 0xB750, 0xD17E, 0xB751, 0xD17F, 0xB752, 0xD180, + 0xB753, 0xD181, 0xB754, 0xD182, 0xB755, 0xD183, 0xB756, 0xD185, 0xB757, 0xD186, 0xB758, 0xD187, 0xB759, 0xD189, 0xB75A, 0xD18A, + 0xB761, 0xD18B, 0xB762, 0xD18C, 0xB763, 0xD18D, 0xB764, 0xD18E, 0xB765, 0xD18F, 0xB766, 0xD190, 0xB767, 0xD191, 0xB768, 0xD192, + 0xB769, 0xD193, 0xB76A, 0xD194, 0xB76B, 0xD195, 0xB76C, 0xD196, 0xB76D, 0xD197, 0xB76E, 0xD198, 0xB76F, 0xD199, 0xB770, 0xD19A, + 0xB771, 0xD19B, 0xB772, 0xD19C, 0xB773, 0xD19D, 0xB774, 0xD19E, 0xB775, 0xD19F, 0xB776, 0xD1A2, 0xB777, 0xD1A3, 0xB778, 0xD1A5, + 0xB779, 0xD1A6, 0xB77A, 0xD1A7, 0xB781, 0xD1A9, 0xB782, 0xD1AA, 0xB783, 0xD1AB, 0xB784, 0xD1AC, 0xB785, 0xD1AD, 0xB786, 0xD1AE, + 0xB787, 0xD1AF, 0xB788, 0xD1B2, 0xB789, 0xD1B4, 0xB78A, 0xD1B6, 0xB78B, 0xD1B7, 0xB78C, 0xD1B8, 0xB78D, 0xD1B9, 0xB78E, 0xD1BB, + 0xB78F, 0xD1BD, 0xB790, 0xD1BE, 0xB791, 0xD1BF, 0xB792, 0xD1C1, 0xB793, 0xD1C2, 0xB794, 0xD1C3, 0xB795, 0xD1C4, 0xB796, 0xD1C5, + 0xB797, 0xD1C6, 0xB798, 0xD1C7, 0xB799, 0xD1C8, 0xB79A, 0xD1C9, 0xB79B, 0xD1CA, 0xB79C, 0xD1CB, 0xB79D, 0xD1CC, 0xB79E, 0xD1CD, + 0xB79F, 0xD1CE, 0xB7A0, 0xD1CF, 0xB7A1, 0xB798, 0xB7A2, 0xB799, 0xB7A3, 0xB79C, 0xB7A4, 0xB7A0, 0xB7A5, 0xB7A8, 0xB7A6, 0xB7A9, + 0xB7A7, 0xB7AB, 0xB7A8, 0xB7AC, 0xB7A9, 0xB7AD, 0xB7AA, 0xB7B4, 0xB7AB, 0xB7B5, 0xB7AC, 0xB7B8, 0xB7AD, 0xB7C7, 0xB7AE, 0xB7C9, + 0xB7AF, 0xB7EC, 0xB7B0, 0xB7ED, 0xB7B1, 0xB7F0, 0xB7B2, 0xB7F4, 0xB7B3, 0xB7FC, 0xB7B4, 0xB7FD, 0xB7B5, 0xB7FF, 0xB7B6, 0xB800, + 0xB7B7, 0xB801, 0xB7B8, 0xB807, 0xB7B9, 0xB808, 0xB7BA, 0xB809, 0xB7BB, 0xB80C, 0xB7BC, 0xB810, 0xB7BD, 0xB818, 0xB7BE, 0xB819, + 0xB7BF, 0xB81B, 0xB7C0, 0xB81D, 0xB7C1, 0xB824, 0xB7C2, 0xB825, 0xB7C3, 0xB828, 0xB7C4, 0xB82C, 0xB7C5, 0xB834, 0xB7C6, 0xB835, + 0xB7C7, 0xB837, 0xB7C8, 0xB838, 0xB7C9, 0xB839, 0xB7CA, 0xB840, 0xB7CB, 0xB844, 0xB7CC, 0xB851, 0xB7CD, 0xB853, 0xB7CE, 0xB85C, + 0xB7CF, 0xB85D, 0xB7D0, 0xB860, 0xB7D1, 0xB864, 0xB7D2, 0xB86C, 0xB7D3, 0xB86D, 0xB7D4, 0xB86F, 0xB7D5, 0xB871, 0xB7D6, 0xB878, + 0xB7D7, 0xB87C, 0xB7D8, 0xB88D, 0xB7D9, 0xB8A8, 0xB7DA, 0xB8B0, 0xB7DB, 0xB8B4, 0xB7DC, 0xB8B8, 0xB7DD, 0xB8C0, 0xB7DE, 0xB8C1, + 0xB7DF, 0xB8C3, 0xB7E0, 0xB8C5, 0xB7E1, 0xB8CC, 0xB7E2, 0xB8D0, 0xB7E3, 0xB8D4, 0xB7E4, 0xB8DD, 0xB7E5, 0xB8DF, 0xB7E6, 0xB8E1, + 0xB7E7, 0xB8E8, 0xB7E8, 0xB8E9, 0xB7E9, 0xB8EC, 0xB7EA, 0xB8F0, 0xB7EB, 0xB8F8, 0xB7EC, 0xB8F9, 0xB7ED, 0xB8FB, 0xB7EE, 0xB8FD, + 0xB7EF, 0xB904, 0xB7F0, 0xB918, 0xB7F1, 0xB920, 0xB7F2, 0xB93C, 0xB7F3, 0xB93D, 0xB7F4, 0xB940, 0xB7F5, 0xB944, 0xB7F6, 0xB94C, + 0xB7F7, 0xB94F, 0xB7F8, 0xB951, 0xB7F9, 0xB958, 0xB7FA, 0xB959, 0xB7FB, 0xB95C, 0xB7FC, 0xB960, 0xB7FD, 0xB968, 0xB7FE, 0xB969, + 0xB841, 0xD1D0, 0xB842, 0xD1D1, 0xB843, 0xD1D2, 0xB844, 0xD1D3, 0xB845, 0xD1D4, 0xB846, 0xD1D5, 0xB847, 0xD1D6, 0xB848, 0xD1D7, + 0xB849, 0xD1D9, 0xB84A, 0xD1DA, 0xB84B, 0xD1DB, 0xB84C, 0xD1DC, 0xB84D, 0xD1DD, 0xB84E, 0xD1DE, 0xB84F, 0xD1DF, 0xB850, 0xD1E0, + 0xB851, 0xD1E1, 0xB852, 0xD1E2, 0xB853, 0xD1E3, 0xB854, 0xD1E4, 0xB855, 0xD1E5, 0xB856, 0xD1E6, 0xB857, 0xD1E7, 0xB858, 0xD1E8, + 0xB859, 0xD1E9, 0xB85A, 0xD1EA, 0xB861, 0xD1EB, 0xB862, 0xD1EC, 0xB863, 0xD1ED, 0xB864, 0xD1EE, 0xB865, 0xD1EF, 0xB866, 0xD1F0, + 0xB867, 0xD1F1, 0xB868, 0xD1F2, 0xB869, 0xD1F3, 0xB86A, 0xD1F5, 0xB86B, 0xD1F6, 0xB86C, 0xD1F7, 0xB86D, 0xD1F9, 0xB86E, 0xD1FA, + 0xB86F, 0xD1FB, 0xB870, 0xD1FC, 0xB871, 0xD1FD, 0xB872, 0xD1FE, 0xB873, 0xD1FF, 0xB874, 0xD200, 0xB875, 0xD201, 0xB876, 0xD202, + 0xB877, 0xD203, 0xB878, 0xD204, 0xB879, 0xD205, 0xB87A, 0xD206, 0xB881, 0xD208, 0xB882, 0xD20A, 0xB883, 0xD20B, 0xB884, 0xD20C, + 0xB885, 0xD20D, 0xB886, 0xD20E, 0xB887, 0xD20F, 0xB888, 0xD211, 0xB889, 0xD212, 0xB88A, 0xD213, 0xB88B, 0xD214, 0xB88C, 0xD215, + 0xB88D, 0xD216, 0xB88E, 0xD217, 0xB88F, 0xD218, 0xB890, 0xD219, 0xB891, 0xD21A, 0xB892, 0xD21B, 0xB893, 0xD21C, 0xB894, 0xD21D, + 0xB895, 0xD21E, 0xB896, 0xD21F, 0xB897, 0xD220, 0xB898, 0xD221, 0xB899, 0xD222, 0xB89A, 0xD223, 0xB89B, 0xD224, 0xB89C, 0xD225, + 0xB89D, 0xD226, 0xB89E, 0xD227, 0xB89F, 0xD228, 0xB8A0, 0xD229, 0xB8A1, 0xB96B, 0xB8A2, 0xB96D, 0xB8A3, 0xB974, 0xB8A4, 0xB975, + 0xB8A5, 0xB978, 0xB8A6, 0xB97C, 0xB8A7, 0xB984, 0xB8A8, 0xB985, 0xB8A9, 0xB987, 0xB8AA, 0xB989, 0xB8AB, 0xB98A, 0xB8AC, 0xB98D, + 0xB8AD, 0xB98E, 0xB8AE, 0xB9AC, 0xB8AF, 0xB9AD, 0xB8B0, 0xB9B0, 0xB8B1, 0xB9B4, 0xB8B2, 0xB9BC, 0xB8B3, 0xB9BD, 0xB8B4, 0xB9BF, + 0xB8B5, 0xB9C1, 0xB8B6, 0xB9C8, 0xB8B7, 0xB9C9, 0xB8B8, 0xB9CC, 0xB8B9, 0xB9CE, 0xB8BA, 0xB9CF, 0xB8BB, 0xB9D0, 0xB8BC, 0xB9D1, + 0xB8BD, 0xB9D2, 0xB8BE, 0xB9D8, 0xB8BF, 0xB9D9, 0xB8C0, 0xB9DB, 0xB8C1, 0xB9DD, 0xB8C2, 0xB9DE, 0xB8C3, 0xB9E1, 0xB8C4, 0xB9E3, + 0xB8C5, 0xB9E4, 0xB8C6, 0xB9E5, 0xB8C7, 0xB9E8, 0xB8C8, 0xB9EC, 0xB8C9, 0xB9F4, 0xB8CA, 0xB9F5, 0xB8CB, 0xB9F7, 0xB8CC, 0xB9F8, + 0xB8CD, 0xB9F9, 0xB8CE, 0xB9FA, 0xB8CF, 0xBA00, 0xB8D0, 0xBA01, 0xB8D1, 0xBA08, 0xB8D2, 0xBA15, 0xB8D3, 0xBA38, 0xB8D4, 0xBA39, + 0xB8D5, 0xBA3C, 0xB8D6, 0xBA40, 0xB8D7, 0xBA42, 0xB8D8, 0xBA48, 0xB8D9, 0xBA49, 0xB8DA, 0xBA4B, 0xB8DB, 0xBA4D, 0xB8DC, 0xBA4E, + 0xB8DD, 0xBA53, 0xB8DE, 0xBA54, 0xB8DF, 0xBA55, 0xB8E0, 0xBA58, 0xB8E1, 0xBA5C, 0xB8E2, 0xBA64, 0xB8E3, 0xBA65, 0xB8E4, 0xBA67, + 0xB8E5, 0xBA68, 0xB8E6, 0xBA69, 0xB8E7, 0xBA70, 0xB8E8, 0xBA71, 0xB8E9, 0xBA74, 0xB8EA, 0xBA78, 0xB8EB, 0xBA83, 0xB8EC, 0xBA84, + 0xB8ED, 0xBA85, 0xB8EE, 0xBA87, 0xB8EF, 0xBA8C, 0xB8F0, 0xBAA8, 0xB8F1, 0xBAA9, 0xB8F2, 0xBAAB, 0xB8F3, 0xBAAC, 0xB8F4, 0xBAB0, + 0xB8F5, 0xBAB2, 0xB8F6, 0xBAB8, 0xB8F7, 0xBAB9, 0xB8F8, 0xBABB, 0xB8F9, 0xBABD, 0xB8FA, 0xBAC4, 0xB8FB, 0xBAC8, 0xB8FC, 0xBAD8, + 0xB8FD, 0xBAD9, 0xB8FE, 0xBAFC, 0xB941, 0xD22A, 0xB942, 0xD22B, 0xB943, 0xD22E, 0xB944, 0xD22F, 0xB945, 0xD231, 0xB946, 0xD232, + 0xB947, 0xD233, 0xB948, 0xD235, 0xB949, 0xD236, 0xB94A, 0xD237, 0xB94B, 0xD238, 0xB94C, 0xD239, 0xB94D, 0xD23A, 0xB94E, 0xD23B, + 0xB94F, 0xD23E, 0xB950, 0xD240, 0xB951, 0xD242, 0xB952, 0xD243, 0xB953, 0xD244, 0xB954, 0xD245, 0xB955, 0xD246, 0xB956, 0xD247, + 0xB957, 0xD249, 0xB958, 0xD24A, 0xB959, 0xD24B, 0xB95A, 0xD24C, 0xB961, 0xD24D, 0xB962, 0xD24E, 0xB963, 0xD24F, 0xB964, 0xD250, + 0xB965, 0xD251, 0xB966, 0xD252, 0xB967, 0xD253, 0xB968, 0xD254, 0xB969, 0xD255, 0xB96A, 0xD256, 0xB96B, 0xD257, 0xB96C, 0xD258, + 0xB96D, 0xD259, 0xB96E, 0xD25A, 0xB96F, 0xD25B, 0xB970, 0xD25D, 0xB971, 0xD25E, 0xB972, 0xD25F, 0xB973, 0xD260, 0xB974, 0xD261, + 0xB975, 0xD262, 0xB976, 0xD263, 0xB977, 0xD265, 0xB978, 0xD266, 0xB979, 0xD267, 0xB97A, 0xD268, 0xB981, 0xD269, 0xB982, 0xD26A, + 0xB983, 0xD26B, 0xB984, 0xD26C, 0xB985, 0xD26D, 0xB986, 0xD26E, 0xB987, 0xD26F, 0xB988, 0xD270, 0xB989, 0xD271, 0xB98A, 0xD272, + 0xB98B, 0xD273, 0xB98C, 0xD274, 0xB98D, 0xD275, 0xB98E, 0xD276, 0xB98F, 0xD277, 0xB990, 0xD278, 0xB991, 0xD279, 0xB992, 0xD27A, + 0xB993, 0xD27B, 0xB994, 0xD27C, 0xB995, 0xD27D, 0xB996, 0xD27E, 0xB997, 0xD27F, 0xB998, 0xD282, 0xB999, 0xD283, 0xB99A, 0xD285, + 0xB99B, 0xD286, 0xB99C, 0xD287, 0xB99D, 0xD289, 0xB99E, 0xD28A, 0xB99F, 0xD28B, 0xB9A0, 0xD28C, 0xB9A1, 0xBB00, 0xB9A2, 0xBB04, + 0xB9A3, 0xBB0D, 0xB9A4, 0xBB0F, 0xB9A5, 0xBB11, 0xB9A6, 0xBB18, 0xB9A7, 0xBB1C, 0xB9A8, 0xBB20, 0xB9A9, 0xBB29, 0xB9AA, 0xBB2B, + 0xB9AB, 0xBB34, 0xB9AC, 0xBB35, 0xB9AD, 0xBB36, 0xB9AE, 0xBB38, 0xB9AF, 0xBB3B, 0xB9B0, 0xBB3C, 0xB9B1, 0xBB3D, 0xB9B2, 0xBB3E, + 0xB9B3, 0xBB44, 0xB9B4, 0xBB45, 0xB9B5, 0xBB47, 0xB9B6, 0xBB49, 0xB9B7, 0xBB4D, 0xB9B8, 0xBB4F, 0xB9B9, 0xBB50, 0xB9BA, 0xBB54, + 0xB9BB, 0xBB58, 0xB9BC, 0xBB61, 0xB9BD, 0xBB63, 0xB9BE, 0xBB6C, 0xB9BF, 0xBB88, 0xB9C0, 0xBB8C, 0xB9C1, 0xBB90, 0xB9C2, 0xBBA4, + 0xB9C3, 0xBBA8, 0xB9C4, 0xBBAC, 0xB9C5, 0xBBB4, 0xB9C6, 0xBBB7, 0xB9C7, 0xBBC0, 0xB9C8, 0xBBC4, 0xB9C9, 0xBBC8, 0xB9CA, 0xBBD0, + 0xB9CB, 0xBBD3, 0xB9CC, 0xBBF8, 0xB9CD, 0xBBF9, 0xB9CE, 0xBBFC, 0xB9CF, 0xBBFF, 0xB9D0, 0xBC00, 0xB9D1, 0xBC02, 0xB9D2, 0xBC08, + 0xB9D3, 0xBC09, 0xB9D4, 0xBC0B, 0xB9D5, 0xBC0C, 0xB9D6, 0xBC0D, 0xB9D7, 0xBC0F, 0xB9D8, 0xBC11, 0xB9D9, 0xBC14, 0xB9DA, 0xBC15, + 0xB9DB, 0xBC16, 0xB9DC, 0xBC17, 0xB9DD, 0xBC18, 0xB9DE, 0xBC1B, 0xB9DF, 0xBC1C, 0xB9E0, 0xBC1D, 0xB9E1, 0xBC1E, 0xB9E2, 0xBC1F, + 0xB9E3, 0xBC24, 0xB9E4, 0xBC25, 0xB9E5, 0xBC27, 0xB9E6, 0xBC29, 0xB9E7, 0xBC2D, 0xB9E8, 0xBC30, 0xB9E9, 0xBC31, 0xB9EA, 0xBC34, + 0xB9EB, 0xBC38, 0xB9EC, 0xBC40, 0xB9ED, 0xBC41, 0xB9EE, 0xBC43, 0xB9EF, 0xBC44, 0xB9F0, 0xBC45, 0xB9F1, 0xBC49, 0xB9F2, 0xBC4C, + 0xB9F3, 0xBC4D, 0xB9F4, 0xBC50, 0xB9F5, 0xBC5D, 0xB9F6, 0xBC84, 0xB9F7, 0xBC85, 0xB9F8, 0xBC88, 0xB9F9, 0xBC8B, 0xB9FA, 0xBC8C, + 0xB9FB, 0xBC8E, 0xB9FC, 0xBC94, 0xB9FD, 0xBC95, 0xB9FE, 0xBC97, 0xBA41, 0xD28D, 0xBA42, 0xD28E, 0xBA43, 0xD28F, 0xBA44, 0xD292, + 0xBA45, 0xD293, 0xBA46, 0xD294, 0xBA47, 0xD296, 0xBA48, 0xD297, 0xBA49, 0xD298, 0xBA4A, 0xD299, 0xBA4B, 0xD29A, 0xBA4C, 0xD29B, + 0xBA4D, 0xD29D, 0xBA4E, 0xD29E, 0xBA4F, 0xD29F, 0xBA50, 0xD2A1, 0xBA51, 0xD2A2, 0xBA52, 0xD2A3, 0xBA53, 0xD2A5, 0xBA54, 0xD2A6, + 0xBA55, 0xD2A7, 0xBA56, 0xD2A8, 0xBA57, 0xD2A9, 0xBA58, 0xD2AA, 0xBA59, 0xD2AB, 0xBA5A, 0xD2AD, 0xBA61, 0xD2AE, 0xBA62, 0xD2AF, + 0xBA63, 0xD2B0, 0xBA64, 0xD2B2, 0xBA65, 0xD2B3, 0xBA66, 0xD2B4, 0xBA67, 0xD2B5, 0xBA68, 0xD2B6, 0xBA69, 0xD2B7, 0xBA6A, 0xD2BA, + 0xBA6B, 0xD2BB, 0xBA6C, 0xD2BD, 0xBA6D, 0xD2BE, 0xBA6E, 0xD2C1, 0xBA6F, 0xD2C3, 0xBA70, 0xD2C4, 0xBA71, 0xD2C5, 0xBA72, 0xD2C6, + 0xBA73, 0xD2C7, 0xBA74, 0xD2CA, 0xBA75, 0xD2CC, 0xBA76, 0xD2CD, 0xBA77, 0xD2CE, 0xBA78, 0xD2CF, 0xBA79, 0xD2D0, 0xBA7A, 0xD2D1, + 0xBA81, 0xD2D2, 0xBA82, 0xD2D3, 0xBA83, 0xD2D5, 0xBA84, 0xD2D6, 0xBA85, 0xD2D7, 0xBA86, 0xD2D9, 0xBA87, 0xD2DA, 0xBA88, 0xD2DB, + 0xBA89, 0xD2DD, 0xBA8A, 0xD2DE, 0xBA8B, 0xD2DF, 0xBA8C, 0xD2E0, 0xBA8D, 0xD2E1, 0xBA8E, 0xD2E2, 0xBA8F, 0xD2E3, 0xBA90, 0xD2E6, + 0xBA91, 0xD2E7, 0xBA92, 0xD2E8, 0xBA93, 0xD2E9, 0xBA94, 0xD2EA, 0xBA95, 0xD2EB, 0xBA96, 0xD2EC, 0xBA97, 0xD2ED, 0xBA98, 0xD2EE, + 0xBA99, 0xD2EF, 0xBA9A, 0xD2F2, 0xBA9B, 0xD2F3, 0xBA9C, 0xD2F5, 0xBA9D, 0xD2F6, 0xBA9E, 0xD2F7, 0xBA9F, 0xD2F9, 0xBAA0, 0xD2FA, + 0xBAA1, 0xBC99, 0xBAA2, 0xBC9A, 0xBAA3, 0xBCA0, 0xBAA4, 0xBCA1, 0xBAA5, 0xBCA4, 0xBAA6, 0xBCA7, 0xBAA7, 0xBCA8, 0xBAA8, 0xBCB0, + 0xBAA9, 0xBCB1, 0xBAAA, 0xBCB3, 0xBAAB, 0xBCB4, 0xBAAC, 0xBCB5, 0xBAAD, 0xBCBC, 0xBAAE, 0xBCBD, 0xBAAF, 0xBCC0, 0xBAB0, 0xBCC4, + 0xBAB1, 0xBCCD, 0xBAB2, 0xBCCF, 0xBAB3, 0xBCD0, 0xBAB4, 0xBCD1, 0xBAB5, 0xBCD5, 0xBAB6, 0xBCD8, 0xBAB7, 0xBCDC, 0xBAB8, 0xBCF4, + 0xBAB9, 0xBCF5, 0xBABA, 0xBCF6, 0xBABB, 0xBCF8, 0xBABC, 0xBCFC, 0xBABD, 0xBD04, 0xBABE, 0xBD05, 0xBABF, 0xBD07, 0xBAC0, 0xBD09, + 0xBAC1, 0xBD10, 0xBAC2, 0xBD14, 0xBAC3, 0xBD24, 0xBAC4, 0xBD2C, 0xBAC5, 0xBD40, 0xBAC6, 0xBD48, 0xBAC7, 0xBD49, 0xBAC8, 0xBD4C, + 0xBAC9, 0xBD50, 0xBACA, 0xBD58, 0xBACB, 0xBD59, 0xBACC, 0xBD64, 0xBACD, 0xBD68, 0xBACE, 0xBD80, 0xBACF, 0xBD81, 0xBAD0, 0xBD84, + 0xBAD1, 0xBD87, 0xBAD2, 0xBD88, 0xBAD3, 0xBD89, 0xBAD4, 0xBD8A, 0xBAD5, 0xBD90, 0xBAD6, 0xBD91, 0xBAD7, 0xBD93, 0xBAD8, 0xBD95, + 0xBAD9, 0xBD99, 0xBADA, 0xBD9A, 0xBADB, 0xBD9C, 0xBADC, 0xBDA4, 0xBADD, 0xBDB0, 0xBADE, 0xBDB8, 0xBADF, 0xBDD4, 0xBAE0, 0xBDD5, + 0xBAE1, 0xBDD8, 0xBAE2, 0xBDDC, 0xBAE3, 0xBDE9, 0xBAE4, 0xBDF0, 0xBAE5, 0xBDF4, 0xBAE6, 0xBDF8, 0xBAE7, 0xBE00, 0xBAE8, 0xBE03, + 0xBAE9, 0xBE05, 0xBAEA, 0xBE0C, 0xBAEB, 0xBE0D, 0xBAEC, 0xBE10, 0xBAED, 0xBE14, 0xBAEE, 0xBE1C, 0xBAEF, 0xBE1D, 0xBAF0, 0xBE1F, + 0xBAF1, 0xBE44, 0xBAF2, 0xBE45, 0xBAF3, 0xBE48, 0xBAF4, 0xBE4C, 0xBAF5, 0xBE4E, 0xBAF6, 0xBE54, 0xBAF7, 0xBE55, 0xBAF8, 0xBE57, + 0xBAF9, 0xBE59, 0xBAFA, 0xBE5A, 0xBAFB, 0xBE5B, 0xBAFC, 0xBE60, 0xBAFD, 0xBE61, 0xBAFE, 0xBE64, 0xBB41, 0xD2FB, 0xBB42, 0xD2FC, + 0xBB43, 0xD2FD, 0xBB44, 0xD2FE, 0xBB45, 0xD2FF, 0xBB46, 0xD302, 0xBB47, 0xD304, 0xBB48, 0xD306, 0xBB49, 0xD307, 0xBB4A, 0xD308, + 0xBB4B, 0xD309, 0xBB4C, 0xD30A, 0xBB4D, 0xD30B, 0xBB4E, 0xD30F, 0xBB4F, 0xD311, 0xBB50, 0xD312, 0xBB51, 0xD313, 0xBB52, 0xD315, + 0xBB53, 0xD317, 0xBB54, 0xD318, 0xBB55, 0xD319, 0xBB56, 0xD31A, 0xBB57, 0xD31B, 0xBB58, 0xD31E, 0xBB59, 0xD322, 0xBB5A, 0xD323, + 0xBB61, 0xD324, 0xBB62, 0xD326, 0xBB63, 0xD327, 0xBB64, 0xD32A, 0xBB65, 0xD32B, 0xBB66, 0xD32D, 0xBB67, 0xD32E, 0xBB68, 0xD32F, + 0xBB69, 0xD331, 0xBB6A, 0xD332, 0xBB6B, 0xD333, 0xBB6C, 0xD334, 0xBB6D, 0xD335, 0xBB6E, 0xD336, 0xBB6F, 0xD337, 0xBB70, 0xD33A, + 0xBB71, 0xD33E, 0xBB72, 0xD33F, 0xBB73, 0xD340, 0xBB74, 0xD341, 0xBB75, 0xD342, 0xBB76, 0xD343, 0xBB77, 0xD346, 0xBB78, 0xD347, + 0xBB79, 0xD348, 0xBB7A, 0xD349, 0xBB81, 0xD34A, 0xBB82, 0xD34B, 0xBB83, 0xD34C, 0xBB84, 0xD34D, 0xBB85, 0xD34E, 0xBB86, 0xD34F, + 0xBB87, 0xD350, 0xBB88, 0xD351, 0xBB89, 0xD352, 0xBB8A, 0xD353, 0xBB8B, 0xD354, 0xBB8C, 0xD355, 0xBB8D, 0xD356, 0xBB8E, 0xD357, + 0xBB8F, 0xD358, 0xBB90, 0xD359, 0xBB91, 0xD35A, 0xBB92, 0xD35B, 0xBB93, 0xD35C, 0xBB94, 0xD35D, 0xBB95, 0xD35E, 0xBB96, 0xD35F, + 0xBB97, 0xD360, 0xBB98, 0xD361, 0xBB99, 0xD362, 0xBB9A, 0xD363, 0xBB9B, 0xD364, 0xBB9C, 0xD365, 0xBB9D, 0xD366, 0xBB9E, 0xD367, + 0xBB9F, 0xD368, 0xBBA0, 0xD369, 0xBBA1, 0xBE68, 0xBBA2, 0xBE6A, 0xBBA3, 0xBE70, 0xBBA4, 0xBE71, 0xBBA5, 0xBE73, 0xBBA6, 0xBE74, + 0xBBA7, 0xBE75, 0xBBA8, 0xBE7B, 0xBBA9, 0xBE7C, 0xBBAA, 0xBE7D, 0xBBAB, 0xBE80, 0xBBAC, 0xBE84, 0xBBAD, 0xBE8C, 0xBBAE, 0xBE8D, + 0xBBAF, 0xBE8F, 0xBBB0, 0xBE90, 0xBBB1, 0xBE91, 0xBBB2, 0xBE98, 0xBBB3, 0xBE99, 0xBBB4, 0xBEA8, 0xBBB5, 0xBED0, 0xBBB6, 0xBED1, + 0xBBB7, 0xBED4, 0xBBB8, 0xBED7, 0xBBB9, 0xBED8, 0xBBBA, 0xBEE0, 0xBBBB, 0xBEE3, 0xBBBC, 0xBEE4, 0xBBBD, 0xBEE5, 0xBBBE, 0xBEEC, + 0xBBBF, 0xBF01, 0xBBC0, 0xBF08, 0xBBC1, 0xBF09, 0xBBC2, 0xBF18, 0xBBC3, 0xBF19, 0xBBC4, 0xBF1B, 0xBBC5, 0xBF1C, 0xBBC6, 0xBF1D, + 0xBBC7, 0xBF40, 0xBBC8, 0xBF41, 0xBBC9, 0xBF44, 0xBBCA, 0xBF48, 0xBBCB, 0xBF50, 0xBBCC, 0xBF51, 0xBBCD, 0xBF55, 0xBBCE, 0xBF94, + 0xBBCF, 0xBFB0, 0xBBD0, 0xBFC5, 0xBBD1, 0xBFCC, 0xBBD2, 0xBFCD, 0xBBD3, 0xBFD0, 0xBBD4, 0xBFD4, 0xBBD5, 0xBFDC, 0xBBD6, 0xBFDF, + 0xBBD7, 0xBFE1, 0xBBD8, 0xC03C, 0xBBD9, 0xC051, 0xBBDA, 0xC058, 0xBBDB, 0xC05C, 0xBBDC, 0xC060, 0xBBDD, 0xC068, 0xBBDE, 0xC069, + 0xBBDF, 0xC090, 0xBBE0, 0xC091, 0xBBE1, 0xC094, 0xBBE2, 0xC098, 0xBBE3, 0xC0A0, 0xBBE4, 0xC0A1, 0xBBE5, 0xC0A3, 0xBBE6, 0xC0A5, + 0xBBE7, 0xC0AC, 0xBBE8, 0xC0AD, 0xBBE9, 0xC0AF, 0xBBEA, 0xC0B0, 0xBBEB, 0xC0B3, 0xBBEC, 0xC0B4, 0xBBED, 0xC0B5, 0xBBEE, 0xC0B6, + 0xBBEF, 0xC0BC, 0xBBF0, 0xC0BD, 0xBBF1, 0xC0BF, 0xBBF2, 0xC0C0, 0xBBF3, 0xC0C1, 0xBBF4, 0xC0C5, 0xBBF5, 0xC0C8, 0xBBF6, 0xC0C9, + 0xBBF7, 0xC0CC, 0xBBF8, 0xC0D0, 0xBBF9, 0xC0D8, 0xBBFA, 0xC0D9, 0xBBFB, 0xC0DB, 0xBBFC, 0xC0DC, 0xBBFD, 0xC0DD, 0xBBFE, 0xC0E4, + 0xBC41, 0xD36A, 0xBC42, 0xD36B, 0xBC43, 0xD36C, 0xBC44, 0xD36D, 0xBC45, 0xD36E, 0xBC46, 0xD36F, 0xBC47, 0xD370, 0xBC48, 0xD371, + 0xBC49, 0xD372, 0xBC4A, 0xD373, 0xBC4B, 0xD374, 0xBC4C, 0xD375, 0xBC4D, 0xD376, 0xBC4E, 0xD377, 0xBC4F, 0xD378, 0xBC50, 0xD379, + 0xBC51, 0xD37A, 0xBC52, 0xD37B, 0xBC53, 0xD37E, 0xBC54, 0xD37F, 0xBC55, 0xD381, 0xBC56, 0xD382, 0xBC57, 0xD383, 0xBC58, 0xD385, + 0xBC59, 0xD386, 0xBC5A, 0xD387, 0xBC61, 0xD388, 0xBC62, 0xD389, 0xBC63, 0xD38A, 0xBC64, 0xD38B, 0xBC65, 0xD38E, 0xBC66, 0xD392, + 0xBC67, 0xD393, 0xBC68, 0xD394, 0xBC69, 0xD395, 0xBC6A, 0xD396, 0xBC6B, 0xD397, 0xBC6C, 0xD39A, 0xBC6D, 0xD39B, 0xBC6E, 0xD39D, + 0xBC6F, 0xD39E, 0xBC70, 0xD39F, 0xBC71, 0xD3A1, 0xBC72, 0xD3A2, 0xBC73, 0xD3A3, 0xBC74, 0xD3A4, 0xBC75, 0xD3A5, 0xBC76, 0xD3A6, + 0xBC77, 0xD3A7, 0xBC78, 0xD3AA, 0xBC79, 0xD3AC, 0xBC7A, 0xD3AE, 0xBC81, 0xD3AF, 0xBC82, 0xD3B0, 0xBC83, 0xD3B1, 0xBC84, 0xD3B2, + 0xBC85, 0xD3B3, 0xBC86, 0xD3B5, 0xBC87, 0xD3B6, 0xBC88, 0xD3B7, 0xBC89, 0xD3B9, 0xBC8A, 0xD3BA, 0xBC8B, 0xD3BB, 0xBC8C, 0xD3BD, + 0xBC8D, 0xD3BE, 0xBC8E, 0xD3BF, 0xBC8F, 0xD3C0, 0xBC90, 0xD3C1, 0xBC91, 0xD3C2, 0xBC92, 0xD3C3, 0xBC93, 0xD3C6, 0xBC94, 0xD3C7, + 0xBC95, 0xD3CA, 0xBC96, 0xD3CB, 0xBC97, 0xD3CC, 0xBC98, 0xD3CD, 0xBC99, 0xD3CE, 0xBC9A, 0xD3CF, 0xBC9B, 0xD3D1, 0xBC9C, 0xD3D2, + 0xBC9D, 0xD3D3, 0xBC9E, 0xD3D4, 0xBC9F, 0xD3D5, 0xBCA0, 0xD3D6, 0xBCA1, 0xC0E5, 0xBCA2, 0xC0E8, 0xBCA3, 0xC0EC, 0xBCA4, 0xC0F4, + 0xBCA5, 0xC0F5, 0xBCA6, 0xC0F7, 0xBCA7, 0xC0F9, 0xBCA8, 0xC100, 0xBCA9, 0xC104, 0xBCAA, 0xC108, 0xBCAB, 0xC110, 0xBCAC, 0xC115, + 0xBCAD, 0xC11C, 0xBCAE, 0xC11D, 0xBCAF, 0xC11E, 0xBCB0, 0xC11F, 0xBCB1, 0xC120, 0xBCB2, 0xC123, 0xBCB3, 0xC124, 0xBCB4, 0xC126, + 0xBCB5, 0xC127, 0xBCB6, 0xC12C, 0xBCB7, 0xC12D, 0xBCB8, 0xC12F, 0xBCB9, 0xC130, 0xBCBA, 0xC131, 0xBCBB, 0xC136, 0xBCBC, 0xC138, + 0xBCBD, 0xC139, 0xBCBE, 0xC13C, 0xBCBF, 0xC140, 0xBCC0, 0xC148, 0xBCC1, 0xC149, 0xBCC2, 0xC14B, 0xBCC3, 0xC14C, 0xBCC4, 0xC14D, + 0xBCC5, 0xC154, 0xBCC6, 0xC155, 0xBCC7, 0xC158, 0xBCC8, 0xC15C, 0xBCC9, 0xC164, 0xBCCA, 0xC165, 0xBCCB, 0xC167, 0xBCCC, 0xC168, + 0xBCCD, 0xC169, 0xBCCE, 0xC170, 0xBCCF, 0xC174, 0xBCD0, 0xC178, 0xBCD1, 0xC185, 0xBCD2, 0xC18C, 0xBCD3, 0xC18D, 0xBCD4, 0xC18E, + 0xBCD5, 0xC190, 0xBCD6, 0xC194, 0xBCD7, 0xC196, 0xBCD8, 0xC19C, 0xBCD9, 0xC19D, 0xBCDA, 0xC19F, 0xBCDB, 0xC1A1, 0xBCDC, 0xC1A5, + 0xBCDD, 0xC1A8, 0xBCDE, 0xC1A9, 0xBCDF, 0xC1AC, 0xBCE0, 0xC1B0, 0xBCE1, 0xC1BD, 0xBCE2, 0xC1C4, 0xBCE3, 0xC1C8, 0xBCE4, 0xC1CC, + 0xBCE5, 0xC1D4, 0xBCE6, 0xC1D7, 0xBCE7, 0xC1D8, 0xBCE8, 0xC1E0, 0xBCE9, 0xC1E4, 0xBCEA, 0xC1E8, 0xBCEB, 0xC1F0, 0xBCEC, 0xC1F1, + 0xBCED, 0xC1F3, 0xBCEE, 0xC1FC, 0xBCEF, 0xC1FD, 0xBCF0, 0xC200, 0xBCF1, 0xC204, 0xBCF2, 0xC20C, 0xBCF3, 0xC20D, 0xBCF4, 0xC20F, + 0xBCF5, 0xC211, 0xBCF6, 0xC218, 0xBCF7, 0xC219, 0xBCF8, 0xC21C, 0xBCF9, 0xC21F, 0xBCFA, 0xC220, 0xBCFB, 0xC228, 0xBCFC, 0xC229, + 0xBCFD, 0xC22B, 0xBCFE, 0xC22D, 0xBD41, 0xD3D7, 0xBD42, 0xD3D9, 0xBD43, 0xD3DA, 0xBD44, 0xD3DB, 0xBD45, 0xD3DC, 0xBD46, 0xD3DD, + 0xBD47, 0xD3DE, 0xBD48, 0xD3DF, 0xBD49, 0xD3E0, 0xBD4A, 0xD3E2, 0xBD4B, 0xD3E4, 0xBD4C, 0xD3E5, 0xBD4D, 0xD3E6, 0xBD4E, 0xD3E7, + 0xBD4F, 0xD3E8, 0xBD50, 0xD3E9, 0xBD51, 0xD3EA, 0xBD52, 0xD3EB, 0xBD53, 0xD3EE, 0xBD54, 0xD3EF, 0xBD55, 0xD3F1, 0xBD56, 0xD3F2, + 0xBD57, 0xD3F3, 0xBD58, 0xD3F5, 0xBD59, 0xD3F6, 0xBD5A, 0xD3F7, 0xBD61, 0xD3F8, 0xBD62, 0xD3F9, 0xBD63, 0xD3FA, 0xBD64, 0xD3FB, + 0xBD65, 0xD3FE, 0xBD66, 0xD400, 0xBD67, 0xD402, 0xBD68, 0xD403, 0xBD69, 0xD404, 0xBD6A, 0xD405, 0xBD6B, 0xD406, 0xBD6C, 0xD407, + 0xBD6D, 0xD409, 0xBD6E, 0xD40A, 0xBD6F, 0xD40B, 0xBD70, 0xD40C, 0xBD71, 0xD40D, 0xBD72, 0xD40E, 0xBD73, 0xD40F, 0xBD74, 0xD410, + 0xBD75, 0xD411, 0xBD76, 0xD412, 0xBD77, 0xD413, 0xBD78, 0xD414, 0xBD79, 0xD415, 0xBD7A, 0xD416, 0xBD81, 0xD417, 0xBD82, 0xD418, + 0xBD83, 0xD419, 0xBD84, 0xD41A, 0xBD85, 0xD41B, 0xBD86, 0xD41C, 0xBD87, 0xD41E, 0xBD88, 0xD41F, 0xBD89, 0xD420, 0xBD8A, 0xD421, + 0xBD8B, 0xD422, 0xBD8C, 0xD423, 0xBD8D, 0xD424, 0xBD8E, 0xD425, 0xBD8F, 0xD426, 0xBD90, 0xD427, 0xBD91, 0xD428, 0xBD92, 0xD429, + 0xBD93, 0xD42A, 0xBD94, 0xD42B, 0xBD95, 0xD42C, 0xBD96, 0xD42D, 0xBD97, 0xD42E, 0xBD98, 0xD42F, 0xBD99, 0xD430, 0xBD9A, 0xD431, + 0xBD9B, 0xD432, 0xBD9C, 0xD433, 0xBD9D, 0xD434, 0xBD9E, 0xD435, 0xBD9F, 0xD436, 0xBDA0, 0xD437, 0xBDA1, 0xC22F, 0xBDA2, 0xC231, + 0xBDA3, 0xC232, 0xBDA4, 0xC234, 0xBDA5, 0xC248, 0xBDA6, 0xC250, 0xBDA7, 0xC251, 0xBDA8, 0xC254, 0xBDA9, 0xC258, 0xBDAA, 0xC260, + 0xBDAB, 0xC265, 0xBDAC, 0xC26C, 0xBDAD, 0xC26D, 0xBDAE, 0xC270, 0xBDAF, 0xC274, 0xBDB0, 0xC27C, 0xBDB1, 0xC27D, 0xBDB2, 0xC27F, + 0xBDB3, 0xC281, 0xBDB4, 0xC288, 0xBDB5, 0xC289, 0xBDB6, 0xC290, 0xBDB7, 0xC298, 0xBDB8, 0xC29B, 0xBDB9, 0xC29D, 0xBDBA, 0xC2A4, + 0xBDBB, 0xC2A5, 0xBDBC, 0xC2A8, 0xBDBD, 0xC2AC, 0xBDBE, 0xC2AD, 0xBDBF, 0xC2B4, 0xBDC0, 0xC2B5, 0xBDC1, 0xC2B7, 0xBDC2, 0xC2B9, + 0xBDC3, 0xC2DC, 0xBDC4, 0xC2DD, 0xBDC5, 0xC2E0, 0xBDC6, 0xC2E3, 0xBDC7, 0xC2E4, 0xBDC8, 0xC2EB, 0xBDC9, 0xC2EC, 0xBDCA, 0xC2ED, + 0xBDCB, 0xC2EF, 0xBDCC, 0xC2F1, 0xBDCD, 0xC2F6, 0xBDCE, 0xC2F8, 0xBDCF, 0xC2F9, 0xBDD0, 0xC2FB, 0xBDD1, 0xC2FC, 0xBDD2, 0xC300, + 0xBDD3, 0xC308, 0xBDD4, 0xC309, 0xBDD5, 0xC30C, 0xBDD6, 0xC30D, 0xBDD7, 0xC313, 0xBDD8, 0xC314, 0xBDD9, 0xC315, 0xBDDA, 0xC318, + 0xBDDB, 0xC31C, 0xBDDC, 0xC324, 0xBDDD, 0xC325, 0xBDDE, 0xC328, 0xBDDF, 0xC329, 0xBDE0, 0xC345, 0xBDE1, 0xC368, 0xBDE2, 0xC369, + 0xBDE3, 0xC36C, 0xBDE4, 0xC370, 0xBDE5, 0xC372, 0xBDE6, 0xC378, 0xBDE7, 0xC379, 0xBDE8, 0xC37C, 0xBDE9, 0xC37D, 0xBDEA, 0xC384, + 0xBDEB, 0xC388, 0xBDEC, 0xC38C, 0xBDED, 0xC3C0, 0xBDEE, 0xC3D8, 0xBDEF, 0xC3D9, 0xBDF0, 0xC3DC, 0xBDF1, 0xC3DF, 0xBDF2, 0xC3E0, + 0xBDF3, 0xC3E2, 0xBDF4, 0xC3E8, 0xBDF5, 0xC3E9, 0xBDF6, 0xC3ED, 0xBDF7, 0xC3F4, 0xBDF8, 0xC3F5, 0xBDF9, 0xC3F8, 0xBDFA, 0xC408, + 0xBDFB, 0xC410, 0xBDFC, 0xC424, 0xBDFD, 0xC42C, 0xBDFE, 0xC430, 0xBE41, 0xD438, 0xBE42, 0xD439, 0xBE43, 0xD43A, 0xBE44, 0xD43B, + 0xBE45, 0xD43C, 0xBE46, 0xD43D, 0xBE47, 0xD43E, 0xBE48, 0xD43F, 0xBE49, 0xD441, 0xBE4A, 0xD442, 0xBE4B, 0xD443, 0xBE4C, 0xD445, + 0xBE4D, 0xD446, 0xBE4E, 0xD447, 0xBE4F, 0xD448, 0xBE50, 0xD449, 0xBE51, 0xD44A, 0xBE52, 0xD44B, 0xBE53, 0xD44C, 0xBE54, 0xD44D, + 0xBE55, 0xD44E, 0xBE56, 0xD44F, 0xBE57, 0xD450, 0xBE58, 0xD451, 0xBE59, 0xD452, 0xBE5A, 0xD453, 0xBE61, 0xD454, 0xBE62, 0xD455, + 0xBE63, 0xD456, 0xBE64, 0xD457, 0xBE65, 0xD458, 0xBE66, 0xD459, 0xBE67, 0xD45A, 0xBE68, 0xD45B, 0xBE69, 0xD45D, 0xBE6A, 0xD45E, + 0xBE6B, 0xD45F, 0xBE6C, 0xD461, 0xBE6D, 0xD462, 0xBE6E, 0xD463, 0xBE6F, 0xD465, 0xBE70, 0xD466, 0xBE71, 0xD467, 0xBE72, 0xD468, + 0xBE73, 0xD469, 0xBE74, 0xD46A, 0xBE75, 0xD46B, 0xBE76, 0xD46C, 0xBE77, 0xD46E, 0xBE78, 0xD470, 0xBE79, 0xD471, 0xBE7A, 0xD472, + 0xBE81, 0xD473, 0xBE82, 0xD474, 0xBE83, 0xD475, 0xBE84, 0xD476, 0xBE85, 0xD477, 0xBE86, 0xD47A, 0xBE87, 0xD47B, 0xBE88, 0xD47D, + 0xBE89, 0xD47E, 0xBE8A, 0xD481, 0xBE8B, 0xD483, 0xBE8C, 0xD484, 0xBE8D, 0xD485, 0xBE8E, 0xD486, 0xBE8F, 0xD487, 0xBE90, 0xD48A, + 0xBE91, 0xD48C, 0xBE92, 0xD48E, 0xBE93, 0xD48F, 0xBE94, 0xD490, 0xBE95, 0xD491, 0xBE96, 0xD492, 0xBE97, 0xD493, 0xBE98, 0xD495, + 0xBE99, 0xD496, 0xBE9A, 0xD497, 0xBE9B, 0xD498, 0xBE9C, 0xD499, 0xBE9D, 0xD49A, 0xBE9E, 0xD49B, 0xBE9F, 0xD49C, 0xBEA0, 0xD49D, + 0xBEA1, 0xC434, 0xBEA2, 0xC43C, 0xBEA3, 0xC43D, 0xBEA4, 0xC448, 0xBEA5, 0xC464, 0xBEA6, 0xC465, 0xBEA7, 0xC468, 0xBEA8, 0xC46C, + 0xBEA9, 0xC474, 0xBEAA, 0xC475, 0xBEAB, 0xC479, 0xBEAC, 0xC480, 0xBEAD, 0xC494, 0xBEAE, 0xC49C, 0xBEAF, 0xC4B8, 0xBEB0, 0xC4BC, + 0xBEB1, 0xC4E9, 0xBEB2, 0xC4F0, 0xBEB3, 0xC4F1, 0xBEB4, 0xC4F4, 0xBEB5, 0xC4F8, 0xBEB6, 0xC4FA, 0xBEB7, 0xC4FF, 0xBEB8, 0xC500, + 0xBEB9, 0xC501, 0xBEBA, 0xC50C, 0xBEBB, 0xC510, 0xBEBC, 0xC514, 0xBEBD, 0xC51C, 0xBEBE, 0xC528, 0xBEBF, 0xC529, 0xBEC0, 0xC52C, + 0xBEC1, 0xC530, 0xBEC2, 0xC538, 0xBEC3, 0xC539, 0xBEC4, 0xC53B, 0xBEC5, 0xC53D, 0xBEC6, 0xC544, 0xBEC7, 0xC545, 0xBEC8, 0xC548, + 0xBEC9, 0xC549, 0xBECA, 0xC54A, 0xBECB, 0xC54C, 0xBECC, 0xC54D, 0xBECD, 0xC54E, 0xBECE, 0xC553, 0xBECF, 0xC554, 0xBED0, 0xC555, + 0xBED1, 0xC557, 0xBED2, 0xC558, 0xBED3, 0xC559, 0xBED4, 0xC55D, 0xBED5, 0xC55E, 0xBED6, 0xC560, 0xBED7, 0xC561, 0xBED8, 0xC564, + 0xBED9, 0xC568, 0xBEDA, 0xC570, 0xBEDB, 0xC571, 0xBEDC, 0xC573, 0xBEDD, 0xC574, 0xBEDE, 0xC575, 0xBEDF, 0xC57C, 0xBEE0, 0xC57D, + 0xBEE1, 0xC580, 0xBEE2, 0xC584, 0xBEE3, 0xC587, 0xBEE4, 0xC58C, 0xBEE5, 0xC58D, 0xBEE6, 0xC58F, 0xBEE7, 0xC591, 0xBEE8, 0xC595, + 0xBEE9, 0xC597, 0xBEEA, 0xC598, 0xBEEB, 0xC59C, 0xBEEC, 0xC5A0, 0xBEED, 0xC5A9, 0xBEEE, 0xC5B4, 0xBEEF, 0xC5B5, 0xBEF0, 0xC5B8, + 0xBEF1, 0xC5B9, 0xBEF2, 0xC5BB, 0xBEF3, 0xC5BC, 0xBEF4, 0xC5BD, 0xBEF5, 0xC5BE, 0xBEF6, 0xC5C4, 0xBEF7, 0xC5C5, 0xBEF8, 0xC5C6, + 0xBEF9, 0xC5C7, 0xBEFA, 0xC5C8, 0xBEFB, 0xC5C9, 0xBEFC, 0xC5CA, 0xBEFD, 0xC5CC, 0xBEFE, 0xC5CE, 0xBF41, 0xD49E, 0xBF42, 0xD49F, + 0xBF43, 0xD4A0, 0xBF44, 0xD4A1, 0xBF45, 0xD4A2, 0xBF46, 0xD4A3, 0xBF47, 0xD4A4, 0xBF48, 0xD4A5, 0xBF49, 0xD4A6, 0xBF4A, 0xD4A7, + 0xBF4B, 0xD4A8, 0xBF4C, 0xD4AA, 0xBF4D, 0xD4AB, 0xBF4E, 0xD4AC, 0xBF4F, 0xD4AD, 0xBF50, 0xD4AE, 0xBF51, 0xD4AF, 0xBF52, 0xD4B0, + 0xBF53, 0xD4B1, 0xBF54, 0xD4B2, 0xBF55, 0xD4B3, 0xBF56, 0xD4B4, 0xBF57, 0xD4B5, 0xBF58, 0xD4B6, 0xBF59, 0xD4B7, 0xBF5A, 0xD4B8, + 0xBF61, 0xD4B9, 0xBF62, 0xD4BA, 0xBF63, 0xD4BB, 0xBF64, 0xD4BC, 0xBF65, 0xD4BD, 0xBF66, 0xD4BE, 0xBF67, 0xD4BF, 0xBF68, 0xD4C0, + 0xBF69, 0xD4C1, 0xBF6A, 0xD4C2, 0xBF6B, 0xD4C3, 0xBF6C, 0xD4C4, 0xBF6D, 0xD4C5, 0xBF6E, 0xD4C6, 0xBF6F, 0xD4C7, 0xBF70, 0xD4C8, + 0xBF71, 0xD4C9, 0xBF72, 0xD4CA, 0xBF73, 0xD4CB, 0xBF74, 0xD4CD, 0xBF75, 0xD4CE, 0xBF76, 0xD4CF, 0xBF77, 0xD4D1, 0xBF78, 0xD4D2, + 0xBF79, 0xD4D3, 0xBF7A, 0xD4D5, 0xBF81, 0xD4D6, 0xBF82, 0xD4D7, 0xBF83, 0xD4D8, 0xBF84, 0xD4D9, 0xBF85, 0xD4DA, 0xBF86, 0xD4DB, + 0xBF87, 0xD4DD, 0xBF88, 0xD4DE, 0xBF89, 0xD4E0, 0xBF8A, 0xD4E1, 0xBF8B, 0xD4E2, 0xBF8C, 0xD4E3, 0xBF8D, 0xD4E4, 0xBF8E, 0xD4E5, + 0xBF8F, 0xD4E6, 0xBF90, 0xD4E7, 0xBF91, 0xD4E9, 0xBF92, 0xD4EA, 0xBF93, 0xD4EB, 0xBF94, 0xD4ED, 0xBF95, 0xD4EE, 0xBF96, 0xD4EF, + 0xBF97, 0xD4F1, 0xBF98, 0xD4F2, 0xBF99, 0xD4F3, 0xBF9A, 0xD4F4, 0xBF9B, 0xD4F5, 0xBF9C, 0xD4F6, 0xBF9D, 0xD4F7, 0xBF9E, 0xD4F9, + 0xBF9F, 0xD4FA, 0xBFA0, 0xD4FC, 0xBFA1, 0xC5D0, 0xBFA2, 0xC5D1, 0xBFA3, 0xC5D4, 0xBFA4, 0xC5D8, 0xBFA5, 0xC5E0, 0xBFA6, 0xC5E1, + 0xBFA7, 0xC5E3, 0xBFA8, 0xC5E5, 0xBFA9, 0xC5EC, 0xBFAA, 0xC5ED, 0xBFAB, 0xC5EE, 0xBFAC, 0xC5F0, 0xBFAD, 0xC5F4, 0xBFAE, 0xC5F6, + 0xBFAF, 0xC5F7, 0xBFB0, 0xC5FC, 0xBFB1, 0xC5FD, 0xBFB2, 0xC5FE, 0xBFB3, 0xC5FF, 0xBFB4, 0xC600, 0xBFB5, 0xC601, 0xBFB6, 0xC605, + 0xBFB7, 0xC606, 0xBFB8, 0xC607, 0xBFB9, 0xC608, 0xBFBA, 0xC60C, 0xBFBB, 0xC610, 0xBFBC, 0xC618, 0xBFBD, 0xC619, 0xBFBE, 0xC61B, + 0xBFBF, 0xC61C, 0xBFC0, 0xC624, 0xBFC1, 0xC625, 0xBFC2, 0xC628, 0xBFC3, 0xC62C, 0xBFC4, 0xC62D, 0xBFC5, 0xC62E, 0xBFC6, 0xC630, + 0xBFC7, 0xC633, 0xBFC8, 0xC634, 0xBFC9, 0xC635, 0xBFCA, 0xC637, 0xBFCB, 0xC639, 0xBFCC, 0xC63B, 0xBFCD, 0xC640, 0xBFCE, 0xC641, + 0xBFCF, 0xC644, 0xBFD0, 0xC648, 0xBFD1, 0xC650, 0xBFD2, 0xC651, 0xBFD3, 0xC653, 0xBFD4, 0xC654, 0xBFD5, 0xC655, 0xBFD6, 0xC65C, + 0xBFD7, 0xC65D, 0xBFD8, 0xC660, 0xBFD9, 0xC66C, 0xBFDA, 0xC66F, 0xBFDB, 0xC671, 0xBFDC, 0xC678, 0xBFDD, 0xC679, 0xBFDE, 0xC67C, + 0xBFDF, 0xC680, 0xBFE0, 0xC688, 0xBFE1, 0xC689, 0xBFE2, 0xC68B, 0xBFE3, 0xC68D, 0xBFE4, 0xC694, 0xBFE5, 0xC695, 0xBFE6, 0xC698, + 0xBFE7, 0xC69C, 0xBFE8, 0xC6A4, 0xBFE9, 0xC6A5, 0xBFEA, 0xC6A7, 0xBFEB, 0xC6A9, 0xBFEC, 0xC6B0, 0xBFED, 0xC6B1, 0xBFEE, 0xC6B4, + 0xBFEF, 0xC6B8, 0xBFF0, 0xC6B9, 0xBFF1, 0xC6BA, 0xBFF2, 0xC6C0, 0xBFF3, 0xC6C1, 0xBFF4, 0xC6C3, 0xBFF5, 0xC6C5, 0xBFF6, 0xC6CC, + 0xBFF7, 0xC6CD, 0xBFF8, 0xC6D0, 0xBFF9, 0xC6D4, 0xBFFA, 0xC6DC, 0xBFFB, 0xC6DD, 0xBFFC, 0xC6E0, 0xBFFD, 0xC6E1, 0xBFFE, 0xC6E8, + 0xC041, 0xD4FE, 0xC042, 0xD4FF, 0xC043, 0xD500, 0xC044, 0xD501, 0xC045, 0xD502, 0xC046, 0xD503, 0xC047, 0xD505, 0xC048, 0xD506, + 0xC049, 0xD507, 0xC04A, 0xD509, 0xC04B, 0xD50A, 0xC04C, 0xD50B, 0xC04D, 0xD50D, 0xC04E, 0xD50E, 0xC04F, 0xD50F, 0xC050, 0xD510, + 0xC051, 0xD511, 0xC052, 0xD512, 0xC053, 0xD513, 0xC054, 0xD516, 0xC055, 0xD518, 0xC056, 0xD519, 0xC057, 0xD51A, 0xC058, 0xD51B, + 0xC059, 0xD51C, 0xC05A, 0xD51D, 0xC061, 0xD51E, 0xC062, 0xD51F, 0xC063, 0xD520, 0xC064, 0xD521, 0xC065, 0xD522, 0xC066, 0xD523, + 0xC067, 0xD524, 0xC068, 0xD525, 0xC069, 0xD526, 0xC06A, 0xD527, 0xC06B, 0xD528, 0xC06C, 0xD529, 0xC06D, 0xD52A, 0xC06E, 0xD52B, + 0xC06F, 0xD52C, 0xC070, 0xD52D, 0xC071, 0xD52E, 0xC072, 0xD52F, 0xC073, 0xD530, 0xC074, 0xD531, 0xC075, 0xD532, 0xC076, 0xD533, + 0xC077, 0xD534, 0xC078, 0xD535, 0xC079, 0xD536, 0xC07A, 0xD537, 0xC081, 0xD538, 0xC082, 0xD539, 0xC083, 0xD53A, 0xC084, 0xD53B, + 0xC085, 0xD53E, 0xC086, 0xD53F, 0xC087, 0xD541, 0xC088, 0xD542, 0xC089, 0xD543, 0xC08A, 0xD545, 0xC08B, 0xD546, 0xC08C, 0xD547, + 0xC08D, 0xD548, 0xC08E, 0xD549, 0xC08F, 0xD54A, 0xC090, 0xD54B, 0xC091, 0xD54E, 0xC092, 0xD550, 0xC093, 0xD552, 0xC094, 0xD553, + 0xC095, 0xD554, 0xC096, 0xD555, 0xC097, 0xD556, 0xC098, 0xD557, 0xC099, 0xD55A, 0xC09A, 0xD55B, 0xC09B, 0xD55D, 0xC09C, 0xD55E, + 0xC09D, 0xD55F, 0xC09E, 0xD561, 0xC09F, 0xD562, 0xC0A0, 0xD563, 0xC0A1, 0xC6E9, 0xC0A2, 0xC6EC, 0xC0A3, 0xC6F0, 0xC0A4, 0xC6F8, + 0xC0A5, 0xC6F9, 0xC0A6, 0xC6FD, 0xC0A7, 0xC704, 0xC0A8, 0xC705, 0xC0A9, 0xC708, 0xC0AA, 0xC70C, 0xC0AB, 0xC714, 0xC0AC, 0xC715, + 0xC0AD, 0xC717, 0xC0AE, 0xC719, 0xC0AF, 0xC720, 0xC0B0, 0xC721, 0xC0B1, 0xC724, 0xC0B2, 0xC728, 0xC0B3, 0xC730, 0xC0B4, 0xC731, + 0xC0B5, 0xC733, 0xC0B6, 0xC735, 0xC0B7, 0xC737, 0xC0B8, 0xC73C, 0xC0B9, 0xC73D, 0xC0BA, 0xC740, 0xC0BB, 0xC744, 0xC0BC, 0xC74A, + 0xC0BD, 0xC74C, 0xC0BE, 0xC74D, 0xC0BF, 0xC74F, 0xC0C0, 0xC751, 0xC0C1, 0xC752, 0xC0C2, 0xC753, 0xC0C3, 0xC754, 0xC0C4, 0xC755, + 0xC0C5, 0xC756, 0xC0C6, 0xC757, 0xC0C7, 0xC758, 0xC0C8, 0xC75C, 0xC0C9, 0xC760, 0xC0CA, 0xC768, 0xC0CB, 0xC76B, 0xC0CC, 0xC774, + 0xC0CD, 0xC775, 0xC0CE, 0xC778, 0xC0CF, 0xC77C, 0xC0D0, 0xC77D, 0xC0D1, 0xC77E, 0xC0D2, 0xC783, 0xC0D3, 0xC784, 0xC0D4, 0xC785, + 0xC0D5, 0xC787, 0xC0D6, 0xC788, 0xC0D7, 0xC789, 0xC0D8, 0xC78A, 0xC0D9, 0xC78E, 0xC0DA, 0xC790, 0xC0DB, 0xC791, 0xC0DC, 0xC794, + 0xC0DD, 0xC796, 0xC0DE, 0xC797, 0xC0DF, 0xC798, 0xC0E0, 0xC79A, 0xC0E1, 0xC7A0, 0xC0E2, 0xC7A1, 0xC0E3, 0xC7A3, 0xC0E4, 0xC7A4, + 0xC0E5, 0xC7A5, 0xC0E6, 0xC7A6, 0xC0E7, 0xC7AC, 0xC0E8, 0xC7AD, 0xC0E9, 0xC7B0, 0xC0EA, 0xC7B4, 0xC0EB, 0xC7BC, 0xC0EC, 0xC7BD, + 0xC0ED, 0xC7BF, 0xC0EE, 0xC7C0, 0xC0EF, 0xC7C1, 0xC0F0, 0xC7C8, 0xC0F1, 0xC7C9, 0xC0F2, 0xC7CC, 0xC0F3, 0xC7CE, 0xC0F4, 0xC7D0, + 0xC0F5, 0xC7D8, 0xC0F6, 0xC7DD, 0xC0F7, 0xC7E4, 0xC0F8, 0xC7E8, 0xC0F9, 0xC7EC, 0xC0FA, 0xC800, 0xC0FB, 0xC801, 0xC0FC, 0xC804, + 0xC0FD, 0xC808, 0xC0FE, 0xC80A, 0xC141, 0xD564, 0xC142, 0xD566, 0xC143, 0xD567, 0xC144, 0xD56A, 0xC145, 0xD56C, 0xC146, 0xD56E, + 0xC147, 0xD56F, 0xC148, 0xD570, 0xC149, 0xD571, 0xC14A, 0xD572, 0xC14B, 0xD573, 0xC14C, 0xD576, 0xC14D, 0xD577, 0xC14E, 0xD579, + 0xC14F, 0xD57A, 0xC150, 0xD57B, 0xC151, 0xD57D, 0xC152, 0xD57E, 0xC153, 0xD57F, 0xC154, 0xD580, 0xC155, 0xD581, 0xC156, 0xD582, + 0xC157, 0xD583, 0xC158, 0xD586, 0xC159, 0xD58A, 0xC15A, 0xD58B, 0xC161, 0xD58C, 0xC162, 0xD58D, 0xC163, 0xD58E, 0xC164, 0xD58F, + 0xC165, 0xD591, 0xC166, 0xD592, 0xC167, 0xD593, 0xC168, 0xD594, 0xC169, 0xD595, 0xC16A, 0xD596, 0xC16B, 0xD597, 0xC16C, 0xD598, + 0xC16D, 0xD599, 0xC16E, 0xD59A, 0xC16F, 0xD59B, 0xC170, 0xD59C, 0xC171, 0xD59D, 0xC172, 0xD59E, 0xC173, 0xD59F, 0xC174, 0xD5A0, + 0xC175, 0xD5A1, 0xC176, 0xD5A2, 0xC177, 0xD5A3, 0xC178, 0xD5A4, 0xC179, 0xD5A6, 0xC17A, 0xD5A7, 0xC181, 0xD5A8, 0xC182, 0xD5A9, + 0xC183, 0xD5AA, 0xC184, 0xD5AB, 0xC185, 0xD5AC, 0xC186, 0xD5AD, 0xC187, 0xD5AE, 0xC188, 0xD5AF, 0xC189, 0xD5B0, 0xC18A, 0xD5B1, + 0xC18B, 0xD5B2, 0xC18C, 0xD5B3, 0xC18D, 0xD5B4, 0xC18E, 0xD5B5, 0xC18F, 0xD5B6, 0xC190, 0xD5B7, 0xC191, 0xD5B8, 0xC192, 0xD5B9, + 0xC193, 0xD5BA, 0xC194, 0xD5BB, 0xC195, 0xD5BC, 0xC196, 0xD5BD, 0xC197, 0xD5BE, 0xC198, 0xD5BF, 0xC199, 0xD5C0, 0xC19A, 0xD5C1, + 0xC19B, 0xD5C2, 0xC19C, 0xD5C3, 0xC19D, 0xD5C4, 0xC19E, 0xD5C5, 0xC19F, 0xD5C6, 0xC1A0, 0xD5C7, 0xC1A1, 0xC810, 0xC1A2, 0xC811, + 0xC1A3, 0xC813, 0xC1A4, 0xC815, 0xC1A5, 0xC816, 0xC1A6, 0xC81C, 0xC1A7, 0xC81D, 0xC1A8, 0xC820, 0xC1A9, 0xC824, 0xC1AA, 0xC82C, + 0xC1AB, 0xC82D, 0xC1AC, 0xC82F, 0xC1AD, 0xC831, 0xC1AE, 0xC838, 0xC1AF, 0xC83C, 0xC1B0, 0xC840, 0xC1B1, 0xC848, 0xC1B2, 0xC849, + 0xC1B3, 0xC84C, 0xC1B4, 0xC84D, 0xC1B5, 0xC854, 0xC1B6, 0xC870, 0xC1B7, 0xC871, 0xC1B8, 0xC874, 0xC1B9, 0xC878, 0xC1BA, 0xC87A, + 0xC1BB, 0xC880, 0xC1BC, 0xC881, 0xC1BD, 0xC883, 0xC1BE, 0xC885, 0xC1BF, 0xC886, 0xC1C0, 0xC887, 0xC1C1, 0xC88B, 0xC1C2, 0xC88C, + 0xC1C3, 0xC88D, 0xC1C4, 0xC894, 0xC1C5, 0xC89D, 0xC1C6, 0xC89F, 0xC1C7, 0xC8A1, 0xC1C8, 0xC8A8, 0xC1C9, 0xC8BC, 0xC1CA, 0xC8BD, + 0xC1CB, 0xC8C4, 0xC1CC, 0xC8C8, 0xC1CD, 0xC8CC, 0xC1CE, 0xC8D4, 0xC1CF, 0xC8D5, 0xC1D0, 0xC8D7, 0xC1D1, 0xC8D9, 0xC1D2, 0xC8E0, + 0xC1D3, 0xC8E1, 0xC1D4, 0xC8E4, 0xC1D5, 0xC8F5, 0xC1D6, 0xC8FC, 0xC1D7, 0xC8FD, 0xC1D8, 0xC900, 0xC1D9, 0xC904, 0xC1DA, 0xC905, + 0xC1DB, 0xC906, 0xC1DC, 0xC90C, 0xC1DD, 0xC90D, 0xC1DE, 0xC90F, 0xC1DF, 0xC911, 0xC1E0, 0xC918, 0xC1E1, 0xC92C, 0xC1E2, 0xC934, + 0xC1E3, 0xC950, 0xC1E4, 0xC951, 0xC1E5, 0xC954, 0xC1E6, 0xC958, 0xC1E7, 0xC960, 0xC1E8, 0xC961, 0xC1E9, 0xC963, 0xC1EA, 0xC96C, + 0xC1EB, 0xC970, 0xC1EC, 0xC974, 0xC1ED, 0xC97C, 0xC1EE, 0xC988, 0xC1EF, 0xC989, 0xC1F0, 0xC98C, 0xC1F1, 0xC990, 0xC1F2, 0xC998, + 0xC1F3, 0xC999, 0xC1F4, 0xC99B, 0xC1F5, 0xC99D, 0xC1F6, 0xC9C0, 0xC1F7, 0xC9C1, 0xC1F8, 0xC9C4, 0xC1F9, 0xC9C7, 0xC1FA, 0xC9C8, + 0xC1FB, 0xC9CA, 0xC1FC, 0xC9D0, 0xC1FD, 0xC9D1, 0xC1FE, 0xC9D3, 0xC241, 0xD5CA, 0xC242, 0xD5CB, 0xC243, 0xD5CD, 0xC244, 0xD5CE, + 0xC245, 0xD5CF, 0xC246, 0xD5D1, 0xC247, 0xD5D3, 0xC248, 0xD5D4, 0xC249, 0xD5D5, 0xC24A, 0xD5D6, 0xC24B, 0xD5D7, 0xC24C, 0xD5DA, + 0xC24D, 0xD5DC, 0xC24E, 0xD5DE, 0xC24F, 0xD5DF, 0xC250, 0xD5E0, 0xC251, 0xD5E1, 0xC252, 0xD5E2, 0xC253, 0xD5E3, 0xC254, 0xD5E6, + 0xC255, 0xD5E7, 0xC256, 0xD5E9, 0xC257, 0xD5EA, 0xC258, 0xD5EB, 0xC259, 0xD5ED, 0xC25A, 0xD5EE, 0xC261, 0xD5EF, 0xC262, 0xD5F0, + 0xC263, 0xD5F1, 0xC264, 0xD5F2, 0xC265, 0xD5F3, 0xC266, 0xD5F6, 0xC267, 0xD5F8, 0xC268, 0xD5FA, 0xC269, 0xD5FB, 0xC26A, 0xD5FC, + 0xC26B, 0xD5FD, 0xC26C, 0xD5FE, 0xC26D, 0xD5FF, 0xC26E, 0xD602, 0xC26F, 0xD603, 0xC270, 0xD605, 0xC271, 0xD606, 0xC272, 0xD607, + 0xC273, 0xD609, 0xC274, 0xD60A, 0xC275, 0xD60B, 0xC276, 0xD60C, 0xC277, 0xD60D, 0xC278, 0xD60E, 0xC279, 0xD60F, 0xC27A, 0xD612, + 0xC281, 0xD616, 0xC282, 0xD617, 0xC283, 0xD618, 0xC284, 0xD619, 0xC285, 0xD61A, 0xC286, 0xD61B, 0xC287, 0xD61D, 0xC288, 0xD61E, + 0xC289, 0xD61F, 0xC28A, 0xD621, 0xC28B, 0xD622, 0xC28C, 0xD623, 0xC28D, 0xD625, 0xC28E, 0xD626, 0xC28F, 0xD627, 0xC290, 0xD628, + 0xC291, 0xD629, 0xC292, 0xD62A, 0xC293, 0xD62B, 0xC294, 0xD62C, 0xC295, 0xD62E, 0xC296, 0xD62F, 0xC297, 0xD630, 0xC298, 0xD631, + 0xC299, 0xD632, 0xC29A, 0xD633, 0xC29B, 0xD634, 0xC29C, 0xD635, 0xC29D, 0xD636, 0xC29E, 0xD637, 0xC29F, 0xD63A, 0xC2A0, 0xD63B, + 0xC2A1, 0xC9D5, 0xC2A2, 0xC9D6, 0xC2A3, 0xC9D9, 0xC2A4, 0xC9DA, 0xC2A5, 0xC9DC, 0xC2A6, 0xC9DD, 0xC2A7, 0xC9E0, 0xC2A8, 0xC9E2, + 0xC2A9, 0xC9E4, 0xC2AA, 0xC9E7, 0xC2AB, 0xC9EC, 0xC2AC, 0xC9ED, 0xC2AD, 0xC9EF, 0xC2AE, 0xC9F0, 0xC2AF, 0xC9F1, 0xC2B0, 0xC9F8, + 0xC2B1, 0xC9F9, 0xC2B2, 0xC9FC, 0xC2B3, 0xCA00, 0xC2B4, 0xCA08, 0xC2B5, 0xCA09, 0xC2B6, 0xCA0B, 0xC2B7, 0xCA0C, 0xC2B8, 0xCA0D, + 0xC2B9, 0xCA14, 0xC2BA, 0xCA18, 0xC2BB, 0xCA29, 0xC2BC, 0xCA4C, 0xC2BD, 0xCA4D, 0xC2BE, 0xCA50, 0xC2BF, 0xCA54, 0xC2C0, 0xCA5C, + 0xC2C1, 0xCA5D, 0xC2C2, 0xCA5F, 0xC2C3, 0xCA60, 0xC2C4, 0xCA61, 0xC2C5, 0xCA68, 0xC2C6, 0xCA7D, 0xC2C7, 0xCA84, 0xC2C8, 0xCA98, + 0xC2C9, 0xCABC, 0xC2CA, 0xCABD, 0xC2CB, 0xCAC0, 0xC2CC, 0xCAC4, 0xC2CD, 0xCACC, 0xC2CE, 0xCACD, 0xC2CF, 0xCACF, 0xC2D0, 0xCAD1, + 0xC2D1, 0xCAD3, 0xC2D2, 0xCAD8, 0xC2D3, 0xCAD9, 0xC2D4, 0xCAE0, 0xC2D5, 0xCAEC, 0xC2D6, 0xCAF4, 0xC2D7, 0xCB08, 0xC2D8, 0xCB10, + 0xC2D9, 0xCB14, 0xC2DA, 0xCB18, 0xC2DB, 0xCB20, 0xC2DC, 0xCB21, 0xC2DD, 0xCB41, 0xC2DE, 0xCB48, 0xC2DF, 0xCB49, 0xC2E0, 0xCB4C, + 0xC2E1, 0xCB50, 0xC2E2, 0xCB58, 0xC2E3, 0xCB59, 0xC2E4, 0xCB5D, 0xC2E5, 0xCB64, 0xC2E6, 0xCB78, 0xC2E7, 0xCB79, 0xC2E8, 0xCB9C, + 0xC2E9, 0xCBB8, 0xC2EA, 0xCBD4, 0xC2EB, 0xCBE4, 0xC2EC, 0xCBE7, 0xC2ED, 0xCBE9, 0xC2EE, 0xCC0C, 0xC2EF, 0xCC0D, 0xC2F0, 0xCC10, + 0xC2F1, 0xCC14, 0xC2F2, 0xCC1C, 0xC2F3, 0xCC1D, 0xC2F4, 0xCC21, 0xC2F5, 0xCC22, 0xC2F6, 0xCC27, 0xC2F7, 0xCC28, 0xC2F8, 0xCC29, + 0xC2F9, 0xCC2C, 0xC2FA, 0xCC2E, 0xC2FB, 0xCC30, 0xC2FC, 0xCC38, 0xC2FD, 0xCC39, 0xC2FE, 0xCC3B, 0xC341, 0xD63D, 0xC342, 0xD63E, + 0xC343, 0xD63F, 0xC344, 0xD641, 0xC345, 0xD642, 0xC346, 0xD643, 0xC347, 0xD644, 0xC348, 0xD646, 0xC349, 0xD647, 0xC34A, 0xD64A, + 0xC34B, 0xD64C, 0xC34C, 0xD64E, 0xC34D, 0xD64F, 0xC34E, 0xD650, 0xC34F, 0xD652, 0xC350, 0xD653, 0xC351, 0xD656, 0xC352, 0xD657, + 0xC353, 0xD659, 0xC354, 0xD65A, 0xC355, 0xD65B, 0xC356, 0xD65D, 0xC357, 0xD65E, 0xC358, 0xD65F, 0xC359, 0xD660, 0xC35A, 0xD661, + 0xC361, 0xD662, 0xC362, 0xD663, 0xC363, 0xD664, 0xC364, 0xD665, 0xC365, 0xD666, 0xC366, 0xD668, 0xC367, 0xD66A, 0xC368, 0xD66B, + 0xC369, 0xD66C, 0xC36A, 0xD66D, 0xC36B, 0xD66E, 0xC36C, 0xD66F, 0xC36D, 0xD672, 0xC36E, 0xD673, 0xC36F, 0xD675, 0xC370, 0xD676, + 0xC371, 0xD677, 0xC372, 0xD678, 0xC373, 0xD679, 0xC374, 0xD67A, 0xC375, 0xD67B, 0xC376, 0xD67C, 0xC377, 0xD67D, 0xC378, 0xD67E, + 0xC379, 0xD67F, 0xC37A, 0xD680, 0xC381, 0xD681, 0xC382, 0xD682, 0xC383, 0xD684, 0xC384, 0xD686, 0xC385, 0xD687, 0xC386, 0xD688, + 0xC387, 0xD689, 0xC388, 0xD68A, 0xC389, 0xD68B, 0xC38A, 0xD68E, 0xC38B, 0xD68F, 0xC38C, 0xD691, 0xC38D, 0xD692, 0xC38E, 0xD693, + 0xC38F, 0xD695, 0xC390, 0xD696, 0xC391, 0xD697, 0xC392, 0xD698, 0xC393, 0xD699, 0xC394, 0xD69A, 0xC395, 0xD69B, 0xC396, 0xD69C, + 0xC397, 0xD69E, 0xC398, 0xD6A0, 0xC399, 0xD6A2, 0xC39A, 0xD6A3, 0xC39B, 0xD6A4, 0xC39C, 0xD6A5, 0xC39D, 0xD6A6, 0xC39E, 0xD6A7, + 0xC39F, 0xD6A9, 0xC3A0, 0xD6AA, 0xC3A1, 0xCC3C, 0xC3A2, 0xCC3D, 0xC3A3, 0xCC3E, 0xC3A4, 0xCC44, 0xC3A5, 0xCC45, 0xC3A6, 0xCC48, + 0xC3A7, 0xCC4C, 0xC3A8, 0xCC54, 0xC3A9, 0xCC55, 0xC3AA, 0xCC57, 0xC3AB, 0xCC58, 0xC3AC, 0xCC59, 0xC3AD, 0xCC60, 0xC3AE, 0xCC64, + 0xC3AF, 0xCC66, 0xC3B0, 0xCC68, 0xC3B1, 0xCC70, 0xC3B2, 0xCC75, 0xC3B3, 0xCC98, 0xC3B4, 0xCC99, 0xC3B5, 0xCC9C, 0xC3B6, 0xCCA0, + 0xC3B7, 0xCCA8, 0xC3B8, 0xCCA9, 0xC3B9, 0xCCAB, 0xC3BA, 0xCCAC, 0xC3BB, 0xCCAD, 0xC3BC, 0xCCB4, 0xC3BD, 0xCCB5, 0xC3BE, 0xCCB8, + 0xC3BF, 0xCCBC, 0xC3C0, 0xCCC4, 0xC3C1, 0xCCC5, 0xC3C2, 0xCCC7, 0xC3C3, 0xCCC9, 0xC3C4, 0xCCD0, 0xC3C5, 0xCCD4, 0xC3C6, 0xCCE4, + 0xC3C7, 0xCCEC, 0xC3C8, 0xCCF0, 0xC3C9, 0xCD01, 0xC3CA, 0xCD08, 0xC3CB, 0xCD09, 0xC3CC, 0xCD0C, 0xC3CD, 0xCD10, 0xC3CE, 0xCD18, + 0xC3CF, 0xCD19, 0xC3D0, 0xCD1B, 0xC3D1, 0xCD1D, 0xC3D2, 0xCD24, 0xC3D3, 0xCD28, 0xC3D4, 0xCD2C, 0xC3D5, 0xCD39, 0xC3D6, 0xCD5C, + 0xC3D7, 0xCD60, 0xC3D8, 0xCD64, 0xC3D9, 0xCD6C, 0xC3DA, 0xCD6D, 0xC3DB, 0xCD6F, 0xC3DC, 0xCD71, 0xC3DD, 0xCD78, 0xC3DE, 0xCD88, + 0xC3DF, 0xCD94, 0xC3E0, 0xCD95, 0xC3E1, 0xCD98, 0xC3E2, 0xCD9C, 0xC3E3, 0xCDA4, 0xC3E4, 0xCDA5, 0xC3E5, 0xCDA7, 0xC3E6, 0xCDA9, + 0xC3E7, 0xCDB0, 0xC3E8, 0xCDC4, 0xC3E9, 0xCDCC, 0xC3EA, 0xCDD0, 0xC3EB, 0xCDE8, 0xC3EC, 0xCDEC, 0xC3ED, 0xCDF0, 0xC3EE, 0xCDF8, + 0xC3EF, 0xCDF9, 0xC3F0, 0xCDFB, 0xC3F1, 0xCDFD, 0xC3F2, 0xCE04, 0xC3F3, 0xCE08, 0xC3F4, 0xCE0C, 0xC3F5, 0xCE14, 0xC3F6, 0xCE19, + 0xC3F7, 0xCE20, 0xC3F8, 0xCE21, 0xC3F9, 0xCE24, 0xC3FA, 0xCE28, 0xC3FB, 0xCE30, 0xC3FC, 0xCE31, 0xC3FD, 0xCE33, 0xC3FE, 0xCE35, + 0xC441, 0xD6AB, 0xC442, 0xD6AD, 0xC443, 0xD6AE, 0xC444, 0xD6AF, 0xC445, 0xD6B1, 0xC446, 0xD6B2, 0xC447, 0xD6B3, 0xC448, 0xD6B4, + 0xC449, 0xD6B5, 0xC44A, 0xD6B6, 0xC44B, 0xD6B7, 0xC44C, 0xD6B8, 0xC44D, 0xD6BA, 0xC44E, 0xD6BC, 0xC44F, 0xD6BD, 0xC450, 0xD6BE, + 0xC451, 0xD6BF, 0xC452, 0xD6C0, 0xC453, 0xD6C1, 0xC454, 0xD6C2, 0xC455, 0xD6C3, 0xC456, 0xD6C6, 0xC457, 0xD6C7, 0xC458, 0xD6C9, + 0xC459, 0xD6CA, 0xC45A, 0xD6CB, 0xC461, 0xD6CD, 0xC462, 0xD6CE, 0xC463, 0xD6CF, 0xC464, 0xD6D0, 0xC465, 0xD6D2, 0xC466, 0xD6D3, + 0xC467, 0xD6D5, 0xC468, 0xD6D6, 0xC469, 0xD6D8, 0xC46A, 0xD6DA, 0xC46B, 0xD6DB, 0xC46C, 0xD6DC, 0xC46D, 0xD6DD, 0xC46E, 0xD6DE, + 0xC46F, 0xD6DF, 0xC470, 0xD6E1, 0xC471, 0xD6E2, 0xC472, 0xD6E3, 0xC473, 0xD6E5, 0xC474, 0xD6E6, 0xC475, 0xD6E7, 0xC476, 0xD6E9, + 0xC477, 0xD6EA, 0xC478, 0xD6EB, 0xC479, 0xD6EC, 0xC47A, 0xD6ED, 0xC481, 0xD6EE, 0xC482, 0xD6EF, 0xC483, 0xD6F1, 0xC484, 0xD6F2, + 0xC485, 0xD6F3, 0xC486, 0xD6F4, 0xC487, 0xD6F6, 0xC488, 0xD6F7, 0xC489, 0xD6F8, 0xC48A, 0xD6F9, 0xC48B, 0xD6FA, 0xC48C, 0xD6FB, + 0xC48D, 0xD6FE, 0xC48E, 0xD6FF, 0xC48F, 0xD701, 0xC490, 0xD702, 0xC491, 0xD703, 0xC492, 0xD705, 0xC493, 0xD706, 0xC494, 0xD707, + 0xC495, 0xD708, 0xC496, 0xD709, 0xC497, 0xD70A, 0xC498, 0xD70B, 0xC499, 0xD70C, 0xC49A, 0xD70D, 0xC49B, 0xD70E, 0xC49C, 0xD70F, + 0xC49D, 0xD710, 0xC49E, 0xD712, 0xC49F, 0xD713, 0xC4A0, 0xD714, 0xC4A1, 0xCE58, 0xC4A2, 0xCE59, 0xC4A3, 0xCE5C, 0xC4A4, 0xCE5F, + 0xC4A5, 0xCE60, 0xC4A6, 0xCE61, 0xC4A7, 0xCE68, 0xC4A8, 0xCE69, 0xC4A9, 0xCE6B, 0xC4AA, 0xCE6D, 0xC4AB, 0xCE74, 0xC4AC, 0xCE75, + 0xC4AD, 0xCE78, 0xC4AE, 0xCE7C, 0xC4AF, 0xCE84, 0xC4B0, 0xCE85, 0xC4B1, 0xCE87, 0xC4B2, 0xCE89, 0xC4B3, 0xCE90, 0xC4B4, 0xCE91, + 0xC4B5, 0xCE94, 0xC4B6, 0xCE98, 0xC4B7, 0xCEA0, 0xC4B8, 0xCEA1, 0xC4B9, 0xCEA3, 0xC4BA, 0xCEA4, 0xC4BB, 0xCEA5, 0xC4BC, 0xCEAC, + 0xC4BD, 0xCEAD, 0xC4BE, 0xCEC1, 0xC4BF, 0xCEE4, 0xC4C0, 0xCEE5, 0xC4C1, 0xCEE8, 0xC4C2, 0xCEEB, 0xC4C3, 0xCEEC, 0xC4C4, 0xCEF4, + 0xC4C5, 0xCEF5, 0xC4C6, 0xCEF7, 0xC4C7, 0xCEF8, 0xC4C8, 0xCEF9, 0xC4C9, 0xCF00, 0xC4CA, 0xCF01, 0xC4CB, 0xCF04, 0xC4CC, 0xCF08, + 0xC4CD, 0xCF10, 0xC4CE, 0xCF11, 0xC4CF, 0xCF13, 0xC4D0, 0xCF15, 0xC4D1, 0xCF1C, 0xC4D2, 0xCF20, 0xC4D3, 0xCF24, 0xC4D4, 0xCF2C, + 0xC4D5, 0xCF2D, 0xC4D6, 0xCF2F, 0xC4D7, 0xCF30, 0xC4D8, 0xCF31, 0xC4D9, 0xCF38, 0xC4DA, 0xCF54, 0xC4DB, 0xCF55, 0xC4DC, 0xCF58, + 0xC4DD, 0xCF5C, 0xC4DE, 0xCF64, 0xC4DF, 0xCF65, 0xC4E0, 0xCF67, 0xC4E1, 0xCF69, 0xC4E2, 0xCF70, 0xC4E3, 0xCF71, 0xC4E4, 0xCF74, + 0xC4E5, 0xCF78, 0xC4E6, 0xCF80, 0xC4E7, 0xCF85, 0xC4E8, 0xCF8C, 0xC4E9, 0xCFA1, 0xC4EA, 0xCFA8, 0xC4EB, 0xCFB0, 0xC4EC, 0xCFC4, + 0xC4ED, 0xCFE0, 0xC4EE, 0xCFE1, 0xC4EF, 0xCFE4, 0xC4F0, 0xCFE8, 0xC4F1, 0xCFF0, 0xC4F2, 0xCFF1, 0xC4F3, 0xCFF3, 0xC4F4, 0xCFF5, + 0xC4F5, 0xCFFC, 0xC4F6, 0xD000, 0xC4F7, 0xD004, 0xC4F8, 0xD011, 0xC4F9, 0xD018, 0xC4FA, 0xD02D, 0xC4FB, 0xD034, 0xC4FC, 0xD035, + 0xC4FD, 0xD038, 0xC4FE, 0xD03C, 0xC541, 0xD715, 0xC542, 0xD716, 0xC543, 0xD717, 0xC544, 0xD71A, 0xC545, 0xD71B, 0xC546, 0xD71D, + 0xC547, 0xD71E, 0xC548, 0xD71F, 0xC549, 0xD721, 0xC54A, 0xD722, 0xC54B, 0xD723, 0xC54C, 0xD724, 0xC54D, 0xD725, 0xC54E, 0xD726, + 0xC54F, 0xD727, 0xC550, 0xD72A, 0xC551, 0xD72C, 0xC552, 0xD72E, 0xC553, 0xD72F, 0xC554, 0xD730, 0xC555, 0xD731, 0xC556, 0xD732, + 0xC557, 0xD733, 0xC558, 0xD736, 0xC559, 0xD737, 0xC55A, 0xD739, 0xC561, 0xD73A, 0xC562, 0xD73B, 0xC563, 0xD73D, 0xC564, 0xD73E, + 0xC565, 0xD73F, 0xC566, 0xD740, 0xC567, 0xD741, 0xC568, 0xD742, 0xC569, 0xD743, 0xC56A, 0xD745, 0xC56B, 0xD746, 0xC56C, 0xD748, + 0xC56D, 0xD74A, 0xC56E, 0xD74B, 0xC56F, 0xD74C, 0xC570, 0xD74D, 0xC571, 0xD74E, 0xC572, 0xD74F, 0xC573, 0xD752, 0xC574, 0xD753, + 0xC575, 0xD755, 0xC576, 0xD75A, 0xC577, 0xD75B, 0xC578, 0xD75C, 0xC579, 0xD75D, 0xC57A, 0xD75E, 0xC581, 0xD75F, 0xC582, 0xD762, + 0xC583, 0xD764, 0xC584, 0xD766, 0xC585, 0xD767, 0xC586, 0xD768, 0xC587, 0xD76A, 0xC588, 0xD76B, 0xC589, 0xD76D, 0xC58A, 0xD76E, + 0xC58B, 0xD76F, 0xC58C, 0xD771, 0xC58D, 0xD772, 0xC58E, 0xD773, 0xC58F, 0xD775, 0xC590, 0xD776, 0xC591, 0xD777, 0xC592, 0xD778, + 0xC593, 0xD779, 0xC594, 0xD77A, 0xC595, 0xD77B, 0xC596, 0xD77E, 0xC597, 0xD77F, 0xC598, 0xD780, 0xC599, 0xD782, 0xC59A, 0xD783, + 0xC59B, 0xD784, 0xC59C, 0xD785, 0xC59D, 0xD786, 0xC59E, 0xD787, 0xC59F, 0xD78A, 0xC5A0, 0xD78B, 0xC5A1, 0xD044, 0xC5A2, 0xD045, + 0xC5A3, 0xD047, 0xC5A4, 0xD049, 0xC5A5, 0xD050, 0xC5A6, 0xD054, 0xC5A7, 0xD058, 0xC5A8, 0xD060, 0xC5A9, 0xD06C, 0xC5AA, 0xD06D, + 0xC5AB, 0xD070, 0xC5AC, 0xD074, 0xC5AD, 0xD07C, 0xC5AE, 0xD07D, 0xC5AF, 0xD081, 0xC5B0, 0xD0A4, 0xC5B1, 0xD0A5, 0xC5B2, 0xD0A8, + 0xC5B3, 0xD0AC, 0xC5B4, 0xD0B4, 0xC5B5, 0xD0B5, 0xC5B6, 0xD0B7, 0xC5B7, 0xD0B9, 0xC5B8, 0xD0C0, 0xC5B9, 0xD0C1, 0xC5BA, 0xD0C4, + 0xC5BB, 0xD0C8, 0xC5BC, 0xD0C9, 0xC5BD, 0xD0D0, 0xC5BE, 0xD0D1, 0xC5BF, 0xD0D3, 0xC5C0, 0xD0D4, 0xC5C1, 0xD0D5, 0xC5C2, 0xD0DC, + 0xC5C3, 0xD0DD, 0xC5C4, 0xD0E0, 0xC5C5, 0xD0E4, 0xC5C6, 0xD0EC, 0xC5C7, 0xD0ED, 0xC5C8, 0xD0EF, 0xC5C9, 0xD0F0, 0xC5CA, 0xD0F1, + 0xC5CB, 0xD0F8, 0xC5CC, 0xD10D, 0xC5CD, 0xD130, 0xC5CE, 0xD131, 0xC5CF, 0xD134, 0xC5D0, 0xD138, 0xC5D1, 0xD13A, 0xC5D2, 0xD140, + 0xC5D3, 0xD141, 0xC5D4, 0xD143, 0xC5D5, 0xD144, 0xC5D6, 0xD145, 0xC5D7, 0xD14C, 0xC5D8, 0xD14D, 0xC5D9, 0xD150, 0xC5DA, 0xD154, + 0xC5DB, 0xD15C, 0xC5DC, 0xD15D, 0xC5DD, 0xD15F, 0xC5DE, 0xD161, 0xC5DF, 0xD168, 0xC5E0, 0xD16C, 0xC5E1, 0xD17C, 0xC5E2, 0xD184, + 0xC5E3, 0xD188, 0xC5E4, 0xD1A0, 0xC5E5, 0xD1A1, 0xC5E6, 0xD1A4, 0xC5E7, 0xD1A8, 0xC5E8, 0xD1B0, 0xC5E9, 0xD1B1, 0xC5EA, 0xD1B3, + 0xC5EB, 0xD1B5, 0xC5EC, 0xD1BA, 0xC5ED, 0xD1BC, 0xC5EE, 0xD1C0, 0xC5EF, 0xD1D8, 0xC5F0, 0xD1F4, 0xC5F1, 0xD1F8, 0xC5F2, 0xD207, + 0xC5F3, 0xD209, 0xC5F4, 0xD210, 0xC5F5, 0xD22C, 0xC5F6, 0xD22D, 0xC5F7, 0xD230, 0xC5F8, 0xD234, 0xC5F9, 0xD23C, 0xC5FA, 0xD23D, + 0xC5FB, 0xD23F, 0xC5FC, 0xD241, 0xC5FD, 0xD248, 0xC5FE, 0xD25C, 0xC641, 0xD78D, 0xC642, 0xD78E, 0xC643, 0xD78F, 0xC644, 0xD791, + 0xC645, 0xD792, 0xC646, 0xD793, 0xC647, 0xD794, 0xC648, 0xD795, 0xC649, 0xD796, 0xC64A, 0xD797, 0xC64B, 0xD79A, 0xC64C, 0xD79C, + 0xC64D, 0xD79E, 0xC64E, 0xD79F, 0xC64F, 0xD7A0, 0xC650, 0xD7A1, 0xC651, 0xD7A2, 0xC652, 0xD7A3, 0xC6A1, 0xD264, 0xC6A2, 0xD280, + 0xC6A3, 0xD281, 0xC6A4, 0xD284, 0xC6A5, 0xD288, 0xC6A6, 0xD290, 0xC6A7, 0xD291, 0xC6A8, 0xD295, 0xC6A9, 0xD29C, 0xC6AA, 0xD2A0, + 0xC6AB, 0xD2A4, 0xC6AC, 0xD2AC, 0xC6AD, 0xD2B1, 0xC6AE, 0xD2B8, 0xC6AF, 0xD2B9, 0xC6B0, 0xD2BC, 0xC6B1, 0xD2BF, 0xC6B2, 0xD2C0, + 0xC6B3, 0xD2C2, 0xC6B4, 0xD2C8, 0xC6B5, 0xD2C9, 0xC6B6, 0xD2CB, 0xC6B7, 0xD2D4, 0xC6B8, 0xD2D8, 0xC6B9, 0xD2DC, 0xC6BA, 0xD2E4, + 0xC6BB, 0xD2E5, 0xC6BC, 0xD2F0, 0xC6BD, 0xD2F1, 0xC6BE, 0xD2F4, 0xC6BF, 0xD2F8, 0xC6C0, 0xD300, 0xC6C1, 0xD301, 0xC6C2, 0xD303, + 0xC6C3, 0xD305, 0xC6C4, 0xD30C, 0xC6C5, 0xD30D, 0xC6C6, 0xD30E, 0xC6C7, 0xD310, 0xC6C8, 0xD314, 0xC6C9, 0xD316, 0xC6CA, 0xD31C, + 0xC6CB, 0xD31D, 0xC6CC, 0xD31F, 0xC6CD, 0xD320, 0xC6CE, 0xD321, 0xC6CF, 0xD325, 0xC6D0, 0xD328, 0xC6D1, 0xD329, 0xC6D2, 0xD32C, + 0xC6D3, 0xD330, 0xC6D4, 0xD338, 0xC6D5, 0xD339, 0xC6D6, 0xD33B, 0xC6D7, 0xD33C, 0xC6D8, 0xD33D, 0xC6D9, 0xD344, 0xC6DA, 0xD345, + 0xC6DB, 0xD37C, 0xC6DC, 0xD37D, 0xC6DD, 0xD380, 0xC6DE, 0xD384, 0xC6DF, 0xD38C, 0xC6E0, 0xD38D, 0xC6E1, 0xD38F, 0xC6E2, 0xD390, + 0xC6E3, 0xD391, 0xC6E4, 0xD398, 0xC6E5, 0xD399, 0xC6E6, 0xD39C, 0xC6E7, 0xD3A0, 0xC6E8, 0xD3A8, 0xC6E9, 0xD3A9, 0xC6EA, 0xD3AB, + 0xC6EB, 0xD3AD, 0xC6EC, 0xD3B4, 0xC6ED, 0xD3B8, 0xC6EE, 0xD3BC, 0xC6EF, 0xD3C4, 0xC6F0, 0xD3C5, 0xC6F1, 0xD3C8, 0xC6F2, 0xD3C9, + 0xC6F3, 0xD3D0, 0xC6F4, 0xD3D8, 0xC6F5, 0xD3E1, 0xC6F6, 0xD3E3, 0xC6F7, 0xD3EC, 0xC6F8, 0xD3ED, 0xC6F9, 0xD3F0, 0xC6FA, 0xD3F4, + 0xC6FB, 0xD3FC, 0xC6FC, 0xD3FD, 0xC6FD, 0xD3FF, 0xC6FE, 0xD401, 0xC7A1, 0xD408, 0xC7A2, 0xD41D, 0xC7A3, 0xD440, 0xC7A4, 0xD444, + 0xC7A5, 0xD45C, 0xC7A6, 0xD460, 0xC7A7, 0xD464, 0xC7A8, 0xD46D, 0xC7A9, 0xD46F, 0xC7AA, 0xD478, 0xC7AB, 0xD479, 0xC7AC, 0xD47C, + 0xC7AD, 0xD47F, 0xC7AE, 0xD480, 0xC7AF, 0xD482, 0xC7B0, 0xD488, 0xC7B1, 0xD489, 0xC7B2, 0xD48B, 0xC7B3, 0xD48D, 0xC7B4, 0xD494, + 0xC7B5, 0xD4A9, 0xC7B6, 0xD4CC, 0xC7B7, 0xD4D0, 0xC7B8, 0xD4D4, 0xC7B9, 0xD4DC, 0xC7BA, 0xD4DF, 0xC7BB, 0xD4E8, 0xC7BC, 0xD4EC, + 0xC7BD, 0xD4F0, 0xC7BE, 0xD4F8, 0xC7BF, 0xD4FB, 0xC7C0, 0xD4FD, 0xC7C1, 0xD504, 0xC7C2, 0xD508, 0xC7C3, 0xD50C, 0xC7C4, 0xD514, + 0xC7C5, 0xD515, 0xC7C6, 0xD517, 0xC7C7, 0xD53C, 0xC7C8, 0xD53D, 0xC7C9, 0xD540, 0xC7CA, 0xD544, 0xC7CB, 0xD54C, 0xC7CC, 0xD54D, + 0xC7CD, 0xD54F, 0xC7CE, 0xD551, 0xC7CF, 0xD558, 0xC7D0, 0xD559, 0xC7D1, 0xD55C, 0xC7D2, 0xD560, 0xC7D3, 0xD565, 0xC7D4, 0xD568, + 0xC7D5, 0xD569, 0xC7D6, 0xD56B, 0xC7D7, 0xD56D, 0xC7D8, 0xD574, 0xC7D9, 0xD575, 0xC7DA, 0xD578, 0xC7DB, 0xD57C, 0xC7DC, 0xD584, + 0xC7DD, 0xD585, 0xC7DE, 0xD587, 0xC7DF, 0xD588, 0xC7E0, 0xD589, 0xC7E1, 0xD590, 0xC7E2, 0xD5A5, 0xC7E3, 0xD5C8, 0xC7E4, 0xD5C9, + 0xC7E5, 0xD5CC, 0xC7E6, 0xD5D0, 0xC7E7, 0xD5D2, 0xC7E8, 0xD5D8, 0xC7E9, 0xD5D9, 0xC7EA, 0xD5DB, 0xC7EB, 0xD5DD, 0xC7EC, 0xD5E4, + 0xC7ED, 0xD5E5, 0xC7EE, 0xD5E8, 0xC7EF, 0xD5EC, 0xC7F0, 0xD5F4, 0xC7F1, 0xD5F5, 0xC7F2, 0xD5F7, 0xC7F3, 0xD5F9, 0xC7F4, 0xD600, + 0xC7F5, 0xD601, 0xC7F6, 0xD604, 0xC7F7, 0xD608, 0xC7F8, 0xD610, 0xC7F9, 0xD611, 0xC7FA, 0xD613, 0xC7FB, 0xD614, 0xC7FC, 0xD615, + 0xC7FD, 0xD61C, 0xC7FE, 0xD620, 0xC8A1, 0xD624, 0xC8A2, 0xD62D, 0xC8A3, 0xD638, 0xC8A4, 0xD639, 0xC8A5, 0xD63C, 0xC8A6, 0xD640, + 0xC8A7, 0xD645, 0xC8A8, 0xD648, 0xC8A9, 0xD649, 0xC8AA, 0xD64B, 0xC8AB, 0xD64D, 0xC8AC, 0xD651, 0xC8AD, 0xD654, 0xC8AE, 0xD655, + 0xC8AF, 0xD658, 0xC8B0, 0xD65C, 0xC8B1, 0xD667, 0xC8B2, 0xD669, 0xC8B3, 0xD670, 0xC8B4, 0xD671, 0xC8B5, 0xD674, 0xC8B6, 0xD683, + 0xC8B7, 0xD685, 0xC8B8, 0xD68C, 0xC8B9, 0xD68D, 0xC8BA, 0xD690, 0xC8BB, 0xD694, 0xC8BC, 0xD69D, 0xC8BD, 0xD69F, 0xC8BE, 0xD6A1, + 0xC8BF, 0xD6A8, 0xC8C0, 0xD6AC, 0xC8C1, 0xD6B0, 0xC8C2, 0xD6B9, 0xC8C3, 0xD6BB, 0xC8C4, 0xD6C4, 0xC8C5, 0xD6C5, 0xC8C6, 0xD6C8, + 0xC8C7, 0xD6CC, 0xC8C8, 0xD6D1, 0xC8C9, 0xD6D4, 0xC8CA, 0xD6D7, 0xC8CB, 0xD6D9, 0xC8CC, 0xD6E0, 0xC8CD, 0xD6E4, 0xC8CE, 0xD6E8, + 0xC8CF, 0xD6F0, 0xC8D0, 0xD6F5, 0xC8D1, 0xD6FC, 0xC8D2, 0xD6FD, 0xC8D3, 0xD700, 0xC8D4, 0xD704, 0xC8D5, 0xD711, 0xC8D6, 0xD718, + 0xC8D7, 0xD719, 0xC8D8, 0xD71C, 0xC8D9, 0xD720, 0xC8DA, 0xD728, 0xC8DB, 0xD729, 0xC8DC, 0xD72B, 0xC8DD, 0xD72D, 0xC8DE, 0xD734, + 0xC8DF, 0xD735, 0xC8E0, 0xD738, 0xC8E1, 0xD73C, 0xC8E2, 0xD744, 0xC8E3, 0xD747, 0xC8E4, 0xD749, 0xC8E5, 0xD750, 0xC8E6, 0xD751, + 0xC8E7, 0xD754, 0xC8E8, 0xD756, 0xC8E9, 0xD757, 0xC8EA, 0xD758, 0xC8EB, 0xD759, 0xC8EC, 0xD760, 0xC8ED, 0xD761, 0xC8EE, 0xD763, + 0xC8EF, 0xD765, 0xC8F0, 0xD769, 0xC8F1, 0xD76C, 0xC8F2, 0xD770, 0xC8F3, 0xD774, 0xC8F4, 0xD77C, 0xC8F5, 0xD77D, 0xC8F6, 0xD781, + 0xC8F7, 0xD788, 0xC8F8, 0xD789, 0xC8F9, 0xD78C, 0xC8FA, 0xD790, 0xC8FB, 0xD798, 0xC8FC, 0xD799, 0xC8FD, 0xD79B, 0xC8FE, 0xD79D, + 0xCAA1, 0x4F3D, 0xCAA2, 0x4F73, 0xCAA3, 0x5047, 0xCAA4, 0x50F9, 0xCAA5, 0x52A0, 0xCAA6, 0x53EF, 0xCAA7, 0x5475, 0xCAA8, 0x54E5, + 0xCAA9, 0x5609, 0xCAAA, 0x5AC1, 0xCAAB, 0x5BB6, 0xCAAC, 0x6687, 0xCAAD, 0x67B6, 0xCAAE, 0x67B7, 0xCAAF, 0x67EF, 0xCAB0, 0x6B4C, + 0xCAB1, 0x73C2, 0xCAB2, 0x75C2, 0xCAB3, 0x7A3C, 0xCAB4, 0x82DB, 0xCAB5, 0x8304, 0xCAB6, 0x8857, 0xCAB7, 0x8888, 0xCAB8, 0x8A36, + 0xCAB9, 0x8CC8, 0xCABA, 0x8DCF, 0xCABB, 0x8EFB, 0xCABC, 0x8FE6, 0xCABD, 0x99D5, 0xCABE, 0x523B, 0xCABF, 0x5374, 0xCAC0, 0x5404, + 0xCAC1, 0x606A, 0xCAC2, 0x6164, 0xCAC3, 0x6BBC, 0xCAC4, 0x73CF, 0xCAC5, 0x811A, 0xCAC6, 0x89BA, 0xCAC7, 0x89D2, 0xCAC8, 0x95A3, + 0xCAC9, 0x4F83, 0xCACA, 0x520A, 0xCACB, 0x58BE, 0xCACC, 0x5978, 0xCACD, 0x59E6, 0xCACE, 0x5E72, 0xCACF, 0x5E79, 0xCAD0, 0x61C7, + 0xCAD1, 0x63C0, 0xCAD2, 0x6746, 0xCAD3, 0x67EC, 0xCAD4, 0x687F, 0xCAD5, 0x6F97, 0xCAD6, 0x764E, 0xCAD7, 0x770B, 0xCAD8, 0x78F5, + 0xCAD9, 0x7A08, 0xCADA, 0x7AFF, 0xCADB, 0x7C21, 0xCADC, 0x809D, 0xCADD, 0x826E, 0xCADE, 0x8271, 0xCADF, 0x8AEB, 0xCAE0, 0x9593, + 0xCAE1, 0x4E6B, 0xCAE2, 0x559D, 0xCAE3, 0x66F7, 0xCAE4, 0x6E34, 0xCAE5, 0x78A3, 0xCAE6, 0x7AED, 0xCAE7, 0x845B, 0xCAE8, 0x8910, + 0xCAE9, 0x874E, 0xCAEA, 0x97A8, 0xCAEB, 0x52D8, 0xCAEC, 0x574E, 0xCAED, 0x582A, 0xCAEE, 0x5D4C, 0xCAEF, 0x611F, 0xCAF0, 0x61BE, + 0xCAF1, 0x6221, 0xCAF2, 0x6562, 0xCAF3, 0x67D1, 0xCAF4, 0x6A44, 0xCAF5, 0x6E1B, 0xCAF6, 0x7518, 0xCAF7, 0x75B3, 0xCAF8, 0x76E3, + 0xCAF9, 0x77B0, 0xCAFA, 0x7D3A, 0xCAFB, 0x90AF, 0xCAFC, 0x9451, 0xCAFD, 0x9452, 0xCAFE, 0x9F95, 0xCBA1, 0x5323, 0xCBA2, 0x5CAC, + 0xCBA3, 0x7532, 0xCBA4, 0x80DB, 0xCBA5, 0x9240, 0xCBA6, 0x9598, 0xCBA7, 0x525B, 0xCBA8, 0x5808, 0xCBA9, 0x59DC, 0xCBAA, 0x5CA1, + 0xCBAB, 0x5D17, 0xCBAC, 0x5EB7, 0xCBAD, 0x5F3A, 0xCBAE, 0x5F4A, 0xCBAF, 0x6177, 0xCBB0, 0x6C5F, 0xCBB1, 0x757A, 0xCBB2, 0x7586, + 0xCBB3, 0x7CE0, 0xCBB4, 0x7D73, 0xCBB5, 0x7DB1, 0xCBB6, 0x7F8C, 0xCBB7, 0x8154, 0xCBB8, 0x8221, 0xCBB9, 0x8591, 0xCBBA, 0x8941, + 0xCBBB, 0x8B1B, 0xCBBC, 0x92FC, 0xCBBD, 0x964D, 0xCBBE, 0x9C47, 0xCBBF, 0x4ECB, 0xCBC0, 0x4EF7, 0xCBC1, 0x500B, 0xCBC2, 0x51F1, + 0xCBC3, 0x584F, 0xCBC4, 0x6137, 0xCBC5, 0x613E, 0xCBC6, 0x6168, 0xCBC7, 0x6539, 0xCBC8, 0x69EA, 0xCBC9, 0x6F11, 0xCBCA, 0x75A5, + 0xCBCB, 0x7686, 0xCBCC, 0x76D6, 0xCBCD, 0x7B87, 0xCBCE, 0x82A5, 0xCBCF, 0x84CB, 0xCBD0, 0xF900, 0xCBD1, 0x93A7, 0xCBD2, 0x958B, + 0xCBD3, 0x5580, 0xCBD4, 0x5BA2, 0xCBD5, 0x5751, 0xCBD6, 0xF901, 0xCBD7, 0x7CB3, 0xCBD8, 0x7FB9, 0xCBD9, 0x91B5, 0xCBDA, 0x5028, + 0xCBDB, 0x53BB, 0xCBDC, 0x5C45, 0xCBDD, 0x5DE8, 0xCBDE, 0x62D2, 0xCBDF, 0x636E, 0xCBE0, 0x64DA, 0xCBE1, 0x64E7, 0xCBE2, 0x6E20, + 0xCBE3, 0x70AC, 0xCBE4, 0x795B, 0xCBE5, 0x8DDD, 0xCBE6, 0x8E1E, 0xCBE7, 0xF902, 0xCBE8, 0x907D, 0xCBE9, 0x9245, 0xCBEA, 0x92F8, + 0xCBEB, 0x4E7E, 0xCBEC, 0x4EF6, 0xCBED, 0x5065, 0xCBEE, 0x5DFE, 0xCBEF, 0x5EFA, 0xCBF0, 0x6106, 0xCBF1, 0x6957, 0xCBF2, 0x8171, + 0xCBF3, 0x8654, 0xCBF4, 0x8E47, 0xCBF5, 0x9375, 0xCBF6, 0x9A2B, 0xCBF7, 0x4E5E, 0xCBF8, 0x5091, 0xCBF9, 0x6770, 0xCBFA, 0x6840, + 0xCBFB, 0x5109, 0xCBFC, 0x528D, 0xCBFD, 0x5292, 0xCBFE, 0x6AA2, 0xCCA1, 0x77BC, 0xCCA2, 0x9210, 0xCCA3, 0x9ED4, 0xCCA4, 0x52AB, + 0xCCA5, 0x602F, 0xCCA6, 0x8FF2, 0xCCA7, 0x5048, 0xCCA8, 0x61A9, 0xCCA9, 0x63ED, 0xCCAA, 0x64CA, 0xCCAB, 0x683C, 0xCCAC, 0x6A84, + 0xCCAD, 0x6FC0, 0xCCAE, 0x8188, 0xCCAF, 0x89A1, 0xCCB0, 0x9694, 0xCCB1, 0x5805, 0xCCB2, 0x727D, 0xCCB3, 0x72AC, 0xCCB4, 0x7504, + 0xCCB5, 0x7D79, 0xCCB6, 0x7E6D, 0xCCB7, 0x80A9, 0xCCB8, 0x898B, 0xCCB9, 0x8B74, 0xCCBA, 0x9063, 0xCCBB, 0x9D51, 0xCCBC, 0x6289, + 0xCCBD, 0x6C7A, 0xCCBE, 0x6F54, 0xCCBF, 0x7D50, 0xCCC0, 0x7F3A, 0xCCC1, 0x8A23, 0xCCC2, 0x517C, 0xCCC3, 0x614A, 0xCCC4, 0x7B9D, + 0xCCC5, 0x8B19, 0xCCC6, 0x9257, 0xCCC7, 0x938C, 0xCCC8, 0x4EAC, 0xCCC9, 0x4FD3, 0xCCCA, 0x501E, 0xCCCB, 0x50BE, 0xCCCC, 0x5106, + 0xCCCD, 0x52C1, 0xCCCE, 0x52CD, 0xCCCF, 0x537F, 0xCCD0, 0x5770, 0xCCD1, 0x5883, 0xCCD2, 0x5E9A, 0xCCD3, 0x5F91, 0xCCD4, 0x6176, + 0xCCD5, 0x61AC, 0xCCD6, 0x64CE, 0xCCD7, 0x656C, 0xCCD8, 0x666F, 0xCCD9, 0x66BB, 0xCCDA, 0x66F4, 0xCCDB, 0x6897, 0xCCDC, 0x6D87, + 0xCCDD, 0x7085, 0xCCDE, 0x70F1, 0xCCDF, 0x749F, 0xCCE0, 0x74A5, 0xCCE1, 0x74CA, 0xCCE2, 0x75D9, 0xCCE3, 0x786C, 0xCCE4, 0x78EC, + 0xCCE5, 0x7ADF, 0xCCE6, 0x7AF6, 0xCCE7, 0x7D45, 0xCCE8, 0x7D93, 0xCCE9, 0x8015, 0xCCEA, 0x803F, 0xCCEB, 0x811B, 0xCCEC, 0x8396, + 0xCCED, 0x8B66, 0xCCEE, 0x8F15, 0xCCEF, 0x9015, 0xCCF0, 0x93E1, 0xCCF1, 0x9803, 0xCCF2, 0x9838, 0xCCF3, 0x9A5A, 0xCCF4, 0x9BE8, + 0xCCF5, 0x4FC2, 0xCCF6, 0x5553, 0xCCF7, 0x583A, 0xCCF8, 0x5951, 0xCCF9, 0x5B63, 0xCCFA, 0x5C46, 0xCCFB, 0x60B8, 0xCCFC, 0x6212, + 0xCCFD, 0x6842, 0xCCFE, 0x68B0, 0xCDA1, 0x68E8, 0xCDA2, 0x6EAA, 0xCDA3, 0x754C, 0xCDA4, 0x7678, 0xCDA5, 0x78CE, 0xCDA6, 0x7A3D, + 0xCDA7, 0x7CFB, 0xCDA8, 0x7E6B, 0xCDA9, 0x7E7C, 0xCDAA, 0x8A08, 0xCDAB, 0x8AA1, 0xCDAC, 0x8C3F, 0xCDAD, 0x968E, 0xCDAE, 0x9DC4, + 0xCDAF, 0x53E4, 0xCDB0, 0x53E9, 0xCDB1, 0x544A, 0xCDB2, 0x5471, 0xCDB3, 0x56FA, 0xCDB4, 0x59D1, 0xCDB5, 0x5B64, 0xCDB6, 0x5C3B, + 0xCDB7, 0x5EAB, 0xCDB8, 0x62F7, 0xCDB9, 0x6537, 0xCDBA, 0x6545, 0xCDBB, 0x6572, 0xCDBC, 0x66A0, 0xCDBD, 0x67AF, 0xCDBE, 0x69C1, + 0xCDBF, 0x6CBD, 0xCDC0, 0x75FC, 0xCDC1, 0x7690, 0xCDC2, 0x777E, 0xCDC3, 0x7A3F, 0xCDC4, 0x7F94, 0xCDC5, 0x8003, 0xCDC6, 0x80A1, + 0xCDC7, 0x818F, 0xCDC8, 0x82E6, 0xCDC9, 0x82FD, 0xCDCA, 0x83F0, 0xCDCB, 0x85C1, 0xCDCC, 0x8831, 0xCDCD, 0x88B4, 0xCDCE, 0x8AA5, + 0xCDCF, 0xF903, 0xCDD0, 0x8F9C, 0xCDD1, 0x932E, 0xCDD2, 0x96C7, 0xCDD3, 0x9867, 0xCDD4, 0x9AD8, 0xCDD5, 0x9F13, 0xCDD6, 0x54ED, + 0xCDD7, 0x659B, 0xCDD8, 0x66F2, 0xCDD9, 0x688F, 0xCDDA, 0x7A40, 0xCDDB, 0x8C37, 0xCDDC, 0x9D60, 0xCDDD, 0x56F0, 0xCDDE, 0x5764, + 0xCDDF, 0x5D11, 0xCDE0, 0x6606, 0xCDE1, 0x68B1, 0xCDE2, 0x68CD, 0xCDE3, 0x6EFE, 0xCDE4, 0x7428, 0xCDE5, 0x889E, 0xCDE6, 0x9BE4, + 0xCDE7, 0x6C68, 0xCDE8, 0xF904, 0xCDE9, 0x9AA8, 0xCDEA, 0x4F9B, 0xCDEB, 0x516C, 0xCDEC, 0x5171, 0xCDED, 0x529F, 0xCDEE, 0x5B54, + 0xCDEF, 0x5DE5, 0xCDF0, 0x6050, 0xCDF1, 0x606D, 0xCDF2, 0x62F1, 0xCDF3, 0x63A7, 0xCDF4, 0x653B, 0xCDF5, 0x73D9, 0xCDF6, 0x7A7A, + 0xCDF7, 0x86A3, 0xCDF8, 0x8CA2, 0xCDF9, 0x978F, 0xCDFA, 0x4E32, 0xCDFB, 0x5BE1, 0xCDFC, 0x6208, 0xCDFD, 0x679C, 0xCDFE, 0x74DC, + 0xCEA1, 0x79D1, 0xCEA2, 0x83D3, 0xCEA3, 0x8A87, 0xCEA4, 0x8AB2, 0xCEA5, 0x8DE8, 0xCEA6, 0x904E, 0xCEA7, 0x934B, 0xCEA8, 0x9846, + 0xCEA9, 0x5ED3, 0xCEAA, 0x69E8, 0xCEAB, 0x85FF, 0xCEAC, 0x90ED, 0xCEAD, 0xF905, 0xCEAE, 0x51A0, 0xCEAF, 0x5B98, 0xCEB0, 0x5BEC, + 0xCEB1, 0x6163, 0xCEB2, 0x68FA, 0xCEB3, 0x6B3E, 0xCEB4, 0x704C, 0xCEB5, 0x742F, 0xCEB6, 0x74D8, 0xCEB7, 0x7BA1, 0xCEB8, 0x7F50, + 0xCEB9, 0x83C5, 0xCEBA, 0x89C0, 0xCEBB, 0x8CAB, 0xCEBC, 0x95DC, 0xCEBD, 0x9928, 0xCEBE, 0x522E, 0xCEBF, 0x605D, 0xCEC0, 0x62EC, + 0xCEC1, 0x9002, 0xCEC2, 0x4F8A, 0xCEC3, 0x5149, 0xCEC4, 0x5321, 0xCEC5, 0x58D9, 0xCEC6, 0x5EE3, 0xCEC7, 0x66E0, 0xCEC8, 0x6D38, + 0xCEC9, 0x709A, 0xCECA, 0x72C2, 0xCECB, 0x73D6, 0xCECC, 0x7B50, 0xCECD, 0x80F1, 0xCECE, 0x945B, 0xCECF, 0x5366, 0xCED0, 0x639B, + 0xCED1, 0x7F6B, 0xCED2, 0x4E56, 0xCED3, 0x5080, 0xCED4, 0x584A, 0xCED5, 0x58DE, 0xCED6, 0x602A, 0xCED7, 0x6127, 0xCED8, 0x62D0, + 0xCED9, 0x69D0, 0xCEDA, 0x9B41, 0xCEDB, 0x5B8F, 0xCEDC, 0x7D18, 0xCEDD, 0x80B1, 0xCEDE, 0x8F5F, 0xCEDF, 0x4EA4, 0xCEE0, 0x50D1, + 0xCEE1, 0x54AC, 0xCEE2, 0x55AC, 0xCEE3, 0x5B0C, 0xCEE4, 0x5DA0, 0xCEE5, 0x5DE7, 0xCEE6, 0x652A, 0xCEE7, 0x654E, 0xCEE8, 0x6821, + 0xCEE9, 0x6A4B, 0xCEEA, 0x72E1, 0xCEEB, 0x768E, 0xCEEC, 0x77EF, 0xCEED, 0x7D5E, 0xCEEE, 0x7FF9, 0xCEEF, 0x81A0, 0xCEF0, 0x854E, + 0xCEF1, 0x86DF, 0xCEF2, 0x8F03, 0xCEF3, 0x8F4E, 0xCEF4, 0x90CA, 0xCEF5, 0x9903, 0xCEF6, 0x9A55, 0xCEF7, 0x9BAB, 0xCEF8, 0x4E18, + 0xCEF9, 0x4E45, 0xCEFA, 0x4E5D, 0xCEFB, 0x4EC7, 0xCEFC, 0x4FF1, 0xCEFD, 0x5177, 0xCEFE, 0x52FE, 0xCFA1, 0x5340, 0xCFA2, 0x53E3, + 0xCFA3, 0x53E5, 0xCFA4, 0x548E, 0xCFA5, 0x5614, 0xCFA6, 0x5775, 0xCFA7, 0x57A2, 0xCFA8, 0x5BC7, 0xCFA9, 0x5D87, 0xCFAA, 0x5ED0, + 0xCFAB, 0x61FC, 0xCFAC, 0x62D8, 0xCFAD, 0x6551, 0xCFAE, 0x67B8, 0xCFAF, 0x67E9, 0xCFB0, 0x69CB, 0xCFB1, 0x6B50, 0xCFB2, 0x6BC6, + 0xCFB3, 0x6BEC, 0xCFB4, 0x6C42, 0xCFB5, 0x6E9D, 0xCFB6, 0x7078, 0xCFB7, 0x72D7, 0xCFB8, 0x7396, 0xCFB9, 0x7403, 0xCFBA, 0x77BF, + 0xCFBB, 0x77E9, 0xCFBC, 0x7A76, 0xCFBD, 0x7D7F, 0xCFBE, 0x8009, 0xCFBF, 0x81FC, 0xCFC0, 0x8205, 0xCFC1, 0x820A, 0xCFC2, 0x82DF, + 0xCFC3, 0x8862, 0xCFC4, 0x8B33, 0xCFC5, 0x8CFC, 0xCFC6, 0x8EC0, 0xCFC7, 0x9011, 0xCFC8, 0x90B1, 0xCFC9, 0x9264, 0xCFCA, 0x92B6, + 0xCFCB, 0x99D2, 0xCFCC, 0x9A45, 0xCFCD, 0x9CE9, 0xCFCE, 0x9DD7, 0xCFCF, 0x9F9C, 0xCFD0, 0x570B, 0xCFD1, 0x5C40, 0xCFD2, 0x83CA, + 0xCFD3, 0x97A0, 0xCFD4, 0x97AB, 0xCFD5, 0x9EB4, 0xCFD6, 0x541B, 0xCFD7, 0x7A98, 0xCFD8, 0x7FA4, 0xCFD9, 0x88D9, 0xCFDA, 0x8ECD, + 0xCFDB, 0x90E1, 0xCFDC, 0x5800, 0xCFDD, 0x5C48, 0xCFDE, 0x6398, 0xCFDF, 0x7A9F, 0xCFE0, 0x5BAE, 0xCFE1, 0x5F13, 0xCFE2, 0x7A79, + 0xCFE3, 0x7AAE, 0xCFE4, 0x828E, 0xCFE5, 0x8EAC, 0xCFE6, 0x5026, 0xCFE7, 0x5238, 0xCFE8, 0x52F8, 0xCFE9, 0x5377, 0xCFEA, 0x5708, + 0xCFEB, 0x62F3, 0xCFEC, 0x6372, 0xCFED, 0x6B0A, 0xCFEE, 0x6DC3, 0xCFEF, 0x7737, 0xCFF0, 0x53A5, 0xCFF1, 0x7357, 0xCFF2, 0x8568, + 0xCFF3, 0x8E76, 0xCFF4, 0x95D5, 0xCFF5, 0x673A, 0xCFF6, 0x6AC3, 0xCFF7, 0x6F70, 0xCFF8, 0x8A6D, 0xCFF9, 0x8ECC, 0xCFFA, 0x994B, + 0xCFFB, 0xF906, 0xCFFC, 0x6677, 0xCFFD, 0x6B78, 0xCFFE, 0x8CB4, 0xD0A1, 0x9B3C, 0xD0A2, 0xF907, 0xD0A3, 0x53EB, 0xD0A4, 0x572D, + 0xD0A5, 0x594E, 0xD0A6, 0x63C6, 0xD0A7, 0x69FB, 0xD0A8, 0x73EA, 0xD0A9, 0x7845, 0xD0AA, 0x7ABA, 0xD0AB, 0x7AC5, 0xD0AC, 0x7CFE, + 0xD0AD, 0x8475, 0xD0AE, 0x898F, 0xD0AF, 0x8D73, 0xD0B0, 0x9035, 0xD0B1, 0x95A8, 0xD0B2, 0x52FB, 0xD0B3, 0x5747, 0xD0B4, 0x7547, + 0xD0B5, 0x7B60, 0xD0B6, 0x83CC, 0xD0B7, 0x921E, 0xD0B8, 0xF908, 0xD0B9, 0x6A58, 0xD0BA, 0x514B, 0xD0BB, 0x524B, 0xD0BC, 0x5287, + 0xD0BD, 0x621F, 0xD0BE, 0x68D8, 0xD0BF, 0x6975, 0xD0C0, 0x9699, 0xD0C1, 0x50C5, 0xD0C2, 0x52A4, 0xD0C3, 0x52E4, 0xD0C4, 0x61C3, + 0xD0C5, 0x65A4, 0xD0C6, 0x6839, 0xD0C7, 0x69FF, 0xD0C8, 0x747E, 0xD0C9, 0x7B4B, 0xD0CA, 0x82B9, 0xD0CB, 0x83EB, 0xD0CC, 0x89B2, + 0xD0CD, 0x8B39, 0xD0CE, 0x8FD1, 0xD0CF, 0x9949, 0xD0D0, 0xF909, 0xD0D1, 0x4ECA, 0xD0D2, 0x5997, 0xD0D3, 0x64D2, 0xD0D4, 0x6611, + 0xD0D5, 0x6A8E, 0xD0D6, 0x7434, 0xD0D7, 0x7981, 0xD0D8, 0x79BD, 0xD0D9, 0x82A9, 0xD0DA, 0x887E, 0xD0DB, 0x887F, 0xD0DC, 0x895F, + 0xD0DD, 0xF90A, 0xD0DE, 0x9326, 0xD0DF, 0x4F0B, 0xD0E0, 0x53CA, 0xD0E1, 0x6025, 0xD0E2, 0x6271, 0xD0E3, 0x6C72, 0xD0E4, 0x7D1A, + 0xD0E5, 0x7D66, 0xD0E6, 0x4E98, 0xD0E7, 0x5162, 0xD0E8, 0x77DC, 0xD0E9, 0x80AF, 0xD0EA, 0x4F01, 0xD0EB, 0x4F0E, 0xD0EC, 0x5176, + 0xD0ED, 0x5180, 0xD0EE, 0x55DC, 0xD0EF, 0x5668, 0xD0F0, 0x573B, 0xD0F1, 0x57FA, 0xD0F2, 0x57FC, 0xD0F3, 0x5914, 0xD0F4, 0x5947, + 0xD0F5, 0x5993, 0xD0F6, 0x5BC4, 0xD0F7, 0x5C90, 0xD0F8, 0x5D0E, 0xD0F9, 0x5DF1, 0xD0FA, 0x5E7E, 0xD0FB, 0x5FCC, 0xD0FC, 0x6280, + 0xD0FD, 0x65D7, 0xD0FE, 0x65E3, 0xD1A1, 0x671E, 0xD1A2, 0x671F, 0xD1A3, 0x675E, 0xD1A4, 0x68CB, 0xD1A5, 0x68C4, 0xD1A6, 0x6A5F, + 0xD1A7, 0x6B3A, 0xD1A8, 0x6C23, 0xD1A9, 0x6C7D, 0xD1AA, 0x6C82, 0xD1AB, 0x6DC7, 0xD1AC, 0x7398, 0xD1AD, 0x7426, 0xD1AE, 0x742A, + 0xD1AF, 0x7482, 0xD1B0, 0x74A3, 0xD1B1, 0x7578, 0xD1B2, 0x757F, 0xD1B3, 0x7881, 0xD1B4, 0x78EF, 0xD1B5, 0x7941, 0xD1B6, 0x7947, + 0xD1B7, 0x7948, 0xD1B8, 0x797A, 0xD1B9, 0x7B95, 0xD1BA, 0x7D00, 0xD1BB, 0x7DBA, 0xD1BC, 0x7F88, 0xD1BD, 0x8006, 0xD1BE, 0x802D, + 0xD1BF, 0x808C, 0xD1C0, 0x8A18, 0xD1C1, 0x8B4F, 0xD1C2, 0x8C48, 0xD1C3, 0x8D77, 0xD1C4, 0x9321, 0xD1C5, 0x9324, 0xD1C6, 0x98E2, + 0xD1C7, 0x9951, 0xD1C8, 0x9A0E, 0xD1C9, 0x9A0F, 0xD1CA, 0x9A65, 0xD1CB, 0x9E92, 0xD1CC, 0x7DCA, 0xD1CD, 0x4F76, 0xD1CE, 0x5409, + 0xD1CF, 0x62EE, 0xD1D0, 0x6854, 0xD1D1, 0x91D1, 0xD1D2, 0x55AB, 0xD1D3, 0x513A, 0xD1D4, 0xF90B, 0xD1D5, 0xF90C, 0xD1D6, 0x5A1C, + 0xD1D7, 0x61E6, 0xD1D8, 0xF90D, 0xD1D9, 0x62CF, 0xD1DA, 0x62FF, 0xD1DB, 0xF90E, 0xD1DC, 0xF90F, 0xD1DD, 0xF910, 0xD1DE, 0xF911, + 0xD1DF, 0xF912, 0xD1E0, 0xF913, 0xD1E1, 0x90A3, 0xD1E2, 0xF914, 0xD1E3, 0xF915, 0xD1E4, 0xF916, 0xD1E5, 0xF917, 0xD1E6, 0xF918, + 0xD1E7, 0x8AFE, 0xD1E8, 0xF919, 0xD1E9, 0xF91A, 0xD1EA, 0xF91B, 0xD1EB, 0xF91C, 0xD1EC, 0x6696, 0xD1ED, 0xF91D, 0xD1EE, 0x7156, + 0xD1EF, 0xF91E, 0xD1F0, 0xF91F, 0xD1F1, 0x96E3, 0xD1F2, 0xF920, 0xD1F3, 0x634F, 0xD1F4, 0x637A, 0xD1F5, 0x5357, 0xD1F6, 0xF921, + 0xD1F7, 0x678F, 0xD1F8, 0x6960, 0xD1F9, 0x6E73, 0xD1FA, 0xF922, 0xD1FB, 0x7537, 0xD1FC, 0xF923, 0xD1FD, 0xF924, 0xD1FE, 0xF925, + 0xD2A1, 0x7D0D, 0xD2A2, 0xF926, 0xD2A3, 0xF927, 0xD2A4, 0x8872, 0xD2A5, 0x56CA, 0xD2A6, 0x5A18, 0xD2A7, 0xF928, 0xD2A8, 0xF929, + 0xD2A9, 0xF92A, 0xD2AA, 0xF92B, 0xD2AB, 0xF92C, 0xD2AC, 0x4E43, 0xD2AD, 0xF92D, 0xD2AE, 0x5167, 0xD2AF, 0x5948, 0xD2B0, 0x67F0, + 0xD2B1, 0x8010, 0xD2B2, 0xF92E, 0xD2B3, 0x5973, 0xD2B4, 0x5E74, 0xD2B5, 0x649A, 0xD2B6, 0x79CA, 0xD2B7, 0x5FF5, 0xD2B8, 0x606C, + 0xD2B9, 0x62C8, 0xD2BA, 0x637B, 0xD2BB, 0x5BE7, 0xD2BC, 0x5BD7, 0xD2BD, 0x52AA, 0xD2BE, 0xF92F, 0xD2BF, 0x5974, 0xD2C0, 0x5F29, + 0xD2C1, 0x6012, 0xD2C2, 0xF930, 0xD2C3, 0xF931, 0xD2C4, 0xF932, 0xD2C5, 0x7459, 0xD2C6, 0xF933, 0xD2C7, 0xF934, 0xD2C8, 0xF935, + 0xD2C9, 0xF936, 0xD2CA, 0xF937, 0xD2CB, 0xF938, 0xD2CC, 0x99D1, 0xD2CD, 0xF939, 0xD2CE, 0xF93A, 0xD2CF, 0xF93B, 0xD2D0, 0xF93C, + 0xD2D1, 0xF93D, 0xD2D2, 0xF93E, 0xD2D3, 0xF93F, 0xD2D4, 0xF940, 0xD2D5, 0xF941, 0xD2D6, 0xF942, 0xD2D7, 0xF943, 0xD2D8, 0x6FC3, + 0xD2D9, 0xF944, 0xD2DA, 0xF945, 0xD2DB, 0x81BF, 0xD2DC, 0x8FB2, 0xD2DD, 0x60F1, 0xD2DE, 0xF946, 0xD2DF, 0xF947, 0xD2E0, 0x8166, + 0xD2E1, 0xF948, 0xD2E2, 0xF949, 0xD2E3, 0x5C3F, 0xD2E4, 0xF94A, 0xD2E5, 0xF94B, 0xD2E6, 0xF94C, 0xD2E7, 0xF94D, 0xD2E8, 0xF94E, + 0xD2E9, 0xF94F, 0xD2EA, 0xF950, 0xD2EB, 0xF951, 0xD2EC, 0x5AE9, 0xD2ED, 0x8A25, 0xD2EE, 0x677B, 0xD2EF, 0x7D10, 0xD2F0, 0xF952, + 0xD2F1, 0xF953, 0xD2F2, 0xF954, 0xD2F3, 0xF955, 0xD2F4, 0xF956, 0xD2F5, 0xF957, 0xD2F6, 0x80FD, 0xD2F7, 0xF958, 0xD2F8, 0xF959, + 0xD2F9, 0x5C3C, 0xD2FA, 0x6CE5, 0xD2FB, 0x533F, 0xD2FC, 0x6EBA, 0xD2FD, 0x591A, 0xD2FE, 0x8336, 0xD3A1, 0x4E39, 0xD3A2, 0x4EB6, + 0xD3A3, 0x4F46, 0xD3A4, 0x55AE, 0xD3A5, 0x5718, 0xD3A6, 0x58C7, 0xD3A7, 0x5F56, 0xD3A8, 0x65B7, 0xD3A9, 0x65E6, 0xD3AA, 0x6A80, + 0xD3AB, 0x6BB5, 0xD3AC, 0x6E4D, 0xD3AD, 0x77ED, 0xD3AE, 0x7AEF, 0xD3AF, 0x7C1E, 0xD3B0, 0x7DDE, 0xD3B1, 0x86CB, 0xD3B2, 0x8892, + 0xD3B3, 0x9132, 0xD3B4, 0x935B, 0xD3B5, 0x64BB, 0xD3B6, 0x6FBE, 0xD3B7, 0x737A, 0xD3B8, 0x75B8, 0xD3B9, 0x9054, 0xD3BA, 0x5556, + 0xD3BB, 0x574D, 0xD3BC, 0x61BA, 0xD3BD, 0x64D4, 0xD3BE, 0x66C7, 0xD3BF, 0x6DE1, 0xD3C0, 0x6E5B, 0xD3C1, 0x6F6D, 0xD3C2, 0x6FB9, + 0xD3C3, 0x75F0, 0xD3C4, 0x8043, 0xD3C5, 0x81BD, 0xD3C6, 0x8541, 0xD3C7, 0x8983, 0xD3C8, 0x8AC7, 0xD3C9, 0x8B5A, 0xD3CA, 0x931F, + 0xD3CB, 0x6C93, 0xD3CC, 0x7553, 0xD3CD, 0x7B54, 0xD3CE, 0x8E0F, 0xD3CF, 0x905D, 0xD3D0, 0x5510, 0xD3D1, 0x5802, 0xD3D2, 0x5858, + 0xD3D3, 0x5E62, 0xD3D4, 0x6207, 0xD3D5, 0x649E, 0xD3D6, 0x68E0, 0xD3D7, 0x7576, 0xD3D8, 0x7CD6, 0xD3D9, 0x87B3, 0xD3DA, 0x9EE8, + 0xD3DB, 0x4EE3, 0xD3DC, 0x5788, 0xD3DD, 0x576E, 0xD3DE, 0x5927, 0xD3DF, 0x5C0D, 0xD3E0, 0x5CB1, 0xD3E1, 0x5E36, 0xD3E2, 0x5F85, + 0xD3E3, 0x6234, 0xD3E4, 0x64E1, 0xD3E5, 0x73B3, 0xD3E6, 0x81FA, 0xD3E7, 0x888B, 0xD3E8, 0x8CB8, 0xD3E9, 0x968A, 0xD3EA, 0x9EDB, + 0xD3EB, 0x5B85, 0xD3EC, 0x5FB7, 0xD3ED, 0x60B3, 0xD3EE, 0x5012, 0xD3EF, 0x5200, 0xD3F0, 0x5230, 0xD3F1, 0x5716, 0xD3F2, 0x5835, + 0xD3F3, 0x5857, 0xD3F4, 0x5C0E, 0xD3F5, 0x5C60, 0xD3F6, 0x5CF6, 0xD3F7, 0x5D8B, 0xD3F8, 0x5EA6, 0xD3F9, 0x5F92, 0xD3FA, 0x60BC, + 0xD3FB, 0x6311, 0xD3FC, 0x6389, 0xD3FD, 0x6417, 0xD3FE, 0x6843, 0xD4A1, 0x68F9, 0xD4A2, 0x6AC2, 0xD4A3, 0x6DD8, 0xD4A4, 0x6E21, + 0xD4A5, 0x6ED4, 0xD4A6, 0x6FE4, 0xD4A7, 0x71FE, 0xD4A8, 0x76DC, 0xD4A9, 0x7779, 0xD4AA, 0x79B1, 0xD4AB, 0x7A3B, 0xD4AC, 0x8404, + 0xD4AD, 0x89A9, 0xD4AE, 0x8CED, 0xD4AF, 0x8DF3, 0xD4B0, 0x8E48, 0xD4B1, 0x9003, 0xD4B2, 0x9014, 0xD4B3, 0x9053, 0xD4B4, 0x90FD, + 0xD4B5, 0x934D, 0xD4B6, 0x9676, 0xD4B7, 0x97DC, 0xD4B8, 0x6BD2, 0xD4B9, 0x7006, 0xD4BA, 0x7258, 0xD4BB, 0x72A2, 0xD4BC, 0x7368, + 0xD4BD, 0x7763, 0xD4BE, 0x79BF, 0xD4BF, 0x7BE4, 0xD4C0, 0x7E9B, 0xD4C1, 0x8B80, 0xD4C2, 0x58A9, 0xD4C3, 0x60C7, 0xD4C4, 0x6566, + 0xD4C5, 0x65FD, 0xD4C6, 0x66BE, 0xD4C7, 0x6C8C, 0xD4C8, 0x711E, 0xD4C9, 0x71C9, 0xD4CA, 0x8C5A, 0xD4CB, 0x9813, 0xD4CC, 0x4E6D, + 0xD4CD, 0x7A81, 0xD4CE, 0x4EDD, 0xD4CF, 0x51AC, 0xD4D0, 0x51CD, 0xD4D1, 0x52D5, 0xD4D2, 0x540C, 0xD4D3, 0x61A7, 0xD4D4, 0x6771, + 0xD4D5, 0x6850, 0xD4D6, 0x68DF, 0xD4D7, 0x6D1E, 0xD4D8, 0x6F7C, 0xD4D9, 0x75BC, 0xD4DA, 0x77B3, 0xD4DB, 0x7AE5, 0xD4DC, 0x80F4, + 0xD4DD, 0x8463, 0xD4DE, 0x9285, 0xD4DF, 0x515C, 0xD4E0, 0x6597, 0xD4E1, 0x675C, 0xD4E2, 0x6793, 0xD4E3, 0x75D8, 0xD4E4, 0x7AC7, + 0xD4E5, 0x8373, 0xD4E6, 0xF95A, 0xD4E7, 0x8C46, 0xD4E8, 0x9017, 0xD4E9, 0x982D, 0xD4EA, 0x5C6F, 0xD4EB, 0x81C0, 0xD4EC, 0x829A, + 0xD4ED, 0x9041, 0xD4EE, 0x906F, 0xD4EF, 0x920D, 0xD4F0, 0x5F97, 0xD4F1, 0x5D9D, 0xD4F2, 0x6A59, 0xD4F3, 0x71C8, 0xD4F4, 0x767B, + 0xD4F5, 0x7B49, 0xD4F6, 0x85E4, 0xD4F7, 0x8B04, 0xD4F8, 0x9127, 0xD4F9, 0x9A30, 0xD4FA, 0x5587, 0xD4FB, 0x61F6, 0xD4FC, 0xF95B, + 0xD4FD, 0x7669, 0xD4FE, 0x7F85, 0xD5A1, 0x863F, 0xD5A2, 0x87BA, 0xD5A3, 0x88F8, 0xD5A4, 0x908F, 0xD5A5, 0xF95C, 0xD5A6, 0x6D1B, + 0xD5A7, 0x70D9, 0xD5A8, 0x73DE, 0xD5A9, 0x7D61, 0xD5AA, 0x843D, 0xD5AB, 0xF95D, 0xD5AC, 0x916A, 0xD5AD, 0x99F1, 0xD5AE, 0xF95E, + 0xD5AF, 0x4E82, 0xD5B0, 0x5375, 0xD5B1, 0x6B04, 0xD5B2, 0x6B12, 0xD5B3, 0x703E, 0xD5B4, 0x721B, 0xD5B5, 0x862D, 0xD5B6, 0x9E1E, + 0xD5B7, 0x524C, 0xD5B8, 0x8FA3, 0xD5B9, 0x5D50, 0xD5BA, 0x64E5, 0xD5BB, 0x652C, 0xD5BC, 0x6B16, 0xD5BD, 0x6FEB, 0xD5BE, 0x7C43, + 0xD5BF, 0x7E9C, 0xD5C0, 0x85CD, 0xD5C1, 0x8964, 0xD5C2, 0x89BD, 0xD5C3, 0x62C9, 0xD5C4, 0x81D8, 0xD5C5, 0x881F, 0xD5C6, 0x5ECA, + 0xD5C7, 0x6717, 0xD5C8, 0x6D6A, 0xD5C9, 0x72FC, 0xD5CA, 0x7405, 0xD5CB, 0x746F, 0xD5CC, 0x8782, 0xD5CD, 0x90DE, 0xD5CE, 0x4F86, + 0xD5CF, 0x5D0D, 0xD5D0, 0x5FA0, 0xD5D1, 0x840A, 0xD5D2, 0x51B7, 0xD5D3, 0x63A0, 0xD5D4, 0x7565, 0xD5D5, 0x4EAE, 0xD5D6, 0x5006, + 0xD5D7, 0x5169, 0xD5D8, 0x51C9, 0xD5D9, 0x6881, 0xD5DA, 0x6A11, 0xD5DB, 0x7CAE, 0xD5DC, 0x7CB1, 0xD5DD, 0x7CE7, 0xD5DE, 0x826F, + 0xD5DF, 0x8AD2, 0xD5E0, 0x8F1B, 0xD5E1, 0x91CF, 0xD5E2, 0x4FB6, 0xD5E3, 0x5137, 0xD5E4, 0x52F5, 0xD5E5, 0x5442, 0xD5E6, 0x5EEC, + 0xD5E7, 0x616E, 0xD5E8, 0x623E, 0xD5E9, 0x65C5, 0xD5EA, 0x6ADA, 0xD5EB, 0x6FFE, 0xD5EC, 0x792A, 0xD5ED, 0x85DC, 0xD5EE, 0x8823, + 0xD5EF, 0x95AD, 0xD5F0, 0x9A62, 0xD5F1, 0x9A6A, 0xD5F2, 0x9E97, 0xD5F3, 0x9ECE, 0xD5F4, 0x529B, 0xD5F5, 0x66C6, 0xD5F6, 0x6B77, + 0xD5F7, 0x701D, 0xD5F8, 0x792B, 0xD5F9, 0x8F62, 0xD5FA, 0x9742, 0xD5FB, 0x6190, 0xD5FC, 0x6200, 0xD5FD, 0x6523, 0xD5FE, 0x6F23, + 0xD6A1, 0x7149, 0xD6A2, 0x7489, 0xD6A3, 0x7DF4, 0xD6A4, 0x806F, 0xD6A5, 0x84EE, 0xD6A6, 0x8F26, 0xD6A7, 0x9023, 0xD6A8, 0x934A, + 0xD6A9, 0x51BD, 0xD6AA, 0x5217, 0xD6AB, 0x52A3, 0xD6AC, 0x6D0C, 0xD6AD, 0x70C8, 0xD6AE, 0x88C2, 0xD6AF, 0x5EC9, 0xD6B0, 0x6582, + 0xD6B1, 0x6BAE, 0xD6B2, 0x6FC2, 0xD6B3, 0x7C3E, 0xD6B4, 0x7375, 0xD6B5, 0x4EE4, 0xD6B6, 0x4F36, 0xD6B7, 0x56F9, 0xD6B8, 0xF95F, + 0xD6B9, 0x5CBA, 0xD6BA, 0x5DBA, 0xD6BB, 0x601C, 0xD6BC, 0x73B2, 0xD6BD, 0x7B2D, 0xD6BE, 0x7F9A, 0xD6BF, 0x7FCE, 0xD6C0, 0x8046, + 0xD6C1, 0x901E, 0xD6C2, 0x9234, 0xD6C3, 0x96F6, 0xD6C4, 0x9748, 0xD6C5, 0x9818, 0xD6C6, 0x9F61, 0xD6C7, 0x4F8B, 0xD6C8, 0x6FA7, + 0xD6C9, 0x79AE, 0xD6CA, 0x91B4, 0xD6CB, 0x96B7, 0xD6CC, 0x52DE, 0xD6CD, 0xF960, 0xD6CE, 0x6488, 0xD6CF, 0x64C4, 0xD6D0, 0x6AD3, + 0xD6D1, 0x6F5E, 0xD6D2, 0x7018, 0xD6D3, 0x7210, 0xD6D4, 0x76E7, 0xD6D5, 0x8001, 0xD6D6, 0x8606, 0xD6D7, 0x865C, 0xD6D8, 0x8DEF, + 0xD6D9, 0x8F05, 0xD6DA, 0x9732, 0xD6DB, 0x9B6F, 0xD6DC, 0x9DFA, 0xD6DD, 0x9E75, 0xD6DE, 0x788C, 0xD6DF, 0x797F, 0xD6E0, 0x7DA0, + 0xD6E1, 0x83C9, 0xD6E2, 0x9304, 0xD6E3, 0x9E7F, 0xD6E4, 0x9E93, 0xD6E5, 0x8AD6, 0xD6E6, 0x58DF, 0xD6E7, 0x5F04, 0xD6E8, 0x6727, + 0xD6E9, 0x7027, 0xD6EA, 0x74CF, 0xD6EB, 0x7C60, 0xD6EC, 0x807E, 0xD6ED, 0x5121, 0xD6EE, 0x7028, 0xD6EF, 0x7262, 0xD6F0, 0x78CA, + 0xD6F1, 0x8CC2, 0xD6F2, 0x8CDA, 0xD6F3, 0x8CF4, 0xD6F4, 0x96F7, 0xD6F5, 0x4E86, 0xD6F6, 0x50DA, 0xD6F7, 0x5BEE, 0xD6F8, 0x5ED6, + 0xD6F9, 0x6599, 0xD6FA, 0x71CE, 0xD6FB, 0x7642, 0xD6FC, 0x77AD, 0xD6FD, 0x804A, 0xD6FE, 0x84FC, 0xD7A1, 0x907C, 0xD7A2, 0x9B27, + 0xD7A3, 0x9F8D, 0xD7A4, 0x58D8, 0xD7A5, 0x5A41, 0xD7A6, 0x5C62, 0xD7A7, 0x6A13, 0xD7A8, 0x6DDA, 0xD7A9, 0x6F0F, 0xD7AA, 0x763B, + 0xD7AB, 0x7D2F, 0xD7AC, 0x7E37, 0xD7AD, 0x851E, 0xD7AE, 0x8938, 0xD7AF, 0x93E4, 0xD7B0, 0x964B, 0xD7B1, 0x5289, 0xD7B2, 0x65D2, + 0xD7B3, 0x67F3, 0xD7B4, 0x69B4, 0xD7B5, 0x6D41, 0xD7B6, 0x6E9C, 0xD7B7, 0x700F, 0xD7B8, 0x7409, 0xD7B9, 0x7460, 0xD7BA, 0x7559, + 0xD7BB, 0x7624, 0xD7BC, 0x786B, 0xD7BD, 0x8B2C, 0xD7BE, 0x985E, 0xD7BF, 0x516D, 0xD7C0, 0x622E, 0xD7C1, 0x9678, 0xD7C2, 0x4F96, + 0xD7C3, 0x502B, 0xD7C4, 0x5D19, 0xD7C5, 0x6DEA, 0xD7C6, 0x7DB8, 0xD7C7, 0x8F2A, 0xD7C8, 0x5F8B, 0xD7C9, 0x6144, 0xD7CA, 0x6817, + 0xD7CB, 0xF961, 0xD7CC, 0x9686, 0xD7CD, 0x52D2, 0xD7CE, 0x808B, 0xD7CF, 0x51DC, 0xD7D0, 0x51CC, 0xD7D1, 0x695E, 0xD7D2, 0x7A1C, + 0xD7D3, 0x7DBE, 0xD7D4, 0x83F1, 0xD7D5, 0x9675, 0xD7D6, 0x4FDA, 0xD7D7, 0x5229, 0xD7D8, 0x5398, 0xD7D9, 0x540F, 0xD7DA, 0x550E, + 0xD7DB, 0x5C65, 0xD7DC, 0x60A7, 0xD7DD, 0x674E, 0xD7DE, 0x68A8, 0xD7DF, 0x6D6C, 0xD7E0, 0x7281, 0xD7E1, 0x72F8, 0xD7E2, 0x7406, + 0xD7E3, 0x7483, 0xD7E4, 0xF962, 0xD7E5, 0x75E2, 0xD7E6, 0x7C6C, 0xD7E7, 0x7F79, 0xD7E8, 0x7FB8, 0xD7E9, 0x8389, 0xD7EA, 0x88CF, + 0xD7EB, 0x88E1, 0xD7EC, 0x91CC, 0xD7ED, 0x91D0, 0xD7EE, 0x96E2, 0xD7EF, 0x9BC9, 0xD7F0, 0x541D, 0xD7F1, 0x6F7E, 0xD7F2, 0x71D0, + 0xD7F3, 0x7498, 0xD7F4, 0x85FA, 0xD7F5, 0x8EAA, 0xD7F6, 0x96A3, 0xD7F7, 0x9C57, 0xD7F8, 0x9E9F, 0xD7F9, 0x6797, 0xD7FA, 0x6DCB, + 0xD7FB, 0x7433, 0xD7FC, 0x81E8, 0xD7FD, 0x9716, 0xD7FE, 0x782C, 0xD8A1, 0x7ACB, 0xD8A2, 0x7B20, 0xD8A3, 0x7C92, 0xD8A4, 0x6469, + 0xD8A5, 0x746A, 0xD8A6, 0x75F2, 0xD8A7, 0x78BC, 0xD8A8, 0x78E8, 0xD8A9, 0x99AC, 0xD8AA, 0x9B54, 0xD8AB, 0x9EBB, 0xD8AC, 0x5BDE, + 0xD8AD, 0x5E55, 0xD8AE, 0x6F20, 0xD8AF, 0x819C, 0xD8B0, 0x83AB, 0xD8B1, 0x9088, 0xD8B2, 0x4E07, 0xD8B3, 0x534D, 0xD8B4, 0x5A29, + 0xD8B5, 0x5DD2, 0xD8B6, 0x5F4E, 0xD8B7, 0x6162, 0xD8B8, 0x633D, 0xD8B9, 0x6669, 0xD8BA, 0x66FC, 0xD8BB, 0x6EFF, 0xD8BC, 0x6F2B, + 0xD8BD, 0x7063, 0xD8BE, 0x779E, 0xD8BF, 0x842C, 0xD8C0, 0x8513, 0xD8C1, 0x883B, 0xD8C2, 0x8F13, 0xD8C3, 0x9945, 0xD8C4, 0x9C3B, + 0xD8C5, 0x551C, 0xD8C6, 0x62B9, 0xD8C7, 0x672B, 0xD8C8, 0x6CAB, 0xD8C9, 0x8309, 0xD8CA, 0x896A, 0xD8CB, 0x977A, 0xD8CC, 0x4EA1, + 0xD8CD, 0x5984, 0xD8CE, 0x5FD8, 0xD8CF, 0x5FD9, 0xD8D0, 0x671B, 0xD8D1, 0x7DB2, 0xD8D2, 0x7F54, 0xD8D3, 0x8292, 0xD8D4, 0x832B, + 0xD8D5, 0x83BD, 0xD8D6, 0x8F1E, 0xD8D7, 0x9099, 0xD8D8, 0x57CB, 0xD8D9, 0x59B9, 0xD8DA, 0x5A92, 0xD8DB, 0x5BD0, 0xD8DC, 0x6627, + 0xD8DD, 0x679A, 0xD8DE, 0x6885, 0xD8DF, 0x6BCF, 0xD8E0, 0x7164, 0xD8E1, 0x7F75, 0xD8E2, 0x8CB7, 0xD8E3, 0x8CE3, 0xD8E4, 0x9081, + 0xD8E5, 0x9B45, 0xD8E6, 0x8108, 0xD8E7, 0x8C8A, 0xD8E8, 0x964C, 0xD8E9, 0x9A40, 0xD8EA, 0x9EA5, 0xD8EB, 0x5B5F, 0xD8EC, 0x6C13, + 0xD8ED, 0x731B, 0xD8EE, 0x76F2, 0xD8EF, 0x76DF, 0xD8F0, 0x840C, 0xD8F1, 0x51AA, 0xD8F2, 0x8993, 0xD8F3, 0x514D, 0xD8F4, 0x5195, + 0xD8F5, 0x52C9, 0xD8F6, 0x68C9, 0xD8F7, 0x6C94, 0xD8F8, 0x7704, 0xD8F9, 0x7720, 0xD8FA, 0x7DBF, 0xD8FB, 0x7DEC, 0xD8FC, 0x9762, + 0xD8FD, 0x9EB5, 0xD8FE, 0x6EC5, 0xD9A1, 0x8511, 0xD9A2, 0x51A5, 0xD9A3, 0x540D, 0xD9A4, 0x547D, 0xD9A5, 0x660E, 0xD9A6, 0x669D, + 0xD9A7, 0x6927, 0xD9A8, 0x6E9F, 0xD9A9, 0x76BF, 0xD9AA, 0x7791, 0xD9AB, 0x8317, 0xD9AC, 0x84C2, 0xD9AD, 0x879F, 0xD9AE, 0x9169, + 0xD9AF, 0x9298, 0xD9B0, 0x9CF4, 0xD9B1, 0x8882, 0xD9B2, 0x4FAE, 0xD9B3, 0x5192, 0xD9B4, 0x52DF, 0xD9B5, 0x59C6, 0xD9B6, 0x5E3D, + 0xD9B7, 0x6155, 0xD9B8, 0x6478, 0xD9B9, 0x6479, 0xD9BA, 0x66AE, 0xD9BB, 0x67D0, 0xD9BC, 0x6A21, 0xD9BD, 0x6BCD, 0xD9BE, 0x6BDB, + 0xD9BF, 0x725F, 0xD9C0, 0x7261, 0xD9C1, 0x7441, 0xD9C2, 0x7738, 0xD9C3, 0x77DB, 0xD9C4, 0x8017, 0xD9C5, 0x82BC, 0xD9C6, 0x8305, + 0xD9C7, 0x8B00, 0xD9C8, 0x8B28, 0xD9C9, 0x8C8C, 0xD9CA, 0x6728, 0xD9CB, 0x6C90, 0xD9CC, 0x7267, 0xD9CD, 0x76EE, 0xD9CE, 0x7766, + 0xD9CF, 0x7A46, 0xD9D0, 0x9DA9, 0xD9D1, 0x6B7F, 0xD9D2, 0x6C92, 0xD9D3, 0x5922, 0xD9D4, 0x6726, 0xD9D5, 0x8499, 0xD9D6, 0x536F, + 0xD9D7, 0x5893, 0xD9D8, 0x5999, 0xD9D9, 0x5EDF, 0xD9DA, 0x63CF, 0xD9DB, 0x6634, 0xD9DC, 0x6773, 0xD9DD, 0x6E3A, 0xD9DE, 0x732B, + 0xD9DF, 0x7AD7, 0xD9E0, 0x82D7, 0xD9E1, 0x9328, 0xD9E2, 0x52D9, 0xD9E3, 0x5DEB, 0xD9E4, 0x61AE, 0xD9E5, 0x61CB, 0xD9E6, 0x620A, + 0xD9E7, 0x62C7, 0xD9E8, 0x64AB, 0xD9E9, 0x65E0, 0xD9EA, 0x6959, 0xD9EB, 0x6B66, 0xD9EC, 0x6BCB, 0xD9ED, 0x7121, 0xD9EE, 0x73F7, + 0xD9EF, 0x755D, 0xD9F0, 0x7E46, 0xD9F1, 0x821E, 0xD9F2, 0x8302, 0xD9F3, 0x856A, 0xD9F4, 0x8AA3, 0xD9F5, 0x8CBF, 0xD9F6, 0x9727, + 0xD9F7, 0x9D61, 0xD9F8, 0x58A8, 0xD9F9, 0x9ED8, 0xD9FA, 0x5011, 0xD9FB, 0x520E, 0xD9FC, 0x543B, 0xD9FD, 0x554F, 0xD9FE, 0x6587, + 0xDAA1, 0x6C76, 0xDAA2, 0x7D0A, 0xDAA3, 0x7D0B, 0xDAA4, 0x805E, 0xDAA5, 0x868A, 0xDAA6, 0x9580, 0xDAA7, 0x96EF, 0xDAA8, 0x52FF, + 0xDAA9, 0x6C95, 0xDAAA, 0x7269, 0xDAAB, 0x5473, 0xDAAC, 0x5A9A, 0xDAAD, 0x5C3E, 0xDAAE, 0x5D4B, 0xDAAF, 0x5F4C, 0xDAB0, 0x5FAE, + 0xDAB1, 0x672A, 0xDAB2, 0x68B6, 0xDAB3, 0x6963, 0xDAB4, 0x6E3C, 0xDAB5, 0x6E44, 0xDAB6, 0x7709, 0xDAB7, 0x7C73, 0xDAB8, 0x7F8E, + 0xDAB9, 0x8587, 0xDABA, 0x8B0E, 0xDABB, 0x8FF7, 0xDABC, 0x9761, 0xDABD, 0x9EF4, 0xDABE, 0x5CB7, 0xDABF, 0x60B6, 0xDAC0, 0x610D, + 0xDAC1, 0x61AB, 0xDAC2, 0x654F, 0xDAC3, 0x65FB, 0xDAC4, 0x65FC, 0xDAC5, 0x6C11, 0xDAC6, 0x6CEF, 0xDAC7, 0x739F, 0xDAC8, 0x73C9, + 0xDAC9, 0x7DE1, 0xDACA, 0x9594, 0xDACB, 0x5BC6, 0xDACC, 0x871C, 0xDACD, 0x8B10, 0xDACE, 0x525D, 0xDACF, 0x535A, 0xDAD0, 0x62CD, + 0xDAD1, 0x640F, 0xDAD2, 0x64B2, 0xDAD3, 0x6734, 0xDAD4, 0x6A38, 0xDAD5, 0x6CCA, 0xDAD6, 0x73C0, 0xDAD7, 0x749E, 0xDAD8, 0x7B94, + 0xDAD9, 0x7C95, 0xDADA, 0x7E1B, 0xDADB, 0x818A, 0xDADC, 0x8236, 0xDADD, 0x8584, 0xDADE, 0x8FEB, 0xDADF, 0x96F9, 0xDAE0, 0x99C1, + 0xDAE1, 0x4F34, 0xDAE2, 0x534A, 0xDAE3, 0x53CD, 0xDAE4, 0x53DB, 0xDAE5, 0x62CC, 0xDAE6, 0x642C, 0xDAE7, 0x6500, 0xDAE8, 0x6591, + 0xDAE9, 0x69C3, 0xDAEA, 0x6CEE, 0xDAEB, 0x6F58, 0xDAEC, 0x73ED, 0xDAED, 0x7554, 0xDAEE, 0x7622, 0xDAEF, 0x76E4, 0xDAF0, 0x76FC, + 0xDAF1, 0x78D0, 0xDAF2, 0x78FB, 0xDAF3, 0x792C, 0xDAF4, 0x7D46, 0xDAF5, 0x822C, 0xDAF6, 0x87E0, 0xDAF7, 0x8FD4, 0xDAF8, 0x9812, + 0xDAF9, 0x98EF, 0xDAFA, 0x52C3, 0xDAFB, 0x62D4, 0xDAFC, 0x64A5, 0xDAFD, 0x6E24, 0xDAFE, 0x6F51, 0xDBA1, 0x767C, 0xDBA2, 0x8DCB, + 0xDBA3, 0x91B1, 0xDBA4, 0x9262, 0xDBA5, 0x9AEE, 0xDBA6, 0x9B43, 0xDBA7, 0x5023, 0xDBA8, 0x508D, 0xDBA9, 0x574A, 0xDBAA, 0x59A8, + 0xDBAB, 0x5C28, 0xDBAC, 0x5E47, 0xDBAD, 0x5F77, 0xDBAE, 0x623F, 0xDBAF, 0x653E, 0xDBB0, 0x65B9, 0xDBB1, 0x65C1, 0xDBB2, 0x6609, + 0xDBB3, 0x678B, 0xDBB4, 0x699C, 0xDBB5, 0x6EC2, 0xDBB6, 0x78C5, 0xDBB7, 0x7D21, 0xDBB8, 0x80AA, 0xDBB9, 0x8180, 0xDBBA, 0x822B, + 0xDBBB, 0x82B3, 0xDBBC, 0x84A1, 0xDBBD, 0x868C, 0xDBBE, 0x8A2A, 0xDBBF, 0x8B17, 0xDBC0, 0x90A6, 0xDBC1, 0x9632, 0xDBC2, 0x9F90, + 0xDBC3, 0x500D, 0xDBC4, 0x4FF3, 0xDBC5, 0xF963, 0xDBC6, 0x57F9, 0xDBC7, 0x5F98, 0xDBC8, 0x62DC, 0xDBC9, 0x6392, 0xDBCA, 0x676F, + 0xDBCB, 0x6E43, 0xDBCC, 0x7119, 0xDBCD, 0x76C3, 0xDBCE, 0x80CC, 0xDBCF, 0x80DA, 0xDBD0, 0x88F4, 0xDBD1, 0x88F5, 0xDBD2, 0x8919, + 0xDBD3, 0x8CE0, 0xDBD4, 0x8F29, 0xDBD5, 0x914D, 0xDBD6, 0x966A, 0xDBD7, 0x4F2F, 0xDBD8, 0x4F70, 0xDBD9, 0x5E1B, 0xDBDA, 0x67CF, + 0xDBDB, 0x6822, 0xDBDC, 0x767D, 0xDBDD, 0x767E, 0xDBDE, 0x9B44, 0xDBDF, 0x5E61, 0xDBE0, 0x6A0A, 0xDBE1, 0x7169, 0xDBE2, 0x71D4, + 0xDBE3, 0x756A, 0xDBE4, 0xF964, 0xDBE5, 0x7E41, 0xDBE6, 0x8543, 0xDBE7, 0x85E9, 0xDBE8, 0x98DC, 0xDBE9, 0x4F10, 0xDBEA, 0x7B4F, + 0xDBEB, 0x7F70, 0xDBEC, 0x95A5, 0xDBED, 0x51E1, 0xDBEE, 0x5E06, 0xDBEF, 0x68B5, 0xDBF0, 0x6C3E, 0xDBF1, 0x6C4E, 0xDBF2, 0x6CDB, + 0xDBF3, 0x72AF, 0xDBF4, 0x7BC4, 0xDBF5, 0x8303, 0xDBF6, 0x6CD5, 0xDBF7, 0x743A, 0xDBF8, 0x50FB, 0xDBF9, 0x5288, 0xDBFA, 0x58C1, + 0xDBFB, 0x64D8, 0xDBFC, 0x6A97, 0xDBFD, 0x74A7, 0xDBFE, 0x7656, 0xDCA1, 0x78A7, 0xDCA2, 0x8617, 0xDCA3, 0x95E2, 0xDCA4, 0x9739, + 0xDCA5, 0xF965, 0xDCA6, 0x535E, 0xDCA7, 0x5F01, 0xDCA8, 0x8B8A, 0xDCA9, 0x8FA8, 0xDCAA, 0x8FAF, 0xDCAB, 0x908A, 0xDCAC, 0x5225, + 0xDCAD, 0x77A5, 0xDCAE, 0x9C49, 0xDCAF, 0x9F08, 0xDCB0, 0x4E19, 0xDCB1, 0x5002, 0xDCB2, 0x5175, 0xDCB3, 0x5C5B, 0xDCB4, 0x5E77, + 0xDCB5, 0x661E, 0xDCB6, 0x663A, 0xDCB7, 0x67C4, 0xDCB8, 0x68C5, 0xDCB9, 0x70B3, 0xDCBA, 0x7501, 0xDCBB, 0x75C5, 0xDCBC, 0x79C9, + 0xDCBD, 0x7ADD, 0xDCBE, 0x8F27, 0xDCBF, 0x9920, 0xDCC0, 0x9A08, 0xDCC1, 0x4FDD, 0xDCC2, 0x5821, 0xDCC3, 0x5831, 0xDCC4, 0x5BF6, + 0xDCC5, 0x666E, 0xDCC6, 0x6B65, 0xDCC7, 0x6D11, 0xDCC8, 0x6E7A, 0xDCC9, 0x6F7D, 0xDCCA, 0x73E4, 0xDCCB, 0x752B, 0xDCCC, 0x83E9, + 0xDCCD, 0x88DC, 0xDCCE, 0x8913, 0xDCCF, 0x8B5C, 0xDCD0, 0x8F14, 0xDCD1, 0x4F0F, 0xDCD2, 0x50D5, 0xDCD3, 0x5310, 0xDCD4, 0x535C, + 0xDCD5, 0x5B93, 0xDCD6, 0x5FA9, 0xDCD7, 0x670D, 0xDCD8, 0x798F, 0xDCD9, 0x8179, 0xDCDA, 0x832F, 0xDCDB, 0x8514, 0xDCDC, 0x8907, + 0xDCDD, 0x8986, 0xDCDE, 0x8F39, 0xDCDF, 0x8F3B, 0xDCE0, 0x99A5, 0xDCE1, 0x9C12, 0xDCE2, 0x672C, 0xDCE3, 0x4E76, 0xDCE4, 0x4FF8, + 0xDCE5, 0x5949, 0xDCE6, 0x5C01, 0xDCE7, 0x5CEF, 0xDCE8, 0x5CF0, 0xDCE9, 0x6367, 0xDCEA, 0x68D2, 0xDCEB, 0x70FD, 0xDCEC, 0x71A2, + 0xDCED, 0x742B, 0xDCEE, 0x7E2B, 0xDCEF, 0x84EC, 0xDCF0, 0x8702, 0xDCF1, 0x9022, 0xDCF2, 0x92D2, 0xDCF3, 0x9CF3, 0xDCF4, 0x4E0D, + 0xDCF5, 0x4ED8, 0xDCF6, 0x4FEF, 0xDCF7, 0x5085, 0xDCF8, 0x5256, 0xDCF9, 0x526F, 0xDCFA, 0x5426, 0xDCFB, 0x5490, 0xDCFC, 0x57E0, + 0xDCFD, 0x592B, 0xDCFE, 0x5A66, 0xDDA1, 0x5B5A, 0xDDA2, 0x5B75, 0xDDA3, 0x5BCC, 0xDDA4, 0x5E9C, 0xDDA5, 0xF966, 0xDDA6, 0x6276, + 0xDDA7, 0x6577, 0xDDA8, 0x65A7, 0xDDA9, 0x6D6E, 0xDDAA, 0x6EA5, 0xDDAB, 0x7236, 0xDDAC, 0x7B26, 0xDDAD, 0x7C3F, 0xDDAE, 0x7F36, + 0xDDAF, 0x8150, 0xDDB0, 0x8151, 0xDDB1, 0x819A, 0xDDB2, 0x8240, 0xDDB3, 0x8299, 0xDDB4, 0x83A9, 0xDDB5, 0x8A03, 0xDDB6, 0x8CA0, + 0xDDB7, 0x8CE6, 0xDDB8, 0x8CFB, 0xDDB9, 0x8D74, 0xDDBA, 0x8DBA, 0xDDBB, 0x90E8, 0xDDBC, 0x91DC, 0xDDBD, 0x961C, 0xDDBE, 0x9644, + 0xDDBF, 0x99D9, 0xDDC0, 0x9CE7, 0xDDC1, 0x5317, 0xDDC2, 0x5206, 0xDDC3, 0x5429, 0xDDC4, 0x5674, 0xDDC5, 0x58B3, 0xDDC6, 0x5954, + 0xDDC7, 0x596E, 0xDDC8, 0x5FFF, 0xDDC9, 0x61A4, 0xDDCA, 0x626E, 0xDDCB, 0x6610, 0xDDCC, 0x6C7E, 0xDDCD, 0x711A, 0xDDCE, 0x76C6, + 0xDDCF, 0x7C89, 0xDDD0, 0x7CDE, 0xDDD1, 0x7D1B, 0xDDD2, 0x82AC, 0xDDD3, 0x8CC1, 0xDDD4, 0x96F0, 0xDDD5, 0xF967, 0xDDD6, 0x4F5B, + 0xDDD7, 0x5F17, 0xDDD8, 0x5F7F, 0xDDD9, 0x62C2, 0xDDDA, 0x5D29, 0xDDDB, 0x670B, 0xDDDC, 0x68DA, 0xDDDD, 0x787C, 0xDDDE, 0x7E43, + 0xDDDF, 0x9D6C, 0xDDE0, 0x4E15, 0xDDE1, 0x5099, 0xDDE2, 0x5315, 0xDDE3, 0x532A, 0xDDE4, 0x5351, 0xDDE5, 0x5983, 0xDDE6, 0x5A62, + 0xDDE7, 0x5E87, 0xDDE8, 0x60B2, 0xDDE9, 0x618A, 0xDDEA, 0x6249, 0xDDEB, 0x6279, 0xDDEC, 0x6590, 0xDDED, 0x6787, 0xDDEE, 0x69A7, + 0xDDEF, 0x6BD4, 0xDDF0, 0x6BD6, 0xDDF1, 0x6BD7, 0xDDF2, 0x6BD8, 0xDDF3, 0x6CB8, 0xDDF4, 0xF968, 0xDDF5, 0x7435, 0xDDF6, 0x75FA, + 0xDDF7, 0x7812, 0xDDF8, 0x7891, 0xDDF9, 0x79D5, 0xDDFA, 0x79D8, 0xDDFB, 0x7C83, 0xDDFC, 0x7DCB, 0xDDFD, 0x7FE1, 0xDDFE, 0x80A5, + 0xDEA1, 0x813E, 0xDEA2, 0x81C2, 0xDEA3, 0x83F2, 0xDEA4, 0x871A, 0xDEA5, 0x88E8, 0xDEA6, 0x8AB9, 0xDEA7, 0x8B6C, 0xDEA8, 0x8CBB, + 0xDEA9, 0x9119, 0xDEAA, 0x975E, 0xDEAB, 0x98DB, 0xDEAC, 0x9F3B, 0xDEAD, 0x56AC, 0xDEAE, 0x5B2A, 0xDEAF, 0x5F6C, 0xDEB0, 0x658C, + 0xDEB1, 0x6AB3, 0xDEB2, 0x6BAF, 0xDEB3, 0x6D5C, 0xDEB4, 0x6FF1, 0xDEB5, 0x7015, 0xDEB6, 0x725D, 0xDEB7, 0x73AD, 0xDEB8, 0x8CA7, + 0xDEB9, 0x8CD3, 0xDEBA, 0x983B, 0xDEBB, 0x6191, 0xDEBC, 0x6C37, 0xDEBD, 0x8058, 0xDEBE, 0x9A01, 0xDEBF, 0x4E4D, 0xDEC0, 0x4E8B, + 0xDEC1, 0x4E9B, 0xDEC2, 0x4ED5, 0xDEC3, 0x4F3A, 0xDEC4, 0x4F3C, 0xDEC5, 0x4F7F, 0xDEC6, 0x4FDF, 0xDEC7, 0x50FF, 0xDEC8, 0x53F2, + 0xDEC9, 0x53F8, 0xDECA, 0x5506, 0xDECB, 0x55E3, 0xDECC, 0x56DB, 0xDECD, 0x58EB, 0xDECE, 0x5962, 0xDECF, 0x5A11, 0xDED0, 0x5BEB, + 0xDED1, 0x5BFA, 0xDED2, 0x5C04, 0xDED3, 0x5DF3, 0xDED4, 0x5E2B, 0xDED5, 0x5F99, 0xDED6, 0x601D, 0xDED7, 0x6368, 0xDED8, 0x659C, + 0xDED9, 0x65AF, 0xDEDA, 0x67F6, 0xDEDB, 0x67FB, 0xDEDC, 0x68AD, 0xDEDD, 0x6B7B, 0xDEDE, 0x6C99, 0xDEDF, 0x6CD7, 0xDEE0, 0x6E23, + 0xDEE1, 0x7009, 0xDEE2, 0x7345, 0xDEE3, 0x7802, 0xDEE4, 0x793E, 0xDEE5, 0x7940, 0xDEE6, 0x7960, 0xDEE7, 0x79C1, 0xDEE8, 0x7BE9, + 0xDEE9, 0x7D17, 0xDEEA, 0x7D72, 0xDEEB, 0x8086, 0xDEEC, 0x820D, 0xDEED, 0x838E, 0xDEEE, 0x84D1, 0xDEEF, 0x86C7, 0xDEF0, 0x88DF, + 0xDEF1, 0x8A50, 0xDEF2, 0x8A5E, 0xDEF3, 0x8B1D, 0xDEF4, 0x8CDC, 0xDEF5, 0x8D66, 0xDEF6, 0x8FAD, 0xDEF7, 0x90AA, 0xDEF8, 0x98FC, + 0xDEF9, 0x99DF, 0xDEFA, 0x9E9D, 0xDEFB, 0x524A, 0xDEFC, 0xF969, 0xDEFD, 0x6714, 0xDEFE, 0xF96A, 0xDFA1, 0x5098, 0xDFA2, 0x522A, + 0xDFA3, 0x5C71, 0xDFA4, 0x6563, 0xDFA5, 0x6C55, 0xDFA6, 0x73CA, 0xDFA7, 0x7523, 0xDFA8, 0x759D, 0xDFA9, 0x7B97, 0xDFAA, 0x849C, + 0xDFAB, 0x9178, 0xDFAC, 0x9730, 0xDFAD, 0x4E77, 0xDFAE, 0x6492, 0xDFAF, 0x6BBA, 0xDFB0, 0x715E, 0xDFB1, 0x85A9, 0xDFB2, 0x4E09, + 0xDFB3, 0xF96B, 0xDFB4, 0x6749, 0xDFB5, 0x68EE, 0xDFB6, 0x6E17, 0xDFB7, 0x829F, 0xDFB8, 0x8518, 0xDFB9, 0x886B, 0xDFBA, 0x63F7, + 0xDFBB, 0x6F81, 0xDFBC, 0x9212, 0xDFBD, 0x98AF, 0xDFBE, 0x4E0A, 0xDFBF, 0x50B7, 0xDFC0, 0x50CF, 0xDFC1, 0x511F, 0xDFC2, 0x5546, + 0xDFC3, 0x55AA, 0xDFC4, 0x5617, 0xDFC5, 0x5B40, 0xDFC6, 0x5C19, 0xDFC7, 0x5CE0, 0xDFC8, 0x5E38, 0xDFC9, 0x5E8A, 0xDFCA, 0x5EA0, + 0xDFCB, 0x5EC2, 0xDFCC, 0x60F3, 0xDFCD, 0x6851, 0xDFCE, 0x6A61, 0xDFCF, 0x6E58, 0xDFD0, 0x723D, 0xDFD1, 0x7240, 0xDFD2, 0x72C0, + 0xDFD3, 0x76F8, 0xDFD4, 0x7965, 0xDFD5, 0x7BB1, 0xDFD6, 0x7FD4, 0xDFD7, 0x88F3, 0xDFD8, 0x89F4, 0xDFD9, 0x8A73, 0xDFDA, 0x8C61, + 0xDFDB, 0x8CDE, 0xDFDC, 0x971C, 0xDFDD, 0x585E, 0xDFDE, 0x74BD, 0xDFDF, 0x8CFD, 0xDFE0, 0x55C7, 0xDFE1, 0xF96C, 0xDFE2, 0x7A61, + 0xDFE3, 0x7D22, 0xDFE4, 0x8272, 0xDFE5, 0x7272, 0xDFE6, 0x751F, 0xDFE7, 0x7525, 0xDFE8, 0xF96D, 0xDFE9, 0x7B19, 0xDFEA, 0x5885, + 0xDFEB, 0x58FB, 0xDFEC, 0x5DBC, 0xDFED, 0x5E8F, 0xDFEE, 0x5EB6, 0xDFEF, 0x5F90, 0xDFF0, 0x6055, 0xDFF1, 0x6292, 0xDFF2, 0x637F, + 0xDFF3, 0x654D, 0xDFF4, 0x6691, 0xDFF5, 0x66D9, 0xDFF6, 0x66F8, 0xDFF7, 0x6816, 0xDFF8, 0x68F2, 0xDFF9, 0x7280, 0xDFFA, 0x745E, + 0xDFFB, 0x7B6E, 0xDFFC, 0x7D6E, 0xDFFD, 0x7DD6, 0xDFFE, 0x7F72, 0xE0A1, 0x80E5, 0xE0A2, 0x8212, 0xE0A3, 0x85AF, 0xE0A4, 0x897F, + 0xE0A5, 0x8A93, 0xE0A6, 0x901D, 0xE0A7, 0x92E4, 0xE0A8, 0x9ECD, 0xE0A9, 0x9F20, 0xE0AA, 0x5915, 0xE0AB, 0x596D, 0xE0AC, 0x5E2D, + 0xE0AD, 0x60DC, 0xE0AE, 0x6614, 0xE0AF, 0x6673, 0xE0B0, 0x6790, 0xE0B1, 0x6C50, 0xE0B2, 0x6DC5, 0xE0B3, 0x6F5F, 0xE0B4, 0x77F3, + 0xE0B5, 0x78A9, 0xE0B6, 0x84C6, 0xE0B7, 0x91CB, 0xE0B8, 0x932B, 0xE0B9, 0x4ED9, 0xE0BA, 0x50CA, 0xE0BB, 0x5148, 0xE0BC, 0x5584, + 0xE0BD, 0x5B0B, 0xE0BE, 0x5BA3, 0xE0BF, 0x6247, 0xE0C0, 0x657E, 0xE0C1, 0x65CB, 0xE0C2, 0x6E32, 0xE0C3, 0x717D, 0xE0C4, 0x7401, + 0xE0C5, 0x7444, 0xE0C6, 0x7487, 0xE0C7, 0x74BF, 0xE0C8, 0x766C, 0xE0C9, 0x79AA, 0xE0CA, 0x7DDA, 0xE0CB, 0x7E55, 0xE0CC, 0x7FA8, + 0xE0CD, 0x817A, 0xE0CE, 0x81B3, 0xE0CF, 0x8239, 0xE0D0, 0x861A, 0xE0D1, 0x87EC, 0xE0D2, 0x8A75, 0xE0D3, 0x8DE3, 0xE0D4, 0x9078, + 0xE0D5, 0x9291, 0xE0D6, 0x9425, 0xE0D7, 0x994D, 0xE0D8, 0x9BAE, 0xE0D9, 0x5368, 0xE0DA, 0x5C51, 0xE0DB, 0x6954, 0xE0DC, 0x6CC4, + 0xE0DD, 0x6D29, 0xE0DE, 0x6E2B, 0xE0DF, 0x820C, 0xE0E0, 0x859B, 0xE0E1, 0x893B, 0xE0E2, 0x8A2D, 0xE0E3, 0x8AAA, 0xE0E4, 0x96EA, + 0xE0E5, 0x9F67, 0xE0E6, 0x5261, 0xE0E7, 0x66B9, 0xE0E8, 0x6BB2, 0xE0E9, 0x7E96, 0xE0EA, 0x87FE, 0xE0EB, 0x8D0D, 0xE0EC, 0x9583, + 0xE0ED, 0x965D, 0xE0EE, 0x651D, 0xE0EF, 0x6D89, 0xE0F0, 0x71EE, 0xE0F1, 0xF96E, 0xE0F2, 0x57CE, 0xE0F3, 0x59D3, 0xE0F4, 0x5BAC, + 0xE0F5, 0x6027, 0xE0F6, 0x60FA, 0xE0F7, 0x6210, 0xE0F8, 0x661F, 0xE0F9, 0x665F, 0xE0FA, 0x7329, 0xE0FB, 0x73F9, 0xE0FC, 0x76DB, + 0xE0FD, 0x7701, 0xE0FE, 0x7B6C, 0xE1A1, 0x8056, 0xE1A2, 0x8072, 0xE1A3, 0x8165, 0xE1A4, 0x8AA0, 0xE1A5, 0x9192, 0xE1A6, 0x4E16, + 0xE1A7, 0x52E2, 0xE1A8, 0x6B72, 0xE1A9, 0x6D17, 0xE1AA, 0x7A05, 0xE1AB, 0x7B39, 0xE1AC, 0x7D30, 0xE1AD, 0xF96F, 0xE1AE, 0x8CB0, + 0xE1AF, 0x53EC, 0xE1B0, 0x562F, 0xE1B1, 0x5851, 0xE1B2, 0x5BB5, 0xE1B3, 0x5C0F, 0xE1B4, 0x5C11, 0xE1B5, 0x5DE2, 0xE1B6, 0x6240, + 0xE1B7, 0x6383, 0xE1B8, 0x6414, 0xE1B9, 0x662D, 0xE1BA, 0x68B3, 0xE1BB, 0x6CBC, 0xE1BC, 0x6D88, 0xE1BD, 0x6EAF, 0xE1BE, 0x701F, + 0xE1BF, 0x70A4, 0xE1C0, 0x71D2, 0xE1C1, 0x7526, 0xE1C2, 0x758F, 0xE1C3, 0x758E, 0xE1C4, 0x7619, 0xE1C5, 0x7B11, 0xE1C6, 0x7BE0, + 0xE1C7, 0x7C2B, 0xE1C8, 0x7D20, 0xE1C9, 0x7D39, 0xE1CA, 0x852C, 0xE1CB, 0x856D, 0xE1CC, 0x8607, 0xE1CD, 0x8A34, 0xE1CE, 0x900D, + 0xE1CF, 0x9061, 0xE1D0, 0x90B5, 0xE1D1, 0x92B7, 0xE1D2, 0x97F6, 0xE1D3, 0x9A37, 0xE1D4, 0x4FD7, 0xE1D5, 0x5C6C, 0xE1D6, 0x675F, + 0xE1D7, 0x6D91, 0xE1D8, 0x7C9F, 0xE1D9, 0x7E8C, 0xE1DA, 0x8B16, 0xE1DB, 0x8D16, 0xE1DC, 0x901F, 0xE1DD, 0x5B6B, 0xE1DE, 0x5DFD, + 0xE1DF, 0x640D, 0xE1E0, 0x84C0, 0xE1E1, 0x905C, 0xE1E2, 0x98E1, 0xE1E3, 0x7387, 0xE1E4, 0x5B8B, 0xE1E5, 0x609A, 0xE1E6, 0x677E, + 0xE1E7, 0x6DDE, 0xE1E8, 0x8A1F, 0xE1E9, 0x8AA6, 0xE1EA, 0x9001, 0xE1EB, 0x980C, 0xE1EC, 0x5237, 0xE1ED, 0xF970, 0xE1EE, 0x7051, + 0xE1EF, 0x788E, 0xE1F0, 0x9396, 0xE1F1, 0x8870, 0xE1F2, 0x91D7, 0xE1F3, 0x4FEE, 0xE1F4, 0x53D7, 0xE1F5, 0x55FD, 0xE1F6, 0x56DA, + 0xE1F7, 0x5782, 0xE1F8, 0x58FD, 0xE1F9, 0x5AC2, 0xE1FA, 0x5B88, 0xE1FB, 0x5CAB, 0xE1FC, 0x5CC0, 0xE1FD, 0x5E25, 0xE1FE, 0x6101, + 0xE2A1, 0x620D, 0xE2A2, 0x624B, 0xE2A3, 0x6388, 0xE2A4, 0x641C, 0xE2A5, 0x6536, 0xE2A6, 0x6578, 0xE2A7, 0x6A39, 0xE2A8, 0x6B8A, + 0xE2A9, 0x6C34, 0xE2AA, 0x6D19, 0xE2AB, 0x6F31, 0xE2AC, 0x71E7, 0xE2AD, 0x72E9, 0xE2AE, 0x7378, 0xE2AF, 0x7407, 0xE2B0, 0x74B2, + 0xE2B1, 0x7626, 0xE2B2, 0x7761, 0xE2B3, 0x79C0, 0xE2B4, 0x7A57, 0xE2B5, 0x7AEA, 0xE2B6, 0x7CB9, 0xE2B7, 0x7D8F, 0xE2B8, 0x7DAC, + 0xE2B9, 0x7E61, 0xE2BA, 0x7F9E, 0xE2BB, 0x8129, 0xE2BC, 0x8331, 0xE2BD, 0x8490, 0xE2BE, 0x84DA, 0xE2BF, 0x85EA, 0xE2C0, 0x8896, + 0xE2C1, 0x8AB0, 0xE2C2, 0x8B90, 0xE2C3, 0x8F38, 0xE2C4, 0x9042, 0xE2C5, 0x9083, 0xE2C6, 0x916C, 0xE2C7, 0x9296, 0xE2C8, 0x92B9, + 0xE2C9, 0x968B, 0xE2CA, 0x96A7, 0xE2CB, 0x96A8, 0xE2CC, 0x96D6, 0xE2CD, 0x9700, 0xE2CE, 0x9808, 0xE2CF, 0x9996, 0xE2D0, 0x9AD3, + 0xE2D1, 0x9B1A, 0xE2D2, 0x53D4, 0xE2D3, 0x587E, 0xE2D4, 0x5919, 0xE2D5, 0x5B70, 0xE2D6, 0x5BBF, 0xE2D7, 0x6DD1, 0xE2D8, 0x6F5A, + 0xE2D9, 0x719F, 0xE2DA, 0x7421, 0xE2DB, 0x74B9, 0xE2DC, 0x8085, 0xE2DD, 0x83FD, 0xE2DE, 0x5DE1, 0xE2DF, 0x5F87, 0xE2E0, 0x5FAA, + 0xE2E1, 0x6042, 0xE2E2, 0x65EC, 0xE2E3, 0x6812, 0xE2E4, 0x696F, 0xE2E5, 0x6A53, 0xE2E6, 0x6B89, 0xE2E7, 0x6D35, 0xE2E8, 0x6DF3, + 0xE2E9, 0x73E3, 0xE2EA, 0x76FE, 0xE2EB, 0x77AC, 0xE2EC, 0x7B4D, 0xE2ED, 0x7D14, 0xE2EE, 0x8123, 0xE2EF, 0x821C, 0xE2F0, 0x8340, + 0xE2F1, 0x84F4, 0xE2F2, 0x8563, 0xE2F3, 0x8A62, 0xE2F4, 0x8AC4, 0xE2F5, 0x9187, 0xE2F6, 0x931E, 0xE2F7, 0x9806, 0xE2F8, 0x99B4, + 0xE2F9, 0x620C, 0xE2FA, 0x8853, 0xE2FB, 0x8FF0, 0xE2FC, 0x9265, 0xE2FD, 0x5D07, 0xE2FE, 0x5D27, 0xE3A1, 0x5D69, 0xE3A2, 0x745F, + 0xE3A3, 0x819D, 0xE3A4, 0x8768, 0xE3A5, 0x6FD5, 0xE3A6, 0x62FE, 0xE3A7, 0x7FD2, 0xE3A8, 0x8936, 0xE3A9, 0x8972, 0xE3AA, 0x4E1E, + 0xE3AB, 0x4E58, 0xE3AC, 0x50E7, 0xE3AD, 0x52DD, 0xE3AE, 0x5347, 0xE3AF, 0x627F, 0xE3B0, 0x6607, 0xE3B1, 0x7E69, 0xE3B2, 0x8805, + 0xE3B3, 0x965E, 0xE3B4, 0x4F8D, 0xE3B5, 0x5319, 0xE3B6, 0x5636, 0xE3B7, 0x59CB, 0xE3B8, 0x5AA4, 0xE3B9, 0x5C38, 0xE3BA, 0x5C4E, + 0xE3BB, 0x5C4D, 0xE3BC, 0x5E02, 0xE3BD, 0x5F11, 0xE3BE, 0x6043, 0xE3BF, 0x65BD, 0xE3C0, 0x662F, 0xE3C1, 0x6642, 0xE3C2, 0x67BE, + 0xE3C3, 0x67F4, 0xE3C4, 0x731C, 0xE3C5, 0x77E2, 0xE3C6, 0x793A, 0xE3C7, 0x7FC5, 0xE3C8, 0x8494, 0xE3C9, 0x84CD, 0xE3CA, 0x8996, + 0xE3CB, 0x8A66, 0xE3CC, 0x8A69, 0xE3CD, 0x8AE1, 0xE3CE, 0x8C55, 0xE3CF, 0x8C7A, 0xE3D0, 0x57F4, 0xE3D1, 0x5BD4, 0xE3D2, 0x5F0F, + 0xE3D3, 0x606F, 0xE3D4, 0x62ED, 0xE3D5, 0x690D, 0xE3D6, 0x6B96, 0xE3D7, 0x6E5C, 0xE3D8, 0x7184, 0xE3D9, 0x7BD2, 0xE3DA, 0x8755, + 0xE3DB, 0x8B58, 0xE3DC, 0x8EFE, 0xE3DD, 0x98DF, 0xE3DE, 0x98FE, 0xE3DF, 0x4F38, 0xE3E0, 0x4F81, 0xE3E1, 0x4FE1, 0xE3E2, 0x547B, + 0xE3E3, 0x5A20, 0xE3E4, 0x5BB8, 0xE3E5, 0x613C, 0xE3E6, 0x65B0, 0xE3E7, 0x6668, 0xE3E8, 0x71FC, 0xE3E9, 0x7533, 0xE3EA, 0x795E, + 0xE3EB, 0x7D33, 0xE3EC, 0x814E, 0xE3ED, 0x81E3, 0xE3EE, 0x8398, 0xE3EF, 0x85AA, 0xE3F0, 0x85CE, 0xE3F1, 0x8703, 0xE3F2, 0x8A0A, + 0xE3F3, 0x8EAB, 0xE3F4, 0x8F9B, 0xE3F5, 0xF971, 0xE3F6, 0x8FC5, 0xE3F7, 0x5931, 0xE3F8, 0x5BA4, 0xE3F9, 0x5BE6, 0xE3FA, 0x6089, + 0xE3FB, 0x5BE9, 0xE3FC, 0x5C0B, 0xE3FD, 0x5FC3, 0xE3FE, 0x6C81, 0xE4A1, 0xF972, 0xE4A2, 0x6DF1, 0xE4A3, 0x700B, 0xE4A4, 0x751A, + 0xE4A5, 0x82AF, 0xE4A6, 0x8AF6, 0xE4A7, 0x4EC0, 0xE4A8, 0x5341, 0xE4A9, 0xF973, 0xE4AA, 0x96D9, 0xE4AB, 0x6C0F, 0xE4AC, 0x4E9E, + 0xE4AD, 0x4FC4, 0xE4AE, 0x5152, 0xE4AF, 0x555E, 0xE4B0, 0x5A25, 0xE4B1, 0x5CE8, 0xE4B2, 0x6211, 0xE4B3, 0x7259, 0xE4B4, 0x82BD, + 0xE4B5, 0x83AA, 0xE4B6, 0x86FE, 0xE4B7, 0x8859, 0xE4B8, 0x8A1D, 0xE4B9, 0x963F, 0xE4BA, 0x96C5, 0xE4BB, 0x9913, 0xE4BC, 0x9D09, + 0xE4BD, 0x9D5D, 0xE4BE, 0x580A, 0xE4BF, 0x5CB3, 0xE4C0, 0x5DBD, 0xE4C1, 0x5E44, 0xE4C2, 0x60E1, 0xE4C3, 0x6115, 0xE4C4, 0x63E1, + 0xE4C5, 0x6A02, 0xE4C6, 0x6E25, 0xE4C7, 0x9102, 0xE4C8, 0x9354, 0xE4C9, 0x984E, 0xE4CA, 0x9C10, 0xE4CB, 0x9F77, 0xE4CC, 0x5B89, + 0xE4CD, 0x5CB8, 0xE4CE, 0x6309, 0xE4CF, 0x664F, 0xE4D0, 0x6848, 0xE4D1, 0x773C, 0xE4D2, 0x96C1, 0xE4D3, 0x978D, 0xE4D4, 0x9854, + 0xE4D5, 0x9B9F, 0xE4D6, 0x65A1, 0xE4D7, 0x8B01, 0xE4D8, 0x8ECB, 0xE4D9, 0x95BC, 0xE4DA, 0x5535, 0xE4DB, 0x5CA9, 0xE4DC, 0x5DD6, + 0xE4DD, 0x5EB5, 0xE4DE, 0x6697, 0xE4DF, 0x764C, 0xE4E0, 0x83F4, 0xE4E1, 0x95C7, 0xE4E2, 0x58D3, 0xE4E3, 0x62BC, 0xE4E4, 0x72CE, + 0xE4E5, 0x9D28, 0xE4E6, 0x4EF0, 0xE4E7, 0x592E, 0xE4E8, 0x600F, 0xE4E9, 0x663B, 0xE4EA, 0x6B83, 0xE4EB, 0x79E7, 0xE4EC, 0x9D26, + 0xE4ED, 0x5393, 0xE4EE, 0x54C0, 0xE4EF, 0x57C3, 0xE4F0, 0x5D16, 0xE4F1, 0x611B, 0xE4F2, 0x66D6, 0xE4F3, 0x6DAF, 0xE4F4, 0x788D, + 0xE4F5, 0x827E, 0xE4F6, 0x9698, 0xE4F7, 0x9744, 0xE4F8, 0x5384, 0xE4F9, 0x627C, 0xE4FA, 0x6396, 0xE4FB, 0x6DB2, 0xE4FC, 0x7E0A, + 0xE4FD, 0x814B, 0xE4FE, 0x984D, 0xE5A1, 0x6AFB, 0xE5A2, 0x7F4C, 0xE5A3, 0x9DAF, 0xE5A4, 0x9E1A, 0xE5A5, 0x4E5F, 0xE5A6, 0x503B, + 0xE5A7, 0x51B6, 0xE5A8, 0x591C, 0xE5A9, 0x60F9, 0xE5AA, 0x63F6, 0xE5AB, 0x6930, 0xE5AC, 0x723A, 0xE5AD, 0x8036, 0xE5AE, 0xF974, + 0xE5AF, 0x91CE, 0xE5B0, 0x5F31, 0xE5B1, 0xF975, 0xE5B2, 0xF976, 0xE5B3, 0x7D04, 0xE5B4, 0x82E5, 0xE5B5, 0x846F, 0xE5B6, 0x84BB, + 0xE5B7, 0x85E5, 0xE5B8, 0x8E8D, 0xE5B9, 0xF977, 0xE5BA, 0x4F6F, 0xE5BB, 0xF978, 0xE5BC, 0xF979, 0xE5BD, 0x58E4, 0xE5BE, 0x5B43, + 0xE5BF, 0x6059, 0xE5C0, 0x63DA, 0xE5C1, 0x6518, 0xE5C2, 0x656D, 0xE5C3, 0x6698, 0xE5C4, 0xF97A, 0xE5C5, 0x694A, 0xE5C6, 0x6A23, + 0xE5C7, 0x6D0B, 0xE5C8, 0x7001, 0xE5C9, 0x716C, 0xE5CA, 0x75D2, 0xE5CB, 0x760D, 0xE5CC, 0x79B3, 0xE5CD, 0x7A70, 0xE5CE, 0xF97B, + 0xE5CF, 0x7F8A, 0xE5D0, 0xF97C, 0xE5D1, 0x8944, 0xE5D2, 0xF97D, 0xE5D3, 0x8B93, 0xE5D4, 0x91C0, 0xE5D5, 0x967D, 0xE5D6, 0xF97E, + 0xE5D7, 0x990A, 0xE5D8, 0x5704, 0xE5D9, 0x5FA1, 0xE5DA, 0x65BC, 0xE5DB, 0x6F01, 0xE5DC, 0x7600, 0xE5DD, 0x79A6, 0xE5DE, 0x8A9E, + 0xE5DF, 0x99AD, 0xE5E0, 0x9B5A, 0xE5E1, 0x9F6C, 0xE5E2, 0x5104, 0xE5E3, 0x61B6, 0xE5E4, 0x6291, 0xE5E5, 0x6A8D, 0xE5E6, 0x81C6, + 0xE5E7, 0x5043, 0xE5E8, 0x5830, 0xE5E9, 0x5F66, 0xE5EA, 0x7109, 0xE5EB, 0x8A00, 0xE5EC, 0x8AFA, 0xE5ED, 0x5B7C, 0xE5EE, 0x8616, + 0xE5EF, 0x4FFA, 0xE5F0, 0x513C, 0xE5F1, 0x56B4, 0xE5F2, 0x5944, 0xE5F3, 0x63A9, 0xE5F4, 0x6DF9, 0xE5F5, 0x5DAA, 0xE5F6, 0x696D, + 0xE5F7, 0x5186, 0xE5F8, 0x4E88, 0xE5F9, 0x4F59, 0xE5FA, 0xF97F, 0xE5FB, 0xF980, 0xE5FC, 0xF981, 0xE5FD, 0x5982, 0xE5FE, 0xF982, + 0xE6A1, 0xF983, 0xE6A2, 0x6B5F, 0xE6A3, 0x6C5D, 0xE6A4, 0xF984, 0xE6A5, 0x74B5, 0xE6A6, 0x7916, 0xE6A7, 0xF985, 0xE6A8, 0x8207, + 0xE6A9, 0x8245, 0xE6AA, 0x8339, 0xE6AB, 0x8F3F, 0xE6AC, 0x8F5D, 0xE6AD, 0xF986, 0xE6AE, 0x9918, 0xE6AF, 0xF987, 0xE6B0, 0xF988, + 0xE6B1, 0xF989, 0xE6B2, 0x4EA6, 0xE6B3, 0xF98A, 0xE6B4, 0x57DF, 0xE6B5, 0x5F79, 0xE6B6, 0x6613, 0xE6B7, 0xF98B, 0xE6B8, 0xF98C, + 0xE6B9, 0x75AB, 0xE6BA, 0x7E79, 0xE6BB, 0x8B6F, 0xE6BC, 0xF98D, 0xE6BD, 0x9006, 0xE6BE, 0x9A5B, 0xE6BF, 0x56A5, 0xE6C0, 0x5827, + 0xE6C1, 0x59F8, 0xE6C2, 0x5A1F, 0xE6C3, 0x5BB4, 0xE6C4, 0xF98E, 0xE6C5, 0x5EF6, 0xE6C6, 0xF98F, 0xE6C7, 0xF990, 0xE6C8, 0x6350, + 0xE6C9, 0x633B, 0xE6CA, 0xF991, 0xE6CB, 0x693D, 0xE6CC, 0x6C87, 0xE6CD, 0x6CBF, 0xE6CE, 0x6D8E, 0xE6CF, 0x6D93, 0xE6D0, 0x6DF5, + 0xE6D1, 0x6F14, 0xE6D2, 0xF992, 0xE6D3, 0x70DF, 0xE6D4, 0x7136, 0xE6D5, 0x7159, 0xE6D6, 0xF993, 0xE6D7, 0x71C3, 0xE6D8, 0x71D5, + 0xE6D9, 0xF994, 0xE6DA, 0x784F, 0xE6DB, 0x786F, 0xE6DC, 0xF995, 0xE6DD, 0x7B75, 0xE6DE, 0x7DE3, 0xE6DF, 0xF996, 0xE6E0, 0x7E2F, + 0xE6E1, 0xF997, 0xE6E2, 0x884D, 0xE6E3, 0x8EDF, 0xE6E4, 0xF998, 0xE6E5, 0xF999, 0xE6E6, 0xF99A, 0xE6E7, 0x925B, 0xE6E8, 0xF99B, + 0xE6E9, 0x9CF6, 0xE6EA, 0xF99C, 0xE6EB, 0xF99D, 0xE6EC, 0xF99E, 0xE6ED, 0x6085, 0xE6EE, 0x6D85, 0xE6EF, 0xF99F, 0xE6F0, 0x71B1, + 0xE6F1, 0xF9A0, 0xE6F2, 0xF9A1, 0xE6F3, 0x95B1, 0xE6F4, 0x53AD, 0xE6F5, 0xF9A2, 0xE6F6, 0xF9A3, 0xE6F7, 0xF9A4, 0xE6F8, 0x67D3, + 0xE6F9, 0xF9A5, 0xE6FA, 0x708E, 0xE6FB, 0x7130, 0xE6FC, 0x7430, 0xE6FD, 0x8276, 0xE6FE, 0x82D2, 0xE7A1, 0xF9A6, 0xE7A2, 0x95BB, + 0xE7A3, 0x9AE5, 0xE7A4, 0x9E7D, 0xE7A5, 0x66C4, 0xE7A6, 0xF9A7, 0xE7A7, 0x71C1, 0xE7A8, 0x8449, 0xE7A9, 0xF9A8, 0xE7AA, 0xF9A9, + 0xE7AB, 0x584B, 0xE7AC, 0xF9AA, 0xE7AD, 0xF9AB, 0xE7AE, 0x5DB8, 0xE7AF, 0x5F71, 0xE7B0, 0xF9AC, 0xE7B1, 0x6620, 0xE7B2, 0x668E, + 0xE7B3, 0x6979, 0xE7B4, 0x69AE, 0xE7B5, 0x6C38, 0xE7B6, 0x6CF3, 0xE7B7, 0x6E36, 0xE7B8, 0x6F41, 0xE7B9, 0x6FDA, 0xE7BA, 0x701B, + 0xE7BB, 0x702F, 0xE7BC, 0x7150, 0xE7BD, 0x71DF, 0xE7BE, 0x7370, 0xE7BF, 0xF9AD, 0xE7C0, 0x745B, 0xE7C1, 0xF9AE, 0xE7C2, 0x74D4, + 0xE7C3, 0x76C8, 0xE7C4, 0x7A4E, 0xE7C5, 0x7E93, 0xE7C6, 0xF9AF, 0xE7C7, 0xF9B0, 0xE7C8, 0x82F1, 0xE7C9, 0x8A60, 0xE7CA, 0x8FCE, + 0xE7CB, 0xF9B1, 0xE7CC, 0x9348, 0xE7CD, 0xF9B2, 0xE7CE, 0x9719, 0xE7CF, 0xF9B3, 0xE7D0, 0xF9B4, 0xE7D1, 0x4E42, 0xE7D2, 0x502A, + 0xE7D3, 0xF9B5, 0xE7D4, 0x5208, 0xE7D5, 0x53E1, 0xE7D6, 0x66F3, 0xE7D7, 0x6C6D, 0xE7D8, 0x6FCA, 0xE7D9, 0x730A, 0xE7DA, 0x777F, + 0xE7DB, 0x7A62, 0xE7DC, 0x82AE, 0xE7DD, 0x85DD, 0xE7DE, 0x8602, 0xE7DF, 0xF9B6, 0xE7E0, 0x88D4, 0xE7E1, 0x8A63, 0xE7E2, 0x8B7D, + 0xE7E3, 0x8C6B, 0xE7E4, 0xF9B7, 0xE7E5, 0x92B3, 0xE7E6, 0xF9B8, 0xE7E7, 0x9713, 0xE7E8, 0x9810, 0xE7E9, 0x4E94, 0xE7EA, 0x4F0D, + 0xE7EB, 0x4FC9, 0xE7EC, 0x50B2, 0xE7ED, 0x5348, 0xE7EE, 0x543E, 0xE7EF, 0x5433, 0xE7F0, 0x55DA, 0xE7F1, 0x5862, 0xE7F2, 0x58BA, + 0xE7F3, 0x5967, 0xE7F4, 0x5A1B, 0xE7F5, 0x5BE4, 0xE7F6, 0x609F, 0xE7F7, 0xF9B9, 0xE7F8, 0x61CA, 0xE7F9, 0x6556, 0xE7FA, 0x65FF, + 0xE7FB, 0x6664, 0xE7FC, 0x68A7, 0xE7FD, 0x6C5A, 0xE7FE, 0x6FB3, 0xE8A1, 0x70CF, 0xE8A2, 0x71AC, 0xE8A3, 0x7352, 0xE8A4, 0x7B7D, + 0xE8A5, 0x8708, 0xE8A6, 0x8AA4, 0xE8A7, 0x9C32, 0xE8A8, 0x9F07, 0xE8A9, 0x5C4B, 0xE8AA, 0x6C83, 0xE8AB, 0x7344, 0xE8AC, 0x7389, + 0xE8AD, 0x923A, 0xE8AE, 0x6EAB, 0xE8AF, 0x7465, 0xE8B0, 0x761F, 0xE8B1, 0x7A69, 0xE8B2, 0x7E15, 0xE8B3, 0x860A, 0xE8B4, 0x5140, + 0xE8B5, 0x58C5, 0xE8B6, 0x64C1, 0xE8B7, 0x74EE, 0xE8B8, 0x7515, 0xE8B9, 0x7670, 0xE8BA, 0x7FC1, 0xE8BB, 0x9095, 0xE8BC, 0x96CD, + 0xE8BD, 0x9954, 0xE8BE, 0x6E26, 0xE8BF, 0x74E6, 0xE8C0, 0x7AA9, 0xE8C1, 0x7AAA, 0xE8C2, 0x81E5, 0xE8C3, 0x86D9, 0xE8C4, 0x8778, + 0xE8C5, 0x8A1B, 0xE8C6, 0x5A49, 0xE8C7, 0x5B8C, 0xE8C8, 0x5B9B, 0xE8C9, 0x68A1, 0xE8CA, 0x6900, 0xE8CB, 0x6D63, 0xE8CC, 0x73A9, + 0xE8CD, 0x7413, 0xE8CE, 0x742C, 0xE8CF, 0x7897, 0xE8D0, 0x7DE9, 0xE8D1, 0x7FEB, 0xE8D2, 0x8118, 0xE8D3, 0x8155, 0xE8D4, 0x839E, + 0xE8D5, 0x8C4C, 0xE8D6, 0x962E, 0xE8D7, 0x9811, 0xE8D8, 0x66F0, 0xE8D9, 0x5F80, 0xE8DA, 0x65FA, 0xE8DB, 0x6789, 0xE8DC, 0x6C6A, + 0xE8DD, 0x738B, 0xE8DE, 0x502D, 0xE8DF, 0x5A03, 0xE8E0, 0x6B6A, 0xE8E1, 0x77EE, 0xE8E2, 0x5916, 0xE8E3, 0x5D6C, 0xE8E4, 0x5DCD, + 0xE8E5, 0x7325, 0xE8E6, 0x754F, 0xE8E7, 0xF9BA, 0xE8E8, 0xF9BB, 0xE8E9, 0x50E5, 0xE8EA, 0x51F9, 0xE8EB, 0x582F, 0xE8EC, 0x592D, + 0xE8ED, 0x5996, 0xE8EE, 0x59DA, 0xE8EF, 0x5BE5, 0xE8F0, 0xF9BC, 0xE8F1, 0xF9BD, 0xE8F2, 0x5DA2, 0xE8F3, 0x62D7, 0xE8F4, 0x6416, + 0xE8F5, 0x6493, 0xE8F6, 0x64FE, 0xE8F7, 0xF9BE, 0xE8F8, 0x66DC, 0xE8F9, 0xF9BF, 0xE8FA, 0x6A48, 0xE8FB, 0xF9C0, 0xE8FC, 0x71FF, + 0xE8FD, 0x7464, 0xE8FE, 0xF9C1, 0xE9A1, 0x7A88, 0xE9A2, 0x7AAF, 0xE9A3, 0x7E47, 0xE9A4, 0x7E5E, 0xE9A5, 0x8000, 0xE9A6, 0x8170, + 0xE9A7, 0xF9C2, 0xE9A8, 0x87EF, 0xE9A9, 0x8981, 0xE9AA, 0x8B20, 0xE9AB, 0x9059, 0xE9AC, 0xF9C3, 0xE9AD, 0x9080, 0xE9AE, 0x9952, + 0xE9AF, 0x617E, 0xE9B0, 0x6B32, 0xE9B1, 0x6D74, 0xE9B2, 0x7E1F, 0xE9B3, 0x8925, 0xE9B4, 0x8FB1, 0xE9B5, 0x4FD1, 0xE9B6, 0x50AD, + 0xE9B7, 0x5197, 0xE9B8, 0x52C7, 0xE9B9, 0x57C7, 0xE9BA, 0x5889, 0xE9BB, 0x5BB9, 0xE9BC, 0x5EB8, 0xE9BD, 0x6142, 0xE9BE, 0x6995, + 0xE9BF, 0x6D8C, 0xE9C0, 0x6E67, 0xE9C1, 0x6EB6, 0xE9C2, 0x7194, 0xE9C3, 0x7462, 0xE9C4, 0x7528, 0xE9C5, 0x752C, 0xE9C6, 0x8073, + 0xE9C7, 0x8338, 0xE9C8, 0x84C9, 0xE9C9, 0x8E0A, 0xE9CA, 0x9394, 0xE9CB, 0x93DE, 0xE9CC, 0xF9C4, 0xE9CD, 0x4E8E, 0xE9CE, 0x4F51, + 0xE9CF, 0x5076, 0xE9D0, 0x512A, 0xE9D1, 0x53C8, 0xE9D2, 0x53CB, 0xE9D3, 0x53F3, 0xE9D4, 0x5B87, 0xE9D5, 0x5BD3, 0xE9D6, 0x5C24, + 0xE9D7, 0x611A, 0xE9D8, 0x6182, 0xE9D9, 0x65F4, 0xE9DA, 0x725B, 0xE9DB, 0x7397, 0xE9DC, 0x7440, 0xE9DD, 0x76C2, 0xE9DE, 0x7950, + 0xE9DF, 0x7991, 0xE9E0, 0x79B9, 0xE9E1, 0x7D06, 0xE9E2, 0x7FBD, 0xE9E3, 0x828B, 0xE9E4, 0x85D5, 0xE9E5, 0x865E, 0xE9E6, 0x8FC2, + 0xE9E7, 0x9047, 0xE9E8, 0x90F5, 0xE9E9, 0x91EA, 0xE9EA, 0x9685, 0xE9EB, 0x96E8, 0xE9EC, 0x96E9, 0xE9ED, 0x52D6, 0xE9EE, 0x5F67, + 0xE9EF, 0x65ED, 0xE9F0, 0x6631, 0xE9F1, 0x682F, 0xE9F2, 0x715C, 0xE9F3, 0x7A36, 0xE9F4, 0x90C1, 0xE9F5, 0x980A, 0xE9F6, 0x4E91, + 0xE9F7, 0xF9C5, 0xE9F8, 0x6A52, 0xE9F9, 0x6B9E, 0xE9FA, 0x6F90, 0xE9FB, 0x7189, 0xE9FC, 0x8018, 0xE9FD, 0x82B8, 0xE9FE, 0x8553, + 0xEAA1, 0x904B, 0xEAA2, 0x9695, 0xEAA3, 0x96F2, 0xEAA4, 0x97FB, 0xEAA5, 0x851A, 0xEAA6, 0x9B31, 0xEAA7, 0x4E90, 0xEAA8, 0x718A, + 0xEAA9, 0x96C4, 0xEAAA, 0x5143, 0xEAAB, 0x539F, 0xEAAC, 0x54E1, 0xEAAD, 0x5713, 0xEAAE, 0x5712, 0xEAAF, 0x57A3, 0xEAB0, 0x5A9B, + 0xEAB1, 0x5AC4, 0xEAB2, 0x5BC3, 0xEAB3, 0x6028, 0xEAB4, 0x613F, 0xEAB5, 0x63F4, 0xEAB6, 0x6C85, 0xEAB7, 0x6D39, 0xEAB8, 0x6E72, + 0xEAB9, 0x6E90, 0xEABA, 0x7230, 0xEABB, 0x733F, 0xEABC, 0x7457, 0xEABD, 0x82D1, 0xEABE, 0x8881, 0xEABF, 0x8F45, 0xEAC0, 0x9060, + 0xEAC1, 0xF9C6, 0xEAC2, 0x9662, 0xEAC3, 0x9858, 0xEAC4, 0x9D1B, 0xEAC5, 0x6708, 0xEAC6, 0x8D8A, 0xEAC7, 0x925E, 0xEAC8, 0x4F4D, + 0xEAC9, 0x5049, 0xEACA, 0x50DE, 0xEACB, 0x5371, 0xEACC, 0x570D, 0xEACD, 0x59D4, 0xEACE, 0x5A01, 0xEACF, 0x5C09, 0xEAD0, 0x6170, + 0xEAD1, 0x6690, 0xEAD2, 0x6E2D, 0xEAD3, 0x7232, 0xEAD4, 0x744B, 0xEAD5, 0x7DEF, 0xEAD6, 0x80C3, 0xEAD7, 0x840E, 0xEAD8, 0x8466, + 0xEAD9, 0x853F, 0xEADA, 0x875F, 0xEADB, 0x885B, 0xEADC, 0x8918, 0xEADD, 0x8B02, 0xEADE, 0x9055, 0xEADF, 0x97CB, 0xEAE0, 0x9B4F, + 0xEAE1, 0x4E73, 0xEAE2, 0x4F91, 0xEAE3, 0x5112, 0xEAE4, 0x516A, 0xEAE5, 0xF9C7, 0xEAE6, 0x552F, 0xEAE7, 0x55A9, 0xEAE8, 0x5B7A, + 0xEAE9, 0x5BA5, 0xEAEA, 0x5E7C, 0xEAEB, 0x5E7D, 0xEAEC, 0x5EBE, 0xEAED, 0x60A0, 0xEAEE, 0x60DF, 0xEAEF, 0x6108, 0xEAF0, 0x6109, + 0xEAF1, 0x63C4, 0xEAF2, 0x6538, 0xEAF3, 0x6709, 0xEAF4, 0xF9C8, 0xEAF5, 0x67D4, 0xEAF6, 0x67DA, 0xEAF7, 0xF9C9, 0xEAF8, 0x6961, + 0xEAF9, 0x6962, 0xEAFA, 0x6CB9, 0xEAFB, 0x6D27, 0xEAFC, 0xF9CA, 0xEAFD, 0x6E38, 0xEAFE, 0xF9CB, 0xEBA1, 0x6FE1, 0xEBA2, 0x7336, + 0xEBA3, 0x7337, 0xEBA4, 0xF9CC, 0xEBA5, 0x745C, 0xEBA6, 0x7531, 0xEBA7, 0xF9CD, 0xEBA8, 0x7652, 0xEBA9, 0xF9CE, 0xEBAA, 0xF9CF, + 0xEBAB, 0x7DAD, 0xEBAC, 0x81FE, 0xEBAD, 0x8438, 0xEBAE, 0x88D5, 0xEBAF, 0x8A98, 0xEBB0, 0x8ADB, 0xEBB1, 0x8AED, 0xEBB2, 0x8E30, + 0xEBB3, 0x8E42, 0xEBB4, 0x904A, 0xEBB5, 0x903E, 0xEBB6, 0x907A, 0xEBB7, 0x9149, 0xEBB8, 0x91C9, 0xEBB9, 0x936E, 0xEBBA, 0xF9D0, + 0xEBBB, 0xF9D1, 0xEBBC, 0x5809, 0xEBBD, 0xF9D2, 0xEBBE, 0x6BD3, 0xEBBF, 0x8089, 0xEBC0, 0x80B2, 0xEBC1, 0xF9D3, 0xEBC2, 0xF9D4, + 0xEBC3, 0x5141, 0xEBC4, 0x596B, 0xEBC5, 0x5C39, 0xEBC6, 0xF9D5, 0xEBC7, 0xF9D6, 0xEBC8, 0x6F64, 0xEBC9, 0x73A7, 0xEBCA, 0x80E4, + 0xEBCB, 0x8D07, 0xEBCC, 0xF9D7, 0xEBCD, 0x9217, 0xEBCE, 0x958F, 0xEBCF, 0xF9D8, 0xEBD0, 0xF9D9, 0xEBD1, 0xF9DA, 0xEBD2, 0xF9DB, + 0xEBD3, 0x807F, 0xEBD4, 0x620E, 0xEBD5, 0x701C, 0xEBD6, 0x7D68, 0xEBD7, 0x878D, 0xEBD8, 0xF9DC, 0xEBD9, 0x57A0, 0xEBDA, 0x6069, + 0xEBDB, 0x6147, 0xEBDC, 0x6BB7, 0xEBDD, 0x8ABE, 0xEBDE, 0x9280, 0xEBDF, 0x96B1, 0xEBE0, 0x4E59, 0xEBE1, 0x541F, 0xEBE2, 0x6DEB, + 0xEBE3, 0x852D, 0xEBE4, 0x9670, 0xEBE5, 0x97F3, 0xEBE6, 0x98EE, 0xEBE7, 0x63D6, 0xEBE8, 0x6CE3, 0xEBE9, 0x9091, 0xEBEA, 0x51DD, + 0xEBEB, 0x61C9, 0xEBEC, 0x81BA, 0xEBED, 0x9DF9, 0xEBEE, 0x4F9D, 0xEBEF, 0x501A, 0xEBF0, 0x5100, 0xEBF1, 0x5B9C, 0xEBF2, 0x610F, + 0xEBF3, 0x61FF, 0xEBF4, 0x64EC, 0xEBF5, 0x6905, 0xEBF6, 0x6BC5, 0xEBF7, 0x7591, 0xEBF8, 0x77E3, 0xEBF9, 0x7FA9, 0xEBFA, 0x8264, + 0xEBFB, 0x858F, 0xEBFC, 0x87FB, 0xEBFD, 0x8863, 0xEBFE, 0x8ABC, 0xECA1, 0x8B70, 0xECA2, 0x91AB, 0xECA3, 0x4E8C, 0xECA4, 0x4EE5, + 0xECA5, 0x4F0A, 0xECA6, 0xF9DD, 0xECA7, 0xF9DE, 0xECA8, 0x5937, 0xECA9, 0x59E8, 0xECAA, 0xF9DF, 0xECAB, 0x5DF2, 0xECAC, 0x5F1B, + 0xECAD, 0x5F5B, 0xECAE, 0x6021, 0xECAF, 0xF9E0, 0xECB0, 0xF9E1, 0xECB1, 0xF9E2, 0xECB2, 0xF9E3, 0xECB3, 0x723E, 0xECB4, 0x73E5, + 0xECB5, 0xF9E4, 0xECB6, 0x7570, 0xECB7, 0x75CD, 0xECB8, 0xF9E5, 0xECB9, 0x79FB, 0xECBA, 0xF9E6, 0xECBB, 0x800C, 0xECBC, 0x8033, + 0xECBD, 0x8084, 0xECBE, 0x82E1, 0xECBF, 0x8351, 0xECC0, 0xF9E7, 0xECC1, 0xF9E8, 0xECC2, 0x8CBD, 0xECC3, 0x8CB3, 0xECC4, 0x9087, + 0xECC5, 0xF9E9, 0xECC6, 0xF9EA, 0xECC7, 0x98F4, 0xECC8, 0x990C, 0xECC9, 0xF9EB, 0xECCA, 0xF9EC, 0xECCB, 0x7037, 0xECCC, 0x76CA, + 0xECCD, 0x7FCA, 0xECCE, 0x7FCC, 0xECCF, 0x7FFC, 0xECD0, 0x8B1A, 0xECD1, 0x4EBA, 0xECD2, 0x4EC1, 0xECD3, 0x5203, 0xECD4, 0x5370, + 0xECD5, 0xF9ED, 0xECD6, 0x54BD, 0xECD7, 0x56E0, 0xECD8, 0x59FB, 0xECD9, 0x5BC5, 0xECDA, 0x5F15, 0xECDB, 0x5FCD, 0xECDC, 0x6E6E, + 0xECDD, 0xF9EE, 0xECDE, 0xF9EF, 0xECDF, 0x7D6A, 0xECE0, 0x8335, 0xECE1, 0xF9F0, 0xECE2, 0x8693, 0xECE3, 0x8A8D, 0xECE4, 0xF9F1, + 0xECE5, 0x976D, 0xECE6, 0x9777, 0xECE7, 0xF9F2, 0xECE8, 0xF9F3, 0xECE9, 0x4E00, 0xECEA, 0x4F5A, 0xECEB, 0x4F7E, 0xECEC, 0x58F9, + 0xECED, 0x65E5, 0xECEE, 0x6EA2, 0xECEF, 0x9038, 0xECF0, 0x93B0, 0xECF1, 0x99B9, 0xECF2, 0x4EFB, 0xECF3, 0x58EC, 0xECF4, 0x598A, + 0xECF5, 0x59D9, 0xECF6, 0x6041, 0xECF7, 0xF9F4, 0xECF8, 0xF9F5, 0xECF9, 0x7A14, 0xECFA, 0xF9F6, 0xECFB, 0x834F, 0xECFC, 0x8CC3, + 0xECFD, 0x5165, 0xECFE, 0x5344, 0xEDA1, 0xF9F7, 0xEDA2, 0xF9F8, 0xEDA3, 0xF9F9, 0xEDA4, 0x4ECD, 0xEDA5, 0x5269, 0xEDA6, 0x5B55, + 0xEDA7, 0x82BF, 0xEDA8, 0x4ED4, 0xEDA9, 0x523A, 0xEDAA, 0x54A8, 0xEDAB, 0x59C9, 0xEDAC, 0x59FF, 0xEDAD, 0x5B50, 0xEDAE, 0x5B57, + 0xEDAF, 0x5B5C, 0xEDB0, 0x6063, 0xEDB1, 0x6148, 0xEDB2, 0x6ECB, 0xEDB3, 0x7099, 0xEDB4, 0x716E, 0xEDB5, 0x7386, 0xEDB6, 0x74F7, + 0xEDB7, 0x75B5, 0xEDB8, 0x78C1, 0xEDB9, 0x7D2B, 0xEDBA, 0x8005, 0xEDBB, 0x81EA, 0xEDBC, 0x8328, 0xEDBD, 0x8517, 0xEDBE, 0x85C9, + 0xEDBF, 0x8AEE, 0xEDC0, 0x8CC7, 0xEDC1, 0x96CC, 0xEDC2, 0x4F5C, 0xEDC3, 0x52FA, 0xEDC4, 0x56BC, 0xEDC5, 0x65AB, 0xEDC6, 0x6628, + 0xEDC7, 0x707C, 0xEDC8, 0x70B8, 0xEDC9, 0x7235, 0xEDCA, 0x7DBD, 0xEDCB, 0x828D, 0xEDCC, 0x914C, 0xEDCD, 0x96C0, 0xEDCE, 0x9D72, + 0xEDCF, 0x5B71, 0xEDD0, 0x68E7, 0xEDD1, 0x6B98, 0xEDD2, 0x6F7A, 0xEDD3, 0x76DE, 0xEDD4, 0x5C91, 0xEDD5, 0x66AB, 0xEDD6, 0x6F5B, + 0xEDD7, 0x7BB4, 0xEDD8, 0x7C2A, 0xEDD9, 0x8836, 0xEDDA, 0x96DC, 0xEDDB, 0x4E08, 0xEDDC, 0x4ED7, 0xEDDD, 0x5320, 0xEDDE, 0x5834, + 0xEDDF, 0x58BB, 0xEDE0, 0x58EF, 0xEDE1, 0x596C, 0xEDE2, 0x5C07, 0xEDE3, 0x5E33, 0xEDE4, 0x5E84, 0xEDE5, 0x5F35, 0xEDE6, 0x638C, + 0xEDE7, 0x66B2, 0xEDE8, 0x6756, 0xEDE9, 0x6A1F, 0xEDEA, 0x6AA3, 0xEDEB, 0x6B0C, 0xEDEC, 0x6F3F, 0xEDED, 0x7246, 0xEDEE, 0xF9FA, + 0xEDEF, 0x7350, 0xEDF0, 0x748B, 0xEDF1, 0x7AE0, 0xEDF2, 0x7CA7, 0xEDF3, 0x8178, 0xEDF4, 0x81DF, 0xEDF5, 0x81E7, 0xEDF6, 0x838A, + 0xEDF7, 0x846C, 0xEDF8, 0x8523, 0xEDF9, 0x8594, 0xEDFA, 0x85CF, 0xEDFB, 0x88DD, 0xEDFC, 0x8D13, 0xEDFD, 0x91AC, 0xEDFE, 0x9577, + 0xEEA1, 0x969C, 0xEEA2, 0x518D, 0xEEA3, 0x54C9, 0xEEA4, 0x5728, 0xEEA5, 0x5BB0, 0xEEA6, 0x624D, 0xEEA7, 0x6750, 0xEEA8, 0x683D, + 0xEEA9, 0x6893, 0xEEAA, 0x6E3D, 0xEEAB, 0x6ED3, 0xEEAC, 0x707D, 0xEEAD, 0x7E21, 0xEEAE, 0x88C1, 0xEEAF, 0x8CA1, 0xEEB0, 0x8F09, + 0xEEB1, 0x9F4B, 0xEEB2, 0x9F4E, 0xEEB3, 0x722D, 0xEEB4, 0x7B8F, 0xEEB5, 0x8ACD, 0xEEB6, 0x931A, 0xEEB7, 0x4F47, 0xEEB8, 0x4F4E, + 0xEEB9, 0x5132, 0xEEBA, 0x5480, 0xEEBB, 0x59D0, 0xEEBC, 0x5E95, 0xEEBD, 0x62B5, 0xEEBE, 0x6775, 0xEEBF, 0x696E, 0xEEC0, 0x6A17, + 0xEEC1, 0x6CAE, 0xEEC2, 0x6E1A, 0xEEC3, 0x72D9, 0xEEC4, 0x732A, 0xEEC5, 0x75BD, 0xEEC6, 0x7BB8, 0xEEC7, 0x7D35, 0xEEC8, 0x82E7, + 0xEEC9, 0x83F9, 0xEECA, 0x8457, 0xEECB, 0x85F7, 0xEECC, 0x8A5B, 0xEECD, 0x8CAF, 0xEECE, 0x8E87, 0xEECF, 0x9019, 0xEED0, 0x90B8, + 0xEED1, 0x96CE, 0xEED2, 0x9F5F, 0xEED3, 0x52E3, 0xEED4, 0x540A, 0xEED5, 0x5AE1, 0xEED6, 0x5BC2, 0xEED7, 0x6458, 0xEED8, 0x6575, + 0xEED9, 0x6EF4, 0xEEDA, 0x72C4, 0xEEDB, 0xF9FB, 0xEEDC, 0x7684, 0xEEDD, 0x7A4D, 0xEEDE, 0x7B1B, 0xEEDF, 0x7C4D, 0xEEE0, 0x7E3E, + 0xEEE1, 0x7FDF, 0xEEE2, 0x837B, 0xEEE3, 0x8B2B, 0xEEE4, 0x8CCA, 0xEEE5, 0x8D64, 0xEEE6, 0x8DE1, 0xEEE7, 0x8E5F, 0xEEE8, 0x8FEA, + 0xEEE9, 0x8FF9, 0xEEEA, 0x9069, 0xEEEB, 0x93D1, 0xEEEC, 0x4F43, 0xEEED, 0x4F7A, 0xEEEE, 0x50B3, 0xEEEF, 0x5168, 0xEEF0, 0x5178, + 0xEEF1, 0x524D, 0xEEF2, 0x526A, 0xEEF3, 0x5861, 0xEEF4, 0x587C, 0xEEF5, 0x5960, 0xEEF6, 0x5C08, 0xEEF7, 0x5C55, 0xEEF8, 0x5EDB, + 0xEEF9, 0x609B, 0xEEFA, 0x6230, 0xEEFB, 0x6813, 0xEEFC, 0x6BBF, 0xEEFD, 0x6C08, 0xEEFE, 0x6FB1, 0xEFA1, 0x714E, 0xEFA2, 0x7420, + 0xEFA3, 0x7530, 0xEFA4, 0x7538, 0xEFA5, 0x7551, 0xEFA6, 0x7672, 0xEFA7, 0x7B4C, 0xEFA8, 0x7B8B, 0xEFA9, 0x7BAD, 0xEFAA, 0x7BC6, + 0xEFAB, 0x7E8F, 0xEFAC, 0x8A6E, 0xEFAD, 0x8F3E, 0xEFAE, 0x8F49, 0xEFAF, 0x923F, 0xEFB0, 0x9293, 0xEFB1, 0x9322, 0xEFB2, 0x942B, + 0xEFB3, 0x96FB, 0xEFB4, 0x985A, 0xEFB5, 0x986B, 0xEFB6, 0x991E, 0xEFB7, 0x5207, 0xEFB8, 0x622A, 0xEFB9, 0x6298, 0xEFBA, 0x6D59, + 0xEFBB, 0x7664, 0xEFBC, 0x7ACA, 0xEFBD, 0x7BC0, 0xEFBE, 0x7D76, 0xEFBF, 0x5360, 0xEFC0, 0x5CBE, 0xEFC1, 0x5E97, 0xEFC2, 0x6F38, + 0xEFC3, 0x70B9, 0xEFC4, 0x7C98, 0xEFC5, 0x9711, 0xEFC6, 0x9B8E, 0xEFC7, 0x9EDE, 0xEFC8, 0x63A5, 0xEFC9, 0x647A, 0xEFCA, 0x8776, + 0xEFCB, 0x4E01, 0xEFCC, 0x4E95, 0xEFCD, 0x4EAD, 0xEFCE, 0x505C, 0xEFCF, 0x5075, 0xEFD0, 0x5448, 0xEFD1, 0x59C3, 0xEFD2, 0x5B9A, + 0xEFD3, 0x5E40, 0xEFD4, 0x5EAD, 0xEFD5, 0x5EF7, 0xEFD6, 0x5F81, 0xEFD7, 0x60C5, 0xEFD8, 0x633A, 0xEFD9, 0x653F, 0xEFDA, 0x6574, + 0xEFDB, 0x65CC, 0xEFDC, 0x6676, 0xEFDD, 0x6678, 0xEFDE, 0x67FE, 0xEFDF, 0x6968, 0xEFE0, 0x6A89, 0xEFE1, 0x6B63, 0xEFE2, 0x6C40, + 0xEFE3, 0x6DC0, 0xEFE4, 0x6DE8, 0xEFE5, 0x6E1F, 0xEFE6, 0x6E5E, 0xEFE7, 0x701E, 0xEFE8, 0x70A1, 0xEFE9, 0x738E, 0xEFEA, 0x73FD, + 0xEFEB, 0x753A, 0xEFEC, 0x775B, 0xEFED, 0x7887, 0xEFEE, 0x798E, 0xEFEF, 0x7A0B, 0xEFF0, 0x7A7D, 0xEFF1, 0x7CBE, 0xEFF2, 0x7D8E, + 0xEFF3, 0x8247, 0xEFF4, 0x8A02, 0xEFF5, 0x8AEA, 0xEFF6, 0x8C9E, 0xEFF7, 0x912D, 0xEFF8, 0x914A, 0xEFF9, 0x91D8, 0xEFFA, 0x9266, + 0xEFFB, 0x92CC, 0xEFFC, 0x9320, 0xEFFD, 0x9706, 0xEFFE, 0x9756, 0xF0A1, 0x975C, 0xF0A2, 0x9802, 0xF0A3, 0x9F0E, 0xF0A4, 0x5236, + 0xF0A5, 0x5291, 0xF0A6, 0x557C, 0xF0A7, 0x5824, 0xF0A8, 0x5E1D, 0xF0A9, 0x5F1F, 0xF0AA, 0x608C, 0xF0AB, 0x63D0, 0xF0AC, 0x68AF, + 0xF0AD, 0x6FDF, 0xF0AE, 0x796D, 0xF0AF, 0x7B2C, 0xF0B0, 0x81CD, 0xF0B1, 0x85BA, 0xF0B2, 0x88FD, 0xF0B3, 0x8AF8, 0xF0B4, 0x8E44, + 0xF0B5, 0x918D, 0xF0B6, 0x9664, 0xF0B7, 0x969B, 0xF0B8, 0x973D, 0xF0B9, 0x984C, 0xF0BA, 0x9F4A, 0xF0BB, 0x4FCE, 0xF0BC, 0x5146, + 0xF0BD, 0x51CB, 0xF0BE, 0x52A9, 0xF0BF, 0x5632, 0xF0C0, 0x5F14, 0xF0C1, 0x5F6B, 0xF0C2, 0x63AA, 0xF0C3, 0x64CD, 0xF0C4, 0x65E9, + 0xF0C5, 0x6641, 0xF0C6, 0x66FA, 0xF0C7, 0x66F9, 0xF0C8, 0x671D, 0xF0C9, 0x689D, 0xF0CA, 0x68D7, 0xF0CB, 0x69FD, 0xF0CC, 0x6F15, + 0xF0CD, 0x6F6E, 0xF0CE, 0x7167, 0xF0CF, 0x71E5, 0xF0D0, 0x722A, 0xF0D1, 0x74AA, 0xF0D2, 0x773A, 0xF0D3, 0x7956, 0xF0D4, 0x795A, + 0xF0D5, 0x79DF, 0xF0D6, 0x7A20, 0xF0D7, 0x7A95, 0xF0D8, 0x7C97, 0xF0D9, 0x7CDF, 0xF0DA, 0x7D44, 0xF0DB, 0x7E70, 0xF0DC, 0x8087, + 0xF0DD, 0x85FB, 0xF0DE, 0x86A4, 0xF0DF, 0x8A54, 0xF0E0, 0x8ABF, 0xF0E1, 0x8D99, 0xF0E2, 0x8E81, 0xF0E3, 0x9020, 0xF0E4, 0x906D, + 0xF0E5, 0x91E3, 0xF0E6, 0x963B, 0xF0E7, 0x96D5, 0xF0E8, 0x9CE5, 0xF0E9, 0x65CF, 0xF0EA, 0x7C07, 0xF0EB, 0x8DB3, 0xF0EC, 0x93C3, + 0xF0ED, 0x5B58, 0xF0EE, 0x5C0A, 0xF0EF, 0x5352, 0xF0F0, 0x62D9, 0xF0F1, 0x731D, 0xF0F2, 0x5027, 0xF0F3, 0x5B97, 0xF0F4, 0x5F9E, + 0xF0F5, 0x60B0, 0xF0F6, 0x616B, 0xF0F7, 0x68D5, 0xF0F8, 0x6DD9, 0xF0F9, 0x742E, 0xF0FA, 0x7A2E, 0xF0FB, 0x7D42, 0xF0FC, 0x7D9C, + 0xF0FD, 0x7E31, 0xF0FE, 0x816B, 0xF1A1, 0x8E2A, 0xF1A2, 0x8E35, 0xF1A3, 0x937E, 0xF1A4, 0x9418, 0xF1A5, 0x4F50, 0xF1A6, 0x5750, + 0xF1A7, 0x5DE6, 0xF1A8, 0x5EA7, 0xF1A9, 0x632B, 0xF1AA, 0x7F6A, 0xF1AB, 0x4E3B, 0xF1AC, 0x4F4F, 0xF1AD, 0x4F8F, 0xF1AE, 0x505A, + 0xF1AF, 0x59DD, 0xF1B0, 0x80C4, 0xF1B1, 0x546A, 0xF1B2, 0x5468, 0xF1B3, 0x55FE, 0xF1B4, 0x594F, 0xF1B5, 0x5B99, 0xF1B6, 0x5DDE, + 0xF1B7, 0x5EDA, 0xF1B8, 0x665D, 0xF1B9, 0x6731, 0xF1BA, 0x67F1, 0xF1BB, 0x682A, 0xF1BC, 0x6CE8, 0xF1BD, 0x6D32, 0xF1BE, 0x6E4A, + 0xF1BF, 0x6F8D, 0xF1C0, 0x70B7, 0xF1C1, 0x73E0, 0xF1C2, 0x7587, 0xF1C3, 0x7C4C, 0xF1C4, 0x7D02, 0xF1C5, 0x7D2C, 0xF1C6, 0x7DA2, + 0xF1C7, 0x821F, 0xF1C8, 0x86DB, 0xF1C9, 0x8A3B, 0xF1CA, 0x8A85, 0xF1CB, 0x8D70, 0xF1CC, 0x8E8A, 0xF1CD, 0x8F33, 0xF1CE, 0x9031, + 0xF1CF, 0x914E, 0xF1D0, 0x9152, 0xF1D1, 0x9444, 0xF1D2, 0x99D0, 0xF1D3, 0x7AF9, 0xF1D4, 0x7CA5, 0xF1D5, 0x4FCA, 0xF1D6, 0x5101, + 0xF1D7, 0x51C6, 0xF1D8, 0x57C8, 0xF1D9, 0x5BEF, 0xF1DA, 0x5CFB, 0xF1DB, 0x6659, 0xF1DC, 0x6A3D, 0xF1DD, 0x6D5A, 0xF1DE, 0x6E96, + 0xF1DF, 0x6FEC, 0xF1E0, 0x710C, 0xF1E1, 0x756F, 0xF1E2, 0x7AE3, 0xF1E3, 0x8822, 0xF1E4, 0x9021, 0xF1E5, 0x9075, 0xF1E6, 0x96CB, + 0xF1E7, 0x99FF, 0xF1E8, 0x8301, 0xF1E9, 0x4E2D, 0xF1EA, 0x4EF2, 0xF1EB, 0x8846, 0xF1EC, 0x91CD, 0xF1ED, 0x537D, 0xF1EE, 0x6ADB, + 0xF1EF, 0x696B, 0xF1F0, 0x6C41, 0xF1F1, 0x847A, 0xF1F2, 0x589E, 0xF1F3, 0x618E, 0xF1F4, 0x66FE, 0xF1F5, 0x62EF, 0xF1F6, 0x70DD, + 0xF1F7, 0x7511, 0xF1F8, 0x75C7, 0xF1F9, 0x7E52, 0xF1FA, 0x84B8, 0xF1FB, 0x8B49, 0xF1FC, 0x8D08, 0xF1FD, 0x4E4B, 0xF1FE, 0x53EA, + 0xF2A1, 0x54AB, 0xF2A2, 0x5730, 0xF2A3, 0x5740, 0xF2A4, 0x5FD7, 0xF2A5, 0x6301, 0xF2A6, 0x6307, 0xF2A7, 0x646F, 0xF2A8, 0x652F, + 0xF2A9, 0x65E8, 0xF2AA, 0x667A, 0xF2AB, 0x679D, 0xF2AC, 0x67B3, 0xF2AD, 0x6B62, 0xF2AE, 0x6C60, 0xF2AF, 0x6C9A, 0xF2B0, 0x6F2C, + 0xF2B1, 0x77E5, 0xF2B2, 0x7825, 0xF2B3, 0x7949, 0xF2B4, 0x7957, 0xF2B5, 0x7D19, 0xF2B6, 0x80A2, 0xF2B7, 0x8102, 0xF2B8, 0x81F3, + 0xF2B9, 0x829D, 0xF2BA, 0x82B7, 0xF2BB, 0x8718, 0xF2BC, 0x8A8C, 0xF2BD, 0xF9FC, 0xF2BE, 0x8D04, 0xF2BF, 0x8DBE, 0xF2C0, 0x9072, + 0xF2C1, 0x76F4, 0xF2C2, 0x7A19, 0xF2C3, 0x7A37, 0xF2C4, 0x7E54, 0xF2C5, 0x8077, 0xF2C6, 0x5507, 0xF2C7, 0x55D4, 0xF2C8, 0x5875, + 0xF2C9, 0x632F, 0xF2CA, 0x6422, 0xF2CB, 0x6649, 0xF2CC, 0x664B, 0xF2CD, 0x686D, 0xF2CE, 0x699B, 0xF2CF, 0x6B84, 0xF2D0, 0x6D25, + 0xF2D1, 0x6EB1, 0xF2D2, 0x73CD, 0xF2D3, 0x7468, 0xF2D4, 0x74A1, 0xF2D5, 0x755B, 0xF2D6, 0x75B9, 0xF2D7, 0x76E1, 0xF2D8, 0x771E, + 0xF2D9, 0x778B, 0xF2DA, 0x79E6, 0xF2DB, 0x7E09, 0xF2DC, 0x7E1D, 0xF2DD, 0x81FB, 0xF2DE, 0x852F, 0xF2DF, 0x8897, 0xF2E0, 0x8A3A, + 0xF2E1, 0x8CD1, 0xF2E2, 0x8EEB, 0xF2E3, 0x8FB0, 0xF2E4, 0x9032, 0xF2E5, 0x93AD, 0xF2E6, 0x9663, 0xF2E7, 0x9673, 0xF2E8, 0x9707, + 0xF2E9, 0x4F84, 0xF2EA, 0x53F1, 0xF2EB, 0x59EA, 0xF2EC, 0x5AC9, 0xF2ED, 0x5E19, 0xF2EE, 0x684E, 0xF2EF, 0x74C6, 0xF2F0, 0x75BE, + 0xF2F1, 0x79E9, 0xF2F2, 0x7A92, 0xF2F3, 0x81A3, 0xF2F4, 0x86ED, 0xF2F5, 0x8CEA, 0xF2F6, 0x8DCC, 0xF2F7, 0x8FED, 0xF2F8, 0x659F, + 0xF2F9, 0x6715, 0xF2FA, 0xF9FD, 0xF2FB, 0x57F7, 0xF2FC, 0x6F57, 0xF2FD, 0x7DDD, 0xF2FE, 0x8F2F, 0xF3A1, 0x93F6, 0xF3A2, 0x96C6, + 0xF3A3, 0x5FB5, 0xF3A4, 0x61F2, 0xF3A5, 0x6F84, 0xF3A6, 0x4E14, 0xF3A7, 0x4F98, 0xF3A8, 0x501F, 0xF3A9, 0x53C9, 0xF3AA, 0x55DF, + 0xF3AB, 0x5D6F, 0xF3AC, 0x5DEE, 0xF3AD, 0x6B21, 0xF3AE, 0x6B64, 0xF3AF, 0x78CB, 0xF3B0, 0x7B9A, 0xF3B1, 0xF9FE, 0xF3B2, 0x8E49, + 0xF3B3, 0x8ECA, 0xF3B4, 0x906E, 0xF3B5, 0x6349, 0xF3B6, 0x643E, 0xF3B7, 0x7740, 0xF3B8, 0x7A84, 0xF3B9, 0x932F, 0xF3BA, 0x947F, + 0xF3BB, 0x9F6A, 0xF3BC, 0x64B0, 0xF3BD, 0x6FAF, 0xF3BE, 0x71E6, 0xF3BF, 0x74A8, 0xF3C0, 0x74DA, 0xF3C1, 0x7AC4, 0xF3C2, 0x7C12, + 0xF3C3, 0x7E82, 0xF3C4, 0x7CB2, 0xF3C5, 0x7E98, 0xF3C6, 0x8B9A, 0xF3C7, 0x8D0A, 0xF3C8, 0x947D, 0xF3C9, 0x9910, 0xF3CA, 0x994C, + 0xF3CB, 0x5239, 0xF3CC, 0x5BDF, 0xF3CD, 0x64E6, 0xF3CE, 0x672D, 0xF3CF, 0x7D2E, 0xF3D0, 0x50ED, 0xF3D1, 0x53C3, 0xF3D2, 0x5879, + 0xF3D3, 0x6158, 0xF3D4, 0x6159, 0xF3D5, 0x61FA, 0xF3D6, 0x65AC, 0xF3D7, 0x7AD9, 0xF3D8, 0x8B92, 0xF3D9, 0x8B96, 0xF3DA, 0x5009, + 0xF3DB, 0x5021, 0xF3DC, 0x5275, 0xF3DD, 0x5531, 0xF3DE, 0x5A3C, 0xF3DF, 0x5EE0, 0xF3E0, 0x5F70, 0xF3E1, 0x6134, 0xF3E2, 0x655E, + 0xF3E3, 0x660C, 0xF3E4, 0x6636, 0xF3E5, 0x66A2, 0xF3E6, 0x69CD, 0xF3E7, 0x6EC4, 0xF3E8, 0x6F32, 0xF3E9, 0x7316, 0xF3EA, 0x7621, + 0xF3EB, 0x7A93, 0xF3EC, 0x8139, 0xF3ED, 0x8259, 0xF3EE, 0x83D6, 0xF3EF, 0x84BC, 0xF3F0, 0x50B5, 0xF3F1, 0x57F0, 0xF3F2, 0x5BC0, + 0xF3F3, 0x5BE8, 0xF3F4, 0x5F69, 0xF3F5, 0x63A1, 0xF3F6, 0x7826, 0xF3F7, 0x7DB5, 0xF3F8, 0x83DC, 0xF3F9, 0x8521, 0xF3FA, 0x91C7, + 0xF3FB, 0x91F5, 0xF3FC, 0x518A, 0xF3FD, 0x67F5, 0xF3FE, 0x7B56, 0xF4A1, 0x8CAC, 0xF4A2, 0x51C4, 0xF4A3, 0x59BB, 0xF4A4, 0x60BD, + 0xF4A5, 0x8655, 0xF4A6, 0x501C, 0xF4A7, 0xF9FF, 0xF4A8, 0x5254, 0xF4A9, 0x5C3A, 0xF4AA, 0x617D, 0xF4AB, 0x621A, 0xF4AC, 0x62D3, + 0xF4AD, 0x64F2, 0xF4AE, 0x65A5, 0xF4AF, 0x6ECC, 0xF4B0, 0x7620, 0xF4B1, 0x810A, 0xF4B2, 0x8E60, 0xF4B3, 0x965F, 0xF4B4, 0x96BB, + 0xF4B5, 0x4EDF, 0xF4B6, 0x5343, 0xF4B7, 0x5598, 0xF4B8, 0x5929, 0xF4B9, 0x5DDD, 0xF4BA, 0x64C5, 0xF4BB, 0x6CC9, 0xF4BC, 0x6DFA, + 0xF4BD, 0x7394, 0xF4BE, 0x7A7F, 0xF4BF, 0x821B, 0xF4C0, 0x85A6, 0xF4C1, 0x8CE4, 0xF4C2, 0x8E10, 0xF4C3, 0x9077, 0xF4C4, 0x91E7, + 0xF4C5, 0x95E1, 0xF4C6, 0x9621, 0xF4C7, 0x97C6, 0xF4C8, 0x51F8, 0xF4C9, 0x54F2, 0xF4CA, 0x5586, 0xF4CB, 0x5FB9, 0xF4CC, 0x64A4, + 0xF4CD, 0x6F88, 0xF4CE, 0x7DB4, 0xF4CF, 0x8F1F, 0xF4D0, 0x8F4D, 0xF4D1, 0x9435, 0xF4D2, 0x50C9, 0xF4D3, 0x5C16, 0xF4D4, 0x6CBE, + 0xF4D5, 0x6DFB, 0xF4D6, 0x751B, 0xF4D7, 0x77BB, 0xF4D8, 0x7C3D, 0xF4D9, 0x7C64, 0xF4DA, 0x8A79, 0xF4DB, 0x8AC2, 0xF4DC, 0x581E, + 0xF4DD, 0x59BE, 0xF4DE, 0x5E16, 0xF4DF, 0x6377, 0xF4E0, 0x7252, 0xF4E1, 0x758A, 0xF4E2, 0x776B, 0xF4E3, 0x8ADC, 0xF4E4, 0x8CBC, + 0xF4E5, 0x8F12, 0xF4E6, 0x5EF3, 0xF4E7, 0x6674, 0xF4E8, 0x6DF8, 0xF4E9, 0x807D, 0xF4EA, 0x83C1, 0xF4EB, 0x8ACB, 0xF4EC, 0x9751, + 0xF4ED, 0x9BD6, 0xF4EE, 0xFA00, 0xF4EF, 0x5243, 0xF4F0, 0x66FF, 0xF4F1, 0x6D95, 0xF4F2, 0x6EEF, 0xF4F3, 0x7DE0, 0xF4F4, 0x8AE6, + 0xF4F5, 0x902E, 0xF4F6, 0x905E, 0xF4F7, 0x9AD4, 0xF4F8, 0x521D, 0xF4F9, 0x527F, 0xF4FA, 0x54E8, 0xF4FB, 0x6194, 0xF4FC, 0x6284, + 0xF4FD, 0x62DB, 0xF4FE, 0x68A2, 0xF5A1, 0x6912, 0xF5A2, 0x695A, 0xF5A3, 0x6A35, 0xF5A4, 0x7092, 0xF5A5, 0x7126, 0xF5A6, 0x785D, + 0xF5A7, 0x7901, 0xF5A8, 0x790E, 0xF5A9, 0x79D2, 0xF5AA, 0x7A0D, 0xF5AB, 0x8096, 0xF5AC, 0x8278, 0xF5AD, 0x82D5, 0xF5AE, 0x8349, + 0xF5AF, 0x8549, 0xF5B0, 0x8C82, 0xF5B1, 0x8D85, 0xF5B2, 0x9162, 0xF5B3, 0x918B, 0xF5B4, 0x91AE, 0xF5B5, 0x4FC3, 0xF5B6, 0x56D1, + 0xF5B7, 0x71ED, 0xF5B8, 0x77D7, 0xF5B9, 0x8700, 0xF5BA, 0x89F8, 0xF5BB, 0x5BF8, 0xF5BC, 0x5FD6, 0xF5BD, 0x6751, 0xF5BE, 0x90A8, + 0xF5BF, 0x53E2, 0xF5C0, 0x585A, 0xF5C1, 0x5BF5, 0xF5C2, 0x60A4, 0xF5C3, 0x6181, 0xF5C4, 0x6460, 0xF5C5, 0x7E3D, 0xF5C6, 0x8070, + 0xF5C7, 0x8525, 0xF5C8, 0x9283, 0xF5C9, 0x64AE, 0xF5CA, 0x50AC, 0xF5CB, 0x5D14, 0xF5CC, 0x6700, 0xF5CD, 0x589C, 0xF5CE, 0x62BD, + 0xF5CF, 0x63A8, 0xF5D0, 0x690E, 0xF5D1, 0x6978, 0xF5D2, 0x6A1E, 0xF5D3, 0x6E6B, 0xF5D4, 0x76BA, 0xF5D5, 0x79CB, 0xF5D6, 0x82BB, + 0xF5D7, 0x8429, 0xF5D8, 0x8ACF, 0xF5D9, 0x8DA8, 0xF5DA, 0x8FFD, 0xF5DB, 0x9112, 0xF5DC, 0x914B, 0xF5DD, 0x919C, 0xF5DE, 0x9310, + 0xF5DF, 0x9318, 0xF5E0, 0x939A, 0xF5E1, 0x96DB, 0xF5E2, 0x9A36, 0xF5E3, 0x9C0D, 0xF5E4, 0x4E11, 0xF5E5, 0x755C, 0xF5E6, 0x795D, + 0xF5E7, 0x7AFA, 0xF5E8, 0x7B51, 0xF5E9, 0x7BC9, 0xF5EA, 0x7E2E, 0xF5EB, 0x84C4, 0xF5EC, 0x8E59, 0xF5ED, 0x8E74, 0xF5EE, 0x8EF8, + 0xF5EF, 0x9010, 0xF5F0, 0x6625, 0xF5F1, 0x693F, 0xF5F2, 0x7443, 0xF5F3, 0x51FA, 0xF5F4, 0x672E, 0xF5F5, 0x9EDC, 0xF5F6, 0x5145, + 0xF5F7, 0x5FE0, 0xF5F8, 0x6C96, 0xF5F9, 0x87F2, 0xF5FA, 0x885D, 0xF5FB, 0x8877, 0xF5FC, 0x60B4, 0xF5FD, 0x81B5, 0xF5FE, 0x8403, + 0xF6A1, 0x8D05, 0xF6A2, 0x53D6, 0xF6A3, 0x5439, 0xF6A4, 0x5634, 0xF6A5, 0x5A36, 0xF6A6, 0x5C31, 0xF6A7, 0x708A, 0xF6A8, 0x7FE0, + 0xF6A9, 0x805A, 0xF6AA, 0x8106, 0xF6AB, 0x81ED, 0xF6AC, 0x8DA3, 0xF6AD, 0x9189, 0xF6AE, 0x9A5F, 0xF6AF, 0x9DF2, 0xF6B0, 0x5074, + 0xF6B1, 0x4EC4, 0xF6B2, 0x53A0, 0xF6B3, 0x60FB, 0xF6B4, 0x6E2C, 0xF6B5, 0x5C64, 0xF6B6, 0x4F88, 0xF6B7, 0x5024, 0xF6B8, 0x55E4, + 0xF6B9, 0x5CD9, 0xF6BA, 0x5E5F, 0xF6BB, 0x6065, 0xF6BC, 0x6894, 0xF6BD, 0x6CBB, 0xF6BE, 0x6DC4, 0xF6BF, 0x71BE, 0xF6C0, 0x75D4, + 0xF6C1, 0x75F4, 0xF6C2, 0x7661, 0xF6C3, 0x7A1A, 0xF6C4, 0x7A49, 0xF6C5, 0x7DC7, 0xF6C6, 0x7DFB, 0xF6C7, 0x7F6E, 0xF6C8, 0x81F4, + 0xF6C9, 0x86A9, 0xF6CA, 0x8F1C, 0xF6CB, 0x96C9, 0xF6CC, 0x99B3, 0xF6CD, 0x9F52, 0xF6CE, 0x5247, 0xF6CF, 0x52C5, 0xF6D0, 0x98ED, + 0xF6D1, 0x89AA, 0xF6D2, 0x4E03, 0xF6D3, 0x67D2, 0xF6D4, 0x6F06, 0xF6D5, 0x4FB5, 0xF6D6, 0x5BE2, 0xF6D7, 0x6795, 0xF6D8, 0x6C88, + 0xF6D9, 0x6D78, 0xF6DA, 0x741B, 0xF6DB, 0x7827, 0xF6DC, 0x91DD, 0xF6DD, 0x937C, 0xF6DE, 0x87C4, 0xF6DF, 0x79E4, 0xF6E0, 0x7A31, + 0xF6E1, 0x5FEB, 0xF6E2, 0x4ED6, 0xF6E3, 0x54A4, 0xF6E4, 0x553E, 0xF6E5, 0x58AE, 0xF6E6, 0x59A5, 0xF6E7, 0x60F0, 0xF6E8, 0x6253, + 0xF6E9, 0x62D6, 0xF6EA, 0x6736, 0xF6EB, 0x6955, 0xF6EC, 0x8235, 0xF6ED, 0x9640, 0xF6EE, 0x99B1, 0xF6EF, 0x99DD, 0xF6F0, 0x502C, + 0xF6F1, 0x5353, 0xF6F2, 0x5544, 0xF6F3, 0x577C, 0xF6F4, 0xFA01, 0xF6F5, 0x6258, 0xF6F6, 0xFA02, 0xF6F7, 0x64E2, 0xF6F8, 0x666B, + 0xF6F9, 0x67DD, 0xF6FA, 0x6FC1, 0xF6FB, 0x6FEF, 0xF6FC, 0x7422, 0xF6FD, 0x7438, 0xF6FE, 0x8A17, 0xF7A1, 0x9438, 0xF7A2, 0x5451, + 0xF7A3, 0x5606, 0xF7A4, 0x5766, 0xF7A5, 0x5F48, 0xF7A6, 0x619A, 0xF7A7, 0x6B4E, 0xF7A8, 0x7058, 0xF7A9, 0x70AD, 0xF7AA, 0x7DBB, + 0xF7AB, 0x8A95, 0xF7AC, 0x596A, 0xF7AD, 0x812B, 0xF7AE, 0x63A2, 0xF7AF, 0x7708, 0xF7B0, 0x803D, 0xF7B1, 0x8CAA, 0xF7B2, 0x5854, + 0xF7B3, 0x642D, 0xF7B4, 0x69BB, 0xF7B5, 0x5B95, 0xF7B6, 0x5E11, 0xF7B7, 0x6E6F, 0xF7B8, 0xFA03, 0xF7B9, 0x8569, 0xF7BA, 0x514C, + 0xF7BB, 0x53F0, 0xF7BC, 0x592A, 0xF7BD, 0x6020, 0xF7BE, 0x614B, 0xF7BF, 0x6B86, 0xF7C0, 0x6C70, 0xF7C1, 0x6CF0, 0xF7C2, 0x7B1E, + 0xF7C3, 0x80CE, 0xF7C4, 0x82D4, 0xF7C5, 0x8DC6, 0xF7C6, 0x90B0, 0xF7C7, 0x98B1, 0xF7C8, 0xFA04, 0xF7C9, 0x64C7, 0xF7CA, 0x6FA4, + 0xF7CB, 0x6491, 0xF7CC, 0x6504, 0xF7CD, 0x514E, 0xF7CE, 0x5410, 0xF7CF, 0x571F, 0xF7D0, 0x8A0E, 0xF7D1, 0x615F, 0xF7D2, 0x6876, + 0xF7D3, 0xFA05, 0xF7D4, 0x75DB, 0xF7D5, 0x7B52, 0xF7D6, 0x7D71, 0xF7D7, 0x901A, 0xF7D8, 0x5806, 0xF7D9, 0x69CC, 0xF7DA, 0x817F, + 0xF7DB, 0x892A, 0xF7DC, 0x9000, 0xF7DD, 0x9839, 0xF7DE, 0x5078, 0xF7DF, 0x5957, 0xF7E0, 0x59AC, 0xF7E1, 0x6295, 0xF7E2, 0x900F, + 0xF7E3, 0x9B2A, 0xF7E4, 0x615D, 0xF7E5, 0x7279, 0xF7E6, 0x95D6, 0xF7E7, 0x5761, 0xF7E8, 0x5A46, 0xF7E9, 0x5DF4, 0xF7EA, 0x628A, + 0xF7EB, 0x64AD, 0xF7EC, 0x64FA, 0xF7ED, 0x6777, 0xF7EE, 0x6CE2, 0xF7EF, 0x6D3E, 0xF7F0, 0x722C, 0xF7F1, 0x7436, 0xF7F2, 0x7834, + 0xF7F3, 0x7F77, 0xF7F4, 0x82AD, 0xF7F5, 0x8DDB, 0xF7F6, 0x9817, 0xF7F7, 0x5224, 0xF7F8, 0x5742, 0xF7F9, 0x677F, 0xF7FA, 0x7248, + 0xF7FB, 0x74E3, 0xF7FC, 0x8CA9, 0xF7FD, 0x8FA6, 0xF7FE, 0x9211, 0xF8A1, 0x962A, 0xF8A2, 0x516B, 0xF8A3, 0x53ED, 0xF8A4, 0x634C, + 0xF8A5, 0x4F69, 0xF8A6, 0x5504, 0xF8A7, 0x6096, 0xF8A8, 0x6557, 0xF8A9, 0x6C9B, 0xF8AA, 0x6D7F, 0xF8AB, 0x724C, 0xF8AC, 0x72FD, + 0xF8AD, 0x7A17, 0xF8AE, 0x8987, 0xF8AF, 0x8C9D, 0xF8B0, 0x5F6D, 0xF8B1, 0x6F8E, 0xF8B2, 0x70F9, 0xF8B3, 0x81A8, 0xF8B4, 0x610E, + 0xF8B5, 0x4FBF, 0xF8B6, 0x504F, 0xF8B7, 0x6241, 0xF8B8, 0x7247, 0xF8B9, 0x7BC7, 0xF8BA, 0x7DE8, 0xF8BB, 0x7FE9, 0xF8BC, 0x904D, + 0xF8BD, 0x97AD, 0xF8BE, 0x9A19, 0xF8BF, 0x8CB6, 0xF8C0, 0x576A, 0xF8C1, 0x5E73, 0xF8C2, 0x67B0, 0xF8C3, 0x840D, 0xF8C4, 0x8A55, + 0xF8C5, 0x5420, 0xF8C6, 0x5B16, 0xF8C7, 0x5E63, 0xF8C8, 0x5EE2, 0xF8C9, 0x5F0A, 0xF8CA, 0x6583, 0xF8CB, 0x80BA, 0xF8CC, 0x853D, + 0xF8CD, 0x9589, 0xF8CE, 0x965B, 0xF8CF, 0x4F48, 0xF8D0, 0x5305, 0xF8D1, 0x530D, 0xF8D2, 0x530F, 0xF8D3, 0x5486, 0xF8D4, 0x54FA, + 0xF8D5, 0x5703, 0xF8D6, 0x5E03, 0xF8D7, 0x6016, 0xF8D8, 0x629B, 0xF8D9, 0x62B1, 0xF8DA, 0x6355, 0xF8DB, 0xFA06, 0xF8DC, 0x6CE1, + 0xF8DD, 0x6D66, 0xF8DE, 0x75B1, 0xF8DF, 0x7832, 0xF8E0, 0x80DE, 0xF8E1, 0x812F, 0xF8E2, 0x82DE, 0xF8E3, 0x8461, 0xF8E4, 0x84B2, + 0xF8E5, 0x888D, 0xF8E6, 0x8912, 0xF8E7, 0x900B, 0xF8E8, 0x92EA, 0xF8E9, 0x98FD, 0xF8EA, 0x9B91, 0xF8EB, 0x5E45, 0xF8EC, 0x66B4, + 0xF8ED, 0x66DD, 0xF8EE, 0x7011, 0xF8EF, 0x7206, 0xF8F0, 0xFA07, 0xF8F1, 0x4FF5, 0xF8F2, 0x527D, 0xF8F3, 0x5F6A, 0xF8F4, 0x6153, + 0xF8F5, 0x6753, 0xF8F6, 0x6A19, 0xF8F7, 0x6F02, 0xF8F8, 0x74E2, 0xF8F9, 0x7968, 0xF8FA, 0x8868, 0xF8FB, 0x8C79, 0xF8FC, 0x98C7, + 0xF8FD, 0x98C4, 0xF8FE, 0x9A43, 0xF9A1, 0x54C1, 0xF9A2, 0x7A1F, 0xF9A3, 0x6953, 0xF9A4, 0x8AF7, 0xF9A5, 0x8C4A, 0xF9A6, 0x98A8, + 0xF9A7, 0x99AE, 0xF9A8, 0x5F7C, 0xF9A9, 0x62AB, 0xF9AA, 0x75B2, 0xF9AB, 0x76AE, 0xF9AC, 0x88AB, 0xF9AD, 0x907F, 0xF9AE, 0x9642, + 0xF9AF, 0x5339, 0xF9B0, 0x5F3C, 0xF9B1, 0x5FC5, 0xF9B2, 0x6CCC, 0xF9B3, 0x73CC, 0xF9B4, 0x7562, 0xF9B5, 0x758B, 0xF9B6, 0x7B46, + 0xF9B7, 0x82FE, 0xF9B8, 0x999D, 0xF9B9, 0x4E4F, 0xF9BA, 0x903C, 0xF9BB, 0x4E0B, 0xF9BC, 0x4F55, 0xF9BD, 0x53A6, 0xF9BE, 0x590F, + 0xF9BF, 0x5EC8, 0xF9C0, 0x6630, 0xF9C1, 0x6CB3, 0xF9C2, 0x7455, 0xF9C3, 0x8377, 0xF9C4, 0x8766, 0xF9C5, 0x8CC0, 0xF9C6, 0x9050, + 0xF9C7, 0x971E, 0xF9C8, 0x9C15, 0xF9C9, 0x58D1, 0xF9CA, 0x5B78, 0xF9CB, 0x8650, 0xF9CC, 0x8B14, 0xF9CD, 0x9DB4, 0xF9CE, 0x5BD2, + 0xF9CF, 0x6068, 0xF9D0, 0x608D, 0xF9D1, 0x65F1, 0xF9D2, 0x6C57, 0xF9D3, 0x6F22, 0xF9D4, 0x6FA3, 0xF9D5, 0x701A, 0xF9D6, 0x7F55, + 0xF9D7, 0x7FF0, 0xF9D8, 0x9591, 0xF9D9, 0x9592, 0xF9DA, 0x9650, 0xF9DB, 0x97D3, 0xF9DC, 0x5272, 0xF9DD, 0x8F44, 0xF9DE, 0x51FD, + 0xF9DF, 0x542B, 0xF9E0, 0x54B8, 0xF9E1, 0x5563, 0xF9E2, 0x558A, 0xF9E3, 0x6ABB, 0xF9E4, 0x6DB5, 0xF9E5, 0x7DD8, 0xF9E6, 0x8266, + 0xF9E7, 0x929C, 0xF9E8, 0x9677, 0xF9E9, 0x9E79, 0xF9EA, 0x5408, 0xF9EB, 0x54C8, 0xF9EC, 0x76D2, 0xF9ED, 0x86E4, 0xF9EE, 0x95A4, + 0xF9EF, 0x95D4, 0xF9F0, 0x965C, 0xF9F1, 0x4EA2, 0xF9F2, 0x4F09, 0xF9F3, 0x59EE, 0xF9F4, 0x5AE6, 0xF9F5, 0x5DF7, 0xF9F6, 0x6052, + 0xF9F7, 0x6297, 0xF9F8, 0x676D, 0xF9F9, 0x6841, 0xF9FA, 0x6C86, 0xF9FB, 0x6E2F, 0xF9FC, 0x7F38, 0xF9FD, 0x809B, 0xF9FE, 0x822A, + 0xFAA1, 0xFA08, 0xFAA2, 0xFA09, 0xFAA3, 0x9805, 0xFAA4, 0x4EA5, 0xFAA5, 0x5055, 0xFAA6, 0x54B3, 0xFAA7, 0x5793, 0xFAA8, 0x595A, + 0xFAA9, 0x5B69, 0xFAAA, 0x5BB3, 0xFAAB, 0x61C8, 0xFAAC, 0x6977, 0xFAAD, 0x6D77, 0xFAAE, 0x7023, 0xFAAF, 0x87F9, 0xFAB0, 0x89E3, + 0xFAB1, 0x8A72, 0xFAB2, 0x8AE7, 0xFAB3, 0x9082, 0xFAB4, 0x99ED, 0xFAB5, 0x9AB8, 0xFAB6, 0x52BE, 0xFAB7, 0x6838, 0xFAB8, 0x5016, + 0xFAB9, 0x5E78, 0xFABA, 0x674F, 0xFABB, 0x8347, 0xFABC, 0x884C, 0xFABD, 0x4EAB, 0xFABE, 0x5411, 0xFABF, 0x56AE, 0xFAC0, 0x73E6, + 0xFAC1, 0x9115, 0xFAC2, 0x97FF, 0xFAC3, 0x9909, 0xFAC4, 0x9957, 0xFAC5, 0x9999, 0xFAC6, 0x5653, 0xFAC7, 0x589F, 0xFAC8, 0x865B, + 0xFAC9, 0x8A31, 0xFACA, 0x61B2, 0xFACB, 0x6AF6, 0xFACC, 0x737B, 0xFACD, 0x8ED2, 0xFACE, 0x6B47, 0xFACF, 0x96AA, 0xFAD0, 0x9A57, + 0xFAD1, 0x5955, 0xFAD2, 0x7200, 0xFAD3, 0x8D6B, 0xFAD4, 0x9769, 0xFAD5, 0x4FD4, 0xFAD6, 0x5CF4, 0xFAD7, 0x5F26, 0xFAD8, 0x61F8, + 0xFAD9, 0x665B, 0xFADA, 0x6CEB, 0xFADB, 0x70AB, 0xFADC, 0x7384, 0xFADD, 0x73B9, 0xFADE, 0x73FE, 0xFADF, 0x7729, 0xFAE0, 0x774D, + 0xFAE1, 0x7D43, 0xFAE2, 0x7D62, 0xFAE3, 0x7E23, 0xFAE4, 0x8237, 0xFAE5, 0x8852, 0xFAE6, 0xFA0A, 0xFAE7, 0x8CE2, 0xFAE8, 0x9249, + 0xFAE9, 0x986F, 0xFAEA, 0x5B51, 0xFAEB, 0x7A74, 0xFAEC, 0x8840, 0xFAED, 0x9801, 0xFAEE, 0x5ACC, 0xFAEF, 0x4FE0, 0xFAF0, 0x5354, + 0xFAF1, 0x593E, 0xFAF2, 0x5CFD, 0xFAF3, 0x633E, 0xFAF4, 0x6D79, 0xFAF5, 0x72F9, 0xFAF6, 0x8105, 0xFAF7, 0x8107, 0xFAF8, 0x83A2, + 0xFAF9, 0x92CF, 0xFAFA, 0x9830, 0xFAFB, 0x4EA8, 0xFAFC, 0x5144, 0xFAFD, 0x5211, 0xFAFE, 0x578B, 0xFBA1, 0x5F62, 0xFBA2, 0x6CC2, + 0xFBA3, 0x6ECE, 0xFBA4, 0x7005, 0xFBA5, 0x7050, 0xFBA6, 0x70AF, 0xFBA7, 0x7192, 0xFBA8, 0x73E9, 0xFBA9, 0x7469, 0xFBAA, 0x834A, + 0xFBAB, 0x87A2, 0xFBAC, 0x8861, 0xFBAD, 0x9008, 0xFBAE, 0x90A2, 0xFBAF, 0x93A3, 0xFBB0, 0x99A8, 0xFBB1, 0x516E, 0xFBB2, 0x5F57, + 0xFBB3, 0x60E0, 0xFBB4, 0x6167, 0xFBB5, 0x66B3, 0xFBB6, 0x8559, 0xFBB7, 0x8E4A, 0xFBB8, 0x91AF, 0xFBB9, 0x978B, 0xFBBA, 0x4E4E, + 0xFBBB, 0x4E92, 0xFBBC, 0x547C, 0xFBBD, 0x58D5, 0xFBBE, 0x58FA, 0xFBBF, 0x597D, 0xFBC0, 0x5CB5, 0xFBC1, 0x5F27, 0xFBC2, 0x6236, + 0xFBC3, 0x6248, 0xFBC4, 0x660A, 0xFBC5, 0x6667, 0xFBC6, 0x6BEB, 0xFBC7, 0x6D69, 0xFBC8, 0x6DCF, 0xFBC9, 0x6E56, 0xFBCA, 0x6EF8, + 0xFBCB, 0x6F94, 0xFBCC, 0x6FE0, 0xFBCD, 0x6FE9, 0xFBCE, 0x705D, 0xFBCF, 0x72D0, 0xFBD0, 0x7425, 0xFBD1, 0x745A, 0xFBD2, 0x74E0, + 0xFBD3, 0x7693, 0xFBD4, 0x795C, 0xFBD5, 0x7CCA, 0xFBD6, 0x7E1E, 0xFBD7, 0x80E1, 0xFBD8, 0x82A6, 0xFBD9, 0x846B, 0xFBDA, 0x84BF, + 0xFBDB, 0x864E, 0xFBDC, 0x865F, 0xFBDD, 0x8774, 0xFBDE, 0x8B77, 0xFBDF, 0x8C6A, 0xFBE0, 0x93AC, 0xFBE1, 0x9800, 0xFBE2, 0x9865, + 0xFBE3, 0x60D1, 0xFBE4, 0x6216, 0xFBE5, 0x9177, 0xFBE6, 0x5A5A, 0xFBE7, 0x660F, 0xFBE8, 0x6DF7, 0xFBE9, 0x6E3E, 0xFBEA, 0x743F, + 0xFBEB, 0x9B42, 0xFBEC, 0x5FFD, 0xFBED, 0x60DA, 0xFBEE, 0x7B0F, 0xFBEF, 0x54C4, 0xFBF0, 0x5F18, 0xFBF1, 0x6C5E, 0xFBF2, 0x6CD3, + 0xFBF3, 0x6D2A, 0xFBF4, 0x70D8, 0xFBF5, 0x7D05, 0xFBF6, 0x8679, 0xFBF7, 0x8A0C, 0xFBF8, 0x9D3B, 0xFBF9, 0x5316, 0xFBFA, 0x548C, + 0xFBFB, 0x5B05, 0xFBFC, 0x6A3A, 0xFBFD, 0x706B, 0xFBFE, 0x7575, 0xFCA1, 0x798D, 0xFCA2, 0x79BE, 0xFCA3, 0x82B1, 0xFCA4, 0x83EF, + 0xFCA5, 0x8A71, 0xFCA6, 0x8B41, 0xFCA7, 0x8CA8, 0xFCA8, 0x9774, 0xFCA9, 0xFA0B, 0xFCAA, 0x64F4, 0xFCAB, 0x652B, 0xFCAC, 0x78BA, + 0xFCAD, 0x78BB, 0xFCAE, 0x7A6B, 0xFCAF, 0x4E38, 0xFCB0, 0x559A, 0xFCB1, 0x5950, 0xFCB2, 0x5BA6, 0xFCB3, 0x5E7B, 0xFCB4, 0x60A3, + 0xFCB5, 0x63DB, 0xFCB6, 0x6B61, 0xFCB7, 0x6665, 0xFCB8, 0x6853, 0xFCB9, 0x6E19, 0xFCBA, 0x7165, 0xFCBB, 0x74B0, 0xFCBC, 0x7D08, + 0xFCBD, 0x9084, 0xFCBE, 0x9A69, 0xFCBF, 0x9C25, 0xFCC0, 0x6D3B, 0xFCC1, 0x6ED1, 0xFCC2, 0x733E, 0xFCC3, 0x8C41, 0xFCC4, 0x95CA, + 0xFCC5, 0x51F0, 0xFCC6, 0x5E4C, 0xFCC7, 0x5FA8, 0xFCC8, 0x604D, 0xFCC9, 0x60F6, 0xFCCA, 0x6130, 0xFCCB, 0x614C, 0xFCCC, 0x6643, + 0xFCCD, 0x6644, 0xFCCE, 0x69A5, 0xFCCF, 0x6CC1, 0xFCD0, 0x6E5F, 0xFCD1, 0x6EC9, 0xFCD2, 0x6F62, 0xFCD3, 0x714C, 0xFCD4, 0x749C, + 0xFCD5, 0x7687, 0xFCD6, 0x7BC1, 0xFCD7, 0x7C27, 0xFCD8, 0x8352, 0xFCD9, 0x8757, 0xFCDA, 0x9051, 0xFCDB, 0x968D, 0xFCDC, 0x9EC3, + 0xFCDD, 0x532F, 0xFCDE, 0x56DE, 0xFCDF, 0x5EFB, 0xFCE0, 0x5F8A, 0xFCE1, 0x6062, 0xFCE2, 0x6094, 0xFCE3, 0x61F7, 0xFCE4, 0x6666, + 0xFCE5, 0x6703, 0xFCE6, 0x6A9C, 0xFCE7, 0x6DEE, 0xFCE8, 0x6FAE, 0xFCE9, 0x7070, 0xFCEA, 0x736A, 0xFCEB, 0x7E6A, 0xFCEC, 0x81BE, + 0xFCED, 0x8334, 0xFCEE, 0x86D4, 0xFCEF, 0x8AA8, 0xFCF0, 0x8CC4, 0xFCF1, 0x5283, 0xFCF2, 0x7372, 0xFCF3, 0x5B96, 0xFCF4, 0x6A6B, + 0xFCF5, 0x9404, 0xFCF6, 0x54EE, 0xFCF7, 0x5686, 0xFCF8, 0x5B5D, 0xFCF9, 0x6548, 0xFCFA, 0x6585, 0xFCFB, 0x66C9, 0xFCFC, 0x689F, + 0xFCFD, 0x6D8D, 0xFCFE, 0x6DC6, 0xFDA1, 0x723B, 0xFDA2, 0x80B4, 0xFDA3, 0x9175, 0xFDA4, 0x9A4D, 0xFDA5, 0x4FAF, 0xFDA6, 0x5019, + 0xFDA7, 0x539A, 0xFDA8, 0x540E, 0xFDA9, 0x543C, 0xFDAA, 0x5589, 0xFDAB, 0x55C5, 0xFDAC, 0x5E3F, 0xFDAD, 0x5F8C, 0xFDAE, 0x673D, + 0xFDAF, 0x7166, 0xFDB0, 0x73DD, 0xFDB1, 0x9005, 0xFDB2, 0x52DB, 0xFDB3, 0x52F3, 0xFDB4, 0x5864, 0xFDB5, 0x58CE, 0xFDB6, 0x7104, + 0xFDB7, 0x718F, 0xFDB8, 0x71FB, 0xFDB9, 0x85B0, 0xFDBA, 0x8A13, 0xFDBB, 0x6688, 0xFDBC, 0x85A8, 0xFDBD, 0x55A7, 0xFDBE, 0x6684, + 0xFDBF, 0x714A, 0xFDC0, 0x8431, 0xFDC1, 0x5349, 0xFDC2, 0x5599, 0xFDC3, 0x6BC1, 0xFDC4, 0x5F59, 0xFDC5, 0x5FBD, 0xFDC6, 0x63EE, + 0xFDC7, 0x6689, 0xFDC8, 0x7147, 0xFDC9, 0x8AF1, 0xFDCA, 0x8F1D, 0xFDCB, 0x9EBE, 0xFDCC, 0x4F11, 0xFDCD, 0x643A, 0xFDCE, 0x70CB, + 0xFDCF, 0x7566, 0xFDD0, 0x8667, 0xFDD1, 0x6064, 0xFDD2, 0x8B4E, 0xFDD3, 0x9DF8, 0xFDD4, 0x5147, 0xFDD5, 0x51F6, 0xFDD6, 0x5308, + 0xFDD7, 0x6D36, 0xFDD8, 0x80F8, 0xFDD9, 0x9ED1, 0xFDDA, 0x6615, 0xFDDB, 0x6B23, 0xFDDC, 0x7098, 0xFDDD, 0x75D5, 0xFDDE, 0x5403, + 0xFDDF, 0x5C79, 0xFDE0, 0x7D07, 0xFDE1, 0x8A16, 0xFDE2, 0x6B20, 0xFDE3, 0x6B3D, 0xFDE4, 0x6B46, 0xFDE5, 0x5438, 0xFDE6, 0x6070, + 0xFDE7, 0x6D3D, 0xFDE8, 0x7FD5, 0xFDE9, 0x8208, 0xFDEA, 0x50D6, 0xFDEB, 0x51DE, 0xFDEC, 0x559C, 0xFDED, 0x566B, 0xFDEE, 0x56CD, + 0xFDEF, 0x59EC, 0xFDF0, 0x5B09, 0xFDF1, 0x5E0C, 0xFDF2, 0x6199, 0xFDF3, 0x6198, 0xFDF4, 0x6231, 0xFDF5, 0x665E, 0xFDF6, 0x66E6, + 0xFDF7, 0x7199, 0xFDF8, 0x71B9, 0xFDF9, 0x71BA, 0xFDFA, 0x72A7, 0xFDFB, 0x79A7, 0xFDFC, 0x7A00, 0xFDFD, 0x7FB2, 0xFDFE, 0x8A70, + 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 950 || FF_CODE_PAGE == 0 /* Traditional Chinese */ +static const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */ + 0x00A7, 0xA1B1, 0x00AF, 0xA1C2, 0x00B0, 0xA258, 0x00B1, 0xA1D3, 0x00B7, 0xA150, 0x00D7, 0xA1D1, 0x00F7, 0xA1D2, 0x02C7, 0xA3BE, + 0x02C9, 0xA3BC, 0x02CA, 0xA3BD, 0x02CB, 0xA3BF, 0x02CD, 0xA1C5, 0x02D9, 0xA3BB, 0x0391, 0xA344, 0x0392, 0xA345, 0x0393, 0xA346, + 0x0394, 0xA347, 0x0395, 0xA348, 0x0396, 0xA349, 0x0397, 0xA34A, 0x0398, 0xA34B, 0x0399, 0xA34C, 0x039A, 0xA34D, 0x039B, 0xA34E, + 0x039C, 0xA34F, 0x039D, 0xA350, 0x039E, 0xA351, 0x039F, 0xA352, 0x03A0, 0xA353, 0x03A1, 0xA354, 0x03A3, 0xA355, 0x03A4, 0xA356, + 0x03A5, 0xA357, 0x03A6, 0xA358, 0x03A7, 0xA359, 0x03A8, 0xA35A, 0x03A9, 0xA35B, 0x03B1, 0xA35C, 0x03B2, 0xA35D, 0x03B3, 0xA35E, + 0x03B4, 0xA35F, 0x03B5, 0xA360, 0x03B6, 0xA361, 0x03B7, 0xA362, 0x03B8, 0xA363, 0x03B9, 0xA364, 0x03BA, 0xA365, 0x03BB, 0xA366, + 0x03BC, 0xA367, 0x03BD, 0xA368, 0x03BE, 0xA369, 0x03BF, 0xA36A, 0x03C0, 0xA36B, 0x03C1, 0xA36C, 0x03C3, 0xA36D, 0x03C4, 0xA36E, + 0x03C5, 0xA36F, 0x03C6, 0xA370, 0x03C7, 0xA371, 0x03C8, 0xA372, 0x03C9, 0xA373, 0x2013, 0xA156, 0x2014, 0xA158, 0x2018, 0xA1A5, + 0x2019, 0xA1A6, 0x201C, 0xA1A7, 0x201D, 0xA1A8, 0x2025, 0xA14C, 0x2026, 0xA14B, 0x2027, 0xA145, 0x2032, 0xA1AC, 0x2035, 0xA1AB, + 0x203B, 0xA1B0, 0x20AC, 0xA3E1, 0x2103, 0xA24A, 0x2105, 0xA1C1, 0x2109, 0xA24B, 0x2160, 0xA2B9, 0x2161, 0xA2BA, 0x2162, 0xA2BB, + 0x2163, 0xA2BC, 0x2164, 0xA2BD, 0x2165, 0xA2BE, 0x2166, 0xA2BF, 0x2167, 0xA2C0, 0x2168, 0xA2C1, 0x2169, 0xA2C2, 0x2190, 0xA1F6, + 0x2191, 0xA1F4, 0x2192, 0xA1F7, 0x2193, 0xA1F5, 0x2196, 0xA1F8, 0x2197, 0xA1F9, 0x2198, 0xA1FB, 0x2199, 0xA1FA, 0x2215, 0xA241, + 0x221A, 0xA1D4, 0x221E, 0xA1DB, 0x221F, 0xA1E8, 0x2220, 0xA1E7, 0x2223, 0xA1FD, 0x2225, 0xA1FC, 0x2229, 0xA1E4, 0x222A, 0xA1E5, + 0x222B, 0xA1EC, 0x222E, 0xA1ED, 0x2234, 0xA1EF, 0x2235, 0xA1EE, 0x2252, 0xA1DC, 0x2260, 0xA1DA, 0x2261, 0xA1DD, 0x2266, 0xA1D8, + 0x2267, 0xA1D9, 0x2295, 0xA1F2, 0x2299, 0xA1F3, 0x22A5, 0xA1E6, 0x22BF, 0xA1E9, 0x2500, 0xA277, 0x2502, 0xA278, 0x250C, 0xA27A, + 0x2510, 0xA27B, 0x2514, 0xA27C, 0x2518, 0xA27D, 0x251C, 0xA275, 0x2524, 0xA274, 0x252C, 0xA273, 0x2534, 0xA272, 0x253C, 0xA271, + 0x2550, 0xA2A4, 0x2550, 0xF9F9, 0x2551, 0xF9F8, 0x2552, 0xF9E6, 0x2553, 0xF9EF, 0x2554, 0xF9DD, 0x2555, 0xF9E8, 0x2556, 0xF9F1, + 0x2557, 0xF9DF, 0x2558, 0xF9EC, 0x2559, 0xF9F5, 0x255A, 0xF9E3, 0x255B, 0xF9EE, 0x255C, 0xF9F7, 0x255D, 0xF9E5, 0x255E, 0xA2A5, + 0x255E, 0xF9E9, 0x255F, 0xF9F2, 0x2560, 0xF9E0, 0x2561, 0xA2A7, 0x2561, 0xF9EB, 0x2562, 0xF9F4, 0x2563, 0xF9E2, 0x2564, 0xF9E7, + 0x2565, 0xF9F0, 0x2566, 0xF9DE, 0x2567, 0xF9ED, 0x2568, 0xF9F6, 0x2569, 0xF9E4, 0x256A, 0xA2A6, 0x256A, 0xF9EA, 0x256B, 0xF9F3, + 0x256C, 0xF9E1, 0x256D, 0xA27E, 0x256D, 0xF9FA, 0x256E, 0xA2A1, 0x256E, 0xF9FB, 0x256F, 0xA2A3, 0x256F, 0xF9FD, 0x2570, 0xA2A2, + 0x2570, 0xF9FC, 0x2571, 0xA2AC, 0x2572, 0xA2AD, 0x2573, 0xA2AE, 0x2574, 0xA15A, 0x2581, 0xA262, 0x2582, 0xA263, 0x2583, 0xA264, + 0x2584, 0xA265, 0x2585, 0xA266, 0x2586, 0xA267, 0x2587, 0xA268, 0x2588, 0xA269, 0x2589, 0xA270, 0x258A, 0xA26F, 0x258B, 0xA26E, + 0x258C, 0xA26D, 0x258D, 0xA26C, 0x258E, 0xA26B, 0x258F, 0xA26A, 0x2593, 0xF9FE, 0x2594, 0xA276, 0x2595, 0xA279, 0x25A0, 0xA1BD, + 0x25A1, 0xA1BC, 0x25B2, 0xA1B6, 0x25B3, 0xA1B5, 0x25BC, 0xA1BF, 0x25BD, 0xA1BE, 0x25C6, 0xA1BB, 0x25C7, 0xA1BA, 0x25CB, 0xA1B3, + 0x25CE, 0xA1B7, 0x25CF, 0xA1B4, 0x25E2, 0xA2A8, 0x25E3, 0xA2A9, 0x25E4, 0xA2AB, 0x25E5, 0xA2AA, 0x2605, 0xA1B9, 0x2606, 0xA1B8, + 0x2640, 0xA1F0, 0x2642, 0xA1F1, 0x3000, 0xA140, 0x3001, 0xA142, 0x3002, 0xA143, 0x3003, 0xA1B2, 0x3008, 0xA171, 0x3009, 0xA172, + 0x300A, 0xA16D, 0x300B, 0xA16E, 0x300C, 0xA175, 0x300D, 0xA176, 0x300E, 0xA179, 0x300F, 0xA17A, 0x3010, 0xA169, 0x3011, 0xA16A, + 0x3012, 0xA245, 0x3014, 0xA165, 0x3015, 0xA166, 0x301D, 0xA1A9, 0x301E, 0xA1AA, 0x3021, 0xA2C3, 0x3022, 0xA2C4, 0x3023, 0xA2C5, + 0x3024, 0xA2C6, 0x3025, 0xA2C7, 0x3026, 0xA2C8, 0x3027, 0xA2C9, 0x3028, 0xA2CA, 0x3029, 0xA2CB, 0x3105, 0xA374, 0x3106, 0xA375, + 0x3107, 0xA376, 0x3108, 0xA377, 0x3109, 0xA378, 0x310A, 0xA379, 0x310B, 0xA37A, 0x310C, 0xA37B, 0x310D, 0xA37C, 0x310E, 0xA37D, + 0x310F, 0xA37E, 0x3110, 0xA3A1, 0x3111, 0xA3A2, 0x3112, 0xA3A3, 0x3113, 0xA3A4, 0x3114, 0xA3A5, 0x3115, 0xA3A6, 0x3116, 0xA3A7, + 0x3117, 0xA3A8, 0x3118, 0xA3A9, 0x3119, 0xA3AA, 0x311A, 0xA3AB, 0x311B, 0xA3AC, 0x311C, 0xA3AD, 0x311D, 0xA3AE, 0x311E, 0xA3AF, + 0x311F, 0xA3B0, 0x3120, 0xA3B1, 0x3121, 0xA3B2, 0x3122, 0xA3B3, 0x3123, 0xA3B4, 0x3124, 0xA3B5, 0x3125, 0xA3B6, 0x3126, 0xA3B7, + 0x3127, 0xA3B8, 0x3128, 0xA3B9, 0x3129, 0xA3BA, 0x32A3, 0xA1C0, 0x338E, 0xA255, 0x338F, 0xA256, 0x339C, 0xA250, 0x339D, 0xA251, + 0x339E, 0xA252, 0x33A1, 0xA254, 0x33C4, 0xA257, 0x33CE, 0xA253, 0x33D1, 0xA1EB, 0x33D2, 0xA1EA, 0x33D5, 0xA24F, 0x4E00, 0xA440, + 0x4E01, 0xA442, 0x4E03, 0xA443, 0x4E07, 0xC945, 0x4E08, 0xA456, 0x4E09, 0xA454, 0x4E0A, 0xA457, 0x4E0B, 0xA455, 0x4E0C, 0xC946, + 0x4E0D, 0xA4A3, 0x4E0E, 0xC94F, 0x4E0F, 0xC94D, 0x4E10, 0xA4A2, 0x4E11, 0xA4A1, 0x4E14, 0xA542, 0x4E15, 0xA541, 0x4E16, 0xA540, + 0x4E18, 0xA543, 0x4E19, 0xA4FE, 0x4E1E, 0xA5E0, 0x4E1F, 0xA5E1, 0x4E26, 0xA8C3, 0x4E2B, 0xA458, 0x4E2D, 0xA4A4, 0x4E2E, 0xC950, + 0x4E30, 0xA4A5, 0x4E31, 0xC963, 0x4E32, 0xA6EA, 0x4E33, 0xCBB1, 0x4E38, 0xA459, 0x4E39, 0xA4A6, 0x4E3B, 0xA544, 0x4E3C, 0xC964, + 0x4E42, 0xC940, 0x4E43, 0xA444, 0x4E45, 0xA45B, 0x4E47, 0xC947, 0x4E48, 0xA45C, 0x4E4B, 0xA4A7, 0x4E4D, 0xA545, 0x4E4E, 0xA547, + 0x4E4F, 0xA546, 0x4E52, 0xA5E2, 0x4E53, 0xA5E3, 0x4E56, 0xA8C4, 0x4E58, 0xADBC, 0x4E59, 0xA441, 0x4E5C, 0xC941, 0x4E5D, 0xA445, + 0x4E5E, 0xA45E, 0x4E5F, 0xA45D, 0x4E69, 0xA5E4, 0x4E73, 0xA8C5, 0x4E7E, 0xB0AE, 0x4E7F, 0xD44B, 0x4E82, 0xB6C3, 0x4E83, 0xDCB1, + 0x4E84, 0xDCB2, 0x4E86, 0xA446, 0x4E88, 0xA4A9, 0x4E8B, 0xA8C6, 0x4E8C, 0xA447, 0x4E8D, 0xC948, 0x4E8E, 0xA45F, 0x4E91, 0xA4AA, + 0x4E92, 0xA4AC, 0x4E93, 0xC951, 0x4E94, 0xA4AD, 0x4E95, 0xA4AB, 0x4E99, 0xA5E5, 0x4E9B, 0xA8C7, 0x4E9E, 0xA8C8, 0x4E9F, 0xAB45, + 0x4EA1, 0xA460, 0x4EA2, 0xA4AE, 0x4EA4, 0xA5E6, 0x4EA5, 0xA5E8, 0x4EA6, 0xA5E7, 0x4EA8, 0xA6EB, 0x4EAB, 0xA8C9, 0x4EAC, 0xA8CA, + 0x4EAD, 0xAB46, 0x4EAE, 0xAB47, 0x4EB3, 0xADBD, 0x4EB6, 0xDCB3, 0x4EB9, 0xF6D6, 0x4EBA, 0xA448, 0x4EC0, 0xA4B0, 0x4EC1, 0xA4AF, + 0x4EC2, 0xC952, 0x4EC3, 0xA4B1, 0x4EC4, 0xA4B7, 0x4EC6, 0xA4B2, 0x4EC7, 0xA4B3, 0x4EC8, 0xC954, 0x4EC9, 0xC953, 0x4ECA, 0xA4B5, + 0x4ECB, 0xA4B6, 0x4ECD, 0xA4B4, 0x4ED4, 0xA54A, 0x4ED5, 0xA54B, 0x4ED6, 0xA54C, 0x4ED7, 0xA54D, 0x4ED8, 0xA549, 0x4ED9, 0xA550, + 0x4EDA, 0xC96A, 0x4EDC, 0xC966, 0x4EDD, 0xC969, 0x4EDE, 0xA551, 0x4EDF, 0xA561, 0x4EE1, 0xC968, 0x4EE3, 0xA54E, 0x4EE4, 0xA54F, + 0x4EE5, 0xA548, 0x4EE8, 0xC965, 0x4EE9, 0xC967, 0x4EF0, 0xA5F5, 0x4EF1, 0xC9B0, 0x4EF2, 0xA5F2, 0x4EF3, 0xA5F6, 0x4EF4, 0xC9BA, + 0x4EF5, 0xC9AE, 0x4EF6, 0xA5F3, 0x4EF7, 0xC9B2, 0x4EFB, 0xA5F4, 0x4EFD, 0xA5F7, 0x4EFF, 0xA5E9, 0x4F00, 0xC9B1, 0x4F01, 0xA5F8, + 0x4F02, 0xC9B5, 0x4F04, 0xC9B9, 0x4F05, 0xC9B6, 0x4F08, 0xC9B3, 0x4F09, 0xA5EA, 0x4F0A, 0xA5EC, 0x4F0B, 0xA5F9, 0x4F0D, 0xA5EE, + 0x4F0E, 0xC9AB, 0x4F0F, 0xA5F1, 0x4F10, 0xA5EF, 0x4F11, 0xA5F0, 0x4F12, 0xC9BB, 0x4F13, 0xC9B8, 0x4F14, 0xC9AF, 0x4F15, 0xA5ED, + 0x4F18, 0xC9AC, 0x4F19, 0xA5EB, 0x4F1D, 0xC9B4, 0x4F22, 0xC9B7, 0x4F2C, 0xC9AD, 0x4F2D, 0xCA66, 0x4F2F, 0xA742, 0x4F30, 0xA6F4, + 0x4F33, 0xCA67, 0x4F34, 0xA6F1, 0x4F36, 0xA744, 0x4F38, 0xA6F9, 0x4F3A, 0xA6F8, 0x4F3B, 0xCA5B, 0x4F3C, 0xA6FC, 0x4F3D, 0xA6F7, + 0x4F3E, 0xCA60, 0x4F3F, 0xCA68, 0x4F41, 0xCA64, 0x4F43, 0xA6FA, 0x4F46, 0xA6FD, 0x4F47, 0xA6EE, 0x4F48, 0xA747, 0x4F49, 0xCA5D, + 0x4F4C, 0xCBBD, 0x4F4D, 0xA6EC, 0x4F4E, 0xA743, 0x4F4F, 0xA6ED, 0x4F50, 0xA6F5, 0x4F51, 0xA6F6, 0x4F52, 0xCA62, 0x4F53, 0xCA5E, + 0x4F54, 0xA6FB, 0x4F55, 0xA6F3, 0x4F56, 0xCA5A, 0x4F57, 0xA6EF, 0x4F58, 0xCA65, 0x4F59, 0xA745, 0x4F5A, 0xA748, 0x4F5B, 0xA6F2, + 0x4F5C, 0xA740, 0x4F5D, 0xA746, 0x4F5E, 0xA6F0, 0x4F5F, 0xCA63, 0x4F60, 0xA741, 0x4F61, 0xCA69, 0x4F62, 0xCA5C, 0x4F63, 0xA6FE, + 0x4F64, 0xCA5F, 0x4F67, 0xCA61, 0x4F69, 0xA8D8, 0x4F6A, 0xCBBF, 0x4F6B, 0xCBCB, 0x4F6C, 0xA8D0, 0x4F6E, 0xCBCC, 0x4F6F, 0xA8CB, + 0x4F70, 0xA8D5, 0x4F73, 0xA8CE, 0x4F74, 0xCBB9, 0x4F75, 0xA8D6, 0x4F76, 0xCBB8, 0x4F77, 0xCBBC, 0x4F78, 0xCBC3, 0x4F79, 0xCBC1, + 0x4F7A, 0xA8DE, 0x4F7B, 0xA8D9, 0x4F7C, 0xCBB3, 0x4F7D, 0xCBB5, 0x4F7E, 0xA8DB, 0x4F7F, 0xA8CF, 0x4F80, 0xCBB6, 0x4F81, 0xCBC2, + 0x4F82, 0xCBC9, 0x4F83, 0xA8D4, 0x4F84, 0xCBBB, 0x4F85, 0xCBB4, 0x4F86, 0xA8D3, 0x4F87, 0xCBB7, 0x4F88, 0xA8D7, 0x4F89, 0xCBBA, + 0x4F8B, 0xA8D2, 0x4F8D, 0xA8CD, 0x4F8F, 0xA8DC, 0x4F90, 0xCBC4, 0x4F91, 0xA8DD, 0x4F92, 0xCBC8, 0x4F94, 0xCBC6, 0x4F95, 0xCBCA, + 0x4F96, 0xA8DA, 0x4F97, 0xCBBE, 0x4F98, 0xCBB2, 0x4F9A, 0xCBC0, 0x4F9B, 0xA8D1, 0x4F9C, 0xCBC5, 0x4F9D, 0xA8CC, 0x4F9E, 0xCBC7, + 0x4FAE, 0xAB56, 0x4FAF, 0xAB4A, 0x4FB2, 0xCDE0, 0x4FB3, 0xCDE8, 0x4FB5, 0xAB49, 0x4FB6, 0xAB51, 0x4FB7, 0xAB5D, 0x4FB9, 0xCDEE, + 0x4FBA, 0xCDEC, 0x4FBB, 0xCDE7, 0x4FBF, 0xAB4B, 0x4FC0, 0xCDED, 0x4FC1, 0xCDE3, 0x4FC2, 0xAB59, 0x4FC3, 0xAB50, 0x4FC4, 0xAB58, + 0x4FC5, 0xCDDE, 0x4FC7, 0xCDEA, 0x4FC9, 0xCDE1, 0x4FCA, 0xAB54, 0x4FCB, 0xCDE2, 0x4FCD, 0xCDDD, 0x4FCE, 0xAB5B, 0x4FCF, 0xAB4E, + 0x4FD0, 0xAB57, 0x4FD1, 0xAB4D, 0x4FD3, 0xCDDF, 0x4FD4, 0xCDE4, 0x4FD6, 0xCDEB, 0x4FD7, 0xAB55, 0x4FD8, 0xAB52, 0x4FD9, 0xCDE6, + 0x4FDA, 0xAB5A, 0x4FDB, 0xCDE9, 0x4FDC, 0xCDE5, 0x4FDD, 0xAB4F, 0x4FDE, 0xAB5C, 0x4FDF, 0xAB53, 0x4FE0, 0xAB4C, 0x4FE1, 0xAB48, + 0x4FEC, 0xCDEF, 0x4FEE, 0xADD7, 0x4FEF, 0xADC1, 0x4FF1, 0xADD1, 0x4FF3, 0xADD6, 0x4FF4, 0xD0D0, 0x4FF5, 0xD0CF, 0x4FF6, 0xD0D4, + 0x4FF7, 0xD0D5, 0x4FF8, 0xADC4, 0x4FFA, 0xADCD, 0x4FFE, 0xADDA, 0x5000, 0xADCE, 0x5005, 0xD0C9, 0x5006, 0xADC7, 0x5007, 0xD0CA, + 0x5009, 0xADDC, 0x500B, 0xADD3, 0x500C, 0xADBE, 0x500D, 0xADBF, 0x500E, 0xD0DD, 0x500F, 0xB0BF, 0x5011, 0xADCC, 0x5012, 0xADCB, + 0x5013, 0xD0CB, 0x5014, 0xADCF, 0x5015, 0xD45B, 0x5016, 0xADC6, 0x5017, 0xD0D6, 0x5018, 0xADD5, 0x5019, 0xADD4, 0x501A, 0xADCA, + 0x501B, 0xD0CE, 0x501C, 0xD0D7, 0x501E, 0xD0C8, 0x501F, 0xADC9, 0x5020, 0xD0D8, 0x5021, 0xADD2, 0x5022, 0xD0CC, 0x5023, 0xADC0, + 0x5025, 0xADC3, 0x5026, 0xADC2, 0x5027, 0xD0D9, 0x5028, 0xADD0, 0x5029, 0xADC5, 0x502A, 0xADD9, 0x502B, 0xADDB, 0x502C, 0xD0D3, + 0x502D, 0xADD8, 0x502F, 0xD0DB, 0x5030, 0xD0CD, 0x5031, 0xD0DC, 0x5033, 0xD0D1, 0x5035, 0xD0DA, 0x5037, 0xD0D2, 0x503C, 0xADC8, + 0x5040, 0xD463, 0x5041, 0xD457, 0x5043, 0xB0B3, 0x5045, 0xD45C, 0x5046, 0xD462, 0x5047, 0xB0B2, 0x5048, 0xD455, 0x5049, 0xB0B6, + 0x504A, 0xD459, 0x504B, 0xD452, 0x504C, 0xB0B4, 0x504D, 0xD456, 0x504E, 0xB0B9, 0x504F, 0xB0BE, 0x5051, 0xD467, 0x5053, 0xD451, + 0x5055, 0xB0BA, 0x5057, 0xD466, 0x505A, 0xB0B5, 0x505B, 0xD458, 0x505C, 0xB0B1, 0x505D, 0xD453, 0x505E, 0xD44F, 0x505F, 0xD45D, + 0x5060, 0xD450, 0x5061, 0xD44E, 0x5062, 0xD45A, 0x5063, 0xD460, 0x5064, 0xD461, 0x5065, 0xB0B7, 0x5068, 0xD85B, 0x5069, 0xD45E, + 0x506A, 0xD44D, 0x506B, 0xD45F, 0x506D, 0xB0C1, 0x506E, 0xD464, 0x506F, 0xB0C0, 0x5070, 0xD44C, 0x5072, 0xD454, 0x5073, 0xD465, + 0x5074, 0xB0BC, 0x5075, 0xB0BB, 0x5076, 0xB0B8, 0x5077, 0xB0BD, 0x507A, 0xB0AF, 0x507D, 0xB0B0, 0x5080, 0xB3C8, 0x5082, 0xD85E, + 0x5083, 0xD857, 0x5085, 0xB3C5, 0x5087, 0xD85F, 0x508B, 0xD855, 0x508C, 0xD858, 0x508D, 0xB3C4, 0x508E, 0xD859, 0x5091, 0xB3C7, + 0x5092, 0xD85D, 0x5094, 0xD853, 0x5095, 0xD852, 0x5096, 0xB3C9, 0x5098, 0xB3CA, 0x5099, 0xB3C6, 0x509A, 0xB3CB, 0x509B, 0xD851, + 0x509C, 0xD85C, 0x509D, 0xD85A, 0x509E, 0xD854, 0x50A2, 0xB3C3, 0x50A3, 0xD856, 0x50AC, 0xB6CA, 0x50AD, 0xB6C4, 0x50AE, 0xDCB7, + 0x50AF, 0xB6CD, 0x50B0, 0xDCBD, 0x50B1, 0xDCC0, 0x50B2, 0xB6C6, 0x50B3, 0xB6C7, 0x50B4, 0xDCBA, 0x50B5, 0xB6C5, 0x50B6, 0xDCC3, + 0x50B7, 0xB6CB, 0x50B8, 0xDCC4, 0x50BA, 0xDCBF, 0x50BB, 0xB6CC, 0x50BD, 0xDCB4, 0x50BE, 0xB6C9, 0x50BF, 0xDCB5, 0x50C1, 0xDCBE, + 0x50C2, 0xDCBC, 0x50C4, 0xDCB8, 0x50C5, 0xB6C8, 0x50C6, 0xDCB6, 0x50C7, 0xB6CE, 0x50C8, 0xDCBB, 0x50C9, 0xDCC2, 0x50CA, 0xDCB9, + 0x50CB, 0xDCC1, 0x50CE, 0xB9B6, 0x50CF, 0xB9B3, 0x50D1, 0xB9B4, 0x50D3, 0xE0F9, 0x50D4, 0xE0F1, 0x50D5, 0xB9B2, 0x50D6, 0xB9AF, + 0x50D7, 0xE0F2, 0x50DA, 0xB9B1, 0x50DB, 0xE0F5, 0x50DD, 0xE0F7, 0x50E0, 0xE0FE, 0x50E3, 0xE0FD, 0x50E4, 0xE0F8, 0x50E5, 0xB9AE, + 0x50E6, 0xE0F0, 0x50E7, 0xB9AC, 0x50E8, 0xE0F3, 0x50E9, 0xB9B7, 0x50EA, 0xE0F6, 0x50EC, 0xE0FA, 0x50ED, 0xB9B0, 0x50EE, 0xB9AD, + 0x50EF, 0xE0FC, 0x50F0, 0xE0FB, 0x50F1, 0xB9B5, 0x50F3, 0xE0F4, 0x50F5, 0xBBF8, 0x50F6, 0xE4EC, 0x50F8, 0xE4E9, 0x50F9, 0xBBF9, + 0x50FB, 0xBBF7, 0x50FD, 0xE4F0, 0x50FE, 0xE4ED, 0x50FF, 0xE4E6, 0x5100, 0xBBF6, 0x5102, 0xBBFA, 0x5103, 0xE4E7, 0x5104, 0xBBF5, + 0x5105, 0xBBFD, 0x5106, 0xE4EA, 0x5107, 0xE4EB, 0x5108, 0xBBFB, 0x5109, 0xBBFC, 0x510A, 0xE4F1, 0x510B, 0xE4EE, 0x510C, 0xE4EF, + 0x5110, 0xBEAA, 0x5111, 0xE8F8, 0x5112, 0xBEA7, 0x5113, 0xE8F5, 0x5114, 0xBEA9, 0x5115, 0xBEAB, 0x5117, 0xE8F6, 0x5118, 0xBEA8, + 0x511A, 0xE8F7, 0x511C, 0xE8F4, 0x511F, 0xC076, 0x5120, 0xECBD, 0x5121, 0xC077, 0x5122, 0xECBB, 0x5124, 0xECBC, 0x5125, 0xECBA, + 0x5126, 0xECB9, 0x5129, 0xECBE, 0x512A, 0xC075, 0x512D, 0xEFB8, 0x512E, 0xEFB9, 0x5130, 0xE4E8, 0x5131, 0xEFB7, 0x5132, 0xC078, + 0x5133, 0xC35F, 0x5134, 0xF1EB, 0x5135, 0xF1EC, 0x5137, 0xC4D7, 0x5138, 0xC4D8, 0x5139, 0xF5C1, 0x513A, 0xF5C0, 0x513B, 0xC56C, + 0x513C, 0xC56B, 0x513D, 0xF7D0, 0x513F, 0xA449, 0x5140, 0xA461, 0x5141, 0xA4B9, 0x5143, 0xA4B8, 0x5144, 0xA553, 0x5145, 0xA552, + 0x5146, 0xA5FC, 0x5147, 0xA5FB, 0x5148, 0xA5FD, 0x5149, 0xA5FA, 0x514B, 0xA74A, 0x514C, 0xA749, 0x514D, 0xA74B, 0x5152, 0xA8E0, + 0x5154, 0xA8DF, 0x5155, 0xA8E1, 0x5157, 0xAB5E, 0x5159, 0xA259, 0x515A, 0xD0DE, 0x515B, 0xA25A, 0x515C, 0xB0C2, 0x515D, 0xA25C, + 0x515E, 0xA25B, 0x515F, 0xD860, 0x5161, 0xA25D, 0x5162, 0xB9B8, 0x5163, 0xA25E, 0x5165, 0xA44A, 0x5167, 0xA4BA, 0x5168, 0xA5FE, + 0x5169, 0xA8E2, 0x516B, 0xA44B, 0x516C, 0xA4BD, 0x516D, 0xA4BB, 0x516E, 0xA4BC, 0x5171, 0xA640, 0x5175, 0xA74C, 0x5176, 0xA8E4, + 0x5177, 0xA8E3, 0x5178, 0xA8E5, 0x517C, 0xADDD, 0x5180, 0xBEAC, 0x5187, 0xC94E, 0x5189, 0xA554, 0x518A, 0xA555, 0x518D, 0xA641, + 0x518F, 0xCA6A, 0x5191, 0xAB60, 0x5192, 0xAB5F, 0x5193, 0xD0E0, 0x5194, 0xD0DF, 0x5195, 0xB0C3, 0x5197, 0xA4BE, 0x5198, 0xC955, + 0x519E, 0xCBCD, 0x51A0, 0xAB61, 0x51A2, 0xADE0, 0x51A4, 0xADDE, 0x51A5, 0xADDF, 0x51AA, 0xBEAD, 0x51AC, 0xA556, 0x51B0, 0xA642, + 0x51B1, 0xC9BC, 0x51B6, 0xA74D, 0x51B7, 0xA74E, 0x51B9, 0xCA6B, 0x51BC, 0xCBCE, 0x51BD, 0xA8E6, 0x51BE, 0xCBCF, 0x51C4, 0xD0E2, + 0x51C5, 0xD0E3, 0x51C6, 0xADE3, 0x51C8, 0xD0E4, 0x51CA, 0xD0E1, 0x51CB, 0xADE4, 0x51CC, 0xADE2, 0x51CD, 0xADE1, 0x51CE, 0xD0E5, + 0x51D0, 0xD468, 0x51D4, 0xD861, 0x51D7, 0xDCC5, 0x51D8, 0xE140, 0x51DC, 0xBBFE, 0x51DD, 0xBEAE, 0x51DE, 0xE8F9, 0x51E0, 0xA44C, + 0x51E1, 0xA45A, 0x51F0, 0xB0C4, 0x51F1, 0xB3CD, 0x51F3, 0xB9B9, 0x51F5, 0xC942, 0x51F6, 0xA4BF, 0x51F8, 0xA559, 0x51F9, 0xA557, + 0x51FA, 0xA558, 0x51FD, 0xA8E7, 0x5200, 0xA44D, 0x5201, 0xA44E, 0x5203, 0xA462, 0x5206, 0xA4C0, 0x5207, 0xA4C1, 0x5208, 0xA4C2, + 0x5209, 0xC9BE, 0x520A, 0xA55A, 0x520C, 0xC96B, 0x520E, 0xA646, 0x5210, 0xC9BF, 0x5211, 0xA644, 0x5212, 0xA645, 0x5213, 0xC9BD, + 0x5216, 0xA647, 0x5217, 0xA643, 0x521C, 0xCA6C, 0x521D, 0xAAEC, 0x521E, 0xCA6D, 0x5221, 0xCA6E, 0x5224, 0xA750, 0x5225, 0xA74F, + 0x5228, 0xA753, 0x5229, 0xA751, 0x522A, 0xA752, 0x522E, 0xA8ED, 0x5230, 0xA8EC, 0x5231, 0xCBD4, 0x5232, 0xCBD1, 0x5233, 0xCBD2, + 0x5235, 0xCBD0, 0x5236, 0xA8EE, 0x5237, 0xA8EA, 0x5238, 0xA8E9, 0x523A, 0xA8EB, 0x523B, 0xA8E8, 0x5241, 0xA8EF, 0x5243, 0xAB63, + 0x5244, 0xCDF0, 0x5246, 0xCBD3, 0x5247, 0xAB68, 0x5249, 0xCDF1, 0x524A, 0xAB64, 0x524B, 0xAB67, 0x524C, 0xAB66, 0x524D, 0xAB65, + 0x524E, 0xAB62, 0x5252, 0xD0E8, 0x5254, 0xADE7, 0x5255, 0xD0EB, 0x5256, 0xADE5, 0x525A, 0xD0E7, 0x525B, 0xADE8, 0x525C, 0xADE6, + 0x525D, 0xADE9, 0x525E, 0xD0E9, 0x525F, 0xD0EA, 0x5261, 0xD0E6, 0x5262, 0xD0EC, 0x5269, 0xB3D1, 0x526A, 0xB0C5, 0x526B, 0xD469, + 0x526C, 0xD46B, 0x526D, 0xD46A, 0x526E, 0xD46C, 0x526F, 0xB0C6, 0x5272, 0xB3CE, 0x5274, 0xB3CF, 0x5275, 0xB3D0, 0x5277, 0xB6D0, + 0x5278, 0xDCC7, 0x527A, 0xDCC6, 0x527B, 0xDCC8, 0x527C, 0xDCC9, 0x527D, 0xB6D1, 0x527F, 0xB6CF, 0x5280, 0xE141, 0x5281, 0xE142, + 0x5282, 0xB9BB, 0x5283, 0xB9BA, 0x5284, 0xE35A, 0x5287, 0xBC40, 0x5288, 0xBC41, 0x5289, 0xBC42, 0x528A, 0xBC44, 0x528B, 0xE4F2, + 0x528C, 0xE4F3, 0x528D, 0xBC43, 0x5291, 0xBEAF, 0x5293, 0xBEB0, 0x5296, 0xF1ED, 0x5297, 0xF5C3, 0x5298, 0xF5C2, 0x5299, 0xF7D1, + 0x529B, 0xA44F, 0x529F, 0xA55C, 0x52A0, 0xA55B, 0x52A3, 0xA648, 0x52A6, 0xC9C0, 0x52A9, 0xA755, 0x52AA, 0xA756, 0x52AB, 0xA754, + 0x52AC, 0xA757, 0x52AD, 0xCA6F, 0x52AE, 0xCA70, 0x52BB, 0xA8F1, 0x52BC, 0xCBD5, 0x52BE, 0xA8F0, 0x52C0, 0xCDF2, 0x52C1, 0xAB6C, + 0x52C2, 0xCDF3, 0x52C3, 0xAB6B, 0x52C7, 0xAB69, 0x52C9, 0xAB6A, 0x52CD, 0xD0ED, 0x52D2, 0xB0C7, 0x52D3, 0xD46E, 0x52D5, 0xB0CA, + 0x52D6, 0xD46D, 0x52D7, 0xB1E5, 0x52D8, 0xB0C9, 0x52D9, 0xB0C8, 0x52DB, 0xB3D4, 0x52DD, 0xB3D3, 0x52DE, 0xB3D2, 0x52DF, 0xB6D2, + 0x52E2, 0xB6D5, 0x52E3, 0xB6D6, 0x52E4, 0xB6D4, 0x52E6, 0xB6D3, 0x52E9, 0xE143, 0x52EB, 0xE144, 0x52EF, 0xE4F5, 0x52F0, 0xBC45, + 0x52F1, 0xE4F4, 0x52F3, 0xBEB1, 0x52F4, 0xECBF, 0x52F5, 0xC079, 0x52F7, 0xF1EE, 0x52F8, 0xC455, 0x52FA, 0xA463, 0x52FB, 0xA4C3, + 0x52FC, 0xC956, 0x52FE, 0xA4C4, 0x52FF, 0xA4C5, 0x5305, 0xA55D, 0x5306, 0xA55E, 0x5308, 0xA649, 0x5309, 0xCA71, 0x530A, 0xCBD6, + 0x530B, 0xCBD7, 0x530D, 0xAB6D, 0x530E, 0xD0EE, 0x530F, 0xB0CC, 0x5310, 0xB0CB, 0x5311, 0xD863, 0x5312, 0xD862, 0x5315, 0xA450, + 0x5316, 0xA4C6, 0x5317, 0xA55F, 0x5319, 0xB0CD, 0x531A, 0xC943, 0x531C, 0xC96C, 0x531D, 0xA560, 0x531F, 0xC9C2, 0x5320, 0xA64B, + 0x5321, 0xA64A, 0x5322, 0xC9C1, 0x5323, 0xA758, 0x532A, 0xADEA, 0x532D, 0xD46F, 0x532F, 0xB6D7, 0x5330, 0xE145, 0x5331, 0xB9BC, + 0x5334, 0xE8FA, 0x5337, 0xF3FD, 0x5339, 0xA4C7, 0x533C, 0xCBD8, 0x533D, 0xCDF4, 0x533E, 0xB0D0, 0x533F, 0xB0CE, 0x5340, 0xB0CF, + 0x5341, 0xA2CC, 0x5341, 0xA451, 0x5343, 0xA464, 0x5344, 0xA2CD, 0x5345, 0xA2CE, 0x5345, 0xA4CA, 0x5347, 0xA4C9, 0x5348, 0xA4C8, + 0x5349, 0xA563, 0x534A, 0xA562, 0x534C, 0xC96D, 0x534D, 0xC9C3, 0x5351, 0xA8F5, 0x5352, 0xA8F2, 0x5353, 0xA8F4, 0x5354, 0xA8F3, + 0x5357, 0xAB6E, 0x535A, 0xB3D5, 0x535C, 0xA452, 0x535E, 0xA4CB, 0x5360, 0xA565, 0x5361, 0xA564, 0x5363, 0xCA72, 0x5366, 0xA8F6, + 0x536C, 0xC957, 0x536E, 0xA567, 0x536F, 0xA566, 0x5370, 0xA64C, 0x5371, 0xA64D, 0x5372, 0xCA73, 0x5373, 0xA759, 0x5375, 0xA75A, + 0x5377, 0xA8F7, 0x5378, 0xA8F8, 0x5379, 0xA8F9, 0x537B, 0xAB6F, 0x537C, 0xCDF5, 0x537F, 0xADEB, 0x5382, 0xC944, 0x5384, 0xA4CC, + 0x538A, 0xC9C4, 0x538E, 0xCA74, 0x538F, 0xCA75, 0x5392, 0xCBD9, 0x5394, 0xCBDA, 0x5396, 0xCDF7, 0x5397, 0xCDF6, 0x5398, 0xCDF9, + 0x5399, 0xCDF8, 0x539A, 0xAB70, 0x539C, 0xD470, 0x539D, 0xADED, 0x539E, 0xD0EF, 0x539F, 0xADEC, 0x53A4, 0xD864, 0x53A5, 0xB3D6, + 0x53A7, 0xD865, 0x53AC, 0xE146, 0x53AD, 0xB9BD, 0x53B2, 0xBC46, 0x53B4, 0xF1EF, 0x53B9, 0xC958, 0x53BB, 0xA568, 0x53C3, 0xB0D1, + 0x53C8, 0xA453, 0x53C9, 0xA465, 0x53CA, 0xA4CE, 0x53CB, 0xA4CD, 0x53CD, 0xA4CF, 0x53D4, 0xA8FB, 0x53D6, 0xA8FA, 0x53D7, 0xA8FC, + 0x53DB, 0xAB71, 0x53DF, 0xADEE, 0x53E1, 0xE8FB, 0x53E2, 0xC24F, 0x53E3, 0xA466, 0x53E4, 0xA56A, 0x53E5, 0xA579, 0x53E6, 0xA574, + 0x53E8, 0xA56F, 0x53E9, 0xA56E, 0x53EA, 0xA575, 0x53EB, 0xA573, 0x53EC, 0xA56C, 0x53ED, 0xA57A, 0x53EE, 0xA56D, 0x53EF, 0xA569, + 0x53F0, 0xA578, 0x53F1, 0xA577, 0x53F2, 0xA576, 0x53F3, 0xA56B, 0x53F5, 0xA572, 0x53F8, 0xA571, 0x53FB, 0xA57B, 0x53FC, 0xA570, + 0x5401, 0xA653, 0x5403, 0xA659, 0x5404, 0xA655, 0x5406, 0xA65B, 0x5407, 0xC9C5, 0x5408, 0xA658, 0x5409, 0xA64E, 0x540A, 0xA651, + 0x540B, 0xA654, 0x540C, 0xA650, 0x540D, 0xA657, 0x540E, 0xA65A, 0x540F, 0xA64F, 0x5410, 0xA652, 0x5411, 0xA656, 0x5412, 0xA65C, + 0x5418, 0xCA7E, 0x5419, 0xCA7B, 0x541B, 0xA767, 0x541C, 0xCA7C, 0x541D, 0xA75B, 0x541E, 0xA75D, 0x541F, 0xA775, 0x5420, 0xA770, + 0x5424, 0xCAA5, 0x5425, 0xCA7D, 0x5426, 0xA75F, 0x5427, 0xA761, 0x5428, 0xCAA4, 0x5429, 0xA768, 0x542A, 0xCA78, 0x542B, 0xA774, + 0x542C, 0xA776, 0x542D, 0xA75C, 0x542E, 0xA76D, 0x5430, 0xCA76, 0x5431, 0xA773, 0x5433, 0xA764, 0x5435, 0xA76E, 0x5436, 0xA76F, + 0x5437, 0xCA77, 0x5438, 0xA76C, 0x5439, 0xA76A, 0x543B, 0xA76B, 0x543C, 0xA771, 0x543D, 0xCAA1, 0x543E, 0xA75E, 0x5440, 0xA772, + 0x5441, 0xCAA3, 0x5442, 0xA766, 0x5443, 0xA763, 0x5445, 0xCA7A, 0x5446, 0xA762, 0x5447, 0xCAA6, 0x5448, 0xA765, 0x544A, 0xA769, + 0x544E, 0xA760, 0x544F, 0xCAA2, 0x5454, 0xCA79, 0x5460, 0xCBEB, 0x5461, 0xCBEA, 0x5462, 0xA94F, 0x5463, 0xCBED, 0x5464, 0xCBEF, + 0x5465, 0xCBE4, 0x5466, 0xCBE7, 0x5467, 0xCBEE, 0x5468, 0xA950, 0x546B, 0xCBE1, 0x546C, 0xCBE5, 0x546F, 0xCBE9, 0x5470, 0xCE49, + 0x5471, 0xA94B, 0x5472, 0xCE4D, 0x5473, 0xA8FD, 0x5474, 0xCBE6, 0x5475, 0xA8FE, 0x5476, 0xA94C, 0x5477, 0xA945, 0x5478, 0xA941, + 0x547A, 0xCBE2, 0x547B, 0xA944, 0x547C, 0xA949, 0x547D, 0xA952, 0x547E, 0xCBE3, 0x547F, 0xCBDC, 0x5480, 0xA943, 0x5481, 0xCBDD, + 0x5482, 0xCBDF, 0x5484, 0xA946, 0x5486, 0xA948, 0x5487, 0xCBDB, 0x5488, 0xCBE0, 0x548B, 0xA951, 0x548C, 0xA94D, 0x548D, 0xCBE8, + 0x548E, 0xA953, 0x5490, 0xA94A, 0x5491, 0xCBDE, 0x5492, 0xA947, 0x5495, 0xA942, 0x5496, 0xA940, 0x5498, 0xCBEC, 0x549A, 0xA94E, + 0x54A0, 0xCE48, 0x54A1, 0xCDFB, 0x54A2, 0xCE4B, 0x54A5, 0xCDFD, 0x54A6, 0xAB78, 0x54A7, 0xABA8, 0x54A8, 0xAB74, 0x54A9, 0xABA7, + 0x54AA, 0xAB7D, 0x54AB, 0xABA4, 0x54AC, 0xAB72, 0x54AD, 0xCDFC, 0x54AE, 0xCE43, 0x54AF, 0xABA3, 0x54B0, 0xCE4F, 0x54B1, 0xABA5, + 0x54B3, 0xAB79, 0x54B6, 0xCE45, 0x54B7, 0xCE42, 0x54B8, 0xAB77, 0x54BA, 0xCDFA, 0x54BB, 0xABA6, 0x54BC, 0xCE4A, 0x54BD, 0xAB7C, + 0x54BE, 0xCE4C, 0x54BF, 0xABA9, 0x54C0, 0xAB73, 0x54C1, 0xAB7E, 0x54C2, 0xAB7B, 0x54C3, 0xCE40, 0x54C4, 0xABA1, 0x54C5, 0xCE46, + 0x54C6, 0xCE47, 0x54C7, 0xAB7A, 0x54C8, 0xABA2, 0x54C9, 0xAB76, 0x54CE, 0xAB75, 0x54CF, 0xCDFE, 0x54D6, 0xCE44, 0x54DE, 0xCE4E, + 0x54E0, 0xD144, 0x54E1, 0xADFB, 0x54E2, 0xD0F1, 0x54E4, 0xD0F6, 0x54E5, 0xADF4, 0x54E6, 0xAE40, 0x54E7, 0xD0F4, 0x54E8, 0xADEF, + 0x54E9, 0xADF9, 0x54EA, 0xADFE, 0x54EB, 0xD0FB, 0x54ED, 0xADFA, 0x54EE, 0xADFD, 0x54F1, 0xD0FE, 0x54F2, 0xADF5, 0x54F3, 0xD0F5, + 0x54F7, 0xD142, 0x54F8, 0xD143, 0x54FA, 0xADF7, 0x54FB, 0xD141, 0x54FC, 0xADF3, 0x54FD, 0xAE43, 0x54FF, 0xD0F8, 0x5501, 0xADF1, + 0x5503, 0xD146, 0x5504, 0xD0F9, 0x5505, 0xD0FD, 0x5506, 0xADF6, 0x5507, 0xAE42, 0x5508, 0xD0FA, 0x5509, 0xADFC, 0x550A, 0xD140, + 0x550B, 0xD147, 0x550C, 0xD4A1, 0x550E, 0xD145, 0x550F, 0xAE44, 0x5510, 0xADF0, 0x5511, 0xD0FC, 0x5512, 0xD0F3, 0x5514, 0xADF8, + 0x5517, 0xD0F2, 0x551A, 0xD0F7, 0x5526, 0xD0F0, 0x5527, 0xAE41, 0x552A, 0xD477, 0x552C, 0xB0E4, 0x552D, 0xD4A7, 0x552E, 0xB0E2, + 0x552F, 0xB0DF, 0x5530, 0xD47C, 0x5531, 0xB0DB, 0x5532, 0xD4A2, 0x5533, 0xB0E6, 0x5534, 0xD476, 0x5535, 0xD47B, 0x5536, 0xD47A, + 0x5537, 0xADF2, 0x5538, 0xB0E1, 0x5539, 0xD4A5, 0x553B, 0xD4A8, 0x553C, 0xD473, 0x553E, 0xB3E8, 0x5540, 0xD4A9, 0x5541, 0xB0E7, + 0x5543, 0xB0D9, 0x5544, 0xB0D6, 0x5545, 0xD47E, 0x5546, 0xB0D3, 0x5548, 0xD4A6, 0x554A, 0xB0DA, 0x554B, 0xD4AA, 0x554D, 0xD474, + 0x554E, 0xD4A4, 0x554F, 0xB0DD, 0x5550, 0xD475, 0x5551, 0xD478, 0x5552, 0xD47D, 0x5555, 0xB0DE, 0x5556, 0xB0DC, 0x5557, 0xB0E8, + 0x555C, 0xB0E3, 0x555E, 0xB0D7, 0x555F, 0xB1D2, 0x5561, 0xB0D8, 0x5562, 0xD479, 0x5563, 0xB0E5, 0x5564, 0xB0E0, 0x5565, 0xD4A3, + 0x5566, 0xB0D5, 0x556A, 0xB0D4, 0x5575, 0xD471, 0x5576, 0xD472, 0x5577, 0xD86A, 0x557B, 0xB3D7, 0x557C, 0xB3DA, 0x557D, 0xD875, + 0x557E, 0xB3EE, 0x557F, 0xD878, 0x5580, 0xB3D8, 0x5581, 0xD871, 0x5582, 0xB3DE, 0x5583, 0xB3E4, 0x5584, 0xB5BD, 0x5587, 0xB3E2, + 0x5588, 0xD86E, 0x5589, 0xB3EF, 0x558A, 0xB3DB, 0x558B, 0xB3E3, 0x558C, 0xD876, 0x558D, 0xDCD7, 0x558E, 0xD87B, 0x558F, 0xD86F, + 0x5591, 0xD866, 0x5592, 0xD873, 0x5593, 0xD86D, 0x5594, 0xB3E1, 0x5595, 0xD879, 0x5598, 0xB3DD, 0x5599, 0xB3F1, 0x559A, 0xB3EA, + 0x559C, 0xB3DF, 0x559D, 0xB3DC, 0x559F, 0xB3E7, 0x55A1, 0xD87A, 0x55A2, 0xD86C, 0x55A3, 0xD872, 0x55A4, 0xD874, 0x55A5, 0xD868, + 0x55A6, 0xD877, 0x55A7, 0xB3D9, 0x55A8, 0xD867, 0x55AA, 0xB3E0, 0x55AB, 0xB3F0, 0x55AC, 0xB3EC, 0x55AD, 0xD869, 0x55AE, 0xB3E6, + 0x55B1, 0xB3ED, 0x55B2, 0xB3E9, 0x55B3, 0xB3E5, 0x55B5, 0xD870, 0x55BB, 0xB3EB, 0x55BF, 0xDCD5, 0x55C0, 0xDCD1, 0x55C2, 0xDCE0, + 0x55C3, 0xDCCA, 0x55C4, 0xDCD3, 0x55C5, 0xB6E5, 0x55C6, 0xB6E6, 0x55C7, 0xB6DE, 0x55C8, 0xDCDC, 0x55C9, 0xB6E8, 0x55CA, 0xDCCF, + 0x55CB, 0xDCCE, 0x55CC, 0xDCCC, 0x55CD, 0xDCDE, 0x55CE, 0xB6DC, 0x55CF, 0xDCD8, 0x55D0, 0xDCCD, 0x55D1, 0xB6DF, 0x55D2, 0xDCD6, + 0x55D3, 0xB6DA, 0x55D4, 0xDCD2, 0x55D5, 0xDCD9, 0x55D6, 0xDCDB, 0x55D9, 0xDCDF, 0x55DA, 0xB6E3, 0x55DB, 0xDCCB, 0x55DC, 0xB6DD, + 0x55DD, 0xDCD0, 0x55DF, 0xB6D8, 0x55E1, 0xB6E4, 0x55E2, 0xDCDA, 0x55E3, 0xB6E0, 0x55E4, 0xB6E1, 0x55E5, 0xB6E7, 0x55E6, 0xB6DB, + 0x55E7, 0xA25F, 0x55E8, 0xB6D9, 0x55E9, 0xDCD4, 0x55EF, 0xB6E2, 0x55F2, 0xDCDD, 0x55F6, 0xB9CD, 0x55F7, 0xB9C8, 0x55F9, 0xE155, + 0x55FA, 0xE151, 0x55FC, 0xE14B, 0x55FD, 0xB9C2, 0x55FE, 0xB9BE, 0x55FF, 0xE154, 0x5600, 0xB9BF, 0x5601, 0xE14E, 0x5602, 0xE150, + 0x5604, 0xE153, 0x5606, 0xB9C4, 0x5608, 0xB9CB, 0x5609, 0xB9C5, 0x560C, 0xE149, 0x560D, 0xB9C6, 0x560E, 0xB9C7, 0x560F, 0xE14C, + 0x5610, 0xB9CC, 0x5612, 0xE14A, 0x5613, 0xE14F, 0x5614, 0xB9C3, 0x5615, 0xE148, 0x5616, 0xB9C9, 0x5617, 0xB9C1, 0x561B, 0xB9C0, + 0x561C, 0xE14D, 0x561D, 0xE152, 0x561F, 0xB9CA, 0x5627, 0xE147, 0x5629, 0xBC4D, 0x562A, 0xE547, 0x562C, 0xE544, 0x562E, 0xBC47, + 0x562F, 0xBC53, 0x5630, 0xBC54, 0x5632, 0xBC4A, 0x5633, 0xE542, 0x5634, 0xBC4C, 0x5635, 0xE4F9, 0x5636, 0xBC52, 0x5638, 0xE546, + 0x5639, 0xBC49, 0x563A, 0xE548, 0x563B, 0xBC48, 0x563D, 0xE543, 0x563E, 0xE545, 0x563F, 0xBC4B, 0x5640, 0xE541, 0x5641, 0xE4FA, + 0x5642, 0xE4F7, 0x5645, 0xD86B, 0x5646, 0xE4FD, 0x5648, 0xE4F6, 0x5649, 0xE4FC, 0x564A, 0xE4FB, 0x564C, 0xE4F8, 0x564E, 0xBC4F, + 0x5653, 0xBC4E, 0x5657, 0xBC50, 0x5658, 0xE4FE, 0x5659, 0xBEB2, 0x565A, 0xE540, 0x565E, 0xE945, 0x5660, 0xE8FD, 0x5662, 0xBEBE, + 0x5663, 0xE942, 0x5664, 0xBEB6, 0x5665, 0xBEBA, 0x5666, 0xE941, 0x5668, 0xBEB9, 0x5669, 0xBEB5, 0x566A, 0xBEB8, 0x566B, 0xBEB3, + 0x566C, 0xBEBD, 0x566D, 0xE943, 0x566E, 0xE8FE, 0x566F, 0xBEBC, 0x5670, 0xE8FC, 0x5671, 0xBEBB, 0x5672, 0xE944, 0x5673, 0xE940, + 0x5674, 0xBC51, 0x5676, 0xBEBF, 0x5677, 0xE946, 0x5678, 0xBEB7, 0x5679, 0xBEB4, 0x567E, 0xECC6, 0x567F, 0xECC8, 0x5680, 0xC07B, + 0x5681, 0xECC9, 0x5682, 0xECC7, 0x5683, 0xECC5, 0x5684, 0xECC4, 0x5685, 0xC07D, 0x5686, 0xECC3, 0x5687, 0xC07E, 0x568C, 0xECC1, + 0x568D, 0xECC2, 0x568E, 0xC07A, 0x568F, 0xC0A1, 0x5690, 0xC07C, 0x5693, 0xECC0, 0x5695, 0xC250, 0x5697, 0xEFBC, 0x5698, 0xEFBA, + 0x5699, 0xEFBF, 0x569A, 0xEFBD, 0x569C, 0xEFBB, 0x569D, 0xEFBE, 0x56A5, 0xC360, 0x56A6, 0xF1F2, 0x56A7, 0xF1F3, 0x56A8, 0xC456, + 0x56AA, 0xF1F4, 0x56AB, 0xF1F0, 0x56AC, 0xF1F5, 0x56AD, 0xF1F1, 0x56AE, 0xC251, 0x56B2, 0xF3FE, 0x56B3, 0xF441, 0x56B4, 0xC459, + 0x56B5, 0xF440, 0x56B6, 0xC458, 0x56B7, 0xC457, 0x56BC, 0xC45A, 0x56BD, 0xF5C5, 0x56BE, 0xF5C6, 0x56C0, 0xC4DA, 0x56C1, 0xC4D9, + 0x56C2, 0xC4DB, 0x56C3, 0xF5C4, 0x56C5, 0xF6D8, 0x56C6, 0xF6D7, 0x56C8, 0xC56D, 0x56C9, 0xC56F, 0x56CA, 0xC56E, 0x56CB, 0xF6D9, + 0x56CC, 0xC5C8, 0x56CD, 0xF8A6, 0x56D1, 0xC5F1, 0x56D3, 0xF8A5, 0x56D4, 0xF8EE, 0x56D7, 0xC949, 0x56DA, 0xA57D, 0x56DB, 0xA57C, + 0x56DD, 0xA65F, 0x56DE, 0xA65E, 0x56DF, 0xC9C7, 0x56E0, 0xA65D, 0x56E1, 0xC9C6, 0x56E4, 0xA779, 0x56E5, 0xCAA9, 0x56E7, 0xCAA8, + 0x56EA, 0xA777, 0x56EB, 0xA77A, 0x56EE, 0xCAA7, 0x56F0, 0xA778, 0x56F7, 0xCBF0, 0x56F9, 0xCBF1, 0x56FA, 0xA954, 0x56FF, 0xABAA, + 0x5701, 0xD148, 0x5702, 0xD149, 0x5703, 0xAE45, 0x5704, 0xAE46, 0x5707, 0xD4AC, 0x5708, 0xB0E9, 0x5709, 0xB0EB, 0x570A, 0xD4AB, + 0x570B, 0xB0EA, 0x570C, 0xD87C, 0x570D, 0xB3F2, 0x5712, 0xB6E9, 0x5713, 0xB6EA, 0x5714, 0xDCE1, 0x5716, 0xB9CF, 0x5718, 0xB9CE, + 0x571A, 0xE549, 0x571B, 0xE948, 0x571C, 0xE947, 0x571E, 0xF96B, 0x571F, 0xA467, 0x5720, 0xC959, 0x5722, 0xC96E, 0x5723, 0xC96F, + 0x5728, 0xA662, 0x5729, 0xA666, 0x572A, 0xC9C9, 0x572C, 0xA664, 0x572D, 0xA663, 0x572E, 0xC9C8, 0x572F, 0xA665, 0x5730, 0xA661, + 0x5733, 0xA660, 0x5734, 0xC9CA, 0x573B, 0xA7A6, 0x573E, 0xA7A3, 0x5740, 0xA77D, 0x5741, 0xCAAA, 0x5745, 0xCAAB, 0x5747, 0xA7A1, + 0x5749, 0xCAAD, 0x574A, 0xA77B, 0x574B, 0xCAAE, 0x574C, 0xCAAC, 0x574D, 0xA77E, 0x574E, 0xA7A2, 0x574F, 0xA7A5, 0x5750, 0xA7A4, + 0x5751, 0xA77C, 0x5752, 0xCAAF, 0x5761, 0xA959, 0x5762, 0xCBFE, 0x5764, 0xA95B, 0x5766, 0xA95A, 0x5768, 0xCC40, 0x5769, 0xA958, + 0x576A, 0xA957, 0x576B, 0xCBF5, 0x576D, 0xCBF4, 0x576F, 0xCBF2, 0x5770, 0xCBF7, 0x5771, 0xCBF6, 0x5772, 0xCBF3, 0x5773, 0xCBFC, + 0x5774, 0xCBFD, 0x5775, 0xCBFA, 0x5776, 0xCBF8, 0x5777, 0xA956, 0x577B, 0xCBFB, 0x577C, 0xA95C, 0x577D, 0xCC41, 0x5780, 0xCBF9, + 0x5782, 0xABAB, 0x5783, 0xA955, 0x578B, 0xABAC, 0x578C, 0xCE54, 0x578F, 0xCE5A, 0x5793, 0xABB2, 0x5794, 0xCE58, 0x5795, 0xCE5E, + 0x5797, 0xCE55, 0x5798, 0xCE59, 0x5799, 0xCE5B, 0x579A, 0xCE5D, 0x579B, 0xCE57, 0x579D, 0xCE56, 0x579E, 0xCE51, 0x579F, 0xCE52, + 0x57A0, 0xABAD, 0x57A2, 0xABAF, 0x57A3, 0xABAE, 0x57A4, 0xCE53, 0x57A5, 0xCE5C, 0x57AE, 0xABB1, 0x57B5, 0xCE50, 0x57B6, 0xD153, + 0x57B8, 0xD152, 0x57B9, 0xD157, 0x57BA, 0xD14E, 0x57BC, 0xD151, 0x57BD, 0xD150, 0x57BF, 0xD154, 0x57C1, 0xD158, 0x57C2, 0xAE47, + 0x57C3, 0xAE4A, 0x57C6, 0xD14F, 0x57C7, 0xD155, 0x57CB, 0xAE49, 0x57CC, 0xD14A, 0x57CE, 0xABB0, 0x57CF, 0xD4BA, 0x57D0, 0xD156, + 0x57D2, 0xD14D, 0x57D4, 0xAE48, 0x57D5, 0xD14C, 0x57DC, 0xD4B1, 0x57DF, 0xB0EC, 0x57E0, 0xB0F0, 0x57E1, 0xD4C1, 0x57E2, 0xD4AF, + 0x57E3, 0xD4BD, 0x57E4, 0xB0F1, 0x57E5, 0xD4BF, 0x57E7, 0xD4C5, 0x57E9, 0xD4C9, 0x57EC, 0xD4C0, 0x57ED, 0xD4B4, 0x57EE, 0xD4BC, + 0x57F0, 0xD4CA, 0x57F1, 0xD4C8, 0x57F2, 0xD4BE, 0x57F3, 0xD4B9, 0x57F4, 0xD4B2, 0x57F5, 0xD8A6, 0x57F6, 0xD4B0, 0x57F7, 0xB0F5, + 0x57F8, 0xD4B7, 0x57F9, 0xB0F6, 0x57FA, 0xB0F2, 0x57FB, 0xD4AD, 0x57FC, 0xD4C3, 0x57FD, 0xD4B5, 0x5800, 0xD4B3, 0x5801, 0xD4C6, + 0x5802, 0xB0F3, 0x5804, 0xD4CC, 0x5805, 0xB0ED, 0x5806, 0xB0EF, 0x5807, 0xD4BB, 0x5808, 0xD4B6, 0x5809, 0xAE4B, 0x580A, 0xB0EE, + 0x580B, 0xD4B8, 0x580C, 0xD4C7, 0x580D, 0xD4CB, 0x580E, 0xD4C2, 0x5810, 0xD4C4, 0x5814, 0xD4AE, 0x5819, 0xD8A1, 0x581B, 0xD8AA, + 0x581C, 0xD8A9, 0x581D, 0xB3FA, 0x581E, 0xD8A2, 0x5820, 0xB3FB, 0x5821, 0xB3F9, 0x5823, 0xD8A4, 0x5824, 0xB3F6, 0x5825, 0xD8A8, + 0x5827, 0xD8A3, 0x5828, 0xD8A5, 0x5829, 0xD87D, 0x582A, 0xB3F4, 0x582C, 0xD8B2, 0x582D, 0xD8B1, 0x582E, 0xD8AE, 0x582F, 0xB3F3, + 0x5830, 0xB3F7, 0x5831, 0xB3F8, 0x5832, 0xD14B, 0x5833, 0xD8AB, 0x5834, 0xB3F5, 0x5835, 0xB0F4, 0x5836, 0xD8AD, 0x5837, 0xD87E, + 0x5838, 0xD8B0, 0x5839, 0xD8AF, 0x583B, 0xD8B3, 0x583D, 0xDCEF, 0x583F, 0xD8AC, 0x5848, 0xD8A7, 0x5849, 0xDCE7, 0x584A, 0xB6F4, + 0x584B, 0xB6F7, 0x584C, 0xB6F2, 0x584D, 0xDCE6, 0x584E, 0xDCEA, 0x584F, 0xDCE5, 0x5851, 0xB6EC, 0x5852, 0xB6F6, 0x5853, 0xDCE2, + 0x5854, 0xB6F0, 0x5855, 0xDCE9, 0x5857, 0xB6EE, 0x5858, 0xB6ED, 0x5859, 0xDCEC, 0x585A, 0xB6EF, 0x585B, 0xDCEE, 0x585D, 0xDCEB, + 0x585E, 0xB6EB, 0x5862, 0xB6F5, 0x5863, 0xDCF0, 0x5864, 0xDCE4, 0x5865, 0xDCED, 0x5868, 0xDCE3, 0x586B, 0xB6F1, 0x586D, 0xB6F3, + 0x586F, 0xDCE8, 0x5871, 0xDCF1, 0x5874, 0xE15D, 0x5875, 0xB9D0, 0x5876, 0xE163, 0x5879, 0xB9D5, 0x587A, 0xE15F, 0x587B, 0xE166, + 0x587C, 0xE157, 0x587D, 0xB9D7, 0x587E, 0xB9D1, 0x587F, 0xE15C, 0x5880, 0xBC55, 0x5881, 0xE15B, 0x5882, 0xE164, 0x5883, 0xB9D2, + 0x5885, 0xB9D6, 0x5886, 0xE15A, 0x5887, 0xE160, 0x5888, 0xE165, 0x5889, 0xE156, 0x588A, 0xB9D4, 0x588B, 0xE15E, 0x588E, 0xE162, + 0x588F, 0xE168, 0x5890, 0xE158, 0x5891, 0xE161, 0x5893, 0xB9D3, 0x5894, 0xE167, 0x5898, 0xE159, 0x589C, 0xBC59, 0x589D, 0xE54B, + 0x589E, 0xBC57, 0x589F, 0xBC56, 0x58A0, 0xE54D, 0x58A1, 0xE552, 0x58A3, 0xE54E, 0x58A5, 0xE551, 0x58A6, 0xBC5C, 0x58A8, 0xBEA5, + 0x58A9, 0xBC5B, 0x58AB, 0xE54A, 0x58AC, 0xE550, 0x58AE, 0xBC5A, 0x58AF, 0xE54F, 0x58B1, 0xE54C, 0x58B3, 0xBC58, 0x58BA, 0xE94D, + 0x58BB, 0xF9D9, 0x58BC, 0xE94F, 0x58BD, 0xE94A, 0x58BE, 0xBEC1, 0x58BF, 0xE94C, 0x58C1, 0xBEC0, 0x58C2, 0xE94E, 0x58C5, 0xBEC3, + 0x58C6, 0xE950, 0x58C7, 0xBEC2, 0x58C8, 0xE949, 0x58C9, 0xE94B, 0x58CE, 0xC0A5, 0x58CF, 0xECCC, 0x58D1, 0xC0A4, 0x58D2, 0xECCD, + 0x58D3, 0xC0A3, 0x58D4, 0xECCB, 0x58D5, 0xC0A2, 0x58D6, 0xECCA, 0x58D8, 0xC253, 0x58D9, 0xC252, 0x58DA, 0xF1F6, 0x58DB, 0xF1F8, + 0x58DD, 0xF1F7, 0x58DE, 0xC361, 0x58DF, 0xC362, 0x58E2, 0xC363, 0x58E3, 0xF442, 0x58E4, 0xC45B, 0x58E7, 0xF7D3, 0x58E8, 0xF7D2, + 0x58E9, 0xC5F2, 0x58EB, 0xA468, 0x58EC, 0xA4D0, 0x58EF, 0xA7A7, 0x58F4, 0xCE5F, 0x58F9, 0xB3FC, 0x58FA, 0xB3FD, 0x58FC, 0xDCF2, + 0x58FD, 0xB9D8, 0x58FE, 0xE169, 0x58FF, 0xE553, 0x5903, 0xC95A, 0x5906, 0xCAB0, 0x590C, 0xCC42, 0x590D, 0xCE60, 0x590E, 0xD159, + 0x590F, 0xAE4C, 0x5912, 0xF1F9, 0x5914, 0xC4DC, 0x5915, 0xA469, 0x5916, 0xA57E, 0x5917, 0xC970, 0x5919, 0xA667, 0x591A, 0xA668, + 0x591C, 0xA95D, 0x5920, 0xB0F7, 0x5922, 0xB9DA, 0x5924, 0xB9DB, 0x5925, 0xB9D9, 0x5927, 0xA46A, 0x5929, 0xA4D1, 0x592A, 0xA4D3, + 0x592B, 0xA4D2, 0x592C, 0xC95B, 0x592D, 0xA4D4, 0x592E, 0xA5A1, 0x592F, 0xC971, 0x5931, 0xA5A2, 0x5937, 0xA669, 0x5938, 0xA66A, + 0x593C, 0xC9CB, 0x593E, 0xA7A8, 0x5940, 0xCAB1, 0x5944, 0xA961, 0x5945, 0xCC43, 0x5947, 0xA95F, 0x5948, 0xA960, 0x5949, 0xA95E, + 0x594A, 0xD15A, 0x594E, 0xABB6, 0x594F, 0xABB5, 0x5950, 0xABB7, 0x5951, 0xABB4, 0x5953, 0xCE61, 0x5954, 0xA962, 0x5955, 0xABB3, + 0x5957, 0xAE4D, 0x5958, 0xAE4E, 0x595A, 0xAE4F, 0x595C, 0xD4CD, 0x5960, 0xB3FE, 0x5961, 0xD8B4, 0x5962, 0xB0F8, 0x5967, 0xB6F8, + 0x5969, 0xB9DD, 0x596A, 0xB9DC, 0x596B, 0xE16A, 0x596D, 0xBC5D, 0x596E, 0xBEC4, 0x5970, 0xEFC0, 0x5971, 0xF6DA, 0x5972, 0xF7D4, + 0x5973, 0xA46B, 0x5974, 0xA5A3, 0x5976, 0xA5A4, 0x5977, 0xC9D1, 0x5978, 0xA66C, 0x5979, 0xA66F, 0x597B, 0xC9CF, 0x597C, 0xC9CD, + 0x597D, 0xA66E, 0x597E, 0xC9D0, 0x597F, 0xC9D2, 0x5980, 0xC9CC, 0x5981, 0xA671, 0x5982, 0xA670, 0x5983, 0xA66D, 0x5984, 0xA66B, + 0x5985, 0xC9CE, 0x598A, 0xA7B3, 0x598D, 0xA7B0, 0x598E, 0xCAB6, 0x598F, 0xCAB9, 0x5990, 0xCAB8, 0x5992, 0xA7AA, 0x5993, 0xA7B2, + 0x5996, 0xA7AF, 0x5997, 0xCAB5, 0x5998, 0xCAB3, 0x5999, 0xA7AE, 0x599D, 0xA7A9, 0x599E, 0xA7AC, 0x59A0, 0xCAB4, 0x59A1, 0xCABB, + 0x59A2, 0xCAB7, 0x59A3, 0xA7AD, 0x59A4, 0xA7B1, 0x59A5, 0xA7B4, 0x59A6, 0xCAB2, 0x59A7, 0xCABA, 0x59A8, 0xA7AB, 0x59AE, 0xA967, + 0x59AF, 0xA96F, 0x59B1, 0xCC4F, 0x59B2, 0xCC48, 0x59B3, 0xA970, 0x59B4, 0xCC53, 0x59B5, 0xCC44, 0x59B6, 0xCC4B, 0x59B9, 0xA966, + 0x59BA, 0xCC45, 0x59BB, 0xA964, 0x59BC, 0xCC4C, 0x59BD, 0xCC50, 0x59BE, 0xA963, 0x59C0, 0xCC51, 0x59C1, 0xCC4A, 0x59C3, 0xCC4D, + 0x59C5, 0xA972, 0x59C6, 0xA969, 0x59C7, 0xCC54, 0x59C8, 0xCC52, 0x59CA, 0xA96E, 0x59CB, 0xA96C, 0x59CC, 0xCC49, 0x59CD, 0xA96B, + 0x59CE, 0xCC47, 0x59CF, 0xCC46, 0x59D0, 0xA96A, 0x59D1, 0xA968, 0x59D2, 0xA971, 0x59D3, 0xA96D, 0x59D4, 0xA965, 0x59D6, 0xCC4E, + 0x59D8, 0xABB9, 0x59DA, 0xABC0, 0x59DB, 0xCE6F, 0x59DC, 0xABB8, 0x59DD, 0xCE67, 0x59DE, 0xCE63, 0x59E0, 0xCE73, 0x59E1, 0xCE62, + 0x59E3, 0xABBB, 0x59E4, 0xCE6C, 0x59E5, 0xABBE, 0x59E6, 0xABC1, 0x59E8, 0xABBC, 0x59E9, 0xCE70, 0x59EA, 0xABBF, 0x59EC, 0xAE56, + 0x59ED, 0xCE76, 0x59EE, 0xCE64, 0x59F1, 0xCE66, 0x59F2, 0xCE6D, 0x59F3, 0xCE71, 0x59F4, 0xCE75, 0x59F5, 0xCE72, 0x59F6, 0xCE6B, + 0x59F7, 0xCE6E, 0x59FA, 0xCE68, 0x59FB, 0xABC3, 0x59FC, 0xCE6A, 0x59FD, 0xCE69, 0x59FE, 0xCE74, 0x59FF, 0xABBA, 0x5A00, 0xCE65, + 0x5A01, 0xABC2, 0x5A03, 0xABBD, 0x5A09, 0xAE5C, 0x5A0A, 0xD162, 0x5A0C, 0xAE5B, 0x5A0F, 0xD160, 0x5A11, 0xAE50, 0x5A13, 0xAE55, + 0x5A15, 0xD15F, 0x5A16, 0xD15C, 0x5A17, 0xD161, 0x5A18, 0xAE51, 0x5A19, 0xD15B, 0x5A1B, 0xAE54, 0x5A1C, 0xAE52, 0x5A1E, 0xD163, + 0x5A1F, 0xAE53, 0x5A20, 0xAE57, 0x5A23, 0xAE58, 0x5A25, 0xAE5A, 0x5A29, 0xAE59, 0x5A2D, 0xD15D, 0x5A2E, 0xD15E, 0x5A33, 0xD164, + 0x5A35, 0xD4D4, 0x5A36, 0xB0F9, 0x5A37, 0xD8C2, 0x5A38, 0xD4D3, 0x5A39, 0xD4E6, 0x5A3C, 0xB140, 0x5A3E, 0xD4E4, 0x5A40, 0xB0FE, + 0x5A41, 0xB0FA, 0x5A42, 0xD4ED, 0x5A43, 0xD4DD, 0x5A44, 0xD4E0, 0x5A46, 0xB143, 0x5A47, 0xD4EA, 0x5A48, 0xD4E2, 0x5A49, 0xB0FB, + 0x5A4A, 0xB144, 0x5A4C, 0xD4E7, 0x5A4D, 0xD4E5, 0x5A50, 0xD4D6, 0x5A51, 0xD4EB, 0x5A52, 0xD4DF, 0x5A53, 0xD4DA, 0x5A55, 0xD4D0, + 0x5A56, 0xD4EC, 0x5A57, 0xD4DC, 0x5A58, 0xD4CF, 0x5A5A, 0xB142, 0x5A5B, 0xD4E1, 0x5A5C, 0xD4EE, 0x5A5D, 0xD4DE, 0x5A5E, 0xD4D2, + 0x5A5F, 0xD4D7, 0x5A60, 0xD4CE, 0x5A62, 0xB141, 0x5A64, 0xD4DB, 0x5A65, 0xD4D8, 0x5A66, 0xB0FC, 0x5A67, 0xD4D1, 0x5A69, 0xD4E9, + 0x5A6A, 0xB0FD, 0x5A6C, 0xD4D9, 0x5A6D, 0xD4D5, 0x5A70, 0xD4E8, 0x5A77, 0xB440, 0x5A78, 0xD8BB, 0x5A7A, 0xD8B8, 0x5A7B, 0xD8C9, + 0x5A7C, 0xD8BD, 0x5A7D, 0xD8CA, 0x5A7F, 0xB442, 0x5A83, 0xD8C6, 0x5A84, 0xD8C3, 0x5A8A, 0xD8C4, 0x5A8B, 0xD8C7, 0x5A8C, 0xD8CB, + 0x5A8E, 0xD4E3, 0x5A8F, 0xD8CD, 0x5A90, 0xDD47, 0x5A92, 0xB443, 0x5A93, 0xD8CE, 0x5A94, 0xD8B6, 0x5A95, 0xD8C0, 0x5A97, 0xD8C5, + 0x5A9A, 0xB441, 0x5A9B, 0xB444, 0x5A9C, 0xD8CC, 0x5A9D, 0xD8CF, 0x5A9E, 0xD8BA, 0x5A9F, 0xD8B7, 0x5AA2, 0xD8B9, 0x5AA5, 0xD8BE, + 0x5AA6, 0xD8BC, 0x5AA7, 0xB445, 0x5AA9, 0xD8C8, 0x5AAC, 0xD8BF, 0x5AAE, 0xD8C1, 0x5AAF, 0xD8B5, 0x5AB0, 0xDCFA, 0x5AB1, 0xDCF8, + 0x5AB2, 0xB742, 0x5AB3, 0xB740, 0x5AB4, 0xDD43, 0x5AB5, 0xDCF9, 0x5AB6, 0xDD44, 0x5AB7, 0xDD40, 0x5AB8, 0xDCF7, 0x5AB9, 0xDD46, + 0x5ABA, 0xDCF6, 0x5ABB, 0xDCFD, 0x5ABC, 0xB6FE, 0x5ABD, 0xB6FD, 0x5ABE, 0xB6FC, 0x5ABF, 0xDCFB, 0x5AC0, 0xDD41, 0x5AC1, 0xB6F9, + 0x5AC2, 0xB741, 0x5AC4, 0xDCF4, 0x5AC6, 0xDCFE, 0x5AC7, 0xDCF3, 0x5AC8, 0xDCFC, 0x5AC9, 0xB6FA, 0x5ACA, 0xDD42, 0x5ACB, 0xDCF5, + 0x5ACC, 0xB6FB, 0x5ACD, 0xDD45, 0x5AD5, 0xE16E, 0x5AD6, 0xB9E2, 0x5AD7, 0xB9E1, 0x5AD8, 0xB9E3, 0x5AD9, 0xE17A, 0x5ADA, 0xE170, + 0x5ADB, 0xE176, 0x5ADC, 0xE16B, 0x5ADD, 0xE179, 0x5ADE, 0xE178, 0x5ADF, 0xE17C, 0x5AE0, 0xE175, 0x5AE1, 0xB9DE, 0x5AE2, 0xE174, + 0x5AE3, 0xB9E4, 0x5AE5, 0xE16D, 0x5AE6, 0xB9DF, 0x5AE8, 0xE17B, 0x5AE9, 0xB9E0, 0x5AEA, 0xE16F, 0x5AEB, 0xE172, 0x5AEC, 0xE177, + 0x5AED, 0xE171, 0x5AEE, 0xE16C, 0x5AF3, 0xE173, 0x5AF4, 0xE555, 0x5AF5, 0xBC61, 0x5AF6, 0xE558, 0x5AF7, 0xE557, 0x5AF8, 0xE55A, + 0x5AF9, 0xE55C, 0x5AFA, 0xF9DC, 0x5AFB, 0xBC5F, 0x5AFD, 0xE556, 0x5AFF, 0xE554, 0x5B01, 0xE55D, 0x5B02, 0xE55B, 0x5B03, 0xE559, + 0x5B05, 0xE55F, 0x5B07, 0xE55E, 0x5B08, 0xBC63, 0x5B09, 0xBC5E, 0x5B0B, 0xBC60, 0x5B0C, 0xBC62, 0x5B0F, 0xE560, 0x5B10, 0xE957, + 0x5B13, 0xE956, 0x5B14, 0xE955, 0x5B16, 0xE958, 0x5B17, 0xE951, 0x5B19, 0xE952, 0x5B1A, 0xE95A, 0x5B1B, 0xE953, 0x5B1D, 0xBEC5, + 0x5B1E, 0xE95C, 0x5B20, 0xE95B, 0x5B21, 0xE954, 0x5B23, 0xECD1, 0x5B24, 0xC0A8, 0x5B25, 0xECCF, 0x5B26, 0xECD4, 0x5B27, 0xECD3, + 0x5B28, 0xE959, 0x5B2A, 0xC0A7, 0x5B2C, 0xECD2, 0x5B2D, 0xECCE, 0x5B2E, 0xECD6, 0x5B2F, 0xECD5, 0x5B30, 0xC0A6, 0x5B32, 0xECD0, + 0x5B34, 0xBEC6, 0x5B38, 0xC254, 0x5B3C, 0xEFC1, 0x5B3D, 0xF1FA, 0x5B3E, 0xF1FB, 0x5B3F, 0xF1FC, 0x5B40, 0xC45C, 0x5B43, 0xC45D, + 0x5B45, 0xF443, 0x5B47, 0xF5C8, 0x5B48, 0xF5C7, 0x5B4B, 0xF6DB, 0x5B4C, 0xF6DC, 0x5B4D, 0xF7D5, 0x5B4E, 0xF8A7, 0x5B50, 0xA46C, + 0x5B51, 0xA46D, 0x5B53, 0xA46E, 0x5B54, 0xA4D5, 0x5B55, 0xA5A5, 0x5B56, 0xC9D3, 0x5B57, 0xA672, 0x5B58, 0xA673, 0x5B5A, 0xA7B7, + 0x5B5B, 0xA7B8, 0x5B5C, 0xA7B6, 0x5B5D, 0xA7B5, 0x5B5F, 0xA973, 0x5B62, 0xCC55, 0x5B63, 0xA975, 0x5B64, 0xA974, 0x5B65, 0xCC56, + 0x5B69, 0xABC4, 0x5B6B, 0xAE5D, 0x5B6C, 0xD165, 0x5B6E, 0xD4F0, 0x5B70, 0xB145, 0x5B71, 0xB447, 0x5B72, 0xD4EF, 0x5B73, 0xB446, + 0x5B75, 0xB9E5, 0x5B77, 0xE17D, 0x5B78, 0xBEC7, 0x5B7A, 0xC0A9, 0x5B7B, 0xECD7, 0x5B7D, 0xC45E, 0x5B7F, 0xC570, 0x5B81, 0xC972, + 0x5B83, 0xA5A6, 0x5B84, 0xC973, 0x5B85, 0xA676, 0x5B87, 0xA674, 0x5B88, 0xA675, 0x5B89, 0xA677, 0x5B8B, 0xA7BA, 0x5B8C, 0xA7B9, + 0x5B8E, 0xCABC, 0x5B8F, 0xA7BB, 0x5B92, 0xCABD, 0x5B93, 0xCC57, 0x5B95, 0xCC58, 0x5B97, 0xA976, 0x5B98, 0xA978, 0x5B99, 0xA97A, + 0x5B9A, 0xA977, 0x5B9B, 0xA97B, 0x5B9C, 0xA979, 0x5BA2, 0xABC8, 0x5BA3, 0xABC5, 0x5BA4, 0xABC7, 0x5BA5, 0xABC9, 0x5BA6, 0xABC6, + 0x5BA7, 0xD166, 0x5BA8, 0xCE77, 0x5BAC, 0xD168, 0x5BAD, 0xD167, 0x5BAE, 0xAE63, 0x5BB0, 0xAE5F, 0x5BB3, 0xAE60, 0x5BB4, 0xAE62, + 0x5BB5, 0xAE64, 0x5BB6, 0xAE61, 0x5BB8, 0xAE66, 0x5BB9, 0xAE65, 0x5BBF, 0xB14A, 0x5BC0, 0xD4F2, 0x5BC1, 0xD4F1, 0x5BC2, 0xB149, + 0x5BC4, 0xB148, 0x5BC5, 0xB147, 0x5BC6, 0xB14B, 0x5BC7, 0xB146, 0x5BCA, 0xD8D5, 0x5BCB, 0xD8D2, 0x5BCC, 0xB449, 0x5BCD, 0xD8D1, + 0x5BCE, 0xD8D6, 0x5BD0, 0xB44B, 0x5BD1, 0xD8D4, 0x5BD2, 0xB448, 0x5BD3, 0xB44A, 0x5BD4, 0xD8D3, 0x5BD6, 0xDD48, 0x5BD8, 0xDD49, + 0x5BD9, 0xDD4A, 0x5BDE, 0xB9E6, 0x5BDF, 0xB9EE, 0x5BE0, 0xE17E, 0x5BE1, 0xB9E8, 0x5BE2, 0xB9EC, 0x5BE3, 0xE1A1, 0x5BE4, 0xB9ED, + 0x5BE5, 0xB9E9, 0x5BE6, 0xB9EA, 0x5BE7, 0xB9E7, 0x5BE8, 0xB9EB, 0x5BE9, 0xBC66, 0x5BEA, 0xD8D0, 0x5BEB, 0xBC67, 0x5BEC, 0xBC65, + 0x5BEE, 0xBC64, 0x5BEF, 0xE95D, 0x5BF0, 0xBEC8, 0x5BF1, 0xECD8, 0x5BF2, 0xECD9, 0x5BF5, 0xC364, 0x5BF6, 0xC45F, 0x5BF8, 0xA46F, + 0x5BFA, 0xA678, 0x5C01, 0xABCA, 0x5C03, 0xD169, 0x5C04, 0xAE67, 0x5C07, 0xB14E, 0x5C08, 0xB14D, 0x5C09, 0xB14C, 0x5C0A, 0xB44C, + 0x5C0B, 0xB44D, 0x5C0C, 0xD8D7, 0x5C0D, 0xB9EF, 0x5C0E, 0xBEC9, 0x5C0F, 0xA470, 0x5C10, 0xC95C, 0x5C11, 0xA4D6, 0x5C12, 0xC974, + 0x5C15, 0xC9D4, 0x5C16, 0xA679, 0x5C1A, 0xA97C, 0x5C1F, 0xDD4B, 0x5C22, 0xA471, 0x5C24, 0xA4D7, 0x5C25, 0xC9D5, 0x5C28, 0xCABE, + 0x5C2A, 0xCABF, 0x5C2C, 0xA7BC, 0x5C30, 0xD8D8, 0x5C31, 0xB44E, 0x5C33, 0xDD4C, 0x5C37, 0xC0AA, 0x5C38, 0xA472, 0x5C39, 0xA4A8, + 0x5C3A, 0xA4D8, 0x5C3B, 0xC975, 0x5C3C, 0xA5A7, 0x5C3E, 0xA7C0, 0x5C3F, 0xA7BF, 0x5C40, 0xA7BD, 0x5C41, 0xA7BE, 0x5C44, 0xCC59, + 0x5C45, 0xA97E, 0x5C46, 0xA9A1, 0x5C47, 0xCC5A, 0x5C48, 0xA97D, 0x5C4B, 0xABCE, 0x5C4C, 0xCE78, 0x5C4D, 0xABCD, 0x5C4E, 0xABCB, + 0x5C4F, 0xABCC, 0x5C50, 0xAE6A, 0x5C51, 0xAE68, 0x5C54, 0xD16B, 0x5C55, 0xAE69, 0x5C56, 0xD16A, 0x5C58, 0xAE5E, 0x5C59, 0xD4F3, + 0x5C5C, 0xB150, 0x5C5D, 0xB151, 0x5C60, 0xB14F, 0x5C62, 0xB9F0, 0x5C63, 0xE1A2, 0x5C64, 0xBC68, 0x5C65, 0xBC69, 0x5C67, 0xE561, + 0x5C68, 0xC0AB, 0x5C69, 0xEFC2, 0x5C6A, 0xEFC3, 0x5C6C, 0xC4DD, 0x5C6D, 0xF8A8, 0x5C6E, 0xC94B, 0x5C6F, 0xA4D9, 0x5C71, 0xA473, + 0x5C73, 0xC977, 0x5C74, 0xC976, 0x5C79, 0xA67A, 0x5C7A, 0xC9D7, 0x5C7B, 0xC9D8, 0x5C7C, 0xC9D6, 0x5C7E, 0xC9D9, 0x5C86, 0xCAC7, + 0x5C88, 0xCAC2, 0x5C89, 0xCAC4, 0x5C8A, 0xCAC6, 0x5C8B, 0xCAC3, 0x5C8C, 0xA7C4, 0x5C8D, 0xCAC0, 0x5C8F, 0xCAC1, 0x5C90, 0xA7C1, + 0x5C91, 0xA7C2, 0x5C92, 0xCAC5, 0x5C93, 0xCAC8, 0x5C94, 0xA7C3, 0x5C95, 0xCAC9, 0x5C9D, 0xCC68, 0x5C9F, 0xCC62, 0x5CA0, 0xCC5D, + 0x5CA1, 0xA9A3, 0x5CA2, 0xCC65, 0x5CA3, 0xCC63, 0x5CA4, 0xCC5C, 0x5CA5, 0xCC69, 0x5CA6, 0xCC6C, 0x5CA7, 0xCC67, 0x5CA8, 0xCC60, + 0x5CA9, 0xA9A5, 0x5CAA, 0xCC66, 0x5CAB, 0xA9A6, 0x5CAC, 0xCC61, 0x5CAD, 0xCC64, 0x5CAE, 0xCC5B, 0x5CAF, 0xCC5F, 0x5CB0, 0xCC6B, + 0x5CB1, 0xA9A7, 0x5CB3, 0xA9A8, 0x5CB5, 0xCC5E, 0x5CB6, 0xCC6A, 0x5CB7, 0xA9A2, 0x5CB8, 0xA9A4, 0x5CC6, 0xCEAB, 0x5CC7, 0xCEA4, + 0x5CC8, 0xCEAA, 0x5CC9, 0xCEA3, 0x5CCA, 0xCEA5, 0x5CCB, 0xCE7D, 0x5CCC, 0xCE7B, 0x5CCE, 0xCEAC, 0x5CCF, 0xCEA9, 0x5CD0, 0xCE79, + 0x5CD2, 0xABD0, 0x5CD3, 0xCEA7, 0x5CD4, 0xCEA8, 0x5CD6, 0xCEA6, 0x5CD7, 0xCE7C, 0x5CD8, 0xCE7A, 0x5CD9, 0xABCF, 0x5CDA, 0xCEA2, + 0x5CDB, 0xCE7E, 0x5CDE, 0xCEA1, 0x5CDF, 0xCEAD, 0x5CE8, 0xAE6F, 0x5CEA, 0xAE6E, 0x5CEC, 0xD16C, 0x5CED, 0xAE6B, 0x5CEE, 0xD16E, + 0x5CF0, 0xAE70, 0x5CF1, 0xD16F, 0x5CF4, 0xAE73, 0x5CF6, 0xAE71, 0x5CF7, 0xD170, 0x5CF8, 0xCEAE, 0x5CF9, 0xD172, 0x5CFB, 0xAE6D, + 0x5CFD, 0xAE6C, 0x5CFF, 0xD16D, 0x5D00, 0xD171, 0x5D01, 0xAE72, 0x5D06, 0xB153, 0x5D07, 0xB152, 0x5D0B, 0xD4F5, 0x5D0C, 0xD4F9, + 0x5D0D, 0xD4FB, 0x5D0E, 0xB154, 0x5D0F, 0xD4FE, 0x5D11, 0xB158, 0x5D12, 0xD541, 0x5D14, 0xB15A, 0x5D16, 0xB156, 0x5D17, 0xB15E, + 0x5D19, 0xB15B, 0x5D1A, 0xD4F7, 0x5D1B, 0xB155, 0x5D1D, 0xD4F6, 0x5D1E, 0xD4F4, 0x5D1F, 0xD543, 0x5D20, 0xD4F8, 0x5D22, 0xB157, + 0x5D23, 0xD542, 0x5D24, 0xB15C, 0x5D25, 0xD4FD, 0x5D26, 0xD4FC, 0x5D27, 0xB15D, 0x5D28, 0xD4FA, 0x5D29, 0xB159, 0x5D2E, 0xD544, + 0x5D30, 0xD540, 0x5D31, 0xD8E7, 0x5D32, 0xD8EE, 0x5D33, 0xD8E3, 0x5D34, 0xB451, 0x5D35, 0xD8DF, 0x5D36, 0xD8EF, 0x5D37, 0xD8D9, + 0x5D38, 0xD8EC, 0x5D39, 0xD8EA, 0x5D3A, 0xD8E4, 0x5D3C, 0xD8ED, 0x5D3D, 0xD8E6, 0x5D3F, 0xD8DE, 0x5D40, 0xD8F0, 0x5D41, 0xD8DC, + 0x5D42, 0xD8E9, 0x5D43, 0xD8DA, 0x5D45, 0xD8F1, 0x5D47, 0xB452, 0x5D49, 0xD8EB, 0x5D4A, 0xDD4F, 0x5D4B, 0xD8DD, 0x5D4C, 0xB44F, + 0x5D4E, 0xD8E1, 0x5D50, 0xB450, 0x5D51, 0xD8E0, 0x5D52, 0xD8E5, 0x5D55, 0xD8E2, 0x5D59, 0xD8E8, 0x5D5E, 0xDD53, 0x5D62, 0xDD56, + 0x5D63, 0xDD4E, 0x5D65, 0xDD50, 0x5D67, 0xDD55, 0x5D68, 0xDD54, 0x5D69, 0xB743, 0x5D6B, 0xD8DB, 0x5D6C, 0xDD52, 0x5D6F, 0xB744, + 0x5D71, 0xDD4D, 0x5D72, 0xDD51, 0x5D77, 0xE1A9, 0x5D79, 0xE1B0, 0x5D7A, 0xE1A7, 0x5D7C, 0xE1AE, 0x5D7D, 0xE1A5, 0x5D7E, 0xE1AD, + 0x5D7F, 0xE1B1, 0x5D80, 0xE1A4, 0x5D81, 0xE1A8, 0x5D82, 0xE1A3, 0x5D84, 0xB9F1, 0x5D86, 0xE1A6, 0x5D87, 0xB9F2, 0x5D88, 0xE1AC, + 0x5D89, 0xE1AB, 0x5D8A, 0xE1AA, 0x5D8D, 0xE1AF, 0x5D92, 0xE565, 0x5D93, 0xE567, 0x5D94, 0xBC6B, 0x5D95, 0xE568, 0x5D97, 0xE563, + 0x5D99, 0xE562, 0x5D9A, 0xE56C, 0x5D9C, 0xE56A, 0x5D9D, 0xBC6A, 0x5D9E, 0xE56D, 0x5D9F, 0xE564, 0x5DA0, 0xE569, 0x5DA1, 0xE56B, + 0x5DA2, 0xE566, 0x5DA7, 0xE961, 0x5DA8, 0xE966, 0x5DA9, 0xE960, 0x5DAA, 0xE965, 0x5DAC, 0xE95E, 0x5DAD, 0xE968, 0x5DAE, 0xE964, + 0x5DAF, 0xE969, 0x5DB0, 0xE963, 0x5DB1, 0xE95F, 0x5DB2, 0xE967, 0x5DB4, 0xE96A, 0x5DB5, 0xE962, 0x5DB7, 0xECDA, 0x5DB8, 0xC0AF, + 0x5DBA, 0xC0AD, 0x5DBC, 0xC0AC, 0x5DBD, 0xC0AE, 0x5DC0, 0xEFC4, 0x5DC2, 0xF172, 0x5DC3, 0xF1FD, 0x5DC6, 0xF444, 0x5DC7, 0xF445, + 0x5DC9, 0xC460, 0x5DCB, 0xF5C9, 0x5DCD, 0xC4DE, 0x5DCF, 0xF5CA, 0x5DD1, 0xF6DE, 0x5DD2, 0xC572, 0x5DD4, 0xC571, 0x5DD5, 0xF6DD, + 0x5DD6, 0xC5C9, 0x5DD8, 0xF7D6, 0x5DDD, 0xA474, 0x5DDE, 0xA67B, 0x5DDF, 0xC9DA, 0x5DE0, 0xCACA, 0x5DE1, 0xA8B5, 0x5DE2, 0xB15F, + 0x5DE5, 0xA475, 0x5DE6, 0xA5AA, 0x5DE7, 0xA5A9, 0x5DE8, 0xA5A8, 0x5DEB, 0xA7C5, 0x5DEE, 0xAE74, 0x5DF0, 0xDD57, 0x5DF1, 0xA476, + 0x5DF2, 0xA477, 0x5DF3, 0xA478, 0x5DF4, 0xA4DA, 0x5DF7, 0xABD1, 0x5DF9, 0xCEAF, 0x5DFD, 0xB453, 0x5DFE, 0xA479, 0x5DFF, 0xC95D, + 0x5E02, 0xA5AB, 0x5E03, 0xA5AC, 0x5E04, 0xC978, 0x5E06, 0xA67C, 0x5E0A, 0xCACB, 0x5E0C, 0xA7C6, 0x5E0E, 0xCACC, 0x5E11, 0xA9AE, + 0x5E14, 0xCC6E, 0x5E15, 0xA9AC, 0x5E16, 0xA9AB, 0x5E17, 0xCC6D, 0x5E18, 0xA9A9, 0x5E19, 0xCC6F, 0x5E1A, 0xA9AA, 0x5E1B, 0xA9AD, + 0x5E1D, 0xABD2, 0x5E1F, 0xABD4, 0x5E20, 0xCEB3, 0x5E21, 0xCEB0, 0x5E22, 0xCEB1, 0x5E23, 0xCEB2, 0x5E24, 0xCEB4, 0x5E25, 0xABD3, + 0x5E28, 0xD174, 0x5E29, 0xD173, 0x5E2B, 0xAE76, 0x5E2D, 0xAE75, 0x5E33, 0xB162, 0x5E34, 0xD546, 0x5E36, 0xB161, 0x5E37, 0xB163, + 0x5E38, 0xB160, 0x5E3D, 0xB455, 0x5E3E, 0xD545, 0x5E40, 0xB456, 0x5E41, 0xD8F3, 0x5E43, 0xB457, 0x5E44, 0xD8F2, 0x5E45, 0xB454, + 0x5E4A, 0xDD5A, 0x5E4B, 0xDD5C, 0x5E4C, 0xB745, 0x5E4D, 0xDD5B, 0x5E4E, 0xDD59, 0x5E4F, 0xDD58, 0x5E53, 0xE1B4, 0x5E54, 0xB9F7, + 0x5E55, 0xB9F5, 0x5E57, 0xB9F6, 0x5E58, 0xE1B2, 0x5E59, 0xE1B3, 0x5E5B, 0xB9F3, 0x5E5C, 0xE571, 0x5E5D, 0xE56F, 0x5E5F, 0xBC6D, + 0x5E60, 0xE570, 0x5E61, 0xBC6E, 0x5E62, 0xBC6C, 0x5E63, 0xB9F4, 0x5E66, 0xE96D, 0x5E67, 0xE96B, 0x5E68, 0xE96C, 0x5E69, 0xE56E, + 0x5E6A, 0xECDC, 0x5E6B, 0xC0B0, 0x5E6C, 0xECDB, 0x5E6D, 0xEFC5, 0x5E6E, 0xEFC6, 0x5E6F, 0xE96E, 0x5E70, 0xF1FE, 0x5E72, 0xA47A, + 0x5E73, 0xA5AD, 0x5E74, 0xA67E, 0x5E75, 0xC9DB, 0x5E76, 0xA67D, 0x5E78, 0xA9AF, 0x5E79, 0xB746, 0x5E7B, 0xA4DB, 0x5E7C, 0xA5AE, + 0x5E7D, 0xABD5, 0x5E7E, 0xB458, 0x5E80, 0xC979, 0x5E82, 0xC97A, 0x5E84, 0xC9DC, 0x5E87, 0xA7C8, 0x5E88, 0xCAD0, 0x5E89, 0xCACE, + 0x5E8A, 0xA7C9, 0x5E8B, 0xCACD, 0x5E8C, 0xCACF, 0x5E8D, 0xCAD1, 0x5E8F, 0xA7C7, 0x5E95, 0xA9B3, 0x5E96, 0xA9B4, 0x5E97, 0xA9B1, + 0x5E9A, 0xA9B0, 0x5E9B, 0xCEB8, 0x5E9C, 0xA9B2, 0x5EA0, 0xABD6, 0x5EA2, 0xCEB7, 0x5EA3, 0xCEB9, 0x5EA4, 0xCEB6, 0x5EA5, 0xCEBA, + 0x5EA6, 0xABD7, 0x5EA7, 0xAE79, 0x5EA8, 0xD175, 0x5EAA, 0xD177, 0x5EAB, 0xAE77, 0x5EAC, 0xD178, 0x5EAD, 0xAE78, 0x5EAE, 0xD176, + 0x5EB0, 0xCEB5, 0x5EB1, 0xD547, 0x5EB2, 0xD54A, 0x5EB3, 0xD54B, 0x5EB4, 0xD548, 0x5EB5, 0xB167, 0x5EB6, 0xB166, 0x5EB7, 0xB164, + 0x5EB8, 0xB165, 0x5EB9, 0xD549, 0x5EBE, 0xB168, 0x5EC1, 0xB45A, 0x5EC2, 0xB45B, 0x5EC4, 0xB45C, 0x5EC5, 0xDD5D, 0x5EC6, 0xDD5F, + 0x5EC7, 0xDD61, 0x5EC8, 0xB748, 0x5EC9, 0xB747, 0x5ECA, 0xB459, 0x5ECB, 0xDD60, 0x5ECC, 0xDD5E, 0x5ECE, 0xE1B8, 0x5ED1, 0xE1B6, + 0x5ED2, 0xE1BC, 0x5ED3, 0xB9F8, 0x5ED4, 0xE1BD, 0x5ED5, 0xE1BA, 0x5ED6, 0xB9F9, 0x5ED7, 0xE1B7, 0x5ED8, 0xE1B5, 0x5ED9, 0xE1BB, + 0x5EDA, 0xBC70, 0x5EDB, 0xE573, 0x5EDC, 0xE1B9, 0x5EDD, 0xBC72, 0x5EDE, 0xE574, 0x5EDF, 0xBC71, 0x5EE0, 0xBC74, 0x5EE1, 0xE575, + 0x5EE2, 0xBC6F, 0x5EE3, 0xBC73, 0x5EE5, 0xE973, 0x5EE6, 0xE971, 0x5EE7, 0xE970, 0x5EE8, 0xE972, 0x5EE9, 0xE96F, 0x5EEC, 0xC366, + 0x5EEE, 0xF446, 0x5EEF, 0xF447, 0x5EF1, 0xF5CB, 0x5EF2, 0xF6DF, 0x5EF3, 0xC655, 0x5EF6, 0xA9B5, 0x5EF7, 0xA7CA, 0x5EFA, 0xABD8, + 0x5EFE, 0xA47B, 0x5EFF, 0xA4DC, 0x5F01, 0xA5AF, 0x5F02, 0xC9DD, 0x5F04, 0xA7CB, 0x5F05, 0xCAD2, 0x5F07, 0xCEBB, 0x5F08, 0xABD9, + 0x5F0A, 0xB9FA, 0x5F0B, 0xA47C, 0x5F0F, 0xA6A1, 0x5F12, 0xB749, 0x5F13, 0xA47D, 0x5F14, 0xA4DD, 0x5F15, 0xA4DE, 0x5F17, 0xA5B1, + 0x5F18, 0xA5B0, 0x5F1A, 0xC9DE, 0x5F1B, 0xA6A2, 0x5F1D, 0xCAD3, 0x5F1F, 0xA7CC, 0x5F22, 0xCC71, 0x5F23, 0xCC72, 0x5F24, 0xCC73, + 0x5F26, 0xA9B6, 0x5F27, 0xA9B7, 0x5F28, 0xCC70, 0x5F29, 0xA9B8, 0x5F2D, 0xABDA, 0x5F2E, 0xCEBC, 0x5F30, 0xD17A, 0x5F31, 0xAE7A, + 0x5F33, 0xD179, 0x5F35, 0xB169, 0x5F36, 0xD54C, 0x5F37, 0xB16A, 0x5F38, 0xD54D, 0x5F3C, 0xB45D, 0x5F40, 0xDD62, 0x5F43, 0xE1BF, + 0x5F44, 0xE1BE, 0x5F46, 0xB9FB, 0x5F48, 0xBC75, 0x5F49, 0xE576, 0x5F4A, 0xBECA, 0x5F4B, 0xE974, 0x5F4C, 0xC0B1, 0x5F4E, 0xC573, + 0x5F4F, 0xF7D8, 0x5F54, 0xCC74, 0x5F56, 0xCEBD, 0x5F57, 0xB16B, 0x5F58, 0xD8F4, 0x5F59, 0xB74A, 0x5F5D, 0xC255, 0x5F62, 0xA7CE, + 0x5F64, 0xA7CD, 0x5F65, 0xABDB, 0x5F67, 0xD17B, 0x5F69, 0xB16D, 0x5F6A, 0xB343, 0x5F6B, 0xB16E, 0x5F6C, 0xB16C, 0x5F6D, 0xB45E, + 0x5F6F, 0xE1C0, 0x5F70, 0xB9FC, 0x5F71, 0xBC76, 0x5F73, 0xC94C, 0x5F74, 0xC9DF, 0x5F76, 0xCAD5, 0x5F77, 0xA7CF, 0x5F78, 0xCAD4, + 0x5F79, 0xA7D0, 0x5F7C, 0xA9BC, 0x5F7D, 0xCC77, 0x5F7E, 0xCC76, 0x5F7F, 0xA9BB, 0x5F80, 0xA9B9, 0x5F81, 0xA9BA, 0x5F82, 0xCC75, + 0x5F85, 0xABDD, 0x5F86, 0xCEBE, 0x5F87, 0xABE0, 0x5F88, 0xABDC, 0x5F89, 0xABE2, 0x5F8A, 0xABDE, 0x5F8B, 0xABDF, 0x5F8C, 0xABE1, + 0x5F90, 0xAE7D, 0x5F91, 0xAE7C, 0x5F92, 0xAE7B, 0x5F96, 0xD54F, 0x5F97, 0xB16F, 0x5F98, 0xB172, 0x5F99, 0xB170, 0x5F9B, 0xD54E, + 0x5F9C, 0xB175, 0x5F9E, 0xB171, 0x5F9F, 0xD550, 0x5FA0, 0xB174, 0x5FA1, 0xB173, 0x5FA5, 0xD8F6, 0x5FA6, 0xD8F5, 0x5FA8, 0xB461, + 0x5FA9, 0xB45F, 0x5FAA, 0xB460, 0x5FAB, 0xD8F7, 0x5FAC, 0xB74B, 0x5FAD, 0xDD64, 0x5FAE, 0xB74C, 0x5FAF, 0xDD63, 0x5FB2, 0xE577, + 0x5FB5, 0xBC78, 0x5FB6, 0xE1C1, 0x5FB7, 0xBC77, 0x5FB9, 0xB9FD, 0x5FBB, 0xECDE, 0x5FBC, 0xE975, 0x5FBD, 0xC0B2, 0x5FBE, 0xECDD, + 0x5FBF, 0xF240, 0x5FC0, 0xF448, 0x5FC1, 0xF449, 0x5FC3, 0xA4DF, 0x5FC5, 0xA5B2, 0x5FC9, 0xC97B, 0x5FCC, 0xA7D2, 0x5FCD, 0xA7D4, + 0x5FCF, 0xC9E2, 0x5FD0, 0xCAD8, 0x5FD1, 0xCAD7, 0x5FD2, 0xCAD6, 0x5FD4, 0xC9E1, 0x5FD5, 0xC9E0, 0x5FD6, 0xA6A4, 0x5FD7, 0xA7D3, + 0x5FD8, 0xA7D1, 0x5FD9, 0xA6A3, 0x5FDD, 0xA9BD, 0x5FDE, 0xCC78, 0x5FE0, 0xA9BE, 0x5FE1, 0xCADD, 0x5FE3, 0xCADF, 0x5FE4, 0xCADE, + 0x5FE5, 0xCC79, 0x5FE8, 0xCADA, 0x5FEA, 0xA7D8, 0x5FEB, 0xA7D6, 0x5FED, 0xCAD9, 0x5FEE, 0xCADB, 0x5FEF, 0xCAE1, 0x5FF1, 0xA7D5, + 0x5FF3, 0xCADC, 0x5FF4, 0xCAE5, 0x5FF5, 0xA9C0, 0x5FF7, 0xCAE2, 0x5FF8, 0xA7D7, 0x5FFA, 0xCAE0, 0x5FFB, 0xCAE3, 0x5FFD, 0xA9BF, + 0x5FFF, 0xA9C1, 0x6000, 0xCAE4, 0x6009, 0xCCAF, 0x600A, 0xCCA2, 0x600B, 0xCC7E, 0x600C, 0xCCAE, 0x600D, 0xCCA9, 0x600E, 0xABE7, + 0x600F, 0xA9C2, 0x6010, 0xCCAA, 0x6011, 0xCCAD, 0x6012, 0xABE3, 0x6013, 0xCCAC, 0x6014, 0xA9C3, 0x6015, 0xA9C8, 0x6016, 0xA9C6, + 0x6017, 0xCCA3, 0x6019, 0xCC7C, 0x601A, 0xCCA5, 0x601B, 0xA9CD, 0x601C, 0xCCB0, 0x601D, 0xABE4, 0x601E, 0xCCA6, 0x6020, 0xABE5, + 0x6021, 0xA9C9, 0x6022, 0xCCA8, 0x6024, 0xCECD, 0x6025, 0xABE6, 0x6026, 0xCC7B, 0x6027, 0xA9CA, 0x6028, 0xABE8, 0x6029, 0xA9CB, + 0x602A, 0xA9C7, 0x602B, 0xA9CC, 0x602C, 0xCCA7, 0x602D, 0xCC7A, 0x602E, 0xCCAB, 0x602F, 0xA9C4, 0x6032, 0xCC7D, 0x6033, 0xCCA4, + 0x6034, 0xCCA1, 0x6035, 0xA9C5, 0x6037, 0xCEBF, 0x6039, 0xCEC0, 0x6040, 0xCECA, 0x6041, 0xD1A1, 0x6042, 0xCECB, 0x6043, 0xABEE, + 0x6044, 0xCECE, 0x6045, 0xCEC4, 0x6046, 0xABED, 0x6047, 0xCEC6, 0x6049, 0xCEC7, 0x604C, 0xCEC9, 0x604D, 0xABE9, 0x6050, 0xAEA3, + 0x6052, 0xF9DA, 0x6053, 0xCEC5, 0x6054, 0xCEC1, 0x6055, 0xAEA4, 0x6058, 0xCECF, 0x6059, 0xAE7E, 0x605A, 0xD17D, 0x605B, 0xCEC8, + 0x605D, 0xD17C, 0x605E, 0xCEC3, 0x605F, 0xCECC, 0x6062, 0xABEC, 0x6063, 0xAEA1, 0x6064, 0xABF2, 0x6065, 0xAEA2, 0x6066, 0xCED0, + 0x6067, 0xD17E, 0x6068, 0xABEB, 0x6069, 0xAEA6, 0x606A, 0xABF1, 0x606B, 0xABF0, 0x606C, 0xABEF, 0x606D, 0xAEA5, 0x606E, 0xCED1, + 0x606F, 0xAEA7, 0x6070, 0xABEA, 0x6072, 0xCEC2, 0x607F, 0xB176, 0x6080, 0xD1A4, 0x6081, 0xD1A6, 0x6083, 0xD1A8, 0x6084, 0xAEA8, + 0x6085, 0xAEAE, 0x6086, 0xD553, 0x6087, 0xD1AC, 0x6088, 0xD1A3, 0x6089, 0xB178, 0x608A, 0xD551, 0x608C, 0xAEAD, 0x608D, 0xAEAB, + 0x608E, 0xD1AE, 0x6090, 0xD552, 0x6092, 0xD1A5, 0x6094, 0xAEAC, 0x6095, 0xD1A9, 0x6096, 0xAEAF, 0x6097, 0xD1AB, 0x609A, 0xAEAA, + 0x609B, 0xD1AA, 0x609C, 0xD1AD, 0x609D, 0xD1A7, 0x609F, 0xAEA9, 0x60A0, 0xB179, 0x60A2, 0xD1A2, 0x60A3, 0xB177, 0x60A8, 0xB17A, + 0x60B0, 0xD555, 0x60B1, 0xD55E, 0x60B2, 0xB464, 0x60B4, 0xB17C, 0x60B5, 0xB1A3, 0x60B6, 0xB465, 0x60B7, 0xD560, 0x60B8, 0xB1AA, + 0x60B9, 0xD8F9, 0x60BA, 0xD556, 0x60BB, 0xB1A2, 0x60BC, 0xB1A5, 0x60BD, 0xB17E, 0x60BE, 0xD554, 0x60BF, 0xD562, 0x60C0, 0xD565, + 0x60C1, 0xD949, 0x60C3, 0xD563, 0x60C4, 0xD8FD, 0x60C5, 0xB1A1, 0x60C6, 0xB1A8, 0x60C7, 0xB1AC, 0x60C8, 0xD55D, 0x60C9, 0xD8F8, + 0x60CA, 0xD561, 0x60CB, 0xB17B, 0x60CC, 0xD8FA, 0x60CD, 0xD564, 0x60CE, 0xD8FC, 0x60CF, 0xD559, 0x60D1, 0xB462, 0x60D3, 0xD557, + 0x60D4, 0xD558, 0x60D5, 0xB1A7, 0x60D8, 0xB1A6, 0x60D9, 0xD55B, 0x60DA, 0xB1AB, 0x60DB, 0xD55F, 0x60DC, 0xB1A4, 0x60DD, 0xD55C, + 0x60DF, 0xB1A9, 0x60E0, 0xB466, 0x60E1, 0xB463, 0x60E2, 0xD8FB, 0x60E4, 0xD55A, 0x60E6, 0xB17D, 0x60F0, 0xB46B, 0x60F1, 0xB46F, + 0x60F2, 0xD940, 0x60F3, 0xB751, 0x60F4, 0xB46D, 0x60F5, 0xD944, 0x60F6, 0xB471, 0x60F7, 0xDD65, 0x60F8, 0xD946, 0x60F9, 0xB753, + 0x60FA, 0xB469, 0x60FB, 0xB46C, 0x60FC, 0xD947, 0x60FE, 0xD948, 0x60FF, 0xD94E, 0x6100, 0xB473, 0x6101, 0xB754, 0x6103, 0xD94A, + 0x6104, 0xD94F, 0x6105, 0xD943, 0x6106, 0xB75E, 0x6108, 0xB755, 0x6109, 0xB472, 0x610A, 0xD941, 0x610B, 0xD950, 0x610D, 0xB75D, + 0x610E, 0xB470, 0x610F, 0xB74E, 0x6110, 0xD94D, 0x6112, 0xB474, 0x6113, 0xD945, 0x6114, 0xD8FE, 0x6115, 0xB46A, 0x6116, 0xD942, + 0x6118, 0xD94B, 0x611A, 0xB74D, 0x611B, 0xB752, 0x611C, 0xB467, 0x611D, 0xD94C, 0x611F, 0xB750, 0x6123, 0xB468, 0x6127, 0xB75C, + 0x6128, 0xE1C3, 0x6129, 0xDD70, 0x612B, 0xDD68, 0x612C, 0xE1C2, 0x612E, 0xDD6C, 0x612F, 0xDD6E, 0x6132, 0xDD6B, 0x6134, 0xB75B, + 0x6136, 0xDD6A, 0x6137, 0xB75F, 0x613B, 0xE1D2, 0x613E, 0xB75A, 0x613F, 0xBA40, 0x6140, 0xDD71, 0x6141, 0xE1C4, 0x6144, 0xB758, + 0x6145, 0xDD69, 0x6146, 0xDD6D, 0x6147, 0xB9FE, 0x6148, 0xB74F, 0x6149, 0xDD66, 0x614A, 0xDD67, 0x614B, 0xBA41, 0x614C, 0xB757, + 0x614D, 0xB759, 0x614E, 0xB756, 0x614F, 0xDD6F, 0x6152, 0xE1C8, 0x6153, 0xE1C9, 0x6154, 0xE1CE, 0x6155, 0xBC7D, 0x6156, 0xE1D5, + 0x6158, 0xBA47, 0x615A, 0xBA46, 0x615B, 0xE1D0, 0x615D, 0xBC7C, 0x615E, 0xE1C5, 0x615F, 0xBA45, 0x6161, 0xE1D4, 0x6162, 0xBA43, + 0x6163, 0xBA44, 0x6165, 0xE1D1, 0x6166, 0xE5AA, 0x6167, 0xBC7A, 0x6168, 0xB46E, 0x616A, 0xE1D3, 0x616B, 0xBCA3, 0x616C, 0xE1CB, + 0x616E, 0xBC7B, 0x6170, 0xBCA2, 0x6171, 0xE1C6, 0x6172, 0xE1CA, 0x6173, 0xE1C7, 0x6174, 0xE1CD, 0x6175, 0xBA48, 0x6176, 0xBC79, + 0x6177, 0xBA42, 0x6179, 0xE57A, 0x617A, 0xE1CF, 0x617C, 0xBCA1, 0x617E, 0xBCA4, 0x6180, 0xE1CC, 0x6182, 0xBC7E, 0x6183, 0xE579, + 0x6189, 0xE57E, 0x618A, 0xBECE, 0x618B, 0xE578, 0x618C, 0xE9A3, 0x618D, 0xE5A9, 0x618E, 0xBCA8, 0x6190, 0xBCA6, 0x6191, 0xBECC, + 0x6192, 0xE5A6, 0x6193, 0xE5A2, 0x6194, 0xBCAC, 0x6196, 0xE978, 0x619A, 0xBCAA, 0x619B, 0xE5A1, 0x619D, 0xE976, 0x619F, 0xE5A5, + 0x61A1, 0xE5A8, 0x61A2, 0xE57D, 0x61A4, 0xBCAB, 0x61A7, 0xBCA5, 0x61A8, 0xE977, 0x61A9, 0xBECD, 0x61AA, 0xE5A7, 0x61AB, 0xBCA7, + 0x61AC, 0xBCA9, 0x61AD, 0xE5A4, 0x61AE, 0xBCAD, 0x61AF, 0xE5A3, 0x61B0, 0xE57C, 0x61B1, 0xE57B, 0x61B2, 0xBECB, 0x61B3, 0xE5AB, + 0x61B4, 0xE97A, 0x61B5, 0xECE0, 0x61B6, 0xBED0, 0x61B8, 0xE9A2, 0x61BA, 0xE97E, 0x61BC, 0xECE1, 0x61BE, 0xBED1, 0x61BF, 0xE9A1, + 0x61C1, 0xE97C, 0x61C2, 0xC0B4, 0x61C3, 0xECDF, 0x61C5, 0xE979, 0x61C6, 0xE97B, 0x61C7, 0xC0B5, 0x61C8, 0xBED3, 0x61C9, 0xC0B3, + 0x61CA, 0xBED2, 0x61CB, 0xC0B7, 0x61CC, 0xE97D, 0x61CD, 0xBECF, 0x61D6, 0xEFCF, 0x61D8, 0xEFC7, 0x61DE, 0xECE7, 0x61DF, 0xEFC8, + 0x61E0, 0xECE3, 0x61E3, 0xC256, 0x61E4, 0xECE5, 0x61E5, 0xECE4, 0x61E6, 0xC0B6, 0x61E7, 0xECE2, 0x61E8, 0xECE6, 0x61E9, 0xEFD0, + 0x61EA, 0xEFCC, 0x61EB, 0xEFCE, 0x61ED, 0xEFC9, 0x61EE, 0xEFCA, 0x61F0, 0xEFCD, 0x61F1, 0xEFCB, 0x61F2, 0xC367, 0x61F5, 0xC36A, + 0x61F6, 0xC369, 0x61F7, 0xC368, 0x61F8, 0xC461, 0x61F9, 0xF44A, 0x61FA, 0xC462, 0x61FB, 0xF241, 0x61FC, 0xC4DF, 0x61FD, 0xF5CC, + 0x61FE, 0xC4E0, 0x61FF, 0xC574, 0x6200, 0xC5CA, 0x6201, 0xF7D9, 0x6203, 0xF7DA, 0x6204, 0xF7DB, 0x6207, 0xF9BA, 0x6208, 0xA4E0, + 0x6209, 0xC97C, 0x620A, 0xA5B3, 0x620C, 0xA6A6, 0x620D, 0xA6A7, 0x620E, 0xA6A5, 0x6210, 0xA6A8, 0x6211, 0xA7DA, 0x6212, 0xA7D9, + 0x6214, 0xCCB1, 0x6215, 0xA9CF, 0x6216, 0xA9CE, 0x6219, 0xD1AF, 0x621A, 0xB1AD, 0x621B, 0xB1AE, 0x621F, 0xB475, 0x6220, 0xDD72, + 0x6221, 0xB760, 0x6222, 0xB761, 0x6223, 0xDD74, 0x6224, 0xDD76, 0x6225, 0xDD75, 0x6227, 0xE1D7, 0x6229, 0xE1D6, 0x622A, 0xBA49, + 0x622B, 0xE1D8, 0x622D, 0xE5AC, 0x622E, 0xBCAE, 0x6230, 0xBED4, 0x6232, 0xC0B8, 0x6233, 0xC257, 0x6234, 0xC0B9, 0x6236, 0xA4E1, + 0x623A, 0xCAE6, 0x623D, 0xCCB2, 0x623E, 0xA9D1, 0x623F, 0xA9D0, 0x6240, 0xA9D2, 0x6241, 0xABF3, 0x6242, 0xCED2, 0x6243, 0xCED3, + 0x6246, 0xD1B0, 0x6247, 0xAEB0, 0x6248, 0xB1AF, 0x6249, 0xB476, 0x624A, 0xD951, 0x624B, 0xA4E2, 0x624D, 0xA47E, 0x624E, 0xA4E3, + 0x6250, 0xC97D, 0x6251, 0xA5B7, 0x6252, 0xA5B6, 0x6253, 0xA5B4, 0x6254, 0xA5B5, 0x6258, 0xA6AB, 0x6259, 0xC9E9, 0x625A, 0xC9EB, + 0x625B, 0xA6AA, 0x625C, 0xC9E3, 0x625E, 0xC9E4, 0x6260, 0xC9EA, 0x6261, 0xC9E6, 0x6262, 0xC9E8, 0x6263, 0xA6A9, 0x6264, 0xC9E5, + 0x6265, 0xC9EC, 0x6266, 0xC9E7, 0x626D, 0xA7E1, 0x626E, 0xA7EA, 0x626F, 0xA7E8, 0x6270, 0xCAF0, 0x6271, 0xCAED, 0x6272, 0xCAF5, + 0x6273, 0xA7E6, 0x6274, 0xCAF6, 0x6276, 0xA7DF, 0x6277, 0xCAF3, 0x6279, 0xA7E5, 0x627A, 0xCAEF, 0x627B, 0xCAEE, 0x627C, 0xA7E3, + 0x627D, 0xCAF4, 0x627E, 0xA7E4, 0x627F, 0xA9D3, 0x6280, 0xA7DE, 0x6281, 0xCAF1, 0x6283, 0xCAE7, 0x6284, 0xA7DB, 0x6286, 0xA7EE, + 0x6287, 0xCAEC, 0x6288, 0xCAF2, 0x6289, 0xA7E0, 0x628A, 0xA7E2, 0x628C, 0xCAE8, 0x628E, 0xCAE9, 0x628F, 0xCAEA, 0x6291, 0xA7ED, + 0x6292, 0xA7E7, 0x6293, 0xA7EC, 0x6294, 0xCAEB, 0x6295, 0xA7EB, 0x6296, 0xA7DD, 0x6297, 0xA7DC, 0x6298, 0xA7E9, 0x62A8, 0xA9E1, + 0x62A9, 0xCCBE, 0x62AA, 0xCCB7, 0x62AB, 0xA9DC, 0x62AC, 0xA9EF, 0x62AD, 0xCCB3, 0x62AE, 0xCCBA, 0x62AF, 0xCCBC, 0x62B0, 0xCCBF, + 0x62B1, 0xA9EA, 0x62B3, 0xCCBB, 0x62B4, 0xCCB4, 0x62B5, 0xA9E8, 0x62B6, 0xCCB8, 0x62B8, 0xCCC0, 0x62B9, 0xA9D9, 0x62BB, 0xCCBD, + 0x62BC, 0xA9E3, 0x62BD, 0xA9E2, 0x62BE, 0xCCB6, 0x62BF, 0xA9D7, 0x62C2, 0xA9D8, 0x62C4, 0xA9D6, 0x62C6, 0xA9EE, 0x62C7, 0xA9E6, + 0x62C8, 0xA9E0, 0x62C9, 0xA9D4, 0x62CA, 0xCCB9, 0x62CB, 0xA9DF, 0x62CC, 0xA9D5, 0x62CD, 0xA9E7, 0x62CE, 0xA9F0, 0x62CF, 0xCED4, + 0x62D0, 0xA9E4, 0x62D1, 0xCCB5, 0x62D2, 0xA9DA, 0x62D3, 0xA9DD, 0x62D4, 0xA9DE, 0x62D6, 0xA9EC, 0x62D7, 0xA9ED, 0x62D8, 0xA9EB, + 0x62D9, 0xA9E5, 0x62DA, 0xA9E9, 0x62DB, 0xA9DB, 0x62DC, 0xABF4, 0x62EB, 0xCEDA, 0x62EC, 0xAC41, 0x62ED, 0xABF8, 0x62EE, 0xABFA, + 0x62EF, 0xAC40, 0x62F0, 0xCEE6, 0x62F1, 0xABFD, 0x62F2, 0xD1B1, 0x62F3, 0xAEB1, 0x62F4, 0xAC43, 0x62F5, 0xCED7, 0x62F6, 0xCEDF, + 0x62F7, 0xABFE, 0x62F8, 0xCEDE, 0x62F9, 0xCEDB, 0x62FA, 0xCEE3, 0x62FB, 0xCEE5, 0x62FC, 0xABF7, 0x62FD, 0xABFB, 0x62FE, 0xAC42, + 0x62FF, 0xAEB3, 0x6300, 0xCEE0, 0x6301, 0xABF9, 0x6302, 0xAC45, 0x6303, 0xCED9, 0x6307, 0xABFC, 0x6308, 0xAEB2, 0x6309, 0xABF6, + 0x630B, 0xCED6, 0x630C, 0xCEDD, 0x630D, 0xCED5, 0x630E, 0xCED8, 0x630F, 0xCEDC, 0x6310, 0xD1B2, 0x6311, 0xAC44, 0x6313, 0xCEE1, + 0x6314, 0xCEE2, 0x6315, 0xCEE4, 0x6316, 0xABF5, 0x6328, 0xAEC1, 0x6329, 0xD1BE, 0x632A, 0xAEBF, 0x632B, 0xAEC0, 0x632C, 0xD1B4, + 0x632D, 0xD1C4, 0x632F, 0xAEB6, 0x6332, 0xD566, 0x6333, 0xD1C6, 0x6334, 0xD1C0, 0x6336, 0xD1B7, 0x6338, 0xD1C9, 0x6339, 0xD1BA, + 0x633A, 0xAEBC, 0x633B, 0xD57D, 0x633C, 0xD1BD, 0x633D, 0xAEBE, 0x633E, 0xAEB5, 0x6340, 0xD1CB, 0x6341, 0xD1BF, 0x6342, 0xAEB8, + 0x6343, 0xD1B8, 0x6344, 0xD1B5, 0x6345, 0xD1B6, 0x6346, 0xAEB9, 0x6347, 0xD1C5, 0x6348, 0xD1CC, 0x6349, 0xAEBB, 0x634A, 0xD1BC, + 0x634B, 0xD1BB, 0x634C, 0xAEC3, 0x634D, 0xAEC2, 0x634E, 0xAEB4, 0x634F, 0xAEBA, 0x6350, 0xAEBD, 0x6351, 0xD1C8, 0x6354, 0xD1C2, + 0x6355, 0xAEB7, 0x6356, 0xD1B3, 0x6357, 0xD1CA, 0x6358, 0xD1C1, 0x6359, 0xD1C3, 0x635A, 0xD1C7, 0x6365, 0xD567, 0x6367, 0xB1B7, + 0x6368, 0xB1CB, 0x6369, 0xB1CA, 0x636B, 0xB1BF, 0x636D, 0xD579, 0x636E, 0xD575, 0x636F, 0xD572, 0x6370, 0xD5A6, 0x6371, 0xB1BA, + 0x6372, 0xB1B2, 0x6375, 0xD577, 0x6376, 0xB4A8, 0x6377, 0xB1B6, 0x6378, 0xD5A1, 0x637A, 0xB1CC, 0x637B, 0xB1C9, 0x637C, 0xD57B, + 0x637D, 0xD56A, 0x6380, 0xB1C8, 0x6381, 0xD5A3, 0x6382, 0xD569, 0x6383, 0xB1BD, 0x6384, 0xB1C1, 0x6385, 0xD5A2, 0x6387, 0xD573, + 0x6388, 0xB1C2, 0x6389, 0xB1BC, 0x638A, 0xD568, 0x638C, 0xB478, 0x638D, 0xD5A5, 0x638E, 0xD571, 0x638F, 0xB1C7, 0x6390, 0xD574, + 0x6391, 0xD5A4, 0x6392, 0xB1C6, 0x6394, 0xD952, 0x6396, 0xB1B3, 0x6397, 0xD56F, 0x6398, 0xB1B8, 0x6399, 0xB1C3, 0x639B, 0xB1BE, + 0x639C, 0xD578, 0x639D, 0xD56E, 0x639E, 0xD56C, 0x639F, 0xD57E, 0x63A0, 0xB1B0, 0x63A1, 0xB1C4, 0x63A2, 0xB1B4, 0x63A3, 0xB477, + 0x63A4, 0xD57C, 0x63A5, 0xB1B5, 0x63A7, 0xB1B1, 0x63A8, 0xB1C0, 0x63A9, 0xB1BB, 0x63AA, 0xB1B9, 0x63AB, 0xD570, 0x63AC, 0xB1C5, + 0x63AD, 0xD56D, 0x63AE, 0xD57A, 0x63AF, 0xD576, 0x63B0, 0xD954, 0x63B1, 0xD953, 0x63BD, 0xD56B, 0x63BE, 0xD964, 0x63C0, 0xB47A, + 0x63C2, 0xD96A, 0x63C3, 0xD959, 0x63C4, 0xD967, 0x63C5, 0xDD77, 0x63C6, 0xB47D, 0x63C7, 0xD96B, 0x63C8, 0xD96E, 0x63C9, 0xB47C, + 0x63CA, 0xD95C, 0x63CB, 0xD96D, 0x63CC, 0xD96C, 0x63CD, 0xB47E, 0x63CE, 0xD955, 0x63CF, 0xB479, 0x63D0, 0xB4A3, 0x63D2, 0xB4A1, + 0x63D3, 0xD969, 0x63D5, 0xD95F, 0x63D6, 0xB4A5, 0x63D7, 0xD970, 0x63D8, 0xD968, 0x63D9, 0xD971, 0x63DA, 0xB4AD, 0x63DB, 0xB4AB, + 0x63DC, 0xD966, 0x63DD, 0xD965, 0x63DF, 0xD963, 0x63E0, 0xD95D, 0x63E1, 0xB4A4, 0x63E3, 0xB4A2, 0x63E4, 0xD1B9, 0x63E5, 0xD956, + 0x63E7, 0xDDB7, 0x63E8, 0xD957, 0x63E9, 0xB47B, 0x63EA, 0xB4AA, 0x63EB, 0xDD79, 0x63ED, 0xB4A6, 0x63EE, 0xB4A7, 0x63EF, 0xD958, + 0x63F0, 0xD96F, 0x63F1, 0xDD78, 0x63F2, 0xD960, 0x63F3, 0xD95B, 0x63F4, 0xB4A9, 0x63F5, 0xD961, 0x63F6, 0xD95E, 0x63F9, 0xB4AE, + 0x6406, 0xB770, 0x6409, 0xDD7C, 0x640A, 0xDDB1, 0x640B, 0xDDB6, 0x640C, 0xDDAA, 0x640D, 0xB76C, 0x640E, 0xDDBB, 0x640F, 0xB769, + 0x6410, 0xDD7A, 0x6412, 0xDD7B, 0x6413, 0xB762, 0x6414, 0xB76B, 0x6415, 0xDDA4, 0x6416, 0xB76E, 0x6417, 0xB76F, 0x6418, 0xDDA5, + 0x641A, 0xDDB2, 0x641B, 0xDDB8, 0x641C, 0xB76A, 0x641E, 0xB764, 0x641F, 0xDDA3, 0x6420, 0xDD7D, 0x6421, 0xDDBA, 0x6422, 0xDDA8, + 0x6423, 0xDDA9, 0x6424, 0xDD7E, 0x6425, 0xDDB4, 0x6426, 0xDDAB, 0x6427, 0xDDB5, 0x6428, 0xDDAD, 0x642A, 0xB765, 0x642B, 0xE1D9, + 0x642C, 0xB768, 0x642D, 0xB766, 0x642E, 0xDDB9, 0x642F, 0xDDB0, 0x6430, 0xDDAC, 0x6433, 0xDDA1, 0x6434, 0xBA53, 0x6435, 0xDDAF, + 0x6436, 0xB76D, 0x6437, 0xDDA7, 0x6439, 0xDDA6, 0x643D, 0xB767, 0x643E, 0xB763, 0x643F, 0xE1EE, 0x6440, 0xDDB3, 0x6441, 0xDDAE, + 0x6443, 0xDDA2, 0x644B, 0xE1E9, 0x644D, 0xE1DA, 0x644E, 0xE1E5, 0x6450, 0xE1EC, 0x6451, 0xBA51, 0x6452, 0xB4AC, 0x6453, 0xE1EA, + 0x6454, 0xBA4C, 0x6458, 0xBA4B, 0x6459, 0xE1F1, 0x645B, 0xE1DB, 0x645C, 0xE1E8, 0x645D, 0xE1DC, 0x645E, 0xE1E7, 0x645F, 0xBA4F, + 0x6460, 0xE1EB, 0x6461, 0xD962, 0x6465, 0xE1F2, 0x6466, 0xE1E3, 0x6467, 0xBA52, 0x6468, 0xE5BA, 0x6469, 0xBCAF, 0x646B, 0xE1F0, + 0x646C, 0xE1EF, 0x646D, 0xBA54, 0x646E, 0xE5AD, 0x646F, 0xBCB0, 0x6470, 0xE5AE, 0x6472, 0xE1DF, 0x6473, 0xE1E0, 0x6474, 0xE1DD, + 0x6475, 0xE1E2, 0x6476, 0xE1DE, 0x6477, 0xE1F3, 0x6478, 0xBA4E, 0x6479, 0xBCB1, 0x647A, 0xBA50, 0x647B, 0xBA55, 0x647D, 0xE1E1, + 0x647F, 0xE1ED, 0x6482, 0xE1E6, 0x6485, 0xE5B1, 0x6487, 0xBA4A, 0x6488, 0xBCB4, 0x6489, 0xE9AA, 0x648A, 0xE5B6, 0x648B, 0xE5B5, + 0x648C, 0xE5B7, 0x648F, 0xE5B4, 0x6490, 0xBCB5, 0x6492, 0xBCBB, 0x6493, 0xBCB8, 0x6495, 0xBCB9, 0x6496, 0xE5AF, 0x6497, 0xE5B2, + 0x6498, 0xE5BC, 0x6499, 0xBCC1, 0x649A, 0xBCBF, 0x649C, 0xE5B3, 0x649D, 0xD95A, 0x649E, 0xBCB2, 0x649F, 0xE5B9, 0x64A0, 0xE5B0, + 0x64A2, 0xBCC2, 0x64A3, 0xE5B8, 0x64A4, 0xBA4D, 0x64A5, 0xBCB7, 0x64A6, 0xE1E4, 0x64A9, 0xBCBA, 0x64AB, 0xBCBE, 0x64AC, 0xBCC0, + 0x64AD, 0xBCBD, 0x64AE, 0xBCBC, 0x64B0, 0xBCB6, 0x64B1, 0xE5BB, 0x64B2, 0xBCB3, 0x64B3, 0xBCC3, 0x64BB, 0xBED8, 0x64BC, 0xBED9, + 0x64BD, 0xE9A9, 0x64BE, 0xBEE2, 0x64BF, 0xBEDF, 0x64C1, 0xBED6, 0x64C2, 0xBEDD, 0x64C3, 0xE9AB, 0x64C4, 0xBEDB, 0x64C5, 0xBED5, + 0x64C7, 0xBEDC, 0x64C9, 0xE9A8, 0x64CA, 0xC0BB, 0x64CB, 0xBED7, 0x64CD, 0xBEDE, 0x64CE, 0xC0BA, 0x64CF, 0xE9A7, 0x64D0, 0xE9A6, + 0x64D2, 0xBEE0, 0x64D4, 0xBEE1, 0x64D6, 0xE9A5, 0x64D7, 0xE9A4, 0x64D8, 0xC0BC, 0x64D9, 0xE9AE, 0x64DA, 0xBEDA, 0x64DB, 0xE9AC, + 0x64E0, 0xC0BD, 0x64E2, 0xC0C2, 0x64E3, 0xECEA, 0x64E4, 0xECEC, 0x64E6, 0xC0BF, 0x64E8, 0xECED, 0x64E9, 0xECE9, 0x64EB, 0xECEB, + 0x64EC, 0xC0C0, 0x64ED, 0xC0C3, 0x64EF, 0xECE8, 0x64F0, 0xC0BE, 0x64F1, 0xC0C1, 0x64F2, 0xC259, 0x64F3, 0xE9AD, 0x64F4, 0xC258, + 0x64F7, 0xC25E, 0x64F8, 0xEFD4, 0x64FA, 0xC25C, 0x64FB, 0xC25D, 0x64FC, 0xEFD7, 0x64FD, 0xEFD3, 0x64FE, 0xC25A, 0x64FF, 0xEFD1, + 0x6500, 0xC36B, 0x6501, 0xEFD5, 0x6503, 0xEFD6, 0x6504, 0xEFD2, 0x6506, 0xC25B, 0x6507, 0xF242, 0x6509, 0xF245, 0x650C, 0xF246, + 0x650D, 0xF244, 0x650E, 0xF247, 0x650F, 0xC36C, 0x6510, 0xF243, 0x6513, 0xF44E, 0x6514, 0xC464, 0x6515, 0xF44D, 0x6516, 0xF44C, + 0x6517, 0xF44B, 0x6518, 0xC463, 0x6519, 0xC465, 0x651B, 0xF5CD, 0x651C, 0xC4E2, 0x651D, 0xC4E1, 0x6520, 0xF6E1, 0x6521, 0xF6E0, + 0x6522, 0xF6E3, 0x6523, 0xC5CB, 0x6524, 0xC575, 0x6525, 0xF7DD, 0x6526, 0xF6E2, 0x6529, 0xF7DC, 0x652A, 0xC5CD, 0x652B, 0xC5CC, + 0x652C, 0xC5F3, 0x652D, 0xF8A9, 0x652E, 0xF8EF, 0x652F, 0xA4E4, 0x6532, 0xD972, 0x6533, 0xE9AF, 0x6536, 0xA6AC, 0x6537, 0xCAF7, + 0x6538, 0xA7F1, 0x6539, 0xA7EF, 0x653B, 0xA7F0, 0x653D, 0xCCC1, 0x653E, 0xA9F1, 0x653F, 0xAC46, 0x6541, 0xCEE7, 0x6543, 0xCEE8, + 0x6545, 0xAC47, 0x6546, 0xD1CE, 0x6548, 0xAEC4, 0x6549, 0xAEC5, 0x654A, 0xD1CD, 0x654F, 0xB1D3, 0x6551, 0xB1CF, 0x6553, 0xD5A7, + 0x6554, 0xB1D6, 0x6555, 0xB1D5, 0x6556, 0xB1CE, 0x6557, 0xB1D1, 0x6558, 0xB1D4, 0x6559, 0xB1D0, 0x655C, 0xD976, 0x655D, 0xB1CD, + 0x655E, 0xB4AF, 0x6562, 0xB4B1, 0x6563, 0xB4B2, 0x6564, 0xD975, 0x6565, 0xD978, 0x6566, 0xB4B0, 0x6567, 0xD973, 0x6568, 0xD977, + 0x656A, 0xD974, 0x656C, 0xB771, 0x656F, 0xDDBC, 0x6572, 0xBA56, 0x6573, 0xE1F4, 0x6574, 0xBEE3, 0x6575, 0xBCC4, 0x6576, 0xE5BD, + 0x6577, 0xBCC5, 0x6578, 0xBCC6, 0x6579, 0xE5BF, 0x657A, 0xE5BE, 0x657B, 0xE5C0, 0x657C, 0xE9B1, 0x657F, 0xE9B0, 0x6580, 0xECEF, + 0x6581, 0xECEE, 0x6582, 0xC0C4, 0x6583, 0xC0C5, 0x6584, 0xF248, 0x6587, 0xA4E5, 0x658C, 0xD979, 0x6590, 0xB4B4, 0x6591, 0xB4B3, + 0x6592, 0xDDBD, 0x6594, 0xEFD8, 0x6595, 0xC4E3, 0x6596, 0xF7DE, 0x6597, 0xA4E6, 0x6599, 0xAEC6, 0x659B, 0xB1D8, 0x659C, 0xB1D7, + 0x659D, 0xD97A, 0x659E, 0xD97B, 0x659F, 0xB772, 0x65A0, 0xE1F5, 0x65A1, 0xBA57, 0x65A2, 0xE9B2, 0x65A4, 0xA4E7, 0x65A5, 0xA5B8, + 0x65A7, 0xA9F2, 0x65A8, 0xCCC2, 0x65AA, 0xCEE9, 0x65AB, 0xAC48, 0x65AC, 0xB1D9, 0x65AE, 0xD97C, 0x65AF, 0xB4B5, 0x65B0, 0xB773, + 0x65B2, 0xE5C1, 0x65B3, 0xE5C2, 0x65B6, 0xECF0, 0x65B7, 0xC25F, 0x65B8, 0xF8F0, 0x65B9, 0xA4E8, 0x65BB, 0xCCC3, 0x65BC, 0xA9F3, + 0x65BD, 0xAC49, 0x65BF, 0xCEEA, 0x65C1, 0xAEC7, 0x65C2, 0xD1D2, 0x65C3, 0xD1D0, 0x65C4, 0xD1D1, 0x65C5, 0xAEC8, 0x65C6, 0xD1CF, + 0x65CB, 0xB1DB, 0x65CC, 0xB1DC, 0x65CD, 0xD5A8, 0x65CE, 0xB1DD, 0x65CF, 0xB1DA, 0x65D0, 0xD97D, 0x65D2, 0xD97E, 0x65D3, 0xDDBE, + 0x65D6, 0xBA59, 0x65D7, 0xBA58, 0x65DA, 0xECF1, 0x65DB, 0xEFD9, 0x65DD, 0xF24A, 0x65DE, 0xF249, 0x65DF, 0xF44F, 0x65E1, 0xC95E, + 0x65E2, 0xAC4A, 0x65E5, 0xA4E9, 0x65E6, 0xA5B9, 0x65E8, 0xA6AE, 0x65E9, 0xA6AD, 0x65EC, 0xA6AF, 0x65ED, 0xA6B0, 0x65EE, 0xC9EE, + 0x65EF, 0xC9ED, 0x65F0, 0xCAF8, 0x65F1, 0xA7F2, 0x65F2, 0xCAFB, 0x65F3, 0xCAFA, 0x65F4, 0xCAF9, 0x65F5, 0xCAFC, 0x65FA, 0xA9F4, + 0x65FB, 0xCCC9, 0x65FC, 0xCCC5, 0x65FD, 0xCCCE, 0x6600, 0xA9FB, 0x6602, 0xA9F9, 0x6603, 0xCCCA, 0x6604, 0xCCC6, 0x6605, 0xCCCD, + 0x6606, 0xA9F8, 0x6607, 0xAA40, 0x6608, 0xCCC8, 0x6609, 0xCCC4, 0x660A, 0xA9FE, 0x660B, 0xCCCB, 0x660C, 0xA9F7, 0x660D, 0xCCCC, + 0x660E, 0xA9FA, 0x660F, 0xA9FC, 0x6610, 0xCCD0, 0x6611, 0xCCCF, 0x6612, 0xCCC7, 0x6613, 0xA9F6, 0x6614, 0xA9F5, 0x6615, 0xA9FD, + 0x661C, 0xCEEF, 0x661D, 0xCEF5, 0x661F, 0xAC50, 0x6620, 0xAC4D, 0x6621, 0xCEEC, 0x6622, 0xCEF1, 0x6624, 0xAC53, 0x6625, 0xAC4B, + 0x6626, 0xCEF0, 0x6627, 0xAC4E, 0x6628, 0xAC51, 0x662B, 0xCEF3, 0x662D, 0xAC4C, 0x662E, 0xCEF8, 0x662F, 0xAC4F, 0x6631, 0xAC52, + 0x6632, 0xCEED, 0x6633, 0xCEF2, 0x6634, 0xCEF6, 0x6635, 0xCEEE, 0x6636, 0xCEEB, 0x6639, 0xCEF7, 0x663A, 0xCEF4, 0x6641, 0xAED0, + 0x6642, 0xAEC9, 0x6643, 0xAECC, 0x6645, 0xAECF, 0x6647, 0xD1D5, 0x6649, 0xAECA, 0x664A, 0xD1D3, 0x664C, 0xAECE, 0x664F, 0xAECB, + 0x6651, 0xD1D6, 0x6652, 0xAECD, 0x6659, 0xD5AC, 0x665A, 0xB1DF, 0x665B, 0xD5AB, 0x665C, 0xD5AD, 0x665D, 0xB1DE, 0x665E, 0xB1E3, + 0x665F, 0xD1D4, 0x6661, 0xD5AA, 0x6662, 0xD5AE, 0x6664, 0xB1E0, 0x6665, 0xD5A9, 0x6666, 0xB1E2, 0x6668, 0xB1E1, 0x666A, 0xD9A7, + 0x666C, 0xD9A2, 0x666E, 0xB4B6, 0x666F, 0xB4BA, 0x6670, 0xB4B7, 0x6671, 0xD9A5, 0x6672, 0xD9A8, 0x6674, 0xB4B8, 0x6676, 0xB4B9, + 0x6677, 0xB4BE, 0x6678, 0xDDC7, 0x6679, 0xD9A6, 0x667A, 0xB4BC, 0x667B, 0xD9A3, 0x667C, 0xD9A1, 0x667E, 0xB4BD, 0x6680, 0xD9A4, + 0x6684, 0xB779, 0x6686, 0xDDBF, 0x6687, 0xB776, 0x6688, 0xB777, 0x6689, 0xB775, 0x668A, 0xDDC4, 0x668B, 0xDDC3, 0x668C, 0xDDC0, + 0x668D, 0xB77B, 0x6690, 0xDDC2, 0x6691, 0xB4BB, 0x6694, 0xDDC6, 0x6695, 0xDDC1, 0x6696, 0xB778, 0x6697, 0xB774, 0x6698, 0xB77A, + 0x6699, 0xDDC5, 0x669D, 0xBA5C, 0x669F, 0xE1F8, 0x66A0, 0xE1F7, 0x66A1, 0xE1F6, 0x66A2, 0xBA5A, 0x66A8, 0xBA5B, 0x66A9, 0xE5C5, + 0x66AA, 0xE5C8, 0x66AB, 0xBCC8, 0x66AE, 0xBCC7, 0x66AF, 0xE5C9, 0x66B0, 0xE5C4, 0x66B1, 0xBCCA, 0x66B2, 0xE5C6, 0x66B4, 0xBCC9, + 0x66B5, 0xE5C3, 0x66B7, 0xE5C7, 0x66B8, 0xBEE9, 0x66B9, 0xBEE6, 0x66BA, 0xE9BB, 0x66BB, 0xE9BA, 0x66BD, 0xE9B9, 0x66BE, 0xE9B4, + 0x66C0, 0xE9B5, 0x66C4, 0xBEE7, 0x66C6, 0xBEE4, 0x66C7, 0xBEE8, 0x66C8, 0xE9B3, 0x66C9, 0xBEE5, 0x66CA, 0xE9B6, 0x66CB, 0xE9B7, + 0x66CC, 0xE9BC, 0x66CF, 0xE9B8, 0x66D2, 0xECF2, 0x66D6, 0xC0C7, 0x66D8, 0xEFDC, 0x66D9, 0xC0C6, 0x66DA, 0xEFDA, 0x66DB, 0xEFDB, + 0x66DC, 0xC260, 0x66DD, 0xC36E, 0x66DE, 0xF24B, 0x66E0, 0xC36D, 0x66E3, 0xF451, 0x66E4, 0xF452, 0x66E6, 0xC466, 0x66E8, 0xF450, + 0x66E9, 0xC4E4, 0x66EB, 0xF7DF, 0x66EC, 0xC5CE, 0x66ED, 0xF8AA, 0x66EE, 0xF8AB, 0x66F0, 0xA4EA, 0x66F2, 0xA6B1, 0x66F3, 0xA6B2, + 0x66F4, 0xA7F3, 0x66F6, 0xCCD1, 0x66F7, 0xAC54, 0x66F8, 0xAED1, 0x66F9, 0xB1E4, 0x66FC, 0xB0D2, 0x66FE, 0xB4BF, 0x66FF, 0xB4C0, + 0x6700, 0xB3CC, 0x6701, 0xD9A9, 0x6703, 0xB77C, 0x6704, 0xE1FA, 0x6705, 0xE1F9, 0x6708, 0xA4EB, 0x6709, 0xA6B3, 0x670A, 0xCCD2, + 0x670B, 0xAA42, 0x670D, 0xAA41, 0x670F, 0xCEF9, 0x6710, 0xCEFA, 0x6712, 0xD1D7, 0x6713, 0xD1D8, 0x6714, 0xAED2, 0x6715, 0xAED3, + 0x6717, 0xAED4, 0x6718, 0xD5AF, 0x671B, 0xB1E6, 0x671D, 0xB4C2, 0x671F, 0xB4C1, 0x6720, 0xDDC8, 0x6721, 0xDF7A, 0x6722, 0xE1FB, + 0x6723, 0xE9BD, 0x6726, 0xC261, 0x6727, 0xC467, 0x6728, 0xA4EC, 0x672A, 0xA5BC, 0x672B, 0xA5BD, 0x672C, 0xA5BB, 0x672D, 0xA5BE, + 0x672E, 0xA5BA, 0x6731, 0xA6B6, 0x6733, 0xC9F6, 0x6734, 0xA6B5, 0x6735, 0xA6B7, 0x6738, 0xC9F1, 0x6739, 0xC9F0, 0x673A, 0xC9F3, + 0x673B, 0xC9F2, 0x673C, 0xC9F5, 0x673D, 0xA6B4, 0x673E, 0xC9EF, 0x673F, 0xC9F4, 0x6745, 0xCAFD, 0x6746, 0xA7FD, 0x6747, 0xCAFE, + 0x6748, 0xCB43, 0x6749, 0xA7FC, 0x674B, 0xCB47, 0x674C, 0xCB42, 0x674D, 0xCB45, 0x674E, 0xA7F5, 0x674F, 0xA7F6, 0x6750, 0xA7F7, + 0x6751, 0xA7F8, 0x6753, 0xA840, 0x6755, 0xCB41, 0x6756, 0xA7FA, 0x6757, 0xA841, 0x6759, 0xCB40, 0x675A, 0xCB46, 0x675C, 0xA7F9, + 0x675D, 0xCB44, 0x675E, 0xA7FB, 0x675F, 0xA7F4, 0x6760, 0xA7FE, 0x676A, 0xAA57, 0x676C, 0xCCD4, 0x676D, 0xAA43, 0x676F, 0xAA4D, + 0x6770, 0xAA4E, 0x6771, 0xAA46, 0x6772, 0xAA58, 0x6773, 0xAA48, 0x6774, 0xCCDC, 0x6775, 0xAA53, 0x6776, 0xCCD7, 0x6777, 0xAA49, + 0x6778, 0xCCE6, 0x6779, 0xCCE7, 0x677A, 0xCCDF, 0x677B, 0xCCD8, 0x677C, 0xAA56, 0x677D, 0xCCE4, 0x677E, 0xAA51, 0x677F, 0xAA4F, + 0x6781, 0xCCE5, 0x6783, 0xCCE3, 0x6784, 0xCCDB, 0x6785, 0xCCD3, 0x6786, 0xCCDA, 0x6787, 0xAA4A, 0x6789, 0xAA50, 0x678B, 0xAA44, + 0x678C, 0xCCDE, 0x678D, 0xCCDD, 0x678E, 0xCCD5, 0x6790, 0xAA52, 0x6791, 0xCCE1, 0x6792, 0xCCD6, 0x6793, 0xAA55, 0x6794, 0xCCE8, + 0x6795, 0xAA45, 0x6797, 0xAA4C, 0x6798, 0xCCD9, 0x6799, 0xCCE2, 0x679A, 0xAA54, 0x679C, 0xAA47, 0x679D, 0xAA4B, 0x679F, 0xCCE0, + 0x67AE, 0xCF5B, 0x67AF, 0xAC5C, 0x67B0, 0xAC69, 0x67B2, 0xCF56, 0x67B3, 0xCF4C, 0x67B4, 0xAC62, 0x67B5, 0xCF4A, 0x67B6, 0xAC5B, + 0x67B7, 0xCF45, 0x67B8, 0xAC65, 0x67B9, 0xCF52, 0x67BA, 0xCEFE, 0x67BB, 0xCF41, 0x67C0, 0xCF44, 0x67C1, 0xCEFB, 0x67C2, 0xCF51, + 0x67C3, 0xCF61, 0x67C4, 0xAC60, 0x67C5, 0xCF46, 0x67C6, 0xCF58, 0x67C8, 0xCEFD, 0x67C9, 0xCF5F, 0x67CA, 0xCF60, 0x67CB, 0xCF63, + 0x67CC, 0xCF5A, 0x67CD, 0xCF4B, 0x67CE, 0xCF53, 0x67CF, 0xAC66, 0x67D0, 0xAC59, 0x67D1, 0xAC61, 0x67D2, 0xAC6D, 0x67D3, 0xAC56, + 0x67D4, 0xAC58, 0x67D8, 0xCF43, 0x67D9, 0xAC6A, 0x67DA, 0xAC63, 0x67DB, 0xCF5D, 0x67DC, 0xCF40, 0x67DD, 0xAC6C, 0x67DE, 0xAC67, + 0x67DF, 0xCF49, 0x67E2, 0xAC6B, 0x67E3, 0xCF50, 0x67E4, 0xCF48, 0x67E5, 0xAC64, 0x67E6, 0xCF5C, 0x67E7, 0xCF54, 0x67E9, 0xAC5E, + 0x67EA, 0xCF62, 0x67EB, 0xCF47, 0x67EC, 0xAC5A, 0x67ED, 0xCF59, 0x67EE, 0xCF4F, 0x67EF, 0xAC5F, 0x67F0, 0xCF55, 0x67F1, 0xAC57, + 0x67F2, 0xCEFC, 0x67F3, 0xAC68, 0x67F4, 0xAEE3, 0x67F5, 0xAC5D, 0x67F6, 0xCF4E, 0x67F7, 0xCF4D, 0x67F8, 0xCF42, 0x67FA, 0xCF5E, + 0x67FC, 0xCF57, 0x67FF, 0xAC55, 0x6812, 0xD1EC, 0x6813, 0xAEEA, 0x6814, 0xD1ED, 0x6816, 0xD1E1, 0x6817, 0xAEDF, 0x6818, 0xAEEB, + 0x681A, 0xD1DA, 0x681C, 0xD1E3, 0x681D, 0xD1EB, 0x681F, 0xD1D9, 0x6820, 0xD1F4, 0x6821, 0xAED5, 0x6825, 0xD1F3, 0x6826, 0xD1EE, + 0x6828, 0xD1EF, 0x6829, 0xAEDD, 0x682A, 0xAEE8, 0x682B, 0xD1E5, 0x682D, 0xD1E6, 0x682E, 0xD1F0, 0x682F, 0xD1E7, 0x6831, 0xD1E2, + 0x6832, 0xD1DC, 0x6833, 0xD1DD, 0x6834, 0xD1EA, 0x6835, 0xD1E4, 0x6838, 0xAED6, 0x6839, 0xAEDA, 0x683A, 0xD1F2, 0x683B, 0xD1DE, + 0x683C, 0xAEE6, 0x683D, 0xAEE2, 0x6840, 0xAEE5, 0x6841, 0xAEEC, 0x6842, 0xAEDB, 0x6843, 0xAEE7, 0x6844, 0xD1E9, 0x6845, 0xAEE9, + 0x6846, 0xAED8, 0x6848, 0xAED7, 0x6849, 0xD1DB, 0x684B, 0xD1DF, 0x684C, 0xAEE0, 0x684D, 0xD1F1, 0x684E, 0xD1E8, 0x684F, 0xD1E0, + 0x6850, 0xAEE4, 0x6851, 0xAEE1, 0x6853, 0xAED9, 0x6854, 0xAEDC, 0x686B, 0xD5C4, 0x686D, 0xD5B4, 0x686E, 0xD5B5, 0x686F, 0xD5B9, + 0x6871, 0xD5C8, 0x6872, 0xD5C5, 0x6874, 0xD5BE, 0x6875, 0xD5BD, 0x6876, 0xB1ED, 0x6877, 0xD5C1, 0x6878, 0xD5D0, 0x6879, 0xD5B0, + 0x687B, 0xD5D1, 0x687C, 0xD5C3, 0x687D, 0xD5D5, 0x687E, 0xD5C9, 0x687F, 0xB1EC, 0x6880, 0xD5C7, 0x6881, 0xB1E7, 0x6882, 0xB1FC, + 0x6883, 0xB1F2, 0x6885, 0xB1F6, 0x6886, 0xB1F5, 0x6887, 0xD5B1, 0x6889, 0xD5CE, 0x688A, 0xD5D4, 0x688B, 0xD5CC, 0x688C, 0xD5D3, + 0x688F, 0xD5C0, 0x6890, 0xD5B2, 0x6891, 0xD5D2, 0x6892, 0xD5C2, 0x6893, 0xB1EA, 0x6894, 0xB1F7, 0x6896, 0xD5CB, 0x6897, 0xB1F0, + 0x689B, 0xD5CA, 0x689C, 0xD5B3, 0x689D, 0xB1F8, 0x689F, 0xB1FA, 0x68A0, 0xD5CD, 0x68A1, 0xB1FB, 0x68A2, 0xB1E9, 0x68A3, 0xD5BA, + 0x68A4, 0xD5CF, 0x68A7, 0xB1EF, 0x68A8, 0xB1F9, 0x68A9, 0xD5BC, 0x68AA, 0xD5C6, 0x68AB, 0xD5B7, 0x68AC, 0xD5BB, 0x68AD, 0xB1F4, + 0x68AE, 0xD5B6, 0x68AF, 0xB1E8, 0x68B0, 0xB1F1, 0x68B1, 0xB1EE, 0x68B2, 0xD5BF, 0x68B3, 0xAEDE, 0x68B4, 0xD9C0, 0x68B5, 0xB1EB, + 0x68C4, 0xB1F3, 0x68C6, 0xD9C3, 0x68C7, 0xD9D9, 0x68C8, 0xD9CE, 0x68C9, 0xB4D6, 0x68CB, 0xB4D1, 0x68CC, 0xD9BD, 0x68CD, 0xB4D2, + 0x68CE, 0xD9CD, 0x68D0, 0xD9C6, 0x68D1, 0xD9D3, 0x68D2, 0xB4CE, 0x68D3, 0xD9AB, 0x68D4, 0xD9D5, 0x68D5, 0xB4C4, 0x68D6, 0xD9B3, + 0x68D7, 0xB4C7, 0x68D8, 0xB4C6, 0x68DA, 0xB4D7, 0x68DC, 0xD9AD, 0x68DD, 0xD9CF, 0x68DE, 0xD9D0, 0x68DF, 0xB4C9, 0x68E0, 0xB4C5, + 0x68E1, 0xD9BB, 0x68E3, 0xB4D0, 0x68E4, 0xD9B6, 0x68E6, 0xD9D1, 0x68E7, 0xB4CC, 0x68E8, 0xD9C9, 0x68E9, 0xD9D6, 0x68EA, 0xD9B0, + 0x68EB, 0xD9B5, 0x68EC, 0xD9AF, 0x68EE, 0xB4CB, 0x68EF, 0xD9C2, 0x68F0, 0xDDDE, 0x68F1, 0xD9B1, 0x68F2, 0xB4CF, 0x68F3, 0xD9BA, + 0x68F4, 0xD9D2, 0x68F5, 0xB4CA, 0x68F6, 0xD9B7, 0x68F7, 0xD9B4, 0x68F8, 0xD9C5, 0x68F9, 0xB4CD, 0x68FA, 0xB4C3, 0x68FB, 0xB4D9, + 0x68FC, 0xD9C8, 0x68FD, 0xD9C7, 0x6904, 0xD9AC, 0x6905, 0xB4C8, 0x6906, 0xD9D4, 0x6907, 0xD9BC, 0x6908, 0xD9BE, 0x690A, 0xD9CB, + 0x690B, 0xD9CA, 0x690C, 0xD9AA, 0x690D, 0xB4D3, 0x690E, 0xB4D5, 0x690F, 0xD9B2, 0x6910, 0xD9B9, 0x6911, 0xD9C1, 0x6912, 0xB4D4, + 0x6913, 0xD9B8, 0x6914, 0xD9C4, 0x6915, 0xD9D7, 0x6917, 0xD9CC, 0x6925, 0xD9D8, 0x692A, 0xD9AE, 0x692F, 0xDDF2, 0x6930, 0xB7A6, + 0x6932, 0xDDF0, 0x6933, 0xDDDB, 0x6934, 0xDDE0, 0x6935, 0xDDD9, 0x6937, 0xDDEC, 0x6938, 0xDDCB, 0x6939, 0xDDD2, 0x693B, 0xDDEA, + 0x693C, 0xDDF4, 0x693D, 0xDDDC, 0x693F, 0xDDCF, 0x6940, 0xDDE2, 0x6941, 0xDDE7, 0x6942, 0xDDD3, 0x6944, 0xDDE4, 0x6945, 0xDDD0, + 0x6948, 0xDDD7, 0x6949, 0xDDD8, 0x694A, 0xB7A8, 0x694B, 0xDDEB, 0x694C, 0xDDE9, 0x694E, 0xDDCC, 0x694F, 0xDDEE, 0x6951, 0xDDEF, + 0x6952, 0xDDF1, 0x6953, 0xB7AC, 0x6954, 0xB7A4, 0x6956, 0xD5B8, 0x6957, 0xDDD4, 0x6958, 0xDDE6, 0x6959, 0xDDD5, 0x695A, 0xB7A1, + 0x695B, 0xB7B1, 0x695C, 0xDDED, 0x695D, 0xB7AF, 0x695E, 0xB7AB, 0x695F, 0xDDCA, 0x6960, 0xB7A3, 0x6962, 0xDDCD, 0x6963, 0xB7B0, + 0x6965, 0xDDDD, 0x6966, 0xDDC9, 0x6968, 0xB7A9, 0x6969, 0xDDE1, 0x696A, 0xDDD1, 0x696B, 0xB7AA, 0x696C, 0xDDDA, 0x696D, 0xB77E, + 0x696E, 0xB4D8, 0x696F, 0xDDE3, 0x6970, 0xD9BF, 0x6971, 0xDDCE, 0x6974, 0xDDE8, 0x6975, 0xB7A5, 0x6976, 0xDDE5, 0x6977, 0xB7A2, + 0x6978, 0xDDDF, 0x6979, 0xB7AD, 0x697A, 0xDDD6, 0x697B, 0xDDF3, 0x6982, 0xB7A7, 0x6983, 0xDEC6, 0x6986, 0xB7AE, 0x698D, 0xE24A, + 0x698E, 0xE248, 0x6990, 0xE25E, 0x6991, 0xE246, 0x6993, 0xE258, 0x6994, 0xB77D, 0x6995, 0xBA5F, 0x6996, 0xE242, 0x6997, 0xE25D, + 0x6999, 0xE247, 0x699A, 0xE255, 0x699B, 0xBA64, 0x699C, 0xBA5D, 0x699E, 0xE25B, 0x69A0, 0xE240, 0x69A1, 0xE25A, 0x69A3, 0xBA6F, + 0x69A4, 0xE251, 0x69A5, 0xE261, 0x69A6, 0xBA6D, 0x69A7, 0xE249, 0x69A8, 0xBA5E, 0x69A9, 0xE24B, 0x69AA, 0xE259, 0x69AB, 0xBA67, + 0x69AC, 0xE244, 0x69AD, 0xBA6B, 0x69AE, 0xBA61, 0x69AF, 0xE24D, 0x69B0, 0xE243, 0x69B1, 0xE1FC, 0x69B3, 0xE257, 0x69B4, 0xBA68, + 0x69B5, 0xE260, 0x69B6, 0xE1FD, 0x69B7, 0xBA65, 0x69B9, 0xE253, 0x69BB, 0xBA66, 0x69BC, 0xE245, 0x69BD, 0xE250, 0x69BE, 0xE24C, + 0x69BF, 0xE24E, 0x69C1, 0xBA60, 0x69C2, 0xE25F, 0x69C3, 0xBA6E, 0x69C4, 0xE24F, 0x69C6, 0xE262, 0x69C9, 0xE1FE, 0x69CA, 0xE254, + 0x69CB, 0xBA63, 0x69CC, 0xBA6C, 0x69CD, 0xBA6A, 0x69CE, 0xE241, 0x69CF, 0xE256, 0x69D0, 0xBA69, 0x69D3, 0xBA62, 0x69D4, 0xE252, + 0x69D9, 0xE25C, 0x69E2, 0xE5D5, 0x69E4, 0xE5D1, 0x69E5, 0xE5CD, 0x69E6, 0xE5E1, 0x69E7, 0xE5DE, 0x69E8, 0xBCCD, 0x69EB, 0xE5E5, + 0x69EC, 0xE5D4, 0x69ED, 0xBCD8, 0x69EE, 0xE5DB, 0x69F1, 0xE5D0, 0x69F2, 0xE5DA, 0x69F3, 0xBCD5, 0x69F4, 0xE5EE, 0x69F6, 0xE5EB, + 0x69F7, 0xE5DD, 0x69F8, 0xE5CE, 0x69FB, 0xE5E2, 0x69FC, 0xE5E4, 0x69FD, 0xBCD1, 0x69FE, 0xE5D8, 0x69FF, 0xE5D3, 0x6A00, 0xE5CA, + 0x6A01, 0xBCCE, 0x6A02, 0xBCD6, 0x6A04, 0xE5E7, 0x6A05, 0xBCD7, 0x6A06, 0xE5CB, 0x6A07, 0xE5ED, 0x6A08, 0xE5E0, 0x6A09, 0xE5E6, + 0x6A0A, 0xBCD4, 0x6A0D, 0xE5E3, 0x6A0F, 0xE5EA, 0x6A11, 0xBCD9, 0x6A13, 0xBCD3, 0x6A14, 0xE5DC, 0x6A15, 0xE5CF, 0x6A16, 0xE5EF, + 0x6A17, 0xE5CC, 0x6A18, 0xE5E8, 0x6A19, 0xBCD0, 0x6A1B, 0xE5D6, 0x6A1D, 0xE5D7, 0x6A1E, 0xBCCF, 0x6A1F, 0xBCCC, 0x6A20, 0xE5D2, + 0x6A21, 0xBCD2, 0x6A23, 0xBCCB, 0x6A25, 0xE5E9, 0x6A26, 0xE5EC, 0x6A27, 0xE5D9, 0x6A28, 0xE9CA, 0x6A32, 0xE9C2, 0x6A34, 0xE9BE, + 0x6A35, 0xBEF6, 0x6A38, 0xBEEB, 0x6A39, 0xBEF0, 0x6A3A, 0xBEEC, 0x6A3B, 0xE9CC, 0x6A3C, 0xE9D7, 0x6A3D, 0xBEEA, 0x6A3E, 0xE9C4, + 0x6A3F, 0xE9CD, 0x6A40, 0xE5DF, 0x6A41, 0xE9CE, 0x6A44, 0xBEF1, 0x6A46, 0xE9DD, 0x6A47, 0xBEF5, 0x6A48, 0xBEF8, 0x6A49, 0xE9C0, + 0x6A4B, 0xBEF4, 0x6A4D, 0xE9DB, 0x6A4E, 0xE9DC, 0x6A4F, 0xE9D2, 0x6A50, 0xE9D1, 0x6A51, 0xE9C9, 0x6A54, 0xE9D3, 0x6A55, 0xE9DA, + 0x6A56, 0xE9D9, 0x6A58, 0xBEEF, 0x6A59, 0xBEED, 0x6A5A, 0xE9CB, 0x6A5B, 0xE9C8, 0x6A5D, 0xE9C5, 0x6A5E, 0xE9D8, 0x6A5F, 0xBEF7, + 0x6A60, 0xE9D6, 0x6A61, 0xBEF3, 0x6A62, 0xBEF2, 0x6A64, 0xE9D0, 0x6A66, 0xE9BF, 0x6A67, 0xE9C1, 0x6A68, 0xE9C3, 0x6A69, 0xE9D5, + 0x6A6A, 0xE9CF, 0x6A6B, 0xBEEE, 0x6A6D, 0xE9C6, 0x6A6F, 0xE9D4, 0x6A76, 0xE9C7, 0x6A7E, 0xC0CF, 0x6A7F, 0xED45, 0x6A80, 0xC0C8, + 0x6A81, 0xECF5, 0x6A83, 0xED41, 0x6A84, 0xC0CA, 0x6A85, 0xED48, 0x6A87, 0xECFC, 0x6A89, 0xECF7, 0x6A8C, 0xED49, 0x6A8D, 0xECF3, + 0x6A8E, 0xECFE, 0x6A90, 0xC0D1, 0x6A91, 0xED44, 0x6A92, 0xED4A, 0x6A93, 0xECFD, 0x6A94, 0xC0C9, 0x6A95, 0xED40, 0x6A96, 0xECF4, + 0x6A97, 0xC0D0, 0x6A9A, 0xED47, 0x6A9B, 0xECF9, 0x6A9C, 0xC0CC, 0x6A9E, 0xECFB, 0x6A9F, 0xECF8, 0x6AA0, 0xC0D2, 0x6AA1, 0xECFA, + 0x6AA2, 0xC0CB, 0x6AA3, 0xC0CE, 0x6AA4, 0xED43, 0x6AA5, 0xECF6, 0x6AA6, 0xED46, 0x6AA8, 0xED42, 0x6AAC, 0xC263, 0x6AAD, 0xEFE7, + 0x6AAE, 0xC268, 0x6AAF, 0xC269, 0x6AB3, 0xC262, 0x6AB4, 0xEFE6, 0x6AB6, 0xEFE3, 0x6AB7, 0xEFE4, 0x6AB8, 0xC266, 0x6AB9, 0xEFDE, + 0x6ABA, 0xEFE2, 0x6ABB, 0xC265, 0x6ABD, 0xEFDF, 0x6AC2, 0xC267, 0x6AC3, 0xC264, 0x6AC5, 0xEFDD, 0x6AC6, 0xEFE1, 0x6AC7, 0xEFE5, + 0x6ACB, 0xF251, 0x6ACC, 0xF24E, 0x6ACD, 0xF257, 0x6ACF, 0xF256, 0x6AD0, 0xF254, 0x6AD1, 0xF24F, 0x6AD3, 0xC372, 0x6AD9, 0xF250, + 0x6ADA, 0xC371, 0x6ADB, 0xC0CD, 0x6ADC, 0xF253, 0x6ADD, 0xC370, 0x6ADE, 0xF258, 0x6ADF, 0xF252, 0x6AE0, 0xF24D, 0x6AE1, 0xEFE0, + 0x6AE5, 0xC36F, 0x6AE7, 0xF24C, 0x6AE8, 0xF456, 0x6AEA, 0xF455, 0x6AEB, 0xF255, 0x6AEC, 0xC468, 0x6AEE, 0xF459, 0x6AEF, 0xF45A, + 0x6AF0, 0xF454, 0x6AF1, 0xF458, 0x6AF3, 0xF453, 0x6AF8, 0xF5D1, 0x6AF9, 0xF457, 0x6AFA, 0xC4E7, 0x6AFB, 0xC4E5, 0x6AFC, 0xF5CF, + 0x6B00, 0xF5D2, 0x6B02, 0xF5CE, 0x6B03, 0xF5D0, 0x6B04, 0xC4E6, 0x6B08, 0xF6E5, 0x6B09, 0xF6E6, 0x6B0A, 0xC576, 0x6B0B, 0xF6E4, + 0x6B0F, 0xF7E2, 0x6B10, 0xC5CF, 0x6B11, 0xF7E0, 0x6B12, 0xF7E1, 0x6B13, 0xF8AC, 0x6B16, 0xC656, 0x6B17, 0xF8F3, 0x6B18, 0xF8F1, + 0x6B19, 0xF8F2, 0x6B1A, 0xF8F4, 0x6B1E, 0xF9BB, 0x6B20, 0xA4ED, 0x6B21, 0xA6B8, 0x6B23, 0xAA59, 0x6B25, 0xCCE9, 0x6B28, 0xCF64, + 0x6B2C, 0xD1F5, 0x6B2D, 0xD1F7, 0x6B2F, 0xD1F6, 0x6B31, 0xD1F8, 0x6B32, 0xB1FD, 0x6B33, 0xD5D7, 0x6B34, 0xD1F9, 0x6B36, 0xD5D6, + 0x6B37, 0xD5D8, 0x6B38, 0xD5D9, 0x6B39, 0xD9DA, 0x6B3A, 0xB4DB, 0x6B3B, 0xD9DB, 0x6B3C, 0xD9DD, 0x6B3D, 0xB4DC, 0x6B3E, 0xB4DA, + 0x6B3F, 0xD9DC, 0x6B41, 0xDDFA, 0x6B42, 0xDDF8, 0x6B43, 0xDDF7, 0x6B45, 0xDDF6, 0x6B46, 0xDDF5, 0x6B47, 0xB7B2, 0x6B48, 0xDDF9, + 0x6B49, 0xBA70, 0x6B4A, 0xE263, 0x6B4B, 0xE265, 0x6B4C, 0xBA71, 0x6B4D, 0xE264, 0x6B4E, 0xBCDB, 0x6B50, 0xBCDA, 0x6B51, 0xE5F0, + 0x6B54, 0xE9DF, 0x6B55, 0xE9DE, 0x6B56, 0xE9E0, 0x6B59, 0xBEF9, 0x6B5B, 0xED4B, 0x6B5C, 0xC0D3, 0x6B5E, 0xEFE8, 0x6B5F, 0xC26A, + 0x6B60, 0xF259, 0x6B61, 0xC577, 0x6B62, 0xA4EE, 0x6B63, 0xA5BF, 0x6B64, 0xA6B9, 0x6B65, 0xA842, 0x6B66, 0xAA5A, 0x6B67, 0xAA5B, + 0x6B6A, 0xAC6E, 0x6B6D, 0xD1FA, 0x6B72, 0xB7B3, 0x6B76, 0xE6D1, 0x6B77, 0xBEFA, 0x6B78, 0xC26B, 0x6B79, 0xA4EF, 0x6B7B, 0xA6BA, + 0x6B7E, 0xCCEB, 0x6B7F, 0xAA5C, 0x6B80, 0xCCEA, 0x6B82, 0xCF65, 0x6B83, 0xAC6F, 0x6B84, 0xCF66, 0x6B86, 0xAC70, 0x6B88, 0xD1FC, + 0x6B89, 0xAEEE, 0x6B8A, 0xAEED, 0x6B8C, 0xD5DE, 0x6B8D, 0xD5DC, 0x6B8E, 0xD5DD, 0x6B8F, 0xD5DB, 0x6B91, 0xD5DA, 0x6B94, 0xD9DE, + 0x6B95, 0xD9E1, 0x6B96, 0xB4DE, 0x6B97, 0xD9DF, 0x6B98, 0xB4DD, 0x6B99, 0xD9E0, 0x6B9B, 0xDDFB, 0x6B9E, 0xE266, 0x6B9F, 0xE267, + 0x6BA0, 0xE268, 0x6BA2, 0xE5F3, 0x6BA3, 0xE5F2, 0x6BA4, 0xBCDC, 0x6BA5, 0xE5F1, 0x6BA6, 0xE5F4, 0x6BA7, 0xE9E1, 0x6BAA, 0xE9E2, + 0x6BAB, 0xE9E3, 0x6BAD, 0xED4C, 0x6BAE, 0xC0D4, 0x6BAF, 0xC26C, 0x6BB0, 0xF25A, 0x6BB2, 0xC4E8, 0x6BB3, 0xC95F, 0x6BB5, 0xAC71, + 0x6BB6, 0xCF67, 0x6BB7, 0xAEEF, 0x6BBA, 0xB1FE, 0x6BBC, 0xB4DF, 0x6BBD, 0xD9E2, 0x6BBF, 0xB7B5, 0x6BC0, 0xB7B4, 0x6BC3, 0xE269, + 0x6BC4, 0xE26A, 0x6BC5, 0xBCDD, 0x6BC6, 0xBCDE, 0x6BC7, 0xE9E5, 0x6BC8, 0xE9E4, 0x6BC9, 0xEFE9, 0x6BCA, 0xF7E3, 0x6BCB, 0xA4F0, + 0x6BCC, 0xC960, 0x6BCD, 0xA5C0, 0x6BCF, 0xA843, 0x6BD0, 0xCB48, 0x6BD2, 0xAC72, 0x6BD3, 0xB7B6, 0x6BD4, 0xA4F1, 0x6BD6, 0xCF68, + 0x6BD7, 0xAC73, 0x6BD8, 0xCF69, 0x6BDA, 0xC0D5, 0x6BDB, 0xA4F2, 0x6BDE, 0xCCEC, 0x6BE0, 0xCF6A, 0x6BE2, 0xD242, 0x6BE3, 0xD241, + 0x6BE4, 0xD1FE, 0x6BE6, 0xD1FD, 0x6BE7, 0xD243, 0x6BE8, 0xD240, 0x6BEB, 0xB240, 0x6BEC, 0xB241, 0x6BEF, 0xB4E0, 0x6BF0, 0xD9E3, + 0x6BF2, 0xD9E4, 0x6BF3, 0xD9E5, 0x6BF7, 0xDE41, 0x6BF8, 0xDE42, 0x6BF9, 0xDE40, 0x6BFB, 0xDDFD, 0x6BFC, 0xDDFE, 0x6BFD, 0xB7B7, + 0x6BFE, 0xE26B, 0x6BFF, 0xE5F7, 0x6C00, 0xE5F6, 0x6C01, 0xE5F5, 0x6C02, 0xE5F8, 0x6C03, 0xE9E7, 0x6C04, 0xE9E6, 0x6C05, 0xBEFB, + 0x6C06, 0xE9E8, 0x6C08, 0xC0D6, 0x6C09, 0xED4D, 0x6C0B, 0xEFEA, 0x6C0C, 0xF25B, 0x6C0D, 0xF6E7, 0x6C0F, 0xA4F3, 0x6C10, 0xA5C2, + 0x6C11, 0xA5C1, 0x6C13, 0xAA5D, 0x6C14, 0xC961, 0x6C15, 0xC97E, 0x6C16, 0xA6BB, 0x6C18, 0xC9F7, 0x6C19, 0xCB49, 0x6C1A, 0xCB4A, + 0x6C1B, 0xAA5E, 0x6C1D, 0xCCED, 0x6C1F, 0xAC74, 0x6C20, 0xCF6B, 0x6C21, 0xCF6C, 0x6C23, 0xAEF0, 0x6C24, 0xAEF4, 0x6C25, 0xD244, + 0x6C26, 0xAEF3, 0x6C27, 0xAEF1, 0x6C28, 0xAEF2, 0x6C2A, 0xD5DF, 0x6C2B, 0xB242, 0x6C2C, 0xB4E3, 0x6C2E, 0xB4E1, 0x6C2F, 0xB4E2, + 0x6C30, 0xD9E6, 0x6C33, 0xBA72, 0x6C34, 0xA4F4, 0x6C36, 0xC9A1, 0x6C38, 0xA5C3, 0x6C3B, 0xC9A4, 0x6C3E, 0xA5C6, 0x6C3F, 0xC9A3, + 0x6C40, 0xA5C5, 0x6C41, 0xA5C4, 0x6C42, 0xA844, 0x6C43, 0xC9A2, 0x6C46, 0xC9F8, 0x6C4A, 0xC9FC, 0x6C4B, 0xC9FE, 0x6C4C, 0xCA40, + 0x6C4D, 0xA6C5, 0x6C4E, 0xA6C6, 0x6C4F, 0xC9FB, 0x6C50, 0xA6C1, 0x6C52, 0xC9F9, 0x6C54, 0xC9FD, 0x6C55, 0xA6C2, 0x6C57, 0xA6BD, + 0x6C59, 0xA6BE, 0x6C5B, 0xA6C4, 0x6C5C, 0xC9FA, 0x6C5D, 0xA6BC, 0x6C5E, 0xA845, 0x6C5F, 0xA6BF, 0x6C60, 0xA6C0, 0x6C61, 0xA6C3, + 0x6C65, 0xCB5B, 0x6C66, 0xCB59, 0x6C67, 0xCB4C, 0x6C68, 0xA851, 0x6C69, 0xCB53, 0x6C6A, 0xA84C, 0x6C6B, 0xCB4D, 0x6C6D, 0xCB55, + 0x6C6F, 0xCB52, 0x6C70, 0xA84F, 0x6C71, 0xCB51, 0x6C72, 0xA856, 0x6C73, 0xCB5A, 0x6C74, 0xA858, 0x6C76, 0xA85A, 0x6C78, 0xCB4B, + 0x6C7A, 0xA84D, 0x6C7B, 0xCB5C, 0x6C7D, 0xA854, 0x6C7E, 0xA857, 0x6C80, 0xCD45, 0x6C81, 0xA847, 0x6C82, 0xA85E, 0x6C83, 0xA855, + 0x6C84, 0xCB4E, 0x6C85, 0xA84A, 0x6C86, 0xA859, 0x6C87, 0xCB56, 0x6C88, 0xA848, 0x6C89, 0xA849, 0x6C8A, 0xCD43, 0x6C8B, 0xCB4F, + 0x6C8C, 0xA850, 0x6C8D, 0xA85B, 0x6C8E, 0xCB5D, 0x6C8F, 0xCB50, 0x6C90, 0xA84E, 0x6C92, 0xA853, 0x6C93, 0xCCEE, 0x6C94, 0xA85C, + 0x6C95, 0xCB57, 0x6C96, 0xA852, 0x6C98, 0xA85D, 0x6C99, 0xA846, 0x6C9A, 0xCB54, 0x6C9B, 0xA84B, 0x6C9C, 0xCB58, 0x6C9D, 0xCD44, + 0x6CAB, 0xAA6A, 0x6CAC, 0xAA7A, 0x6CAD, 0xCCF5, 0x6CAE, 0xAA71, 0x6CB0, 0xCD4B, 0x6CB1, 0xAA62, 0x6CB3, 0xAA65, 0x6CB4, 0xCD42, + 0x6CB6, 0xCCF3, 0x6CB7, 0xCCF7, 0x6CB8, 0xAA6D, 0x6CB9, 0xAA6F, 0x6CBA, 0xCCFA, 0x6CBB, 0xAA76, 0x6CBC, 0xAA68, 0x6CBD, 0xAA66, + 0x6CBE, 0xAA67, 0x6CBF, 0xAA75, 0x6CC0, 0xCD47, 0x6CC1, 0xAA70, 0x6CC2, 0xCCF9, 0x6CC3, 0xCCFB, 0x6CC4, 0xAA6E, 0x6CC5, 0xAA73, + 0x6CC6, 0xCCFC, 0x6CC7, 0xCD4A, 0x6CC9, 0xAC75, 0x6CCA, 0xAA79, 0x6CCC, 0xAA63, 0x6CCD, 0xCD49, 0x6CCF, 0xCD4D, 0x6CD0, 0xCCF8, + 0x6CD1, 0xCD4F, 0x6CD2, 0xCD40, 0x6CD3, 0xAA6C, 0x6CD4, 0xCCF4, 0x6CD5, 0xAA6B, 0x6CD6, 0xAA7D, 0x6CD7, 0xAA72, 0x6CD9, 0xCCF2, + 0x6CDA, 0xCF75, 0x6CDB, 0xAA78, 0x6CDC, 0xAA7C, 0x6CDD, 0xCD41, 0x6CDE, 0xCD46, 0x6CE0, 0xAA7E, 0x6CE1, 0xAA77, 0x6CE2, 0xAA69, + 0x6CE3, 0xAA5F, 0x6CE5, 0xAA64, 0x6CE7, 0xCCF6, 0x6CE8, 0xAA60, 0x6CE9, 0xCD4E, 0x6CEB, 0xCCF0, 0x6CEC, 0xCCEF, 0x6CED, 0xCCFD, + 0x6CEE, 0xCCF1, 0x6CEF, 0xAA7B, 0x6CF0, 0xAEF5, 0x6CF1, 0xAA74, 0x6CF2, 0xCCFE, 0x6CF3, 0xAA61, 0x6CF5, 0xACA6, 0x6CF9, 0xCD4C, + 0x6D00, 0xCF7C, 0x6D01, 0xCFA1, 0x6D03, 0xCFA4, 0x6D04, 0xCF77, 0x6D07, 0xCFA7, 0x6D08, 0xCFAA, 0x6D09, 0xCFAC, 0x6D0A, 0xCF74, + 0x6D0B, 0xAC76, 0x6D0C, 0xAC7B, 0x6D0D, 0xD249, 0x6D0E, 0xACAD, 0x6D0F, 0xCFA5, 0x6D10, 0xCFAD, 0x6D11, 0xCF7B, 0x6D12, 0xCF73, + 0x6D16, 0xD264, 0x6D17, 0xAC7E, 0x6D18, 0xCFA2, 0x6D19, 0xCF78, 0x6D1A, 0xCF7A, 0x6D1B, 0xACA5, 0x6D1D, 0xCF7D, 0x6D1E, 0xAC7D, + 0x6D1F, 0xCF70, 0x6D20, 0xCFA8, 0x6D22, 0xCFAB, 0x6D25, 0xAC7A, 0x6D27, 0xACA8, 0x6D28, 0xCF6D, 0x6D29, 0xACAA, 0x6D2A, 0xAC78, + 0x6D2B, 0xACAE, 0x6D2C, 0xCFA9, 0x6D2D, 0xCF6F, 0x6D2E, 0xACAB, 0x6D2F, 0xD25E, 0x6D30, 0xCD48, 0x6D31, 0xAC7C, 0x6D32, 0xAC77, + 0x6D33, 0xCF76, 0x6D34, 0xCF6E, 0x6D35, 0xACAC, 0x6D36, 0xACA4, 0x6D37, 0xCFA3, 0x6D38, 0xACA9, 0x6D39, 0xACA7, 0x6D3A, 0xCF79, + 0x6D3B, 0xACA1, 0x6D3C, 0xCF71, 0x6D3D, 0xACA2, 0x6D3E, 0xACA3, 0x6D3F, 0xCF72, 0x6D40, 0xCFA6, 0x6D41, 0xAC79, 0x6D42, 0xCF7E, + 0x6D58, 0xD24C, 0x6D59, 0xAEFD, 0x6D5A, 0xAF43, 0x6D5E, 0xD255, 0x6D5F, 0xD25B, 0x6D60, 0xD257, 0x6D61, 0xD24A, 0x6D62, 0xD24D, + 0x6D63, 0xD246, 0x6D64, 0xD247, 0x6D65, 0xAF4A, 0x6D66, 0xAEFA, 0x6D67, 0xD256, 0x6D68, 0xD25F, 0x6D69, 0xAF45, 0x6D6A, 0xAEF6, + 0x6D6C, 0xAF40, 0x6D6D, 0xD24E, 0x6D6E, 0xAF42, 0x6D6F, 0xD24F, 0x6D70, 0xD259, 0x6D74, 0xAF44, 0x6D75, 0xD268, 0x6D76, 0xD248, + 0x6D77, 0xAEFC, 0x6D78, 0xAEFB, 0x6D79, 0xAF48, 0x6D7A, 0xD245, 0x6D7B, 0xD266, 0x6D7C, 0xD25A, 0x6D7D, 0xD267, 0x6D7E, 0xD261, + 0x6D7F, 0xD253, 0x6D80, 0xD262, 0x6D82, 0xD25C, 0x6D83, 0xD265, 0x6D84, 0xD263, 0x6D85, 0xAF49, 0x6D86, 0xD254, 0x6D87, 0xAEF9, + 0x6D88, 0xAEF8, 0x6D89, 0xAF41, 0x6D8A, 0xAF47, 0x6D8B, 0xD260, 0x6D8C, 0xAF46, 0x6D8D, 0xD251, 0x6D8E, 0xB243, 0x6D90, 0xD269, + 0x6D91, 0xD250, 0x6D92, 0xD24B, 0x6D93, 0xAEFE, 0x6D94, 0xAF4B, 0x6D95, 0xAEF7, 0x6D97, 0xD258, 0x6D98, 0xD25D, 0x6DAA, 0xB265, + 0x6DAB, 0xD5E1, 0x6DAC, 0xD5E5, 0x6DAE, 0xB252, 0x6DAF, 0xB250, 0x6DB2, 0xB247, 0x6DB3, 0xD5E3, 0x6DB4, 0xD5E2, 0x6DB5, 0xB25B, + 0x6DB7, 0xD5E8, 0x6DB8, 0xB255, 0x6DBA, 0xD5FA, 0x6DBB, 0xD647, 0x6DBC, 0xB244, 0x6DBD, 0xD5F7, 0x6DBE, 0xD5F0, 0x6DBF, 0xB267, + 0x6DC0, 0xD5E0, 0x6DC2, 0xD5FC, 0x6DC4, 0xB264, 0x6DC5, 0xB258, 0x6DC6, 0xB263, 0x6DC7, 0xB24E, 0x6DC8, 0xD5EC, 0x6DC9, 0xD5FE, + 0x6DCA, 0xD5F6, 0x6DCB, 0xB24F, 0x6DCC, 0xB249, 0x6DCD, 0xD645, 0x6DCF, 0xD5FD, 0x6DD0, 0xD640, 0x6DD1, 0xB251, 0x6DD2, 0xB259, + 0x6DD3, 0xD642, 0x6DD4, 0xD5EA, 0x6DD5, 0xD5FB, 0x6DD6, 0xD5EF, 0x6DD7, 0xD644, 0x6DD8, 0xB25E, 0x6DD9, 0xB246, 0x6DDA, 0xB25C, + 0x6DDB, 0xD5F4, 0x6DDC, 0xD5F2, 0x6DDD, 0xD5F3, 0x6DDE, 0xB253, 0x6DDF, 0xD5EE, 0x6DE0, 0xD5ED, 0x6DE1, 0xB248, 0x6DE2, 0xD5E7, + 0x6DE3, 0xD646, 0x6DE4, 0xB24A, 0x6DE5, 0xD5F1, 0x6DE6, 0xB268, 0x6DE8, 0xB262, 0x6DE9, 0xD5E6, 0x6DEA, 0xB25F, 0x6DEB, 0xB25D, + 0x6DEC, 0xB266, 0x6DED, 0xD5F8, 0x6DEE, 0xB261, 0x6DEF, 0xD252, 0x6DF0, 0xD5F9, 0x6DF1, 0xB260, 0x6DF2, 0xD641, 0x6DF3, 0xB245, + 0x6DF4, 0xD5F5, 0x6DF5, 0xB257, 0x6DF6, 0xD5E9, 0x6DF7, 0xB256, 0x6DF9, 0xB254, 0x6DFA, 0xB24C, 0x6DFB, 0xB24B, 0x6DFC, 0xD9E7, + 0x6DFD, 0xD643, 0x6E00, 0xD5EB, 0x6E03, 0xD9FC, 0x6E05, 0xB24D, 0x6E19, 0xB541, 0x6E1A, 0xB25A, 0x6E1B, 0xB4EE, 0x6E1C, 0xD9F6, + 0x6E1D, 0xB4FC, 0x6E1F, 0xD9EA, 0x6E20, 0xB4EB, 0x6E21, 0xB4E7, 0x6E22, 0xDA49, 0x6E23, 0xB4ED, 0x6E24, 0xB4F1, 0x6E25, 0xB4EC, + 0x6E26, 0xB4F5, 0x6E27, 0xDA4D, 0x6E28, 0xDA44, 0x6E2B, 0xD9F1, 0x6E2C, 0xB4FA, 0x6E2D, 0xB4F4, 0x6E2E, 0xD9FD, 0x6E2F, 0xB4E4, + 0x6E30, 0xDA4A, 0x6E31, 0xDA43, 0x6E32, 0xB4E8, 0x6E33, 0xD9F7, 0x6E34, 0xB4F7, 0x6E35, 0xDA55, 0x6E36, 0xDA56, 0x6E38, 0xB4E5, + 0x6E39, 0xDA48, 0x6E3A, 0xB4F9, 0x6E3B, 0xD9FB, 0x6E3C, 0xD9ED, 0x6E3D, 0xD9EE, 0x6E3E, 0xB4FD, 0x6E3F, 0xD9F2, 0x6E40, 0xD9F9, + 0x6E41, 0xD9F3, 0x6E43, 0xB4FB, 0x6E44, 0xB544, 0x6E45, 0xD9EF, 0x6E46, 0xD9E8, 0x6E47, 0xD9E9, 0x6E49, 0xD9EB, 0x6E4A, 0xB4EA, + 0x6E4B, 0xD9F8, 0x6E4D, 0xB4F8, 0x6E4E, 0xB542, 0x6E51, 0xD9FA, 0x6E52, 0xDA53, 0x6E53, 0xDA4B, 0x6E54, 0xB4E6, 0x6E55, 0xDA51, + 0x6E56, 0xB4F2, 0x6E58, 0xB4F0, 0x6E5A, 0xDA57, 0x6E5B, 0xB4EF, 0x6E5C, 0xDA41, 0x6E5D, 0xD9F4, 0x6E5E, 0xD9FE, 0x6E5F, 0xB547, + 0x6E60, 0xDA45, 0x6E61, 0xDA42, 0x6E62, 0xD9F0, 0x6E63, 0xB543, 0x6E64, 0xDA4F, 0x6E65, 0xDA4C, 0x6E66, 0xDA54, 0x6E67, 0xB4E9, + 0x6E68, 0xDA40, 0x6E69, 0xB546, 0x6E6B, 0xDA47, 0x6E6E, 0xB4F3, 0x6E6F, 0xB4F6, 0x6E71, 0xDA46, 0x6E72, 0xB545, 0x6E73, 0xD9F5, + 0x6E74, 0xD5E4, 0x6E77, 0xDA50, 0x6E78, 0xDA4E, 0x6E79, 0xDA52, 0x6E88, 0xD9EC, 0x6E89, 0xB540, 0x6E8D, 0xDE61, 0x6E8E, 0xDE60, + 0x6E8F, 0xDE46, 0x6E90, 0xB7BD, 0x6E92, 0xDE5F, 0x6E93, 0xDE49, 0x6E94, 0xDE4A, 0x6E96, 0xB7C7, 0x6E97, 0xDE68, 0x6E98, 0xB7C2, + 0x6E99, 0xDE5E, 0x6E9B, 0xDE43, 0x6E9C, 0xB7C8, 0x6E9D, 0xB7BE, 0x6E9E, 0xDE52, 0x6E9F, 0xDE48, 0x6EA0, 0xDE4B, 0x6EA1, 0xDE63, + 0x6EA2, 0xB7B8, 0x6EA3, 0xDE6A, 0x6EA4, 0xDE62, 0x6EA5, 0xB7C1, 0x6EA6, 0xDE57, 0x6EA7, 0xB7CC, 0x6EAA, 0xB7CB, 0x6EAB, 0xB7C5, + 0x6EAE, 0xDE69, 0x6EAF, 0xB7B9, 0x6EB0, 0xDE55, 0x6EB1, 0xDE4C, 0x6EB2, 0xDE59, 0x6EB3, 0xDE65, 0x6EB4, 0xB7CD, 0x6EB6, 0xB7BB, + 0x6EB7, 0xDE54, 0x6EB9, 0xDE4D, 0x6EBA, 0xB7C4, 0x6EBC, 0xB7C3, 0x6EBD, 0xDE50, 0x6EBE, 0xDE5A, 0x6EBF, 0xDE64, 0x6EC0, 0xDE47, + 0x6EC1, 0xDE51, 0x6EC2, 0xB7BC, 0x6EC3, 0xDE5B, 0x6EC4, 0xB7C9, 0x6EC5, 0xB7C0, 0x6EC6, 0xDE4E, 0x6EC7, 0xB7BF, 0x6EC8, 0xDE45, + 0x6EC9, 0xDE53, 0x6ECA, 0xDE67, 0x6ECB, 0xB4FE, 0x6ECC, 0xBAB0, 0x6ECD, 0xDE56, 0x6ECE, 0xE26C, 0x6ECF, 0xDE58, 0x6ED0, 0xDE66, + 0x6ED1, 0xB7C6, 0x6ED2, 0xDE4F, 0x6ED3, 0xB7BA, 0x6ED4, 0xB7CA, 0x6ED5, 0xBCF0, 0x6ED6, 0xDE44, 0x6ED8, 0xDE5D, 0x6EDC, 0xDE5C, + 0x6EEB, 0xE2AA, 0x6EEC, 0xBAAD, 0x6EED, 0xE27D, 0x6EEE, 0xE2A4, 0x6EEF, 0xBAA2, 0x6EF1, 0xE26E, 0x6EF2, 0xBAAF, 0x6EF4, 0xBA77, + 0x6EF5, 0xE26D, 0x6EF6, 0xE2B0, 0x6EF7, 0xBAB1, 0x6EF8, 0xE271, 0x6EF9, 0xE2A3, 0x6EFB, 0xE273, 0x6EFC, 0xE2B3, 0x6EFD, 0xE2AF, + 0x6EFE, 0xBA75, 0x6EFF, 0xBAA1, 0x6F00, 0xE653, 0x6F01, 0xBAAE, 0x6F02, 0xBA7D, 0x6F03, 0xE26F, 0x6F05, 0xE2AE, 0x6F06, 0xBAA3, + 0x6F07, 0xE2AB, 0x6F08, 0xE2B8, 0x6F09, 0xE275, 0x6F0A, 0xE27E, 0x6F0D, 0xE2B6, 0x6F0E, 0xE2AC, 0x6F0F, 0xBA7C, 0x6F12, 0xE27C, + 0x6F13, 0xBA76, 0x6F14, 0xBA74, 0x6F15, 0xBAA8, 0x6F18, 0xE27A, 0x6F19, 0xE277, 0x6F1A, 0xE278, 0x6F1C, 0xE2B2, 0x6F1E, 0xE2B7, + 0x6F1F, 0xE2B5, 0x6F20, 0xBA7A, 0x6F21, 0xE2B9, 0x6F22, 0xBA7E, 0x6F23, 0xBAA7, 0x6F25, 0xE270, 0x6F26, 0xE5FA, 0x6F27, 0xE279, + 0x6F29, 0xBA78, 0x6F2A, 0xBAAC, 0x6F2B, 0xBAA9, 0x6F2C, 0xBA7B, 0x6F2D, 0xE2A5, 0x6F2E, 0xE274, 0x6F2F, 0xBAAA, 0x6F30, 0xE2A7, + 0x6F31, 0xBAA4, 0x6F32, 0xBAA6, 0x6F33, 0xBA73, 0x6F35, 0xE2A9, 0x6F36, 0xE2A1, 0x6F37, 0xE272, 0x6F38, 0xBAA5, 0x6F39, 0xE2B1, + 0x6F3A, 0xE2B4, 0x6F3B, 0xE27B, 0x6F3C, 0xE2A8, 0x6F3E, 0xBA79, 0x6F3F, 0xBCDF, 0x6F40, 0xE2A6, 0x6F41, 0xE5F9, 0x6F43, 0xE2AD, + 0x6F4E, 0xE276, 0x6F4F, 0xE644, 0x6F50, 0xE64E, 0x6F51, 0xBCE2, 0x6F52, 0xE64D, 0x6F53, 0xE659, 0x6F54, 0xBCE4, 0x6F55, 0xE64B, + 0x6F57, 0xE64F, 0x6F58, 0xBCEF, 0x6F5A, 0xE646, 0x6F5B, 0xBCE7, 0x6F5D, 0xE652, 0x6F5E, 0xE9F0, 0x6F5F, 0xBCF3, 0x6F60, 0xBCF2, + 0x6F61, 0xE654, 0x6F62, 0xE643, 0x6F63, 0xE65E, 0x6F64, 0xBCED, 0x6F66, 0xBCE3, 0x6F67, 0xE657, 0x6F69, 0xE65B, 0x6F6A, 0xE660, + 0x6F6B, 0xE655, 0x6F6C, 0xE649, 0x6F6D, 0xBCE6, 0x6F6E, 0xBCE9, 0x6F6F, 0xBCF1, 0x6F70, 0xBCEC, 0x6F72, 0xE64C, 0x6F73, 0xE2A2, + 0x6F76, 0xE648, 0x6F77, 0xE65F, 0x6F78, 0xBCE8, 0x6F7A, 0xBCEB, 0x6F7B, 0xE661, 0x6F7C, 0xBCE0, 0x6F7D, 0xE656, 0x6F7E, 0xE5FB, + 0x6F7F, 0xE65C, 0x6F80, 0xC0DF, 0x6F82, 0xE64A, 0x6F84, 0xBCE1, 0x6F85, 0xE645, 0x6F86, 0xBCE5, 0x6F87, 0xE5FC, 0x6F88, 0xBAAB, + 0x6F89, 0xE641, 0x6F8B, 0xE65A, 0x6F8C, 0xE642, 0x6F8D, 0xE640, 0x6F8E, 0xBCEA, 0x6F90, 0xE658, 0x6F92, 0xE5FE, 0x6F93, 0xE651, + 0x6F94, 0xE650, 0x6F95, 0xE65D, 0x6F96, 0xE647, 0x6F97, 0xBCEE, 0x6F9E, 0xE9F3, 0x6FA0, 0xBF49, 0x6FA1, 0xBEFE, 0x6FA2, 0xEA40, + 0x6FA3, 0xE9EB, 0x6FA4, 0xBF41, 0x6FA5, 0xE9F7, 0x6FA6, 0xBF48, 0x6FA7, 0xBF43, 0x6FA8, 0xE9F5, 0x6FA9, 0xED4F, 0x6FAA, 0xE9FB, + 0x6FAB, 0xEA42, 0x6FAC, 0xE9FA, 0x6FAD, 0xE9E9, 0x6FAE, 0xE9F8, 0x6FAF, 0xEA44, 0x6FB0, 0xEA46, 0x6FB1, 0xBEFD, 0x6FB2, 0xEA45, + 0x6FB3, 0xBF44, 0x6FB4, 0xBF4A, 0x6FB6, 0xBF47, 0x6FB8, 0xE9FE, 0x6FB9, 0xBF46, 0x6FBA, 0xE9F9, 0x6FBC, 0xE9ED, 0x6FBD, 0xE9F2, + 0x6FBF, 0xE9FD, 0x6FC0, 0xBF45, 0x6FC1, 0xBF42, 0x6FC2, 0xBEFC, 0x6FC3, 0xBF40, 0x6FC4, 0xE9F1, 0x6FC6, 0xE5FD, 0x6FC7, 0xE9EC, + 0x6FC8, 0xE9EF, 0x6FC9, 0xEA41, 0x6FCA, 0xE9F4, 0x6FCB, 0xE9EA, 0x6FCC, 0xED4E, 0x6FCD, 0xEA43, 0x6FCE, 0xE9EE, 0x6FCF, 0xE9FC, + 0x6FD4, 0xED51, 0x6FD5, 0xC0E3, 0x6FD8, 0xC0D7, 0x6FDB, 0xC0DB, 0x6FDC, 0xED53, 0x6FDD, 0xED59, 0x6FDE, 0xED57, 0x6FDF, 0xC0D9, + 0x6FE0, 0xC0DA, 0x6FE1, 0xC0E1, 0x6FE2, 0xED5A, 0x6FE3, 0xED52, 0x6FE4, 0xC0DC, 0x6FE6, 0xED56, 0x6FE7, 0xED55, 0x6FE8, 0xED5B, + 0x6FE9, 0xC0E2, 0x6FEB, 0xC0DD, 0x6FEC, 0xC0E0, 0x6FED, 0xED54, 0x6FEE, 0xC0E4, 0x6FEF, 0xC0DE, 0x6FF0, 0xC0E5, 0x6FF1, 0xC0D8, + 0x6FF2, 0xED58, 0x6FF4, 0xED50, 0x6FF7, 0xEFF7, 0x6FFA, 0xC271, 0x6FFB, 0xEFF4, 0x6FFC, 0xEFF6, 0x6FFE, 0xC26F, 0x6FFF, 0xEFF2, + 0x7000, 0xEFF3, 0x7001, 0xEFEE, 0x7004, 0xE9F6, 0x7005, 0xEFEF, 0x7006, 0xC270, 0x7007, 0xEFEB, 0x7009, 0xC26D, 0x700A, 0xEFF8, + 0x700B, 0xC26E, 0x700C, 0xEFEC, 0x700D, 0xEFED, 0x700E, 0xEFF1, 0x700F, 0xC273, 0x7011, 0xC272, 0x7014, 0xEFF0, 0x7015, 0xC378, + 0x7016, 0xF25F, 0x7017, 0xF265, 0x7018, 0xC379, 0x7019, 0xF25C, 0x701A, 0xC376, 0x701B, 0xC373, 0x701C, 0xF267, 0x701D, 0xC377, + 0x701F, 0xC374, 0x7020, 0xF25E, 0x7021, 0xF261, 0x7022, 0xF262, 0x7023, 0xF263, 0x7024, 0xF266, 0x7026, 0xEFF5, 0x7027, 0xF25D, + 0x7028, 0xC375, 0x7029, 0xF264, 0x702A, 0xF268, 0x702B, 0xF260, 0x702F, 0xF45D, 0x7030, 0xC46A, 0x7031, 0xF460, 0x7032, 0xC46B, + 0x7033, 0xF468, 0x7034, 0xF45F, 0x7035, 0xF45C, 0x7037, 0xF45E, 0x7038, 0xF462, 0x7039, 0xF465, 0x703A, 0xF464, 0x703B, 0xF467, + 0x703C, 0xF45B, 0x703E, 0xC469, 0x703F, 0xF463, 0x7040, 0xF466, 0x7041, 0xF469, 0x7042, 0xF461, 0x7043, 0xF5D3, 0x7044, 0xF5D4, + 0x7045, 0xF5D8, 0x7046, 0xF5D9, 0x7048, 0xF5D6, 0x7049, 0xF5D7, 0x704A, 0xF5D5, 0x704C, 0xC4E9, 0x7051, 0xC578, 0x7052, 0xF6EB, + 0x7055, 0xF6E8, 0x7056, 0xF6E9, 0x7057, 0xF6EA, 0x7058, 0xC579, 0x705A, 0xF7E5, 0x705B, 0xF7E4, 0x705D, 0xF8AF, 0x705E, 0xC5F4, + 0x705F, 0xF8AD, 0x7060, 0xF8B0, 0x7061, 0xF8AE, 0x7062, 0xF8F5, 0x7063, 0xC657, 0x7064, 0xC665, 0x7065, 0xF9A3, 0x7066, 0xF96C, + 0x7068, 0xF9A2, 0x7069, 0xF9D0, 0x706A, 0xF9D1, 0x706B, 0xA4F5, 0x7070, 0xA6C7, 0x7071, 0xCA41, 0x7074, 0xCB5E, 0x7076, 0xA85F, + 0x7078, 0xA862, 0x707A, 0xCB5F, 0x707C, 0xA860, 0x707D, 0xA861, 0x7082, 0xCD58, 0x7083, 0xCD5A, 0x7084, 0xCD55, 0x7085, 0xCD52, + 0x7086, 0xCD54, 0x708A, 0xAAA4, 0x708E, 0xAAA2, 0x7091, 0xCD56, 0x7092, 0xAAA3, 0x7093, 0xCD53, 0x7094, 0xCD50, 0x7095, 0xAAA1, + 0x7096, 0xCD57, 0x7098, 0xCD51, 0x7099, 0xAAA5, 0x709A, 0xCD59, 0x709F, 0xCFAF, 0x70A1, 0xCFB3, 0x70A4, 0xACB7, 0x70A9, 0xCFB6, + 0x70AB, 0xACAF, 0x70AC, 0xACB2, 0x70AD, 0xACB4, 0x70AE, 0xACB6, 0x70AF, 0xACB3, 0x70B0, 0xCFB2, 0x70B1, 0xCFB1, 0x70B3, 0xACB1, + 0x70B4, 0xCFB4, 0x70B5, 0xCFB5, 0x70B7, 0xCFAE, 0x70B8, 0xACB5, 0x70BA, 0xACB0, 0x70BE, 0xCFB0, 0x70C5, 0xD277, 0x70C6, 0xD278, + 0x70C7, 0xD279, 0x70C8, 0xAF50, 0x70CA, 0xAF4C, 0x70CB, 0xD26E, 0x70CD, 0xD276, 0x70CE, 0xD27B, 0x70CF, 0xAF51, 0x70D1, 0xD26C, + 0x70D2, 0xD272, 0x70D3, 0xD26B, 0x70D4, 0xD275, 0x70D7, 0xD271, 0x70D8, 0xAF4D, 0x70D9, 0xAF4F, 0x70DA, 0xD27A, 0x70DC, 0xD26A, + 0x70DD, 0xD26D, 0x70DE, 0xD273, 0x70E0, 0xD274, 0x70E1, 0xD27C, 0x70E2, 0xD270, 0x70E4, 0xAF4E, 0x70EF, 0xB26D, 0x70F0, 0xD64E, + 0x70F3, 0xD650, 0x70F4, 0xD64C, 0x70F6, 0xD658, 0x70F7, 0xD64A, 0x70F8, 0xD657, 0x70F9, 0xB269, 0x70FA, 0xD648, 0x70FB, 0xDA5B, + 0x70FC, 0xD652, 0x70FD, 0xB26C, 0x70FF, 0xD653, 0x7100, 0xD656, 0x7102, 0xD65A, 0x7104, 0xD64F, 0x7106, 0xD654, 0x7109, 0xB26A, + 0x710A, 0xB26B, 0x710B, 0xD659, 0x710C, 0xD64D, 0x710D, 0xD649, 0x710E, 0xD65B, 0x7110, 0xD651, 0x7113, 0xD655, 0x7117, 0xD64B, + 0x7119, 0xB548, 0x711A, 0xB549, 0x711B, 0xDA65, 0x711C, 0xB54F, 0x711E, 0xDA59, 0x711F, 0xDA62, 0x7120, 0xDA58, 0x7121, 0xB54C, + 0x7122, 0xDA60, 0x7123, 0xDA5E, 0x7125, 0xDA5F, 0x7126, 0xB54A, 0x7128, 0xDA63, 0x712E, 0xDA5C, 0x712F, 0xDA5A, 0x7130, 0xB54B, + 0x7131, 0xDA5D, 0x7132, 0xDA61, 0x7136, 0xB54D, 0x713A, 0xDA64, 0x7141, 0xDE70, 0x7142, 0xDE77, 0x7143, 0xDE79, 0x7144, 0xDEA1, + 0x7146, 0xB7DA, 0x7147, 0xDE6B, 0x7149, 0xB7D2, 0x714B, 0xDE7A, 0x714C, 0xB7D7, 0x714D, 0xDEA2, 0x714E, 0xB7CE, 0x7150, 0xDE7D, + 0x7152, 0xDE6D, 0x7153, 0xDE7E, 0x7154, 0xDE6C, 0x7156, 0xB7DC, 0x7158, 0xDE78, 0x7159, 0xB7CF, 0x715A, 0xDEA3, 0x715C, 0xB7D4, + 0x715D, 0xDE71, 0x715E, 0xB7D9, 0x715F, 0xDE7C, 0x7160, 0xDE6F, 0x7161, 0xDE76, 0x7162, 0xDE72, 0x7163, 0xDE6E, 0x7164, 0xB7D1, + 0x7165, 0xB7D8, 0x7166, 0xB7D6, 0x7167, 0xB7D3, 0x7168, 0xB7DB, 0x7169, 0xB7D0, 0x716A, 0xDE75, 0x716C, 0xB7D5, 0x716E, 0xB54E, + 0x7170, 0xDE7B, 0x7172, 0xDE73, 0x7178, 0xDE74, 0x717B, 0xE2C1, 0x717D, 0xBAB4, 0x7180, 0xE2BD, 0x7181, 0xE2C3, 0x7182, 0xE2BF, + 0x7184, 0xBAB6, 0x7185, 0xE2BE, 0x7186, 0xE2C2, 0x7187, 0xE2BA, 0x7189, 0xE2BC, 0x718A, 0xBAB5, 0x718F, 0xE2C0, 0x7190, 0xE2BB, + 0x7192, 0xBAB7, 0x7194, 0xBAB2, 0x7197, 0xE2C4, 0x7199, 0xBAB3, 0x719A, 0xE667, 0x719B, 0xE664, 0x719C, 0xE670, 0x719D, 0xE66A, + 0x719E, 0xE66C, 0x719F, 0xBCF4, 0x71A0, 0xE666, 0x71A1, 0xE66E, 0x71A4, 0xE66D, 0x71A5, 0xE66B, 0x71A7, 0xE671, 0x71A8, 0xBCF7, + 0x71A9, 0xE668, 0x71AA, 0xE66F, 0x71AC, 0xBCF5, 0x71AF, 0xE663, 0x71B0, 0xE665, 0x71B1, 0xBCF6, 0x71B2, 0xE662, 0x71B3, 0xE672, + 0x71B5, 0xE669, 0x71B8, 0xEA4A, 0x71B9, 0xBF51, 0x71BC, 0xEA55, 0x71BD, 0xEA53, 0x71BE, 0xBF4B, 0x71BF, 0xEA49, 0x71C0, 0xEA4C, + 0x71C1, 0xEA4D, 0x71C2, 0xEA48, 0x71C3, 0xBF55, 0x71C4, 0xBF56, 0x71C5, 0xEA47, 0x71C6, 0xEA56, 0x71C7, 0xEA51, 0x71C8, 0xBF4F, + 0x71C9, 0xBF4C, 0x71CA, 0xEA50, 0x71CB, 0xEA4E, 0x71CE, 0xBF52, 0x71CF, 0xEA52, 0x71D0, 0xBF4D, 0x71D2, 0xBF4E, 0x71D4, 0xEA4F, + 0x71D5, 0xBF50, 0x71D6, 0xEA4B, 0x71D8, 0xEA54, 0x71D9, 0xBF53, 0x71DA, 0xEA57, 0x71DB, 0xEA58, 0x71DC, 0xBF54, 0x71DF, 0xC0E7, + 0x71E0, 0xC0EE, 0x71E1, 0xED5C, 0x71E2, 0xED62, 0x71E4, 0xED60, 0x71E5, 0xC0EA, 0x71E6, 0xC0E9, 0x71E7, 0xC0E6, 0x71E8, 0xED5E, + 0x71EC, 0xC0EC, 0x71ED, 0xC0EB, 0x71EE, 0xC0E8, 0x71F0, 0xED61, 0x71F1, 0xED5D, 0x71F2, 0xED5F, 0x71F4, 0xC0ED, 0x71F8, 0xC277, + 0x71F9, 0xEFFB, 0x71FB, 0xC274, 0x71FC, 0xC275, 0x71FD, 0xEFFD, 0x71FE, 0xC276, 0x71FF, 0xEFFA, 0x7201, 0xEFF9, 0x7202, 0xF26C, + 0x7203, 0xEFFC, 0x7205, 0xF26D, 0x7206, 0xC37A, 0x7207, 0xF26B, 0x720A, 0xF26A, 0x720C, 0xF269, 0x720D, 0xC37B, 0x7210, 0xC46C, + 0x7213, 0xF46A, 0x7214, 0xF46B, 0x7219, 0xF5DC, 0x721A, 0xF5DB, 0x721B, 0xC4EA, 0x721D, 0xF5DA, 0x721E, 0xF6EC, 0x721F, 0xF6ED, + 0x7222, 0xF7E6, 0x7223, 0xF8B1, 0x7226, 0xF8F6, 0x7227, 0xF9BC, 0x7228, 0xC679, 0x7229, 0xF9C6, 0x722A, 0xA4F6, 0x722C, 0xAAA6, + 0x722D, 0xAAA7, 0x7230, 0xACB8, 0x7235, 0xC0EF, 0x7236, 0xA4F7, 0x7238, 0xAAA8, 0x7239, 0xAF52, 0x723A, 0xB7DD, 0x723B, 0xA4F8, + 0x723D, 0xB26E, 0x723E, 0xBAB8, 0x723F, 0xC962, 0x7241, 0xCFB7, 0x7242, 0xD27D, 0x7244, 0xE2C5, 0x7246, 0xC0F0, 0x7247, 0xA4F9, + 0x7248, 0xAAA9, 0x7249, 0xCFB8, 0x724A, 0xCFB9, 0x724B, 0xDA66, 0x724C, 0xB550, 0x724F, 0xDEA4, 0x7252, 0xB7DE, 0x7253, 0xE2C6, + 0x7256, 0xBCF8, 0x7258, 0xC37C, 0x7259, 0xA4FA, 0x725A, 0xDA67, 0x725B, 0xA4FB, 0x725D, 0xA6C9, 0x725E, 0xCA42, 0x725F, 0xA6C8, + 0x7260, 0xA865, 0x7261, 0xA864, 0x7262, 0xA863, 0x7263, 0xCB60, 0x7267, 0xAAAA, 0x7269, 0xAAAB, 0x726A, 0xCD5B, 0x726C, 0xCFBA, + 0x726E, 0xCFBD, 0x726F, 0xACBA, 0x7270, 0xCFBB, 0x7272, 0xACB9, 0x7273, 0xCFBC, 0x7274, 0xACBB, 0x7276, 0xD2A2, 0x7277, 0xD2A1, + 0x7278, 0xD27E, 0x7279, 0xAF53, 0x727B, 0xD65D, 0x727C, 0xD65E, 0x727D, 0xB26F, 0x727E, 0xD65C, 0x727F, 0xD65F, 0x7280, 0xB552, + 0x7281, 0xB270, 0x7284, 0xB551, 0x7285, 0xDA6B, 0x7286, 0xDA6A, 0x7288, 0xDA68, 0x7289, 0xDA69, 0x728B, 0xDA6C, 0x728C, 0xDEA6, + 0x728D, 0xDEA5, 0x728E, 0xDEA9, 0x7290, 0xDEA8, 0x7291, 0xDEA7, 0x7292, 0xBAB9, 0x7293, 0xE2C9, 0x7295, 0xE2C8, 0x7296, 0xBABA, + 0x7297, 0xE2C7, 0x7298, 0xE673, 0x729A, 0xE674, 0x729B, 0xBCF9, 0x729D, 0xEA59, 0x729E, 0xEA5A, 0x72A1, 0xF272, 0x72A2, 0xC37D, + 0x72A3, 0xF271, 0x72A4, 0xF270, 0x72A5, 0xF26E, 0x72A6, 0xF26F, 0x72A7, 0xC4EB, 0x72A8, 0xF46C, 0x72A9, 0xF6EE, 0x72AA, 0xF8F7, + 0x72AC, 0xA4FC, 0x72AE, 0xC9A5, 0x72AF, 0xA5C7, 0x72B0, 0xC9A6, 0x72B4, 0xCA43, 0x72B5, 0xCA44, 0x72BA, 0xCB66, 0x72BD, 0xCB62, + 0x72BF, 0xCB61, 0x72C0, 0xAAAC, 0x72C1, 0xCB65, 0x72C2, 0xA867, 0x72C3, 0xCB63, 0x72C4, 0xA866, 0x72C5, 0xCB67, 0x72C6, 0xCB64, + 0x72C9, 0xCD5F, 0x72CA, 0xCFBE, 0x72CB, 0xCD5D, 0x72CC, 0xCD64, 0x72CE, 0xAAAD, 0x72D0, 0xAAB0, 0x72D1, 0xCD65, 0x72D2, 0xCD61, + 0x72D4, 0xCD62, 0x72D6, 0xCD5C, 0x72D7, 0xAAAF, 0x72D8, 0xCD5E, 0x72D9, 0xAAAE, 0x72DA, 0xCD63, 0x72DC, 0xCD60, 0x72DF, 0xCFC2, + 0x72E0, 0xACBD, 0x72E1, 0xACBE, 0x72E3, 0xCFC5, 0x72E4, 0xCFBF, 0x72E6, 0xCFC4, 0x72E8, 0xCFC0, 0x72E9, 0xACBC, 0x72EA, 0xCFC3, + 0x72EB, 0xCFC1, 0x72F3, 0xD2A8, 0x72F4, 0xD2A5, 0x72F6, 0xD2A7, 0x72F7, 0xAF58, 0x72F8, 0xAF57, 0x72F9, 0xAF55, 0x72FA, 0xD2A4, + 0x72FB, 0xD2A9, 0x72FC, 0xAF54, 0x72FD, 0xAF56, 0x72FE, 0xD2A6, 0x72FF, 0xD667, 0x7300, 0xD2A3, 0x7301, 0xD2AA, 0x7307, 0xD662, + 0x7308, 0xD666, 0x730A, 0xD665, 0x730B, 0xDA6E, 0x730C, 0xDA79, 0x730F, 0xD668, 0x7311, 0xD663, 0x7312, 0xDA6D, 0x7313, 0xB274, + 0x7316, 0xB273, 0x7317, 0xD661, 0x7318, 0xD664, 0x7319, 0xB275, 0x731B, 0xB272, 0x731C, 0xB271, 0x731D, 0xD660, 0x731E, 0xD669, + 0x7322, 0xDA70, 0x7323, 0xDA77, 0x7325, 0xB554, 0x7326, 0xDA76, 0x7327, 0xDA73, 0x7329, 0xB556, 0x732D, 0xDA75, 0x7330, 0xDA6F, + 0x7331, 0xDA71, 0x7332, 0xDA74, 0x7333, 0xDA72, 0x7334, 0xB555, 0x7335, 0xDA78, 0x7336, 0xB553, 0x7337, 0xB7DF, 0x733A, 0xDEAD, + 0x733B, 0xDEAC, 0x733C, 0xDEAA, 0x733E, 0xB7E2, 0x733F, 0xB7E1, 0x7340, 0xDEAE, 0x7342, 0xDEAB, 0x7343, 0xE2CA, 0x7344, 0xBABB, + 0x7345, 0xB7E0, 0x7349, 0xDEB0, 0x734A, 0xDEAF, 0x734C, 0xE2CD, 0x734D, 0xE2CB, 0x734E, 0xBCFA, 0x7350, 0xBABC, 0x7351, 0xE2CC, + 0x7352, 0xE676, 0x7357, 0xBCFB, 0x7358, 0xE675, 0x7359, 0xE67E, 0x735A, 0xE67D, 0x735B, 0xE67B, 0x735D, 0xE67A, 0x735E, 0xE677, + 0x735F, 0xE678, 0x7360, 0xE679, 0x7361, 0xE67C, 0x7362, 0xE6A1, 0x7365, 0xEA5F, 0x7366, 0xEA5C, 0x7367, 0xEA5D, 0x7368, 0xBF57, + 0x7369, 0xEA5B, 0x736A, 0xEA61, 0x736B, 0xEA60, 0x736C, 0xEA5E, 0x736E, 0xED64, 0x736F, 0xED65, 0x7370, 0xC0F1, 0x7372, 0xC0F2, + 0x7373, 0xED63, 0x7375, 0xC279, 0x7376, 0xEFFE, 0x7377, 0xC278, 0x7378, 0xC37E, 0x737A, 0xC3A1, 0x737B, 0xC46D, 0x737C, 0xF46E, + 0x737D, 0xF46D, 0x737E, 0xF5DD, 0x737F, 0xF6EF, 0x7380, 0xC57A, 0x7381, 0xF7E8, 0x7382, 0xF7E7, 0x7383, 0xF7E9, 0x7384, 0xA5C8, + 0x7385, 0xCFC6, 0x7386, 0xAF59, 0x7387, 0xB276, 0x7388, 0xD66A, 0x7389, 0xA5C9, 0x738A, 0xC9A7, 0x738B, 0xA4FD, 0x738E, 0xCA45, + 0x7392, 0xCB6C, 0x7393, 0xCB6A, 0x7394, 0xCB6B, 0x7395, 0xCB68, 0x7396, 0xA868, 0x7397, 0xCB69, 0x739D, 0xCD6D, 0x739F, 0xAAB3, + 0x73A0, 0xCD6B, 0x73A1, 0xCD67, 0x73A2, 0xCD6A, 0x73A4, 0xCD66, 0x73A5, 0xAAB5, 0x73A6, 0xCD69, 0x73A8, 0xAAB2, 0x73A9, 0xAAB1, + 0x73AB, 0xAAB4, 0x73AC, 0xCD6C, 0x73AD, 0xCD68, 0x73B2, 0xACC2, 0x73B3, 0xACC5, 0x73B4, 0xCFCE, 0x73B5, 0xCFCD, 0x73B6, 0xCFCC, + 0x73B7, 0xACBF, 0x73B8, 0xCFD5, 0x73B9, 0xCFCB, 0x73BB, 0xACC1, 0x73BC, 0xD2AF, 0x73BE, 0xCFD2, 0x73BF, 0xCFD0, 0x73C0, 0xACC4, + 0x73C2, 0xCFC8, 0x73C3, 0xCFD3, 0x73C5, 0xCFCA, 0x73C6, 0xCFD4, 0x73C7, 0xCFD1, 0x73C8, 0xCFC9, 0x73CA, 0xACC0, 0x73CB, 0xCFD6, + 0x73CC, 0xCFC7, 0x73CD, 0xACC3, 0x73D2, 0xD2B4, 0x73D3, 0xD2AB, 0x73D4, 0xD2B6, 0x73D6, 0xD2AE, 0x73D7, 0xD2B9, 0x73D8, 0xD2BA, + 0x73D9, 0xD2AC, 0x73DA, 0xD2B8, 0x73DB, 0xD2B5, 0x73DC, 0xD2B3, 0x73DD, 0xD2B7, 0x73DE, 0xAF5F, 0x73E0, 0xAF5D, 0x73E3, 0xD2B1, + 0x73E5, 0xD2AD, 0x73E7, 0xD2B0, 0x73E8, 0xD2BB, 0x73E9, 0xD2B2, 0x73EA, 0xAF5E, 0x73EB, 0xCFCF, 0x73ED, 0xAF5A, 0x73EE, 0xAF5C, + 0x73F4, 0xD678, 0x73F5, 0xD66D, 0x73F6, 0xD66B, 0x73F8, 0xD66C, 0x73FA, 0xD673, 0x73FC, 0xD674, 0x73FD, 0xD670, 0x73FE, 0xB27B, + 0x73FF, 0xD675, 0x7400, 0xD672, 0x7401, 0xD66F, 0x7403, 0xB279, 0x7404, 0xD66E, 0x7405, 0xB277, 0x7406, 0xB27A, 0x7407, 0xD671, + 0x7408, 0xD679, 0x7409, 0xAF5B, 0x740A, 0xB278, 0x740B, 0xD677, 0x740C, 0xD676, 0x740D, 0xB27C, 0x7416, 0xDA7E, 0x741A, 0xDAA1, + 0x741B, 0xB560, 0x741D, 0xDAA7, 0x7420, 0xDAA9, 0x7421, 0xDAA2, 0x7422, 0xB55A, 0x7423, 0xDAA6, 0x7424, 0xDAA5, 0x7425, 0xB55B, + 0x7426, 0xB561, 0x7428, 0xB562, 0x7429, 0xDAA8, 0x742A, 0xB558, 0x742B, 0xDA7D, 0x742C, 0xDA7B, 0x742D, 0xDAA3, 0x742E, 0xDA7A, + 0x742F, 0xB55F, 0x7430, 0xDA7C, 0x7431, 0xDAA4, 0x7432, 0xDAAA, 0x7433, 0xB559, 0x7434, 0xB55E, 0x7435, 0xB55C, 0x7436, 0xB55D, + 0x743A, 0xB557, 0x743F, 0xB7E9, 0x7440, 0xDEB7, 0x7441, 0xB7E8, 0x7442, 0xDEBB, 0x7444, 0xDEB1, 0x7446, 0xDEBC, 0x744A, 0xDEB2, + 0x744B, 0xDEB3, 0x744D, 0xDEBD, 0x744E, 0xDEBA, 0x744F, 0xDEB8, 0x7450, 0xDEB9, 0x7451, 0xDEB5, 0x7452, 0xDEB4, 0x7454, 0xDEBE, + 0x7455, 0xB7E5, 0x7457, 0xDEB6, 0x7459, 0xB7EA, 0x745A, 0xB7E4, 0x745B, 0xB7EB, 0x745C, 0xB7EC, 0x745E, 0xB7E7, 0x745F, 0xB7E6, + 0x7462, 0xE2CE, 0x7463, 0xBABE, 0x7464, 0xBABD, 0x7467, 0xE2D3, 0x7469, 0xBCFC, 0x746A, 0xBABF, 0x746D, 0xBAC1, 0x746E, 0xE2D4, + 0x746F, 0xB7E3, 0x7470, 0xBAC0, 0x7471, 0xE2D0, 0x7472, 0xE2D2, 0x7473, 0xE2CF, 0x7475, 0xE2D1, 0x7479, 0xE6AB, 0x747C, 0xE6AA, + 0x747D, 0xE6A7, 0x747E, 0xBD40, 0x747F, 0xEA62, 0x7480, 0xBD41, 0x7481, 0xE6A6, 0x7483, 0xBCFE, 0x7485, 0xE6A8, 0x7486, 0xE6A5, + 0x7487, 0xE6A2, 0x7488, 0xE6A9, 0x7489, 0xE6A3, 0x748A, 0xE6A4, 0x748B, 0xBCFD, 0x7490, 0xED69, 0x7492, 0xEA66, 0x7494, 0xEA65, + 0x7495, 0xEA67, 0x7497, 0xED66, 0x7498, 0xBF5A, 0x749A, 0xEA63, 0x749C, 0xBF58, 0x749E, 0xBF5C, 0x749F, 0xBF5B, 0x74A0, 0xEA64, + 0x74A1, 0xEA68, 0x74A3, 0xBF59, 0x74A5, 0xED6D, 0x74A6, 0xC0F5, 0x74A7, 0xC27A, 0x74A8, 0xC0F6, 0x74A9, 0xC0F3, 0x74AA, 0xED6A, + 0x74AB, 0xED68, 0x74AD, 0xED6B, 0x74AF, 0xED6E, 0x74B0, 0xC0F4, 0x74B1, 0xED6C, 0x74B2, 0xED67, 0x74B5, 0xF042, 0x74B6, 0xF045, + 0x74B7, 0xF275, 0x74B8, 0xF040, 0x74BA, 0xF46F, 0x74BB, 0xF046, 0x74BD, 0xC3A2, 0x74BE, 0xF044, 0x74BF, 0xC27B, 0x74C0, 0xF041, + 0x74C1, 0xF043, 0x74C2, 0xF047, 0x74C3, 0xF276, 0x74C5, 0xF274, 0x74CA, 0xC3A3, 0x74CB, 0xF273, 0x74CF, 0xC46E, 0x74D4, 0xC4ED, + 0x74D5, 0xF6F1, 0x74D6, 0xC4EC, 0x74D7, 0xF6F3, 0x74D8, 0xF6F0, 0x74D9, 0xF6F2, 0x74DA, 0xC5D0, 0x74DB, 0xF8B2, 0x74DC, 0xA5CA, + 0x74DD, 0xCD6E, 0x74DE, 0xD2BC, 0x74DF, 0xD2BD, 0x74E0, 0xB27D, 0x74E1, 0xDEBF, 0x74E2, 0xBF5D, 0x74E3, 0xC3A4, 0x74E4, 0xC57B, + 0x74E5, 0xF8B3, 0x74E6, 0xA5CB, 0x74E8, 0xCD6F, 0x74E9, 0xA260, 0x74EC, 0xCFD7, 0x74EE, 0xCFD8, 0x74F4, 0xD2BE, 0x74F5, 0xD2BF, + 0x74F6, 0xB27E, 0x74F7, 0xB2A1, 0x74FB, 0xDAAB, 0x74FD, 0xDEC2, 0x74FE, 0xDEC1, 0x74FF, 0xDEC0, 0x7500, 0xE2D5, 0x7502, 0xE2D6, + 0x7503, 0xE2D7, 0x7504, 0xBAC2, 0x7507, 0xE6AD, 0x7508, 0xE6AC, 0x750B, 0xEA69, 0x750C, 0xBF5E, 0x750D, 0xBF5F, 0x750F, 0xED72, + 0x7510, 0xED6F, 0x7511, 0xED70, 0x7512, 0xED71, 0x7513, 0xF049, 0x7514, 0xF048, 0x7515, 0xC27C, 0x7516, 0xF277, 0x7517, 0xF5DE, + 0x7518, 0xA5CC, 0x751A, 0xACC6, 0x751C, 0xB2A2, 0x751D, 0xDEC3, 0x751F, 0xA5CD, 0x7521, 0xD2C0, 0x7522, 0xB2A3, 0x7525, 0xB563, + 0x7526, 0xB564, 0x7528, 0xA5CE, 0x7529, 0xA5CF, 0x752A, 0xCA46, 0x752B, 0xA86A, 0x752C, 0xA869, 0x752D, 0xACC7, 0x752E, 0xCFD9, + 0x752F, 0xDAAC, 0x7530, 0xA5D0, 0x7531, 0xA5D1, 0x7532, 0xA5D2, 0x7533, 0xA5D3, 0x7537, 0xA86B, 0x7538, 0xA86C, 0x7539, 0xCB6E, + 0x753A, 0xCB6D, 0x753D, 0xAAB6, 0x753E, 0xCD72, 0x753F, 0xCD70, 0x7540, 0xCD71, 0x7547, 0xCFDA, 0x7548, 0xCFDB, 0x754B, 0xACCB, + 0x754C, 0xACC9, 0x754E, 0xACCA, 0x754F, 0xACC8, 0x7554, 0xAF60, 0x7559, 0xAF64, 0x755A, 0xAF63, 0x755B, 0xD2C1, 0x755C, 0xAF62, + 0x755D, 0xAF61, 0x755F, 0xD2C2, 0x7562, 0xB2A6, 0x7563, 0xD67B, 0x7564, 0xD67A, 0x7565, 0xB2A4, 0x7566, 0xB2A5, 0x756A, 0xB566, + 0x756B, 0xB565, 0x756C, 0xDAAE, 0x756F, 0xDAAD, 0x7570, 0xB2A7, 0x7576, 0xB7ED, 0x7577, 0xDEC5, 0x7578, 0xB7EE, 0x7579, 0xDEC4, + 0x757D, 0xE2D8, 0x757E, 0xE6AE, 0x757F, 0xBD42, 0x7580, 0xEA6A, 0x7584, 0xED73, 0x7586, 0xC3A6, 0x7587, 0xC3A5, 0x758A, 0xC57C, + 0x758B, 0xA5D4, 0x758C, 0xCD73, 0x758F, 0xB2A8, 0x7590, 0xE2D9, 0x7591, 0xBAC3, 0x7594, 0xCB6F, 0x7595, 0xCB70, 0x7598, 0xCD74, + 0x7599, 0xAAB8, 0x759A, 0xAAB9, 0x759D, 0xAAB7, 0x75A2, 0xACCF, 0x75A3, 0xACD0, 0x75A4, 0xACCD, 0x75A5, 0xACCE, 0x75A7, 0xCFDC, + 0x75AA, 0xCFDD, 0x75AB, 0xACCC, 0x75B0, 0xD2C3, 0x75B2, 0xAF68, 0x75B3, 0xAF69, 0x75B5, 0xB2AB, 0x75B6, 0xD2C9, 0x75B8, 0xAF6E, + 0x75B9, 0xAF6C, 0x75BA, 0xD2CA, 0x75BB, 0xD2C5, 0x75BC, 0xAF6B, 0x75BD, 0xAF6A, 0x75BE, 0xAF65, 0x75BF, 0xD2C8, 0x75C0, 0xD2C7, + 0x75C1, 0xD2C4, 0x75C2, 0xAF6D, 0x75C4, 0xD2C6, 0x75C5, 0xAF66, 0x75C7, 0xAF67, 0x75CA, 0xB2AC, 0x75CB, 0xD6A1, 0x75CC, 0xD6A2, + 0x75CD, 0xB2AD, 0x75CE, 0xD67C, 0x75CF, 0xD67E, 0x75D0, 0xD6A4, 0x75D1, 0xD6A3, 0x75D2, 0xD67D, 0x75D4, 0xB2A9, 0x75D5, 0xB2AA, + 0x75D7, 0xDAB6, 0x75D8, 0xB56B, 0x75D9, 0xB56A, 0x75DA, 0xDAB0, 0x75DB, 0xB568, 0x75DD, 0xDAB3, 0x75DE, 0xB56C, 0x75DF, 0xDAB4, + 0x75E0, 0xB56D, 0x75E1, 0xDAB1, 0x75E2, 0xB567, 0x75E3, 0xB569, 0x75E4, 0xDAB5, 0x75E6, 0xDAB2, 0x75E7, 0xDAAF, 0x75ED, 0xDED2, + 0x75EF, 0xDEC7, 0x75F0, 0xB7F0, 0x75F1, 0xB7F3, 0x75F2, 0xB7F2, 0x75F3, 0xB7F7, 0x75F4, 0xB7F6, 0x75F5, 0xDED3, 0x75F6, 0xDED1, + 0x75F7, 0xDECA, 0x75F8, 0xDECE, 0x75F9, 0xDECD, 0x75FA, 0xB7F4, 0x75FB, 0xDED0, 0x75FC, 0xDECC, 0x75FD, 0xDED4, 0x75FE, 0xDECB, + 0x75FF, 0xB7F5, 0x7600, 0xB7EF, 0x7601, 0xB7F1, 0x7603, 0xDEC9, 0x7608, 0xE2DB, 0x7609, 0xBAC7, 0x760A, 0xE2DF, 0x760B, 0xBAC6, + 0x760C, 0xE2DC, 0x760D, 0xBAC5, 0x760F, 0xDEC8, 0x7610, 0xDECF, 0x7611, 0xE2DE, 0x7613, 0xBAC8, 0x7614, 0xE2E0, 0x7615, 0xE2DD, + 0x7616, 0xE2DA, 0x7619, 0xE6B1, 0x761A, 0xE6B5, 0x761B, 0xE6B7, 0x761C, 0xE6B3, 0x761D, 0xE6B2, 0x761E, 0xE6B0, 0x761F, 0xBD45, + 0x7620, 0xBD43, 0x7621, 0xBD48, 0x7622, 0xBD49, 0x7623, 0xE6B4, 0x7624, 0xBD46, 0x7625, 0xE6AF, 0x7626, 0xBD47, 0x7627, 0xBAC4, + 0x7628, 0xE6B6, 0x7629, 0xBD44, 0x762D, 0xEA6C, 0x762F, 0xEA6B, 0x7630, 0xEA73, 0x7631, 0xEA6D, 0x7632, 0xEA72, 0x7633, 0xEA6F, + 0x7634, 0xBF60, 0x7635, 0xEA71, 0x7638, 0xBF61, 0x763A, 0xBF62, 0x763C, 0xEA70, 0x763D, 0xEA6E, 0x7642, 0xC0F8, 0x7643, 0xED74, + 0x7646, 0xC0F7, 0x7647, 0xED77, 0x7648, 0xED75, 0x7649, 0xED76, 0x764C, 0xC0F9, 0x7650, 0xF04D, 0x7652, 0xC2A1, 0x7653, 0xF04E, + 0x7656, 0xC27D, 0x7657, 0xF04F, 0x7658, 0xC27E, 0x7659, 0xF04C, 0x765A, 0xF050, 0x765C, 0xF04A, 0x765F, 0xC3A7, 0x7660, 0xF278, + 0x7661, 0xC3A8, 0x7662, 0xC46F, 0x7664, 0xF04B, 0x7665, 0xC470, 0x7669, 0xC4EE, 0x766A, 0xF5DF, 0x766C, 0xC57E, 0x766D, 0xF6F4, + 0x766E, 0xC57D, 0x7670, 0xF7EA, 0x7671, 0xC5F5, 0x7672, 0xC5F6, 0x7675, 0xF9CC, 0x7678, 0xACD1, 0x7679, 0xCFDE, 0x767B, 0xB56E, + 0x767C, 0xB56F, 0x767D, 0xA5D5, 0x767E, 0xA6CA, 0x767F, 0xCA47, 0x7681, 0xCB71, 0x7682, 0xA86D, 0x7684, 0xAABA, 0x7686, 0xACD2, + 0x7687, 0xACD3, 0x7688, 0xACD4, 0x7689, 0xD6A6, 0x768A, 0xD2CB, 0x768B, 0xAF6F, 0x768E, 0xB2AE, 0x768F, 0xD6A5, 0x7692, 0xDAB8, + 0x7693, 0xB571, 0x7695, 0xDAB7, 0x7696, 0xB570, 0x7699, 0xDED5, 0x769A, 0xBD4A, 0x769B, 0xE6BB, 0x769C, 0xE6B8, 0x769D, 0xE6B9, + 0x769E, 0xE6BA, 0x76A4, 0xED78, 0x76A6, 0xF051, 0x76AA, 0xF471, 0x76AB, 0xF470, 0x76AD, 0xF6F5, 0x76AE, 0xA5D6, 0x76AF, 0xCD75, + 0x76B0, 0xAF70, 0x76B4, 0xB572, 0x76B5, 0xDED6, 0x76B8, 0xE2E1, 0x76BA, 0xBD4B, 0x76BB, 0xEA74, 0x76BD, 0xF052, 0x76BE, 0xF472, + 0x76BF, 0xA5D7, 0x76C2, 0xAABB, 0x76C3, 0xACD7, 0x76C4, 0xCFDF, 0x76C5, 0xACD8, 0x76C6, 0xACD6, 0x76C8, 0xACD5, 0x76C9, 0xD2CC, + 0x76CA, 0xAF71, 0x76CD, 0xAF72, 0x76CE, 0xAF73, 0x76D2, 0xB2B0, 0x76D3, 0xD6A7, 0x76D4, 0xB2AF, 0x76DA, 0xDAB9, 0x76DB, 0xB2B1, + 0x76DC, 0xB573, 0x76DD, 0xDED7, 0x76DE, 0xB7F8, 0x76DF, 0xB7F9, 0x76E1, 0xBAC9, 0x76E3, 0xBACA, 0x76E4, 0xBD4C, 0x76E5, 0xBF64, + 0x76E6, 0xEA75, 0x76E7, 0xBF63, 0x76E9, 0xED79, 0x76EA, 0xC0FA, 0x76EC, 0xF053, 0x76ED, 0xF473, 0x76EE, 0xA5D8, 0x76EF, 0xA86E, + 0x76F0, 0xCD78, 0x76F1, 0xCD77, 0x76F2, 0xAABC, 0x76F3, 0xCD76, 0x76F4, 0xAABD, 0x76F5, 0xCD79, 0x76F7, 0xCFE5, 0x76F8, 0xACDB, + 0x76F9, 0xACDA, 0x76FA, 0xCFE7, 0x76FB, 0xCFE6, 0x76FC, 0xACDF, 0x76FE, 0xACDE, 0x7701, 0xACD9, 0x7703, 0xCFE1, 0x7704, 0xCFE2, + 0x7705, 0xCFE3, 0x7707, 0xACE0, 0x7708, 0xCFE0, 0x7709, 0xACDC, 0x770A, 0xCFE4, 0x770B, 0xACDD, 0x7710, 0xD2CF, 0x7711, 0xD2D3, + 0x7712, 0xD2D1, 0x7713, 0xD2D0, 0x7715, 0xD2D4, 0x7719, 0xD2D5, 0x771A, 0xD2D6, 0x771B, 0xD2CE, 0x771D, 0xD2CD, 0x771F, 0xAF75, + 0x7720, 0xAF76, 0x7722, 0xD2D7, 0x7723, 0xD2D2, 0x7725, 0xD6B0, 0x7727, 0xD2D8, 0x7728, 0xAF77, 0x7729, 0xAF74, 0x772D, 0xD6AA, + 0x772F, 0xD6A9, 0x7731, 0xD6AB, 0x7732, 0xD6AC, 0x7733, 0xD6AE, 0x7734, 0xD6AD, 0x7735, 0xD6B2, 0x7736, 0xB2B5, 0x7737, 0xB2B2, + 0x7738, 0xB2B6, 0x7739, 0xD6A8, 0x773A, 0xB2B7, 0x773B, 0xD6B1, 0x773C, 0xB2B4, 0x773D, 0xD6AF, 0x773E, 0xB2B3, 0x7744, 0xDABC, + 0x7745, 0xDABE, 0x7746, 0xDABA, 0x7747, 0xDABB, 0x774A, 0xDABF, 0x774B, 0xDAC1, 0x774C, 0xDAC2, 0x774D, 0xDABD, 0x774E, 0xDAC0, + 0x774F, 0xB574, 0x7752, 0xDEDB, 0x7754, 0xDEE0, 0x7755, 0xDED8, 0x7756, 0xDEDC, 0x7759, 0xDEE1, 0x775A, 0xDEDD, 0x775B, 0xB7FA, + 0x775C, 0xB843, 0x775E, 0xB7FD, 0x775F, 0xDED9, 0x7760, 0xDEDA, 0x7761, 0xBACE, 0x7762, 0xB846, 0x7763, 0xB7FE, 0x7765, 0xB844, + 0x7766, 0xB7FC, 0x7767, 0xDEDF, 0x7768, 0xB845, 0x7769, 0xDEDE, 0x776A, 0xB841, 0x776B, 0xB7FB, 0x776C, 0xB842, 0x776D, 0xDEE2, + 0x776E, 0xE2E6, 0x776F, 0xE2E8, 0x7779, 0xB840, 0x777C, 0xE2E3, 0x777D, 0xBACC, 0x777E, 0xE2E9, 0x777F, 0xBACD, 0x7780, 0xE2E7, + 0x7781, 0xE2E2, 0x7782, 0xE2E5, 0x7783, 0xE2EA, 0x7784, 0xBACB, 0x7785, 0xE2E4, 0x7787, 0xBD4E, 0x7788, 0xE6BF, 0x7789, 0xE6BE, + 0x778B, 0xBD51, 0x778C, 0xBD4F, 0x778D, 0xE6BC, 0x778E, 0xBD4D, 0x778F, 0xE6BD, 0x7791, 0xBD50, 0x7795, 0xEA7D, 0x7797, 0xEAA1, + 0x7799, 0xEA7E, 0x779A, 0xEA76, 0x779B, 0xEA7A, 0x779C, 0xEA79, 0x779D, 0xEA77, 0x779E, 0xBF66, 0x779F, 0xBF67, 0x77A0, 0xBF65, + 0x77A1, 0xEA78, 0x77A2, 0xEA7B, 0x77A3, 0xEA7C, 0x77A5, 0xBF68, 0x77A7, 0xC140, 0x77A8, 0xEDA3, 0x77AA, 0xC0FC, 0x77AB, 0xED7B, + 0x77AC, 0xC0FE, 0x77AD, 0xC141, 0x77B0, 0xC0FD, 0x77B1, 0xEDA2, 0x77B2, 0xED7C, 0x77B3, 0xC0FB, 0x77B4, 0xEDA1, 0x77B5, 0xED7A, + 0x77B6, 0xED7E, 0x77B7, 0xED7D, 0x77BA, 0xF055, 0x77BB, 0xC2A4, 0x77BC, 0xC2A5, 0x77BD, 0xC2A2, 0x77BF, 0xC2A3, 0x77C2, 0xF054, + 0x77C4, 0xF27B, 0x77C7, 0xC3A9, 0x77C9, 0xF279, 0x77CA, 0xF27A, 0x77CC, 0xF474, 0x77CD, 0xF477, 0x77CE, 0xF475, 0x77CF, 0xF476, + 0x77D0, 0xF5E0, 0x77D3, 0xC4EF, 0x77D4, 0xF7EB, 0x77D5, 0xF8B4, 0x77D7, 0xC5F7, 0x77D8, 0xF8F8, 0x77D9, 0xF8F9, 0x77DA, 0xC666, + 0x77DB, 0xA5D9, 0x77DC, 0xACE1, 0x77DE, 0xDAC3, 0x77E0, 0xDEE3, 0x77E2, 0xA5DA, 0x77E3, 0xA86F, 0x77E5, 0xAABE, 0x77E7, 0xCFE8, + 0x77E8, 0xCFE9, 0x77E9, 0xAF78, 0x77EC, 0xDAC4, 0x77ED, 0xB575, 0x77EE, 0xB847, 0x77EF, 0xC142, 0x77F0, 0xEDA4, 0x77F1, 0xF27C, + 0x77F2, 0xF478, 0x77F3, 0xA5DB, 0x77F7, 0xCDA1, 0x77F8, 0xCD7A, 0x77F9, 0xCD7C, 0x77FA, 0xCD7E, 0x77FB, 0xCD7D, 0x77FC, 0xCD7B, + 0x77FD, 0xAABF, 0x7802, 0xACE2, 0x7803, 0xCFF2, 0x7805, 0xCFED, 0x7806, 0xCFEA, 0x7809, 0xCFF1, 0x780C, 0xACE4, 0x780D, 0xACE5, + 0x780E, 0xCFF0, 0x780F, 0xCFEF, 0x7810, 0xCFEE, 0x7811, 0xCFEB, 0x7812, 0xCFEC, 0x7813, 0xCFF3, 0x7814, 0xACE3, 0x781D, 0xAF7C, + 0x781F, 0xAFA4, 0x7820, 0xAFA3, 0x7821, 0xD2E1, 0x7822, 0xD2DB, 0x7823, 0xD2D9, 0x7825, 0xAFA1, 0x7826, 0xD6B9, 0x7827, 0xAF7A, + 0x7828, 0xD2DE, 0x7829, 0xD2E2, 0x782A, 0xD2E4, 0x782B, 0xD2E0, 0x782C, 0xD2DA, 0x782D, 0xAFA2, 0x782E, 0xD2DF, 0x782F, 0xD2DD, + 0x7830, 0xAF79, 0x7831, 0xD2E5, 0x7832, 0xAFA5, 0x7833, 0xD2E3, 0x7834, 0xAF7D, 0x7835, 0xD2DC, 0x7837, 0xAF7E, 0x7838, 0xAF7B, + 0x7843, 0xB2B9, 0x7845, 0xD6BA, 0x7848, 0xD6B3, 0x7849, 0xD6B5, 0x784A, 0xD6B7, 0x784C, 0xD6B8, 0x784D, 0xD6B6, 0x784E, 0xB2BA, + 0x7850, 0xD6BB, 0x7852, 0xD6B4, 0x785C, 0xDAC8, 0x785D, 0xB576, 0x785E, 0xDAD0, 0x7860, 0xDAC5, 0x7862, 0xDAD1, 0x7864, 0xDAC6, + 0x7865, 0xDAC7, 0x7868, 0xDACF, 0x7869, 0xDACE, 0x786A, 0xDACB, 0x786B, 0xB2B8, 0x786C, 0xB577, 0x786D, 0xDAC9, 0x786E, 0xDACC, + 0x786F, 0xB578, 0x7870, 0xDACD, 0x7871, 0xDACA, 0x7879, 0xDEEE, 0x787B, 0xDEF2, 0x787C, 0xB84E, 0x787E, 0xE2F0, 0x787F, 0xB851, + 0x7880, 0xDEF0, 0x7881, 0xF9D6, 0x7883, 0xDEED, 0x7884, 0xDEE8, 0x7885, 0xDEEA, 0x7886, 0xDEEB, 0x7887, 0xDEE4, 0x7889, 0xB84D, + 0x788C, 0xB84C, 0x788E, 0xB848, 0x788F, 0xDEE7, 0x7891, 0xB84F, 0x7893, 0xB850, 0x7894, 0xDEE6, 0x7895, 0xDEE9, 0x7896, 0xDEF1, + 0x7897, 0xB84A, 0x7898, 0xB84B, 0x7899, 0xDEEF, 0x789A, 0xDEE5, 0x789E, 0xE2F2, 0x789F, 0xBAD0, 0x78A0, 0xE2F4, 0x78A1, 0xDEEC, + 0x78A2, 0xE2F6, 0x78A3, 0xBAD4, 0x78A4, 0xE2F7, 0x78A5, 0xE2F3, 0x78A7, 0xBAD1, 0x78A8, 0xE2EF, 0x78A9, 0xBAD3, 0x78AA, 0xE2EC, + 0x78AB, 0xE2F1, 0x78AC, 0xE2F5, 0x78AD, 0xE2EE, 0x78B0, 0xB849, 0x78B2, 0xE2EB, 0x78B3, 0xBAD2, 0x78B4, 0xE2ED, 0x78BA, 0xBD54, + 0x78BB, 0xE6C1, 0x78BC, 0xBD58, 0x78BE, 0xBD56, 0x78C1, 0xBACF, 0x78C3, 0xE6C8, 0x78C4, 0xE6C9, 0x78C5, 0xBD53, 0x78C8, 0xE6C7, + 0x78C9, 0xE6CA, 0x78CA, 0xBD55, 0x78CB, 0xBD52, 0x78CC, 0xE6C3, 0x78CD, 0xE6C0, 0x78CE, 0xE6C5, 0x78CF, 0xE6C2, 0x78D0, 0xBD59, + 0x78D1, 0xE6C4, 0x78D4, 0xE6C6, 0x78D5, 0xBD57, 0x78DA, 0xBF6A, 0x78DB, 0xEAA8, 0x78DD, 0xEAA2, 0x78DE, 0xEAA6, 0x78DF, 0xEAAC, + 0x78E0, 0xEAAD, 0x78E1, 0xEAA9, 0x78E2, 0xEAAA, 0x78E3, 0xEAA7, 0x78E5, 0xEAA4, 0x78E7, 0xBF6C, 0x78E8, 0xBF69, 0x78E9, 0xEAA3, + 0x78EA, 0xEAA5, 0x78EC, 0xBF6B, 0x78ED, 0xEAAB, 0x78EF, 0xC146, 0x78F2, 0xEDAA, 0x78F3, 0xEDA5, 0x78F4, 0xC145, 0x78F7, 0xC143, + 0x78F9, 0xEDAC, 0x78FA, 0xC144, 0x78FB, 0xEDA8, 0x78FC, 0xEDA9, 0x78FD, 0xEDA6, 0x78FE, 0xEDAD, 0x78FF, 0xF056, 0x7901, 0xC147, + 0x7902, 0xEDA7, 0x7904, 0xEDAE, 0x7905, 0xEDAB, 0x7909, 0xF05A, 0x790C, 0xF057, 0x790E, 0xC2A6, 0x7910, 0xF05B, 0x7911, 0xF05D, + 0x7912, 0xF05C, 0x7913, 0xF058, 0x7914, 0xF059, 0x7917, 0xF2A3, 0x7919, 0xC3AA, 0x791B, 0xF27E, 0x791C, 0xF2A2, 0x791D, 0xF27D, + 0x791E, 0xF2A4, 0x7921, 0xF2A1, 0x7923, 0xF47A, 0x7924, 0xF47D, 0x7925, 0xF479, 0x7926, 0xC471, 0x7927, 0xF47B, 0x7928, 0xF47C, + 0x7929, 0xF47E, 0x792A, 0xC472, 0x792B, 0xC474, 0x792C, 0xC473, 0x792D, 0xF5E1, 0x792F, 0xF5E3, 0x7931, 0xF5E2, 0x7935, 0xF6F6, + 0x7938, 0xF8B5, 0x7939, 0xF8FA, 0x793A, 0xA5DC, 0x793D, 0xCB72, 0x793E, 0xAAC0, 0x793F, 0xCDA3, 0x7940, 0xAAC1, 0x7941, 0xAAC2, + 0x7942, 0xCDA2, 0x7944, 0xCFF8, 0x7945, 0xCFF7, 0x7946, 0xACE6, 0x7947, 0xACE9, 0x7948, 0xACE8, 0x7949, 0xACE7, 0x794A, 0xCFF4, + 0x794B, 0xCFF6, 0x794C, 0xCFF5, 0x794F, 0xD2E8, 0x7950, 0xAFA7, 0x7951, 0xD2EC, 0x7952, 0xD2EB, 0x7953, 0xD2EA, 0x7954, 0xD2E6, + 0x7955, 0xAFA6, 0x7956, 0xAFAA, 0x7957, 0xAFAD, 0x795A, 0xAFAE, 0x795B, 0xD2E7, 0x795C, 0xD2E9, 0x795D, 0xAFAC, 0x795E, 0xAFAB, + 0x795F, 0xAFA9, 0x7960, 0xAFA8, 0x7961, 0xD6C2, 0x7963, 0xD6C0, 0x7964, 0xD6BC, 0x7965, 0xB2BB, 0x7967, 0xD6BD, 0x7968, 0xB2BC, + 0x7969, 0xD6BE, 0x796A, 0xD6BF, 0x796B, 0xD6C1, 0x796D, 0xB2BD, 0x7970, 0xDAD5, 0x7972, 0xDAD4, 0x7973, 0xDAD3, 0x7974, 0xDAD2, + 0x7979, 0xDEF6, 0x797A, 0xB852, 0x797C, 0xDEF3, 0x797D, 0xDEF5, 0x797F, 0xB853, 0x7981, 0xB854, 0x7982, 0xDEF4, 0x7988, 0xE341, + 0x798A, 0xE2F9, 0x798B, 0xE2FA, 0x798D, 0xBAD7, 0x798E, 0xBAD5, 0x798F, 0xBAD6, 0x7990, 0xE343, 0x7992, 0xE342, 0x7993, 0xE2FE, + 0x7994, 0xE2FD, 0x7995, 0xE2FC, 0x7996, 0xE2FB, 0x7997, 0xE340, 0x7998, 0xE2F8, 0x799A, 0xE6CB, 0x799B, 0xE6D0, 0x799C, 0xE6CE, + 0x79A0, 0xE6CD, 0x79A1, 0xE6CC, 0x79A2, 0xE6CF, 0x79A4, 0xEAAE, 0x79A6, 0xBF6D, 0x79A7, 0xC148, 0x79A8, 0xEDB0, 0x79AA, 0xC149, + 0x79AB, 0xEDAF, 0x79AC, 0xF05F, 0x79AD, 0xF05E, 0x79AE, 0xC2A7, 0x79B0, 0xF2A5, 0x79B1, 0xC3AB, 0x79B2, 0xF4A1, 0x79B3, 0xC5A1, + 0x79B4, 0xF6F7, 0x79B6, 0xF8B7, 0x79B7, 0xF8B6, 0x79B8, 0xC9A8, 0x79B9, 0xACEA, 0x79BA, 0xACEB, 0x79BB, 0xD6C3, 0x79BD, 0xB856, + 0x79BE, 0xA5DD, 0x79BF, 0xA872, 0x79C0, 0xA871, 0x79C1, 0xA870, 0x79C5, 0xCDA4, 0x79C8, 0xAAC4, 0x79C9, 0xAAC3, 0x79CB, 0xACEE, + 0x79CD, 0xCFFA, 0x79CE, 0xCFFD, 0x79CF, 0xCFFB, 0x79D1, 0xACEC, 0x79D2, 0xACED, 0x79D5, 0xCFF9, 0x79D6, 0xCFFC, 0x79D8, 0xAFB5, + 0x79DC, 0xD2F3, 0x79DD, 0xD2F5, 0x79DE, 0xD2F4, 0x79DF, 0xAFB2, 0x79E0, 0xD2EF, 0x79E3, 0xAFB0, 0x79E4, 0xAFAF, 0x79E6, 0xAFB3, + 0x79E7, 0xAFB1, 0x79E9, 0xAFB4, 0x79EA, 0xD2F2, 0x79EB, 0xD2ED, 0x79EC, 0xD2EE, 0x79ED, 0xD2F1, 0x79EE, 0xD2F0, 0x79F6, 0xD6C6, + 0x79F7, 0xD6C7, 0x79F8, 0xD6C5, 0x79FA, 0xD6C4, 0x79FB, 0xB2BE, 0x7A00, 0xB57D, 0x7A02, 0xDAD6, 0x7A03, 0xDAD8, 0x7A04, 0xDADA, + 0x7A05, 0xB57C, 0x7A08, 0xB57A, 0x7A0A, 0xDAD7, 0x7A0B, 0xB57B, 0x7A0C, 0xDAD9, 0x7A0D, 0xB579, 0x7A10, 0xDF41, 0x7A11, 0xDEF7, + 0x7A12, 0xDEFA, 0x7A13, 0xDEFE, 0x7A14, 0xB85A, 0x7A15, 0xDEFC, 0x7A17, 0xDEFB, 0x7A18, 0xDEF8, 0x7A19, 0xDEF9, 0x7A1A, 0xB858, + 0x7A1B, 0xDF40, 0x7A1C, 0xB857, 0x7A1E, 0xB85C, 0x7A1F, 0xB85B, 0x7A20, 0xB859, 0x7A22, 0xDEFD, 0x7A26, 0xE349, 0x7A28, 0xE348, + 0x7A2B, 0xE344, 0x7A2E, 0xBAD8, 0x7A2F, 0xE347, 0x7A30, 0xE346, 0x7A31, 0xBAD9, 0x7A37, 0xBD5E, 0x7A39, 0xE6D2, 0x7A3B, 0xBD5F, + 0x7A3C, 0xBD5B, 0x7A3D, 0xBD5D, 0x7A3F, 0xBD5A, 0x7A40, 0xBD5C, 0x7A44, 0xEAAF, 0x7A46, 0xBF70, 0x7A47, 0xEAB1, 0x7A48, 0xEAB0, + 0x7A4A, 0xE345, 0x7A4B, 0xBF72, 0x7A4C, 0xBF71, 0x7A4D, 0xBF6E, 0x7A4E, 0xBF6F, 0x7A54, 0xEDB5, 0x7A56, 0xEDB3, 0x7A57, 0xC14A, + 0x7A58, 0xEDB4, 0x7A5A, 0xEDB6, 0x7A5B, 0xEDB2, 0x7A5C, 0xEDB1, 0x7A5F, 0xF060, 0x7A60, 0xC2AA, 0x7A61, 0xC2A8, 0x7A62, 0xC2A9, + 0x7A67, 0xF2A6, 0x7A68, 0xF2A7, 0x7A69, 0xC3AD, 0x7A6B, 0xC3AC, 0x7A6C, 0xF4A3, 0x7A6D, 0xF4A4, 0x7A6E, 0xF4A2, 0x7A70, 0xF6F8, + 0x7A71, 0xF6F9, 0x7A74, 0xA5DE, 0x7A75, 0xCA48, 0x7A76, 0xA873, 0x7A78, 0xCDA5, 0x7A79, 0xAAC6, 0x7A7A, 0xAAC5, 0x7A7B, 0xCDA6, + 0x7A7E, 0xD040, 0x7A7F, 0xACEF, 0x7A80, 0xCFFE, 0x7A81, 0xACF0, 0x7A84, 0xAFB6, 0x7A85, 0xD2F8, 0x7A86, 0xD2F6, 0x7A87, 0xD2FC, + 0x7A88, 0xAFB7, 0x7A89, 0xD2F7, 0x7A8A, 0xD2FB, 0x7A8B, 0xD2F9, 0x7A8C, 0xD2FA, 0x7A8F, 0xD6C8, 0x7A90, 0xD6CA, 0x7A92, 0xB2BF, + 0x7A94, 0xD6C9, 0x7A95, 0xB2C0, 0x7A96, 0xB5A2, 0x7A97, 0xB5A1, 0x7A98, 0xB57E, 0x7A99, 0xDADB, 0x7A9E, 0xDF44, 0x7A9F, 0xB85D, + 0x7AA0, 0xB85E, 0x7AA2, 0xDF43, 0x7AA3, 0xDF42, 0x7AA8, 0xE34A, 0x7AA9, 0xBADB, 0x7AAA, 0xBADA, 0x7AAB, 0xE34B, 0x7AAC, 0xE34C, + 0x7AAE, 0xBD61, 0x7AAF, 0xBD60, 0x7AB1, 0xEAB5, 0x7AB2, 0xE6D3, 0x7AB3, 0xE6D5, 0x7AB4, 0xE6D4, 0x7AB5, 0xEAB4, 0x7AB6, 0xEAB2, + 0x7AB7, 0xEAB6, 0x7AB8, 0xEAB3, 0x7ABA, 0xBF73, 0x7ABE, 0xEDB7, 0x7ABF, 0xC14B, 0x7AC0, 0xEDB8, 0x7AC1, 0xEDB9, 0x7AC4, 0xC2AB, + 0x7AC5, 0xC2AC, 0x7AC7, 0xC475, 0x7ACA, 0xC5D1, 0x7ACB, 0xA5DF, 0x7AD1, 0xD041, 0x7AD8, 0xD2FD, 0x7AD9, 0xAFB8, 0x7ADF, 0xB3BA, + 0x7AE0, 0xB3B9, 0x7AE3, 0xB5A4, 0x7AE4, 0xDADD, 0x7AE5, 0xB5A3, 0x7AE6, 0xDADC, 0x7AEB, 0xDF45, 0x7AED, 0xBADC, 0x7AEE, 0xE34D, + 0x7AEF, 0xBADD, 0x7AF6, 0xC476, 0x7AF7, 0xF4A5, 0x7AF9, 0xA6CB, 0x7AFA, 0xAAC7, 0x7AFB, 0xCDA7, 0x7AFD, 0xACF2, 0x7AFF, 0xACF1, + 0x7B00, 0xD042, 0x7B01, 0xD043, 0x7B04, 0xD340, 0x7B05, 0xD342, 0x7B06, 0xAFB9, 0x7B08, 0xD344, 0x7B09, 0xD347, 0x7B0A, 0xD345, + 0x7B0E, 0xD346, 0x7B0F, 0xD343, 0x7B10, 0xD2FE, 0x7B11, 0xAFBA, 0x7B12, 0xD348, 0x7B13, 0xD341, 0x7B18, 0xD6D3, 0x7B19, 0xB2C6, + 0x7B1A, 0xD6DC, 0x7B1B, 0xB2C3, 0x7B1D, 0xD6D5, 0x7B1E, 0xB2C7, 0x7B20, 0xB2C1, 0x7B22, 0xD6D0, 0x7B23, 0xD6DD, 0x7B24, 0xD6D1, + 0x7B25, 0xD6CE, 0x7B26, 0xB2C5, 0x7B28, 0xB2C2, 0x7B2A, 0xD6D4, 0x7B2B, 0xD6D7, 0x7B2C, 0xB2C4, 0x7B2D, 0xD6D8, 0x7B2E, 0xB2C8, + 0x7B2F, 0xD6D9, 0x7B30, 0xD6CF, 0x7B31, 0xD6D6, 0x7B32, 0xD6DA, 0x7B33, 0xD6D2, 0x7B34, 0xD6CD, 0x7B35, 0xD6CB, 0x7B38, 0xD6DB, + 0x7B3B, 0xDADF, 0x7B40, 0xDAE4, 0x7B44, 0xDAE0, 0x7B45, 0xDAE6, 0x7B46, 0xB5A7, 0x7B47, 0xD6CC, 0x7B48, 0xDAE1, 0x7B49, 0xB5A5, + 0x7B4A, 0xDADE, 0x7B4B, 0xB5AC, 0x7B4C, 0xDAE2, 0x7B4D, 0xB5AB, 0x7B4E, 0xDAE3, 0x7B4F, 0xB5AD, 0x7B50, 0xB5A8, 0x7B51, 0xB5AE, + 0x7B52, 0xB5A9, 0x7B54, 0xB5AA, 0x7B56, 0xB5A6, 0x7B58, 0xDAE5, 0x7B60, 0xB861, 0x7B61, 0xDF50, 0x7B63, 0xDF53, 0x7B64, 0xDF47, + 0x7B65, 0xDF4C, 0x7B66, 0xDF46, 0x7B67, 0xB863, 0x7B69, 0xDF4A, 0x7B6D, 0xDF48, 0x7B6E, 0xB862, 0x7B70, 0xDF4F, 0x7B71, 0xDF4E, + 0x7B72, 0xDF4B, 0x7B73, 0xDF4D, 0x7B74, 0xDF49, 0x7B75, 0xBAE1, 0x7B76, 0xDF52, 0x7B77, 0xB85F, 0x7B78, 0xDF51, 0x7B82, 0xE35D, + 0x7B84, 0xBAE8, 0x7B85, 0xE358, 0x7B87, 0xBAE7, 0x7B88, 0xE34E, 0x7B8A, 0xE350, 0x7B8B, 0xBAE0, 0x7B8C, 0xE355, 0x7B8D, 0xE354, + 0x7B8E, 0xE357, 0x7B8F, 0xBAE5, 0x7B90, 0xE352, 0x7B91, 0xE351, 0x7B94, 0xBAE4, 0x7B95, 0xBADF, 0x7B96, 0xE353, 0x7B97, 0xBAE2, + 0x7B98, 0xE359, 0x7B99, 0xE35B, 0x7B9B, 0xE356, 0x7B9C, 0xE34F, 0x7B9D, 0xBAE3, 0x7BA0, 0xBD69, 0x7BA1, 0xBADE, 0x7BA4, 0xE35C, + 0x7BAC, 0xE6D9, 0x7BAD, 0xBD62, 0x7BAF, 0xE6DB, 0x7BB1, 0xBD63, 0x7BB4, 0xBD65, 0x7BB5, 0xE6DE, 0x7BB7, 0xE6D6, 0x7BB8, 0xBAE6, + 0x7BB9, 0xE6DC, 0x7BBE, 0xE6D8, 0x7BC0, 0xB860, 0x7BC1, 0xBD68, 0x7BC4, 0xBD64, 0x7BC6, 0xBD66, 0x7BC7, 0xBD67, 0x7BC9, 0xBF76, + 0x7BCA, 0xE6DD, 0x7BCB, 0xE6D7, 0x7BCC, 0xBD6A, 0x7BCE, 0xE6DA, 0x7BD4, 0xEAC0, 0x7BD5, 0xEABB, 0x7BD8, 0xEAC5, 0x7BD9, 0xBF74, + 0x7BDA, 0xEABD, 0x7BDB, 0xBF78, 0x7BDC, 0xEAC3, 0x7BDD, 0xEABA, 0x7BDE, 0xEAB7, 0x7BDF, 0xEAC6, 0x7BE0, 0xC151, 0x7BE1, 0xBF79, + 0x7BE2, 0xEAC2, 0x7BE3, 0xEAB8, 0x7BE4, 0xBF77, 0x7BE5, 0xEABC, 0x7BE6, 0xBF7B, 0x7BE7, 0xEAB9, 0x7BE8, 0xEABE, 0x7BE9, 0xBF7A, + 0x7BEA, 0xEAC1, 0x7BEB, 0xEAC4, 0x7BF0, 0xEDCB, 0x7BF1, 0xEDCC, 0x7BF2, 0xEDBC, 0x7BF3, 0xEDC3, 0x7BF4, 0xEDC1, 0x7BF7, 0xC14F, + 0x7BF8, 0xEDC8, 0x7BF9, 0xEABF, 0x7BFB, 0xEDBF, 0x7BFD, 0xEDC9, 0x7BFE, 0xC14E, 0x7BFF, 0xEDBE, 0x7C00, 0xEDBD, 0x7C01, 0xEDC7, + 0x7C02, 0xEDC4, 0x7C03, 0xEDC6, 0x7C05, 0xEDBA, 0x7C06, 0xEDCA, 0x7C07, 0xC14C, 0x7C09, 0xEDC5, 0x7C0A, 0xEDCE, 0x7C0B, 0xEDC2, + 0x7C0C, 0xC150, 0x7C0D, 0xC14D, 0x7C0E, 0xEDC0, 0x7C0F, 0xEDBB, 0x7C10, 0xEDCD, 0x7C11, 0xBF75, 0x7C19, 0xF063, 0x7C1C, 0xF061, + 0x7C1D, 0xF067, 0x7C1E, 0xC2B0, 0x7C1F, 0xF065, 0x7C20, 0xF064, 0x7C21, 0xC2B2, 0x7C22, 0xF06A, 0x7C23, 0xC2B1, 0x7C25, 0xF06B, + 0x7C26, 0xF068, 0x7C27, 0xC2AE, 0x7C28, 0xF069, 0x7C29, 0xF062, 0x7C2A, 0xC2AF, 0x7C2B, 0xC2AD, 0x7C2C, 0xF2AB, 0x7C2D, 0xF066, + 0x7C30, 0xF06C, 0x7C33, 0xF2A8, 0x7C37, 0xC3B2, 0x7C38, 0xC3B0, 0x7C39, 0xF2AA, 0x7C3B, 0xF2AC, 0x7C3C, 0xF2A9, 0x7C3D, 0xC3B1, + 0x7C3E, 0xC3AE, 0x7C3F, 0xC3AF, 0x7C40, 0xC3B3, 0x7C43, 0xC478, 0x7C45, 0xF4AA, 0x7C47, 0xF4A9, 0x7C48, 0xF4A7, 0x7C49, 0xF4A6, + 0x7C4A, 0xF4A8, 0x7C4C, 0xC477, 0x7C4D, 0xC479, 0x7C50, 0xC4F0, 0x7C53, 0xF5E5, 0x7C54, 0xF5E4, 0x7C57, 0xF6FA, 0x7C59, 0xF6FC, + 0x7C5A, 0xF6FE, 0x7C5B, 0xF6FD, 0x7C5C, 0xF6FB, 0x7C5F, 0xC5A3, 0x7C60, 0xC5A2, 0x7C63, 0xC5D3, 0x7C64, 0xC5D2, 0x7C65, 0xC5D4, + 0x7C66, 0xF7ED, 0x7C67, 0xF7EC, 0x7C69, 0xF8FB, 0x7C6A, 0xF8B8, 0x7C6B, 0xF8FC, 0x7C6C, 0xC658, 0x7C6E, 0xC659, 0x7C6F, 0xF96D, + 0x7C72, 0xC67E, 0x7C73, 0xA6CC, 0x7C75, 0xCDA8, 0x7C78, 0xD045, 0x7C79, 0xD046, 0x7C7A, 0xD044, 0x7C7D, 0xACF3, 0x7C7F, 0xD047, + 0x7C80, 0xD048, 0x7C81, 0xD049, 0x7C84, 0xD349, 0x7C85, 0xD34F, 0x7C88, 0xD34D, 0x7C89, 0xAFBB, 0x7C8A, 0xD34B, 0x7C8C, 0xD34C, + 0x7C8D, 0xD34E, 0x7C91, 0xD34A, 0x7C92, 0xB2C9, 0x7C94, 0xD6DE, 0x7C95, 0xB2CB, 0x7C96, 0xD6E0, 0x7C97, 0xB2CA, 0x7C98, 0xD6DF, + 0x7C9E, 0xDAE8, 0x7C9F, 0xB5AF, 0x7CA1, 0xDAEA, 0x7CA2, 0xDAE7, 0x7CA3, 0xD6E1, 0x7CA5, 0xB5B0, 0x7CA7, 0xF9DB, 0x7CA8, 0xDAE9, + 0x7CAF, 0xDF56, 0x7CB1, 0xB864, 0x7CB2, 0xDF54, 0x7CB3, 0xB865, 0x7CB4, 0xDF55, 0x7CB5, 0xB866, 0x7CB9, 0xBAE9, 0x7CBA, 0xE361, + 0x7CBB, 0xE35E, 0x7CBC, 0xE360, 0x7CBD, 0xBAEA, 0x7CBE, 0xBAEB, 0x7CBF, 0xE35F, 0x7CC5, 0xE6DF, 0x7CC8, 0xE6E0, 0x7CCA, 0xBD6B, + 0x7CCB, 0xE6E2, 0x7CCC, 0xE6E1, 0x7CCE, 0xA261, 0x7CD0, 0xEACA, 0x7CD1, 0xEACB, 0x7CD2, 0xEAC7, 0x7CD4, 0xEAC8, 0x7CD5, 0xBF7C, + 0x7CD6, 0xBF7D, 0x7CD7, 0xEAC9, 0x7CD9, 0xC157, 0x7CDC, 0xC153, 0x7CDD, 0xC158, 0x7CDE, 0xC154, 0x7CDF, 0xC156, 0x7CE0, 0xC152, + 0x7CE2, 0xC155, 0x7CE7, 0xC2B3, 0x7CE8, 0xEDCF, 0x7CEA, 0xF2AE, 0x7CEC, 0xF2AD, 0x7CEE, 0xF4AB, 0x7CEF, 0xC47A, 0x7CF0, 0xC47B, + 0x7CF1, 0xF741, 0x7CF2, 0xF5E6, 0x7CF4, 0xF740, 0x7CF6, 0xF8FD, 0x7CF7, 0xF9A4, 0x7CF8, 0xA6CD, 0x7CFB, 0xA874, 0x7CFD, 0xCDA9, + 0x7CFE, 0xAAC8, 0x7D00, 0xACF6, 0x7D01, 0xD04C, 0x7D02, 0xACF4, 0x7D03, 0xD04A, 0x7D04, 0xACF9, 0x7D05, 0xACF5, 0x7D06, 0xACFA, + 0x7D07, 0xACF8, 0x7D08, 0xD04B, 0x7D09, 0xACF7, 0x7D0A, 0xAFBF, 0x7D0B, 0xAFBE, 0x7D0C, 0xD35A, 0x7D0D, 0xAFC7, 0x7D0E, 0xD353, + 0x7D0F, 0xD359, 0x7D10, 0xAFC3, 0x7D11, 0xD352, 0x7D12, 0xD358, 0x7D13, 0xD356, 0x7D14, 0xAFC2, 0x7D15, 0xAFC4, 0x7D16, 0xD355, + 0x7D17, 0xAFBD, 0x7D18, 0xD354, 0x7D19, 0xAFC8, 0x7D1A, 0xAFC5, 0x7D1B, 0xAFC9, 0x7D1C, 0xAFC6, 0x7D1D, 0xD351, 0x7D1E, 0xD350, + 0x7D1F, 0xD357, 0x7D20, 0xAFC0, 0x7D21, 0xAFBC, 0x7D22, 0xAFC1, 0x7D28, 0xD6F0, 0x7D29, 0xD6E9, 0x7D2B, 0xB5B5, 0x7D2C, 0xD6E8, + 0x7D2E, 0xB2CF, 0x7D2F, 0xB2D6, 0x7D30, 0xB2D3, 0x7D31, 0xB2D9, 0x7D32, 0xB2D8, 0x7D33, 0xB2D4, 0x7D35, 0xD6E2, 0x7D36, 0xD6E5, + 0x7D38, 0xD6E4, 0x7D39, 0xB2D0, 0x7D3A, 0xD6E6, 0x7D3B, 0xD6EF, 0x7D3C, 0xB2D1, 0x7D3D, 0xD6E3, 0x7D3E, 0xD6EC, 0x7D3F, 0xD6ED, + 0x7D40, 0xB2D2, 0x7D41, 0xD6EA, 0x7D42, 0xB2D7, 0x7D43, 0xB2CD, 0x7D44, 0xB2D5, 0x7D45, 0xD6E7, 0x7D46, 0xB2CC, 0x7D47, 0xD6EB, + 0x7D4A, 0xD6EE, 0x7D4E, 0xDAFB, 0x7D4F, 0xDAF2, 0x7D50, 0xB5B2, 0x7D51, 0xDAF9, 0x7D52, 0xDAF6, 0x7D53, 0xDAEE, 0x7D54, 0xDAF7, + 0x7D55, 0xB5B4, 0x7D56, 0xDAEF, 0x7D58, 0xDAEB, 0x7D5B, 0xB86C, 0x7D5C, 0xDAF4, 0x7D5E, 0xB5B1, 0x7D5F, 0xDAFA, 0x7D61, 0xB5B8, + 0x7D62, 0xB5BA, 0x7D63, 0xDAED, 0x7D66, 0xB5B9, 0x7D67, 0xDAF0, 0x7D68, 0xB5B3, 0x7D69, 0xDAF8, 0x7D6A, 0xDAF1, 0x7D6B, 0xDAF5, + 0x7D6D, 0xDAF3, 0x7D6E, 0xB5B6, 0x7D6F, 0xDAEC, 0x7D70, 0xB5BB, 0x7D71, 0xB2CE, 0x7D72, 0xB5B7, 0x7D73, 0xB5BC, 0x7D79, 0xB868, + 0x7D7A, 0xDF5D, 0x7D7B, 0xDF5F, 0x7D7C, 0xDF61, 0x7D7D, 0xDF65, 0x7D7F, 0xDF5B, 0x7D80, 0xDF59, 0x7D81, 0xB86A, 0x7D83, 0xDF60, + 0x7D84, 0xDF64, 0x7D85, 0xDF5C, 0x7D86, 0xDF58, 0x7D88, 0xDF57, 0x7D8C, 0xDF62, 0x7D8D, 0xDF5A, 0x7D8E, 0xDF5E, 0x7D8F, 0xB86B, + 0x7D91, 0xB869, 0x7D92, 0xDF66, 0x7D93, 0xB867, 0x7D94, 0xDF63, 0x7D96, 0xE372, 0x7D9C, 0xBAEE, 0x7D9D, 0xE36A, 0x7D9E, 0xBD78, + 0x7D9F, 0xE374, 0x7DA0, 0xBAF1, 0x7DA1, 0xE378, 0x7DA2, 0xBAF7, 0x7DA3, 0xE365, 0x7DA6, 0xE375, 0x7DA7, 0xE362, 0x7DA9, 0xE377, + 0x7DAA, 0xE366, 0x7DAC, 0xBAFE, 0x7DAD, 0xBAFB, 0x7DAE, 0xE376, 0x7DAF, 0xE370, 0x7DB0, 0xBAED, 0x7DB1, 0xBAF5, 0x7DB2, 0xBAF4, + 0x7DB4, 0xBAF3, 0x7DB5, 0xBAF9, 0x7DB7, 0xE363, 0x7DB8, 0xBAFA, 0x7DB9, 0xE371, 0x7DBA, 0xBAF6, 0x7DBB, 0xBAEC, 0x7DBC, 0xE373, + 0x7DBD, 0xBAEF, 0x7DBE, 0xBAF0, 0x7DBF, 0xBAF8, 0x7DC0, 0xE368, 0x7DC1, 0xE367, 0x7DC2, 0xE364, 0x7DC4, 0xE36C, 0x7DC5, 0xE369, + 0x7DC6, 0xE36D, 0x7DC7, 0xBAFD, 0x7DC9, 0xE379, 0x7DCA, 0xBAF2, 0x7DCB, 0xE36E, 0x7DCC, 0xE36F, 0x7DCE, 0xE36B, 0x7DD2, 0xBAFC, + 0x7DD7, 0xE6E7, 0x7DD8, 0xBD70, 0x7DD9, 0xBD79, 0x7DDA, 0xBD75, 0x7DDB, 0xE6E4, 0x7DDD, 0xBD72, 0x7DDE, 0xBD76, 0x7DDF, 0xE6F0, + 0x7DE0, 0xBD6C, 0x7DE1, 0xE6E8, 0x7DE3, 0xBD74, 0x7DE6, 0xE6EB, 0x7DE7, 0xE6E6, 0x7DE8, 0xBD73, 0x7DE9, 0xBD77, 0x7DEA, 0xE6E5, + 0x7DEC, 0xBD71, 0x7DEE, 0xE6EF, 0x7DEF, 0xBD6E, 0x7DF0, 0xE6EE, 0x7DF1, 0xE6ED, 0x7DF2, 0xBD7A, 0x7DF3, 0xE572, 0x7DF4, 0xBD6D, + 0x7DF6, 0xE6EC, 0x7DF7, 0xE6E3, 0x7DF9, 0xBD7B, 0x7DFA, 0xE6EA, 0x7DFB, 0xBD6F, 0x7E03, 0xE6E9, 0x7E08, 0xBFA2, 0x7E09, 0xBFA7, + 0x7E0A, 0xBF7E, 0x7E0B, 0xEAD8, 0x7E0C, 0xEACF, 0x7E0D, 0xEADB, 0x7E0E, 0xEAD3, 0x7E0F, 0xEAD9, 0x7E10, 0xBFA8, 0x7E11, 0xBFA1, + 0x7E12, 0xEACC, 0x7E13, 0xEAD2, 0x7E14, 0xEADC, 0x7E15, 0xEAD5, 0x7E16, 0xEADA, 0x7E17, 0xEACE, 0x7E1A, 0xEAD6, 0x7E1B, 0xBFA3, + 0x7E1C, 0xEAD4, 0x7E1D, 0xBFA6, 0x7E1E, 0xBFA5, 0x7E1F, 0xEAD0, 0x7E20, 0xEAD1, 0x7E21, 0xEACD, 0x7E22, 0xEAD7, 0x7E23, 0xBFA4, + 0x7E24, 0xEADE, 0x7E25, 0xEADD, 0x7E29, 0xEDDA, 0x7E2A, 0xEDD6, 0x7E2B, 0xC15F, 0x7E2D, 0xEDD0, 0x7E2E, 0xC159, 0x7E2F, 0xC169, + 0x7E30, 0xEDDC, 0x7E31, 0xC161, 0x7E32, 0xC15D, 0x7E33, 0xEDD3, 0x7E34, 0xC164, 0x7E35, 0xC167, 0x7E36, 0xEDDE, 0x7E37, 0xC15C, + 0x7E38, 0xEDD5, 0x7E39, 0xC165, 0x7E3A, 0xEDE0, 0x7E3B, 0xEDDD, 0x7E3C, 0xEDD1, 0x7E3D, 0xC160, 0x7E3E, 0xC15A, 0x7E3F, 0xC168, + 0x7E40, 0xEDD8, 0x7E41, 0xC163, 0x7E42, 0xEDD2, 0x7E43, 0xC15E, 0x7E44, 0xEDDF, 0x7E45, 0xC162, 0x7E46, 0xC15B, 0x7E47, 0xEDD9, + 0x7E48, 0xC166, 0x7E49, 0xEDD7, 0x7E4C, 0xEDDB, 0x7E50, 0xF06E, 0x7E51, 0xF074, 0x7E52, 0xC2B9, 0x7E53, 0xF077, 0x7E54, 0xC2B4, + 0x7E55, 0xC2B5, 0x7E56, 0xF06F, 0x7E57, 0xF076, 0x7E58, 0xF071, 0x7E59, 0xC2BA, 0x7E5A, 0xC2B7, 0x7E5C, 0xF06D, 0x7E5E, 0xC2B6, + 0x7E5F, 0xF073, 0x7E60, 0xF075, 0x7E61, 0xC2B8, 0x7E62, 0xF072, 0x7E63, 0xF070, 0x7E68, 0xF2B8, 0x7E69, 0xC3B7, 0x7E6A, 0xC3B8, + 0x7E6B, 0xC3B4, 0x7E6D, 0xC3B5, 0x7E6F, 0xF2B4, 0x7E70, 0xF2B2, 0x7E72, 0xF2B6, 0x7E73, 0xC3BA, 0x7E74, 0xF2B7, 0x7E75, 0xF2B0, + 0x7E76, 0xF2AF, 0x7E77, 0xF2B3, 0x7E78, 0xF2B1, 0x7E79, 0xC3B6, 0x7E7A, 0xF2B5, 0x7E7B, 0xF4AC, 0x7E7C, 0xC47E, 0x7E7D, 0xC47D, + 0x7E7E, 0xF4AD, 0x7E80, 0xF4AF, 0x7E81, 0xF4AE, 0x7E82, 0xC4A1, 0x7E86, 0xF5EB, 0x7E87, 0xF5E8, 0x7E88, 0xF5E9, 0x7E8A, 0xF5E7, + 0x7E8B, 0xF5EA, 0x7E8C, 0xC4F2, 0x7E8D, 0xF5EC, 0x7E8F, 0xC4F1, 0x7E91, 0xF742, 0x7E93, 0xC5D5, 0x7E94, 0xC5D7, 0x7E95, 0xF7EE, + 0x7E96, 0xC5D6, 0x7E97, 0xF8B9, 0x7E98, 0xF940, 0x7E99, 0xF942, 0x7E9A, 0xF8FE, 0x7E9B, 0xF941, 0x7E9C, 0xC66C, 0x7F36, 0xA6CE, + 0x7F38, 0xACFB, 0x7F39, 0xD26F, 0x7F3A, 0xAFCA, 0x7F3D, 0xB2DA, 0x7F3E, 0xDAFC, 0x7F3F, 0xDAFD, 0x7F43, 0xEADF, 0x7F44, 0xC16A, + 0x7F45, 0xEDE1, 0x7F48, 0xC2BB, 0x7F4A, 0xF2BA, 0x7F4B, 0xF2B9, 0x7F4C, 0xC4A2, 0x7F4D, 0xF5ED, 0x7F4F, 0xF743, 0x7F50, 0xC5F8, + 0x7F51, 0xCA49, 0x7F54, 0xAAC9, 0x7F55, 0xA875, 0x7F58, 0xD04D, 0x7F5B, 0xD360, 0x7F5C, 0xD35B, 0x7F5D, 0xD35F, 0x7F5E, 0xD35D, + 0x7F5F, 0xAFCB, 0x7F60, 0xD35E, 0x7F61, 0xD35C, 0x7F63, 0xD6F1, 0x7F65, 0xDAFE, 0x7F66, 0xDB40, 0x7F67, 0xDF69, 0x7F68, 0xDF6A, + 0x7F69, 0xB86E, 0x7F6A, 0xB86F, 0x7F6B, 0xDF68, 0x7F6C, 0xDF6B, 0x7F6D, 0xDF67, 0x7F6E, 0xB86D, 0x7F70, 0xBB40, 0x7F72, 0xB870, + 0x7F73, 0xE37A, 0x7F75, 0xBD7C, 0x7F76, 0xE6F1, 0x7F77, 0xBD7D, 0x7F79, 0xBFA9, 0x7F7A, 0xEAE2, 0x7F7B, 0xEAE0, 0x7F7C, 0xEAE1, + 0x7F7D, 0xEDE4, 0x7F7E, 0xEDE3, 0x7F7F, 0xEDE2, 0x7F83, 0xF2BB, 0x7F85, 0xC3B9, 0x7F86, 0xF2BC, 0x7F87, 0xF744, 0x7F88, 0xC5F9, + 0x7F89, 0xF8BA, 0x7F8A, 0xA6CF, 0x7F8B, 0xAACB, 0x7F8C, 0xAACA, 0x7F8D, 0xD04F, 0x7F8E, 0xACFC, 0x7F91, 0xD04E, 0x7F92, 0xD362, + 0x7F94, 0xAFCC, 0x7F95, 0xD6F2, 0x7F96, 0xD361, 0x7F9A, 0xB2DC, 0x7F9B, 0xD6F5, 0x7F9C, 0xD6F3, 0x7F9D, 0xD6F4, 0x7F9E, 0xB2DB, + 0x7FA0, 0xDB42, 0x7FA1, 0xDB43, 0x7FA2, 0xDB41, 0x7FA4, 0xB873, 0x7FA5, 0xDF6D, 0x7FA6, 0xDF6C, 0x7FA7, 0xDF6E, 0x7FA8, 0xB872, + 0x7FA9, 0xB871, 0x7FAC, 0xE6F2, 0x7FAD, 0xE6F4, 0x7FAF, 0xBD7E, 0x7FB0, 0xE6F3, 0x7FB1, 0xEAE3, 0x7FB2, 0xBFAA, 0x7FB3, 0xF079, + 0x7FB5, 0xF078, 0x7FB6, 0xC3BB, 0x7FB7, 0xF2BD, 0x7FB8, 0xC3BD, 0x7FB9, 0xC3BC, 0x7FBA, 0xF4B0, 0x7FBB, 0xF5EE, 0x7FBC, 0xC4F3, + 0x7FBD, 0xA6D0, 0x7FBE, 0xD050, 0x7FBF, 0xACFD, 0x7FC0, 0xD365, 0x7FC1, 0xAFCE, 0x7FC2, 0xD364, 0x7FC3, 0xD363, 0x7FC5, 0xAFCD, + 0x7FC7, 0xD6FB, 0x7FC9, 0xD6FD, 0x7FCA, 0xD6F6, 0x7FCB, 0xD6F7, 0x7FCC, 0xB2DD, 0x7FCD, 0xD6F8, 0x7FCE, 0xB2DE, 0x7FCF, 0xD6FC, + 0x7FD0, 0xD6F9, 0x7FD1, 0xD6FA, 0x7FD2, 0xB2DF, 0x7FD4, 0xB5BE, 0x7FD5, 0xB5BF, 0x7FD7, 0xDB44, 0x7FDB, 0xDF6F, 0x7FDC, 0xDF70, + 0x7FDE, 0xE37E, 0x7FDF, 0xBB43, 0x7FE0, 0xBB41, 0x7FE1, 0xBB42, 0x7FE2, 0xE37B, 0x7FE3, 0xE37C, 0x7FE5, 0xE37D, 0x7FE6, 0xE6F9, + 0x7FE8, 0xE6FA, 0x7FE9, 0xBDA1, 0x7FEA, 0xE6F7, 0x7FEB, 0xE6F6, 0x7FEC, 0xE6F8, 0x7FED, 0xE6F5, 0x7FEE, 0xBFAD, 0x7FEF, 0xEAE4, + 0x7FF0, 0xBFAB, 0x7FF1, 0xBFAC, 0x7FF2, 0xEDE6, 0x7FF3, 0xC16B, 0x7FF4, 0xEDE5, 0x7FF5, 0xEFA8, 0x7FF7, 0xF07A, 0x7FF8, 0xF07B, + 0x7FF9, 0xC2BC, 0x7FFB, 0xC2BD, 0x7FFC, 0xC16C, 0x7FFD, 0xF2BE, 0x7FFE, 0xF2BF, 0x7FFF, 0xF4B1, 0x8000, 0xC4A3, 0x8001, 0xA6D1, + 0x8003, 0xA6D2, 0x8004, 0xACFE, 0x8005, 0xAACC, 0x8006, 0xAFCF, 0x8007, 0xD051, 0x800B, 0xB5C0, 0x800C, 0xA6D3, 0x800D, 0xAD41, + 0x800E, 0xD052, 0x800F, 0xD053, 0x8010, 0xAD40, 0x8011, 0xAD42, 0x8012, 0xA6D4, 0x8014, 0xD054, 0x8015, 0xAFD1, 0x8016, 0xD366, + 0x8017, 0xAFD3, 0x8018, 0xAFD0, 0x8019, 0xAFD2, 0x801B, 0xD741, 0x801C, 0xB2E0, 0x801E, 0xD740, 0x801F, 0xD6FE, 0x8021, 0xDF71, + 0x8024, 0xE3A1, 0x8026, 0xBDA2, 0x8028, 0xBFAE, 0x8029, 0xEAE6, 0x802A, 0xEAE5, 0x802C, 0xEDE7, 0x8030, 0xF5EF, 0x8033, 0xA6D5, + 0x8034, 0xCB73, 0x8035, 0xCDAA, 0x8036, 0xAD43, 0x8037, 0xD055, 0x8039, 0xD368, 0x803D, 0xAFD4, 0x803E, 0xD367, 0x803F, 0xAFD5, + 0x8043, 0xD743, 0x8046, 0xB2E2, 0x8047, 0xD742, 0x8048, 0xD744, 0x804A, 0xB2E1, 0x804F, 0xDB46, 0x8050, 0xDB47, 0x8051, 0xDB45, + 0x8052, 0xB5C1, 0x8056, 0xB874, 0x8058, 0xB875, 0x805A, 0xBB45, 0x805C, 0xE3A3, 0x805D, 0xE3A2, 0x805E, 0xBB44, 0x8064, 0xE6FB, + 0x8067, 0xE6FC, 0x806C, 0xEAE7, 0x806F, 0xC170, 0x8070, 0xC16F, 0x8071, 0xC16D, 0x8072, 0xC16E, 0x8073, 0xC171, 0x8075, 0xF07C, + 0x8076, 0xC2BF, 0x8077, 0xC2BE, 0x8078, 0xF2C0, 0x8079, 0xF4B2, 0x807D, 0xC5A5, 0x807E, 0xC5A4, 0x807F, 0xA6D6, 0x8082, 0xD1FB, + 0x8084, 0xB877, 0x8085, 0xB5C2, 0x8086, 0xB876, 0x8087, 0xBB46, 0x8089, 0xA6D7, 0x808A, 0xC9A9, 0x808B, 0xA6D8, 0x808C, 0xA6D9, + 0x808F, 0xCDAB, 0x8090, 0xCB76, 0x8092, 0xCB77, 0x8093, 0xA877, 0x8095, 0xCB74, 0x8096, 0xA876, 0x8098, 0xA879, 0x8099, 0xCB75, + 0x809A, 0xA87B, 0x809B, 0xA87A, 0x809C, 0xCB78, 0x809D, 0xA878, 0x80A1, 0xAAD1, 0x80A2, 0xAACF, 0x80A3, 0xCDAD, 0x80A5, 0xAACE, + 0x80A9, 0xAAD3, 0x80AA, 0xAAD5, 0x80AB, 0xAAD2, 0x80AD, 0xCDB0, 0x80AE, 0xCDAC, 0x80AF, 0xAAD6, 0x80B1, 0xAAD0, 0x80B2, 0xA87C, + 0x80B4, 0xAAD4, 0x80B5, 0xCDAF, 0x80B8, 0xCDAE, 0x80BA, 0xAACD, 0x80C2, 0xD05B, 0x80C3, 0xAD47, 0x80C4, 0xAD48, 0x80C5, 0xD05D, + 0x80C7, 0xD057, 0x80C8, 0xD05A, 0x80C9, 0xD063, 0x80CA, 0xD061, 0x80CC, 0xAD49, 0x80CD, 0xD067, 0x80CE, 0xAD4C, 0x80CF, 0xD064, + 0x80D0, 0xD05C, 0x80D1, 0xD059, 0x80D4, 0xDB49, 0x80D5, 0xD062, 0x80D6, 0xAD44, 0x80D7, 0xD065, 0x80D8, 0xD056, 0x80D9, 0xD05F, + 0x80DA, 0xAD46, 0x80DB, 0xAD4B, 0x80DC, 0xD060, 0x80DD, 0xAD4F, 0x80DE, 0xAD4D, 0x80E0, 0xD058, 0x80E1, 0xAD4A, 0x80E3, 0xD05E, + 0x80E4, 0xAD4E, 0x80E5, 0xAD45, 0x80E6, 0xD066, 0x80ED, 0xAFDA, 0x80EF, 0xAFE3, 0x80F0, 0xAFD8, 0x80F1, 0xAFD6, 0x80F2, 0xD36A, + 0x80F3, 0xAFDE, 0x80F4, 0xAFDB, 0x80F5, 0xD36C, 0x80F8, 0xAFDD, 0x80F9, 0xD36B, 0x80FA, 0xD369, 0x80FB, 0xD36E, 0x80FC, 0xAFE2, + 0x80FD, 0xAFE0, 0x80FE, 0xDB48, 0x8100, 0xD36F, 0x8101, 0xD36D, 0x8102, 0xAFD7, 0x8105, 0xAFD9, 0x8106, 0xAFDC, 0x8108, 0xAFDF, + 0x810A, 0xAFE1, 0x8115, 0xD74E, 0x8116, 0xB2E4, 0x8118, 0xD745, 0x8119, 0xD747, 0x811B, 0xD748, 0x811D, 0xD750, 0x811E, 0xD74C, + 0x811F, 0xD74A, 0x8121, 0xD74D, 0x8122, 0xD751, 0x8123, 0xB2E5, 0x8124, 0xB2E9, 0x8125, 0xD746, 0x8127, 0xD74F, 0x8129, 0xB2E7, + 0x812B, 0xB2E6, 0x812C, 0xD74B, 0x812D, 0xD749, 0x812F, 0xB2E3, 0x8130, 0xB2E8, 0x8139, 0xB5C8, 0x813A, 0xDB51, 0x813D, 0xDB4F, + 0x813E, 0xB5CA, 0x8143, 0xDB4A, 0x8144, 0xDFA1, 0x8146, 0xB5C9, 0x8147, 0xDB4E, 0x814A, 0xDB4B, 0x814B, 0xB5C5, 0x814C, 0xB5CB, + 0x814D, 0xDB50, 0x814E, 0xB5C7, 0x814F, 0xDB4D, 0x8150, 0xBB47, 0x8151, 0xB5C6, 0x8152, 0xDB4C, 0x8153, 0xB5CC, 0x8154, 0xB5C4, + 0x8155, 0xB5C3, 0x815B, 0xDF77, 0x815C, 0xDF75, 0x815E, 0xDF7B, 0x8160, 0xDF73, 0x8161, 0xDFA2, 0x8162, 0xDF78, 0x8164, 0xDF72, + 0x8165, 0xB87B, 0x8166, 0xB8A3, 0x8167, 0xDF7D, 0x8169, 0xDF76, 0x816B, 0xB87E, 0x816E, 0xB87C, 0x816F, 0xDF7E, 0x8170, 0xB879, + 0x8171, 0xB878, 0x8172, 0xDF79, 0x8173, 0xB87D, 0x8174, 0xB5CD, 0x8176, 0xDF7C, 0x8177, 0xDF74, 0x8178, 0xB87A, 0x8179, 0xB8A1, + 0x817A, 0xB8A2, 0x817F, 0xBB4C, 0x8180, 0xBB48, 0x8182, 0xBB4D, 0x8183, 0xE3A6, 0x8186, 0xE3A5, 0x8187, 0xE3A7, 0x8188, 0xBB4A, + 0x8189, 0xE3A4, 0x818A, 0xBB4B, 0x818B, 0xE3AA, 0x818C, 0xE3A9, 0x818D, 0xE3A8, 0x818F, 0xBB49, 0x8195, 0xE741, 0x8197, 0xE744, + 0x8198, 0xBDA8, 0x8199, 0xE743, 0x819A, 0xBDA7, 0x819B, 0xBDA3, 0x819C, 0xBDA4, 0x819D, 0xBDA5, 0x819E, 0xE740, 0x819F, 0xE6FE, + 0x81A0, 0xBDA6, 0x81A2, 0xE742, 0x81A3, 0xE6FD, 0x81A6, 0xEAE9, 0x81A7, 0xEAF3, 0x81A8, 0xBFB1, 0x81A9, 0xBFB0, 0x81AB, 0xEAED, + 0x81AC, 0xEAEF, 0x81AE, 0xEAEA, 0x81B0, 0xEAEE, 0x81B1, 0xEAE8, 0x81B2, 0xEAF1, 0x81B3, 0xBFAF, 0x81B4, 0xEAF0, 0x81B5, 0xEAEC, + 0x81B7, 0xEAF2, 0x81B9, 0xEAEB, 0x81BA, 0xC174, 0x81BB, 0xEDE8, 0x81BC, 0xEDEE, 0x81BD, 0xC178, 0x81BE, 0xC17A, 0x81BF, 0xC177, + 0x81C0, 0xC176, 0x81C2, 0xC175, 0x81C3, 0xC173, 0x81C4, 0xEDE9, 0x81C5, 0xEDEC, 0x81C6, 0xC172, 0x81C7, 0xEDED, 0x81C9, 0xC179, + 0x81CA, 0xEDEB, 0x81CC, 0xEDEA, 0x81CD, 0xC2C0, 0x81CF, 0xC2C1, 0x81D0, 0xF0A1, 0x81D1, 0xF07D, 0x81D2, 0xF07E, 0x81D5, 0xF2C2, + 0x81D7, 0xF2C1, 0x81D8, 0xC3BE, 0x81D9, 0xF4B4, 0x81DA, 0xC4A4, 0x81DB, 0xF4B3, 0x81DD, 0xF5F0, 0x81DE, 0xF745, 0x81DF, 0xC5A6, + 0x81E0, 0xF943, 0x81E1, 0xF944, 0x81E2, 0xC5D8, 0x81E3, 0xA6DA, 0x81E5, 0xAAD7, 0x81E6, 0xDB52, 0x81E7, 0xBB4E, 0x81E8, 0xC17B, + 0x81E9, 0xEDEF, 0x81EA, 0xA6DB, 0x81EC, 0xAFE5, 0x81ED, 0xAFE4, 0x81EE, 0xDB53, 0x81F2, 0xEAF4, 0x81F3, 0xA6DC, 0x81F4, 0xAD50, + 0x81F7, 0xDB54, 0x81F8, 0xDB55, 0x81F9, 0xDB56, 0x81FA, 0xBB4F, 0x81FB, 0xBFB2, 0x81FC, 0xA6DD, 0x81FE, 0xAAD8, 0x81FF, 0xD068, + 0x8200, 0xAFE6, 0x8201, 0xD370, 0x8202, 0xB2EA, 0x8204, 0xDB57, 0x8205, 0xB8A4, 0x8207, 0xBB50, 0x8208, 0xBFB3, 0x8209, 0xC17C, + 0x820A, 0xC2C2, 0x820B, 0xF4B5, 0x820C, 0xA6DE, 0x820D, 0xAAD9, 0x8210, 0xAFE7, 0x8211, 0xD752, 0x8212, 0xB5CE, 0x8214, 0xBB51, + 0x8215, 0xE3AB, 0x8216, 0xE745, 0x821B, 0xA6DF, 0x821C, 0xB5CF, 0x821D, 0xDFA3, 0x821E, 0xBB52, 0x821F, 0xA6E0, 0x8220, 0xCDB1, + 0x8221, 0xD069, 0x8222, 0xAD51, 0x8225, 0xD372, 0x8228, 0xAFEA, 0x822A, 0xAFE8, 0x822B, 0xAFE9, 0x822C, 0xAFEB, 0x822F, 0xD371, + 0x8232, 0xD757, 0x8233, 0xD754, 0x8234, 0xD756, 0x8235, 0xB2EB, 0x8236, 0xB2ED, 0x8237, 0xB2EC, 0x8238, 0xD753, 0x8239, 0xB2EE, + 0x823A, 0xD755, 0x823C, 0xDB58, 0x823D, 0xDB59, 0x823F, 0xDB5A, 0x8240, 0xDFA6, 0x8242, 0xDFA7, 0x8244, 0xDFA5, 0x8245, 0xDFA8, + 0x8247, 0xB8A5, 0x8249, 0xDFA4, 0x824B, 0xBB53, 0x824E, 0xE74A, 0x824F, 0xE746, 0x8250, 0xE749, 0x8251, 0xE74B, 0x8252, 0xE748, + 0x8253, 0xE747, 0x8255, 0xEAF5, 0x8256, 0xEAF6, 0x8257, 0xEAF7, 0x8258, 0xBFB4, 0x8259, 0xBFB5, 0x825A, 0xEDF1, 0x825B, 0xEDF0, + 0x825C, 0xEDF2, 0x825E, 0xF0A3, 0x825F, 0xF0A2, 0x8261, 0xF2C4, 0x8263, 0xF2C5, 0x8264, 0xF2C3, 0x8266, 0xC4A5, 0x8268, 0xF4B6, + 0x8269, 0xF4B7, 0x826B, 0xF746, 0x826C, 0xF7EF, 0x826D, 0xF8BB, 0x826E, 0xA6E1, 0x826F, 0xA87D, 0x8271, 0xC17D, 0x8272, 0xA6E2, + 0x8274, 0xD758, 0x8275, 0xDB5B, 0x8277, 0xC641, 0x8278, 0xCA4A, 0x827C, 0xCA4B, 0x827D, 0xCA4D, 0x827E, 0xA6E3, 0x827F, 0xCA4E, + 0x8280, 0xCA4C, 0x8283, 0xCBA2, 0x8284, 0xCBA3, 0x8285, 0xCB7B, 0x828A, 0xCBA1, 0x828B, 0xA8A1, 0x828D, 0xA8A2, 0x828E, 0xCB7C, + 0x828F, 0xCB7A, 0x8290, 0xCB79, 0x8291, 0xCB7D, 0x8292, 0xA87E, 0x8293, 0xCB7E, 0x8294, 0xD06A, 0x8298, 0xCDB6, 0x8299, 0xAADC, + 0x829A, 0xCDB5, 0x829B, 0xCDB7, 0x829D, 0xAADB, 0x829E, 0xCDBC, 0x829F, 0xAADF, 0x82A0, 0xCDB2, 0x82A1, 0xCDC0, 0x82A2, 0xCDC6, + 0x82A3, 0xAAE6, 0x82A4, 0xCDC3, 0x82A5, 0xAAE3, 0x82A7, 0xCDB9, 0x82A8, 0xCDBF, 0x82A9, 0xCDC1, 0x82AB, 0xCDB4, 0x82AC, 0xAAE2, + 0x82AD, 0xAADD, 0x82AE, 0xCDBA, 0x82AF, 0xAAE4, 0x82B0, 0xAAE7, 0x82B1, 0xAAE1, 0x82B3, 0xAADA, 0x82B4, 0xCDBE, 0x82B5, 0xCDB8, + 0x82B6, 0xCDC5, 0x82B7, 0xAAE9, 0x82B8, 0xAAE5, 0x82B9, 0xAAE0, 0x82BA, 0xCDBD, 0x82BB, 0xAFEC, 0x82BC, 0xCDBB, 0x82BD, 0xAADE, + 0x82BE, 0xAAE8, 0x82C0, 0xCDB3, 0x82C2, 0xCDC2, 0x82C3, 0xCDC4, 0x82D1, 0xAD62, 0x82D2, 0xAD5C, 0x82D3, 0xAD64, 0x82D4, 0xAD61, + 0x82D5, 0xD071, 0x82D6, 0xD074, 0x82D7, 0xAD5D, 0x82D9, 0xD06B, 0x82DB, 0xAD56, 0x82DC, 0xAD60, 0x82DE, 0xAD63, 0x82DF, 0xAD65, + 0x82E0, 0xD0A2, 0x82E1, 0xD077, 0x82E3, 0xAD55, 0x82E4, 0xD0A1, 0x82E5, 0xAD59, 0x82E6, 0xAD57, 0x82E7, 0xAD52, 0x82E8, 0xD06F, + 0x82EA, 0xD07E, 0x82EB, 0xD073, 0x82EC, 0xD076, 0x82ED, 0xD0A5, 0x82EF, 0xAD66, 0x82F0, 0xD07D, 0x82F1, 0xAD5E, 0x82F2, 0xD078, + 0x82F3, 0xD0A4, 0x82F4, 0xD075, 0x82F5, 0xD079, 0x82F6, 0xD07C, 0x82F9, 0xD06D, 0x82FA, 0xD0A3, 0x82FB, 0xD07B, 0x82FE, 0xD06C, + 0x8300, 0xD070, 0x8301, 0xAD5F, 0x8302, 0xAD5A, 0x8303, 0xAD53, 0x8304, 0xAD58, 0x8305, 0xAD54, 0x8306, 0xAD67, 0x8307, 0xD06E, + 0x8308, 0xD3A5, 0x8309, 0xAD5B, 0x830C, 0xD07A, 0x830D, 0xCE41, 0x8316, 0xD3A8, 0x8317, 0xAFFA, 0x8319, 0xD376, 0x831B, 0xD3A3, + 0x831C, 0xD37D, 0x831E, 0xD3B2, 0x8320, 0xD3AA, 0x8322, 0xD37E, 0x8324, 0xD3A9, 0x8325, 0xD378, 0x8326, 0xD37C, 0x8327, 0xD3B5, + 0x8328, 0xAFFD, 0x8329, 0xD3AD, 0x832A, 0xD3A4, 0x832B, 0xAFED, 0x832C, 0xD3B3, 0x832D, 0xD374, 0x832F, 0xD3AC, 0x8331, 0xAFFC, + 0x8332, 0xAFF7, 0x8333, 0xD373, 0x8334, 0xAFF5, 0x8335, 0xAFF4, 0x8336, 0xAFF9, 0x8337, 0xD3AB, 0x8338, 0xAFF1, 0x8339, 0xAFF8, + 0x833A, 0xD072, 0x833B, 0xDB5C, 0x833C, 0xD3A6, 0x833F, 0xD37A, 0x8340, 0xAFFB, 0x8341, 0xD37B, 0x8342, 0xD3A1, 0x8343, 0xAFFE, + 0x8344, 0xD375, 0x8345, 0xD3AF, 0x8347, 0xD3AE, 0x8348, 0xD3B6, 0x8349, 0xAFF3, 0x834A, 0xAFF0, 0x834B, 0xD3B4, 0x834C, 0xD3B0, + 0x834D, 0xD3A7, 0x834E, 0xD3A2, 0x834F, 0xAFF6, 0x8350, 0xAFF2, 0x8351, 0xD377, 0x8352, 0xAFEE, 0x8353, 0xD3B1, 0x8354, 0xAFEF, + 0x8356, 0xD379, 0x8373, 0xD75E, 0x8374, 0xD760, 0x8375, 0xD765, 0x8376, 0xD779, 0x8377, 0xB2FC, 0x8378, 0xB2F2, 0x837A, 0xD75D, + 0x837B, 0xB2FD, 0x837C, 0xB2FE, 0x837D, 0xD768, 0x837E, 0xD76F, 0x837F, 0xD775, 0x8381, 0xD762, 0x8383, 0xD769, 0x8386, 0xB340, + 0x8387, 0xD777, 0x8388, 0xD772, 0x8389, 0xB2FA, 0x838A, 0xB2F8, 0x838B, 0xD76E, 0x838C, 0xD76A, 0x838D, 0xD75C, 0x838E, 0xB2EF, + 0x838F, 0xD761, 0x8390, 0xD759, 0x8392, 0xB2F7, 0x8393, 0xB2F9, 0x8394, 0xD766, 0x8395, 0xD763, 0x8396, 0xB2F4, 0x8397, 0xD773, + 0x8398, 0xB2F1, 0x8399, 0xD764, 0x839A, 0xD77A, 0x839B, 0xD76C, 0x839D, 0xD76B, 0x839E, 0xB2F0, 0x83A0, 0xB2FB, 0x83A2, 0xB2F3, + 0x83A3, 0xD75A, 0x83A4, 0xD75F, 0x83A5, 0xD770, 0x83A6, 0xD776, 0x83A7, 0xB341, 0x83A8, 0xD75B, 0x83A9, 0xD767, 0x83AA, 0xD76D, + 0x83AB, 0xB2F6, 0x83AE, 0xD778, 0x83AF, 0xD771, 0x83B0, 0xD774, 0x83BD, 0xB2F5, 0x83BF, 0xDB6C, 0x83C0, 0xDB60, 0x83C1, 0xB5D7, + 0x83C2, 0xDB7D, 0x83C3, 0xDBA7, 0x83C4, 0xDBAA, 0x83C5, 0xB5D5, 0x83C6, 0xDB68, 0x83C7, 0xDBA3, 0x83C8, 0xDB69, 0x83C9, 0xDB77, + 0x83CA, 0xB5E2, 0x83CB, 0xDB73, 0x83CC, 0xB5DF, 0x83CE, 0xDB74, 0x83CF, 0xDB5D, 0x83D1, 0xDBA4, 0x83D4, 0xB5E8, 0x83D5, 0xDBA1, + 0x83D6, 0xDB75, 0x83D7, 0xDBAC, 0x83D8, 0xDB70, 0x83D9, 0xDFC8, 0x83DB, 0xDBAF, 0x83DC, 0xB5E6, 0x83DD, 0xDB6E, 0x83DE, 0xDB7A, + 0x83DF, 0xB5E9, 0x83E0, 0xB5D4, 0x83E1, 0xDB72, 0x83E2, 0xDBAD, 0x83E3, 0xDB6B, 0x83E4, 0xDB64, 0x83E5, 0xDB6F, 0x83E7, 0xDB63, + 0x83E8, 0xDB61, 0x83E9, 0xB5D0, 0x83EA, 0xDBA5, 0x83EB, 0xDB6A, 0x83EC, 0xDBA8, 0x83EE, 0xDBA9, 0x83EF, 0xB5D8, 0x83F0, 0xB5DD, + 0x83F1, 0xB5D9, 0x83F2, 0xB5E1, 0x83F3, 0xDB7E, 0x83F4, 0xB5DA, 0x83F5, 0xDB76, 0x83F6, 0xDB66, 0x83F8, 0xB5D2, 0x83F9, 0xDB5E, + 0x83FA, 0xDBA2, 0x83FB, 0xDBAB, 0x83FC, 0xDB65, 0x83FD, 0xB5E0, 0x83FE, 0xDBB0, 0x83FF, 0xDB71, 0x8401, 0xDB6D, 0x8403, 0xB5D1, + 0x8404, 0xB5E5, 0x8406, 0xDB7C, 0x8407, 0xB5E7, 0x8409, 0xDB78, 0x840A, 0xB5DC, 0x840B, 0xB5D6, 0x840C, 0xB5DE, 0x840D, 0xB5D3, + 0x840E, 0xB5E4, 0x840F, 0xDB79, 0x8410, 0xDB67, 0x8411, 0xDB7B, 0x8412, 0xDB62, 0x8413, 0xDBA6, 0x841B, 0xDBAE, 0x8423, 0xDB5F, + 0x8429, 0xDFC7, 0x842B, 0xDFDD, 0x842C, 0xB855, 0x842D, 0xDFCC, 0x842F, 0xDFCA, 0x8430, 0xDFB5, 0x8431, 0xB8A9, 0x8432, 0xDFC5, + 0x8433, 0xDFD9, 0x8434, 0xDFC1, 0x8435, 0xB8B1, 0x8436, 0xDFD8, 0x8437, 0xDFBF, 0x8438, 0xB5E3, 0x8439, 0xDFCF, 0x843A, 0xDFC0, + 0x843B, 0xDFD6, 0x843C, 0xB8B0, 0x843D, 0xB8A8, 0x843F, 0xDFAA, 0x8440, 0xDFB2, 0x8442, 0xDFCB, 0x8443, 0xDFC3, 0x8444, 0xDFDC, + 0x8445, 0xDFC6, 0x8446, 0xB8B6, 0x8447, 0xDFD7, 0x8449, 0xB8AD, 0x844B, 0xDFC9, 0x844C, 0xDFD1, 0x844D, 0xDFB6, 0x844E, 0xDFD0, + 0x8450, 0xDFE1, 0x8451, 0xDFB1, 0x8452, 0xDFD2, 0x8454, 0xDFDF, 0x8456, 0xDFAB, 0x8457, 0xB5DB, 0x8459, 0xDFB9, 0x845A, 0xDFB8, + 0x845B, 0xB8AF, 0x845D, 0xDFBC, 0x845E, 0xDFBE, 0x845F, 0xDFCD, 0x8460, 0xDFDE, 0x8461, 0xB8B2, 0x8463, 0xB8B3, 0x8465, 0xDFB0, + 0x8466, 0xB8AB, 0x8467, 0xDFB4, 0x8468, 0xDFDA, 0x8469, 0xB8B4, 0x846B, 0xB8AC, 0x846C, 0xB8AE, 0x846D, 0xB8B5, 0x846E, 0xDFE0, + 0x846F, 0xDFD3, 0x8470, 0xDFCE, 0x8473, 0xDFBB, 0x8474, 0xDFBA, 0x8475, 0xB8AA, 0x8476, 0xDFAC, 0x8477, 0xB8A7, 0x8478, 0xDFC4, + 0x8479, 0xDFAD, 0x847A, 0xDFC2, 0x847D, 0xDFB7, 0x847E, 0xDFDB, 0x8482, 0xB8A6, 0x8486, 0xDFB3, 0x848D, 0xDFAF, 0x848E, 0xDFD5, + 0x848F, 0xDFAE, 0x8490, 0xBB60, 0x8491, 0xE3D3, 0x8494, 0xE3C2, 0x8497, 0xE3AC, 0x8498, 0xE3CA, 0x8499, 0xBB58, 0x849A, 0xE3BB, + 0x849B, 0xE3C5, 0x849C, 0xBB5B, 0x849D, 0xE3BE, 0x849E, 0xBB59, 0x849F, 0xE3AF, 0x84A0, 0xE3CD, 0x84A1, 0xE3AE, 0x84A2, 0xE3C1, + 0x84A4, 0xE3AD, 0x84A7, 0xE3BF, 0x84A8, 0xE3C8, 0x84A9, 0xE3C6, 0x84AA, 0xE3BA, 0x84AB, 0xE3B5, 0x84AC, 0xE3B3, 0x84AE, 0xE3B4, + 0x84AF, 0xE3C7, 0x84B0, 0xE3D2, 0x84B1, 0xE3BC, 0x84B2, 0xBB5A, 0x84B4, 0xE3B7, 0x84B6, 0xE3CB, 0x84B8, 0xBB5D, 0x84B9, 0xE3B6, + 0x84BA, 0xE3B0, 0x84BB, 0xE3C0, 0x84BC, 0xBB61, 0x84BF, 0xBB55, 0x84C0, 0xBB5E, 0x84C1, 0xE3B8, 0x84C2, 0xE3B2, 0x84C4, 0xBB57, + 0x84C5, 0xDFD4, 0x84C6, 0xBB56, 0x84C7, 0xE3C3, 0x84C9, 0xBB54, 0x84CA, 0xBB63, 0x84CB, 0xBB5C, 0x84CC, 0xE3C4, 0x84CD, 0xE3B9, + 0x84CE, 0xE3B1, 0x84CF, 0xE3CC, 0x84D0, 0xE3BD, 0x84D1, 0xBB62, 0x84D2, 0xE3D0, 0x84D3, 0xBB5F, 0x84D4, 0xE3CF, 0x84D6, 0xE3C9, + 0x84D7, 0xE3CE, 0x84DB, 0xE3D1, 0x84E7, 0xE773, 0x84E8, 0xE774, 0x84E9, 0xE767, 0x84EA, 0xE766, 0x84EB, 0xE762, 0x84EC, 0xBDB4, + 0x84EE, 0xBDAC, 0x84EF, 0xE776, 0x84F0, 0xE775, 0x84F1, 0xDFA9, 0x84F2, 0xE75F, 0x84F3, 0xE763, 0x84F4, 0xE75D, 0x84F6, 0xE770, + 0x84F7, 0xE761, 0x84F9, 0xE777, 0x84FA, 0xE75A, 0x84FB, 0xE758, 0x84FC, 0xE764, 0x84FD, 0xE76E, 0x84FE, 0xE769, 0x84FF, 0xBDB6, + 0x8500, 0xE74F, 0x8502, 0xE76D, 0x8506, 0xBDB7, 0x8507, 0xDFBD, 0x8508, 0xE75B, 0x8509, 0xE752, 0x850A, 0xE755, 0x850B, 0xE77B, + 0x850C, 0xE75C, 0x850D, 0xE753, 0x850E, 0xE751, 0x850F, 0xE74E, 0x8511, 0xBDB0, 0x8512, 0xE765, 0x8513, 0xBDAF, 0x8514, 0xBDB3, + 0x8515, 0xE760, 0x8516, 0xE768, 0x8517, 0xBDA9, 0x8518, 0xE778, 0x8519, 0xE77C, 0x851A, 0xBDAB, 0x851C, 0xE757, 0x851D, 0xE76B, + 0x851E, 0xE76F, 0x851F, 0xE754, 0x8520, 0xE779, 0x8521, 0xBDB2, 0x8523, 0xBDB1, 0x8524, 0xE74C, 0x8525, 0xBDB5, 0x8526, 0xE772, + 0x8527, 0xE756, 0x8528, 0xE76A, 0x8529, 0xE750, 0x852A, 0xE75E, 0x852B, 0xE759, 0x852C, 0xBDAD, 0x852D, 0xBDAE, 0x852E, 0xE76C, + 0x852F, 0xE77D, 0x8530, 0xE77A, 0x8531, 0xE771, 0x853B, 0xE74D, 0x853D, 0xBDAA, 0x853E, 0xEB49, 0x8540, 0xEB40, 0x8541, 0xEB43, + 0x8543, 0xBFBB, 0x8544, 0xEB45, 0x8545, 0xEAF9, 0x8546, 0xEB41, 0x8547, 0xEB47, 0x8548, 0xBFB8, 0x8549, 0xBFBC, 0x854A, 0xBFB6, + 0x854D, 0xEAFB, 0x854E, 0xEB4C, 0x8551, 0xEB46, 0x8553, 0xEAFC, 0x8554, 0xEB55, 0x8555, 0xEB4F, 0x8556, 0xEAF8, 0x8557, 0xEE46, + 0x8558, 0xEAFE, 0x8559, 0xBFB7, 0x855B, 0xEB4A, 0x855D, 0xEB54, 0x855E, 0xBFBF, 0x8560, 0xEB51, 0x8561, 0xEAFD, 0x8562, 0xEB44, + 0x8563, 0xEB48, 0x8564, 0xEB42, 0x8565, 0xEB56, 0x8566, 0xEB53, 0x8567, 0xEB50, 0x8568, 0xBFB9, 0x8569, 0xBFBA, 0x856A, 0xBFBE, + 0x856B, 0xEAFA, 0x856C, 0xEB57, 0x856D, 0xBFBD, 0x856E, 0xEB4D, 0x8571, 0xEB4B, 0x8575, 0xEB4E, 0x8576, 0xEE53, 0x8577, 0xEE40, + 0x8578, 0xEE45, 0x8579, 0xEE52, 0x857A, 0xEE44, 0x857B, 0xEDFB, 0x857C, 0xEE41, 0x857E, 0xC1A2, 0x8580, 0xEDF4, 0x8581, 0xEE4D, + 0x8582, 0xEE4F, 0x8583, 0xEDF3, 0x8584, 0xC1A1, 0x8585, 0xEE51, 0x8586, 0xEE49, 0x8587, 0xC1A8, 0x8588, 0xEE50, 0x8589, 0xEE42, + 0x858A, 0xC1AA, 0x858B, 0xEDF9, 0x858C, 0xEB52, 0x858D, 0xEE4A, 0x858E, 0xEE47, 0x858F, 0xEDF5, 0x8590, 0xEE55, 0x8591, 0xC1A4, + 0x8594, 0xC1A5, 0x8595, 0xEDF7, 0x8596, 0xEE48, 0x8598, 0xEE54, 0x8599, 0xEE4B, 0x859A, 0xEDFD, 0x859B, 0xC1A7, 0x859C, 0xC1A3, + 0x859D, 0xEE4C, 0x859E, 0xEDFE, 0x859F, 0xEE56, 0x85A0, 0xEDF8, 0x85A1, 0xEE43, 0x85A2, 0xEE4E, 0x85A3, 0xEDFA, 0x85A4, 0xEDFC, + 0x85A6, 0xC2CB, 0x85A7, 0xEDF6, 0x85A8, 0xC1A9, 0x85A9, 0xC2C4, 0x85AA, 0xC17E, 0x85AF, 0xC1A6, 0x85B0, 0xC2C8, 0x85B1, 0xF0B3, + 0x85B3, 0xF0A9, 0x85B4, 0xF0A4, 0x85B5, 0xF0AA, 0x85B6, 0xF0B4, 0x85B7, 0xF0B8, 0x85B8, 0xF0B7, 0x85B9, 0xC2CA, 0x85BA, 0xC2C9, + 0x85BD, 0xF0AB, 0x85BE, 0xF0B9, 0x85BF, 0xF0AE, 0x85C0, 0xF0A6, 0x85C2, 0xF0A8, 0x85C3, 0xF0A7, 0x85C4, 0xF0AD, 0x85C5, 0xF0B2, + 0x85C6, 0xF0A5, 0x85C7, 0xF0AC, 0x85C8, 0xF0B1, 0x85C9, 0xC2C7, 0x85CB, 0xF0AF, 0x85CD, 0xC2C5, 0x85CE, 0xF0B0, 0x85CF, 0xC2C3, + 0x85D0, 0xC2C6, 0x85D1, 0xF2D5, 0x85D2, 0xF0B5, 0x85D5, 0xC3C2, 0x85D7, 0xF2CD, 0x85D8, 0xF2D1, 0x85D9, 0xF2C9, 0x85DA, 0xF2CC, + 0x85DC, 0xF2D4, 0x85DD, 0xC3C0, 0x85DE, 0xF2D9, 0x85DF, 0xF2D2, 0x85E1, 0xF2CA, 0x85E2, 0xF2DA, 0x85E3, 0xF2D3, 0x85E4, 0xC3C3, + 0x85E5, 0xC3C4, 0x85E6, 0xF2D7, 0x85E8, 0xF2CB, 0x85E9, 0xC3BF, 0x85EA, 0xC3C1, 0x85EB, 0xF2C6, 0x85EC, 0xF2CE, 0x85ED, 0xF2C8, + 0x85EF, 0xF2D8, 0x85F0, 0xF2D6, 0x85F1, 0xF2C7, 0x85F2, 0xF2CF, 0x85F6, 0xF4BE, 0x85F7, 0xC3C5, 0x85F8, 0xF2D0, 0x85F9, 0xC4A7, + 0x85FA, 0xC4A9, 0x85FB, 0xC4A6, 0x85FD, 0xF4C3, 0x85FE, 0xF4BB, 0x85FF, 0xF4B9, 0x8600, 0xF4BD, 0x8601, 0xF4BA, 0x8604, 0xF4BF, + 0x8605, 0xF4C1, 0x8606, 0xC4AA, 0x8607, 0xC4AC, 0x8609, 0xF4C0, 0x860A, 0xC4AD, 0x860B, 0xC4AB, 0x860C, 0xF4C2, 0x8611, 0xC4A8, + 0x8617, 0xC4F4, 0x8618, 0xF5F1, 0x8619, 0xF5F7, 0x861A, 0xC4F6, 0x861B, 0xF4BC, 0x861C, 0xF5F6, 0x861E, 0xF5FD, 0x861F, 0xF5F4, + 0x8620, 0xF5FB, 0x8621, 0xF5FA, 0x8622, 0xF4B8, 0x8623, 0xF5F5, 0x8624, 0xF0B6, 0x8625, 0xF5FE, 0x8626, 0xF5F3, 0x8627, 0xF5F8, + 0x8629, 0xF5FC, 0x862A, 0xF5F2, 0x862C, 0xF74A, 0x862D, 0xC4F5, 0x862E, 0xF5F9, 0x8631, 0xF7F4, 0x8632, 0xF74B, 0x8633, 0xF749, + 0x8634, 0xF747, 0x8635, 0xF748, 0x8636, 0xF74C, 0x8638, 0xC5D9, 0x8639, 0xF7F2, 0x863A, 0xF7F0, 0x863B, 0xF7F5, 0x863C, 0xF7F3, + 0x863E, 0xF7F6, 0x863F, 0xC5DA, 0x8640, 0xF7F1, 0x8643, 0xF8BC, 0x8646, 0xF945, 0x8647, 0xF946, 0x8648, 0xF947, 0x864B, 0xF9C7, + 0x864C, 0xF9BD, 0x864D, 0xCA4F, 0x864E, 0xAAEA, 0x8650, 0xAD68, 0x8652, 0xD3B8, 0x8653, 0xD3B7, 0x8654, 0xB040, 0x8655, 0xB342, + 0x8656, 0xD77C, 0x8659, 0xD77B, 0x865B, 0xB5EA, 0x865C, 0xB8B8, 0x865E, 0xB8B7, 0x865F, 0xB8B9, 0x8661, 0xE3D4, 0x8662, 0xE77E, + 0x8663, 0xEB58, 0x8664, 0xEB5A, 0x8665, 0xEB59, 0x8667, 0xC1AB, 0x8668, 0xEE57, 0x8669, 0xF0BA, 0x866A, 0xF9A5, 0x866B, 0xA6E4, + 0x866D, 0xCDC9, 0x866E, 0xCDCA, 0x866F, 0xCDC8, 0x8670, 0xCDC7, 0x8671, 0xAAEB, 0x8673, 0xD0A9, 0x8674, 0xD0A7, 0x8677, 0xD0A6, + 0x8679, 0xAD69, 0x867A, 0xAD6B, 0x867B, 0xAD6A, 0x867C, 0xD0A8, 0x8685, 0xD3C4, 0x8686, 0xD3C1, 0x8687, 0xD3BF, 0x868A, 0xB041, + 0x868B, 0xD3C2, 0x868C, 0xB046, 0x868D, 0xD3BC, 0x868E, 0xD3CB, 0x8690, 0xD3CD, 0x8691, 0xD3BD, 0x8693, 0xB043, 0x8694, 0xD3CE, + 0x8695, 0xD3C9, 0x8696, 0xD3BB, 0x8697, 0xD3C0, 0x8698, 0xD3CA, 0x8699, 0xD3C6, 0x869A, 0xD3C3, 0x869C, 0xB048, 0x869D, 0xD3CC, + 0x869E, 0xD3BE, 0x86A1, 0xD3C7, 0x86A2, 0xD3B9, 0x86A3, 0xB047, 0x86A4, 0xB044, 0x86A5, 0xD3C5, 0x86A7, 0xD3C8, 0x86A8, 0xD3BA, + 0x86A9, 0xB045, 0x86AA, 0xB042, 0x86AF, 0xB34C, 0x86B0, 0xD7A5, 0x86B1, 0xB34B, 0x86B3, 0xD7A8, 0x86B4, 0xD7AB, 0x86B5, 0xB348, + 0x86B6, 0xB346, 0x86B7, 0xD77E, 0x86B8, 0xD7A9, 0x86B9, 0xD7A7, 0x86BA, 0xD7A4, 0x86BB, 0xD7AC, 0x86BC, 0xD7AD, 0x86BD, 0xD7AF, + 0x86BE, 0xD7B0, 0x86BF, 0xD77D, 0x86C0, 0xB345, 0x86C1, 0xD7A2, 0x86C2, 0xD7A1, 0x86C3, 0xD7AE, 0x86C4, 0xB347, 0x86C5, 0xD7A3, + 0x86C6, 0xB349, 0x86C7, 0xB344, 0x86C8, 0xD7A6, 0x86C9, 0xB34D, 0x86CB, 0xB34A, 0x86CC, 0xD7AA, 0x86D0, 0xB5F1, 0x86D1, 0xDBBF, + 0x86D3, 0xDBB4, 0x86D4, 0xB5EE, 0x86D6, 0xDFE7, 0x86D7, 0xDBBD, 0x86D8, 0xDBB1, 0x86D9, 0xB5EC, 0x86DA, 0xDBB6, 0x86DB, 0xB5EF, + 0x86DC, 0xDBBA, 0x86DD, 0xDBB8, 0x86DE, 0xB5F2, 0x86DF, 0xB5EB, 0x86E2, 0xDBB2, 0x86E3, 0xDBB5, 0x86E4, 0xB5F0, 0x86E6, 0xDBB3, + 0x86E8, 0xDBBE, 0x86E9, 0xDBBC, 0x86EA, 0xDBB7, 0x86EB, 0xDBB9, 0x86EC, 0xDBBB, 0x86ED, 0xB5ED, 0x86F5, 0xDFE8, 0x86F6, 0xDFEE, + 0x86F7, 0xDFE4, 0x86F8, 0xDFEA, 0x86F9, 0xB8BA, 0x86FA, 0xDFE6, 0x86FB, 0xB8C0, 0x86FE, 0xB8BF, 0x8700, 0xB8BE, 0x8701, 0xDFED, + 0x8702, 0xB8C1, 0x8703, 0xB8C2, 0x8704, 0xDFE3, 0x8705, 0xDFF0, 0x8706, 0xB8C3, 0x8707, 0xB8BD, 0x8708, 0xB8BC, 0x8709, 0xDFEC, + 0x870A, 0xB8C4, 0x870B, 0xDFE2, 0x870C, 0xDFE5, 0x870D, 0xDFEF, 0x870E, 0xDFEB, 0x8711, 0xE3F4, 0x8712, 0xE3E9, 0x8713, 0xB8BB, + 0x8718, 0xBB6A, 0x8719, 0xE3DD, 0x871A, 0xE3F2, 0x871B, 0xE3DE, 0x871C, 0xBB65, 0x871E, 0xE3DB, 0x8720, 0xE3E4, 0x8721, 0xE3DC, + 0x8722, 0xBB67, 0x8723, 0xE3D6, 0x8724, 0xE3F1, 0x8725, 0xBB68, 0x8726, 0xE3EE, 0x8727, 0xE3EF, 0x8728, 0xE3D7, 0x8729, 0xBB6D, + 0x872A, 0xE3E6, 0x872C, 0xE3E0, 0x872D, 0xE3E7, 0x872E, 0xE3DA, 0x8730, 0xE3F3, 0x8731, 0xE3EB, 0x8732, 0xE3E5, 0x8733, 0xE3D5, + 0x8734, 0xBB69, 0x8735, 0xE3EC, 0x8737, 0xBB6C, 0x8738, 0xE3F0, 0x873A, 0xE3EA, 0x873B, 0xBB66, 0x873C, 0xE3E8, 0x873E, 0xE3E2, + 0x873F, 0xBB64, 0x8740, 0xE3D9, 0x8741, 0xE3E1, 0x8742, 0xE3ED, 0x8743, 0xE3DF, 0x8746, 0xE3E3, 0x874C, 0xBDC1, 0x874D, 0xDFE9, + 0x874E, 0xE7B2, 0x874F, 0xE7BB, 0x8750, 0xE7B1, 0x8751, 0xE7AD, 0x8752, 0xE7AA, 0x8753, 0xBDC2, 0x8754, 0xE7A8, 0x8755, 0xBB6B, + 0x8756, 0xE7A1, 0x8757, 0xBDC0, 0x8758, 0xE7A7, 0x8759, 0xBDBF, 0x875A, 0xE7AC, 0x875B, 0xE7A9, 0x875C, 0xE7B9, 0x875D, 0xE7B4, + 0x875E, 0xE7AE, 0x875F, 0xE7B3, 0x8760, 0xBDBB, 0x8761, 0xE7AB, 0x8762, 0xE7BE, 0x8763, 0xE7A2, 0x8764, 0xE7A3, 0x8765, 0xE7BA, + 0x8766, 0xBDBC, 0x8767, 0xE7BF, 0x8768, 0xBDBE, 0x8769, 0xE7C0, 0x876A, 0xE7B0, 0x876B, 0xE3D8, 0x876C, 0xE7B6, 0x876D, 0xE7AF, + 0x876E, 0xE7B8, 0x876F, 0xE7B5, 0x8773, 0xE7A6, 0x8774, 0xBDB9, 0x8775, 0xE7BD, 0x8776, 0xBDBA, 0x8777, 0xE7A4, 0x8778, 0xBDBD, + 0x8779, 0xEB64, 0x877A, 0xE7B7, 0x877B, 0xE7BC, 0x8781, 0xEB61, 0x8782, 0xBDB8, 0x8783, 0xBFC0, 0x8784, 0xEB6B, 0x8785, 0xEB67, + 0x8787, 0xEB65, 0x8788, 0xEB60, 0x8789, 0xEB6F, 0x878D, 0xBFC4, 0x878F, 0xEB5C, 0x8790, 0xEB68, 0x8791, 0xEB69, 0x8792, 0xEB5F, + 0x8793, 0xEB5E, 0x8794, 0xEB6C, 0x8796, 0xEB62, 0x8797, 0xEB5D, 0x8798, 0xEB63, 0x879A, 0xEB6E, 0x879B, 0xEB5B, 0x879C, 0xEB6D, + 0x879D, 0xEB6A, 0x879E, 0xBFC2, 0x879F, 0xBFC1, 0x87A2, 0xBFC3, 0x87A3, 0xEB66, 0x87A4, 0xF0CB, 0x87AA, 0xEE59, 0x87AB, 0xC1B1, + 0x87AC, 0xEE5D, 0x87AD, 0xEE5A, 0x87AE, 0xEE61, 0x87AF, 0xEE67, 0x87B0, 0xEE5C, 0x87B2, 0xEE70, 0x87B3, 0xC1AE, 0x87B4, 0xEE6A, + 0x87B5, 0xEE5F, 0x87B6, 0xEE6B, 0x87B7, 0xEE66, 0x87B8, 0xEE6D, 0x87B9, 0xEE5E, 0x87BA, 0xC1B3, 0x87BB, 0xC1B2, 0x87BC, 0xEE60, + 0x87BD, 0xEE6E, 0x87BE, 0xEE58, 0x87BF, 0xEE6C, 0x87C0, 0xC1AC, 0x87C2, 0xEE64, 0x87C3, 0xEE63, 0x87C4, 0xEE68, 0x87C5, 0xEE5B, + 0x87C6, 0xC1B0, 0x87C8, 0xC1B4, 0x87C9, 0xEE62, 0x87CA, 0xEE69, 0x87CB, 0xC1B5, 0x87CC, 0xEE65, 0x87D1, 0xC1AD, 0x87D2, 0xC1AF, + 0x87D3, 0xF0C7, 0x87D4, 0xF0C5, 0x87D7, 0xF0CC, 0x87D8, 0xF0C9, 0x87D9, 0xF0CD, 0x87DB, 0xF0BE, 0x87DC, 0xF0C6, 0x87DD, 0xF0D1, + 0x87DE, 0xEE6F, 0x87DF, 0xF0C2, 0x87E0, 0xC2CF, 0x87E1, 0xE7A5, 0x87E2, 0xF0BD, 0x87E3, 0xF0CA, 0x87E4, 0xF0C4, 0x87E5, 0xF0C1, + 0x87E6, 0xF0BC, 0x87E7, 0xF0BB, 0x87E8, 0xF0D0, 0x87EA, 0xF0C0, 0x87EB, 0xF0BF, 0x87EC, 0xC2CD, 0x87ED, 0xF0C8, 0x87EF, 0xC2CC, + 0x87F2, 0xC2CE, 0x87F3, 0xF0C3, 0x87F4, 0xF0CF, 0x87F6, 0xF2DE, 0x87F7, 0xF2DF, 0x87F9, 0xC3C9, 0x87FA, 0xF2DC, 0x87FB, 0xC3C6, + 0x87FC, 0xF2E4, 0x87FE, 0xC3CA, 0x87FF, 0xF2E6, 0x8800, 0xF2DB, 0x8801, 0xF0CE, 0x8802, 0xF2E8, 0x8803, 0xF2DD, 0x8805, 0xC3C7, + 0x8806, 0xF2E3, 0x8808, 0xF2E5, 0x8809, 0xF2E0, 0x880A, 0xF2E7, 0x880B, 0xF2E2, 0x880C, 0xF2E1, 0x880D, 0xC3C8, 0x8810, 0xF4C5, + 0x8811, 0xF4C6, 0x8813, 0xF4C8, 0x8814, 0xC4AE, 0x8815, 0xC4AF, 0x8816, 0xF4C9, 0x8817, 0xF4C7, 0x8819, 0xF4C4, 0x881B, 0xF642, + 0x881C, 0xF645, 0x881D, 0xF641, 0x881F, 0xC4FA, 0x8820, 0xF643, 0x8821, 0xC4F9, 0x8822, 0xC4F8, 0x8823, 0xC4F7, 0x8824, 0xF644, + 0x8825, 0xF751, 0x8826, 0xF74F, 0x8828, 0xF74E, 0x8829, 0xF640, 0x882A, 0xF750, 0x882B, 0xF646, 0x882C, 0xF74D, 0x882E, 0xF7F9, + 0x882F, 0xF7D7, 0x8830, 0xF7F7, 0x8831, 0xC5DB, 0x8832, 0xF7F8, 0x8833, 0xF7FA, 0x8835, 0xF8BF, 0x8836, 0xC5FA, 0x8837, 0xF8BE, + 0x8838, 0xF8BD, 0x8839, 0xC5FB, 0x883B, 0xC65A, 0x883C, 0xF96E, 0x883D, 0xF9A7, 0x883E, 0xF9A6, 0x883F, 0xF9A8, 0x8840, 0xA6E5, + 0x8841, 0xD0AA, 0x8843, 0xD3CF, 0x8844, 0xD3D0, 0x8848, 0xDBC0, 0x884A, 0xF647, 0x884B, 0xF8C0, 0x884C, 0xA6E6, 0x884D, 0xAD6C, + 0x884E, 0xD0AB, 0x8852, 0xD7B1, 0x8853, 0xB34E, 0x8855, 0xDBC2, 0x8856, 0xDBC1, 0x8857, 0xB5F3, 0x8859, 0xB8C5, 0x885A, 0xE7C1, + 0x885B, 0xBDC3, 0x885D, 0xBDC4, 0x8861, 0xBFC5, 0x8862, 0xC5FC, 0x8863, 0xA6E7, 0x8867, 0xD0AC, 0x8868, 0xAAED, 0x8869, 0xD0AE, + 0x886A, 0xD0AD, 0x886B, 0xAD6D, 0x886D, 0xD3D1, 0x886F, 0xD3D8, 0x8870, 0xB049, 0x8871, 0xD3D6, 0x8872, 0xD3D4, 0x8874, 0xD3DB, + 0x8875, 0xD3D2, 0x8876, 0xD3D3, 0x8877, 0xB04A, 0x8879, 0xB04E, 0x887C, 0xD3DC, 0x887D, 0xB04D, 0x887E, 0xD3DA, 0x887F, 0xD3D7, + 0x8880, 0xD3D5, 0x8881, 0xB04B, 0x8882, 0xB04C, 0x8883, 0xD3D9, 0x8888, 0xB350, 0x8889, 0xD7B2, 0x888B, 0xB355, 0x888C, 0xD7C2, + 0x888D, 0xB354, 0x888E, 0xD7C4, 0x8891, 0xD7B8, 0x8892, 0xB352, 0x8893, 0xD7C3, 0x8895, 0xD7B3, 0x8896, 0xB353, 0x8897, 0xD7BF, + 0x8898, 0xD7BB, 0x8899, 0xD7BD, 0x889A, 0xD7B7, 0x889B, 0xD7BE, 0x889E, 0xB34F, 0x889F, 0xD7BA, 0x88A1, 0xD7B9, 0x88A2, 0xD7B5, + 0x88A4, 0xD7C0, 0x88A7, 0xD7BC, 0x88A8, 0xD7B4, 0x88AA, 0xD7B6, 0x88AB, 0xB351, 0x88AC, 0xD7C1, 0x88B1, 0xB5F6, 0x88B2, 0xDBCD, + 0x88B6, 0xDBC9, 0x88B7, 0xDBCB, 0x88B8, 0xDBC6, 0x88B9, 0xDBC5, 0x88BA, 0xDBC3, 0x88BC, 0xDBCA, 0x88BD, 0xDBCC, 0x88BE, 0xDBC8, + 0x88C0, 0xDBC7, 0x88C1, 0xB5F4, 0x88C2, 0xB5F5, 0x88C9, 0xDBCF, 0x88CA, 0xB8CD, 0x88CB, 0xDFF2, 0x88CC, 0xDFF8, 0x88CD, 0xDFF3, + 0x88CE, 0xDFF4, 0x88CF, 0xF9D8, 0x88D0, 0xDFF9, 0x88D2, 0xB8CF, 0x88D4, 0xB8C7, 0x88D5, 0xB8CE, 0x88D6, 0xDFF1, 0x88D7, 0xDBC4, + 0x88D8, 0xB8CA, 0x88D9, 0xB8C8, 0x88DA, 0xDFF7, 0x88DB, 0xDFF6, 0x88DC, 0xB8C9, 0x88DD, 0xB8CB, 0x88DE, 0xDFF5, 0x88DF, 0xB8C6, + 0x88E1, 0xB8CC, 0x88E7, 0xE3F6, 0x88E8, 0xBB74, 0x88EB, 0xE442, 0x88EC, 0xE441, 0x88EE, 0xE3FB, 0x88EF, 0xBB76, 0x88F0, 0xE440, + 0x88F1, 0xE3F7, 0x88F2, 0xE3F8, 0x88F3, 0xBB6E, 0x88F4, 0xBB70, 0x88F6, 0xE3FD, 0x88F7, 0xE3F5, 0x88F8, 0xBB72, 0x88F9, 0xBB71, + 0x88FA, 0xE3F9, 0x88FB, 0xE3FE, 0x88FC, 0xE3FC, 0x88FD, 0xBB73, 0x88FE, 0xE3FA, 0x8901, 0xDBCE, 0x8902, 0xBB6F, 0x8905, 0xE7C2, + 0x8906, 0xE7C9, 0x8907, 0xBDC6, 0x8909, 0xE7CD, 0x890A, 0xBDCA, 0x890B, 0xE7C5, 0x890C, 0xE7C3, 0x890E, 0xE7CC, 0x8910, 0xBDC5, + 0x8911, 0xE7CB, 0x8912, 0xBDC7, 0x8913, 0xBDC8, 0x8914, 0xE7C4, 0x8915, 0xBDC9, 0x8916, 0xE7CA, 0x8917, 0xE7C6, 0x8918, 0xE7C7, + 0x8919, 0xE7C8, 0x891A, 0xBB75, 0x891E, 0xEB70, 0x891F, 0xEB7C, 0x8921, 0xBFCA, 0x8922, 0xEB77, 0x8923, 0xEB79, 0x8925, 0xBFC8, + 0x8926, 0xEB71, 0x8927, 0xEB75, 0x8929, 0xEB78, 0x892A, 0xBFC6, 0x892B, 0xBFC9, 0x892C, 0xEB7B, 0x892D, 0xEB73, 0x892E, 0xEB74, + 0x892F, 0xEB7A, 0x8930, 0xEB72, 0x8931, 0xEB76, 0x8932, 0xBFC7, 0x8933, 0xEE72, 0x8935, 0xEE71, 0x8936, 0xC1B7, 0x8937, 0xEE77, + 0x8938, 0xC1B9, 0x893B, 0xC1B6, 0x893C, 0xEE73, 0x893D, 0xC1BA, 0x893E, 0xEE74, 0x8941, 0xEE75, 0x8942, 0xEE78, 0x8944, 0xC1B8, + 0x8946, 0xF0D6, 0x8949, 0xF0D9, 0x894B, 0xF0D3, 0x894C, 0xF0D5, 0x894F, 0xF0D4, 0x8950, 0xF0D7, 0x8951, 0xF0D8, 0x8952, 0xEE76, + 0x8953, 0xF0D2, 0x8956, 0xC3CD, 0x8957, 0xF2EC, 0x8958, 0xF2EF, 0x8959, 0xF2F1, 0x895A, 0xF2EA, 0x895B, 0xF2EB, 0x895C, 0xF2EE, + 0x895D, 0xF2F0, 0x895E, 0xC3CE, 0x895F, 0xC3CC, 0x8960, 0xC3CB, 0x8961, 0xF2ED, 0x8962, 0xF2E9, 0x8963, 0xF4CA, 0x8964, 0xC4B0, + 0x8966, 0xF4CB, 0x8969, 0xF649, 0x896A, 0xC4FB, 0x896B, 0xF64B, 0x896C, 0xC4FC, 0x896D, 0xF648, 0x896E, 0xF64A, 0x896F, 0xC5A8, + 0x8971, 0xF752, 0x8972, 0xC5A7, 0x8973, 0xF7FD, 0x8974, 0xF7FC, 0x8976, 0xF7FB, 0x8979, 0xF948, 0x897A, 0xF949, 0x897B, 0xF94B, + 0x897C, 0xF94A, 0x897E, 0xCA50, 0x897F, 0xA6E8, 0x8981, 0xAD6E, 0x8982, 0xD7C5, 0x8983, 0xB5F7, 0x8985, 0xDFFA, 0x8986, 0xC2D0, + 0x8988, 0xF2F2, 0x898B, 0xA8A3, 0x898F, 0xB357, 0x8993, 0xB356, 0x8995, 0xDBD0, 0x8996, 0xB5F8, 0x8997, 0xDBD2, 0x8998, 0xDBD1, + 0x899B, 0xDFFB, 0x899C, 0xB8D0, 0x899D, 0xE443, 0x899E, 0xE446, 0x899F, 0xE445, 0x89A1, 0xE444, 0x89A2, 0xE7CE, 0x89A3, 0xE7D0, + 0x89A4, 0xE7CF, 0x89A6, 0xBFCC, 0x89AA, 0xBFCB, 0x89AC, 0xC1BB, 0x89AD, 0xEE79, 0x89AE, 0xEE7B, 0x89AF, 0xEE7A, 0x89B2, 0xC2D1, + 0x89B6, 0xF2F4, 0x89B7, 0xF2F3, 0x89B9, 0xF4CC, 0x89BA, 0xC4B1, 0x89BD, 0xC4FD, 0x89BE, 0xF754, 0x89BF, 0xF753, 0x89C0, 0xC65B, + 0x89D2, 0xA8A4, 0x89D3, 0xD0AF, 0x89D4, 0xAD6F, 0x89D5, 0xD7C8, 0x89D6, 0xD7C6, 0x89D9, 0xD7C7, 0x89DA, 0xDBD4, 0x89DB, 0xDBD5, + 0x89DC, 0xE043, 0x89DD, 0xDBD3, 0x89DF, 0xDFFC, 0x89E0, 0xE041, 0x89E1, 0xE040, 0x89E2, 0xE042, 0x89E3, 0xB8D1, 0x89E4, 0xDFFE, + 0x89E5, 0xDFFD, 0x89E6, 0xE044, 0x89E8, 0xE449, 0x89E9, 0xE447, 0x89EB, 0xE448, 0x89EC, 0xE7D3, 0x89ED, 0xE7D1, 0x89F0, 0xE7D2, + 0x89F1, 0xEB7D, 0x89F2, 0xEE7C, 0x89F3, 0xEE7D, 0x89F4, 0xC2D2, 0x89F6, 0xF2F5, 0x89F7, 0xF4CD, 0x89F8, 0xC4B2, 0x89FA, 0xF64C, + 0x89FB, 0xF755, 0x89FC, 0xC5A9, 0x89FE, 0xF7FE, 0x89FF, 0xF94C, 0x8A00, 0xA8A5, 0x8A02, 0xAD71, 0x8A03, 0xAD72, 0x8A04, 0xD0B0, + 0x8A07, 0xD0B1, 0x8A08, 0xAD70, 0x8A0A, 0xB054, 0x8A0C, 0xB052, 0x8A0E, 0xB051, 0x8A0F, 0xB058, 0x8A10, 0xB050, 0x8A11, 0xB059, + 0x8A12, 0xD3DD, 0x8A13, 0xB056, 0x8A15, 0xB053, 0x8A16, 0xB057, 0x8A17, 0xB055, 0x8A18, 0xB04F, 0x8A1B, 0xB35F, 0x8A1D, 0xB359, + 0x8A1E, 0xD7CC, 0x8A1F, 0xB35E, 0x8A22, 0xB360, 0x8A23, 0xB35A, 0x8A25, 0xB35B, 0x8A27, 0xD7CA, 0x8A2A, 0xB358, 0x8A2C, 0xD7CB, + 0x8A2D, 0xB35D, 0x8A30, 0xD7C9, 0x8A31, 0xB35C, 0x8A34, 0xB644, 0x8A36, 0xB646, 0x8A39, 0xDBD8, 0x8A3A, 0xB645, 0x8A3B, 0xB5F9, + 0x8A3C, 0xB5FD, 0x8A3E, 0xB8E4, 0x8A3F, 0xE049, 0x8A40, 0xDBDA, 0x8A41, 0xB5FE, 0x8A44, 0xDBDD, 0x8A45, 0xDBDE, 0x8A46, 0xB643, + 0x8A48, 0xDBE0, 0x8A4A, 0xDBE2, 0x8A4C, 0xDBE3, 0x8A4D, 0xDBD7, 0x8A4E, 0xDBD6, 0x8A4F, 0xDBE4, 0x8A50, 0xB642, 0x8A51, 0xDBE1, + 0x8A52, 0xDBDF, 0x8A54, 0xB640, 0x8A55, 0xB5FB, 0x8A56, 0xB647, 0x8A57, 0xDBDB, 0x8A58, 0xDBDC, 0x8A59, 0xDBD9, 0x8A5B, 0xB641, + 0x8A5E, 0xB5FC, 0x8A60, 0xB5FA, 0x8A61, 0xE048, 0x8A62, 0xB8DF, 0x8A63, 0xB8DA, 0x8A66, 0xB8D5, 0x8A68, 0xB8E5, 0x8A69, 0xB8D6, + 0x8A6B, 0xB8D2, 0x8A6C, 0xB8E1, 0x8A6D, 0xB8DE, 0x8A6E, 0xB8E0, 0x8A70, 0xB8D7, 0x8A71, 0xB8DC, 0x8A72, 0xB8D3, 0x8A73, 0xB8D4, + 0x8A74, 0xE050, 0x8A75, 0xE04D, 0x8A76, 0xE045, 0x8A77, 0xE04A, 0x8A79, 0xB8E2, 0x8A7A, 0xE051, 0x8A7B, 0xB8E3, 0x8A7C, 0xB8D9, + 0x8A7F, 0xE047, 0x8A81, 0xE04F, 0x8A82, 0xE04B, 0x8A83, 0xE04E, 0x8A84, 0xE04C, 0x8A85, 0xB8DD, 0x8A86, 0xE046, 0x8A87, 0xB8D8, + 0x8A8B, 0xE44C, 0x8A8C, 0xBB78, 0x8A8D, 0xBB7B, 0x8A8F, 0xE44E, 0x8A91, 0xBBA5, 0x8A92, 0xE44D, 0x8A93, 0xBB7D, 0x8A95, 0xBDCF, + 0x8A96, 0xE44F, 0x8A98, 0xBBA4, 0x8A99, 0xE44B, 0x8A9A, 0xBBA6, 0x8A9E, 0xBB79, 0x8AA0, 0xB8DB, 0x8AA1, 0xBB7C, 0x8AA3, 0xBB7A, + 0x8AA4, 0xBB7E, 0x8AA5, 0xBBA2, 0x8AA6, 0xBB77, 0x8AA7, 0xBBA7, 0x8AA8, 0xBBA3, 0x8AAA, 0xBBA1, 0x8AAB, 0xE44A, 0x8AB0, 0xBDD6, + 0x8AB2, 0xBDD2, 0x8AB6, 0xBDD9, 0x8AB8, 0xE7D6, 0x8AB9, 0xBDDA, 0x8ABA, 0xE7E2, 0x8ABB, 0xE7DB, 0x8ABC, 0xBDCB, 0x8ABD, 0xE7E3, + 0x8ABE, 0xE7DD, 0x8ABF, 0xBDD5, 0x8AC0, 0xE7DE, 0x8AC2, 0xBDD4, 0x8AC3, 0xE7E1, 0x8AC4, 0xBDCE, 0x8AC5, 0xE7DF, 0x8AC6, 0xE7D5, + 0x8AC7, 0xBDCD, 0x8AC8, 0xEBAA, 0x8AC9, 0xBDD3, 0x8ACB, 0xBDD0, 0x8ACD, 0xBDD8, 0x8ACF, 0xE7D4, 0x8AD1, 0xE7D8, 0x8AD2, 0xBDCC, + 0x8AD3, 0xE7D7, 0x8AD4, 0xE7D9, 0x8AD5, 0xE7DA, 0x8AD6, 0xBDD7, 0x8AD7, 0xE7DC, 0x8AD8, 0xE7E0, 0x8AD9, 0xE7E4, 0x8ADB, 0xBDDB, + 0x8ADC, 0xBFD2, 0x8ADD, 0xEBA5, 0x8ADE, 0xEBAB, 0x8ADF, 0xEBA8, 0x8AE0, 0xEB7E, 0x8AE1, 0xEBAC, 0x8AE2, 0xEBA1, 0x8AE4, 0xEBA7, + 0x8AE6, 0xBFCD, 0x8AE7, 0xBFD3, 0x8AE8, 0xEBAD, 0x8AEB, 0xBFCF, 0x8AED, 0xBFD9, 0x8AEE, 0xBFD4, 0x8AEF, 0xEBAF, 0x8AF0, 0xEBA9, + 0x8AF1, 0xBFD0, 0x8AF2, 0xEBA2, 0x8AF3, 0xBFDA, 0x8AF4, 0xEBA3, 0x8AF5, 0xEBA4, 0x8AF6, 0xBFDB, 0x8AF7, 0xBFD8, 0x8AF8, 0xBDD1, + 0x8AFA, 0xBFCE, 0x8AFB, 0xEBB0, 0x8AFC, 0xBFDC, 0x8AFE, 0xBFD5, 0x8AFF, 0xEBAE, 0x8B00, 0xBFD1, 0x8B01, 0xBFD6, 0x8B02, 0xBFD7, + 0x8B04, 0xC1C3, 0x8B05, 0xEEA4, 0x8B06, 0xEEAD, 0x8B07, 0xEEAA, 0x8B08, 0xEEAC, 0x8B0A, 0xC1C0, 0x8B0B, 0xEEA5, 0x8B0D, 0xEEAB, + 0x8B0E, 0xC1BC, 0x8B0F, 0xEEA7, 0x8B10, 0xC1C4, 0x8B11, 0xEEA3, 0x8B12, 0xEEA8, 0x8B13, 0xEEAF, 0x8B14, 0xEBA6, 0x8B15, 0xEEA9, + 0x8B16, 0xEEA2, 0x8B17, 0xC1BD, 0x8B18, 0xEEA1, 0x8B19, 0xC1BE, 0x8B1A, 0xEEB0, 0x8B1B, 0xC1BF, 0x8B1C, 0xEEAE, 0x8B1D, 0xC1C2, + 0x8B1E, 0xEE7E, 0x8B20, 0xC1C1, 0x8B22, 0xEEA6, 0x8B23, 0xF0DC, 0x8B24, 0xF0EA, 0x8B25, 0xF0E5, 0x8B26, 0xF0E7, 0x8B27, 0xF0DB, + 0x8B28, 0xC2D3, 0x8B2A, 0xF0DA, 0x8B2B, 0xC2D6, 0x8B2C, 0xC2D5, 0x8B2E, 0xF0E9, 0x8B2F, 0xF0E1, 0x8B30, 0xF0DE, 0x8B31, 0xF0E4, + 0x8B33, 0xF0DD, 0x8B35, 0xF0DF, 0x8B36, 0xF0E8, 0x8B37, 0xF0E6, 0x8B39, 0xC2D4, 0x8B3A, 0xF0ED, 0x8B3B, 0xF0EB, 0x8B3C, 0xF0E2, + 0x8B3D, 0xF0EC, 0x8B3E, 0xF0E3, 0x8B40, 0xF2F9, 0x8B41, 0xC3CF, 0x8B42, 0xF341, 0x8B45, 0xF64F, 0x8B46, 0xC3D6, 0x8B47, 0xF0E0, + 0x8B48, 0xF2F7, 0x8B49, 0xC3D2, 0x8B4A, 0xF2F8, 0x8B4B, 0xF2FD, 0x8B4E, 0xC3D4, 0x8B4F, 0xC3D5, 0x8B50, 0xF2F6, 0x8B51, 0xF340, + 0x8B52, 0xF342, 0x8B53, 0xF2FA, 0x8B54, 0xF2FC, 0x8B55, 0xF2FE, 0x8B56, 0xF2FB, 0x8B57, 0xF343, 0x8B58, 0xC3D1, 0x8B59, 0xC3D7, + 0x8B5A, 0xC3D3, 0x8B5C, 0xC3D0, 0x8B5D, 0xF4D0, 0x8B5F, 0xC4B7, 0x8B60, 0xF4CE, 0x8B63, 0xF4D2, 0x8B65, 0xF4D3, 0x8B66, 0xC4B5, + 0x8B67, 0xF4D4, 0x8B68, 0xF4D1, 0x8B6A, 0xF4CF, 0x8B6B, 0xC4B8, 0x8B6C, 0xC4B4, 0x8B6D, 0xF4D5, 0x8B6F, 0xC4B6, 0x8B70, 0xC4B3, + 0x8B74, 0xC4FE, 0x8B77, 0xC540, 0x8B78, 0xF64E, 0x8B79, 0xF64D, 0x8B7A, 0xF650, 0x8B7B, 0xF651, 0x8B7D, 0xC541, 0x8B7E, 0xF756, + 0x8B7F, 0xF75B, 0x8B80, 0xC5AA, 0x8B82, 0xF758, 0x8B84, 0xF757, 0x8B85, 0xF75A, 0x8B86, 0xF759, 0x8B88, 0xF843, 0x8B8A, 0xC5DC, + 0x8B8B, 0xF842, 0x8B8C, 0xF840, 0x8B8E, 0xF841, 0x8B92, 0xC5FE, 0x8B93, 0xC5FD, 0x8B94, 0xF8C1, 0x8B95, 0xF8C2, 0x8B96, 0xC640, + 0x8B98, 0xF94D, 0x8B99, 0xF94E, 0x8B9A, 0xC667, 0x8B9C, 0xC66D, 0x8B9E, 0xF9A9, 0x8B9F, 0xF9C8, 0x8C37, 0xA8A6, 0x8C39, 0xD7CD, + 0x8C3B, 0xD7CE, 0x8C3C, 0xE052, 0x8C3D, 0xE450, 0x8C3E, 0xE7E5, 0x8C3F, 0xC1C6, 0x8C41, 0xC1C5, 0x8C42, 0xF0EE, 0x8C43, 0xF344, + 0x8C45, 0xF844, 0x8C46, 0xA8A7, 0x8C47, 0xD3DE, 0x8C48, 0xB05A, 0x8C49, 0xB361, 0x8C4A, 0xE054, 0x8C4B, 0xE053, 0x8C4C, 0xBDDC, + 0x8C4D, 0xE7E6, 0x8C4E, 0xBDDD, 0x8C4F, 0xEEB1, 0x8C50, 0xC2D7, 0x8C54, 0xC676, 0x8C55, 0xA8A8, 0x8C56, 0xCDCB, 0x8C57, 0xD3DF, + 0x8C5A, 0xB362, 0x8C5C, 0xD7CF, 0x8C5D, 0xD7D0, 0x8C5F, 0xDBE5, 0x8C61, 0xB648, 0x8C62, 0xB8E6, 0x8C64, 0xE056, 0x8C65, 0xE055, + 0x8C66, 0xE057, 0x8C68, 0xE451, 0x8C69, 0xE452, 0x8C6A, 0xBBA8, 0x8C6B, 0xBFDD, 0x8C6C, 0xBDDE, 0x8C6D, 0xBFDE, 0x8C6F, 0xEEB5, + 0x8C70, 0xEEB2, 0x8C71, 0xEEB4, 0x8C72, 0xEEB3, 0x8C73, 0xC1C7, 0x8C75, 0xF0EF, 0x8C76, 0xF346, 0x8C77, 0xF345, 0x8C78, 0xCBA4, + 0x8C79, 0xB05C, 0x8C7A, 0xB05B, 0x8C7B, 0xD3E0, 0x8C7D, 0xD7D1, 0x8C80, 0xDBE7, 0x8C81, 0xDBE6, 0x8C82, 0xB649, 0x8C84, 0xE059, + 0x8C85, 0xE05A, 0x8C86, 0xE058, 0x8C89, 0xB8E8, 0x8C8A, 0xB8E7, 0x8C8C, 0xBBAA, 0x8C8D, 0xBBA9, 0x8C8F, 0xE7E7, 0x8C90, 0xEBB3, + 0x8C91, 0xEBB1, 0x8C92, 0xEBB2, 0x8C93, 0xBFDF, 0x8C94, 0xEEB7, 0x8C95, 0xEEB6, 0x8C97, 0xF0F2, 0x8C98, 0xF0F1, 0x8C99, 0xF0F0, + 0x8C9A, 0xF347, 0x8C9C, 0xF9AA, 0x8C9D, 0xA8A9, 0x8C9E, 0xAD73, 0x8CA0, 0xAD74, 0x8CA1, 0xB05D, 0x8CA2, 0xB05E, 0x8CA3, 0xD3E2, + 0x8CA4, 0xD3E1, 0x8CA5, 0xD7D2, 0x8CA7, 0xB368, 0x8CA8, 0xB366, 0x8CA9, 0xB363, 0x8CAA, 0xB367, 0x8CAB, 0xB365, 0x8CAC, 0xB364, + 0x8CAF, 0xB64A, 0x8CB0, 0xDBEA, 0x8CB2, 0xB8ED, 0x8CB3, 0xB64C, 0x8CB4, 0xB651, 0x8CB5, 0xDBEC, 0x8CB6, 0xB653, 0x8CB7, 0xB652, + 0x8CB8, 0xB655, 0x8CB9, 0xDBEB, 0x8CBA, 0xDBE8, 0x8CBB, 0xB64F, 0x8CBC, 0xB64B, 0x8CBD, 0xB64D, 0x8CBE, 0xDBE9, 0x8CBF, 0xB654, + 0x8CC0, 0xB650, 0x8CC1, 0xB64E, 0x8CC2, 0xB8EF, 0x8CC3, 0xB8EE, 0x8CC4, 0xB8EC, 0x8CC5, 0xB8F0, 0x8CC7, 0xB8EA, 0x8CC8, 0xB8EB, + 0x8CCA, 0xB8E9, 0x8CCC, 0xE05B, 0x8CCF, 0xE454, 0x8CD1, 0xBBAC, 0x8CD2, 0xBBAD, 0x8CD3, 0xBBAB, 0x8CD5, 0xE453, 0x8CD7, 0xE455, + 0x8CD9, 0xE7EA, 0x8CDA, 0xE7EC, 0x8CDC, 0xBDE7, 0x8CDD, 0xE7ED, 0x8CDE, 0xBDE0, 0x8CDF, 0xE7E9, 0x8CE0, 0xBDDF, 0x8CE1, 0xBDE9, + 0x8CE2, 0xBDE5, 0x8CE3, 0xBDE6, 0x8CE4, 0xBDE2, 0x8CE5, 0xE7E8, 0x8CE6, 0xBDE1, 0x8CE7, 0xE7EE, 0x8CE8, 0xE7EB, 0x8CEA, 0xBDE8, + 0x8CEC, 0xBDE3, 0x8CED, 0xBDE4, 0x8CEE, 0xEBB5, 0x8CF0, 0xEBB7, 0x8CF1, 0xEBB6, 0x8CF3, 0xEBB8, 0x8CF4, 0xBFE0, 0x8CF5, 0xEBB4, + 0x8CF8, 0xC1CB, 0x8CF9, 0xEEB8, 0x8CFA, 0xC1C8, 0x8CFB, 0xC1CC, 0x8CFC, 0xC1CA, 0x8CFD, 0xC1C9, 0x8CFE, 0xF0F3, 0x8D00, 0xF0F6, + 0x8D02, 0xF0F5, 0x8D04, 0xF0F4, 0x8D05, 0xC2D8, 0x8D06, 0xF348, 0x8D07, 0xF349, 0x8D08, 0xC3D8, 0x8D09, 0xF34A, 0x8D0A, 0xC3D9, + 0x8D0D, 0xC4BA, 0x8D0F, 0xC4B9, 0x8D10, 0xF652, 0x8D13, 0xC542, 0x8D14, 0xF653, 0x8D15, 0xF75C, 0x8D16, 0xC5AB, 0x8D17, 0xC5AC, + 0x8D19, 0xF845, 0x8D1B, 0xC642, 0x8D64, 0xA8AA, 0x8D66, 0xB36A, 0x8D67, 0xB369, 0x8D68, 0xE05C, 0x8D69, 0xE05D, 0x8D6B, 0xBBAE, + 0x8D6C, 0xEBB9, 0x8D6D, 0xBDEA, 0x8D6E, 0xEBBA, 0x8D6F, 0xEEB9, 0x8D70, 0xA8AB, 0x8D72, 0xD0B2, 0x8D73, 0xAD76, 0x8D74, 0xAD75, + 0x8D76, 0xD3E3, 0x8D77, 0xB05F, 0x8D78, 0xD3E4, 0x8D79, 0xD7D5, 0x8D7B, 0xD7D4, 0x8D7D, 0xD7D3, 0x8D80, 0xDBEE, 0x8D81, 0xB658, + 0x8D84, 0xDBED, 0x8D85, 0xB657, 0x8D89, 0xDBEF, 0x8D8A, 0xB656, 0x8D8C, 0xE05F, 0x8D8D, 0xE062, 0x8D8E, 0xE060, 0x8D8F, 0xE061, + 0x8D90, 0xE065, 0x8D91, 0xE05E, 0x8D92, 0xE066, 0x8D93, 0xE063, 0x8D94, 0xE064, 0x8D95, 0xBBB0, 0x8D96, 0xE456, 0x8D99, 0xBBAF, + 0x8D9B, 0xE7F2, 0x8D9C, 0xE7F0, 0x8D9F, 0xBDEB, 0x8DA0, 0xE7EF, 0x8DA1, 0xE7F1, 0x8DA3, 0xBDEC, 0x8DA5, 0xEBBB, 0x8DA7, 0xEBBC, + 0x8DA8, 0xC1CD, 0x8DAA, 0xF34C, 0x8DAB, 0xF34E, 0x8DAC, 0xF34B, 0x8DAD, 0xF34D, 0x8DAE, 0xF4D6, 0x8DAF, 0xF654, 0x8DB2, 0xF96F, + 0x8DB3, 0xA8AC, 0x8DB4, 0xAD77, 0x8DB5, 0xD3E5, 0x8DB6, 0xD3E7, 0x8DB7, 0xD3E6, 0x8DB9, 0xD7D8, 0x8DBA, 0xB36C, 0x8DBC, 0xD7D6, + 0x8DBE, 0xB36B, 0x8DBF, 0xD7D9, 0x8DC1, 0xD7DA, 0x8DC2, 0xD7D7, 0x8DC5, 0xDBFB, 0x8DC6, 0xB660, 0x8DC7, 0xDBF3, 0x8DC8, 0xDBF9, + 0x8DCB, 0xB65B, 0x8DCC, 0xB65E, 0x8DCD, 0xDBF2, 0x8DCE, 0xB659, 0x8DCF, 0xDBF6, 0x8DD0, 0xE06C, 0x8DD1, 0xB65D, 0x8DD3, 0xDBF1, + 0x8DD5, 0xDBF7, 0x8DD6, 0xDBF4, 0x8DD7, 0xDBFA, 0x8DD8, 0xDBF0, 0x8DD9, 0xDBF8, 0x8DDA, 0xB65C, 0x8DDB, 0xB65F, 0x8DDC, 0xDBF5, + 0x8DDD, 0xB65A, 0x8DDF, 0xB8F2, 0x8DE0, 0xE068, 0x8DE1, 0xB8F1, 0x8DE2, 0xE06F, 0x8DE3, 0xE06E, 0x8DE4, 0xB8F8, 0x8DE6, 0xB8F9, + 0x8DE7, 0xE070, 0x8DE8, 0xB8F3, 0x8DE9, 0xE06D, 0x8DEA, 0xB8F7, 0x8DEB, 0xE072, 0x8DEC, 0xE069, 0x8DEE, 0xE06B, 0x8DEF, 0xB8F4, + 0x8DF0, 0xE067, 0x8DF1, 0xE06A, 0x8DF2, 0xE071, 0x8DF3, 0xB8F5, 0x8DF4, 0xE073, 0x8DFA, 0xB8F6, 0x8DFC, 0xBBB1, 0x8DFD, 0xE45B, + 0x8DFE, 0xE461, 0x8DFF, 0xE459, 0x8E00, 0xE462, 0x8E02, 0xE458, 0x8E03, 0xE45D, 0x8E04, 0xE463, 0x8E05, 0xE460, 0x8E06, 0xE45F, + 0x8E07, 0xE45E, 0x8E09, 0xE457, 0x8E0A, 0xE45C, 0x8E0D, 0xE45A, 0x8E0F, 0xBDF1, 0x8E10, 0xBDEE, 0x8E11, 0xE7FB, 0x8E12, 0xE841, + 0x8E13, 0xE843, 0x8E14, 0xE840, 0x8E15, 0xE7F8, 0x8E16, 0xE7FA, 0x8E17, 0xE845, 0x8E18, 0xE842, 0x8E19, 0xE7FC, 0x8E1A, 0xE846, + 0x8E1B, 0xE7F9, 0x8E1C, 0xE844, 0x8E1D, 0xBDEF, 0x8E1E, 0xBDF5, 0x8E1F, 0xBDF3, 0x8E20, 0xE7F3, 0x8E21, 0xBDF4, 0x8E22, 0xBDF0, + 0x8E23, 0xE7F4, 0x8E24, 0xE7F6, 0x8E25, 0xE7F5, 0x8E26, 0xE7FD, 0x8E27, 0xE7FE, 0x8E29, 0xBDF2, 0x8E2B, 0xBDED, 0x8E2E, 0xE7F7, + 0x8E30, 0xEBC6, 0x8E31, 0xBFE2, 0x8E33, 0xEBBD, 0x8E34, 0xBFE3, 0x8E35, 0xBFE6, 0x8E36, 0xEBC2, 0x8E38, 0xEBBF, 0x8E39, 0xBFE5, + 0x8E3C, 0xEBC3, 0x8E3D, 0xEBC4, 0x8E3E, 0xEBBE, 0x8E3F, 0xEBC7, 0x8E40, 0xEBC0, 0x8E41, 0xEBC5, 0x8E42, 0xBFE4, 0x8E44, 0xBFE1, + 0x8E45, 0xEBC1, 0x8E47, 0xEEBF, 0x8E48, 0xC1D0, 0x8E49, 0xC1CE, 0x8E4A, 0xC1D1, 0x8E4B, 0xC1CF, 0x8E4C, 0xEEBE, 0x8E4D, 0xEEBB, + 0x8E4E, 0xEEBA, 0x8E50, 0xEEBD, 0x8E53, 0xEEBC, 0x8E54, 0xF145, 0x8E55, 0xC2DE, 0x8E56, 0xF0FB, 0x8E57, 0xF0FA, 0x8E59, 0xC2D9, + 0x8E5A, 0xF141, 0x8E5B, 0xF140, 0x8E5C, 0xF0F7, 0x8E5D, 0xF143, 0x8E5E, 0xF0FC, 0x8E5F, 0xC2DD, 0x8E60, 0xF0F9, 0x8E61, 0xF142, + 0x8E62, 0xF0F8, 0x8E63, 0xC2DA, 0x8E64, 0xC2DC, 0x8E65, 0xF0FD, 0x8E66, 0xC2DB, 0x8E67, 0xF0FE, 0x8E69, 0xF144, 0x8E6A, 0xF352, + 0x8E6C, 0xC3DE, 0x8E6D, 0xF34F, 0x8E6F, 0xF353, 0x8E72, 0xC3DB, 0x8E73, 0xF351, 0x8E74, 0xC3E0, 0x8E76, 0xC3DD, 0x8E78, 0xF350, + 0x8E7A, 0xC3DF, 0x8E7B, 0xF354, 0x8E7C, 0xC3DA, 0x8E81, 0xC4BC, 0x8E82, 0xC4BE, 0x8E84, 0xF4D9, 0x8E85, 0xC4BD, 0x8E86, 0xF4D7, + 0x8E87, 0xC3DC, 0x8E88, 0xF4D8, 0x8E89, 0xC4BB, 0x8E8A, 0xC543, 0x8E8B, 0xC545, 0x8E8C, 0xF656, 0x8E8D, 0xC544, 0x8E8E, 0xF655, + 0x8E90, 0xF761, 0x8E91, 0xC5AD, 0x8E92, 0xF760, 0x8E93, 0xC5AE, 0x8E94, 0xF75E, 0x8E95, 0xF75D, 0x8E96, 0xF762, 0x8E97, 0xF763, + 0x8E98, 0xF846, 0x8E9A, 0xF75F, 0x8E9D, 0xF8C6, 0x8E9E, 0xF8C3, 0x8E9F, 0xF8C4, 0x8EA0, 0xF8C5, 0x8EA1, 0xC65C, 0x8EA3, 0xF951, + 0x8EA4, 0xF950, 0x8EA5, 0xF94F, 0x8EA6, 0xF970, 0x8EA8, 0xF9BE, 0x8EA9, 0xF9AB, 0x8EAA, 0xC66E, 0x8EAB, 0xA8AD, 0x8EAC, 0xB060, + 0x8EB2, 0xB8FA, 0x8EBA, 0xBDF6, 0x8EBD, 0xEBC8, 0x8EC0, 0xC2DF, 0x8EC2, 0xF355, 0x8EC9, 0xF9AC, 0x8ECA, 0xA8AE, 0x8ECB, 0xAAEE, + 0x8ECC, 0xAD79, 0x8ECD, 0xAD78, 0x8ECF, 0xB063, 0x8ED1, 0xD3E8, 0x8ED2, 0xB061, 0x8ED3, 0xD3E9, 0x8ED4, 0xB062, 0x8ED7, 0xD7DF, + 0x8ED8, 0xD7DB, 0x8EDB, 0xB36D, 0x8EDC, 0xD7DE, 0x8EDD, 0xD7DD, 0x8EDE, 0xD7DC, 0x8EDF, 0xB36E, 0x8EE0, 0xD7E0, 0x8EE1, 0xD7E1, + 0x8EE5, 0xDC43, 0x8EE6, 0xDC41, 0x8EE7, 0xDC45, 0x8EE8, 0xDC46, 0x8EE9, 0xDC4C, 0x8EEB, 0xDC48, 0x8EEC, 0xDC4A, 0x8EEE, 0xDC42, + 0x8EEF, 0xDBFC, 0x8EF1, 0xDC49, 0x8EF4, 0xDC4B, 0x8EF5, 0xDC44, 0x8EF6, 0xDC47, 0x8EF7, 0xDBFD, 0x8EF8, 0xB662, 0x8EF9, 0xDC40, + 0x8EFA, 0xDBFE, 0x8EFB, 0xB661, 0x8EFC, 0xB663, 0x8EFE, 0xB8FD, 0x8EFF, 0xE075, 0x8F00, 0xE077, 0x8F01, 0xE076, 0x8F02, 0xE07B, + 0x8F03, 0xB8FB, 0x8F05, 0xE078, 0x8F06, 0xE074, 0x8F07, 0xE079, 0x8F08, 0xE07A, 0x8F09, 0xB8FC, 0x8F0A, 0xB8FE, 0x8F0B, 0xE07C, + 0x8F0D, 0xE467, 0x8F0E, 0xE466, 0x8F10, 0xE464, 0x8F11, 0xE465, 0x8F12, 0xBBB3, 0x8F13, 0xBBB5, 0x8F14, 0xBBB2, 0x8F15, 0xBBB4, + 0x8F16, 0xE84D, 0x8F17, 0xE84E, 0x8F18, 0xE849, 0x8F1A, 0xE84A, 0x8F1B, 0xBDF8, 0x8F1C, 0xBDFD, 0x8F1D, 0xBDF7, 0x8F1E, 0xBDFE, + 0x8F1F, 0xBDF9, 0x8F20, 0xE84B, 0x8F23, 0xE84C, 0x8F24, 0xE848, 0x8F25, 0xBE40, 0x8F26, 0xBDFB, 0x8F29, 0xBDFA, 0x8F2A, 0xBDFC, + 0x8F2C, 0xE847, 0x8F2E, 0xEBCA, 0x8F2F, 0xBFE8, 0x8F32, 0xEBCC, 0x8F33, 0xBFEA, 0x8F34, 0xEBCF, 0x8F35, 0xEBCB, 0x8F36, 0xEBC9, + 0x8F37, 0xEBCE, 0x8F38, 0xBFE9, 0x8F39, 0xEBCD, 0x8F3B, 0xBFE7, 0x8F3E, 0xC1D3, 0x8F3F, 0xC1D6, 0x8F40, 0xEEC1, 0x8F42, 0xC1D4, + 0x8F43, 0xEEC0, 0x8F44, 0xC1D2, 0x8F45, 0xC1D5, 0x8F46, 0xF146, 0x8F47, 0xF147, 0x8F48, 0xF148, 0x8F49, 0xC2E0, 0x8F4B, 0xF149, + 0x8F4D, 0xC2E1, 0x8F4E, 0xC3E2, 0x8F4F, 0xF358, 0x8F50, 0xF359, 0x8F51, 0xF357, 0x8F52, 0xF356, 0x8F53, 0xF35A, 0x8F54, 0xC3E1, + 0x8F55, 0xF4DD, 0x8F56, 0xF4DB, 0x8F57, 0xF4DC, 0x8F58, 0xF4DE, 0x8F59, 0xF4DA, 0x8F5A, 0xF4DF, 0x8F5B, 0xF658, 0x8F5D, 0xF659, + 0x8F5E, 0xF657, 0x8F5F, 0xC546, 0x8F60, 0xF764, 0x8F61, 0xC5AF, 0x8F62, 0xF765, 0x8F63, 0xF848, 0x8F64, 0xF847, 0x8F9B, 0xA8AF, + 0x8F9C, 0xB664, 0x8F9F, 0xB940, 0x8FA3, 0xBBB6, 0x8FA6, 0xBFEC, 0x8FA8, 0xBFEB, 0x8FAD, 0xC3E3, 0x8FAE, 0xC47C, 0x8FAF, 0xC547, + 0x8FB0, 0xA8B0, 0x8FB1, 0xB064, 0x8FB2, 0xB941, 0x8FB4, 0xF35B, 0x8FBF, 0xCBA6, 0x8FC2, 0xA8B1, 0x8FC4, 0xA8B4, 0x8FC5, 0xA8B3, + 0x8FC6, 0xA8B2, 0x8FC9, 0xCBA5, 0x8FCB, 0xCDCD, 0x8FCD, 0xCDCF, 0x8FCE, 0xAAEF, 0x8FD1, 0xAAF1, 0x8FD2, 0xCDCC, 0x8FD3, 0xCDCE, + 0x8FD4, 0xAAF0, 0x8FD5, 0xCDD1, 0x8FD6, 0xCDD0, 0x8FD7, 0xCDD2, 0x8FE0, 0xD0B6, 0x8FE1, 0xD0B4, 0x8FE2, 0xAD7C, 0x8FE3, 0xD0B3, + 0x8FE4, 0xADA3, 0x8FE5, 0xAD7E, 0x8FE6, 0xAD7B, 0x8FE8, 0xADA4, 0x8FEA, 0xAD7D, 0x8FEB, 0xADA2, 0x8FED, 0xADA1, 0x8FEE, 0xD0B5, + 0x8FF0, 0xAD7A, 0x8FF4, 0xB06A, 0x8FF5, 0xD3EB, 0x8FF6, 0xD3F1, 0x8FF7, 0xB067, 0x8FF8, 0xB06E, 0x8FFA, 0xB069, 0x8FFB, 0xD3EE, + 0x8FFC, 0xD3F0, 0x8FFD, 0xB06C, 0x8FFE, 0xD3EA, 0x8FFF, 0xD3ED, 0x9000, 0xB068, 0x9001, 0xB065, 0x9002, 0xD3EC, 0x9003, 0xB06B, + 0x9004, 0xD3EF, 0x9005, 0xB06D, 0x9006, 0xB066, 0x900B, 0xD7E3, 0x900C, 0xD7E6, 0x900D, 0xB370, 0x900F, 0xB37A, 0x9010, 0xB376, + 0x9011, 0xD7E4, 0x9014, 0xB37E, 0x9015, 0xB377, 0x9016, 0xB37C, 0x9017, 0xB372, 0x9019, 0xB36F, 0x901A, 0xB371, 0x901B, 0xB37D, + 0x901C, 0xD7E5, 0x901D, 0xB375, 0x901E, 0xB378, 0x901F, 0xB374, 0x9020, 0xB379, 0x9021, 0xD7E7, 0x9022, 0xB37B, 0x9023, 0xB373, + 0x9024, 0xD7E2, 0x902D, 0xDC4D, 0x902E, 0xB665, 0x902F, 0xDC4F, 0x9031, 0xB667, 0x9032, 0xB669, 0x9034, 0xDC4E, 0x9035, 0xB666, + 0x9036, 0xB66A, 0x9038, 0xB668, 0x903C, 0xB947, 0x903D, 0xE0A3, 0x903E, 0xB94F, 0x903F, 0xE07E, 0x9041, 0xB950, 0x9042, 0xB945, + 0x9044, 0xE0A1, 0x9047, 0xB94A, 0x9049, 0xE0A2, 0x904A, 0xB943, 0x904B, 0xB942, 0x904D, 0xB94D, 0x904E, 0xB94C, 0x904F, 0xB94B, + 0x9050, 0xB949, 0x9051, 0xB94E, 0x9052, 0xE07D, 0x9053, 0xB944, 0x9054, 0xB946, 0x9055, 0xB948, 0x9058, 0xBBB8, 0x9059, 0xBBBB, + 0x905B, 0xBBBF, 0x905C, 0xBBB9, 0x905D, 0xBBBE, 0x905E, 0xBBBC, 0x9060, 0xBBB7, 0x9062, 0xBBBD, 0x9063, 0xBBBA, 0x9067, 0xE852, + 0x9068, 0xBE43, 0x9069, 0xBE41, 0x906B, 0xE853, 0x906D, 0xBE44, 0x906E, 0xBE42, 0x906F, 0xE851, 0x9070, 0xE850, 0x9072, 0xBFF0, + 0x9073, 0xE84F, 0x9074, 0xBFEE, 0x9075, 0xBFED, 0x9076, 0xEBD0, 0x9077, 0xBE45, 0x9078, 0xBFEF, 0x9079, 0xEBD1, 0x907A, 0xBFF2, + 0x907B, 0xEBD2, 0x907C, 0xBFF1, 0x907D, 0xC1D8, 0x907E, 0xEEC3, 0x907F, 0xC1D7, 0x9080, 0xC1DC, 0x9081, 0xC1DA, 0x9082, 0xC1DB, + 0x9083, 0xC2E3, 0x9084, 0xC1D9, 0x9085, 0xEEC2, 0x9086, 0xEBD3, 0x9087, 0xC2E2, 0x9088, 0xC2E4, 0x908A, 0xC3E4, 0x908B, 0xC3E5, + 0x908D, 0xF4E0, 0x908F, 0xC5DE, 0x9090, 0xC5DD, 0x9091, 0xA8B6, 0x9094, 0xCA55, 0x9095, 0xB06F, 0x9097, 0xCA52, 0x9098, 0xCA53, + 0x9099, 0xCA51, 0x909B, 0xCA54, 0x909E, 0xCBAA, 0x909F, 0xCBA7, 0x90A0, 0xCBAC, 0x90A1, 0xCBA8, 0x90A2, 0xA8B7, 0x90A3, 0xA8BA, + 0x90A5, 0xCBA9, 0x90A6, 0xA8B9, 0x90A7, 0xCBAB, 0x90AA, 0xA8B8, 0x90AF, 0xCDD5, 0x90B0, 0xCDD7, 0x90B1, 0xAAF4, 0x90B2, 0xCDD3, + 0x90B3, 0xCDD6, 0x90B4, 0xCDD4, 0x90B5, 0xAAF2, 0x90B6, 0xAAF5, 0x90B8, 0xAAF3, 0x90BD, 0xD0B8, 0x90BE, 0xD0BC, 0x90BF, 0xD0B9, + 0x90C1, 0xADA7, 0x90C3, 0xADA8, 0x90C5, 0xD0BB, 0x90C7, 0xD0BD, 0x90C8, 0xD0BF, 0x90CA, 0xADA5, 0x90CB, 0xD0BE, 0x90CE, 0xADA6, + 0x90D4, 0xD7EE, 0x90D5, 0xD0BA, 0x90D6, 0xD3F2, 0x90D7, 0xD3FB, 0x90D8, 0xD3F9, 0x90D9, 0xD3F4, 0x90DA, 0xD3F5, 0x90DB, 0xD3FA, + 0x90DC, 0xD3FC, 0x90DD, 0xB071, 0x90DF, 0xD3F7, 0x90E0, 0xD3F3, 0x90E1, 0xB070, 0x90E2, 0xB072, 0x90E3, 0xD3F6, 0x90E4, 0xD3FD, + 0x90E5, 0xD3F8, 0x90E8, 0xB3A1, 0x90E9, 0xD7F1, 0x90EA, 0xD7E9, 0x90EB, 0xD7EF, 0x90EC, 0xD7F0, 0x90ED, 0xB3A2, 0x90EF, 0xD7E8, + 0x90F0, 0xD7EA, 0x90F1, 0xD0B7, 0x90F2, 0xD7EC, 0x90F3, 0xD7ED, 0x90F4, 0xD7EB, 0x90F5, 0xB66C, 0x90F9, 0xDC56, 0x90FA, 0xEBD4, + 0x90FB, 0xDC57, 0x90FC, 0xDC54, 0x90FD, 0xB3A3, 0x90FE, 0xB66E, 0x90FF, 0xDC53, 0x9100, 0xDC59, 0x9101, 0xDC58, 0x9102, 0xB66B, + 0x9103, 0xDC5C, 0x9104, 0xDC52, 0x9105, 0xDC5B, 0x9106, 0xDC50, 0x9107, 0xDC5A, 0x9108, 0xDC55, 0x9109, 0xB66D, 0x910B, 0xE0AA, + 0x910D, 0xE0A5, 0x910E, 0xE0AB, 0x910F, 0xE0A6, 0x9110, 0xE0A4, 0x9111, 0xE0A7, 0x9112, 0xB951, 0x9114, 0xE0A9, 0x9116, 0xE0A8, + 0x9117, 0xB952, 0x9118, 0xBBC1, 0x9119, 0xBBC0, 0x911A, 0xE46E, 0x911B, 0xE471, 0x911C, 0xE469, 0x911D, 0xE46D, 0x911E, 0xBBC2, + 0x911F, 0xE46C, 0x9120, 0xE46A, 0x9121, 0xE470, 0x9122, 0xE46B, 0x9123, 0xE468, 0x9124, 0xE46F, 0x9126, 0xE859, 0x9127, 0xBE48, + 0x9128, 0xF14A, 0x9129, 0xE856, 0x912A, 0xE857, 0x912B, 0xE855, 0x912C, 0xDC51, 0x912D, 0xBE47, 0x912E, 0xE85A, 0x912F, 0xE854, + 0x9130, 0xBE46, 0x9131, 0xBE49, 0x9132, 0xE858, 0x9133, 0xEBD5, 0x9134, 0xBFF3, 0x9135, 0xEBD6, 0x9136, 0xEBD7, 0x9138, 0xEEC4, + 0x9139, 0xC1DD, 0x913A, 0xF14B, 0x913B, 0xF14C, 0x913E, 0xF14D, 0x913F, 0xF35D, 0x9140, 0xF35C, 0x9141, 0xF4E2, 0x9143, 0xF4E1, + 0x9144, 0xF65B, 0x9145, 0xF65C, 0x9146, 0xF65A, 0x9147, 0xF766, 0x9148, 0xC5B0, 0x9149, 0xA8BB, 0x914A, 0xADAA, 0x914B, 0xADA9, + 0x914C, 0xB075, 0x914D, 0xB074, 0x914E, 0xD440, 0x914F, 0xD441, 0x9150, 0xD3FE, 0x9152, 0xB073, 0x9153, 0xD7F5, 0x9155, 0xD7F6, + 0x9156, 0xD7F2, 0x9157, 0xB3A4, 0x9158, 0xD7F3, 0x915A, 0xD7F4, 0x915F, 0xDC5F, 0x9160, 0xDC61, 0x9161, 0xDC5D, 0x9162, 0xDC60, + 0x9163, 0xB66F, 0x9164, 0xDC5E, 0x9165, 0xB670, 0x9168, 0xDD73, 0x9169, 0xB955, 0x916A, 0xB954, 0x916C, 0xB953, 0x916E, 0xE0AC, + 0x916F, 0xE0AD, 0x9172, 0xE473, 0x9173, 0xE475, 0x9174, 0xBBC6, 0x9175, 0xBBC3, 0x9177, 0xBBC5, 0x9178, 0xBBC4, 0x9179, 0xE474, + 0x917A, 0xE472, 0x9180, 0xE861, 0x9181, 0xE85E, 0x9182, 0xE85F, 0x9183, 0xBE4D, 0x9184, 0xE860, 0x9185, 0xE85B, 0x9186, 0xE85C, + 0x9187, 0xBE4A, 0x9189, 0xBE4B, 0x918A, 0xE85D, 0x918B, 0xBE4C, 0x918D, 0xEBDB, 0x918F, 0xEBDC, 0x9190, 0xEBD9, 0x9191, 0xEBDA, + 0x9192, 0xBFF4, 0x9193, 0xEBD8, 0x9199, 0xEEC8, 0x919A, 0xEEC5, 0x919B, 0xEEC7, 0x919C, 0xC1E0, 0x919D, 0xEECB, 0x919E, 0xC1DF, + 0x919F, 0xEEC9, 0x91A0, 0xEECC, 0x91A1, 0xEECA, 0x91A2, 0xEEC6, 0x91A3, 0xC1DE, 0x91A5, 0xF14F, 0x91A7, 0xF150, 0x91A8, 0xF14E, + 0x91AA, 0xF152, 0x91AB, 0xC2E5, 0x91AC, 0xC2E6, 0x91AD, 0xF35F, 0x91AE, 0xC3E7, 0x91AF, 0xF151, 0x91B0, 0xF35E, 0x91B1, 0xC3E6, + 0x91B2, 0xF4E5, 0x91B3, 0xF4E6, 0x91B4, 0xC4BF, 0x91B5, 0xF4E4, 0x91B7, 0xF4E3, 0x91B9, 0xF65D, 0x91BA, 0xC548, 0x91BC, 0xF849, + 0x91BD, 0xF8C8, 0x91BE, 0xF8C7, 0x91C0, 0xC643, 0x91C1, 0xC65D, 0x91C2, 0xF8C9, 0x91C3, 0xF971, 0x91C5, 0xC66F, 0x91C6, 0xA8BC, + 0x91C7, 0xAAF6, 0x91C9, 0xB956, 0x91CB, 0xC4C0, 0x91CC, 0xA8BD, 0x91CD, 0xADAB, 0x91CE, 0xB3A5, 0x91CF, 0xB671, 0x91D0, 0xC2E7, + 0x91D1, 0xAAF7, 0x91D3, 0xD0C1, 0x91D4, 0xD0C0, 0x91D5, 0xD442, 0x91D7, 0xB078, 0x91D8, 0xB076, 0x91D9, 0xB07A, 0x91DA, 0xD444, + 0x91DC, 0xB079, 0x91DD, 0xB077, 0x91E2, 0xD443, 0x91E3, 0xB3A8, 0x91E4, 0xD7FC, 0x91E6, 0xB3A7, 0x91E7, 0xB3A9, 0x91E8, 0xD842, + 0x91E9, 0xB3AB, 0x91EA, 0xD7FE, 0x91EB, 0xD840, 0x91EC, 0xD7F7, 0x91ED, 0xB3AA, 0x91EE, 0xD843, 0x91F1, 0xD7F9, 0x91F3, 0xD7FA, + 0x91F4, 0xD7F8, 0x91F5, 0xB3A6, 0x91F7, 0xD841, 0x91F8, 0xD7FB, 0x91F9, 0xD7FD, 0x91FD, 0xDC6D, 0x91FF, 0xDC6C, 0x9200, 0xDC6A, + 0x9201, 0xDC62, 0x9202, 0xDC71, 0x9203, 0xDC65, 0x9204, 0xDC6F, 0x9205, 0xDC76, 0x9206, 0xDC6E, 0x9207, 0xB679, 0x9209, 0xB675, + 0x920A, 0xDC63, 0x920C, 0xDC69, 0x920D, 0xB677, 0x920F, 0xDC68, 0x9210, 0xB678, 0x9211, 0xB67A, 0x9212, 0xDC6B, 0x9214, 0xB672, + 0x9215, 0xB673, 0x9216, 0xDC77, 0x9217, 0xDC75, 0x9219, 0xDC74, 0x921A, 0xDC66, 0x921C, 0xDC72, 0x921E, 0xB676, 0x9223, 0xB674, + 0x9224, 0xDC73, 0x9225, 0xDC64, 0x9226, 0xDC67, 0x9227, 0xDC70, 0x922D, 0xE4BA, 0x922E, 0xE0B7, 0x9230, 0xE0B0, 0x9231, 0xE0C3, + 0x9232, 0xE0CC, 0x9233, 0xE0B3, 0x9234, 0xB961, 0x9236, 0xE0C0, 0x9237, 0xB957, 0x9238, 0xB959, 0x9239, 0xB965, 0x923A, 0xE0B1, + 0x923D, 0xB95A, 0x923E, 0xB95C, 0x923F, 0xB966, 0x9240, 0xB95B, 0x9245, 0xB964, 0x9246, 0xE0B9, 0x9248, 0xE0AE, 0x9249, 0xB962, + 0x924A, 0xE0B8, 0x924B, 0xB95E, 0x924C, 0xE0CA, 0x924D, 0xB963, 0x924E, 0xE0C8, 0x924F, 0xE0BC, 0x9250, 0xE0C6, 0x9251, 0xB960, + 0x9252, 0xE0AF, 0x9253, 0xE0C9, 0x9254, 0xE0C4, 0x9256, 0xE0CB, 0x9257, 0xB958, 0x925A, 0xB967, 0x925B, 0xB95D, 0x925E, 0xE0B5, + 0x9260, 0xE0BD, 0x9261, 0xE0C1, 0x9263, 0xE0C5, 0x9264, 0xB95F, 0x9265, 0xE0B4, 0x9266, 0xE0B2, 0x9267, 0xE0BE, 0x926C, 0xE0BB, + 0x926D, 0xE0BA, 0x926F, 0xE0BF, 0x9270, 0xE0C2, 0x9272, 0xE0C7, 0x9276, 0xE478, 0x9278, 0xBBC7, 0x9279, 0xE4A4, 0x927A, 0xE47A, + 0x927B, 0xBBCC, 0x927C, 0xBBD0, 0x927D, 0xE4AD, 0x927E, 0xE4B5, 0x927F, 0xE4A6, 0x9280, 0xBBC8, 0x9282, 0xE4AA, 0x9283, 0xE0B6, + 0x9285, 0xBBC9, 0x9286, 0xE4B1, 0x9287, 0xE4B6, 0x9288, 0xE4AE, 0x928A, 0xE4B0, 0x928B, 0xE4B9, 0x928C, 0xE4B2, 0x928D, 0xE47E, + 0x928E, 0xE4A9, 0x9291, 0xBBD1, 0x9293, 0xBBCD, 0x9294, 0xE47C, 0x9295, 0xE4AB, 0x9296, 0xBBCB, 0x9297, 0xE4A5, 0x9298, 0xBBCA, + 0x9299, 0xE4B3, 0x929A, 0xE4A2, 0x929B, 0xE479, 0x929C, 0xBBCE, 0x929D, 0xE4B8, 0x92A0, 0xE47B, 0x92A1, 0xE4AF, 0x92A2, 0xE4AC, + 0x92A3, 0xE4A7, 0x92A4, 0xE477, 0x92A5, 0xE476, 0x92A6, 0xE4A1, 0x92A7, 0xE4B4, 0x92A8, 0xBBCF, 0x92A9, 0xE4B7, 0x92AA, 0xE47D, + 0x92AB, 0xE4A3, 0x92AC, 0xBE52, 0x92B2, 0xBE5A, 0x92B3, 0xBE55, 0x92B4, 0xE8A4, 0x92B5, 0xE8A1, 0x92B6, 0xE867, 0x92B7, 0xBE50, + 0x92B9, 0xF9D7, 0x92BB, 0xBE4F, 0x92BC, 0xBE56, 0x92C0, 0xE865, 0x92C1, 0xBE54, 0x92C2, 0xE871, 0x92C3, 0xE863, 0x92C4, 0xE864, + 0x92C5, 0xBE4E, 0x92C6, 0xE8A3, 0x92C7, 0xBE58, 0x92C8, 0xE874, 0x92C9, 0xE879, 0x92CA, 0xE873, 0x92CB, 0xEBEE, 0x92CC, 0xE86F, + 0x92CD, 0xE877, 0x92CE, 0xE875, 0x92CF, 0xE868, 0x92D0, 0xE862, 0x92D1, 0xE87D, 0x92D2, 0xBE57, 0x92D3, 0xE87E, 0x92D5, 0xE878, + 0x92D7, 0xE86D, 0x92D8, 0xE86B, 0x92D9, 0xE866, 0x92DD, 0xE86E, 0x92DE, 0xE87B, 0x92DF, 0xE86A, 0x92E0, 0xE87A, 0x92E1, 0xE8A2, + 0x92E4, 0xBE53, 0x92E6, 0xE876, 0x92E7, 0xE87C, 0x92E8, 0xE872, 0x92E9, 0xE86C, 0x92EA, 0xBE51, 0x92EE, 0xE4A8, 0x92EF, 0xE870, + 0x92F0, 0xBE59, 0x92F1, 0xE869, 0x92F7, 0xEBF4, 0x92F8, 0xBFF7, 0x92F9, 0xEBF3, 0x92FA, 0xEBF0, 0x92FB, 0xEC44, 0x92FC, 0xBFFB, + 0x92FE, 0xEC41, 0x92FF, 0xEBF8, 0x9300, 0xEC43, 0x9301, 0xEBE9, 0x9302, 0xEBF6, 0x9304, 0xBFFD, 0x9306, 0xEBE1, 0x9308, 0xEBDF, + 0x9309, 0xEC42, 0x930B, 0xEC40, 0x930C, 0xEBFE, 0x930D, 0xEBED, 0x930E, 0xEBEC, 0x930F, 0xEBE2, 0x9310, 0xC040, 0x9312, 0xEBE8, + 0x9313, 0xEBF2, 0x9314, 0xEBFD, 0x9315, 0xC043, 0x9316, 0xEC45, 0x9318, 0xC1E8, 0x9319, 0xC045, 0x931A, 0xBFFE, 0x931B, 0xEBE6, + 0x931D, 0xEBEF, 0x931E, 0xEBDE, 0x931F, 0xEBE0, 0x9320, 0xBFF5, 0x9321, 0xC042, 0x9322, 0xBFFA, 0x9323, 0xEBE7, 0x9324, 0xEBF7, + 0x9325, 0xEBF1, 0x9326, 0xC041, 0x9327, 0xEBDD, 0x9328, 0xC1E3, 0x9329, 0xEBF9, 0x932A, 0xEBFC, 0x932B, 0xBFFC, 0x932D, 0xEBEB, + 0x932E, 0xC044, 0x932F, 0xBFF9, 0x9333, 0xBFF8, 0x9334, 0xEBF5, 0x9335, 0xEBFB, 0x9336, 0xBFF6, 0x9338, 0xEBE4, 0x9339, 0xEBFA, + 0x933C, 0xEBE5, 0x9346, 0xEBEA, 0x9347, 0xEED2, 0x9349, 0xEED7, 0x934A, 0xC1E5, 0x934B, 0xC1E7, 0x934C, 0xEEDD, 0x934D, 0xC1E1, + 0x934E, 0xEEEC, 0x934F, 0xEEE3, 0x9350, 0xEED8, 0x9351, 0xEED9, 0x9352, 0xEEE2, 0x9354, 0xC1EE, 0x9355, 0xEEE1, 0x9356, 0xEED1, + 0x9357, 0xEEE0, 0x9358, 0xEED4, 0x9359, 0xEEED, 0x935A, 0xC1ED, 0x935B, 0xC1EB, 0x935C, 0xEED5, 0x935E, 0xEEE8, 0x9360, 0xEEDA, + 0x9361, 0xEEE7, 0x9363, 0xEEE9, 0x9364, 0xEED0, 0x9365, 0xC1E6, 0x9367, 0xEEEA, 0x936A, 0xEEDE, 0x936C, 0xC1EA, 0x936D, 0xEEDB, + 0x9370, 0xC1EC, 0x9371, 0xEEE4, 0x9375, 0xC1E4, 0x9376, 0xEED6, 0x9377, 0xEEE5, 0x9379, 0xEEDF, 0x937A, 0xEBE3, 0x937B, 0xEEE6, + 0x937C, 0xEED3, 0x937E, 0xC1E9, 0x9380, 0xEEEB, 0x9382, 0xC1E2, 0x9383, 0xEECE, 0x9388, 0xF160, 0x9389, 0xF159, 0x938A, 0xC2E9, + 0x938C, 0xF154, 0x938D, 0xF163, 0x938E, 0xF15B, 0x938F, 0xEEDC, 0x9391, 0xF165, 0x9392, 0xF155, 0x9394, 0xC2E8, 0x9395, 0xF15F, + 0x9396, 0xC2EA, 0x9397, 0xC2F2, 0x9398, 0xC2F0, 0x9399, 0xF161, 0x939A, 0xC2F1, 0x939B, 0xF157, 0x939D, 0xF158, 0x939E, 0xF15D, + 0x939F, 0xF162, 0x93A1, 0xEECD, 0x93A2, 0xC2EB, 0x93A3, 0xF16A, 0x93A4, 0xF167, 0x93A5, 0xF16B, 0x93A6, 0xF15E, 0x93A7, 0xF15A, + 0x93A8, 0xF168, 0x93A9, 0xF36A, 0x93AA, 0xF15C, 0x93AC, 0xC2EE, 0x93AE, 0xC2ED, 0x93AF, 0xEECF, 0x93B0, 0xC2EF, 0x93B1, 0xF164, + 0x93B2, 0xF166, 0x93B3, 0xC2EC, 0x93B4, 0xF169, 0x93B5, 0xF153, 0x93B7, 0xF156, 0x93C0, 0xF373, 0x93C2, 0xF363, 0x93C3, 0xC3EB, + 0x93C4, 0xF371, 0x93C7, 0xF361, 0x93C8, 0xC3EC, 0x93CA, 0xF36C, 0x93CC, 0xF368, 0x93CD, 0xC3F1, 0x93CE, 0xF372, 0x93CF, 0xF362, + 0x93D0, 0xF365, 0x93D1, 0xC3E9, 0x93D2, 0xF374, 0x93D4, 0xF36D, 0x93D5, 0xF370, 0x93D6, 0xC3EF, 0x93D7, 0xC3F4, 0x93D8, 0xC3F2, + 0x93D9, 0xF369, 0x93DA, 0xF364, 0x93DC, 0xC3ED, 0x93DD, 0xC3EE, 0x93DE, 0xF360, 0x93DF, 0xC3EA, 0x93E1, 0xC3E8, 0x93E2, 0xC3F0, + 0x93E3, 0xF36F, 0x93E4, 0xC3F3, 0x93E6, 0xF36B, 0x93E7, 0xF375, 0x93E8, 0xC3F5, 0x93EC, 0xF367, 0x93EE, 0xF36E, 0x93F5, 0xF4F3, + 0x93F6, 0xF542, 0x93F7, 0xF4F5, 0x93F8, 0xF4FC, 0x93F9, 0xF366, 0x93FA, 0xF4FA, 0x93FB, 0xF4E9, 0x93FC, 0xF540, 0x93FD, 0xC4C3, + 0x93FE, 0xF4ED, 0x93FF, 0xF4FE, 0x9400, 0xF4F4, 0x9403, 0xC4C2, 0x9406, 0xF544, 0x9407, 0xF4F6, 0x9409, 0xF4FB, 0x940A, 0xF4FD, + 0x940B, 0xF4E7, 0x940C, 0xF541, 0x940D, 0xF4F2, 0x940E, 0xF4F7, 0x940F, 0xF4EB, 0x9410, 0xF4EF, 0x9411, 0xF543, 0x9412, 0xF4F9, + 0x9413, 0xF4E8, 0x9414, 0xF4EC, 0x9415, 0xF4EE, 0x9416, 0xF4F8, 0x9418, 0xC4C1, 0x9419, 0xF4F1, 0x9420, 0xF4EA, 0x9428, 0xF4F0, + 0x9429, 0xF661, 0x942A, 0xF666, 0x942B, 0xC54F, 0x942C, 0xF668, 0x942E, 0xC549, 0x9430, 0xF664, 0x9431, 0xF66A, 0x9432, 0xC54E, + 0x9433, 0xC54A, 0x9435, 0xC54B, 0x9436, 0xF660, 0x9437, 0xF667, 0x9438, 0xC54D, 0x9439, 0xF665, 0x943A, 0xC54C, 0x943B, 0xF65F, + 0x943C, 0xF663, 0x943D, 0xF662, 0x943F, 0xF65E, 0x9440, 0xF669, 0x9444, 0xC5B1, 0x9445, 0xF76D, 0x9446, 0xF770, 0x9447, 0xF76C, + 0x9448, 0xF76E, 0x9449, 0xF76F, 0x944A, 0xF769, 0x944B, 0xF76A, 0x944C, 0xF767, 0x944F, 0xF76B, 0x9450, 0xF768, 0x9451, 0xC5B2, + 0x9452, 0xC5B3, 0x9455, 0xF84B, 0x9457, 0xF84D, 0x945D, 0xF84C, 0x945E, 0xF84E, 0x9460, 0xC5E0, 0x9462, 0xF84A, 0x9463, 0xC5DF, + 0x9464, 0xC5E1, 0x9468, 0xF8CB, 0x9469, 0xF8CC, 0x946A, 0xC644, 0x946B, 0xF8CA, 0x946D, 0xF953, 0x946E, 0xF952, 0x946F, 0xF954, + 0x9470, 0xC65F, 0x9471, 0xF955, 0x9472, 0xC65E, 0x9473, 0xF956, 0x9474, 0xF972, 0x9475, 0xF975, 0x9476, 0xF974, 0x9477, 0xC668, + 0x9478, 0xF973, 0x947C, 0xC672, 0x947D, 0xC670, 0x947E, 0xC671, 0x947F, 0xC677, 0x9480, 0xF9C0, 0x9481, 0xF9C1, 0x9482, 0xF9BF, + 0x9483, 0xF9C9, 0x9577, 0xAAF8, 0x957A, 0xD844, 0x957B, 0xDC78, 0x957C, 0xE8A5, 0x957D, 0xF376, 0x9580, 0xAAF9, 0x9582, 0xADAC, + 0x9583, 0xB07B, 0x9586, 0xD845, 0x9588, 0xD846, 0x9589, 0xB3AC, 0x958B, 0xB67D, 0x958C, 0xDC7A, 0x958D, 0xDC79, 0x958E, 0xB6A3, + 0x958F, 0xB67C, 0x9590, 0xDC7B, 0x9591, 0xB67E, 0x9592, 0xB6A2, 0x9593, 0xB6A1, 0x9594, 0xB67B, 0x9598, 0xB968, 0x959B, 0xE0D0, + 0x959C, 0xE0CE, 0x959E, 0xE0CF, 0x959F, 0xE0CD, 0x95A1, 0xBBD2, 0x95A3, 0xBBD5, 0x95A4, 0xBBD7, 0x95A5, 0xBBD6, 0x95A8, 0xBBD3, + 0x95A9, 0xBBD4, 0x95AB, 0xE8A7, 0x95AC, 0xE8A6, 0x95AD, 0xBE5B, 0x95AE, 0xE8A8, 0x95B0, 0xE8A9, 0x95B1, 0xBE5C, 0x95B5, 0xEC4D, + 0x95B6, 0xEC4B, 0x95B7, 0xEEF3, 0x95B9, 0xEC49, 0x95BA, 0xEC4A, 0x95BB, 0xC046, 0x95BC, 0xEC46, 0x95BD, 0xEC4E, 0x95BE, 0xEC48, + 0x95BF, 0xEC4C, 0x95C0, 0xEEEF, 0x95C3, 0xEEF1, 0x95C5, 0xEEF2, 0x95C6, 0xC1F3, 0x95C7, 0xEEEE, 0x95C8, 0xC1F2, 0x95C9, 0xEEF0, + 0x95CA, 0xC1EF, 0x95CB, 0xC1F0, 0x95CC, 0xC1F1, 0x95CD, 0xEC47, 0x95D0, 0xC2F5, 0x95D1, 0xF16E, 0x95D2, 0xF16C, 0x95D3, 0xF16D, + 0x95D4, 0xC2F3, 0x95D5, 0xC2F6, 0x95D6, 0xC2F4, 0x95DA, 0xF377, 0x95DB, 0xF378, 0x95DC, 0xC3F6, 0x95DE, 0xF545, 0x95DF, 0xF547, + 0x95E0, 0xF546, 0x95E1, 0xC4C4, 0x95E2, 0xC550, 0x95E3, 0xF66D, 0x95E4, 0xF66C, 0x95E5, 0xF66B, 0x961C, 0xAAFA, 0x961E, 0xC9AA, + 0x9620, 0xCA58, 0x9621, 0xA6E9, 0x9622, 0xCA56, 0x9623, 0xCA59, 0x9624, 0xCA57, 0x9628, 0xCBAE, 0x962A, 0xA8C1, 0x962C, 0xA8C2, + 0x962D, 0xCBB0, 0x962E, 0xA8BF, 0x962F, 0xCBAF, 0x9630, 0xCBAD, 0x9631, 0xA8C0, 0x9632, 0xA8BE, 0x9639, 0xCDD8, 0x963A, 0xCDDB, + 0x963B, 0xAAFD, 0x963C, 0xCDDA, 0x963D, 0xCDD9, 0x963F, 0xAAFC, 0x9640, 0xAAFB, 0x9642, 0xAB40, 0x9643, 0xCDDC, 0x9644, 0xAAFE, + 0x964A, 0xD0C6, 0x964B, 0xADAE, 0x964C, 0xADAF, 0x964D, 0xADB0, 0x964E, 0xD0C7, 0x964F, 0xD0C3, 0x9650, 0xADAD, 0x9651, 0xD0C4, + 0x9653, 0xD0C5, 0x9654, 0xD0C2, 0x9658, 0xB0A4, 0x965B, 0xB0A1, 0x965C, 0xD445, 0x965D, 0xB0A2, 0x965E, 0xB0A5, 0x965F, 0xD446, + 0x9661, 0xB07E, 0x9662, 0xB07C, 0x9663, 0xB07D, 0x9664, 0xB0A3, 0x966A, 0xB3AD, 0x966B, 0xD849, 0x966C, 0xB3B5, 0x966D, 0xD848, + 0x966F, 0xD84B, 0x9670, 0xB3B1, 0x9671, 0xD84A, 0x9672, 0xB6AB, 0x9673, 0xB3AF, 0x9674, 0xB3B2, 0x9675, 0xB3AE, 0x9676, 0xB3B3, + 0x9677, 0xB3B4, 0x9678, 0xB3B0, 0x967C, 0xD847, 0x967D, 0xB6A7, 0x967E, 0xDC7D, 0x9680, 0xDCA3, 0x9683, 0xDCA2, 0x9684, 0xB6AC, + 0x9685, 0xB6A8, 0x9686, 0xB6A9, 0x9687, 0xDC7C, 0x9688, 0xDC7E, 0x9689, 0xDCA1, 0x968A, 0xB6A4, 0x968B, 0xB6A6, 0x968D, 0xB6AA, + 0x968E, 0xB6A5, 0x9691, 0xE0D3, 0x9692, 0xE0D1, 0x9693, 0xE0D2, 0x9694, 0xB96A, 0x9695, 0xB96B, 0x9697, 0xE0D4, 0x9698, 0xB969, + 0x9699, 0xBBD8, 0x969B, 0xBBDA, 0x969C, 0xBBD9, 0x969E, 0xE4BB, 0x96A1, 0xE4BC, 0x96A2, 0xE8AB, 0x96A4, 0xE8AA, 0x96A7, 0xC047, + 0x96A8, 0xC048, 0x96A9, 0xEC4F, 0x96AA, 0xC049, 0x96AC, 0xEEF6, 0x96AE, 0xEEF4, 0x96B0, 0xEEF5, 0x96B1, 0xC1F4, 0x96B3, 0xF16F, + 0x96B4, 0xC3F7, 0x96B8, 0xC1F5, 0x96B9, 0xAB41, 0x96BB, 0xB0A6, 0x96BC, 0xD447, 0x96BF, 0xD84C, 0x96C0, 0xB3B6, 0x96C1, 0xB6AD, + 0x96C2, 0xDCA4, 0x96C3, 0xDCA6, 0x96C4, 0xB6AF, 0x96C5, 0xB6AE, 0x96C6, 0xB6B0, 0x96C7, 0xB6B1, 0x96C8, 0xDCA5, 0x96C9, 0xB96E, + 0x96CA, 0xB96F, 0x96CB, 0xB96D, 0x96CC, 0xBBDB, 0x96CD, 0xB96C, 0x96CE, 0xE0D5, 0x96D2, 0xBBDC, 0x96D3, 0xE8AC, 0x96D4, 0xEC50, + 0x96D5, 0xC04A, 0x96D6, 0xC1F6, 0x96D7, 0xF170, 0x96D8, 0xF174, 0x96D9, 0xC2F9, 0x96DA, 0xF171, 0x96DB, 0xC2FA, 0x96DC, 0xC2F8, + 0x96DD, 0xF175, 0x96DE, 0xC2FB, 0x96DF, 0xF173, 0x96E1, 0xF379, 0x96E2, 0xC2F7, 0x96E3, 0xC3F8, 0x96E5, 0xF8CD, 0x96E8, 0xAB42, + 0x96E9, 0xB3B8, 0x96EA, 0xB3B7, 0x96EF, 0xB6B2, 0x96F0, 0xDCA8, 0x96F1, 0xDCA7, 0x96F2, 0xB6B3, 0x96F5, 0xE0D9, 0x96F6, 0xB973, + 0x96F7, 0xB970, 0x96F8, 0xE0D8, 0x96F9, 0xB972, 0x96FA, 0xE0D6, 0x96FB, 0xB971, 0x96FD, 0xE0D7, 0x96FF, 0xE4BD, 0x9700, 0xBBDD, + 0x9702, 0xE8AF, 0x9704, 0xBE5D, 0x9705, 0xE8AD, 0x9706, 0xBE5E, 0x9707, 0xBE5F, 0x9708, 0xE8AE, 0x9709, 0xBE60, 0x970B, 0xEC51, + 0x970D, 0xC04E, 0x970E, 0xC04B, 0x970F, 0xC050, 0x9710, 0xEC53, 0x9711, 0xC04C, 0x9712, 0xEC52, 0x9713, 0xC04F, 0x9716, 0xC04D, + 0x9718, 0xEEF9, 0x9719, 0xEEFB, 0x971C, 0xC1F7, 0x971D, 0xEEFA, 0x971E, 0xC1F8, 0x971F, 0xEEF8, 0x9720, 0xEEF7, 0x9722, 0xF177, + 0x9723, 0xF176, 0x9724, 0xC2FC, 0x9725, 0xF178, 0x9726, 0xF37E, 0x9727, 0xC3FA, 0x9728, 0xF37D, 0x9729, 0xF37A, 0x972A, 0xC3F9, + 0x972B, 0xF37B, 0x972C, 0xF37C, 0x972E, 0xF548, 0x972F, 0xF549, 0x9730, 0xC4C5, 0x9732, 0xC553, 0x9735, 0xF66E, 0x9738, 0xC551, + 0x9739, 0xC552, 0x973A, 0xF66F, 0x973D, 0xC5B4, 0x973E, 0xC5B5, 0x973F, 0xF771, 0x9742, 0xC645, 0x9743, 0xF8CF, 0x9744, 0xC647, + 0x9746, 0xF8CE, 0x9747, 0xF8D0, 0x9748, 0xC646, 0x9749, 0xF957, 0x974B, 0xF9AD, 0x9752, 0xAB43, 0x9756, 0xB974, 0x9758, 0xE4BE, + 0x975A, 0xE8B0, 0x975B, 0xC051, 0x975C, 0xC052, 0x975E, 0xAB44, 0x9760, 0xBE61, 0x9761, 0xC3FB, 0x9762, 0xADB1, 0x9766, 0xC053, + 0x9768, 0xC5E2, 0x9769, 0xADB2, 0x976A, 0xD84D, 0x976C, 0xDCA9, 0x976E, 0xDCAB, 0x9770, 0xDCAA, 0x9772, 0xE0DD, 0x9773, 0xE0DA, + 0x9774, 0xB975, 0x9776, 0xB976, 0x9777, 0xE0DB, 0x9778, 0xE0DC, 0x977A, 0xE4C0, 0x977B, 0xE4C5, 0x977C, 0xBBDE, 0x977D, 0xE4BF, + 0x977E, 0xE4C1, 0x977F, 0xE4C8, 0x9780, 0xE4C3, 0x9781, 0xE4C7, 0x9782, 0xE4C4, 0x9783, 0xE4C2, 0x9784, 0xE4C6, 0x9785, 0xBBDF, + 0x9788, 0xE8B3, 0x978A, 0xE8B1, 0x978B, 0xBE63, 0x978D, 0xBE62, 0x978E, 0xE8B2, 0x978F, 0xBE64, 0x9794, 0xEC56, 0x9797, 0xEC55, + 0x9798, 0xC054, 0x9799, 0xEC54, 0x979A, 0xEEFC, 0x979C, 0xEEFE, 0x979D, 0xEF41, 0x979E, 0xEF40, 0x97A0, 0xC1F9, 0x97A1, 0xEEFD, + 0x97A2, 0xF1A1, 0x97A3, 0xC2FD, 0x97A4, 0xF17D, 0x97A5, 0xF1A2, 0x97A6, 0xC2FE, 0x97A8, 0xF17B, 0x97AA, 0xF17E, 0x97AB, 0xF17C, + 0x97AC, 0xF179, 0x97AD, 0xC340, 0x97AE, 0xF17A, 0x97B3, 0xF3A1, 0x97B6, 0xF3A3, 0x97B7, 0xF3A2, 0x97B9, 0xF54A, 0x97BB, 0xF54B, + 0x97BF, 0xF670, 0x97C1, 0xC5B7, 0x97C3, 0xC5B6, 0x97C4, 0xF84F, 0x97C5, 0xF850, 0x97C6, 0xC648, 0x97C7, 0xF8D1, 0x97C9, 0xC669, + 0x97CB, 0xADB3, 0x97CC, 0xB6B4, 0x97CD, 0xE4CA, 0x97CE, 0xE4C9, 0x97CF, 0xE8B5, 0x97D0, 0xE8B4, 0x97D3, 0xC1FA, 0x97D4, 0xEF43, + 0x97D5, 0xEF42, 0x97D6, 0xF1A5, 0x97D7, 0xF1A3, 0x97D8, 0xF1A6, 0x97D9, 0xF1A4, 0x97DC, 0xC3FC, 0x97DD, 0xF3A4, 0x97DE, 0xF3A5, + 0x97DF, 0xF3A6, 0x97E1, 0xF671, 0x97E3, 0xF772, 0x97E5, 0xF8D2, 0x97ED, 0xADB4, 0x97F0, 0xEC57, 0x97F1, 0xEF44, 0x97F3, 0xADB5, + 0x97F6, 0xBBE0, 0x97F8, 0xEC58, 0x97F9, 0xC341, 0x97FA, 0xF1A7, 0x97FB, 0xC3FD, 0x97FD, 0xF54C, 0x97FE, 0xF54D, 0x97FF, 0xC554, + 0x9800, 0xF851, 0x9801, 0xADB6, 0x9802, 0xB3BB, 0x9803, 0xB3BC, 0x9804, 0xD84E, 0x9805, 0xB6B5, 0x9806, 0xB6B6, 0x9807, 0xDCAC, + 0x9808, 0xB6B7, 0x980A, 0xB97A, 0x980C, 0xB97C, 0x980D, 0xE0DF, 0x980E, 0xE0E0, 0x980F, 0xE0DE, 0x9810, 0xB977, 0x9811, 0xB978, + 0x9812, 0xB97B, 0x9813, 0xB979, 0x9816, 0xE4CB, 0x9817, 0xBBE1, 0x9818, 0xBBE2, 0x981B, 0xE8BC, 0x981C, 0xBE67, 0x981D, 0xE8B7, + 0x981E, 0xE8B6, 0x9820, 0xE8BB, 0x9821, 0xBE65, 0x9824, 0xC05B, 0x9826, 0xE8B8, 0x9827, 0xE8BD, 0x9828, 0xE8BA, 0x9829, 0xE8B9, + 0x982B, 0xBE66, 0x982D, 0xC059, 0x982F, 0xEC5A, 0x9830, 0xC055, 0x9832, 0xEC5B, 0x9835, 0xEC59, 0x9837, 0xC058, 0x9838, 0xC056, + 0x9839, 0xC05A, 0x983B, 0xC057, 0x9841, 0xEF45, 0x9843, 0xEF4A, 0x9844, 0xEF46, 0x9845, 0xEF49, 0x9846, 0xC1FB, 0x9848, 0xEDD4, + 0x9849, 0xEF48, 0x984A, 0xEF47, 0x984C, 0xC344, 0x984D, 0xC342, 0x984E, 0xC345, 0x984F, 0xC343, 0x9850, 0xF1A8, 0x9851, 0xF1A9, + 0x9852, 0xF1AA, 0x9853, 0xC346, 0x9857, 0xF3AA, 0x9858, 0xC440, 0x9859, 0xF3A8, 0x985B, 0xC441, 0x985C, 0xF3A7, 0x985D, 0xF3A9, + 0x985E, 0xC3FE, 0x985F, 0xF551, 0x9860, 0xF54E, 0x9862, 0xF54F, 0x9863, 0xF550, 0x9864, 0xF672, 0x9865, 0xC556, 0x9867, 0xC555, + 0x9869, 0xF774, 0x986A, 0xF773, 0x986B, 0xC5B8, 0x986F, 0xC5E3, 0x9870, 0xC649, 0x9871, 0xC660, 0x9872, 0xF958, 0x9873, 0xF9AE, + 0x9874, 0xF9AF, 0x98A8, 0xADB7, 0x98A9, 0xDCAD, 0x98AC, 0xE0E1, 0x98AD, 0xE4CC, 0x98AE, 0xE4CD, 0x98AF, 0xBBE3, 0x98B1, 0xBBE4, + 0x98B2, 0xE8BE, 0x98B3, 0xBE68, 0x98B6, 0xC1FC, 0x98B8, 0xF1AB, 0x98BA, 0xC347, 0x98BB, 0xF3AD, 0x98BC, 0xC442, 0x98BD, 0xF3AC, + 0x98BE, 0xF3AE, 0x98BF, 0xF3AB, 0x98C0, 0xF675, 0x98C1, 0xF552, 0x98C2, 0xF553, 0x98C4, 0xC4C6, 0x98C6, 0xF674, 0x98C9, 0xF673, + 0x98CB, 0xF775, 0x98CC, 0xF9B0, 0x98DB, 0xADB8, 0x98DF, 0xADB9, 0x98E2, 0xB0A7, 0x98E3, 0xD448, 0x98E5, 0xD84F, 0x98E7, 0xB6B8, + 0x98E9, 0xB6BB, 0x98EA, 0xB6B9, 0x98EB, 0xDCAE, 0x98ED, 0xB6BD, 0x98EF, 0xB6BA, 0x98F2, 0xB6BC, 0x98F4, 0xB97E, 0x98F6, 0xE0E2, + 0x98F9, 0xE0E3, 0x98FA, 0xE8C0, 0x98FC, 0xB97D, 0x98FD, 0xB9A1, 0x98FE, 0xB9A2, 0x9900, 0xE4CF, 0x9902, 0xE4CE, 0x9903, 0xBBE5, + 0x9905, 0xBBE6, 0x9907, 0xE4D0, 0x9908, 0xE8BF, 0x9909, 0xBBE8, 0x990A, 0xBE69, 0x990C, 0xBBE7, 0x9910, 0xC05C, 0x9911, 0xE8C1, + 0x9912, 0xBE6B, 0x9913, 0xBE6A, 0x9914, 0xE8C2, 0x9915, 0xE8C5, 0x9916, 0xE8C3, 0x9917, 0xE8C4, 0x9918, 0xBE6C, 0x991A, 0xC061, + 0x991B, 0xC05F, 0x991E, 0xC05E, 0x991F, 0xEC5D, 0x9921, 0xC060, 0x9924, 0xEC5C, 0x9925, 0xEF4B, 0x9927, 0xEC5E, 0x9928, 0xC05D, + 0x9929, 0xEC5F, 0x992A, 0xEF4E, 0x992B, 0xEF4C, 0x992C, 0xEF4D, 0x992D, 0xEF52, 0x992E, 0xC34B, 0x992F, 0xEF51, 0x9930, 0xEF54, + 0x9931, 0xEF53, 0x9932, 0xEF50, 0x9933, 0xEF4F, 0x9935, 0xC1FD, 0x993A, 0xF1AE, 0x993C, 0xF1AD, 0x993D, 0xC34A, 0x993E, 0xC348, + 0x993F, 0xC349, 0x9941, 0xF1AC, 0x9943, 0xF3B1, 0x9945, 0xC443, 0x9947, 0xF3B0, 0x9948, 0xF3AF, 0x9949, 0xC444, 0x994B, 0xF558, + 0x994C, 0xF557, 0x994E, 0xF555, 0x9950, 0xF554, 0x9951, 0xC4C8, 0x9952, 0xC4C7, 0x9953, 0xF559, 0x9954, 0xF776, 0x9955, 0xC5B9, + 0x9956, 0xF677, 0x9957, 0xC557, 0x9958, 0xF676, 0x9959, 0xF556, 0x995B, 0xF777, 0x995C, 0xC5E4, 0x995E, 0xC661, 0x995F, 0xF959, + 0x9961, 0xF9B1, 0x9996, 0xADBA, 0x9997, 0xD850, 0x9998, 0xEF55, 0x9999, 0xADBB, 0x999C, 0xE4D2, 0x999D, 0xE4D1, 0x999E, 0xEC60, + 0x99A1, 0xEF57, 0x99A3, 0xEF56, 0x99A5, 0xC34C, 0x99A6, 0xF3B2, 0x99A7, 0xF3B3, 0x99A8, 0xC4C9, 0x99AB, 0xF9B2, 0x99AC, 0xB0A8, + 0x99AD, 0xB6BF, 0x99AE, 0xB6BE, 0x99AF, 0xE0E4, 0x99B0, 0xE0E6, 0x99B1, 0xB9A4, 0x99B2, 0xE0E5, 0x99B3, 0xB9A3, 0x99B4, 0xB9A5, + 0x99B5, 0xE0E7, 0x99B9, 0xE4D4, 0x99BA, 0xE4D6, 0x99BB, 0xE4D5, 0x99BD, 0xE4D8, 0x99C1, 0xBBE9, 0x99C2, 0xE4D7, 0x99C3, 0xE4D3, + 0x99C7, 0xE4D9, 0x99C9, 0xE8CC, 0x99CB, 0xE8CF, 0x99CC, 0xE8D1, 0x99CD, 0xE8C7, 0x99CE, 0xE8CB, 0x99CF, 0xE8C8, 0x99D0, 0xBE6E, + 0x99D1, 0xBE71, 0x99D2, 0xBE73, 0x99D3, 0xE8C9, 0x99D4, 0xE8CA, 0x99D5, 0xBE72, 0x99D6, 0xE8CD, 0x99D7, 0xE8D0, 0x99D8, 0xE8CE, + 0x99D9, 0xBE74, 0x99DB, 0xBE70, 0x99DC, 0xE8C6, 0x99DD, 0xBE6D, 0x99DF, 0xBE6F, 0x99E2, 0xC063, 0x99E3, 0xEC66, 0x99E4, 0xEC64, + 0x99E5, 0xEC63, 0x99E7, 0xEC69, 0x99E9, 0xEC68, 0x99EA, 0xEC67, 0x99EC, 0xEC62, 0x99ED, 0xC062, 0x99EE, 0xEC61, 0x99F0, 0xEC65, + 0x99F1, 0xC064, 0x99F4, 0xEF5A, 0x99F6, 0xEF5E, 0x99F7, 0xEF5B, 0x99F8, 0xEF5D, 0x99F9, 0xEF5C, 0x99FA, 0xEF59, 0x99FB, 0xEF5F, + 0x99FC, 0xEF62, 0x99FD, 0xEF60, 0x99FE, 0xEF61, 0x99FF, 0xC240, 0x9A01, 0xC1FE, 0x9A02, 0xEF58, 0x9A03, 0xEF63, 0x9A04, 0xF1B3, + 0x9A05, 0xF1B6, 0x9A06, 0xF1B8, 0x9A07, 0xF1B7, 0x9A09, 0xF1B1, 0x9A0A, 0xF1B5, 0x9A0B, 0xF1B0, 0x9A0D, 0xF1B2, 0x9A0E, 0xC34D, + 0x9A0F, 0xF1AF, 0x9A11, 0xF1B4, 0x9A14, 0xF3C0, 0x9A15, 0xF3B5, 0x9A16, 0xC445, 0x9A19, 0xC446, 0x9A1A, 0xF3B4, 0x9A1B, 0xF3B9, + 0x9A1C, 0xF3BF, 0x9A1D, 0xF3B7, 0x9A1E, 0xF3BE, 0x9A20, 0xF3BB, 0x9A22, 0xF3BA, 0x9A23, 0xF3BD, 0x9A24, 0xF3B8, 0x9A25, 0xF3B6, + 0x9A27, 0xF3BC, 0x9A29, 0xF560, 0x9A2A, 0xF55E, 0x9A2B, 0xC4CA, 0x9A2C, 0xF55D, 0x9A2D, 0xF563, 0x9A2E, 0xF561, 0x9A30, 0xC4CB, + 0x9A31, 0xF55C, 0x9A32, 0xF55A, 0x9A34, 0xF55B, 0x9A35, 0xC4CD, 0x9A36, 0xF55F, 0x9A37, 0xC4CC, 0x9A38, 0xF562, 0x9A39, 0xF678, + 0x9A3A, 0xF67E, 0x9A3D, 0xF679, 0x9A3E, 0xC55B, 0x9A3F, 0xF6A1, 0x9A40, 0xC55A, 0x9A41, 0xF67D, 0x9A42, 0xF67C, 0x9A43, 0xC559, + 0x9A44, 0xF67B, 0x9A45, 0xC558, 0x9A46, 0xF67A, 0x9A48, 0xF77D, 0x9A49, 0xF7A1, 0x9A4A, 0xF77E, 0x9A4C, 0xF77B, 0x9A4D, 0xC5BB, + 0x9A4E, 0xF778, 0x9A4F, 0xF77C, 0x9A50, 0xF7A3, 0x9A52, 0xF7A2, 0x9A53, 0xF779, 0x9A54, 0xF77A, 0x9A55, 0xC5BA, 0x9A56, 0xF852, + 0x9A57, 0xC5E7, 0x9A59, 0xF853, 0x9A5A, 0xC5E5, 0x9A5B, 0xC5E6, 0x9A5E, 0xF8D3, 0x9A5F, 0xC64A, 0x9A60, 0xF976, 0x9A62, 0xC66A, + 0x9A64, 0xF9B3, 0x9A65, 0xC66B, 0x9A66, 0xF9B4, 0x9A67, 0xF9B5, 0x9A68, 0xF9C3, 0x9A69, 0xF9C2, 0x9A6A, 0xC67A, 0x9A6B, 0xF9CD, + 0x9AA8, 0xB0A9, 0x9AAB, 0xE0E9, 0x9AAD, 0xE0E8, 0x9AAF, 0xBBEA, 0x9AB0, 0xBBEB, 0x9AB1, 0xE4DA, 0x9AB3, 0xE8D2, 0x9AB4, 0xEC6C, + 0x9AB7, 0xBE75, 0x9AB8, 0xC065, 0x9AB9, 0xEC6A, 0x9ABB, 0xEC6D, 0x9ABC, 0xC066, 0x9ABE, 0xEF64, 0x9ABF, 0xEC6B, 0x9AC0, 0xF1B9, + 0x9AC1, 0xC34E, 0x9AC2, 0xF3C1, 0x9AC6, 0xF566, 0x9AC7, 0xF564, 0x9ACA, 0xF565, 0x9ACD, 0xF6A2, 0x9ACF, 0xC55C, 0x9AD0, 0xF7A4, + 0x9AD1, 0xC5EA, 0x9AD2, 0xC5BC, 0x9AD3, 0xC5E8, 0x9AD4, 0xC5E9, 0x9AD5, 0xF8D4, 0x9AD6, 0xC662, 0x9AD8, 0xB0AA, 0x9ADC, 0xF1BA, + 0x9ADF, 0xD449, 0x9AE1, 0xB9A6, 0x9AE3, 0xE4DB, 0x9AE6, 0xBBEC, 0x9AE7, 0xE4DC, 0x9AEB, 0xE8D4, 0x9AEC, 0xE8D3, 0x9AED, 0xC068, + 0x9AEE, 0xBE76, 0x9AEF, 0xBE77, 0x9AF1, 0xE8D7, 0x9AF2, 0xE8D6, 0x9AF3, 0xE8D5, 0x9AF6, 0xEC6E, 0x9AF7, 0xEC71, 0x9AF9, 0xEC70, + 0x9AFA, 0xEC6F, 0x9AFB, 0xC067, 0x9AFC, 0xEF68, 0x9AFD, 0xEF66, 0x9AFE, 0xEF65, 0x9B01, 0xEF67, 0x9B03, 0xC34F, 0x9B04, 0xF1BC, + 0x9B05, 0xF1BD, 0x9B06, 0xC350, 0x9B08, 0xF1BB, 0x9B0A, 0xF3C3, 0x9B0B, 0xF3C2, 0x9B0C, 0xF3C5, 0x9B0D, 0xC447, 0x9B0E, 0xF3C4, + 0x9B10, 0xF567, 0x9B11, 0xF569, 0x9B12, 0xF568, 0x9B15, 0xF6A3, 0x9B16, 0xF6A6, 0x9B17, 0xF6A4, 0x9B18, 0xF6A5, 0x9B19, 0xF7A5, + 0x9B1A, 0xC5BD, 0x9B1E, 0xF854, 0x9B1F, 0xF855, 0x9B20, 0xF856, 0x9B22, 0xC64B, 0x9B23, 0xC663, 0x9B24, 0xF9B6, 0x9B25, 0xB0AB, + 0x9B27, 0xBE78, 0x9B28, 0xC069, 0x9B29, 0xF1BE, 0x9B2B, 0xF7A6, 0x9B2E, 0xF9C4, 0x9B2F, 0xD44A, 0x9B31, 0xC67B, 0x9B32, 0xB0AC, + 0x9B33, 0xEC72, 0x9B35, 0xF1BF, 0x9B37, 0xF3C6, 0x9B3A, 0xF6A7, 0x9B3B, 0xF7A7, 0x9B3C, 0xB0AD, 0x9B3E, 0xE4DD, 0x9B3F, 0xE4DE, + 0x9B41, 0xBBED, 0x9B42, 0xBBEE, 0x9B43, 0xE8D9, 0x9B44, 0xBE7A, 0x9B45, 0xBE79, 0x9B46, 0xE8D8, 0x9B48, 0xEF69, 0x9B4A, 0xF1C0, + 0x9B4B, 0xF1C2, 0x9B4C, 0xF1C1, 0x9B4D, 0xC353, 0x9B4E, 0xC352, 0x9B4F, 0xC351, 0x9B51, 0xC55E, 0x9B52, 0xF6A8, 0x9B54, 0xC55D, + 0x9B55, 0xF7A9, 0x9B56, 0xF7A8, 0x9B58, 0xC64C, 0x9B59, 0xF8D5, 0x9B5A, 0xB3BD, 0x9B5B, 0xE0EA, 0x9B5F, 0xE4E1, 0x9B60, 0xE4DF, + 0x9B61, 0xE4E0, 0x9B64, 0xE8E2, 0x9B66, 0xE8DD, 0x9B67, 0xE8DA, 0x9B68, 0xE8E1, 0x9B6C, 0xE8E3, 0x9B6F, 0xBE7C, 0x9B70, 0xE8E0, + 0x9B71, 0xE8DC, 0x9B74, 0xE8DB, 0x9B75, 0xE8DF, 0x9B76, 0xE8DE, 0x9B77, 0xBE7B, 0x9B7A, 0xEC7D, 0x9B7B, 0xEC78, 0x9B7C, 0xEC76, + 0x9B7D, 0xECA1, 0x9B7E, 0xEC77, 0x9B80, 0xEC73, 0x9B82, 0xEC79, 0x9B85, 0xEC74, 0x9B86, 0xEF72, 0x9B87, 0xEC75, 0x9B88, 0xECA2, + 0x9B90, 0xEC7C, 0x9B91, 0xC06A, 0x9B92, 0xEC7B, 0x9B93, 0xEC7A, 0x9B95, 0xEC7E, 0x9B9A, 0xEF6A, 0x9B9B, 0xEF6D, 0x9B9E, 0xEF6C, + 0x9BA0, 0xEF74, 0x9BA1, 0xEF6F, 0x9BA2, 0xEF73, 0x9BA4, 0xEF71, 0x9BA5, 0xEF70, 0x9BA6, 0xEF6E, 0x9BA8, 0xEF6B, 0x9BAA, 0xC243, + 0x9BAB, 0xC242, 0x9BAD, 0xC244, 0x9BAE, 0xC241, 0x9BAF, 0xEF75, 0x9BB5, 0xF1C8, 0x9BB6, 0xF1CB, 0x9BB8, 0xF1C9, 0x9BB9, 0xF1CD, + 0x9BBD, 0xF1CE, 0x9BBF, 0xF1C6, 0x9BC0, 0xC358, 0x9BC1, 0xF1C7, 0x9BC3, 0xF1C5, 0x9BC4, 0xF1CC, 0x9BC6, 0xF1C4, 0x9BC7, 0xF1C3, + 0x9BC8, 0xC357, 0x9BC9, 0xC355, 0x9BCA, 0xC354, 0x9BD3, 0xF1CA, 0x9BD4, 0xF3CF, 0x9BD5, 0xF3D5, 0x9BD6, 0xC44A, 0x9BD7, 0xF3D0, + 0x9BD9, 0xF3D3, 0x9BDA, 0xF3D7, 0x9BDB, 0xC44B, 0x9BDC, 0xF3D2, 0x9BDE, 0xF3CA, 0x9BE0, 0xF3C9, 0x9BE1, 0xF3D6, 0x9BE2, 0xF3CD, + 0x9BE4, 0xF3CB, 0x9BE5, 0xF3D4, 0x9BE6, 0xF3CC, 0x9BE7, 0xC449, 0x9BE8, 0xC448, 0x9BEA, 0xF3C7, 0x9BEB, 0xF3C8, 0x9BEC, 0xF3D1, + 0x9BF0, 0xF3CE, 0x9BF7, 0xF56C, 0x9BF8, 0xF56F, 0x9BFD, 0xC356, 0x9C05, 0xF56D, 0x9C06, 0xF573, 0x9C07, 0xF571, 0x9C08, 0xF56B, + 0x9C09, 0xF576, 0x9C0B, 0xF56A, 0x9C0D, 0xC4CF, 0x9C0E, 0xF572, 0x9C12, 0xF56E, 0x9C13, 0xC4CE, 0x9C14, 0xF575, 0x9C17, 0xF574, + 0x9C1C, 0xF6AB, 0x9C1D, 0xF6AA, 0x9C21, 0xF6B1, 0x9C23, 0xF6AD, 0x9C24, 0xF6B0, 0x9C25, 0xC560, 0x9C28, 0xF6AE, 0x9C29, 0xF6AF, + 0x9C2B, 0xF6A9, 0x9C2C, 0xF6AC, 0x9C2D, 0xC55F, 0x9C31, 0xC5BF, 0x9C32, 0xF7B4, 0x9C33, 0xF7AF, 0x9C34, 0xF7B3, 0x9C36, 0xF7B6, + 0x9C37, 0xF7B2, 0x9C39, 0xF7AE, 0x9C3B, 0xC5C1, 0x9C3C, 0xF7B1, 0x9C3D, 0xF7B5, 0x9C3E, 0xC5C0, 0x9C3F, 0xF7AC, 0x9C40, 0xF570, + 0x9C41, 0xF7B0, 0x9C44, 0xF7AD, 0x9C46, 0xF7AA, 0x9C48, 0xF7AB, 0x9C49, 0xC5BE, 0x9C4A, 0xF85A, 0x9C4B, 0xF85C, 0x9C4C, 0xF85F, + 0x9C4D, 0xF85B, 0x9C4E, 0xF860, 0x9C50, 0xF859, 0x9C52, 0xF857, 0x9C54, 0xC5EB, 0x9C55, 0xF85D, 0x9C56, 0xC5ED, 0x9C57, 0xC5EC, + 0x9C58, 0xF858, 0x9C59, 0xF85E, 0x9C5E, 0xF8DA, 0x9C5F, 0xC64D, 0x9C60, 0xF8DB, 0x9C62, 0xF8D9, 0x9C63, 0xF8D6, 0x9C66, 0xF8D8, + 0x9C67, 0xF8D7, 0x9C68, 0xF95A, 0x9C6D, 0xF95C, 0x9C6E, 0xF95B, 0x9C71, 0xF979, 0x9C73, 0xF978, 0x9C74, 0xF977, 0x9C75, 0xF97A, + 0x9C77, 0xC673, 0x9C78, 0xC674, 0x9C79, 0xF9CA, 0x9C7A, 0xF9CE, 0x9CE5, 0xB3BE, 0x9CE6, 0xDCAF, 0x9CE7, 0xE0ED, 0x9CE9, 0xB9A7, + 0x9CEA, 0xE0EB, 0x9CED, 0xE0EC, 0x9CF1, 0xE4E2, 0x9CF2, 0xE4E3, 0x9CF3, 0xBBF1, 0x9CF4, 0xBBEF, 0x9CF5, 0xE4E4, 0x9CF6, 0xBBF0, + 0x9CF7, 0xE8E8, 0x9CF9, 0xE8EB, 0x9CFA, 0xE8E5, 0x9CFB, 0xE8EC, 0x9CFC, 0xE8E4, 0x9CFD, 0xE8E6, 0x9CFF, 0xE8E7, 0x9D00, 0xE8EA, + 0x9D03, 0xBEA1, 0x9D04, 0xE8EF, 0x9D05, 0xE8EE, 0x9D06, 0xBE7D, 0x9D07, 0xE8E9, 0x9D08, 0xE8ED, 0x9D09, 0xBE7E, 0x9D10, 0xECAC, + 0x9D12, 0xC06F, 0x9D14, 0xECA7, 0x9D15, 0xC06B, 0x9D17, 0xECA4, 0x9D18, 0xECAA, 0x9D19, 0xECAD, 0x9D1B, 0xC070, 0x9D1D, 0xECA9, + 0x9D1E, 0xECA6, 0x9D1F, 0xECAE, 0x9D20, 0xECA5, 0x9D22, 0xECAB, 0x9D23, 0xC06C, 0x9D25, 0xECA3, 0x9D26, 0xC06D, 0x9D28, 0xC06E, + 0x9D29, 0xECA8, 0x9D2D, 0xEFA9, 0x9D2E, 0xEF7A, 0x9D2F, 0xEF7B, 0x9D30, 0xEF7E, 0x9D31, 0xEF7C, 0x9D33, 0xEF76, 0x9D36, 0xEF79, + 0x9D37, 0xEFA5, 0x9D38, 0xEF7D, 0x9D3B, 0xC245, 0x9D3D, 0xEFA7, 0x9D3E, 0xEFA4, 0x9D3F, 0xC246, 0x9D40, 0xEFA6, 0x9D41, 0xEF77, + 0x9D42, 0xEFA2, 0x9D43, 0xEFA3, 0x9D45, 0xEFA1, 0x9D4A, 0xF1D2, 0x9D4B, 0xF1D4, 0x9D4C, 0xF1D7, 0x9D4F, 0xF1D1, 0x9D51, 0xC359, + 0x9D52, 0xF1D9, 0x9D53, 0xF1D0, 0x9D54, 0xF1DA, 0x9D56, 0xF1D6, 0x9D57, 0xF1D8, 0x9D58, 0xF1DC, 0x9D59, 0xF1D5, 0x9D5A, 0xF1DD, + 0x9D5B, 0xF1D3, 0x9D5C, 0xF1CF, 0x9D5D, 0xC35A, 0x9D5F, 0xF1DB, 0x9D60, 0xC35B, 0x9D61, 0xC44D, 0x9D67, 0xEF78, 0x9D68, 0xF3F1, + 0x9D69, 0xF3E8, 0x9D6A, 0xC44F, 0x9D6B, 0xF3E4, 0x9D6C, 0xC450, 0x9D6F, 0xF3ED, 0x9D70, 0xF3E7, 0x9D71, 0xF3DD, 0x9D72, 0xC44E, + 0x9D73, 0xF3EA, 0x9D74, 0xF3E5, 0x9D75, 0xF3E6, 0x9D77, 0xF3D8, 0x9D78, 0xF3DF, 0x9D79, 0xF3EE, 0x9D7B, 0xF3EB, 0x9D7D, 0xF3E3, + 0x9D7F, 0xF3EF, 0x9D80, 0xF3DE, 0x9D81, 0xF3D9, 0x9D82, 0xF3EC, 0x9D84, 0xF3DB, 0x9D85, 0xF3E9, 0x9D86, 0xF3E0, 0x9D87, 0xF3F0, + 0x9D88, 0xF3DC, 0x9D89, 0xC44C, 0x9D8A, 0xF3DA, 0x9D8B, 0xF3E1, 0x9D8C, 0xF3E2, 0x9D90, 0xF57D, 0x9D92, 0xF57B, 0x9D94, 0xF5A2, + 0x9D96, 0xF5AE, 0x9D97, 0xF5A5, 0x9D98, 0xF57C, 0x9D99, 0xF578, 0x9D9A, 0xF5A7, 0x9D9B, 0xF57E, 0x9D9C, 0xF5A3, 0x9D9D, 0xF57A, + 0x9D9E, 0xF5AA, 0x9D9F, 0xF577, 0x9DA0, 0xF5A1, 0x9DA1, 0xF5A6, 0x9DA2, 0xF5A8, 0x9DA3, 0xF5AB, 0x9DA4, 0xF579, 0x9DA6, 0xF5AF, + 0x9DA7, 0xF5B0, 0x9DA8, 0xF5A9, 0x9DA9, 0xF5AD, 0x9DAA, 0xF5A4, 0x9DAC, 0xF6C1, 0x9DAD, 0xF6C4, 0x9DAF, 0xC561, 0x9DB1, 0xF6C3, + 0x9DB2, 0xF6C8, 0x9DB3, 0xF6C6, 0x9DB4, 0xC562, 0x9DB5, 0xF6BD, 0x9DB6, 0xF6B3, 0x9DB7, 0xF6B2, 0x9DB8, 0xC564, 0x9DB9, 0xF6BF, + 0x9DBA, 0xF6C0, 0x9DBB, 0xF6BC, 0x9DBC, 0xF6B4, 0x9DBE, 0xF6B9, 0x9DBF, 0xF5AC, 0x9DC1, 0xF6B5, 0x9DC2, 0xC563, 0x9DC3, 0xF6BB, + 0x9DC5, 0xF6BA, 0x9DC7, 0xF6B6, 0x9DC8, 0xF6C2, 0x9DCA, 0xF6B7, 0x9DCB, 0xF7BB, 0x9DCC, 0xF6C5, 0x9DCD, 0xF6C7, 0x9DCE, 0xF6BE, + 0x9DCF, 0xF6B8, 0x9DD0, 0xF7BC, 0x9DD1, 0xF7BE, 0x9DD2, 0xF7B8, 0x9DD3, 0xC5C2, 0x9DD5, 0xF7C5, 0x9DD6, 0xF7C3, 0x9DD7, 0xC5C3, + 0x9DD8, 0xF7C2, 0x9DD9, 0xF7C1, 0x9DDA, 0xF7BA, 0x9DDB, 0xF7B7, 0x9DDC, 0xF7BD, 0x9DDD, 0xF7C6, 0x9DDE, 0xF7B9, 0x9DDF, 0xF7BF, + 0x9DE1, 0xF869, 0x9DE2, 0xF86E, 0x9DE3, 0xF864, 0x9DE4, 0xF867, 0x9DE5, 0xC5EE, 0x9DE6, 0xF86B, 0x9DE8, 0xF872, 0x9DE9, 0xF7C0, + 0x9DEB, 0xF865, 0x9DEC, 0xF86F, 0x9DED, 0xF873, 0x9DEE, 0xF86A, 0x9DEF, 0xF863, 0x9DF0, 0xF86D, 0x9DF2, 0xF86C, 0x9DF3, 0xF871, + 0x9DF4, 0xF870, 0x9DF5, 0xF7C4, 0x9DF6, 0xF868, 0x9DF7, 0xF862, 0x9DF8, 0xF866, 0x9DF9, 0xC64E, 0x9DFA, 0xC64F, 0x9DFB, 0xF861, + 0x9DFD, 0xF8E6, 0x9DFE, 0xF8DD, 0x9DFF, 0xF8E5, 0x9E00, 0xF8E2, 0x9E01, 0xF8E3, 0x9E02, 0xF8DC, 0x9E03, 0xF8DF, 0x9E04, 0xF8E7, + 0x9E05, 0xF8E1, 0x9E06, 0xF8E0, 0x9E07, 0xF8DE, 0x9E09, 0xF8E4, 0x9E0B, 0xF95D, 0x9E0D, 0xF95E, 0x9E0F, 0xF960, 0x9E10, 0xF95F, + 0x9E11, 0xF962, 0x9E12, 0xF961, 0x9E13, 0xF97C, 0x9E14, 0xF97B, 0x9E15, 0xF9B7, 0x9E17, 0xF9B8, 0x9E19, 0xF9C5, 0x9E1A, 0xC678, + 0x9E1B, 0xC67C, 0x9E1D, 0xF9CF, 0x9E1E, 0xC67D, 0x9E75, 0xB3BF, 0x9E79, 0xC4D0, 0x9E7A, 0xF6C9, 0x9E7C, 0xC650, 0x9E7D, 0xC651, + 0x9E7F, 0xB3C0, 0x9E80, 0xE0EE, 0x9E82, 0xB9A8, 0x9E83, 0xE8F0, 0x9E86, 0xECB0, 0x9E87, 0xECB1, 0x9E88, 0xECAF, 0x9E89, 0xEFAB, + 0x9E8A, 0xEFAA, 0x9E8B, 0xC247, 0x9E8C, 0xF1DF, 0x9E8D, 0xEFAC, 0x9E8E, 0xF1DE, 0x9E91, 0xF3F3, 0x9E92, 0xC451, 0x9E93, 0xC453, + 0x9E94, 0xF3F2, 0x9E97, 0xC452, 0x9E99, 0xF5B1, 0x9E9A, 0xF5B3, 0x9E9B, 0xF5B2, 0x9E9C, 0xF6CA, 0x9E9D, 0xC565, 0x9E9F, 0xC5EF, + 0x9EA0, 0xF8E8, 0x9EA1, 0xF963, 0x9EA4, 0xF9D2, 0x9EA5, 0xB3C1, 0x9EA7, 0xE4E5, 0x9EA9, 0xBEA2, 0x9EAD, 0xECB3, 0x9EAE, 0xECB2, + 0x9EB0, 0xEFAD, 0x9EB4, 0xC454, 0x9EB5, 0xC4D1, 0x9EB6, 0xF7C7, 0x9EB7, 0xF9CB, 0x9EBB, 0xB3C2, 0x9EBC, 0xBBF2, 0x9EBE, 0xBEA3, + 0x9EC0, 0xF3F4, 0x9EC2, 0xF874, 0x9EC3, 0xB6C0, 0x9EC8, 0xEFAE, 0x9ECC, 0xC664, 0x9ECD, 0xB6C1, 0x9ECE, 0xBEA4, 0x9ECF, 0xC248, + 0x9ED0, 0xF875, 0x9ED1, 0xB6C2, 0x9ED3, 0xE8F1, 0x9ED4, 0xC072, 0x9ED5, 0xECB4, 0x9ED6, 0xECB5, 0x9ED8, 0xC071, 0x9EDA, 0xEFAF, + 0x9EDB, 0xC24C, 0x9EDC, 0xC24A, 0x9EDD, 0xC24B, 0x9EDE, 0xC249, 0x9EDF, 0xF1E0, 0x9EE0, 0xC35C, 0x9EE4, 0xF5B5, 0x9EE5, 0xF5B4, + 0x9EE6, 0xF5B7, 0x9EE7, 0xF5B6, 0x9EE8, 0xC4D2, 0x9EEB, 0xF6CB, 0x9EED, 0xF6CD, 0x9EEE, 0xF6CC, 0x9EEF, 0xC566, 0x9EF0, 0xF7C8, + 0x9EF2, 0xF876, 0x9EF3, 0xF877, 0x9EF4, 0xC5F0, 0x9EF5, 0xF964, 0x9EF6, 0xF97D, 0x9EF7, 0xC675, 0x9EF9, 0xDCB0, 0x9EFA, 0xECB6, + 0x9EFB, 0xEFB0, 0x9EFC, 0xF3F5, 0x9EFD, 0xE0EF, 0x9EFF, 0xEFB1, 0x9F00, 0xF1E2, 0x9F01, 0xF1E1, 0x9F06, 0xF878, 0x9F07, 0xC652, + 0x9F09, 0xF965, 0x9F0A, 0xF97E, 0x9F0E, 0xB9A9, 0x9F0F, 0xE8F2, 0x9F10, 0xE8F3, 0x9F12, 0xECB7, 0x9F13, 0xB9AA, 0x9F15, 0xC35D, + 0x9F16, 0xF1E3, 0x9F18, 0xF6CF, 0x9F19, 0xC567, 0x9F1A, 0xF6D0, 0x9F1B, 0xF6CE, 0x9F1C, 0xF879, 0x9F1E, 0xF8E9, 0x9F20, 0xB9AB, + 0x9F22, 0xEFB4, 0x9F23, 0xEFB3, 0x9F24, 0xEFB2, 0x9F25, 0xF1E4, 0x9F28, 0xF1E8, 0x9F29, 0xF1E7, 0x9F2A, 0xF1E6, 0x9F2B, 0xF1E5, + 0x9F2C, 0xC35E, 0x9F2D, 0xF3F6, 0x9F2E, 0xF5B9, 0x9F2F, 0xC4D3, 0x9F30, 0xF5B8, 0x9F31, 0xF6D1, 0x9F32, 0xF7CB, 0x9F33, 0xF7CA, + 0x9F34, 0xC5C4, 0x9F35, 0xF7C9, 0x9F36, 0xF87C, 0x9F37, 0xF87B, 0x9F38, 0xF87A, 0x9F3B, 0xBBF3, 0x9F3D, 0xECB8, 0x9F3E, 0xC24D, + 0x9F40, 0xF3F7, 0x9F41, 0xF3F8, 0x9F42, 0xF7CC, 0x9F43, 0xF87D, 0x9F46, 0xF8EA, 0x9F47, 0xF966, 0x9F48, 0xF9B9, 0x9F49, 0xF9D4, + 0x9F4A, 0xBBF4, 0x9F4B, 0xC24E, 0x9F4C, 0xF1E9, 0x9F4D, 0xF3F9, 0x9F4E, 0xF6D2, 0x9F4F, 0xF87E, 0x9F52, 0xBEA6, 0x9F54, 0xEFB5, + 0x9F55, 0xF1EA, 0x9F56, 0xF3FA, 0x9F57, 0xF3FB, 0x9F58, 0xF3FC, 0x9F59, 0xF5BE, 0x9F5B, 0xF5BA, 0x9F5C, 0xC568, 0x9F5D, 0xF5BD, + 0x9F5E, 0xF5BC, 0x9F5F, 0xC4D4, 0x9F60, 0xF5BB, 0x9F61, 0xC4D6, 0x9F63, 0xC4D5, 0x9F64, 0xF6D4, 0x9F65, 0xF6D3, 0x9F66, 0xC569, + 0x9F67, 0xC56A, 0x9F6A, 0xC5C6, 0x9F6B, 0xF7CD, 0x9F6C, 0xC5C5, 0x9F6E, 0xF8A3, 0x9F6F, 0xF8A4, 0x9F70, 0xF8A2, 0x9F71, 0xF8A1, + 0x9F72, 0xC654, 0x9F74, 0xF8EB, 0x9F75, 0xF8EC, 0x9F76, 0xF8ED, 0x9F77, 0xC653, 0x9F78, 0xF967, 0x9F79, 0xF96A, 0x9F7A, 0xF969, + 0x9F7B, 0xF968, 0x9F7E, 0xF9D3, 0x9F8D, 0xC073, 0x9F90, 0xC365, 0x9F91, 0xF5BF, 0x9F92, 0xF6D5, 0x9F94, 0xC5C7, 0x9F95, 0xF7CE, + 0x9F98, 0xF9D5, 0x9F9C, 0xC074, 0x9FA0, 0xEFB6, 0x9FA2, 0xF7CF, 0x9FA4, 0xF9A1, 0xFA0C, 0xC94A, 0xFA0D, 0xDDFC, 0xFE30, 0xA14A, + 0xFE31, 0xA157, 0xFE33, 0xA159, 0xFE34, 0xA15B, 0xFE35, 0xA15F, 0xFE36, 0xA160, 0xFE37, 0xA163, 0xFE38, 0xA164, 0xFE39, 0xA167, + 0xFE3A, 0xA168, 0xFE3B, 0xA16B, 0xFE3C, 0xA16C, 0xFE3D, 0xA16F, 0xFE3E, 0xA170, 0xFE3F, 0xA173, 0xFE40, 0xA174, 0xFE41, 0xA177, + 0xFE42, 0xA178, 0xFE43, 0xA17B, 0xFE44, 0xA17C, 0xFE49, 0xA1C6, 0xFE4A, 0xA1C7, 0xFE4B, 0xA1CA, 0xFE4C, 0xA1CB, 0xFE4D, 0xA1C8, + 0xFE4E, 0xA1C9, 0xFE4F, 0xA15C, 0xFE50, 0xA14D, 0xFE51, 0xA14E, 0xFE52, 0xA14F, 0xFE54, 0xA151, 0xFE55, 0xA152, 0xFE56, 0xA153, + 0xFE57, 0xA154, 0xFE59, 0xA17D, 0xFE5A, 0xA17E, 0xFE5B, 0xA1A1, 0xFE5C, 0xA1A2, 0xFE5D, 0xA1A3, 0xFE5E, 0xA1A4, 0xFE5F, 0xA1CC, + 0xFE60, 0xA1CD, 0xFE61, 0xA1CE, 0xFE62, 0xA1DE, 0xFE63, 0xA1DF, 0xFE64, 0xA1E0, 0xFE65, 0xA1E1, 0xFE66, 0xA1E2, 0xFE68, 0xA242, + 0xFE69, 0xA24C, 0xFE6A, 0xA24D, 0xFE6B, 0xA24E, 0xFF01, 0xA149, 0xFF03, 0xA1AD, 0xFF04, 0xA243, 0xFF05, 0xA248, 0xFF06, 0xA1AE, + 0xFF08, 0xA15D, 0xFF09, 0xA15E, 0xFF0A, 0xA1AF, 0xFF0B, 0xA1CF, 0xFF0C, 0xA141, 0xFF0D, 0xA1D0, 0xFF0E, 0xA144, 0xFF0F, 0xA1FE, + 0xFF10, 0xA2AF, 0xFF11, 0xA2B0, 0xFF12, 0xA2B1, 0xFF13, 0xA2B2, 0xFF14, 0xA2B3, 0xFF15, 0xA2B4, 0xFF16, 0xA2B5, 0xFF17, 0xA2B6, + 0xFF18, 0xA2B7, 0xFF19, 0xA2B8, 0xFF1A, 0xA147, 0xFF1B, 0xA146, 0xFF1C, 0xA1D5, 0xFF1D, 0xA1D7, 0xFF1E, 0xA1D6, 0xFF1F, 0xA148, + 0xFF20, 0xA249, 0xFF21, 0xA2CF, 0xFF22, 0xA2D0, 0xFF23, 0xA2D1, 0xFF24, 0xA2D2, 0xFF25, 0xA2D3, 0xFF26, 0xA2D4, 0xFF27, 0xA2D5, + 0xFF28, 0xA2D6, 0xFF29, 0xA2D7, 0xFF2A, 0xA2D8, 0xFF2B, 0xA2D9, 0xFF2C, 0xA2DA, 0xFF2D, 0xA2DB, 0xFF2E, 0xA2DC, 0xFF2F, 0xA2DD, + 0xFF30, 0xA2DE, 0xFF31, 0xA2DF, 0xFF32, 0xA2E0, 0xFF33, 0xA2E1, 0xFF34, 0xA2E2, 0xFF35, 0xA2E3, 0xFF36, 0xA2E4, 0xFF37, 0xA2E5, + 0xFF38, 0xA2E6, 0xFF39, 0xA2E7, 0xFF3A, 0xA2E8, 0xFF3C, 0xA240, 0xFF3F, 0xA1C4, 0xFF41, 0xA2E9, 0xFF42, 0xA2EA, 0xFF43, 0xA2EB, + 0xFF44, 0xA2EC, 0xFF45, 0xA2ED, 0xFF46, 0xA2EE, 0xFF47, 0xA2EF, 0xFF48, 0xA2F0, 0xFF49, 0xA2F1, 0xFF4A, 0xA2F2, 0xFF4B, 0xA2F3, + 0xFF4C, 0xA2F4, 0xFF4D, 0xA2F5, 0xFF4E, 0xA2F6, 0xFF4F, 0xA2F7, 0xFF50, 0xA2F8, 0xFF51, 0xA2F9, 0xFF52, 0xA2FA, 0xFF53, 0xA2FB, + 0xFF54, 0xA2FC, 0xFF55, 0xA2FD, 0xFF56, 0xA2FE, 0xFF57, 0xA340, 0xFF58, 0xA341, 0xFF59, 0xA342, 0xFF5A, 0xA343, 0xFF5B, 0xA161, + 0xFF5C, 0xA155, 0xFF5D, 0xA162, 0xFF5E, 0xA1E3, 0xFFE0, 0xA246, 0xFFE1, 0xA247, 0xFFE3, 0xA1C3, 0xFFE5, 0xA244, 0, 0 +}; + +static const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */ + 0xA140, 0x3000, 0xA141, 0xFF0C, 0xA142, 0x3001, 0xA143, 0x3002, 0xA144, 0xFF0E, 0xA145, 0x2027, 0xA146, 0xFF1B, 0xA147, 0xFF1A, + 0xA148, 0xFF1F, 0xA149, 0xFF01, 0xA14A, 0xFE30, 0xA14B, 0x2026, 0xA14C, 0x2025, 0xA14D, 0xFE50, 0xA14E, 0xFE51, 0xA14F, 0xFE52, + 0xA150, 0x00B7, 0xA151, 0xFE54, 0xA152, 0xFE55, 0xA153, 0xFE56, 0xA154, 0xFE57, 0xA155, 0xFF5C, 0xA156, 0x2013, 0xA157, 0xFE31, + 0xA158, 0x2014, 0xA159, 0xFE33, 0xA15A, 0x2574, 0xA15B, 0xFE34, 0xA15C, 0xFE4F, 0xA15D, 0xFF08, 0xA15E, 0xFF09, 0xA15F, 0xFE35, + 0xA160, 0xFE36, 0xA161, 0xFF5B, 0xA162, 0xFF5D, 0xA163, 0xFE37, 0xA164, 0xFE38, 0xA165, 0x3014, 0xA166, 0x3015, 0xA167, 0xFE39, + 0xA168, 0xFE3A, 0xA169, 0x3010, 0xA16A, 0x3011, 0xA16B, 0xFE3B, 0xA16C, 0xFE3C, 0xA16D, 0x300A, 0xA16E, 0x300B, 0xA16F, 0xFE3D, + 0xA170, 0xFE3E, 0xA171, 0x3008, 0xA172, 0x3009, 0xA173, 0xFE3F, 0xA174, 0xFE40, 0xA175, 0x300C, 0xA176, 0x300D, 0xA177, 0xFE41, + 0xA178, 0xFE42, 0xA179, 0x300E, 0xA17A, 0x300F, 0xA17B, 0xFE43, 0xA17C, 0xFE44, 0xA17D, 0xFE59, 0xA17E, 0xFE5A, 0xA1A1, 0xFE5B, + 0xA1A2, 0xFE5C, 0xA1A3, 0xFE5D, 0xA1A4, 0xFE5E, 0xA1A5, 0x2018, 0xA1A6, 0x2019, 0xA1A7, 0x201C, 0xA1A8, 0x201D, 0xA1A9, 0x301D, + 0xA1AA, 0x301E, 0xA1AB, 0x2035, 0xA1AC, 0x2032, 0xA1AD, 0xFF03, 0xA1AE, 0xFF06, 0xA1AF, 0xFF0A, 0xA1B0, 0x203B, 0xA1B1, 0x00A7, + 0xA1B2, 0x3003, 0xA1B3, 0x25CB, 0xA1B4, 0x25CF, 0xA1B5, 0x25B3, 0xA1B6, 0x25B2, 0xA1B7, 0x25CE, 0xA1B8, 0x2606, 0xA1B9, 0x2605, + 0xA1BA, 0x25C7, 0xA1BB, 0x25C6, 0xA1BC, 0x25A1, 0xA1BD, 0x25A0, 0xA1BE, 0x25BD, 0xA1BF, 0x25BC, 0xA1C0, 0x32A3, 0xA1C1, 0x2105, + 0xA1C2, 0x00AF, 0xA1C3, 0xFFE3, 0xA1C4, 0xFF3F, 0xA1C5, 0x02CD, 0xA1C6, 0xFE49, 0xA1C7, 0xFE4A, 0xA1C8, 0xFE4D, 0xA1C9, 0xFE4E, + 0xA1CA, 0xFE4B, 0xA1CB, 0xFE4C, 0xA1CC, 0xFE5F, 0xA1CD, 0xFE60, 0xA1CE, 0xFE61, 0xA1CF, 0xFF0B, 0xA1D0, 0xFF0D, 0xA1D1, 0x00D7, + 0xA1D2, 0x00F7, 0xA1D3, 0x00B1, 0xA1D4, 0x221A, 0xA1D5, 0xFF1C, 0xA1D6, 0xFF1E, 0xA1D7, 0xFF1D, 0xA1D8, 0x2266, 0xA1D9, 0x2267, + 0xA1DA, 0x2260, 0xA1DB, 0x221E, 0xA1DC, 0x2252, 0xA1DD, 0x2261, 0xA1DE, 0xFE62, 0xA1DF, 0xFE63, 0xA1E0, 0xFE64, 0xA1E1, 0xFE65, + 0xA1E2, 0xFE66, 0xA1E3, 0xFF5E, 0xA1E4, 0x2229, 0xA1E5, 0x222A, 0xA1E6, 0x22A5, 0xA1E7, 0x2220, 0xA1E8, 0x221F, 0xA1E9, 0x22BF, + 0xA1EA, 0x33D2, 0xA1EB, 0x33D1, 0xA1EC, 0x222B, 0xA1ED, 0x222E, 0xA1EE, 0x2235, 0xA1EF, 0x2234, 0xA1F0, 0x2640, 0xA1F1, 0x2642, + 0xA1F2, 0x2295, 0xA1F3, 0x2299, 0xA1F4, 0x2191, 0xA1F5, 0x2193, 0xA1F6, 0x2190, 0xA1F7, 0x2192, 0xA1F8, 0x2196, 0xA1F9, 0x2197, + 0xA1FA, 0x2199, 0xA1FB, 0x2198, 0xA1FC, 0x2225, 0xA1FD, 0x2223, 0xA1FE, 0xFF0F, 0xA240, 0xFF3C, 0xA241, 0x2215, 0xA242, 0xFE68, + 0xA243, 0xFF04, 0xA244, 0xFFE5, 0xA245, 0x3012, 0xA246, 0xFFE0, 0xA247, 0xFFE1, 0xA248, 0xFF05, 0xA249, 0xFF20, 0xA24A, 0x2103, + 0xA24B, 0x2109, 0xA24C, 0xFE69, 0xA24D, 0xFE6A, 0xA24E, 0xFE6B, 0xA24F, 0x33D5, 0xA250, 0x339C, 0xA251, 0x339D, 0xA252, 0x339E, + 0xA253, 0x33CE, 0xA254, 0x33A1, 0xA255, 0x338E, 0xA256, 0x338F, 0xA257, 0x33C4, 0xA258, 0x00B0, 0xA259, 0x5159, 0xA25A, 0x515B, + 0xA25B, 0x515E, 0xA25C, 0x515D, 0xA25D, 0x5161, 0xA25E, 0x5163, 0xA25F, 0x55E7, 0xA260, 0x74E9, 0xA261, 0x7CCE, 0xA262, 0x2581, + 0xA263, 0x2582, 0xA264, 0x2583, 0xA265, 0x2584, 0xA266, 0x2585, 0xA267, 0x2586, 0xA268, 0x2587, 0xA269, 0x2588, 0xA26A, 0x258F, + 0xA26B, 0x258E, 0xA26C, 0x258D, 0xA26D, 0x258C, 0xA26E, 0x258B, 0xA26F, 0x258A, 0xA270, 0x2589, 0xA271, 0x253C, 0xA272, 0x2534, + 0xA273, 0x252C, 0xA274, 0x2524, 0xA275, 0x251C, 0xA276, 0x2594, 0xA277, 0x2500, 0xA278, 0x2502, 0xA279, 0x2595, 0xA27A, 0x250C, + 0xA27B, 0x2510, 0xA27C, 0x2514, 0xA27D, 0x2518, 0xA27E, 0x256D, 0xA2A1, 0x256E, 0xA2A2, 0x2570, 0xA2A3, 0x256F, 0xA2A4, 0x2550, + 0xA2A5, 0x255E, 0xA2A6, 0x256A, 0xA2A7, 0x2561, 0xA2A8, 0x25E2, 0xA2A9, 0x25E3, 0xA2AA, 0x25E5, 0xA2AB, 0x25E4, 0xA2AC, 0x2571, + 0xA2AD, 0x2572, 0xA2AE, 0x2573, 0xA2AF, 0xFF10, 0xA2B0, 0xFF11, 0xA2B1, 0xFF12, 0xA2B2, 0xFF13, 0xA2B3, 0xFF14, 0xA2B4, 0xFF15, + 0xA2B5, 0xFF16, 0xA2B6, 0xFF17, 0xA2B7, 0xFF18, 0xA2B8, 0xFF19, 0xA2B9, 0x2160, 0xA2BA, 0x2161, 0xA2BB, 0x2162, 0xA2BC, 0x2163, + 0xA2BD, 0x2164, 0xA2BE, 0x2165, 0xA2BF, 0x2166, 0xA2C0, 0x2167, 0xA2C1, 0x2168, 0xA2C2, 0x2169, 0xA2C3, 0x3021, 0xA2C4, 0x3022, + 0xA2C5, 0x3023, 0xA2C6, 0x3024, 0xA2C7, 0x3025, 0xA2C8, 0x3026, 0xA2C9, 0x3027, 0xA2CA, 0x3028, 0xA2CB, 0x3029, 0xA2CC, 0x5341, + 0xA2CD, 0x5344, 0xA2CE, 0x5345, 0xA2CF, 0xFF21, 0xA2D0, 0xFF22, 0xA2D1, 0xFF23, 0xA2D2, 0xFF24, 0xA2D3, 0xFF25, 0xA2D4, 0xFF26, + 0xA2D5, 0xFF27, 0xA2D6, 0xFF28, 0xA2D7, 0xFF29, 0xA2D8, 0xFF2A, 0xA2D9, 0xFF2B, 0xA2DA, 0xFF2C, 0xA2DB, 0xFF2D, 0xA2DC, 0xFF2E, + 0xA2DD, 0xFF2F, 0xA2DE, 0xFF30, 0xA2DF, 0xFF31, 0xA2E0, 0xFF32, 0xA2E1, 0xFF33, 0xA2E2, 0xFF34, 0xA2E3, 0xFF35, 0xA2E4, 0xFF36, + 0xA2E5, 0xFF37, 0xA2E6, 0xFF38, 0xA2E7, 0xFF39, 0xA2E8, 0xFF3A, 0xA2E9, 0xFF41, 0xA2EA, 0xFF42, 0xA2EB, 0xFF43, 0xA2EC, 0xFF44, + 0xA2ED, 0xFF45, 0xA2EE, 0xFF46, 0xA2EF, 0xFF47, 0xA2F0, 0xFF48, 0xA2F1, 0xFF49, 0xA2F2, 0xFF4A, 0xA2F3, 0xFF4B, 0xA2F4, 0xFF4C, + 0xA2F5, 0xFF4D, 0xA2F6, 0xFF4E, 0xA2F7, 0xFF4F, 0xA2F8, 0xFF50, 0xA2F9, 0xFF51, 0xA2FA, 0xFF52, 0xA2FB, 0xFF53, 0xA2FC, 0xFF54, + 0xA2FD, 0xFF55, 0xA2FE, 0xFF56, 0xA340, 0xFF57, 0xA341, 0xFF58, 0xA342, 0xFF59, 0xA343, 0xFF5A, 0xA344, 0x0391, 0xA345, 0x0392, + 0xA346, 0x0393, 0xA347, 0x0394, 0xA348, 0x0395, 0xA349, 0x0396, 0xA34A, 0x0397, 0xA34B, 0x0398, 0xA34C, 0x0399, 0xA34D, 0x039A, + 0xA34E, 0x039B, 0xA34F, 0x039C, 0xA350, 0x039D, 0xA351, 0x039E, 0xA352, 0x039F, 0xA353, 0x03A0, 0xA354, 0x03A1, 0xA355, 0x03A3, + 0xA356, 0x03A4, 0xA357, 0x03A5, 0xA358, 0x03A6, 0xA359, 0x03A7, 0xA35A, 0x03A8, 0xA35B, 0x03A9, 0xA35C, 0x03B1, 0xA35D, 0x03B2, + 0xA35E, 0x03B3, 0xA35F, 0x03B4, 0xA360, 0x03B5, 0xA361, 0x03B6, 0xA362, 0x03B7, 0xA363, 0x03B8, 0xA364, 0x03B9, 0xA365, 0x03BA, + 0xA366, 0x03BB, 0xA367, 0x03BC, 0xA368, 0x03BD, 0xA369, 0x03BE, 0xA36A, 0x03BF, 0xA36B, 0x03C0, 0xA36C, 0x03C1, 0xA36D, 0x03C3, + 0xA36E, 0x03C4, 0xA36F, 0x03C5, 0xA370, 0x03C6, 0xA371, 0x03C7, 0xA372, 0x03C8, 0xA373, 0x03C9, 0xA374, 0x3105, 0xA375, 0x3106, + 0xA376, 0x3107, 0xA377, 0x3108, 0xA378, 0x3109, 0xA379, 0x310A, 0xA37A, 0x310B, 0xA37B, 0x310C, 0xA37C, 0x310D, 0xA37D, 0x310E, + 0xA37E, 0x310F, 0xA3A1, 0x3110, 0xA3A2, 0x3111, 0xA3A3, 0x3112, 0xA3A4, 0x3113, 0xA3A5, 0x3114, 0xA3A6, 0x3115, 0xA3A7, 0x3116, + 0xA3A8, 0x3117, 0xA3A9, 0x3118, 0xA3AA, 0x3119, 0xA3AB, 0x311A, 0xA3AC, 0x311B, 0xA3AD, 0x311C, 0xA3AE, 0x311D, 0xA3AF, 0x311E, + 0xA3B0, 0x311F, 0xA3B1, 0x3120, 0xA3B2, 0x3121, 0xA3B3, 0x3122, 0xA3B4, 0x3123, 0xA3B5, 0x3124, 0xA3B6, 0x3125, 0xA3B7, 0x3126, + 0xA3B8, 0x3127, 0xA3B9, 0x3128, 0xA3BA, 0x3129, 0xA3BB, 0x02D9, 0xA3BC, 0x02C9, 0xA3BD, 0x02CA, 0xA3BE, 0x02C7, 0xA3BF, 0x02CB, + 0xA3E1, 0x20AC, 0xA440, 0x4E00, 0xA441, 0x4E59, 0xA442, 0x4E01, 0xA443, 0x4E03, 0xA444, 0x4E43, 0xA445, 0x4E5D, 0xA446, 0x4E86, + 0xA447, 0x4E8C, 0xA448, 0x4EBA, 0xA449, 0x513F, 0xA44A, 0x5165, 0xA44B, 0x516B, 0xA44C, 0x51E0, 0xA44D, 0x5200, 0xA44E, 0x5201, + 0xA44F, 0x529B, 0xA450, 0x5315, 0xA451, 0x5341, 0xA452, 0x535C, 0xA453, 0x53C8, 0xA454, 0x4E09, 0xA455, 0x4E0B, 0xA456, 0x4E08, + 0xA457, 0x4E0A, 0xA458, 0x4E2B, 0xA459, 0x4E38, 0xA45A, 0x51E1, 0xA45B, 0x4E45, 0xA45C, 0x4E48, 0xA45D, 0x4E5F, 0xA45E, 0x4E5E, + 0xA45F, 0x4E8E, 0xA460, 0x4EA1, 0xA461, 0x5140, 0xA462, 0x5203, 0xA463, 0x52FA, 0xA464, 0x5343, 0xA465, 0x53C9, 0xA466, 0x53E3, + 0xA467, 0x571F, 0xA468, 0x58EB, 0xA469, 0x5915, 0xA46A, 0x5927, 0xA46B, 0x5973, 0xA46C, 0x5B50, 0xA46D, 0x5B51, 0xA46E, 0x5B53, + 0xA46F, 0x5BF8, 0xA470, 0x5C0F, 0xA471, 0x5C22, 0xA472, 0x5C38, 0xA473, 0x5C71, 0xA474, 0x5DDD, 0xA475, 0x5DE5, 0xA476, 0x5DF1, + 0xA477, 0x5DF2, 0xA478, 0x5DF3, 0xA479, 0x5DFE, 0xA47A, 0x5E72, 0xA47B, 0x5EFE, 0xA47C, 0x5F0B, 0xA47D, 0x5F13, 0xA47E, 0x624D, + 0xA4A1, 0x4E11, 0xA4A2, 0x4E10, 0xA4A3, 0x4E0D, 0xA4A4, 0x4E2D, 0xA4A5, 0x4E30, 0xA4A6, 0x4E39, 0xA4A7, 0x4E4B, 0xA4A8, 0x5C39, + 0xA4A9, 0x4E88, 0xA4AA, 0x4E91, 0xA4AB, 0x4E95, 0xA4AC, 0x4E92, 0xA4AD, 0x4E94, 0xA4AE, 0x4EA2, 0xA4AF, 0x4EC1, 0xA4B0, 0x4EC0, + 0xA4B1, 0x4EC3, 0xA4B2, 0x4EC6, 0xA4B3, 0x4EC7, 0xA4B4, 0x4ECD, 0xA4B5, 0x4ECA, 0xA4B6, 0x4ECB, 0xA4B7, 0x4EC4, 0xA4B8, 0x5143, + 0xA4B9, 0x5141, 0xA4BA, 0x5167, 0xA4BB, 0x516D, 0xA4BC, 0x516E, 0xA4BD, 0x516C, 0xA4BE, 0x5197, 0xA4BF, 0x51F6, 0xA4C0, 0x5206, + 0xA4C1, 0x5207, 0xA4C2, 0x5208, 0xA4C3, 0x52FB, 0xA4C4, 0x52FE, 0xA4C5, 0x52FF, 0xA4C6, 0x5316, 0xA4C7, 0x5339, 0xA4C8, 0x5348, + 0xA4C9, 0x5347, 0xA4CA, 0x5345, 0xA4CB, 0x535E, 0xA4CC, 0x5384, 0xA4CD, 0x53CB, 0xA4CE, 0x53CA, 0xA4CF, 0x53CD, 0xA4D0, 0x58EC, + 0xA4D1, 0x5929, 0xA4D2, 0x592B, 0xA4D3, 0x592A, 0xA4D4, 0x592D, 0xA4D5, 0x5B54, 0xA4D6, 0x5C11, 0xA4D7, 0x5C24, 0xA4D8, 0x5C3A, + 0xA4D9, 0x5C6F, 0xA4DA, 0x5DF4, 0xA4DB, 0x5E7B, 0xA4DC, 0x5EFF, 0xA4DD, 0x5F14, 0xA4DE, 0x5F15, 0xA4DF, 0x5FC3, 0xA4E0, 0x6208, + 0xA4E1, 0x6236, 0xA4E2, 0x624B, 0xA4E3, 0x624E, 0xA4E4, 0x652F, 0xA4E5, 0x6587, 0xA4E6, 0x6597, 0xA4E7, 0x65A4, 0xA4E8, 0x65B9, + 0xA4E9, 0x65E5, 0xA4EA, 0x66F0, 0xA4EB, 0x6708, 0xA4EC, 0x6728, 0xA4ED, 0x6B20, 0xA4EE, 0x6B62, 0xA4EF, 0x6B79, 0xA4F0, 0x6BCB, + 0xA4F1, 0x6BD4, 0xA4F2, 0x6BDB, 0xA4F3, 0x6C0F, 0xA4F4, 0x6C34, 0xA4F5, 0x706B, 0xA4F6, 0x722A, 0xA4F7, 0x7236, 0xA4F8, 0x723B, + 0xA4F9, 0x7247, 0xA4FA, 0x7259, 0xA4FB, 0x725B, 0xA4FC, 0x72AC, 0xA4FD, 0x738B, 0xA4FE, 0x4E19, 0xA540, 0x4E16, 0xA541, 0x4E15, + 0xA542, 0x4E14, 0xA543, 0x4E18, 0xA544, 0x4E3B, 0xA545, 0x4E4D, 0xA546, 0x4E4F, 0xA547, 0x4E4E, 0xA548, 0x4EE5, 0xA549, 0x4ED8, + 0xA54A, 0x4ED4, 0xA54B, 0x4ED5, 0xA54C, 0x4ED6, 0xA54D, 0x4ED7, 0xA54E, 0x4EE3, 0xA54F, 0x4EE4, 0xA550, 0x4ED9, 0xA551, 0x4EDE, + 0xA552, 0x5145, 0xA553, 0x5144, 0xA554, 0x5189, 0xA555, 0x518A, 0xA556, 0x51AC, 0xA557, 0x51F9, 0xA558, 0x51FA, 0xA559, 0x51F8, + 0xA55A, 0x520A, 0xA55B, 0x52A0, 0xA55C, 0x529F, 0xA55D, 0x5305, 0xA55E, 0x5306, 0xA55F, 0x5317, 0xA560, 0x531D, 0xA561, 0x4EDF, + 0xA562, 0x534A, 0xA563, 0x5349, 0xA564, 0x5361, 0xA565, 0x5360, 0xA566, 0x536F, 0xA567, 0x536E, 0xA568, 0x53BB, 0xA569, 0x53EF, + 0xA56A, 0x53E4, 0xA56B, 0x53F3, 0xA56C, 0x53EC, 0xA56D, 0x53EE, 0xA56E, 0x53E9, 0xA56F, 0x53E8, 0xA570, 0x53FC, 0xA571, 0x53F8, + 0xA572, 0x53F5, 0xA573, 0x53EB, 0xA574, 0x53E6, 0xA575, 0x53EA, 0xA576, 0x53F2, 0xA577, 0x53F1, 0xA578, 0x53F0, 0xA579, 0x53E5, + 0xA57A, 0x53ED, 0xA57B, 0x53FB, 0xA57C, 0x56DB, 0xA57D, 0x56DA, 0xA57E, 0x5916, 0xA5A1, 0x592E, 0xA5A2, 0x5931, 0xA5A3, 0x5974, + 0xA5A4, 0x5976, 0xA5A5, 0x5B55, 0xA5A6, 0x5B83, 0xA5A7, 0x5C3C, 0xA5A8, 0x5DE8, 0xA5A9, 0x5DE7, 0xA5AA, 0x5DE6, 0xA5AB, 0x5E02, + 0xA5AC, 0x5E03, 0xA5AD, 0x5E73, 0xA5AE, 0x5E7C, 0xA5AF, 0x5F01, 0xA5B0, 0x5F18, 0xA5B1, 0x5F17, 0xA5B2, 0x5FC5, 0xA5B3, 0x620A, + 0xA5B4, 0x6253, 0xA5B5, 0x6254, 0xA5B6, 0x6252, 0xA5B7, 0x6251, 0xA5B8, 0x65A5, 0xA5B9, 0x65E6, 0xA5BA, 0x672E, 0xA5BB, 0x672C, + 0xA5BC, 0x672A, 0xA5BD, 0x672B, 0xA5BE, 0x672D, 0xA5BF, 0x6B63, 0xA5C0, 0x6BCD, 0xA5C1, 0x6C11, 0xA5C2, 0x6C10, 0xA5C3, 0x6C38, + 0xA5C4, 0x6C41, 0xA5C5, 0x6C40, 0xA5C6, 0x6C3E, 0xA5C7, 0x72AF, 0xA5C8, 0x7384, 0xA5C9, 0x7389, 0xA5CA, 0x74DC, 0xA5CB, 0x74E6, + 0xA5CC, 0x7518, 0xA5CD, 0x751F, 0xA5CE, 0x7528, 0xA5CF, 0x7529, 0xA5D0, 0x7530, 0xA5D1, 0x7531, 0xA5D2, 0x7532, 0xA5D3, 0x7533, + 0xA5D4, 0x758B, 0xA5D5, 0x767D, 0xA5D6, 0x76AE, 0xA5D7, 0x76BF, 0xA5D8, 0x76EE, 0xA5D9, 0x77DB, 0xA5DA, 0x77E2, 0xA5DB, 0x77F3, + 0xA5DC, 0x793A, 0xA5DD, 0x79BE, 0xA5DE, 0x7A74, 0xA5DF, 0x7ACB, 0xA5E0, 0x4E1E, 0xA5E1, 0x4E1F, 0xA5E2, 0x4E52, 0xA5E3, 0x4E53, + 0xA5E4, 0x4E69, 0xA5E5, 0x4E99, 0xA5E6, 0x4EA4, 0xA5E7, 0x4EA6, 0xA5E8, 0x4EA5, 0xA5E9, 0x4EFF, 0xA5EA, 0x4F09, 0xA5EB, 0x4F19, + 0xA5EC, 0x4F0A, 0xA5ED, 0x4F15, 0xA5EE, 0x4F0D, 0xA5EF, 0x4F10, 0xA5F0, 0x4F11, 0xA5F1, 0x4F0F, 0xA5F2, 0x4EF2, 0xA5F3, 0x4EF6, + 0xA5F4, 0x4EFB, 0xA5F5, 0x4EF0, 0xA5F6, 0x4EF3, 0xA5F7, 0x4EFD, 0xA5F8, 0x4F01, 0xA5F9, 0x4F0B, 0xA5FA, 0x5149, 0xA5FB, 0x5147, + 0xA5FC, 0x5146, 0xA5FD, 0x5148, 0xA5FE, 0x5168, 0xA640, 0x5171, 0xA641, 0x518D, 0xA642, 0x51B0, 0xA643, 0x5217, 0xA644, 0x5211, + 0xA645, 0x5212, 0xA646, 0x520E, 0xA647, 0x5216, 0xA648, 0x52A3, 0xA649, 0x5308, 0xA64A, 0x5321, 0xA64B, 0x5320, 0xA64C, 0x5370, + 0xA64D, 0x5371, 0xA64E, 0x5409, 0xA64F, 0x540F, 0xA650, 0x540C, 0xA651, 0x540A, 0xA652, 0x5410, 0xA653, 0x5401, 0xA654, 0x540B, + 0xA655, 0x5404, 0xA656, 0x5411, 0xA657, 0x540D, 0xA658, 0x5408, 0xA659, 0x5403, 0xA65A, 0x540E, 0xA65B, 0x5406, 0xA65C, 0x5412, + 0xA65D, 0x56E0, 0xA65E, 0x56DE, 0xA65F, 0x56DD, 0xA660, 0x5733, 0xA661, 0x5730, 0xA662, 0x5728, 0xA663, 0x572D, 0xA664, 0x572C, + 0xA665, 0x572F, 0xA666, 0x5729, 0xA667, 0x5919, 0xA668, 0x591A, 0xA669, 0x5937, 0xA66A, 0x5938, 0xA66B, 0x5984, 0xA66C, 0x5978, + 0xA66D, 0x5983, 0xA66E, 0x597D, 0xA66F, 0x5979, 0xA670, 0x5982, 0xA671, 0x5981, 0xA672, 0x5B57, 0xA673, 0x5B58, 0xA674, 0x5B87, + 0xA675, 0x5B88, 0xA676, 0x5B85, 0xA677, 0x5B89, 0xA678, 0x5BFA, 0xA679, 0x5C16, 0xA67A, 0x5C79, 0xA67B, 0x5DDE, 0xA67C, 0x5E06, + 0xA67D, 0x5E76, 0xA67E, 0x5E74, 0xA6A1, 0x5F0F, 0xA6A2, 0x5F1B, 0xA6A3, 0x5FD9, 0xA6A4, 0x5FD6, 0xA6A5, 0x620E, 0xA6A6, 0x620C, + 0xA6A7, 0x620D, 0xA6A8, 0x6210, 0xA6A9, 0x6263, 0xA6AA, 0x625B, 0xA6AB, 0x6258, 0xA6AC, 0x6536, 0xA6AD, 0x65E9, 0xA6AE, 0x65E8, + 0xA6AF, 0x65EC, 0xA6B0, 0x65ED, 0xA6B1, 0x66F2, 0xA6B2, 0x66F3, 0xA6B3, 0x6709, 0xA6B4, 0x673D, 0xA6B5, 0x6734, 0xA6B6, 0x6731, + 0xA6B7, 0x6735, 0xA6B8, 0x6B21, 0xA6B9, 0x6B64, 0xA6BA, 0x6B7B, 0xA6BB, 0x6C16, 0xA6BC, 0x6C5D, 0xA6BD, 0x6C57, 0xA6BE, 0x6C59, + 0xA6BF, 0x6C5F, 0xA6C0, 0x6C60, 0xA6C1, 0x6C50, 0xA6C2, 0x6C55, 0xA6C3, 0x6C61, 0xA6C4, 0x6C5B, 0xA6C5, 0x6C4D, 0xA6C6, 0x6C4E, + 0xA6C7, 0x7070, 0xA6C8, 0x725F, 0xA6C9, 0x725D, 0xA6CA, 0x767E, 0xA6CB, 0x7AF9, 0xA6CC, 0x7C73, 0xA6CD, 0x7CF8, 0xA6CE, 0x7F36, + 0xA6CF, 0x7F8A, 0xA6D0, 0x7FBD, 0xA6D1, 0x8001, 0xA6D2, 0x8003, 0xA6D3, 0x800C, 0xA6D4, 0x8012, 0xA6D5, 0x8033, 0xA6D6, 0x807F, + 0xA6D7, 0x8089, 0xA6D8, 0x808B, 0xA6D9, 0x808C, 0xA6DA, 0x81E3, 0xA6DB, 0x81EA, 0xA6DC, 0x81F3, 0xA6DD, 0x81FC, 0xA6DE, 0x820C, + 0xA6DF, 0x821B, 0xA6E0, 0x821F, 0xA6E1, 0x826E, 0xA6E2, 0x8272, 0xA6E3, 0x827E, 0xA6E4, 0x866B, 0xA6E5, 0x8840, 0xA6E6, 0x884C, + 0xA6E7, 0x8863, 0xA6E8, 0x897F, 0xA6E9, 0x9621, 0xA6EA, 0x4E32, 0xA6EB, 0x4EA8, 0xA6EC, 0x4F4D, 0xA6ED, 0x4F4F, 0xA6EE, 0x4F47, + 0xA6EF, 0x4F57, 0xA6F0, 0x4F5E, 0xA6F1, 0x4F34, 0xA6F2, 0x4F5B, 0xA6F3, 0x4F55, 0xA6F4, 0x4F30, 0xA6F5, 0x4F50, 0xA6F6, 0x4F51, + 0xA6F7, 0x4F3D, 0xA6F8, 0x4F3A, 0xA6F9, 0x4F38, 0xA6FA, 0x4F43, 0xA6FB, 0x4F54, 0xA6FC, 0x4F3C, 0xA6FD, 0x4F46, 0xA6FE, 0x4F63, + 0xA740, 0x4F5C, 0xA741, 0x4F60, 0xA742, 0x4F2F, 0xA743, 0x4F4E, 0xA744, 0x4F36, 0xA745, 0x4F59, 0xA746, 0x4F5D, 0xA747, 0x4F48, + 0xA748, 0x4F5A, 0xA749, 0x514C, 0xA74A, 0x514B, 0xA74B, 0x514D, 0xA74C, 0x5175, 0xA74D, 0x51B6, 0xA74E, 0x51B7, 0xA74F, 0x5225, + 0xA750, 0x5224, 0xA751, 0x5229, 0xA752, 0x522A, 0xA753, 0x5228, 0xA754, 0x52AB, 0xA755, 0x52A9, 0xA756, 0x52AA, 0xA757, 0x52AC, + 0xA758, 0x5323, 0xA759, 0x5373, 0xA75A, 0x5375, 0xA75B, 0x541D, 0xA75C, 0x542D, 0xA75D, 0x541E, 0xA75E, 0x543E, 0xA75F, 0x5426, + 0xA760, 0x544E, 0xA761, 0x5427, 0xA762, 0x5446, 0xA763, 0x5443, 0xA764, 0x5433, 0xA765, 0x5448, 0xA766, 0x5442, 0xA767, 0x541B, + 0xA768, 0x5429, 0xA769, 0x544A, 0xA76A, 0x5439, 0xA76B, 0x543B, 0xA76C, 0x5438, 0xA76D, 0x542E, 0xA76E, 0x5435, 0xA76F, 0x5436, + 0xA770, 0x5420, 0xA771, 0x543C, 0xA772, 0x5440, 0xA773, 0x5431, 0xA774, 0x542B, 0xA775, 0x541F, 0xA776, 0x542C, 0xA777, 0x56EA, + 0xA778, 0x56F0, 0xA779, 0x56E4, 0xA77A, 0x56EB, 0xA77B, 0x574A, 0xA77C, 0x5751, 0xA77D, 0x5740, 0xA77E, 0x574D, 0xA7A1, 0x5747, + 0xA7A2, 0x574E, 0xA7A3, 0x573E, 0xA7A4, 0x5750, 0xA7A5, 0x574F, 0xA7A6, 0x573B, 0xA7A7, 0x58EF, 0xA7A8, 0x593E, 0xA7A9, 0x599D, + 0xA7AA, 0x5992, 0xA7AB, 0x59A8, 0xA7AC, 0x599E, 0xA7AD, 0x59A3, 0xA7AE, 0x5999, 0xA7AF, 0x5996, 0xA7B0, 0x598D, 0xA7B1, 0x59A4, + 0xA7B2, 0x5993, 0xA7B3, 0x598A, 0xA7B4, 0x59A5, 0xA7B5, 0x5B5D, 0xA7B6, 0x5B5C, 0xA7B7, 0x5B5A, 0xA7B8, 0x5B5B, 0xA7B9, 0x5B8C, + 0xA7BA, 0x5B8B, 0xA7BB, 0x5B8F, 0xA7BC, 0x5C2C, 0xA7BD, 0x5C40, 0xA7BE, 0x5C41, 0xA7BF, 0x5C3F, 0xA7C0, 0x5C3E, 0xA7C1, 0x5C90, + 0xA7C2, 0x5C91, 0xA7C3, 0x5C94, 0xA7C4, 0x5C8C, 0xA7C5, 0x5DEB, 0xA7C6, 0x5E0C, 0xA7C7, 0x5E8F, 0xA7C8, 0x5E87, 0xA7C9, 0x5E8A, + 0xA7CA, 0x5EF7, 0xA7CB, 0x5F04, 0xA7CC, 0x5F1F, 0xA7CD, 0x5F64, 0xA7CE, 0x5F62, 0xA7CF, 0x5F77, 0xA7D0, 0x5F79, 0xA7D1, 0x5FD8, + 0xA7D2, 0x5FCC, 0xA7D3, 0x5FD7, 0xA7D4, 0x5FCD, 0xA7D5, 0x5FF1, 0xA7D6, 0x5FEB, 0xA7D7, 0x5FF8, 0xA7D8, 0x5FEA, 0xA7D9, 0x6212, + 0xA7DA, 0x6211, 0xA7DB, 0x6284, 0xA7DC, 0x6297, 0xA7DD, 0x6296, 0xA7DE, 0x6280, 0xA7DF, 0x6276, 0xA7E0, 0x6289, 0xA7E1, 0x626D, + 0xA7E2, 0x628A, 0xA7E3, 0x627C, 0xA7E4, 0x627E, 0xA7E5, 0x6279, 0xA7E6, 0x6273, 0xA7E7, 0x6292, 0xA7E8, 0x626F, 0xA7E9, 0x6298, + 0xA7EA, 0x626E, 0xA7EB, 0x6295, 0xA7EC, 0x6293, 0xA7ED, 0x6291, 0xA7EE, 0x6286, 0xA7EF, 0x6539, 0xA7F0, 0x653B, 0xA7F1, 0x6538, + 0xA7F2, 0x65F1, 0xA7F3, 0x66F4, 0xA7F4, 0x675F, 0xA7F5, 0x674E, 0xA7F6, 0x674F, 0xA7F7, 0x6750, 0xA7F8, 0x6751, 0xA7F9, 0x675C, + 0xA7FA, 0x6756, 0xA7FB, 0x675E, 0xA7FC, 0x6749, 0xA7FD, 0x6746, 0xA7FE, 0x6760, 0xA840, 0x6753, 0xA841, 0x6757, 0xA842, 0x6B65, + 0xA843, 0x6BCF, 0xA844, 0x6C42, 0xA845, 0x6C5E, 0xA846, 0x6C99, 0xA847, 0x6C81, 0xA848, 0x6C88, 0xA849, 0x6C89, 0xA84A, 0x6C85, + 0xA84B, 0x6C9B, 0xA84C, 0x6C6A, 0xA84D, 0x6C7A, 0xA84E, 0x6C90, 0xA84F, 0x6C70, 0xA850, 0x6C8C, 0xA851, 0x6C68, 0xA852, 0x6C96, + 0xA853, 0x6C92, 0xA854, 0x6C7D, 0xA855, 0x6C83, 0xA856, 0x6C72, 0xA857, 0x6C7E, 0xA858, 0x6C74, 0xA859, 0x6C86, 0xA85A, 0x6C76, + 0xA85B, 0x6C8D, 0xA85C, 0x6C94, 0xA85D, 0x6C98, 0xA85E, 0x6C82, 0xA85F, 0x7076, 0xA860, 0x707C, 0xA861, 0x707D, 0xA862, 0x7078, + 0xA863, 0x7262, 0xA864, 0x7261, 0xA865, 0x7260, 0xA866, 0x72C4, 0xA867, 0x72C2, 0xA868, 0x7396, 0xA869, 0x752C, 0xA86A, 0x752B, + 0xA86B, 0x7537, 0xA86C, 0x7538, 0xA86D, 0x7682, 0xA86E, 0x76EF, 0xA86F, 0x77E3, 0xA870, 0x79C1, 0xA871, 0x79C0, 0xA872, 0x79BF, + 0xA873, 0x7A76, 0xA874, 0x7CFB, 0xA875, 0x7F55, 0xA876, 0x8096, 0xA877, 0x8093, 0xA878, 0x809D, 0xA879, 0x8098, 0xA87A, 0x809B, + 0xA87B, 0x809A, 0xA87C, 0x80B2, 0xA87D, 0x826F, 0xA87E, 0x8292, 0xA8A1, 0x828B, 0xA8A2, 0x828D, 0xA8A3, 0x898B, 0xA8A4, 0x89D2, + 0xA8A5, 0x8A00, 0xA8A6, 0x8C37, 0xA8A7, 0x8C46, 0xA8A8, 0x8C55, 0xA8A9, 0x8C9D, 0xA8AA, 0x8D64, 0xA8AB, 0x8D70, 0xA8AC, 0x8DB3, + 0xA8AD, 0x8EAB, 0xA8AE, 0x8ECA, 0xA8AF, 0x8F9B, 0xA8B0, 0x8FB0, 0xA8B1, 0x8FC2, 0xA8B2, 0x8FC6, 0xA8B3, 0x8FC5, 0xA8B4, 0x8FC4, + 0xA8B5, 0x5DE1, 0xA8B6, 0x9091, 0xA8B7, 0x90A2, 0xA8B8, 0x90AA, 0xA8B9, 0x90A6, 0xA8BA, 0x90A3, 0xA8BB, 0x9149, 0xA8BC, 0x91C6, + 0xA8BD, 0x91CC, 0xA8BE, 0x9632, 0xA8BF, 0x962E, 0xA8C0, 0x9631, 0xA8C1, 0x962A, 0xA8C2, 0x962C, 0xA8C3, 0x4E26, 0xA8C4, 0x4E56, + 0xA8C5, 0x4E73, 0xA8C6, 0x4E8B, 0xA8C7, 0x4E9B, 0xA8C8, 0x4E9E, 0xA8C9, 0x4EAB, 0xA8CA, 0x4EAC, 0xA8CB, 0x4F6F, 0xA8CC, 0x4F9D, + 0xA8CD, 0x4F8D, 0xA8CE, 0x4F73, 0xA8CF, 0x4F7F, 0xA8D0, 0x4F6C, 0xA8D1, 0x4F9B, 0xA8D2, 0x4F8B, 0xA8D3, 0x4F86, 0xA8D4, 0x4F83, + 0xA8D5, 0x4F70, 0xA8D6, 0x4F75, 0xA8D7, 0x4F88, 0xA8D8, 0x4F69, 0xA8D9, 0x4F7B, 0xA8DA, 0x4F96, 0xA8DB, 0x4F7E, 0xA8DC, 0x4F8F, + 0xA8DD, 0x4F91, 0xA8DE, 0x4F7A, 0xA8DF, 0x5154, 0xA8E0, 0x5152, 0xA8E1, 0x5155, 0xA8E2, 0x5169, 0xA8E3, 0x5177, 0xA8E4, 0x5176, + 0xA8E5, 0x5178, 0xA8E6, 0x51BD, 0xA8E7, 0x51FD, 0xA8E8, 0x523B, 0xA8E9, 0x5238, 0xA8EA, 0x5237, 0xA8EB, 0x523A, 0xA8EC, 0x5230, + 0xA8ED, 0x522E, 0xA8EE, 0x5236, 0xA8EF, 0x5241, 0xA8F0, 0x52BE, 0xA8F1, 0x52BB, 0xA8F2, 0x5352, 0xA8F3, 0x5354, 0xA8F4, 0x5353, + 0xA8F5, 0x5351, 0xA8F6, 0x5366, 0xA8F7, 0x5377, 0xA8F8, 0x5378, 0xA8F9, 0x5379, 0xA8FA, 0x53D6, 0xA8FB, 0x53D4, 0xA8FC, 0x53D7, + 0xA8FD, 0x5473, 0xA8FE, 0x5475, 0xA940, 0x5496, 0xA941, 0x5478, 0xA942, 0x5495, 0xA943, 0x5480, 0xA944, 0x547B, 0xA945, 0x5477, + 0xA946, 0x5484, 0xA947, 0x5492, 0xA948, 0x5486, 0xA949, 0x547C, 0xA94A, 0x5490, 0xA94B, 0x5471, 0xA94C, 0x5476, 0xA94D, 0x548C, + 0xA94E, 0x549A, 0xA94F, 0x5462, 0xA950, 0x5468, 0xA951, 0x548B, 0xA952, 0x547D, 0xA953, 0x548E, 0xA954, 0x56FA, 0xA955, 0x5783, + 0xA956, 0x5777, 0xA957, 0x576A, 0xA958, 0x5769, 0xA959, 0x5761, 0xA95A, 0x5766, 0xA95B, 0x5764, 0xA95C, 0x577C, 0xA95D, 0x591C, + 0xA95E, 0x5949, 0xA95F, 0x5947, 0xA960, 0x5948, 0xA961, 0x5944, 0xA962, 0x5954, 0xA963, 0x59BE, 0xA964, 0x59BB, 0xA965, 0x59D4, + 0xA966, 0x59B9, 0xA967, 0x59AE, 0xA968, 0x59D1, 0xA969, 0x59C6, 0xA96A, 0x59D0, 0xA96B, 0x59CD, 0xA96C, 0x59CB, 0xA96D, 0x59D3, + 0xA96E, 0x59CA, 0xA96F, 0x59AF, 0xA970, 0x59B3, 0xA971, 0x59D2, 0xA972, 0x59C5, 0xA973, 0x5B5F, 0xA974, 0x5B64, 0xA975, 0x5B63, + 0xA976, 0x5B97, 0xA977, 0x5B9A, 0xA978, 0x5B98, 0xA979, 0x5B9C, 0xA97A, 0x5B99, 0xA97B, 0x5B9B, 0xA97C, 0x5C1A, 0xA97D, 0x5C48, + 0xA97E, 0x5C45, 0xA9A1, 0x5C46, 0xA9A2, 0x5CB7, 0xA9A3, 0x5CA1, 0xA9A4, 0x5CB8, 0xA9A5, 0x5CA9, 0xA9A6, 0x5CAB, 0xA9A7, 0x5CB1, + 0xA9A8, 0x5CB3, 0xA9A9, 0x5E18, 0xA9AA, 0x5E1A, 0xA9AB, 0x5E16, 0xA9AC, 0x5E15, 0xA9AD, 0x5E1B, 0xA9AE, 0x5E11, 0xA9AF, 0x5E78, + 0xA9B0, 0x5E9A, 0xA9B1, 0x5E97, 0xA9B2, 0x5E9C, 0xA9B3, 0x5E95, 0xA9B4, 0x5E96, 0xA9B5, 0x5EF6, 0xA9B6, 0x5F26, 0xA9B7, 0x5F27, + 0xA9B8, 0x5F29, 0xA9B9, 0x5F80, 0xA9BA, 0x5F81, 0xA9BB, 0x5F7F, 0xA9BC, 0x5F7C, 0xA9BD, 0x5FDD, 0xA9BE, 0x5FE0, 0xA9BF, 0x5FFD, + 0xA9C0, 0x5FF5, 0xA9C1, 0x5FFF, 0xA9C2, 0x600F, 0xA9C3, 0x6014, 0xA9C4, 0x602F, 0xA9C5, 0x6035, 0xA9C6, 0x6016, 0xA9C7, 0x602A, + 0xA9C8, 0x6015, 0xA9C9, 0x6021, 0xA9CA, 0x6027, 0xA9CB, 0x6029, 0xA9CC, 0x602B, 0xA9CD, 0x601B, 0xA9CE, 0x6216, 0xA9CF, 0x6215, + 0xA9D0, 0x623F, 0xA9D1, 0x623E, 0xA9D2, 0x6240, 0xA9D3, 0x627F, 0xA9D4, 0x62C9, 0xA9D5, 0x62CC, 0xA9D6, 0x62C4, 0xA9D7, 0x62BF, + 0xA9D8, 0x62C2, 0xA9D9, 0x62B9, 0xA9DA, 0x62D2, 0xA9DB, 0x62DB, 0xA9DC, 0x62AB, 0xA9DD, 0x62D3, 0xA9DE, 0x62D4, 0xA9DF, 0x62CB, + 0xA9E0, 0x62C8, 0xA9E1, 0x62A8, 0xA9E2, 0x62BD, 0xA9E3, 0x62BC, 0xA9E4, 0x62D0, 0xA9E5, 0x62D9, 0xA9E6, 0x62C7, 0xA9E7, 0x62CD, + 0xA9E8, 0x62B5, 0xA9E9, 0x62DA, 0xA9EA, 0x62B1, 0xA9EB, 0x62D8, 0xA9EC, 0x62D6, 0xA9ED, 0x62D7, 0xA9EE, 0x62C6, 0xA9EF, 0x62AC, + 0xA9F0, 0x62CE, 0xA9F1, 0x653E, 0xA9F2, 0x65A7, 0xA9F3, 0x65BC, 0xA9F4, 0x65FA, 0xA9F5, 0x6614, 0xA9F6, 0x6613, 0xA9F7, 0x660C, + 0xA9F8, 0x6606, 0xA9F9, 0x6602, 0xA9FA, 0x660E, 0xA9FB, 0x6600, 0xA9FC, 0x660F, 0xA9FD, 0x6615, 0xA9FE, 0x660A, 0xAA40, 0x6607, + 0xAA41, 0x670D, 0xAA42, 0x670B, 0xAA43, 0x676D, 0xAA44, 0x678B, 0xAA45, 0x6795, 0xAA46, 0x6771, 0xAA47, 0x679C, 0xAA48, 0x6773, + 0xAA49, 0x6777, 0xAA4A, 0x6787, 0xAA4B, 0x679D, 0xAA4C, 0x6797, 0xAA4D, 0x676F, 0xAA4E, 0x6770, 0xAA4F, 0x677F, 0xAA50, 0x6789, + 0xAA51, 0x677E, 0xAA52, 0x6790, 0xAA53, 0x6775, 0xAA54, 0x679A, 0xAA55, 0x6793, 0xAA56, 0x677C, 0xAA57, 0x676A, 0xAA58, 0x6772, + 0xAA59, 0x6B23, 0xAA5A, 0x6B66, 0xAA5B, 0x6B67, 0xAA5C, 0x6B7F, 0xAA5D, 0x6C13, 0xAA5E, 0x6C1B, 0xAA5F, 0x6CE3, 0xAA60, 0x6CE8, + 0xAA61, 0x6CF3, 0xAA62, 0x6CB1, 0xAA63, 0x6CCC, 0xAA64, 0x6CE5, 0xAA65, 0x6CB3, 0xAA66, 0x6CBD, 0xAA67, 0x6CBE, 0xAA68, 0x6CBC, + 0xAA69, 0x6CE2, 0xAA6A, 0x6CAB, 0xAA6B, 0x6CD5, 0xAA6C, 0x6CD3, 0xAA6D, 0x6CB8, 0xAA6E, 0x6CC4, 0xAA6F, 0x6CB9, 0xAA70, 0x6CC1, + 0xAA71, 0x6CAE, 0xAA72, 0x6CD7, 0xAA73, 0x6CC5, 0xAA74, 0x6CF1, 0xAA75, 0x6CBF, 0xAA76, 0x6CBB, 0xAA77, 0x6CE1, 0xAA78, 0x6CDB, + 0xAA79, 0x6CCA, 0xAA7A, 0x6CAC, 0xAA7B, 0x6CEF, 0xAA7C, 0x6CDC, 0xAA7D, 0x6CD6, 0xAA7E, 0x6CE0, 0xAAA1, 0x7095, 0xAAA2, 0x708E, + 0xAAA3, 0x7092, 0xAAA4, 0x708A, 0xAAA5, 0x7099, 0xAAA6, 0x722C, 0xAAA7, 0x722D, 0xAAA8, 0x7238, 0xAAA9, 0x7248, 0xAAAA, 0x7267, + 0xAAAB, 0x7269, 0xAAAC, 0x72C0, 0xAAAD, 0x72CE, 0xAAAE, 0x72D9, 0xAAAF, 0x72D7, 0xAAB0, 0x72D0, 0xAAB1, 0x73A9, 0xAAB2, 0x73A8, + 0xAAB3, 0x739F, 0xAAB4, 0x73AB, 0xAAB5, 0x73A5, 0xAAB6, 0x753D, 0xAAB7, 0x759D, 0xAAB8, 0x7599, 0xAAB9, 0x759A, 0xAABA, 0x7684, + 0xAABB, 0x76C2, 0xAABC, 0x76F2, 0xAABD, 0x76F4, 0xAABE, 0x77E5, 0xAABF, 0x77FD, 0xAAC0, 0x793E, 0xAAC1, 0x7940, 0xAAC2, 0x7941, + 0xAAC3, 0x79C9, 0xAAC4, 0x79C8, 0xAAC5, 0x7A7A, 0xAAC6, 0x7A79, 0xAAC7, 0x7AFA, 0xAAC8, 0x7CFE, 0xAAC9, 0x7F54, 0xAACA, 0x7F8C, + 0xAACB, 0x7F8B, 0xAACC, 0x8005, 0xAACD, 0x80BA, 0xAACE, 0x80A5, 0xAACF, 0x80A2, 0xAAD0, 0x80B1, 0xAAD1, 0x80A1, 0xAAD2, 0x80AB, + 0xAAD3, 0x80A9, 0xAAD4, 0x80B4, 0xAAD5, 0x80AA, 0xAAD6, 0x80AF, 0xAAD7, 0x81E5, 0xAAD8, 0x81FE, 0xAAD9, 0x820D, 0xAADA, 0x82B3, + 0xAADB, 0x829D, 0xAADC, 0x8299, 0xAADD, 0x82AD, 0xAADE, 0x82BD, 0xAADF, 0x829F, 0xAAE0, 0x82B9, 0xAAE1, 0x82B1, 0xAAE2, 0x82AC, + 0xAAE3, 0x82A5, 0xAAE4, 0x82AF, 0xAAE5, 0x82B8, 0xAAE6, 0x82A3, 0xAAE7, 0x82B0, 0xAAE8, 0x82BE, 0xAAE9, 0x82B7, 0xAAEA, 0x864E, + 0xAAEB, 0x8671, 0xAAEC, 0x521D, 0xAAED, 0x8868, 0xAAEE, 0x8ECB, 0xAAEF, 0x8FCE, 0xAAF0, 0x8FD4, 0xAAF1, 0x8FD1, 0xAAF2, 0x90B5, + 0xAAF3, 0x90B8, 0xAAF4, 0x90B1, 0xAAF5, 0x90B6, 0xAAF6, 0x91C7, 0xAAF7, 0x91D1, 0xAAF8, 0x9577, 0xAAF9, 0x9580, 0xAAFA, 0x961C, + 0xAAFB, 0x9640, 0xAAFC, 0x963F, 0xAAFD, 0x963B, 0xAAFE, 0x9644, 0xAB40, 0x9642, 0xAB41, 0x96B9, 0xAB42, 0x96E8, 0xAB43, 0x9752, + 0xAB44, 0x975E, 0xAB45, 0x4E9F, 0xAB46, 0x4EAD, 0xAB47, 0x4EAE, 0xAB48, 0x4FE1, 0xAB49, 0x4FB5, 0xAB4A, 0x4FAF, 0xAB4B, 0x4FBF, + 0xAB4C, 0x4FE0, 0xAB4D, 0x4FD1, 0xAB4E, 0x4FCF, 0xAB4F, 0x4FDD, 0xAB50, 0x4FC3, 0xAB51, 0x4FB6, 0xAB52, 0x4FD8, 0xAB53, 0x4FDF, + 0xAB54, 0x4FCA, 0xAB55, 0x4FD7, 0xAB56, 0x4FAE, 0xAB57, 0x4FD0, 0xAB58, 0x4FC4, 0xAB59, 0x4FC2, 0xAB5A, 0x4FDA, 0xAB5B, 0x4FCE, + 0xAB5C, 0x4FDE, 0xAB5D, 0x4FB7, 0xAB5E, 0x5157, 0xAB5F, 0x5192, 0xAB60, 0x5191, 0xAB61, 0x51A0, 0xAB62, 0x524E, 0xAB63, 0x5243, + 0xAB64, 0x524A, 0xAB65, 0x524D, 0xAB66, 0x524C, 0xAB67, 0x524B, 0xAB68, 0x5247, 0xAB69, 0x52C7, 0xAB6A, 0x52C9, 0xAB6B, 0x52C3, + 0xAB6C, 0x52C1, 0xAB6D, 0x530D, 0xAB6E, 0x5357, 0xAB6F, 0x537B, 0xAB70, 0x539A, 0xAB71, 0x53DB, 0xAB72, 0x54AC, 0xAB73, 0x54C0, + 0xAB74, 0x54A8, 0xAB75, 0x54CE, 0xAB76, 0x54C9, 0xAB77, 0x54B8, 0xAB78, 0x54A6, 0xAB79, 0x54B3, 0xAB7A, 0x54C7, 0xAB7B, 0x54C2, + 0xAB7C, 0x54BD, 0xAB7D, 0x54AA, 0xAB7E, 0x54C1, 0xABA1, 0x54C4, 0xABA2, 0x54C8, 0xABA3, 0x54AF, 0xABA4, 0x54AB, 0xABA5, 0x54B1, + 0xABA6, 0x54BB, 0xABA7, 0x54A9, 0xABA8, 0x54A7, 0xABA9, 0x54BF, 0xABAA, 0x56FF, 0xABAB, 0x5782, 0xABAC, 0x578B, 0xABAD, 0x57A0, + 0xABAE, 0x57A3, 0xABAF, 0x57A2, 0xABB0, 0x57CE, 0xABB1, 0x57AE, 0xABB2, 0x5793, 0xABB3, 0x5955, 0xABB4, 0x5951, 0xABB5, 0x594F, + 0xABB6, 0x594E, 0xABB7, 0x5950, 0xABB8, 0x59DC, 0xABB9, 0x59D8, 0xABBA, 0x59FF, 0xABBB, 0x59E3, 0xABBC, 0x59E8, 0xABBD, 0x5A03, + 0xABBE, 0x59E5, 0xABBF, 0x59EA, 0xABC0, 0x59DA, 0xABC1, 0x59E6, 0xABC2, 0x5A01, 0xABC3, 0x59FB, 0xABC4, 0x5B69, 0xABC5, 0x5BA3, + 0xABC6, 0x5BA6, 0xABC7, 0x5BA4, 0xABC8, 0x5BA2, 0xABC9, 0x5BA5, 0xABCA, 0x5C01, 0xABCB, 0x5C4E, 0xABCC, 0x5C4F, 0xABCD, 0x5C4D, + 0xABCE, 0x5C4B, 0xABCF, 0x5CD9, 0xABD0, 0x5CD2, 0xABD1, 0x5DF7, 0xABD2, 0x5E1D, 0xABD3, 0x5E25, 0xABD4, 0x5E1F, 0xABD5, 0x5E7D, + 0xABD6, 0x5EA0, 0xABD7, 0x5EA6, 0xABD8, 0x5EFA, 0xABD9, 0x5F08, 0xABDA, 0x5F2D, 0xABDB, 0x5F65, 0xABDC, 0x5F88, 0xABDD, 0x5F85, + 0xABDE, 0x5F8A, 0xABDF, 0x5F8B, 0xABE0, 0x5F87, 0xABE1, 0x5F8C, 0xABE2, 0x5F89, 0xABE3, 0x6012, 0xABE4, 0x601D, 0xABE5, 0x6020, + 0xABE6, 0x6025, 0xABE7, 0x600E, 0xABE8, 0x6028, 0xABE9, 0x604D, 0xABEA, 0x6070, 0xABEB, 0x6068, 0xABEC, 0x6062, 0xABED, 0x6046, + 0xABEE, 0x6043, 0xABEF, 0x606C, 0xABF0, 0x606B, 0xABF1, 0x606A, 0xABF2, 0x6064, 0xABF3, 0x6241, 0xABF4, 0x62DC, 0xABF5, 0x6316, + 0xABF6, 0x6309, 0xABF7, 0x62FC, 0xABF8, 0x62ED, 0xABF9, 0x6301, 0xABFA, 0x62EE, 0xABFB, 0x62FD, 0xABFC, 0x6307, 0xABFD, 0x62F1, + 0xABFE, 0x62F7, 0xAC40, 0x62EF, 0xAC41, 0x62EC, 0xAC42, 0x62FE, 0xAC43, 0x62F4, 0xAC44, 0x6311, 0xAC45, 0x6302, 0xAC46, 0x653F, + 0xAC47, 0x6545, 0xAC48, 0x65AB, 0xAC49, 0x65BD, 0xAC4A, 0x65E2, 0xAC4B, 0x6625, 0xAC4C, 0x662D, 0xAC4D, 0x6620, 0xAC4E, 0x6627, + 0xAC4F, 0x662F, 0xAC50, 0x661F, 0xAC51, 0x6628, 0xAC52, 0x6631, 0xAC53, 0x6624, 0xAC54, 0x66F7, 0xAC55, 0x67FF, 0xAC56, 0x67D3, + 0xAC57, 0x67F1, 0xAC58, 0x67D4, 0xAC59, 0x67D0, 0xAC5A, 0x67EC, 0xAC5B, 0x67B6, 0xAC5C, 0x67AF, 0xAC5D, 0x67F5, 0xAC5E, 0x67E9, + 0xAC5F, 0x67EF, 0xAC60, 0x67C4, 0xAC61, 0x67D1, 0xAC62, 0x67B4, 0xAC63, 0x67DA, 0xAC64, 0x67E5, 0xAC65, 0x67B8, 0xAC66, 0x67CF, + 0xAC67, 0x67DE, 0xAC68, 0x67F3, 0xAC69, 0x67B0, 0xAC6A, 0x67D9, 0xAC6B, 0x67E2, 0xAC6C, 0x67DD, 0xAC6D, 0x67D2, 0xAC6E, 0x6B6A, + 0xAC6F, 0x6B83, 0xAC70, 0x6B86, 0xAC71, 0x6BB5, 0xAC72, 0x6BD2, 0xAC73, 0x6BD7, 0xAC74, 0x6C1F, 0xAC75, 0x6CC9, 0xAC76, 0x6D0B, + 0xAC77, 0x6D32, 0xAC78, 0x6D2A, 0xAC79, 0x6D41, 0xAC7A, 0x6D25, 0xAC7B, 0x6D0C, 0xAC7C, 0x6D31, 0xAC7D, 0x6D1E, 0xAC7E, 0x6D17, + 0xACA1, 0x6D3B, 0xACA2, 0x6D3D, 0xACA3, 0x6D3E, 0xACA4, 0x6D36, 0xACA5, 0x6D1B, 0xACA6, 0x6CF5, 0xACA7, 0x6D39, 0xACA8, 0x6D27, + 0xACA9, 0x6D38, 0xACAA, 0x6D29, 0xACAB, 0x6D2E, 0xACAC, 0x6D35, 0xACAD, 0x6D0E, 0xACAE, 0x6D2B, 0xACAF, 0x70AB, 0xACB0, 0x70BA, + 0xACB1, 0x70B3, 0xACB2, 0x70AC, 0xACB3, 0x70AF, 0xACB4, 0x70AD, 0xACB5, 0x70B8, 0xACB6, 0x70AE, 0xACB7, 0x70A4, 0xACB8, 0x7230, + 0xACB9, 0x7272, 0xACBA, 0x726F, 0xACBB, 0x7274, 0xACBC, 0x72E9, 0xACBD, 0x72E0, 0xACBE, 0x72E1, 0xACBF, 0x73B7, 0xACC0, 0x73CA, + 0xACC1, 0x73BB, 0xACC2, 0x73B2, 0xACC3, 0x73CD, 0xACC4, 0x73C0, 0xACC5, 0x73B3, 0xACC6, 0x751A, 0xACC7, 0x752D, 0xACC8, 0x754F, + 0xACC9, 0x754C, 0xACCA, 0x754E, 0xACCB, 0x754B, 0xACCC, 0x75AB, 0xACCD, 0x75A4, 0xACCE, 0x75A5, 0xACCF, 0x75A2, 0xACD0, 0x75A3, + 0xACD1, 0x7678, 0xACD2, 0x7686, 0xACD3, 0x7687, 0xACD4, 0x7688, 0xACD5, 0x76C8, 0xACD6, 0x76C6, 0xACD7, 0x76C3, 0xACD8, 0x76C5, + 0xACD9, 0x7701, 0xACDA, 0x76F9, 0xACDB, 0x76F8, 0xACDC, 0x7709, 0xACDD, 0x770B, 0xACDE, 0x76FE, 0xACDF, 0x76FC, 0xACE0, 0x7707, + 0xACE1, 0x77DC, 0xACE2, 0x7802, 0xACE3, 0x7814, 0xACE4, 0x780C, 0xACE5, 0x780D, 0xACE6, 0x7946, 0xACE7, 0x7949, 0xACE8, 0x7948, + 0xACE9, 0x7947, 0xACEA, 0x79B9, 0xACEB, 0x79BA, 0xACEC, 0x79D1, 0xACED, 0x79D2, 0xACEE, 0x79CB, 0xACEF, 0x7A7F, 0xACF0, 0x7A81, + 0xACF1, 0x7AFF, 0xACF2, 0x7AFD, 0xACF3, 0x7C7D, 0xACF4, 0x7D02, 0xACF5, 0x7D05, 0xACF6, 0x7D00, 0xACF7, 0x7D09, 0xACF8, 0x7D07, + 0xACF9, 0x7D04, 0xACFA, 0x7D06, 0xACFB, 0x7F38, 0xACFC, 0x7F8E, 0xACFD, 0x7FBF, 0xACFE, 0x8004, 0xAD40, 0x8010, 0xAD41, 0x800D, + 0xAD42, 0x8011, 0xAD43, 0x8036, 0xAD44, 0x80D6, 0xAD45, 0x80E5, 0xAD46, 0x80DA, 0xAD47, 0x80C3, 0xAD48, 0x80C4, 0xAD49, 0x80CC, + 0xAD4A, 0x80E1, 0xAD4B, 0x80DB, 0xAD4C, 0x80CE, 0xAD4D, 0x80DE, 0xAD4E, 0x80E4, 0xAD4F, 0x80DD, 0xAD50, 0x81F4, 0xAD51, 0x8222, + 0xAD52, 0x82E7, 0xAD53, 0x8303, 0xAD54, 0x8305, 0xAD55, 0x82E3, 0xAD56, 0x82DB, 0xAD57, 0x82E6, 0xAD58, 0x8304, 0xAD59, 0x82E5, + 0xAD5A, 0x8302, 0xAD5B, 0x8309, 0xAD5C, 0x82D2, 0xAD5D, 0x82D7, 0xAD5E, 0x82F1, 0xAD5F, 0x8301, 0xAD60, 0x82DC, 0xAD61, 0x82D4, + 0xAD62, 0x82D1, 0xAD63, 0x82DE, 0xAD64, 0x82D3, 0xAD65, 0x82DF, 0xAD66, 0x82EF, 0xAD67, 0x8306, 0xAD68, 0x8650, 0xAD69, 0x8679, + 0xAD6A, 0x867B, 0xAD6B, 0x867A, 0xAD6C, 0x884D, 0xAD6D, 0x886B, 0xAD6E, 0x8981, 0xAD6F, 0x89D4, 0xAD70, 0x8A08, 0xAD71, 0x8A02, + 0xAD72, 0x8A03, 0xAD73, 0x8C9E, 0xAD74, 0x8CA0, 0xAD75, 0x8D74, 0xAD76, 0x8D73, 0xAD77, 0x8DB4, 0xAD78, 0x8ECD, 0xAD79, 0x8ECC, + 0xAD7A, 0x8FF0, 0xAD7B, 0x8FE6, 0xAD7C, 0x8FE2, 0xAD7D, 0x8FEA, 0xAD7E, 0x8FE5, 0xADA1, 0x8FED, 0xADA2, 0x8FEB, 0xADA3, 0x8FE4, + 0xADA4, 0x8FE8, 0xADA5, 0x90CA, 0xADA6, 0x90CE, 0xADA7, 0x90C1, 0xADA8, 0x90C3, 0xADA9, 0x914B, 0xADAA, 0x914A, 0xADAB, 0x91CD, + 0xADAC, 0x9582, 0xADAD, 0x9650, 0xADAE, 0x964B, 0xADAF, 0x964C, 0xADB0, 0x964D, 0xADB1, 0x9762, 0xADB2, 0x9769, 0xADB3, 0x97CB, + 0xADB4, 0x97ED, 0xADB5, 0x97F3, 0xADB6, 0x9801, 0xADB7, 0x98A8, 0xADB8, 0x98DB, 0xADB9, 0x98DF, 0xADBA, 0x9996, 0xADBB, 0x9999, + 0xADBC, 0x4E58, 0xADBD, 0x4EB3, 0xADBE, 0x500C, 0xADBF, 0x500D, 0xADC0, 0x5023, 0xADC1, 0x4FEF, 0xADC2, 0x5026, 0xADC3, 0x5025, + 0xADC4, 0x4FF8, 0xADC5, 0x5029, 0xADC6, 0x5016, 0xADC7, 0x5006, 0xADC8, 0x503C, 0xADC9, 0x501F, 0xADCA, 0x501A, 0xADCB, 0x5012, + 0xADCC, 0x5011, 0xADCD, 0x4FFA, 0xADCE, 0x5000, 0xADCF, 0x5014, 0xADD0, 0x5028, 0xADD1, 0x4FF1, 0xADD2, 0x5021, 0xADD3, 0x500B, + 0xADD4, 0x5019, 0xADD5, 0x5018, 0xADD6, 0x4FF3, 0xADD7, 0x4FEE, 0xADD8, 0x502D, 0xADD9, 0x502A, 0xADDA, 0x4FFE, 0xADDB, 0x502B, + 0xADDC, 0x5009, 0xADDD, 0x517C, 0xADDE, 0x51A4, 0xADDF, 0x51A5, 0xADE0, 0x51A2, 0xADE1, 0x51CD, 0xADE2, 0x51CC, 0xADE3, 0x51C6, + 0xADE4, 0x51CB, 0xADE5, 0x5256, 0xADE6, 0x525C, 0xADE7, 0x5254, 0xADE8, 0x525B, 0xADE9, 0x525D, 0xADEA, 0x532A, 0xADEB, 0x537F, + 0xADEC, 0x539F, 0xADED, 0x539D, 0xADEE, 0x53DF, 0xADEF, 0x54E8, 0xADF0, 0x5510, 0xADF1, 0x5501, 0xADF2, 0x5537, 0xADF3, 0x54FC, + 0xADF4, 0x54E5, 0xADF5, 0x54F2, 0xADF6, 0x5506, 0xADF7, 0x54FA, 0xADF8, 0x5514, 0xADF9, 0x54E9, 0xADFA, 0x54ED, 0xADFB, 0x54E1, + 0xADFC, 0x5509, 0xADFD, 0x54EE, 0xADFE, 0x54EA, 0xAE40, 0x54E6, 0xAE41, 0x5527, 0xAE42, 0x5507, 0xAE43, 0x54FD, 0xAE44, 0x550F, + 0xAE45, 0x5703, 0xAE46, 0x5704, 0xAE47, 0x57C2, 0xAE48, 0x57D4, 0xAE49, 0x57CB, 0xAE4A, 0x57C3, 0xAE4B, 0x5809, 0xAE4C, 0x590F, + 0xAE4D, 0x5957, 0xAE4E, 0x5958, 0xAE4F, 0x595A, 0xAE50, 0x5A11, 0xAE51, 0x5A18, 0xAE52, 0x5A1C, 0xAE53, 0x5A1F, 0xAE54, 0x5A1B, + 0xAE55, 0x5A13, 0xAE56, 0x59EC, 0xAE57, 0x5A20, 0xAE58, 0x5A23, 0xAE59, 0x5A29, 0xAE5A, 0x5A25, 0xAE5B, 0x5A0C, 0xAE5C, 0x5A09, + 0xAE5D, 0x5B6B, 0xAE5E, 0x5C58, 0xAE5F, 0x5BB0, 0xAE60, 0x5BB3, 0xAE61, 0x5BB6, 0xAE62, 0x5BB4, 0xAE63, 0x5BAE, 0xAE64, 0x5BB5, + 0xAE65, 0x5BB9, 0xAE66, 0x5BB8, 0xAE67, 0x5C04, 0xAE68, 0x5C51, 0xAE69, 0x5C55, 0xAE6A, 0x5C50, 0xAE6B, 0x5CED, 0xAE6C, 0x5CFD, + 0xAE6D, 0x5CFB, 0xAE6E, 0x5CEA, 0xAE6F, 0x5CE8, 0xAE70, 0x5CF0, 0xAE71, 0x5CF6, 0xAE72, 0x5D01, 0xAE73, 0x5CF4, 0xAE74, 0x5DEE, + 0xAE75, 0x5E2D, 0xAE76, 0x5E2B, 0xAE77, 0x5EAB, 0xAE78, 0x5EAD, 0xAE79, 0x5EA7, 0xAE7A, 0x5F31, 0xAE7B, 0x5F92, 0xAE7C, 0x5F91, + 0xAE7D, 0x5F90, 0xAE7E, 0x6059, 0xAEA1, 0x6063, 0xAEA2, 0x6065, 0xAEA3, 0x6050, 0xAEA4, 0x6055, 0xAEA5, 0x606D, 0xAEA6, 0x6069, + 0xAEA7, 0x606F, 0xAEA8, 0x6084, 0xAEA9, 0x609F, 0xAEAA, 0x609A, 0xAEAB, 0x608D, 0xAEAC, 0x6094, 0xAEAD, 0x608C, 0xAEAE, 0x6085, + 0xAEAF, 0x6096, 0xAEB0, 0x6247, 0xAEB1, 0x62F3, 0xAEB2, 0x6308, 0xAEB3, 0x62FF, 0xAEB4, 0x634E, 0xAEB5, 0x633E, 0xAEB6, 0x632F, + 0xAEB7, 0x6355, 0xAEB8, 0x6342, 0xAEB9, 0x6346, 0xAEBA, 0x634F, 0xAEBB, 0x6349, 0xAEBC, 0x633A, 0xAEBD, 0x6350, 0xAEBE, 0x633D, + 0xAEBF, 0x632A, 0xAEC0, 0x632B, 0xAEC1, 0x6328, 0xAEC2, 0x634D, 0xAEC3, 0x634C, 0xAEC4, 0x6548, 0xAEC5, 0x6549, 0xAEC6, 0x6599, + 0xAEC7, 0x65C1, 0xAEC8, 0x65C5, 0xAEC9, 0x6642, 0xAECA, 0x6649, 0xAECB, 0x664F, 0xAECC, 0x6643, 0xAECD, 0x6652, 0xAECE, 0x664C, + 0xAECF, 0x6645, 0xAED0, 0x6641, 0xAED1, 0x66F8, 0xAED2, 0x6714, 0xAED3, 0x6715, 0xAED4, 0x6717, 0xAED5, 0x6821, 0xAED6, 0x6838, + 0xAED7, 0x6848, 0xAED8, 0x6846, 0xAED9, 0x6853, 0xAEDA, 0x6839, 0xAEDB, 0x6842, 0xAEDC, 0x6854, 0xAEDD, 0x6829, 0xAEDE, 0x68B3, + 0xAEDF, 0x6817, 0xAEE0, 0x684C, 0xAEE1, 0x6851, 0xAEE2, 0x683D, 0xAEE3, 0x67F4, 0xAEE4, 0x6850, 0xAEE5, 0x6840, 0xAEE6, 0x683C, + 0xAEE7, 0x6843, 0xAEE8, 0x682A, 0xAEE9, 0x6845, 0xAEEA, 0x6813, 0xAEEB, 0x6818, 0xAEEC, 0x6841, 0xAEED, 0x6B8A, 0xAEEE, 0x6B89, + 0xAEEF, 0x6BB7, 0xAEF0, 0x6C23, 0xAEF1, 0x6C27, 0xAEF2, 0x6C28, 0xAEF3, 0x6C26, 0xAEF4, 0x6C24, 0xAEF5, 0x6CF0, 0xAEF6, 0x6D6A, + 0xAEF7, 0x6D95, 0xAEF8, 0x6D88, 0xAEF9, 0x6D87, 0xAEFA, 0x6D66, 0xAEFB, 0x6D78, 0xAEFC, 0x6D77, 0xAEFD, 0x6D59, 0xAEFE, 0x6D93, + 0xAF40, 0x6D6C, 0xAF41, 0x6D89, 0xAF42, 0x6D6E, 0xAF43, 0x6D5A, 0xAF44, 0x6D74, 0xAF45, 0x6D69, 0xAF46, 0x6D8C, 0xAF47, 0x6D8A, + 0xAF48, 0x6D79, 0xAF49, 0x6D85, 0xAF4A, 0x6D65, 0xAF4B, 0x6D94, 0xAF4C, 0x70CA, 0xAF4D, 0x70D8, 0xAF4E, 0x70E4, 0xAF4F, 0x70D9, + 0xAF50, 0x70C8, 0xAF51, 0x70CF, 0xAF52, 0x7239, 0xAF53, 0x7279, 0xAF54, 0x72FC, 0xAF55, 0x72F9, 0xAF56, 0x72FD, 0xAF57, 0x72F8, + 0xAF58, 0x72F7, 0xAF59, 0x7386, 0xAF5A, 0x73ED, 0xAF5B, 0x7409, 0xAF5C, 0x73EE, 0xAF5D, 0x73E0, 0xAF5E, 0x73EA, 0xAF5F, 0x73DE, + 0xAF60, 0x7554, 0xAF61, 0x755D, 0xAF62, 0x755C, 0xAF63, 0x755A, 0xAF64, 0x7559, 0xAF65, 0x75BE, 0xAF66, 0x75C5, 0xAF67, 0x75C7, + 0xAF68, 0x75B2, 0xAF69, 0x75B3, 0xAF6A, 0x75BD, 0xAF6B, 0x75BC, 0xAF6C, 0x75B9, 0xAF6D, 0x75C2, 0xAF6E, 0x75B8, 0xAF6F, 0x768B, + 0xAF70, 0x76B0, 0xAF71, 0x76CA, 0xAF72, 0x76CD, 0xAF73, 0x76CE, 0xAF74, 0x7729, 0xAF75, 0x771F, 0xAF76, 0x7720, 0xAF77, 0x7728, + 0xAF78, 0x77E9, 0xAF79, 0x7830, 0xAF7A, 0x7827, 0xAF7B, 0x7838, 0xAF7C, 0x781D, 0xAF7D, 0x7834, 0xAF7E, 0x7837, 0xAFA1, 0x7825, + 0xAFA2, 0x782D, 0xAFA3, 0x7820, 0xAFA4, 0x781F, 0xAFA5, 0x7832, 0xAFA6, 0x7955, 0xAFA7, 0x7950, 0xAFA8, 0x7960, 0xAFA9, 0x795F, + 0xAFAA, 0x7956, 0xAFAB, 0x795E, 0xAFAC, 0x795D, 0xAFAD, 0x7957, 0xAFAE, 0x795A, 0xAFAF, 0x79E4, 0xAFB0, 0x79E3, 0xAFB1, 0x79E7, + 0xAFB2, 0x79DF, 0xAFB3, 0x79E6, 0xAFB4, 0x79E9, 0xAFB5, 0x79D8, 0xAFB6, 0x7A84, 0xAFB7, 0x7A88, 0xAFB8, 0x7AD9, 0xAFB9, 0x7B06, + 0xAFBA, 0x7B11, 0xAFBB, 0x7C89, 0xAFBC, 0x7D21, 0xAFBD, 0x7D17, 0xAFBE, 0x7D0B, 0xAFBF, 0x7D0A, 0xAFC0, 0x7D20, 0xAFC1, 0x7D22, + 0xAFC2, 0x7D14, 0xAFC3, 0x7D10, 0xAFC4, 0x7D15, 0xAFC5, 0x7D1A, 0xAFC6, 0x7D1C, 0xAFC7, 0x7D0D, 0xAFC8, 0x7D19, 0xAFC9, 0x7D1B, + 0xAFCA, 0x7F3A, 0xAFCB, 0x7F5F, 0xAFCC, 0x7F94, 0xAFCD, 0x7FC5, 0xAFCE, 0x7FC1, 0xAFCF, 0x8006, 0xAFD0, 0x8018, 0xAFD1, 0x8015, + 0xAFD2, 0x8019, 0xAFD3, 0x8017, 0xAFD4, 0x803D, 0xAFD5, 0x803F, 0xAFD6, 0x80F1, 0xAFD7, 0x8102, 0xAFD8, 0x80F0, 0xAFD9, 0x8105, + 0xAFDA, 0x80ED, 0xAFDB, 0x80F4, 0xAFDC, 0x8106, 0xAFDD, 0x80F8, 0xAFDE, 0x80F3, 0xAFDF, 0x8108, 0xAFE0, 0x80FD, 0xAFE1, 0x810A, + 0xAFE2, 0x80FC, 0xAFE3, 0x80EF, 0xAFE4, 0x81ED, 0xAFE5, 0x81EC, 0xAFE6, 0x8200, 0xAFE7, 0x8210, 0xAFE8, 0x822A, 0xAFE9, 0x822B, + 0xAFEA, 0x8228, 0xAFEB, 0x822C, 0xAFEC, 0x82BB, 0xAFED, 0x832B, 0xAFEE, 0x8352, 0xAFEF, 0x8354, 0xAFF0, 0x834A, 0xAFF1, 0x8338, + 0xAFF2, 0x8350, 0xAFF3, 0x8349, 0xAFF4, 0x8335, 0xAFF5, 0x8334, 0xAFF6, 0x834F, 0xAFF7, 0x8332, 0xAFF8, 0x8339, 0xAFF9, 0x8336, + 0xAFFA, 0x8317, 0xAFFB, 0x8340, 0xAFFC, 0x8331, 0xAFFD, 0x8328, 0xAFFE, 0x8343, 0xB040, 0x8654, 0xB041, 0x868A, 0xB042, 0x86AA, + 0xB043, 0x8693, 0xB044, 0x86A4, 0xB045, 0x86A9, 0xB046, 0x868C, 0xB047, 0x86A3, 0xB048, 0x869C, 0xB049, 0x8870, 0xB04A, 0x8877, + 0xB04B, 0x8881, 0xB04C, 0x8882, 0xB04D, 0x887D, 0xB04E, 0x8879, 0xB04F, 0x8A18, 0xB050, 0x8A10, 0xB051, 0x8A0E, 0xB052, 0x8A0C, + 0xB053, 0x8A15, 0xB054, 0x8A0A, 0xB055, 0x8A17, 0xB056, 0x8A13, 0xB057, 0x8A16, 0xB058, 0x8A0F, 0xB059, 0x8A11, 0xB05A, 0x8C48, + 0xB05B, 0x8C7A, 0xB05C, 0x8C79, 0xB05D, 0x8CA1, 0xB05E, 0x8CA2, 0xB05F, 0x8D77, 0xB060, 0x8EAC, 0xB061, 0x8ED2, 0xB062, 0x8ED4, + 0xB063, 0x8ECF, 0xB064, 0x8FB1, 0xB065, 0x9001, 0xB066, 0x9006, 0xB067, 0x8FF7, 0xB068, 0x9000, 0xB069, 0x8FFA, 0xB06A, 0x8FF4, + 0xB06B, 0x9003, 0xB06C, 0x8FFD, 0xB06D, 0x9005, 0xB06E, 0x8FF8, 0xB06F, 0x9095, 0xB070, 0x90E1, 0xB071, 0x90DD, 0xB072, 0x90E2, + 0xB073, 0x9152, 0xB074, 0x914D, 0xB075, 0x914C, 0xB076, 0x91D8, 0xB077, 0x91DD, 0xB078, 0x91D7, 0xB079, 0x91DC, 0xB07A, 0x91D9, + 0xB07B, 0x9583, 0xB07C, 0x9662, 0xB07D, 0x9663, 0xB07E, 0x9661, 0xB0A1, 0x965B, 0xB0A2, 0x965D, 0xB0A3, 0x9664, 0xB0A4, 0x9658, + 0xB0A5, 0x965E, 0xB0A6, 0x96BB, 0xB0A7, 0x98E2, 0xB0A8, 0x99AC, 0xB0A9, 0x9AA8, 0xB0AA, 0x9AD8, 0xB0AB, 0x9B25, 0xB0AC, 0x9B32, + 0xB0AD, 0x9B3C, 0xB0AE, 0x4E7E, 0xB0AF, 0x507A, 0xB0B0, 0x507D, 0xB0B1, 0x505C, 0xB0B2, 0x5047, 0xB0B3, 0x5043, 0xB0B4, 0x504C, + 0xB0B5, 0x505A, 0xB0B6, 0x5049, 0xB0B7, 0x5065, 0xB0B8, 0x5076, 0xB0B9, 0x504E, 0xB0BA, 0x5055, 0xB0BB, 0x5075, 0xB0BC, 0x5074, + 0xB0BD, 0x5077, 0xB0BE, 0x504F, 0xB0BF, 0x500F, 0xB0C0, 0x506F, 0xB0C1, 0x506D, 0xB0C2, 0x515C, 0xB0C3, 0x5195, 0xB0C4, 0x51F0, + 0xB0C5, 0x526A, 0xB0C6, 0x526F, 0xB0C7, 0x52D2, 0xB0C8, 0x52D9, 0xB0C9, 0x52D8, 0xB0CA, 0x52D5, 0xB0CB, 0x5310, 0xB0CC, 0x530F, + 0xB0CD, 0x5319, 0xB0CE, 0x533F, 0xB0CF, 0x5340, 0xB0D0, 0x533E, 0xB0D1, 0x53C3, 0xB0D2, 0x66FC, 0xB0D3, 0x5546, 0xB0D4, 0x556A, + 0xB0D5, 0x5566, 0xB0D6, 0x5544, 0xB0D7, 0x555E, 0xB0D8, 0x5561, 0xB0D9, 0x5543, 0xB0DA, 0x554A, 0xB0DB, 0x5531, 0xB0DC, 0x5556, + 0xB0DD, 0x554F, 0xB0DE, 0x5555, 0xB0DF, 0x552F, 0xB0E0, 0x5564, 0xB0E1, 0x5538, 0xB0E2, 0x552E, 0xB0E3, 0x555C, 0xB0E4, 0x552C, + 0xB0E5, 0x5563, 0xB0E6, 0x5533, 0xB0E7, 0x5541, 0xB0E8, 0x5557, 0xB0E9, 0x5708, 0xB0EA, 0x570B, 0xB0EB, 0x5709, 0xB0EC, 0x57DF, + 0xB0ED, 0x5805, 0xB0EE, 0x580A, 0xB0EF, 0x5806, 0xB0F0, 0x57E0, 0xB0F1, 0x57E4, 0xB0F2, 0x57FA, 0xB0F3, 0x5802, 0xB0F4, 0x5835, + 0xB0F5, 0x57F7, 0xB0F6, 0x57F9, 0xB0F7, 0x5920, 0xB0F8, 0x5962, 0xB0F9, 0x5A36, 0xB0FA, 0x5A41, 0xB0FB, 0x5A49, 0xB0FC, 0x5A66, + 0xB0FD, 0x5A6A, 0xB0FE, 0x5A40, 0xB140, 0x5A3C, 0xB141, 0x5A62, 0xB142, 0x5A5A, 0xB143, 0x5A46, 0xB144, 0x5A4A, 0xB145, 0x5B70, + 0xB146, 0x5BC7, 0xB147, 0x5BC5, 0xB148, 0x5BC4, 0xB149, 0x5BC2, 0xB14A, 0x5BBF, 0xB14B, 0x5BC6, 0xB14C, 0x5C09, 0xB14D, 0x5C08, + 0xB14E, 0x5C07, 0xB14F, 0x5C60, 0xB150, 0x5C5C, 0xB151, 0x5C5D, 0xB152, 0x5D07, 0xB153, 0x5D06, 0xB154, 0x5D0E, 0xB155, 0x5D1B, + 0xB156, 0x5D16, 0xB157, 0x5D22, 0xB158, 0x5D11, 0xB159, 0x5D29, 0xB15A, 0x5D14, 0xB15B, 0x5D19, 0xB15C, 0x5D24, 0xB15D, 0x5D27, + 0xB15E, 0x5D17, 0xB15F, 0x5DE2, 0xB160, 0x5E38, 0xB161, 0x5E36, 0xB162, 0x5E33, 0xB163, 0x5E37, 0xB164, 0x5EB7, 0xB165, 0x5EB8, + 0xB166, 0x5EB6, 0xB167, 0x5EB5, 0xB168, 0x5EBE, 0xB169, 0x5F35, 0xB16A, 0x5F37, 0xB16B, 0x5F57, 0xB16C, 0x5F6C, 0xB16D, 0x5F69, + 0xB16E, 0x5F6B, 0xB16F, 0x5F97, 0xB170, 0x5F99, 0xB171, 0x5F9E, 0xB172, 0x5F98, 0xB173, 0x5FA1, 0xB174, 0x5FA0, 0xB175, 0x5F9C, + 0xB176, 0x607F, 0xB177, 0x60A3, 0xB178, 0x6089, 0xB179, 0x60A0, 0xB17A, 0x60A8, 0xB17B, 0x60CB, 0xB17C, 0x60B4, 0xB17D, 0x60E6, + 0xB17E, 0x60BD, 0xB1A1, 0x60C5, 0xB1A2, 0x60BB, 0xB1A3, 0x60B5, 0xB1A4, 0x60DC, 0xB1A5, 0x60BC, 0xB1A6, 0x60D8, 0xB1A7, 0x60D5, + 0xB1A8, 0x60C6, 0xB1A9, 0x60DF, 0xB1AA, 0x60B8, 0xB1AB, 0x60DA, 0xB1AC, 0x60C7, 0xB1AD, 0x621A, 0xB1AE, 0x621B, 0xB1AF, 0x6248, + 0xB1B0, 0x63A0, 0xB1B1, 0x63A7, 0xB1B2, 0x6372, 0xB1B3, 0x6396, 0xB1B4, 0x63A2, 0xB1B5, 0x63A5, 0xB1B6, 0x6377, 0xB1B7, 0x6367, + 0xB1B8, 0x6398, 0xB1B9, 0x63AA, 0xB1BA, 0x6371, 0xB1BB, 0x63A9, 0xB1BC, 0x6389, 0xB1BD, 0x6383, 0xB1BE, 0x639B, 0xB1BF, 0x636B, + 0xB1C0, 0x63A8, 0xB1C1, 0x6384, 0xB1C2, 0x6388, 0xB1C3, 0x6399, 0xB1C4, 0x63A1, 0xB1C5, 0x63AC, 0xB1C6, 0x6392, 0xB1C7, 0x638F, + 0xB1C8, 0x6380, 0xB1C9, 0x637B, 0xB1CA, 0x6369, 0xB1CB, 0x6368, 0xB1CC, 0x637A, 0xB1CD, 0x655D, 0xB1CE, 0x6556, 0xB1CF, 0x6551, + 0xB1D0, 0x6559, 0xB1D1, 0x6557, 0xB1D2, 0x555F, 0xB1D3, 0x654F, 0xB1D4, 0x6558, 0xB1D5, 0x6555, 0xB1D6, 0x6554, 0xB1D7, 0x659C, + 0xB1D8, 0x659B, 0xB1D9, 0x65AC, 0xB1DA, 0x65CF, 0xB1DB, 0x65CB, 0xB1DC, 0x65CC, 0xB1DD, 0x65CE, 0xB1DE, 0x665D, 0xB1DF, 0x665A, + 0xB1E0, 0x6664, 0xB1E1, 0x6668, 0xB1E2, 0x6666, 0xB1E3, 0x665E, 0xB1E4, 0x66F9, 0xB1E5, 0x52D7, 0xB1E6, 0x671B, 0xB1E7, 0x6881, + 0xB1E8, 0x68AF, 0xB1E9, 0x68A2, 0xB1EA, 0x6893, 0xB1EB, 0x68B5, 0xB1EC, 0x687F, 0xB1ED, 0x6876, 0xB1EE, 0x68B1, 0xB1EF, 0x68A7, + 0xB1F0, 0x6897, 0xB1F1, 0x68B0, 0xB1F2, 0x6883, 0xB1F3, 0x68C4, 0xB1F4, 0x68AD, 0xB1F5, 0x6886, 0xB1F6, 0x6885, 0xB1F7, 0x6894, + 0xB1F8, 0x689D, 0xB1F9, 0x68A8, 0xB1FA, 0x689F, 0xB1FB, 0x68A1, 0xB1FC, 0x6882, 0xB1FD, 0x6B32, 0xB1FE, 0x6BBA, 0xB240, 0x6BEB, + 0xB241, 0x6BEC, 0xB242, 0x6C2B, 0xB243, 0x6D8E, 0xB244, 0x6DBC, 0xB245, 0x6DF3, 0xB246, 0x6DD9, 0xB247, 0x6DB2, 0xB248, 0x6DE1, + 0xB249, 0x6DCC, 0xB24A, 0x6DE4, 0xB24B, 0x6DFB, 0xB24C, 0x6DFA, 0xB24D, 0x6E05, 0xB24E, 0x6DC7, 0xB24F, 0x6DCB, 0xB250, 0x6DAF, + 0xB251, 0x6DD1, 0xB252, 0x6DAE, 0xB253, 0x6DDE, 0xB254, 0x6DF9, 0xB255, 0x6DB8, 0xB256, 0x6DF7, 0xB257, 0x6DF5, 0xB258, 0x6DC5, + 0xB259, 0x6DD2, 0xB25A, 0x6E1A, 0xB25B, 0x6DB5, 0xB25C, 0x6DDA, 0xB25D, 0x6DEB, 0xB25E, 0x6DD8, 0xB25F, 0x6DEA, 0xB260, 0x6DF1, + 0xB261, 0x6DEE, 0xB262, 0x6DE8, 0xB263, 0x6DC6, 0xB264, 0x6DC4, 0xB265, 0x6DAA, 0xB266, 0x6DEC, 0xB267, 0x6DBF, 0xB268, 0x6DE6, + 0xB269, 0x70F9, 0xB26A, 0x7109, 0xB26B, 0x710A, 0xB26C, 0x70FD, 0xB26D, 0x70EF, 0xB26E, 0x723D, 0xB26F, 0x727D, 0xB270, 0x7281, + 0xB271, 0x731C, 0xB272, 0x731B, 0xB273, 0x7316, 0xB274, 0x7313, 0xB275, 0x7319, 0xB276, 0x7387, 0xB277, 0x7405, 0xB278, 0x740A, + 0xB279, 0x7403, 0xB27A, 0x7406, 0xB27B, 0x73FE, 0xB27C, 0x740D, 0xB27D, 0x74E0, 0xB27E, 0x74F6, 0xB2A1, 0x74F7, 0xB2A2, 0x751C, + 0xB2A3, 0x7522, 0xB2A4, 0x7565, 0xB2A5, 0x7566, 0xB2A6, 0x7562, 0xB2A7, 0x7570, 0xB2A8, 0x758F, 0xB2A9, 0x75D4, 0xB2AA, 0x75D5, + 0xB2AB, 0x75B5, 0xB2AC, 0x75CA, 0xB2AD, 0x75CD, 0xB2AE, 0x768E, 0xB2AF, 0x76D4, 0xB2B0, 0x76D2, 0xB2B1, 0x76DB, 0xB2B2, 0x7737, + 0xB2B3, 0x773E, 0xB2B4, 0x773C, 0xB2B5, 0x7736, 0xB2B6, 0x7738, 0xB2B7, 0x773A, 0xB2B8, 0x786B, 0xB2B9, 0x7843, 0xB2BA, 0x784E, + 0xB2BB, 0x7965, 0xB2BC, 0x7968, 0xB2BD, 0x796D, 0xB2BE, 0x79FB, 0xB2BF, 0x7A92, 0xB2C0, 0x7A95, 0xB2C1, 0x7B20, 0xB2C2, 0x7B28, + 0xB2C3, 0x7B1B, 0xB2C4, 0x7B2C, 0xB2C5, 0x7B26, 0xB2C6, 0x7B19, 0xB2C7, 0x7B1E, 0xB2C8, 0x7B2E, 0xB2C9, 0x7C92, 0xB2CA, 0x7C97, + 0xB2CB, 0x7C95, 0xB2CC, 0x7D46, 0xB2CD, 0x7D43, 0xB2CE, 0x7D71, 0xB2CF, 0x7D2E, 0xB2D0, 0x7D39, 0xB2D1, 0x7D3C, 0xB2D2, 0x7D40, + 0xB2D3, 0x7D30, 0xB2D4, 0x7D33, 0xB2D5, 0x7D44, 0xB2D6, 0x7D2F, 0xB2D7, 0x7D42, 0xB2D8, 0x7D32, 0xB2D9, 0x7D31, 0xB2DA, 0x7F3D, + 0xB2DB, 0x7F9E, 0xB2DC, 0x7F9A, 0xB2DD, 0x7FCC, 0xB2DE, 0x7FCE, 0xB2DF, 0x7FD2, 0xB2E0, 0x801C, 0xB2E1, 0x804A, 0xB2E2, 0x8046, + 0xB2E3, 0x812F, 0xB2E4, 0x8116, 0xB2E5, 0x8123, 0xB2E6, 0x812B, 0xB2E7, 0x8129, 0xB2E8, 0x8130, 0xB2E9, 0x8124, 0xB2EA, 0x8202, + 0xB2EB, 0x8235, 0xB2EC, 0x8237, 0xB2ED, 0x8236, 0xB2EE, 0x8239, 0xB2EF, 0x838E, 0xB2F0, 0x839E, 0xB2F1, 0x8398, 0xB2F2, 0x8378, + 0xB2F3, 0x83A2, 0xB2F4, 0x8396, 0xB2F5, 0x83BD, 0xB2F6, 0x83AB, 0xB2F7, 0x8392, 0xB2F8, 0x838A, 0xB2F9, 0x8393, 0xB2FA, 0x8389, + 0xB2FB, 0x83A0, 0xB2FC, 0x8377, 0xB2FD, 0x837B, 0xB2FE, 0x837C, 0xB340, 0x8386, 0xB341, 0x83A7, 0xB342, 0x8655, 0xB343, 0x5F6A, + 0xB344, 0x86C7, 0xB345, 0x86C0, 0xB346, 0x86B6, 0xB347, 0x86C4, 0xB348, 0x86B5, 0xB349, 0x86C6, 0xB34A, 0x86CB, 0xB34B, 0x86B1, + 0xB34C, 0x86AF, 0xB34D, 0x86C9, 0xB34E, 0x8853, 0xB34F, 0x889E, 0xB350, 0x8888, 0xB351, 0x88AB, 0xB352, 0x8892, 0xB353, 0x8896, + 0xB354, 0x888D, 0xB355, 0x888B, 0xB356, 0x8993, 0xB357, 0x898F, 0xB358, 0x8A2A, 0xB359, 0x8A1D, 0xB35A, 0x8A23, 0xB35B, 0x8A25, + 0xB35C, 0x8A31, 0xB35D, 0x8A2D, 0xB35E, 0x8A1F, 0xB35F, 0x8A1B, 0xB360, 0x8A22, 0xB361, 0x8C49, 0xB362, 0x8C5A, 0xB363, 0x8CA9, + 0xB364, 0x8CAC, 0xB365, 0x8CAB, 0xB366, 0x8CA8, 0xB367, 0x8CAA, 0xB368, 0x8CA7, 0xB369, 0x8D67, 0xB36A, 0x8D66, 0xB36B, 0x8DBE, + 0xB36C, 0x8DBA, 0xB36D, 0x8EDB, 0xB36E, 0x8EDF, 0xB36F, 0x9019, 0xB370, 0x900D, 0xB371, 0x901A, 0xB372, 0x9017, 0xB373, 0x9023, + 0xB374, 0x901F, 0xB375, 0x901D, 0xB376, 0x9010, 0xB377, 0x9015, 0xB378, 0x901E, 0xB379, 0x9020, 0xB37A, 0x900F, 0xB37B, 0x9022, + 0xB37C, 0x9016, 0xB37D, 0x901B, 0xB37E, 0x9014, 0xB3A1, 0x90E8, 0xB3A2, 0x90ED, 0xB3A3, 0x90FD, 0xB3A4, 0x9157, 0xB3A5, 0x91CE, + 0xB3A6, 0x91F5, 0xB3A7, 0x91E6, 0xB3A8, 0x91E3, 0xB3A9, 0x91E7, 0xB3AA, 0x91ED, 0xB3AB, 0x91E9, 0xB3AC, 0x9589, 0xB3AD, 0x966A, + 0xB3AE, 0x9675, 0xB3AF, 0x9673, 0xB3B0, 0x9678, 0xB3B1, 0x9670, 0xB3B2, 0x9674, 0xB3B3, 0x9676, 0xB3B4, 0x9677, 0xB3B5, 0x966C, + 0xB3B6, 0x96C0, 0xB3B7, 0x96EA, 0xB3B8, 0x96E9, 0xB3B9, 0x7AE0, 0xB3BA, 0x7ADF, 0xB3BB, 0x9802, 0xB3BC, 0x9803, 0xB3BD, 0x9B5A, + 0xB3BE, 0x9CE5, 0xB3BF, 0x9E75, 0xB3C0, 0x9E7F, 0xB3C1, 0x9EA5, 0xB3C2, 0x9EBB, 0xB3C3, 0x50A2, 0xB3C4, 0x508D, 0xB3C5, 0x5085, + 0xB3C6, 0x5099, 0xB3C7, 0x5091, 0xB3C8, 0x5080, 0xB3C9, 0x5096, 0xB3CA, 0x5098, 0xB3CB, 0x509A, 0xB3CC, 0x6700, 0xB3CD, 0x51F1, + 0xB3CE, 0x5272, 0xB3CF, 0x5274, 0xB3D0, 0x5275, 0xB3D1, 0x5269, 0xB3D2, 0x52DE, 0xB3D3, 0x52DD, 0xB3D4, 0x52DB, 0xB3D5, 0x535A, + 0xB3D6, 0x53A5, 0xB3D7, 0x557B, 0xB3D8, 0x5580, 0xB3D9, 0x55A7, 0xB3DA, 0x557C, 0xB3DB, 0x558A, 0xB3DC, 0x559D, 0xB3DD, 0x5598, + 0xB3DE, 0x5582, 0xB3DF, 0x559C, 0xB3E0, 0x55AA, 0xB3E1, 0x5594, 0xB3E2, 0x5587, 0xB3E3, 0x558B, 0xB3E4, 0x5583, 0xB3E5, 0x55B3, + 0xB3E6, 0x55AE, 0xB3E7, 0x559F, 0xB3E8, 0x553E, 0xB3E9, 0x55B2, 0xB3EA, 0x559A, 0xB3EB, 0x55BB, 0xB3EC, 0x55AC, 0xB3ED, 0x55B1, + 0xB3EE, 0x557E, 0xB3EF, 0x5589, 0xB3F0, 0x55AB, 0xB3F1, 0x5599, 0xB3F2, 0x570D, 0xB3F3, 0x582F, 0xB3F4, 0x582A, 0xB3F5, 0x5834, + 0xB3F6, 0x5824, 0xB3F7, 0x5830, 0xB3F8, 0x5831, 0xB3F9, 0x5821, 0xB3FA, 0x581D, 0xB3FB, 0x5820, 0xB3FC, 0x58F9, 0xB3FD, 0x58FA, + 0xB3FE, 0x5960, 0xB440, 0x5A77, 0xB441, 0x5A9A, 0xB442, 0x5A7F, 0xB443, 0x5A92, 0xB444, 0x5A9B, 0xB445, 0x5AA7, 0xB446, 0x5B73, + 0xB447, 0x5B71, 0xB448, 0x5BD2, 0xB449, 0x5BCC, 0xB44A, 0x5BD3, 0xB44B, 0x5BD0, 0xB44C, 0x5C0A, 0xB44D, 0x5C0B, 0xB44E, 0x5C31, + 0xB44F, 0x5D4C, 0xB450, 0x5D50, 0xB451, 0x5D34, 0xB452, 0x5D47, 0xB453, 0x5DFD, 0xB454, 0x5E45, 0xB455, 0x5E3D, 0xB456, 0x5E40, + 0xB457, 0x5E43, 0xB458, 0x5E7E, 0xB459, 0x5ECA, 0xB45A, 0x5EC1, 0xB45B, 0x5EC2, 0xB45C, 0x5EC4, 0xB45D, 0x5F3C, 0xB45E, 0x5F6D, + 0xB45F, 0x5FA9, 0xB460, 0x5FAA, 0xB461, 0x5FA8, 0xB462, 0x60D1, 0xB463, 0x60E1, 0xB464, 0x60B2, 0xB465, 0x60B6, 0xB466, 0x60E0, + 0xB467, 0x611C, 0xB468, 0x6123, 0xB469, 0x60FA, 0xB46A, 0x6115, 0xB46B, 0x60F0, 0xB46C, 0x60FB, 0xB46D, 0x60F4, 0xB46E, 0x6168, + 0xB46F, 0x60F1, 0xB470, 0x610E, 0xB471, 0x60F6, 0xB472, 0x6109, 0xB473, 0x6100, 0xB474, 0x6112, 0xB475, 0x621F, 0xB476, 0x6249, + 0xB477, 0x63A3, 0xB478, 0x638C, 0xB479, 0x63CF, 0xB47A, 0x63C0, 0xB47B, 0x63E9, 0xB47C, 0x63C9, 0xB47D, 0x63C6, 0xB47E, 0x63CD, + 0xB4A1, 0x63D2, 0xB4A2, 0x63E3, 0xB4A3, 0x63D0, 0xB4A4, 0x63E1, 0xB4A5, 0x63D6, 0xB4A6, 0x63ED, 0xB4A7, 0x63EE, 0xB4A8, 0x6376, + 0xB4A9, 0x63F4, 0xB4AA, 0x63EA, 0xB4AB, 0x63DB, 0xB4AC, 0x6452, 0xB4AD, 0x63DA, 0xB4AE, 0x63F9, 0xB4AF, 0x655E, 0xB4B0, 0x6566, + 0xB4B1, 0x6562, 0xB4B2, 0x6563, 0xB4B3, 0x6591, 0xB4B4, 0x6590, 0xB4B5, 0x65AF, 0xB4B6, 0x666E, 0xB4B7, 0x6670, 0xB4B8, 0x6674, + 0xB4B9, 0x6676, 0xB4BA, 0x666F, 0xB4BB, 0x6691, 0xB4BC, 0x667A, 0xB4BD, 0x667E, 0xB4BE, 0x6677, 0xB4BF, 0x66FE, 0xB4C0, 0x66FF, + 0xB4C1, 0x671F, 0xB4C2, 0x671D, 0xB4C3, 0x68FA, 0xB4C4, 0x68D5, 0xB4C5, 0x68E0, 0xB4C6, 0x68D8, 0xB4C7, 0x68D7, 0xB4C8, 0x6905, + 0xB4C9, 0x68DF, 0xB4CA, 0x68F5, 0xB4CB, 0x68EE, 0xB4CC, 0x68E7, 0xB4CD, 0x68F9, 0xB4CE, 0x68D2, 0xB4CF, 0x68F2, 0xB4D0, 0x68E3, + 0xB4D1, 0x68CB, 0xB4D2, 0x68CD, 0xB4D3, 0x690D, 0xB4D4, 0x6912, 0xB4D5, 0x690E, 0xB4D6, 0x68C9, 0xB4D7, 0x68DA, 0xB4D8, 0x696E, + 0xB4D9, 0x68FB, 0xB4DA, 0x6B3E, 0xB4DB, 0x6B3A, 0xB4DC, 0x6B3D, 0xB4DD, 0x6B98, 0xB4DE, 0x6B96, 0xB4DF, 0x6BBC, 0xB4E0, 0x6BEF, + 0xB4E1, 0x6C2E, 0xB4E2, 0x6C2F, 0xB4E3, 0x6C2C, 0xB4E4, 0x6E2F, 0xB4E5, 0x6E38, 0xB4E6, 0x6E54, 0xB4E7, 0x6E21, 0xB4E8, 0x6E32, + 0xB4E9, 0x6E67, 0xB4EA, 0x6E4A, 0xB4EB, 0x6E20, 0xB4EC, 0x6E25, 0xB4ED, 0x6E23, 0xB4EE, 0x6E1B, 0xB4EF, 0x6E5B, 0xB4F0, 0x6E58, + 0xB4F1, 0x6E24, 0xB4F2, 0x6E56, 0xB4F3, 0x6E6E, 0xB4F4, 0x6E2D, 0xB4F5, 0x6E26, 0xB4F6, 0x6E6F, 0xB4F7, 0x6E34, 0xB4F8, 0x6E4D, + 0xB4F9, 0x6E3A, 0xB4FA, 0x6E2C, 0xB4FB, 0x6E43, 0xB4FC, 0x6E1D, 0xB4FD, 0x6E3E, 0xB4FE, 0x6ECB, 0xB540, 0x6E89, 0xB541, 0x6E19, + 0xB542, 0x6E4E, 0xB543, 0x6E63, 0xB544, 0x6E44, 0xB545, 0x6E72, 0xB546, 0x6E69, 0xB547, 0x6E5F, 0xB548, 0x7119, 0xB549, 0x711A, + 0xB54A, 0x7126, 0xB54B, 0x7130, 0xB54C, 0x7121, 0xB54D, 0x7136, 0xB54E, 0x716E, 0xB54F, 0x711C, 0xB550, 0x724C, 0xB551, 0x7284, + 0xB552, 0x7280, 0xB553, 0x7336, 0xB554, 0x7325, 0xB555, 0x7334, 0xB556, 0x7329, 0xB557, 0x743A, 0xB558, 0x742A, 0xB559, 0x7433, + 0xB55A, 0x7422, 0xB55B, 0x7425, 0xB55C, 0x7435, 0xB55D, 0x7436, 0xB55E, 0x7434, 0xB55F, 0x742F, 0xB560, 0x741B, 0xB561, 0x7426, + 0xB562, 0x7428, 0xB563, 0x7525, 0xB564, 0x7526, 0xB565, 0x756B, 0xB566, 0x756A, 0xB567, 0x75E2, 0xB568, 0x75DB, 0xB569, 0x75E3, + 0xB56A, 0x75D9, 0xB56B, 0x75D8, 0xB56C, 0x75DE, 0xB56D, 0x75E0, 0xB56E, 0x767B, 0xB56F, 0x767C, 0xB570, 0x7696, 0xB571, 0x7693, + 0xB572, 0x76B4, 0xB573, 0x76DC, 0xB574, 0x774F, 0xB575, 0x77ED, 0xB576, 0x785D, 0xB577, 0x786C, 0xB578, 0x786F, 0xB579, 0x7A0D, + 0xB57A, 0x7A08, 0xB57B, 0x7A0B, 0xB57C, 0x7A05, 0xB57D, 0x7A00, 0xB57E, 0x7A98, 0xB5A1, 0x7A97, 0xB5A2, 0x7A96, 0xB5A3, 0x7AE5, + 0xB5A4, 0x7AE3, 0xB5A5, 0x7B49, 0xB5A6, 0x7B56, 0xB5A7, 0x7B46, 0xB5A8, 0x7B50, 0xB5A9, 0x7B52, 0xB5AA, 0x7B54, 0xB5AB, 0x7B4D, + 0xB5AC, 0x7B4B, 0xB5AD, 0x7B4F, 0xB5AE, 0x7B51, 0xB5AF, 0x7C9F, 0xB5B0, 0x7CA5, 0xB5B1, 0x7D5E, 0xB5B2, 0x7D50, 0xB5B3, 0x7D68, + 0xB5B4, 0x7D55, 0xB5B5, 0x7D2B, 0xB5B6, 0x7D6E, 0xB5B7, 0x7D72, 0xB5B8, 0x7D61, 0xB5B9, 0x7D66, 0xB5BA, 0x7D62, 0xB5BB, 0x7D70, + 0xB5BC, 0x7D73, 0xB5BD, 0x5584, 0xB5BE, 0x7FD4, 0xB5BF, 0x7FD5, 0xB5C0, 0x800B, 0xB5C1, 0x8052, 0xB5C2, 0x8085, 0xB5C3, 0x8155, + 0xB5C4, 0x8154, 0xB5C5, 0x814B, 0xB5C6, 0x8151, 0xB5C7, 0x814E, 0xB5C8, 0x8139, 0xB5C9, 0x8146, 0xB5CA, 0x813E, 0xB5CB, 0x814C, + 0xB5CC, 0x8153, 0xB5CD, 0x8174, 0xB5CE, 0x8212, 0xB5CF, 0x821C, 0xB5D0, 0x83E9, 0xB5D1, 0x8403, 0xB5D2, 0x83F8, 0xB5D3, 0x840D, + 0xB5D4, 0x83E0, 0xB5D5, 0x83C5, 0xB5D6, 0x840B, 0xB5D7, 0x83C1, 0xB5D8, 0x83EF, 0xB5D9, 0x83F1, 0xB5DA, 0x83F4, 0xB5DB, 0x8457, + 0xB5DC, 0x840A, 0xB5DD, 0x83F0, 0xB5DE, 0x840C, 0xB5DF, 0x83CC, 0xB5E0, 0x83FD, 0xB5E1, 0x83F2, 0xB5E2, 0x83CA, 0xB5E3, 0x8438, + 0xB5E4, 0x840E, 0xB5E5, 0x8404, 0xB5E6, 0x83DC, 0xB5E7, 0x8407, 0xB5E8, 0x83D4, 0xB5E9, 0x83DF, 0xB5EA, 0x865B, 0xB5EB, 0x86DF, + 0xB5EC, 0x86D9, 0xB5ED, 0x86ED, 0xB5EE, 0x86D4, 0xB5EF, 0x86DB, 0xB5F0, 0x86E4, 0xB5F1, 0x86D0, 0xB5F2, 0x86DE, 0xB5F3, 0x8857, + 0xB5F4, 0x88C1, 0xB5F5, 0x88C2, 0xB5F6, 0x88B1, 0xB5F7, 0x8983, 0xB5F8, 0x8996, 0xB5F9, 0x8A3B, 0xB5FA, 0x8A60, 0xB5FB, 0x8A55, + 0xB5FC, 0x8A5E, 0xB5FD, 0x8A3C, 0xB5FE, 0x8A41, 0xB640, 0x8A54, 0xB641, 0x8A5B, 0xB642, 0x8A50, 0xB643, 0x8A46, 0xB644, 0x8A34, + 0xB645, 0x8A3A, 0xB646, 0x8A36, 0xB647, 0x8A56, 0xB648, 0x8C61, 0xB649, 0x8C82, 0xB64A, 0x8CAF, 0xB64B, 0x8CBC, 0xB64C, 0x8CB3, + 0xB64D, 0x8CBD, 0xB64E, 0x8CC1, 0xB64F, 0x8CBB, 0xB650, 0x8CC0, 0xB651, 0x8CB4, 0xB652, 0x8CB7, 0xB653, 0x8CB6, 0xB654, 0x8CBF, + 0xB655, 0x8CB8, 0xB656, 0x8D8A, 0xB657, 0x8D85, 0xB658, 0x8D81, 0xB659, 0x8DCE, 0xB65A, 0x8DDD, 0xB65B, 0x8DCB, 0xB65C, 0x8DDA, + 0xB65D, 0x8DD1, 0xB65E, 0x8DCC, 0xB65F, 0x8DDB, 0xB660, 0x8DC6, 0xB661, 0x8EFB, 0xB662, 0x8EF8, 0xB663, 0x8EFC, 0xB664, 0x8F9C, + 0xB665, 0x902E, 0xB666, 0x9035, 0xB667, 0x9031, 0xB668, 0x9038, 0xB669, 0x9032, 0xB66A, 0x9036, 0xB66B, 0x9102, 0xB66C, 0x90F5, + 0xB66D, 0x9109, 0xB66E, 0x90FE, 0xB66F, 0x9163, 0xB670, 0x9165, 0xB671, 0x91CF, 0xB672, 0x9214, 0xB673, 0x9215, 0xB674, 0x9223, + 0xB675, 0x9209, 0xB676, 0x921E, 0xB677, 0x920D, 0xB678, 0x9210, 0xB679, 0x9207, 0xB67A, 0x9211, 0xB67B, 0x9594, 0xB67C, 0x958F, + 0xB67D, 0x958B, 0xB67E, 0x9591, 0xB6A1, 0x9593, 0xB6A2, 0x9592, 0xB6A3, 0x958E, 0xB6A4, 0x968A, 0xB6A5, 0x968E, 0xB6A6, 0x968B, + 0xB6A7, 0x967D, 0xB6A8, 0x9685, 0xB6A9, 0x9686, 0xB6AA, 0x968D, 0xB6AB, 0x9672, 0xB6AC, 0x9684, 0xB6AD, 0x96C1, 0xB6AE, 0x96C5, + 0xB6AF, 0x96C4, 0xB6B0, 0x96C6, 0xB6B1, 0x96C7, 0xB6B2, 0x96EF, 0xB6B3, 0x96F2, 0xB6B4, 0x97CC, 0xB6B5, 0x9805, 0xB6B6, 0x9806, + 0xB6B7, 0x9808, 0xB6B8, 0x98E7, 0xB6B9, 0x98EA, 0xB6BA, 0x98EF, 0xB6BB, 0x98E9, 0xB6BC, 0x98F2, 0xB6BD, 0x98ED, 0xB6BE, 0x99AE, + 0xB6BF, 0x99AD, 0xB6C0, 0x9EC3, 0xB6C1, 0x9ECD, 0xB6C2, 0x9ED1, 0xB6C3, 0x4E82, 0xB6C4, 0x50AD, 0xB6C5, 0x50B5, 0xB6C6, 0x50B2, + 0xB6C7, 0x50B3, 0xB6C8, 0x50C5, 0xB6C9, 0x50BE, 0xB6CA, 0x50AC, 0xB6CB, 0x50B7, 0xB6CC, 0x50BB, 0xB6CD, 0x50AF, 0xB6CE, 0x50C7, + 0xB6CF, 0x527F, 0xB6D0, 0x5277, 0xB6D1, 0x527D, 0xB6D2, 0x52DF, 0xB6D3, 0x52E6, 0xB6D4, 0x52E4, 0xB6D5, 0x52E2, 0xB6D6, 0x52E3, + 0xB6D7, 0x532F, 0xB6D8, 0x55DF, 0xB6D9, 0x55E8, 0xB6DA, 0x55D3, 0xB6DB, 0x55E6, 0xB6DC, 0x55CE, 0xB6DD, 0x55DC, 0xB6DE, 0x55C7, + 0xB6DF, 0x55D1, 0xB6E0, 0x55E3, 0xB6E1, 0x55E4, 0xB6E2, 0x55EF, 0xB6E3, 0x55DA, 0xB6E4, 0x55E1, 0xB6E5, 0x55C5, 0xB6E6, 0x55C6, + 0xB6E7, 0x55E5, 0xB6E8, 0x55C9, 0xB6E9, 0x5712, 0xB6EA, 0x5713, 0xB6EB, 0x585E, 0xB6EC, 0x5851, 0xB6ED, 0x5858, 0xB6EE, 0x5857, + 0xB6EF, 0x585A, 0xB6F0, 0x5854, 0xB6F1, 0x586B, 0xB6F2, 0x584C, 0xB6F3, 0x586D, 0xB6F4, 0x584A, 0xB6F5, 0x5862, 0xB6F6, 0x5852, + 0xB6F7, 0x584B, 0xB6F8, 0x5967, 0xB6F9, 0x5AC1, 0xB6FA, 0x5AC9, 0xB6FB, 0x5ACC, 0xB6FC, 0x5ABE, 0xB6FD, 0x5ABD, 0xB6FE, 0x5ABC, + 0xB740, 0x5AB3, 0xB741, 0x5AC2, 0xB742, 0x5AB2, 0xB743, 0x5D69, 0xB744, 0x5D6F, 0xB745, 0x5E4C, 0xB746, 0x5E79, 0xB747, 0x5EC9, + 0xB748, 0x5EC8, 0xB749, 0x5F12, 0xB74A, 0x5F59, 0xB74B, 0x5FAC, 0xB74C, 0x5FAE, 0xB74D, 0x611A, 0xB74E, 0x610F, 0xB74F, 0x6148, + 0xB750, 0x611F, 0xB751, 0x60F3, 0xB752, 0x611B, 0xB753, 0x60F9, 0xB754, 0x6101, 0xB755, 0x6108, 0xB756, 0x614E, 0xB757, 0x614C, + 0xB758, 0x6144, 0xB759, 0x614D, 0xB75A, 0x613E, 0xB75B, 0x6134, 0xB75C, 0x6127, 0xB75D, 0x610D, 0xB75E, 0x6106, 0xB75F, 0x6137, + 0xB760, 0x6221, 0xB761, 0x6222, 0xB762, 0x6413, 0xB763, 0x643E, 0xB764, 0x641E, 0xB765, 0x642A, 0xB766, 0x642D, 0xB767, 0x643D, + 0xB768, 0x642C, 0xB769, 0x640F, 0xB76A, 0x641C, 0xB76B, 0x6414, 0xB76C, 0x640D, 0xB76D, 0x6436, 0xB76E, 0x6416, 0xB76F, 0x6417, + 0xB770, 0x6406, 0xB771, 0x656C, 0xB772, 0x659F, 0xB773, 0x65B0, 0xB774, 0x6697, 0xB775, 0x6689, 0xB776, 0x6687, 0xB777, 0x6688, + 0xB778, 0x6696, 0xB779, 0x6684, 0xB77A, 0x6698, 0xB77B, 0x668D, 0xB77C, 0x6703, 0xB77D, 0x6994, 0xB77E, 0x696D, 0xB7A1, 0x695A, + 0xB7A2, 0x6977, 0xB7A3, 0x6960, 0xB7A4, 0x6954, 0xB7A5, 0x6975, 0xB7A6, 0x6930, 0xB7A7, 0x6982, 0xB7A8, 0x694A, 0xB7A9, 0x6968, + 0xB7AA, 0x696B, 0xB7AB, 0x695E, 0xB7AC, 0x6953, 0xB7AD, 0x6979, 0xB7AE, 0x6986, 0xB7AF, 0x695D, 0xB7B0, 0x6963, 0xB7B1, 0x695B, + 0xB7B2, 0x6B47, 0xB7B3, 0x6B72, 0xB7B4, 0x6BC0, 0xB7B5, 0x6BBF, 0xB7B6, 0x6BD3, 0xB7B7, 0x6BFD, 0xB7B8, 0x6EA2, 0xB7B9, 0x6EAF, + 0xB7BA, 0x6ED3, 0xB7BB, 0x6EB6, 0xB7BC, 0x6EC2, 0xB7BD, 0x6E90, 0xB7BE, 0x6E9D, 0xB7BF, 0x6EC7, 0xB7C0, 0x6EC5, 0xB7C1, 0x6EA5, + 0xB7C2, 0x6E98, 0xB7C3, 0x6EBC, 0xB7C4, 0x6EBA, 0xB7C5, 0x6EAB, 0xB7C6, 0x6ED1, 0xB7C7, 0x6E96, 0xB7C8, 0x6E9C, 0xB7C9, 0x6EC4, + 0xB7CA, 0x6ED4, 0xB7CB, 0x6EAA, 0xB7CC, 0x6EA7, 0xB7CD, 0x6EB4, 0xB7CE, 0x714E, 0xB7CF, 0x7159, 0xB7D0, 0x7169, 0xB7D1, 0x7164, + 0xB7D2, 0x7149, 0xB7D3, 0x7167, 0xB7D4, 0x715C, 0xB7D5, 0x716C, 0xB7D6, 0x7166, 0xB7D7, 0x714C, 0xB7D8, 0x7165, 0xB7D9, 0x715E, + 0xB7DA, 0x7146, 0xB7DB, 0x7168, 0xB7DC, 0x7156, 0xB7DD, 0x723A, 0xB7DE, 0x7252, 0xB7DF, 0x7337, 0xB7E0, 0x7345, 0xB7E1, 0x733F, + 0xB7E2, 0x733E, 0xB7E3, 0x746F, 0xB7E4, 0x745A, 0xB7E5, 0x7455, 0xB7E6, 0x745F, 0xB7E7, 0x745E, 0xB7E8, 0x7441, 0xB7E9, 0x743F, + 0xB7EA, 0x7459, 0xB7EB, 0x745B, 0xB7EC, 0x745C, 0xB7ED, 0x7576, 0xB7EE, 0x7578, 0xB7EF, 0x7600, 0xB7F0, 0x75F0, 0xB7F1, 0x7601, + 0xB7F2, 0x75F2, 0xB7F3, 0x75F1, 0xB7F4, 0x75FA, 0xB7F5, 0x75FF, 0xB7F6, 0x75F4, 0xB7F7, 0x75F3, 0xB7F8, 0x76DE, 0xB7F9, 0x76DF, + 0xB7FA, 0x775B, 0xB7FB, 0x776B, 0xB7FC, 0x7766, 0xB7FD, 0x775E, 0xB7FE, 0x7763, 0xB840, 0x7779, 0xB841, 0x776A, 0xB842, 0x776C, + 0xB843, 0x775C, 0xB844, 0x7765, 0xB845, 0x7768, 0xB846, 0x7762, 0xB847, 0x77EE, 0xB848, 0x788E, 0xB849, 0x78B0, 0xB84A, 0x7897, + 0xB84B, 0x7898, 0xB84C, 0x788C, 0xB84D, 0x7889, 0xB84E, 0x787C, 0xB84F, 0x7891, 0xB850, 0x7893, 0xB851, 0x787F, 0xB852, 0x797A, + 0xB853, 0x797F, 0xB854, 0x7981, 0xB855, 0x842C, 0xB856, 0x79BD, 0xB857, 0x7A1C, 0xB858, 0x7A1A, 0xB859, 0x7A20, 0xB85A, 0x7A14, + 0xB85B, 0x7A1F, 0xB85C, 0x7A1E, 0xB85D, 0x7A9F, 0xB85E, 0x7AA0, 0xB85F, 0x7B77, 0xB860, 0x7BC0, 0xB861, 0x7B60, 0xB862, 0x7B6E, + 0xB863, 0x7B67, 0xB864, 0x7CB1, 0xB865, 0x7CB3, 0xB866, 0x7CB5, 0xB867, 0x7D93, 0xB868, 0x7D79, 0xB869, 0x7D91, 0xB86A, 0x7D81, + 0xB86B, 0x7D8F, 0xB86C, 0x7D5B, 0xB86D, 0x7F6E, 0xB86E, 0x7F69, 0xB86F, 0x7F6A, 0xB870, 0x7F72, 0xB871, 0x7FA9, 0xB872, 0x7FA8, + 0xB873, 0x7FA4, 0xB874, 0x8056, 0xB875, 0x8058, 0xB876, 0x8086, 0xB877, 0x8084, 0xB878, 0x8171, 0xB879, 0x8170, 0xB87A, 0x8178, + 0xB87B, 0x8165, 0xB87C, 0x816E, 0xB87D, 0x8173, 0xB87E, 0x816B, 0xB8A1, 0x8179, 0xB8A2, 0x817A, 0xB8A3, 0x8166, 0xB8A4, 0x8205, + 0xB8A5, 0x8247, 0xB8A6, 0x8482, 0xB8A7, 0x8477, 0xB8A8, 0x843D, 0xB8A9, 0x8431, 0xB8AA, 0x8475, 0xB8AB, 0x8466, 0xB8AC, 0x846B, + 0xB8AD, 0x8449, 0xB8AE, 0x846C, 0xB8AF, 0x845B, 0xB8B0, 0x843C, 0xB8B1, 0x8435, 0xB8B2, 0x8461, 0xB8B3, 0x8463, 0xB8B4, 0x8469, + 0xB8B5, 0x846D, 0xB8B6, 0x8446, 0xB8B7, 0x865E, 0xB8B8, 0x865C, 0xB8B9, 0x865F, 0xB8BA, 0x86F9, 0xB8BB, 0x8713, 0xB8BC, 0x8708, + 0xB8BD, 0x8707, 0xB8BE, 0x8700, 0xB8BF, 0x86FE, 0xB8C0, 0x86FB, 0xB8C1, 0x8702, 0xB8C2, 0x8703, 0xB8C3, 0x8706, 0xB8C4, 0x870A, + 0xB8C5, 0x8859, 0xB8C6, 0x88DF, 0xB8C7, 0x88D4, 0xB8C8, 0x88D9, 0xB8C9, 0x88DC, 0xB8CA, 0x88D8, 0xB8CB, 0x88DD, 0xB8CC, 0x88E1, + 0xB8CD, 0x88CA, 0xB8CE, 0x88D5, 0xB8CF, 0x88D2, 0xB8D0, 0x899C, 0xB8D1, 0x89E3, 0xB8D2, 0x8A6B, 0xB8D3, 0x8A72, 0xB8D4, 0x8A73, + 0xB8D5, 0x8A66, 0xB8D6, 0x8A69, 0xB8D7, 0x8A70, 0xB8D8, 0x8A87, 0xB8D9, 0x8A7C, 0xB8DA, 0x8A63, 0xB8DB, 0x8AA0, 0xB8DC, 0x8A71, + 0xB8DD, 0x8A85, 0xB8DE, 0x8A6D, 0xB8DF, 0x8A62, 0xB8E0, 0x8A6E, 0xB8E1, 0x8A6C, 0xB8E2, 0x8A79, 0xB8E3, 0x8A7B, 0xB8E4, 0x8A3E, + 0xB8E5, 0x8A68, 0xB8E6, 0x8C62, 0xB8E7, 0x8C8A, 0xB8E8, 0x8C89, 0xB8E9, 0x8CCA, 0xB8EA, 0x8CC7, 0xB8EB, 0x8CC8, 0xB8EC, 0x8CC4, + 0xB8ED, 0x8CB2, 0xB8EE, 0x8CC3, 0xB8EF, 0x8CC2, 0xB8F0, 0x8CC5, 0xB8F1, 0x8DE1, 0xB8F2, 0x8DDF, 0xB8F3, 0x8DE8, 0xB8F4, 0x8DEF, + 0xB8F5, 0x8DF3, 0xB8F6, 0x8DFA, 0xB8F7, 0x8DEA, 0xB8F8, 0x8DE4, 0xB8F9, 0x8DE6, 0xB8FA, 0x8EB2, 0xB8FB, 0x8F03, 0xB8FC, 0x8F09, + 0xB8FD, 0x8EFE, 0xB8FE, 0x8F0A, 0xB940, 0x8F9F, 0xB941, 0x8FB2, 0xB942, 0x904B, 0xB943, 0x904A, 0xB944, 0x9053, 0xB945, 0x9042, + 0xB946, 0x9054, 0xB947, 0x903C, 0xB948, 0x9055, 0xB949, 0x9050, 0xB94A, 0x9047, 0xB94B, 0x904F, 0xB94C, 0x904E, 0xB94D, 0x904D, + 0xB94E, 0x9051, 0xB94F, 0x903E, 0xB950, 0x9041, 0xB951, 0x9112, 0xB952, 0x9117, 0xB953, 0x916C, 0xB954, 0x916A, 0xB955, 0x9169, + 0xB956, 0x91C9, 0xB957, 0x9237, 0xB958, 0x9257, 0xB959, 0x9238, 0xB95A, 0x923D, 0xB95B, 0x9240, 0xB95C, 0x923E, 0xB95D, 0x925B, + 0xB95E, 0x924B, 0xB95F, 0x9264, 0xB960, 0x9251, 0xB961, 0x9234, 0xB962, 0x9249, 0xB963, 0x924D, 0xB964, 0x9245, 0xB965, 0x9239, + 0xB966, 0x923F, 0xB967, 0x925A, 0xB968, 0x9598, 0xB969, 0x9698, 0xB96A, 0x9694, 0xB96B, 0x9695, 0xB96C, 0x96CD, 0xB96D, 0x96CB, + 0xB96E, 0x96C9, 0xB96F, 0x96CA, 0xB970, 0x96F7, 0xB971, 0x96FB, 0xB972, 0x96F9, 0xB973, 0x96F6, 0xB974, 0x9756, 0xB975, 0x9774, + 0xB976, 0x9776, 0xB977, 0x9810, 0xB978, 0x9811, 0xB979, 0x9813, 0xB97A, 0x980A, 0xB97B, 0x9812, 0xB97C, 0x980C, 0xB97D, 0x98FC, + 0xB97E, 0x98F4, 0xB9A1, 0x98FD, 0xB9A2, 0x98FE, 0xB9A3, 0x99B3, 0xB9A4, 0x99B1, 0xB9A5, 0x99B4, 0xB9A6, 0x9AE1, 0xB9A7, 0x9CE9, + 0xB9A8, 0x9E82, 0xB9A9, 0x9F0E, 0xB9AA, 0x9F13, 0xB9AB, 0x9F20, 0xB9AC, 0x50E7, 0xB9AD, 0x50EE, 0xB9AE, 0x50E5, 0xB9AF, 0x50D6, + 0xB9B0, 0x50ED, 0xB9B1, 0x50DA, 0xB9B2, 0x50D5, 0xB9B3, 0x50CF, 0xB9B4, 0x50D1, 0xB9B5, 0x50F1, 0xB9B6, 0x50CE, 0xB9B7, 0x50E9, + 0xB9B8, 0x5162, 0xB9B9, 0x51F3, 0xB9BA, 0x5283, 0xB9BB, 0x5282, 0xB9BC, 0x5331, 0xB9BD, 0x53AD, 0xB9BE, 0x55FE, 0xB9BF, 0x5600, + 0xB9C0, 0x561B, 0xB9C1, 0x5617, 0xB9C2, 0x55FD, 0xB9C3, 0x5614, 0xB9C4, 0x5606, 0xB9C5, 0x5609, 0xB9C6, 0x560D, 0xB9C7, 0x560E, + 0xB9C8, 0x55F7, 0xB9C9, 0x5616, 0xB9CA, 0x561F, 0xB9CB, 0x5608, 0xB9CC, 0x5610, 0xB9CD, 0x55F6, 0xB9CE, 0x5718, 0xB9CF, 0x5716, + 0xB9D0, 0x5875, 0xB9D1, 0x587E, 0xB9D2, 0x5883, 0xB9D3, 0x5893, 0xB9D4, 0x588A, 0xB9D5, 0x5879, 0xB9D6, 0x5885, 0xB9D7, 0x587D, + 0xB9D8, 0x58FD, 0xB9D9, 0x5925, 0xB9DA, 0x5922, 0xB9DB, 0x5924, 0xB9DC, 0x596A, 0xB9DD, 0x5969, 0xB9DE, 0x5AE1, 0xB9DF, 0x5AE6, + 0xB9E0, 0x5AE9, 0xB9E1, 0x5AD7, 0xB9E2, 0x5AD6, 0xB9E3, 0x5AD8, 0xB9E4, 0x5AE3, 0xB9E5, 0x5B75, 0xB9E6, 0x5BDE, 0xB9E7, 0x5BE7, + 0xB9E8, 0x5BE1, 0xB9E9, 0x5BE5, 0xB9EA, 0x5BE6, 0xB9EB, 0x5BE8, 0xB9EC, 0x5BE2, 0xB9ED, 0x5BE4, 0xB9EE, 0x5BDF, 0xB9EF, 0x5C0D, + 0xB9F0, 0x5C62, 0xB9F1, 0x5D84, 0xB9F2, 0x5D87, 0xB9F3, 0x5E5B, 0xB9F4, 0x5E63, 0xB9F5, 0x5E55, 0xB9F6, 0x5E57, 0xB9F7, 0x5E54, + 0xB9F8, 0x5ED3, 0xB9F9, 0x5ED6, 0xB9FA, 0x5F0A, 0xB9FB, 0x5F46, 0xB9FC, 0x5F70, 0xB9FD, 0x5FB9, 0xB9FE, 0x6147, 0xBA40, 0x613F, + 0xBA41, 0x614B, 0xBA42, 0x6177, 0xBA43, 0x6162, 0xBA44, 0x6163, 0xBA45, 0x615F, 0xBA46, 0x615A, 0xBA47, 0x6158, 0xBA48, 0x6175, + 0xBA49, 0x622A, 0xBA4A, 0x6487, 0xBA4B, 0x6458, 0xBA4C, 0x6454, 0xBA4D, 0x64A4, 0xBA4E, 0x6478, 0xBA4F, 0x645F, 0xBA50, 0x647A, + 0xBA51, 0x6451, 0xBA52, 0x6467, 0xBA53, 0x6434, 0xBA54, 0x646D, 0xBA55, 0x647B, 0xBA56, 0x6572, 0xBA57, 0x65A1, 0xBA58, 0x65D7, + 0xBA59, 0x65D6, 0xBA5A, 0x66A2, 0xBA5B, 0x66A8, 0xBA5C, 0x669D, 0xBA5D, 0x699C, 0xBA5E, 0x69A8, 0xBA5F, 0x6995, 0xBA60, 0x69C1, + 0xBA61, 0x69AE, 0xBA62, 0x69D3, 0xBA63, 0x69CB, 0xBA64, 0x699B, 0xBA65, 0x69B7, 0xBA66, 0x69BB, 0xBA67, 0x69AB, 0xBA68, 0x69B4, + 0xBA69, 0x69D0, 0xBA6A, 0x69CD, 0xBA6B, 0x69AD, 0xBA6C, 0x69CC, 0xBA6D, 0x69A6, 0xBA6E, 0x69C3, 0xBA6F, 0x69A3, 0xBA70, 0x6B49, + 0xBA71, 0x6B4C, 0xBA72, 0x6C33, 0xBA73, 0x6F33, 0xBA74, 0x6F14, 0xBA75, 0x6EFE, 0xBA76, 0x6F13, 0xBA77, 0x6EF4, 0xBA78, 0x6F29, + 0xBA79, 0x6F3E, 0xBA7A, 0x6F20, 0xBA7B, 0x6F2C, 0xBA7C, 0x6F0F, 0xBA7D, 0x6F02, 0xBA7E, 0x6F22, 0xBAA1, 0x6EFF, 0xBAA2, 0x6EEF, + 0xBAA3, 0x6F06, 0xBAA4, 0x6F31, 0xBAA5, 0x6F38, 0xBAA6, 0x6F32, 0xBAA7, 0x6F23, 0xBAA8, 0x6F15, 0xBAA9, 0x6F2B, 0xBAAA, 0x6F2F, + 0xBAAB, 0x6F88, 0xBAAC, 0x6F2A, 0xBAAD, 0x6EEC, 0xBAAE, 0x6F01, 0xBAAF, 0x6EF2, 0xBAB0, 0x6ECC, 0xBAB1, 0x6EF7, 0xBAB2, 0x7194, + 0xBAB3, 0x7199, 0xBAB4, 0x717D, 0xBAB5, 0x718A, 0xBAB6, 0x7184, 0xBAB7, 0x7192, 0xBAB8, 0x723E, 0xBAB9, 0x7292, 0xBABA, 0x7296, + 0xBABB, 0x7344, 0xBABC, 0x7350, 0xBABD, 0x7464, 0xBABE, 0x7463, 0xBABF, 0x746A, 0xBAC0, 0x7470, 0xBAC1, 0x746D, 0xBAC2, 0x7504, + 0xBAC3, 0x7591, 0xBAC4, 0x7627, 0xBAC5, 0x760D, 0xBAC6, 0x760B, 0xBAC7, 0x7609, 0xBAC8, 0x7613, 0xBAC9, 0x76E1, 0xBACA, 0x76E3, + 0xBACB, 0x7784, 0xBACC, 0x777D, 0xBACD, 0x777F, 0xBACE, 0x7761, 0xBACF, 0x78C1, 0xBAD0, 0x789F, 0xBAD1, 0x78A7, 0xBAD2, 0x78B3, + 0xBAD3, 0x78A9, 0xBAD4, 0x78A3, 0xBAD5, 0x798E, 0xBAD6, 0x798F, 0xBAD7, 0x798D, 0xBAD8, 0x7A2E, 0xBAD9, 0x7A31, 0xBADA, 0x7AAA, + 0xBADB, 0x7AA9, 0xBADC, 0x7AED, 0xBADD, 0x7AEF, 0xBADE, 0x7BA1, 0xBADF, 0x7B95, 0xBAE0, 0x7B8B, 0xBAE1, 0x7B75, 0xBAE2, 0x7B97, + 0xBAE3, 0x7B9D, 0xBAE4, 0x7B94, 0xBAE5, 0x7B8F, 0xBAE6, 0x7BB8, 0xBAE7, 0x7B87, 0xBAE8, 0x7B84, 0xBAE9, 0x7CB9, 0xBAEA, 0x7CBD, + 0xBAEB, 0x7CBE, 0xBAEC, 0x7DBB, 0xBAED, 0x7DB0, 0xBAEE, 0x7D9C, 0xBAEF, 0x7DBD, 0xBAF0, 0x7DBE, 0xBAF1, 0x7DA0, 0xBAF2, 0x7DCA, + 0xBAF3, 0x7DB4, 0xBAF4, 0x7DB2, 0xBAF5, 0x7DB1, 0xBAF6, 0x7DBA, 0xBAF7, 0x7DA2, 0xBAF8, 0x7DBF, 0xBAF9, 0x7DB5, 0xBAFA, 0x7DB8, + 0xBAFB, 0x7DAD, 0xBAFC, 0x7DD2, 0xBAFD, 0x7DC7, 0xBAFE, 0x7DAC, 0xBB40, 0x7F70, 0xBB41, 0x7FE0, 0xBB42, 0x7FE1, 0xBB43, 0x7FDF, + 0xBB44, 0x805E, 0xBB45, 0x805A, 0xBB46, 0x8087, 0xBB47, 0x8150, 0xBB48, 0x8180, 0xBB49, 0x818F, 0xBB4A, 0x8188, 0xBB4B, 0x818A, + 0xBB4C, 0x817F, 0xBB4D, 0x8182, 0xBB4E, 0x81E7, 0xBB4F, 0x81FA, 0xBB50, 0x8207, 0xBB51, 0x8214, 0xBB52, 0x821E, 0xBB53, 0x824B, + 0xBB54, 0x84C9, 0xBB55, 0x84BF, 0xBB56, 0x84C6, 0xBB57, 0x84C4, 0xBB58, 0x8499, 0xBB59, 0x849E, 0xBB5A, 0x84B2, 0xBB5B, 0x849C, + 0xBB5C, 0x84CB, 0xBB5D, 0x84B8, 0xBB5E, 0x84C0, 0xBB5F, 0x84D3, 0xBB60, 0x8490, 0xBB61, 0x84BC, 0xBB62, 0x84D1, 0xBB63, 0x84CA, + 0xBB64, 0x873F, 0xBB65, 0x871C, 0xBB66, 0x873B, 0xBB67, 0x8722, 0xBB68, 0x8725, 0xBB69, 0x8734, 0xBB6A, 0x8718, 0xBB6B, 0x8755, + 0xBB6C, 0x8737, 0xBB6D, 0x8729, 0xBB6E, 0x88F3, 0xBB6F, 0x8902, 0xBB70, 0x88F4, 0xBB71, 0x88F9, 0xBB72, 0x88F8, 0xBB73, 0x88FD, + 0xBB74, 0x88E8, 0xBB75, 0x891A, 0xBB76, 0x88EF, 0xBB77, 0x8AA6, 0xBB78, 0x8A8C, 0xBB79, 0x8A9E, 0xBB7A, 0x8AA3, 0xBB7B, 0x8A8D, + 0xBB7C, 0x8AA1, 0xBB7D, 0x8A93, 0xBB7E, 0x8AA4, 0xBBA1, 0x8AAA, 0xBBA2, 0x8AA5, 0xBBA3, 0x8AA8, 0xBBA4, 0x8A98, 0xBBA5, 0x8A91, + 0xBBA6, 0x8A9A, 0xBBA7, 0x8AA7, 0xBBA8, 0x8C6A, 0xBBA9, 0x8C8D, 0xBBAA, 0x8C8C, 0xBBAB, 0x8CD3, 0xBBAC, 0x8CD1, 0xBBAD, 0x8CD2, + 0xBBAE, 0x8D6B, 0xBBAF, 0x8D99, 0xBBB0, 0x8D95, 0xBBB1, 0x8DFC, 0xBBB2, 0x8F14, 0xBBB3, 0x8F12, 0xBBB4, 0x8F15, 0xBBB5, 0x8F13, + 0xBBB6, 0x8FA3, 0xBBB7, 0x9060, 0xBBB8, 0x9058, 0xBBB9, 0x905C, 0xBBBA, 0x9063, 0xBBBB, 0x9059, 0xBBBC, 0x905E, 0xBBBD, 0x9062, + 0xBBBE, 0x905D, 0xBBBF, 0x905B, 0xBBC0, 0x9119, 0xBBC1, 0x9118, 0xBBC2, 0x911E, 0xBBC3, 0x9175, 0xBBC4, 0x9178, 0xBBC5, 0x9177, + 0xBBC6, 0x9174, 0xBBC7, 0x9278, 0xBBC8, 0x9280, 0xBBC9, 0x9285, 0xBBCA, 0x9298, 0xBBCB, 0x9296, 0xBBCC, 0x927B, 0xBBCD, 0x9293, + 0xBBCE, 0x929C, 0xBBCF, 0x92A8, 0xBBD0, 0x927C, 0xBBD1, 0x9291, 0xBBD2, 0x95A1, 0xBBD3, 0x95A8, 0xBBD4, 0x95A9, 0xBBD5, 0x95A3, + 0xBBD6, 0x95A5, 0xBBD7, 0x95A4, 0xBBD8, 0x9699, 0xBBD9, 0x969C, 0xBBDA, 0x969B, 0xBBDB, 0x96CC, 0xBBDC, 0x96D2, 0xBBDD, 0x9700, + 0xBBDE, 0x977C, 0xBBDF, 0x9785, 0xBBE0, 0x97F6, 0xBBE1, 0x9817, 0xBBE2, 0x9818, 0xBBE3, 0x98AF, 0xBBE4, 0x98B1, 0xBBE5, 0x9903, + 0xBBE6, 0x9905, 0xBBE7, 0x990C, 0xBBE8, 0x9909, 0xBBE9, 0x99C1, 0xBBEA, 0x9AAF, 0xBBEB, 0x9AB0, 0xBBEC, 0x9AE6, 0xBBED, 0x9B41, + 0xBBEE, 0x9B42, 0xBBEF, 0x9CF4, 0xBBF0, 0x9CF6, 0xBBF1, 0x9CF3, 0xBBF2, 0x9EBC, 0xBBF3, 0x9F3B, 0xBBF4, 0x9F4A, 0xBBF5, 0x5104, + 0xBBF6, 0x5100, 0xBBF7, 0x50FB, 0xBBF8, 0x50F5, 0xBBF9, 0x50F9, 0xBBFA, 0x5102, 0xBBFB, 0x5108, 0xBBFC, 0x5109, 0xBBFD, 0x5105, + 0xBBFE, 0x51DC, 0xBC40, 0x5287, 0xBC41, 0x5288, 0xBC42, 0x5289, 0xBC43, 0x528D, 0xBC44, 0x528A, 0xBC45, 0x52F0, 0xBC46, 0x53B2, + 0xBC47, 0x562E, 0xBC48, 0x563B, 0xBC49, 0x5639, 0xBC4A, 0x5632, 0xBC4B, 0x563F, 0xBC4C, 0x5634, 0xBC4D, 0x5629, 0xBC4E, 0x5653, + 0xBC4F, 0x564E, 0xBC50, 0x5657, 0xBC51, 0x5674, 0xBC52, 0x5636, 0xBC53, 0x562F, 0xBC54, 0x5630, 0xBC55, 0x5880, 0xBC56, 0x589F, + 0xBC57, 0x589E, 0xBC58, 0x58B3, 0xBC59, 0x589C, 0xBC5A, 0x58AE, 0xBC5B, 0x58A9, 0xBC5C, 0x58A6, 0xBC5D, 0x596D, 0xBC5E, 0x5B09, + 0xBC5F, 0x5AFB, 0xBC60, 0x5B0B, 0xBC61, 0x5AF5, 0xBC62, 0x5B0C, 0xBC63, 0x5B08, 0xBC64, 0x5BEE, 0xBC65, 0x5BEC, 0xBC66, 0x5BE9, + 0xBC67, 0x5BEB, 0xBC68, 0x5C64, 0xBC69, 0x5C65, 0xBC6A, 0x5D9D, 0xBC6B, 0x5D94, 0xBC6C, 0x5E62, 0xBC6D, 0x5E5F, 0xBC6E, 0x5E61, + 0xBC6F, 0x5EE2, 0xBC70, 0x5EDA, 0xBC71, 0x5EDF, 0xBC72, 0x5EDD, 0xBC73, 0x5EE3, 0xBC74, 0x5EE0, 0xBC75, 0x5F48, 0xBC76, 0x5F71, + 0xBC77, 0x5FB7, 0xBC78, 0x5FB5, 0xBC79, 0x6176, 0xBC7A, 0x6167, 0xBC7B, 0x616E, 0xBC7C, 0x615D, 0xBC7D, 0x6155, 0xBC7E, 0x6182, + 0xBCA1, 0x617C, 0xBCA2, 0x6170, 0xBCA3, 0x616B, 0xBCA4, 0x617E, 0xBCA5, 0x61A7, 0xBCA6, 0x6190, 0xBCA7, 0x61AB, 0xBCA8, 0x618E, + 0xBCA9, 0x61AC, 0xBCAA, 0x619A, 0xBCAB, 0x61A4, 0xBCAC, 0x6194, 0xBCAD, 0x61AE, 0xBCAE, 0x622E, 0xBCAF, 0x6469, 0xBCB0, 0x646F, + 0xBCB1, 0x6479, 0xBCB2, 0x649E, 0xBCB3, 0x64B2, 0xBCB4, 0x6488, 0xBCB5, 0x6490, 0xBCB6, 0x64B0, 0xBCB7, 0x64A5, 0xBCB8, 0x6493, + 0xBCB9, 0x6495, 0xBCBA, 0x64A9, 0xBCBB, 0x6492, 0xBCBC, 0x64AE, 0xBCBD, 0x64AD, 0xBCBE, 0x64AB, 0xBCBF, 0x649A, 0xBCC0, 0x64AC, + 0xBCC1, 0x6499, 0xBCC2, 0x64A2, 0xBCC3, 0x64B3, 0xBCC4, 0x6575, 0xBCC5, 0x6577, 0xBCC6, 0x6578, 0xBCC7, 0x66AE, 0xBCC8, 0x66AB, + 0xBCC9, 0x66B4, 0xBCCA, 0x66B1, 0xBCCB, 0x6A23, 0xBCCC, 0x6A1F, 0xBCCD, 0x69E8, 0xBCCE, 0x6A01, 0xBCCF, 0x6A1E, 0xBCD0, 0x6A19, + 0xBCD1, 0x69FD, 0xBCD2, 0x6A21, 0xBCD3, 0x6A13, 0xBCD4, 0x6A0A, 0xBCD5, 0x69F3, 0xBCD6, 0x6A02, 0xBCD7, 0x6A05, 0xBCD8, 0x69ED, + 0xBCD9, 0x6A11, 0xBCDA, 0x6B50, 0xBCDB, 0x6B4E, 0xBCDC, 0x6BA4, 0xBCDD, 0x6BC5, 0xBCDE, 0x6BC6, 0xBCDF, 0x6F3F, 0xBCE0, 0x6F7C, + 0xBCE1, 0x6F84, 0xBCE2, 0x6F51, 0xBCE3, 0x6F66, 0xBCE4, 0x6F54, 0xBCE5, 0x6F86, 0xBCE6, 0x6F6D, 0xBCE7, 0x6F5B, 0xBCE8, 0x6F78, + 0xBCE9, 0x6F6E, 0xBCEA, 0x6F8E, 0xBCEB, 0x6F7A, 0xBCEC, 0x6F70, 0xBCED, 0x6F64, 0xBCEE, 0x6F97, 0xBCEF, 0x6F58, 0xBCF0, 0x6ED5, + 0xBCF1, 0x6F6F, 0xBCF2, 0x6F60, 0xBCF3, 0x6F5F, 0xBCF4, 0x719F, 0xBCF5, 0x71AC, 0xBCF6, 0x71B1, 0xBCF7, 0x71A8, 0xBCF8, 0x7256, + 0xBCF9, 0x729B, 0xBCFA, 0x734E, 0xBCFB, 0x7357, 0xBCFC, 0x7469, 0xBCFD, 0x748B, 0xBCFE, 0x7483, 0xBD40, 0x747E, 0xBD41, 0x7480, + 0xBD42, 0x757F, 0xBD43, 0x7620, 0xBD44, 0x7629, 0xBD45, 0x761F, 0xBD46, 0x7624, 0xBD47, 0x7626, 0xBD48, 0x7621, 0xBD49, 0x7622, + 0xBD4A, 0x769A, 0xBD4B, 0x76BA, 0xBD4C, 0x76E4, 0xBD4D, 0x778E, 0xBD4E, 0x7787, 0xBD4F, 0x778C, 0xBD50, 0x7791, 0xBD51, 0x778B, + 0xBD52, 0x78CB, 0xBD53, 0x78C5, 0xBD54, 0x78BA, 0xBD55, 0x78CA, 0xBD56, 0x78BE, 0xBD57, 0x78D5, 0xBD58, 0x78BC, 0xBD59, 0x78D0, + 0xBD5A, 0x7A3F, 0xBD5B, 0x7A3C, 0xBD5C, 0x7A40, 0xBD5D, 0x7A3D, 0xBD5E, 0x7A37, 0xBD5F, 0x7A3B, 0xBD60, 0x7AAF, 0xBD61, 0x7AAE, + 0xBD62, 0x7BAD, 0xBD63, 0x7BB1, 0xBD64, 0x7BC4, 0xBD65, 0x7BB4, 0xBD66, 0x7BC6, 0xBD67, 0x7BC7, 0xBD68, 0x7BC1, 0xBD69, 0x7BA0, + 0xBD6A, 0x7BCC, 0xBD6B, 0x7CCA, 0xBD6C, 0x7DE0, 0xBD6D, 0x7DF4, 0xBD6E, 0x7DEF, 0xBD6F, 0x7DFB, 0xBD70, 0x7DD8, 0xBD71, 0x7DEC, + 0xBD72, 0x7DDD, 0xBD73, 0x7DE8, 0xBD74, 0x7DE3, 0xBD75, 0x7DDA, 0xBD76, 0x7DDE, 0xBD77, 0x7DE9, 0xBD78, 0x7D9E, 0xBD79, 0x7DD9, + 0xBD7A, 0x7DF2, 0xBD7B, 0x7DF9, 0xBD7C, 0x7F75, 0xBD7D, 0x7F77, 0xBD7E, 0x7FAF, 0xBDA1, 0x7FE9, 0xBDA2, 0x8026, 0xBDA3, 0x819B, + 0xBDA4, 0x819C, 0xBDA5, 0x819D, 0xBDA6, 0x81A0, 0xBDA7, 0x819A, 0xBDA8, 0x8198, 0xBDA9, 0x8517, 0xBDAA, 0x853D, 0xBDAB, 0x851A, + 0xBDAC, 0x84EE, 0xBDAD, 0x852C, 0xBDAE, 0x852D, 0xBDAF, 0x8513, 0xBDB0, 0x8511, 0xBDB1, 0x8523, 0xBDB2, 0x8521, 0xBDB3, 0x8514, + 0xBDB4, 0x84EC, 0xBDB5, 0x8525, 0xBDB6, 0x84FF, 0xBDB7, 0x8506, 0xBDB8, 0x8782, 0xBDB9, 0x8774, 0xBDBA, 0x8776, 0xBDBB, 0x8760, + 0xBDBC, 0x8766, 0xBDBD, 0x8778, 0xBDBE, 0x8768, 0xBDBF, 0x8759, 0xBDC0, 0x8757, 0xBDC1, 0x874C, 0xBDC2, 0x8753, 0xBDC3, 0x885B, + 0xBDC4, 0x885D, 0xBDC5, 0x8910, 0xBDC6, 0x8907, 0xBDC7, 0x8912, 0xBDC8, 0x8913, 0xBDC9, 0x8915, 0xBDCA, 0x890A, 0xBDCB, 0x8ABC, + 0xBDCC, 0x8AD2, 0xBDCD, 0x8AC7, 0xBDCE, 0x8AC4, 0xBDCF, 0x8A95, 0xBDD0, 0x8ACB, 0xBDD1, 0x8AF8, 0xBDD2, 0x8AB2, 0xBDD3, 0x8AC9, + 0xBDD4, 0x8AC2, 0xBDD5, 0x8ABF, 0xBDD6, 0x8AB0, 0xBDD7, 0x8AD6, 0xBDD8, 0x8ACD, 0xBDD9, 0x8AB6, 0xBDDA, 0x8AB9, 0xBDDB, 0x8ADB, + 0xBDDC, 0x8C4C, 0xBDDD, 0x8C4E, 0xBDDE, 0x8C6C, 0xBDDF, 0x8CE0, 0xBDE0, 0x8CDE, 0xBDE1, 0x8CE6, 0xBDE2, 0x8CE4, 0xBDE3, 0x8CEC, + 0xBDE4, 0x8CED, 0xBDE5, 0x8CE2, 0xBDE6, 0x8CE3, 0xBDE7, 0x8CDC, 0xBDE8, 0x8CEA, 0xBDE9, 0x8CE1, 0xBDEA, 0x8D6D, 0xBDEB, 0x8D9F, + 0xBDEC, 0x8DA3, 0xBDED, 0x8E2B, 0xBDEE, 0x8E10, 0xBDEF, 0x8E1D, 0xBDF0, 0x8E22, 0xBDF1, 0x8E0F, 0xBDF2, 0x8E29, 0xBDF3, 0x8E1F, + 0xBDF4, 0x8E21, 0xBDF5, 0x8E1E, 0xBDF6, 0x8EBA, 0xBDF7, 0x8F1D, 0xBDF8, 0x8F1B, 0xBDF9, 0x8F1F, 0xBDFA, 0x8F29, 0xBDFB, 0x8F26, + 0xBDFC, 0x8F2A, 0xBDFD, 0x8F1C, 0xBDFE, 0x8F1E, 0xBE40, 0x8F25, 0xBE41, 0x9069, 0xBE42, 0x906E, 0xBE43, 0x9068, 0xBE44, 0x906D, + 0xBE45, 0x9077, 0xBE46, 0x9130, 0xBE47, 0x912D, 0xBE48, 0x9127, 0xBE49, 0x9131, 0xBE4A, 0x9187, 0xBE4B, 0x9189, 0xBE4C, 0x918B, + 0xBE4D, 0x9183, 0xBE4E, 0x92C5, 0xBE4F, 0x92BB, 0xBE50, 0x92B7, 0xBE51, 0x92EA, 0xBE52, 0x92AC, 0xBE53, 0x92E4, 0xBE54, 0x92C1, + 0xBE55, 0x92B3, 0xBE56, 0x92BC, 0xBE57, 0x92D2, 0xBE58, 0x92C7, 0xBE59, 0x92F0, 0xBE5A, 0x92B2, 0xBE5B, 0x95AD, 0xBE5C, 0x95B1, + 0xBE5D, 0x9704, 0xBE5E, 0x9706, 0xBE5F, 0x9707, 0xBE60, 0x9709, 0xBE61, 0x9760, 0xBE62, 0x978D, 0xBE63, 0x978B, 0xBE64, 0x978F, + 0xBE65, 0x9821, 0xBE66, 0x982B, 0xBE67, 0x981C, 0xBE68, 0x98B3, 0xBE69, 0x990A, 0xBE6A, 0x9913, 0xBE6B, 0x9912, 0xBE6C, 0x9918, + 0xBE6D, 0x99DD, 0xBE6E, 0x99D0, 0xBE6F, 0x99DF, 0xBE70, 0x99DB, 0xBE71, 0x99D1, 0xBE72, 0x99D5, 0xBE73, 0x99D2, 0xBE74, 0x99D9, + 0xBE75, 0x9AB7, 0xBE76, 0x9AEE, 0xBE77, 0x9AEF, 0xBE78, 0x9B27, 0xBE79, 0x9B45, 0xBE7A, 0x9B44, 0xBE7B, 0x9B77, 0xBE7C, 0x9B6F, + 0xBE7D, 0x9D06, 0xBE7E, 0x9D09, 0xBEA1, 0x9D03, 0xBEA2, 0x9EA9, 0xBEA3, 0x9EBE, 0xBEA4, 0x9ECE, 0xBEA5, 0x58A8, 0xBEA6, 0x9F52, + 0xBEA7, 0x5112, 0xBEA8, 0x5118, 0xBEA9, 0x5114, 0xBEAA, 0x5110, 0xBEAB, 0x5115, 0xBEAC, 0x5180, 0xBEAD, 0x51AA, 0xBEAE, 0x51DD, + 0xBEAF, 0x5291, 0xBEB0, 0x5293, 0xBEB1, 0x52F3, 0xBEB2, 0x5659, 0xBEB3, 0x566B, 0xBEB4, 0x5679, 0xBEB5, 0x5669, 0xBEB6, 0x5664, + 0xBEB7, 0x5678, 0xBEB8, 0x566A, 0xBEB9, 0x5668, 0xBEBA, 0x5665, 0xBEBB, 0x5671, 0xBEBC, 0x566F, 0xBEBD, 0x566C, 0xBEBE, 0x5662, + 0xBEBF, 0x5676, 0xBEC0, 0x58C1, 0xBEC1, 0x58BE, 0xBEC2, 0x58C7, 0xBEC3, 0x58C5, 0xBEC4, 0x596E, 0xBEC5, 0x5B1D, 0xBEC6, 0x5B34, + 0xBEC7, 0x5B78, 0xBEC8, 0x5BF0, 0xBEC9, 0x5C0E, 0xBECA, 0x5F4A, 0xBECB, 0x61B2, 0xBECC, 0x6191, 0xBECD, 0x61A9, 0xBECE, 0x618A, + 0xBECF, 0x61CD, 0xBED0, 0x61B6, 0xBED1, 0x61BE, 0xBED2, 0x61CA, 0xBED3, 0x61C8, 0xBED4, 0x6230, 0xBED5, 0x64C5, 0xBED6, 0x64C1, + 0xBED7, 0x64CB, 0xBED8, 0x64BB, 0xBED9, 0x64BC, 0xBEDA, 0x64DA, 0xBEDB, 0x64C4, 0xBEDC, 0x64C7, 0xBEDD, 0x64C2, 0xBEDE, 0x64CD, + 0xBEDF, 0x64BF, 0xBEE0, 0x64D2, 0xBEE1, 0x64D4, 0xBEE2, 0x64BE, 0xBEE3, 0x6574, 0xBEE4, 0x66C6, 0xBEE5, 0x66C9, 0xBEE6, 0x66B9, + 0xBEE7, 0x66C4, 0xBEE8, 0x66C7, 0xBEE9, 0x66B8, 0xBEEA, 0x6A3D, 0xBEEB, 0x6A38, 0xBEEC, 0x6A3A, 0xBEED, 0x6A59, 0xBEEE, 0x6A6B, + 0xBEEF, 0x6A58, 0xBEF0, 0x6A39, 0xBEF1, 0x6A44, 0xBEF2, 0x6A62, 0xBEF3, 0x6A61, 0xBEF4, 0x6A4B, 0xBEF5, 0x6A47, 0xBEF6, 0x6A35, + 0xBEF7, 0x6A5F, 0xBEF8, 0x6A48, 0xBEF9, 0x6B59, 0xBEFA, 0x6B77, 0xBEFB, 0x6C05, 0xBEFC, 0x6FC2, 0xBEFD, 0x6FB1, 0xBEFE, 0x6FA1, + 0xBF40, 0x6FC3, 0xBF41, 0x6FA4, 0xBF42, 0x6FC1, 0xBF43, 0x6FA7, 0xBF44, 0x6FB3, 0xBF45, 0x6FC0, 0xBF46, 0x6FB9, 0xBF47, 0x6FB6, + 0xBF48, 0x6FA6, 0xBF49, 0x6FA0, 0xBF4A, 0x6FB4, 0xBF4B, 0x71BE, 0xBF4C, 0x71C9, 0xBF4D, 0x71D0, 0xBF4E, 0x71D2, 0xBF4F, 0x71C8, + 0xBF50, 0x71D5, 0xBF51, 0x71B9, 0xBF52, 0x71CE, 0xBF53, 0x71D9, 0xBF54, 0x71DC, 0xBF55, 0x71C3, 0xBF56, 0x71C4, 0xBF57, 0x7368, + 0xBF58, 0x749C, 0xBF59, 0x74A3, 0xBF5A, 0x7498, 0xBF5B, 0x749F, 0xBF5C, 0x749E, 0xBF5D, 0x74E2, 0xBF5E, 0x750C, 0xBF5F, 0x750D, + 0xBF60, 0x7634, 0xBF61, 0x7638, 0xBF62, 0x763A, 0xBF63, 0x76E7, 0xBF64, 0x76E5, 0xBF65, 0x77A0, 0xBF66, 0x779E, 0xBF67, 0x779F, + 0xBF68, 0x77A5, 0xBF69, 0x78E8, 0xBF6A, 0x78DA, 0xBF6B, 0x78EC, 0xBF6C, 0x78E7, 0xBF6D, 0x79A6, 0xBF6E, 0x7A4D, 0xBF6F, 0x7A4E, + 0xBF70, 0x7A46, 0xBF71, 0x7A4C, 0xBF72, 0x7A4B, 0xBF73, 0x7ABA, 0xBF74, 0x7BD9, 0xBF75, 0x7C11, 0xBF76, 0x7BC9, 0xBF77, 0x7BE4, + 0xBF78, 0x7BDB, 0xBF79, 0x7BE1, 0xBF7A, 0x7BE9, 0xBF7B, 0x7BE6, 0xBF7C, 0x7CD5, 0xBF7D, 0x7CD6, 0xBF7E, 0x7E0A, 0xBFA1, 0x7E11, + 0xBFA2, 0x7E08, 0xBFA3, 0x7E1B, 0xBFA4, 0x7E23, 0xBFA5, 0x7E1E, 0xBFA6, 0x7E1D, 0xBFA7, 0x7E09, 0xBFA8, 0x7E10, 0xBFA9, 0x7F79, + 0xBFAA, 0x7FB2, 0xBFAB, 0x7FF0, 0xBFAC, 0x7FF1, 0xBFAD, 0x7FEE, 0xBFAE, 0x8028, 0xBFAF, 0x81B3, 0xBFB0, 0x81A9, 0xBFB1, 0x81A8, + 0xBFB2, 0x81FB, 0xBFB3, 0x8208, 0xBFB4, 0x8258, 0xBFB5, 0x8259, 0xBFB6, 0x854A, 0xBFB7, 0x8559, 0xBFB8, 0x8548, 0xBFB9, 0x8568, + 0xBFBA, 0x8569, 0xBFBB, 0x8543, 0xBFBC, 0x8549, 0xBFBD, 0x856D, 0xBFBE, 0x856A, 0xBFBF, 0x855E, 0xBFC0, 0x8783, 0xBFC1, 0x879F, + 0xBFC2, 0x879E, 0xBFC3, 0x87A2, 0xBFC4, 0x878D, 0xBFC5, 0x8861, 0xBFC6, 0x892A, 0xBFC7, 0x8932, 0xBFC8, 0x8925, 0xBFC9, 0x892B, + 0xBFCA, 0x8921, 0xBFCB, 0x89AA, 0xBFCC, 0x89A6, 0xBFCD, 0x8AE6, 0xBFCE, 0x8AFA, 0xBFCF, 0x8AEB, 0xBFD0, 0x8AF1, 0xBFD1, 0x8B00, + 0xBFD2, 0x8ADC, 0xBFD3, 0x8AE7, 0xBFD4, 0x8AEE, 0xBFD5, 0x8AFE, 0xBFD6, 0x8B01, 0xBFD7, 0x8B02, 0xBFD8, 0x8AF7, 0xBFD9, 0x8AED, + 0xBFDA, 0x8AF3, 0xBFDB, 0x8AF6, 0xBFDC, 0x8AFC, 0xBFDD, 0x8C6B, 0xBFDE, 0x8C6D, 0xBFDF, 0x8C93, 0xBFE0, 0x8CF4, 0xBFE1, 0x8E44, + 0xBFE2, 0x8E31, 0xBFE3, 0x8E34, 0xBFE4, 0x8E42, 0xBFE5, 0x8E39, 0xBFE6, 0x8E35, 0xBFE7, 0x8F3B, 0xBFE8, 0x8F2F, 0xBFE9, 0x8F38, + 0xBFEA, 0x8F33, 0xBFEB, 0x8FA8, 0xBFEC, 0x8FA6, 0xBFED, 0x9075, 0xBFEE, 0x9074, 0xBFEF, 0x9078, 0xBFF0, 0x9072, 0xBFF1, 0x907C, + 0xBFF2, 0x907A, 0xBFF3, 0x9134, 0xBFF4, 0x9192, 0xBFF5, 0x9320, 0xBFF6, 0x9336, 0xBFF7, 0x92F8, 0xBFF8, 0x9333, 0xBFF9, 0x932F, + 0xBFFA, 0x9322, 0xBFFB, 0x92FC, 0xBFFC, 0x932B, 0xBFFD, 0x9304, 0xBFFE, 0x931A, 0xC040, 0x9310, 0xC041, 0x9326, 0xC042, 0x9321, + 0xC043, 0x9315, 0xC044, 0x932E, 0xC045, 0x9319, 0xC046, 0x95BB, 0xC047, 0x96A7, 0xC048, 0x96A8, 0xC049, 0x96AA, 0xC04A, 0x96D5, + 0xC04B, 0x970E, 0xC04C, 0x9711, 0xC04D, 0x9716, 0xC04E, 0x970D, 0xC04F, 0x9713, 0xC050, 0x970F, 0xC051, 0x975B, 0xC052, 0x975C, + 0xC053, 0x9766, 0xC054, 0x9798, 0xC055, 0x9830, 0xC056, 0x9838, 0xC057, 0x983B, 0xC058, 0x9837, 0xC059, 0x982D, 0xC05A, 0x9839, + 0xC05B, 0x9824, 0xC05C, 0x9910, 0xC05D, 0x9928, 0xC05E, 0x991E, 0xC05F, 0x991B, 0xC060, 0x9921, 0xC061, 0x991A, 0xC062, 0x99ED, + 0xC063, 0x99E2, 0xC064, 0x99F1, 0xC065, 0x9AB8, 0xC066, 0x9ABC, 0xC067, 0x9AFB, 0xC068, 0x9AED, 0xC069, 0x9B28, 0xC06A, 0x9B91, + 0xC06B, 0x9D15, 0xC06C, 0x9D23, 0xC06D, 0x9D26, 0xC06E, 0x9D28, 0xC06F, 0x9D12, 0xC070, 0x9D1B, 0xC071, 0x9ED8, 0xC072, 0x9ED4, + 0xC073, 0x9F8D, 0xC074, 0x9F9C, 0xC075, 0x512A, 0xC076, 0x511F, 0xC077, 0x5121, 0xC078, 0x5132, 0xC079, 0x52F5, 0xC07A, 0x568E, + 0xC07B, 0x5680, 0xC07C, 0x5690, 0xC07D, 0x5685, 0xC07E, 0x5687, 0xC0A1, 0x568F, 0xC0A2, 0x58D5, 0xC0A3, 0x58D3, 0xC0A4, 0x58D1, + 0xC0A5, 0x58CE, 0xC0A6, 0x5B30, 0xC0A7, 0x5B2A, 0xC0A8, 0x5B24, 0xC0A9, 0x5B7A, 0xC0AA, 0x5C37, 0xC0AB, 0x5C68, 0xC0AC, 0x5DBC, + 0xC0AD, 0x5DBA, 0xC0AE, 0x5DBD, 0xC0AF, 0x5DB8, 0xC0B0, 0x5E6B, 0xC0B1, 0x5F4C, 0xC0B2, 0x5FBD, 0xC0B3, 0x61C9, 0xC0B4, 0x61C2, + 0xC0B5, 0x61C7, 0xC0B6, 0x61E6, 0xC0B7, 0x61CB, 0xC0B8, 0x6232, 0xC0B9, 0x6234, 0xC0BA, 0x64CE, 0xC0BB, 0x64CA, 0xC0BC, 0x64D8, + 0xC0BD, 0x64E0, 0xC0BE, 0x64F0, 0xC0BF, 0x64E6, 0xC0C0, 0x64EC, 0xC0C1, 0x64F1, 0xC0C2, 0x64E2, 0xC0C3, 0x64ED, 0xC0C4, 0x6582, + 0xC0C5, 0x6583, 0xC0C6, 0x66D9, 0xC0C7, 0x66D6, 0xC0C8, 0x6A80, 0xC0C9, 0x6A94, 0xC0CA, 0x6A84, 0xC0CB, 0x6AA2, 0xC0CC, 0x6A9C, + 0xC0CD, 0x6ADB, 0xC0CE, 0x6AA3, 0xC0CF, 0x6A7E, 0xC0D0, 0x6A97, 0xC0D1, 0x6A90, 0xC0D2, 0x6AA0, 0xC0D3, 0x6B5C, 0xC0D4, 0x6BAE, + 0xC0D5, 0x6BDA, 0xC0D6, 0x6C08, 0xC0D7, 0x6FD8, 0xC0D8, 0x6FF1, 0xC0D9, 0x6FDF, 0xC0DA, 0x6FE0, 0xC0DB, 0x6FDB, 0xC0DC, 0x6FE4, + 0xC0DD, 0x6FEB, 0xC0DE, 0x6FEF, 0xC0DF, 0x6F80, 0xC0E0, 0x6FEC, 0xC0E1, 0x6FE1, 0xC0E2, 0x6FE9, 0xC0E3, 0x6FD5, 0xC0E4, 0x6FEE, + 0xC0E5, 0x6FF0, 0xC0E6, 0x71E7, 0xC0E7, 0x71DF, 0xC0E8, 0x71EE, 0xC0E9, 0x71E6, 0xC0EA, 0x71E5, 0xC0EB, 0x71ED, 0xC0EC, 0x71EC, + 0xC0ED, 0x71F4, 0xC0EE, 0x71E0, 0xC0EF, 0x7235, 0xC0F0, 0x7246, 0xC0F1, 0x7370, 0xC0F2, 0x7372, 0xC0F3, 0x74A9, 0xC0F4, 0x74B0, + 0xC0F5, 0x74A6, 0xC0F6, 0x74A8, 0xC0F7, 0x7646, 0xC0F8, 0x7642, 0xC0F9, 0x764C, 0xC0FA, 0x76EA, 0xC0FB, 0x77B3, 0xC0FC, 0x77AA, + 0xC0FD, 0x77B0, 0xC0FE, 0x77AC, 0xC140, 0x77A7, 0xC141, 0x77AD, 0xC142, 0x77EF, 0xC143, 0x78F7, 0xC144, 0x78FA, 0xC145, 0x78F4, + 0xC146, 0x78EF, 0xC147, 0x7901, 0xC148, 0x79A7, 0xC149, 0x79AA, 0xC14A, 0x7A57, 0xC14B, 0x7ABF, 0xC14C, 0x7C07, 0xC14D, 0x7C0D, + 0xC14E, 0x7BFE, 0xC14F, 0x7BF7, 0xC150, 0x7C0C, 0xC151, 0x7BE0, 0xC152, 0x7CE0, 0xC153, 0x7CDC, 0xC154, 0x7CDE, 0xC155, 0x7CE2, + 0xC156, 0x7CDF, 0xC157, 0x7CD9, 0xC158, 0x7CDD, 0xC159, 0x7E2E, 0xC15A, 0x7E3E, 0xC15B, 0x7E46, 0xC15C, 0x7E37, 0xC15D, 0x7E32, + 0xC15E, 0x7E43, 0xC15F, 0x7E2B, 0xC160, 0x7E3D, 0xC161, 0x7E31, 0xC162, 0x7E45, 0xC163, 0x7E41, 0xC164, 0x7E34, 0xC165, 0x7E39, + 0xC166, 0x7E48, 0xC167, 0x7E35, 0xC168, 0x7E3F, 0xC169, 0x7E2F, 0xC16A, 0x7F44, 0xC16B, 0x7FF3, 0xC16C, 0x7FFC, 0xC16D, 0x8071, + 0xC16E, 0x8072, 0xC16F, 0x8070, 0xC170, 0x806F, 0xC171, 0x8073, 0xC172, 0x81C6, 0xC173, 0x81C3, 0xC174, 0x81BA, 0xC175, 0x81C2, + 0xC176, 0x81C0, 0xC177, 0x81BF, 0xC178, 0x81BD, 0xC179, 0x81C9, 0xC17A, 0x81BE, 0xC17B, 0x81E8, 0xC17C, 0x8209, 0xC17D, 0x8271, + 0xC17E, 0x85AA, 0xC1A1, 0x8584, 0xC1A2, 0x857E, 0xC1A3, 0x859C, 0xC1A4, 0x8591, 0xC1A5, 0x8594, 0xC1A6, 0x85AF, 0xC1A7, 0x859B, + 0xC1A8, 0x8587, 0xC1A9, 0x85A8, 0xC1AA, 0x858A, 0xC1AB, 0x8667, 0xC1AC, 0x87C0, 0xC1AD, 0x87D1, 0xC1AE, 0x87B3, 0xC1AF, 0x87D2, + 0xC1B0, 0x87C6, 0xC1B1, 0x87AB, 0xC1B2, 0x87BB, 0xC1B3, 0x87BA, 0xC1B4, 0x87C8, 0xC1B5, 0x87CB, 0xC1B6, 0x893B, 0xC1B7, 0x8936, + 0xC1B8, 0x8944, 0xC1B9, 0x8938, 0xC1BA, 0x893D, 0xC1BB, 0x89AC, 0xC1BC, 0x8B0E, 0xC1BD, 0x8B17, 0xC1BE, 0x8B19, 0xC1BF, 0x8B1B, + 0xC1C0, 0x8B0A, 0xC1C1, 0x8B20, 0xC1C2, 0x8B1D, 0xC1C3, 0x8B04, 0xC1C4, 0x8B10, 0xC1C5, 0x8C41, 0xC1C6, 0x8C3F, 0xC1C7, 0x8C73, + 0xC1C8, 0x8CFA, 0xC1C9, 0x8CFD, 0xC1CA, 0x8CFC, 0xC1CB, 0x8CF8, 0xC1CC, 0x8CFB, 0xC1CD, 0x8DA8, 0xC1CE, 0x8E49, 0xC1CF, 0x8E4B, + 0xC1D0, 0x8E48, 0xC1D1, 0x8E4A, 0xC1D2, 0x8F44, 0xC1D3, 0x8F3E, 0xC1D4, 0x8F42, 0xC1D5, 0x8F45, 0xC1D6, 0x8F3F, 0xC1D7, 0x907F, + 0xC1D8, 0x907D, 0xC1D9, 0x9084, 0xC1DA, 0x9081, 0xC1DB, 0x9082, 0xC1DC, 0x9080, 0xC1DD, 0x9139, 0xC1DE, 0x91A3, 0xC1DF, 0x919E, + 0xC1E0, 0x919C, 0xC1E1, 0x934D, 0xC1E2, 0x9382, 0xC1E3, 0x9328, 0xC1E4, 0x9375, 0xC1E5, 0x934A, 0xC1E6, 0x9365, 0xC1E7, 0x934B, + 0xC1E8, 0x9318, 0xC1E9, 0x937E, 0xC1EA, 0x936C, 0xC1EB, 0x935B, 0xC1EC, 0x9370, 0xC1ED, 0x935A, 0xC1EE, 0x9354, 0xC1EF, 0x95CA, + 0xC1F0, 0x95CB, 0xC1F1, 0x95CC, 0xC1F2, 0x95C8, 0xC1F3, 0x95C6, 0xC1F4, 0x96B1, 0xC1F5, 0x96B8, 0xC1F6, 0x96D6, 0xC1F7, 0x971C, + 0xC1F8, 0x971E, 0xC1F9, 0x97A0, 0xC1FA, 0x97D3, 0xC1FB, 0x9846, 0xC1FC, 0x98B6, 0xC1FD, 0x9935, 0xC1FE, 0x9A01, 0xC240, 0x99FF, + 0xC241, 0x9BAE, 0xC242, 0x9BAB, 0xC243, 0x9BAA, 0xC244, 0x9BAD, 0xC245, 0x9D3B, 0xC246, 0x9D3F, 0xC247, 0x9E8B, 0xC248, 0x9ECF, + 0xC249, 0x9EDE, 0xC24A, 0x9EDC, 0xC24B, 0x9EDD, 0xC24C, 0x9EDB, 0xC24D, 0x9F3E, 0xC24E, 0x9F4B, 0xC24F, 0x53E2, 0xC250, 0x5695, + 0xC251, 0x56AE, 0xC252, 0x58D9, 0xC253, 0x58D8, 0xC254, 0x5B38, 0xC255, 0x5F5D, 0xC256, 0x61E3, 0xC257, 0x6233, 0xC258, 0x64F4, + 0xC259, 0x64F2, 0xC25A, 0x64FE, 0xC25B, 0x6506, 0xC25C, 0x64FA, 0xC25D, 0x64FB, 0xC25E, 0x64F7, 0xC25F, 0x65B7, 0xC260, 0x66DC, + 0xC261, 0x6726, 0xC262, 0x6AB3, 0xC263, 0x6AAC, 0xC264, 0x6AC3, 0xC265, 0x6ABB, 0xC266, 0x6AB8, 0xC267, 0x6AC2, 0xC268, 0x6AAE, + 0xC269, 0x6AAF, 0xC26A, 0x6B5F, 0xC26B, 0x6B78, 0xC26C, 0x6BAF, 0xC26D, 0x7009, 0xC26E, 0x700B, 0xC26F, 0x6FFE, 0xC270, 0x7006, + 0xC271, 0x6FFA, 0xC272, 0x7011, 0xC273, 0x700F, 0xC274, 0x71FB, 0xC275, 0x71FC, 0xC276, 0x71FE, 0xC277, 0x71F8, 0xC278, 0x7377, + 0xC279, 0x7375, 0xC27A, 0x74A7, 0xC27B, 0x74BF, 0xC27C, 0x7515, 0xC27D, 0x7656, 0xC27E, 0x7658, 0xC2A1, 0x7652, 0xC2A2, 0x77BD, + 0xC2A3, 0x77BF, 0xC2A4, 0x77BB, 0xC2A5, 0x77BC, 0xC2A6, 0x790E, 0xC2A7, 0x79AE, 0xC2A8, 0x7A61, 0xC2A9, 0x7A62, 0xC2AA, 0x7A60, + 0xC2AB, 0x7AC4, 0xC2AC, 0x7AC5, 0xC2AD, 0x7C2B, 0xC2AE, 0x7C27, 0xC2AF, 0x7C2A, 0xC2B0, 0x7C1E, 0xC2B1, 0x7C23, 0xC2B2, 0x7C21, + 0xC2B3, 0x7CE7, 0xC2B4, 0x7E54, 0xC2B5, 0x7E55, 0xC2B6, 0x7E5E, 0xC2B7, 0x7E5A, 0xC2B8, 0x7E61, 0xC2B9, 0x7E52, 0xC2BA, 0x7E59, + 0xC2BB, 0x7F48, 0xC2BC, 0x7FF9, 0xC2BD, 0x7FFB, 0xC2BE, 0x8077, 0xC2BF, 0x8076, 0xC2C0, 0x81CD, 0xC2C1, 0x81CF, 0xC2C2, 0x820A, + 0xC2C3, 0x85CF, 0xC2C4, 0x85A9, 0xC2C5, 0x85CD, 0xC2C6, 0x85D0, 0xC2C7, 0x85C9, 0xC2C8, 0x85B0, 0xC2C9, 0x85BA, 0xC2CA, 0x85B9, + 0xC2CB, 0x85A6, 0xC2CC, 0x87EF, 0xC2CD, 0x87EC, 0xC2CE, 0x87F2, 0xC2CF, 0x87E0, 0xC2D0, 0x8986, 0xC2D1, 0x89B2, 0xC2D2, 0x89F4, + 0xC2D3, 0x8B28, 0xC2D4, 0x8B39, 0xC2D5, 0x8B2C, 0xC2D6, 0x8B2B, 0xC2D7, 0x8C50, 0xC2D8, 0x8D05, 0xC2D9, 0x8E59, 0xC2DA, 0x8E63, + 0xC2DB, 0x8E66, 0xC2DC, 0x8E64, 0xC2DD, 0x8E5F, 0xC2DE, 0x8E55, 0xC2DF, 0x8EC0, 0xC2E0, 0x8F49, 0xC2E1, 0x8F4D, 0xC2E2, 0x9087, + 0xC2E3, 0x9083, 0xC2E4, 0x9088, 0xC2E5, 0x91AB, 0xC2E6, 0x91AC, 0xC2E7, 0x91D0, 0xC2E8, 0x9394, 0xC2E9, 0x938A, 0xC2EA, 0x9396, + 0xC2EB, 0x93A2, 0xC2EC, 0x93B3, 0xC2ED, 0x93AE, 0xC2EE, 0x93AC, 0xC2EF, 0x93B0, 0xC2F0, 0x9398, 0xC2F1, 0x939A, 0xC2F2, 0x9397, + 0xC2F3, 0x95D4, 0xC2F4, 0x95D6, 0xC2F5, 0x95D0, 0xC2F6, 0x95D5, 0xC2F7, 0x96E2, 0xC2F8, 0x96DC, 0xC2F9, 0x96D9, 0xC2FA, 0x96DB, + 0xC2FB, 0x96DE, 0xC2FC, 0x9724, 0xC2FD, 0x97A3, 0xC2FE, 0x97A6, 0xC340, 0x97AD, 0xC341, 0x97F9, 0xC342, 0x984D, 0xC343, 0x984F, + 0xC344, 0x984C, 0xC345, 0x984E, 0xC346, 0x9853, 0xC347, 0x98BA, 0xC348, 0x993E, 0xC349, 0x993F, 0xC34A, 0x993D, 0xC34B, 0x992E, + 0xC34C, 0x99A5, 0xC34D, 0x9A0E, 0xC34E, 0x9AC1, 0xC34F, 0x9B03, 0xC350, 0x9B06, 0xC351, 0x9B4F, 0xC352, 0x9B4E, 0xC353, 0x9B4D, + 0xC354, 0x9BCA, 0xC355, 0x9BC9, 0xC356, 0x9BFD, 0xC357, 0x9BC8, 0xC358, 0x9BC0, 0xC359, 0x9D51, 0xC35A, 0x9D5D, 0xC35B, 0x9D60, + 0xC35C, 0x9EE0, 0xC35D, 0x9F15, 0xC35E, 0x9F2C, 0xC35F, 0x5133, 0xC360, 0x56A5, 0xC361, 0x58DE, 0xC362, 0x58DF, 0xC363, 0x58E2, + 0xC364, 0x5BF5, 0xC365, 0x9F90, 0xC366, 0x5EEC, 0xC367, 0x61F2, 0xC368, 0x61F7, 0xC369, 0x61F6, 0xC36A, 0x61F5, 0xC36B, 0x6500, + 0xC36C, 0x650F, 0xC36D, 0x66E0, 0xC36E, 0x66DD, 0xC36F, 0x6AE5, 0xC370, 0x6ADD, 0xC371, 0x6ADA, 0xC372, 0x6AD3, 0xC373, 0x701B, + 0xC374, 0x701F, 0xC375, 0x7028, 0xC376, 0x701A, 0xC377, 0x701D, 0xC378, 0x7015, 0xC379, 0x7018, 0xC37A, 0x7206, 0xC37B, 0x720D, + 0xC37C, 0x7258, 0xC37D, 0x72A2, 0xC37E, 0x7378, 0xC3A1, 0x737A, 0xC3A2, 0x74BD, 0xC3A3, 0x74CA, 0xC3A4, 0x74E3, 0xC3A5, 0x7587, + 0xC3A6, 0x7586, 0xC3A7, 0x765F, 0xC3A8, 0x7661, 0xC3A9, 0x77C7, 0xC3AA, 0x7919, 0xC3AB, 0x79B1, 0xC3AC, 0x7A6B, 0xC3AD, 0x7A69, + 0xC3AE, 0x7C3E, 0xC3AF, 0x7C3F, 0xC3B0, 0x7C38, 0xC3B1, 0x7C3D, 0xC3B2, 0x7C37, 0xC3B3, 0x7C40, 0xC3B4, 0x7E6B, 0xC3B5, 0x7E6D, + 0xC3B6, 0x7E79, 0xC3B7, 0x7E69, 0xC3B8, 0x7E6A, 0xC3B9, 0x7F85, 0xC3BA, 0x7E73, 0xC3BB, 0x7FB6, 0xC3BC, 0x7FB9, 0xC3BD, 0x7FB8, + 0xC3BE, 0x81D8, 0xC3BF, 0x85E9, 0xC3C0, 0x85DD, 0xC3C1, 0x85EA, 0xC3C2, 0x85D5, 0xC3C3, 0x85E4, 0xC3C4, 0x85E5, 0xC3C5, 0x85F7, + 0xC3C6, 0x87FB, 0xC3C7, 0x8805, 0xC3C8, 0x880D, 0xC3C9, 0x87F9, 0xC3CA, 0x87FE, 0xC3CB, 0x8960, 0xC3CC, 0x895F, 0xC3CD, 0x8956, + 0xC3CE, 0x895E, 0xC3CF, 0x8B41, 0xC3D0, 0x8B5C, 0xC3D1, 0x8B58, 0xC3D2, 0x8B49, 0xC3D3, 0x8B5A, 0xC3D4, 0x8B4E, 0xC3D5, 0x8B4F, + 0xC3D6, 0x8B46, 0xC3D7, 0x8B59, 0xC3D8, 0x8D08, 0xC3D9, 0x8D0A, 0xC3DA, 0x8E7C, 0xC3DB, 0x8E72, 0xC3DC, 0x8E87, 0xC3DD, 0x8E76, + 0xC3DE, 0x8E6C, 0xC3DF, 0x8E7A, 0xC3E0, 0x8E74, 0xC3E1, 0x8F54, 0xC3E2, 0x8F4E, 0xC3E3, 0x8FAD, 0xC3E4, 0x908A, 0xC3E5, 0x908B, + 0xC3E6, 0x91B1, 0xC3E7, 0x91AE, 0xC3E8, 0x93E1, 0xC3E9, 0x93D1, 0xC3EA, 0x93DF, 0xC3EB, 0x93C3, 0xC3EC, 0x93C8, 0xC3ED, 0x93DC, + 0xC3EE, 0x93DD, 0xC3EF, 0x93D6, 0xC3F0, 0x93E2, 0xC3F1, 0x93CD, 0xC3F2, 0x93D8, 0xC3F3, 0x93E4, 0xC3F4, 0x93D7, 0xC3F5, 0x93E8, + 0xC3F6, 0x95DC, 0xC3F7, 0x96B4, 0xC3F8, 0x96E3, 0xC3F9, 0x972A, 0xC3FA, 0x9727, 0xC3FB, 0x9761, 0xC3FC, 0x97DC, 0xC3FD, 0x97FB, + 0xC3FE, 0x985E, 0xC440, 0x9858, 0xC441, 0x985B, 0xC442, 0x98BC, 0xC443, 0x9945, 0xC444, 0x9949, 0xC445, 0x9A16, 0xC446, 0x9A19, + 0xC447, 0x9B0D, 0xC448, 0x9BE8, 0xC449, 0x9BE7, 0xC44A, 0x9BD6, 0xC44B, 0x9BDB, 0xC44C, 0x9D89, 0xC44D, 0x9D61, 0xC44E, 0x9D72, + 0xC44F, 0x9D6A, 0xC450, 0x9D6C, 0xC451, 0x9E92, 0xC452, 0x9E97, 0xC453, 0x9E93, 0xC454, 0x9EB4, 0xC455, 0x52F8, 0xC456, 0x56A8, + 0xC457, 0x56B7, 0xC458, 0x56B6, 0xC459, 0x56B4, 0xC45A, 0x56BC, 0xC45B, 0x58E4, 0xC45C, 0x5B40, 0xC45D, 0x5B43, 0xC45E, 0x5B7D, + 0xC45F, 0x5BF6, 0xC460, 0x5DC9, 0xC461, 0x61F8, 0xC462, 0x61FA, 0xC463, 0x6518, 0xC464, 0x6514, 0xC465, 0x6519, 0xC466, 0x66E6, + 0xC467, 0x6727, 0xC468, 0x6AEC, 0xC469, 0x703E, 0xC46A, 0x7030, 0xC46B, 0x7032, 0xC46C, 0x7210, 0xC46D, 0x737B, 0xC46E, 0x74CF, + 0xC46F, 0x7662, 0xC470, 0x7665, 0xC471, 0x7926, 0xC472, 0x792A, 0xC473, 0x792C, 0xC474, 0x792B, 0xC475, 0x7AC7, 0xC476, 0x7AF6, + 0xC477, 0x7C4C, 0xC478, 0x7C43, 0xC479, 0x7C4D, 0xC47A, 0x7CEF, 0xC47B, 0x7CF0, 0xC47C, 0x8FAE, 0xC47D, 0x7E7D, 0xC47E, 0x7E7C, + 0xC4A1, 0x7E82, 0xC4A2, 0x7F4C, 0xC4A3, 0x8000, 0xC4A4, 0x81DA, 0xC4A5, 0x8266, 0xC4A6, 0x85FB, 0xC4A7, 0x85F9, 0xC4A8, 0x8611, + 0xC4A9, 0x85FA, 0xC4AA, 0x8606, 0xC4AB, 0x860B, 0xC4AC, 0x8607, 0xC4AD, 0x860A, 0xC4AE, 0x8814, 0xC4AF, 0x8815, 0xC4B0, 0x8964, + 0xC4B1, 0x89BA, 0xC4B2, 0x89F8, 0xC4B3, 0x8B70, 0xC4B4, 0x8B6C, 0xC4B5, 0x8B66, 0xC4B6, 0x8B6F, 0xC4B7, 0x8B5F, 0xC4B8, 0x8B6B, + 0xC4B9, 0x8D0F, 0xC4BA, 0x8D0D, 0xC4BB, 0x8E89, 0xC4BC, 0x8E81, 0xC4BD, 0x8E85, 0xC4BE, 0x8E82, 0xC4BF, 0x91B4, 0xC4C0, 0x91CB, + 0xC4C1, 0x9418, 0xC4C2, 0x9403, 0xC4C3, 0x93FD, 0xC4C4, 0x95E1, 0xC4C5, 0x9730, 0xC4C6, 0x98C4, 0xC4C7, 0x9952, 0xC4C8, 0x9951, + 0xC4C9, 0x99A8, 0xC4CA, 0x9A2B, 0xC4CB, 0x9A30, 0xC4CC, 0x9A37, 0xC4CD, 0x9A35, 0xC4CE, 0x9C13, 0xC4CF, 0x9C0D, 0xC4D0, 0x9E79, + 0xC4D1, 0x9EB5, 0xC4D2, 0x9EE8, 0xC4D3, 0x9F2F, 0xC4D4, 0x9F5F, 0xC4D5, 0x9F63, 0xC4D6, 0x9F61, 0xC4D7, 0x5137, 0xC4D8, 0x5138, + 0xC4D9, 0x56C1, 0xC4DA, 0x56C0, 0xC4DB, 0x56C2, 0xC4DC, 0x5914, 0xC4DD, 0x5C6C, 0xC4DE, 0x5DCD, 0xC4DF, 0x61FC, 0xC4E0, 0x61FE, + 0xC4E1, 0x651D, 0xC4E2, 0x651C, 0xC4E3, 0x6595, 0xC4E4, 0x66E9, 0xC4E5, 0x6AFB, 0xC4E6, 0x6B04, 0xC4E7, 0x6AFA, 0xC4E8, 0x6BB2, + 0xC4E9, 0x704C, 0xC4EA, 0x721B, 0xC4EB, 0x72A7, 0xC4EC, 0x74D6, 0xC4ED, 0x74D4, 0xC4EE, 0x7669, 0xC4EF, 0x77D3, 0xC4F0, 0x7C50, + 0xC4F1, 0x7E8F, 0xC4F2, 0x7E8C, 0xC4F3, 0x7FBC, 0xC4F4, 0x8617, 0xC4F5, 0x862D, 0xC4F6, 0x861A, 0xC4F7, 0x8823, 0xC4F8, 0x8822, + 0xC4F9, 0x8821, 0xC4FA, 0x881F, 0xC4FB, 0x896A, 0xC4FC, 0x896C, 0xC4FD, 0x89BD, 0xC4FE, 0x8B74, 0xC540, 0x8B77, 0xC541, 0x8B7D, + 0xC542, 0x8D13, 0xC543, 0x8E8A, 0xC544, 0x8E8D, 0xC545, 0x8E8B, 0xC546, 0x8F5F, 0xC547, 0x8FAF, 0xC548, 0x91BA, 0xC549, 0x942E, + 0xC54A, 0x9433, 0xC54B, 0x9435, 0xC54C, 0x943A, 0xC54D, 0x9438, 0xC54E, 0x9432, 0xC54F, 0x942B, 0xC550, 0x95E2, 0xC551, 0x9738, + 0xC552, 0x9739, 0xC553, 0x9732, 0xC554, 0x97FF, 0xC555, 0x9867, 0xC556, 0x9865, 0xC557, 0x9957, 0xC558, 0x9A45, 0xC559, 0x9A43, + 0xC55A, 0x9A40, 0xC55B, 0x9A3E, 0xC55C, 0x9ACF, 0xC55D, 0x9B54, 0xC55E, 0x9B51, 0xC55F, 0x9C2D, 0xC560, 0x9C25, 0xC561, 0x9DAF, + 0xC562, 0x9DB4, 0xC563, 0x9DC2, 0xC564, 0x9DB8, 0xC565, 0x9E9D, 0xC566, 0x9EEF, 0xC567, 0x9F19, 0xC568, 0x9F5C, 0xC569, 0x9F66, + 0xC56A, 0x9F67, 0xC56B, 0x513C, 0xC56C, 0x513B, 0xC56D, 0x56C8, 0xC56E, 0x56CA, 0xC56F, 0x56C9, 0xC570, 0x5B7F, 0xC571, 0x5DD4, + 0xC572, 0x5DD2, 0xC573, 0x5F4E, 0xC574, 0x61FF, 0xC575, 0x6524, 0xC576, 0x6B0A, 0xC577, 0x6B61, 0xC578, 0x7051, 0xC579, 0x7058, + 0xC57A, 0x7380, 0xC57B, 0x74E4, 0xC57C, 0x758A, 0xC57D, 0x766E, 0xC57E, 0x766C, 0xC5A1, 0x79B3, 0xC5A2, 0x7C60, 0xC5A3, 0x7C5F, + 0xC5A4, 0x807E, 0xC5A5, 0x807D, 0xC5A6, 0x81DF, 0xC5A7, 0x8972, 0xC5A8, 0x896F, 0xC5A9, 0x89FC, 0xC5AA, 0x8B80, 0xC5AB, 0x8D16, + 0xC5AC, 0x8D17, 0xC5AD, 0x8E91, 0xC5AE, 0x8E93, 0xC5AF, 0x8F61, 0xC5B0, 0x9148, 0xC5B1, 0x9444, 0xC5B2, 0x9451, 0xC5B3, 0x9452, + 0xC5B4, 0x973D, 0xC5B5, 0x973E, 0xC5B6, 0x97C3, 0xC5B7, 0x97C1, 0xC5B8, 0x986B, 0xC5B9, 0x9955, 0xC5BA, 0x9A55, 0xC5BB, 0x9A4D, + 0xC5BC, 0x9AD2, 0xC5BD, 0x9B1A, 0xC5BE, 0x9C49, 0xC5BF, 0x9C31, 0xC5C0, 0x9C3E, 0xC5C1, 0x9C3B, 0xC5C2, 0x9DD3, 0xC5C3, 0x9DD7, + 0xC5C4, 0x9F34, 0xC5C5, 0x9F6C, 0xC5C6, 0x9F6A, 0xC5C7, 0x9F94, 0xC5C8, 0x56CC, 0xC5C9, 0x5DD6, 0xC5CA, 0x6200, 0xC5CB, 0x6523, + 0xC5CC, 0x652B, 0xC5CD, 0x652A, 0xC5CE, 0x66EC, 0xC5CF, 0x6B10, 0xC5D0, 0x74DA, 0xC5D1, 0x7ACA, 0xC5D2, 0x7C64, 0xC5D3, 0x7C63, + 0xC5D4, 0x7C65, 0xC5D5, 0x7E93, 0xC5D6, 0x7E96, 0xC5D7, 0x7E94, 0xC5D8, 0x81E2, 0xC5D9, 0x8638, 0xC5DA, 0x863F, 0xC5DB, 0x8831, + 0xC5DC, 0x8B8A, 0xC5DD, 0x9090, 0xC5DE, 0x908F, 0xC5DF, 0x9463, 0xC5E0, 0x9460, 0xC5E1, 0x9464, 0xC5E2, 0x9768, 0xC5E3, 0x986F, + 0xC5E4, 0x995C, 0xC5E5, 0x9A5A, 0xC5E6, 0x9A5B, 0xC5E7, 0x9A57, 0xC5E8, 0x9AD3, 0xC5E9, 0x9AD4, 0xC5EA, 0x9AD1, 0xC5EB, 0x9C54, + 0xC5EC, 0x9C57, 0xC5ED, 0x9C56, 0xC5EE, 0x9DE5, 0xC5EF, 0x9E9F, 0xC5F0, 0x9EF4, 0xC5F1, 0x56D1, 0xC5F2, 0x58E9, 0xC5F3, 0x652C, + 0xC5F4, 0x705E, 0xC5F5, 0x7671, 0xC5F6, 0x7672, 0xC5F7, 0x77D7, 0xC5F8, 0x7F50, 0xC5F9, 0x7F88, 0xC5FA, 0x8836, 0xC5FB, 0x8839, + 0xC5FC, 0x8862, 0xC5FD, 0x8B93, 0xC5FE, 0x8B92, 0xC640, 0x8B96, 0xC641, 0x8277, 0xC642, 0x8D1B, 0xC643, 0x91C0, 0xC644, 0x946A, + 0xC645, 0x9742, 0xC646, 0x9748, 0xC647, 0x9744, 0xC648, 0x97C6, 0xC649, 0x9870, 0xC64A, 0x9A5F, 0xC64B, 0x9B22, 0xC64C, 0x9B58, + 0xC64D, 0x9C5F, 0xC64E, 0x9DF9, 0xC64F, 0x9DFA, 0xC650, 0x9E7C, 0xC651, 0x9E7D, 0xC652, 0x9F07, 0xC653, 0x9F77, 0xC654, 0x9F72, + 0xC655, 0x5EF3, 0xC656, 0x6B16, 0xC657, 0x7063, 0xC658, 0x7C6C, 0xC659, 0x7C6E, 0xC65A, 0x883B, 0xC65B, 0x89C0, 0xC65C, 0x8EA1, + 0xC65D, 0x91C1, 0xC65E, 0x9472, 0xC65F, 0x9470, 0xC660, 0x9871, 0xC661, 0x995E, 0xC662, 0x9AD6, 0xC663, 0x9B23, 0xC664, 0x9ECC, + 0xC665, 0x7064, 0xC666, 0x77DA, 0xC667, 0x8B9A, 0xC668, 0x9477, 0xC669, 0x97C9, 0xC66A, 0x9A62, 0xC66B, 0x9A65, 0xC66C, 0x7E9C, + 0xC66D, 0x8B9C, 0xC66E, 0x8EAA, 0xC66F, 0x91C5, 0xC670, 0x947D, 0xC671, 0x947E, 0xC672, 0x947C, 0xC673, 0x9C77, 0xC674, 0x9C78, + 0xC675, 0x9EF7, 0xC676, 0x8C54, 0xC677, 0x947F, 0xC678, 0x9E1A, 0xC679, 0x7228, 0xC67A, 0x9A6A, 0xC67B, 0x9B31, 0xC67C, 0x9E1B, + 0xC67D, 0x9E1E, 0xC67E, 0x7C72, 0xC940, 0x4E42, 0xC941, 0x4E5C, 0xC942, 0x51F5, 0xC943, 0x531A, 0xC944, 0x5382, 0xC945, 0x4E07, + 0xC946, 0x4E0C, 0xC947, 0x4E47, 0xC948, 0x4E8D, 0xC949, 0x56D7, 0xC94A, 0xFA0C, 0xC94B, 0x5C6E, 0xC94C, 0x5F73, 0xC94D, 0x4E0F, + 0xC94E, 0x5187, 0xC94F, 0x4E0E, 0xC950, 0x4E2E, 0xC951, 0x4E93, 0xC952, 0x4EC2, 0xC953, 0x4EC9, 0xC954, 0x4EC8, 0xC955, 0x5198, + 0xC956, 0x52FC, 0xC957, 0x536C, 0xC958, 0x53B9, 0xC959, 0x5720, 0xC95A, 0x5903, 0xC95B, 0x592C, 0xC95C, 0x5C10, 0xC95D, 0x5DFF, + 0xC95E, 0x65E1, 0xC95F, 0x6BB3, 0xC960, 0x6BCC, 0xC961, 0x6C14, 0xC962, 0x723F, 0xC963, 0x4E31, 0xC964, 0x4E3C, 0xC965, 0x4EE8, + 0xC966, 0x4EDC, 0xC967, 0x4EE9, 0xC968, 0x4EE1, 0xC969, 0x4EDD, 0xC96A, 0x4EDA, 0xC96B, 0x520C, 0xC96C, 0x531C, 0xC96D, 0x534C, + 0xC96E, 0x5722, 0xC96F, 0x5723, 0xC970, 0x5917, 0xC971, 0x592F, 0xC972, 0x5B81, 0xC973, 0x5B84, 0xC974, 0x5C12, 0xC975, 0x5C3B, + 0xC976, 0x5C74, 0xC977, 0x5C73, 0xC978, 0x5E04, 0xC979, 0x5E80, 0xC97A, 0x5E82, 0xC97B, 0x5FC9, 0xC97C, 0x6209, 0xC97D, 0x6250, + 0xC97E, 0x6C15, 0xC9A1, 0x6C36, 0xC9A2, 0x6C43, 0xC9A3, 0x6C3F, 0xC9A4, 0x6C3B, 0xC9A5, 0x72AE, 0xC9A6, 0x72B0, 0xC9A7, 0x738A, + 0xC9A8, 0x79B8, 0xC9A9, 0x808A, 0xC9AA, 0x961E, 0xC9AB, 0x4F0E, 0xC9AC, 0x4F18, 0xC9AD, 0x4F2C, 0xC9AE, 0x4EF5, 0xC9AF, 0x4F14, + 0xC9B0, 0x4EF1, 0xC9B1, 0x4F00, 0xC9B2, 0x4EF7, 0xC9B3, 0x4F08, 0xC9B4, 0x4F1D, 0xC9B5, 0x4F02, 0xC9B6, 0x4F05, 0xC9B7, 0x4F22, + 0xC9B8, 0x4F13, 0xC9B9, 0x4F04, 0xC9BA, 0x4EF4, 0xC9BB, 0x4F12, 0xC9BC, 0x51B1, 0xC9BD, 0x5213, 0xC9BE, 0x5209, 0xC9BF, 0x5210, + 0xC9C0, 0x52A6, 0xC9C1, 0x5322, 0xC9C2, 0x531F, 0xC9C3, 0x534D, 0xC9C4, 0x538A, 0xC9C5, 0x5407, 0xC9C6, 0x56E1, 0xC9C7, 0x56DF, + 0xC9C8, 0x572E, 0xC9C9, 0x572A, 0xC9CA, 0x5734, 0xC9CB, 0x593C, 0xC9CC, 0x5980, 0xC9CD, 0x597C, 0xC9CE, 0x5985, 0xC9CF, 0x597B, + 0xC9D0, 0x597E, 0xC9D1, 0x5977, 0xC9D2, 0x597F, 0xC9D3, 0x5B56, 0xC9D4, 0x5C15, 0xC9D5, 0x5C25, 0xC9D6, 0x5C7C, 0xC9D7, 0x5C7A, + 0xC9D8, 0x5C7B, 0xC9D9, 0x5C7E, 0xC9DA, 0x5DDF, 0xC9DB, 0x5E75, 0xC9DC, 0x5E84, 0xC9DD, 0x5F02, 0xC9DE, 0x5F1A, 0xC9DF, 0x5F74, + 0xC9E0, 0x5FD5, 0xC9E1, 0x5FD4, 0xC9E2, 0x5FCF, 0xC9E3, 0x625C, 0xC9E4, 0x625E, 0xC9E5, 0x6264, 0xC9E6, 0x6261, 0xC9E7, 0x6266, + 0xC9E8, 0x6262, 0xC9E9, 0x6259, 0xC9EA, 0x6260, 0xC9EB, 0x625A, 0xC9EC, 0x6265, 0xC9ED, 0x65EF, 0xC9EE, 0x65EE, 0xC9EF, 0x673E, + 0xC9F0, 0x6739, 0xC9F1, 0x6738, 0xC9F2, 0x673B, 0xC9F3, 0x673A, 0xC9F4, 0x673F, 0xC9F5, 0x673C, 0xC9F6, 0x6733, 0xC9F7, 0x6C18, + 0xC9F8, 0x6C46, 0xC9F9, 0x6C52, 0xC9FA, 0x6C5C, 0xC9FB, 0x6C4F, 0xC9FC, 0x6C4A, 0xC9FD, 0x6C54, 0xC9FE, 0x6C4B, 0xCA40, 0x6C4C, + 0xCA41, 0x7071, 0xCA42, 0x725E, 0xCA43, 0x72B4, 0xCA44, 0x72B5, 0xCA45, 0x738E, 0xCA46, 0x752A, 0xCA47, 0x767F, 0xCA48, 0x7A75, + 0xCA49, 0x7F51, 0xCA4A, 0x8278, 0xCA4B, 0x827C, 0xCA4C, 0x8280, 0xCA4D, 0x827D, 0xCA4E, 0x827F, 0xCA4F, 0x864D, 0xCA50, 0x897E, + 0xCA51, 0x9099, 0xCA52, 0x9097, 0xCA53, 0x9098, 0xCA54, 0x909B, 0xCA55, 0x9094, 0xCA56, 0x9622, 0xCA57, 0x9624, 0xCA58, 0x9620, + 0xCA59, 0x9623, 0xCA5A, 0x4F56, 0xCA5B, 0x4F3B, 0xCA5C, 0x4F62, 0xCA5D, 0x4F49, 0xCA5E, 0x4F53, 0xCA5F, 0x4F64, 0xCA60, 0x4F3E, + 0xCA61, 0x4F67, 0xCA62, 0x4F52, 0xCA63, 0x4F5F, 0xCA64, 0x4F41, 0xCA65, 0x4F58, 0xCA66, 0x4F2D, 0xCA67, 0x4F33, 0xCA68, 0x4F3F, + 0xCA69, 0x4F61, 0xCA6A, 0x518F, 0xCA6B, 0x51B9, 0xCA6C, 0x521C, 0xCA6D, 0x521E, 0xCA6E, 0x5221, 0xCA6F, 0x52AD, 0xCA70, 0x52AE, + 0xCA71, 0x5309, 0xCA72, 0x5363, 0xCA73, 0x5372, 0xCA74, 0x538E, 0xCA75, 0x538F, 0xCA76, 0x5430, 0xCA77, 0x5437, 0xCA78, 0x542A, + 0xCA79, 0x5454, 0xCA7A, 0x5445, 0xCA7B, 0x5419, 0xCA7C, 0x541C, 0xCA7D, 0x5425, 0xCA7E, 0x5418, 0xCAA1, 0x543D, 0xCAA2, 0x544F, + 0xCAA3, 0x5441, 0xCAA4, 0x5428, 0xCAA5, 0x5424, 0xCAA6, 0x5447, 0xCAA7, 0x56EE, 0xCAA8, 0x56E7, 0xCAA9, 0x56E5, 0xCAAA, 0x5741, + 0xCAAB, 0x5745, 0xCAAC, 0x574C, 0xCAAD, 0x5749, 0xCAAE, 0x574B, 0xCAAF, 0x5752, 0xCAB0, 0x5906, 0xCAB1, 0x5940, 0xCAB2, 0x59A6, + 0xCAB3, 0x5998, 0xCAB4, 0x59A0, 0xCAB5, 0x5997, 0xCAB6, 0x598E, 0xCAB7, 0x59A2, 0xCAB8, 0x5990, 0xCAB9, 0x598F, 0xCABA, 0x59A7, + 0xCABB, 0x59A1, 0xCABC, 0x5B8E, 0xCABD, 0x5B92, 0xCABE, 0x5C28, 0xCABF, 0x5C2A, 0xCAC0, 0x5C8D, 0xCAC1, 0x5C8F, 0xCAC2, 0x5C88, + 0xCAC3, 0x5C8B, 0xCAC4, 0x5C89, 0xCAC5, 0x5C92, 0xCAC6, 0x5C8A, 0xCAC7, 0x5C86, 0xCAC8, 0x5C93, 0xCAC9, 0x5C95, 0xCACA, 0x5DE0, + 0xCACB, 0x5E0A, 0xCACC, 0x5E0E, 0xCACD, 0x5E8B, 0xCACE, 0x5E89, 0xCACF, 0x5E8C, 0xCAD0, 0x5E88, 0xCAD1, 0x5E8D, 0xCAD2, 0x5F05, + 0xCAD3, 0x5F1D, 0xCAD4, 0x5F78, 0xCAD5, 0x5F76, 0xCAD6, 0x5FD2, 0xCAD7, 0x5FD1, 0xCAD8, 0x5FD0, 0xCAD9, 0x5FED, 0xCADA, 0x5FE8, + 0xCADB, 0x5FEE, 0xCADC, 0x5FF3, 0xCADD, 0x5FE1, 0xCADE, 0x5FE4, 0xCADF, 0x5FE3, 0xCAE0, 0x5FFA, 0xCAE1, 0x5FEF, 0xCAE2, 0x5FF7, + 0xCAE3, 0x5FFB, 0xCAE4, 0x6000, 0xCAE5, 0x5FF4, 0xCAE6, 0x623A, 0xCAE7, 0x6283, 0xCAE8, 0x628C, 0xCAE9, 0x628E, 0xCAEA, 0x628F, + 0xCAEB, 0x6294, 0xCAEC, 0x6287, 0xCAED, 0x6271, 0xCAEE, 0x627B, 0xCAEF, 0x627A, 0xCAF0, 0x6270, 0xCAF1, 0x6281, 0xCAF2, 0x6288, + 0xCAF3, 0x6277, 0xCAF4, 0x627D, 0xCAF5, 0x6272, 0xCAF6, 0x6274, 0xCAF7, 0x6537, 0xCAF8, 0x65F0, 0xCAF9, 0x65F4, 0xCAFA, 0x65F3, + 0xCAFB, 0x65F2, 0xCAFC, 0x65F5, 0xCAFD, 0x6745, 0xCAFE, 0x6747, 0xCB40, 0x6759, 0xCB41, 0x6755, 0xCB42, 0x674C, 0xCB43, 0x6748, + 0xCB44, 0x675D, 0xCB45, 0x674D, 0xCB46, 0x675A, 0xCB47, 0x674B, 0xCB48, 0x6BD0, 0xCB49, 0x6C19, 0xCB4A, 0x6C1A, 0xCB4B, 0x6C78, + 0xCB4C, 0x6C67, 0xCB4D, 0x6C6B, 0xCB4E, 0x6C84, 0xCB4F, 0x6C8B, 0xCB50, 0x6C8F, 0xCB51, 0x6C71, 0xCB52, 0x6C6F, 0xCB53, 0x6C69, + 0xCB54, 0x6C9A, 0xCB55, 0x6C6D, 0xCB56, 0x6C87, 0xCB57, 0x6C95, 0xCB58, 0x6C9C, 0xCB59, 0x6C66, 0xCB5A, 0x6C73, 0xCB5B, 0x6C65, + 0xCB5C, 0x6C7B, 0xCB5D, 0x6C8E, 0xCB5E, 0x7074, 0xCB5F, 0x707A, 0xCB60, 0x7263, 0xCB61, 0x72BF, 0xCB62, 0x72BD, 0xCB63, 0x72C3, + 0xCB64, 0x72C6, 0xCB65, 0x72C1, 0xCB66, 0x72BA, 0xCB67, 0x72C5, 0xCB68, 0x7395, 0xCB69, 0x7397, 0xCB6A, 0x7393, 0xCB6B, 0x7394, + 0xCB6C, 0x7392, 0xCB6D, 0x753A, 0xCB6E, 0x7539, 0xCB6F, 0x7594, 0xCB70, 0x7595, 0xCB71, 0x7681, 0xCB72, 0x793D, 0xCB73, 0x8034, + 0xCB74, 0x8095, 0xCB75, 0x8099, 0xCB76, 0x8090, 0xCB77, 0x8092, 0xCB78, 0x809C, 0xCB79, 0x8290, 0xCB7A, 0x828F, 0xCB7B, 0x8285, + 0xCB7C, 0x828E, 0xCB7D, 0x8291, 0xCB7E, 0x8293, 0xCBA1, 0x828A, 0xCBA2, 0x8283, 0xCBA3, 0x8284, 0xCBA4, 0x8C78, 0xCBA5, 0x8FC9, + 0xCBA6, 0x8FBF, 0xCBA7, 0x909F, 0xCBA8, 0x90A1, 0xCBA9, 0x90A5, 0xCBAA, 0x909E, 0xCBAB, 0x90A7, 0xCBAC, 0x90A0, 0xCBAD, 0x9630, + 0xCBAE, 0x9628, 0xCBAF, 0x962F, 0xCBB0, 0x962D, 0xCBB1, 0x4E33, 0xCBB2, 0x4F98, 0xCBB3, 0x4F7C, 0xCBB4, 0x4F85, 0xCBB5, 0x4F7D, + 0xCBB6, 0x4F80, 0xCBB7, 0x4F87, 0xCBB8, 0x4F76, 0xCBB9, 0x4F74, 0xCBBA, 0x4F89, 0xCBBB, 0x4F84, 0xCBBC, 0x4F77, 0xCBBD, 0x4F4C, + 0xCBBE, 0x4F97, 0xCBBF, 0x4F6A, 0xCBC0, 0x4F9A, 0xCBC1, 0x4F79, 0xCBC2, 0x4F81, 0xCBC3, 0x4F78, 0xCBC4, 0x4F90, 0xCBC5, 0x4F9C, + 0xCBC6, 0x4F94, 0xCBC7, 0x4F9E, 0xCBC8, 0x4F92, 0xCBC9, 0x4F82, 0xCBCA, 0x4F95, 0xCBCB, 0x4F6B, 0xCBCC, 0x4F6E, 0xCBCD, 0x519E, + 0xCBCE, 0x51BC, 0xCBCF, 0x51BE, 0xCBD0, 0x5235, 0xCBD1, 0x5232, 0xCBD2, 0x5233, 0xCBD3, 0x5246, 0xCBD4, 0x5231, 0xCBD5, 0x52BC, + 0xCBD6, 0x530A, 0xCBD7, 0x530B, 0xCBD8, 0x533C, 0xCBD9, 0x5392, 0xCBDA, 0x5394, 0xCBDB, 0x5487, 0xCBDC, 0x547F, 0xCBDD, 0x5481, + 0xCBDE, 0x5491, 0xCBDF, 0x5482, 0xCBE0, 0x5488, 0xCBE1, 0x546B, 0xCBE2, 0x547A, 0xCBE3, 0x547E, 0xCBE4, 0x5465, 0xCBE5, 0x546C, + 0xCBE6, 0x5474, 0xCBE7, 0x5466, 0xCBE8, 0x548D, 0xCBE9, 0x546F, 0xCBEA, 0x5461, 0xCBEB, 0x5460, 0xCBEC, 0x5498, 0xCBED, 0x5463, + 0xCBEE, 0x5467, 0xCBEF, 0x5464, 0xCBF0, 0x56F7, 0xCBF1, 0x56F9, 0xCBF2, 0x576F, 0xCBF3, 0x5772, 0xCBF4, 0x576D, 0xCBF5, 0x576B, + 0xCBF6, 0x5771, 0xCBF7, 0x5770, 0xCBF8, 0x5776, 0xCBF9, 0x5780, 0xCBFA, 0x5775, 0xCBFB, 0x577B, 0xCBFC, 0x5773, 0xCBFD, 0x5774, + 0xCBFE, 0x5762, 0xCC40, 0x5768, 0xCC41, 0x577D, 0xCC42, 0x590C, 0xCC43, 0x5945, 0xCC44, 0x59B5, 0xCC45, 0x59BA, 0xCC46, 0x59CF, + 0xCC47, 0x59CE, 0xCC48, 0x59B2, 0xCC49, 0x59CC, 0xCC4A, 0x59C1, 0xCC4B, 0x59B6, 0xCC4C, 0x59BC, 0xCC4D, 0x59C3, 0xCC4E, 0x59D6, + 0xCC4F, 0x59B1, 0xCC50, 0x59BD, 0xCC51, 0x59C0, 0xCC52, 0x59C8, 0xCC53, 0x59B4, 0xCC54, 0x59C7, 0xCC55, 0x5B62, 0xCC56, 0x5B65, + 0xCC57, 0x5B93, 0xCC58, 0x5B95, 0xCC59, 0x5C44, 0xCC5A, 0x5C47, 0xCC5B, 0x5CAE, 0xCC5C, 0x5CA4, 0xCC5D, 0x5CA0, 0xCC5E, 0x5CB5, + 0xCC5F, 0x5CAF, 0xCC60, 0x5CA8, 0xCC61, 0x5CAC, 0xCC62, 0x5C9F, 0xCC63, 0x5CA3, 0xCC64, 0x5CAD, 0xCC65, 0x5CA2, 0xCC66, 0x5CAA, + 0xCC67, 0x5CA7, 0xCC68, 0x5C9D, 0xCC69, 0x5CA5, 0xCC6A, 0x5CB6, 0xCC6B, 0x5CB0, 0xCC6C, 0x5CA6, 0xCC6D, 0x5E17, 0xCC6E, 0x5E14, + 0xCC6F, 0x5E19, 0xCC70, 0x5F28, 0xCC71, 0x5F22, 0xCC72, 0x5F23, 0xCC73, 0x5F24, 0xCC74, 0x5F54, 0xCC75, 0x5F82, 0xCC76, 0x5F7E, + 0xCC77, 0x5F7D, 0xCC78, 0x5FDE, 0xCC79, 0x5FE5, 0xCC7A, 0x602D, 0xCC7B, 0x6026, 0xCC7C, 0x6019, 0xCC7D, 0x6032, 0xCC7E, 0x600B, + 0xCCA1, 0x6034, 0xCCA2, 0x600A, 0xCCA3, 0x6017, 0xCCA4, 0x6033, 0xCCA5, 0x601A, 0xCCA6, 0x601E, 0xCCA7, 0x602C, 0xCCA8, 0x6022, + 0xCCA9, 0x600D, 0xCCAA, 0x6010, 0xCCAB, 0x602E, 0xCCAC, 0x6013, 0xCCAD, 0x6011, 0xCCAE, 0x600C, 0xCCAF, 0x6009, 0xCCB0, 0x601C, + 0xCCB1, 0x6214, 0xCCB2, 0x623D, 0xCCB3, 0x62AD, 0xCCB4, 0x62B4, 0xCCB5, 0x62D1, 0xCCB6, 0x62BE, 0xCCB7, 0x62AA, 0xCCB8, 0x62B6, + 0xCCB9, 0x62CA, 0xCCBA, 0x62AE, 0xCCBB, 0x62B3, 0xCCBC, 0x62AF, 0xCCBD, 0x62BB, 0xCCBE, 0x62A9, 0xCCBF, 0x62B0, 0xCCC0, 0x62B8, + 0xCCC1, 0x653D, 0xCCC2, 0x65A8, 0xCCC3, 0x65BB, 0xCCC4, 0x6609, 0xCCC5, 0x65FC, 0xCCC6, 0x6604, 0xCCC7, 0x6612, 0xCCC8, 0x6608, + 0xCCC9, 0x65FB, 0xCCCA, 0x6603, 0xCCCB, 0x660B, 0xCCCC, 0x660D, 0xCCCD, 0x6605, 0xCCCE, 0x65FD, 0xCCCF, 0x6611, 0xCCD0, 0x6610, + 0xCCD1, 0x66F6, 0xCCD2, 0x670A, 0xCCD3, 0x6785, 0xCCD4, 0x676C, 0xCCD5, 0x678E, 0xCCD6, 0x6792, 0xCCD7, 0x6776, 0xCCD8, 0x677B, + 0xCCD9, 0x6798, 0xCCDA, 0x6786, 0xCCDB, 0x6784, 0xCCDC, 0x6774, 0xCCDD, 0x678D, 0xCCDE, 0x678C, 0xCCDF, 0x677A, 0xCCE0, 0x679F, + 0xCCE1, 0x6791, 0xCCE2, 0x6799, 0xCCE3, 0x6783, 0xCCE4, 0x677D, 0xCCE5, 0x6781, 0xCCE6, 0x6778, 0xCCE7, 0x6779, 0xCCE8, 0x6794, + 0xCCE9, 0x6B25, 0xCCEA, 0x6B80, 0xCCEB, 0x6B7E, 0xCCEC, 0x6BDE, 0xCCED, 0x6C1D, 0xCCEE, 0x6C93, 0xCCEF, 0x6CEC, 0xCCF0, 0x6CEB, + 0xCCF1, 0x6CEE, 0xCCF2, 0x6CD9, 0xCCF3, 0x6CB6, 0xCCF4, 0x6CD4, 0xCCF5, 0x6CAD, 0xCCF6, 0x6CE7, 0xCCF7, 0x6CB7, 0xCCF8, 0x6CD0, + 0xCCF9, 0x6CC2, 0xCCFA, 0x6CBA, 0xCCFB, 0x6CC3, 0xCCFC, 0x6CC6, 0xCCFD, 0x6CED, 0xCCFE, 0x6CF2, 0xCD40, 0x6CD2, 0xCD41, 0x6CDD, + 0xCD42, 0x6CB4, 0xCD43, 0x6C8A, 0xCD44, 0x6C9D, 0xCD45, 0x6C80, 0xCD46, 0x6CDE, 0xCD47, 0x6CC0, 0xCD48, 0x6D30, 0xCD49, 0x6CCD, + 0xCD4A, 0x6CC7, 0xCD4B, 0x6CB0, 0xCD4C, 0x6CF9, 0xCD4D, 0x6CCF, 0xCD4E, 0x6CE9, 0xCD4F, 0x6CD1, 0xCD50, 0x7094, 0xCD51, 0x7098, + 0xCD52, 0x7085, 0xCD53, 0x7093, 0xCD54, 0x7086, 0xCD55, 0x7084, 0xCD56, 0x7091, 0xCD57, 0x7096, 0xCD58, 0x7082, 0xCD59, 0x709A, + 0xCD5A, 0x7083, 0xCD5B, 0x726A, 0xCD5C, 0x72D6, 0xCD5D, 0x72CB, 0xCD5E, 0x72D8, 0xCD5F, 0x72C9, 0xCD60, 0x72DC, 0xCD61, 0x72D2, + 0xCD62, 0x72D4, 0xCD63, 0x72DA, 0xCD64, 0x72CC, 0xCD65, 0x72D1, 0xCD66, 0x73A4, 0xCD67, 0x73A1, 0xCD68, 0x73AD, 0xCD69, 0x73A6, + 0xCD6A, 0x73A2, 0xCD6B, 0x73A0, 0xCD6C, 0x73AC, 0xCD6D, 0x739D, 0xCD6E, 0x74DD, 0xCD6F, 0x74E8, 0xCD70, 0x753F, 0xCD71, 0x7540, + 0xCD72, 0x753E, 0xCD73, 0x758C, 0xCD74, 0x7598, 0xCD75, 0x76AF, 0xCD76, 0x76F3, 0xCD77, 0x76F1, 0xCD78, 0x76F0, 0xCD79, 0x76F5, + 0xCD7A, 0x77F8, 0xCD7B, 0x77FC, 0xCD7C, 0x77F9, 0xCD7D, 0x77FB, 0xCD7E, 0x77FA, 0xCDA1, 0x77F7, 0xCDA2, 0x7942, 0xCDA3, 0x793F, + 0xCDA4, 0x79C5, 0xCDA5, 0x7A78, 0xCDA6, 0x7A7B, 0xCDA7, 0x7AFB, 0xCDA8, 0x7C75, 0xCDA9, 0x7CFD, 0xCDAA, 0x8035, 0xCDAB, 0x808F, + 0xCDAC, 0x80AE, 0xCDAD, 0x80A3, 0xCDAE, 0x80B8, 0xCDAF, 0x80B5, 0xCDB0, 0x80AD, 0xCDB1, 0x8220, 0xCDB2, 0x82A0, 0xCDB3, 0x82C0, + 0xCDB4, 0x82AB, 0xCDB5, 0x829A, 0xCDB6, 0x8298, 0xCDB7, 0x829B, 0xCDB8, 0x82B5, 0xCDB9, 0x82A7, 0xCDBA, 0x82AE, 0xCDBB, 0x82BC, + 0xCDBC, 0x829E, 0xCDBD, 0x82BA, 0xCDBE, 0x82B4, 0xCDBF, 0x82A8, 0xCDC0, 0x82A1, 0xCDC1, 0x82A9, 0xCDC2, 0x82C2, 0xCDC3, 0x82A4, + 0xCDC4, 0x82C3, 0xCDC5, 0x82B6, 0xCDC6, 0x82A2, 0xCDC7, 0x8670, 0xCDC8, 0x866F, 0xCDC9, 0x866D, 0xCDCA, 0x866E, 0xCDCB, 0x8C56, + 0xCDCC, 0x8FD2, 0xCDCD, 0x8FCB, 0xCDCE, 0x8FD3, 0xCDCF, 0x8FCD, 0xCDD0, 0x8FD6, 0xCDD1, 0x8FD5, 0xCDD2, 0x8FD7, 0xCDD3, 0x90B2, + 0xCDD4, 0x90B4, 0xCDD5, 0x90AF, 0xCDD6, 0x90B3, 0xCDD7, 0x90B0, 0xCDD8, 0x9639, 0xCDD9, 0x963D, 0xCDDA, 0x963C, 0xCDDB, 0x963A, + 0xCDDC, 0x9643, 0xCDDD, 0x4FCD, 0xCDDE, 0x4FC5, 0xCDDF, 0x4FD3, 0xCDE0, 0x4FB2, 0xCDE1, 0x4FC9, 0xCDE2, 0x4FCB, 0xCDE3, 0x4FC1, + 0xCDE4, 0x4FD4, 0xCDE5, 0x4FDC, 0xCDE6, 0x4FD9, 0xCDE7, 0x4FBB, 0xCDE8, 0x4FB3, 0xCDE9, 0x4FDB, 0xCDEA, 0x4FC7, 0xCDEB, 0x4FD6, + 0xCDEC, 0x4FBA, 0xCDED, 0x4FC0, 0xCDEE, 0x4FB9, 0xCDEF, 0x4FEC, 0xCDF0, 0x5244, 0xCDF1, 0x5249, 0xCDF2, 0x52C0, 0xCDF3, 0x52C2, + 0xCDF4, 0x533D, 0xCDF5, 0x537C, 0xCDF6, 0x5397, 0xCDF7, 0x5396, 0xCDF8, 0x5399, 0xCDF9, 0x5398, 0xCDFA, 0x54BA, 0xCDFB, 0x54A1, + 0xCDFC, 0x54AD, 0xCDFD, 0x54A5, 0xCDFE, 0x54CF, 0xCE40, 0x54C3, 0xCE41, 0x830D, 0xCE42, 0x54B7, 0xCE43, 0x54AE, 0xCE44, 0x54D6, + 0xCE45, 0x54B6, 0xCE46, 0x54C5, 0xCE47, 0x54C6, 0xCE48, 0x54A0, 0xCE49, 0x5470, 0xCE4A, 0x54BC, 0xCE4B, 0x54A2, 0xCE4C, 0x54BE, + 0xCE4D, 0x5472, 0xCE4E, 0x54DE, 0xCE4F, 0x54B0, 0xCE50, 0x57B5, 0xCE51, 0x579E, 0xCE52, 0x579F, 0xCE53, 0x57A4, 0xCE54, 0x578C, + 0xCE55, 0x5797, 0xCE56, 0x579D, 0xCE57, 0x579B, 0xCE58, 0x5794, 0xCE59, 0x5798, 0xCE5A, 0x578F, 0xCE5B, 0x5799, 0xCE5C, 0x57A5, + 0xCE5D, 0x579A, 0xCE5E, 0x5795, 0xCE5F, 0x58F4, 0xCE60, 0x590D, 0xCE61, 0x5953, 0xCE62, 0x59E1, 0xCE63, 0x59DE, 0xCE64, 0x59EE, + 0xCE65, 0x5A00, 0xCE66, 0x59F1, 0xCE67, 0x59DD, 0xCE68, 0x59FA, 0xCE69, 0x59FD, 0xCE6A, 0x59FC, 0xCE6B, 0x59F6, 0xCE6C, 0x59E4, + 0xCE6D, 0x59F2, 0xCE6E, 0x59F7, 0xCE6F, 0x59DB, 0xCE70, 0x59E9, 0xCE71, 0x59F3, 0xCE72, 0x59F5, 0xCE73, 0x59E0, 0xCE74, 0x59FE, + 0xCE75, 0x59F4, 0xCE76, 0x59ED, 0xCE77, 0x5BA8, 0xCE78, 0x5C4C, 0xCE79, 0x5CD0, 0xCE7A, 0x5CD8, 0xCE7B, 0x5CCC, 0xCE7C, 0x5CD7, + 0xCE7D, 0x5CCB, 0xCE7E, 0x5CDB, 0xCEA1, 0x5CDE, 0xCEA2, 0x5CDA, 0xCEA3, 0x5CC9, 0xCEA4, 0x5CC7, 0xCEA5, 0x5CCA, 0xCEA6, 0x5CD6, + 0xCEA7, 0x5CD3, 0xCEA8, 0x5CD4, 0xCEA9, 0x5CCF, 0xCEAA, 0x5CC8, 0xCEAB, 0x5CC6, 0xCEAC, 0x5CCE, 0xCEAD, 0x5CDF, 0xCEAE, 0x5CF8, + 0xCEAF, 0x5DF9, 0xCEB0, 0x5E21, 0xCEB1, 0x5E22, 0xCEB2, 0x5E23, 0xCEB3, 0x5E20, 0xCEB4, 0x5E24, 0xCEB5, 0x5EB0, 0xCEB6, 0x5EA4, + 0xCEB7, 0x5EA2, 0xCEB8, 0x5E9B, 0xCEB9, 0x5EA3, 0xCEBA, 0x5EA5, 0xCEBB, 0x5F07, 0xCEBC, 0x5F2E, 0xCEBD, 0x5F56, 0xCEBE, 0x5F86, + 0xCEBF, 0x6037, 0xCEC0, 0x6039, 0xCEC1, 0x6054, 0xCEC2, 0x6072, 0xCEC3, 0x605E, 0xCEC4, 0x6045, 0xCEC5, 0x6053, 0xCEC6, 0x6047, + 0xCEC7, 0x6049, 0xCEC8, 0x605B, 0xCEC9, 0x604C, 0xCECA, 0x6040, 0xCECB, 0x6042, 0xCECC, 0x605F, 0xCECD, 0x6024, 0xCECE, 0x6044, + 0xCECF, 0x6058, 0xCED0, 0x6066, 0xCED1, 0x606E, 0xCED2, 0x6242, 0xCED3, 0x6243, 0xCED4, 0x62CF, 0xCED5, 0x630D, 0xCED6, 0x630B, + 0xCED7, 0x62F5, 0xCED8, 0x630E, 0xCED9, 0x6303, 0xCEDA, 0x62EB, 0xCEDB, 0x62F9, 0xCEDC, 0x630F, 0xCEDD, 0x630C, 0xCEDE, 0x62F8, + 0xCEDF, 0x62F6, 0xCEE0, 0x6300, 0xCEE1, 0x6313, 0xCEE2, 0x6314, 0xCEE3, 0x62FA, 0xCEE4, 0x6315, 0xCEE5, 0x62FB, 0xCEE6, 0x62F0, + 0xCEE7, 0x6541, 0xCEE8, 0x6543, 0xCEE9, 0x65AA, 0xCEEA, 0x65BF, 0xCEEB, 0x6636, 0xCEEC, 0x6621, 0xCEED, 0x6632, 0xCEEE, 0x6635, + 0xCEEF, 0x661C, 0xCEF0, 0x6626, 0xCEF1, 0x6622, 0xCEF2, 0x6633, 0xCEF3, 0x662B, 0xCEF4, 0x663A, 0xCEF5, 0x661D, 0xCEF6, 0x6634, + 0xCEF7, 0x6639, 0xCEF8, 0x662E, 0xCEF9, 0x670F, 0xCEFA, 0x6710, 0xCEFB, 0x67C1, 0xCEFC, 0x67F2, 0xCEFD, 0x67C8, 0xCEFE, 0x67BA, + 0xCF40, 0x67DC, 0xCF41, 0x67BB, 0xCF42, 0x67F8, 0xCF43, 0x67D8, 0xCF44, 0x67C0, 0xCF45, 0x67B7, 0xCF46, 0x67C5, 0xCF47, 0x67EB, + 0xCF48, 0x67E4, 0xCF49, 0x67DF, 0xCF4A, 0x67B5, 0xCF4B, 0x67CD, 0xCF4C, 0x67B3, 0xCF4D, 0x67F7, 0xCF4E, 0x67F6, 0xCF4F, 0x67EE, + 0xCF50, 0x67E3, 0xCF51, 0x67C2, 0xCF52, 0x67B9, 0xCF53, 0x67CE, 0xCF54, 0x67E7, 0xCF55, 0x67F0, 0xCF56, 0x67B2, 0xCF57, 0x67FC, + 0xCF58, 0x67C6, 0xCF59, 0x67ED, 0xCF5A, 0x67CC, 0xCF5B, 0x67AE, 0xCF5C, 0x67E6, 0xCF5D, 0x67DB, 0xCF5E, 0x67FA, 0xCF5F, 0x67C9, + 0xCF60, 0x67CA, 0xCF61, 0x67C3, 0xCF62, 0x67EA, 0xCF63, 0x67CB, 0xCF64, 0x6B28, 0xCF65, 0x6B82, 0xCF66, 0x6B84, 0xCF67, 0x6BB6, + 0xCF68, 0x6BD6, 0xCF69, 0x6BD8, 0xCF6A, 0x6BE0, 0xCF6B, 0x6C20, 0xCF6C, 0x6C21, 0xCF6D, 0x6D28, 0xCF6E, 0x6D34, 0xCF6F, 0x6D2D, + 0xCF70, 0x6D1F, 0xCF71, 0x6D3C, 0xCF72, 0x6D3F, 0xCF73, 0x6D12, 0xCF74, 0x6D0A, 0xCF75, 0x6CDA, 0xCF76, 0x6D33, 0xCF77, 0x6D04, + 0xCF78, 0x6D19, 0xCF79, 0x6D3A, 0xCF7A, 0x6D1A, 0xCF7B, 0x6D11, 0xCF7C, 0x6D00, 0xCF7D, 0x6D1D, 0xCF7E, 0x6D42, 0xCFA1, 0x6D01, + 0xCFA2, 0x6D18, 0xCFA3, 0x6D37, 0xCFA4, 0x6D03, 0xCFA5, 0x6D0F, 0xCFA6, 0x6D40, 0xCFA7, 0x6D07, 0xCFA8, 0x6D20, 0xCFA9, 0x6D2C, + 0xCFAA, 0x6D08, 0xCFAB, 0x6D22, 0xCFAC, 0x6D09, 0xCFAD, 0x6D10, 0xCFAE, 0x70B7, 0xCFAF, 0x709F, 0xCFB0, 0x70BE, 0xCFB1, 0x70B1, + 0xCFB2, 0x70B0, 0xCFB3, 0x70A1, 0xCFB4, 0x70B4, 0xCFB5, 0x70B5, 0xCFB6, 0x70A9, 0xCFB7, 0x7241, 0xCFB8, 0x7249, 0xCFB9, 0x724A, + 0xCFBA, 0x726C, 0xCFBB, 0x7270, 0xCFBC, 0x7273, 0xCFBD, 0x726E, 0xCFBE, 0x72CA, 0xCFBF, 0x72E4, 0xCFC0, 0x72E8, 0xCFC1, 0x72EB, + 0xCFC2, 0x72DF, 0xCFC3, 0x72EA, 0xCFC4, 0x72E6, 0xCFC5, 0x72E3, 0xCFC6, 0x7385, 0xCFC7, 0x73CC, 0xCFC8, 0x73C2, 0xCFC9, 0x73C8, + 0xCFCA, 0x73C5, 0xCFCB, 0x73B9, 0xCFCC, 0x73B6, 0xCFCD, 0x73B5, 0xCFCE, 0x73B4, 0xCFCF, 0x73EB, 0xCFD0, 0x73BF, 0xCFD1, 0x73C7, + 0xCFD2, 0x73BE, 0xCFD3, 0x73C3, 0xCFD4, 0x73C6, 0xCFD5, 0x73B8, 0xCFD6, 0x73CB, 0xCFD7, 0x74EC, 0xCFD8, 0x74EE, 0xCFD9, 0x752E, + 0xCFDA, 0x7547, 0xCFDB, 0x7548, 0xCFDC, 0x75A7, 0xCFDD, 0x75AA, 0xCFDE, 0x7679, 0xCFDF, 0x76C4, 0xCFE0, 0x7708, 0xCFE1, 0x7703, + 0xCFE2, 0x7704, 0xCFE3, 0x7705, 0xCFE4, 0x770A, 0xCFE5, 0x76F7, 0xCFE6, 0x76FB, 0xCFE7, 0x76FA, 0xCFE8, 0x77E7, 0xCFE9, 0x77E8, + 0xCFEA, 0x7806, 0xCFEB, 0x7811, 0xCFEC, 0x7812, 0xCFED, 0x7805, 0xCFEE, 0x7810, 0xCFEF, 0x780F, 0xCFF0, 0x780E, 0xCFF1, 0x7809, + 0xCFF2, 0x7803, 0xCFF3, 0x7813, 0xCFF4, 0x794A, 0xCFF5, 0x794C, 0xCFF6, 0x794B, 0xCFF7, 0x7945, 0xCFF8, 0x7944, 0xCFF9, 0x79D5, + 0xCFFA, 0x79CD, 0xCFFB, 0x79CF, 0xCFFC, 0x79D6, 0xCFFD, 0x79CE, 0xCFFE, 0x7A80, 0xD040, 0x7A7E, 0xD041, 0x7AD1, 0xD042, 0x7B00, + 0xD043, 0x7B01, 0xD044, 0x7C7A, 0xD045, 0x7C78, 0xD046, 0x7C79, 0xD047, 0x7C7F, 0xD048, 0x7C80, 0xD049, 0x7C81, 0xD04A, 0x7D03, + 0xD04B, 0x7D08, 0xD04C, 0x7D01, 0xD04D, 0x7F58, 0xD04E, 0x7F91, 0xD04F, 0x7F8D, 0xD050, 0x7FBE, 0xD051, 0x8007, 0xD052, 0x800E, + 0xD053, 0x800F, 0xD054, 0x8014, 0xD055, 0x8037, 0xD056, 0x80D8, 0xD057, 0x80C7, 0xD058, 0x80E0, 0xD059, 0x80D1, 0xD05A, 0x80C8, + 0xD05B, 0x80C2, 0xD05C, 0x80D0, 0xD05D, 0x80C5, 0xD05E, 0x80E3, 0xD05F, 0x80D9, 0xD060, 0x80DC, 0xD061, 0x80CA, 0xD062, 0x80D5, + 0xD063, 0x80C9, 0xD064, 0x80CF, 0xD065, 0x80D7, 0xD066, 0x80E6, 0xD067, 0x80CD, 0xD068, 0x81FF, 0xD069, 0x8221, 0xD06A, 0x8294, + 0xD06B, 0x82D9, 0xD06C, 0x82FE, 0xD06D, 0x82F9, 0xD06E, 0x8307, 0xD06F, 0x82E8, 0xD070, 0x8300, 0xD071, 0x82D5, 0xD072, 0x833A, + 0xD073, 0x82EB, 0xD074, 0x82D6, 0xD075, 0x82F4, 0xD076, 0x82EC, 0xD077, 0x82E1, 0xD078, 0x82F2, 0xD079, 0x82F5, 0xD07A, 0x830C, + 0xD07B, 0x82FB, 0xD07C, 0x82F6, 0xD07D, 0x82F0, 0xD07E, 0x82EA, 0xD0A1, 0x82E4, 0xD0A2, 0x82E0, 0xD0A3, 0x82FA, 0xD0A4, 0x82F3, + 0xD0A5, 0x82ED, 0xD0A6, 0x8677, 0xD0A7, 0x8674, 0xD0A8, 0x867C, 0xD0A9, 0x8673, 0xD0AA, 0x8841, 0xD0AB, 0x884E, 0xD0AC, 0x8867, + 0xD0AD, 0x886A, 0xD0AE, 0x8869, 0xD0AF, 0x89D3, 0xD0B0, 0x8A04, 0xD0B1, 0x8A07, 0xD0B2, 0x8D72, 0xD0B3, 0x8FE3, 0xD0B4, 0x8FE1, + 0xD0B5, 0x8FEE, 0xD0B6, 0x8FE0, 0xD0B7, 0x90F1, 0xD0B8, 0x90BD, 0xD0B9, 0x90BF, 0xD0BA, 0x90D5, 0xD0BB, 0x90C5, 0xD0BC, 0x90BE, + 0xD0BD, 0x90C7, 0xD0BE, 0x90CB, 0xD0BF, 0x90C8, 0xD0C0, 0x91D4, 0xD0C1, 0x91D3, 0xD0C2, 0x9654, 0xD0C3, 0x964F, 0xD0C4, 0x9651, + 0xD0C5, 0x9653, 0xD0C6, 0x964A, 0xD0C7, 0x964E, 0xD0C8, 0x501E, 0xD0C9, 0x5005, 0xD0CA, 0x5007, 0xD0CB, 0x5013, 0xD0CC, 0x5022, + 0xD0CD, 0x5030, 0xD0CE, 0x501B, 0xD0CF, 0x4FF5, 0xD0D0, 0x4FF4, 0xD0D1, 0x5033, 0xD0D2, 0x5037, 0xD0D3, 0x502C, 0xD0D4, 0x4FF6, + 0xD0D5, 0x4FF7, 0xD0D6, 0x5017, 0xD0D7, 0x501C, 0xD0D8, 0x5020, 0xD0D9, 0x5027, 0xD0DA, 0x5035, 0xD0DB, 0x502F, 0xD0DC, 0x5031, + 0xD0DD, 0x500E, 0xD0DE, 0x515A, 0xD0DF, 0x5194, 0xD0E0, 0x5193, 0xD0E1, 0x51CA, 0xD0E2, 0x51C4, 0xD0E3, 0x51C5, 0xD0E4, 0x51C8, + 0xD0E5, 0x51CE, 0xD0E6, 0x5261, 0xD0E7, 0x525A, 0xD0E8, 0x5252, 0xD0E9, 0x525E, 0xD0EA, 0x525F, 0xD0EB, 0x5255, 0xD0EC, 0x5262, + 0xD0ED, 0x52CD, 0xD0EE, 0x530E, 0xD0EF, 0x539E, 0xD0F0, 0x5526, 0xD0F1, 0x54E2, 0xD0F2, 0x5517, 0xD0F3, 0x5512, 0xD0F4, 0x54E7, + 0xD0F5, 0x54F3, 0xD0F6, 0x54E4, 0xD0F7, 0x551A, 0xD0F8, 0x54FF, 0xD0F9, 0x5504, 0xD0FA, 0x5508, 0xD0FB, 0x54EB, 0xD0FC, 0x5511, + 0xD0FD, 0x5505, 0xD0FE, 0x54F1, 0xD140, 0x550A, 0xD141, 0x54FB, 0xD142, 0x54F7, 0xD143, 0x54F8, 0xD144, 0x54E0, 0xD145, 0x550E, + 0xD146, 0x5503, 0xD147, 0x550B, 0xD148, 0x5701, 0xD149, 0x5702, 0xD14A, 0x57CC, 0xD14B, 0x5832, 0xD14C, 0x57D5, 0xD14D, 0x57D2, + 0xD14E, 0x57BA, 0xD14F, 0x57C6, 0xD150, 0x57BD, 0xD151, 0x57BC, 0xD152, 0x57B8, 0xD153, 0x57B6, 0xD154, 0x57BF, 0xD155, 0x57C7, + 0xD156, 0x57D0, 0xD157, 0x57B9, 0xD158, 0x57C1, 0xD159, 0x590E, 0xD15A, 0x594A, 0xD15B, 0x5A19, 0xD15C, 0x5A16, 0xD15D, 0x5A2D, + 0xD15E, 0x5A2E, 0xD15F, 0x5A15, 0xD160, 0x5A0F, 0xD161, 0x5A17, 0xD162, 0x5A0A, 0xD163, 0x5A1E, 0xD164, 0x5A33, 0xD165, 0x5B6C, + 0xD166, 0x5BA7, 0xD167, 0x5BAD, 0xD168, 0x5BAC, 0xD169, 0x5C03, 0xD16A, 0x5C56, 0xD16B, 0x5C54, 0xD16C, 0x5CEC, 0xD16D, 0x5CFF, + 0xD16E, 0x5CEE, 0xD16F, 0x5CF1, 0xD170, 0x5CF7, 0xD171, 0x5D00, 0xD172, 0x5CF9, 0xD173, 0x5E29, 0xD174, 0x5E28, 0xD175, 0x5EA8, + 0xD176, 0x5EAE, 0xD177, 0x5EAA, 0xD178, 0x5EAC, 0xD179, 0x5F33, 0xD17A, 0x5F30, 0xD17B, 0x5F67, 0xD17C, 0x605D, 0xD17D, 0x605A, + 0xD17E, 0x6067, 0xD1A1, 0x6041, 0xD1A2, 0x60A2, 0xD1A3, 0x6088, 0xD1A4, 0x6080, 0xD1A5, 0x6092, 0xD1A6, 0x6081, 0xD1A7, 0x609D, + 0xD1A8, 0x6083, 0xD1A9, 0x6095, 0xD1AA, 0x609B, 0xD1AB, 0x6097, 0xD1AC, 0x6087, 0xD1AD, 0x609C, 0xD1AE, 0x608E, 0xD1AF, 0x6219, + 0xD1B0, 0x6246, 0xD1B1, 0x62F2, 0xD1B2, 0x6310, 0xD1B3, 0x6356, 0xD1B4, 0x632C, 0xD1B5, 0x6344, 0xD1B6, 0x6345, 0xD1B7, 0x6336, + 0xD1B8, 0x6343, 0xD1B9, 0x63E4, 0xD1BA, 0x6339, 0xD1BB, 0x634B, 0xD1BC, 0x634A, 0xD1BD, 0x633C, 0xD1BE, 0x6329, 0xD1BF, 0x6341, + 0xD1C0, 0x6334, 0xD1C1, 0x6358, 0xD1C2, 0x6354, 0xD1C3, 0x6359, 0xD1C4, 0x632D, 0xD1C5, 0x6347, 0xD1C6, 0x6333, 0xD1C7, 0x635A, + 0xD1C8, 0x6351, 0xD1C9, 0x6338, 0xD1CA, 0x6357, 0xD1CB, 0x6340, 0xD1CC, 0x6348, 0xD1CD, 0x654A, 0xD1CE, 0x6546, 0xD1CF, 0x65C6, + 0xD1D0, 0x65C3, 0xD1D1, 0x65C4, 0xD1D2, 0x65C2, 0xD1D3, 0x664A, 0xD1D4, 0x665F, 0xD1D5, 0x6647, 0xD1D6, 0x6651, 0xD1D7, 0x6712, + 0xD1D8, 0x6713, 0xD1D9, 0x681F, 0xD1DA, 0x681A, 0xD1DB, 0x6849, 0xD1DC, 0x6832, 0xD1DD, 0x6833, 0xD1DE, 0x683B, 0xD1DF, 0x684B, + 0xD1E0, 0x684F, 0xD1E1, 0x6816, 0xD1E2, 0x6831, 0xD1E3, 0x681C, 0xD1E4, 0x6835, 0xD1E5, 0x682B, 0xD1E6, 0x682D, 0xD1E7, 0x682F, + 0xD1E8, 0x684E, 0xD1E9, 0x6844, 0xD1EA, 0x6834, 0xD1EB, 0x681D, 0xD1EC, 0x6812, 0xD1ED, 0x6814, 0xD1EE, 0x6826, 0xD1EF, 0x6828, + 0xD1F0, 0x682E, 0xD1F1, 0x684D, 0xD1F2, 0x683A, 0xD1F3, 0x6825, 0xD1F4, 0x6820, 0xD1F5, 0x6B2C, 0xD1F6, 0x6B2F, 0xD1F7, 0x6B2D, + 0xD1F8, 0x6B31, 0xD1F9, 0x6B34, 0xD1FA, 0x6B6D, 0xD1FB, 0x8082, 0xD1FC, 0x6B88, 0xD1FD, 0x6BE6, 0xD1FE, 0x6BE4, 0xD240, 0x6BE8, + 0xD241, 0x6BE3, 0xD242, 0x6BE2, 0xD243, 0x6BE7, 0xD244, 0x6C25, 0xD245, 0x6D7A, 0xD246, 0x6D63, 0xD247, 0x6D64, 0xD248, 0x6D76, + 0xD249, 0x6D0D, 0xD24A, 0x6D61, 0xD24B, 0x6D92, 0xD24C, 0x6D58, 0xD24D, 0x6D62, 0xD24E, 0x6D6D, 0xD24F, 0x6D6F, 0xD250, 0x6D91, + 0xD251, 0x6D8D, 0xD252, 0x6DEF, 0xD253, 0x6D7F, 0xD254, 0x6D86, 0xD255, 0x6D5E, 0xD256, 0x6D67, 0xD257, 0x6D60, 0xD258, 0x6D97, + 0xD259, 0x6D70, 0xD25A, 0x6D7C, 0xD25B, 0x6D5F, 0xD25C, 0x6D82, 0xD25D, 0x6D98, 0xD25E, 0x6D2F, 0xD25F, 0x6D68, 0xD260, 0x6D8B, + 0xD261, 0x6D7E, 0xD262, 0x6D80, 0xD263, 0x6D84, 0xD264, 0x6D16, 0xD265, 0x6D83, 0xD266, 0x6D7B, 0xD267, 0x6D7D, 0xD268, 0x6D75, + 0xD269, 0x6D90, 0xD26A, 0x70DC, 0xD26B, 0x70D3, 0xD26C, 0x70D1, 0xD26D, 0x70DD, 0xD26E, 0x70CB, 0xD26F, 0x7F39, 0xD270, 0x70E2, + 0xD271, 0x70D7, 0xD272, 0x70D2, 0xD273, 0x70DE, 0xD274, 0x70E0, 0xD275, 0x70D4, 0xD276, 0x70CD, 0xD277, 0x70C5, 0xD278, 0x70C6, + 0xD279, 0x70C7, 0xD27A, 0x70DA, 0xD27B, 0x70CE, 0xD27C, 0x70E1, 0xD27D, 0x7242, 0xD27E, 0x7278, 0xD2A1, 0x7277, 0xD2A2, 0x7276, + 0xD2A3, 0x7300, 0xD2A4, 0x72FA, 0xD2A5, 0x72F4, 0xD2A6, 0x72FE, 0xD2A7, 0x72F6, 0xD2A8, 0x72F3, 0xD2A9, 0x72FB, 0xD2AA, 0x7301, + 0xD2AB, 0x73D3, 0xD2AC, 0x73D9, 0xD2AD, 0x73E5, 0xD2AE, 0x73D6, 0xD2AF, 0x73BC, 0xD2B0, 0x73E7, 0xD2B1, 0x73E3, 0xD2B2, 0x73E9, + 0xD2B3, 0x73DC, 0xD2B4, 0x73D2, 0xD2B5, 0x73DB, 0xD2B6, 0x73D4, 0xD2B7, 0x73DD, 0xD2B8, 0x73DA, 0xD2B9, 0x73D7, 0xD2BA, 0x73D8, + 0xD2BB, 0x73E8, 0xD2BC, 0x74DE, 0xD2BD, 0x74DF, 0xD2BE, 0x74F4, 0xD2BF, 0x74F5, 0xD2C0, 0x7521, 0xD2C1, 0x755B, 0xD2C2, 0x755F, + 0xD2C3, 0x75B0, 0xD2C4, 0x75C1, 0xD2C5, 0x75BB, 0xD2C6, 0x75C4, 0xD2C7, 0x75C0, 0xD2C8, 0x75BF, 0xD2C9, 0x75B6, 0xD2CA, 0x75BA, + 0xD2CB, 0x768A, 0xD2CC, 0x76C9, 0xD2CD, 0x771D, 0xD2CE, 0x771B, 0xD2CF, 0x7710, 0xD2D0, 0x7713, 0xD2D1, 0x7712, 0xD2D2, 0x7723, + 0xD2D3, 0x7711, 0xD2D4, 0x7715, 0xD2D5, 0x7719, 0xD2D6, 0x771A, 0xD2D7, 0x7722, 0xD2D8, 0x7727, 0xD2D9, 0x7823, 0xD2DA, 0x782C, + 0xD2DB, 0x7822, 0xD2DC, 0x7835, 0xD2DD, 0x782F, 0xD2DE, 0x7828, 0xD2DF, 0x782E, 0xD2E0, 0x782B, 0xD2E1, 0x7821, 0xD2E2, 0x7829, + 0xD2E3, 0x7833, 0xD2E4, 0x782A, 0xD2E5, 0x7831, 0xD2E6, 0x7954, 0xD2E7, 0x795B, 0xD2E8, 0x794F, 0xD2E9, 0x795C, 0xD2EA, 0x7953, + 0xD2EB, 0x7952, 0xD2EC, 0x7951, 0xD2ED, 0x79EB, 0xD2EE, 0x79EC, 0xD2EF, 0x79E0, 0xD2F0, 0x79EE, 0xD2F1, 0x79ED, 0xD2F2, 0x79EA, + 0xD2F3, 0x79DC, 0xD2F4, 0x79DE, 0xD2F5, 0x79DD, 0xD2F6, 0x7A86, 0xD2F7, 0x7A89, 0xD2F8, 0x7A85, 0xD2F9, 0x7A8B, 0xD2FA, 0x7A8C, + 0xD2FB, 0x7A8A, 0xD2FC, 0x7A87, 0xD2FD, 0x7AD8, 0xD2FE, 0x7B10, 0xD340, 0x7B04, 0xD341, 0x7B13, 0xD342, 0x7B05, 0xD343, 0x7B0F, + 0xD344, 0x7B08, 0xD345, 0x7B0A, 0xD346, 0x7B0E, 0xD347, 0x7B09, 0xD348, 0x7B12, 0xD349, 0x7C84, 0xD34A, 0x7C91, 0xD34B, 0x7C8A, + 0xD34C, 0x7C8C, 0xD34D, 0x7C88, 0xD34E, 0x7C8D, 0xD34F, 0x7C85, 0xD350, 0x7D1E, 0xD351, 0x7D1D, 0xD352, 0x7D11, 0xD353, 0x7D0E, + 0xD354, 0x7D18, 0xD355, 0x7D16, 0xD356, 0x7D13, 0xD357, 0x7D1F, 0xD358, 0x7D12, 0xD359, 0x7D0F, 0xD35A, 0x7D0C, 0xD35B, 0x7F5C, + 0xD35C, 0x7F61, 0xD35D, 0x7F5E, 0xD35E, 0x7F60, 0xD35F, 0x7F5D, 0xD360, 0x7F5B, 0xD361, 0x7F96, 0xD362, 0x7F92, 0xD363, 0x7FC3, + 0xD364, 0x7FC2, 0xD365, 0x7FC0, 0xD366, 0x8016, 0xD367, 0x803E, 0xD368, 0x8039, 0xD369, 0x80FA, 0xD36A, 0x80F2, 0xD36B, 0x80F9, + 0xD36C, 0x80F5, 0xD36D, 0x8101, 0xD36E, 0x80FB, 0xD36F, 0x8100, 0xD370, 0x8201, 0xD371, 0x822F, 0xD372, 0x8225, 0xD373, 0x8333, + 0xD374, 0x832D, 0xD375, 0x8344, 0xD376, 0x8319, 0xD377, 0x8351, 0xD378, 0x8325, 0xD379, 0x8356, 0xD37A, 0x833F, 0xD37B, 0x8341, + 0xD37C, 0x8326, 0xD37D, 0x831C, 0xD37E, 0x8322, 0xD3A1, 0x8342, 0xD3A2, 0x834E, 0xD3A3, 0x831B, 0xD3A4, 0x832A, 0xD3A5, 0x8308, + 0xD3A6, 0x833C, 0xD3A7, 0x834D, 0xD3A8, 0x8316, 0xD3A9, 0x8324, 0xD3AA, 0x8320, 0xD3AB, 0x8337, 0xD3AC, 0x832F, 0xD3AD, 0x8329, + 0xD3AE, 0x8347, 0xD3AF, 0x8345, 0xD3B0, 0x834C, 0xD3B1, 0x8353, 0xD3B2, 0x831E, 0xD3B3, 0x832C, 0xD3B4, 0x834B, 0xD3B5, 0x8327, + 0xD3B6, 0x8348, 0xD3B7, 0x8653, 0xD3B8, 0x8652, 0xD3B9, 0x86A2, 0xD3BA, 0x86A8, 0xD3BB, 0x8696, 0xD3BC, 0x868D, 0xD3BD, 0x8691, + 0xD3BE, 0x869E, 0xD3BF, 0x8687, 0xD3C0, 0x8697, 0xD3C1, 0x8686, 0xD3C2, 0x868B, 0xD3C3, 0x869A, 0xD3C4, 0x8685, 0xD3C5, 0x86A5, + 0xD3C6, 0x8699, 0xD3C7, 0x86A1, 0xD3C8, 0x86A7, 0xD3C9, 0x8695, 0xD3CA, 0x8698, 0xD3CB, 0x868E, 0xD3CC, 0x869D, 0xD3CD, 0x8690, + 0xD3CE, 0x8694, 0xD3CF, 0x8843, 0xD3D0, 0x8844, 0xD3D1, 0x886D, 0xD3D2, 0x8875, 0xD3D3, 0x8876, 0xD3D4, 0x8872, 0xD3D5, 0x8880, + 0xD3D6, 0x8871, 0xD3D7, 0x887F, 0xD3D8, 0x886F, 0xD3D9, 0x8883, 0xD3DA, 0x887E, 0xD3DB, 0x8874, 0xD3DC, 0x887C, 0xD3DD, 0x8A12, + 0xD3DE, 0x8C47, 0xD3DF, 0x8C57, 0xD3E0, 0x8C7B, 0xD3E1, 0x8CA4, 0xD3E2, 0x8CA3, 0xD3E3, 0x8D76, 0xD3E4, 0x8D78, 0xD3E5, 0x8DB5, + 0xD3E6, 0x8DB7, 0xD3E7, 0x8DB6, 0xD3E8, 0x8ED1, 0xD3E9, 0x8ED3, 0xD3EA, 0x8FFE, 0xD3EB, 0x8FF5, 0xD3EC, 0x9002, 0xD3ED, 0x8FFF, + 0xD3EE, 0x8FFB, 0xD3EF, 0x9004, 0xD3F0, 0x8FFC, 0xD3F1, 0x8FF6, 0xD3F2, 0x90D6, 0xD3F3, 0x90E0, 0xD3F4, 0x90D9, 0xD3F5, 0x90DA, + 0xD3F6, 0x90E3, 0xD3F7, 0x90DF, 0xD3F8, 0x90E5, 0xD3F9, 0x90D8, 0xD3FA, 0x90DB, 0xD3FB, 0x90D7, 0xD3FC, 0x90DC, 0xD3FD, 0x90E4, + 0xD3FE, 0x9150, 0xD440, 0x914E, 0xD441, 0x914F, 0xD442, 0x91D5, 0xD443, 0x91E2, 0xD444, 0x91DA, 0xD445, 0x965C, 0xD446, 0x965F, + 0xD447, 0x96BC, 0xD448, 0x98E3, 0xD449, 0x9ADF, 0xD44A, 0x9B2F, 0xD44B, 0x4E7F, 0xD44C, 0x5070, 0xD44D, 0x506A, 0xD44E, 0x5061, + 0xD44F, 0x505E, 0xD450, 0x5060, 0xD451, 0x5053, 0xD452, 0x504B, 0xD453, 0x505D, 0xD454, 0x5072, 0xD455, 0x5048, 0xD456, 0x504D, + 0xD457, 0x5041, 0xD458, 0x505B, 0xD459, 0x504A, 0xD45A, 0x5062, 0xD45B, 0x5015, 0xD45C, 0x5045, 0xD45D, 0x505F, 0xD45E, 0x5069, + 0xD45F, 0x506B, 0xD460, 0x5063, 0xD461, 0x5064, 0xD462, 0x5046, 0xD463, 0x5040, 0xD464, 0x506E, 0xD465, 0x5073, 0xD466, 0x5057, + 0xD467, 0x5051, 0xD468, 0x51D0, 0xD469, 0x526B, 0xD46A, 0x526D, 0xD46B, 0x526C, 0xD46C, 0x526E, 0xD46D, 0x52D6, 0xD46E, 0x52D3, + 0xD46F, 0x532D, 0xD470, 0x539C, 0xD471, 0x5575, 0xD472, 0x5576, 0xD473, 0x553C, 0xD474, 0x554D, 0xD475, 0x5550, 0xD476, 0x5534, + 0xD477, 0x552A, 0xD478, 0x5551, 0xD479, 0x5562, 0xD47A, 0x5536, 0xD47B, 0x5535, 0xD47C, 0x5530, 0xD47D, 0x5552, 0xD47E, 0x5545, + 0xD4A1, 0x550C, 0xD4A2, 0x5532, 0xD4A3, 0x5565, 0xD4A4, 0x554E, 0xD4A5, 0x5539, 0xD4A6, 0x5548, 0xD4A7, 0x552D, 0xD4A8, 0x553B, + 0xD4A9, 0x5540, 0xD4AA, 0x554B, 0xD4AB, 0x570A, 0xD4AC, 0x5707, 0xD4AD, 0x57FB, 0xD4AE, 0x5814, 0xD4AF, 0x57E2, 0xD4B0, 0x57F6, + 0xD4B1, 0x57DC, 0xD4B2, 0x57F4, 0xD4B3, 0x5800, 0xD4B4, 0x57ED, 0xD4B5, 0x57FD, 0xD4B6, 0x5808, 0xD4B7, 0x57F8, 0xD4B8, 0x580B, + 0xD4B9, 0x57F3, 0xD4BA, 0x57CF, 0xD4BB, 0x5807, 0xD4BC, 0x57EE, 0xD4BD, 0x57E3, 0xD4BE, 0x57F2, 0xD4BF, 0x57E5, 0xD4C0, 0x57EC, + 0xD4C1, 0x57E1, 0xD4C2, 0x580E, 0xD4C3, 0x57FC, 0xD4C4, 0x5810, 0xD4C5, 0x57E7, 0xD4C6, 0x5801, 0xD4C7, 0x580C, 0xD4C8, 0x57F1, + 0xD4C9, 0x57E9, 0xD4CA, 0x57F0, 0xD4CB, 0x580D, 0xD4CC, 0x5804, 0xD4CD, 0x595C, 0xD4CE, 0x5A60, 0xD4CF, 0x5A58, 0xD4D0, 0x5A55, + 0xD4D1, 0x5A67, 0xD4D2, 0x5A5E, 0xD4D3, 0x5A38, 0xD4D4, 0x5A35, 0xD4D5, 0x5A6D, 0xD4D6, 0x5A50, 0xD4D7, 0x5A5F, 0xD4D8, 0x5A65, + 0xD4D9, 0x5A6C, 0xD4DA, 0x5A53, 0xD4DB, 0x5A64, 0xD4DC, 0x5A57, 0xD4DD, 0x5A43, 0xD4DE, 0x5A5D, 0xD4DF, 0x5A52, 0xD4E0, 0x5A44, + 0xD4E1, 0x5A5B, 0xD4E2, 0x5A48, 0xD4E3, 0x5A8E, 0xD4E4, 0x5A3E, 0xD4E5, 0x5A4D, 0xD4E6, 0x5A39, 0xD4E7, 0x5A4C, 0xD4E8, 0x5A70, + 0xD4E9, 0x5A69, 0xD4EA, 0x5A47, 0xD4EB, 0x5A51, 0xD4EC, 0x5A56, 0xD4ED, 0x5A42, 0xD4EE, 0x5A5C, 0xD4EF, 0x5B72, 0xD4F0, 0x5B6E, + 0xD4F1, 0x5BC1, 0xD4F2, 0x5BC0, 0xD4F3, 0x5C59, 0xD4F4, 0x5D1E, 0xD4F5, 0x5D0B, 0xD4F6, 0x5D1D, 0xD4F7, 0x5D1A, 0xD4F8, 0x5D20, + 0xD4F9, 0x5D0C, 0xD4FA, 0x5D28, 0xD4FB, 0x5D0D, 0xD4FC, 0x5D26, 0xD4FD, 0x5D25, 0xD4FE, 0x5D0F, 0xD540, 0x5D30, 0xD541, 0x5D12, + 0xD542, 0x5D23, 0xD543, 0x5D1F, 0xD544, 0x5D2E, 0xD545, 0x5E3E, 0xD546, 0x5E34, 0xD547, 0x5EB1, 0xD548, 0x5EB4, 0xD549, 0x5EB9, + 0xD54A, 0x5EB2, 0xD54B, 0x5EB3, 0xD54C, 0x5F36, 0xD54D, 0x5F38, 0xD54E, 0x5F9B, 0xD54F, 0x5F96, 0xD550, 0x5F9F, 0xD551, 0x608A, + 0xD552, 0x6090, 0xD553, 0x6086, 0xD554, 0x60BE, 0xD555, 0x60B0, 0xD556, 0x60BA, 0xD557, 0x60D3, 0xD558, 0x60D4, 0xD559, 0x60CF, + 0xD55A, 0x60E4, 0xD55B, 0x60D9, 0xD55C, 0x60DD, 0xD55D, 0x60C8, 0xD55E, 0x60B1, 0xD55F, 0x60DB, 0xD560, 0x60B7, 0xD561, 0x60CA, + 0xD562, 0x60BF, 0xD563, 0x60C3, 0xD564, 0x60CD, 0xD565, 0x60C0, 0xD566, 0x6332, 0xD567, 0x6365, 0xD568, 0x638A, 0xD569, 0x6382, + 0xD56A, 0x637D, 0xD56B, 0x63BD, 0xD56C, 0x639E, 0xD56D, 0x63AD, 0xD56E, 0x639D, 0xD56F, 0x6397, 0xD570, 0x63AB, 0xD571, 0x638E, + 0xD572, 0x636F, 0xD573, 0x6387, 0xD574, 0x6390, 0xD575, 0x636E, 0xD576, 0x63AF, 0xD577, 0x6375, 0xD578, 0x639C, 0xD579, 0x636D, + 0xD57A, 0x63AE, 0xD57B, 0x637C, 0xD57C, 0x63A4, 0xD57D, 0x633B, 0xD57E, 0x639F, 0xD5A1, 0x6378, 0xD5A2, 0x6385, 0xD5A3, 0x6381, + 0xD5A4, 0x6391, 0xD5A5, 0x638D, 0xD5A6, 0x6370, 0xD5A7, 0x6553, 0xD5A8, 0x65CD, 0xD5A9, 0x6665, 0xD5AA, 0x6661, 0xD5AB, 0x665B, + 0xD5AC, 0x6659, 0xD5AD, 0x665C, 0xD5AE, 0x6662, 0xD5AF, 0x6718, 0xD5B0, 0x6879, 0xD5B1, 0x6887, 0xD5B2, 0x6890, 0xD5B3, 0x689C, + 0xD5B4, 0x686D, 0xD5B5, 0x686E, 0xD5B6, 0x68AE, 0xD5B7, 0x68AB, 0xD5B8, 0x6956, 0xD5B9, 0x686F, 0xD5BA, 0x68A3, 0xD5BB, 0x68AC, + 0xD5BC, 0x68A9, 0xD5BD, 0x6875, 0xD5BE, 0x6874, 0xD5BF, 0x68B2, 0xD5C0, 0x688F, 0xD5C1, 0x6877, 0xD5C2, 0x6892, 0xD5C3, 0x687C, + 0xD5C4, 0x686B, 0xD5C5, 0x6872, 0xD5C6, 0x68AA, 0xD5C7, 0x6880, 0xD5C8, 0x6871, 0xD5C9, 0x687E, 0xD5CA, 0x689B, 0xD5CB, 0x6896, + 0xD5CC, 0x688B, 0xD5CD, 0x68A0, 0xD5CE, 0x6889, 0xD5CF, 0x68A4, 0xD5D0, 0x6878, 0xD5D1, 0x687B, 0xD5D2, 0x6891, 0xD5D3, 0x688C, + 0xD5D4, 0x688A, 0xD5D5, 0x687D, 0xD5D6, 0x6B36, 0xD5D7, 0x6B33, 0xD5D8, 0x6B37, 0xD5D9, 0x6B38, 0xD5DA, 0x6B91, 0xD5DB, 0x6B8F, + 0xD5DC, 0x6B8D, 0xD5DD, 0x6B8E, 0xD5DE, 0x6B8C, 0xD5DF, 0x6C2A, 0xD5E0, 0x6DC0, 0xD5E1, 0x6DAB, 0xD5E2, 0x6DB4, 0xD5E3, 0x6DB3, + 0xD5E4, 0x6E74, 0xD5E5, 0x6DAC, 0xD5E6, 0x6DE9, 0xD5E7, 0x6DE2, 0xD5E8, 0x6DB7, 0xD5E9, 0x6DF6, 0xD5EA, 0x6DD4, 0xD5EB, 0x6E00, + 0xD5EC, 0x6DC8, 0xD5ED, 0x6DE0, 0xD5EE, 0x6DDF, 0xD5EF, 0x6DD6, 0xD5F0, 0x6DBE, 0xD5F1, 0x6DE5, 0xD5F2, 0x6DDC, 0xD5F3, 0x6DDD, + 0xD5F4, 0x6DDB, 0xD5F5, 0x6DF4, 0xD5F6, 0x6DCA, 0xD5F7, 0x6DBD, 0xD5F8, 0x6DED, 0xD5F9, 0x6DF0, 0xD5FA, 0x6DBA, 0xD5FB, 0x6DD5, + 0xD5FC, 0x6DC2, 0xD5FD, 0x6DCF, 0xD5FE, 0x6DC9, 0xD640, 0x6DD0, 0xD641, 0x6DF2, 0xD642, 0x6DD3, 0xD643, 0x6DFD, 0xD644, 0x6DD7, + 0xD645, 0x6DCD, 0xD646, 0x6DE3, 0xD647, 0x6DBB, 0xD648, 0x70FA, 0xD649, 0x710D, 0xD64A, 0x70F7, 0xD64B, 0x7117, 0xD64C, 0x70F4, + 0xD64D, 0x710C, 0xD64E, 0x70F0, 0xD64F, 0x7104, 0xD650, 0x70F3, 0xD651, 0x7110, 0xD652, 0x70FC, 0xD653, 0x70FF, 0xD654, 0x7106, + 0xD655, 0x7113, 0xD656, 0x7100, 0xD657, 0x70F8, 0xD658, 0x70F6, 0xD659, 0x710B, 0xD65A, 0x7102, 0xD65B, 0x710E, 0xD65C, 0x727E, + 0xD65D, 0x727B, 0xD65E, 0x727C, 0xD65F, 0x727F, 0xD660, 0x731D, 0xD661, 0x7317, 0xD662, 0x7307, 0xD663, 0x7311, 0xD664, 0x7318, + 0xD665, 0x730A, 0xD666, 0x7308, 0xD667, 0x72FF, 0xD668, 0x730F, 0xD669, 0x731E, 0xD66A, 0x7388, 0xD66B, 0x73F6, 0xD66C, 0x73F8, + 0xD66D, 0x73F5, 0xD66E, 0x7404, 0xD66F, 0x7401, 0xD670, 0x73FD, 0xD671, 0x7407, 0xD672, 0x7400, 0xD673, 0x73FA, 0xD674, 0x73FC, + 0xD675, 0x73FF, 0xD676, 0x740C, 0xD677, 0x740B, 0xD678, 0x73F4, 0xD679, 0x7408, 0xD67A, 0x7564, 0xD67B, 0x7563, 0xD67C, 0x75CE, + 0xD67D, 0x75D2, 0xD67E, 0x75CF, 0xD6A1, 0x75CB, 0xD6A2, 0x75CC, 0xD6A3, 0x75D1, 0xD6A4, 0x75D0, 0xD6A5, 0x768F, 0xD6A6, 0x7689, + 0xD6A7, 0x76D3, 0xD6A8, 0x7739, 0xD6A9, 0x772F, 0xD6AA, 0x772D, 0xD6AB, 0x7731, 0xD6AC, 0x7732, 0xD6AD, 0x7734, 0xD6AE, 0x7733, + 0xD6AF, 0x773D, 0xD6B0, 0x7725, 0xD6B1, 0x773B, 0xD6B2, 0x7735, 0xD6B3, 0x7848, 0xD6B4, 0x7852, 0xD6B5, 0x7849, 0xD6B6, 0x784D, + 0xD6B7, 0x784A, 0xD6B8, 0x784C, 0xD6B9, 0x7826, 0xD6BA, 0x7845, 0xD6BB, 0x7850, 0xD6BC, 0x7964, 0xD6BD, 0x7967, 0xD6BE, 0x7969, + 0xD6BF, 0x796A, 0xD6C0, 0x7963, 0xD6C1, 0x796B, 0xD6C2, 0x7961, 0xD6C3, 0x79BB, 0xD6C4, 0x79FA, 0xD6C5, 0x79F8, 0xD6C6, 0x79F6, + 0xD6C7, 0x79F7, 0xD6C8, 0x7A8F, 0xD6C9, 0x7A94, 0xD6CA, 0x7A90, 0xD6CB, 0x7B35, 0xD6CC, 0x7B47, 0xD6CD, 0x7B34, 0xD6CE, 0x7B25, + 0xD6CF, 0x7B30, 0xD6D0, 0x7B22, 0xD6D1, 0x7B24, 0xD6D2, 0x7B33, 0xD6D3, 0x7B18, 0xD6D4, 0x7B2A, 0xD6D5, 0x7B1D, 0xD6D6, 0x7B31, + 0xD6D7, 0x7B2B, 0xD6D8, 0x7B2D, 0xD6D9, 0x7B2F, 0xD6DA, 0x7B32, 0xD6DB, 0x7B38, 0xD6DC, 0x7B1A, 0xD6DD, 0x7B23, 0xD6DE, 0x7C94, + 0xD6DF, 0x7C98, 0xD6E0, 0x7C96, 0xD6E1, 0x7CA3, 0xD6E2, 0x7D35, 0xD6E3, 0x7D3D, 0xD6E4, 0x7D38, 0xD6E5, 0x7D36, 0xD6E6, 0x7D3A, + 0xD6E7, 0x7D45, 0xD6E8, 0x7D2C, 0xD6E9, 0x7D29, 0xD6EA, 0x7D41, 0xD6EB, 0x7D47, 0xD6EC, 0x7D3E, 0xD6ED, 0x7D3F, 0xD6EE, 0x7D4A, + 0xD6EF, 0x7D3B, 0xD6F0, 0x7D28, 0xD6F1, 0x7F63, 0xD6F2, 0x7F95, 0xD6F3, 0x7F9C, 0xD6F4, 0x7F9D, 0xD6F5, 0x7F9B, 0xD6F6, 0x7FCA, + 0xD6F7, 0x7FCB, 0xD6F8, 0x7FCD, 0xD6F9, 0x7FD0, 0xD6FA, 0x7FD1, 0xD6FB, 0x7FC7, 0xD6FC, 0x7FCF, 0xD6FD, 0x7FC9, 0xD6FE, 0x801F, + 0xD740, 0x801E, 0xD741, 0x801B, 0xD742, 0x8047, 0xD743, 0x8043, 0xD744, 0x8048, 0xD745, 0x8118, 0xD746, 0x8125, 0xD747, 0x8119, + 0xD748, 0x811B, 0xD749, 0x812D, 0xD74A, 0x811F, 0xD74B, 0x812C, 0xD74C, 0x811E, 0xD74D, 0x8121, 0xD74E, 0x8115, 0xD74F, 0x8127, + 0xD750, 0x811D, 0xD751, 0x8122, 0xD752, 0x8211, 0xD753, 0x8238, 0xD754, 0x8233, 0xD755, 0x823A, 0xD756, 0x8234, 0xD757, 0x8232, + 0xD758, 0x8274, 0xD759, 0x8390, 0xD75A, 0x83A3, 0xD75B, 0x83A8, 0xD75C, 0x838D, 0xD75D, 0x837A, 0xD75E, 0x8373, 0xD75F, 0x83A4, + 0xD760, 0x8374, 0xD761, 0x838F, 0xD762, 0x8381, 0xD763, 0x8395, 0xD764, 0x8399, 0xD765, 0x8375, 0xD766, 0x8394, 0xD767, 0x83A9, + 0xD768, 0x837D, 0xD769, 0x8383, 0xD76A, 0x838C, 0xD76B, 0x839D, 0xD76C, 0x839B, 0xD76D, 0x83AA, 0xD76E, 0x838B, 0xD76F, 0x837E, + 0xD770, 0x83A5, 0xD771, 0x83AF, 0xD772, 0x8388, 0xD773, 0x8397, 0xD774, 0x83B0, 0xD775, 0x837F, 0xD776, 0x83A6, 0xD777, 0x8387, + 0xD778, 0x83AE, 0xD779, 0x8376, 0xD77A, 0x839A, 0xD77B, 0x8659, 0xD77C, 0x8656, 0xD77D, 0x86BF, 0xD77E, 0x86B7, 0xD7A1, 0x86C2, + 0xD7A2, 0x86C1, 0xD7A3, 0x86C5, 0xD7A4, 0x86BA, 0xD7A5, 0x86B0, 0xD7A6, 0x86C8, 0xD7A7, 0x86B9, 0xD7A8, 0x86B3, 0xD7A9, 0x86B8, + 0xD7AA, 0x86CC, 0xD7AB, 0x86B4, 0xD7AC, 0x86BB, 0xD7AD, 0x86BC, 0xD7AE, 0x86C3, 0xD7AF, 0x86BD, 0xD7B0, 0x86BE, 0xD7B1, 0x8852, + 0xD7B2, 0x8889, 0xD7B3, 0x8895, 0xD7B4, 0x88A8, 0xD7B5, 0x88A2, 0xD7B6, 0x88AA, 0xD7B7, 0x889A, 0xD7B8, 0x8891, 0xD7B9, 0x88A1, + 0xD7BA, 0x889F, 0xD7BB, 0x8898, 0xD7BC, 0x88A7, 0xD7BD, 0x8899, 0xD7BE, 0x889B, 0xD7BF, 0x8897, 0xD7C0, 0x88A4, 0xD7C1, 0x88AC, + 0xD7C2, 0x888C, 0xD7C3, 0x8893, 0xD7C4, 0x888E, 0xD7C5, 0x8982, 0xD7C6, 0x89D6, 0xD7C7, 0x89D9, 0xD7C8, 0x89D5, 0xD7C9, 0x8A30, + 0xD7CA, 0x8A27, 0xD7CB, 0x8A2C, 0xD7CC, 0x8A1E, 0xD7CD, 0x8C39, 0xD7CE, 0x8C3B, 0xD7CF, 0x8C5C, 0xD7D0, 0x8C5D, 0xD7D1, 0x8C7D, + 0xD7D2, 0x8CA5, 0xD7D3, 0x8D7D, 0xD7D4, 0x8D7B, 0xD7D5, 0x8D79, 0xD7D6, 0x8DBC, 0xD7D7, 0x8DC2, 0xD7D8, 0x8DB9, 0xD7D9, 0x8DBF, + 0xD7DA, 0x8DC1, 0xD7DB, 0x8ED8, 0xD7DC, 0x8EDE, 0xD7DD, 0x8EDD, 0xD7DE, 0x8EDC, 0xD7DF, 0x8ED7, 0xD7E0, 0x8EE0, 0xD7E1, 0x8EE1, + 0xD7E2, 0x9024, 0xD7E3, 0x900B, 0xD7E4, 0x9011, 0xD7E5, 0x901C, 0xD7E6, 0x900C, 0xD7E7, 0x9021, 0xD7E8, 0x90EF, 0xD7E9, 0x90EA, + 0xD7EA, 0x90F0, 0xD7EB, 0x90F4, 0xD7EC, 0x90F2, 0xD7ED, 0x90F3, 0xD7EE, 0x90D4, 0xD7EF, 0x90EB, 0xD7F0, 0x90EC, 0xD7F1, 0x90E9, + 0xD7F2, 0x9156, 0xD7F3, 0x9158, 0xD7F4, 0x915A, 0xD7F5, 0x9153, 0xD7F6, 0x9155, 0xD7F7, 0x91EC, 0xD7F8, 0x91F4, 0xD7F9, 0x91F1, + 0xD7FA, 0x91F3, 0xD7FB, 0x91F8, 0xD7FC, 0x91E4, 0xD7FD, 0x91F9, 0xD7FE, 0x91EA, 0xD840, 0x91EB, 0xD841, 0x91F7, 0xD842, 0x91E8, + 0xD843, 0x91EE, 0xD844, 0x957A, 0xD845, 0x9586, 0xD846, 0x9588, 0xD847, 0x967C, 0xD848, 0x966D, 0xD849, 0x966B, 0xD84A, 0x9671, + 0xD84B, 0x966F, 0xD84C, 0x96BF, 0xD84D, 0x976A, 0xD84E, 0x9804, 0xD84F, 0x98E5, 0xD850, 0x9997, 0xD851, 0x509B, 0xD852, 0x5095, + 0xD853, 0x5094, 0xD854, 0x509E, 0xD855, 0x508B, 0xD856, 0x50A3, 0xD857, 0x5083, 0xD858, 0x508C, 0xD859, 0x508E, 0xD85A, 0x509D, + 0xD85B, 0x5068, 0xD85C, 0x509C, 0xD85D, 0x5092, 0xD85E, 0x5082, 0xD85F, 0x5087, 0xD860, 0x515F, 0xD861, 0x51D4, 0xD862, 0x5312, + 0xD863, 0x5311, 0xD864, 0x53A4, 0xD865, 0x53A7, 0xD866, 0x5591, 0xD867, 0x55A8, 0xD868, 0x55A5, 0xD869, 0x55AD, 0xD86A, 0x5577, + 0xD86B, 0x5645, 0xD86C, 0x55A2, 0xD86D, 0x5593, 0xD86E, 0x5588, 0xD86F, 0x558F, 0xD870, 0x55B5, 0xD871, 0x5581, 0xD872, 0x55A3, + 0xD873, 0x5592, 0xD874, 0x55A4, 0xD875, 0x557D, 0xD876, 0x558C, 0xD877, 0x55A6, 0xD878, 0x557F, 0xD879, 0x5595, 0xD87A, 0x55A1, + 0xD87B, 0x558E, 0xD87C, 0x570C, 0xD87D, 0x5829, 0xD87E, 0x5837, 0xD8A1, 0x5819, 0xD8A2, 0x581E, 0xD8A3, 0x5827, 0xD8A4, 0x5823, + 0xD8A5, 0x5828, 0xD8A6, 0x57F5, 0xD8A7, 0x5848, 0xD8A8, 0x5825, 0xD8A9, 0x581C, 0xD8AA, 0x581B, 0xD8AB, 0x5833, 0xD8AC, 0x583F, + 0xD8AD, 0x5836, 0xD8AE, 0x582E, 0xD8AF, 0x5839, 0xD8B0, 0x5838, 0xD8B1, 0x582D, 0xD8B2, 0x582C, 0xD8B3, 0x583B, 0xD8B4, 0x5961, + 0xD8B5, 0x5AAF, 0xD8B6, 0x5A94, 0xD8B7, 0x5A9F, 0xD8B8, 0x5A7A, 0xD8B9, 0x5AA2, 0xD8BA, 0x5A9E, 0xD8BB, 0x5A78, 0xD8BC, 0x5AA6, + 0xD8BD, 0x5A7C, 0xD8BE, 0x5AA5, 0xD8BF, 0x5AAC, 0xD8C0, 0x5A95, 0xD8C1, 0x5AAE, 0xD8C2, 0x5A37, 0xD8C3, 0x5A84, 0xD8C4, 0x5A8A, + 0xD8C5, 0x5A97, 0xD8C6, 0x5A83, 0xD8C7, 0x5A8B, 0xD8C8, 0x5AA9, 0xD8C9, 0x5A7B, 0xD8CA, 0x5A7D, 0xD8CB, 0x5A8C, 0xD8CC, 0x5A9C, + 0xD8CD, 0x5A8F, 0xD8CE, 0x5A93, 0xD8CF, 0x5A9D, 0xD8D0, 0x5BEA, 0xD8D1, 0x5BCD, 0xD8D2, 0x5BCB, 0xD8D3, 0x5BD4, 0xD8D4, 0x5BD1, + 0xD8D5, 0x5BCA, 0xD8D6, 0x5BCE, 0xD8D7, 0x5C0C, 0xD8D8, 0x5C30, 0xD8D9, 0x5D37, 0xD8DA, 0x5D43, 0xD8DB, 0x5D6B, 0xD8DC, 0x5D41, + 0xD8DD, 0x5D4B, 0xD8DE, 0x5D3F, 0xD8DF, 0x5D35, 0xD8E0, 0x5D51, 0xD8E1, 0x5D4E, 0xD8E2, 0x5D55, 0xD8E3, 0x5D33, 0xD8E4, 0x5D3A, + 0xD8E5, 0x5D52, 0xD8E6, 0x5D3D, 0xD8E7, 0x5D31, 0xD8E8, 0x5D59, 0xD8E9, 0x5D42, 0xD8EA, 0x5D39, 0xD8EB, 0x5D49, 0xD8EC, 0x5D38, + 0xD8ED, 0x5D3C, 0xD8EE, 0x5D32, 0xD8EF, 0x5D36, 0xD8F0, 0x5D40, 0xD8F1, 0x5D45, 0xD8F2, 0x5E44, 0xD8F3, 0x5E41, 0xD8F4, 0x5F58, + 0xD8F5, 0x5FA6, 0xD8F6, 0x5FA5, 0xD8F7, 0x5FAB, 0xD8F8, 0x60C9, 0xD8F9, 0x60B9, 0xD8FA, 0x60CC, 0xD8FB, 0x60E2, 0xD8FC, 0x60CE, + 0xD8FD, 0x60C4, 0xD8FE, 0x6114, 0xD940, 0x60F2, 0xD941, 0x610A, 0xD942, 0x6116, 0xD943, 0x6105, 0xD944, 0x60F5, 0xD945, 0x6113, + 0xD946, 0x60F8, 0xD947, 0x60FC, 0xD948, 0x60FE, 0xD949, 0x60C1, 0xD94A, 0x6103, 0xD94B, 0x6118, 0xD94C, 0x611D, 0xD94D, 0x6110, + 0xD94E, 0x60FF, 0xD94F, 0x6104, 0xD950, 0x610B, 0xD951, 0x624A, 0xD952, 0x6394, 0xD953, 0x63B1, 0xD954, 0x63B0, 0xD955, 0x63CE, + 0xD956, 0x63E5, 0xD957, 0x63E8, 0xD958, 0x63EF, 0xD959, 0x63C3, 0xD95A, 0x649D, 0xD95B, 0x63F3, 0xD95C, 0x63CA, 0xD95D, 0x63E0, + 0xD95E, 0x63F6, 0xD95F, 0x63D5, 0xD960, 0x63F2, 0xD961, 0x63F5, 0xD962, 0x6461, 0xD963, 0x63DF, 0xD964, 0x63BE, 0xD965, 0x63DD, + 0xD966, 0x63DC, 0xD967, 0x63C4, 0xD968, 0x63D8, 0xD969, 0x63D3, 0xD96A, 0x63C2, 0xD96B, 0x63C7, 0xD96C, 0x63CC, 0xD96D, 0x63CB, + 0xD96E, 0x63C8, 0xD96F, 0x63F0, 0xD970, 0x63D7, 0xD971, 0x63D9, 0xD972, 0x6532, 0xD973, 0x6567, 0xD974, 0x656A, 0xD975, 0x6564, + 0xD976, 0x655C, 0xD977, 0x6568, 0xD978, 0x6565, 0xD979, 0x658C, 0xD97A, 0x659D, 0xD97B, 0x659E, 0xD97C, 0x65AE, 0xD97D, 0x65D0, + 0xD97E, 0x65D2, 0xD9A1, 0x667C, 0xD9A2, 0x666C, 0xD9A3, 0x667B, 0xD9A4, 0x6680, 0xD9A5, 0x6671, 0xD9A6, 0x6679, 0xD9A7, 0x666A, + 0xD9A8, 0x6672, 0xD9A9, 0x6701, 0xD9AA, 0x690C, 0xD9AB, 0x68D3, 0xD9AC, 0x6904, 0xD9AD, 0x68DC, 0xD9AE, 0x692A, 0xD9AF, 0x68EC, + 0xD9B0, 0x68EA, 0xD9B1, 0x68F1, 0xD9B2, 0x690F, 0xD9B3, 0x68D6, 0xD9B4, 0x68F7, 0xD9B5, 0x68EB, 0xD9B6, 0x68E4, 0xD9B7, 0x68F6, + 0xD9B8, 0x6913, 0xD9B9, 0x6910, 0xD9BA, 0x68F3, 0xD9BB, 0x68E1, 0xD9BC, 0x6907, 0xD9BD, 0x68CC, 0xD9BE, 0x6908, 0xD9BF, 0x6970, + 0xD9C0, 0x68B4, 0xD9C1, 0x6911, 0xD9C2, 0x68EF, 0xD9C3, 0x68C6, 0xD9C4, 0x6914, 0xD9C5, 0x68F8, 0xD9C6, 0x68D0, 0xD9C7, 0x68FD, + 0xD9C8, 0x68FC, 0xD9C9, 0x68E8, 0xD9CA, 0x690B, 0xD9CB, 0x690A, 0xD9CC, 0x6917, 0xD9CD, 0x68CE, 0xD9CE, 0x68C8, 0xD9CF, 0x68DD, + 0xD9D0, 0x68DE, 0xD9D1, 0x68E6, 0xD9D2, 0x68F4, 0xD9D3, 0x68D1, 0xD9D4, 0x6906, 0xD9D5, 0x68D4, 0xD9D6, 0x68E9, 0xD9D7, 0x6915, + 0xD9D8, 0x6925, 0xD9D9, 0x68C7, 0xD9DA, 0x6B39, 0xD9DB, 0x6B3B, 0xD9DC, 0x6B3F, 0xD9DD, 0x6B3C, 0xD9DE, 0x6B94, 0xD9DF, 0x6B97, + 0xD9E0, 0x6B99, 0xD9E1, 0x6B95, 0xD9E2, 0x6BBD, 0xD9E3, 0x6BF0, 0xD9E4, 0x6BF2, 0xD9E5, 0x6BF3, 0xD9E6, 0x6C30, 0xD9E7, 0x6DFC, + 0xD9E8, 0x6E46, 0xD9E9, 0x6E47, 0xD9EA, 0x6E1F, 0xD9EB, 0x6E49, 0xD9EC, 0x6E88, 0xD9ED, 0x6E3C, 0xD9EE, 0x6E3D, 0xD9EF, 0x6E45, + 0xD9F0, 0x6E62, 0xD9F1, 0x6E2B, 0xD9F2, 0x6E3F, 0xD9F3, 0x6E41, 0xD9F4, 0x6E5D, 0xD9F5, 0x6E73, 0xD9F6, 0x6E1C, 0xD9F7, 0x6E33, + 0xD9F8, 0x6E4B, 0xD9F9, 0x6E40, 0xD9FA, 0x6E51, 0xD9FB, 0x6E3B, 0xD9FC, 0x6E03, 0xD9FD, 0x6E2E, 0xD9FE, 0x6E5E, 0xDA40, 0x6E68, + 0xDA41, 0x6E5C, 0xDA42, 0x6E61, 0xDA43, 0x6E31, 0xDA44, 0x6E28, 0xDA45, 0x6E60, 0xDA46, 0x6E71, 0xDA47, 0x6E6B, 0xDA48, 0x6E39, + 0xDA49, 0x6E22, 0xDA4A, 0x6E30, 0xDA4B, 0x6E53, 0xDA4C, 0x6E65, 0xDA4D, 0x6E27, 0xDA4E, 0x6E78, 0xDA4F, 0x6E64, 0xDA50, 0x6E77, + 0xDA51, 0x6E55, 0xDA52, 0x6E79, 0xDA53, 0x6E52, 0xDA54, 0x6E66, 0xDA55, 0x6E35, 0xDA56, 0x6E36, 0xDA57, 0x6E5A, 0xDA58, 0x7120, + 0xDA59, 0x711E, 0xDA5A, 0x712F, 0xDA5B, 0x70FB, 0xDA5C, 0x712E, 0xDA5D, 0x7131, 0xDA5E, 0x7123, 0xDA5F, 0x7125, 0xDA60, 0x7122, + 0xDA61, 0x7132, 0xDA62, 0x711F, 0xDA63, 0x7128, 0xDA64, 0x713A, 0xDA65, 0x711B, 0xDA66, 0x724B, 0xDA67, 0x725A, 0xDA68, 0x7288, + 0xDA69, 0x7289, 0xDA6A, 0x7286, 0xDA6B, 0x7285, 0xDA6C, 0x728B, 0xDA6D, 0x7312, 0xDA6E, 0x730B, 0xDA6F, 0x7330, 0xDA70, 0x7322, + 0xDA71, 0x7331, 0xDA72, 0x7333, 0xDA73, 0x7327, 0xDA74, 0x7332, 0xDA75, 0x732D, 0xDA76, 0x7326, 0xDA77, 0x7323, 0xDA78, 0x7335, + 0xDA79, 0x730C, 0xDA7A, 0x742E, 0xDA7B, 0x742C, 0xDA7C, 0x7430, 0xDA7D, 0x742B, 0xDA7E, 0x7416, 0xDAA1, 0x741A, 0xDAA2, 0x7421, + 0xDAA3, 0x742D, 0xDAA4, 0x7431, 0xDAA5, 0x7424, 0xDAA6, 0x7423, 0xDAA7, 0x741D, 0xDAA8, 0x7429, 0xDAA9, 0x7420, 0xDAAA, 0x7432, + 0xDAAB, 0x74FB, 0xDAAC, 0x752F, 0xDAAD, 0x756F, 0xDAAE, 0x756C, 0xDAAF, 0x75E7, 0xDAB0, 0x75DA, 0xDAB1, 0x75E1, 0xDAB2, 0x75E6, + 0xDAB3, 0x75DD, 0xDAB4, 0x75DF, 0xDAB5, 0x75E4, 0xDAB6, 0x75D7, 0xDAB7, 0x7695, 0xDAB8, 0x7692, 0xDAB9, 0x76DA, 0xDABA, 0x7746, + 0xDABB, 0x7747, 0xDABC, 0x7744, 0xDABD, 0x774D, 0xDABE, 0x7745, 0xDABF, 0x774A, 0xDAC0, 0x774E, 0xDAC1, 0x774B, 0xDAC2, 0x774C, + 0xDAC3, 0x77DE, 0xDAC4, 0x77EC, 0xDAC5, 0x7860, 0xDAC6, 0x7864, 0xDAC7, 0x7865, 0xDAC8, 0x785C, 0xDAC9, 0x786D, 0xDACA, 0x7871, + 0xDACB, 0x786A, 0xDACC, 0x786E, 0xDACD, 0x7870, 0xDACE, 0x7869, 0xDACF, 0x7868, 0xDAD0, 0x785E, 0xDAD1, 0x7862, 0xDAD2, 0x7974, + 0xDAD3, 0x7973, 0xDAD4, 0x7972, 0xDAD5, 0x7970, 0xDAD6, 0x7A02, 0xDAD7, 0x7A0A, 0xDAD8, 0x7A03, 0xDAD9, 0x7A0C, 0xDADA, 0x7A04, + 0xDADB, 0x7A99, 0xDADC, 0x7AE6, 0xDADD, 0x7AE4, 0xDADE, 0x7B4A, 0xDADF, 0x7B3B, 0xDAE0, 0x7B44, 0xDAE1, 0x7B48, 0xDAE2, 0x7B4C, + 0xDAE3, 0x7B4E, 0xDAE4, 0x7B40, 0xDAE5, 0x7B58, 0xDAE6, 0x7B45, 0xDAE7, 0x7CA2, 0xDAE8, 0x7C9E, 0xDAE9, 0x7CA8, 0xDAEA, 0x7CA1, + 0xDAEB, 0x7D58, 0xDAEC, 0x7D6F, 0xDAED, 0x7D63, 0xDAEE, 0x7D53, 0xDAEF, 0x7D56, 0xDAF0, 0x7D67, 0xDAF1, 0x7D6A, 0xDAF2, 0x7D4F, + 0xDAF3, 0x7D6D, 0xDAF4, 0x7D5C, 0xDAF5, 0x7D6B, 0xDAF6, 0x7D52, 0xDAF7, 0x7D54, 0xDAF8, 0x7D69, 0xDAF9, 0x7D51, 0xDAFA, 0x7D5F, + 0xDAFB, 0x7D4E, 0xDAFC, 0x7F3E, 0xDAFD, 0x7F3F, 0xDAFE, 0x7F65, 0xDB40, 0x7F66, 0xDB41, 0x7FA2, 0xDB42, 0x7FA0, 0xDB43, 0x7FA1, + 0xDB44, 0x7FD7, 0xDB45, 0x8051, 0xDB46, 0x804F, 0xDB47, 0x8050, 0xDB48, 0x80FE, 0xDB49, 0x80D4, 0xDB4A, 0x8143, 0xDB4B, 0x814A, + 0xDB4C, 0x8152, 0xDB4D, 0x814F, 0xDB4E, 0x8147, 0xDB4F, 0x813D, 0xDB50, 0x814D, 0xDB51, 0x813A, 0xDB52, 0x81E6, 0xDB53, 0x81EE, + 0xDB54, 0x81F7, 0xDB55, 0x81F8, 0xDB56, 0x81F9, 0xDB57, 0x8204, 0xDB58, 0x823C, 0xDB59, 0x823D, 0xDB5A, 0x823F, 0xDB5B, 0x8275, + 0xDB5C, 0x833B, 0xDB5D, 0x83CF, 0xDB5E, 0x83F9, 0xDB5F, 0x8423, 0xDB60, 0x83C0, 0xDB61, 0x83E8, 0xDB62, 0x8412, 0xDB63, 0x83E7, + 0xDB64, 0x83E4, 0xDB65, 0x83FC, 0xDB66, 0x83F6, 0xDB67, 0x8410, 0xDB68, 0x83C6, 0xDB69, 0x83C8, 0xDB6A, 0x83EB, 0xDB6B, 0x83E3, + 0xDB6C, 0x83BF, 0xDB6D, 0x8401, 0xDB6E, 0x83DD, 0xDB6F, 0x83E5, 0xDB70, 0x83D8, 0xDB71, 0x83FF, 0xDB72, 0x83E1, 0xDB73, 0x83CB, + 0xDB74, 0x83CE, 0xDB75, 0x83D6, 0xDB76, 0x83F5, 0xDB77, 0x83C9, 0xDB78, 0x8409, 0xDB79, 0x840F, 0xDB7A, 0x83DE, 0xDB7B, 0x8411, + 0xDB7C, 0x8406, 0xDB7D, 0x83C2, 0xDB7E, 0x83F3, 0xDBA1, 0x83D5, 0xDBA2, 0x83FA, 0xDBA3, 0x83C7, 0xDBA4, 0x83D1, 0xDBA5, 0x83EA, + 0xDBA6, 0x8413, 0xDBA7, 0x83C3, 0xDBA8, 0x83EC, 0xDBA9, 0x83EE, 0xDBAA, 0x83C4, 0xDBAB, 0x83FB, 0xDBAC, 0x83D7, 0xDBAD, 0x83E2, + 0xDBAE, 0x841B, 0xDBAF, 0x83DB, 0xDBB0, 0x83FE, 0xDBB1, 0x86D8, 0xDBB2, 0x86E2, 0xDBB3, 0x86E6, 0xDBB4, 0x86D3, 0xDBB5, 0x86E3, + 0xDBB6, 0x86DA, 0xDBB7, 0x86EA, 0xDBB8, 0x86DD, 0xDBB9, 0x86EB, 0xDBBA, 0x86DC, 0xDBBB, 0x86EC, 0xDBBC, 0x86E9, 0xDBBD, 0x86D7, + 0xDBBE, 0x86E8, 0xDBBF, 0x86D1, 0xDBC0, 0x8848, 0xDBC1, 0x8856, 0xDBC2, 0x8855, 0xDBC3, 0x88BA, 0xDBC4, 0x88D7, 0xDBC5, 0x88B9, + 0xDBC6, 0x88B8, 0xDBC7, 0x88C0, 0xDBC8, 0x88BE, 0xDBC9, 0x88B6, 0xDBCA, 0x88BC, 0xDBCB, 0x88B7, 0xDBCC, 0x88BD, 0xDBCD, 0x88B2, + 0xDBCE, 0x8901, 0xDBCF, 0x88C9, 0xDBD0, 0x8995, 0xDBD1, 0x8998, 0xDBD2, 0x8997, 0xDBD3, 0x89DD, 0xDBD4, 0x89DA, 0xDBD5, 0x89DB, + 0xDBD6, 0x8A4E, 0xDBD7, 0x8A4D, 0xDBD8, 0x8A39, 0xDBD9, 0x8A59, 0xDBDA, 0x8A40, 0xDBDB, 0x8A57, 0xDBDC, 0x8A58, 0xDBDD, 0x8A44, + 0xDBDE, 0x8A45, 0xDBDF, 0x8A52, 0xDBE0, 0x8A48, 0xDBE1, 0x8A51, 0xDBE2, 0x8A4A, 0xDBE3, 0x8A4C, 0xDBE4, 0x8A4F, 0xDBE5, 0x8C5F, + 0xDBE6, 0x8C81, 0xDBE7, 0x8C80, 0xDBE8, 0x8CBA, 0xDBE9, 0x8CBE, 0xDBEA, 0x8CB0, 0xDBEB, 0x8CB9, 0xDBEC, 0x8CB5, 0xDBED, 0x8D84, + 0xDBEE, 0x8D80, 0xDBEF, 0x8D89, 0xDBF0, 0x8DD8, 0xDBF1, 0x8DD3, 0xDBF2, 0x8DCD, 0xDBF3, 0x8DC7, 0xDBF4, 0x8DD6, 0xDBF5, 0x8DDC, + 0xDBF6, 0x8DCF, 0xDBF7, 0x8DD5, 0xDBF8, 0x8DD9, 0xDBF9, 0x8DC8, 0xDBFA, 0x8DD7, 0xDBFB, 0x8DC5, 0xDBFC, 0x8EEF, 0xDBFD, 0x8EF7, + 0xDBFE, 0x8EFA, 0xDC40, 0x8EF9, 0xDC41, 0x8EE6, 0xDC42, 0x8EEE, 0xDC43, 0x8EE5, 0xDC44, 0x8EF5, 0xDC45, 0x8EE7, 0xDC46, 0x8EE8, + 0xDC47, 0x8EF6, 0xDC48, 0x8EEB, 0xDC49, 0x8EF1, 0xDC4A, 0x8EEC, 0xDC4B, 0x8EF4, 0xDC4C, 0x8EE9, 0xDC4D, 0x902D, 0xDC4E, 0x9034, + 0xDC4F, 0x902F, 0xDC50, 0x9106, 0xDC51, 0x912C, 0xDC52, 0x9104, 0xDC53, 0x90FF, 0xDC54, 0x90FC, 0xDC55, 0x9108, 0xDC56, 0x90F9, + 0xDC57, 0x90FB, 0xDC58, 0x9101, 0xDC59, 0x9100, 0xDC5A, 0x9107, 0xDC5B, 0x9105, 0xDC5C, 0x9103, 0xDC5D, 0x9161, 0xDC5E, 0x9164, + 0xDC5F, 0x915F, 0xDC60, 0x9162, 0xDC61, 0x9160, 0xDC62, 0x9201, 0xDC63, 0x920A, 0xDC64, 0x9225, 0xDC65, 0x9203, 0xDC66, 0x921A, + 0xDC67, 0x9226, 0xDC68, 0x920F, 0xDC69, 0x920C, 0xDC6A, 0x9200, 0xDC6B, 0x9212, 0xDC6C, 0x91FF, 0xDC6D, 0x91FD, 0xDC6E, 0x9206, + 0xDC6F, 0x9204, 0xDC70, 0x9227, 0xDC71, 0x9202, 0xDC72, 0x921C, 0xDC73, 0x9224, 0xDC74, 0x9219, 0xDC75, 0x9217, 0xDC76, 0x9205, + 0xDC77, 0x9216, 0xDC78, 0x957B, 0xDC79, 0x958D, 0xDC7A, 0x958C, 0xDC7B, 0x9590, 0xDC7C, 0x9687, 0xDC7D, 0x967E, 0xDC7E, 0x9688, + 0xDCA1, 0x9689, 0xDCA2, 0x9683, 0xDCA3, 0x9680, 0xDCA4, 0x96C2, 0xDCA5, 0x96C8, 0xDCA6, 0x96C3, 0xDCA7, 0x96F1, 0xDCA8, 0x96F0, + 0xDCA9, 0x976C, 0xDCAA, 0x9770, 0xDCAB, 0x976E, 0xDCAC, 0x9807, 0xDCAD, 0x98A9, 0xDCAE, 0x98EB, 0xDCAF, 0x9CE6, 0xDCB0, 0x9EF9, + 0xDCB1, 0x4E83, 0xDCB2, 0x4E84, 0xDCB3, 0x4EB6, 0xDCB4, 0x50BD, 0xDCB5, 0x50BF, 0xDCB6, 0x50C6, 0xDCB7, 0x50AE, 0xDCB8, 0x50C4, + 0xDCB9, 0x50CA, 0xDCBA, 0x50B4, 0xDCBB, 0x50C8, 0xDCBC, 0x50C2, 0xDCBD, 0x50B0, 0xDCBE, 0x50C1, 0xDCBF, 0x50BA, 0xDCC0, 0x50B1, + 0xDCC1, 0x50CB, 0xDCC2, 0x50C9, 0xDCC3, 0x50B6, 0xDCC4, 0x50B8, 0xDCC5, 0x51D7, 0xDCC6, 0x527A, 0xDCC7, 0x5278, 0xDCC8, 0x527B, + 0xDCC9, 0x527C, 0xDCCA, 0x55C3, 0xDCCB, 0x55DB, 0xDCCC, 0x55CC, 0xDCCD, 0x55D0, 0xDCCE, 0x55CB, 0xDCCF, 0x55CA, 0xDCD0, 0x55DD, + 0xDCD1, 0x55C0, 0xDCD2, 0x55D4, 0xDCD3, 0x55C4, 0xDCD4, 0x55E9, 0xDCD5, 0x55BF, 0xDCD6, 0x55D2, 0xDCD7, 0x558D, 0xDCD8, 0x55CF, + 0xDCD9, 0x55D5, 0xDCDA, 0x55E2, 0xDCDB, 0x55D6, 0xDCDC, 0x55C8, 0xDCDD, 0x55F2, 0xDCDE, 0x55CD, 0xDCDF, 0x55D9, 0xDCE0, 0x55C2, + 0xDCE1, 0x5714, 0xDCE2, 0x5853, 0xDCE3, 0x5868, 0xDCE4, 0x5864, 0xDCE5, 0x584F, 0xDCE6, 0x584D, 0xDCE7, 0x5849, 0xDCE8, 0x586F, + 0xDCE9, 0x5855, 0xDCEA, 0x584E, 0xDCEB, 0x585D, 0xDCEC, 0x5859, 0xDCED, 0x5865, 0xDCEE, 0x585B, 0xDCEF, 0x583D, 0xDCF0, 0x5863, + 0xDCF1, 0x5871, 0xDCF2, 0x58FC, 0xDCF3, 0x5AC7, 0xDCF4, 0x5AC4, 0xDCF5, 0x5ACB, 0xDCF6, 0x5ABA, 0xDCF7, 0x5AB8, 0xDCF8, 0x5AB1, + 0xDCF9, 0x5AB5, 0xDCFA, 0x5AB0, 0xDCFB, 0x5ABF, 0xDCFC, 0x5AC8, 0xDCFD, 0x5ABB, 0xDCFE, 0x5AC6, 0xDD40, 0x5AB7, 0xDD41, 0x5AC0, + 0xDD42, 0x5ACA, 0xDD43, 0x5AB4, 0xDD44, 0x5AB6, 0xDD45, 0x5ACD, 0xDD46, 0x5AB9, 0xDD47, 0x5A90, 0xDD48, 0x5BD6, 0xDD49, 0x5BD8, + 0xDD4A, 0x5BD9, 0xDD4B, 0x5C1F, 0xDD4C, 0x5C33, 0xDD4D, 0x5D71, 0xDD4E, 0x5D63, 0xDD4F, 0x5D4A, 0xDD50, 0x5D65, 0xDD51, 0x5D72, + 0xDD52, 0x5D6C, 0xDD53, 0x5D5E, 0xDD54, 0x5D68, 0xDD55, 0x5D67, 0xDD56, 0x5D62, 0xDD57, 0x5DF0, 0xDD58, 0x5E4F, 0xDD59, 0x5E4E, + 0xDD5A, 0x5E4A, 0xDD5B, 0x5E4D, 0xDD5C, 0x5E4B, 0xDD5D, 0x5EC5, 0xDD5E, 0x5ECC, 0xDD5F, 0x5EC6, 0xDD60, 0x5ECB, 0xDD61, 0x5EC7, + 0xDD62, 0x5F40, 0xDD63, 0x5FAF, 0xDD64, 0x5FAD, 0xDD65, 0x60F7, 0xDD66, 0x6149, 0xDD67, 0x614A, 0xDD68, 0x612B, 0xDD69, 0x6145, + 0xDD6A, 0x6136, 0xDD6B, 0x6132, 0xDD6C, 0x612E, 0xDD6D, 0x6146, 0xDD6E, 0x612F, 0xDD6F, 0x614F, 0xDD70, 0x6129, 0xDD71, 0x6140, + 0xDD72, 0x6220, 0xDD73, 0x9168, 0xDD74, 0x6223, 0xDD75, 0x6225, 0xDD76, 0x6224, 0xDD77, 0x63C5, 0xDD78, 0x63F1, 0xDD79, 0x63EB, + 0xDD7A, 0x6410, 0xDD7B, 0x6412, 0xDD7C, 0x6409, 0xDD7D, 0x6420, 0xDD7E, 0x6424, 0xDDA1, 0x6433, 0xDDA2, 0x6443, 0xDDA3, 0x641F, + 0xDDA4, 0x6415, 0xDDA5, 0x6418, 0xDDA6, 0x6439, 0xDDA7, 0x6437, 0xDDA8, 0x6422, 0xDDA9, 0x6423, 0xDDAA, 0x640C, 0xDDAB, 0x6426, + 0xDDAC, 0x6430, 0xDDAD, 0x6428, 0xDDAE, 0x6441, 0xDDAF, 0x6435, 0xDDB0, 0x642F, 0xDDB1, 0x640A, 0xDDB2, 0x641A, 0xDDB3, 0x6440, + 0xDDB4, 0x6425, 0xDDB5, 0x6427, 0xDDB6, 0x640B, 0xDDB7, 0x63E7, 0xDDB8, 0x641B, 0xDDB9, 0x642E, 0xDDBA, 0x6421, 0xDDBB, 0x640E, + 0xDDBC, 0x656F, 0xDDBD, 0x6592, 0xDDBE, 0x65D3, 0xDDBF, 0x6686, 0xDDC0, 0x668C, 0xDDC1, 0x6695, 0xDDC2, 0x6690, 0xDDC3, 0x668B, + 0xDDC4, 0x668A, 0xDDC5, 0x6699, 0xDDC6, 0x6694, 0xDDC7, 0x6678, 0xDDC8, 0x6720, 0xDDC9, 0x6966, 0xDDCA, 0x695F, 0xDDCB, 0x6938, + 0xDDCC, 0x694E, 0xDDCD, 0x6962, 0xDDCE, 0x6971, 0xDDCF, 0x693F, 0xDDD0, 0x6945, 0xDDD1, 0x696A, 0xDDD2, 0x6939, 0xDDD3, 0x6942, + 0xDDD4, 0x6957, 0xDDD5, 0x6959, 0xDDD6, 0x697A, 0xDDD7, 0x6948, 0xDDD8, 0x6949, 0xDDD9, 0x6935, 0xDDDA, 0x696C, 0xDDDB, 0x6933, + 0xDDDC, 0x693D, 0xDDDD, 0x6965, 0xDDDE, 0x68F0, 0xDDDF, 0x6978, 0xDDE0, 0x6934, 0xDDE1, 0x6969, 0xDDE2, 0x6940, 0xDDE3, 0x696F, + 0xDDE4, 0x6944, 0xDDE5, 0x6976, 0xDDE6, 0x6958, 0xDDE7, 0x6941, 0xDDE8, 0x6974, 0xDDE9, 0x694C, 0xDDEA, 0x693B, 0xDDEB, 0x694B, + 0xDDEC, 0x6937, 0xDDED, 0x695C, 0xDDEE, 0x694F, 0xDDEF, 0x6951, 0xDDF0, 0x6932, 0xDDF1, 0x6952, 0xDDF2, 0x692F, 0xDDF3, 0x697B, + 0xDDF4, 0x693C, 0xDDF5, 0x6B46, 0xDDF6, 0x6B45, 0xDDF7, 0x6B43, 0xDDF8, 0x6B42, 0xDDF9, 0x6B48, 0xDDFA, 0x6B41, 0xDDFB, 0x6B9B, + 0xDDFC, 0xFA0D, 0xDDFD, 0x6BFB, 0xDDFE, 0x6BFC, 0xDE40, 0x6BF9, 0xDE41, 0x6BF7, 0xDE42, 0x6BF8, 0xDE43, 0x6E9B, 0xDE44, 0x6ED6, + 0xDE45, 0x6EC8, 0xDE46, 0x6E8F, 0xDE47, 0x6EC0, 0xDE48, 0x6E9F, 0xDE49, 0x6E93, 0xDE4A, 0x6E94, 0xDE4B, 0x6EA0, 0xDE4C, 0x6EB1, + 0xDE4D, 0x6EB9, 0xDE4E, 0x6EC6, 0xDE4F, 0x6ED2, 0xDE50, 0x6EBD, 0xDE51, 0x6EC1, 0xDE52, 0x6E9E, 0xDE53, 0x6EC9, 0xDE54, 0x6EB7, + 0xDE55, 0x6EB0, 0xDE56, 0x6ECD, 0xDE57, 0x6EA6, 0xDE58, 0x6ECF, 0xDE59, 0x6EB2, 0xDE5A, 0x6EBE, 0xDE5B, 0x6EC3, 0xDE5C, 0x6EDC, + 0xDE5D, 0x6ED8, 0xDE5E, 0x6E99, 0xDE5F, 0x6E92, 0xDE60, 0x6E8E, 0xDE61, 0x6E8D, 0xDE62, 0x6EA4, 0xDE63, 0x6EA1, 0xDE64, 0x6EBF, + 0xDE65, 0x6EB3, 0xDE66, 0x6ED0, 0xDE67, 0x6ECA, 0xDE68, 0x6E97, 0xDE69, 0x6EAE, 0xDE6A, 0x6EA3, 0xDE6B, 0x7147, 0xDE6C, 0x7154, + 0xDE6D, 0x7152, 0xDE6E, 0x7163, 0xDE6F, 0x7160, 0xDE70, 0x7141, 0xDE71, 0x715D, 0xDE72, 0x7162, 0xDE73, 0x7172, 0xDE74, 0x7178, + 0xDE75, 0x716A, 0xDE76, 0x7161, 0xDE77, 0x7142, 0xDE78, 0x7158, 0xDE79, 0x7143, 0xDE7A, 0x714B, 0xDE7B, 0x7170, 0xDE7C, 0x715F, + 0xDE7D, 0x7150, 0xDE7E, 0x7153, 0xDEA1, 0x7144, 0xDEA2, 0x714D, 0xDEA3, 0x715A, 0xDEA4, 0x724F, 0xDEA5, 0x728D, 0xDEA6, 0x728C, + 0xDEA7, 0x7291, 0xDEA8, 0x7290, 0xDEA9, 0x728E, 0xDEAA, 0x733C, 0xDEAB, 0x7342, 0xDEAC, 0x733B, 0xDEAD, 0x733A, 0xDEAE, 0x7340, + 0xDEAF, 0x734A, 0xDEB0, 0x7349, 0xDEB1, 0x7444, 0xDEB2, 0x744A, 0xDEB3, 0x744B, 0xDEB4, 0x7452, 0xDEB5, 0x7451, 0xDEB6, 0x7457, + 0xDEB7, 0x7440, 0xDEB8, 0x744F, 0xDEB9, 0x7450, 0xDEBA, 0x744E, 0xDEBB, 0x7442, 0xDEBC, 0x7446, 0xDEBD, 0x744D, 0xDEBE, 0x7454, + 0xDEBF, 0x74E1, 0xDEC0, 0x74FF, 0xDEC1, 0x74FE, 0xDEC2, 0x74FD, 0xDEC3, 0x751D, 0xDEC4, 0x7579, 0xDEC5, 0x7577, 0xDEC6, 0x6983, + 0xDEC7, 0x75EF, 0xDEC8, 0x760F, 0xDEC9, 0x7603, 0xDECA, 0x75F7, 0xDECB, 0x75FE, 0xDECC, 0x75FC, 0xDECD, 0x75F9, 0xDECE, 0x75F8, + 0xDECF, 0x7610, 0xDED0, 0x75FB, 0xDED1, 0x75F6, 0xDED2, 0x75ED, 0xDED3, 0x75F5, 0xDED4, 0x75FD, 0xDED5, 0x7699, 0xDED6, 0x76B5, + 0xDED7, 0x76DD, 0xDED8, 0x7755, 0xDED9, 0x775F, 0xDEDA, 0x7760, 0xDEDB, 0x7752, 0xDEDC, 0x7756, 0xDEDD, 0x775A, 0xDEDE, 0x7769, + 0xDEDF, 0x7767, 0xDEE0, 0x7754, 0xDEE1, 0x7759, 0xDEE2, 0x776D, 0xDEE3, 0x77E0, 0xDEE4, 0x7887, 0xDEE5, 0x789A, 0xDEE6, 0x7894, + 0xDEE7, 0x788F, 0xDEE8, 0x7884, 0xDEE9, 0x7895, 0xDEEA, 0x7885, 0xDEEB, 0x7886, 0xDEEC, 0x78A1, 0xDEED, 0x7883, 0xDEEE, 0x7879, + 0xDEEF, 0x7899, 0xDEF0, 0x7880, 0xDEF1, 0x7896, 0xDEF2, 0x787B, 0xDEF3, 0x797C, 0xDEF4, 0x7982, 0xDEF5, 0x797D, 0xDEF6, 0x7979, + 0xDEF7, 0x7A11, 0xDEF8, 0x7A18, 0xDEF9, 0x7A19, 0xDEFA, 0x7A12, 0xDEFB, 0x7A17, 0xDEFC, 0x7A15, 0xDEFD, 0x7A22, 0xDEFE, 0x7A13, + 0xDF40, 0x7A1B, 0xDF41, 0x7A10, 0xDF42, 0x7AA3, 0xDF43, 0x7AA2, 0xDF44, 0x7A9E, 0xDF45, 0x7AEB, 0xDF46, 0x7B66, 0xDF47, 0x7B64, + 0xDF48, 0x7B6D, 0xDF49, 0x7B74, 0xDF4A, 0x7B69, 0xDF4B, 0x7B72, 0xDF4C, 0x7B65, 0xDF4D, 0x7B73, 0xDF4E, 0x7B71, 0xDF4F, 0x7B70, + 0xDF50, 0x7B61, 0xDF51, 0x7B78, 0xDF52, 0x7B76, 0xDF53, 0x7B63, 0xDF54, 0x7CB2, 0xDF55, 0x7CB4, 0xDF56, 0x7CAF, 0xDF57, 0x7D88, + 0xDF58, 0x7D86, 0xDF59, 0x7D80, 0xDF5A, 0x7D8D, 0xDF5B, 0x7D7F, 0xDF5C, 0x7D85, 0xDF5D, 0x7D7A, 0xDF5E, 0x7D8E, 0xDF5F, 0x7D7B, + 0xDF60, 0x7D83, 0xDF61, 0x7D7C, 0xDF62, 0x7D8C, 0xDF63, 0x7D94, 0xDF64, 0x7D84, 0xDF65, 0x7D7D, 0xDF66, 0x7D92, 0xDF67, 0x7F6D, + 0xDF68, 0x7F6B, 0xDF69, 0x7F67, 0xDF6A, 0x7F68, 0xDF6B, 0x7F6C, 0xDF6C, 0x7FA6, 0xDF6D, 0x7FA5, 0xDF6E, 0x7FA7, 0xDF6F, 0x7FDB, + 0xDF70, 0x7FDC, 0xDF71, 0x8021, 0xDF72, 0x8164, 0xDF73, 0x8160, 0xDF74, 0x8177, 0xDF75, 0x815C, 0xDF76, 0x8169, 0xDF77, 0x815B, + 0xDF78, 0x8162, 0xDF79, 0x8172, 0xDF7A, 0x6721, 0xDF7B, 0x815E, 0xDF7C, 0x8176, 0xDF7D, 0x8167, 0xDF7E, 0x816F, 0xDFA1, 0x8144, + 0xDFA2, 0x8161, 0xDFA3, 0x821D, 0xDFA4, 0x8249, 0xDFA5, 0x8244, 0xDFA6, 0x8240, 0xDFA7, 0x8242, 0xDFA8, 0x8245, 0xDFA9, 0x84F1, + 0xDFAA, 0x843F, 0xDFAB, 0x8456, 0xDFAC, 0x8476, 0xDFAD, 0x8479, 0xDFAE, 0x848F, 0xDFAF, 0x848D, 0xDFB0, 0x8465, 0xDFB1, 0x8451, + 0xDFB2, 0x8440, 0xDFB3, 0x8486, 0xDFB4, 0x8467, 0xDFB5, 0x8430, 0xDFB6, 0x844D, 0xDFB7, 0x847D, 0xDFB8, 0x845A, 0xDFB9, 0x8459, + 0xDFBA, 0x8474, 0xDFBB, 0x8473, 0xDFBC, 0x845D, 0xDFBD, 0x8507, 0xDFBE, 0x845E, 0xDFBF, 0x8437, 0xDFC0, 0x843A, 0xDFC1, 0x8434, + 0xDFC2, 0x847A, 0xDFC3, 0x8443, 0xDFC4, 0x8478, 0xDFC5, 0x8432, 0xDFC6, 0x8445, 0xDFC7, 0x8429, 0xDFC8, 0x83D9, 0xDFC9, 0x844B, + 0xDFCA, 0x842F, 0xDFCB, 0x8442, 0xDFCC, 0x842D, 0xDFCD, 0x845F, 0xDFCE, 0x8470, 0xDFCF, 0x8439, 0xDFD0, 0x844E, 0xDFD1, 0x844C, + 0xDFD2, 0x8452, 0xDFD3, 0x846F, 0xDFD4, 0x84C5, 0xDFD5, 0x848E, 0xDFD6, 0x843B, 0xDFD7, 0x8447, 0xDFD8, 0x8436, 0xDFD9, 0x8433, + 0xDFDA, 0x8468, 0xDFDB, 0x847E, 0xDFDC, 0x8444, 0xDFDD, 0x842B, 0xDFDE, 0x8460, 0xDFDF, 0x8454, 0xDFE0, 0x846E, 0xDFE1, 0x8450, + 0xDFE2, 0x870B, 0xDFE3, 0x8704, 0xDFE4, 0x86F7, 0xDFE5, 0x870C, 0xDFE6, 0x86FA, 0xDFE7, 0x86D6, 0xDFE8, 0x86F5, 0xDFE9, 0x874D, + 0xDFEA, 0x86F8, 0xDFEB, 0x870E, 0xDFEC, 0x8709, 0xDFED, 0x8701, 0xDFEE, 0x86F6, 0xDFEF, 0x870D, 0xDFF0, 0x8705, 0xDFF1, 0x88D6, + 0xDFF2, 0x88CB, 0xDFF3, 0x88CD, 0xDFF4, 0x88CE, 0xDFF5, 0x88DE, 0xDFF6, 0x88DB, 0xDFF7, 0x88DA, 0xDFF8, 0x88CC, 0xDFF9, 0x88D0, + 0xDFFA, 0x8985, 0xDFFB, 0x899B, 0xDFFC, 0x89DF, 0xDFFD, 0x89E5, 0xDFFE, 0x89E4, 0xE040, 0x89E1, 0xE041, 0x89E0, 0xE042, 0x89E2, + 0xE043, 0x89DC, 0xE044, 0x89E6, 0xE045, 0x8A76, 0xE046, 0x8A86, 0xE047, 0x8A7F, 0xE048, 0x8A61, 0xE049, 0x8A3F, 0xE04A, 0x8A77, + 0xE04B, 0x8A82, 0xE04C, 0x8A84, 0xE04D, 0x8A75, 0xE04E, 0x8A83, 0xE04F, 0x8A81, 0xE050, 0x8A74, 0xE051, 0x8A7A, 0xE052, 0x8C3C, + 0xE053, 0x8C4B, 0xE054, 0x8C4A, 0xE055, 0x8C65, 0xE056, 0x8C64, 0xE057, 0x8C66, 0xE058, 0x8C86, 0xE059, 0x8C84, 0xE05A, 0x8C85, + 0xE05B, 0x8CCC, 0xE05C, 0x8D68, 0xE05D, 0x8D69, 0xE05E, 0x8D91, 0xE05F, 0x8D8C, 0xE060, 0x8D8E, 0xE061, 0x8D8F, 0xE062, 0x8D8D, + 0xE063, 0x8D93, 0xE064, 0x8D94, 0xE065, 0x8D90, 0xE066, 0x8D92, 0xE067, 0x8DF0, 0xE068, 0x8DE0, 0xE069, 0x8DEC, 0xE06A, 0x8DF1, + 0xE06B, 0x8DEE, 0xE06C, 0x8DD0, 0xE06D, 0x8DE9, 0xE06E, 0x8DE3, 0xE06F, 0x8DE2, 0xE070, 0x8DE7, 0xE071, 0x8DF2, 0xE072, 0x8DEB, + 0xE073, 0x8DF4, 0xE074, 0x8F06, 0xE075, 0x8EFF, 0xE076, 0x8F01, 0xE077, 0x8F00, 0xE078, 0x8F05, 0xE079, 0x8F07, 0xE07A, 0x8F08, + 0xE07B, 0x8F02, 0xE07C, 0x8F0B, 0xE07D, 0x9052, 0xE07E, 0x903F, 0xE0A1, 0x9044, 0xE0A2, 0x9049, 0xE0A3, 0x903D, 0xE0A4, 0x9110, + 0xE0A5, 0x910D, 0xE0A6, 0x910F, 0xE0A7, 0x9111, 0xE0A8, 0x9116, 0xE0A9, 0x9114, 0xE0AA, 0x910B, 0xE0AB, 0x910E, 0xE0AC, 0x916E, + 0xE0AD, 0x916F, 0xE0AE, 0x9248, 0xE0AF, 0x9252, 0xE0B0, 0x9230, 0xE0B1, 0x923A, 0xE0B2, 0x9266, 0xE0B3, 0x9233, 0xE0B4, 0x9265, + 0xE0B5, 0x925E, 0xE0B6, 0x9283, 0xE0B7, 0x922E, 0xE0B8, 0x924A, 0xE0B9, 0x9246, 0xE0BA, 0x926D, 0xE0BB, 0x926C, 0xE0BC, 0x924F, + 0xE0BD, 0x9260, 0xE0BE, 0x9267, 0xE0BF, 0x926F, 0xE0C0, 0x9236, 0xE0C1, 0x9261, 0xE0C2, 0x9270, 0xE0C3, 0x9231, 0xE0C4, 0x9254, + 0xE0C5, 0x9263, 0xE0C6, 0x9250, 0xE0C7, 0x9272, 0xE0C8, 0x924E, 0xE0C9, 0x9253, 0xE0CA, 0x924C, 0xE0CB, 0x9256, 0xE0CC, 0x9232, + 0xE0CD, 0x959F, 0xE0CE, 0x959C, 0xE0CF, 0x959E, 0xE0D0, 0x959B, 0xE0D1, 0x9692, 0xE0D2, 0x9693, 0xE0D3, 0x9691, 0xE0D4, 0x9697, + 0xE0D5, 0x96CE, 0xE0D6, 0x96FA, 0xE0D7, 0x96FD, 0xE0D8, 0x96F8, 0xE0D9, 0x96F5, 0xE0DA, 0x9773, 0xE0DB, 0x9777, 0xE0DC, 0x9778, + 0xE0DD, 0x9772, 0xE0DE, 0x980F, 0xE0DF, 0x980D, 0xE0E0, 0x980E, 0xE0E1, 0x98AC, 0xE0E2, 0x98F6, 0xE0E3, 0x98F9, 0xE0E4, 0x99AF, + 0xE0E5, 0x99B2, 0xE0E6, 0x99B0, 0xE0E7, 0x99B5, 0xE0E8, 0x9AAD, 0xE0E9, 0x9AAB, 0xE0EA, 0x9B5B, 0xE0EB, 0x9CEA, 0xE0EC, 0x9CED, + 0xE0ED, 0x9CE7, 0xE0EE, 0x9E80, 0xE0EF, 0x9EFD, 0xE0F0, 0x50E6, 0xE0F1, 0x50D4, 0xE0F2, 0x50D7, 0xE0F3, 0x50E8, 0xE0F4, 0x50F3, + 0xE0F5, 0x50DB, 0xE0F6, 0x50EA, 0xE0F7, 0x50DD, 0xE0F8, 0x50E4, 0xE0F9, 0x50D3, 0xE0FA, 0x50EC, 0xE0FB, 0x50F0, 0xE0FC, 0x50EF, + 0xE0FD, 0x50E3, 0xE0FE, 0x50E0, 0xE140, 0x51D8, 0xE141, 0x5280, 0xE142, 0x5281, 0xE143, 0x52E9, 0xE144, 0x52EB, 0xE145, 0x5330, + 0xE146, 0x53AC, 0xE147, 0x5627, 0xE148, 0x5615, 0xE149, 0x560C, 0xE14A, 0x5612, 0xE14B, 0x55FC, 0xE14C, 0x560F, 0xE14D, 0x561C, + 0xE14E, 0x5601, 0xE14F, 0x5613, 0xE150, 0x5602, 0xE151, 0x55FA, 0xE152, 0x561D, 0xE153, 0x5604, 0xE154, 0x55FF, 0xE155, 0x55F9, + 0xE156, 0x5889, 0xE157, 0x587C, 0xE158, 0x5890, 0xE159, 0x5898, 0xE15A, 0x5886, 0xE15B, 0x5881, 0xE15C, 0x587F, 0xE15D, 0x5874, + 0xE15E, 0x588B, 0xE15F, 0x587A, 0xE160, 0x5887, 0xE161, 0x5891, 0xE162, 0x588E, 0xE163, 0x5876, 0xE164, 0x5882, 0xE165, 0x5888, + 0xE166, 0x587B, 0xE167, 0x5894, 0xE168, 0x588F, 0xE169, 0x58FE, 0xE16A, 0x596B, 0xE16B, 0x5ADC, 0xE16C, 0x5AEE, 0xE16D, 0x5AE5, + 0xE16E, 0x5AD5, 0xE16F, 0x5AEA, 0xE170, 0x5ADA, 0xE171, 0x5AED, 0xE172, 0x5AEB, 0xE173, 0x5AF3, 0xE174, 0x5AE2, 0xE175, 0x5AE0, + 0xE176, 0x5ADB, 0xE177, 0x5AEC, 0xE178, 0x5ADE, 0xE179, 0x5ADD, 0xE17A, 0x5AD9, 0xE17B, 0x5AE8, 0xE17C, 0x5ADF, 0xE17D, 0x5B77, + 0xE17E, 0x5BE0, 0xE1A1, 0x5BE3, 0xE1A2, 0x5C63, 0xE1A3, 0x5D82, 0xE1A4, 0x5D80, 0xE1A5, 0x5D7D, 0xE1A6, 0x5D86, 0xE1A7, 0x5D7A, + 0xE1A8, 0x5D81, 0xE1A9, 0x5D77, 0xE1AA, 0x5D8A, 0xE1AB, 0x5D89, 0xE1AC, 0x5D88, 0xE1AD, 0x5D7E, 0xE1AE, 0x5D7C, 0xE1AF, 0x5D8D, + 0xE1B0, 0x5D79, 0xE1B1, 0x5D7F, 0xE1B2, 0x5E58, 0xE1B3, 0x5E59, 0xE1B4, 0x5E53, 0xE1B5, 0x5ED8, 0xE1B6, 0x5ED1, 0xE1B7, 0x5ED7, + 0xE1B8, 0x5ECE, 0xE1B9, 0x5EDC, 0xE1BA, 0x5ED5, 0xE1BB, 0x5ED9, 0xE1BC, 0x5ED2, 0xE1BD, 0x5ED4, 0xE1BE, 0x5F44, 0xE1BF, 0x5F43, + 0xE1C0, 0x5F6F, 0xE1C1, 0x5FB6, 0xE1C2, 0x612C, 0xE1C3, 0x6128, 0xE1C4, 0x6141, 0xE1C5, 0x615E, 0xE1C6, 0x6171, 0xE1C7, 0x6173, + 0xE1C8, 0x6152, 0xE1C9, 0x6153, 0xE1CA, 0x6172, 0xE1CB, 0x616C, 0xE1CC, 0x6180, 0xE1CD, 0x6174, 0xE1CE, 0x6154, 0xE1CF, 0x617A, + 0xE1D0, 0x615B, 0xE1D1, 0x6165, 0xE1D2, 0x613B, 0xE1D3, 0x616A, 0xE1D4, 0x6161, 0xE1D5, 0x6156, 0xE1D6, 0x6229, 0xE1D7, 0x6227, + 0xE1D8, 0x622B, 0xE1D9, 0x642B, 0xE1DA, 0x644D, 0xE1DB, 0x645B, 0xE1DC, 0x645D, 0xE1DD, 0x6474, 0xE1DE, 0x6476, 0xE1DF, 0x6472, + 0xE1E0, 0x6473, 0xE1E1, 0x647D, 0xE1E2, 0x6475, 0xE1E3, 0x6466, 0xE1E4, 0x64A6, 0xE1E5, 0x644E, 0xE1E6, 0x6482, 0xE1E7, 0x645E, + 0xE1E8, 0x645C, 0xE1E9, 0x644B, 0xE1EA, 0x6453, 0xE1EB, 0x6460, 0xE1EC, 0x6450, 0xE1ED, 0x647F, 0xE1EE, 0x643F, 0xE1EF, 0x646C, + 0xE1F0, 0x646B, 0xE1F1, 0x6459, 0xE1F2, 0x6465, 0xE1F3, 0x6477, 0xE1F4, 0x6573, 0xE1F5, 0x65A0, 0xE1F6, 0x66A1, 0xE1F7, 0x66A0, + 0xE1F8, 0x669F, 0xE1F9, 0x6705, 0xE1FA, 0x6704, 0xE1FB, 0x6722, 0xE1FC, 0x69B1, 0xE1FD, 0x69B6, 0xE1FE, 0x69C9, 0xE240, 0x69A0, + 0xE241, 0x69CE, 0xE242, 0x6996, 0xE243, 0x69B0, 0xE244, 0x69AC, 0xE245, 0x69BC, 0xE246, 0x6991, 0xE247, 0x6999, 0xE248, 0x698E, + 0xE249, 0x69A7, 0xE24A, 0x698D, 0xE24B, 0x69A9, 0xE24C, 0x69BE, 0xE24D, 0x69AF, 0xE24E, 0x69BF, 0xE24F, 0x69C4, 0xE250, 0x69BD, + 0xE251, 0x69A4, 0xE252, 0x69D4, 0xE253, 0x69B9, 0xE254, 0x69CA, 0xE255, 0x699A, 0xE256, 0x69CF, 0xE257, 0x69B3, 0xE258, 0x6993, + 0xE259, 0x69AA, 0xE25A, 0x69A1, 0xE25B, 0x699E, 0xE25C, 0x69D9, 0xE25D, 0x6997, 0xE25E, 0x6990, 0xE25F, 0x69C2, 0xE260, 0x69B5, + 0xE261, 0x69A5, 0xE262, 0x69C6, 0xE263, 0x6B4A, 0xE264, 0x6B4D, 0xE265, 0x6B4B, 0xE266, 0x6B9E, 0xE267, 0x6B9F, 0xE268, 0x6BA0, + 0xE269, 0x6BC3, 0xE26A, 0x6BC4, 0xE26B, 0x6BFE, 0xE26C, 0x6ECE, 0xE26D, 0x6EF5, 0xE26E, 0x6EF1, 0xE26F, 0x6F03, 0xE270, 0x6F25, + 0xE271, 0x6EF8, 0xE272, 0x6F37, 0xE273, 0x6EFB, 0xE274, 0x6F2E, 0xE275, 0x6F09, 0xE276, 0x6F4E, 0xE277, 0x6F19, 0xE278, 0x6F1A, + 0xE279, 0x6F27, 0xE27A, 0x6F18, 0xE27B, 0x6F3B, 0xE27C, 0x6F12, 0xE27D, 0x6EED, 0xE27E, 0x6F0A, 0xE2A1, 0x6F36, 0xE2A2, 0x6F73, + 0xE2A3, 0x6EF9, 0xE2A4, 0x6EEE, 0xE2A5, 0x6F2D, 0xE2A6, 0x6F40, 0xE2A7, 0x6F30, 0xE2A8, 0x6F3C, 0xE2A9, 0x6F35, 0xE2AA, 0x6EEB, + 0xE2AB, 0x6F07, 0xE2AC, 0x6F0E, 0xE2AD, 0x6F43, 0xE2AE, 0x6F05, 0xE2AF, 0x6EFD, 0xE2B0, 0x6EF6, 0xE2B1, 0x6F39, 0xE2B2, 0x6F1C, + 0xE2B3, 0x6EFC, 0xE2B4, 0x6F3A, 0xE2B5, 0x6F1F, 0xE2B6, 0x6F0D, 0xE2B7, 0x6F1E, 0xE2B8, 0x6F08, 0xE2B9, 0x6F21, 0xE2BA, 0x7187, + 0xE2BB, 0x7190, 0xE2BC, 0x7189, 0xE2BD, 0x7180, 0xE2BE, 0x7185, 0xE2BF, 0x7182, 0xE2C0, 0x718F, 0xE2C1, 0x717B, 0xE2C2, 0x7186, + 0xE2C3, 0x7181, 0xE2C4, 0x7197, 0xE2C5, 0x7244, 0xE2C6, 0x7253, 0xE2C7, 0x7297, 0xE2C8, 0x7295, 0xE2C9, 0x7293, 0xE2CA, 0x7343, + 0xE2CB, 0x734D, 0xE2CC, 0x7351, 0xE2CD, 0x734C, 0xE2CE, 0x7462, 0xE2CF, 0x7473, 0xE2D0, 0x7471, 0xE2D1, 0x7475, 0xE2D2, 0x7472, + 0xE2D3, 0x7467, 0xE2D4, 0x746E, 0xE2D5, 0x7500, 0xE2D6, 0x7502, 0xE2D7, 0x7503, 0xE2D8, 0x757D, 0xE2D9, 0x7590, 0xE2DA, 0x7616, + 0xE2DB, 0x7608, 0xE2DC, 0x760C, 0xE2DD, 0x7615, 0xE2DE, 0x7611, 0xE2DF, 0x760A, 0xE2E0, 0x7614, 0xE2E1, 0x76B8, 0xE2E2, 0x7781, + 0xE2E3, 0x777C, 0xE2E4, 0x7785, 0xE2E5, 0x7782, 0xE2E6, 0x776E, 0xE2E7, 0x7780, 0xE2E8, 0x776F, 0xE2E9, 0x777E, 0xE2EA, 0x7783, + 0xE2EB, 0x78B2, 0xE2EC, 0x78AA, 0xE2ED, 0x78B4, 0xE2EE, 0x78AD, 0xE2EF, 0x78A8, 0xE2F0, 0x787E, 0xE2F1, 0x78AB, 0xE2F2, 0x789E, + 0xE2F3, 0x78A5, 0xE2F4, 0x78A0, 0xE2F5, 0x78AC, 0xE2F6, 0x78A2, 0xE2F7, 0x78A4, 0xE2F8, 0x7998, 0xE2F9, 0x798A, 0xE2FA, 0x798B, + 0xE2FB, 0x7996, 0xE2FC, 0x7995, 0xE2FD, 0x7994, 0xE2FE, 0x7993, 0xE340, 0x7997, 0xE341, 0x7988, 0xE342, 0x7992, 0xE343, 0x7990, + 0xE344, 0x7A2B, 0xE345, 0x7A4A, 0xE346, 0x7A30, 0xE347, 0x7A2F, 0xE348, 0x7A28, 0xE349, 0x7A26, 0xE34A, 0x7AA8, 0xE34B, 0x7AAB, + 0xE34C, 0x7AAC, 0xE34D, 0x7AEE, 0xE34E, 0x7B88, 0xE34F, 0x7B9C, 0xE350, 0x7B8A, 0xE351, 0x7B91, 0xE352, 0x7B90, 0xE353, 0x7B96, + 0xE354, 0x7B8D, 0xE355, 0x7B8C, 0xE356, 0x7B9B, 0xE357, 0x7B8E, 0xE358, 0x7B85, 0xE359, 0x7B98, 0xE35A, 0x5284, 0xE35B, 0x7B99, + 0xE35C, 0x7BA4, 0xE35D, 0x7B82, 0xE35E, 0x7CBB, 0xE35F, 0x7CBF, 0xE360, 0x7CBC, 0xE361, 0x7CBA, 0xE362, 0x7DA7, 0xE363, 0x7DB7, + 0xE364, 0x7DC2, 0xE365, 0x7DA3, 0xE366, 0x7DAA, 0xE367, 0x7DC1, 0xE368, 0x7DC0, 0xE369, 0x7DC5, 0xE36A, 0x7D9D, 0xE36B, 0x7DCE, + 0xE36C, 0x7DC4, 0xE36D, 0x7DC6, 0xE36E, 0x7DCB, 0xE36F, 0x7DCC, 0xE370, 0x7DAF, 0xE371, 0x7DB9, 0xE372, 0x7D96, 0xE373, 0x7DBC, + 0xE374, 0x7D9F, 0xE375, 0x7DA6, 0xE376, 0x7DAE, 0xE377, 0x7DA9, 0xE378, 0x7DA1, 0xE379, 0x7DC9, 0xE37A, 0x7F73, 0xE37B, 0x7FE2, + 0xE37C, 0x7FE3, 0xE37D, 0x7FE5, 0xE37E, 0x7FDE, 0xE3A1, 0x8024, 0xE3A2, 0x805D, 0xE3A3, 0x805C, 0xE3A4, 0x8189, 0xE3A5, 0x8186, + 0xE3A6, 0x8183, 0xE3A7, 0x8187, 0xE3A8, 0x818D, 0xE3A9, 0x818C, 0xE3AA, 0x818B, 0xE3AB, 0x8215, 0xE3AC, 0x8497, 0xE3AD, 0x84A4, + 0xE3AE, 0x84A1, 0xE3AF, 0x849F, 0xE3B0, 0x84BA, 0xE3B1, 0x84CE, 0xE3B2, 0x84C2, 0xE3B3, 0x84AC, 0xE3B4, 0x84AE, 0xE3B5, 0x84AB, + 0xE3B6, 0x84B9, 0xE3B7, 0x84B4, 0xE3B8, 0x84C1, 0xE3B9, 0x84CD, 0xE3BA, 0x84AA, 0xE3BB, 0x849A, 0xE3BC, 0x84B1, 0xE3BD, 0x84D0, + 0xE3BE, 0x849D, 0xE3BF, 0x84A7, 0xE3C0, 0x84BB, 0xE3C1, 0x84A2, 0xE3C2, 0x8494, 0xE3C3, 0x84C7, 0xE3C4, 0x84CC, 0xE3C5, 0x849B, + 0xE3C6, 0x84A9, 0xE3C7, 0x84AF, 0xE3C8, 0x84A8, 0xE3C9, 0x84D6, 0xE3CA, 0x8498, 0xE3CB, 0x84B6, 0xE3CC, 0x84CF, 0xE3CD, 0x84A0, + 0xE3CE, 0x84D7, 0xE3CF, 0x84D4, 0xE3D0, 0x84D2, 0xE3D1, 0x84DB, 0xE3D2, 0x84B0, 0xE3D3, 0x8491, 0xE3D4, 0x8661, 0xE3D5, 0x8733, + 0xE3D6, 0x8723, 0xE3D7, 0x8728, 0xE3D8, 0x876B, 0xE3D9, 0x8740, 0xE3DA, 0x872E, 0xE3DB, 0x871E, 0xE3DC, 0x8721, 0xE3DD, 0x8719, + 0xE3DE, 0x871B, 0xE3DF, 0x8743, 0xE3E0, 0x872C, 0xE3E1, 0x8741, 0xE3E2, 0x873E, 0xE3E3, 0x8746, 0xE3E4, 0x8720, 0xE3E5, 0x8732, + 0xE3E6, 0x872A, 0xE3E7, 0x872D, 0xE3E8, 0x873C, 0xE3E9, 0x8712, 0xE3EA, 0x873A, 0xE3EB, 0x8731, 0xE3EC, 0x8735, 0xE3ED, 0x8742, + 0xE3EE, 0x8726, 0xE3EF, 0x8727, 0xE3F0, 0x8738, 0xE3F1, 0x8724, 0xE3F2, 0x871A, 0xE3F3, 0x8730, 0xE3F4, 0x8711, 0xE3F5, 0x88F7, + 0xE3F6, 0x88E7, 0xE3F7, 0x88F1, 0xE3F8, 0x88F2, 0xE3F9, 0x88FA, 0xE3FA, 0x88FE, 0xE3FB, 0x88EE, 0xE3FC, 0x88FC, 0xE3FD, 0x88F6, + 0xE3FE, 0x88FB, 0xE440, 0x88F0, 0xE441, 0x88EC, 0xE442, 0x88EB, 0xE443, 0x899D, 0xE444, 0x89A1, 0xE445, 0x899F, 0xE446, 0x899E, + 0xE447, 0x89E9, 0xE448, 0x89EB, 0xE449, 0x89E8, 0xE44A, 0x8AAB, 0xE44B, 0x8A99, 0xE44C, 0x8A8B, 0xE44D, 0x8A92, 0xE44E, 0x8A8F, + 0xE44F, 0x8A96, 0xE450, 0x8C3D, 0xE451, 0x8C68, 0xE452, 0x8C69, 0xE453, 0x8CD5, 0xE454, 0x8CCF, 0xE455, 0x8CD7, 0xE456, 0x8D96, + 0xE457, 0x8E09, 0xE458, 0x8E02, 0xE459, 0x8DFF, 0xE45A, 0x8E0D, 0xE45B, 0x8DFD, 0xE45C, 0x8E0A, 0xE45D, 0x8E03, 0xE45E, 0x8E07, + 0xE45F, 0x8E06, 0xE460, 0x8E05, 0xE461, 0x8DFE, 0xE462, 0x8E00, 0xE463, 0x8E04, 0xE464, 0x8F10, 0xE465, 0x8F11, 0xE466, 0x8F0E, + 0xE467, 0x8F0D, 0xE468, 0x9123, 0xE469, 0x911C, 0xE46A, 0x9120, 0xE46B, 0x9122, 0xE46C, 0x911F, 0xE46D, 0x911D, 0xE46E, 0x911A, + 0xE46F, 0x9124, 0xE470, 0x9121, 0xE471, 0x911B, 0xE472, 0x917A, 0xE473, 0x9172, 0xE474, 0x9179, 0xE475, 0x9173, 0xE476, 0x92A5, + 0xE477, 0x92A4, 0xE478, 0x9276, 0xE479, 0x929B, 0xE47A, 0x927A, 0xE47B, 0x92A0, 0xE47C, 0x9294, 0xE47D, 0x92AA, 0xE47E, 0x928D, + 0xE4A1, 0x92A6, 0xE4A2, 0x929A, 0xE4A3, 0x92AB, 0xE4A4, 0x9279, 0xE4A5, 0x9297, 0xE4A6, 0x927F, 0xE4A7, 0x92A3, 0xE4A8, 0x92EE, + 0xE4A9, 0x928E, 0xE4AA, 0x9282, 0xE4AB, 0x9295, 0xE4AC, 0x92A2, 0xE4AD, 0x927D, 0xE4AE, 0x9288, 0xE4AF, 0x92A1, 0xE4B0, 0x928A, + 0xE4B1, 0x9286, 0xE4B2, 0x928C, 0xE4B3, 0x9299, 0xE4B4, 0x92A7, 0xE4B5, 0x927E, 0xE4B6, 0x9287, 0xE4B7, 0x92A9, 0xE4B8, 0x929D, + 0xE4B9, 0x928B, 0xE4BA, 0x922D, 0xE4BB, 0x969E, 0xE4BC, 0x96A1, 0xE4BD, 0x96FF, 0xE4BE, 0x9758, 0xE4BF, 0x977D, 0xE4C0, 0x977A, + 0xE4C1, 0x977E, 0xE4C2, 0x9783, 0xE4C3, 0x9780, 0xE4C4, 0x9782, 0xE4C5, 0x977B, 0xE4C6, 0x9784, 0xE4C7, 0x9781, 0xE4C8, 0x977F, + 0xE4C9, 0x97CE, 0xE4CA, 0x97CD, 0xE4CB, 0x9816, 0xE4CC, 0x98AD, 0xE4CD, 0x98AE, 0xE4CE, 0x9902, 0xE4CF, 0x9900, 0xE4D0, 0x9907, + 0xE4D1, 0x999D, 0xE4D2, 0x999C, 0xE4D3, 0x99C3, 0xE4D4, 0x99B9, 0xE4D5, 0x99BB, 0xE4D6, 0x99BA, 0xE4D7, 0x99C2, 0xE4D8, 0x99BD, + 0xE4D9, 0x99C7, 0xE4DA, 0x9AB1, 0xE4DB, 0x9AE3, 0xE4DC, 0x9AE7, 0xE4DD, 0x9B3E, 0xE4DE, 0x9B3F, 0xE4DF, 0x9B60, 0xE4E0, 0x9B61, + 0xE4E1, 0x9B5F, 0xE4E2, 0x9CF1, 0xE4E3, 0x9CF2, 0xE4E4, 0x9CF5, 0xE4E5, 0x9EA7, 0xE4E6, 0x50FF, 0xE4E7, 0x5103, 0xE4E8, 0x5130, + 0xE4E9, 0x50F8, 0xE4EA, 0x5106, 0xE4EB, 0x5107, 0xE4EC, 0x50F6, 0xE4ED, 0x50FE, 0xE4EE, 0x510B, 0xE4EF, 0x510C, 0xE4F0, 0x50FD, + 0xE4F1, 0x510A, 0xE4F2, 0x528B, 0xE4F3, 0x528C, 0xE4F4, 0x52F1, 0xE4F5, 0x52EF, 0xE4F6, 0x5648, 0xE4F7, 0x5642, 0xE4F8, 0x564C, + 0xE4F9, 0x5635, 0xE4FA, 0x5641, 0xE4FB, 0x564A, 0xE4FC, 0x5649, 0xE4FD, 0x5646, 0xE4FE, 0x5658, 0xE540, 0x565A, 0xE541, 0x5640, + 0xE542, 0x5633, 0xE543, 0x563D, 0xE544, 0x562C, 0xE545, 0x563E, 0xE546, 0x5638, 0xE547, 0x562A, 0xE548, 0x563A, 0xE549, 0x571A, + 0xE54A, 0x58AB, 0xE54B, 0x589D, 0xE54C, 0x58B1, 0xE54D, 0x58A0, 0xE54E, 0x58A3, 0xE54F, 0x58AF, 0xE550, 0x58AC, 0xE551, 0x58A5, + 0xE552, 0x58A1, 0xE553, 0x58FF, 0xE554, 0x5AFF, 0xE555, 0x5AF4, 0xE556, 0x5AFD, 0xE557, 0x5AF7, 0xE558, 0x5AF6, 0xE559, 0x5B03, + 0xE55A, 0x5AF8, 0xE55B, 0x5B02, 0xE55C, 0x5AF9, 0xE55D, 0x5B01, 0xE55E, 0x5B07, 0xE55F, 0x5B05, 0xE560, 0x5B0F, 0xE561, 0x5C67, + 0xE562, 0x5D99, 0xE563, 0x5D97, 0xE564, 0x5D9F, 0xE565, 0x5D92, 0xE566, 0x5DA2, 0xE567, 0x5D93, 0xE568, 0x5D95, 0xE569, 0x5DA0, + 0xE56A, 0x5D9C, 0xE56B, 0x5DA1, 0xE56C, 0x5D9A, 0xE56D, 0x5D9E, 0xE56E, 0x5E69, 0xE56F, 0x5E5D, 0xE570, 0x5E60, 0xE571, 0x5E5C, + 0xE572, 0x7DF3, 0xE573, 0x5EDB, 0xE574, 0x5EDE, 0xE575, 0x5EE1, 0xE576, 0x5F49, 0xE577, 0x5FB2, 0xE578, 0x618B, 0xE579, 0x6183, + 0xE57A, 0x6179, 0xE57B, 0x61B1, 0xE57C, 0x61B0, 0xE57D, 0x61A2, 0xE57E, 0x6189, 0xE5A1, 0x619B, 0xE5A2, 0x6193, 0xE5A3, 0x61AF, + 0xE5A4, 0x61AD, 0xE5A5, 0x619F, 0xE5A6, 0x6192, 0xE5A7, 0x61AA, 0xE5A8, 0x61A1, 0xE5A9, 0x618D, 0xE5AA, 0x6166, 0xE5AB, 0x61B3, + 0xE5AC, 0x622D, 0xE5AD, 0x646E, 0xE5AE, 0x6470, 0xE5AF, 0x6496, 0xE5B0, 0x64A0, 0xE5B1, 0x6485, 0xE5B2, 0x6497, 0xE5B3, 0x649C, + 0xE5B4, 0x648F, 0xE5B5, 0x648B, 0xE5B6, 0x648A, 0xE5B7, 0x648C, 0xE5B8, 0x64A3, 0xE5B9, 0x649F, 0xE5BA, 0x6468, 0xE5BB, 0x64B1, + 0xE5BC, 0x6498, 0xE5BD, 0x6576, 0xE5BE, 0x657A, 0xE5BF, 0x6579, 0xE5C0, 0x657B, 0xE5C1, 0x65B2, 0xE5C2, 0x65B3, 0xE5C3, 0x66B5, + 0xE5C4, 0x66B0, 0xE5C5, 0x66A9, 0xE5C6, 0x66B2, 0xE5C7, 0x66B7, 0xE5C8, 0x66AA, 0xE5C9, 0x66AF, 0xE5CA, 0x6A00, 0xE5CB, 0x6A06, + 0xE5CC, 0x6A17, 0xE5CD, 0x69E5, 0xE5CE, 0x69F8, 0xE5CF, 0x6A15, 0xE5D0, 0x69F1, 0xE5D1, 0x69E4, 0xE5D2, 0x6A20, 0xE5D3, 0x69FF, + 0xE5D4, 0x69EC, 0xE5D5, 0x69E2, 0xE5D6, 0x6A1B, 0xE5D7, 0x6A1D, 0xE5D8, 0x69FE, 0xE5D9, 0x6A27, 0xE5DA, 0x69F2, 0xE5DB, 0x69EE, + 0xE5DC, 0x6A14, 0xE5DD, 0x69F7, 0xE5DE, 0x69E7, 0xE5DF, 0x6A40, 0xE5E0, 0x6A08, 0xE5E1, 0x69E6, 0xE5E2, 0x69FB, 0xE5E3, 0x6A0D, + 0xE5E4, 0x69FC, 0xE5E5, 0x69EB, 0xE5E6, 0x6A09, 0xE5E7, 0x6A04, 0xE5E8, 0x6A18, 0xE5E9, 0x6A25, 0xE5EA, 0x6A0F, 0xE5EB, 0x69F6, + 0xE5EC, 0x6A26, 0xE5ED, 0x6A07, 0xE5EE, 0x69F4, 0xE5EF, 0x6A16, 0xE5F0, 0x6B51, 0xE5F1, 0x6BA5, 0xE5F2, 0x6BA3, 0xE5F3, 0x6BA2, + 0xE5F4, 0x6BA6, 0xE5F5, 0x6C01, 0xE5F6, 0x6C00, 0xE5F7, 0x6BFF, 0xE5F8, 0x6C02, 0xE5F9, 0x6F41, 0xE5FA, 0x6F26, 0xE5FB, 0x6F7E, + 0xE5FC, 0x6F87, 0xE5FD, 0x6FC6, 0xE5FE, 0x6F92, 0xE640, 0x6F8D, 0xE641, 0x6F89, 0xE642, 0x6F8C, 0xE643, 0x6F62, 0xE644, 0x6F4F, + 0xE645, 0x6F85, 0xE646, 0x6F5A, 0xE647, 0x6F96, 0xE648, 0x6F76, 0xE649, 0x6F6C, 0xE64A, 0x6F82, 0xE64B, 0x6F55, 0xE64C, 0x6F72, + 0xE64D, 0x6F52, 0xE64E, 0x6F50, 0xE64F, 0x6F57, 0xE650, 0x6F94, 0xE651, 0x6F93, 0xE652, 0x6F5D, 0xE653, 0x6F00, 0xE654, 0x6F61, + 0xE655, 0x6F6B, 0xE656, 0x6F7D, 0xE657, 0x6F67, 0xE658, 0x6F90, 0xE659, 0x6F53, 0xE65A, 0x6F8B, 0xE65B, 0x6F69, 0xE65C, 0x6F7F, + 0xE65D, 0x6F95, 0xE65E, 0x6F63, 0xE65F, 0x6F77, 0xE660, 0x6F6A, 0xE661, 0x6F7B, 0xE662, 0x71B2, 0xE663, 0x71AF, 0xE664, 0x719B, + 0xE665, 0x71B0, 0xE666, 0x71A0, 0xE667, 0x719A, 0xE668, 0x71A9, 0xE669, 0x71B5, 0xE66A, 0x719D, 0xE66B, 0x71A5, 0xE66C, 0x719E, + 0xE66D, 0x71A4, 0xE66E, 0x71A1, 0xE66F, 0x71AA, 0xE670, 0x719C, 0xE671, 0x71A7, 0xE672, 0x71B3, 0xE673, 0x7298, 0xE674, 0x729A, + 0xE675, 0x7358, 0xE676, 0x7352, 0xE677, 0x735E, 0xE678, 0x735F, 0xE679, 0x7360, 0xE67A, 0x735D, 0xE67B, 0x735B, 0xE67C, 0x7361, + 0xE67D, 0x735A, 0xE67E, 0x7359, 0xE6A1, 0x7362, 0xE6A2, 0x7487, 0xE6A3, 0x7489, 0xE6A4, 0x748A, 0xE6A5, 0x7486, 0xE6A6, 0x7481, + 0xE6A7, 0x747D, 0xE6A8, 0x7485, 0xE6A9, 0x7488, 0xE6AA, 0x747C, 0xE6AB, 0x7479, 0xE6AC, 0x7508, 0xE6AD, 0x7507, 0xE6AE, 0x757E, + 0xE6AF, 0x7625, 0xE6B0, 0x761E, 0xE6B1, 0x7619, 0xE6B2, 0x761D, 0xE6B3, 0x761C, 0xE6B4, 0x7623, 0xE6B5, 0x761A, 0xE6B6, 0x7628, + 0xE6B7, 0x761B, 0xE6B8, 0x769C, 0xE6B9, 0x769D, 0xE6BA, 0x769E, 0xE6BB, 0x769B, 0xE6BC, 0x778D, 0xE6BD, 0x778F, 0xE6BE, 0x7789, + 0xE6BF, 0x7788, 0xE6C0, 0x78CD, 0xE6C1, 0x78BB, 0xE6C2, 0x78CF, 0xE6C3, 0x78CC, 0xE6C4, 0x78D1, 0xE6C5, 0x78CE, 0xE6C6, 0x78D4, + 0xE6C7, 0x78C8, 0xE6C8, 0x78C3, 0xE6C9, 0x78C4, 0xE6CA, 0x78C9, 0xE6CB, 0x799A, 0xE6CC, 0x79A1, 0xE6CD, 0x79A0, 0xE6CE, 0x799C, + 0xE6CF, 0x79A2, 0xE6D0, 0x799B, 0xE6D1, 0x6B76, 0xE6D2, 0x7A39, 0xE6D3, 0x7AB2, 0xE6D4, 0x7AB4, 0xE6D5, 0x7AB3, 0xE6D6, 0x7BB7, + 0xE6D7, 0x7BCB, 0xE6D8, 0x7BBE, 0xE6D9, 0x7BAC, 0xE6DA, 0x7BCE, 0xE6DB, 0x7BAF, 0xE6DC, 0x7BB9, 0xE6DD, 0x7BCA, 0xE6DE, 0x7BB5, + 0xE6DF, 0x7CC5, 0xE6E0, 0x7CC8, 0xE6E1, 0x7CCC, 0xE6E2, 0x7CCB, 0xE6E3, 0x7DF7, 0xE6E4, 0x7DDB, 0xE6E5, 0x7DEA, 0xE6E6, 0x7DE7, + 0xE6E7, 0x7DD7, 0xE6E8, 0x7DE1, 0xE6E9, 0x7E03, 0xE6EA, 0x7DFA, 0xE6EB, 0x7DE6, 0xE6EC, 0x7DF6, 0xE6ED, 0x7DF1, 0xE6EE, 0x7DF0, + 0xE6EF, 0x7DEE, 0xE6F0, 0x7DDF, 0xE6F1, 0x7F76, 0xE6F2, 0x7FAC, 0xE6F3, 0x7FB0, 0xE6F4, 0x7FAD, 0xE6F5, 0x7FED, 0xE6F6, 0x7FEB, + 0xE6F7, 0x7FEA, 0xE6F8, 0x7FEC, 0xE6F9, 0x7FE6, 0xE6FA, 0x7FE8, 0xE6FB, 0x8064, 0xE6FC, 0x8067, 0xE6FD, 0x81A3, 0xE6FE, 0x819F, + 0xE740, 0x819E, 0xE741, 0x8195, 0xE742, 0x81A2, 0xE743, 0x8199, 0xE744, 0x8197, 0xE745, 0x8216, 0xE746, 0x824F, 0xE747, 0x8253, + 0xE748, 0x8252, 0xE749, 0x8250, 0xE74A, 0x824E, 0xE74B, 0x8251, 0xE74C, 0x8524, 0xE74D, 0x853B, 0xE74E, 0x850F, 0xE74F, 0x8500, + 0xE750, 0x8529, 0xE751, 0x850E, 0xE752, 0x8509, 0xE753, 0x850D, 0xE754, 0x851F, 0xE755, 0x850A, 0xE756, 0x8527, 0xE757, 0x851C, + 0xE758, 0x84FB, 0xE759, 0x852B, 0xE75A, 0x84FA, 0xE75B, 0x8508, 0xE75C, 0x850C, 0xE75D, 0x84F4, 0xE75E, 0x852A, 0xE75F, 0x84F2, + 0xE760, 0x8515, 0xE761, 0x84F7, 0xE762, 0x84EB, 0xE763, 0x84F3, 0xE764, 0x84FC, 0xE765, 0x8512, 0xE766, 0x84EA, 0xE767, 0x84E9, + 0xE768, 0x8516, 0xE769, 0x84FE, 0xE76A, 0x8528, 0xE76B, 0x851D, 0xE76C, 0x852E, 0xE76D, 0x8502, 0xE76E, 0x84FD, 0xE76F, 0x851E, + 0xE770, 0x84F6, 0xE771, 0x8531, 0xE772, 0x8526, 0xE773, 0x84E7, 0xE774, 0x84E8, 0xE775, 0x84F0, 0xE776, 0x84EF, 0xE777, 0x84F9, + 0xE778, 0x8518, 0xE779, 0x8520, 0xE77A, 0x8530, 0xE77B, 0x850B, 0xE77C, 0x8519, 0xE77D, 0x852F, 0xE77E, 0x8662, 0xE7A1, 0x8756, + 0xE7A2, 0x8763, 0xE7A3, 0x8764, 0xE7A4, 0x8777, 0xE7A5, 0x87E1, 0xE7A6, 0x8773, 0xE7A7, 0x8758, 0xE7A8, 0x8754, 0xE7A9, 0x875B, + 0xE7AA, 0x8752, 0xE7AB, 0x8761, 0xE7AC, 0x875A, 0xE7AD, 0x8751, 0xE7AE, 0x875E, 0xE7AF, 0x876D, 0xE7B0, 0x876A, 0xE7B1, 0x8750, + 0xE7B2, 0x874E, 0xE7B3, 0x875F, 0xE7B4, 0x875D, 0xE7B5, 0x876F, 0xE7B6, 0x876C, 0xE7B7, 0x877A, 0xE7B8, 0x876E, 0xE7B9, 0x875C, + 0xE7BA, 0x8765, 0xE7BB, 0x874F, 0xE7BC, 0x877B, 0xE7BD, 0x8775, 0xE7BE, 0x8762, 0xE7BF, 0x8767, 0xE7C0, 0x8769, 0xE7C1, 0x885A, + 0xE7C2, 0x8905, 0xE7C3, 0x890C, 0xE7C4, 0x8914, 0xE7C5, 0x890B, 0xE7C6, 0x8917, 0xE7C7, 0x8918, 0xE7C8, 0x8919, 0xE7C9, 0x8906, + 0xE7CA, 0x8916, 0xE7CB, 0x8911, 0xE7CC, 0x890E, 0xE7CD, 0x8909, 0xE7CE, 0x89A2, 0xE7CF, 0x89A4, 0xE7D0, 0x89A3, 0xE7D1, 0x89ED, + 0xE7D2, 0x89F0, 0xE7D3, 0x89EC, 0xE7D4, 0x8ACF, 0xE7D5, 0x8AC6, 0xE7D6, 0x8AB8, 0xE7D7, 0x8AD3, 0xE7D8, 0x8AD1, 0xE7D9, 0x8AD4, + 0xE7DA, 0x8AD5, 0xE7DB, 0x8ABB, 0xE7DC, 0x8AD7, 0xE7DD, 0x8ABE, 0xE7DE, 0x8AC0, 0xE7DF, 0x8AC5, 0xE7E0, 0x8AD8, 0xE7E1, 0x8AC3, + 0xE7E2, 0x8ABA, 0xE7E3, 0x8ABD, 0xE7E4, 0x8AD9, 0xE7E5, 0x8C3E, 0xE7E6, 0x8C4D, 0xE7E7, 0x8C8F, 0xE7E8, 0x8CE5, 0xE7E9, 0x8CDF, + 0xE7EA, 0x8CD9, 0xE7EB, 0x8CE8, 0xE7EC, 0x8CDA, 0xE7ED, 0x8CDD, 0xE7EE, 0x8CE7, 0xE7EF, 0x8DA0, 0xE7F0, 0x8D9C, 0xE7F1, 0x8DA1, + 0xE7F2, 0x8D9B, 0xE7F3, 0x8E20, 0xE7F4, 0x8E23, 0xE7F5, 0x8E25, 0xE7F6, 0x8E24, 0xE7F7, 0x8E2E, 0xE7F8, 0x8E15, 0xE7F9, 0x8E1B, + 0xE7FA, 0x8E16, 0xE7FB, 0x8E11, 0xE7FC, 0x8E19, 0xE7FD, 0x8E26, 0xE7FE, 0x8E27, 0xE840, 0x8E14, 0xE841, 0x8E12, 0xE842, 0x8E18, + 0xE843, 0x8E13, 0xE844, 0x8E1C, 0xE845, 0x8E17, 0xE846, 0x8E1A, 0xE847, 0x8F2C, 0xE848, 0x8F24, 0xE849, 0x8F18, 0xE84A, 0x8F1A, + 0xE84B, 0x8F20, 0xE84C, 0x8F23, 0xE84D, 0x8F16, 0xE84E, 0x8F17, 0xE84F, 0x9073, 0xE850, 0x9070, 0xE851, 0x906F, 0xE852, 0x9067, + 0xE853, 0x906B, 0xE854, 0x912F, 0xE855, 0x912B, 0xE856, 0x9129, 0xE857, 0x912A, 0xE858, 0x9132, 0xE859, 0x9126, 0xE85A, 0x912E, + 0xE85B, 0x9185, 0xE85C, 0x9186, 0xE85D, 0x918A, 0xE85E, 0x9181, 0xE85F, 0x9182, 0xE860, 0x9184, 0xE861, 0x9180, 0xE862, 0x92D0, + 0xE863, 0x92C3, 0xE864, 0x92C4, 0xE865, 0x92C0, 0xE866, 0x92D9, 0xE867, 0x92B6, 0xE868, 0x92CF, 0xE869, 0x92F1, 0xE86A, 0x92DF, + 0xE86B, 0x92D8, 0xE86C, 0x92E9, 0xE86D, 0x92D7, 0xE86E, 0x92DD, 0xE86F, 0x92CC, 0xE870, 0x92EF, 0xE871, 0x92C2, 0xE872, 0x92E8, + 0xE873, 0x92CA, 0xE874, 0x92C8, 0xE875, 0x92CE, 0xE876, 0x92E6, 0xE877, 0x92CD, 0xE878, 0x92D5, 0xE879, 0x92C9, 0xE87A, 0x92E0, + 0xE87B, 0x92DE, 0xE87C, 0x92E7, 0xE87D, 0x92D1, 0xE87E, 0x92D3, 0xE8A1, 0x92B5, 0xE8A2, 0x92E1, 0xE8A3, 0x92C6, 0xE8A4, 0x92B4, + 0xE8A5, 0x957C, 0xE8A6, 0x95AC, 0xE8A7, 0x95AB, 0xE8A8, 0x95AE, 0xE8A9, 0x95B0, 0xE8AA, 0x96A4, 0xE8AB, 0x96A2, 0xE8AC, 0x96D3, + 0xE8AD, 0x9705, 0xE8AE, 0x9708, 0xE8AF, 0x9702, 0xE8B0, 0x975A, 0xE8B1, 0x978A, 0xE8B2, 0x978E, 0xE8B3, 0x9788, 0xE8B4, 0x97D0, + 0xE8B5, 0x97CF, 0xE8B6, 0x981E, 0xE8B7, 0x981D, 0xE8B8, 0x9826, 0xE8B9, 0x9829, 0xE8BA, 0x9828, 0xE8BB, 0x9820, 0xE8BC, 0x981B, + 0xE8BD, 0x9827, 0xE8BE, 0x98B2, 0xE8BF, 0x9908, 0xE8C0, 0x98FA, 0xE8C1, 0x9911, 0xE8C2, 0x9914, 0xE8C3, 0x9916, 0xE8C4, 0x9917, + 0xE8C5, 0x9915, 0xE8C6, 0x99DC, 0xE8C7, 0x99CD, 0xE8C8, 0x99CF, 0xE8C9, 0x99D3, 0xE8CA, 0x99D4, 0xE8CB, 0x99CE, 0xE8CC, 0x99C9, + 0xE8CD, 0x99D6, 0xE8CE, 0x99D8, 0xE8CF, 0x99CB, 0xE8D0, 0x99D7, 0xE8D1, 0x99CC, 0xE8D2, 0x9AB3, 0xE8D3, 0x9AEC, 0xE8D4, 0x9AEB, + 0xE8D5, 0x9AF3, 0xE8D6, 0x9AF2, 0xE8D7, 0x9AF1, 0xE8D8, 0x9B46, 0xE8D9, 0x9B43, 0xE8DA, 0x9B67, 0xE8DB, 0x9B74, 0xE8DC, 0x9B71, + 0xE8DD, 0x9B66, 0xE8DE, 0x9B76, 0xE8DF, 0x9B75, 0xE8E0, 0x9B70, 0xE8E1, 0x9B68, 0xE8E2, 0x9B64, 0xE8E3, 0x9B6C, 0xE8E4, 0x9CFC, + 0xE8E5, 0x9CFA, 0xE8E6, 0x9CFD, 0xE8E7, 0x9CFF, 0xE8E8, 0x9CF7, 0xE8E9, 0x9D07, 0xE8EA, 0x9D00, 0xE8EB, 0x9CF9, 0xE8EC, 0x9CFB, + 0xE8ED, 0x9D08, 0xE8EE, 0x9D05, 0xE8EF, 0x9D04, 0xE8F0, 0x9E83, 0xE8F1, 0x9ED3, 0xE8F2, 0x9F0F, 0xE8F3, 0x9F10, 0xE8F4, 0x511C, + 0xE8F5, 0x5113, 0xE8F6, 0x5117, 0xE8F7, 0x511A, 0xE8F8, 0x5111, 0xE8F9, 0x51DE, 0xE8FA, 0x5334, 0xE8FB, 0x53E1, 0xE8FC, 0x5670, + 0xE8FD, 0x5660, 0xE8FE, 0x566E, 0xE940, 0x5673, 0xE941, 0x5666, 0xE942, 0x5663, 0xE943, 0x566D, 0xE944, 0x5672, 0xE945, 0x565E, + 0xE946, 0x5677, 0xE947, 0x571C, 0xE948, 0x571B, 0xE949, 0x58C8, 0xE94A, 0x58BD, 0xE94B, 0x58C9, 0xE94C, 0x58BF, 0xE94D, 0x58BA, + 0xE94E, 0x58C2, 0xE94F, 0x58BC, 0xE950, 0x58C6, 0xE951, 0x5B17, 0xE952, 0x5B19, 0xE953, 0x5B1B, 0xE954, 0x5B21, 0xE955, 0x5B14, + 0xE956, 0x5B13, 0xE957, 0x5B10, 0xE958, 0x5B16, 0xE959, 0x5B28, 0xE95A, 0x5B1A, 0xE95B, 0x5B20, 0xE95C, 0x5B1E, 0xE95D, 0x5BEF, + 0xE95E, 0x5DAC, 0xE95F, 0x5DB1, 0xE960, 0x5DA9, 0xE961, 0x5DA7, 0xE962, 0x5DB5, 0xE963, 0x5DB0, 0xE964, 0x5DAE, 0xE965, 0x5DAA, + 0xE966, 0x5DA8, 0xE967, 0x5DB2, 0xE968, 0x5DAD, 0xE969, 0x5DAF, 0xE96A, 0x5DB4, 0xE96B, 0x5E67, 0xE96C, 0x5E68, 0xE96D, 0x5E66, + 0xE96E, 0x5E6F, 0xE96F, 0x5EE9, 0xE970, 0x5EE7, 0xE971, 0x5EE6, 0xE972, 0x5EE8, 0xE973, 0x5EE5, 0xE974, 0x5F4B, 0xE975, 0x5FBC, + 0xE976, 0x619D, 0xE977, 0x61A8, 0xE978, 0x6196, 0xE979, 0x61C5, 0xE97A, 0x61B4, 0xE97B, 0x61C6, 0xE97C, 0x61C1, 0xE97D, 0x61CC, + 0xE97E, 0x61BA, 0xE9A1, 0x61BF, 0xE9A2, 0x61B8, 0xE9A3, 0x618C, 0xE9A4, 0x64D7, 0xE9A5, 0x64D6, 0xE9A6, 0x64D0, 0xE9A7, 0x64CF, + 0xE9A8, 0x64C9, 0xE9A9, 0x64BD, 0xE9AA, 0x6489, 0xE9AB, 0x64C3, 0xE9AC, 0x64DB, 0xE9AD, 0x64F3, 0xE9AE, 0x64D9, 0xE9AF, 0x6533, + 0xE9B0, 0x657F, 0xE9B1, 0x657C, 0xE9B2, 0x65A2, 0xE9B3, 0x66C8, 0xE9B4, 0x66BE, 0xE9B5, 0x66C0, 0xE9B6, 0x66CA, 0xE9B7, 0x66CB, + 0xE9B8, 0x66CF, 0xE9B9, 0x66BD, 0xE9BA, 0x66BB, 0xE9BB, 0x66BA, 0xE9BC, 0x66CC, 0xE9BD, 0x6723, 0xE9BE, 0x6A34, 0xE9BF, 0x6A66, + 0xE9C0, 0x6A49, 0xE9C1, 0x6A67, 0xE9C2, 0x6A32, 0xE9C3, 0x6A68, 0xE9C4, 0x6A3E, 0xE9C5, 0x6A5D, 0xE9C6, 0x6A6D, 0xE9C7, 0x6A76, + 0xE9C8, 0x6A5B, 0xE9C9, 0x6A51, 0xE9CA, 0x6A28, 0xE9CB, 0x6A5A, 0xE9CC, 0x6A3B, 0xE9CD, 0x6A3F, 0xE9CE, 0x6A41, 0xE9CF, 0x6A6A, + 0xE9D0, 0x6A64, 0xE9D1, 0x6A50, 0xE9D2, 0x6A4F, 0xE9D3, 0x6A54, 0xE9D4, 0x6A6F, 0xE9D5, 0x6A69, 0xE9D6, 0x6A60, 0xE9D7, 0x6A3C, + 0xE9D8, 0x6A5E, 0xE9D9, 0x6A56, 0xE9DA, 0x6A55, 0xE9DB, 0x6A4D, 0xE9DC, 0x6A4E, 0xE9DD, 0x6A46, 0xE9DE, 0x6B55, 0xE9DF, 0x6B54, + 0xE9E0, 0x6B56, 0xE9E1, 0x6BA7, 0xE9E2, 0x6BAA, 0xE9E3, 0x6BAB, 0xE9E4, 0x6BC8, 0xE9E5, 0x6BC7, 0xE9E6, 0x6C04, 0xE9E7, 0x6C03, + 0xE9E8, 0x6C06, 0xE9E9, 0x6FAD, 0xE9EA, 0x6FCB, 0xE9EB, 0x6FA3, 0xE9EC, 0x6FC7, 0xE9ED, 0x6FBC, 0xE9EE, 0x6FCE, 0xE9EF, 0x6FC8, + 0xE9F0, 0x6F5E, 0xE9F1, 0x6FC4, 0xE9F2, 0x6FBD, 0xE9F3, 0x6F9E, 0xE9F4, 0x6FCA, 0xE9F5, 0x6FA8, 0xE9F6, 0x7004, 0xE9F7, 0x6FA5, + 0xE9F8, 0x6FAE, 0xE9F9, 0x6FBA, 0xE9FA, 0x6FAC, 0xE9FB, 0x6FAA, 0xE9FC, 0x6FCF, 0xE9FD, 0x6FBF, 0xE9FE, 0x6FB8, 0xEA40, 0x6FA2, + 0xEA41, 0x6FC9, 0xEA42, 0x6FAB, 0xEA43, 0x6FCD, 0xEA44, 0x6FAF, 0xEA45, 0x6FB2, 0xEA46, 0x6FB0, 0xEA47, 0x71C5, 0xEA48, 0x71C2, + 0xEA49, 0x71BF, 0xEA4A, 0x71B8, 0xEA4B, 0x71D6, 0xEA4C, 0x71C0, 0xEA4D, 0x71C1, 0xEA4E, 0x71CB, 0xEA4F, 0x71D4, 0xEA50, 0x71CA, + 0xEA51, 0x71C7, 0xEA52, 0x71CF, 0xEA53, 0x71BD, 0xEA54, 0x71D8, 0xEA55, 0x71BC, 0xEA56, 0x71C6, 0xEA57, 0x71DA, 0xEA58, 0x71DB, + 0xEA59, 0x729D, 0xEA5A, 0x729E, 0xEA5B, 0x7369, 0xEA5C, 0x7366, 0xEA5D, 0x7367, 0xEA5E, 0x736C, 0xEA5F, 0x7365, 0xEA60, 0x736B, + 0xEA61, 0x736A, 0xEA62, 0x747F, 0xEA63, 0x749A, 0xEA64, 0x74A0, 0xEA65, 0x7494, 0xEA66, 0x7492, 0xEA67, 0x7495, 0xEA68, 0x74A1, + 0xEA69, 0x750B, 0xEA6A, 0x7580, 0xEA6B, 0x762F, 0xEA6C, 0x762D, 0xEA6D, 0x7631, 0xEA6E, 0x763D, 0xEA6F, 0x7633, 0xEA70, 0x763C, + 0xEA71, 0x7635, 0xEA72, 0x7632, 0xEA73, 0x7630, 0xEA74, 0x76BB, 0xEA75, 0x76E6, 0xEA76, 0x779A, 0xEA77, 0x779D, 0xEA78, 0x77A1, + 0xEA79, 0x779C, 0xEA7A, 0x779B, 0xEA7B, 0x77A2, 0xEA7C, 0x77A3, 0xEA7D, 0x7795, 0xEA7E, 0x7799, 0xEAA1, 0x7797, 0xEAA2, 0x78DD, + 0xEAA3, 0x78E9, 0xEAA4, 0x78E5, 0xEAA5, 0x78EA, 0xEAA6, 0x78DE, 0xEAA7, 0x78E3, 0xEAA8, 0x78DB, 0xEAA9, 0x78E1, 0xEAAA, 0x78E2, + 0xEAAB, 0x78ED, 0xEAAC, 0x78DF, 0xEAAD, 0x78E0, 0xEAAE, 0x79A4, 0xEAAF, 0x7A44, 0xEAB0, 0x7A48, 0xEAB1, 0x7A47, 0xEAB2, 0x7AB6, + 0xEAB3, 0x7AB8, 0xEAB4, 0x7AB5, 0xEAB5, 0x7AB1, 0xEAB6, 0x7AB7, 0xEAB7, 0x7BDE, 0xEAB8, 0x7BE3, 0xEAB9, 0x7BE7, 0xEABA, 0x7BDD, + 0xEABB, 0x7BD5, 0xEABC, 0x7BE5, 0xEABD, 0x7BDA, 0xEABE, 0x7BE8, 0xEABF, 0x7BF9, 0xEAC0, 0x7BD4, 0xEAC1, 0x7BEA, 0xEAC2, 0x7BE2, + 0xEAC3, 0x7BDC, 0xEAC4, 0x7BEB, 0xEAC5, 0x7BD8, 0xEAC6, 0x7BDF, 0xEAC7, 0x7CD2, 0xEAC8, 0x7CD4, 0xEAC9, 0x7CD7, 0xEACA, 0x7CD0, + 0xEACB, 0x7CD1, 0xEACC, 0x7E12, 0xEACD, 0x7E21, 0xEACE, 0x7E17, 0xEACF, 0x7E0C, 0xEAD0, 0x7E1F, 0xEAD1, 0x7E20, 0xEAD2, 0x7E13, + 0xEAD3, 0x7E0E, 0xEAD4, 0x7E1C, 0xEAD5, 0x7E15, 0xEAD6, 0x7E1A, 0xEAD7, 0x7E22, 0xEAD8, 0x7E0B, 0xEAD9, 0x7E0F, 0xEADA, 0x7E16, + 0xEADB, 0x7E0D, 0xEADC, 0x7E14, 0xEADD, 0x7E25, 0xEADE, 0x7E24, 0xEADF, 0x7F43, 0xEAE0, 0x7F7B, 0xEAE1, 0x7F7C, 0xEAE2, 0x7F7A, + 0xEAE3, 0x7FB1, 0xEAE4, 0x7FEF, 0xEAE5, 0x802A, 0xEAE6, 0x8029, 0xEAE7, 0x806C, 0xEAE8, 0x81B1, 0xEAE9, 0x81A6, 0xEAEA, 0x81AE, + 0xEAEB, 0x81B9, 0xEAEC, 0x81B5, 0xEAED, 0x81AB, 0xEAEE, 0x81B0, 0xEAEF, 0x81AC, 0xEAF0, 0x81B4, 0xEAF1, 0x81B2, 0xEAF2, 0x81B7, + 0xEAF3, 0x81A7, 0xEAF4, 0x81F2, 0xEAF5, 0x8255, 0xEAF6, 0x8256, 0xEAF7, 0x8257, 0xEAF8, 0x8556, 0xEAF9, 0x8545, 0xEAFA, 0x856B, + 0xEAFB, 0x854D, 0xEAFC, 0x8553, 0xEAFD, 0x8561, 0xEAFE, 0x8558, 0xEB40, 0x8540, 0xEB41, 0x8546, 0xEB42, 0x8564, 0xEB43, 0x8541, + 0xEB44, 0x8562, 0xEB45, 0x8544, 0xEB46, 0x8551, 0xEB47, 0x8547, 0xEB48, 0x8563, 0xEB49, 0x853E, 0xEB4A, 0x855B, 0xEB4B, 0x8571, + 0xEB4C, 0x854E, 0xEB4D, 0x856E, 0xEB4E, 0x8575, 0xEB4F, 0x8555, 0xEB50, 0x8567, 0xEB51, 0x8560, 0xEB52, 0x858C, 0xEB53, 0x8566, + 0xEB54, 0x855D, 0xEB55, 0x8554, 0xEB56, 0x8565, 0xEB57, 0x856C, 0xEB58, 0x8663, 0xEB59, 0x8665, 0xEB5A, 0x8664, 0xEB5B, 0x879B, + 0xEB5C, 0x878F, 0xEB5D, 0x8797, 0xEB5E, 0x8793, 0xEB5F, 0x8792, 0xEB60, 0x8788, 0xEB61, 0x8781, 0xEB62, 0x8796, 0xEB63, 0x8798, + 0xEB64, 0x8779, 0xEB65, 0x8787, 0xEB66, 0x87A3, 0xEB67, 0x8785, 0xEB68, 0x8790, 0xEB69, 0x8791, 0xEB6A, 0x879D, 0xEB6B, 0x8784, + 0xEB6C, 0x8794, 0xEB6D, 0x879C, 0xEB6E, 0x879A, 0xEB6F, 0x8789, 0xEB70, 0x891E, 0xEB71, 0x8926, 0xEB72, 0x8930, 0xEB73, 0x892D, + 0xEB74, 0x892E, 0xEB75, 0x8927, 0xEB76, 0x8931, 0xEB77, 0x8922, 0xEB78, 0x8929, 0xEB79, 0x8923, 0xEB7A, 0x892F, 0xEB7B, 0x892C, + 0xEB7C, 0x891F, 0xEB7D, 0x89F1, 0xEB7E, 0x8AE0, 0xEBA1, 0x8AE2, 0xEBA2, 0x8AF2, 0xEBA3, 0x8AF4, 0xEBA4, 0x8AF5, 0xEBA5, 0x8ADD, + 0xEBA6, 0x8B14, 0xEBA7, 0x8AE4, 0xEBA8, 0x8ADF, 0xEBA9, 0x8AF0, 0xEBAA, 0x8AC8, 0xEBAB, 0x8ADE, 0xEBAC, 0x8AE1, 0xEBAD, 0x8AE8, + 0xEBAE, 0x8AFF, 0xEBAF, 0x8AEF, 0xEBB0, 0x8AFB, 0xEBB1, 0x8C91, 0xEBB2, 0x8C92, 0xEBB3, 0x8C90, 0xEBB4, 0x8CF5, 0xEBB5, 0x8CEE, + 0xEBB6, 0x8CF1, 0xEBB7, 0x8CF0, 0xEBB8, 0x8CF3, 0xEBB9, 0x8D6C, 0xEBBA, 0x8D6E, 0xEBBB, 0x8DA5, 0xEBBC, 0x8DA7, 0xEBBD, 0x8E33, + 0xEBBE, 0x8E3E, 0xEBBF, 0x8E38, 0xEBC0, 0x8E40, 0xEBC1, 0x8E45, 0xEBC2, 0x8E36, 0xEBC3, 0x8E3C, 0xEBC4, 0x8E3D, 0xEBC5, 0x8E41, + 0xEBC6, 0x8E30, 0xEBC7, 0x8E3F, 0xEBC8, 0x8EBD, 0xEBC9, 0x8F36, 0xEBCA, 0x8F2E, 0xEBCB, 0x8F35, 0xEBCC, 0x8F32, 0xEBCD, 0x8F39, + 0xEBCE, 0x8F37, 0xEBCF, 0x8F34, 0xEBD0, 0x9076, 0xEBD1, 0x9079, 0xEBD2, 0x907B, 0xEBD3, 0x9086, 0xEBD4, 0x90FA, 0xEBD5, 0x9133, + 0xEBD6, 0x9135, 0xEBD7, 0x9136, 0xEBD8, 0x9193, 0xEBD9, 0x9190, 0xEBDA, 0x9191, 0xEBDB, 0x918D, 0xEBDC, 0x918F, 0xEBDD, 0x9327, + 0xEBDE, 0x931E, 0xEBDF, 0x9308, 0xEBE0, 0x931F, 0xEBE1, 0x9306, 0xEBE2, 0x930F, 0xEBE3, 0x937A, 0xEBE4, 0x9338, 0xEBE5, 0x933C, + 0xEBE6, 0x931B, 0xEBE7, 0x9323, 0xEBE8, 0x9312, 0xEBE9, 0x9301, 0xEBEA, 0x9346, 0xEBEB, 0x932D, 0xEBEC, 0x930E, 0xEBED, 0x930D, + 0xEBEE, 0x92CB, 0xEBEF, 0x931D, 0xEBF0, 0x92FA, 0xEBF1, 0x9325, 0xEBF2, 0x9313, 0xEBF3, 0x92F9, 0xEBF4, 0x92F7, 0xEBF5, 0x9334, + 0xEBF6, 0x9302, 0xEBF7, 0x9324, 0xEBF8, 0x92FF, 0xEBF9, 0x9329, 0xEBFA, 0x9339, 0xEBFB, 0x9335, 0xEBFC, 0x932A, 0xEBFD, 0x9314, + 0xEBFE, 0x930C, 0xEC40, 0x930B, 0xEC41, 0x92FE, 0xEC42, 0x9309, 0xEC43, 0x9300, 0xEC44, 0x92FB, 0xEC45, 0x9316, 0xEC46, 0x95BC, + 0xEC47, 0x95CD, 0xEC48, 0x95BE, 0xEC49, 0x95B9, 0xEC4A, 0x95BA, 0xEC4B, 0x95B6, 0xEC4C, 0x95BF, 0xEC4D, 0x95B5, 0xEC4E, 0x95BD, + 0xEC4F, 0x96A9, 0xEC50, 0x96D4, 0xEC51, 0x970B, 0xEC52, 0x9712, 0xEC53, 0x9710, 0xEC54, 0x9799, 0xEC55, 0x9797, 0xEC56, 0x9794, + 0xEC57, 0x97F0, 0xEC58, 0x97F8, 0xEC59, 0x9835, 0xEC5A, 0x982F, 0xEC5B, 0x9832, 0xEC5C, 0x9924, 0xEC5D, 0x991F, 0xEC5E, 0x9927, + 0xEC5F, 0x9929, 0xEC60, 0x999E, 0xEC61, 0x99EE, 0xEC62, 0x99EC, 0xEC63, 0x99E5, 0xEC64, 0x99E4, 0xEC65, 0x99F0, 0xEC66, 0x99E3, + 0xEC67, 0x99EA, 0xEC68, 0x99E9, 0xEC69, 0x99E7, 0xEC6A, 0x9AB9, 0xEC6B, 0x9ABF, 0xEC6C, 0x9AB4, 0xEC6D, 0x9ABB, 0xEC6E, 0x9AF6, + 0xEC6F, 0x9AFA, 0xEC70, 0x9AF9, 0xEC71, 0x9AF7, 0xEC72, 0x9B33, 0xEC73, 0x9B80, 0xEC74, 0x9B85, 0xEC75, 0x9B87, 0xEC76, 0x9B7C, + 0xEC77, 0x9B7E, 0xEC78, 0x9B7B, 0xEC79, 0x9B82, 0xEC7A, 0x9B93, 0xEC7B, 0x9B92, 0xEC7C, 0x9B90, 0xEC7D, 0x9B7A, 0xEC7E, 0x9B95, + 0xECA1, 0x9B7D, 0xECA2, 0x9B88, 0xECA3, 0x9D25, 0xECA4, 0x9D17, 0xECA5, 0x9D20, 0xECA6, 0x9D1E, 0xECA7, 0x9D14, 0xECA8, 0x9D29, + 0xECA9, 0x9D1D, 0xECAA, 0x9D18, 0xECAB, 0x9D22, 0xECAC, 0x9D10, 0xECAD, 0x9D19, 0xECAE, 0x9D1F, 0xECAF, 0x9E88, 0xECB0, 0x9E86, + 0xECB1, 0x9E87, 0xECB2, 0x9EAE, 0xECB3, 0x9EAD, 0xECB4, 0x9ED5, 0xECB5, 0x9ED6, 0xECB6, 0x9EFA, 0xECB7, 0x9F12, 0xECB8, 0x9F3D, + 0xECB9, 0x5126, 0xECBA, 0x5125, 0xECBB, 0x5122, 0xECBC, 0x5124, 0xECBD, 0x5120, 0xECBE, 0x5129, 0xECBF, 0x52F4, 0xECC0, 0x5693, + 0xECC1, 0x568C, 0xECC2, 0x568D, 0xECC3, 0x5686, 0xECC4, 0x5684, 0xECC5, 0x5683, 0xECC6, 0x567E, 0xECC7, 0x5682, 0xECC8, 0x567F, + 0xECC9, 0x5681, 0xECCA, 0x58D6, 0xECCB, 0x58D4, 0xECCC, 0x58CF, 0xECCD, 0x58D2, 0xECCE, 0x5B2D, 0xECCF, 0x5B25, 0xECD0, 0x5B32, + 0xECD1, 0x5B23, 0xECD2, 0x5B2C, 0xECD3, 0x5B27, 0xECD4, 0x5B26, 0xECD5, 0x5B2F, 0xECD6, 0x5B2E, 0xECD7, 0x5B7B, 0xECD8, 0x5BF1, + 0xECD9, 0x5BF2, 0xECDA, 0x5DB7, 0xECDB, 0x5E6C, 0xECDC, 0x5E6A, 0xECDD, 0x5FBE, 0xECDE, 0x5FBB, 0xECDF, 0x61C3, 0xECE0, 0x61B5, + 0xECE1, 0x61BC, 0xECE2, 0x61E7, 0xECE3, 0x61E0, 0xECE4, 0x61E5, 0xECE5, 0x61E4, 0xECE6, 0x61E8, 0xECE7, 0x61DE, 0xECE8, 0x64EF, + 0xECE9, 0x64E9, 0xECEA, 0x64E3, 0xECEB, 0x64EB, 0xECEC, 0x64E4, 0xECED, 0x64E8, 0xECEE, 0x6581, 0xECEF, 0x6580, 0xECF0, 0x65B6, + 0xECF1, 0x65DA, 0xECF2, 0x66D2, 0xECF3, 0x6A8D, 0xECF4, 0x6A96, 0xECF5, 0x6A81, 0xECF6, 0x6AA5, 0xECF7, 0x6A89, 0xECF8, 0x6A9F, + 0xECF9, 0x6A9B, 0xECFA, 0x6AA1, 0xECFB, 0x6A9E, 0xECFC, 0x6A87, 0xECFD, 0x6A93, 0xECFE, 0x6A8E, 0xED40, 0x6A95, 0xED41, 0x6A83, + 0xED42, 0x6AA8, 0xED43, 0x6AA4, 0xED44, 0x6A91, 0xED45, 0x6A7F, 0xED46, 0x6AA6, 0xED47, 0x6A9A, 0xED48, 0x6A85, 0xED49, 0x6A8C, + 0xED4A, 0x6A92, 0xED4B, 0x6B5B, 0xED4C, 0x6BAD, 0xED4D, 0x6C09, 0xED4E, 0x6FCC, 0xED4F, 0x6FA9, 0xED50, 0x6FF4, 0xED51, 0x6FD4, + 0xED52, 0x6FE3, 0xED53, 0x6FDC, 0xED54, 0x6FED, 0xED55, 0x6FE7, 0xED56, 0x6FE6, 0xED57, 0x6FDE, 0xED58, 0x6FF2, 0xED59, 0x6FDD, + 0xED5A, 0x6FE2, 0xED5B, 0x6FE8, 0xED5C, 0x71E1, 0xED5D, 0x71F1, 0xED5E, 0x71E8, 0xED5F, 0x71F2, 0xED60, 0x71E4, 0xED61, 0x71F0, + 0xED62, 0x71E2, 0xED63, 0x7373, 0xED64, 0x736E, 0xED65, 0x736F, 0xED66, 0x7497, 0xED67, 0x74B2, 0xED68, 0x74AB, 0xED69, 0x7490, + 0xED6A, 0x74AA, 0xED6B, 0x74AD, 0xED6C, 0x74B1, 0xED6D, 0x74A5, 0xED6E, 0x74AF, 0xED6F, 0x7510, 0xED70, 0x7511, 0xED71, 0x7512, + 0xED72, 0x750F, 0xED73, 0x7584, 0xED74, 0x7643, 0xED75, 0x7648, 0xED76, 0x7649, 0xED77, 0x7647, 0xED78, 0x76A4, 0xED79, 0x76E9, + 0xED7A, 0x77B5, 0xED7B, 0x77AB, 0xED7C, 0x77B2, 0xED7D, 0x77B7, 0xED7E, 0x77B6, 0xEDA1, 0x77B4, 0xEDA2, 0x77B1, 0xEDA3, 0x77A8, + 0xEDA4, 0x77F0, 0xEDA5, 0x78F3, 0xEDA6, 0x78FD, 0xEDA7, 0x7902, 0xEDA8, 0x78FB, 0xEDA9, 0x78FC, 0xEDAA, 0x78F2, 0xEDAB, 0x7905, + 0xEDAC, 0x78F9, 0xEDAD, 0x78FE, 0xEDAE, 0x7904, 0xEDAF, 0x79AB, 0xEDB0, 0x79A8, 0xEDB1, 0x7A5C, 0xEDB2, 0x7A5B, 0xEDB3, 0x7A56, + 0xEDB4, 0x7A58, 0xEDB5, 0x7A54, 0xEDB6, 0x7A5A, 0xEDB7, 0x7ABE, 0xEDB8, 0x7AC0, 0xEDB9, 0x7AC1, 0xEDBA, 0x7C05, 0xEDBB, 0x7C0F, + 0xEDBC, 0x7BF2, 0xEDBD, 0x7C00, 0xEDBE, 0x7BFF, 0xEDBF, 0x7BFB, 0xEDC0, 0x7C0E, 0xEDC1, 0x7BF4, 0xEDC2, 0x7C0B, 0xEDC3, 0x7BF3, + 0xEDC4, 0x7C02, 0xEDC5, 0x7C09, 0xEDC6, 0x7C03, 0xEDC7, 0x7C01, 0xEDC8, 0x7BF8, 0xEDC9, 0x7BFD, 0xEDCA, 0x7C06, 0xEDCB, 0x7BF0, + 0xEDCC, 0x7BF1, 0xEDCD, 0x7C10, 0xEDCE, 0x7C0A, 0xEDCF, 0x7CE8, 0xEDD0, 0x7E2D, 0xEDD1, 0x7E3C, 0xEDD2, 0x7E42, 0xEDD3, 0x7E33, + 0xEDD4, 0x9848, 0xEDD5, 0x7E38, 0xEDD6, 0x7E2A, 0xEDD7, 0x7E49, 0xEDD8, 0x7E40, 0xEDD9, 0x7E47, 0xEDDA, 0x7E29, 0xEDDB, 0x7E4C, + 0xEDDC, 0x7E30, 0xEDDD, 0x7E3B, 0xEDDE, 0x7E36, 0xEDDF, 0x7E44, 0xEDE0, 0x7E3A, 0xEDE1, 0x7F45, 0xEDE2, 0x7F7F, 0xEDE3, 0x7F7E, + 0xEDE4, 0x7F7D, 0xEDE5, 0x7FF4, 0xEDE6, 0x7FF2, 0xEDE7, 0x802C, 0xEDE8, 0x81BB, 0xEDE9, 0x81C4, 0xEDEA, 0x81CC, 0xEDEB, 0x81CA, + 0xEDEC, 0x81C5, 0xEDED, 0x81C7, 0xEDEE, 0x81BC, 0xEDEF, 0x81E9, 0xEDF0, 0x825B, 0xEDF1, 0x825A, 0xEDF2, 0x825C, 0xEDF3, 0x8583, + 0xEDF4, 0x8580, 0xEDF5, 0x858F, 0xEDF6, 0x85A7, 0xEDF7, 0x8595, 0xEDF8, 0x85A0, 0xEDF9, 0x858B, 0xEDFA, 0x85A3, 0xEDFB, 0x857B, + 0xEDFC, 0x85A4, 0xEDFD, 0x859A, 0xEDFE, 0x859E, 0xEE40, 0x8577, 0xEE41, 0x857C, 0xEE42, 0x8589, 0xEE43, 0x85A1, 0xEE44, 0x857A, + 0xEE45, 0x8578, 0xEE46, 0x8557, 0xEE47, 0x858E, 0xEE48, 0x8596, 0xEE49, 0x8586, 0xEE4A, 0x858D, 0xEE4B, 0x8599, 0xEE4C, 0x859D, + 0xEE4D, 0x8581, 0xEE4E, 0x85A2, 0xEE4F, 0x8582, 0xEE50, 0x8588, 0xEE51, 0x8585, 0xEE52, 0x8579, 0xEE53, 0x8576, 0xEE54, 0x8598, + 0xEE55, 0x8590, 0xEE56, 0x859F, 0xEE57, 0x8668, 0xEE58, 0x87BE, 0xEE59, 0x87AA, 0xEE5A, 0x87AD, 0xEE5B, 0x87C5, 0xEE5C, 0x87B0, + 0xEE5D, 0x87AC, 0xEE5E, 0x87B9, 0xEE5F, 0x87B5, 0xEE60, 0x87BC, 0xEE61, 0x87AE, 0xEE62, 0x87C9, 0xEE63, 0x87C3, 0xEE64, 0x87C2, + 0xEE65, 0x87CC, 0xEE66, 0x87B7, 0xEE67, 0x87AF, 0xEE68, 0x87C4, 0xEE69, 0x87CA, 0xEE6A, 0x87B4, 0xEE6B, 0x87B6, 0xEE6C, 0x87BF, + 0xEE6D, 0x87B8, 0xEE6E, 0x87BD, 0xEE6F, 0x87DE, 0xEE70, 0x87B2, 0xEE71, 0x8935, 0xEE72, 0x8933, 0xEE73, 0x893C, 0xEE74, 0x893E, + 0xEE75, 0x8941, 0xEE76, 0x8952, 0xEE77, 0x8937, 0xEE78, 0x8942, 0xEE79, 0x89AD, 0xEE7A, 0x89AF, 0xEE7B, 0x89AE, 0xEE7C, 0x89F2, + 0xEE7D, 0x89F3, 0xEE7E, 0x8B1E, 0xEEA1, 0x8B18, 0xEEA2, 0x8B16, 0xEEA3, 0x8B11, 0xEEA4, 0x8B05, 0xEEA5, 0x8B0B, 0xEEA6, 0x8B22, + 0xEEA7, 0x8B0F, 0xEEA8, 0x8B12, 0xEEA9, 0x8B15, 0xEEAA, 0x8B07, 0xEEAB, 0x8B0D, 0xEEAC, 0x8B08, 0xEEAD, 0x8B06, 0xEEAE, 0x8B1C, + 0xEEAF, 0x8B13, 0xEEB0, 0x8B1A, 0xEEB1, 0x8C4F, 0xEEB2, 0x8C70, 0xEEB3, 0x8C72, 0xEEB4, 0x8C71, 0xEEB5, 0x8C6F, 0xEEB6, 0x8C95, + 0xEEB7, 0x8C94, 0xEEB8, 0x8CF9, 0xEEB9, 0x8D6F, 0xEEBA, 0x8E4E, 0xEEBB, 0x8E4D, 0xEEBC, 0x8E53, 0xEEBD, 0x8E50, 0xEEBE, 0x8E4C, + 0xEEBF, 0x8E47, 0xEEC0, 0x8F43, 0xEEC1, 0x8F40, 0xEEC2, 0x9085, 0xEEC3, 0x907E, 0xEEC4, 0x9138, 0xEEC5, 0x919A, 0xEEC6, 0x91A2, + 0xEEC7, 0x919B, 0xEEC8, 0x9199, 0xEEC9, 0x919F, 0xEECA, 0x91A1, 0xEECB, 0x919D, 0xEECC, 0x91A0, 0xEECD, 0x93A1, 0xEECE, 0x9383, + 0xEECF, 0x93AF, 0xEED0, 0x9364, 0xEED1, 0x9356, 0xEED2, 0x9347, 0xEED3, 0x937C, 0xEED4, 0x9358, 0xEED5, 0x935C, 0xEED6, 0x9376, + 0xEED7, 0x9349, 0xEED8, 0x9350, 0xEED9, 0x9351, 0xEEDA, 0x9360, 0xEEDB, 0x936D, 0xEEDC, 0x938F, 0xEEDD, 0x934C, 0xEEDE, 0x936A, + 0xEEDF, 0x9379, 0xEEE0, 0x9357, 0xEEE1, 0x9355, 0xEEE2, 0x9352, 0xEEE3, 0x934F, 0xEEE4, 0x9371, 0xEEE5, 0x9377, 0xEEE6, 0x937B, + 0xEEE7, 0x9361, 0xEEE8, 0x935E, 0xEEE9, 0x9363, 0xEEEA, 0x9367, 0xEEEB, 0x9380, 0xEEEC, 0x934E, 0xEEED, 0x9359, 0xEEEE, 0x95C7, + 0xEEEF, 0x95C0, 0xEEF0, 0x95C9, 0xEEF1, 0x95C3, 0xEEF2, 0x95C5, 0xEEF3, 0x95B7, 0xEEF4, 0x96AE, 0xEEF5, 0x96B0, 0xEEF6, 0x96AC, + 0xEEF7, 0x9720, 0xEEF8, 0x971F, 0xEEF9, 0x9718, 0xEEFA, 0x971D, 0xEEFB, 0x9719, 0xEEFC, 0x979A, 0xEEFD, 0x97A1, 0xEEFE, 0x979C, + 0xEF40, 0x979E, 0xEF41, 0x979D, 0xEF42, 0x97D5, 0xEF43, 0x97D4, 0xEF44, 0x97F1, 0xEF45, 0x9841, 0xEF46, 0x9844, 0xEF47, 0x984A, + 0xEF48, 0x9849, 0xEF49, 0x9845, 0xEF4A, 0x9843, 0xEF4B, 0x9925, 0xEF4C, 0x992B, 0xEF4D, 0x992C, 0xEF4E, 0x992A, 0xEF4F, 0x9933, + 0xEF50, 0x9932, 0xEF51, 0x992F, 0xEF52, 0x992D, 0xEF53, 0x9931, 0xEF54, 0x9930, 0xEF55, 0x9998, 0xEF56, 0x99A3, 0xEF57, 0x99A1, + 0xEF58, 0x9A02, 0xEF59, 0x99FA, 0xEF5A, 0x99F4, 0xEF5B, 0x99F7, 0xEF5C, 0x99F9, 0xEF5D, 0x99F8, 0xEF5E, 0x99F6, 0xEF5F, 0x99FB, + 0xEF60, 0x99FD, 0xEF61, 0x99FE, 0xEF62, 0x99FC, 0xEF63, 0x9A03, 0xEF64, 0x9ABE, 0xEF65, 0x9AFE, 0xEF66, 0x9AFD, 0xEF67, 0x9B01, + 0xEF68, 0x9AFC, 0xEF69, 0x9B48, 0xEF6A, 0x9B9A, 0xEF6B, 0x9BA8, 0xEF6C, 0x9B9E, 0xEF6D, 0x9B9B, 0xEF6E, 0x9BA6, 0xEF6F, 0x9BA1, + 0xEF70, 0x9BA5, 0xEF71, 0x9BA4, 0xEF72, 0x9B86, 0xEF73, 0x9BA2, 0xEF74, 0x9BA0, 0xEF75, 0x9BAF, 0xEF76, 0x9D33, 0xEF77, 0x9D41, + 0xEF78, 0x9D67, 0xEF79, 0x9D36, 0xEF7A, 0x9D2E, 0xEF7B, 0x9D2F, 0xEF7C, 0x9D31, 0xEF7D, 0x9D38, 0xEF7E, 0x9D30, 0xEFA1, 0x9D45, + 0xEFA2, 0x9D42, 0xEFA3, 0x9D43, 0xEFA4, 0x9D3E, 0xEFA5, 0x9D37, 0xEFA6, 0x9D40, 0xEFA7, 0x9D3D, 0xEFA8, 0x7FF5, 0xEFA9, 0x9D2D, + 0xEFAA, 0x9E8A, 0xEFAB, 0x9E89, 0xEFAC, 0x9E8D, 0xEFAD, 0x9EB0, 0xEFAE, 0x9EC8, 0xEFAF, 0x9EDA, 0xEFB0, 0x9EFB, 0xEFB1, 0x9EFF, + 0xEFB2, 0x9F24, 0xEFB3, 0x9F23, 0xEFB4, 0x9F22, 0xEFB5, 0x9F54, 0xEFB6, 0x9FA0, 0xEFB7, 0x5131, 0xEFB8, 0x512D, 0xEFB9, 0x512E, + 0xEFBA, 0x5698, 0xEFBB, 0x569C, 0xEFBC, 0x5697, 0xEFBD, 0x569A, 0xEFBE, 0x569D, 0xEFBF, 0x5699, 0xEFC0, 0x5970, 0xEFC1, 0x5B3C, + 0xEFC2, 0x5C69, 0xEFC3, 0x5C6A, 0xEFC4, 0x5DC0, 0xEFC5, 0x5E6D, 0xEFC6, 0x5E6E, 0xEFC7, 0x61D8, 0xEFC8, 0x61DF, 0xEFC9, 0x61ED, + 0xEFCA, 0x61EE, 0xEFCB, 0x61F1, 0xEFCC, 0x61EA, 0xEFCD, 0x61F0, 0xEFCE, 0x61EB, 0xEFCF, 0x61D6, 0xEFD0, 0x61E9, 0xEFD1, 0x64FF, + 0xEFD2, 0x6504, 0xEFD3, 0x64FD, 0xEFD4, 0x64F8, 0xEFD5, 0x6501, 0xEFD6, 0x6503, 0xEFD7, 0x64FC, 0xEFD8, 0x6594, 0xEFD9, 0x65DB, + 0xEFDA, 0x66DA, 0xEFDB, 0x66DB, 0xEFDC, 0x66D8, 0xEFDD, 0x6AC5, 0xEFDE, 0x6AB9, 0xEFDF, 0x6ABD, 0xEFE0, 0x6AE1, 0xEFE1, 0x6AC6, + 0xEFE2, 0x6ABA, 0xEFE3, 0x6AB6, 0xEFE4, 0x6AB7, 0xEFE5, 0x6AC7, 0xEFE6, 0x6AB4, 0xEFE7, 0x6AAD, 0xEFE8, 0x6B5E, 0xEFE9, 0x6BC9, + 0xEFEA, 0x6C0B, 0xEFEB, 0x7007, 0xEFEC, 0x700C, 0xEFED, 0x700D, 0xEFEE, 0x7001, 0xEFEF, 0x7005, 0xEFF0, 0x7014, 0xEFF1, 0x700E, + 0xEFF2, 0x6FFF, 0xEFF3, 0x7000, 0xEFF4, 0x6FFB, 0xEFF5, 0x7026, 0xEFF6, 0x6FFC, 0xEFF7, 0x6FF7, 0xEFF8, 0x700A, 0xEFF9, 0x7201, + 0xEFFA, 0x71FF, 0xEFFB, 0x71F9, 0xEFFC, 0x7203, 0xEFFD, 0x71FD, 0xEFFE, 0x7376, 0xF040, 0x74B8, 0xF041, 0x74C0, 0xF042, 0x74B5, + 0xF043, 0x74C1, 0xF044, 0x74BE, 0xF045, 0x74B6, 0xF046, 0x74BB, 0xF047, 0x74C2, 0xF048, 0x7514, 0xF049, 0x7513, 0xF04A, 0x765C, + 0xF04B, 0x7664, 0xF04C, 0x7659, 0xF04D, 0x7650, 0xF04E, 0x7653, 0xF04F, 0x7657, 0xF050, 0x765A, 0xF051, 0x76A6, 0xF052, 0x76BD, + 0xF053, 0x76EC, 0xF054, 0x77C2, 0xF055, 0x77BA, 0xF056, 0x78FF, 0xF057, 0x790C, 0xF058, 0x7913, 0xF059, 0x7914, 0xF05A, 0x7909, + 0xF05B, 0x7910, 0xF05C, 0x7912, 0xF05D, 0x7911, 0xF05E, 0x79AD, 0xF05F, 0x79AC, 0xF060, 0x7A5F, 0xF061, 0x7C1C, 0xF062, 0x7C29, + 0xF063, 0x7C19, 0xF064, 0x7C20, 0xF065, 0x7C1F, 0xF066, 0x7C2D, 0xF067, 0x7C1D, 0xF068, 0x7C26, 0xF069, 0x7C28, 0xF06A, 0x7C22, + 0xF06B, 0x7C25, 0xF06C, 0x7C30, 0xF06D, 0x7E5C, 0xF06E, 0x7E50, 0xF06F, 0x7E56, 0xF070, 0x7E63, 0xF071, 0x7E58, 0xF072, 0x7E62, + 0xF073, 0x7E5F, 0xF074, 0x7E51, 0xF075, 0x7E60, 0xF076, 0x7E57, 0xF077, 0x7E53, 0xF078, 0x7FB5, 0xF079, 0x7FB3, 0xF07A, 0x7FF7, + 0xF07B, 0x7FF8, 0xF07C, 0x8075, 0xF07D, 0x81D1, 0xF07E, 0x81D2, 0xF0A1, 0x81D0, 0xF0A2, 0x825F, 0xF0A3, 0x825E, 0xF0A4, 0x85B4, + 0xF0A5, 0x85C6, 0xF0A6, 0x85C0, 0xF0A7, 0x85C3, 0xF0A8, 0x85C2, 0xF0A9, 0x85B3, 0xF0AA, 0x85B5, 0xF0AB, 0x85BD, 0xF0AC, 0x85C7, + 0xF0AD, 0x85C4, 0xF0AE, 0x85BF, 0xF0AF, 0x85CB, 0xF0B0, 0x85CE, 0xF0B1, 0x85C8, 0xF0B2, 0x85C5, 0xF0B3, 0x85B1, 0xF0B4, 0x85B6, + 0xF0B5, 0x85D2, 0xF0B6, 0x8624, 0xF0B7, 0x85B8, 0xF0B8, 0x85B7, 0xF0B9, 0x85BE, 0xF0BA, 0x8669, 0xF0BB, 0x87E7, 0xF0BC, 0x87E6, + 0xF0BD, 0x87E2, 0xF0BE, 0x87DB, 0xF0BF, 0x87EB, 0xF0C0, 0x87EA, 0xF0C1, 0x87E5, 0xF0C2, 0x87DF, 0xF0C3, 0x87F3, 0xF0C4, 0x87E4, + 0xF0C5, 0x87D4, 0xF0C6, 0x87DC, 0xF0C7, 0x87D3, 0xF0C8, 0x87ED, 0xF0C9, 0x87D8, 0xF0CA, 0x87E3, 0xF0CB, 0x87A4, 0xF0CC, 0x87D7, + 0xF0CD, 0x87D9, 0xF0CE, 0x8801, 0xF0CF, 0x87F4, 0xF0D0, 0x87E8, 0xF0D1, 0x87DD, 0xF0D2, 0x8953, 0xF0D3, 0x894B, 0xF0D4, 0x894F, + 0xF0D5, 0x894C, 0xF0D6, 0x8946, 0xF0D7, 0x8950, 0xF0D8, 0x8951, 0xF0D9, 0x8949, 0xF0DA, 0x8B2A, 0xF0DB, 0x8B27, 0xF0DC, 0x8B23, + 0xF0DD, 0x8B33, 0xF0DE, 0x8B30, 0xF0DF, 0x8B35, 0xF0E0, 0x8B47, 0xF0E1, 0x8B2F, 0xF0E2, 0x8B3C, 0xF0E3, 0x8B3E, 0xF0E4, 0x8B31, + 0xF0E5, 0x8B25, 0xF0E6, 0x8B37, 0xF0E7, 0x8B26, 0xF0E8, 0x8B36, 0xF0E9, 0x8B2E, 0xF0EA, 0x8B24, 0xF0EB, 0x8B3B, 0xF0EC, 0x8B3D, + 0xF0ED, 0x8B3A, 0xF0EE, 0x8C42, 0xF0EF, 0x8C75, 0xF0F0, 0x8C99, 0xF0F1, 0x8C98, 0xF0F2, 0x8C97, 0xF0F3, 0x8CFE, 0xF0F4, 0x8D04, + 0xF0F5, 0x8D02, 0xF0F6, 0x8D00, 0xF0F7, 0x8E5C, 0xF0F8, 0x8E62, 0xF0F9, 0x8E60, 0xF0FA, 0x8E57, 0xF0FB, 0x8E56, 0xF0FC, 0x8E5E, + 0xF0FD, 0x8E65, 0xF0FE, 0x8E67, 0xF140, 0x8E5B, 0xF141, 0x8E5A, 0xF142, 0x8E61, 0xF143, 0x8E5D, 0xF144, 0x8E69, 0xF145, 0x8E54, + 0xF146, 0x8F46, 0xF147, 0x8F47, 0xF148, 0x8F48, 0xF149, 0x8F4B, 0xF14A, 0x9128, 0xF14B, 0x913A, 0xF14C, 0x913B, 0xF14D, 0x913E, + 0xF14E, 0x91A8, 0xF14F, 0x91A5, 0xF150, 0x91A7, 0xF151, 0x91AF, 0xF152, 0x91AA, 0xF153, 0x93B5, 0xF154, 0x938C, 0xF155, 0x9392, + 0xF156, 0x93B7, 0xF157, 0x939B, 0xF158, 0x939D, 0xF159, 0x9389, 0xF15A, 0x93A7, 0xF15B, 0x938E, 0xF15C, 0x93AA, 0xF15D, 0x939E, + 0xF15E, 0x93A6, 0xF15F, 0x9395, 0xF160, 0x9388, 0xF161, 0x9399, 0xF162, 0x939F, 0xF163, 0x938D, 0xF164, 0x93B1, 0xF165, 0x9391, + 0xF166, 0x93B2, 0xF167, 0x93A4, 0xF168, 0x93A8, 0xF169, 0x93B4, 0xF16A, 0x93A3, 0xF16B, 0x93A5, 0xF16C, 0x95D2, 0xF16D, 0x95D3, + 0xF16E, 0x95D1, 0xF16F, 0x96B3, 0xF170, 0x96D7, 0xF171, 0x96DA, 0xF172, 0x5DC2, 0xF173, 0x96DF, 0xF174, 0x96D8, 0xF175, 0x96DD, + 0xF176, 0x9723, 0xF177, 0x9722, 0xF178, 0x9725, 0xF179, 0x97AC, 0xF17A, 0x97AE, 0xF17B, 0x97A8, 0xF17C, 0x97AB, 0xF17D, 0x97A4, + 0xF17E, 0x97AA, 0xF1A1, 0x97A2, 0xF1A2, 0x97A5, 0xF1A3, 0x97D7, 0xF1A4, 0x97D9, 0xF1A5, 0x97D6, 0xF1A6, 0x97D8, 0xF1A7, 0x97FA, + 0xF1A8, 0x9850, 0xF1A9, 0x9851, 0xF1AA, 0x9852, 0xF1AB, 0x98B8, 0xF1AC, 0x9941, 0xF1AD, 0x993C, 0xF1AE, 0x993A, 0xF1AF, 0x9A0F, + 0xF1B0, 0x9A0B, 0xF1B1, 0x9A09, 0xF1B2, 0x9A0D, 0xF1B3, 0x9A04, 0xF1B4, 0x9A11, 0xF1B5, 0x9A0A, 0xF1B6, 0x9A05, 0xF1B7, 0x9A07, + 0xF1B8, 0x9A06, 0xF1B9, 0x9AC0, 0xF1BA, 0x9ADC, 0xF1BB, 0x9B08, 0xF1BC, 0x9B04, 0xF1BD, 0x9B05, 0xF1BE, 0x9B29, 0xF1BF, 0x9B35, + 0xF1C0, 0x9B4A, 0xF1C1, 0x9B4C, 0xF1C2, 0x9B4B, 0xF1C3, 0x9BC7, 0xF1C4, 0x9BC6, 0xF1C5, 0x9BC3, 0xF1C6, 0x9BBF, 0xF1C7, 0x9BC1, + 0xF1C8, 0x9BB5, 0xF1C9, 0x9BB8, 0xF1CA, 0x9BD3, 0xF1CB, 0x9BB6, 0xF1CC, 0x9BC4, 0xF1CD, 0x9BB9, 0xF1CE, 0x9BBD, 0xF1CF, 0x9D5C, + 0xF1D0, 0x9D53, 0xF1D1, 0x9D4F, 0xF1D2, 0x9D4A, 0xF1D3, 0x9D5B, 0xF1D4, 0x9D4B, 0xF1D5, 0x9D59, 0xF1D6, 0x9D56, 0xF1D7, 0x9D4C, + 0xF1D8, 0x9D57, 0xF1D9, 0x9D52, 0xF1DA, 0x9D54, 0xF1DB, 0x9D5F, 0xF1DC, 0x9D58, 0xF1DD, 0x9D5A, 0xF1DE, 0x9E8E, 0xF1DF, 0x9E8C, + 0xF1E0, 0x9EDF, 0xF1E1, 0x9F01, 0xF1E2, 0x9F00, 0xF1E3, 0x9F16, 0xF1E4, 0x9F25, 0xF1E5, 0x9F2B, 0xF1E6, 0x9F2A, 0xF1E7, 0x9F29, + 0xF1E8, 0x9F28, 0xF1E9, 0x9F4C, 0xF1EA, 0x9F55, 0xF1EB, 0x5134, 0xF1EC, 0x5135, 0xF1ED, 0x5296, 0xF1EE, 0x52F7, 0xF1EF, 0x53B4, + 0xF1F0, 0x56AB, 0xF1F1, 0x56AD, 0xF1F2, 0x56A6, 0xF1F3, 0x56A7, 0xF1F4, 0x56AA, 0xF1F5, 0x56AC, 0xF1F6, 0x58DA, 0xF1F7, 0x58DD, + 0xF1F8, 0x58DB, 0xF1F9, 0x5912, 0xF1FA, 0x5B3D, 0xF1FB, 0x5B3E, 0xF1FC, 0x5B3F, 0xF1FD, 0x5DC3, 0xF1FE, 0x5E70, 0xF240, 0x5FBF, + 0xF241, 0x61FB, 0xF242, 0x6507, 0xF243, 0x6510, 0xF244, 0x650D, 0xF245, 0x6509, 0xF246, 0x650C, 0xF247, 0x650E, 0xF248, 0x6584, + 0xF249, 0x65DE, 0xF24A, 0x65DD, 0xF24B, 0x66DE, 0xF24C, 0x6AE7, 0xF24D, 0x6AE0, 0xF24E, 0x6ACC, 0xF24F, 0x6AD1, 0xF250, 0x6AD9, + 0xF251, 0x6ACB, 0xF252, 0x6ADF, 0xF253, 0x6ADC, 0xF254, 0x6AD0, 0xF255, 0x6AEB, 0xF256, 0x6ACF, 0xF257, 0x6ACD, 0xF258, 0x6ADE, + 0xF259, 0x6B60, 0xF25A, 0x6BB0, 0xF25B, 0x6C0C, 0xF25C, 0x7019, 0xF25D, 0x7027, 0xF25E, 0x7020, 0xF25F, 0x7016, 0xF260, 0x702B, + 0xF261, 0x7021, 0xF262, 0x7022, 0xF263, 0x7023, 0xF264, 0x7029, 0xF265, 0x7017, 0xF266, 0x7024, 0xF267, 0x701C, 0xF268, 0x702A, + 0xF269, 0x720C, 0xF26A, 0x720A, 0xF26B, 0x7207, 0xF26C, 0x7202, 0xF26D, 0x7205, 0xF26E, 0x72A5, 0xF26F, 0x72A6, 0xF270, 0x72A4, + 0xF271, 0x72A3, 0xF272, 0x72A1, 0xF273, 0x74CB, 0xF274, 0x74C5, 0xF275, 0x74B7, 0xF276, 0x74C3, 0xF277, 0x7516, 0xF278, 0x7660, + 0xF279, 0x77C9, 0xF27A, 0x77CA, 0xF27B, 0x77C4, 0xF27C, 0x77F1, 0xF27D, 0x791D, 0xF27E, 0x791B, 0xF2A1, 0x7921, 0xF2A2, 0x791C, + 0xF2A3, 0x7917, 0xF2A4, 0x791E, 0xF2A5, 0x79B0, 0xF2A6, 0x7A67, 0xF2A7, 0x7A68, 0xF2A8, 0x7C33, 0xF2A9, 0x7C3C, 0xF2AA, 0x7C39, + 0xF2AB, 0x7C2C, 0xF2AC, 0x7C3B, 0xF2AD, 0x7CEC, 0xF2AE, 0x7CEA, 0xF2AF, 0x7E76, 0xF2B0, 0x7E75, 0xF2B1, 0x7E78, 0xF2B2, 0x7E70, + 0xF2B3, 0x7E77, 0xF2B4, 0x7E6F, 0xF2B5, 0x7E7A, 0xF2B6, 0x7E72, 0xF2B7, 0x7E74, 0xF2B8, 0x7E68, 0xF2B9, 0x7F4B, 0xF2BA, 0x7F4A, + 0xF2BB, 0x7F83, 0xF2BC, 0x7F86, 0xF2BD, 0x7FB7, 0xF2BE, 0x7FFD, 0xF2BF, 0x7FFE, 0xF2C0, 0x8078, 0xF2C1, 0x81D7, 0xF2C2, 0x81D5, + 0xF2C3, 0x8264, 0xF2C4, 0x8261, 0xF2C5, 0x8263, 0xF2C6, 0x85EB, 0xF2C7, 0x85F1, 0xF2C8, 0x85ED, 0xF2C9, 0x85D9, 0xF2CA, 0x85E1, + 0xF2CB, 0x85E8, 0xF2CC, 0x85DA, 0xF2CD, 0x85D7, 0xF2CE, 0x85EC, 0xF2CF, 0x85F2, 0xF2D0, 0x85F8, 0xF2D1, 0x85D8, 0xF2D2, 0x85DF, + 0xF2D3, 0x85E3, 0xF2D4, 0x85DC, 0xF2D5, 0x85D1, 0xF2D6, 0x85F0, 0xF2D7, 0x85E6, 0xF2D8, 0x85EF, 0xF2D9, 0x85DE, 0xF2DA, 0x85E2, + 0xF2DB, 0x8800, 0xF2DC, 0x87FA, 0xF2DD, 0x8803, 0xF2DE, 0x87F6, 0xF2DF, 0x87F7, 0xF2E0, 0x8809, 0xF2E1, 0x880C, 0xF2E2, 0x880B, + 0xF2E3, 0x8806, 0xF2E4, 0x87FC, 0xF2E5, 0x8808, 0xF2E6, 0x87FF, 0xF2E7, 0x880A, 0xF2E8, 0x8802, 0xF2E9, 0x8962, 0xF2EA, 0x895A, + 0xF2EB, 0x895B, 0xF2EC, 0x8957, 0xF2ED, 0x8961, 0xF2EE, 0x895C, 0xF2EF, 0x8958, 0xF2F0, 0x895D, 0xF2F1, 0x8959, 0xF2F2, 0x8988, + 0xF2F3, 0x89B7, 0xF2F4, 0x89B6, 0xF2F5, 0x89F6, 0xF2F6, 0x8B50, 0xF2F7, 0x8B48, 0xF2F8, 0x8B4A, 0xF2F9, 0x8B40, 0xF2FA, 0x8B53, + 0xF2FB, 0x8B56, 0xF2FC, 0x8B54, 0xF2FD, 0x8B4B, 0xF2FE, 0x8B55, 0xF340, 0x8B51, 0xF341, 0x8B42, 0xF342, 0x8B52, 0xF343, 0x8B57, + 0xF344, 0x8C43, 0xF345, 0x8C77, 0xF346, 0x8C76, 0xF347, 0x8C9A, 0xF348, 0x8D06, 0xF349, 0x8D07, 0xF34A, 0x8D09, 0xF34B, 0x8DAC, + 0xF34C, 0x8DAA, 0xF34D, 0x8DAD, 0xF34E, 0x8DAB, 0xF34F, 0x8E6D, 0xF350, 0x8E78, 0xF351, 0x8E73, 0xF352, 0x8E6A, 0xF353, 0x8E6F, + 0xF354, 0x8E7B, 0xF355, 0x8EC2, 0xF356, 0x8F52, 0xF357, 0x8F51, 0xF358, 0x8F4F, 0xF359, 0x8F50, 0xF35A, 0x8F53, 0xF35B, 0x8FB4, + 0xF35C, 0x9140, 0xF35D, 0x913F, 0xF35E, 0x91B0, 0xF35F, 0x91AD, 0xF360, 0x93DE, 0xF361, 0x93C7, 0xF362, 0x93CF, 0xF363, 0x93C2, + 0xF364, 0x93DA, 0xF365, 0x93D0, 0xF366, 0x93F9, 0xF367, 0x93EC, 0xF368, 0x93CC, 0xF369, 0x93D9, 0xF36A, 0x93A9, 0xF36B, 0x93E6, + 0xF36C, 0x93CA, 0xF36D, 0x93D4, 0xF36E, 0x93EE, 0xF36F, 0x93E3, 0xF370, 0x93D5, 0xF371, 0x93C4, 0xF372, 0x93CE, 0xF373, 0x93C0, + 0xF374, 0x93D2, 0xF375, 0x93E7, 0xF376, 0x957D, 0xF377, 0x95DA, 0xF378, 0x95DB, 0xF379, 0x96E1, 0xF37A, 0x9729, 0xF37B, 0x972B, + 0xF37C, 0x972C, 0xF37D, 0x9728, 0xF37E, 0x9726, 0xF3A1, 0x97B3, 0xF3A2, 0x97B7, 0xF3A3, 0x97B6, 0xF3A4, 0x97DD, 0xF3A5, 0x97DE, + 0xF3A6, 0x97DF, 0xF3A7, 0x985C, 0xF3A8, 0x9859, 0xF3A9, 0x985D, 0xF3AA, 0x9857, 0xF3AB, 0x98BF, 0xF3AC, 0x98BD, 0xF3AD, 0x98BB, + 0xF3AE, 0x98BE, 0xF3AF, 0x9948, 0xF3B0, 0x9947, 0xF3B1, 0x9943, 0xF3B2, 0x99A6, 0xF3B3, 0x99A7, 0xF3B4, 0x9A1A, 0xF3B5, 0x9A15, + 0xF3B6, 0x9A25, 0xF3B7, 0x9A1D, 0xF3B8, 0x9A24, 0xF3B9, 0x9A1B, 0xF3BA, 0x9A22, 0xF3BB, 0x9A20, 0xF3BC, 0x9A27, 0xF3BD, 0x9A23, + 0xF3BE, 0x9A1E, 0xF3BF, 0x9A1C, 0xF3C0, 0x9A14, 0xF3C1, 0x9AC2, 0xF3C2, 0x9B0B, 0xF3C3, 0x9B0A, 0xF3C4, 0x9B0E, 0xF3C5, 0x9B0C, + 0xF3C6, 0x9B37, 0xF3C7, 0x9BEA, 0xF3C8, 0x9BEB, 0xF3C9, 0x9BE0, 0xF3CA, 0x9BDE, 0xF3CB, 0x9BE4, 0xF3CC, 0x9BE6, 0xF3CD, 0x9BE2, + 0xF3CE, 0x9BF0, 0xF3CF, 0x9BD4, 0xF3D0, 0x9BD7, 0xF3D1, 0x9BEC, 0xF3D2, 0x9BDC, 0xF3D3, 0x9BD9, 0xF3D4, 0x9BE5, 0xF3D5, 0x9BD5, + 0xF3D6, 0x9BE1, 0xF3D7, 0x9BDA, 0xF3D8, 0x9D77, 0xF3D9, 0x9D81, 0xF3DA, 0x9D8A, 0xF3DB, 0x9D84, 0xF3DC, 0x9D88, 0xF3DD, 0x9D71, + 0xF3DE, 0x9D80, 0xF3DF, 0x9D78, 0xF3E0, 0x9D86, 0xF3E1, 0x9D8B, 0xF3E2, 0x9D8C, 0xF3E3, 0x9D7D, 0xF3E4, 0x9D6B, 0xF3E5, 0x9D74, + 0xF3E6, 0x9D75, 0xF3E7, 0x9D70, 0xF3E8, 0x9D69, 0xF3E9, 0x9D85, 0xF3EA, 0x9D73, 0xF3EB, 0x9D7B, 0xF3EC, 0x9D82, 0xF3ED, 0x9D6F, + 0xF3EE, 0x9D79, 0xF3EF, 0x9D7F, 0xF3F0, 0x9D87, 0xF3F1, 0x9D68, 0xF3F2, 0x9E94, 0xF3F3, 0x9E91, 0xF3F4, 0x9EC0, 0xF3F5, 0x9EFC, + 0xF3F6, 0x9F2D, 0xF3F7, 0x9F40, 0xF3F8, 0x9F41, 0xF3F9, 0x9F4D, 0xF3FA, 0x9F56, 0xF3FB, 0x9F57, 0xF3FC, 0x9F58, 0xF3FD, 0x5337, + 0xF3FE, 0x56B2, 0xF440, 0x56B5, 0xF441, 0x56B3, 0xF442, 0x58E3, 0xF443, 0x5B45, 0xF444, 0x5DC6, 0xF445, 0x5DC7, 0xF446, 0x5EEE, + 0xF447, 0x5EEF, 0xF448, 0x5FC0, 0xF449, 0x5FC1, 0xF44A, 0x61F9, 0xF44B, 0x6517, 0xF44C, 0x6516, 0xF44D, 0x6515, 0xF44E, 0x6513, + 0xF44F, 0x65DF, 0xF450, 0x66E8, 0xF451, 0x66E3, 0xF452, 0x66E4, 0xF453, 0x6AF3, 0xF454, 0x6AF0, 0xF455, 0x6AEA, 0xF456, 0x6AE8, + 0xF457, 0x6AF9, 0xF458, 0x6AF1, 0xF459, 0x6AEE, 0xF45A, 0x6AEF, 0xF45B, 0x703C, 0xF45C, 0x7035, 0xF45D, 0x702F, 0xF45E, 0x7037, + 0xF45F, 0x7034, 0xF460, 0x7031, 0xF461, 0x7042, 0xF462, 0x7038, 0xF463, 0x703F, 0xF464, 0x703A, 0xF465, 0x7039, 0xF466, 0x7040, + 0xF467, 0x703B, 0xF468, 0x7033, 0xF469, 0x7041, 0xF46A, 0x7213, 0xF46B, 0x7214, 0xF46C, 0x72A8, 0xF46D, 0x737D, 0xF46E, 0x737C, + 0xF46F, 0x74BA, 0xF470, 0x76AB, 0xF471, 0x76AA, 0xF472, 0x76BE, 0xF473, 0x76ED, 0xF474, 0x77CC, 0xF475, 0x77CE, 0xF476, 0x77CF, + 0xF477, 0x77CD, 0xF478, 0x77F2, 0xF479, 0x7925, 0xF47A, 0x7923, 0xF47B, 0x7927, 0xF47C, 0x7928, 0xF47D, 0x7924, 0xF47E, 0x7929, + 0xF4A1, 0x79B2, 0xF4A2, 0x7A6E, 0xF4A3, 0x7A6C, 0xF4A4, 0x7A6D, 0xF4A5, 0x7AF7, 0xF4A6, 0x7C49, 0xF4A7, 0x7C48, 0xF4A8, 0x7C4A, + 0xF4A9, 0x7C47, 0xF4AA, 0x7C45, 0xF4AB, 0x7CEE, 0xF4AC, 0x7E7B, 0xF4AD, 0x7E7E, 0xF4AE, 0x7E81, 0xF4AF, 0x7E80, 0xF4B0, 0x7FBA, + 0xF4B1, 0x7FFF, 0xF4B2, 0x8079, 0xF4B3, 0x81DB, 0xF4B4, 0x81D9, 0xF4B5, 0x820B, 0xF4B6, 0x8268, 0xF4B7, 0x8269, 0xF4B8, 0x8622, + 0xF4B9, 0x85FF, 0xF4BA, 0x8601, 0xF4BB, 0x85FE, 0xF4BC, 0x861B, 0xF4BD, 0x8600, 0xF4BE, 0x85F6, 0xF4BF, 0x8604, 0xF4C0, 0x8609, + 0xF4C1, 0x8605, 0xF4C2, 0x860C, 0xF4C3, 0x85FD, 0xF4C4, 0x8819, 0xF4C5, 0x8810, 0xF4C6, 0x8811, 0xF4C7, 0x8817, 0xF4C8, 0x8813, + 0xF4C9, 0x8816, 0xF4CA, 0x8963, 0xF4CB, 0x8966, 0xF4CC, 0x89B9, 0xF4CD, 0x89F7, 0xF4CE, 0x8B60, 0xF4CF, 0x8B6A, 0xF4D0, 0x8B5D, + 0xF4D1, 0x8B68, 0xF4D2, 0x8B63, 0xF4D3, 0x8B65, 0xF4D4, 0x8B67, 0xF4D5, 0x8B6D, 0xF4D6, 0x8DAE, 0xF4D7, 0x8E86, 0xF4D8, 0x8E88, + 0xF4D9, 0x8E84, 0xF4DA, 0x8F59, 0xF4DB, 0x8F56, 0xF4DC, 0x8F57, 0xF4DD, 0x8F55, 0xF4DE, 0x8F58, 0xF4DF, 0x8F5A, 0xF4E0, 0x908D, + 0xF4E1, 0x9143, 0xF4E2, 0x9141, 0xF4E3, 0x91B7, 0xF4E4, 0x91B5, 0xF4E5, 0x91B2, 0xF4E6, 0x91B3, 0xF4E7, 0x940B, 0xF4E8, 0x9413, + 0xF4E9, 0x93FB, 0xF4EA, 0x9420, 0xF4EB, 0x940F, 0xF4EC, 0x9414, 0xF4ED, 0x93FE, 0xF4EE, 0x9415, 0xF4EF, 0x9410, 0xF4F0, 0x9428, + 0xF4F1, 0x9419, 0xF4F2, 0x940D, 0xF4F3, 0x93F5, 0xF4F4, 0x9400, 0xF4F5, 0x93F7, 0xF4F6, 0x9407, 0xF4F7, 0x940E, 0xF4F8, 0x9416, + 0xF4F9, 0x9412, 0xF4FA, 0x93FA, 0xF4FB, 0x9409, 0xF4FC, 0x93F8, 0xF4FD, 0x940A, 0xF4FE, 0x93FF, 0xF540, 0x93FC, 0xF541, 0x940C, + 0xF542, 0x93F6, 0xF543, 0x9411, 0xF544, 0x9406, 0xF545, 0x95DE, 0xF546, 0x95E0, 0xF547, 0x95DF, 0xF548, 0x972E, 0xF549, 0x972F, + 0xF54A, 0x97B9, 0xF54B, 0x97BB, 0xF54C, 0x97FD, 0xF54D, 0x97FE, 0xF54E, 0x9860, 0xF54F, 0x9862, 0xF550, 0x9863, 0xF551, 0x985F, + 0xF552, 0x98C1, 0xF553, 0x98C2, 0xF554, 0x9950, 0xF555, 0x994E, 0xF556, 0x9959, 0xF557, 0x994C, 0xF558, 0x994B, 0xF559, 0x9953, + 0xF55A, 0x9A32, 0xF55B, 0x9A34, 0xF55C, 0x9A31, 0xF55D, 0x9A2C, 0xF55E, 0x9A2A, 0xF55F, 0x9A36, 0xF560, 0x9A29, 0xF561, 0x9A2E, + 0xF562, 0x9A38, 0xF563, 0x9A2D, 0xF564, 0x9AC7, 0xF565, 0x9ACA, 0xF566, 0x9AC6, 0xF567, 0x9B10, 0xF568, 0x9B12, 0xF569, 0x9B11, + 0xF56A, 0x9C0B, 0xF56B, 0x9C08, 0xF56C, 0x9BF7, 0xF56D, 0x9C05, 0xF56E, 0x9C12, 0xF56F, 0x9BF8, 0xF570, 0x9C40, 0xF571, 0x9C07, + 0xF572, 0x9C0E, 0xF573, 0x9C06, 0xF574, 0x9C17, 0xF575, 0x9C14, 0xF576, 0x9C09, 0xF577, 0x9D9F, 0xF578, 0x9D99, 0xF579, 0x9DA4, + 0xF57A, 0x9D9D, 0xF57B, 0x9D92, 0xF57C, 0x9D98, 0xF57D, 0x9D90, 0xF57E, 0x9D9B, 0xF5A1, 0x9DA0, 0xF5A2, 0x9D94, 0xF5A3, 0x9D9C, + 0xF5A4, 0x9DAA, 0xF5A5, 0x9D97, 0xF5A6, 0x9DA1, 0xF5A7, 0x9D9A, 0xF5A8, 0x9DA2, 0xF5A9, 0x9DA8, 0xF5AA, 0x9D9E, 0xF5AB, 0x9DA3, + 0xF5AC, 0x9DBF, 0xF5AD, 0x9DA9, 0xF5AE, 0x9D96, 0xF5AF, 0x9DA6, 0xF5B0, 0x9DA7, 0xF5B1, 0x9E99, 0xF5B2, 0x9E9B, 0xF5B3, 0x9E9A, + 0xF5B4, 0x9EE5, 0xF5B5, 0x9EE4, 0xF5B6, 0x9EE7, 0xF5B7, 0x9EE6, 0xF5B8, 0x9F30, 0xF5B9, 0x9F2E, 0xF5BA, 0x9F5B, 0xF5BB, 0x9F60, + 0xF5BC, 0x9F5E, 0xF5BD, 0x9F5D, 0xF5BE, 0x9F59, 0xF5BF, 0x9F91, 0xF5C0, 0x513A, 0xF5C1, 0x5139, 0xF5C2, 0x5298, 0xF5C3, 0x5297, + 0xF5C4, 0x56C3, 0xF5C5, 0x56BD, 0xF5C6, 0x56BE, 0xF5C7, 0x5B48, 0xF5C8, 0x5B47, 0xF5C9, 0x5DCB, 0xF5CA, 0x5DCF, 0xF5CB, 0x5EF1, + 0xF5CC, 0x61FD, 0xF5CD, 0x651B, 0xF5CE, 0x6B02, 0xF5CF, 0x6AFC, 0xF5D0, 0x6B03, 0xF5D1, 0x6AF8, 0xF5D2, 0x6B00, 0xF5D3, 0x7043, + 0xF5D4, 0x7044, 0xF5D5, 0x704A, 0xF5D6, 0x7048, 0xF5D7, 0x7049, 0xF5D8, 0x7045, 0xF5D9, 0x7046, 0xF5DA, 0x721D, 0xF5DB, 0x721A, + 0xF5DC, 0x7219, 0xF5DD, 0x737E, 0xF5DE, 0x7517, 0xF5DF, 0x766A, 0xF5E0, 0x77D0, 0xF5E1, 0x792D, 0xF5E2, 0x7931, 0xF5E3, 0x792F, + 0xF5E4, 0x7C54, 0xF5E5, 0x7C53, 0xF5E6, 0x7CF2, 0xF5E7, 0x7E8A, 0xF5E8, 0x7E87, 0xF5E9, 0x7E88, 0xF5EA, 0x7E8B, 0xF5EB, 0x7E86, + 0xF5EC, 0x7E8D, 0xF5ED, 0x7F4D, 0xF5EE, 0x7FBB, 0xF5EF, 0x8030, 0xF5F0, 0x81DD, 0xF5F1, 0x8618, 0xF5F2, 0x862A, 0xF5F3, 0x8626, + 0xF5F4, 0x861F, 0xF5F5, 0x8623, 0xF5F6, 0x861C, 0xF5F7, 0x8619, 0xF5F8, 0x8627, 0xF5F9, 0x862E, 0xF5FA, 0x8621, 0xF5FB, 0x8620, + 0xF5FC, 0x8629, 0xF5FD, 0x861E, 0xF5FE, 0x8625, 0xF640, 0x8829, 0xF641, 0x881D, 0xF642, 0x881B, 0xF643, 0x8820, 0xF644, 0x8824, + 0xF645, 0x881C, 0xF646, 0x882B, 0xF647, 0x884A, 0xF648, 0x896D, 0xF649, 0x8969, 0xF64A, 0x896E, 0xF64B, 0x896B, 0xF64C, 0x89FA, + 0xF64D, 0x8B79, 0xF64E, 0x8B78, 0xF64F, 0x8B45, 0xF650, 0x8B7A, 0xF651, 0x8B7B, 0xF652, 0x8D10, 0xF653, 0x8D14, 0xF654, 0x8DAF, + 0xF655, 0x8E8E, 0xF656, 0x8E8C, 0xF657, 0x8F5E, 0xF658, 0x8F5B, 0xF659, 0x8F5D, 0xF65A, 0x9146, 0xF65B, 0x9144, 0xF65C, 0x9145, + 0xF65D, 0x91B9, 0xF65E, 0x943F, 0xF65F, 0x943B, 0xF660, 0x9436, 0xF661, 0x9429, 0xF662, 0x943D, 0xF663, 0x943C, 0xF664, 0x9430, + 0xF665, 0x9439, 0xF666, 0x942A, 0xF667, 0x9437, 0xF668, 0x942C, 0xF669, 0x9440, 0xF66A, 0x9431, 0xF66B, 0x95E5, 0xF66C, 0x95E4, + 0xF66D, 0x95E3, 0xF66E, 0x9735, 0xF66F, 0x973A, 0xF670, 0x97BF, 0xF671, 0x97E1, 0xF672, 0x9864, 0xF673, 0x98C9, 0xF674, 0x98C6, + 0xF675, 0x98C0, 0xF676, 0x9958, 0xF677, 0x9956, 0xF678, 0x9A39, 0xF679, 0x9A3D, 0xF67A, 0x9A46, 0xF67B, 0x9A44, 0xF67C, 0x9A42, + 0xF67D, 0x9A41, 0xF67E, 0x9A3A, 0xF6A1, 0x9A3F, 0xF6A2, 0x9ACD, 0xF6A3, 0x9B15, 0xF6A4, 0x9B17, 0xF6A5, 0x9B18, 0xF6A6, 0x9B16, + 0xF6A7, 0x9B3A, 0xF6A8, 0x9B52, 0xF6A9, 0x9C2B, 0xF6AA, 0x9C1D, 0xF6AB, 0x9C1C, 0xF6AC, 0x9C2C, 0xF6AD, 0x9C23, 0xF6AE, 0x9C28, + 0xF6AF, 0x9C29, 0xF6B0, 0x9C24, 0xF6B1, 0x9C21, 0xF6B2, 0x9DB7, 0xF6B3, 0x9DB6, 0xF6B4, 0x9DBC, 0xF6B5, 0x9DC1, 0xF6B6, 0x9DC7, + 0xF6B7, 0x9DCA, 0xF6B8, 0x9DCF, 0xF6B9, 0x9DBE, 0xF6BA, 0x9DC5, 0xF6BB, 0x9DC3, 0xF6BC, 0x9DBB, 0xF6BD, 0x9DB5, 0xF6BE, 0x9DCE, + 0xF6BF, 0x9DB9, 0xF6C0, 0x9DBA, 0xF6C1, 0x9DAC, 0xF6C2, 0x9DC8, 0xF6C3, 0x9DB1, 0xF6C4, 0x9DAD, 0xF6C5, 0x9DCC, 0xF6C6, 0x9DB3, + 0xF6C7, 0x9DCD, 0xF6C8, 0x9DB2, 0xF6C9, 0x9E7A, 0xF6CA, 0x9E9C, 0xF6CB, 0x9EEB, 0xF6CC, 0x9EEE, 0xF6CD, 0x9EED, 0xF6CE, 0x9F1B, + 0xF6CF, 0x9F18, 0xF6D0, 0x9F1A, 0xF6D1, 0x9F31, 0xF6D2, 0x9F4E, 0xF6D3, 0x9F65, 0xF6D4, 0x9F64, 0xF6D5, 0x9F92, 0xF6D6, 0x4EB9, + 0xF6D7, 0x56C6, 0xF6D8, 0x56C5, 0xF6D9, 0x56CB, 0xF6DA, 0x5971, 0xF6DB, 0x5B4B, 0xF6DC, 0x5B4C, 0xF6DD, 0x5DD5, 0xF6DE, 0x5DD1, + 0xF6DF, 0x5EF2, 0xF6E0, 0x6521, 0xF6E1, 0x6520, 0xF6E2, 0x6526, 0xF6E3, 0x6522, 0xF6E4, 0x6B0B, 0xF6E5, 0x6B08, 0xF6E6, 0x6B09, + 0xF6E7, 0x6C0D, 0xF6E8, 0x7055, 0xF6E9, 0x7056, 0xF6EA, 0x7057, 0xF6EB, 0x7052, 0xF6EC, 0x721E, 0xF6ED, 0x721F, 0xF6EE, 0x72A9, + 0xF6EF, 0x737F, 0xF6F0, 0x74D8, 0xF6F1, 0x74D5, 0xF6F2, 0x74D9, 0xF6F3, 0x74D7, 0xF6F4, 0x766D, 0xF6F5, 0x76AD, 0xF6F6, 0x7935, + 0xF6F7, 0x79B4, 0xF6F8, 0x7A70, 0xF6F9, 0x7A71, 0xF6FA, 0x7C57, 0xF6FB, 0x7C5C, 0xF6FC, 0x7C59, 0xF6FD, 0x7C5B, 0xF6FE, 0x7C5A, + 0xF740, 0x7CF4, 0xF741, 0x7CF1, 0xF742, 0x7E91, 0xF743, 0x7F4F, 0xF744, 0x7F87, 0xF745, 0x81DE, 0xF746, 0x826B, 0xF747, 0x8634, + 0xF748, 0x8635, 0xF749, 0x8633, 0xF74A, 0x862C, 0xF74B, 0x8632, 0xF74C, 0x8636, 0xF74D, 0x882C, 0xF74E, 0x8828, 0xF74F, 0x8826, + 0xF750, 0x882A, 0xF751, 0x8825, 0xF752, 0x8971, 0xF753, 0x89BF, 0xF754, 0x89BE, 0xF755, 0x89FB, 0xF756, 0x8B7E, 0xF757, 0x8B84, + 0xF758, 0x8B82, 0xF759, 0x8B86, 0xF75A, 0x8B85, 0xF75B, 0x8B7F, 0xF75C, 0x8D15, 0xF75D, 0x8E95, 0xF75E, 0x8E94, 0xF75F, 0x8E9A, + 0xF760, 0x8E92, 0xF761, 0x8E90, 0xF762, 0x8E96, 0xF763, 0x8E97, 0xF764, 0x8F60, 0xF765, 0x8F62, 0xF766, 0x9147, 0xF767, 0x944C, + 0xF768, 0x9450, 0xF769, 0x944A, 0xF76A, 0x944B, 0xF76B, 0x944F, 0xF76C, 0x9447, 0xF76D, 0x9445, 0xF76E, 0x9448, 0xF76F, 0x9449, + 0xF770, 0x9446, 0xF771, 0x973F, 0xF772, 0x97E3, 0xF773, 0x986A, 0xF774, 0x9869, 0xF775, 0x98CB, 0xF776, 0x9954, 0xF777, 0x995B, + 0xF778, 0x9A4E, 0xF779, 0x9A53, 0xF77A, 0x9A54, 0xF77B, 0x9A4C, 0xF77C, 0x9A4F, 0xF77D, 0x9A48, 0xF77E, 0x9A4A, 0xF7A1, 0x9A49, + 0xF7A2, 0x9A52, 0xF7A3, 0x9A50, 0xF7A4, 0x9AD0, 0xF7A5, 0x9B19, 0xF7A6, 0x9B2B, 0xF7A7, 0x9B3B, 0xF7A8, 0x9B56, 0xF7A9, 0x9B55, + 0xF7AA, 0x9C46, 0xF7AB, 0x9C48, 0xF7AC, 0x9C3F, 0xF7AD, 0x9C44, 0xF7AE, 0x9C39, 0xF7AF, 0x9C33, 0xF7B0, 0x9C41, 0xF7B1, 0x9C3C, + 0xF7B2, 0x9C37, 0xF7B3, 0x9C34, 0xF7B4, 0x9C32, 0xF7B5, 0x9C3D, 0xF7B6, 0x9C36, 0xF7B7, 0x9DDB, 0xF7B8, 0x9DD2, 0xF7B9, 0x9DDE, + 0xF7BA, 0x9DDA, 0xF7BB, 0x9DCB, 0xF7BC, 0x9DD0, 0xF7BD, 0x9DDC, 0xF7BE, 0x9DD1, 0xF7BF, 0x9DDF, 0xF7C0, 0x9DE9, 0xF7C1, 0x9DD9, + 0xF7C2, 0x9DD8, 0xF7C3, 0x9DD6, 0xF7C4, 0x9DF5, 0xF7C5, 0x9DD5, 0xF7C6, 0x9DDD, 0xF7C7, 0x9EB6, 0xF7C8, 0x9EF0, 0xF7C9, 0x9F35, + 0xF7CA, 0x9F33, 0xF7CB, 0x9F32, 0xF7CC, 0x9F42, 0xF7CD, 0x9F6B, 0xF7CE, 0x9F95, 0xF7CF, 0x9FA2, 0xF7D0, 0x513D, 0xF7D1, 0x5299, + 0xF7D2, 0x58E8, 0xF7D3, 0x58E7, 0xF7D4, 0x5972, 0xF7D5, 0x5B4D, 0xF7D6, 0x5DD8, 0xF7D7, 0x882F, 0xF7D8, 0x5F4F, 0xF7D9, 0x6201, + 0xF7DA, 0x6203, 0xF7DB, 0x6204, 0xF7DC, 0x6529, 0xF7DD, 0x6525, 0xF7DE, 0x6596, 0xF7DF, 0x66EB, 0xF7E0, 0x6B11, 0xF7E1, 0x6B12, + 0xF7E2, 0x6B0F, 0xF7E3, 0x6BCA, 0xF7E4, 0x705B, 0xF7E5, 0x705A, 0xF7E6, 0x7222, 0xF7E7, 0x7382, 0xF7E8, 0x7381, 0xF7E9, 0x7383, + 0xF7EA, 0x7670, 0xF7EB, 0x77D4, 0xF7EC, 0x7C67, 0xF7ED, 0x7C66, 0xF7EE, 0x7E95, 0xF7EF, 0x826C, 0xF7F0, 0x863A, 0xF7F1, 0x8640, + 0xF7F2, 0x8639, 0xF7F3, 0x863C, 0xF7F4, 0x8631, 0xF7F5, 0x863B, 0xF7F6, 0x863E, 0xF7F7, 0x8830, 0xF7F8, 0x8832, 0xF7F9, 0x882E, + 0xF7FA, 0x8833, 0xF7FB, 0x8976, 0xF7FC, 0x8974, 0xF7FD, 0x8973, 0xF7FE, 0x89FE, 0xF840, 0x8B8C, 0xF841, 0x8B8E, 0xF842, 0x8B8B, + 0xF843, 0x8B88, 0xF844, 0x8C45, 0xF845, 0x8D19, 0xF846, 0x8E98, 0xF847, 0x8F64, 0xF848, 0x8F63, 0xF849, 0x91BC, 0xF84A, 0x9462, + 0xF84B, 0x9455, 0xF84C, 0x945D, 0xF84D, 0x9457, 0xF84E, 0x945E, 0xF84F, 0x97C4, 0xF850, 0x97C5, 0xF851, 0x9800, 0xF852, 0x9A56, + 0xF853, 0x9A59, 0xF854, 0x9B1E, 0xF855, 0x9B1F, 0xF856, 0x9B20, 0xF857, 0x9C52, 0xF858, 0x9C58, 0xF859, 0x9C50, 0xF85A, 0x9C4A, + 0xF85B, 0x9C4D, 0xF85C, 0x9C4B, 0xF85D, 0x9C55, 0xF85E, 0x9C59, 0xF85F, 0x9C4C, 0xF860, 0x9C4E, 0xF861, 0x9DFB, 0xF862, 0x9DF7, + 0xF863, 0x9DEF, 0xF864, 0x9DE3, 0xF865, 0x9DEB, 0xF866, 0x9DF8, 0xF867, 0x9DE4, 0xF868, 0x9DF6, 0xF869, 0x9DE1, 0xF86A, 0x9DEE, + 0xF86B, 0x9DE6, 0xF86C, 0x9DF2, 0xF86D, 0x9DF0, 0xF86E, 0x9DE2, 0xF86F, 0x9DEC, 0xF870, 0x9DF4, 0xF871, 0x9DF3, 0xF872, 0x9DE8, + 0xF873, 0x9DED, 0xF874, 0x9EC2, 0xF875, 0x9ED0, 0xF876, 0x9EF2, 0xF877, 0x9EF3, 0xF878, 0x9F06, 0xF879, 0x9F1C, 0xF87A, 0x9F38, + 0xF87B, 0x9F37, 0xF87C, 0x9F36, 0xF87D, 0x9F43, 0xF87E, 0x9F4F, 0xF8A1, 0x9F71, 0xF8A2, 0x9F70, 0xF8A3, 0x9F6E, 0xF8A4, 0x9F6F, + 0xF8A5, 0x56D3, 0xF8A6, 0x56CD, 0xF8A7, 0x5B4E, 0xF8A8, 0x5C6D, 0xF8A9, 0x652D, 0xF8AA, 0x66ED, 0xF8AB, 0x66EE, 0xF8AC, 0x6B13, + 0xF8AD, 0x705F, 0xF8AE, 0x7061, 0xF8AF, 0x705D, 0xF8B0, 0x7060, 0xF8B1, 0x7223, 0xF8B2, 0x74DB, 0xF8B3, 0x74E5, 0xF8B4, 0x77D5, + 0xF8B5, 0x7938, 0xF8B6, 0x79B7, 0xF8B7, 0x79B6, 0xF8B8, 0x7C6A, 0xF8B9, 0x7E97, 0xF8BA, 0x7F89, 0xF8BB, 0x826D, 0xF8BC, 0x8643, + 0xF8BD, 0x8838, 0xF8BE, 0x8837, 0xF8BF, 0x8835, 0xF8C0, 0x884B, 0xF8C1, 0x8B94, 0xF8C2, 0x8B95, 0xF8C3, 0x8E9E, 0xF8C4, 0x8E9F, + 0xF8C5, 0x8EA0, 0xF8C6, 0x8E9D, 0xF8C7, 0x91BE, 0xF8C8, 0x91BD, 0xF8C9, 0x91C2, 0xF8CA, 0x946B, 0xF8CB, 0x9468, 0xF8CC, 0x9469, + 0xF8CD, 0x96E5, 0xF8CE, 0x9746, 0xF8CF, 0x9743, 0xF8D0, 0x9747, 0xF8D1, 0x97C7, 0xF8D2, 0x97E5, 0xF8D3, 0x9A5E, 0xF8D4, 0x9AD5, + 0xF8D5, 0x9B59, 0xF8D6, 0x9C63, 0xF8D7, 0x9C67, 0xF8D8, 0x9C66, 0xF8D9, 0x9C62, 0xF8DA, 0x9C5E, 0xF8DB, 0x9C60, 0xF8DC, 0x9E02, + 0xF8DD, 0x9DFE, 0xF8DE, 0x9E07, 0xF8DF, 0x9E03, 0xF8E0, 0x9E06, 0xF8E1, 0x9E05, 0xF8E2, 0x9E00, 0xF8E3, 0x9E01, 0xF8E4, 0x9E09, + 0xF8E5, 0x9DFF, 0xF8E6, 0x9DFD, 0xF8E7, 0x9E04, 0xF8E8, 0x9EA0, 0xF8E9, 0x9F1E, 0xF8EA, 0x9F46, 0xF8EB, 0x9F74, 0xF8EC, 0x9F75, + 0xF8ED, 0x9F76, 0xF8EE, 0x56D4, 0xF8EF, 0x652E, 0xF8F0, 0x65B8, 0xF8F1, 0x6B18, 0xF8F2, 0x6B19, 0xF8F3, 0x6B17, 0xF8F4, 0x6B1A, + 0xF8F5, 0x7062, 0xF8F6, 0x7226, 0xF8F7, 0x72AA, 0xF8F8, 0x77D8, 0xF8F9, 0x77D9, 0xF8FA, 0x7939, 0xF8FB, 0x7C69, 0xF8FC, 0x7C6B, + 0xF8FD, 0x7CF6, 0xF8FE, 0x7E9A, 0xF940, 0x7E98, 0xF941, 0x7E9B, 0xF942, 0x7E99, 0xF943, 0x81E0, 0xF944, 0x81E1, 0xF945, 0x8646, + 0xF946, 0x8647, 0xF947, 0x8648, 0xF948, 0x8979, 0xF949, 0x897A, 0xF94A, 0x897C, 0xF94B, 0x897B, 0xF94C, 0x89FF, 0xF94D, 0x8B98, + 0xF94E, 0x8B99, 0xF94F, 0x8EA5, 0xF950, 0x8EA4, 0xF951, 0x8EA3, 0xF952, 0x946E, 0xF953, 0x946D, 0xF954, 0x946F, 0xF955, 0x9471, + 0xF956, 0x9473, 0xF957, 0x9749, 0xF958, 0x9872, 0xF959, 0x995F, 0xF95A, 0x9C68, 0xF95B, 0x9C6E, 0xF95C, 0x9C6D, 0xF95D, 0x9E0B, + 0xF95E, 0x9E0D, 0xF95F, 0x9E10, 0xF960, 0x9E0F, 0xF961, 0x9E12, 0xF962, 0x9E11, 0xF963, 0x9EA1, 0xF964, 0x9EF5, 0xF965, 0x9F09, + 0xF966, 0x9F47, 0xF967, 0x9F78, 0xF968, 0x9F7B, 0xF969, 0x9F7A, 0xF96A, 0x9F79, 0xF96B, 0x571E, 0xF96C, 0x7066, 0xF96D, 0x7C6F, + 0xF96E, 0x883C, 0xF96F, 0x8DB2, 0xF970, 0x8EA6, 0xF971, 0x91C3, 0xF972, 0x9474, 0xF973, 0x9478, 0xF974, 0x9476, 0xF975, 0x9475, + 0xF976, 0x9A60, 0xF977, 0x9C74, 0xF978, 0x9C73, 0xF979, 0x9C71, 0xF97A, 0x9C75, 0xF97B, 0x9E14, 0xF97C, 0x9E13, 0xF97D, 0x9EF6, + 0xF97E, 0x9F0A, 0xF9A1, 0x9FA4, 0xF9A2, 0x7068, 0xF9A3, 0x7065, 0xF9A4, 0x7CF7, 0xF9A5, 0x866A, 0xF9A6, 0x883E, 0xF9A7, 0x883D, + 0xF9A8, 0x883F, 0xF9A9, 0x8B9E, 0xF9AA, 0x8C9C, 0xF9AB, 0x8EA9, 0xF9AC, 0x8EC9, 0xF9AD, 0x974B, 0xF9AE, 0x9873, 0xF9AF, 0x9874, + 0xF9B0, 0x98CC, 0xF9B1, 0x9961, 0xF9B2, 0x99AB, 0xF9B3, 0x9A64, 0xF9B4, 0x9A66, 0xF9B5, 0x9A67, 0xF9B6, 0x9B24, 0xF9B7, 0x9E15, + 0xF9B8, 0x9E17, 0xF9B9, 0x9F48, 0xF9BA, 0x6207, 0xF9BB, 0x6B1E, 0xF9BC, 0x7227, 0xF9BD, 0x864C, 0xF9BE, 0x8EA8, 0xF9BF, 0x9482, + 0xF9C0, 0x9480, 0xF9C1, 0x9481, 0xF9C2, 0x9A69, 0xF9C3, 0x9A68, 0xF9C4, 0x9B2E, 0xF9C5, 0x9E19, 0xF9C6, 0x7229, 0xF9C7, 0x864B, + 0xF9C8, 0x8B9F, 0xF9C9, 0x9483, 0xF9CA, 0x9C79, 0xF9CB, 0x9EB7, 0xF9CC, 0x7675, 0xF9CD, 0x9A6B, 0xF9CE, 0x9C7A, 0xF9CF, 0x9E1D, + 0xF9D0, 0x7069, 0xF9D1, 0x706A, 0xF9D2, 0x9EA4, 0xF9D3, 0x9F7E, 0xF9D4, 0x9F49, 0xF9D5, 0x9F98, 0xF9D6, 0x7881, 0xF9D7, 0x92B9, + 0xF9D8, 0x88CF, 0xF9D9, 0x58BB, 0xF9DA, 0x6052, 0xF9DB, 0x7CA7, 0xF9DC, 0x5AFA, 0xF9DD, 0x2554, 0xF9DE, 0x2566, 0xF9DF, 0x2557, + 0xF9E0, 0x2560, 0xF9E1, 0x256C, 0xF9E2, 0x2563, 0xF9E3, 0x255A, 0xF9E4, 0x2569, 0xF9E5, 0x255D, 0xF9E6, 0x2552, 0xF9E7, 0x2564, + 0xF9E8, 0x2555, 0xF9E9, 0x255E, 0xF9EA, 0x256A, 0xF9EB, 0x2561, 0xF9EC, 0x2558, 0xF9ED, 0x2567, 0xF9EE, 0x255B, 0xF9EF, 0x2553, + 0xF9F0, 0x2565, 0xF9F1, 0x2556, 0xF9F2, 0x255F, 0xF9F3, 0x256B, 0xF9F4, 0x2562, 0xF9F5, 0x2559, 0xF9F6, 0x2568, 0xF9F7, 0x255C, + 0xF9F8, 0x2551, 0xF9F9, 0x2550, 0xF9FA, 0x256D, 0xF9FB, 0x256E, 0xF9FC, 0x2570, 0xF9FD, 0x256F, 0xF9FE, 0x2593, 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0 +static const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0 +static const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */ + 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, + 0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0 +static const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */ + 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, + 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, + 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E, + 0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0 +static const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */ + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x0104, 0x0105, 0x010C, 0x010D, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x0118, 0x0119, 0x0116, 0x0117, 0x012E, 0x012F, 0x0160, 0x0161, 0x0172, 0x0173, 0x016A, 0x016B, 0x017D, 0x017E, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0 +static const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */ + 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4, + 0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D, + 0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019, + 0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0 +static const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0 +static const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, + 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4, + 0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0 +static const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */ + 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, + 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A, + 0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580, + 0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116, + 0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0 +static const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0 +static const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2, + 0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0 +static const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0 +static const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */ + 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0 +static const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0, + 0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192, + 0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2219, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0 +static const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */ + 0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518, + 0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000, + 0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5, + 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFED1, 0x061B, 0xFEB1, 0xFEB5, 0xFEB9, 0x061F, + 0x00A2, 0xFE80, 0xFE81, 0xFE83, 0xFE85, 0xFECA, 0xFE8B, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9, + 0xFEAB, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0x00A6, 0x00AC, 0x00F7, 0x00D7, 0xFEC9, + 0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFEBD, 0xFECC, 0xFECE, 0xFECD, 0xFEE1, + 0xFE7D, 0x0651, 0xFEE5, 0xFEE9, 0xFEEC, 0xFEF0, 0xFEF2, 0xFED0, 0xFED5, 0xFEF5, 0xFEF6, 0xFEDD, 0xFED9, 0xFEF1, 0x25A0, 0x0000 +}; +#endif +#if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0 +static const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0 +static const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */ + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0 +static const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */ + 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389, + 0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF, + 0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x039A, 0x039B, 0x039C, 0x039D, 0x2563, 0x2551, 0x2557, 0x255D, 0x039E, 0x039F, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0A30, 0x03A1, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x03A3, + 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x2518, 0x250C, 0x2588, 0x2584, 0x03B4, 0x03B5, 0x2580, + 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x0384, + 0x00AD, 0x00B1, 0x03C5, 0x03C6, 0x03C7, 0x00A7, 0x03C8, 0x0385, 0x00B0, 0x00A8, 0x03C9, 0x03CB, 0x03B0, 0x03CE, 0x25A0, 0x00A0 +}; +#endif + + + + +/*------------------------------------------------------------------------*/ +/* OEM <==> Unicode conversions for static code page configuration */ +/* SBCS fixed code page */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900 +WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ + DWORD uni, /* UTF-16 encoded character to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + WCHAR c = 0; + const WCHAR *p = CVTBL(uc, FF_CODE_PAGE); + + + if (uni < 0x80) { /* ASCII? */ + c = (WCHAR)uni; + + } else { /* Non-ASCII */ + if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */ + for (c = 0; c < 0x80 && uni != p[c]; c++) ; + c = (c + 0x80) & 0xFF; + } + } + + return c; +} + +WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */ + WCHAR oem, /* OEM code to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + WCHAR c = 0; + const WCHAR *p = CVTBL(uc, FF_CODE_PAGE); + + + if (oem < 0x80) { /* ASCII? */ + c = oem; + + } else { /* Extended char */ + if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */ + if (oem < 0x100) c = p[oem - 0x80]; + } + } + + return c; +} + +#endif + + + +/*------------------------------------------------------------------------*/ +/* OEM <==> Unicode conversions for static code page configuration */ +/* DBCS fixed code page */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE >= 900 +WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ + DWORD uni, /* UTF-16 encoded character to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0, uc; + UINT i = 0, n, li, hi; + + + if (uni < 0x80) { /* ASCII? */ + c = (WCHAR)uni; + + } else { /* Non-ASCII */ + if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */ + uc = (WCHAR)uni; + p = CVTBL(uni2oem, FF_CODE_PAGE); + hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1; + li = 0; + for (n = 16; n; n--) { + i = li + (hi - li) / 2; + if (uc == p[i * 2]) break; + if (uc > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + + return c; +} + + +WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */ + WCHAR oem, /* OEM code to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0; + UINT i = 0, n, li, hi; + + + if (oem < 0x80) { /* ASCII? */ + c = oem; + + } else { /* Extended char */ + if (cp == FF_CODE_PAGE) { /* Is it valid code page? */ + p = CVTBL(oem2uni, FF_CODE_PAGE); + hi = sizeof CVTBL(oem2uni, FF_CODE_PAGE) / 4 - 1; + li = 0; + for (n = 16; n; n--) { + i = li + (hi - li) / 2; + if (oem == p[i * 2]) break; + if (oem > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + + return c; +} +#endif + + + +/*------------------------------------------------------------------------*/ +/* OEM <==> Unicode conversions for dynamic code page configuration */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE == 0 + +static const WORD cp_code[] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 0}; +static const WCHAR* const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0}; + + +WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ + DWORD uni, /* UTF-16 encoded character to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0, uc; + UINT i, n, li, hi; + + + if (uni < 0x80) { /* ASCII? */ + c = (WCHAR)uni; + + } else { /* Non-ASCII */ + if (uni < 0x10000) { /* Is it in BMP? */ + uc = (WCHAR)uni; + p = 0; + if (cp < 900) { /* SBCS */ + for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get conversion table */ + p = cp_table[i]; + if (p) { /* Is it valid code page ? */ + for (c = 0; c < 0x80 && uc != p[c]; c++) ; /* Find OEM code in the table */ + c = (c + 0x80) & 0xFF; + } + } else { /* DBCS */ + switch (cp) { /* Get conversion table */ + case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break; + case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break; + case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break; + case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break; + } + if (p) { /* Is it valid code page? */ + li = 0; + for (n = 16; n; n--) { /* Find OEM code */ + i = li + (hi - li) / 2; + if (uc == p[i * 2]) break; + if (uc > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + } + } + + return c; +} + + +WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */ + WCHAR oem, /* OEM code to be converted (DBC if >=0x100) */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0; + UINT i, n, li, hi; + + + if (oem < 0x80) { /* ASCII? */ + c = oem; + + } else { /* Extended char */ + p = 0; + if (cp < 900) { /* SBCS */ + for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get table */ + p = cp_table[i]; + if (p) { /* Is it a valid CP ? */ + if (oem < 0x100) c = p[oem - 0x80]; + } + } else { /* DBCS */ + switch (cp) { + case 932 : p = oem2uni932; hi = sizeof oem2uni932 / 4 - 1; break; + case 936 : p = oem2uni936; hi = sizeof oem2uni936 / 4 - 1; break; + case 949 : p = oem2uni949; hi = sizeof oem2uni949 / 4 - 1; break; + case 950 : p = oem2uni950; hi = sizeof oem2uni950 / 4 - 1; break; + } + if (p) { + li = 0; + for (n = 16; n; n--) { + i = li + (hi - li) / 2; + if (oem == p[i * 2]) break; + if (oem > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + } + + return c; +} +#endif + + + +/*------------------------------------------------------------------------*/ +/* Unicode up-case conversion */ +/*------------------------------------------------------------------------*/ + +DWORD ff_wtoupper ( /* Returns up-converted code point */ + DWORD uni /* Unicode code point to be up-converted */ +) +{ + const WORD *p; + WORD uc, bc, nc, cmd; + static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */ + /* Basic Latin */ + 0x0061,0x031A, + /* Latin-1 Supplement */ + 0x00E0,0x0317, + 0x00F8,0x0307, + 0x00FF,0x0001,0x0178, + /* Latin Extended-A */ + 0x0100,0x0130, + 0x0132,0x0106, + 0x0139,0x0110, + 0x014A,0x012E, + 0x0179,0x0106, + /* Latin Extended-B */ + 0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA, + 0x01CD,0x0110, + 0x01DD,0x0001,0x018E, + 0x01DE,0x0112, + 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, + 0x01F8,0x0128, + 0x0222,0x0112, + 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, + 0x0246,0x010A, + /* IPA Extensions */ + 0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7, + /* Greek, Coptic */ + 0x037B,0x0003,0x03FD,0x03FE,0x03FF, + 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, + 0x03B1,0x0311, + 0x03C2,0x0002,0x03A3,0x03A3, + 0x03C4,0x0308, + 0x03CC,0x0003,0x038C,0x038E,0x038F, + 0x03D8,0x0118, + 0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA, + /* Cyrillic */ + 0x0430,0x0320, + 0x0450,0x0710, + 0x0460,0x0122, + 0x048A,0x0136, + 0x04C1,0x010E, + 0x04CF,0x0001,0x04C0, + 0x04D0,0x0144, + /* Armenian */ + 0x0561,0x0426, + + 0x0000 /* EOT */ + }; + static const WORD cvt2[] = { /* Compressed up conversion table for U+1000 - U+FFFF */ + /* Phonetic Extensions */ + 0x1D7D,0x0001,0x2C63, + /* Latin Extended Additional */ + 0x1E00,0x0196, + 0x1EA0,0x015A, + /* Greek Extended */ + 0x1F00,0x0608, + 0x1F10,0x0606, + 0x1F20,0x0608, + 0x1F30,0x0608, + 0x1F40,0x0606, + 0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, + 0x1F60,0x0608, + 0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB, + 0x1F80,0x0608, + 0x1F90,0x0608, + 0x1FA0,0x0608, + 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC, + 0x1FCC,0x0001,0x1FC3, + 0x1FD0,0x0602, + 0x1FE0,0x0602, + 0x1FE5,0x0001,0x1FEC, + 0x1FF3,0x0001,0x1FFC, + /* Letterlike Symbols */ + 0x214E,0x0001,0x2132, + /* Number forms */ + 0x2170,0x0210, + 0x2184,0x0001,0x2183, + /* Enclosed Alphanumerics */ + 0x24D0,0x051A, + 0x2C30,0x042F, + /* Latin Extended-C */ + 0x2C60,0x0102, + 0x2C67,0x0106, 0x2C75,0x0102, + /* Coptic */ + 0x2C80,0x0164, + /* Georgian Supplement */ + 0x2D00,0x0826, + /* Full-width */ + 0xFF41,0x031A, + + 0x0000 /* EOT */ + }; + + + if (uni < 0x10000) { /* Is it in BMP? */ + uc = (WORD)uni; + p = uc < 0x1000 ? cvt1 : cvt2; + for (;;) { + bc = *p++; /* Get the block base */ + if (bc == 0 || uc < bc) break; /* Not matched? */ + nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */ + if (uc < bc + nc) { /* In the block? */ + switch (cmd) { + case 0: uc = p[uc - bc]; break; /* Table conversion */ + case 1: uc -= (uc - bc) & 1; break; /* Case pairs */ + case 2: uc -= 16; break; /* Shift -16 */ + case 3: uc -= 32; break; /* Shift -32 */ + case 4: uc -= 48; break; /* Shift -48 */ + case 5: uc -= 26; break; /* Shift -26 */ + case 6: uc += 8; break; /* Shift +8 */ + case 7: uc -= 80; break; /* Shift -80 */ + case 8: uc -= 0x1C60; break; /* Shift -0x1C60 */ + } + break; + } + if (cmd == 0) p += nc; /* Skip table if needed */ + } + uni = uc; + } + + return uni; +} + + +#endif /* #if FF_USE_LFN */ diff --git a/lib-hal/include/console.h b/lib-hal/include/console.h index 38aab859..5c010711 100644 --- a/lib-hal/include/console.h +++ b/lib-hal/include/console.h @@ -2,7 +2,7 @@ * @file console.h * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -56,11 +56,11 @@ typedef enum { # endif #elif defined (CONSOLE_NULL) inline void console_init(void) {} -inline void console_putc(__attribute__((unused)) int i) {} -inline void console_puts(__attribute__((unused)) const char *p) {} -inline void console_write(__attribute__((unused)) const char *p, __attribute__((unused)) unsigned int i) {} -inline void console_status(__attribute__((unused)) uint32_t i, __attribute__((unused)) const char *p) {} -inline void console_error(__attribute__((unused)) const char *p) {} +inline void console_putc([[maybe_unused]] int i) {} +inline void console_puts([[maybe_unused]] const char *p) {} +inline void console_write([[maybe_unused]] const char *p, [[maybe_unused]] unsigned int i) {} +inline void console_status([[maybe_unused]] uint32_t i, [[maybe_unused]] const char *p) {} +extern "C" inline void console_error([[maybe_unused]] const char *p) {} #else #ifdef __cplusplus extern "C" { @@ -74,21 +74,19 @@ extern void console_set_bg_color(uint16_t); #endif #endif +#if !defined (CONSOLE_NULL) +extern void console_init(); #ifdef __cplusplus extern "C" { #endif - -#if !defined (CONSOLE_NULL) -extern void console_init(void); extern void console_putc(int); extern void console_puts(const char*); extern void console_write(const char*, unsigned int); extern void console_status(uint32_t, const char *); extern void console_error(const char*); -#endif - #ifdef __cplusplus } #endif +#endif #endif /* CONSOLE_H_ */ diff --git a/lib-debug/include/debug.h b/lib-hal/include/debug.h old mode 100644 new mode 100755 similarity index 74% rename from lib-debug/include/debug.h rename to lib-hal/include/debug.h index e98f90d6..ef8e29d5 --- a/lib-debug/include/debug.h +++ b/lib-hal/include/debug.h @@ -2,7 +2,7 @@ * @file debug.h * */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,17 +30,9 @@ #include #define DEBUG_ENTRY printf("--> %s:%s:%d\n", __FILE__, __func__, __LINE__); #define DEBUG_EXIT printf("<-- %s:%s:%d\n", __FILE__, __func__, __LINE__); - #define DEBUG1_ENTRY printf("\t--> %s:%s:%d\n", __FILE__, __func__, __LINE__); - #define DEBUG1_EXIT printf("\t<-- %s:%s:%d\n", __FILE__, __func__, __LINE__); - #define DEBUG2_ENTRY printf("\t\t--> %s:%s:%d\n", __FILE__, __func__, __LINE__); - #define DEBUG2_EXIT printf("\t\t<-- %s:%s:%d\n", __FILE__, __func__, __LINE__); #else #define DEBUG_ENTRY ((void)0); #define DEBUG_EXIT ((void)0); - #define DEBUG1_ENTRY ((void)0); - #define DEBUG1_EXIT ((void)0); - #define DEBUG2_ENTRY ((void)0); - #define DEBUG2_EXIT ((void)0); #endif #ifdef NDEBUG @@ -50,14 +42,8 @@ #define debug_print_bits(x) ((void)0) #else #include - #ifdef __cplusplus - extern "C" { - #endif - extern void debug_dump(const void *, uint16_t); - extern void debug_print_bits(uint32_t); - #ifdef __cplusplus - } - #endif + void debug_dump(const void *, uint32_t); + void debug_print_bits(uint32_t); #if defined (__linux__) || defined (__CYGWIN__) #define DEBUG_PRINTF(FORMAT, ...) \ fprintf(stderr, "%s() %s, line %i: " FORMAT "\n", __func__, __FILE__, __LINE__, __VA_ARGS__) diff --git a/lib-hal/include/device/usb/host.h b/lib-hal/include/device/usb/host.h new file mode 100644 index 00000000..fbce6622 --- /dev/null +++ b/lib-hal/include/device/usb/host.h @@ -0,0 +1,43 @@ +/* + * host.h + */ + +#ifndef DEVICE_USB_HOSTMSC_H_ +#define DEVICE_USB_HOSTMSC_H_ + +namespace usb { +namespace host { + +enum class Status { + NOT_AVAILABLE, + DISCONNECTED, + RESET, + SPEED_AVAILALBE, + ATTACHED, + CONNECTED, + ENUMERATION_COMPLETED, + READY, + DEVICE_NOT_SUPPORTED, + UNRECOVERABLE_ERROR +}; + +enum class Speed { + FAULT, + LOW, + FULL, + HIGH +}; + +enum class Class { + NOT_SUPPORTED, + MSC, + HID +}; + +Status get_status(); +Speed get_speed(); +Class get_class(); +} // namespace host +} // namespace usb + +#endif /* DEVICE_USB_HOSTMSC_H_ */ diff --git a/lib-hal/include/gd32/hal_api.h b/lib-hal/include/gd32/hal_api.h index a41381ed..cf6f7045 100644 --- a/lib-hal/include/gd32/hal_api.h +++ b/lib-hal/include/gd32/hal_api.h @@ -28,20 +28,4 @@ #define FUNC_PREFIX(x) gd32_##x -#if defined __cplusplus -# include -# if !defined(GD32_UDELAY) -# define GD32_UDELAY - void udelay(uint32_t us, uint32_t offset = 0); -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - #endif /* GD32_HAL_API_H_ */ diff --git a/lib-hal/include/gd32/hal_i2c.h b/lib-hal/include/gd32/hal_i2c.h index f6e7b057..925eb224 100644 --- a/lib-hal/include/gd32/hal_i2c.h +++ b/lib-hal/include/gd32/hal_i2c.h @@ -26,6 +26,7 @@ #ifndef GD32_HAL_I2C_H_ #define GD32_HAL_I2C_H_ +#include "gd32.h" #include "gd32_i2c.h" #endif /* GD32_HAL_I2C_H_ */ diff --git a/lib-hal/include/gd32/hal_spi.h b/lib-hal/include/gd32/hal_spi.h index 348bb332..6e8cf335 100644 --- a/lib-hal/include/gd32/hal_spi.h +++ b/lib-hal/include/gd32/hal_spi.h @@ -2,7 +2,7 @@ * @file hal_spi.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,12 +28,6 @@ #include "gd32_spi.h" -namespace hal { -namespace spi { - -} // namespace spi -} // namespace hal - #define SPI_MODE0 GD32_SPI_MODE0 #define SPI_MODE1 GD32_SPI_MODE1 #define SPI_MODE2 GD32_SPI_MODE2 diff --git a/lib-hal/include/gd32/hal_uart.h b/lib-hal/include/gd32/hal_uart.h index 665807a7..205e38a6 100644 --- a/lib-hal/include/gd32/hal_uart.h +++ b/lib-hal/include/gd32/hal_uart.h @@ -2,7 +2,7 @@ * @file hal_uart.h * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-hal/include/gd32/hardware.h b/lib-hal/include/gd32/hardware.h index bda7f289..98254b61 100644 --- a/lib-hal/include/gd32/hardware.h +++ b/lib-hal/include/gd32/hardware.h @@ -2,7 +2,7 @@ * @file hardware.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,6 +27,7 @@ #define GD32_HARDWARE_H_ #include +#include #include #include @@ -34,12 +35,19 @@ #include "gd32.h" #include "gd32_adc.h" -#include "gd32_micros.h" + +#if !defined (CONFIG_LEDBLINK_USE_PANELLED) && (defined (GD32F4XX) || defined(GD32H7XX)) +# define HAL_HAVE_PORT_BIT_TOGGLE +#endif #if defined (ENABLE_USB_HOST) && defined (CONFIG_USB_HOST_MSC) extern "C" { #include "usbh_core.h" -extern usbh_host usb_host_msc; +#if defined (GD32H7XX) || defined (GD32F4XX) + extern usbh_host usb_host_msc; +#else + extern usbh_host usb_host; +#endif } #endif @@ -50,12 +58,13 @@ extern usbh_host usb_host_msc; void emac_debug_run(); #endif -#if defined (USE_LEDBLINK_BITBANGING595) -# include "gd32_bitbanging595.h" -# include "panel_led.h" +#ifdef NDEBUG + extern "C" void console_error(const char *); #endif -extern volatile uint32_t s_nSysTickMillis; +#include "panel_led.h" + +#include "debug.h" class Hardware { public: @@ -65,40 +74,77 @@ class Hardware { return 0; // FIXME GetReleaseId } - void GetUuid(uuid_t out); + void GetUuid(uuid_t out) { + memcpy(out, m_uuid, sizeof(uuid_t)); + } uint32_t Millis() { - extern volatile uint32_t s_nSysTickMillis; - return s_nSysTickMillis; +#if defined (CONFIG_HAL_USE_SYSTICK) + extern volatile uint32_t gv_nSysTickMillis; + return gv_nSysTickMillis; +#else + extern uint32_t timer6_get_elapsed_milliseconds(); + return timer6_get_elapsed_milliseconds(); +#endif } uint32_t Micros() { - return micros(); + static uint32_t nMicrosPrevious; + static uint32_t nResult; + const auto nMicros = DWT->CYCCNT / (MCU_CLOCK_FREQ / 1000000U); + + if (nMicros > nMicrosPrevious) { + nResult += (nMicros - nMicrosPrevious); + } else { + nResult += ((UINT32_MAX / (MCU_CLOCK_FREQ / 1000000U)) - nMicrosPrevious + nMicros); + } + + nMicrosPrevious = nMicros; + + return nResult; } - uint32_t GetUpTime() { - return Millis() / 1000U; + uint32_t GetUpTime() const { + extern struct HwTimersSeconds g_Seconds; + return g_Seconds.nUptime; } - bool SetTime(const struct tm *pTime); - void GetTime(struct tm *pTime); + bool SetTime(__attribute__((unused)) const struct tm *pTime) { +#if !defined(DISABLE_RTC) + m_HwClock.Set(pTime); + return true; +#else + return false; +#endif + } - const char *GetBoardName(uint8_t &nLength) { +#if !defined(DISABLE_RTC) + bool SetAlarm(const struct tm *pTime) { + const auto b = m_HwClock.AlarmSet(pTime); + return b; + } + + void GetAlarm(struct tm *pTime) { + m_HwClock.AlarmGet(pTime); + } +#endif + + const char *GetBoardName(uint8_t& nLength) { nLength = sizeof(GD32_BOARD_NAME) - 1U; return GD32_BOARD_NAME; } - const char *GetSysName(uint8_t &nLength) { + const char* GetSysName(uint8_t& nLength) { nLength = 8; return "Embedded"; } - const char *GetSocName(uint8_t &nLength) { - nLength = 5; - return "GD32F"; + const char* GetSocName(uint8_t& nLength) { + nLength = 4; + return "GD32"; } - const char *GetCpuName(uint8_t &nLength) { + const char *GetCpuName(uint8_t& nLength) { nLength = sizeof(GD32_MCU_NAME) - 1U; return GD32_MCU_NAME; } @@ -112,8 +158,8 @@ class Hardware { } void WatchdogInit() { - const auto status = fwdgt_config(0xFFFF, FWDGT_PSC_DIV16); - m_bIsWatchdog = (SUCCESS == status); + m_bIsWatchdog = (SUCCESS == fwdgt_config(0xFFFF, FWDGT_PSC_DIV16)); + if (m_bIsWatchdog) { fwdgt_enable(); } @@ -138,11 +184,11 @@ class Hardware { return gd32_adc_gettemp(); } - float GetCoreTemperatureMin() { + float GetCoreTemperatureMin() const { return -40.0f; } - float GetCoreTemperatureMax() { + float GetCoreTemperatureMax() const { return 85.0f; } @@ -152,35 +198,85 @@ class Hardware { return m_Mode; } - void Run() { -#if defined (ENABLE_USB_HOST) && defined (CONFIG_USB_HOST_MSC) - usbh_core_task(&usb_host_msc); + struct Timer { + uint32_t nExpireTime; + uint32_t nIntervalMillis; + int32_t nId; + hal::TimerCallback callback; + }; + + int32_t SoftwareTimerAdd(const uint32_t nIntervalMillis, const hal::TimerCallback callback) { + if (m_nTimersCount >= hal::SOFTWARE_TIMERS_MAX) { +#ifdef NDEBUG + console_error("SoftwareTimerAdd\n"); #endif - if (__builtin_expect (m_nTicksPerSecond != 0, 1)) { - if (__builtin_expect (!(s_nSysTickMillis - m_nMillisPrevious < m_nTicksPerSecond), 1)) { - m_nMillisPrevious = s_nSysTickMillis; + return -1; + } - m_nToggleLed ^= 0x1; + const auto nCurrentTime = Hardware::Millis(); - if (m_nToggleLed != 0) { -#if defined (USE_LEDBLINK_BITBANGING595) - hal::panel_led_on(hal::panelled::ACTIVITY); -#else - GPIO_BOP(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; -#endif - } else { -#if defined (USE_LEDBLINK_BITBANGING595) - hal::panel_led_off(hal::panelled::ACTIVITY); -#else - GPIO_BC(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; -#endif + Timer newTimer = { + .nExpireTime = nCurrentTime + nIntervalMillis, + .nIntervalMillis = nIntervalMillis, + .nId = m_nNextId++, + .callback = callback, + }; + + m_Timers[m_nTimersCount++] = newTimer; + + return newTimer.nId; + } + + bool SoftwareTimerDelete(int32_t& nId) { + if (nId >= 0) { + for (uint32_t i = 0; i < m_nTimersCount; ++i) { + if (m_Timers[i].nId == nId) { + for (uint32_t j = i; j < m_nTimersCount - 1; ++j) { + m_Timers[j] = m_Timers[j + 1]; + } + --m_nTimersCount; + nId = -1; + return true; } } } -#if defined (USE_LEDBLINK_BITBANGING595) - bitBanging595.Run(); + return false; + } + + bool SoftwareTimerChange(const int32_t nId, const uint32_t nIntervalMillis) { + if (nId >= 0) { + for (uint32_t i = 0; i < m_nTimersCount; ++i) { + if (m_Timers[i].nId == nId) { + m_Timers[i].nExpireTime = Hardware::Millis() + nIntervalMillis; + m_Timers[i].nIntervalMillis = nIntervalMillis; + + return true; + } + } + } + + return false; + } + + void Run() { +#if defined (ENABLE_USB_HOST) && defined (CONFIG_USB_HOST_MSC) +# if defined (GD32H7XX) || defined (GD32F4XX) + usbh_core_task(&usb_host_msc); +# else + usbh_core_task(&usb_host); +# endif #endif + const auto nCurrentTime = Hardware::Get()->Millis(); + + for (uint32_t i = 0; i < m_nTimersCount; i++) { + if (m_Timers[i].nExpireTime <= nCurrentTime) { + m_Timers[i].callback(); + m_Timers[i].nExpireTime = nCurrentTime + m_Timers[i].nIntervalMillis; + } + } + + hal::panel_led_run(); #if defined (DEBUG_STACK) stack_debug_run(); @@ -198,54 +294,94 @@ class Hardware { private: void RebootHandler(); + static void ledblink() { +#if defined(HAL_HAVE_PORT_BIT_TOGGLE) + GPIO_TG(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; +#else + m_nToggleLed = -m_nToggleLed; + + if (m_nToggleLed > 0) { +# if defined (CONFIG_LEDBLINK_USE_PANELLED) + hal::panel_led_on(hal::panelled::ACTIVITY); +# else + GPIO_BOP(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; +# endif + } else { +# if defined (CONFIG_LEDBLINK_USE_PANELLED) + hal::panel_led_off(hal::panelled::ACTIVITY); +# else + GPIO_BC(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; +# endif + } +#endif + } + void SetFrequency(const uint32_t nFreqHz) { + DEBUG_ENTRY + DEBUG_PRINTF("m_nTimerId=%d, nFreqHz=%u", m_nTimerId, nFreqHz); + + if (m_nTimerId < 0) { + m_nTimerId = SoftwareTimerAdd((1000U / nFreqHz), ledblink); + DEBUG_EXIT + return; + } + switch (nFreqHz) { case 0: - m_nTicksPerSecond = 0; -#if defined (USE_LEDBLINK_BITBANGING595) + SoftwareTimerDelete(m_nTimerId); +#if defined (CONFIG_LEDBLINK_USE_PANELLED) hal::panel_led_off(hal::panelled::ACTIVITY); #else GPIO_BC(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; #endif break; +# if !defined (CONFIG_HAL_USE_MINIMUM) case 1: - m_nTicksPerSecond = (1000 / 1); + SoftwareTimerChange(m_nTimerId, (1000U / 1)); break; case 3: - m_nTicksPerSecond = (1000 / 3); + SoftwareTimerChange(m_nTimerId, (1000U / 3)); break; case 5: - m_nTicksPerSecond = (1000 / 5); + SoftwareTimerChange(m_nTimerId, (1000U / 5)); break; + case 8: + SoftwareTimerChange(m_nTimerId, (1000U / 8)); + break; +# endif case 255: - m_nTicksPerSecond = 0; -#if defined (USE_LEDBLINK_BITBANGING595) + SoftwareTimerDelete(m_nTimerId); +#if defined (CONFIG_LEDBLINK_USE_PANELLED) hal::panel_led_on(hal::panelled::ACTIVITY); #else GPIO_BOP(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; #endif break; default: - m_nTicksPerSecond = (1000 / nFreqHz); + SoftwareTimerChange(m_nTimerId, (1000U / nFreqHz)); break; } + + DEBUG_EXIT } private: #if !defined(DISABLE_RTC) HwClock m_HwClock; #endif + uuid_t m_uuid; bool m_bIsWatchdog { false }; - -#if defined (USE_LEDBLINK_BITBANGING595) - BitBanging595 bitBanging595; -#endif hardware::ledblink::Mode m_Mode { hardware::ledblink::Mode::UNKNOWN }; bool m_doLock { false }; - uint32_t m_nTicksPerSecond { 1000 / 2 }; - int32_t m_nToggleLed { 0 }; - uint32_t m_nMillisPrevious { 0 }; + int32_t m_nTimerId { -1 }; + Timer m_Timers[hal::SOFTWARE_TIMERS_MAX]; + uint32_t m_nTimersCount { 0 }; + int32_t m_nNextId { 0 }; + +#if !defined(HAL_HAVE_PORT_BIT_TOGGLE) + static inline int32_t m_nToggleLed { 1 }; +#endif static Hardware *s_pThis; }; diff --git a/lib-hal/include/gd32/panel_led.h b/lib-hal/include/gd32/panel_led.h index 8b6f3236..fbda082b 100644 --- a/lib-hal/include/gd32/panel_led.h +++ b/lib-hal/include/gd32/panel_led.h @@ -30,7 +30,7 @@ #include "gd32.h" -#if !defined (LEDPANEL_595_COUNT) +#if !defined (PANELLED_595_COUNT) # if !defined (UNUSED) # define UNUSED __attribute__((unused)) # endif @@ -45,11 +45,11 @@ namespace panelled { extern uint32_t g_nData; } // namespace panelled -inline static void panel_led_spi(const UNUSED uint32_t nData) { -#if defined(LEDPANEL_595_COUNT) - GPIO_BC(LEDPANEL_595_CS_GPIOx) = LEDPANEL_595_CS_GPIO_PINx; +inline void panel_led_spi(const UNUSED uint32_t nData) { +#if defined(PANELLED_595_COUNT) + GPIO_BC(PANELLED_595_CS_GPIOx) = PANELLED_595_CS_GPIO_PINx; -#if (LEDPANEL_595_COUNT >= 1) +#if (PANELLED_595_COUNT >= 1) while (RESET == (SPI_STAT(SPI_PERIPH) & SPI_FLAG_TBE)) ; @@ -60,7 +60,7 @@ inline static void panel_led_spi(const UNUSED uint32_t nData) { static_cast(SPI_DATA(SPI_PERIPH)); #endif -#if (LEDPANEL_595_COUNT >= 2) +#if (PANELLED_595_COUNT >= 2) while (RESET == (SPI_STAT(SPI_PERIPH) & SPI_FLAG_TBE)) ; @@ -71,7 +71,7 @@ inline static void panel_led_spi(const UNUSED uint32_t nData) { static_cast(SPI_DATA(SPI_PERIPH)); #endif -#if (LEDPANEL_595_COUNT >= 3) +#if (PANELLED_595_COUNT >= 3) while (RESET == (SPI_STAT(SPI_PERIPH) & SPI_FLAG_TBE)) ; @@ -82,7 +82,7 @@ inline static void panel_led_spi(const UNUSED uint32_t nData) { static_cast(SPI_DATA(SPI_PERIPH)); #endif -#if (LEDPANEL_595_COUNT == 4) +#if (PANELLED_595_COUNT == 4) while (RESET == (SPI_STAT(SPI_PERIPH) & SPI_FLAG_TBE)) ; @@ -94,12 +94,18 @@ inline static void panel_led_spi(const UNUSED uint32_t nData) { static_cast(SPI_DATA(SPI_PERIPH)); #endif - GPIO_BOP(LEDPANEL_595_CS_GPIOx) = LEDPANEL_595_CS_GPIO_PINx; + GPIO_BOP(PANELLED_595_CS_GPIOx) = PANELLED_595_CS_GPIO_PINx; #endif } -inline static void panel_led_on(uint32_t UNUSED on) { -#if defined(LEDPANEL_595_COUNT) +inline void panel_led_init() { +#if defined(PANELLED_595_COUNT) + +#endif +} + +inline void panel_led_on(uint32_t UNUSED on) { +#if defined(PANELLED_595_COUNT) if (panelled::g_nData == (panelled::g_nData | on)) { return; } @@ -110,8 +116,8 @@ inline static void panel_led_on(uint32_t UNUSED on) { #endif } -inline static void panel_led_off(uint32_t UNUSED off) { -#if defined(LEDPANEL_595_COUNT) +inline void panel_led_off(uint32_t UNUSED off) { +#if defined(PANELLED_595_COUNT) if (panelled::g_nData == (panelled::g_nData & ~off)) { return; } @@ -121,6 +127,13 @@ inline static void panel_led_off(uint32_t UNUSED off) { panel_led_spi(panelled::g_nData); #endif } + +inline void panel_led_run() { +#if defined(PANELLED_595_COUNT) + +#endif +} + } // namespace hal #endif /* GD32_PANEL_LED_H_ */ diff --git a/gd32_emac_ddp_pixel_multi/include/display_timeout.h b/lib-hal/include/hal_api.h old mode 100644 new mode 100755 similarity index 69% rename from gd32_emac_ddp_pixel_multi/include/display_timeout.h rename to lib-hal/include/hal_api.h index a8556629..71d7f29a --- a/gd32_emac_ddp_pixel_multi/include/display_timeout.h +++ b/lib-hal/include/hal_api.h @@ -1,8 +1,8 @@ /** - * @file display_timeout.h + * @file hal_api.h * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,23 +23,25 @@ * THE SOFTWARE. */ -#ifndef DISPLAY_TIMEOUT_H_ -#define DISPLAY_TIMEOUT_H_ - -#include "gd32.h" - -namespace display { -namespace timeout { - -void gpio_init() { - gpio_fsel(KEY2_GPIOx, KEY2_PINx, GPIO_FSEL_INPUT); -} - -bool gpio_renew() { - return (GPIO_ISTAT(KEY2_GPIOx) & KEY2_PINx) == 0; -} - -} // namespace timeout -} // namespace display - -#endif /* DISPLAY_TIMEOUT_H_ */ +#ifndef HAL_API_H_ +#define HAL_API_H_ + +#if defined(__linux__) || defined (__APPLE__) +# include "linux/hal_api.h" +#elif defined(H3) +# include "h3/hal_api.h" +#elif defined(GD32) +# include "gd32/hal_api.h" +#else +# include "rpi/hal_api.h" +#endif + +#ifdef __cplusplus +# if !defined(UDELAY) +# define UDELAY +# include + void udelay(uint32_t us, uint32_t offset = 0); +# endif +#endif + +#endif /* HAL_API_H_ */ diff --git a/lib-hal/include/hal_gpio.h b/lib-hal/include/hal_gpio.h index da3fdb20..8066e944 100644 --- a/lib-hal/include/hal_gpio.h +++ b/lib-hal/include/hal_gpio.h @@ -2,7 +2,7 @@ * @file hal_gpio.h * */ -/* Copyright (C) 2020-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-hal/include/hal_i2c.h b/lib-hal/include/hal_i2c.h index f3664083..150c7bdd 100644 --- a/lib-hal/include/hal_i2c.h +++ b/lib-hal/include/hal_i2c.h @@ -26,6 +26,8 @@ #ifndef HAL_I2C_H_ #define HAL_I2C_H_ +#include "hal_api.h" + #if defined(__linux__) || defined (__APPLE__) # include "linux/hal_api.h" # include "linux/hal_i2c.h" diff --git a/lib-hal/include/hal_spi.h b/lib-hal/include/hal_spi.h index ef7e22c1..ded9f3f7 100644 --- a/lib-hal/include/hal_spi.h +++ b/lib-hal/include/hal_spi.h @@ -26,6 +26,8 @@ #ifndef HAL_SPI_H_ #define HAL_SPI_H_ +#include "hal_api.h" + #if defined(__linux__) || defined (__APPLE__) # include "linux/hal_api.h" # include "linux/hal_spi.h" @@ -40,7 +42,8 @@ # include "rpi/hal_spi.h" #endif -#include +#ifdef __cplusplus +# include class HAL_SPI { void Setup() { @@ -80,5 +83,6 @@ class HAL_SPI { uint8_t m_nChipSelect; uint8_t m_nMode; }; +#endif #endif /* HAL_SPI_H_ */ diff --git a/lib-hal/include/hardware.h b/lib-hal/include/hardware.h index 6d8f9e07..e7a2d94d 100644 --- a/lib-hal/include/hardware.h +++ b/lib-hal/include/hardware.h @@ -2,7 +2,7 @@ * @file hardware.h * */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,6 +27,8 @@ #define HARDWARE_H_ #include +#include +#include namespace hardware { enum class BootDevice { @@ -42,12 +44,26 @@ namespace ledblink { enum class Mode { OFF_OFF, OFF_ON, NORMAL, DATA, FAST, REBOOT, UNKNOWN }; - -void display(const uint32_t nState); } // namespace ledblink } // namespace hardware -#if defined (BARE_METAL) +namespace hal { +#if !defined (CONFIG_HAL_TIMERS_COUNT) +# define CONFIG_HAL_TIMERS_COUNT 8 +#endif + +static constexpr uint32_t SOFTWARE_TIMERS_MAX = CONFIG_HAL_TIMERS_COUNT; + +typedef void (*TimerCallback)(); +} // namespace hal + +#if defined(__linux__) || defined (__APPLE__) +# if defined (CONFIG_HAL_USE_MINIMUM) +# include "linux/minimum/hardware.h" +# else +# include "linux/hardware.h" +# endif +#else # if defined (H3) # include "h3/hardware.h" # elif defined (GD32) @@ -55,8 +71,6 @@ void display(const uint32_t nState); # else # include "rpi/hardware.h" # endif -#else -# include "linux/hardware.h" #endif #endif /* HARDWARE_H_ */ diff --git a/lib-hal/include/hwclock.h b/lib-hal/include/hwclock.h index 579949eb..331d293a 100644 --- a/lib-hal/include/hwclock.h +++ b/lib-hal/include/hwclock.h @@ -3,7 +3,7 @@ * @file hwclock.h * */ -/* Copyright (C) 2020-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,6 +28,7 @@ #define HWCLOCK_H_ #include +#include #include namespace rtc { @@ -36,18 +37,6 @@ enum class Type : uint8_t { }; } // namespace rtc -struct rtc_time { - int tm_sec; - int tm_min; - int tm_hour; - int tm_mday; - int tm_mon; - int tm_year; - int tm_wday; /* unused */ - int tm_yday; /* unused */ - int tm_isdst; /* unused */ -}; - class HwClock { public: HwClock(); @@ -56,16 +45,34 @@ class HwClock { void HcToSys(); // Set the System Clock from the Hardware Clock void SysToHc(); // Set the Hardware Clock from the System Clock - bool Set(const struct rtc_time *pRtcTime); - bool Get(struct rtc_time *pRtcTime) { - return RtcGet(pRtcTime); + bool Set(const struct tm *pTime); + bool Get(struct tm *pTime) { + return RtcGet(pTime); + } + + bool AlarmSet(const struct tm *pTime) { + return RtcSetAlarm(pTime); + } + bool AlarmGet(struct tm *pTime) { + return RtcGetAlarm(pTime); + } + void AlarmEnable(const bool bEnable) { + m_bRtcAlarmEnabled = bEnable; + } + bool AlarmIsEnabled() const { + return m_bRtcAlarmEnabled; } bool IsConnected() const { return m_bIsConnected; } - void Run(bool bDoRun); + void Run(const bool bDoRun) { + if (!bDoRun || !m_bIsConnected) { + return; + } + Process(); + } void Print(); @@ -74,8 +81,14 @@ class HwClock { } private: - bool RtcSet(const struct rtc_time *pRtcTime); - bool RtcGet(struct rtc_time *pRtcTime); + void Process(); + bool RtcSet(const struct tm *pime); + bool RtcGet(struct tm *pTime); + bool RtcSetAlarm(const struct tm *pTime); + bool RtcGetAlarm(struct tm *pTime); + int MCP794xxAlarmWeekday(struct tm *pTime); + void PCF8563GetAlarmMode(); + void PCF8563SetAlarmMode(); private: uint32_t m_nSetDelayMicros { 0 }; @@ -83,6 +96,8 @@ class HwClock { uint8_t m_nAddress { 0 }; rtc::Type m_Type { rtc::Type::UNKNOWN }; bool m_bIsConnected { false }; + bool m_bRtcAlarmEnabled { false }; + bool m_bRtcAlarmPending { false }; static HwClock *s_pThis; }; diff --git a/lib-hal/include/panel_led.h b/lib-hal/include/panel_led.h index 1ff5843d..89563f88 100644 --- a/lib-hal/include/panel_led.h +++ b/lib-hal/include/panel_led.h @@ -2,7 +2,7 @@ * @file panel_led.h * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -56,7 +56,9 @@ * } // namespace hal */ -#if defined (BARE_METAL) +#if defined(__linux__) || defined (__APPLE__) +# include "linux/panel_led.h" +#else # if defined (H3) # include "h3/panel_led.h" # elif defined (GD32) @@ -64,8 +66,6 @@ # else # include "rpi/panel_led.h" # endif -#else -# include "linux/panel_led.h" #endif #endif /* PANEL_LED_H_ */ diff --git a/lib-hal/include/uart0_debug.h b/lib-hal/include/uart0_debug.h index 81469d3d..58f17412 100644 --- a/lib-hal/include/uart0_debug.h +++ b/lib-hal/include/uart0_debug.h @@ -2,7 +2,7 @@ * @file uart0_debug.h * */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-hal/include/utc.h b/lib-hal/include/utc.h index 3fda86b7..a2c714a3 100644 --- a/lib-hal/include/utc.h +++ b/lib-hal/include/utc.h @@ -2,7 +2,7 @@ * @file utc.h * */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,14 +26,70 @@ #include -enum TUtcOffset { +#include "debug.h" + +// https://en.wikipedia.org/wiki/List_of_UTC_time_offsets + +namespace hal { +enum class UtcOffset { UTC_OFFSET_MIN = -12, UTC_OFFSET_MAX = 14 }; -class Utc { -public: - static int32_t Validate(float fOffset); -}; +inline int32_t utc_validate(const float fOffset) { + static constexpr float s_ValidOffets[] = { -9.5, -3.5, 3.5, 4.5, 5.5, 5.75, 6.5, 8.75, 9.5, 10.5, 12.75 }; + auto nInt = static_cast(fOffset); + + if ((nInt >= -12) && (nInt <= 14)) { + if (fOffset == static_cast(nInt)) { + return (nInt * 3600); + } else { + for (uint32_t i = 0; i < sizeof(s_ValidOffets) / sizeof(s_ValidOffets[0]); i++) { + if (fOffset == s_ValidOffets[i]) { + return static_cast(fOffset * 3600.0f); + } + } + } + } + + return 0; +} + +inline bool utc_validate(const int8_t nHours, const uint8_t nMinutes, int32_t& nUtcOffset) { + struct Offset { + int8_t nHours; + uint8_t nMinutes; + }; + // https://en.wikipedia.org/wiki/List_of_UTC_time_offsets + static constexpr Offset s_ValidOffsets[] = { {-9, 30}, {-3, 30}, + {3, 30}, {4, 30}, {5, 30}, {5, 45}, {6, 30}, {8, 45}, {9, 30}, {10, 30}, {12, 45} }; + constexpr int8_t UTC_OFFSET_MIN = -12; + constexpr int8_t UTC_OFFSET_MAX = 14; + + // Check if nHours is within valid range + if (nHours >= UTC_OFFSET_MIN && nHours <= UTC_OFFSET_MAX) { + // Check if minutes are 0, meaning a whole hour offset + if (nMinutes == 0) { + nUtcOffset = nHours * 3600; + return true; + } else { + for (const auto& offset : s_ValidOffsets) { + if (nHours == offset.nHours && nMinutes == offset.nMinutes) { + nUtcOffset = (nHours * 3600); + if (nHours > 0) { + nUtcOffset = nUtcOffset + (nMinutes * 60); + } else { + nUtcOffset = nUtcOffset - (nMinutes * 60); + } + return true; + } + } + } + } + + // Return false if validation fails + return false; +} +} // namespace hal #endif /* UTC_H_ */ diff --git a/lib-hal/posix/file.cpp b/lib-hal/posix/file.cpp new file mode 100644 index 00000000..26a5438a --- /dev/null +++ b/lib-hal/posix/file.cpp @@ -0,0 +1,486 @@ +/** + * @file file.c + * + */ +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if defined (DEBUG_POSIX) +# if defined (NDEBUG) +# undef NDEBUG +# endif +#endif + +#include +#include +#include +#include +#include + +#include "../ff14b/source/ff.h" +#include /* DO NOT MOVE -> DIR is defined in ff.h */ + +#include "debug.h" + +#if !defined (CONFIG_POSIX_OPEN_FILES_MAX) || (CONFIG_POSIX_OPEN_FILES_MAX < 1) +# define CONFIG_POSIX_OPEN_FILES_MAX 2 +#endif + +namespace posix { +static constexpr int OPEN_FILES_MAX = CONFIG_POSIX_OPEN_FILES_MAX; +} // namespace posix + +#if defined(CONFIG_POSIX_ENABLE_STDIN) +static FILE s_file[3 + posix::OPEN_FILES_MAX]; +FILE *stdin = &s_file[0]; +FILE *stdout = &s_file[1]; +FILE *stderr = &s_file[2]; +#else +static FILE s_file[posix::OPEN_FILES_MAX]; +#endif +static FIL s_ff_file[posix::OPEN_FILES_MAX]; + +static FRESULT s_fresult; + +static int get_file_descriptor() { + for (int nFile = 0; nFile < posix::OPEN_FILES_MAX; nFile++) { +#if defined(CONFIG_POSIX_ENABLE_STDIN) + if (isatty(nFile)) { + continue; + } +#endif + if (s_file[nFile].udata == nullptr) { +#if defined(CONFIG_POSIX_ENABLE_STDIN) + s_file[nFile].udata = &s_ff_file[nFile - 3]; +#else + s_file[nFile].udata = &s_ff_file[nFile]; +#endif + return nFile; + } + } + + errno = ENFILE; + return -1; +} + +static int fatfs_to_errno(const BYTE err) { + switch (static_cast(err)) { + case FR_OK: /* FatFS (0) Succeeded */ + return (0); /* POSIX OK */ + case FR_DISK_ERR: /* FatFS (1) A hard error occurred in the low level disk I/O layer */ + return (EIO); /* POSIX Input/output error (POSIX.1) */ + case FR_INT_ERR: /* FatFS (2) Assertion failed */ + return (EPERM); /* POSIX Operation not permitted (POSIX.1) */ + case FR_NOT_READY: /* FatFS (3) The physical drive cannot work */ + return (EBUSY); /* POSIX Device or resource busy (POSIX.1) */ + case FR_NO_FILE: /* FatFS (4) Could not find the file */ + return (ENOENT); /* POSIX No such file or directory (POSIX.1) */ + case FR_NO_PATH: /* FatFS (5) Could not find the path */ + return (ENOENT); /* POSIX No such file or directory (POSIX.1) */ + case FR_INVALID_NAME: /* FatFS (6) The path name format is invalid */ + return (EINVAL); /* POSIX Invalid argument (POSIX.1) */ + case FR_DENIED: /* FatFS (7) Access denied due to prohibited access or directory full */ + return (EACCES); /* POSIX Permission denied (POSIX.1) */ + case FR_EXIST: /* FatFS (8) Access denied due to prohibited access */ + return (EACCES); /* POSIX Permission denied (POSIX.1) */ + case FR_INVALID_OBJECT: /* FatFS (9) The file/directory object is invalid */ + return (EINVAL); /* POSIX Invalid argument (POSIX.1) */ + case FR_WRITE_PROTECTED: /* FatFS (10) The physical drive is write protected */ + return (EROFS); /* POSIX Read-only filesystem (POSIX.1) */ + case FR_INVALID_DRIVE: /* FatFS (11) The logical drive number is invalid */ + return (ENXIO); /* POSIX No such device or address (POSIX.1) */ + case FR_NOT_ENABLED: /* FatFS (12) The volume has no work area */ + return (ENOSPC); /* POSIX No space left on device (POSIX.1) */ + case FR_NO_FILESYSTEM: /* FatFS (13) There is no valid FAT volume */ + return (ENXIO); /* POSIX No such device or address (POSIX.1) */ + case FR_MKFS_ABORTED: /* FatFS (14) The f_mkfs() aborted due to any parameter error */ + return (EINVAL); /* POSIX Invalid argument (POSIX.1) */ + case FR_TIMEOUT: /* FatFS (15) Could not get a grant to access the volume within defined period */ + return (EBUSY); /* POSIX Device or resource busy (POSIX.1) */ + case FR_LOCKED: /* FatFS (16) The operation is rejected according to the file sharing policy */ + return (EBUSY); /* POSIX Device or resource busy (POSIX.1) */ + case FR_NOT_ENOUGH_CORE: /* FatFS (17) LFN working buffer could not be allocated */ + return (ENOMEM); /* POSIX Not enough space (POSIX.1) */ + case FR_TOO_MANY_OPEN_FILES:/* FatFS (18) Number of open files > _FS_SHARE */ + return (EMFILE); /* POSIX Too many open files (POSIX.1) */ + case FR_INVALID_PARAMETER:/* FatFS (19) Given parameter is invalid */ + return (EINVAL); /* POSIX Invalid argument (POSIX.1) */ + } + + return (EBADMSG); /* POSIX Bad message (POSIX.1) */ +} + +extern "C" { +int fileno(FILE *stream) { + if (stream == nullptr) { + errno = EBADF; + return -1; + } + + for (int nFile = 0; nFile < posix::OPEN_FILES_MAX; nFile++) { + if (&s_file[nFile] == stream) { + return nFile; + } + } + + return EOF; +} + +// http://elm-chan.org/fsw/ff/doc/open.html +FILE *fopen(const char *path, const char *mode) { + assert(path != nullptr); + assert(mode != nullptr); + + DEBUG_PRINTF("%s %s", path, mode); + + errno = 0; + BYTE fm, fo; + + switch (mode[0]) { + case 'r': + fm = (BYTE) FA_READ; + fo = 0; + break; + case 'w': + fm = (BYTE) FA_WRITE; + fo = (BYTE) FA_CREATE_ALWAYS; + break; + case 'a': + fm = (BYTE) FA_WRITE; + fo = (BYTE) FA_OPEN_APPEND; + break; + default: + return nullptr; + break; + } + + while (*++mode != '\0') { + switch (*mode) { + case '+': + fm = (BYTE) (FA_READ | FA_WRITE); + break; + case 'x': + fo = (BYTE) FA_CREATE_NEW; + break; + default: + return nullptr; + break; + } + } + + const auto fd = get_file_descriptor(); + DEBUG_PRINTF("fd=%d", fd); + + if (fd < 0) { + errno = EBADF; + return nullptr; + } + + s_fresult = f_open(&s_ff_file[fd], (TCHAR *) path, (BYTE) (fm | fo)); + errno = fatfs_to_errno(s_fresult); + + DEBUG_PRINTF("errno=%d", errno); + + if (s_fresult == FR_OK) { + return &s_file[fd]; + } else { + s_file[fd].udata = nullptr; + return nullptr; + } +} + +int fclose(FILE *stream) { + errno = 0; + + if (stream == nullptr) { + return 0; + } + + const auto fd = fileno(stream); + DEBUG_PRINTF("fd=%d", fd); + + if (fd < 0) { + errno = EBADF; + return EOF; + } + + s_fresult = f_close((FIL *)stream->udata); + errno = fatfs_to_errno(s_fresult); + + DEBUG_PRINTF("errno=%d", errno); + + stream->udata = nullptr; + + if (s_fresult == FR_OK) { + return 0; + } + + return EOF; +} + +int fgetc(FILE *stream) { + char c; + UINT bytes_read; + errno = 0; + + if (stream == nullptr) { + return EOF; + } + + if ((s_fresult = f_read((FIL *)stream->udata, &c, (UINT) 1, &bytes_read)) == FR_OK) { + if (bytes_read > 0) { + return c; + } + + if (bytes_read < 1) { + errno = fatfs_to_errno(s_fresult); + stream->flags |= __SEOF; + return EOF; + } + } + + errno = fatfs_to_errno(s_fresult); + return EOF; +} + +size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) { + UINT bytes_read; + + s_fresult = f_read((FIL *)stream->udata, ptr, (size * nmemb), &bytes_read); + errno = fatfs_to_errno(s_fresult); + + if (s_fresult == FR_OK) { + return bytes_read; + } + + return 0; +} + +int fseek(FILE *stream, long offset, int whence) { + if (whence == SEEK_SET) { + s_fresult = f_lseek((FIL *)stream->udata, (FSIZE_t) offset); + } else if (whence == SEEK_END) { + s_fresult = f_lseek((FIL *)stream->udata, f_size((FIL *)stream->udata)); + } + + errno = fatfs_to_errno(s_fresult); + + if (s_fresult == FR_OK) { + return 0; + } + + return -1; +} + +long ftell(FILE *stream) { + return (long) f_tell((FIL *)stream->udata); +} + +char *fgets(char *s, int size, FILE *stream) { + assert(s != nullptr); + errno = 0; + + if (stream == nullptr) { + *s = '\0'; + return nullptr; + } + + if (f_gets(s, size, (FIL *)stream->udata) != s) { + *s = '\0'; + errno = fatfs_to_errno(f_error((FIL *)stream->udata)); + return nullptr; + } + + return s; +} + +void clearerr(FILE *stream) { + stream->flags &= static_cast(~__SEOF); + stream->flags &= static_cast(~__SERR); +} + +int ferror(FILE *stream) { + return (stream->flags & __SERR) ? 1 : 0; +} + +int feof(FILE *stream) { + return (stream->flags & __SEOF) ? 1 : 0; +} + +/* + * The following API´s are implemented when CONFIG_FS_ENABLE_WRITE is defined + */ + +int fputs([[maybe_unused]] const char *s, [[maybe_unused]] FILE *stream) { +#if !defined (CONFIG_FS_ENABLE_WRITE) + errno = ENOSYS; + return -1; +#else + assert(s != nullptr); + assert(stream != nullptr); + errno = 0; + + return f_puts(s, (FIL *)stream->udata); +#endif +} + +size_t fwrite([[maybe_unused]] const void *ptr, [[maybe_unused]] size_t size, [[maybe_unused]] size_t nmemb, [[maybe_unused]] FILE *stream) { +#if !defined (CONFIG_FS_ENABLE_WRITE) + errno = ENOSYS; + return 0; +#else + assert(stream != nullptr); + UINT bytes_write; + + s_fresult = f_write((FIL *)stream->udata, ptr, (size * nmemb), &bytes_write); + errno = fatfs_to_errno(s_fresult); + + if (s_fresult == FR_OK) { + return bytes_write; + } + + return 0; +#endif +} + +int fputc([[maybe_unused]] int c, [[maybe_unused]] FILE *stream) { +#if !defined (CONFIG_FS_ENABLE_WRITE) + errno = ENOSYS; + return 0; +#else + assert(stream != nullptr); + + UINT bytes_write; + + s_fresult = f_write((FIL *)stream->udata, &c, 1, &bytes_write); + errno = fatfs_to_errno(s_fresult); + + if (s_fresult == FR_OK) { + return 1; + } + + return 0; +#endif +} + +int unlink([[maybe_unused]] const char *pathname) { +#if !defined (CONFIG_FS_ENABLE_WRITE) + errno = ENOSYS; + return -1; +#else + s_fresult = f_unlink(pathname); + errno = fatfs_to_errno(s_fresult); + + if (s_fresult == FR_OK) { + return 0; + } + + return -1; +#endif +} + +#if !defined (CONFIG_FS_ENABLE_WRITE) +#else +static DIR s_dir; +static dirent_t s_dirent; +#endif + +DIR *opendir([[maybe_unused]] const char *dirname) { +#if !defined (CONFIG_FS_ENABLE_WRITE) + errno = ENOSYS; + return nullptr; +#else + const auto len = strlen(dirname); + + if ((len > 0) && (dirname[len - 1] == '.')) { + char *pathdir = (char *) dirname; + pathdir[len - 1] = '\0'; + s_fresult = f_opendir(&s_dir, pathdir); + } else { + s_fresult = f_opendir(&s_dir, dirname); + } + + errno = fatfs_to_errno(s_fresult); + + if (s_fresult != FR_OK) { + return nullptr; + } + + return &s_dir; +#endif +} + +/** + * On success, readdir() returns a pointer to a dirent structure. + * If the end of the directory stream is reached, nullptr is returned and errno is not changed. + * If an error occurs, nullptr is returned and errno is set appropriately. + */ + +struct dirent *readdir([[maybe_unused]] DIR *dirp) { +#if !defined (CONFIG_FS_ENABLE_WRITE) + errno = ENOSYS; + return nullptr; +#else + FILINFO fno; + + fno.fname[0] = '\0'; + + s_fresult = f_readdir(&s_dir, &fno); + + if (s_fresult != FR_OK) { + errno = fatfs_to_errno(s_fresult); + return nullptr; + } + + if (fno.fname[0] == '\0') { + return nullptr; + } + + errno = 0; + + strncpy(s_dirent.d_name, fno.fname, sizeof(s_dirent.d_name) - 1); + + if (fno.fattrib == AM_DIR) { + s_dirent.d_type = DT_DIR; + } else { + s_dirent.d_type = DT_REG; + } + + return &s_dirent; +#endif +} + +int closedir([[maybe_unused]] DIR *dirp) { +#if !defined (CONFIG_FS_ENABLE_WRITE) + errno = ENOSYS; + return -1; +#else + s_fresult = f_closedir(&s_dir); + errno = fatfs_to_errno(s_fresult); + + if (s_fresult == FR_OK) { + return 0; + } + + return -1; +#endif +} +} diff --git a/lib-hal/rtc/gd32/hwclockrtc.cpp b/lib-hal/rtc/gd32/hwclockrtc.cpp index fbe9f5d8..708e6920 100644 --- a/lib-hal/rtc/gd32/hwclockrtc.cpp +++ b/lib-hal/rtc/gd32/hwclockrtc.cpp @@ -2,7 +2,7 @@ * @file hwclockrtc.cpp * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,20 +27,68 @@ #include #include +#include "hwclock.h" + #include "hardware.h" #include "gd32.h" #include "debug.h" -bool rtc_configuration(void) { - rcu_osci_on (RCU_LXTAL); +#define BCD2DEC(val) ( ((val) & 0x0f) + ((val) >> 4) * 10 ) +#define DEC2BCD(val) static_cast( (((val) / 10) << 4) + (val) % 10 ) + +#if defined (GD32F4XX) || defined (GD32H7XX) +# define RTC_CLOCK_SOURCE_LXTAL +static rtc_parameter_struct rtc_initpara; +#endif + +#if defined (GD32F4XX) || defined (GD32H7XX) +bool rtc_configuration() { +# if defined (RTC_CLOCK_SOURCE_IRC32K) + rcu_osci_on (RCU_IRC32K); + if (SUCCESS != rcu_osci_stab_wait(RCU_IRC32K)) { + return false; + } + rcu_rtc_clock_config (RCU_RTCSRC_IRC32K); +# elif defined (RTC_CLOCK_SOURCE_LXTAL) + rcu_osci_on(RCU_LXTAL); + + if (SUCCESS != rcu_osci_stab_wait(RCU_LXTAL)) { + return false; + } + + rcu_rtc_clock_config(RCU_RTCSRC_LXTAL); +# else +# error RTC clock source should be defined. +# endif + rcu_periph_clock_enable(RCU_RTC); + + if (SUCCESS != rtc_register_sync_wait()) { + return false; + } + + rtc_initpara.date = DEC2BCD(_TIME_STAMP_DAY_); + rtc_initpara.month = DEC2BCD(_TIME_STAMP_MONTH_ - 1); + rtc_initpara.year = DEC2BCD(_TIME_STAMP_YEAR_ - 1900); + + if (SUCCESS != rtc_init(&rtc_initpara)) { + DEBUG_PUTS("RTC time configuration failed!"); + return false; + } + + DEBUG_PUTS("RTC time configuration success!"); + return true; +} +#else +bool rtc_configuration() { + rcu_osci_on(RCU_LXTAL); if (SUCCESS != rcu_osci_stab_wait(RCU_LXTAL)) { return false; } - rcu_rtc_clock_config (RCU_RTCSRC_LXTAL); - rcu_periph_clock_enable (RCU_RTC); + rcu_rtc_clock_config(RCU_RTCSRC_LXTAL); + rcu_periph_clock_enable(RCU_RTC); rtc_register_sync_wait(); rtc_lwoff_wait(); rtc_prescaler_set(32767); @@ -48,12 +96,26 @@ bool rtc_configuration(void) { return true; } +#endif using namespace rtc; void HwClock::RtcProbe() { DEBUG_ENTRY +#if defined (GD32F4XX) || defined (GD32H7XX) +# if defined (RTC_CLOCK_SOURCE_IRC32K) + rtc_initpara.factor_syn = 0x13F; + rtc_initpara.factor_asyn = = 0x63; +# elif defined (RTC_CLOCK_SOURCE_LXTAL) + rtc_initpara.factor_syn = 0xFF; + rtc_initpara.factor_asyn = 0x7F; +# else +# error RTC clock source should be defined. +# endif + rtc_initpara.display_format = RTC_24HOUR; +#endif + if (bkp_data_read(BKP_DATA_0) != 0xA5A5) { DEBUG_PUTS("RTC not yet configured"); @@ -64,14 +126,25 @@ void HwClock::RtcProbe() { return; } - rtc_lwoff_wait(); - rtc_counter_set(time(nullptr)); - rtc_lwoff_wait(); bkp_data_write(BKP_DATA_0, 0xA5A5); + + struct tm RtcTime; + + RtcTime.tm_hour = 0; + RtcTime.tm_min = 0; + RtcTime.tm_sec = 0; + RtcTime.tm_mday = _TIME_STAMP_DAY_; + RtcTime.tm_mon = _TIME_STAMP_MONTH_ - 1; + RtcTime.tm_year = _TIME_STAMP_YEAR_ - 1900; + + RtcSet(&RtcTime); } else { DEBUG_PUTS("No need to configure RTC"); rtc_register_sync_wait(); - rtc_lwoff_wait(); +#if defined (GD32F4XX) || defined (GD32H7XX) +#else + rtc_lwoff_wait(); +#endif } m_Type = rtc::Type::SOC_INTERNAL; @@ -81,24 +154,141 @@ void HwClock::RtcProbe() { DEBUG_EXIT } -bool HwClock::RtcSet(const struct rtc_time *pRtcTime) { +bool HwClock::RtcSet(const struct tm *pTime) { + assert(pTime != nullptr); + + DEBUG_PRINTF("sec=%d, min=%d, hour=%d, mday=%d, mon=%d, year=%d, wday=%d", + pTime->tm_sec, + pTime->tm_min, + pTime->tm_hour, + pTime->tm_mday, + pTime->tm_mon, + pTime->tm_year, + pTime->tm_wday); + +#if defined (GD32F4XX) || defined (GD32H7XX) + rtc_initpara.year = DEC2BCD(pTime->tm_year); + rtc_initpara.month = DEC2BCD(pTime->tm_mon); + rtc_initpara.date = DEC2BCD(pTime->tm_mday); + rtc_initpara.day_of_week = DEC2BCD(pTime->tm_wday); + rtc_initpara.hour = DEC2BCD(pTime->tm_hour); + rtc_initpara.minute = DEC2BCD(pTime->tm_min); + rtc_initpara.second = DEC2BCD(pTime->tm_sec); + + return (SUCCESS == rtc_init(&rtc_initpara)); +#else + rtc_counter_set(mktime(const_cast(pTime))); +#endif + return true; +} + +bool HwClock::RtcGet(struct tm *pTime) { + assert(pTime != nullptr); + +#if defined (GD32F4XX) || defined (GD32H7XX) + const auto tr = reinterpret_cast(RTC_TIME); + const auto dr = reinterpret_cast(RTC_DATE); + + pTime->tm_year = BCD2DEC(GET_DATE_YR(dr)); + pTime->tm_mon = BCD2DEC(GET_DATE_MON(dr)); + pTime->tm_mday = BCD2DEC(GET_DATE_DAY(dr)); + pTime->tm_wday = BCD2DEC(GET_DATE_DOW(dr)); + pTime->tm_hour = BCD2DEC(GET_TIME_HR(tr)); + pTime->tm_min = BCD2DEC(GET_TIME_MN(tr)); + pTime->tm_sec = BCD2DEC(GET_TIME_SC(tr)); +#else + const auto nSeconds = static_cast(rtc_counter_get()); + const auto *pTm = gmtime(&nSeconds); + memcpy(pTime, pTm, sizeof(struct tm)); +#endif + + DEBUG_PRINTF("sec=%d, min=%d, hour=%d, mday=%d, mon=%d, year=%d, wday=%d", + pTime->tm_sec, + pTime->tm_min, + pTime->tm_hour, + pTime->tm_mday, + pTime->tm_mon, + pTime->tm_year, + pTime->tm_wday); + + return true; +} + +bool HwClock::RtcSetAlarm(const struct tm *pTime) { DEBUG_ENTRY - assert(pRtcTime != nullptr); + assert(pTime != nullptr); + + DEBUG_PRINTF("secs=%d, mins=%d, hours=%d, mday=%d, mon=%d, year=%d, wday=%d, enabled=%d", + pTime->tm_sec, + pTime->tm_min, + pTime->tm_hour, + pTime->tm_mday, + pTime->tm_mon, + pTime->tm_year, + pTime->tm_wday, + m_bRtcAlarmEnabled); + +#if defined (GD32F4XX) || defined (GD32H7XX) + rtc_alarm_disable (RTC_ALARM0); + rtc_alarm_struct rtc_alarm; - rtc_counter_set(mktime(const_cast(reinterpret_cast(pRtcTime)))); -// rtc_lwoff_wait(); + rtc_alarm.alarm_mask = RTC_ALARM_ALL_MASK; + rtc_alarm.weekday_or_date = RTC_ALARM_DATE_SELECTED; + rtc_alarm.am_pm = 0; + rtc_alarm.alarm_day = DEC2BCD(pTime->tm_mday); + rtc_alarm.alarm_hour = DEC2BCD(pTime->tm_hour); + rtc_alarm.alarm_minute = DEC2BCD(pTime->tm_min); + rtc_alarm.alarm_second = DEC2BCD(pTime->tm_sec); + + rtc_alarm_config(RTC_ALARM0, &rtc_alarm); + + if (m_bRtcAlarmEnabled) { + rtc_interrupt_enable (RTC_INT_ALARM0); + rtc_alarm_enable(RTC_ALARM0); + } else { + rtc_alarm_disable(RTC_ALARM0); + rtc_interrupt_disable(RTC_INT_ALARM0); + } +#else + rtc_alarm_config(mktime(const_cast(pTime))); +#endif DEBUG_EXIT return true; } -bool HwClock::RtcGet(struct rtc_time *pRtcTime) { +bool HwClock::RtcGetAlarm(struct tm *pTime) { DEBUG_ENTRY - assert(pRtcTime != nullptr); + assert(pTime != nullptr); + +#if defined (GD32F4XX) || defined (GD32H7XX) + if (!RtcGet(pTime)) { + DEBUG_EXIT + return false; + } + + rtc_alarm_struct rtc_alarm; + rtc_alarm_get(RTC_ALARM0, &rtc_alarm); - const auto nSeconds = static_cast(rtc_counter_get()); + pTime->tm_sec= BCD2DEC(rtc_alarm.alarm_second); + pTime->tm_min = BCD2DEC(rtc_alarm.alarm_minute); + pTime->tm_hour = BCD2DEC(rtc_alarm.alarm_hour); + pTime->tm_mday = BCD2DEC(rtc_alarm.alarm_day); +#else + const auto nSeconds = static_cast((RTC_ALRMH << 16U) | RTC_ALRML); const auto *pTm = localtime(&nSeconds); - memcpy(pRtcTime, pTm, sizeof(struct rtc_time)); + memcpy(pTime, pTm, sizeof(struct tm)); +#endif + + DEBUG_PRINTF("secs=%d, mins=%d, hours=%d, mday=%d, mon=%d, year=%d, wday=%d, enabled=%d", + pTime->tm_sec, + pTime->tm_min, + pTime->tm_hour, + pTime->tm_mday, + pTime->tm_mon, + pTime->tm_year, + pTime->tm_wday, + m_bRtcAlarmEnabled); DEBUG_EXIT return true; diff --git a/lib-hal/rtc/hwclock.cpp b/lib-hal/rtc/hwclock.cpp old mode 100644 new mode 100755 index 43d73a79..e065f5ca --- a/lib-hal/rtc/hwclock.cpp +++ b/lib-hal/rtc/hwclock.cpp @@ -2,7 +2,7 @@ * @file hwclock.cpp * */ -/* Copyright (C) 2020-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,9 +34,7 @@ #include "debug.h" -using namespace rtc; - -HwClock *HwClock::s_pThis = nullptr; +HwClock *HwClock::s_pThis; HwClock::HwClock() { assert(s_pThis == nullptr); @@ -52,27 +50,25 @@ void HwClock::Print() { const char *pType = "Unknown"; switch (m_Type) { - case Type::MCP7941X: + case rtc::Type::MCP7941X: pType = "MCP7941X"; break; - case Type::DS3231: + case rtc::Type::DS3231: pType = "DS3231"; break; - case Type::PCF8563: + case rtc::Type::PCF8563: pType = "PCF8563"; break; - case Type::SOC_INTERNAL: + case rtc::Type::SOC_INTERNAL: pType = "SOC_INTERNAL"; break; default: break; } - printf("%s\n", pType); - - struct rtc_time tm; + struct tm tm; RtcGet(&tm); - printf("%.4d/%.2d/%.2d %.2d:%.2d:%.2d\n", 1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); + printf("%s %.4d/%.2d/%.2d %.2d:%.2d:%.2d\n", pType, 1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); } /* @@ -85,39 +81,28 @@ void HwClock::HcToSys() { return; } - assert(Hardware::Get() != nullptr); - const bool bIsWatchdog = Hardware::Get()->IsWatchdog(); + const auto bIsWatchdog = Hardware::Get()->IsWatchdog(); if (bIsWatchdog) { Hardware::Get()->WatchdogStop(); } - struct rtc_time rtcT1; - struct rtc_time rtcT2; - + struct tm rtcT1; struct timeval tvT1; - struct timeval tvT2; RtcGet(&rtcT1); gettimeofday(&tvT1, nullptr); - const int32_t nSecondsT1 = rtcT1.tm_sec + rtcT1.tm_min * 60; - - struct tm tm; - - tm.tm_sec = rtcT1.tm_sec; - tm.tm_min = rtcT1.tm_min; - tm.tm_hour = rtcT1.tm_hour; - tm.tm_mday = rtcT1.tm_mday; - tm.tm_mon = rtcT1.tm_mon; - tm.tm_year = rtcT1.tm_year; + const auto nSecondsT1 = rtcT1.tm_sec + rtcT1.tm_min * 60; + const auto nSeconds = mktime(&rtcT1); - const time_t nSeconds = mktime(&tm); + struct tm rtcT2; + struct timeval tvT2; while(true) { RtcGet(&rtcT2); - const int32_t nSeconds2 = rtcT2.tm_sec + rtcT2.tm_min * 60; + const auto nSeconds2 = rtcT2.tm_sec + rtcT2.tm_min * 60; if (nSecondsT1 != nSeconds2) { gettimeofday(&tvT2, nullptr); @@ -159,8 +144,7 @@ void HwClock::SysToHc() { return; } - assert(Hardware::Get() != nullptr); - const bool bIsWatchdog = Hardware::Get()->IsWatchdog(); + const auto bIsWatchdog = Hardware::Get()->IsWatchdog(); if (bIsWatchdog) { Hardware::Get()->WatchdogStop(); @@ -174,18 +158,8 @@ void HwClock::SysToHc() { gettimeofday(&tv2, nullptr); if (tv2.tv_sec >= (tv1.tv_sec + 1)) { - const struct tm *tm = localtime(&tv2.tv_sec); - - struct rtc_time rtc; - - rtc.tm_sec = tm->tm_sec; - rtc.tm_min = tm->tm_min; - rtc.tm_hour = tm->tm_hour; - rtc.tm_mday = tm->tm_mday; - rtc.tm_mon = tm->tm_mon; - rtc.tm_year = tm->tm_year; - - RtcSet(&rtc); + const auto *tm = gmtime(&tv2.tv_sec); + RtcSet(tm); break; } } diff --git a/lib-hal/rtc/hwclockrun.cpp b/lib-hal/rtc/hwclockrun.cpp index 839f8290..dae0bea9 100644 --- a/lib-hal/rtc/hwclockrun.cpp +++ b/lib-hal/rtc/hwclockrun.cpp @@ -2,7 +2,7 @@ * @file hwclockrun.cpp * */ -/* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,23 +34,18 @@ #include "debug.h" enum class Status { - WAITING, - SAMPLING + WAITING, SAMPLING }; static Status Status = Status::WAITING; static time_t nSeconds; static int32_t nSecondsT1; -static struct rtc_time rtcT1; +static struct tm rtcT1; static struct timeval tvT1; -static struct rtc_time rtcT2; +static struct tm rtcT2; static struct timeval tvT2; -void HwClock::Run(bool bDoRun) { - if (!bDoRun || !m_bIsConnected) { - return; - } - +void HwClock::Process() { if (Status == Status::WAITING) { if (__builtin_expect(((Hardware::Get()->Millis() - m_nLastHcToSysMillis) > 7200 * 1000), 0)) { Status = Status::SAMPLING; @@ -59,17 +54,7 @@ void HwClock::Run(bool bDoRun) { gettimeofday(&tvT1, nullptr); nSecondsT1 = rtcT1.tm_sec + rtcT1.tm_min * 60; - - struct tm tm; - - tm.tm_sec = rtcT1.tm_sec; - tm.tm_min = rtcT1.tm_min; - tm.tm_hour = rtcT1.tm_hour; - tm.tm_mday = rtcT1.tm_mday; - tm.tm_mon = rtcT1.tm_mon; - tm.tm_year = rtcT1.tm_year; - - nSeconds = mktime(&tm); + nSeconds = mktime(&rtcT1); } return; @@ -78,7 +63,7 @@ void HwClock::Run(bool bDoRun) { if (Status == Status::SAMPLING) { RtcGet(&rtcT2); - const int32_t nSeconds2 = rtcT2.tm_sec + rtcT2.tm_min * 60; + const auto nSeconds2 = rtcT2.tm_sec + rtcT2.tm_min * 60; if (nSecondsT1 != nSeconds2) { gettimeofday(&tvT2, nullptr); @@ -101,7 +86,7 @@ void HwClock::Run(bool bDoRun) { m_nLastHcToSysMillis = Hardware::Get()->Millis(); Status = Status::WAITING; - DEBUG_PRINTF("%d:%d (%ld %u) (%ld %u) -> %u", nSecondsT1, nSeconds2, tvT1.tv_sec, tvT1.tv_usec, tvT2.tv_sec, tvT2.tv_usec, tv.tv_usec); + DEBUG_PRINTF("%d:%d (%d %d) (%d %d) -> %d", nSecondsT1, nSeconds2, static_cast(tvT1.tv_sec), static_cast(tvT1.tv_usec), static_cast(tvT2.tv_sec), static_cast(tvT2.tv_usec), static_cast(tv.tv_usec)); } return; diff --git a/lib-hal/rtc/hwclockset.cpp b/lib-hal/rtc/hwclockset.cpp index 622bdfed..6a2cd383 100644 --- a/lib-hal/rtc/hwclockset.cpp +++ b/lib-hal/rtc/hwclockset.cpp @@ -2,7 +2,7 @@ * @file hwclockset.cpp * */ -/* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,7 +31,7 @@ #include "debug.h" -bool HwClock::Set(const rtc_time *pRtcTime) { +bool HwClock::Set(const tm *pTime) { if (!m_bIsConnected) { return false; } @@ -39,19 +39,10 @@ bool HwClock::Set(const rtc_time *pRtcTime) { struct timeval tvT1; gettimeofday(&tvT1, nullptr); - RtcSet(pRtcTime); - - struct tm tm; - tm.tm_sec = pRtcTime->tm_sec; - tm.tm_min = pRtcTime->tm_min; - tm.tm_hour = pRtcTime->tm_hour; - tm.tm_mday = pRtcTime->tm_mday; - tm.tm_mon = pRtcTime->tm_mon; - tm.tm_year = pRtcTime->tm_year; - tm.tm_isdst = 0; + RtcSet(pTime); struct timeval tv; - tv.tv_sec = mktime(&tm); + tv.tv_sec = mktime(const_cast(pTime)); struct timeval tvT2; gettimeofday(&tvT2, nullptr); diff --git a/lib-hal/rtc/i2c/hwclockrtc.cpp b/lib-hal/rtc/i2c/hwclockrtc.cpp index 2bc00b7f..892d2c20 100644 --- a/lib-hal/rtc/i2c/hwclockrtc.cpp +++ b/lib-hal/rtc/i2c/hwclockrtc.cpp @@ -2,7 +2,7 @@ * @file hwclockrtc.cpp * */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,6 +24,7 @@ */ #include +#include #include "hwclock.h" #include "hardware.h" @@ -38,38 +39,67 @@ namespace rtc { namespace reg { static constexpr uint8_t SECONDS = 0x00; static constexpr uint8_t MINUTES = 0x01; -static constexpr uint8_t HOURS = 0x02; -static constexpr uint8_t DAY = 0x03; -static constexpr uint8_t DATE = 0x04; -static constexpr uint8_t MONTH = 0x05; -static constexpr uint8_t YEAR = 0x06; +static constexpr uint8_t HOURS = 0x02; +static constexpr uint8_t DAY = 0x03; +static constexpr uint8_t DATE = 0x04; +static constexpr uint8_t MONTH = 0x05; +static constexpr uint8_t YEAR = 0x06; } // namespace reg namespace mcp7941x { +namespace reg { +static constexpr uint8_t CONTROL = 0x07; +} // namespace reg namespace bit { -static constexpr uint8_t ST = 0x80; -static constexpr uint8_t VBATEN = 0x08; +static constexpr uint8_t ST = 0x80; +static constexpr uint8_t VBATEN = 0x08; +static constexpr uint8_t ALM0_EN = 0x10; +static constexpr uint8_t ALMX_IF = (1U << 3); +static constexpr uint8_t ALMX_C0 = (1U << 4); +static constexpr uint8_t ALMX_C1 = (1U << 5); +static constexpr uint8_t ALMX_C2 = (1U << 6); +#ifndef NDEBUG +static constexpr uint8_t ALMX_POL = (1U << 7); +#endif +static constexpr uint8_t MSK_ALMX_MATCH = (ALMX_C0 | ALMX_C1 | ALMX_C2); } // namespace bit } // namespace mcp7941x +namespace ds3231 { +namespace reg { +static constexpr uint8_t ALARM1_SECONDS = 0x07; +static constexpr uint8_t CONTROL = 0x0e; +//static constexpr uint8_t STATUS = 0x0f; +} // namespace reg +namespace bit { +static constexpr uint8_t A1IE = (1U << 0); +static constexpr uint8_t A2IE = (1U << 1); +static constexpr uint8_t A1F = (1U << 0); +static constexpr uint8_t A2F = (1U << 1); +} // namespace bit +} // namespace ds3231 namespace pcf8563 { namespace reg { static constexpr uint8_t CONTROL_STATUS1 = 0x00; static constexpr uint8_t CONTROL_STATUS2 = 0x01; -static constexpr uint8_t SECONDS = 0x02; -static constexpr uint8_t MINUTES = 0x03; -static constexpr uint8_t HOURS = 0x04; -static constexpr uint8_t DAY = 0x05; -static constexpr uint8_t WEEKDAY = 0x06; -static constexpr uint8_t MONTH = 0x07; -static constexpr uint8_t YEAR = 0x08; +static constexpr uint8_t SECONDS = 0x02; +//static constexpr uint8_t MINUTES = 0x03; +//static constexpr uint8_t HOURS = 0x04; +//static constexpr uint8_t DAY = 0x05; +//static constexpr uint8_t WEEKDAY = 0x06; +//static constexpr uint8_t MONTH = 0x07; +static constexpr uint8_t YEAR = 0x08; +static constexpr uint8_t ALARM = 0x09; } // namespace reg namespace bit { -static constexpr uint8_t SEC_VL = (1U << 7); +static constexpr uint8_t SEC_VL = (1U << 7); +static constexpr uint8_t AIE = (1U << 1); +static constexpr uint8_t AF = (1U << 3); +static constexpr uint8_t ST2_N = (7U << 5); } // namespace bit } // namespace pcf8563 namespace i2caddress { -static constexpr uint8_t PCF8563 = 0x51; +static constexpr uint8_t PCF8563 = 0x51; static constexpr uint8_t MCP7941X = 0x6F; -static constexpr uint8_t DS3231 = 0x68; +static constexpr uint8_t DS3231 = 0x68; } // namespace i2caddress } // namespace rtc @@ -94,10 +124,6 @@ void HwClock::RtcProbe() { char registers[1]; #if !defined (CONFIG_RTC_DISABLE_MCP7941X) - /** - * MCP7941X - */ - FUNC_PREFIX(i2c_set_address(i2caddress::MCP7941X)); registers[0] = reg::YEAR; @@ -122,7 +148,7 @@ void HwClock::RtcProbe() { if ((registers[0] & mcp7941x::bit::ST) == 0) { DEBUG_PUTS("Start the on-board oscillator"); - struct rtc_time RtcTime; + struct tm RtcTime; RtcTime.tm_hour = 0; RtcTime.tm_min = 0; @@ -140,10 +166,6 @@ void HwClock::RtcProbe() { #endif #if !defined (CONFIG_RTC_DISABLE_DS3231) - /** - * DS3231 - */ - FUNC_PREFIX(i2c_set_address(i2caddress::DS3231)); registers[0] = reg::YEAR; @@ -158,7 +180,7 @@ void HwClock::RtcProbe() { m_Type = Type::DS3231; m_nAddress = i2caddress::DS3231; - struct rtc_time tm; + struct tm tm; RtcGet(&tm); if ((tm.tm_hour > 24) || (tm.tm_year > _TIME_STAMP_YEAR_ - 1900)) { @@ -178,10 +200,6 @@ void HwClock::RtcProbe() { #endif #if !defined (CONFIG_RTC_DISABLE_PCF8563) - /** - * PCF8563 - */ - FUNC_PREFIX(i2c_set_address(i2caddress::PCF8563)); registers[0] = pcf8563::reg::YEAR; @@ -207,7 +225,7 @@ void HwClock::RtcProbe() { if (registers[0] & pcf8563::bit::SEC_VL) { DEBUG_PUTS("Integrity of the clock information is not guaranteed"); - struct rtc_time RtcTime; + struct tm RtcTime; RtcTime.tm_hour = 0; RtcTime.tm_min = 0; @@ -237,54 +255,53 @@ void HwClock::RtcProbe() { DEBUG_EXIT } -bool HwClock::RtcSet(const struct rtc_time *pRtcTime) { - assert(pRtcTime != nullptr); +bool HwClock::RtcSet(const struct tm *pTime) { + assert(pTime != nullptr); if (!m_bIsConnected) { return false; } - char registers[7]; + DEBUG_PRINTF("secs=%d, mins=%d, hours=%d, mday=%d, mon=%d, year=%d, wday=%d", + pTime->tm_sec, + pTime->tm_min, + pTime->tm_hour, + pTime->tm_mday, + pTime->tm_mon, + pTime->tm_year, + pTime->tm_wday); - registers[reg::SECONDS] = DEC2BCD(pRtcTime->tm_sec & 0x7f); - registers[reg::MINUTES] = DEC2BCD(pRtcTime->tm_min & 0x7f); - registers[reg::HOURS] = DEC2BCD(pRtcTime->tm_hour & 0x1f); - registers[reg::DAY] = DEC2BCD(pRtcTime->tm_wday & 0x07); - registers[reg::DATE] = DEC2BCD(pRtcTime->tm_mday & 0x3f); - registers[reg::MONTH] = DEC2BCD((pRtcTime->tm_mon + 1) & 0x1f); - registers[reg::YEAR] = DEC2BCD((pRtcTime->tm_year - 100) & 0xff); + char data[8]; + auto registers = &data[1]; + + registers[reg::SECONDS] = DEC2BCD(pTime->tm_sec & 0x7f); + registers[reg::MINUTES] = DEC2BCD(pTime->tm_min & 0x7f); + registers[reg::HOURS] = DEC2BCD(pTime->tm_hour & 0x1f); + registers[reg::DAY] = DEC2BCD(pTime->tm_wday & 0x07); + registers[reg::DATE] = DEC2BCD(pTime->tm_mday & 0x3f); + registers[reg::MONTH] = DEC2BCD((pTime->tm_mon + 1) & 0x1f); + registers[reg::YEAR] = DEC2BCD((pTime->tm_year - 100) & 0xff); if (m_Type == Type::MCP7941X) { registers[reg::SECONDS] |= mcp7941x::bit::ST; registers[reg::DAY] |= mcp7941x::bit::VBATEN; } - char data[8]; - if (m_Type == Type::PCF8563) { data[0] = pcf8563::reg::SECONDS; } else { data[0] = reg::SECONDS; } - data[1] = registers[0]; - data[2] = registers[1]; - data[3] = registers[2]; - data[4] = registers[3]; - data[5] = registers[4]; - data[6] = registers[5]; - data[7] = registers[6]; - FUNC_PREFIX(i2c_set_address(m_nAddress)); FUNC_PREFIX(i2c_set_baudrate(hal::i2c::FULL_SPEED)); - FUNC_PREFIX(i2c_write(data, sizeof(data) / sizeof(data[0]))); return true; } -bool HwClock::RtcGet(struct rtc_time *pRtcTime) { - assert(pRtcTime != nullptr); +bool HwClock::RtcGet(struct tm *pTime) { + assert(pTime != nullptr); if (!m_bIsConnected) { return false; @@ -300,17 +317,328 @@ bool HwClock::RtcGet(struct rtc_time *pRtcTime) { FUNC_PREFIX(i2c_set_address(m_nAddress)); FUNC_PREFIX(i2c_set_baudrate(hal::i2c::FULL_SPEED)); - FUNC_PREFIX(i2c_write(registers, 1)); FUNC_PREFIX(i2c_read(registers, sizeof(registers) / sizeof(registers[0]))); - pRtcTime->tm_sec = BCD2DEC(registers[reg::SECONDS] & 0x7f); - pRtcTime->tm_min = BCD2DEC(registers[reg::MINUTES] & 0x7f); - pRtcTime->tm_hour = BCD2DEC(registers[reg::HOURS] & 0x3f); - pRtcTime->tm_wday = BCD2DEC(registers[reg::DAY] & 0x07); - pRtcTime->tm_mday = BCD2DEC(registers[reg::DATE] & 0x3f); - pRtcTime->tm_mon = BCD2DEC(registers[reg::MONTH] & 0x1f) - 1; - pRtcTime->tm_year = BCD2DEC(registers[reg::YEAR]) + 100; + pTime->tm_sec = BCD2DEC(registers[reg::SECONDS] & 0x7f); + pTime->tm_min = BCD2DEC(registers[reg::MINUTES] & 0x7f); + pTime->tm_hour = BCD2DEC(registers[reg::HOURS] & 0x3f); + pTime->tm_wday = BCD2DEC(registers[reg::DAY] & 0x07); + pTime->tm_mday = BCD2DEC(registers[reg::DATE] & 0x3f); + pTime->tm_mon = BCD2DEC(registers[reg::MONTH] & 0x1f) - 1; + pTime->tm_year = BCD2DEC(registers[reg::YEAR]) + 100; + + DEBUG_PRINTF("secs=%d, mins=%d, hours=%d, mday=%d, mon=%d, year=%d, wday=%d", + pTime->tm_sec, + pTime->tm_min, + pTime->tm_hour, + pTime->tm_mday, + pTime->tm_mon, + pTime->tm_year, + pTime->tm_wday); return true; } + +bool HwClock::RtcSetAlarm(const struct tm *pTime) { + DEBUG_ENTRY + assert(pTime != nullptr); + + DEBUG_PRINTF("secs=%d, mins=%d, hours=%d, mday=%d, mon=%d, year=%d, wday=%d", + pTime->tm_sec, + pTime->tm_min, + pTime->tm_hour, + pTime->tm_mday, + pTime->tm_mon, + pTime->tm_year, + pTime->tm_wday); + + switch (m_Type) { +#if !defined (CONFIG_RTC_DISABLE_MCP7941X) + case Type::MCP7941X: { + const auto wday = static_cast(MCP794xxAlarmWeekday(const_cast(pTime))); + + // Read control and alarm 0 registers. + char registers[11]; + auto data = ®isters[1]; + data[0] = mcp7941x::reg::CONTROL; + + FUNC_PREFIX(i2c_write(data, 1)); + FUNC_PREFIX(i2c_read(data, 10)); + + // Set alarm 0, using 24-hour and day-of-month modes. + data[3] = DEC2BCD(pTime->tm_sec); + data[4] = DEC2BCD(pTime->tm_min); + data[5] = DEC2BCD(pTime->tm_hour); + data[6] = wday; + data[7] = DEC2BCD(pTime->tm_mday); + data[8] = DEC2BCD(pTime->tm_mon + 1); + // Clear the alarm 0 interrupt flag. + data[6] &= static_cast(~mcp7941x::bit::ALMX_IF); + // Set alarm match: second, minute, hour, day, date, month. + data[6] |= mcp7941x::bit::MSK_ALMX_MATCH; + // Disable interrupt. We will not enable until completely programmed. + data[0] &= static_cast(~mcp7941x::bit::ALM0_EN); + + registers[0] = mcp7941x::reg::CONTROL; + FUNC_PREFIX(i2c_write(registers, sizeof(registers) / sizeof(registers[0]))); + + if (m_bRtcAlarmEnabled) { + registers[0] = mcp7941x::reg::CONTROL; + registers[1] |= mcp7941x::bit::ALM0_EN; + FUNC_PREFIX(i2c_write(registers, 2)); + } + + DEBUG_EXIT + return true; + } + break; +#endif +#if !defined (CONFIG_RTC_DISABLE_DS3231) + case Type::DS3231: { + char registers[10]; + auto data = ®isters[1]; + data[0] = ds3231::reg::ALARM1_SECONDS; + + FUNC_PREFIX(i2c_set_address(m_nAddress)); + FUNC_PREFIX(i2c_set_baudrate(hal::i2c::FULL_SPEED)); + FUNC_PREFIX(i2c_write(data, 1)); + FUNC_PREFIX(i2c_read(data, 9)); + + const auto control = data[7]; + const auto status = data[8]; + + // set ALARM1, using 24 hour and day-of-month modes + data[0] = DEC2BCD(pTime->tm_sec); + data[1] = DEC2BCD(pTime->tm_min); + data[2] = DEC2BCD(pTime->tm_hour); + data[3] = DEC2BCD(pTime->tm_mday); + // set ALARM2 to non-garbage + data[4] = 0; + data[5] = 0; + data[6] = 0; + // disable alarms + data[7] = control & static_cast(~(ds3231::bit::A1IE | ds3231::bit::A2IE)); + data[8] = status & static_cast(~(ds3231::bit::A1F | ds3231::bit::A2F)); + + registers[0] = ds3231::reg::ALARM1_SECONDS; + FUNC_PREFIX(i2c_write(registers, sizeof(registers) / sizeof(registers[0]))); + + if (m_bRtcAlarmEnabled) { + registers[0] = ds3231::reg::CONTROL; + registers[1] |= ds3231::bit::A1IE; + FUNC_PREFIX(i2c_write(registers, 2)); + } + + DEBUG_EXIT + return true; + } + break; +#endif +#if !defined (CONFIG_RTC_DISABLE_PCF8563) + case Type::PCF8563: { + char data[5]; + + data[0] = pcf8563::reg::ALARM; + data[1] = DEC2BCD(pTime->tm_min); + data[2] = DEC2BCD(pTime->tm_hour); + data[3] = DEC2BCD(pTime->tm_mday); + data[4] = pTime->tm_wday & 0x07; + + FUNC_PREFIX(i2c_set_address(m_nAddress)); + FUNC_PREFIX(i2c_set_baudrate(hal::i2c::FULL_SPEED)); + FUNC_PREFIX(i2c_write(data, sizeof(data) / sizeof(data[0]))); + + PCF8563SetAlarmMode(); + + DEBUG_EXIT + return true; + } + break; +#endif + default: + break; + } + + DEBUG_EXIT + return false; +} + +bool HwClock::RtcGetAlarm(struct tm *pTime) { + DEBUG_ENTRY + assert(pTime != nullptr); + + if (!RtcGet(pTime)) { + DEBUG_EXIT + return false; + } + + switch (m_Type) { +#if !defined (CONFIG_RTC_DISABLE_MCP7941X) + case Type::MCP7941X: { + char registers[10]; + + registers[0] = mcp7941x::reg::CONTROL; + + FUNC_PREFIX(i2c_set_address(m_nAddress)); + FUNC_PREFIX(i2c_set_baudrate(hal::i2c::FULL_SPEED)); + FUNC_PREFIX(i2c_write(registers, 1)); + FUNC_PREFIX(i2c_read(registers, sizeof(registers) / sizeof(registers[0]))); + + pTime->tm_sec = BCD2DEC(registers[3] & 0x7f); + pTime->tm_min = BCD2DEC(registers[4] & 0x7f); + pTime->tm_hour = BCD2DEC(registers[5] & 0x3f); + pTime->tm_wday = BCD2DEC(registers[6] & 0x7) - 1; + pTime->tm_mday = BCD2DEC(registers[7] & 0x3f); + pTime->tm_mon = BCD2DEC(registers[8] & 0x1f) - 1; + + m_bRtcAlarmEnabled = registers[0] & mcp7941x::bit::ALM0_EN; + + DEBUG_PRINTF("sec=%d min=%d hour=%d wday=%d mday=%d mon=%d enabled=%d polarity=%d irq=%d match=%u", + pTime->tm_sec, + pTime->tm_min, + pTime->tm_hour, + pTime->tm_wday, + pTime->tm_mday, + pTime->tm_mon, + m_bRtcAlarmEnabled, + (registers[6] & mcp7941x::bit::ALMX_POL), + (registers[6] & mcp7941x::bit::ALMX_IF), + (registers[6] & mcp7941x::bit::MSK_ALMX_MATCH) >> 4); + + DEBUG_EXIT + return true; + } + break; +#endif +#if !defined (CONFIG_RTC_DISABLE_DS3231) + case Type::DS3231: { + char registers[10]; + + registers[0] = ds3231::reg::ALARM1_SECONDS; + + FUNC_PREFIX(i2c_set_address(m_nAddress)); + FUNC_PREFIX(i2c_set_baudrate(hal::i2c::FULL_SPEED)); + FUNC_PREFIX(i2c_write(registers, 1)); + FUNC_PREFIX(i2c_read(registers, sizeof(registers) / sizeof(registers[0]))); + + pTime->tm_sec = BCD2DEC(registers[0] & 0x7f); + pTime->tm_min = BCD2DEC(registers[1] & 0x7f); + pTime->tm_hour = BCD2DEC(registers[2] & 0x3f); + pTime->tm_mday = BCD2DEC(registers[3] & 0x3f); + + m_bRtcAlarmEnabled = (registers[7] & ds3231::bit::A1IE); + m_bRtcAlarmPending = (registers[8] &ds3231::bit::A1F); + + DEBUG_PRINTF("tm is sec=%d, min=%d, hour=%d, mday=%d, enabled=%d, pending=%d", + pTime->tm_sec, + pTime->tm_min, + pTime->tm_hour, + pTime->tm_mday, + m_bRtcAlarmEnabled, + m_bRtcAlarmPending); + + DEBUG_EXIT + return true; + } + + break; +#endif +#if !defined (CONFIG_RTC_DISABLE_PCF8563) + case Type::PCF8563: { + char registers[4]; + + registers[0] = pcf8563::reg::ALARM; + + FUNC_PREFIX(i2c_set_address(m_nAddress)); + FUNC_PREFIX(i2c_set_baudrate(hal::i2c::FULL_SPEED)); + FUNC_PREFIX(i2c_write(registers, 1)); + FUNC_PREFIX(i2c_read(registers, sizeof(registers) / sizeof(registers[0]))); + + DEBUG_PRINTF("raw data is min=%02x, hr=%02x, mday=%02x, wday=%02x", + registers[0], + registers[1], + registers[2], + registers[3]); + + pTime->tm_sec = 0; + pTime->tm_min = BCD2DEC(registers[0] & 0x7F); + pTime->tm_hour = BCD2DEC(registers[1] & 0x3F); + pTime->tm_mday = BCD2DEC(registers[2] & 0x3F); + pTime->tm_wday = BCD2DEC(registers[3] & 0x7); + + PCF8563GetAlarmMode(); + + DEBUG_PRINTF("tm is mins=%d, hours=%d, mday=%d, wday=%d, enabled=%d, pending=%d", + pTime->tm_min, + pTime->tm_hour, + pTime->tm_mday, + pTime->tm_wday, + m_bRtcAlarmEnabled, + m_bRtcAlarmPending); + + DEBUG_EXIT + return true; + } + break; +#endif + default: + break; + } + + DEBUG_EXIT + return false; +} + +int HwClock::MCP794xxAlarmWeekday(struct tm *pTime) { + DEBUG_ENTRY + assert(pTime != nullptr); + assert(m_Type == rtc::Type::MCP7941X); + + struct tm tm_now; + RtcGet(&tm_now); + + const auto days_now = mktime(&tm_now) / (24 * 60 * 60); + const auto days_alarm = mktime(pTime) / (24 * 60 * 60); + const auto i = (tm_now.tm_wday + days_alarm - days_now) % 7 + 1; + + DEBUG_EXIT + return i; +} + +void HwClock::PCF8563GetAlarmMode() { + assert(m_Type == rtc::Type::PCF8563); + + char data[1]; + + data[0] = pcf8563::reg::CONTROL_STATUS2; + + FUNC_PREFIX(i2c_write(data, 1)); + FUNC_PREFIX(i2c_read(data, sizeof(data) / sizeof(data[0]))); + + m_bRtcAlarmEnabled = data[0] & pcf8563::bit::AIE; + m_bRtcAlarmPending = data[0] & pcf8563::bit::AF; +} + +void HwClock::PCF8563SetAlarmMode() { + assert(m_Type == rtc::Type::PCF8563); + + char data[2]; + + data[1] = pcf8563::reg::CONTROL_STATUS2; + + FUNC_PREFIX(i2c_write(&data[1], 1)); + FUNC_PREFIX(i2c_read(&data[1], 1)); + + if (m_bRtcAlarmEnabled) { + data[1] |= pcf8563::bit::AIE; + } else { + data[1] &= static_cast(~pcf8563::bit::AIE); + } + + data[1] &= static_cast(~pcf8563::bit::AF | pcf8563::bit::ST2_N); + + data[0] = pcf8563::reg::CONTROL_STATUS2; + + FUNC_PREFIX(i2c_write(data, 2)); +} diff --git a/lib-hal/rtc/json_rtc.cpp b/lib-hal/rtc/json_rtc.cpp new file mode 100755 index 00000000..443dd51a --- /dev/null +++ b/lib-hal/rtc/json_rtc.cpp @@ -0,0 +1,155 @@ +/** + * @file json_rtc.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include "hwclock.h" + +#include "debug.h" + +// ISO 8601 format (YYYY-MM-DDTHH:MM:SS) + +#include "readconfigfile.h" +#include "sscan.h" + +static constexpr auto iso8601FormatSize = sizeof("YYYY-MM-DDTHH:MM:SS"); +static char iso8601Format[iso8601FormatSize]; + +static void staticCallbackFunction([[maybe_unused]] void *p, const char *s) { + assert(p == nullptr); + assert(s != nullptr); + + uint32_t nLength = iso8601FormatSize; + + if (Sscan::Char(s, "alarm" , iso8601Format, nLength) == Sscan::OK) { + DEBUG_PUTS("alarm"); + return; + } + + char action[8]; + nLength = sizeof(action) - 1; + + if (Sscan::Char(s, "action" , action, nLength) == Sscan::OK) { + if (strncmp(action, "hctosys", nLength) == 0) { + HwClock::Get()->HcToSys(); + return; + } + + if (strncmp(action, "systohc", nLength) == 0) { + HwClock::Get()->SysToHc(); + return; + } + + return; + } + + uint8_t nValue8; + + if (Sscan::Uint8(s, "enable", nValue8) == Sscan::OK) { + HwClock::Get()->AlarmEnable(nValue8 != 0); + return; + } +} + +namespace remoteconfig { +namespace rtc { +static int atoi(const char *pBuffer, uint32_t nSize) { + assert(pBuffer != nullptr); + assert(nSize <= 4); + + const char *p = pBuffer; + int32_t res = 0; + + for (; (nSize > 0) && (*p >= '0' && *p <= '9'); nSize--) { + res = res * 10 + *p - '0'; + p++; + } + + return res; +} + +uint32_t json_get_rtc(char *pOutBuffer, const uint32_t nOutBufferSize) { + DEBUG_ENTRY + + struct tm tm; + + if (HwClock::Get()->Get(&tm)) { + auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, + "{\"rtc\":\"%d-%.2d-%.2dT%.2d:%.2d:%.2d\",", + 1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec)); + + if (HwClock::Get()->AlarmGet(&tm)) { + nLength += static_cast(snprintf(&pOutBuffer[nLength], nOutBufferSize, + "\"alarm\":\"%d-%.2d-%.2dT%.2d:%.2d:%.2d\",", + 1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec)); + + nLength += static_cast(snprintf(&pOutBuffer[nLength], nOutBufferSize, + "\"enabled\":\"%d\"}", HwClock::Get()->AlarmIsEnabled())); + + DEBUG_EXIT + return nLength; + } else { + pOutBuffer[nLength++] = '}'; + } + } + + DEBUG_EXIT + return 0; +} + +void json_set_rtc(const char *pBuffer, const uint32_t nBufferSize) { + DEBUG_ENTRY + debug_dump(pBuffer, static_cast(nBufferSize)); + + iso8601Format[0] = 0; + + ReadConfigFile config(staticCallbackFunction, nullptr); + config.Read(pBuffer, nBufferSize); + + debug_dump(iso8601Format, static_cast(sizeof(iso8601Format))); + + if (iso8601Format[0] != 0) { + struct tm tm; + tm.tm_year = atoi(&iso8601Format[0], 4) - 1900; + tm.tm_mon = atoi(&iso8601Format[5], 2) - 1; + tm.tm_mday = atoi(&iso8601Format[8], 2); + tm.tm_hour = atoi(&iso8601Format[11], 2); + tm.tm_min = atoi(&iso8601Format[14], 2); + tm.tm_sec = atoi(&iso8601Format[17], 2); + HwClock::Get()->AlarmSet(&tm); + + DEBUG_EXIT + return; + } + + DEBUG_EXIT +} +} // namespace rtc +} // namespace remoteconfig diff --git a/lib-hal/src/gd32/hardware.cpp b/lib-hal/src/gd32/hardware.cpp index 57a96564..2795b715 100644 --- a/lib-hal/src/gd32/hardware.cpp +++ b/lib-hal/src/gd32/hardware.cpp @@ -2,7 +2,7 @@ * @file hardware.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,14 +25,18 @@ #include #include +#include #include #include "hardware.h" +#include "panel_led.h" #include "gd32.h" #include "gd32_i2c.h" #include "gd32_adc.h" -#include "gd32_board.h" +#if defined (CONFIG_ENET_ENABLE_PTP) +# include "gd32_ptp.h" +#endif #if defined (DEBUG_I2C) # include "../debug/i2c/i2cdetect.h" @@ -42,44 +46,92 @@ void usb_init(); #endif +#include "logic_analyzer.h" + #include "debug.h" +#if (defined (GD32F4XX) || defined (GD32H7XX)) && defined(GPIO_INIT) +# error +#endif + extern "C" { -void console_init(void); -void __libc_init_array(void); void systick_config(void); } +void console_init(); void udelay_init(); void gd32_adc_init(); -Hardware *Hardware::s_pThis = nullptr; +#if defined (GD32H7XX) +void cache_enable(); +void mpu_config(); +#endif + +namespace hal { +void uuid_init(uuid_t out); +} // namespace hardware + +namespace net { +void net_shutdown(); +} // namespace net + +void timer6_config(); +#if !defined (CONFIG_ENET_ENABLE_PTP) +# if defined (CONFIG_TIME_USE_TIMER) +# if defined(GD32H7XX) +void timer16_config(); +# else +void timer7_config(); +# endif +# endif +#endif + +Hardware *Hardware::s_pThis; Hardware::Hardware() { - DEBUG_ENTRY assert(s_pThis == nullptr); s_pThis = this; - console_init(); -#if !defined (ENABLE_TFTP_SERVER) - __libc_init_array(); +#if defined (GD32H7XX) + cache_enable(); + mpu_config(); #endif + + console_init(); + timer6_config(); +#if defined (CONFIG_HAL_USE_SYSTICK) systick_config(); +#endif +#if !defined (CONFIG_ENET_ENABLE_PTP) +# if defined (CONFIG_TIME_USE_TIMER) +# if defined(GD32H7XX) + timer16_config(); +# else + timer7_config(); +# endif +# endif +#endif udelay_init(); + hal::uuid_init(m_uuid); gd32_adc_init(); gd32_i2c_begin(); rcu_periph_clock_enable(RCU_TIMER5); + timer_deinit(TIMER5); + timer_parameter_struct timer_initpara; + timer_struct_para_init(&timer_initpara); + timer_initpara.prescaler = TIMER_PSC_1MHZ; timer_initpara.period = static_cast(~0); timer_init(TIMER5, &timer_initpara); timer_enable(TIMER5); -#if !defined (GD32F4XX) -#else +#if defined (GD32H7XX) +#elif defined (GD32F4XX) rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4); +#else #endif #ifndef NDEBUG @@ -89,30 +141,45 @@ Hardware::Hardware() { const auto nAPB2 = rcu_clock_freq_get(CK_APB2); printf("CK_SYS=%u\nCK_AHB=%u\nCK_APB1=%u\nCK_APB2=%u\n", nSYS, nAHB, nAPB1, nAPB2); assert(nSYS == MCU_CLOCK_FREQ); + assert(nAHB == AHB_CLOCK_FREQ); assert(nAPB1 == APB1_CLOCK_FREQ); assert(nAPB2 == APB2_CLOCK_FREQ); +# if defined (GD32H7XX) + const auto nAPB3 = rcu_clock_freq_get(CK_APB3); + const auto nAPB4 = rcu_clock_freq_get(CK_APB4); + printf("nCK_APB3=%u\nCK_APB4=%u\n", nAPB3, nAPB4); + assert(nAPB3 == APB3_CLOCK_FREQ); + assert(nAPB4 == APB4_CLOCK_FREQ); +# endif #endif -#if !defined (GD32F4XX) - rcu_periph_clock_enable (RCU_BKPI); - rcu_periph_clock_enable (RCU_PMU); - pmu_backup_write_enable(); -#else +#if defined (GD32H7XX) + rcu_periph_clock_enable(RCU_PMU); + rcu_periph_clock_enable(RCU_BKPSRAM); + pmu_backup_write_enable(); +#elif defined (GD32F4XX) + rcu_periph_clock_enable(RCU_RTC); rcu_periph_clock_enable(RCU_PMU); pmu_backup_ldo_config(PMU_BLDOON_ON); rcu_periph_clock_enable(RCU_BKPSRAM); pmu_backup_write_enable(); +#else + rcu_periph_clock_enable (RCU_BKPI); + rcu_periph_clock_enable (RCU_PMU); + pmu_backup_write_enable(); #endif bkp_data_write(BKP_DATA_1, 0x0); #if !defined (ENABLE_TFTP_SERVER) -# if defined (GD32F207RG) || defined (GD32F4XX) +# if defined (GD32F207RG) || defined (GD32F4XX) || defined (GD32H7XX) +# if !defined (GD32H7XX) // clear section .dmx extern unsigned char _sdmx; extern unsigned char _edmx; DEBUG_PRINTF("clearing .dmx at %p, size %u", &_sdmx, &_edmx - &_sdmx); memset(&_sdmx, 0, &_edmx - &_sdmx); -# if defined (GD32F450VI) +# endif +# if defined (GD32F450VI) || defined (GD32H7XX) // clear section .lightset extern unsigned char _slightset; extern unsigned char _elightset; @@ -124,7 +191,7 @@ Hardware::Hardware() { extern unsigned char _enetwork; DEBUG_PRINTF("clearing .network at %p, size %u", &_snetwork, &_enetwork - &_snetwork); memset(&_snetwork, 0, &_enetwork - &_snetwork); -# if !defined (GD32F450VE) +# if !defined (GD32F450VE) && !defined (GD32H7XX) // clear section .pixel extern unsigned char _spixel; extern unsigned char _epixel; @@ -133,7 +200,7 @@ Hardware::Hardware() { # endif # endif #else -# if defined (GD32F207RG) || defined (GD32F4XX) +# if defined (GD32F20X) || defined (GD32F4XX) || defined (GD32H7XX) // clear section .network extern unsigned char _snetwork; extern unsigned char _enetwork; @@ -142,131 +209,81 @@ Hardware::Hardware() { # endif #endif +#if !defined (CONFIG_ENET_ENABLE_PTP) struct tm tmbuf; - - tmbuf.tm_hour = 0; - tmbuf.tm_min = 0; - tmbuf.tm_sec = 0; + memset(&tmbuf, 0, sizeof(struct tm)); tmbuf.tm_mday = _TIME_STAMP_DAY_; // The day of the month, in the range 1 to 31. tmbuf.tm_mon = _TIME_STAMP_MONTH_ - 1; // The number of months since January, in the range 0 to 11. tmbuf.tm_year = _TIME_STAMP_YEAR_ - 1900; // The number of years since 1900. - tmbuf.tm_isdst = 0; // 0 (DST not in effect, just take RTC time) const auto seconds = mktime(&tmbuf); const struct timeval tv = { seconds, 0 }; settimeofday(&tv, nullptr); - -#if defined (DEBUG_I2C) - I2cDetect i2cdetect; #endif #if !defined(DISABLE_RTC) m_HwClock.RtcProbe(); m_HwClock.Print(); +# if !defined (CONFIG_ENET_ENABLE_PTP) + // Set the System Clock from the Hardware Clock m_HwClock.HcToSys(); +# endif #endif -#if !defined(USE_LEDBLINK_BITBANGING595) +#if !defined(CONFIG_LEDBLINK_USE_PANELLED) rcu_periph_clock_enable(LED_BLINK_GPIO_CLK); -# if !defined (GD32F4XX) +# if defined (GPIO_INIT) gpio_init(LED_BLINK_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LED_BLINK_PIN); # else gpio_mode_set(LED_BLINK_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_BLINK_PIN); - gpio_output_options_set(LED_BLINK_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LED_BLINK_PIN); + gpio_output_options_set(LED_BLINK_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED, LED_BLINK_PIN); # endif - GPIO_BC(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; + GPIO_BOP(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; #endif -#if defined (LEDPANEL_595_CS_GPIOx) - rcu_periph_clock_enable(LEDPANEL_595_CS_RCU_GPIOx); -# if !defined (GD32F4XX) - gpio_init(LEDPANEL_595_CS_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LEDPANEL_595_CS_GPIO_PINx); +#if defined (PANELLED_595_CS_GPIOx) + rcu_periph_clock_enable(PANELLED_595_CS_RCU_GPIOx); +# if defined (GPIO_INIT) + gpio_init(PANELLED_595_CS_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, PANELLED_595_CS_GPIO_PINx); # else - gpio_mode_set(LEDPANEL_595_CS_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LEDPANEL_595_CS_GPIO_PINx); - gpio_output_options_set(LEDPANEL_595_CS_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LEDPANEL_595_CS_GPIO_PINx); + gpio_mode_set(PANELLED_595_CS_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, PANELLED_595_CS_GPIO_PINx); + gpio_output_options_set(PANELLED_595_CS_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED, PANELLED_595_CS_GPIO_PINx); # endif - GPIO_BOP(LEDPANEL_595_CS_GPIOx) = LEDPANEL_595_CS_GPIO_PINx; + GPIO_BOP(PANELLED_595_CS_GPIOx) = PANELLED_595_CS_GPIO_PINx; #endif + hal::panel_led_init(); + #if defined ENABLE_USB_HOST usb_init(); #endif - DEBUG_EXIT -} - -typedef union pcast32 { - uuid_t uuid; - uint32_t u32[4]; -} _pcast32; - -void Hardware::GetUuid(uuid_t out) { - _pcast32 cast; + logic_analyzer::init(); -#if !defined (GD32F4XX) - cast.u32[0] = *(volatile uint32_t*) (0x1FFFF7E8); - cast.u32[1] = *(volatile uint32_t*) (0x1FFFF7EC); - cast.u32[2] = *(volatile uint32_t*) (0x1FFFF7F0); -#else - cast.u32[0] = *(volatile uint32_t*) (0x1FFF7A10); - cast.u32[1] = *(volatile uint32_t*) (0x1FFF7A14); - cast.u32[2] = *(volatile uint32_t*) (0x1FFF7A18); +#if defined (DEBUG_I2C) + I2cDetect i2cdetect; #endif - cast.u32[3] = cast.u32[0] + cast.u32[1] + cast.u32[2]; - memcpy(out, cast.uuid, sizeof(uuid_t)); + SetFrequency(1U); } -bool Hardware::SetTime(__attribute__((unused)) const struct tm *pTime) { - DEBUG_ENTRY +bool Hardware::Reboot() { + puts("Rebooting ..."); + #if !defined(DISABLE_RTC) - rtc_time rtc_time; - - rtc_time.tm_sec = pTime->tm_sec; - rtc_time.tm_min = pTime->tm_min; - rtc_time.tm_hour = pTime->tm_hour; - rtc_time.tm_mday = pTime->tm_mday; - rtc_time.tm_mon = pTime->tm_mon; - rtc_time.tm_year = pTime->tm_year; - - m_HwClock.Set(&rtc_time); - - DEBUG_EXIT - return true; -#else - DEBUG_EXIT - return false; + m_HwClock.SysToHc(); #endif -} - -void Hardware::GetTime(struct tm *pTime) { - auto ltime = time(nullptr); - const auto *local_time = localtime(<ime); - pTime->tm_year = local_time->tm_year; - pTime->tm_mon = local_time->tm_mon; - pTime->tm_mday = local_time->tm_mday; - pTime->tm_hour = local_time->tm_hour; - pTime->tm_min = local_time->tm_min; - pTime->tm_sec = local_time->tm_sec; -} - -#include - -bool Hardware::Reboot() { - printf("Rebooting ...\n"); WatchdogStop(); - + RebootHandler(); - WatchdogInit(); + net::net_shutdown(); - SetMode(hardware::ledblink::Mode::REBOOT); + SetMode(hardware::ledblink::Mode::OFF_OFF); - for (;;) { - Run(); - } + NVIC_SystemReset(); __builtin_unreachable(); return true; diff --git a/lib-hal/src/hardware.cpp b/lib-hal/src/hardware.cpp index c25347ad..706f1853 100755 --- a/lib-hal/src/hardware.cpp +++ b/lib-hal/src/hardware.cpp @@ -2,7 +2,7 @@ * @file hardware.cpp * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,16 +28,15 @@ #include "hardware.h" #include "debug.h" -namespace hardware { -namespace ledblink { -void __attribute__((weak)) display(__attribute__((unused)) const uint32_t nState) {} -} // namespace ledblink -} // namespace hardware +namespace hardware::ledblink { +void __attribute__((weak)) display([[maybe_unused]] const uint32_t nState) {} +} // namespace hardware::ledblink enum class FreqMode { OFF_OFF = 0, NORMAL = 1, DATA = 3, FAST = 5, REBOOT = 8, OFF_ON = 255 }; +#if !defined (CONFIG_HAL_USE_MINIMUM) void Hardware::SetModeWithLock(hardware::ledblink::Mode mode, bool doLock) { m_doLock = false; SetMode(mode); @@ -79,3 +78,4 @@ void Hardware::SetMode(hardware::ledblink::Mode mode) { DEBUG_PRINTF("Mode=%d", static_cast(m_Mode)); } +#endif diff --git a/lib-hal/src/json_datetime.cpp b/lib-hal/src/json_datetime.cpp new file mode 100755 index 00000000..6b07ae64 --- /dev/null +++ b/lib-hal/src/json_datetime.cpp @@ -0,0 +1,125 @@ +/** + * @file json_datetime.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include "configstore.h" + +#include "debug.h" + +namespace remoteconfig { +namespace timedate { +static int atoi(const char *pBuffer, uint32_t nSize) { + assert(pBuffer != nullptr); + assert(nSize <= 4); + + const char *p = pBuffer; + int32_t res = 0; + + for (; (nSize > 0) && (*p >= '0' && *p <= '9'); nSize--) { + res = res * 10 + *p - '0'; + p++; + } + + return res; +} + +uint32_t json_get_timeofday(char *pOutBuffer, const uint32_t nOutBufferSize) { + DEBUG_ENTRY + + struct timeval tv; + if (gettimeofday(&tv, nullptr) >= 0) { + auto *tm = localtime(&tv.tv_sec); + + int8_t nHours; + uint8_t nMinutes; + ConfigStore::Get()->GetEnvUtcOffset(nHours, nMinutes); + + if ((nHours == 0) && (nMinutes == 0)) { + const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, + "{\"date\":\"%d-%.2d-%.2dT%.2d:%.2d:%.2dZ\"}\n", + 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec)); + + DEBUG_EXIT + return nLength; + } else { + const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, + "{\"date\":\"%d-%.2d-%.2dT%.2d:%.2d:%.2d%s%.2d:%.2u\"}\n", + 1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, + nHours > 0 ? "+" : "", nHours, nMinutes)); + + DEBUG_EXIT + return nLength; + } + } + + DEBUG_EXIT + return 0; +} + +void json_set_timeofday(const char *pBuffer, const uint32_t nBufferSize) { + DEBUG_ENTRY + debug_dump(pBuffer, nBufferSize); + + if ((nBufferSize == 26) || (nBufferSize == 31)) { + struct tm tm; + tm.tm_year = atoi(&pBuffer[5], 4) - 1900; + tm.tm_mon = atoi(&pBuffer[10], 2) - 1; + tm.tm_mday = atoi(&pBuffer[13], 2); + tm.tm_hour = atoi(&pBuffer[16], 2); + tm.tm_min = atoi(&pBuffer[19], 2); + tm.tm_sec = atoi(&pBuffer[22], 2); + + struct timeval tv; + tv.tv_sec = mktime(&tm); + tv.tv_usec = 0; + + if (nBufferSize == 26) { + assert(pBuffer[23] == 'Z'); + } else { + const int8_t nSign = pBuffer[24] == '-' ? -1 : 1; + const auto nHours = static_cast(atoi(&pBuffer[25], 2) * nSign); + const auto nMinutes = static_cast(atoi(&pBuffer[28], 2)); + + ConfigStore::Get()->SetEnvUtcOffset(nHours, nMinutes); + + tv.tv_sec = tv.tv_sec - ConfigStore::Get()->GetEnvUtcOffset(); + } + + settimeofday(&tv, nullptr); + + DEBUG_PRINTF("%.4d/%.2d/%.2d %.2d:%.2d:%.2d", 1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); + DEBUG_EXIT + return; + } + + DEBUG_EXIT +} +} // namespace timedate +} // namespace remoteconfig diff --git a/lib-hal/src/json_get_directory.cpp b/lib-hal/src/json_get_directory.cpp new file mode 100755 index 00000000..67ae9b88 --- /dev/null +++ b/lib-hal/src/json_get_directory.cpp @@ -0,0 +1,96 @@ +/** + * @file json_get_directory.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include +#ifndef NDEBUG +# include +#endif + +namespace remoteconfig { +namespace storage { +static bool filter(const char *pName) { + return *pName == '.'; +} + +uint32_t json_get_directory(char *pOutBuffer, const uint32_t nOutBufferSize) { + const auto nBufferSize = nOutBufferSize - 2U; +#if defined (__linux__) || defined (__APPLE__) + auto *dirp = opendir("storage"); +#elif defined (CONFIG_USB_HOST_MSC) + auto *dirp = opendir("0:/"); +#else + auto *dirp = opendir("."); +#endif +#ifndef NDEBUG + perror("opendir"); +#endif + + auto nLength = static_cast(snprintf(pOutBuffer, nBufferSize, "{\"label\":\"%s\",\"files\":[", (dirp != nullptr) ? "storage" : "No storage")); + + if (dirp != nullptr) { + struct dirent *dp; + do { + if ((dp = readdir(dirp)) != nullptr) { + if (dp->d_type == DT_DIR) { + continue; + } + + if (filter(dp->d_name)) { + continue; + } + + const auto nSize = nBufferSize - nLength; + const auto nCharacters = static_cast(snprintf(&pOutBuffer[nLength], nSize, "\"%s\",", dp->d_name)); + + if (nCharacters > nSize) { + break; + } + + nLength+=nCharacters; + + if (nLength >= nBufferSize) { + break; + } + } + } while (dp != nullptr); + + closedir(dirp); + + if (pOutBuffer[nLength - 1] == ',') { + nLength--; + } + } + + pOutBuffer[nLength++] = ']'; + pOutBuffer[nLength++] = '}'; + + assert(nLength <= nOutBufferSize); + return nLength; +} +} // namespace storage +} // namespace remoteconfig diff --git a/lib-lightset/.cproject b/lib-lightset/.cproject index 7710fa78..0eb196bf 100644 --- a/lib-lightset/.cproject +++ b/lib-lightset/.cproject @@ -30,12 +30,10 @@ - diff --git a/lib-lightset/Rules.mk b/lib-lightset/Rules.mk index a36ce7e5..5922504e 100644 --- a/lib-lightset/Rules.mk +++ b/lib-lightset/Rules.mk @@ -1,10 +1,4 @@ ifneq ($(MAKE_FLAGS),) - ifeq ($(findstring ESP8266,$(MAKE_FLAGS)), ESP8266) - EXTRA_SRCDIR+=src/esp8266 - endif else DEFINES+=OUTPUT_HAVE_STYLESWITCH - DEFINES+=LIGHTSET_HAVE_RUN - DEFINES+=ESP8266 - EXTRA_SRCDIR+=src/esp8266 endif \ No newline at end of file diff --git a/lib-lightset/include/lightset.h b/lib-lightset/include/lightset.h index 04f7598c..28a72272 100755 --- a/lib-lightset/include/lightset.h +++ b/lib-lightset/include/lightset.h @@ -2,7 +2,7 @@ * @file lightset.h * */ -/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -43,7 +43,7 @@ namespace node { static constexpr uint32_t LABEL_NAME_LENGTH = 18; inline void get_short_name_default(const uint32_t nPortIndex, char *pShortName) { - snprintf(pShortName, node::LABEL_NAME_LENGTH - 1, "Port %u", 1U + nPortIndex); + snprintf(pShortName, node::LABEL_NAME_LENGTH - 1, "Port %u", static_cast(1 + nPortIndex)); } } // namespace node @@ -68,12 +68,6 @@ struct SlotInfo { uint8_t nType; }; -#if defined (ESP8266) -enum class OutputType { - DMX, SPI, MONITOR, UNDEFINED -}; -#endif - inline MergeMode get_merge_mode(const char *pMergeMode) { if (pMergeMode != nullptr) { if (((pMergeMode[0] | 0x20) == 'l') @@ -85,14 +79,14 @@ inline MergeMode get_merge_mode(const char *pMergeMode) { return MergeMode::HTP; } -inline const char* get_merge_mode(const MergeMode mergeMode, const bool bToUpper = false) { +inline const char *get_merge_mode(const MergeMode mergeMode, const bool bToUpper = false) { if (bToUpper) { return (mergeMode == MergeMode::HTP) ? "HTP" : "LTP"; } return (mergeMode == MergeMode::HTP) ? "htp" : "ltp"; } -inline const char* get_merge_mode(const unsigned m, const bool bToUpper = false) { +inline const char *get_merge_mode(const unsigned m, const bool bToUpper = false) { return get_merge_mode(static_cast(m), bToUpper); } @@ -151,27 +145,15 @@ inline FailSafe get_failsafe(const char *pFailSafe) { } inline const char* get_failsafe(const FailSafe failsafe) { - switch (failsafe) { - case FailSafe::HOLD: - return "hold"; - break; - case FailSafe::OFF: + if (failsafe == FailSafe::OFF) { return "off"; - break; - case FailSafe::ON: + } else if (failsafe == FailSafe::ON) { return "on"; - break; - case FailSafe::PLAYBACK: + } else if (failsafe == FailSafe::PLAYBACK) { return "playback"; - break; - default: - assert(0); - __builtin_unreachable(); - break; } - __builtin_unreachable(); - return ""; + return "hold"; } inline OutputStyle get_output_style(const char *pOutputStyle) { @@ -203,38 +185,38 @@ class LightSet { virtual void Start(const uint32_t nPortIndex)= 0; virtual void Stop(const uint32_t nPortIndex)= 0; - virtual void SetData(uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate = true)= 0; + virtual void SetData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate = true)= 0; /** * This is used for preparing the lightset output for a SYNC * Typically used with DMX512 output * @param [IN] PortIndex */ virtual void Sync(const uint32_t PortIndex)= 0; - /** - * - * @param [IN] doForce This parameter is used with Art-Net ArtSync only. - */ - virtual void Sync(const bool doForce = false)= 0; + virtual void Sync()= 0; #if defined (OUTPUT_HAVE_STYLESWITCH) virtual void SetOutputStyle(const uint32_t nPortIndex, const lightset::OutputStyle outputStyle)=0; virtual lightset::OutputStyle GetOutputStyle(const uint32_t nPortIndex) const=0; #endif // Optional - virtual void Blackout(__attribute__((unused)) bool bBlackout) {} + virtual uint32_t GetRefreshRate() { return 0; } + virtual void Blackout([[maybe_unused]] bool bBlackout) {} virtual void FullOn() {} virtual void Print() {} // RDM Optional - virtual bool SetDmxStartAddress(uint16_t nDmxStartAddress); - virtual uint16_t GetDmxStartAddress(); - virtual uint16_t GetDmxFootprint(); - virtual bool GetSlotInfo(uint16_t nSlotOffset, lightset::SlotInfo &tSlotInfo); -#if defined (LIGHTSET_HAVE_RUN) - virtual void Run()= 0; -#endif -#if defined (ESP8266) - static const char *GetOutputType(lightset::OutputType type); - static lightset::OutputType GetOutputType(const char *sType); -#endif + virtual bool SetDmxStartAddress([[maybe_unused]] const uint16_t nDmxStartAddress) { + return false; + } + virtual uint16_t GetDmxStartAddress() { + return lightset::dmx::START_ADDRESS_DEFAULT; + } + virtual uint16_t GetDmxFootprint() { + return lightset::dmx::UNIVERSE_SIZE; + } + virtual bool GetSlotInfo([[maybe_unused]] const uint16_t nSlotOffset, lightset::SlotInfo &slotInfo) { + slotInfo.nType = 0x00; // ST_PRIMARY + slotInfo.nCategory = 0x0001; // SD_INTENSITY + return true; + } }; #endif /* LIGHTSET_H_ */ diff --git a/lib-lightset/include/lightsetdata.h b/lib-lightset/include/lightsetdata.h old mode 100644 new mode 100755 index 95f74647..b55a29da --- a/lib-lightset/include/lightsetdata.h +++ b/lib-lightset/include/lightsetdata.h @@ -2,7 +2,7 @@ * @file lightsetdata.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,7 +38,7 @@ * https://www.gd32-dmx.org/memory.html */ # include "gd32.h" -# if defined (GD32F450VI) +# if defined (GD32F450VI) || defined (GD32H7XX) # define SECTION_LIGHTSET __attribute__ ((section (".lightset"))) # else # define SECTION_LIGHTSET @@ -50,7 +50,7 @@ namespace lightset { class Data { public: - Data(const Data&) = delete; +// Data(const Data&) = delete; static Data& Get() { static Data instance SECTION_LIGHTSET; @@ -89,6 +89,10 @@ class Data { Get().IClearLength(nPortIndex); } + static uint32_t GetLength(const uint32_t nPortIndex) { + return Get().IGetLength(nPortIndex); + } + static const uint8_t *Backup(const uint32_t nPortIndex) { return Get().IBackup(nPortIndex); } @@ -98,7 +102,7 @@ class Data { } private: - Data() {} +// Data() {} void IMergeSourceA(const uint32_t nPortIndex, const uint8_t *pData, const uint32_t nLength, const MergeMode mergeMode) { assert(nPortIndex < PORTS); @@ -169,6 +173,10 @@ class Data { m_OutputPort[nPortIndex].nLength = 0; } + uint32_t IGetLength(const uint32_t nPortIndex) const { + return m_OutputPort[nPortIndex].nLength; + } + const uint8_t *IBackup(const uint32_t nPortIndex) { assert(nPortIndex < PORTS); return const_cast(m_OutputPort[nPortIndex].data); @@ -193,13 +201,13 @@ class Data { #endif struct Source { - uint8_t data[dmx::UNIVERSE_SIZE]; + uint8_t data[dmx::UNIVERSE_SIZE] __attribute__ ((aligned (4))); }; struct OutputPort { Source sourceA; Source sourceB; - uint8_t data[dmx::UNIVERSE_SIZE]; + uint8_t data[dmx::UNIVERSE_SIZE] __attribute__ ((aligned (4))); uint32_t nLength; }; diff --git a/lib-lightset/src/dmxslotinfo.cpp b/lib-lightset/src/dmxslotinfo.cpp index c5dc365a..b12e1a20 100644 --- a/lib-lightset/src/dmxslotinfo.cpp +++ b/lib-lightset/src/dmxslotinfo.cpp @@ -2,7 +2,7 @@ * @file dmxslotinfo.h * */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -140,7 +140,7 @@ const char *DmxSlotInfo::ToString(uint32_t nMask) { void DmxSlotInfo::Dump() { for (uint32_t i = 0; i < m_nSize; i++) { - printf(" Slot:%d %.2X:%.4X\n", i, m_pSlotInfo[i].nType, m_pSlotInfo[i].nCategory); + printf(" Slot:%u %.2X:%.4X\n", static_cast(i), m_pSlotInfo[i].nType, m_pSlotInfo[i].nCategory); } } diff --git a/lib-network/.cproject b/lib-network/.cproject index 5e671f68..43ab5ac3 100644 --- a/lib-network/.cproject +++ b/lib-network/.cproject @@ -30,11 +30,9 @@ - diff --git a/lib-network/Makefile.GD32 b/lib-network/Makefile.GD32 index aaed2317..161f1c6b 100644 --- a/lib-network/Makefile.GD32 +++ b/lib-network/Makefile.GD32 @@ -1,15 +1,41 @@ -DEFINES =DISABLE_FS +$(info "lib-network/Makefile.GD32") + +DEFINES =DISABLE_FS DEFINES+=NDEBUG -EXTRA_INCLUDES=../lib-properties/include +EXTRA_INCLUDES=../lib-properties/include ../lib-display/include EXTRA_SRCDIR=src/emac/gd32 -ifeq ($(findstring RTL8201F,$(PHY_TYPE)), RTL8201F) - EXTRA_SRCDIR+=src/emac/gd32/rtl8201f - DEFINES+=RTL8201F_LED1_LINK_ALL - DEFINES+=ENET_LINK_CHECK_USE_INT +ifneq ($(MAKE_FLAGS),) + ifeq ($(findstring gd32f10x,$(FAMILY)), gd32f10x) + EXTRA_SRCDIR+=src/emac/gd32/f + endif + ifeq ($(findstring gd32f20x,$(FAMILY)), gd32f20x) + EXTRA_SRCDIR+=src/emac/gd32/f + endif + ifeq ($(findstring gd32f4xx,$(FAMILY)), gd32f4xx) + EXTRA_SRCDIR+=src/emac/gd32/f + endif + ifeq ($(findstring gd32h7xx,$(FAMILY)), gd32h7xx) + EXTRA_SRCDIR+=src/emac/gd32/h + endif + + ifeq ($(findstring RTL8201F,$(MAKE_FLAGS)), RTL8201F) + EXTRA_SRCDIR+=src/emac/gd32/rtl8201f + endif + + ifeq ($(findstring ENABLE_PHY_SWITCH,$(MAKE_FLAGS)), ENABLE_PHY_SWITCH) + EXTRA_SRCDIR+=src/emac/gd32/dsa/88e6161 + endif + + ifeq ($(findstring CONFIG_ENET_ENABLE_PTP,$(MAKE_FLAGS)), CONFIG_ENET_ENABLE_PTP) + ifeq ($(findstring ENABLE_NTP_PTP_CLIENT,$(MAKE_FLAGS)), ENABLE_NTP_PTP_CLIENT) + EXTRA_SRCDIR+=src/net/apps/ntp/gd32/ptp + endif + endif else - #DEFINES+=ENET_LINK_CHECK_REG_POLL + EXTRA_SRCDIR+=src/emac/gd32/f + ENET_PHY=RTL8201F endif include Rules.mk diff --git a/lib-network/Rules.mk b/lib-network/Rules.mk index 069b63b0..15e929df 100644 --- a/lib-network/Rules.mk +++ b/lib-network/Rules.mk @@ -15,9 +15,9 @@ ifneq ($(MAKE_FLAGS),) endif endif ifndef COND - EXTRA_SRCDIR+=src/apps/mdns src/apps/ntp src/apps/tftp - EXTRA_SRCDIR+=src/emac src/params src/net - EXTRA_SRCDIR+=src/emac/phy + EXTRA_SRCDIR+=src/net/apps/mdns src/net/apps/ntp src/net/apps/tftp + EXTRA_SRCDIR+=src/emac src/net src/emac/phy + EXTRA_SRCDIR+=src/params ifeq ($(findstring ENABLE_PHY_SWITCH,$(MAKE_FLAGS)), ENABLE_PHY_SWITCH) EXTRA_SRCDIR+=src/emac/dsa endif @@ -39,9 +39,10 @@ ifneq ($(MAKE_FLAGS),) endif endif else - EXTRA_SRCDIR+=src/apps/mdns src/apps/ntp src/apps/tftp + EXTRA_SRCDIR+=src/net/apps/mdns src/net/apps/ntp src/net/apps/tftp EXTRA_SRCDIR+=src/emac src/net EXTRA_SRCDIR+=src/emac/phy EXTRA_SRCDIR+=src/emac/phy/dp83848 src/emac/phy/lan8700 src/emac/phy/phygen src/emac/phy/rtl8201f + EXTRA_SRCDIR+=src/params DEFINES+=RTL8201F_LED1_LINK_ALL endif diff --git a/lib-network/config/apps_config.h b/lib-network/config/apps_config.h index d2bc3a38..3e82f26e 100644 --- a/lib-network/config/apps_config.h +++ b/lib-network/config/apps_config.h @@ -2,7 +2,7 @@ * @file apps_config * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,7 +26,9 @@ #ifndef APPS_CONFIG_H_ #define APPS_CONFIG_H_ -#if defined (BARE_METAL) +#if defined(__linux__) || defined (__APPLE__) +# define MDNS_SERVICE_RECORDS_MAX 8 +#else # if defined (H3) # define MDNS_SERVICE_RECORDS_MAX 8 # elif defined (GD32) @@ -36,8 +38,6 @@ # else # error # endif -#else -# define MDNS_SERVICE_RECORDS_MAX 8 #endif #if !defined (MDNS_SERVICE_RECORDS_MAX) diff --git a/lib-network/config/net_config.h b/lib-network/config/net_config.h index 550dd2df..96ce794a 100644 --- a/lib-network/config/net_config.h +++ b/lib-network/config/net_config.h @@ -2,7 +2,7 @@ * @file net_config * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,26 +26,40 @@ #ifndef NET_CONFIG_H_ #define NET_CONFIG_H_ -#if defined (BARE_METAL) -# define TCP_MAX_PORTS_ALLOWED 1 +#if defined(__linux__) || defined (__APPLE__) +# define UDP_MAX_PORTS_ALLOWED 16 +# define IGMP_MAX_JOINS_ALLOWED (4 + (8 * 4)) /* 8 outputs x 4 Universes */ +# define TCP_MAX_TCBS_ALLOWED 16 +# define TCP_MAX_PORTS_ALLOWED 2 +#else +# define TCP_MAX_PORTS_ALLOWED 1 # if defined (H3) -# define HOST_NAME_PREFIX "allwinner_" +# if !defined(HOST_NAME_PREFIX) +# define HOST_NAME_PREFIX "allwinner_" +# endif # define UDP_MAX_PORTS_ALLOWED 16 # define IGMP_MAX_JOINS_ALLOWED (4 + (8 * 4)) /* 8 outputs x 4 Universes */ +# define TCP_MAX_TCBS_ALLOWED 16 # elif defined (GD32) +/* + * Supports checking IPv4 header checksum and TCP, UDP, or ICMP checksum encapsulated in IPv4 or IPv6 datagram. + */ # define CHECKSUM_BY_HARDWARE -# define HOST_NAME_PREFIX "gigadevice_" +# if !defined(HOST_NAME_PREFIX) +# define HOST_NAME_PREFIX "gigadevice_" +# endif # if !defined (UDP_MAX_PORTS_ALLOWED) # define UDP_MAX_PORTS_ALLOWED 8 # endif # if !defined (IGMP_MAX_JOINS_ALLOWED) # define IGMP_MAX_JOINS_ALLOWED (4 + (8 * 4)) /* 8 outputs x 4 Universes */ # endif +# if !defined (TCP_MAX_TCBS_ALLOWED) +# define TCP_MAX_TCBS_ALLOWED 6 +# endif # else # error # endif -#else -# error #endif #if !defined (UDP_MAX_PORTS_ALLOWED) @@ -60,4 +74,8 @@ # error #endif +#if !defined (TCP_MAX_TCBS_ALLOWED) +# error +#endif + #endif /* NET_CONFIG_H_ */ diff --git a/lib-network/include/emac/emac.h b/lib-network/include/emac/emac.h index dbb8597a..61eb20e7 100755 --- a/lib-network/include/emac/emac.h +++ b/lib-network/include/emac/emac.h @@ -1,5 +1,26 @@ -/* - * emac.h +/** + * @file emac.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. */ #ifndef EMAC_EMAC_H_ diff --git a/lib-network/include/emac/network.h b/lib-network/include/emac/network.h index 0e946b21..ffd368ae 100755 --- a/lib-network/include/emac/network.h +++ b/lib-network/include/emac/network.h @@ -2,7 +2,7 @@ * @file network.h * */ -/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,6 +30,17 @@ # error This file should not be included #endif +#if !defined (HAVE_NET_HANDLE) +# define HAVE_NET_HANDLE +#endif + +namespace net { +void dhcp_run(); +#if defined (CONFIG_ENET_ENABLE_PTP) +void ptp_run(); +#endif +} // namespace net + #include #include #include @@ -37,7 +48,10 @@ #include "networkparams.h" -#include "../src/net/net.h" +#include "net.h" +#include "netif.h" +#include "ip4_address.h" +#include "net/dhcp.h" #include "emac/net_link_check.h" @@ -45,42 +59,36 @@ class Network { public: - Network(NetworkParamsStore *pNetworkParamsStore); - ~Network() {} + Network(); + ~Network() = default; void Print(); - void Shutdown() { - network::display_emac_shutdown(); - network::mdns_shutdown(); - net_shutdown(); - } - void MacAddressCopyTo(uint8_t *pMacAddress) { - memcpy(pMacAddress, m_aNetMacaddr, network::MAC_SIZE); + memcpy(pMacAddress, net::netif_hwaddr(), NETIF_MAX_HWADDR_LEN); } - uint32_t GetSecondaryIp() const { - return m_IpInfo.secondary_ip.addr; + uint32_t GetSecondaryIp() { + return net::netif_secondary_ipaddr(); } void SetIp(uint32_t nIp); - uint32_t GetIp() const { - return m_IpInfo.ip.addr; + uint32_t GetIp() { + return net::netif_ipaddr(); } void SetNetmask(uint32_t nNetmask); - uint32_t GetNetmask() const { - return m_IpInfo.netmask.addr; + uint32_t GetNetmask() { + return net::netif_netmask(); } void SetGatewayIp(uint32_t nGatewayIp); - uint32_t GetGatewayIp() const { - return m_IpInfo.gw.addr; + uint32_t GetGatewayIp() { + return net::netif_gw(); } - uint32_t GetBroadcastIp() const { - return m_IpInfo.broadcast_ip.addr; + uint32_t GetBroadcastIp() { + return net::netif_broadcast_ipaddr(); } /* @@ -91,18 +99,19 @@ class Network { return m_IsDhcpCapable; } - bool EnableDhcp(); + void EnableDhcp(); - bool IsDhcpUsed() const { - return m_IsDhcpUsed; + bool IsDhcpUsed() { + const auto b = net::netif_dhcp(); + return b; } bool IsDhcpKnown() const { return true; } - network::dhcp::Mode GetDhcpMode() const { - if (m_IsDhcpUsed) { + network::dhcp::Mode GetDhcpMode() { + if (IsDhcpUsed()) { return network::dhcp::Mode::ACTIVE; } @@ -110,22 +119,31 @@ class Network { } /* - * Zeroconf + * Zeroconf / autoip */ + void SetZeroconf(); + bool IsZeroconfUsed() const { + return net::netif_autoip(); + } + bool IsZeroconfCapable() const { return m_IsZeroconfCapable; } - bool SetZeroconf(); - bool IsZeroconfUsed() const { - return m_IsZeroconfUsed; - } + + /* + * Host name + */ void SetHostName(const char *pHostName); const char *GetHostName() const { return m_aHostName; } + /* + * Domain name + */ + void SetDomainName(const char *pDomainName) { strncpy(m_aDomainName, pDomainName, network::DOMAINNAME_SIZE - 1); m_aDomainName[network::DOMAINNAME_SIZE - 1] = '\0'; @@ -134,32 +152,62 @@ class Network { return m_aDomainName; } + /* + * Name servers + */ + + uint32_t GetNameServer(const uint32_t nIndex) const { + if (nIndex < network::NAMESERVERS_COUNT) { + return m_nNameservers[nIndex]; + } + + return 0; + } + + uint32_t GetNameServers() const { + return network::NAMESERVERS_COUNT; + } + + const char *GetIfName() const { + return m_aIfName; + } + + uint32_t GetIfIndex() const { + return 1; + } + /* * UDP/IP */ int32_t Begin(uint16_t nPort) { - const auto nIndex = udp_begin(nPort); + const auto nIndex = net::udp_begin(nPort); assert(nIndex != -1); return nIndex; } int32_t End(uint16_t nPort) { - const auto nIndex = udp_end(nPort); + const auto nIndex = net::udp_end(nPort); assert(nIndex == 0); return nIndex; } - uint16_t RecvFrom(int32_t nHandle, void *pBuffer, uint16_t nLength, uint32_t *from_ip, uint16_t *from_port) { - return udp_recv1(nHandle, reinterpret_cast(pBuffer), nLength, from_ip, from_port); + uint32_t RecvFrom(int32_t nHandle, void *pBuffer, uint32_t nLength, uint32_t *from_ip, uint16_t *from_port) { + return net::udp_recv1(nHandle, reinterpret_cast(pBuffer), nLength, from_ip, from_port); } - uint16_t RecvFrom(int32_t nHandle, const void **ppBuffer, uint32_t *pFromIp, uint16_t *pFromPort) { - return udp_recv2(nHandle, reinterpret_cast(ppBuffer), pFromIp, pFromPort); + uint32_t RecvFrom(int32_t nHandle, const void **ppBuffer, uint32_t *pFromIp, uint16_t *pFromPort) { + return net::udp_recv2(nHandle, reinterpret_cast(ppBuffer), pFromIp, pFromPort); } - void SendTo(int32_t nHandle, const void *pBuffer, uint16_t nLength, uint32_t to_ip, uint16_t remote_port) { - udp_send(nHandle, reinterpret_cast(pBuffer), nLength, to_ip, remote_port); + void SendTo(int32_t nHandle, const void *pBuffer, uint32_t nLength, uint32_t to_ip, uint16_t remote_port) { + if (__builtin_expect((GetIp() != 0), 1)) { + net::udp_send(nHandle, reinterpret_cast(pBuffer), nLength, to_ip, remote_port); + } + } + + void SendToTimestamp(int32_t nHandle, const void *pBuffer, uint32_t nLength, uint32_t to_ip, uint16_t remote_port) { + net::udp_send_timestamp(nHandle, reinterpret_cast(pBuffer), nLength, to_ip, remote_port); } /* @@ -167,33 +215,35 @@ class Network { */ int32_t TcpBegin(const uint16_t nLocalPort) { - return tcp_begin(nLocalPort); + return net::tcp_begin(nLocalPort); } int32_t TcpEnd(const int32_t nHandle); uint16_t TcpRead(const int32_t nHandleListen, const uint8_t **ppBuffer, uint32_t &HandleConnection) { - return tcp_read(nHandleListen, ppBuffer, HandleConnection); + return net::tcp_read(nHandleListen, ppBuffer, HandleConnection); } - void TcpWrite(const int32_t nHandleListen, const uint8_t *pBuffer, uint16_t nLength, const uint32_t HandleConnection) { - tcp_write(nHandleListen, pBuffer, nLength, HandleConnection); + void TcpWrite(const int32_t nHandleListen, const uint8_t *pBuffer, uint32_t nLength, const uint32_t HandleConnection) { + net::tcp_write(nHandleListen, pBuffer, nLength, HandleConnection); } /* * IGMP */ - void JoinGroup(__attribute__((unused)) int32_t nHandle, uint32_t nIp) { - igmp_join(nIp); + void JoinGroup([[maybe_unused]] int32_t nHandle, uint32_t nIp) { + net::igmp_join(nIp); } - void LeaveGroup(__attribute__((unused)) int32_t nHandle, uint32_t nIp) { - igmp_leave(nIp); + void LeaveGroup([[maybe_unused]] int32_t nHandle, uint32_t nIp) { + net::igmp_leave(nIp); } - void SetQueuedStaticIp(uint32_t nLocalIp = 0, uint32_t nNetmask = 0); - void SetQueuedDhcp() { + void SetQueuedStaticIp(const uint32_t nStaticIp, const uint32_t nNetmask); + void SetQueuedDefaultRoute(const uint32_t nGatewayIp); + void SetQueuedDhcp(const network::dhcp::Mode mode) { + m_QueuedConfig.mode = mode; m_QueuedConfig.nMask |= QueuedConfig::DHCP; } void SetQueuedZeroconf() { @@ -202,15 +252,15 @@ class Network { bool ApplyQueuedConfig(); - uint32_t GetNetmaskCIDR() const { - return static_cast(__builtin_popcount(m_IpInfo.netmask.addr)); + uint32_t GetNetmaskCIDR() { + return static_cast(__builtin_popcount(GetNetmask())); } char GetAddressingMode() { - if (Network::Get()->IsZeroconfUsed()) { + if (IsZeroconfUsed()) { return 'Z'; - } else if (Network::Get()->IsDhcpKnown()) { - if (Network::Get()->IsDhcpUsed()) { + } else if (IsDhcpKnown()) { + if (IsDhcpUsed()) { return 'D'; } else { return 'S'; @@ -220,28 +270,15 @@ class Network { return 'U'; } - const char *GetIfName() const { - return m_aIfName; - } - - uint32_t GetIfIndex() const { - return m_nIfIndex; - } - - uint32_t GetNtpServerIp() const { - return m_nNtpServerIp; - } - - float GetNtpUtcOffset() const { - return m_fNtpUtcOffset; - } - - bool IsValidIp(uint32_t nIp) { - return (m_IpInfo.ip.addr & m_IpInfo.netmask.addr) == (nIp & m_IpInfo.netmask.addr); + bool IsValidIp(const uint32_t nIp) { + return (GetIp() & GetNetmask()) == (nIp & GetNetmask()); } void Run() { - net_handle(); + net::net_handle(); +#if defined (CONFIG_ENET_ENABLE_PTP) + net::ptp_run(); +#endif #if defined (ENET_LINK_CHECK_USE_PIN_POLL) net::link_pin_poll(); #elif defined (ENET_LINK_CHECK_REG_POLL) @@ -252,6 +289,7 @@ class Network { net::link_handle_change(link_state); } #endif + net::dhcp_run(); } static Network *Get() { @@ -261,31 +299,25 @@ class Network { private: net::Link s_lastState { net::Link::STATE_DOWN }; bool m_IsDhcpCapable { true }; - bool m_IsDhcpUsed { false }; bool m_IsZeroconfCapable { true }; - bool m_IsZeroconfUsed { false }; - uint32_t m_nIfIndex { 1 }; - uint32_t m_nNtpServerIp { 0 }; - float m_fNtpUtcOffset { 0 }; - - struct IpInfo m_IpInfo; + char m_aIfName[IFNAMSIZ]; char m_aHostName[network::HOSTNAME_SIZE]; char m_aDomainName[network::DOMAINNAME_SIZE]; - uint8_t m_aNetMacaddr[network::MAC_SIZE]; - char m_aIfName[IFNAMSIZ]; - - NetworkStore *m_pNetworkStore { nullptr }; + uint32_t m_nNameservers[network::NAMESERVERS_COUNT]; struct QueuedConfig { static constexpr uint32_t NONE = 0; static constexpr uint32_t STATIC_IP = (1U << 0); - static constexpr uint32_t NET_MASK = (1U << 1); - static constexpr uint32_t DHCP = (1U << 2); - static constexpr uint32_t ZEROCONF = (1U << 3); + static constexpr uint32_t NETMASK = (1U << 1); + static constexpr uint32_t GW = (1U << 2); + static constexpr uint32_t DHCP = (1U << 3); + static constexpr uint32_t ZEROCONF = (1U << 4); uint32_t nMask = QueuedConfig::NONE; - uint32_t nLocalIp = 0; - uint32_t nNetmask = 0; + uint32_t nStaticIp; + uint32_t nNetmask; + uint32_t nGateway; + network::dhcp::Mode mode; }; QueuedConfig m_QueuedConfig; diff --git a/lib-network/include/emac/phy.h b/lib-network/include/emac/phy.h index ddae0832..63a8351c 100755 --- a/lib-network/include/emac/phy.h +++ b/lib-network/include/emac/phy.h @@ -2,7 +2,7 @@ * @file phy.h * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,7 +30,7 @@ namespace net { enum class Link { - STATE_UP, STATE_DOWN + STATE_DOWN, STATE_UP }; enum class Duplex { @@ -59,6 +59,7 @@ struct PhyIdentifier { */ bool phy_get_id(const uint32_t nAddress, PhyIdentifier& phyIdentifier); +Link phy_get_link(const uint32_t nAddress); /** * diff --git a/lib-lightset/src/lightsetdmx.cpp b/lib-network/include/emac/phy/rtl8201f.h old mode 100644 new mode 100755 similarity index 73% rename from lib-lightset/src/lightsetdmx.cpp rename to lib-network/include/emac/phy/rtl8201f.h index f2e54ee9..eaef1a2e --- a/lib-lightset/src/lightsetdmx.cpp +++ b/lib-network/include/emac/phy/rtl8201f.h @@ -1,8 +1,8 @@ /** - * @file lightset.cpp + * @file rtl8201f.h * */ -/* Copyright (C) 2016-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,20 +23,15 @@ * THE SOFTWARE. */ -#include - -#include "lightset.h" +#ifndef EMAC_PHY_RTL8201F_H_ +#define EMAC_PHY_RTL8201F_H_ -using namespace lightset; - -uint16_t LightSet::GetDmxStartAddress() { - return dmx::START_ADDRESS_DEFAULT; -} +#include -uint16_t LightSet::GetDmxFootprint() { - return dmx::UNIVERSE_SIZE; -} +namespace net::phy { +void rtl8201f_set_rxtiming(const uint32_t nRxTiming); +void rtl8201f_set_txtiming(const uint32_t nTxTiming); +void rtl8201f_get_timings(uint32_t& nRxTiming, uint32_t& nTxTiming); +} // namespace net::phy -bool LightSet::SetDmxStartAddress(__attribute__((unused)) uint16_t nDmxStartAddress) { - return false; -} +#endif /* EMAC_PHY_RTL8201F_H_ */ diff --git a/lib-network/include/ip4_address.h b/lib-network/include/ip4_address.h new file mode 100755 index 00000000..1ba355bd --- /dev/null +++ b/lib-network/include/ip4_address.h @@ -0,0 +1,79 @@ +/* + * ip4_address.h + */ + +#ifndef IP4_ADDRESS_H_ +#define IP4_ADDRESS_H_ + +#include + +#define IP2STR(addr) static_cast(addr & 0xFF), static_cast((addr >> 8) & 0xFF), static_cast((addr >> 16) & 0xFF), static_cast((addr >> 24) & 0xFF) +#define IPSTR "%d.%d.%d.%d" + +#define MAC2STR(mac) static_cast(mac[0]),static_cast(mac[1]),static_cast(mac[2]),static_cast(mac[3]), static_cast(mac[4]), static_cast(mac[5]) +#define MACSTR "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" + +namespace network { +static constexpr uint32_t STORE = 96; ///< Configuration store in bytes +static constexpr uint32_t MAC_SIZE = 6; +static constexpr uint32_t HOSTNAME_SIZE = 64; ///< Including a terminating null byte. +static constexpr uint32_t DOMAINNAME_SIZE = 64; ///< Including a terminating null byte. +static constexpr uint32_t NAMESERVERS_COUNT = 3; +static constexpr uint32_t IP4_ANY = 0x00000000; +static constexpr uint32_t IP4_BROADCAST = 0xffffffff; + +static constexpr uint32_t convert_to_uint(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d) { + return static_cast(a) | + static_cast(b) << 8 | + static_cast(c) << 16 | + static_cast(d) << 24; +} + +inline bool is_netmask_valid(uint32_t nNetMask) { + if (nNetMask == 0) { + return false; + } + nNetMask = __builtin_bswap32(nNetMask); + return !(nNetMask & (~nNetMask >> 1)); + +} +/** + * The private address ranges are defined in RFC1918. + */ +inline bool is_private_ip(const uint32_t nIp) { + const uint8_t n = (nIp >> 8) & 0xFF; + + switch (nIp & 0xFF) { + case 10: + return true; + break; + case 172: + return (n >= 16) && (n < 32); + case 192: + return n == 168; + default: + break; + } + + return false; +} + +inline bool is_linklocal_ip(const uint32_t nIp) { + return (nIp & 0xFFFF) == 0xA9FE; +} + +inline bool is_multicast_ip(const uint32_t nIp) { + return (nIp & 0xF0) == 0xE0; +} + +inline uint32_t cidr_to_netmask(const uint8_t nCIDR) { + if (nCIDR != 0) { + const auto nNetmask = __builtin_bswap32(static_cast(~0x0) << (32 - nCIDR)); + return nNetmask; + } + + return 0; +} +} // namespace network + +#endif /* IP4_ADDRESS_H_ */ diff --git a/lib-network/src/net/net.h b/lib-network/include/net.h old mode 100644 new mode 100755 similarity index 51% rename from lib-network/src/net/net.h rename to lib-network/include/net.h index 47a27861..a60df004 --- a/lib-network/src/net/net.h +++ b/lib-network/include/net.h @@ -2,7 +2,7 @@ * @file net.h * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,46 +28,63 @@ #include -struct ip_addr { - uint32_t addr; -}; +#include "netif.h" +#include "emac/phy.h" +#include "net/dhcp.h" +#include "net/protocol/dhcp.h" -typedef struct ip_addr ip_addr_t; +#include "debug.h" -struct IpInfo { - struct ip_addr ip; - struct ip_addr netmask; - struct ip_addr gw; - struct ip_addr broadcast_ip; - struct ip_addr secondary_ip; -}; +namespace network { +void mdns_shutdown(); +} // namespace network -#define IP_BROADCAST (0xFFFFFFFF) -#define HOST_NAME_MAX 64 /* including a terminating null byte. */ +namespace net { +void tcp_shutdown(); +void igmp_shutdown(); +} -void net_init(const uint8_t *const, struct IpInfo *, const char *, bool *, bool *); -void net_shutdown(); +namespace net { +void net_init(net::Link link, ip4_addr_t ipaddr, ip4_addr_t netmask, ip4_addr_t gw, bool &bUseDhcp); +void net_set_primary_ip(const ip4_addr_t ipaddr); +void net_set_secondary_ip(); void net_handle(); -void net_set_ip(struct IpInfo *); -void net_set_netmask(struct IpInfo *); -void net_set_gw(struct IpInfo *); -bool net_set_zeroconf(struct IpInfo *); - -bool net_set_dhcp(struct IpInfo *, const char *const, bool *); -void net_dhcp_release(); +inline void net_link_down() { + network::mdns_shutdown(); +#if defined (ENABLE_HTTPD) + tcp_shutdown(); +#endif + igmp_shutdown(); + dhcp_release_and_stop(); +} int udp_begin(uint16_t); int udp_end(uint16_t); -uint16_t udp_recv1(int, uint8_t *, uint16_t, uint32_t *, uint16_t *); -uint16_t udp_recv2(int, const uint8_t **, uint32_t *, uint16_t *); -int udp_send(int, const uint8_t *, uint16_t, uint32_t, uint16_t); +uint32_t udp_recv1(int, uint8_t *, uint32_t, uint32_t *, uint16_t *); +uint32_t udp_recv2(int, const uint8_t **, uint32_t *, uint16_t *); +void udp_send(int, const uint8_t *, uint32_t, uint32_t, uint16_t); +void udp_send_timestamp(int, const uint8_t *, uint32_t, uint32_t, uint16_t); void igmp_join(uint32_t); void igmp_leave(uint32_t); int tcp_begin(const uint16_t); uint16_t tcp_read(const int32_t, const uint8_t **, uint32_t &); -void tcp_write(const int32_t, const uint8_t *, uint16_t, const uint32_t); +void tcp_write(const int32_t, const uint8_t *, uint32_t, const uint32_t); + +/** + * Must be provided by the application + */ +void display_emac_config(); +void display_emac_start(); +void display_emac_status(const bool); +void display_emac_shutdown(); +void display_ip(); +void display_netmask(); +void display_gateway(); +void display_hostname(); +void display_dhcp_status(net::dhcp::State); +} // namespace het #endif /* NET_H_ */ diff --git a/lib-network/include/net/acd.h b/lib-network/include/net/acd.h new file mode 100755 index 00000000..f4a8d4fe --- /dev/null +++ b/lib-network/include/net/acd.h @@ -0,0 +1,71 @@ +/** + * @file acd.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* This code is inspired by: lwIP + * https://savannah.nongnu.org/projects/lwip/ + */ + +#ifndef NET_ACD_H_ +#define NET_ACD_H_ + +#include + +#include "netif.h" +#include "arp.h" +#include "net/protocol/acd.h" +#include "ip4_address.h" + +/** + * https://datatracker.ietf.org/doc/html/rfc5227.html + * IPv4 Address Conflict Detection + */ + +namespace net { +typedef void (*acd_conflict_callback_t)(acd::Callback callback); + +namespace acd { +struct Acd { + ip4_addr_t ipaddr; + State state; + uint8_t sent_num; + uint8_t lastconflict; + uint8_t num_conflicts; + acd_conflict_callback_t acd_conflict_callback; + uint16_t ttw; +}; +} // namespace acd + +void acd_add(struct acd::Acd *, acd_conflict_callback_t); +void acd_remove(struct acd::Acd *); + +void acd_start(struct acd::Acd *, const ip4_addr_t ipaddr); +void acd_stop(struct acd::Acd *); + +void acd_arp_reply(struct t_arp *); + +void acd_network_changed_link_down(); +void acd_netif_ip_addr_changed(const ip4_addr_t nOldIpAddress, const ip4_addr_t nNewIpAddress); +} // namespace net + +#endif /* NET_ACD_H_ */ diff --git a/lib-network/include/mdns.h b/lib-network/include/net/apps/mdns.h similarity index 77% rename from lib-network/include/mdns.h rename to lib-network/include/net/apps/mdns.h index 71578e20..4cf05e60 100755 --- a/lib-network/include/mdns.h +++ b/lib-network/include/net/apps/mdns.h @@ -2,7 +2,7 @@ * @file mdns.h * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,12 +23,13 @@ * THE SOFTWARE. */ -#ifndef MDNS_H_ -#define MDNS_H_ +#ifndef NET_APPS_MDNS_H_ +#define NET_APPS_MDNS_H_ #include #include "network.h" +#include "net/protocol/dns.h" #include "../config/apps_config.h" @@ -37,16 +38,6 @@ enum class Services { CONFIG, TFTP, HTTP, RDMNET_LLRP, NTP, MIDI, OSC, DDP, PP, LAST_NOT_USED }; -struct Header { - uint16_t xid; - uint8_t nFlag1; - uint8_t nFlag2; - uint16_t nQueryCount; - uint16_t nAnswerCount; - uint16_t nAuthorityCount; - uint16_t nAdditionalCount; -} __attribute__((__packed__)); - struct ServiceRecord { char *pName; char *pTextContent; @@ -61,25 +52,28 @@ class MDNS { MDNS(); ~MDNS(); - bool AddServiceRecord(const char *pName, const mdns::Services service, const char *pTextContent = nullptr, const uint16_t nPort = 0); + bool ServiceRecordAdd(const char *pName, const mdns::Services service, const char *pTextContent = nullptr, const uint16_t nPort = 0); + bool ServiceRecordDelete(const mdns::Services service); + void Print(); + void SendAnnouncement(const uint32_t nTTL); void Run() { s_nBytesReceived = Network::Get()->RecvFrom(s_nHandle, const_cast(reinterpret_cast(&s_pReceiveBuffer)), &s_nRemoteIp, &s_nRemotePort); - if (__builtin_expect((s_nBytesReceived < sizeof(struct mdns::Header)), 1)) { + if (__builtin_expect((s_nBytesReceived < sizeof(struct net::dns::Header)), 1)) { return; } - const auto *const pHeader = reinterpret_cast(s_pReceiveBuffer); + const auto *const pHeader = reinterpret_cast(s_pReceiveBuffer); const auto nFlag1 = pHeader->nFlag1; if ((nFlag1 >> 3) & 0xF) { return; } - HandleQuestions(__builtin_bswap16(pHeader->nQueryCount)); + HandleQuestions(static_cast(__builtin_bswap16(pHeader->nQueryCount))); } static MDNS *Get() { @@ -91,16 +85,16 @@ class MDNS { void HandleQuestions(const uint32_t nQuestions); void SendAnswerLocalIpAddress(const uint16_t nTransActionID, const uint32_t nTTL); void SendMessage(mdns::ServiceRecord const& serviceRecord, const uint16_t nTransActionID, const uint32_t nTTL); - void SendTo(const uint16_t nLength); + void SendTo(const uint32_t nLength); private: static int32_t s_nHandle; static uint32_t s_nRemoteIp; - static uint16_t s_nRemotePort; - static uint16_t s_nBytesReceived; + static uint32_t s_nBytesReceived; static uint8_t *s_pReceiveBuffer; + static uint16_t s_nRemotePort; static MDNS *s_pThis; }; -#endif /* MDNS_H_ */ +#endif /* NET_APPS_MDNS_H_ */ diff --git a/lib-network/include/net/apps/ntpclient.h b/lib-network/include/net/apps/ntpclient.h new file mode 100755 index 00000000..1a1d526a --- /dev/null +++ b/lib-network/include/net/apps/ntpclient.h @@ -0,0 +1,147 @@ +/** + * @file ntpclient.h + * + */ +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_APPS_NTPCLIENT_H_ +#define NET_APPS_NTPCLIENT_H_ + +#include +#include +#include + +#include "net/protocol/ntp.h" +#include "hardware.h" + +#include "debug.h" + +#if !defined(CONFIG_NTP_CLIENT_POLL_POWER) +# define CONFIG_NTP_CLIENT_POLL_POWER 10 +#endif + +namespace ntpclient { +static constexpr uint32_t TIMEOUT_MILLIS = 3000; +static constexpr uint8_t POLL_POWER = CONFIG_NTP_CLIENT_POLL_POWER; +static constexpr uint32_t POLL_SECONDS = (1U << POLL_POWER); + +void display_status(const ::ntp::Status status); +} // namespace ntpclient + +class NtpClient { +public: + NtpClient(); + + void Start(); + void Stop(); + void Print(); + + void SetServerIp(const uint32_t nServerIp) { + m_nServerIp = nServerIp; + } + + ntp::Status GetStatus() const { + return m_Status; + } + + void Run() { + if (m_Status == ntp::Status::STOPPED) { + return; + } + + if ((m_Status == ntp::Status::IDLE) || (m_Status == ntp::Status::FAILED)) { + if (__builtin_expect(((Hardware::Get()->Millis() - m_MillisLastPoll) > (1000 * ntpclient::POLL_SECONDS)), 0)) { + Send(); + m_MillisRequest = Hardware::Get()->Millis(); + m_Status = ntp::Status::WAITING; + ntpclient::display_status(ntp::Status::WAITING); + DEBUG_PUTS("ntp::Status::WAITING"); + } + + return; + } + + if (m_Status == ntp::Status::WAITING) { + uint8_t LiVnMode; + + if (!Receive(LiVnMode)) { + if (__builtin_expect(((Hardware::Get()->Millis() - m_MillisRequest) > ntpclient::TIMEOUT_MILLIS), 0)) { + m_Status = ntp::Status::FAILED; + ntpclient::display_status(ntp::Status::FAILED); + DEBUG_PUTS("ntp::Status::FAILED"); + } + + return; + } + + if (__builtin_expect(((LiVnMode & ntp::MODE_SERVER) == ntp::MODE_SERVER), 1)) { + m_MillisLastPoll = Hardware::Get()->Millis(); + + SetTimeOfDay(); +#ifndef NDEBUG + const auto nTime = time(nullptr); + const auto *pLocalTime = localtime(&nTime); + DEBUG_PRINTF("localtime: %.4d/%.2d/%.2d %.2d:%.2d:%.2d", pLocalTime->tm_year + 1900, pLocalTime->tm_mon + 1, pLocalTime->tm_mday, pLocalTime->tm_hour, pLocalTime->tm_min, pLocalTime->tm_sec); +#endif + } else { + DEBUG_PUTS("!>> Invalid reply < +#include namespace tftp { enum class Mode { @@ -70,11 +71,11 @@ class TFTPDaemon { int m_nIdx { -1 }; uint8_t *m_pBuffer { nullptr }; uint32_t m_nFromIp { 0 }; + uint32_t m_nLength { 0 }; + uint32_t m_nDataLength { 0 }; + uint32_t m_nPacketLength { 0 }; uint16_t m_nFromPort { 0 }; - size_t m_nLength { 0 }; uint16_t m_nBlockNumber { 0 }; - size_t m_nDataLength { 0 }; - uint16_t m_nPacketLength { 0 }; bool m_bIsLastBlock { false }; static TFTPDaemon* Get() { @@ -85,4 +86,4 @@ class TFTPDaemon { static TFTPDaemon *s_pThis; }; -#endif /* TFTPDAEMON_H_ */ +#endif /* NET_APPS_TFTPDAEMON_H_ */ diff --git a/lib-network/src/net/net_debug.h b/lib-network/include/net/arp.h old mode 100644 new mode 100755 similarity index 60% rename from lib-network/src/net/net_debug.h rename to lib-network/include/net/arp.h index 85095c4b..cddb33d9 --- a/lib-network/src/net/net_debug.h +++ b/lib-network/include/net/arp.h @@ -1,8 +1,8 @@ /** - * @file net_debug.h + * @file arp_private.h * */ -/* Copyright (C) 2018-2019 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,22 +23,29 @@ * THE SOFTWARE. */ -#ifndef NET_DEBUG_H_ -#define NET_DEBUG_H_ +#ifndef ARP_PRIVATE_H_ +#define ARP_PRIVATE_H_ -#include "debug.h" +#include "netif.h" +#include "net/protocol/ip4.h" +#include "net/protocol/arp.h" +#include "net/protocol/udp.h" -#ifndef IP2STR - #define IP2STR(addr) (addr & 0xFF), ((addr >> 8) & 0xFF), ((addr >> 16) & 0xFF), ((addr >> 24) & 0xFF) - #define IPSTR "%d.%d.%d.%d" -#endif -#ifndef MAC2STR - #define MAC2STR(mac) (mac[0]),(mac[1]),(mac[2]),(mac[3]), (mac[4]), (mac[5]) - #define MACSTR "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" -#endif +namespace net { +namespace arp { +enum class Flags { + FLAG_INSERT, FLAG_UPDATE +}; +} // namespace arp -#if defined (H3) -# include "h3_timer.h" +void arp_init(); +void arp_handle(struct t_arp *); +void arp_send(struct t_udp *, const uint32_t, const uint32_t); +#if defined CONFIG_ENET_ENABLE_PTP +void arp_send_timestamp(struct t_udp *, const uint32_t, const uint32_t); #endif +void arp_acd_probe(const ip4_addr_t ipaddr); +void arp_acd_send_announcement(const ip4_addr_t ipaddr); +} // namespace net -#endif /* NET_DEBUG_H_ */ +#endif /* ARP_PRIVATE_H_ */ diff --git a/lib-network/include/net/autoip.h b/lib-network/include/net/autoip.h new file mode 100755 index 00000000..332fd7df --- /dev/null +++ b/lib-network/include/net/autoip.h @@ -0,0 +1,90 @@ +/** + * @file autoip.h + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* This code is inspired by the lwIP TCP/IP stack. + * https://savannah.nongnu.org/projects/lwip/ + */ +/** + * The autoip.cpp aims to be conform to RFC 3927. + * https://datatracker.ietf.org/doc/html/rfc3927 + * Dynamic Configuration of IPv4 Link-Local Addresses + */ + +#ifndef NET_AUTOIP_H_ +#define NET_AUTOIP_H_ + +#include + +#include "netif.h" +#include "net/acd.h" +#include "net/protocol/autoip.h" + +#include "debug.h" + +namespace net { +namespace autoip { +struct Autoip { + ip4_addr_t llipaddr; + State state; + uint8_t tried_llipaddr; + acd::Acd acd; +}; +} // namespace autoip + +void autoip_start(); +void autoip_stop(); + +inline bool autoip_supplied_address() { + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + + return (autoip != nullptr) + && (globals::netif_default.ip.addr == autoip->llipaddr.addr) + && (autoip->state == autoip::State::AUTOIP_STATE_BOUND); +} + +inline void autoip_network_changed_link_up() { + DEBUG_ENTRY + + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + + if ((autoip != nullptr) && (autoip->state != autoip::State::AUTOIP_STATE_OFF)) { + acd_start(&autoip->acd, autoip->llipaddr); + } + + DEBUG_EXIT +} + +inline void autoip_network_changed_link_down() { + DEBUG_EXIT + + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + + if ((autoip != nullptr) && (autoip->state != autoip::State::AUTOIP_STATE_OFF)) { + autoip_stop(); + } + + DEBUG_EXIT +} +} // namespace net + +#endif /* NET_AUTOIP_H_ */ diff --git a/lib-network/include/net/dhcp.h b/lib-network/include/net/dhcp.h new file mode 100755 index 00000000..1c6f1670 --- /dev/null +++ b/lib-network/include/net/dhcp.h @@ -0,0 +1,139 @@ +/** + * @file dhcp.h + * + */ +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_DHCP_H_ +#define NET_DHCP_H_ + +#include +#include + +#include + +#include "netif.h" +#include "acd.h" +#include "ip4_address.h" +#include "net/protocol/dhcp.h" +#include "net/protocol/iana.h" + +#include "debug.h" + +namespace net { +namespace dhcp { +static constexpr uint32_t DHCP_COARSE_TIMER_SECS = 60; +/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ +static constexpr uint32_t DHCP_COARSE_TIMER_MSECS = (DHCP_COARSE_TIMER_SECS * 1000UL); +/** period (in milliseconds) of the application calling dhcp_fine_tmr() */ +static constexpr uint32_t DHCP_FINE_TIMER_MSECS = 500; + +#define DHCP_FLAG_SUBNET_MASK_GIVEN 0x01 +#define DHCP_AUTOIP_COOP_TRIES 9 + +enum class AutoipCoopState { + DHCP_AUTOIP_COOP_STATE_OFF = 0, + DHCP_AUTOIP_COOP_STATE_ON = 1 +}; + +typedef uint16_t dhcp_timeout_t; + +struct Dhcp { + int32_t nHandle; + uint32_t xid; + State state; + uint8_t tries; + uint8_t flags; + + dhcp_timeout_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ + dhcp_timeout_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ + dhcp_timeout_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ + dhcp_timeout_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */ + dhcp_timeout_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */ + dhcp_timeout_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */ + dhcp_timeout_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */ + + ip4_addr_t server_ip_addr; + + struct Offered { + ip4_addr_t offered_ip_addr; + ip4_addr_t offered_sn_mask; + ip4_addr_t offered_gw_addr; + + uint32_t offered_t0_lease; /* lease period (in seconds) */ + uint32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ + uint32_t offered_t2_rebind; /* recommended rebind time (usually 87.5 of lease period) */ + }; + + Offered offered; + + acd::Acd acd; +}; +} // namespace dhcp + +bool dhcp_start(); +bool dhcp_renew(); +bool dhcp_release(); +void dhcp_stop(); +void dhcp_release_and_stop(); +void dhcp_inform(); +void dhcp_network_changed_link_up(); + +uint32_t udp_recv2(int, const uint8_t **, uint32_t *, uint16_t *); +void dhcp_process(const dhcp::Message *const, const uint32_t nSize); + +inline void dhcp_run() { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + if (dhcp == nullptr) { + return; + } + + uint8_t *pResponse; + uint32_t nFromIp; + uint16_t nFromPort; + + const auto nSize = udp_recv2(dhcp->nHandle, const_cast(&pResponse), &nFromIp, &nFromPort); + + if (__builtin_expect((nSize > 0), 0)) { + if (nFromPort == net::iana::IANA_PORT_DHCP_SERVER) { + const auto *const p = reinterpret_cast(pResponse); + + if (p->xid != dhcp->xid) { + DEBUG_PRINTF("pDhcpMessage->xid=%u, dhcp->xid=%u", p->xid, dhcp->xid); + return; + } + + dhcp_process(p, nSize); + } + } +} + +inline bool dhcp_supplied_address() { + const auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + if ((dhcp != nullptr)) { + return (dhcp->state == dhcp::State::STATE_BOUND) || (dhcp->state == dhcp::State::STATE_RENEWING) || (dhcp->state == dhcp::State::STATE_REBINDING); + } + return false; +} +} // namespace net + +#endif /* NET_DHCP_H_ */ diff --git a/lib-network/include/net/igmp.h b/lib-network/include/net/igmp.h new file mode 100755 index 00000000..252cce6c --- /dev/null +++ b/lib-network/include/net/igmp.h @@ -0,0 +1,13 @@ +/* + * igmp.h + */ + +#ifndef NET_IGMP_H_ +#define NET_IGMP_H_ + +namespace net { +//TODO implement +void igmp_report_groups(); +} // namespace net + +#endif /* NET_IGMP_H_ */ diff --git a/lib-network/include/net/protocol/acd.h b/lib-network/include/net/protocol/acd.h new file mode 100644 index 00000000..035b3e5d --- /dev/null +++ b/lib-network/include/net/protocol/acd.h @@ -0,0 +1,64 @@ +/** + * @file acd.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_PROTOCOL_ACD_H_ +#define NET_PROTOCOL_ACD_H_ + +#include + +namespace net::acd { +/** + * RFC 5227 and RFC 3927 Constants + */ +#define PROBE_WAIT 1 ///< second (initial random delay) +#define PROBE_MIN 1 ///< second (minimum delay till repeated probe) +#define PROBE_MAX 2 ///< seconds (maximum delay till repeated probe) +#define PROBE_NUM 3 ///< (number of probe packets) +#define ANNOUNCE_NUM 2 ///< (number of announcement packets) +#define ANNOUNCE_INTERVAL 2 ///< seconds (time between announcement packets) +#define ANNOUNCE_WAIT 2 ///< seconds (delay before announcing) +#define MAX_CONFLICTS 10 ///< (max conflicts before rate limiting) +#define RATE_LIMIT_INTERVAL 60 ///< seconds (delay between successive attempts) +#define DEFEND_INTERVAL 10 ///< seconds (minimum interval between defensive ARPs) + +enum class State: uint8_t { + ACD_STATE_OFF, + ACD_STATE_PROBE_WAIT, + ACD_STATE_PROBING, + ACD_STATE_ANNOUNCE_WAIT, + ACD_STATE_ANNOUNCING, + ACD_STATE_ONGOING, + ACD_STATE_PASSIVE_ONGOING, + ACD_STATE_RATE_LIMIT +}; + +enum class Callback { + ACD_IP_OK, ///< IP address is good, no conflicts found in checking state + ACD_RESTART_CLIENT, ///< Conflict found -> the client should try again + ACD_DECLINE ///< Decline the received IP address (rate limiting) +}; +} // namespace acd + +#endif /* NET_PROTOCOL_ACD_H_ */ diff --git a/lib-network/src/net/dhcp_internal.h b/lib-network/include/net/protocol/arp.h old mode 100644 new mode 100755 similarity index 50% rename from lib-network/src/net/dhcp_internal.h rename to lib-network/include/net/protocol/arp.h index 1ce0e730..3d6b6b1c --- a/lib-network/src/net/dhcp_internal.h +++ b/lib-network/include/net/protocol/arp.h @@ -1,8 +1,8 @@ /** - * @file dhcp_internal.h + * @file arp.h * */ -/* Copyright (C) 2018-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,47 +23,54 @@ * THE SOFTWARE. */ -#ifndef DHCP_INTERNAL_H_ -#define DHCP_INTERNAL_H_ +#ifndef NET_PROTOCOL_ARP_H_ +#define NET_PROTOCOL_ARP_H_ -enum DHCP_PORT { - DHCP_PORT_SERVER = 67, - DHCP_PORT_CLIENT = 68 +#include "ip4_address.h" +#include "net/protocol/ethernet.h" +#include "net/protocol/ieee.h" + +#if !defined (PACKED) +# define PACKED __attribute__((packed)) +#endif + +enum ARP_HARDWARE_TYPE { + ARP_HWTYPE_ETHERNET = 1 }; -enum DHCP_OP { - DHCP_OP_BOOTREQUEST = 1, - DHCP_OP_BOOTREPLY = 2 +enum ARP_PROTOCOL_TYPE { + ARP_PRTYPE_IPv4 = ETHER_TYPE_IPv4 }; -enum DHCP_HTYPE { - DHCP_HTYPE_10MB = 1, - DHCP_HTYPE_100MB = 2 +enum ARP_HARDWARE { + ARP_HARDWARE_SIZE = ETH_ADDR_LEN }; -enum DCHP_TYPE { - DCHP_TYPE_DISCOVER = 1, - DCHP_TYPE_OFFER = 2, - DCHP_TYPE_REQUEST = 3, - DCHP_TYPE_DECLINE = 4, - DCHP_TYPE_ACK = 5, - DCHP_TYPE_NAK = 6, - DCHP_TYPE_RELEASE = 7, - DCHP_TYPE_INFORM = 8 +enum ARP_PROTOCOL { + ARP_PROTOCOL_SIZE = IPv4_ADDR_LEN }; -enum DHCP_STATE { - DHCP_STATE_DHCP_INIT = 0, - DHCP_STATE_DHCP_DISCOVER = 1, - DHCP_STATE_DHCP_REQUEST = 2, - DHCP_STATE_DHCP_LEASED = 3, - DHCP_STATE_DHCP_REREQUEST = 4, - DHCP_STATE_DHCP_RELEASE = 5, - DHCP_STATE_DHCP_STOP = 6 +enum ARP_OPCODE { + ARP_OPCODE_RQST = 1, + ARP_OPCODE_REPLY = 2 }; -#define DHCP_OPT_SIZE 312 +struct arp_packet { + uint16_t hardware_type; /* 2 */ + uint16_t protocol_type; /* 4 */ + uint8_t hardware_size; /* 5 */ + uint8_t protocol_size; /* 6 */ + uint16_t opcode; /* 8 */ + uint8_t sender_mac[ETH_ADDR_LEN];/*14 */ + uint8_t sender_ip[IPv4_ADDR_LEN];/* 18 */ + uint8_t target_mac[ETH_ADDR_LEN];/*24 */ + uint8_t target_ip[IPv4_ADDR_LEN];/* 28 */ + uint8_t padding[18]; /* 46 */ /* +14 = 60 */ +} PACKED; -#define MAGIC_COOKIE 0x63825363 ///< You should not modify it number. +struct t_arp { + struct ether_header ether; + struct arp_packet arp; +} PACKED; -#endif /* DHCP_INTERNAL_H_ */ +#endif /* NET_PROTOCOL_ARP_H_ */ diff --git a/lib-network/include/net/protocol/autoip.h b/lib-network/include/net/protocol/autoip.h new file mode 100644 index 00000000..dc3d900a --- /dev/null +++ b/lib-network/include/net/protocol/autoip.h @@ -0,0 +1,43 @@ +/** + * @file autoip.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_PROTOCOL_AUTOIP_H_ +#define NET_PROTOCOL_AUTOIP_H_ + +#include "ip4_address.h" + +namespace net::autoip { +static constexpr auto AUTOIP_NET = network::convert_to_uint(169,254,0,0); +static constexpr auto AUTOIP_RANGE_START = network::convert_to_uint(169,254,1,0); +static constexpr auto AUTOIP_RANGE_END = network::convert_to_uint(169,254,254,255); + +enum class State { + AUTOIP_STATE_OFF, + AUTOIP_STATE_CHECKING, + AUTOIP_STATE_BOUND +}; +} // namespace autoip + +#endif /* NET_PROTOCOL_AUTOIP_H_ */ diff --git a/lib-network/include/net/protocol/dhcp.h b/lib-network/include/net/protocol/dhcp.h new file mode 100644 index 00000000..94064171 --- /dev/null +++ b/lib-network/include/net/protocol/dhcp.h @@ -0,0 +1,120 @@ +/** + * @file dhcp.h + * + */ +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_PROTOCOL_DHCP_H +#define NET_PROTOCOL_DHCP_H + +#include + +#include "ip4.h" + +namespace net::dhcp { +static constexpr uint32_t OPT_SIZE = 312; +static constexpr uint32_t MAGIC_COOKIE = 0x63825363; ///< You should not modify it number. + +struct OpCode { + static constexpr uint8_t BOOTREQUEST = 1; + static constexpr uint8_t BOOTREPLY = 2; +}; + +struct HardwareType { + static constexpr uint8_t HTYPE_10MB = 1; + static constexpr uint8_t HTYPE_100MB = 2; +}; + +struct Type { + static constexpr uint8_t DISCOVER = 1; + static constexpr uint8_t OFFER = 2; + static constexpr uint8_t REQUEST = 3; + static constexpr uint8_t DECLINE = 4; + static constexpr uint8_t ACK = 5; + static constexpr uint8_t NAK = 6; + static constexpr uint8_t RELEASE = 7; + static constexpr uint8_t INFORM = 8; +}; + +struct Options { + /* BootP options */ + static constexpr uint8_t OPTION_PAD_OPTION = 0; + static constexpr uint8_t OPTION_SUBNET_MASK = 1; ///< RFC 2132 3.3 + static constexpr uint8_t OPTION_ROUTER = 3; + static constexpr uint8_t OPTION_DNS_SERVER = 6; + static constexpr uint8_t OPTION_HOSTNAME = 12; + static constexpr uint8_t OPTION_DOMAIN_NAME = 15; + static constexpr uint8_t OPTION_IP_TTL = 23; + static constexpr uint8_t OPTION_MTU = 26; + static constexpr uint8_t OPTION_BROADCAST = 28; + static constexpr uint8_t OPTION_TCP_TTL = 37; + static constexpr uint8_t OPTION_NTP = 42; + static constexpr uint8_t OPTION_END = 255; + /* DHCP options */ + static constexpr uint8_t OPTION_REQUESTED_IP = 50; ///< RFC 2132 9.1, requested IP address + static constexpr uint8_t OPTION_LEASE_TIME = 51; ///< RFC 2132 9.2, time in seconds, in 4 bytes + static constexpr uint8_t OPTION_OVERLOAD = 52; ///< RFC2132 9.3, use file and/or sname field for options + static constexpr uint8_t OPTION_MESSAGE_TYPE = 53; ///< RFC 2132 9.6, important for DHCP + static constexpr uint8_t OPTION_SERVER_IDENTIFIER = 54; ///< RFC 2132 9.7, server IP address + static constexpr uint8_t OPTION_PARAM_REQUEST = 55; ///< RFC 2132 9.8, requested option types + static constexpr uint8_t OPTION_MAX_MSG_SIZE = 57; ///< RFC 2132 9.10, message size accepted >= 576 + static constexpr uint8_t OPTION_DHCP_T1_VALUE = 58; ///< T1 renewal time + static constexpr uint8_t OPTION_DHCP_T2_VALUE = 59; ///< T2 renewal time + static constexpr uint8_t OPTION_CLIENT_IDENTIFIER = 61; +}; + +enum class State: uint8_t { + STATE_OFF = 0, + STATE_REQUESTING = 1, + STATE_INIT = 2, + STATE_REBOOTING = 3, + STATE_REBINDING = 4, + STATE_RENEWING = 5, + STATE_SELECTING = 6, + STATE_INFORMING = 7, + STATE_CHECKING = 8, + STATE_PERMANENT = 9, + STATE_BOUND = 10, + STATE_RELEASING = 11, + STATE_BACKING_OFF = 12 +}; + +struct Message { + uint8_t op; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + uint8_t ciaddr[IPv4_ADDR_LEN]; + uint8_t yiaddr[IPv4_ADDR_LEN]; + uint8_t siaddr[IPv4_ADDR_LEN]; + uint8_t giaddr[IPv4_ADDR_LEN]; + uint8_t chaddr[16]; + uint8_t sname[64]; + uint8_t file[128]; + uint8_t options[dhcp::OPT_SIZE]; +} __attribute__((packed)); +} // namespace net::dhcp + +#endif /* NET_PROTOCOL_DHCP_H */ diff --git a/lib-network/include/net/protocol/dns.h b/lib-network/include/net/protocol/dns.h new file mode 100644 index 00000000..e486563f --- /dev/null +++ b/lib-network/include/net/protocol/dns.h @@ -0,0 +1,93 @@ +/** + * @file dns.h + * + */ +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_PROTOCOL_DNS_H_ +#define NET_PROTOCOL_DNS_H_ + +#include + +#include "ip4_address.h" + +namespace net { namespace dns { +static constexpr uint32_t SIZEOF_DNS_HDR = 12; + +enum class Flag1 : uint8_t { + FLAG1_RESPONSE = 0x80, ///< query (0), or a response (1). + FLAG1_OPCODE_STATUS = 0x10, ///< a server status request (STATUS) + FLAG1_OPCODE_IQUERY = 0x08, ///< an inverse query (IQUERY) + FLAG1_OPCODE_STANDARD = 0x00, ///< (RFC 6762, section 18.3) + FLAG1_AUTHORATIVE = 0x04, ///< Authoritative Answer + FLAG1_TRUNC = 0x02, ///< TrunCation + FLAG1_RD = 0x01 ///< If RD is set, it directs the name server to pursue the query recursively. +}; + +static constexpr uint8_t operator| (Flag1 a, Flag1 b) { + return static_cast((static_cast(a) | static_cast(b))); +} + +///< NS field TYPE used for "Resource Records" +enum class RRType : uint16_t { + RRTYPE_A = 1, ///< a host address + RRTYPE_PTR = 12, ///< a domain name pointer + RRTYPE_TXT = 16, ///< text strings + RRTYPE_SRV = 33, ///< service location + RRTYPE_ALL = 255 ///< any type +}; + +///< DNS field CLASS used for "Resource Records" +enum class RRClass : uint16_t { + RRCLASS_INTERNET = 1, ///< Internet + RRCLASS_ANY = 255, ///< Any class + RRCLASS_FLUSH = 0x8000 ///< Flush bit +}; + +static constexpr uint16_t operator| (RRClass a, RRClass b) { + return static_cast((static_cast(a) | static_cast(b))); +} + +struct Header { + uint16_t xid; + uint8_t nFlag1; + uint8_t nFlag2; + uint16_t nQueryCount; + uint16_t nAnswerCount; + uint16_t nAuthorityCount; + uint16_t nAdditionalCount; +} __attribute__((__packed__)); + +inline uint8_t dns_header_get_opcode(const Header *const header) { + return ((header->nFlag1) >> 3) & 0xF; +} + +/* + * mDNS + */ + +static constexpr uint32_t MULTICAST_MESSAGE_SIZE = 512; ///< The 1987 DNS specification [RFC1035] restricts DNS messages carried by UDP to no more than 512 bytes +static constexpr uint32_t MULTICAST_ADDRESS = network::convert_to_uint(224, 0, 0, 251); + +} } // namespace net::dns + +#endif /* NET_PROTOCOL_DNS_H_ */ diff --git a/lib-network/src/emac/gd32/debug_print_bits.c b/lib-network/include/net/protocol/ethernet.h old mode 100644 new mode 100755 similarity index 67% rename from lib-network/src/emac/gd32/debug_print_bits.c rename to lib-network/include/net/protocol/ethernet.h index 48747959..323c2339 --- a/lib-network/src/emac/gd32/debug_print_bits.c +++ b/lib-network/include/net/protocol/ethernet.h @@ -1,8 +1,8 @@ /** - * @file debug_print_bits.c + * @file ethernet.h * */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,26 +23,33 @@ * THE SOFTWARE. */ -#include +#ifndef NET_PROTOCOL_ETHERNET_H_ +#define NET_PROTOCOL_ETHERNET_H_ + #include -#if defined (H3) -extern int uart0_printf(const char* fmt, ...); -# define printf uart0_printf +#if !defined (PACKED) +# define PACKED __attribute__((packed)) #endif -void debug_print_bits(uint32_t u) { - uint32_t i; +enum MTU { + MTU_SIZE = 1500 +}; + +enum ETH_ADDR { + ETH_ADDR_LEN = 6 +}; + +struct ether_header { + uint8_t dst[ETH_ADDR_LEN]; /* 6 */ + uint8_t src[ETH_ADDR_LEN]; /* 12 */ + uint16_t type; /* 14 */ +} PACKED; + +namespace net { +static constexpr uint32_t ETH_HWADDR_LEN = 6; - uint32_t b = 1U << 31; - for (i = 0; i < 32; i++) { - if ((b & u) == b) { - uint32_t bit_number = 31 - i; - printf("%-2d ", bit_number); - } - b = b >> 1; - } +} // namespace net - printf("\n"); -} +#endif /* NET_PROTOCOL_ETHERNET_H_ */ diff --git a/lib-network/include/net/protocol/iana.h b/lib-network/include/net/protocol/iana.h new file mode 100644 index 00000000..bc5c6990 --- /dev/null +++ b/lib-network/include/net/protocol/iana.h @@ -0,0 +1,40 @@ +/** + * @file iana.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_PROTOCOL_IANA_H_ +#define NET_PROTOCOL_IANA_H_ + +#include + +namespace net::iana { +static constexpr uint16_t IANA_PORT_DHCP_SERVER = 67; +static constexpr uint16_t IANA_PORT_DHCP_CLIENT = 68; +static constexpr uint16_t IANA_PORT_TFTP = 69; +static constexpr uint16_t IANA_PORT_HTTP = 80; +static constexpr uint16_t IANA_PORT_NTP_SERVER = 123; +static constexpr uint16_t IANA_PORT_MDNS = 5353; +} // namespace net::iana + +#endif /* NET_PROTOCOL_IANA_H_ */ diff --git a/lib-network/include/net/protocol/icmp.h b/lib-network/include/net/protocol/icmp.h new file mode 100755 index 00000000..a9cb2a83 --- /dev/null +++ b/lib-network/include/net/protocol/icmp.h @@ -0,0 +1,65 @@ +/** + * @file icmp.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_PROTOCOL_ICMP_H_ +#define NET_PROTOCOL_ICMP_H_ + +#include + +#include "net/protocol/ethernet.h" +#include "net/protocol/ip4.h" + +#if !defined (PACKED) +# define PACKED __attribute__((packed)) +#endif + +enum ICMP_TYPE { + ICMP_TYPE_ECHO_REPLY = 0, + ICMP_TYPE_ECHO = 8 +}; + +enum ICMP_CODE { + ICMP_CODE_ECHO = 0 +}; + +struct t_icmp_packet { + uint8_t type; /* 1 */ + uint8_t code; /* 2 */ + uint16_t checksum; /* 4 */ + uint8_t parameter[4]; /* 8 */ +#define ICMP_HEADER_SIZE 8 +#define ICMP_PAYLOAD_SIZE (MTU_SIZE - ICMP_HEADER_SIZE - sizeof(struct ip4_header)) + uint8_t payload[ICMP_PAYLOAD_SIZE]; +} PACKED; + +struct t_icmp { + struct ether_header ether; + struct ip4_header ip4; + struct t_icmp_packet icmp; +} PACKED; + +#define IPv4_ICMP_HEADERS_SIZE (sizeof(struct t_icmp) - sizeof(struct ether_header)) + +#endif /* NET_PROTOCOL_ICMP_H_ */ diff --git a/gd32_rdm_responder/lib/dmxstartaddressupdate.cpp b/lib-network/include/net/protocol/ieee.h old mode 100644 new mode 100755 similarity index 78% rename from gd32_rdm_responder/lib/dmxstartaddressupdate.cpp rename to lib-network/include/net/protocol/ieee.h index d5c8130d..c65ef053 --- a/gd32_rdm_responder/lib/dmxstartaddressupdate.cpp +++ b/lib-network/include/net/protocol/ieee.h @@ -1,8 +1,8 @@ /** - * @file dmxstartaddressupdate.cpp + * @file ieee.h * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,14 +23,15 @@ * THE SOFTWARE. */ -#include - -#include "rdmresponder.h" +#ifndef NET_PROTOCOL_IEEE_H_ +#define NET_PROTOCOL_IEEE_H_ -#include "displayudf.h" +#include -#include "debug.h" +enum ETHER_TYPE { + ETHER_TYPE_IPv4 = 0x0800, + ETHER_TYPE_ARP = 0x0806, + ETHER_TYPE_PTP = 0x88F7 /* IEEE1588v2 (PTPv2) over Ethernet */ +}; -void RDMResponder::DmxStartAddressUpdate(__attribute__((unused)) uint16_t nDmxStartAddress) { - DisplayUdf::Get()->Show(); -} +#endif /* NET_PROTOCOL_IEEE_H_ */ diff --git a/lib-artnet/include/artnetrdm.h b/lib-network/include/net/protocol/igmp.h old mode 100644 new mode 100755 similarity index 55% rename from lib-artnet/include/artnetrdm.h rename to lib-network/include/net/protocol/igmp.h index a36a5b60..d49a7d9f --- a/lib-artnet/include/artnetrdm.h +++ b/lib-network/include/net/protocol/igmp.h @@ -1,11 +1,8 @@ /** - * @file artnetrdm.h + * @file igmp.h * */ -/** - * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. - */ -/* Copyright (C) 2017-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,29 +23,44 @@ * THE SOFTWARE. */ -#ifndef ARTNETRDM_H_ -#define ARTNETRDM_H_ +#ifndef NET_PROTOCOL_IGMP_H_ +#define NET_PROTOCOL_IGMP_H_ #include -namespace artnet { -void rdm_send(uint32_t nPortIndex, const uint8_t *pRdmData); -} // namespace artnet +#include "net/protocol/ethernet.h" +#include "net/protocol/ip4.h" -class ArtNetRdm { -public: - virtual ~ArtNetRdm() {} +#if !defined (PACKED) +# define PACKED __attribute__((packed)) +#endif - virtual void Full(uint32_t nPortIndex)=0; - virtual uint32_t GetUidCount(uint32_t nPortIndex)=0; - virtual void TodCopy(uint32_t nPortIndex, uint8_t *)=0; +enum IGMP_TYPE { + IGMP_TYPE_QUERY = 0x11, + IGMP_TYPE_REPORT = 0x16, + IGMP_TYPE_LEAVE = 0x17 +}; - virtual void TodReset(uint32_t nPortIndex)=0; - virtual bool TodAddUid(uint32_t nPortIndex, const uint8_t *pUid)=0; +struct t_igmp_packet { + uint8_t type; + uint8_t max_resp_time; + uint16_t checksum; + uint8_t group_address[IPv4_ADDR_LEN]; +} PACKED; - virtual const uint8_t *Handler(uint32_t nPortIndex, const uint8_t *)=0; +struct t_igmp { + struct ether_header ether; + struct ip4_header ip4; + union { + struct { + uint32_t ip4_options; + struct t_igmp_packet igmp; + } report; + struct t_igmp_packet igmp; + } igmp; +} PACKED; - virtual bool RdmReceive(uint32_t nPortIndex, uint8_t *pRdmData)=0; -}; +#define IPv4_IGMP_REPORT_HEADERS_SIZE (sizeof(struct t_igmp) - sizeof(struct ether_header)) +#define IGMP_REPORT_PACKET_SIZE (sizeof(struct t_igmp)) -#endif /* ARTNETRDM_H_ */ +#endif /* NET_PROTOCOL_IGMP_H_ */ diff --git a/lib-network/include/net/protocol/ip4.h b/lib-network/include/net/protocol/ip4.h new file mode 100755 index 00000000..346b9974 --- /dev/null +++ b/lib-network/include/net/protocol/ip4.h @@ -0,0 +1,71 @@ +/** + * @file ip4.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef NET_PROTOCOL_IP4_H_ +#define NET_PROTOCOL_IP4_H_ + +#include + +#include "net/protocol/ethernet.h" + +#if !defined (PACKED) +# define PACKED __attribute__((packed)) +#endif + +enum IPv4_ADDR { + IPv4_ADDR_LEN = 4 +}; + +enum IPv4_PROTO { + IPv4_PROTO_ICMP = 1, + IPv4_PROTO_IGMP = 2, + IPv4_PROTO_TCP = 6, + IPv4_PROTO_UDP = 17 +}; + +enum IPv4_FLAG { + IPv4_FLAG_LF = 0x0000, + IPv4_FLAG_MF = 0x2000, + IPv4_FLAG_DF = 0x4000 +}; + +struct ip4_header { + uint8_t ver_ihl; /* 1 */ + uint8_t tos; /* 2 */ + uint16_t len; /* 4 */ + uint16_t id; /* 6 */ + uint16_t flags_froff; /* 8 */ + uint8_t ttl; /* 9 */ + uint8_t proto; /* 10 */ + uint16_t chksum; /* 12 */ + uint8_t src[IPv4_ADDR_LEN]; /* 16 */ + uint8_t dst[IPv4_ADDR_LEN]; /* 20 */ +} PACKED; + +struct t_ip4 { + struct ether_header ether; + struct ip4_header ip4; +} PACKED; + +#endif /* NET_PROTOCOL_IP4_H_ */ diff --git a/lib-network/include/ntp.h b/lib-network/include/net/protocol/ntp.h old mode 100644 new mode 100755 similarity index 50% rename from lib-network/include/ntp.h rename to lib-network/include/net/protocol/ntp.h index fdf6b0d4..2999c4ce --- a/lib-network/include/ntp.h +++ b/lib-network/include/net/protocol/ntp.h @@ -2,7 +2,7 @@ * @file ntp.h * */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,34 +23,23 @@ * THE SOFTWARE. */ -#ifndef NTP_H_ -#define NTP_H_ +#ifndef NET_PROTOCOL_NTP_H_ +#define NET_PROTOCOL_NTP_H_ -static constexpr auto LOCAL_TIME_YEAR_OFFSET = 1900; -static constexpr auto NTP_TIMESTAMP_DELTA = 2208988800u; +#include -enum TNtpUdpPort { - NTP_UDP_PORT = 123 -}; - -enum TNtpVersion { - NTP_VERSION = (4 << 3) -}; +namespace ntp { +static constexpr uint32_t JAN_1970 = 0x83aa7e80; // 2208988800 1970 - 1900 in seconds +static constexpr uint32_t LOCAL_TIME_YEAR_OFFSET = 1900; +static constexpr uint32_t MICROSECONDS_IN_SECOND = 1000000; +static constexpr uint16_t UDP_PORT = 123; +static constexpr uint8_t VERSION = (4U << 3); +static constexpr uint8_t MODE_CLIENT = (3U << 0); +static constexpr uint8_t MODE_SERVER = (4U << 0); +static constexpr uint8_t STRATUM = 2; +static constexpr uint8_t MINPOLL = 4; -enum TNtpMode { - NTP_MODE_CLIENT = (3 << 0), - NTP_MODE_SERVER = (4 << 0) -}; - -enum TNtpStratum { - NTP_STRATUM = 2 -}; - -enum TNtpPoll { - NTP_MINPOLL = 4 -}; - -struct TNtpPacket { +struct Packet { uint8_t LiVnMode; uint8_t Stratum; uint8_t Poll; @@ -68,4 +57,45 @@ struct TNtpPacket { uint32_t TransmitTimestamp_f; }__attribute__((packed)); -#endif /* NTP_H_ */ +struct TimeStamp { + uint32_t nSeconds; + uint32_t nFraction; +}; + +struct time_t { + int32_t tv_sec; + int32_t tv_usec; +}; + +enum class Status { + STOPPED, IDLE, WAITING, FAILED +}; + +static constexpr char STATUS[4][8] = { "Stopped", "Idle", "Waiting", "Failed" }; + +enum class Modes { + BASIC, INTERLEAVED, UNKNOWN +}; + +inline void normalize_time(ntp::time_t *r) { + r->tv_sec += r->tv_usec / 1000000; + r->tv_usec -= r->tv_usec / 1000000 * 1000000; + + if (r->tv_sec > 0 && r->tv_usec < 0) { + r->tv_sec -= 1; + r->tv_usec += 1000000; + } else if (r->tv_sec < 0 && r->tv_usec > 0) { + r->tv_sec += 1; + r->tv_usec -= 1000000; + } +} + +inline void sub_time(struct ntp::time_t *r, const struct ntp::time_t *x, const struct ntp::time_t *y) { + r->tv_sec = x->tv_sec - y->tv_sec; + r->tv_usec = x->tv_usec - y->tv_usec; + + normalize_time(r); +} +} // namespace ntp + +#endif /* NET_PROTOCOL_NTP_H_ */ diff --git a/lib-network/include/net/protocol/tcp.h b/lib-network/include/net/protocol/tcp.h new file mode 100755 index 00000000..b20047f2 --- /dev/null +++ b/lib-network/include/net/protocol/tcp.h @@ -0,0 +1,62 @@ +/** + * @file tcp.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_PROTOCOL_TCP_H_ +#define NET_PROTOCOL_TCP_H_ + +#include + +#include "net/protocol/ethernet.h" +#include "net/protocol/ip4.h" + +#if !defined (PACKED) +# define PACKED __attribute__((packed)) +#endif + +struct t_tcp_packet { + uint16_t srcpt; /* 2 */ + uint16_t dstpt; /* 4 */ + uint32_t seqnum; /* 8 */ + uint32_t acknum; /* 12 */ + uint8_t offset; /* 13 */ + uint8_t control; /* 14 */ + uint16_t window; /* 16 */ + uint16_t checksum; /* 18 */ + uint16_t urgent; /* 20 */ +#define TCP_HEADER_SIZE 20 +#define TCP_OPTIONS_SIZE 40 /* Assuming maximum TCP options size is 40 bytes */ +#define TCP_DATA_SIZE (MTU_SIZE - TCP_HEADER_SIZE - sizeof(struct ip4_header) - TCP_OPTIONS_SIZE) + uint8_t data[MTU_SIZE - TCP_HEADER_SIZE - sizeof(struct ip4_header)]; +} PACKED; + +struct t_tcp { + struct ether_header ether; + struct ip4_header ip4; + struct t_tcp_packet tcp; +} PACKED; + +#define IPv4_UDP_HEADERS_SIZE (sizeof(struct ip4_header) + UDP_HEADER_SIZE) /* IP | UDP */ + +#endif /* NET_PROTOCOL_TCP_H_ */ diff --git a/lib-gd32/include/gd32_micros.h b/lib-network/include/net/protocol/udp.h old mode 100644 new mode 100755 similarity index 58% rename from lib-gd32/include/gd32_micros.h rename to lib-network/include/net/protocol/udp.h index 14e654dd..49bd5ec2 --- a/lib-gd32/include/gd32_micros.h +++ b/lib-network/include/net/protocol/udp.h @@ -1,8 +1,8 @@ /** - * @file gd32_micros.h + * @file udp.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,33 +23,34 @@ * THE SOFTWARE. */ -#ifndef GD32_MICROS_H_ -#define GD32_MICROS_H_ +#ifndef NET_PROTOCOL_UDP_H_ +#define NET_PROTOCOL_UDP_H_ #include -#include "gd32.h" +#include "net/protocol/ethernet.h" +#include "net/protocol/ip4.h" -#if defined (GD32F4XX) && !defined(MICROS_DO_NOT_USE_TIMER4) -static inline uint32_t micros() { - return TIMER_CNT(TIMER4); -} -#else -static inline uint32_t micros() { - static uint32_t nMicrosPrevious; - static uint32_t nResult; - const auto nMicros = DWT->CYCCNT / (MCU_CLOCK_FREQ / 1000000U); - - if (nMicros > nMicrosPrevious) { - nResult += (nMicros - nMicrosPrevious); - } else { - nResult += ((UINT32_MAX/ (MCU_CLOCK_FREQ / 1000000U)) - nMicrosPrevious + nMicros); - } - - nMicrosPrevious = nMicros; - - return nResult; -} +#if !defined (PACKED) +# define PACKED __attribute__((packed)) #endif -#endif /* GD32_MICROS_H_ */ +struct t_udp_packet { + uint16_t source_port; /* 2 */ + uint16_t destination_port; /* 4 */ + uint16_t len; /* 6 */ + uint16_t checksum; /* 8 */ +#define UDP_HEADER_SIZE 8 +#define UDP_DATA_SIZE (MTU_SIZE - UDP_HEADER_SIZE - sizeof(struct ip4_header)) + uint8_t data[UDP_DATA_SIZE]; +}PACKED; + +struct t_udp { + struct ether_header ether; + struct ip4_header ip4; + struct t_udp_packet udp; +} PACKED; + +#define UDP_PACKET_HEADERS_SIZE (sizeof(struct ether_header) + IPv4_UDP_HEADERS_SIZE) /* ETH | IP | UDP */ + +#endif /* NET_PROTOCOL_UDP_H_ */ diff --git a/lib-network/include/netif.h b/lib-network/include/netif.h new file mode 100755 index 00000000..5e7f5dc0 --- /dev/null +++ b/lib-network/include/netif.h @@ -0,0 +1,168 @@ +/** + * @file netif.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NETIF_H_ +#define NETIF_H_ + +#include + +#include "netif.h" +#include "ip4_address.h" + +#include "debug.h" + +#ifndef NETIF_MAX_HWADDR_LEN +# define NETIF_MAX_HWADDR_LEN 6U +#endif + +namespace net { +struct ip_addr { + uint32_t addr; +}; + +typedef struct ip_addr ip4_addr_t; + +struct netif { + static constexpr uint8_t NETIF_FLAG_LINK_UP = (1U << 0); + static constexpr uint8_t NETIF_FLAG_DHCP_OK = (1U << 1); + static constexpr uint8_t NETIF_FLAG_AUTOIP_OK = (1U << 2); + static constexpr uint8_t NETIF_FLAG_STATICIP_OK = (1U << 3); + + struct ip_addr ip; + struct ip_addr netmask; + struct ip_addr gw; + struct ip_addr broadcast_ip; + struct ip_addr secondary_ip; + + uint8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + uint8_t flags; + + const char *hostname; + + void *dhcp; + void *acd; + void *autoip; +}; + +struct NetifReason { + static constexpr uint16_t NSC_NONE = 0x0000; + static constexpr uint16_t NSC_LINK_CHANGED = 0x0004; + static constexpr uint16_t NSC_IPV4_ADDRESS_CHANGED = 0x0010; + static constexpr uint16_t NSC_IPV4_GATEWAY_CHANGED = 0x0020; + static constexpr uint16_t NSC_IPV4_NETMASK_CHANGED = 0x0040; + static constexpr uint16_t NSC_IPV4_SETTINGS_CHANGED = 0x0080; + static constexpr uint16_t NSC_IPV4_ADDR_VALID = 0x0400; +}; + +struct ipv4_changed { + ip4_addr_t old_address; + ip4_addr_t old_netmask; + ip4_addr_t old_gw; +}; + +struct link_changed { + /** 1: up; 0: down */ + uint8_t state; +} ; + +union netif_ext_callback_args_t { + struct link_changed link_changed; + struct ipv4_changed ipv4_changed; +}; + +namespace globals { +extern struct netif netif_default; +} // namespace globals + +typedef void (* netif_ext_callback_fn)(const uint16_t reason, const netif_ext_callback_args_t *args); + +inline void netif_set_flags(uint8_t flags) { + globals::netif_default.flags |= flags; +} + +inline void netif_clear_flags(uint8_t flags) { + globals::netif_default.flags &= static_cast(~flags); +} + +inline bool netif_dhcp() { + return (globals::netif_default.flags & netif::NETIF_FLAG_DHCP_OK) == netif::NETIF_FLAG_DHCP_OK; +} + +inline bool netif_autoip() { + return (globals::netif_default.flags & netif::NETIF_FLAG_AUTOIP_OK) == netif::NETIF_FLAG_AUTOIP_OK; +} + +inline uint32_t netif_ipaddr() { + return globals::netif_default.ip.addr; +} + +inline uint32_t netif_netmask() { + return globals::netif_default.netmask.addr; +} + +inline uint32_t netif_gw() { + return globals::netif_default.gw.addr; +} + +inline void netif_set_hostname(const char *hostname) { + globals::netif_default.hostname = hostname; +} + +inline const char *netif_hostname() { + return globals::netif_default.hostname; +} + +inline uint32_t netif_secondary_ipaddr() { + return globals::netif_default.secondary_ip.addr; +} + +inline uint32_t netif_broadcast_ipaddr() { + return globals::netif_default.broadcast_ip.addr; +} + +inline const uint8_t *netif_hwaddr() { + return globals::netif_default.hwaddr; +} +void netif_init(); +void netif_set_ipaddr(const ip4_addr_t ipaddr); +void netif_set_netmask(const ip4_addr_t netmask); +void netif_set_gw(const ip4_addr_t gw); +void netif_set_addr(const ip4_addr_t ipaddr, const ip4_addr_t netmask, const ip4_addr_t gw); + +void netif_add_ext_callback(netif_ext_callback_fn fn); + +/** + * Link + */ + +void netif_set_link_up(); +void netif_set_link_down(); + +inline bool netif_is_link_up() { + return (globals::netif_default.flags & netif::NETIF_FLAG_LINK_UP) == netif::NETIF_FLAG_LINK_UP; +} +} // namespace net + +#endif /* NETIF_H_ */ diff --git a/lib-network/include/network.h b/lib-network/include/network.h index da334071..7fe09f45 100644 --- a/lib-network/include/network.h +++ b/lib-network/include/network.h @@ -2,7 +2,7 @@ * @file network.h * */ -/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,117 +28,25 @@ #include -#define IP2STR(addr) (addr & 0xFF), ((addr >> 8) & 0xFF), ((addr >> 16) & 0xFF), ((addr >> 24) & 0xFF) -#define IPSTR "%d.%d.%d.%d" - -#define MAC2STR(mac) static_cast(mac[0]),static_cast(mac[1]),static_cast(mac[2]),static_cast(mac[3]), static_cast(mac[4]), static_cast(mac[5]) -#define MACSTR "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" +#include "ip4_address.h" namespace network { -static constexpr auto STORE = 96; ///< Configuration store in bytes -static constexpr auto IP_SIZE = 4U; -static constexpr auto MAC_SIZE = 6U; -static constexpr auto HOSTNAME_SIZE = 64U; ///< Including a terminating null byte. -static constexpr auto DOMAINNAME_SIZE = 64U; ///< Including a terminating null byte. -static constexpr auto IP4_BROADCAST = 0xffffffff; namespace dhcp { enum class Mode: uint8_t { INACTIVE = 0x00, ///< The IP address was not obtained via DHCP ACTIVE = 0x01, ///< The IP address was obtained via DHCP UNKNOWN = 0x02 ///< The system cannot determine if the address was obtained via DHCP }; -enum class ClientStatus { - IDLE, RENEW, GOT_IP, RETRYING, FAILED -}; } // namespace dhcp - -static constexpr uint32_t convert_to_uint(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d) { - return static_cast(a) | - static_cast(b) << 8 | - static_cast(c) << 16 | - static_cast(d) << 24; -} - -inline bool is_netmask_valid(uint32_t nNetMask) { - if (nNetMask == 0) { - return false; - } - nNetMask = __builtin_bswap32(nNetMask); - return !(nNetMask & (~nNetMask >> 1)); - -} -/** - * The private address ranges are defined in RFC1918. - */ -inline bool is_private_ip(const uint32_t nIp) { - const uint8_t n = (nIp >> 8) & 0xFF; - - switch (nIp & 0xFF) { - case 10: - return true; - break; - case 172: - return (n >= 16) && (n < 32); - case 192: - return n == 168; - default: - break; - } - - return false; -} - -inline bool is_multicast_ip(const uint32_t nIp) { - if ((nIp & 0xE0) != 0xE0) { - return false; - } - - if ((nIp & 0xFFFFEF) == 0x0000E0) { // 224.0.0.0 to 224.0.0.255 Local subnetwork - return false; - } - - if ((nIp & 0xFFFFEF) == 0x0100E0) { // 224.0.1.0 to 224.0.1.255 Internetwork control - return false; - } - - return true; -} - -inline uint32_t cidr_to_netmask(const uint8_t nCIDR) { - if (nCIDR != 0) { - const auto nNetmask = __builtin_bswap32(static_cast(~0x0) << (32 - nCIDR)); - return nNetmask; - } - - return 0; -} - -void display_emac_config(); -void display_emac_start(); -void display_emac_status(const bool isLinkUp); -void display_ip(); -void display_netmask(); -void display_gateway(); -void display_hostname(); -void display_dhcp_status(network::dhcp::ClientStatus nStatus); -void display_emac_shutdown(); - -void mdns_announcement(); -void mdns_shutdown(); } // namespace network -class NetworkStore { -public: - virtual ~NetworkStore() {} - - virtual void SaveIp(uint32_t nIp)=0; - virtual void SaveNetMask(uint32_t nNetMask)=0; - virtual void SaveGatewayIp(uint32_t nGatewayIp)=0; - virtual void SaveHostName(const char *pHostName, uint32_t nLength)=0; - virtual void SaveDhcp(bool bIsDhcpUsed)=0; -}; - -#if defined (BARE_METAL) +#if defined(__linux__) || defined (__APPLE__) +# if defined (CONFIG_NETWORK_USE_MINIMUM) +# include "linux/minimum/network.h" +# else +# include "linux/network.h" +# endif +#else # if defined (ESP8266) # include "esp8266/network.h" # elif defined (NO_EMAC) @@ -146,8 +54,6 @@ class NetworkStore { # else # include "emac/network.h" # endif -#else -# include "linux/network.h" #endif #endif /* NETWORK_H_ */ diff --git a/lib-network/include/networkconst.h b/lib-network/include/networkconst.h index 4809ea1b..185d103c 100644 --- a/lib-network/include/networkconst.h +++ b/lib-network/include/networkconst.h @@ -2,7 +2,7 @@ * @file networkconst.h * */ -/* Copyright (C) 2019-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-network/include/networkparams.h b/lib-network/include/networkparams.h index c975b87d..33008df0 100644 --- a/lib-network/include/networkparams.h +++ b/lib-network/include/networkparams.h @@ -29,6 +29,7 @@ #include #include "network.h" +#include "configstore.h" namespace networkparams { namespace defaults { @@ -79,26 +80,27 @@ struct Mask { class NetworkParamsStore { public: - virtual ~NetworkParamsStore() {} + static void Update(const struct networkparams::Params *pParams) { + ConfigStore::Get()->Update(configstore::Store::NETWORK, pParams, sizeof(struct networkparams::Params)); + } - virtual void Update(const networkparams::Params *pNetworkParams)=0; - virtual void Copy(networkparams::Params *pNetworkParams)=0; + static void Copy(struct networkparams::Params *pParams) { + ConfigStore::Get()->Copy(configstore::Store::NETWORK, pParams, sizeof(struct networkparams::Params)); + } }; class NetworkParams { public: - NetworkParams(NetworkParamsStore *pNetworkParamsStore); + NetworkParams(); - bool Load(); + void Load(); void Load(const char *pBuffer, uint32_t nLength); - void Builder(const networkparams::Params *ptNetworkParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); + void Builder(const networkparams::Params *pParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); void Save(char *pBuffer, uint32_t nLength, uint32_t& nSize) { Builder(nullptr, pBuffer, nLength, nSize); } - void Dump(); - bool isDhcpUsed() const { return m_Params.bIsDhcpUsed; } @@ -155,13 +157,13 @@ class NetworkParams { static void staticCallbackFunction(void *p, const char *s); private: + void Dump(); void callbackFunction(const char *s); bool isMaskSet(uint32_t nMask) const { return (m_Params.nSetList & nMask) == nMask; } private: - NetworkParamsStore *m_pNetworkParamsStore; networkparams::Params m_Params; }; diff --git a/lib-network/include/networkparamsconst.h b/lib-network/include/networkparamsconst.h index 93aef889..a5af8678 100644 --- a/lib-network/include/networkparamsconst.h +++ b/lib-network/include/networkparamsconst.h @@ -2,7 +2,7 @@ * @file networkparamsconst.h * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,7 +38,6 @@ struct NetworkParamsConst { static const char HOSTNAME[]; static const char NTP_SERVER[]; - static const char NTP_UTC_OFFSET[]; #if defined (ESP8266) static const char NAME_SERVER[]; diff --git a/lib-network/include/networkstore.h b/lib-network/include/networkstore.h new file mode 100755 index 00000000..26fe06cf --- /dev/null +++ b/lib-network/include/networkstore.h @@ -0,0 +1,60 @@ +/** + * @file networkstore.h + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NETWORKSTORE_H_ +#define NETWORKSTORE_H_ + +#include +#include +#include + +#include "networkparams.h" +#include "configstore.h" + +class NetworkStore { +public: + static void SaveIp(uint32_t nIp) { + ConfigStore::Get()->Update(configstore::Store::NETWORK, offsetof(struct networkparams::Params, nLocalIp), &nIp, sizeof(uint32_t), networkparams::Mask::IP_ADDRESS); + } + + static void SaveNetMask(uint32_t nNetMask) { + ConfigStore::Get()->Update(configstore::Store::NETWORK, offsetof(struct networkparams::Params, nNetmask), &nNetMask, sizeof(uint32_t), networkparams::Mask::NET_MASK); + } + + static void SaveGatewayIp(uint32_t nGatewayIp) { + ConfigStore::Get()->Update(configstore::Store::NETWORK, offsetof(struct networkparams::Params, nGatewayIp), &nGatewayIp, sizeof(uint32_t), networkparams::Mask::DEFAULT_GATEWAY); + } + + static void SaveHostName(const char *pHostName, uint32_t nLength) { + nLength = std::min(nLength,static_cast(network::HOSTNAME_SIZE)); + ConfigStore::Get()->Update(configstore::Store::NETWORK, offsetof(struct networkparams::Params, aHostName), pHostName, nLength, networkparams::Mask::HOSTNAME); + } + + static void SaveDhcp(bool bIsDhcpUsed) { + ConfigStore::Get()->Update(configstore::Store::NETWORK, offsetof(struct networkparams::Params, bIsDhcpUsed), &bIsDhcpUsed, sizeof(bool), networkparams::Mask::DHCP); + } +}; + +#endif /* NETWORKSTORE_H_ */ diff --git a/lib-network/include/ntpclient.h b/lib-network/include/ntpclient.h deleted file mode 100644 index a8eb05b7..00000000 --- a/lib-network/include/ntpclient.h +++ /dev/null @@ -1,96 +0,0 @@ -/** - * @file ntpclient.h - * - */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef NTPCLIENT_H_ -#define NTPCLIENT_H_ - -#include -#include - -#include "ntp.h" - -namespace ntpclient { -enum class Status { - IDLE, FAILED, STOPPED, WAITING -}; - -void display_status(Status status); -} // namespace ntpclient - -class NtpClient { -public: - NtpClient(uint32_t nServerIp = 0); - - void Start(); - void Stop(); - void Run(); - - void Print(); - - ntpclient::Status GetStatus() { - return m_Status; - } - - static NtpClient *Get() { - return s_pThis; - } - -private: - void SetUtcOffset(float fUtcOffset); - void GetTimeNtpFormat(uint32_t &nSeconds, uint32_t &nFraction); - void Send(); - bool Receive(uint8_t& LiVnMode); - - struct TimeStamp { - uint32_t nSeconds; - uint32_t nFraction; - }; - - void Difference(const struct TimeStamp *Start, const struct TimeStamp *Stop, int32_t &nDiffSeconds, uint32_t &nDiffFraction); - int SetTimeOfDay(); - - void PrintNtpTime(const char *pText, const struct TimeStamp *pNtpTime); - -private: - uint32_t m_nServerIp; - int32_t m_nUtcOffset; - int32_t m_nHandle { -1 }; - ntpclient::Status m_Status { ntpclient::Status::IDLE }; - struct TNtpPacket m_Request; - uint32_t m_MillisRequest { 0 }; - uint32_t m_MillisLastPoll { 0 }; - - struct TimeStamp T1 { 0, 0 }; // time request sent by client - struct TimeStamp T2 { 0, 0 }; // time request received by server - struct TimeStamp T3 { 0, 0 }; // time reply sent by server - struct TimeStamp T4 { 0, 0 }; // time reply received by client - - int32_t m_nOffsetSeconds { 0 }; - uint32_t m_nOffsetMicros { 0 }; - - static NtpClient *s_pThis; -}; - -#endif /* NTPCLIENT_H_ */ diff --git a/lib-network/src/apps/ntp/ntpclient.cpp b/lib-network/src/apps/ntp/ntpclient.cpp deleted file mode 100644 index 9d2a68d6..00000000 --- a/lib-network/src/apps/ntp/ntpclient.cpp +++ /dev/null @@ -1,365 +0,0 @@ -/** - * @file ntpclient.cpp - * - */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#include -#include - -#include "ntpclient.h" -#include "ntp.h" - -#include "utc.h" - -#include "network.h" -#include "hardware.h" - -#include "debug.h" - -static constexpr auto RETRIES = 3; -static constexpr auto TIMEOUT_MILLIS = 3000; // 3 seconds -static constexpr auto POLL_SECONDS = 1024; // 2ˆ10 -static constexpr auto JAN_1970 = 0x83aa7e80; // 2208988800 1970 - 1900 in seconds - -/* How to multiply by 4294.967296 quickly (and not quite exactly) - * without using floating point or greater than 32-bit integers. - * If you want to fix the last 12 microseconds of error, add in - * (2911*(x))>>28) - */ -#define NTPFRAC(x) ( 4294U*static_cast(x) + ( (1981U*static_cast(x))>>11 ) + ((2911U*static_cast(x))>>28) ) - -/* The reverse of the above, needed if we want to set our microsecond - * clock (via clock_settime) based on the incoming time in NTP format. - * Basically exact. - */ -#define USEC(x) ( ( (x) >> 12 ) - 759 * ( ( ( (x) >> 10 ) + 32768 ) >> 16 ) ) - -/* -Timestamp Name ID When Generated ----------------------------------------------------------------- -Originate Timestamp T1 time request sent by client -Receive Timestamp T2 time request received by server -Transmit Timestamp T3 time reply sent by server -Destination Timestamp T4 time reply received by client -*/ - -NtpClient *NtpClient::s_pThis; - -NtpClient::NtpClient(uint32_t nServerIp): m_nServerIp(nServerIp) { - DEBUG_ENTRY - assert(s_pThis == nullptr); - s_pThis = this; - - if (m_nServerIp == 0) { - m_nServerIp = Network::Get()->GetNtpServerIp(); - } - - SetUtcOffset(Network::Get()->GetNtpUtcOffset()); - - memset(&m_Request, 0, sizeof m_Request); - - m_Request.LiVnMode = NTP_VERSION | NTP_MODE_CLIENT; - m_Request.Poll = 10; // Poll: 1024 seconds - m_Request.ReferenceID = ('A' << 0) | ('V' << 8) | ('S' << 16); - - DEBUG_EXIT -} - -void NtpClient::SetUtcOffset(float fUtcOffset) { - // https://en.wikipedia.org/wiki/List_of_UTC_time_offsets - m_nUtcOffset = Utc::Validate(fUtcOffset); -} - -/* - * Seconds and Fractions since 01.01.1900 - */ -void NtpClient::GetTimeNtpFormat(uint32_t &nSeconds, uint32_t &nFraction) { - struct timeval now; - gettimeofday(&now, nullptr); - nSeconds = static_cast(now.tv_sec - m_nUtcOffset) + JAN_1970; - nFraction = NTPFRAC(now.tv_usec); -} - -void NtpClient::Send() { - GetTimeNtpFormat(T1.nSeconds, T1.nFraction); - - m_Request.OriginTimestamp_s = __builtin_bswap32(T1.nSeconds); - m_Request.OriginTimestamp_f = __builtin_bswap32(T1.nFraction); - - Network::Get()->SendTo(m_nHandle, &m_Request, sizeof m_Request, m_nServerIp, NTP_UDP_PORT); -} - -bool NtpClient::Receive(uint8_t& LiVnMode) { - uint32_t nFromIp; - uint16_t nFromPort; - TNtpPacket *pReply; - - const auto nBytesReceived = Network::Get()->RecvFrom(m_nHandle, const_cast(reinterpret_cast(&pReply)), &nFromIp, &nFromPort); - - if (__builtin_expect((nBytesReceived != sizeof(struct TNtpPacket)), 1)) { - return false; - } - - GetTimeNtpFormat(T4.nSeconds, T4.nFraction); - - if (__builtin_expect((nFromIp != m_nServerIp), 0)) { - DEBUG_PUTS("nFromIp != m_nServerIp"); - return false; - } - - LiVnMode = pReply->LiVnMode; - - T2.nSeconds = __builtin_bswap32(pReply->ReceiveTimestamp_s); - T2.nFraction = __builtin_bswap32(pReply->ReceiveTimestamp_f); - - T3.nSeconds = __builtin_bswap32(pReply->TransmitTimestamp_s); - T3.nFraction = __builtin_bswap32(pReply->TransmitTimestamp_f); - - PrintNtpTime("Originate", &T1); - PrintNtpTime("Receive", &T2); - PrintNtpTime("Transmit", &T3); - PrintNtpTime("Destination", &T4); - - return true; -} - -void NtpClient::Difference(const struct TimeStamp *Start, const struct TimeStamp *Stop, int32_t &nDiffSeconds, uint32_t &nDiffMicros) { - nDiffSeconds = static_cast(Stop->nSeconds - Start->nSeconds); - uint32_t nDiffFraction; - - if (Stop->nFraction >= Start->nFraction) { - nDiffFraction = Stop->nFraction - Start->nFraction; - } else { - nDiffFraction = Start->nFraction - Stop->nFraction; - nDiffFraction = ~nDiffFraction; - nDiffSeconds -= 1; - } - - nDiffMicros = USEC(nDiffFraction); - - DEBUG_PRINTF("Seconds %u - %u = %d", Stop->nSeconds, Start->nSeconds, nDiffSeconds); - DEBUG_PRINTF("Micros %u - %u = %u", USEC(Stop->nFraction), USEC(Start->nFraction), nDiffMicros); -} - -int NtpClient::SetTimeOfDay() { - int32_t nDiffSeconds1, nDiffSeconds2 ; - uint32_t nDiffFraction1, nDiffFraction2; - - Difference(&T1, &T2, nDiffSeconds1, nDiffFraction1); - Difference(&T4, &T3, nDiffSeconds2, nDiffFraction2); - - m_nOffsetSeconds = nDiffSeconds1 + nDiffSeconds2; - m_nOffsetMicros = nDiffFraction1 + nDiffFraction2; - - if (m_nOffsetMicros >= 1000000u) { - m_nOffsetMicros -= 1000000u; - m_nOffsetSeconds += 1; - } - - m_nOffsetSeconds /= 2; - m_nOffsetMicros /= 2; - - struct timeval tv; - - tv.tv_sec = static_cast(T4.nSeconds - JAN_1970) + m_nOffsetSeconds + m_nUtcOffset; - tv.tv_usec = (static_cast(USEC(T4.nFraction)) + static_cast(m_nOffsetMicros)); - - if (tv.tv_usec >= 1000000) { - tv.tv_sec++; - tv.tv_usec = 1000000 - tv.tv_usec; - } - - DEBUG_PRINTF("(%ld, %d) %s ", tv.tv_sec, static_cast(tv.tv_usec) , tv.tv_usec >= 1E6 ? "!" : ""); - DEBUG_PRINTF("%d %u",m_nOffsetSeconds, m_nOffsetMicros); - - return settimeofday(&tv, nullptr); -} - -void NtpClient::Start() { - DEBUG_ENTRY - - if (m_nServerIp == 0) { - m_Status = ntpclient::Status::FAILED; - ntpclient::display_status(ntpclient::Status::FAILED); - DEBUG_EXIT - return; - } - - if ((m_Status != ntpclient::Status::IDLE) && (m_Status != ntpclient::Status::STOPPED)) { - DEBUG_EXIT - return; - } - - m_nHandle = Network::Get()->Begin(NTP_UDP_PORT); - assert(m_nHandle != -1); - - ntpclient::display_status(ntpclient::Status::IDLE); - - const auto nNow = Hardware::Get()->Millis(); - uint32_t nRetries; - - for (nRetries = 0; nRetries < RETRIES; nRetries++) { - Send(); - - uint8_t LiVnMode = 0; - - while (!Receive(LiVnMode)) { -#if defined (HAVE_NET_HANDLE) - net_handle(); -#endif - if ((Hardware::Get()->Millis() - nNow) > TIMEOUT_MILLIS) { - break; - } - } - - if ((LiVnMode & NTP_MODE_SERVER) == NTP_MODE_SERVER) { - if (SetTimeOfDay() == 0) { - m_Status = ntpclient::Status::IDLE; - } else { - // Error - } - } else { - m_Status = ntpclient::Status::FAILED; - DEBUG_PUTS("!>> Invalid reply <Millis(); - - if (nRetries == RETRIES) { - m_Status = ntpclient::Status::FAILED; - ntpclient::display_status(ntpclient::Status::FAILED); - } - - DEBUG_PRINTF("nRetries=%d, m_Status=%d", nRetries, static_cast(m_Status)); - -#if !defined(DISABLE_RTC) - if (m_Status != ntpclient::Status::FAILED) { - printf("Set RTC from System Clock\n"); - HwClock::Get()->SysToHc(); -#ifndef NDEBUG - const auto rawtime = time(nullptr); - printf(asctime(localtime(&rawtime))); -#endif - } -#endif - - DEBUG_EXIT -} - -void NtpClient::Stop() { - DEBUG_ENTRY - - if (m_Status == ntpclient::Status::STOPPED) { - return; - } - - m_nHandle = Network::Get()->End(NTP_UDP_PORT); - m_Status = ntpclient::Status::STOPPED; - - ntpclient::display_status(ntpclient::Status::STOPPED); - - DEBUG_EXIT -} - -void NtpClient::Run() { - if (__builtin_expect((m_nServerIp == 0), 0)) { - return; - } - - if ((m_Status == ntpclient::Status::IDLE) || (m_Status == ntpclient::Status::FAILED)) { - if (__builtin_expect(((Hardware::Get()->Millis() - m_MillisLastPoll) > (1000 * POLL_SECONDS)), 0)) { - Send(); - m_MillisRequest = Hardware::Get()->Millis(); - m_Status = ntpclient::Status::WAITING; - DEBUG_PUTS("ntpclient::Status::WAITING"); - } - - return; - } - - if (m_Status == ntpclient::Status::WAITING) { - uint8_t LiVnMode; - - if (!Receive(LiVnMode)) { - if (__builtin_expect(((Hardware::Get()->Millis() - m_MillisRequest) > TIMEOUT_MILLIS), 0)) { - m_Status = ntpclient::Status::FAILED; - ntpclient::display_status(ntpclient::Status::FAILED); - DEBUG_PUTS("ntpclient::Status::FAILED"); - } - - return; - } - - if (__builtin_expect(((LiVnMode & NTP_MODE_SERVER) == NTP_MODE_SERVER), 1)) { - m_MillisLastPoll = Hardware::Get()->Millis(); - - if (SetTimeOfDay() == 0) { -#ifndef NDEBUG - const auto nTime = time(nullptr); - const auto *pLocalTime = localtime(&nTime); - DEBUG_PRINTF("%.4d/%.2d/%.2d %.2d:%.2d:%.2d", pLocalTime->tm_year, pLocalTime->tm_mon, pLocalTime->tm_mday, pLocalTime->tm_hour, pLocalTime->tm_min, pLocalTime->tm_sec); -#endif - } else { - // Error - } - } else { - DEBUG_PUTS("!>> Invalid reply <(pNtpTime->nSeconds - JAN_1970); - const auto *pTm = localtime(&nSeconds); - printf("%s %02d:%02d:%02d.%06d %04d [%u]\n", pText, pTm->tm_hour, pTm->tm_min, pTm->tm_sec, USEC(pNtpTime->nFraction), pTm->tm_year + 1900, pNtpTime->nSeconds); -#endif -} - -static constexpr char STATUS[4][8] = { "Idle", "Failed", "Stopped", "Waiting" }; - -void NtpClient::Print() { - printf("NTP v%d Client\n", NTP_VERSION >> 3); - if (m_nServerIp == 0) { - printf(" Not enabled\n"); - return; - } - printf(" Server : " IPSTR ":%d\n", IP2STR(m_nServerIp), NTP_UDP_PORT); - printf(" Status : %s\n", STATUS[static_cast(m_Status)]); - printf(" UTC offset : %d (seconds)\n", m_nUtcOffset); -#ifndef NDEBUG - PrintNtpTime("Originate", &T1); - PrintNtpTime("Receive", &T2); - PrintNtpTime("Transmit", &T3); - PrintNtpTime("Destination", &T4); -#endif -} diff --git a/lib-network/src/emac/gd32/emac.cpp b/lib-network/src/emac/gd32/emac.cpp index 811fedf3..e482d334 100644 --- a/lib-network/src/emac/gd32/emac.cpp +++ b/lib-network/src/emac/gd32/emac.cpp @@ -2,7 +2,7 @@ * emac.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,117 +30,23 @@ #include "emac/phy.h" +#include "hwclock.h" + #include "debug.h" -extern enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; +extern "C" { +void console_error(const char *); +} +extern void enet_gpio_config(); +extern enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; extern void mac_address_get(uint8_t paddr[]); -static void enet_gpio_config(void) { - DEBUG_ENTRY -#if defined (GD32F10X) || defined (GD32F20X) - rcu_periph_clock_enable(RCU_GPIOA); - rcu_periph_clock_enable(RCU_GPIOB); - rcu_periph_clock_enable(RCU_GPIOC); - rcu_periph_clock_enable(RCU_AF); - - gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8); - - rcu_pll2_config(RCU_PLL2_MUL10); - rcu_osci_on(RCU_PLL2_CK); - rcu_osci_stab_wait(RCU_PLL2_CK); - /* get 50MHz from CK_PLL2 on CKOUT0 pin (PA8) to clock the PHY */ -# if defined (GD32F10X_CL) - rcu_ckout0_config(RCU_CKOUT0SRC_CKPLL2); -# else - rcu_ckout0_config(RCU_CKOUT0SRC_CKPLL2,RCU_CKOUT0_DIV1); -# endif - gpio_ethernet_phy_select(GPIO_ENET_PHY_RMII); - - /* PA1: ETH_RMII_REF_CLK */ - gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_1); - /* PA2: ETH_MDIO */ - gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2); - /* PA7: ETH_RMII_CRS_DV */ - gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_7); - - /* PC1: ETH_MDC */ - gpio_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1); - /* PC4: ETH_RMII_RXD0 */ - gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_4); - /* PC5: ETH_RMII_RXD1 */ - gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_5); - - /* PB11: ETH_RMII_TX_EN */ - gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11); - /* PB12: ETH_RMII_TXD0 */ - gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12); - /* PB13: ETH_RMII_TXD1 */ - gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13); -#else - rcu_periph_clock_enable(RCU_GPIOA); - rcu_periph_clock_enable(RCU_GPIOB); - rcu_periph_clock_enable(RCU_GPIOC); - rcu_periph_clock_enable(RCU_SYSCFG); - - gpio_af_set(GPIOA, GPIO_AF_0, GPIO_PIN_8); - gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8); - gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,GPIO_PIN_8); - - /* choose DIV4 to get 50MHz from 200MHz on CKOUT0 pin (PA8) to clock the PHY */ - rcu_ckout0_config(RCU_CKOUT0SRC_PLLP, RCU_CKOUT0_DIV4); - syscfg_enet_phy_interface_config(SYSCFG_ENET_PHY_RMII); - - /* PA1: ETH_RMII_REF_CLK */ - gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1); - gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,GPIO_PIN_1); - - /* PA2: ETH_MDIO */ - gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2); - gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,GPIO_PIN_2); - - /* PA7: ETH_RMII_CRS_DV */ - gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7); - gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,GPIO_PIN_7); - - gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_1); - gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_2); - gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_7); - - /* PB11: ETH_RMII_TX_EN */ - gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11); - gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,GPIO_PIN_11); - - /* PB12: ETH_RMII_TXD0 */ - gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12); - gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,GPIO_PIN_13); - - /* PB13: ETH_RMII_TXD1 */ - gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13); - gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,GPIO_PIN_14); - - gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_11); - gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_12); - gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_13); - - /* PC1: ETH_MDC */ - gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1); - gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,GPIO_PIN_1); - - /* PC4: ETH_RMII_RXD0 */ - gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4); - gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,GPIO_PIN_4); - - /* PC5: ETH_RMII_RXD1 */ - gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5); - gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,GPIO_PIN_5); - - gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_1); - gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_4); - gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_5); +#if defined (CONFIG_ENET_ENABLE_PTP) +# include "gd32_ptp.h" +enet_descriptors_struct ptp_rxdesc_tab[ENET_RXBUF_NUM] __attribute__((aligned(4))); +enet_descriptors_struct ptp_txdesc_tab[ENET_TXBUF_NUM] __attribute__((aligned(4))); #endif - DEBUG_EXIT -} /* * Public function @@ -164,30 +70,40 @@ void __attribute__((cold)) emac_config() { rcu_periph_clock_enable(RCU_ENETTX); rcu_periph_clock_enable(RCU_ENETRX); - enet_deinit(); - enet_software_reset(); + enet_deinit(ENETx); + enet_software_reset(ENETx); - net::phy_config(PHY_ADDRESS); + if(!net::phy_config(PHY_ADDRESS)) { + console_error("net::phy_config(PHY_ADDRESS)"); + } DEBUG_EXIT } -void __attribute__((cold)) emac_start(uint8_t mac_address[], net::Link& link) { +void emac_adjust_link(const net::PhyStatus phyStatus) { DEBUG_ENTRY - DEBUG_PRINTF("ENET_RXBUF_NUM=%u, ENET_TXBUF_NUM=%u", ENET_RXBUF_NUM, ENET_TXBUF_NUM); - net::PhyStatus phyStatus; - net::phy_start(PHY_ADDRESS, phyStatus); - - link = phyStatus.link; + printf("Link %s, %d, %s\n", + phyStatus.link == net::Link::STATE_UP ? "Up" : "Down", + phyStatus.speed == net::Speed::SPEED10 ? 10 : 100, + phyStatus.duplex == net::Duplex::DUPLEX_HALF ? "HALF" : "FULL"); #ifndef NDEBUG { uint16_t phy_value; +#if defined (GD32H7XX) + ErrStatus phy_state = enet_phy_write_read(ENETx, ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value); +#else ErrStatus phy_state = enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value); +#endif printf("BCR: %.4x %s\n", phy_value, phy_state == SUCCESS ? "SUCCES" : "ERROR" ); +#if defined (GD32H7XX) + enet_phy_write_read(ENETx, ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_state = enet_phy_write_read(ENETx, ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); +#else enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); phy_state = enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); +#endif printf("BSR: %.4x %s\n", phy_value & (PHY_AUTONEGO_COMPLETE | PHY_LINKED_STATUS | PHY_JABBER_DETECTION), phy_state == SUCCESS ? "SUCCES" : "ERROR" ); } #endif @@ -204,12 +120,11 @@ void __attribute__((cold)) emac_start(uint8_t mac_address[], net::Link& link) { mediamode = ENET_10M_FULLDUPLEX; } - printf("Link %s, %d, %s\n", - phyStatus.link == net::Link::STATE_UP ? "Up" : "Down", - phyStatus.speed == net::Speed::SPEED10 ? 10 : 100, - phyStatus.duplex == net::Duplex::DUPLEX_HALF ? "HALF" : "FULL"); - +#if defined (GD32H7XX) + const auto enet_init_status = enet_init(ENETx, mediamode, ENET_AUTOCHECKSUM_DROP_FAILFRAMES, ENET_CUSTOM); +#else const auto enet_init_status = enet_init(mediamode, ENET_AUTOCHECKSUM_DROP_FAILFRAMES, ENET_CUSTOM); +#endif if (enet_init_status != SUCCESS) {} @@ -218,26 +133,71 @@ void __attribute__((cold)) emac_start(uint8_t mac_address[], net::Link& link) { #ifndef NDEBUG { uint16_t phy_value; +#if defined (GD32H7XX) + ErrStatus phy_state = enet_phy_write_read(ENETx, ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value); +#else ErrStatus phy_state = enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value); +#endif printf("BCR: %.4x %s\n", phy_value, phy_state == SUCCESS ? "SUCCES" : "ERROR" ); +#if defined (GD32H7XX) + enet_phy_write_read(ENETx, ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + phy_state = enet_phy_write_read(ENETx, ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); +#else enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); phy_state = enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); +#endif printf("BSR: %.4x %s\n", phy_value & (PHY_AUTONEGO_COMPLETE | PHY_LINKED_STATUS | PHY_JABBER_DETECTION), phy_state == SUCCESS ? "SUCCES" : "ERROR" ); } #endif + DEBUG_EXIT +} + +void __attribute__((cold)) emac_start(uint8_t mac_address[], net::Link& link) { + DEBUG_ENTRY + DEBUG_PRINTF("ENET_RXBUF_NUM=%u, ENET_TXBUF_NUM=%u", ENET_RXBUF_NUM, ENET_TXBUF_NUM); + + net::PhyStatus phyStatus; + net::phy_start(PHY_ADDRESS, phyStatus); + + link = phyStatus.link; + + emac_adjust_link(phyStatus); mac_address_get(mac_address); +#if defined (GD32H7XX) + enet_mac_address_set(ENETx, ENET_MAC_ADDRESS0, mac_address); +# if defined (CONFIG_ENET_ENABLE_PTP) + enet_ptp_normal_descriptors_chain_init(ENETx, ENET_DMA_TX, ptp_txdesc_tab); + enet_ptp_normal_descriptors_chain_init(ENETx, ENET_DMA_RX, ptp_rxdesc_tab); +# else + enet_descriptors_chain_init(ENETx, ENET_DMA_TX); + enet_descriptors_chain_init(ENETx, ENET_DMA_RX); +# endif +#else enet_mac_address_set(ENET_MAC_ADDRESS0, mac_address); - +# if defined (CONFIG_ENET_ENABLE_PTP) + enet_ptp_normal_descriptors_chain_init(ENET_DMA_TX, ptp_txdesc_tab); + enet_ptp_normal_descriptors_chain_init(ENET_DMA_RX, ptp_rxdesc_tab); +# else enet_descriptors_chain_init(ENET_DMA_TX); enet_descriptors_chain_init(ENET_DMA_RX); +# endif +#endif - for (unsigned i = 0; i < ENET_TXBUF_NUM; i++) { + for (uint32_t i = 0; i < ENET_TXBUF_NUM; i++) { enet_transmit_checksum_config(&txdesc_tab[i], ENET_CHECKSUM_TCPUDPICMP_FULL); } - enet_enable(); +#if defined (CONFIG_ENET_ENABLE_PTP) + gd32_ptp_start(); +# if !defined(DISABLE_RTC) + // Set the System Clock from the Hardware Clock + HwClock::Get()->HcToSys(); +# endif +#endif + + enet_enable(ENETx); DEBUG_EXIT } diff --git a/lib-network/src/emac/gd32/f/emac.cpp b/lib-network/src/emac/gd32/f/emac.cpp new file mode 100644 index 00000000..b33bf4b2 --- /dev/null +++ b/lib-network/src/emac/gd32/f/emac.cpp @@ -0,0 +1,144 @@ +/** + * emac.cpp + * + */ +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "gd32.h" + +#include "debug.h" + +/** + * Needed for older GD32F firmware + */ +#if !defined(GPIO_OSPEED_MAX) +# define GPIO_OSPEED_MAX GPIO_OSPEED_200MHZ +#endif + +void enet_gpio_config() { + DEBUG_ENTRY +#if defined (GD32F10X) || defined (GD32F20X) + rcu_periph_clock_enable(RCU_GPIOA); + rcu_periph_clock_enable(RCU_GPIOB); + rcu_periph_clock_enable(RCU_GPIOC); + rcu_periph_clock_enable(RCU_AF); + + gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8); + + rcu_pll2_config(RCU_PLL2_MUL10); + rcu_osci_on(RCU_PLL2_CK); + rcu_osci_stab_wait(RCU_PLL2_CK); + /* get 50MHz from CK_PLL2 on CKOUT0 pin (PA8) to clock the PHY */ +# if defined (GD32F10X_CL) + rcu_ckout0_config(RCU_CKOUT0SRC_CKPLL2); +# else + rcu_ckout0_config(RCU_CKOUT0SRC_CKPLL2,RCU_CKOUT0_DIV1); +# endif + gpio_ethernet_phy_select(GPIO_ENET_PHY_RMII); + + /* PA1: ETH_RMII_REF_CLK */ + gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_1); + /* PA2: ETH_MDIO */ + gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2); + /* PA7: ETH_RMII_CRS_DV */ + gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_7); + + /* PC1: ETH_MDC */ + gpio_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1); + /* PC4: ETH_RMII_RXD0 */ + gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_4); + /* PC5: ETH_RMII_RXD1 */ + gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_5); + + /* PB11: ETH_RMII_TX_EN */ + gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11); + /* PB12: ETH_RMII_TXD0 */ + gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12); + /* PB13: ETH_RMII_TXD1 */ + gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13); +#else + rcu_periph_clock_enable(RCU_GPIOA); + rcu_periph_clock_enable(RCU_GPIOB); + rcu_periph_clock_enable(RCU_GPIOC); + rcu_periph_clock_enable(RCU_SYSCFG); + + gpio_af_set(GPIOA, GPIO_AF_0, GPIO_PIN_8); + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,GPIO_PIN_8); + + /* choose DIV4 to get 50MHz from 200MHz on CKOUT0 pin (PA8) to clock the PHY */ + rcu_ckout0_config(RCU_CKOUT0SRC_PLLP, RCU_CKOUT0_DIV4); + syscfg_enet_phy_interface_config(SYSCFG_ENET_PHY_RMII); + + /* PA1: ETH_RMII_REF_CLK */ + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,GPIO_PIN_1); + + /* PA2: ETH_MDIO */ + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,GPIO_PIN_2); + + /* PA7: ETH_RMII_CRS_DV */ + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,GPIO_PIN_7); + + gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_1); + gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_2); + gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_7); + + /* PB11: ETH_RMII_TX_EN */ + gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11); + gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,GPIO_PIN_11); + + /* PB12: ETH_RMII_TXD0 */ + gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12); + gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,GPIO_PIN_13); + + /* PB13: ETH_RMII_TXD1 */ + gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13); + gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,GPIO_PIN_14); + + gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_11); + gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_12); + gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_13); + + /* PC1: ETH_MDC */ + gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1); + gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,GPIO_PIN_1); + + /* PC4: ETH_RMII_RXD0 */ + gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4); + gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,GPIO_PIN_4); + + /* PC5: ETH_RMII_RXD1 */ + gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5); + gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,GPIO_PIN_5); + + gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_1); + gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_4); + gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_5); +#endif + DEBUG_EXIT +} diff --git a/lib-network/src/emac/gd32/f/net.cpp b/lib-network/src/emac/gd32/f/net.cpp new file mode 100644 index 00000000..713d281b --- /dev/null +++ b/lib-network/src/emac/gd32/f/net.cpp @@ -0,0 +1,244 @@ +/** + * net.cpp + * + */ +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif + +#include +#include + +#include "gd32.h" +#include "../src/net/net_memcpy.h" + +#include "debug.h" + +#if defined (CONFIG_ENET_ENABLE_PTP) +#include "gd32_ptp.h" + +extern enet_descriptors_struct *dma_current_ptp_rxdesc; +extern enet_descriptors_struct *dma_current_ptp_txdesc; +namespace net { +namespace globals { +extern uint32_t ptpTimestamp[2]; +} // namespace globals +} // namespace net +#endif +extern enet_descriptors_struct *dma_current_rxdesc; +extern enet_descriptors_struct *dma_current_txdesc; + +int emac_eth_recv(uint8_t **ppPacket) { + const auto nLength = enet_desc_information_get(dma_current_rxdesc, RXDESC_FRAME_LENGTH); + + if (nLength > 0) { +#if defined (CONFIG_ENET_ENABLE_PTP) + *ppPacket = reinterpret_cast(dma_current_ptp_rxdesc->buffer1_addr); +#else + *ppPacket = reinterpret_cast(dma_current_rxdesc->buffer1_addr); +#endif + return nLength; + } + + return -1; +} + +#if defined (CONFIG_ENET_ENABLE_PTP) +static void ptpframe_receive_normal_mode() { + net::globals::ptpTimestamp[0] = dma_current_rxdesc->buffer1_addr; + net::globals::ptpTimestamp[1] = dma_current_rxdesc->buffer2_next_desc_addr; + + dma_current_rxdesc->buffer1_addr = dma_current_ptp_rxdesc->buffer1_addr; + dma_current_rxdesc->buffer2_next_desc_addr = dma_current_ptp_rxdesc->buffer2_next_desc_addr; + dma_current_rxdesc->status = ENET_RDES0_DAV; + + if (0 != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)) { + /* clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0U; + } + + assert(0 != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)); + + dma_current_rxdesc = reinterpret_cast(dma_current_ptp_rxdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if (0 != dma_current_ptp_rxdesc->status) { + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_rxdesc = reinterpret_cast(dma_current_ptp_rxdesc->status); + } else { + /* ponter to the next ptp descriptor */ + dma_current_ptp_rxdesc++; + } +} +#else +static void frame_receive() { + dma_current_rxdesc->status = ENET_RDES0_DAV; + + /* check Rx buffer unavailable flag status */ + if (0 != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)) { + /* clear RBU flag */ + ENET_DMA_STAT = ENET_DMA_STAT_RBU; + /* resume DMA reception by writing to the RPEN register*/ + ENET_DMA_RPEN = 0U; + } + + assert(0 != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)); + + dma_current_rxdesc = reinterpret_cast(dma_current_rxdesc->buffer2_next_desc_addr); +} +#endif + +void emac_free_pkt() { + while(0 != (dma_current_rxdesc->status & ENET_RDES0_DAV)) { + __DMB(); + } +#if defined (CONFIG_ENET_ENABLE_PTP) + ptpframe_receive_normal_mode(); +#else + frame_receive(); +#endif +} + +#if defined (CONFIG_ENET_ENABLE_PTP) +inline static void ptpframe_transmit(const uint8_t *pBuffer, const uint32_t nLength, const bool bCaptureTimestamp) { + assert (nullptr != pBuffer); + assert(nLength <= ENET_MAX_FRAME_SIZE); + + auto *pDst = reinterpret_cast(dma_current_ptp_txdesc->buffer1_addr); + net::memcpy(pDst, pBuffer, nLength); + + dma_current_txdesc->control_buffer_size = (nLength & (uint32_t)0x1FFF); + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + const auto dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + const auto dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if ((0 != dma_tbu_flag) || (0 != dma_tu_flag)) { + /* clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0U; + } + + uint32_t timeout = 0; + uint32_t tdes0_ttmss_flag; + + if (bCaptureTimestamp) { + do { + tdes0_ttmss_flag = (dma_current_txdesc->status & ENET_TDES0_TTMSS); + __DMB(); + timeout++; + } while((0 == tdes0_ttmss_flag) && (timeout < UINT32_MAX)); + + DEBUG_PRINTF("timeout=%x %d", timeout, (dma_current_txdesc->status & ENET_TDES0_TTMSS)); + + dma_current_txdesc->status &= ~ENET_TDES0_TTMSS; + + net::globals::ptpTimestamp[0] = dma_current_txdesc->buffer1_addr; + net::globals::ptpTimestamp[1] = dma_current_txdesc->buffer2_next_desc_addr; + } + + dma_current_txdesc->buffer1_addr = dma_current_ptp_txdesc->buffer1_addr; + dma_current_txdesc->buffer2_next_desc_addr = dma_current_ptp_txdesc->buffer2_next_desc_addr; + + assert(0 != (dma_current_txdesc->status & ENET_TDES0_TCHM)); /* chained mode */ + + /* update the current TxDMA descriptor pointer to the next descriptor in TxDMA descriptor table */ + dma_current_txdesc = reinterpret_cast(dma_current_ptp_txdesc->buffer2_next_desc_addr); + /* if it is the last ptp descriptor */ + if(0 != dma_current_ptp_txdesc->status) { + /* pointer back to the first ptp descriptor address in the desc_ptptab list address */ + dma_current_ptp_txdesc = reinterpret_cast(dma_current_ptp_txdesc->status); + } else { + /* pointer to the next ptp descriptor */ + dma_current_ptp_txdesc++; + } +} + +void emac_eth_send(void *pBuffer, uint32_t nLength) { + while (0 != (dma_current_txdesc->status & ENET_TDES0_DAV)) { + __DMB(); + } + + auto nStatus = dma_current_txdesc->status; + nStatus &= ~ENET_TDES0_TTSEN; + dma_current_txdesc->status = nStatus; + + ptpframe_transmit(reinterpret_cast(pBuffer), nLength, false); +} + +void emac_eth_send_timestamp(void *pBuffer, uint32_t nLength) { + while (0 != (dma_current_txdesc->status & ENET_TDES0_DAV)) { + __DMB(); + } + + auto nStatus = dma_current_txdesc->status; + nStatus |= ENET_TDES0_TTSEN; + dma_current_txdesc->status = nStatus; + + ptpframe_transmit(reinterpret_cast(pBuffer), nLength, true); +} +#else +void emac_eth_send(void *pBuffer, uint32_t nLength) { + assert(nullptr != pBuffer); + assert(nLength <= static_cast(ENET_MAX_FRAME_SIZE)); + + while (0 != (dma_current_txdesc->status & ENET_TDES0_DAV)) { + __DMB(); + } + + auto *pDst = reinterpret_cast(dma_current_txdesc->buffer1_addr); + net::memcpy(pDst, pBuffer, nLength); + + /* set the frame length */ + dma_current_txdesc->control_buffer_size = nLength; + /* set the segment of frame, frame is transmitted in one descriptor */ + dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG; + /* enable the DMA transmission */ + dma_current_txdesc->status |= ENET_TDES0_DAV; + + /* check Tx buffer unavailable flag status */ + const auto dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU); + const auto dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU); + + if ((0 != dma_tbu_flag) || (0 != dma_tu_flag)) { + /* clear TBU and TU flag */ + ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag); + /* resume DMA transmission by writing to the TPEN register*/ + ENET_DMA_TPEN = 0; + } + + assert(0 != (dma_current_txdesc->status & ENET_TDES0_TCHM)); /* chained mode */ + + /* update the current TxDMA descriptor pointer to the next descriptor in TxDMA descriptor table*/ + dma_current_txdesc = reinterpret_cast(dma_current_txdesc->buffer2_next_desc_addr); +} +#endif diff --git a/lib-network/src/emac/gd32/net_link_check.cpp b/lib-network/src/emac/gd32/net_link_check.cpp index 15711075..f3efe054 100644 --- a/lib-network/src/emac/gd32/net_link_check.cpp +++ b/lib-network/src/emac/gd32/net_link_check.cpp @@ -25,6 +25,7 @@ #include +#include "emac/phy.h" #include "emac/net_link_check.h" #include "gd32.h" diff --git a/lib-network/src/emac/gd32/net_phy.cpp b/lib-network/src/emac/gd32/net_phy.cpp index 018729ac..693aa290 100644 --- a/lib-network/src/emac/gd32/net_phy.cpp +++ b/lib-network/src/emac/gd32/net_phy.cpp @@ -2,7 +2,7 @@ * net_phy.cpp * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,22 +28,28 @@ #include "emac/phy.h" #include "emac/mmi.h" +#include "hardware.h" #include "gd32.h" #include "debug.h" -extern volatile uint32_t s_nSysTickMillis; - namespace net { - bool phy_read(uint32_t nAddress, const uint32_t nRegister, uint16_t &nValue) { +#if defined (GD32H7XX) + const auto bResult = enet_phy_write_read(ENETx, ENET_PHY_READ, nAddress, nRegister, &nValue) == SUCCESS; +#else const auto bResult = enet_phy_write_read(ENET_PHY_READ, nAddress, nRegister, &nValue) == SUCCESS; +#endif // DEBUG_PRINTF("%d %.2x %.2x %.4x", bResult, nAddress, nRegister, nValue); return bResult; } bool phy_write(uint32_t nAddress, const uint32_t nRegister, uint16_t nValue) { +#if defined (GD32H7XX) + const auto bResult = enet_phy_write_read(ENETx, ENET_PHY_WRITE, nAddress, nRegister, &nValue) == SUCCESS; +#else const auto bResult = enet_phy_write_read(ENET_PHY_WRITE, nAddress, nRegister, &nValue) == SUCCESS; +#endif // DEBUG_PRINTF("%d %.2x %.2x %.4x", bResult, nAddress, nRegister, nValue); return bResult; } @@ -51,11 +57,17 @@ bool phy_write(uint32_t nAddress, const uint32_t nRegister, uint16_t nValue) { bool phy_config(const uint32_t nAddress) { DEBUG_ENTRY +#if defined (GD32H7XX) + uint32_t reg = ENET_MAC_PHY_CTL(ENETx); +#else uint32_t reg = ENET_MAC_PHY_CTL; +#endif reg &= ~ENET_MAC_PHY_CTL_CLR; const uint32_t ahbclk = rcu_clock_freq_get(CK_AHB); + DEBUG_PRINTF("ahbclk=%u", ahbclk); + #if defined GD32F10X_CL if (ENET_RANGE(ahbclk, 20000000U, 35000000U)) { reg |= ENET_MDC_HCLK_DIV16; @@ -89,14 +101,38 @@ bool phy_config(const uint32_t nAddress) { reg |= ENET_MDC_HCLK_DIV42; } else if (ENET_RANGE(ahbclk, 100000000U, 150000000U)) { reg |= ENET_MDC_HCLK_DIV62; - } else if ((ENET_RANGE(ahbclk, 150000000U, 200000000U)) || (200000000U == ahbclk)) { + } else if ((ENET_RANGE(ahbclk, 150000000U, 240000000U)) || (240000000U == ahbclk)) { reg |= ENET_MDC_HCLK_DIV102; } else { return false; } +#elif defined GD32H7XX + if (ENET_RANGE(ahbclk, 20000000U, 35000000U)) { + reg |= ENET_MDC_HCLK_DIV16; + } else if (ENET_RANGE(ahbclk, 35000000U, 60000000U)) { + reg |= ENET_MDC_HCLK_DIV26; + } else if (ENET_RANGE(ahbclk, 60000000U, 100000000U)) { + reg |= ENET_MDC_HCLK_DIV42; + } else if (ENET_RANGE(ahbclk, 100000000U, 150000000U)) { + reg |= ENET_MDC_HCLK_DIV62; + } else if ((ENET_RANGE(ahbclk, 150000000U, 180000000U)) || (180000000U == ahbclk)) { + reg |= ENET_MDC_HCLK_DIV102; + } else if (ENET_RANGE(ahbclk, 250000000U, 300000000U)) { + reg |= ENET_MDC_HCLK_DIV124; + } else if (ENET_RANGE(ahbclk, 300000000U, 350000000U)) { + reg |= ENET_MDC_HCLK_DIV142; + } else if ((ENET_RANGE(ahbclk, 350000000U, 400000000U)) || (400000000U == ahbclk)) { + reg |= ENET_MDC_HCLK_DIV162; + } else { + return false; + } #endif +#if defined (GD32H7XX) + ENET_MAC_PHY_CTL(ENETx) = reg; +#else ENET_MAC_PHY_CTL = reg; +#endif if (!phy_write(nAddress, mmi::REG_BMCR, mmi::BMCR_RESET)) { DEBUG_PUTS("PHY reset failed"); @@ -109,17 +145,17 @@ bool phy_config(const uint32_t nAddress) { * IEEE spec. */ - const auto nMillis = s_nSysTickMillis; + const auto nMillis = Hardware::Get()->Millis(); uint16_t nValue; - while (s_nSysTickMillis - nMillis < 500) { + while (Hardware::Get()->Millis() - nMillis < 500) { if (!phy_read(nAddress, mmi::REG_BMCR, nValue)) { DEBUG_PUTS("PHY status read failed"); return false; } if (!(nValue & mmi::BMCR_RESET)) { - DEBUG_PRINTF("%u", s_nSysTickMillis - nMillis); + DEBUG_PRINTF("%u", Hardware::Get()->Millis() - nMillis); DEBUG_EXIT return true; } @@ -130,7 +166,7 @@ bool phy_config(const uint32_t nAddress) { return false; } - DEBUG_PRINTF("%u", s_nSysTickMillis - nMillis); + DEBUG_PRINTF("%u", Hardware::Get()->Millis() - nMillis); DEBUG_EXIT return true; } diff --git a/lib-network/src/emac/network.cpp b/lib-network/src/emac/network.cpp index 8ad248a3..e993f43b 100755 --- a/lib-network/src/emac/network.cpp +++ b/lib-network/src/emac/network.cpp @@ -2,7 +2,7 @@ * network.cpp * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,29 +23,37 @@ * THE SOFTWARE. */ +#ifdef DEBUG_NETWORK +# undef NDEBUG +#endif + #include +#include #include #include #include #include "network.h" #include "networkparams.h" +#include "networkstore.h" #include "hardware.h" -#include "../net/net.h" -#include "../../config/net_config.h" - #include "emac/emac.h" #include "emac/phy.h" #include "emac/mmi.h" #include "emac/net_link_check.h" +#include "netif.h" +#include "net/autoip.h" +#include "net/dhcp.h" + +#include "../../config/net_config.h" + #include "debug.h" namespace network { void __attribute__((weak)) mdns_announcement() {} -void __attribute__((weak)) mdns_shutdown() {} } // namespace network static constexpr char TO_HEX(const char i) { @@ -56,42 +64,71 @@ static constexpr char TO_HEX(const char i) { # define PHY_ADDRESS 1 #endif +static void netif_ext_callback(const uint16_t reason, [[maybe_unused]] const net::netif_ext_callback_args_t *args) { + DEBUG_ENTRY + + if ((reason & net::NetifReason::NSC_IPV4_ADDRESS_CHANGED) == net::NetifReason::NSC_IPV4_ADDRESS_CHANGED) { + net::display_ip(); + network::mdns_announcement(); + + printf("ip: " IPSTR " -> " IPSTR "\n", IP2STR(args->ipv4_changed.old_address.addr), IP2STR(net::netif_ipaddr())); + } + + if ((reason & net::NetifReason::NSC_IPV4_NETMASK_CHANGED) == net::NetifReason::NSC_IPV4_NETMASK_CHANGED) { + net::display_netmask(); + + printf("netmask: " IPSTR " -> " IPSTR "\n", IP2STR(args->ipv4_changed.old_netmask.addr), IP2STR(net::netif_netmask())); + } + + if ((reason & net::NetifReason::NSC_IPV4_GATEWAY_CHANGED) == net::NetifReason::NSC_IPV4_GATEWAY_CHANGED) { + net::display_gateway(); + + printf("gw: " IPSTR " -> " IPSTR "\n", IP2STR(args->ipv4_changed.old_gw.addr), IP2STR(net::netif_gw())); + } + + if ((reason & net::NetifReason::NSC_LINK_CHANGED) == net::NetifReason::NSC_LINK_CHANGED) { + if (args->link_changed.state == 0) { // Link down + net::net_link_down(); + + DEBUG_EXIT + return; + } + } + + DEBUG_EXIT +} + Network *Network::s_pThis; -Network::Network(NetworkParamsStore *pNetworkParamsStore) { +Network::Network() { DEBUG_ENTRY assert(s_pThis == nullptr); s_pThis = this; - m_aDomainName[0] = '\0'; - strcpy(m_aIfName, "eth0"); + m_aDomainName[0] = '\0'; + memset(&m_nNameservers, 0, sizeof(m_nNameservers)); - network::display_emac_config(); + net::display_emac_config(); emac_config(); - network::display_emac_start(); - - emac_start(m_aNetMacaddr, s_lastState); - - NetworkParams params(pNetworkParamsStore); - - if (params.Load()) { - params.Dump(); - } + net::display_emac_start(); - m_IpInfo.ip.addr = params.GetIpAddress(); - m_IpInfo.netmask.addr = params.GetNetMask(); - m_IpInfo.gw.addr = params.GetDefaultGateway(); - m_IsDhcpUsed = params.isDhcpUsed(); - m_nNtpServerIp = params.GetNtpServer(); - m_fNtpUtcOffset = params.GetNtpUtcOffset(); + emac_start(net::globals::netif_default.hwaddr, s_lastState); + printf(MACSTR "\n", MAC2STR(net::globals::netif_default.hwaddr)); net::phy_customized_timing(); net::phy_customized_led(); + net::netif_init(); + net::netif_add_ext_callback(netif_ext_callback); + + NetworkParams params; + params.Load(); + const auto *p = params.GetHostName(); + assert(p != nullptr); if (*p == '\0') { uint32_t k = 0; @@ -100,18 +137,35 @@ Network::Network(NetworkParamsStore *pNetworkParamsStore) { m_aHostName[k++] = HOST_NAME_PREFIX[i]; } - m_aHostName[k++] = TO_HEX(m_aNetMacaddr[3] >> 4); - m_aHostName[k++] = TO_HEX(m_aNetMacaddr[3] & 0x0F); - m_aHostName[k++] = TO_HEX(m_aNetMacaddr[4] >> 4); - m_aHostName[k++] = TO_HEX(m_aNetMacaddr[4] & 0x0F); - m_aHostName[k++] = TO_HEX(m_aNetMacaddr[5] >> 4); - m_aHostName[k++] = TO_HEX(m_aNetMacaddr[5] & 0x0F); + auto hwaddr = net::globals::netif_default.hwaddr; + + m_aHostName[k++] = TO_HEX(hwaddr[3] >> 4); + m_aHostName[k++] = TO_HEX(hwaddr[3] & 0x0F); + m_aHostName[k++] = TO_HEX(hwaddr[4] >> 4); + m_aHostName[k++] = TO_HEX(hwaddr[4] & 0x0F); + m_aHostName[k++] = TO_HEX(hwaddr[5] >> 4); + m_aHostName[k++] = TO_HEX(hwaddr[5] & 0x0F); m_aHostName[k] = '\0'; } else { strncpy(m_aHostName, p, sizeof(m_aHostName) - 1); m_aHostName[sizeof(m_aHostName) - 1] = '\0'; } + net::netif_set_hostname(m_aHostName); + + net::ip4_addr_t ipaddr; + net::ip4_addr_t netmask; + net::ip4_addr_t gw; + + ipaddr.addr = params.GetIpAddress(); + netmask.addr = params.GetNetMask(); + gw.addr = params.GetDefaultGateway(); + + bool isDhcpUsed = params.isDhcpUsed(); + + net::display_emac_status(net::Link::STATE_UP == s_lastState); + net::net_init(s_lastState, ipaddr, netmask, gw, isDhcpUsed); + #if defined (ENET_LINK_CHECK_USE_INT) net::link_interrupt_init(); #elif defined (ENET_LINK_CHECK_USE_PIN_POLL) @@ -119,110 +173,23 @@ Network::Network(NetworkParamsStore *pNetworkParamsStore) { #elif defined (ENET_LINK_CHECK_REG_POLL) net::link_status_read(); #endif - - network::display_emac_status(net::Link::STATE_UP == s_lastState); - - if (net::Link::STATE_UP == s_lastState) { - DEBUG_PUTS("net::Link::STATE_UP"); - - if (!m_IsDhcpUsed) { - DEBUG_PUTS(""); - if (m_IpInfo.ip.addr == 0) { - DEBUG_PUTS(""); - } else if (!IsValidIp(m_IpInfo.gw.addr)) { - DEBUG_PUTS(""); - m_IpInfo.gw.addr = m_IpInfo.ip.addr; - } - } - - if (m_IsDhcpUsed) { - network::display_dhcp_status(network::dhcp::ClientStatus::RENEW); - } - - net_init(m_aNetMacaddr, &m_IpInfo, m_aHostName, &m_IsDhcpUsed, &m_IsZeroconfUsed); - - if (m_IsZeroconfUsed) { - network::display_dhcp_status(network::dhcp::ClientStatus::FAILED); - } - - const auto nRetryTime = params.GetDhcpRetryTime(); - const auto bUseDhcp = params.isDhcpUsed(); - - while (m_IsZeroconfUsed && (nRetryTime != 0) && bUseDhcp) { - Hardware::Get()->SetMode(hardware::ledblink::Mode::FAST); - - network::display_dhcp_status(network::dhcp::ClientStatus::RETRYING); - - DEBUG_PUTS(""); - auto nTime = time(nullptr); - while ((time(nullptr) - nTime) < (nRetryTime * 60)) { - Hardware::Get()->Run(); - } - - network::display_dhcp_status(network::dhcp::ClientStatus::RENEW); - - Hardware::Get()->SetMode(hardware::ledblink::Mode::OFF_ON); - - m_IsDhcpUsed = true; - m_IsZeroconfUsed = false; - - net_init(m_aNetMacaddr, &m_IpInfo, m_aHostName, &m_IsDhcpUsed, &m_IsZeroconfUsed); - - if (m_IsDhcpUsed) { - break; - } - } - } else { - DEBUG_PUTS("net::Link::STATE_DOWN"); - - if (m_IsDhcpUsed) { - DEBUG_PUTS("m_IsDhcpUsed=true"); - m_IpInfo.ip.addr = 0; - m_IpInfo.netmask.addr = 0; - m_IpInfo.gw.addr = 0; - } - - auto bFalse = false; - - net_init(m_aNetMacaddr, &m_IpInfo, m_aHostName, &bFalse, &bFalse); - } - - network::display_ip(); - network::display_netmask(); - network::display_gateway(); - DEBUG_EXIT } void Network::SetIp(uint32_t nIp) { DEBUG_ENTRY - if (m_IsDhcpUsed) { - m_IsDhcpUsed = false; - net_dhcp_release(); - } - - m_IsZeroconfUsed = false; - - m_IpInfo.ip.addr = nIp; - - if (nIp == 0) { - } else { - m_IpInfo.gw.addr = m_IpInfo.ip.addr; + if (nIp == net::netif_ipaddr()) { + DEBUG_EXIT + return; } - net_set_ip(&m_IpInfo); - net_set_gw(&m_IpInfo); - - if (m_pNetworkStore != nullptr) { - m_pNetworkStore->SaveIp(m_IpInfo.ip.addr); - m_pNetworkStore->SaveGatewayIp(m_IpInfo.gw.addr); - m_pNetworkStore->SaveDhcp(false); - } + net::ip4_addr_t ipaddr; + ipaddr.addr = nIp; + net_set_primary_ip(ipaddr); - network::mdns_announcement(); - network::display_ip(); - network::display_netmask(); + NetworkStore::SaveIp(nIp); + NetworkStore::SaveDhcp(false); DEBUG_EXIT } @@ -230,20 +197,17 @@ void Network::SetIp(uint32_t nIp) { void Network::SetNetmask(uint32_t nNetmask) { DEBUG_ENTRY - if (m_IpInfo.netmask.addr == nNetmask) { + if (nNetmask == net::netif_netmask()) { DEBUG_EXIT return; } - m_IpInfo.netmask.addr = nNetmask; - net_set_netmask(&m_IpInfo); + net::ip4_addr_t netmask; + netmask.addr = nNetmask; - if (m_pNetworkStore != nullptr) { - m_pNetworkStore->SaveNetMask(m_IpInfo.netmask.addr); - } + net::netif_set_netmask(netmask); - network::display_ip(); - network::display_netmask(); + NetworkStore::SaveNetMask(nNetmask); DEBUG_EXIT } @@ -251,19 +215,17 @@ void Network::SetNetmask(uint32_t nNetmask) { void Network::SetGatewayIp(uint32_t nGatewayIp) { DEBUG_ENTRY - if (m_IpInfo.gw.addr == nGatewayIp) { + if (nGatewayIp == net::netif_gw()) { DEBUG_EXIT return; } - m_IpInfo.gw.addr = nGatewayIp; - net_set_gw(&m_IpInfo); + net::ip4_addr_t gw; + gw.addr = nGatewayIp; - if (m_pNetworkStore != nullptr) { - m_pNetworkStore->SaveGatewayIp(m_IpInfo.gw.addr); - } + net::netif_set_gw(gw); - network::display_gateway(); + NetworkStore::SaveGatewayIp(nGatewayIp); DEBUG_EXIT } @@ -274,145 +236,126 @@ void Network::SetHostName(const char *pHostName) { strncpy(m_aHostName, pHostName, network::HOSTNAME_SIZE - 1); m_aHostName[network::HOSTNAME_SIZE - 1] = '\0'; - if (m_pNetworkStore != nullptr) { - m_pNetworkStore->SaveHostName(m_aHostName, static_cast(strlen(m_aHostName))); - } + NetworkStore::SaveHostName(m_aHostName, static_cast(strlen(m_aHostName))); network::mdns_announcement(); - network::display_hostname(); + net::display_hostname(); DEBUG_EXIT } -bool Network::SetZeroconf() { +void Network::SetZeroconf() { DEBUG_ENTRY - const auto bWatchdog = Hardware::Get()->IsWatchdog(); - - if (bWatchdog) { - Hardware::Get()->WatchdogStop(); - } - - m_IsZeroconfUsed = net_set_zeroconf(&m_IpInfo); - - if (m_IsZeroconfUsed) { - m_IsDhcpUsed = false; - - if (m_pNetworkStore != nullptr) { - m_pNetworkStore->SaveDhcp(true);// Zeroconf is enabled only when use_dhcp=1 - } - } - - network::mdns_announcement(); - network::display_ip(); - network::display_netmask(); + net::autoip_start(); - if (bWatchdog) { - Hardware::Get()->WatchdogInit(); - } + NetworkStore::SaveDhcp(false); DEBUG_EXIT - return m_IsZeroconfUsed; } -bool Network::EnableDhcp() { +void Network::EnableDhcp() { DEBUG_ENTRY - const auto bWatchdog = Hardware::Get()->IsWatchdog(); - - if (bWatchdog) { - Hardware::Get()->WatchdogStop(); - } - - network::display_dhcp_status(network::dhcp::ClientStatus::RENEW); + net::dhcp_start(); - m_IsDhcpUsed = net_set_dhcp(&m_IpInfo, m_aHostName, &m_IsZeroconfUsed); - - if (m_IsZeroconfUsed) { - network::display_dhcp_status(network::dhcp::ClientStatus::FAILED); - } else { - network::display_dhcp_status(network::dhcp::ClientStatus::GOT_IP); - } - - DEBUG_PRINTF("m_IsDhcpUsed=%d, m_IsZeroconfUsed=%d", m_IsDhcpUsed, m_IsZeroconfUsed); - - if (m_pNetworkStore != nullptr) { - m_pNetworkStore->SaveDhcp(m_IsDhcpUsed); - } - - network::mdns_announcement(); - network::display_ip(); - network::display_netmask(); - network::display_gateway(); - - if (bWatchdog) { - Hardware::Get()->WatchdogInit(); - } + NetworkStore::SaveDhcp(true); DEBUG_EXIT - return m_IsDhcpUsed; } -void Network::SetQueuedStaticIp(uint32_t nLocalIp, uint32_t nNetmask) { +void Network::SetQueuedStaticIp(const uint32_t nStaticIp, const uint32_t nNetmask) { DEBUG_ENTRY - DEBUG_PRINTF(IPSTR ", nNetmask=" IPSTR, IP2STR(nLocalIp), IP2STR(nNetmask)); + DEBUG_PRINTF(IPSTR ", nNetmask=" IPSTR, IP2STR(nStaticIp), IP2STR(nNetmask)); - if (nLocalIp != 0) { - m_QueuedConfig.nLocalIp = nLocalIp; + if (nStaticIp != 0) { + m_QueuedConfig.nStaticIp = nStaticIp; + } else { + m_QueuedConfig.nStaticIp = GetIp(); } if (nNetmask != 0) { m_QueuedConfig.nNetmask = nNetmask; + } else { + m_QueuedConfig.nNetmask = GetNetmask(); } m_QueuedConfig.nMask |= QueuedConfig::STATIC_IP; - m_QueuedConfig.nMask |= QueuedConfig::NET_MASK; + m_QueuedConfig.nMask |= QueuedConfig::NETMASK; DEBUG_EXIT } +void Network::SetQueuedDefaultRoute(const uint32_t nGatewayIp) { + if (nGatewayIp != 0) { + m_QueuedConfig.nGateway = nGatewayIp; + } else { + m_QueuedConfig.nGateway = GetGatewayIp(); + } + + m_QueuedConfig.nMask |= QueuedConfig::GW; +} + bool Network::ApplyQueuedConfig() { DEBUG_ENTRY - DEBUG_PRINTF("m_QueuedConfig.nMask=%x, " IPSTR ", " IPSTR, m_QueuedConfig.nMask, IP2STR(m_QueuedConfig.nLocalIp), IP2STR(m_QueuedConfig.nNetmask)); + DEBUG_PRINTF("m_QueuedConfig.nMask=%x, " IPSTR ", " IPSTR, m_QueuedConfig.nMask, IP2STR(m_QueuedConfig.nStaticIp), IP2STR(m_QueuedConfig.nNetmask)); if (m_QueuedConfig.nMask == QueuedConfig::NONE) { DEBUG_EXIT return false; } - if ((isQueuedMaskSet(QueuedConfig::STATIC_IP)) || (isQueuedMaskSet(QueuedConfig::NET_MASK))) { - if (isQueuedMaskSet(QueuedConfig::NET_MASK)) { + if ((isQueuedMaskSet(QueuedConfig::STATIC_IP)) || (isQueuedMaskSet(QueuedConfig::NETMASK)) || (isQueuedMaskSet(QueuedConfig::GW))) { + // After SetIp all ip address might be zero. + if (isQueuedMaskSet(QueuedConfig::STATIC_IP)) { + SetIp(m_QueuedConfig.nStaticIp); + } + + if (isQueuedMaskSet(QueuedConfig::NETMASK)) { SetNetmask(m_QueuedConfig.nNetmask); - m_QueuedConfig.nMask &= ~(QueuedConfig::NET_MASK); } - if (isQueuedMaskSet(QueuedConfig::STATIC_IP)) { - SetIp(m_QueuedConfig.nLocalIp); - m_QueuedConfig.nMask &= ~(QueuedConfig::STATIC_IP); + if (isQueuedMaskSet(QueuedConfig::GW)) { + SetGatewayIp(m_QueuedConfig.nGateway); } + + m_QueuedConfig.nMask = QueuedConfig::NONE; + + DEBUG_EXIT + return true; } if (isQueuedMaskSet(QueuedConfig::DHCP)) { - EnableDhcp(); - m_QueuedConfig.nMask &= ~(QueuedConfig::DHCP); + if (m_QueuedConfig.mode == network::dhcp::Mode::ACTIVE) { + EnableDhcp(); + } else if (m_QueuedConfig.mode == network::dhcp::Mode::INACTIVE) { + + } + + m_QueuedConfig.mode = network::dhcp::Mode::UNKNOWN; + m_QueuedConfig.nMask = QueuedConfig::NONE; + + DEBUG_EXIT + return true; } if (isQueuedMaskSet(QueuedConfig::ZEROCONF)) { SetZeroconf(); - m_QueuedConfig.nMask &= ~(QueuedConfig::ZEROCONF); + m_QueuedConfig.nMask = QueuedConfig::NONE; + + DEBUG_EXIT + return true; } DEBUG_EXIT - return true; + return false; } -#include - void Network::Print() { printf("Network [%c]\n", GetAddressingMode()); printf(" Hostname : %s\n", m_aHostName); - printf(" IfName : %d: %s " MACSTR "\n", m_nIfIndex, m_aIfName, MAC2STR(m_aNetMacaddr)); - printf(" Primary : " IPSTR "/%d (HTTP only " IPSTR ")\n", IP2STR(m_IpInfo.ip.addr), GetNetmaskCIDR(), IP2STR(m_IpInfo.secondary_ip.addr)); - printf(" Gateway : " IPSTR "\n", IP2STR(m_IpInfo.gw.addr)); + printf(" IfName : %u: %s " MACSTR "\n", static_cast(GetIfIndex()), m_aIfName, MAC2STR(net::netif_hwaddr())); + printf(" Primary : " IPSTR "/%u (HTTP only " IPSTR ")\n", IP2STR(net::netif_ipaddr()), static_cast(GetNetmaskCIDR()), IP2STR(net::netif_secondary_ipaddr())); + printf(" Gateway : " IPSTR "\n", IP2STR(net::netif_gw())); printf(" Broadcast : " IPSTR "\n", IP2STR(GetBroadcastIp())); } diff --git a/lib-network/src/emac/phy/json_get_phystatus.cpp b/lib-network/src/emac/phy/json_get_phystatus.cpp index 73fa4ee4..ace4991d 100755 --- a/lib-network/src/emac/phy/json_get_phystatus.cpp +++ b/lib-network/src/emac/phy/json_get_phystatus.cpp @@ -29,11 +29,11 @@ namespace remoteconfig { namespace net { -uint16_t json_get_phystatus(char *pOutBuffer, const uint16_t nOutBufferSize) { +uint32_t json_get_phystatus(char *pOutBuffer, const uint32_t nOutBufferSize) { ::net::PhyStatus phyStatus; ::net::phy_customized_status(phyStatus); - const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, + const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, "{\"link\":\"%s\",\"speed\":\"%s\",\"duplex\":\"%s\",\"autonegotiation\":\"%s\"}", ::net::phy_string_get_link(phyStatus.link), ::net::phy_string_get_speed(phyStatus.speed), diff --git a/lib-network/src/emac/phy/link_handle_change.cpp b/lib-network/src/emac/phy/link_handle_change.cpp old mode 100644 new mode 100755 index 5b86f3a6..44bd517c --- a/lib-network/src/emac/phy/link_handle_change.cpp +++ b/lib-network/src/emac/phy/link_handle_change.cpp @@ -2,7 +2,7 @@ * link_handle_change.cpp * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,23 +23,41 @@ * THE SOFTWARE. */ +#include "hardware.h" #include "network.h" +#include "netif.h" #include "debug.h" -/** - * Default implementation - */ +#if !defined(PHY_ADDRESS) +# define PHY_ADDRESS 1 +#endif + +extern void emac_adjust_link(const net::PhyStatus); namespace net { -void __attribute__((weak)) link_handle_change(const net::Link state) { +void link_handle_change(const net::Link state) { DEBUG_PRINTF("net::Link %s", state == net::Link::STATE_UP ? "UP" : "DOWN"); - if (net::Link::STATE_UP == state) { - if (Network::Get()->IsDhcpUsed()) { - DEBUG_PUTS("Enable DHCP"); - Network::Get()->EnableDhcp(); + if (Link::STATE_UP == state) { + const bool isWatchdog = Hardware::Get()->IsWatchdog(); + if (isWatchdog) { + Hardware::Get()->WatchdogStop(); } + + PhyStatus phyStatus; + phy_start(PHY_ADDRESS, phyStatus); + + emac_adjust_link(phyStatus); + + if (isWatchdog) { + Hardware::Get()->WatchdogInit(); + } + + netif_set_link_up(); + return; } + + netif_set_link_down(); } } // namespace net diff --git a/lib-network/src/emac/phy/net_link_check.cpp b/lib-network/src/emac/phy/net_link_check.cpp old mode 100644 new mode 100755 index c266780d..ddacbd92 --- a/lib-network/src/emac/phy/net_link_check.cpp +++ b/lib-network/src/emac/phy/net_link_check.cpp @@ -2,7 +2,7 @@ * net_link_check.cpp * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -48,13 +48,6 @@ void link_pin_poll_init() { #endif net::Link link_status_read() { - uint16_t nValue = 0; - phy_read(PHY_ADDRESS, mmi::REG_BMSR, nValue); - - if (mmi::BMSR_LINKED_STATUS == (nValue & mmi::BMSR_LINKED_STATUS)) { - return net::Link::STATE_UP; - } - - return net::Link::STATE_DOWN; + return net::phy_get_link(PHY_ADDRESS); } } // namespace net diff --git a/lib-network/src/emac/phy/net_phy.cpp b/lib-network/src/emac/phy/net_phy.cpp index 61be500a..82190181 100755 --- a/lib-network/src/emac/phy/net_phy.cpp +++ b/lib-network/src/emac/phy/net_phy.cpp @@ -2,7 +2,7 @@ * net_phy.cpp * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,10 +33,11 @@ #include "hardware.h" #include "debug.h" -namespace net { - -static PhyStatus s_phyStatus; +#if !defined(PHY_ADDRESS) +# define PHY_ADDRESS 1 +#endif +namespace net { bool phy_get_id(const uint32_t nAddress, PhyIdentifier& phyIdentifier) { DEBUG_ENTRY DEBUG_PRINTF("nAddress=%.2x", nAddress); @@ -64,6 +65,17 @@ bool phy_get_id(const uint32_t nAddress, PhyIdentifier& phyIdentifier) { return true; } +Link phy_get_link(const uint32_t nAddress) { + uint16_t nValue = 0; + phy_read(nAddress, mmi::REG_BMSR, nValue); + + if (mmi::BMSR_LINKED_STATUS == (nValue & mmi::BMSR_LINKED_STATUS)) { + return net::Link::STATE_UP; + } + + return net::Link::STATE_DOWN; +} + bool phy_powerdown(const uint32_t nAddress) { return phy_write(nAddress, mmi::REG_BMCR, mmi::BMCR_POWERDOWN); } @@ -163,7 +175,7 @@ static bool phy_config_autonegotiation(const uint32_t nAddress, const uint16_t n * @param nAddress PHY address * @return true for success, false for failure */ -static bool phy_update_link(const uint32_t nAddress) { +static bool phy_update_link(const uint32_t nAddress, PhyStatus& phyStatus) { DEBUG_ENTRY uint16_t nBMSR; @@ -178,7 +190,7 @@ static bool phy_update_link(const uint32_t nAddress) { * we don't need to wait for autoneg again */ - if ((s_phyStatus.link == Link::STATE_DOWN) && (nBMSR & mmi::BMSR_LINKED_STATUS)) { + if ((phyStatus.link == Link::STATE_DOWN) && (nBMSR & mmi::BMSR_LINKED_STATUS)) { DEBUG_EXIT return true; } @@ -195,14 +207,14 @@ static bool phy_update_link(const uint32_t nAddress) { phy_read(nAddress, mmi::REG_BMSR, nBMSR); } - s_phyStatus.link = Link::STATE_UP; + phyStatus.link = Link::STATE_UP; DEBUG_PRINTF("%u", Hardware::Get()->Millis() - nMillis); DEBUG_EXIT return true; } else { phy_read(nAddress, mmi::REG_BMSR, nBMSR); - s_phyStatus.link = nBMSR & mmi::BMSR_LINKED_STATUS ? Link::STATE_UP : Link::STATE_DOWN; + phyStatus.link = nBMSR & mmi::BMSR_LINKED_STATUS ? Link::STATE_UP : Link::STATE_DOWN; DEBUG_EXIT return true; @@ -214,10 +226,10 @@ static bool phy_update_link(const uint32_t nAddress) { return true; } -static bool phy_parse_link(const uint32_t nAddress) { +static void phy_parse_link(const uint32_t nAddress, PhyStatus& phyStatus) { - s_phyStatus.duplex = Duplex::DUPLEX_HALF; - s_phyStatus.speed = Speed::SPEED10; + phyStatus.duplex = Duplex::DUPLEX_HALF; + phyStatus.speed = Speed::SPEED10; uint16_t nADVERTISE; phy_read(nAddress, mmi::REG_ADVERTISE, nADVERTISE); @@ -227,16 +239,14 @@ static bool phy_parse_link(const uint32_t nAddress) { nLPA &= nADVERTISE; if (nLPA & (mmi::LPA_100FULL | mmi::LPA_100HALF)) { - s_phyStatus.speed = Speed::SPEED100; + phyStatus.speed = Speed::SPEED100; if (nLPA & mmi::LPA_100FULL) { - s_phyStatus.duplex = Duplex::DUPLEX_FULL; + phyStatus.duplex = Duplex::DUPLEX_FULL; } } else if (nLPA & mmi::LPA_10FULL) { - s_phyStatus.duplex = Duplex::DUPLEX_FULL; + phyStatus.duplex = Duplex::DUPLEX_FULL; } - - return true; } bool phy_start(const uint32_t nAddress, PhyStatus& phyStatus) { @@ -249,17 +259,19 @@ bool phy_start(const uint32_t nAddress, PhyStatus& phyStatus) { return false; } - if (!phy_update_link(nAddress)) { + if (!phy_update_link(nAddress, phyStatus)) { DEBUG_EXIT return false; } - if (!phy_parse_link(nAddress)) { - DEBUG_EXIT - return false; - } + phy_parse_link(nAddress, phyStatus); + + phyStatus.link = phy_get_link(nAddress); - phyStatus = s_phyStatus; + DEBUG_PRINTF("Link %s, %d, %s", + phyStatus.link == net::Link::STATE_UP ? "Up" : "Down", + phyStatus.speed == net::Speed::SPEED10 ? 10 : 100, + phyStatus.duplex == net::Duplex::DUPLEX_HALF ? "HALF" : "FULL"); DEBUG_EXIT return true; diff --git a/lib-network/src/emac/phy/phygen/net_phy.cpp b/lib-network/src/emac/phy/phygen/net_phy.cpp index 07b68f29..aeb63abb 100755 --- a/lib-network/src/emac/phy/phygen/net_phy.cpp +++ b/lib-network/src/emac/phy/phygen/net_phy.cpp @@ -53,16 +53,14 @@ void phy_customized_timing() { } void phy_customized_status(PhyStatus& phyStatus) { - phyStatus.link = link_status_read(); - uint16_t nValue; - phy_read(PHY_ADDRESS, mmi::REG_BMCR, nValue); + phy_read(PHY_ADDRESS, mmi::REG_BMSR, nValue); debug_print_bits(nValue); - phyStatus.duplex = ((nValue & BIT(8)) == BIT(8)) ? Duplex::DUPLEX_FULL : Duplex::DUPLEX_HALF; - phyStatus.speed = ((nValue & BIT(13)) == BIT(13)) ? Speed::SPEED100 : Speed::SPEED10; - phyStatus.bAutonegotiation = ((nValue & mmi::BMCR_AUTONEGOTIATION) == mmi::BMCR_AUTONEGOTIATION); - + phyStatus.duplex = Duplex::DUPLEX_FULL; + phyStatus.speed = Speed::SPEED100; + phyStatus.link = (nValue & mmi::BMSR_LINKED_STATUS) ? Link::STATE_UP : Link::STATE_DOWN; + phyStatus.bAutonegotiation = (nValue & mmi::BMSR_AUTONEGO_COMPLETE); } } // namespace net diff --git a/lib-network/src/emac/phy/rtl8201f/net_phy.cpp b/lib-network/src/emac/phy/rtl8201f/net_phy.cpp index f8c54332..38050050 100755 --- a/lib-network/src/emac/phy/rtl8201f/net_phy.cpp +++ b/lib-network/src/emac/phy/rtl8201f/net_phy.cpp @@ -2,7 +2,7 @@ * phy.cpp * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -56,9 +56,16 @@ void phy_write_paged(uint16_t phy_page, uint16_t phy_reg, uint16_t phy_value, ui DEBUG_PRINTF("tmp_value=0x%.4x, phy_value=0x%.4x", tmp_value, phy_value); phy_write(PHY_ADDRESS, phy_reg, tmp_value); + phy_write(PHY_ADDRESS, PHY_REG_PAGE_SELECT, 0); +} - phy_page = 0; +void phy_read_paged(const uint16_t phy_page, const uint16_t phy_reg, uint16_t& phy_value, const uint16_t mask = 0x0) { phy_write(PHY_ADDRESS, PHY_REG_PAGE_SELECT, phy_page); + + phy_read(PHY_ADDRESS, phy_reg, phy_value); + phy_value &= mask; + + phy_write(PHY_ADDRESS, PHY_REG_PAGE_SELECT, 0); } void phy_customized_led() { @@ -75,18 +82,26 @@ void phy_customized_led() { DEBUG_EXIT } +#define RMSR_RX_TIMING_SHIFT 4 +#define RMSR_RX_TIMING_MASK 0xF0 + +#define RMSR_TX_TIMING_SHIFT 8 +#define RMSR_TX_TIMING_MASK 0xF00 + void phy_customized_timing() { DEBUG_ENTRY -#if defined (GD32F407) || defined (GD32F450) -# define RMSR_RX_TIMING_SHIFT 4 -# define RMSR_RX_TIMING_MASK 0xF0 +#if defined (GD32F4XX) # define RMSR_RX_TIMING_VAL 0x4 -# define RMSR_TX_TIMING_SHIFT 8 -# define RMSR_TX_TIMING_MASK 0xF00 -# define RMSR_TX_TIMING_VAL 0xF +# if defined (GD32F407) +# define RMSR_TX_TIMING_VAL 0x2 // The GD32F407 is now running at 200MHz +# elif defined (GD32F470) +# define RMSR_TX_TIMING_VAL 0x1 +# else +# define RMSR_TX_TIMING_VAL 0xF +# endif constexpr uint16_t phy_value = (RMSR_RX_TIMING_VAL << RMSR_RX_TIMING_SHIFT) - | (RMSR_TX_TIMING_VAL << RMSR_TX_TIMING_SHIFT); + | (RMSR_TX_TIMING_VAL << RMSR_TX_TIMING_SHIFT); phy_write_paged(0x7, PHY_REG_RMSR, phy_value, RMSR_RX_TIMING_MASK | RMSR_TX_TIMING_MASK); #endif DEBUG_EXIT @@ -103,4 +118,24 @@ void phy_customized_status(PhyStatus& phyStatus) { phyStatus.bAutonegotiation = ((nValue & mmi::BMCR_AUTONEGOTIATION) == mmi::BMCR_AUTONEGOTIATION); } +namespace phy { +void rtl8201f_get_timings(uint32_t& nRxTiming, uint32_t& nTxTiming) { + uint16_t nValue; + phy_read_paged(0x7, PHY_REG_RMSR, nValue, RMSR_RX_TIMING_MASK | RMSR_TX_TIMING_MASK); + + nRxTiming = (nValue >> RMSR_RX_TIMING_SHIFT) & 0xF; + nTxTiming = (nValue >> RMSR_TX_TIMING_SHIFT) & 0xF; +} + +void rtl8201f_set_rxtiming(const uint32_t nRxTiming) { + const auto nValue = static_cast((nRxTiming & 0xF) << RMSR_RX_TIMING_SHIFT); + phy_write_paged(0x7, PHY_REG_RMSR, nValue, RMSR_RX_TIMING_MASK); +} + +void rtl8201f_set_txtiming(const uint32_t nTxTiming) { + const auto nValue = static_cast((nTxTiming & 0xF) << RMSR_TX_TIMING_SHIFT); + phy_write_paged(0x7, PHY_REG_RMSR, nValue, RMSR_TX_TIMING_MASK); +} + +} // namespace phy } // namespace net diff --git a/lib-network/src/net/acd.cpp b/lib-network/src/net/acd.cpp new file mode 100755 index 00000000..ea97ef63 --- /dev/null +++ b/lib-network/src/net/acd.cpp @@ -0,0 +1,328 @@ +/** + * @file acd.cpp + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* This code is inspired by the lwIP TCP/IP stack. + * https://savannah.nongnu.org/projects/lwip/ + */ +/** + * The acp.cpp aims to be conform to RFC 5227. + * https://datatracker.ietf.org/doc/html/rfc5227.html + * IPv4 Address Conflict Detection + */ + +#if defined (DEBUG_NET_ACD) +# undef NDEBUG +#endif + +#pragma GCC push_options +#pragma GCC optimize ("Os") + +#include +#include +#include +#include + +#include "../../config/net_config.h" + +#include "net/acd.h" +#include "net/protocol/acd.h" +#include "net/protocol/arp.h" +#include "net_memcpy.h" + +#include "hardware.h" +#include "debug.h" + +namespace net { +namespace acd { +static constexpr uint32_t ACD_TMR_INTERVAL = 100; +static constexpr uint32_t ACD_TICKS_PER_SECOND = (1000U / ACD_TMR_INTERVAL); +} // namespace acd + +static int32_t nTimerId; + +static void acd_timer() { + auto *acd = reinterpret_cast(globals::netif_default.acd); + assert(acd != nullptr); + + if (acd->lastconflict > 0) { + acd->lastconflict--; + } + + DEBUG_PRINTF("state=%u, ttw=%u", static_cast(acd->state), acd->ttw); + + if (acd->ttw > 0) { + acd->ttw--; + } + + switch (acd->state) { + case acd::State::ACD_STATE_PROBE_WAIT: + case acd::State::ACD_STATE_PROBING: + if (acd->ttw == 0) { + acd->state = acd::State::ACD_STATE_PROBING; + arp_acd_probe(acd->ipaddr); + DEBUG_PUTS("PROBING Sent Probe"); + acd->sent_num++; + if (acd->sent_num >= PROBE_NUM) { + acd->state = acd::State::ACD_STATE_ANNOUNCE_WAIT; + acd->sent_num = 0; + acd->ttw = static_cast(ANNOUNCE_WAIT * acd::ACD_TICKS_PER_SECOND); + } else { + acd->ttw = static_cast(random() % (((PROBE_MAX - PROBE_MIN) * acd::ACD_TICKS_PER_SECOND)) + (PROBE_MIN * acd::ACD_TICKS_PER_SECOND)); + } + } + break; + case acd::State::ACD_STATE_ANNOUNCE_WAIT: + case acd::State::ACD_STATE_ANNOUNCING: + if (acd->ttw == 0) { + if (acd->sent_num == 0) { + acd->state = acd::State::ACD_STATE_ANNOUNCING; + acd->num_conflicts = 0; + } + arp_acd_send_announcement(acd->ipaddr); + DEBUG_PUTS("ANNOUNCING Sent Announce"); + acd->ttw = static_cast(ANNOUNCE_INTERVAL * acd::ACD_TICKS_PER_SECOND); + acd->sent_num++; + + if (acd->sent_num >= ANNOUNCE_NUM) { + acd->state = acd::State::ACD_STATE_ONGOING; + acd->sent_num = 0; + acd->ttw = 0; + acd->acd_conflict_callback(acd::Callback::ACD_IP_OK); + } + } + break; + case acd::State::ACD_STATE_RATE_LIMIT: + if (acd->ttw == 0) { + acd_stop(acd); + acd->acd_conflict_callback(acd::Callback::ACD_RESTART_CLIENT); + } + break; + default: + break; + } +} + +static void acd_restart(struct acd::Acd *acd) { + acd->num_conflicts++; + acd->acd_conflict_callback(acd::Callback::ACD_DECLINE); + + if (acd->num_conflicts >= MAX_CONFLICTS) { + acd->state = acd::State::ACD_STATE_RATE_LIMIT; + acd->ttw = static_cast(RATE_LIMIT_INTERVAL * acd::ACD_TICKS_PER_SECOND); + DEBUG_PUTS("rate limiting initiated. too many conflicts"); + } + else { + acd_stop(acd); + acd->acd_conflict_callback(acd::Callback::ACD_RESTART_CLIENT); + } +} + +static void acd_handle_arp_conflict(struct acd::Acd *acd) { + /* RFC5227, 2.4 "Ongoing Address Conflict Detection and Address Defense" + allows three options where: + a) means retreat on the first conflict, + b) allows to keep an already configured address when having only one + conflict in DEFEND_INTERVAL seconds and + c) the host will not give up it's address and defend it indefinitely + + We use option b) when the acd module represents the netif address, since it + helps to improve the chance that one of the two conflicting hosts may be + able to retain its address. while we are flexible enough to help network + performance + + We use option a) when the acd module does not represent the netif address, + since we cannot have the acd module announcing or restarting. This + situation occurs for the LL acd module when a routable address is used on + the netif but the LL address is still open in the background. */ + + if (acd->state == acd::State::ACD_STATE_PASSIVE_ONGOING) { + DEBUG_PUTS("conflict when we are in passive mode -> back off"); + acd_stop(acd); + acd->acd_conflict_callback(acd::Callback::ACD_DECLINE); + } + else { + if (acd->lastconflict > 0) { + DEBUG_PUTS("conflict within DEFEND_INTERVAL -> retreating"); + acd_restart(acd); + } else { + DEBUG_PUTS("we are defending, send ARP Announce"); + arp_acd_send_announcement(acd->ipaddr); + acd->lastconflict = DEFEND_INTERVAL * acd::ACD_TICKS_PER_SECOND; + } + } +} + +static void acd_put_in_passive_mode() { + auto *acd = reinterpret_cast(globals::netif_default.acd); + assert(acd != nullptr); + + switch (acd->state) { + case acd::State::ACD_STATE_OFF: + case acd::State::ACD_STATE_PASSIVE_ONGOING: + default: + /* do nothing */ + break; + case acd::State::ACD_STATE_PROBE_WAIT: + case acd::State::ACD_STATE_PROBING: + case acd::State::ACD_STATE_ANNOUNCE_WAIT: + case acd::State::ACD_STATE_RATE_LIMIT: + acd_stop(acd); + acd->acd_conflict_callback(acd::Callback::ACD_DECLINE); + break; + case acd::State::ACD_STATE_ANNOUNCING: + case acd::State::ACD_STATE_ONGOING: + acd->state = acd::State::ACD_STATE_PASSIVE_ONGOING; + break; + } +} + +/* + * Public interface + */ + +void acd_start(struct acd::Acd *acd, const ip4_addr_t ipaddr) { + DEBUG_ENTRY + assert(acd != nullptr); + + acd->ipaddr.addr = ipaddr.addr; + acd->state = acd::State::ACD_STATE_PROBE_WAIT; + acd->ttw = static_cast(random() % (PROBE_WAIT * acd::ACD_TICKS_PER_SECOND)); + + nTimerId = Hardware::Get()->SoftwareTimerAdd(acd::ACD_TMR_INTERVAL, acd_timer); + assert(nTimerId >= 0); + + DEBUG_EXIT +} + +void acd_stop(struct acd::Acd *acd) { + DEBUG_ENTRY + assert(acd != nullptr); + + acd->state = acd::State::ACD_STATE_OFF; + + assert(nTimerId >= 0); + Hardware::Get()->SoftwareTimerDelete(nTimerId); + nTimerId = -1; + + DEBUG_EXIT +} + +void acd_network_changed_link_down() { + DEBUG_ENTRY + + auto *acd = reinterpret_cast(globals::netif_default.acd); + acd_stop(acd); + + DEBUG_EXIT +} + +void acd_arp_reply(struct t_arp *pArp) { + DEBUG_ENTRY + auto *acd = reinterpret_cast(globals::netif_default.acd); + + switch (acd->state) { + case acd::State::ACD_STATE_OFF: + case acd::State::ACD_STATE_RATE_LIMIT: + default: + break; + case acd::State::ACD_STATE_PROBE_WAIT: + case acd::State::ACD_STATE_PROBING: + case acd::State::ACD_STATE_ANNOUNCE_WAIT: + /* RFC 5227 Section 2.1.1: + * from beginning to after ANNOUNCE_WAIT seconds we have a conflict if + * ip.sender == ipaddr (someone is already using the address) + * OR + * ip.dst == ipaddr && hw.src != own macAddress (someone else is probing it) + */ + if (((memcpy_ip(pArp->arp.sender_ip) == acd->ipaddr.addr)) + || (!(memcpy_ip(pArp->arp.sender_ip) == 0) + && ((memcpy_ip(pArp->arp.target_ip)) == acd->ipaddr.addr) + && (memcmp(pArp->arp.sender_mac, globals::netif_default.hwaddr, ETH_ADDR_LEN) == 0))) + { + DEBUG_PUTS("Probe Conflict detected"); + acd_restart(acd); + } + break; + case acd::State::ACD_STATE_ANNOUNCING: + case acd::State::ACD_STATE_ONGOING: + case acd::State::ACD_STATE_PASSIVE_ONGOING: + /* RFC 5227 Section 2.4: + * in any state we have a conflict if + * ip.sender == ipaddr && hw.src != own macAddress (someone is using our address) + */ + if ((memcpy_ip(pArp->arp.sender_ip) == acd->ipaddr.addr) + && (memcmp(pArp->arp.sender_mac, globals::netif_default.hwaddr, ETH_ADDR_LEN) != 0)) { + DEBUG_PUTS("Conflicting ARP-Packet detected"); + acd_handle_arp_conflict(acd); + } + break; + } + + DEBUG_EXIT +} + +void acd_add(struct acd::Acd *pAcd, acd_conflict_callback_t acd_conflict_callback) { + DEBUG_ENTRY + assert(pAcd != nullptr); + assert(acd_conflict_callback != nullptr); + + pAcd->acd_conflict_callback = acd_conflict_callback; + + auto &netif = globals::netif_default; + netif.acd = pAcd; + + DEBUG_EXIT +} + +void acd_remove(struct acd::Acd *pAcd) { + DEBUG_ENTRY + + assert(pAcd != nullptr); + auto &netif = globals::netif_default; + + if (netif.acd == pAcd) { + netif.acd = nullptr; + + DEBUG_EXIT + return; + } + + DEBUG_EXIT +} + +void acd_netif_ip_addr_changed(const ip4_addr_t old_addr, const ip4_addr_t new_addr) { + if ((old_addr.addr == 0) || (new_addr.addr == 0)) { + return; + } + + auto *acd = reinterpret_cast(globals::netif_default.acd); + + if (acd->ipaddr.addr == old_addr.addr) { + /* Did we change from a LL address to a routable address? */ + if (network::is_linklocal_ip(old_addr.addr) && !network::is_linklocal_ip(new_addr.addr)) { + /* Put the module in passive conflict detection mode */ + acd_put_in_passive_mode(); + } + } +} +} // namespace net diff --git a/lib-network/src/apps/mdns/mdns.cpp b/lib-network/src/net/apps/mdns/mdns.cpp similarity index 88% rename from lib-network/src/apps/mdns/mdns.cpp rename to lib-network/src/net/apps/mdns/mdns.cpp index 8bc029c2..669588ce 100755 --- a/lib-network/src/apps/mdns/mdns.cpp +++ b/lib-network/src/net/apps/mdns/mdns.cpp @@ -2,7 +2,7 @@ * @file mdns.cpp * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,13 +23,21 @@ * THE SOFTWARE. */ +#if defined (DEBUG_NET_APPS_MDNS) +# if defined (NDEBUG) +# undef NDEBUG +# endif +#endif + #include #include #include #include #include -#include "mdns.h" +#include "net/apps/mdns.h" +#include "net/protocol/ip4.h" +#include "net/protocol/iana.h" #include "network.h" #include "hardware.h" @@ -43,10 +51,6 @@ static constexpr auto SERVICE_RECORDS_MAX = 8; static constexpr auto SERVICE_RECORDS_MAX = MDNS_SERVICE_RECORDS_MAX; #endif -static constexpr uint32_t MULTICAST_MESSAGE_SIZE = 512; ///< The 1987 DNS specification [RFC1035] restricts DNS messages carried by UDP to no more than 512 bytes -static constexpr uint32_t MULTICAST_ADDRESS = network::convert_to_uint(224, 0, 0, 251); -static constexpr uint16_t UDP_PORT = 5353; - static constexpr uint32_t MDNS_RESPONSE_TTL = 3600; ///< (in seconds) static constexpr size_t DOMAIN_MAXLEN = 256; @@ -69,24 +73,6 @@ static constexpr char DOMAIN_OSC[] = { 4 , '_','o','s','c'}; static constexpr char DOMAIN_DDP[] = { 4 , '_','d','d','p'}; static constexpr char DOMAIN_PP[] = { 3 , '_','p','p'}; -enum class Flags1 : uint8_t { - RESPONSE = 0x80, ///< query (0), or a response (1). - OPCODE_STATUS = 0x10, ///< a server status request (STATUS) - OPCODE_IQUERY = 0x08, ///< an inverse query (IQUERY) - OPCODE_STANDARD = 0x00, ///< (RFC 6762, section 18.3) - AUTHORATIVE = 0x04, ///< Authoritative Answer - TRUNC = 0x02, ///< TrunCation - RD = 0x01 ///< If RD is set, it directs the name server to pursue the query recursively. -}; - -enum class Classes : uint16_t { - Internet = 1, Any = 255, Flush = 0x8000 -}; - -enum class Types : uint16_t { - A = 1, PTR = 12, TXT = 16, SRV = 33, ALL = 255 -}; - enum class HostReply : uint32_t { A = 0x01, PTR = 0x02 }; @@ -206,20 +192,12 @@ static constexpr Domain DOMAIN_DNSSD { static ServiceRecord s_ServiceRecords[mdns::SERVICE_RECORDS_MAX]; static HostReply s_HostReplies; static ServiceReply s_ServiceReplies; -static uint8_t s_RecordsData[MULTICAST_MESSAGE_SIZE]; +static uint8_t s_RecordsData[net::dns::MULTICAST_MESSAGE_SIZE]; static bool s_isUnicast; static bool s_bLegacyQuery; } // namespace mdns -static constexpr uint8_t operator| (mdns::Flags1 a, mdns::Flags1 b) { - return static_cast((static_cast(a) | static_cast(b))); -} - -static constexpr uint16_t operator| (mdns::Classes a, mdns::Classes b) { - return static_cast((static_cast(a) | static_cast(b))); -} - static constexpr mdns::HostReply operator| (mdns::HostReply a, mdns::HostReply b) { return static_cast((static_cast(a) | static_cast(b))); } @@ -239,7 +217,7 @@ static constexpr mdns::ServiceReply operator& (mdns::ServiceReply a, mdns::Servi int32_t MDNS::s_nHandle; uint32_t MDNS::s_nRemoteIp; uint16_t MDNS::s_nRemotePort; -uint16_t MDNS::s_nBytesReceived; +uint32_t MDNS::s_nBytesReceived; uint8_t *MDNS::s_pReceiveBuffer; MDNS *MDNS::s_pThis; @@ -303,7 +281,7 @@ static void create_reverse_domain(Domain &domain) { auto nIp = Network::Get()->GetIp(); const auto *pIp = reinterpret_cast(&nIp); - for (int32_t i = network::IP_SIZE - 1; i >= 0; i--) { + for (int32_t i = IPv4_ADDR_LEN - 1; i >= 0; i--) { char buffer[3]; uint32_t nLength = 1; @@ -439,12 +417,12 @@ static uint8_t *put_domain_name_as_labels(uint8_t *ptr, Domain const &domain) { return ptr; } -static uint8_t *add_question(uint8_t *pDestination, const Domain& domain, const Types type, const bool bFlush) { +static uint8_t *add_question(uint8_t *pDestination, const Domain& domain, const net::dns::RRType type, const bool bFlush) { auto *pDst = put_domain_name_as_labels(pDestination, domain); *reinterpret_cast(pDst) = __builtin_bswap16(static_cast(type)); pDst += 2; - *reinterpret_cast(pDst) = __builtin_bswap16((bFlush ? Classes::Flush : static_cast(0)) | Classes::Internet); + *reinterpret_cast(pDst) = __builtin_bswap16((bFlush ? net::dns::RRClass::RRCLASS_FLUSH : static_cast(0)) | net::dns::RRClass::RRCLASS_INTERNET); pDst += 2; return pDst; @@ -456,7 +434,7 @@ static uint32_t add_answer_srv(mdns::ServiceRecord const& serviceRecord, uint8_t Domain domain; create_service_domain(domain, serviceRecord, true); - auto *pDst = add_question(pDestination, domain, Types::SRV, true); + auto *pDst = add_question(pDestination, domain, net::dns::RRType::RRTYPE_SRV, true); *reinterpret_cast(pDst) = __builtin_bswap32(nTTL); pDst += 4; @@ -483,7 +461,7 @@ static uint32_t add_answer_txt(mdns::ServiceRecord const& serviceRecord, uint8_t Domain domain; create_service_domain(domain, serviceRecord, true); - auto *pDst = add_question(pDestination, domain, Types::TXT, true); + auto *pDst = add_question(pDestination, domain, net::dns::RRType::RRTYPE_TXT, true); *reinterpret_cast(pDst) = __builtin_bswap32(nTTL); pDst += 4; @@ -513,7 +491,7 @@ static uint32_t add_answer_ptr(mdns::ServiceRecord const& serviceRecord, uint8_t Domain domain; create_service_domain(domain, serviceRecord, false); - auto *pDst = add_question(pDestination, domain, Types::PTR, false); + auto *pDst = add_question(pDestination, domain, net::dns::RRType::RRTYPE_PTR, false); *reinterpret_cast(pDst) = __builtin_bswap32(nTTL); pDst += 4; @@ -533,7 +511,7 @@ static uint32_t add_answer_ptr(mdns::ServiceRecord const& serviceRecord, uint8_t static uint32_t add_answer_dnsd_ptr(mdns::ServiceRecord const& serviceRecord, uint8_t *pDestination, const uint32_t nTTL) { DEBUG_ENTRY - auto *pDst = add_question(pDestination, DOMAIN_DNSSD, Types::PTR, false); + auto *pDst = add_question(pDestination, DOMAIN_DNSSD, net::dns::RRType::RRTYPE_PTR, false); *reinterpret_cast(pDst) = __builtin_bswap32(nTTL); pDst += 4; @@ -558,7 +536,7 @@ static uint32_t add_answer_a(uint8_t *pDestination, const uint32_t nTTL) { Domain domain; create_host_domain(domain); - auto *pDst = add_question(pDestination, domain, Types::A, true); + auto *pDst = add_question(pDestination, domain, net::dns::RRType::RRTYPE_A, true); *reinterpret_cast(pDst) = __builtin_bswap32(nTTL); pDst += 4; @@ -578,7 +556,7 @@ static uint32_t add_answer_hostv4_ptr(uint8_t *pDestination, const uint32_t nTTL Domain domain; create_reverse_domain(domain); - auto *pDst = add_question(pDestination, domain, Types::PTR, true); + auto *pDst = add_question(pDestination, domain, net::dns::RRType::RRTYPE_PTR, true); *reinterpret_cast(pDst) = __builtin_bswap32(nTTL); pDst += 4; @@ -675,14 +653,14 @@ void MDNS::SendAnswerLocalIpAddress(const uint16_t nTransActionID, const uint32_ DEBUG_ENTRY uint32_t nAnswers = 0; - uint8_t *pDst = reinterpret_cast(&s_RecordsData) + sizeof(struct Header); + uint8_t *pDst = reinterpret_cast(&s_RecordsData) + sizeof(struct net::dns::Header); #if defined (CONFIG_MDNS_DOMAIN_REVERSE) if ((HostReply::PTR & s_HostReplies) == HostReply::PTR) { if (s_bLegacyQuery) { Domain domain; create_reverse_domain(domain); - pDst = add_question(pDst, domain, Types::PTR, false); + pDst = add_question(pDst, domain, net::dns::RRType::RRTYPE_PTR, false); } } #endif @@ -698,10 +676,10 @@ void MDNS::SendAnswerLocalIpAddress(const uint16_t nTransActionID, const uint32_ } #endif - auto *pHeader = reinterpret_cast(&s_RecordsData); + auto *pHeader = reinterpret_cast< net::dns::Header *>(&s_RecordsData); pHeader->xid = nTransActionID; - pHeader->nFlag1 = Flags1::RESPONSE | Flags1::AUTHORATIVE; + pHeader->nFlag1 = net::dns::Flag1::FLAG1_RESPONSE | net::dns::Flag1::FLAG1_AUTHORATIVE; pHeader->nFlag2 = 0; #if defined (CONFIG_MDNS_DOMAIN_REVERSE) pHeader->nQueryCount = __builtin_bswap16(static_cast(s_bLegacyQuery)); @@ -726,10 +704,10 @@ MDNS::MDNS() { record.services = Services::LAST_NOT_USED; } - s_nHandle = Network::Get()->Begin(mdns::UDP_PORT); + s_nHandle = Network::Get()->Begin(net::iana::IANA_PORT_MDNS); assert(s_nHandle != -1); - Network::Get()->JoinGroup(s_nHandle, mdns::MULTICAST_ADDRESS); + Network::Get()->JoinGroup(s_nHandle, net::dns::MULTICAST_ADDRESS); Network::Get()->SetDomainName(&DOMAIN_LOCAL[1]); SendAnnouncement(MDNS_RESPONSE_TTL); @@ -748,15 +726,15 @@ MDNS::~MDNS() { } } - Network::Get()->LeaveGroup(s_nHandle, mdns::MULTICAST_ADDRESS); - Network::Get()->End(mdns::UDP_PORT); + Network::Get()->LeaveGroup(s_nHandle, net::dns::MULTICAST_ADDRESS); + Network::Get()->End(net::iana::IANA_PORT_MDNS); s_nHandle = -1; } void MDNS::SendAnnouncement(const uint32_t nTTL) { DEBUG_ENTRY - s_nRemotePort = mdns::UDP_PORT; //FIXME Hack ;-) + s_nRemotePort = net::iana::IANA_PORT_MDNS; //FIXME Hack ;-) s_HostReplies = HostReply::A; SendAnswerLocalIpAddress(0, nTTL); @@ -774,7 +752,7 @@ void MDNS::SendAnnouncement(const uint32_t nTTL) { DEBUG_EXIT } -bool MDNS::AddServiceRecord(const char *pName, const mdns::Services services, const char *pTextContent, const uint16_t nPort) { +bool MDNS::ServiceRecordAdd(const char *pName, const mdns::Services services, const char *pTextContent, const uint16_t nPort) { DEBUG_ENTRY assert(services < mdns::Services::LAST_NOT_USED); @@ -812,7 +790,7 @@ bool MDNS::AddServiceRecord(const char *pName, const mdns::Services services, co record.nTextContentLength = static_cast(nLength); } - s_nRemotePort = mdns::UDP_PORT; //FIXME Hack ;-) + s_nRemotePort = net::iana::IANA_PORT_MDNS; //FIXME Hack ;-) s_ServiceReplies = ServiceReply::TYPE_PTR | ServiceReply::NAME_PTR @@ -828,9 +806,34 @@ bool MDNS::AddServiceRecord(const char *pName, const mdns::Services services, co return false; } -void MDNS::SendTo(const uint16_t nLength) { +bool MDNS::ServiceRecordDelete(const mdns::Services service) { + DEBUG_ENTRY + assert(service < mdns::Services::LAST_NOT_USED); + + for (auto &record : s_ServiceRecords) { + if (record.services == service) { + SendMessage(record, 0, 0); + + if (record.pName != nullptr) { + delete[] record.pName; + } + + if (record.pTextContent != nullptr) { + delete[] record.pTextContent; + } + + DEBUG_EXIT + return true; + } + } + + DEBUG_EXIT + return false; +} + +void MDNS::SendTo(const uint32_t nLength) { if (!s_isUnicast) { - Network::Get()->SendTo(s_nHandle, s_RecordsData, nLength, mdns::MULTICAST_ADDRESS, mdns::UDP_PORT); + Network::Get()->SendTo(s_nHandle, s_RecordsData, nLength, net::dns::MULTICAST_ADDRESS, net::iana::IANA_PORT_MDNS); return; } @@ -841,7 +844,7 @@ void MDNS::SendMessage(mdns::ServiceRecord const& serviceRecord, const uint16_t DEBUG_ENTRY uint32_t nAnswers = 0; - auto *pDst = reinterpret_cast(&s_RecordsData) + sizeof(struct Header); + auto *pDst = reinterpret_cast(&s_RecordsData) + sizeof(struct net::dns::Header); if ((s_ServiceReplies & ServiceReply::TYPE_PTR) == ServiceReply::TYPE_PTR) { nAnswers++; @@ -865,10 +868,10 @@ void MDNS::SendMessage(mdns::ServiceRecord const& serviceRecord, const uint16_t pDst += add_answer_a(pDst, nTT); - auto *pHeader = reinterpret_cast
(&s_RecordsData); + auto *pHeader = reinterpret_cast(&s_RecordsData); pHeader->xid = nTransActionID; - pHeader->nFlag1 = Flags1::RESPONSE | Flags1::AUTHORATIVE; + pHeader->nFlag1 = net::dns::Flag1::FLAG1_RESPONSE | net::dns::Flag1::FLAG1_AUTHORATIVE; pHeader->nFlag2 = 0; pHeader->nQueryCount = 0; pHeader->nAnswerCount = __builtin_bswap16(static_cast(nAnswers)); @@ -886,12 +889,12 @@ void MDNS::HandleQuestions(const uint32_t nQuestions) { DEBUG_PRINTF("nQuestions=%u", nQuestions); s_HostReplies = static_cast(0); - s_isUnicast = (s_nRemotePort != mdns::UDP_PORT); + s_isUnicast = (s_nRemotePort != net::iana::IANA_PORT_MDNS); s_bLegacyQuery = s_isUnicast && (nQuestions == 1); const auto nTransactionID = s_bLegacyQuery ? *reinterpret_cast(&s_pReceiveBuffer[0]) : static_cast(0); - uint32_t nOffset = sizeof(struct Header); + uint32_t nOffset = sizeof(struct net::dns::Header); for (uint32_t i = 0; i < nQuestions; i++) { Domain resourceDomain; @@ -905,10 +908,10 @@ void MDNS::HandleQuestions(const uint32_t nQuestions) { resourceDomain.nLength = static_cast(pResult - &s_pReceiveBuffer[nOffset]); nOffset += resourceDomain.nLength; - const auto nType = static_cast(__builtin_bswap16(*reinterpret_cast(&s_pReceiveBuffer[nOffset]))); + const auto nType = static_cast(__builtin_bswap16(*reinterpret_cast(&s_pReceiveBuffer[nOffset]))); nOffset += 2; - const auto nClass = static_cast(__builtin_bswap16(*reinterpret_cast(&s_pReceiveBuffer[nOffset])) & 0x7F); + const auto nClass = static_cast(__builtin_bswap16(*reinterpret_cast(&s_pReceiveBuffer[nOffset])) & 0x7F); nOffset += 2; #ifndef NDEBUG @@ -916,7 +919,7 @@ void MDNS::HandleQuestions(const uint32_t nQuestions) { printf(" ==> Type : %d, Class: %d\n", static_cast(nType), static_cast(nClass)); #endif - if ((nClass != Classes::Internet) && (nClass != Classes::Any)) { + if ((nClass != net::dns::RRClass::RRCLASS_INTERNET) && (nClass != net::dns::RRClass::RRCLASS_ANY)) { continue; } @@ -926,7 +929,7 @@ void MDNS::HandleQuestions(const uint32_t nQuestions) { Domain domainHost; - if ((nType == Types::A) || (nType == Types::ALL)) { + if ((nType == net::dns::RRType::RRTYPE_A) || (nType == net::dns::RRType::RRTYPE_ALL)) { DEBUG_PUTS(""); create_host_domain(domainHost); @@ -936,7 +939,7 @@ void MDNS::HandleQuestions(const uint32_t nQuestions) { } #if defined (CONFIG_MDNS_DOMAIN_REVERSE) - if (nType == Types::PTR || nType == Types::ALL) { + if (nType == net::dns::RRType::RRTYPE_PTR || nType == net::dns::RRType::RRTYPE_ALL) { DEBUG_PUTS(""); create_reverse_domain(domainHost); @@ -956,7 +959,7 @@ void MDNS::HandleQuestions(const uint32_t nQuestions) { s_ServiceReplies = static_cast(0); Domain serviceDomain; - if (nType == Types::PTR || nType == Types::ALL) { + if (nType == net::dns::RRType::RRTYPE_PTR || nType == net::dns::RRType::RRTYPE_ALL) { if (DOMAIN_DNSSD == resourceDomain) { s_ServiceReplies = s_ServiceReplies | ServiceReply::TYPE_PTR; } @@ -971,11 +974,11 @@ void MDNS::HandleQuestions(const uint32_t nQuestions) { create_service_domain(serviceDomain, record, true); if (serviceDomain == resourceDomain) { - if ((nType == Types::SRV) || (nType == Types::ALL)) { + if ((nType == net::dns::RRType::RRTYPE_SRV) || (nType == net::dns::RRType::RRTYPE_ALL)) { s_ServiceReplies = s_ServiceReplies | ServiceReply::SRV; } - if ((nType == Types::TXT) || (nType == Types::ALL)) { + if ((nType == net::dns::RRType::RRTYPE_TXT) || (nType == net::dns::RRType::RRTYPE_ALL)) { s_ServiceReplies = s_ServiceReplies | ServiceReply::TXT; } } diff --git a/lib-network/src/net/apps/ntp/gd32/ptp/net_ptp.cpp b/lib-network/src/net/apps/ntp/gd32/ptp/net_ptp.cpp new file mode 100644 index 00000000..4f69e630 --- /dev/null +++ b/lib-network/src/net/apps/ntp/gd32/ptp/net_ptp.cpp @@ -0,0 +1,484 @@ +/** + * @file net_ptp.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * https://www.ietf.org/archive/id/draft-ietf-ntp-interleaved-modes-07.html#name-interleaved-client-server-m + */ +/* +Server t2 t3 t6 t7 t10 t11 + -----+----+----------------+----+----------------+----+----- + / \ / \ / \ +Client / \ / \ / \ + --+----------+----------+----------+----------+----------+-- + t1 t4 t5 t8 t9 t12 + +Mode: B B I I I I + +----+ +----+ +----+ +----+ +----+ +----+ +Org | 0 | | t1~| | t2 | | t4 | | t6 | | t8 | +Rx | 0 | | t2 | | t4 | | t6 | | t8 | |t10 | +Tx | t1~| | t3~| | t1 | | t3 | | t5 | | t7 | + +----+ +----+ +----+ +----+ +----+ +----+ + +T1 - local transmit timestamp of the latest request (t5) +T2 - remote receive timestamp from the latest response (t6) +T3 - remote transmit timestamp from the latest response (t3) +T4 - local receive timestamp of the previous response (t4) + */ + +#undef NDEBUG + +#if !defined (CONFIG_ENET_ENABLE_PTP) +# error +#endif +#if defined (ENABLE_NTP_CLIENT) +# error +#endif + +#pragma GCC push_options +#pragma GCC optimize ("O2") +#pragma GCC optimize ("no-tree-loop-distribute-patterns") + +#include +#include +#include +#include + +#include "hardware.h" +#include "network.h" +#include "networkparams.h" + +#include "net/protocol/ntp.h" + +#include "gd32_ptp.h" + +#include "debug.h" + +namespace net { +namespace globals { +extern uint32_t ptpTimestamp[2]; +} // namespace globals + +#define _NTPFRAC_(x) ( 4294U*static_cast(x) + ( (1981U*static_cast(x))>>11 ) + ((2911U*static_cast(x))>>28) ) +#define NTPFRAC(x) _NTPFRAC_(x / 1000) + +/** + * The reverse of the above, needed if we want to set our microsecond + * clock (via clock_settime) based on the incoming time in NTP format. + * Basically exact. + */ +#define USEC(x) ( ( (x) >> 12 ) - 759 * ( ( ( (x) >> 10 ) + 32768 ) >> 16 ) ) + +static constexpr uint32_t TIMEOUT_SECONDS = 3; +static constexpr uint8_t POLL_POWER = 3; +static constexpr uint32_t POLL_SECONDS = (1U << POLL_POWER); + +struct ntpClient { + uint32_t nServerIp; + int32_t nHandle; + ntp::Packet *pReply; + uint32_t nMillisRequest; + uint32_t nMillisLastPoll; + ntp::Status status; + ntp::Packet Request; + ntp::TimeStamp T1; // time request sent by client + ntp::TimeStamp T2; // time request received by server + ntp::TimeStamp T3; // time reply sent by server + ntp::TimeStamp T4; // time reply received by client + ntp::TimeStamp cookieBasic; + struct { + ntp::TimeStamp previousReceive; + ntp::TimeStamp dst; // destination timestamp + ntp::TimeStamp sentA; + ntp::TimeStamp sentB; + int32_t x; // interleave switch + uint32_t missedResponses; +#ifndef NDEBUG + ntp::Modes mode; +#endif + } state; +}; + +static ntpClient s_ntpClient; +static uint16_t s_id; +static constexpr uint16_t REQUEST_SIZE = sizeof s_ntpClient.Request; + +static void print(const char *pText, const struct ntp::TimeStamp *pNtpTime) { +#ifndef NDEBUG + const auto nSeconds = static_cast(pNtpTime->nSeconds - ntp::JAN_1970); + const auto *pTm = localtime(&nSeconds); + printf("%s %02d:%02d:%02d.%06d %04d [%u][0x%.8x]\n", pText, pTm->tm_hour, pTm->tm_min, pTm->tm_sec, USEC(pNtpTime->nFraction), pTm->tm_year + 1900, pNtpTime->nSeconds, pNtpTime->nFraction); +#endif +} + +void ptp_init() { + DEBUG_ENTRY + + memset(&s_ntpClient, 0, sizeof(struct ntpClient)); + s_ntpClient.state.previousReceive.nSeconds = ntp::JAN_1970; + s_ntpClient.state.dst.nSeconds = ntp::JAN_1970; + s_ntpClient.state.sentA.nSeconds = ntp::JAN_1970; + s_ntpClient.state.sentB.nSeconds = ntp::JAN_1970; + + s_ntpClient.state.missedResponses = 4; + + NetworkParams networkParams; + networkParams.Load(); + + s_ntpClient.nServerIp = networkParams.GetNtpServer(); + + if (s_ntpClient.nServerIp == 0) { + s_ntpClient.status = ntp::Status::STOPPED; + DEBUG_EXIT + return; + } + + struct timeval tv; + gettimeofday(&tv, nullptr); + srandom(static_cast(tv.tv_sec ^ tv.tv_usec)); + + s_ntpClient.Request.LiVnMode = ntp::VERSION | ntp::MODE_CLIENT; + s_ntpClient.Request.Poll = POLL_POWER; + + s_ntpClient.state.x = 1; + + s_ntpClient.nHandle = Network::Get()->Begin(ntp::UDP_PORT); + assert(s_ntpClient.nHandle != -1); + + s_ntpClient.status = ntp::Status::IDLE; + s_ntpClient.nMillisLastPoll = Hardware::Get()->Millis() - (1000U * POLL_SECONDS); + + DEBUG_PRINTF("Poll: %u", POLL_SECONDS); + DEBUG_EXIT +} + +void ptp_ntp_set_server_ip(const uint32_t nServerIp) { + s_ntpClient.nServerIp = nServerIp; +} + +void ptp_handle([[maybe_unused]] const uint8_t *pBuffer, [[maybe_unused]] const uint32_t nLength) { + /* Can only be used for PTP level 2 messages */ +} + +/** + * The interleaved client/server mode is similar to the basic client/ server mode. + * The difference between the two modes is in the values saved to the origin and transmit timestamp fields. + */ + +static bool send() { + s_ntpClient.state.missedResponses++; + + /** + * The first request from a client is always in the basic mode and so is the server response. + * It has a zero origin timestamp and zero receive timestamp. + * Only when the client receives a valid response from the server, + * it will be able to send a request in the interleaved mode + */ + if (s_ntpClient.state.missedResponses > 4) { + s_ntpClient.cookieBasic.nSeconds = random(); + s_ntpClient.cookieBasic.nFraction = 0; + + s_ntpClient.Request.OriginTimestamp_s = 0; + s_ntpClient.Request.OriginTimestamp_f = 0; + + s_ntpClient.Request.ReceiveTimestamp_s = 0; + s_ntpClient.Request.ReceiveTimestamp_f = 0; + + /** + * The origin timestamp is a cookie which is used to detect that a received packet + * is a response to the last packet sent in the other direction of the association. + */ + s_ntpClient.Request.TransmitTimestamp_s = __builtin_bswap32(s_ntpClient.cookieBasic.nSeconds); + s_ntpClient.Request.TransmitTimestamp_f = __builtin_bswap32(s_ntpClient.cookieBasic.nFraction); + } else { + /** + * A client request in the interleaved mode has an origin timestamp equal to + * the receive timestamp from the last valid server response. + */ + s_ntpClient.Request.OriginTimestamp_s = __builtin_bswap32(s_ntpClient.state.dst.nSeconds); + s_ntpClient.Request.OriginTimestamp_f = __builtin_bswap32(s_ntpClient.state.dst.nFraction); + + s_ntpClient.Request.ReceiveTimestamp_s = __builtin_bswap32(s_ntpClient.state.previousReceive.nSeconds); + s_ntpClient.Request.ReceiveTimestamp_f = __builtin_bswap32(s_ntpClient.state.previousReceive.nFraction); + + if (s_ntpClient.state.x > 0) { + s_ntpClient.Request.TransmitTimestamp_s = __builtin_bswap32(s_ntpClient.state.sentB.nSeconds); + s_ntpClient.Request.TransmitTimestamp_f = __builtin_bswap32(s_ntpClient.state.sentB.nFraction); + } else { + s_ntpClient.Request.TransmitTimestamp_s = __builtin_bswap32(s_ntpClient.state.sentA.nSeconds); + s_ntpClient.Request.TransmitTimestamp_f = __builtin_bswap32(s_ntpClient.state.sentA.nFraction); + } + } + + Network::Get()->SendToTimestamp(s_ntpClient.nHandle, &s_ntpClient.Request, REQUEST_SIZE, s_ntpClient.nServerIp, ntp::UDP_PORT); + +#ifndef NDEBUG + printf("Request: org=%.8x%.8x rx=%.8x%.8x tx=%.8x%.8x\n", + __builtin_bswap32(s_ntpClient.Request.OriginTimestamp_s), __builtin_bswap32(s_ntpClient.Request.OriginTimestamp_f), + __builtin_bswap32(s_ntpClient.Request.ReceiveTimestamp_s), __builtin_bswap32(s_ntpClient.Request.ReceiveTimestamp_f), + __builtin_bswap32(s_ntpClient.Request.TransmitTimestamp_s), __builtin_bswap32(s_ntpClient.Request.TransmitTimestamp_f)); +#endif + + if (s_ntpClient.state.x > 0) { + s_ntpClient.state.sentA.nSeconds = net::globals::ptpTimestamp[1] + ntp::JAN_1970; + s_ntpClient.state.sentA.nFraction = NTPFRAC(gd32::ptp_subsecond_2_nanosecond(net::globals::ptpTimestamp[0])); + } else { + s_ntpClient.state.sentB.nSeconds = net::globals::ptpTimestamp[1] + ntp::JAN_1970; + s_ntpClient.state.sentB.nFraction = NTPFRAC(gd32::ptp_subsecond_2_nanosecond(net::globals::ptpTimestamp[0])); + } + + s_ntpClient.state.x = -s_ntpClient.state.x; + s_id++; + + return true; +} + +static void difference(const ntp::TimeStamp& Start, const ntp::TimeStamp& Stop, int32_t& nDiffSeconds, int32_t& nDiffNanoSeconds) { + gd32::ptp::time_t r; + const gd32::ptp::time_t x = {.tv_sec = static_cast(Stop.nSeconds), .tv_nsec = static_cast(USEC(Stop.nFraction) * 1000)}; + const gd32::ptp::time_t y = {.tv_sec = static_cast(Start.nSeconds), .tv_nsec = static_cast(USEC(Start.nFraction) * 1000)}; + gd32::sub_time(&r, &x, &y); + + nDiffSeconds = r.tv_sec; + nDiffNanoSeconds = r.tv_nsec; +} + +static void update_ptp_time() { + int32_t nDiffSeconds1, nDiffNanoSeconds1; + difference(s_ntpClient.T1, s_ntpClient.T2, nDiffSeconds1, nDiffNanoSeconds1); + + int32_t nDiffSeconds2, nDiffNanoSeconds2; + difference(s_ntpClient.T4, s_ntpClient.T3, nDiffSeconds2, nDiffNanoSeconds2); + + auto nOffsetSeconds = static_cast(nDiffSeconds1) + static_cast(nDiffSeconds2); + auto nOffsetNanoSeconds = static_cast(nDiffNanoSeconds1) + static_cast(nDiffNanoSeconds2); + + const int32_t nOffsetSecondsAverage = nOffsetSeconds / 2; + const int32_t nOffsetNanosverage = nOffsetNanoSeconds / 2; + + gd32::ptp::time_t ptpOffset = {.tv_sec = nOffsetSecondsAverage, .tv_nsec = nOffsetNanosverage}; + gd32::normalize_time(&ptpOffset); + gd32_ptp_update_time(&ptpOffset); + + gd32::ptp::ptptime ptp_get; + gd32_ptp_get_time(&ptp_get); + + s_ntpClient.Request.ReferenceTimestamp_s = __builtin_bswap32(static_cast(ptp_get.tv_sec) + ntp::JAN_1970); + s_ntpClient.Request.ReferenceTimestamp_f = __builtin_bswap32(NTPFRAC(ptp_get.tv_nsec)); + +#ifndef NDEBUG + /** + * Network delay calculation + */ + gd32::ptp::time_t diff1; + gd32::ptp::time_t diff2; + + if (s_ntpClient.state.mode == ntp::Modes::BASIC) { + difference(s_ntpClient.T1, s_ntpClient.T4, diff1.tv_sec, diff1.tv_nsec); + difference(s_ntpClient.T2, s_ntpClient.T3, diff2.tv_sec, diff2.tv_nsec); + } else { + ntp::TimeStamp start; + start.nSeconds = __builtin_bswap32(s_ntpClient.Request.TransmitTimestamp_s); + start.nFraction = __builtin_bswap32(s_ntpClient.Request.TransmitTimestamp_f); + ntp::TimeStamp stop; + stop.nSeconds = __builtin_bswap32(s_ntpClient.Request.ReceiveTimestamp_s); + stop.nFraction = __builtin_bswap32(s_ntpClient.Request.ReceiveTimestamp_f); + difference(start, stop, diff1.tv_sec, diff1.tv_nsec); + + const auto *const pReply = s_ntpClient.pReply; + start.nSeconds = __builtin_bswap32(s_ntpClient.Request.OriginTimestamp_s); + start.nFraction = __builtin_bswap32(s_ntpClient.Request.OriginTimestamp_f); + stop.nSeconds = __builtin_bswap32(pReply->TransmitTimestamp_s); + stop.nFraction = __builtin_bswap32(pReply->TransmitTimestamp_f); + difference(start, stop, diff2.tv_sec, diff2.tv_nsec); + } + + gd32::ptp::time_t ptpDelay; + gd32::sub_time(&ptpDelay, &diff1, &diff2); + + char sign = '+'; + + if (ptpOffset.tv_sec < 0) { + ptpOffset.tv_sec = -ptpOffset.tv_sec; + sign = '-'; + } + + if (ptpOffset.tv_nsec < 0) { + ptpOffset.tv_nsec = -ptpOffset.tv_nsec; + sign = '-'; + } + + printf(" %s : offset=%c%d.%09d delay=%d.%09d\n", + s_ntpClient.state.mode == ntp::Modes::BASIC ? "Basic" : "Interleaved", + sign, ptpOffset.tv_sec, ptpOffset.tv_nsec, + ptpDelay.tv_sec, ptpDelay.tv_nsec); +#endif +} + +/** + * Two of the tests are modified for the interleaved mode: + * + * 1. The check for duplicate packets SHOULD compare both receive and + * transmit timestamps in order to not drop a valid response in the interleaved mode if + * it follows a response in the basic mode and they contain the same transmit timestamp. + * 2. The check for bogus packets SHOULD compare the origin timestamp with both transmit and + * receive timestamps from the request. + * If the origin timestamp is equal to the transmit timestamp, the response is in the basic mode. + * If the origin timestamp is equal to the receive timestamp, the response is in the interleaved mode. + */ + +static bool receive() { + uint32_t nFromIp; + uint16_t nFromPort; + + const auto nBytesReceived = Network::Get()->RecvFrom(s_ntpClient.nHandle, const_cast(reinterpret_cast(&s_ntpClient.pReply)), &nFromIp, &nFromPort); + + if (__builtin_expect((nBytesReceived != sizeof(struct ntp::Packet)), 1)) { + return false; + } + + if (__builtin_expect((nFromIp != s_ntpClient.nServerIp), 0)) { + DEBUG_PUTS("nFromIp != s_ntpClient.nServerIp"); + return false; + } + + if (s_ntpClient.state.missedResponses == 0) { + DEBUG_PUTS("Ignore duplicates"); + return false; + } + + return true; +} + +static void process() { + const auto *const pReply = s_ntpClient.pReply; +#ifndef NDEBUG + printf("Response: org=%.8x%.8x rx=%.8x%.8x tx=%.8x%.8x\n", + __builtin_bswap32(pReply->OriginTimestamp_s), __builtin_bswap32(pReply->OriginTimestamp_f), + __builtin_bswap32(pReply->ReceiveTimestamp_s), __builtin_bswap32(pReply->ReceiveTimestamp_f), + __builtin_bswap32(pReply->TransmitTimestamp_s), __builtin_bswap32(pReply->TransmitTimestamp_f)); +#endif + /** + * If the origin timestamp is equal to the transmit timestamp, + * the response is in the basic mode. + */ + if ((pReply->OriginTimestamp_s == s_ntpClient.Request.TransmitTimestamp_s) && (pReply->OriginTimestamp_f == s_ntpClient.Request.TransmitTimestamp_f)) { + if (s_ntpClient.state.x < 0) { + s_ntpClient.T1.nSeconds = s_ntpClient.state.sentA.nSeconds; + s_ntpClient.T1.nFraction = s_ntpClient.state.sentA.nFraction; + } else { + s_ntpClient.T1.nSeconds = s_ntpClient.state.sentB.nSeconds; + s_ntpClient.T1.nFraction = s_ntpClient.state.sentB.nFraction; + } + + s_ntpClient.T4.nSeconds = net::globals::ptpTimestamp[1] + ntp::JAN_1970; + s_ntpClient.T4.nFraction = NTPFRAC(gd32::ptp_subsecond_2_nanosecond(net::globals::ptpTimestamp[0])); +#ifndef NDEBUG + s_ntpClient.state.mode = ntp::Modes::BASIC; +#endif + } else + /** + * If the origin timestamp is equal to the receive timestamp, + * the response is in the interleaved mode. + */ + if ((pReply->OriginTimestamp_s == s_ntpClient.Request.ReceiveTimestamp_s) && (pReply->OriginTimestamp_f == s_ntpClient.Request.ReceiveTimestamp_f)) { + if (s_ntpClient.state.x > 0) { + s_ntpClient.T1.nSeconds = s_ntpClient.state.sentB.nSeconds; + s_ntpClient.T1.nFraction = s_ntpClient.state.sentB.nFraction; + } else { + s_ntpClient.T1.nSeconds = s_ntpClient.state.sentA.nSeconds; + s_ntpClient.T1.nFraction = s_ntpClient.state.sentA.nFraction; + } + + s_ntpClient.T4.nSeconds = s_ntpClient.state.previousReceive.nSeconds; + s_ntpClient.T4.nFraction = s_ntpClient.state.previousReceive.nFraction; +#ifndef NDEBUG + s_ntpClient.state.mode = ntp::Modes::INTERLEAVED; +#endif + } else { + DEBUG_PUTS("INVALID RESPONSE"); + return; + } + + s_ntpClient.T2.nSeconds = __builtin_bswap32(pReply->ReceiveTimestamp_s); + s_ntpClient.T2.nFraction = __builtin_bswap32(pReply->ReceiveTimestamp_f); + + s_ntpClient.T3.nSeconds = __builtin_bswap32(pReply->TransmitTimestamp_s); + s_ntpClient.T3.nFraction = __builtin_bswap32(pReply->TransmitTimestamp_f); + + s_ntpClient.state.dst.nSeconds = __builtin_bswap32(pReply->ReceiveTimestamp_s); + s_ntpClient.state.dst.nFraction = __builtin_bswap32(pReply->ReceiveTimestamp_f); + + s_ntpClient.state.previousReceive.nSeconds = net::globals::ptpTimestamp[1] + ntp::JAN_1970; + s_ntpClient.state.previousReceive.nFraction = NTPFRAC(gd32::ptp_subsecond_2_nanosecond(net::globals::ptpTimestamp[0])); + + update_ptp_time(); + + s_ntpClient.state.missedResponses = 0; + + print("T1: ", &s_ntpClient.T1); + print("T2: ", &s_ntpClient.T2); + print("T3: ", &s_ntpClient.T3); + print("T4: ", &s_ntpClient.T4); +} + +void ptp_run() { + if (s_ntpClient.status == ntp::Status::STOPPED) { + return; + } + + if ((s_ntpClient.status == ntp::Status::IDLE) || (s_ntpClient.status == ntp::Status::FAILED)) { + const auto nMillis = Hardware::Get()->Millis(); + if (__builtin_expect(((nMillis - s_ntpClient.nMillisLastPoll) > (1000U * POLL_SECONDS)), 0)) { + if (send()) { + s_ntpClient.status = ntp::Status::WAITING; + s_ntpClient.nMillisRequest = nMillis; + } else { + s_ntpClient.status = ntp::Status::FAILED; + s_ntpClient.nMillisLastPoll = nMillis; + } + } + return; + } + + if (s_ntpClient.status == ntp::Status::WAITING) { + if (__builtin_expect((!receive()), 1)) { + if (__builtin_expect(((Hardware::Get()->Millis() - s_ntpClient.nMillisRequest) > (1000U * TIMEOUT_SECONDS)), 0)) { + s_ntpClient.status = ntp::Status::FAILED; + DEBUG_PUTS("FAILED"); + } + return; + } + + if (__builtin_expect(((s_ntpClient.pReply->LiVnMode & ntp::MODE_SERVER) == ntp::MODE_SERVER), 1)) { + s_ntpClient.nMillisLastPoll = Hardware::Get()->Millis(); + process(); + } else { + DEBUG_PUTS("INVALID REPLY"); + } + + s_ntpClient.status = ntp::Status::IDLE; + } +} +} // namespace net diff --git a/lib-network/src/net/apps/ntp/ntpclient.cpp b/lib-network/src/net/apps/ntp/ntpclient.cpp new file mode 100755 index 00000000..4db22dce --- /dev/null +++ b/lib-network/src/net/apps/ntp/ntpclient.cpp @@ -0,0 +1,263 @@ +/** + * @file ntpclient.cpp + * + */ +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if defined (DEBUG_NTP_CLIENT) +# if defined (NDEBUG) +# undef NDEBUG +# endif +#endif + +#include +#include +#include +#include +#include + +#include "net/apps/ntpclient.h" +#include "net/protocol/ntp.h" +#include "utc.h" + +#include "network.h" +#include "networkparams.h" +#include "hardware.h" + +#include "debug.h" + +/* How to multiply by 4294.967296 quickly (and not quite exactly) + * without using floating point or greater than 32-bit integers. + * If you want to fix the last 12 microseconds of error, add in + * (2911*(x))>>28) + */ +#define NTPFRAC(x) ( 4294U*static_cast(x) + ( (1981U*static_cast(x))>>11 ) + ((2911U*static_cast(x))>>28) ) + +/* The reverse of the above, needed if we want to set our microsecond + * clock (via clock_settime) based on the incoming time in NTP format. + * Basically exact. + */ +#define USEC(x) ( ( (x) >> 12 ) - 759 * ( ( ( (x) >> 10 ) + 32768 ) >> 16 ) ) + +/* +Timestamp Name ID When Generated +---------------------------------------------------------------- +Originate Timestamp T1 time request sent by client +Receive Timestamp T2 time request received by server +Transmit Timestamp T3 time reply sent by server +Destination Timestamp T4 time reply received by client +*/ + +NtpClient *NtpClient::s_pThis; + +NtpClient::NtpClient() { + DEBUG_ENTRY + assert(s_pThis == nullptr); + s_pThis = this; + + memset(&m_Request, 0, sizeof m_Request); + + m_Request.LiVnMode = ntp::VERSION | ntp::MODE_CLIENT; + m_Request.Poll = ntpclient::POLL_POWER; + m_Request.ReferenceID = ('A' << 0) | ('V' << 8) | ('S' << 16); + + NetworkParams networkParams; + networkParams.Load(); + + m_nServerIp = networkParams.GetNtpServer(); + + if (m_nServerIp == 0) { + m_Status = ntp::Status::STOPPED; + } + + DEBUG_EXIT +} + +/* + * Seconds and Fractions since 01.01.1900 + */ +void NtpClient::GetTimeNtpFormat(uint32_t &nSeconds, uint32_t &nFraction) { + struct timeval now; + gettimeofday(&now, nullptr); + nSeconds = now.tv_sec + ntp::JAN_1970; + nFraction = NTPFRAC(now.tv_usec); +} + +void NtpClient::Send() { + GetTimeNtpFormat(T1.nSeconds, T1.nFraction); + + m_Request.OriginTimestamp_s = __builtin_bswap32(T1.nSeconds); + m_Request.OriginTimestamp_f = __builtin_bswap32(T1.nFraction); + + Network::Get()->SendTo(m_nHandle, &m_Request, sizeof m_Request, m_nServerIp, ntp::UDP_PORT); +} + +bool NtpClient::Receive(uint8_t& LiVnMode) { + uint32_t nFromIp; + uint16_t nFromPort; + ntp::Packet *pReply; + + const auto nBytesReceived = Network::Get()->RecvFrom(m_nHandle, const_cast(reinterpret_cast(&pReply)), &nFromIp, &nFromPort); + + if (__builtin_expect((nBytesReceived != sizeof(struct ntp::Packet)), 1)) { + return false; + } + + GetTimeNtpFormat(T4.nSeconds, T4.nFraction); + + if (__builtin_expect((nFromIp != m_nServerIp), 0)) { + DEBUG_PUTS("nFromIp != m_nServerIp"); + return false; + } + + LiVnMode = pReply->LiVnMode; + + T2.nSeconds = __builtin_bswap32(pReply->ReceiveTimestamp_s); + T2.nFraction = __builtin_bswap32(pReply->ReceiveTimestamp_f); + + T3.nSeconds = __builtin_bswap32(pReply->TransmitTimestamp_s); + T3.nFraction = __builtin_bswap32(pReply->TransmitTimestamp_f); + + PrintNtpTime("T1: ", &T1); + PrintNtpTime("T2: ", &T2); + PrintNtpTime("T3: ", &T3); + PrintNtpTime("T4: ", &T4); + + return true; +} + +void NtpClient::Difference(const struct ntp::TimeStamp& Start, const struct ntp::TimeStamp& Stop, int32_t &nDiffSeconds, int32_t &nDiffMicroSeconds) { + ntp::time_t r; + const ntp::time_t x = {.tv_sec = static_cast(Stop.nSeconds), .tv_usec = static_cast(USEC(Stop.nFraction))}; + const ntp::time_t y = {.tv_sec = static_cast(Start.nSeconds), .tv_usec = static_cast(USEC(Start.nFraction))}; + ntp::sub_time(&r, &x, &y); + + nDiffSeconds = r.tv_sec; + nDiffMicroSeconds = r.tv_usec; +} + +void NtpClient::SetTimeOfDay() { + int32_t nDiffSeconds1, nDiffSeconds2 ; + int32_t nDiffMicroSeconds1, nDiffMicroSeconds2; + + Difference(T1, T2, nDiffSeconds1, nDiffMicroSeconds1); + Difference(T4, T3, nDiffSeconds2, nDiffMicroSeconds2); + + auto nOffsetSeconds = static_cast(nDiffSeconds1) + static_cast(nDiffSeconds2); + auto nOffsetMicroSeconds = static_cast(nDiffMicroSeconds1) + static_cast(nDiffMicroSeconds2); + + const int32_t nOffsetSecondsAverage = nOffsetSeconds / 2; + const int32_t nOffsetMicrosAverage = nOffsetMicroSeconds / 2; + + ntp::time_t ptpOffset = {.tv_sec = nOffsetSecondsAverage, .tv_usec = nOffsetMicrosAverage}; + ntp::normalize_time(&ptpOffset); + + struct timeval tv; + + tv.tv_sec = static_cast(T4.nSeconds - ntp::JAN_1970) + nOffsetSecondsAverage; + tv.tv_usec = (static_cast(USEC(T4.nFraction)) + static_cast(nOffsetMicrosAverage)); + + settimeofday(&tv, nullptr); + +#ifndef NDEBUG + /* delay */ + ntp::time_t diff1; + ntp::time_t diff2; + + Difference(T1, T4, diff1.tv_sec, diff1.tv_usec); + Difference(T2, T3, diff2.tv_sec, diff2.tv_usec); + + ntp::time_t ntpDelay; + ntp::sub_time(&ntpDelay, &diff1, &diff2); + + char sign = '+'; + + if (ptpOffset.tv_sec < 0) { + ptpOffset.tv_sec = -ptpOffset.tv_sec; + sign = '-'; + } + + if (ptpOffset.tv_usec < 0) { + ptpOffset.tv_usec = -ptpOffset.tv_usec; + sign = '-'; + } + + printf(" offset=%c%d.%06d delay=%d.%06d\n", sign, ptpOffset.tv_sec, ptpOffset.tv_usec, ntpDelay.tv_sec, ntpDelay.tv_usec); +#endif +} + +void NtpClient::Start() { + DEBUG_ENTRY + + if (m_nServerIp == 0) { + m_Status = ntp::Status::STOPPED; + ntpclient::display_status(ntp::Status::STOPPED); + DEBUG_EXIT + return; + } + + assert(m_nHandle == -1); + m_nHandle = Network::Get()->Begin(ntp::UDP_PORT); + assert(m_nHandle != -1); + + m_MillisLastPoll = Hardware::Get()->Millis() - (1000 * ntpclient::POLL_SECONDS); + + m_Status = ntp::Status::IDLE; + ntpclient::display_status(ntp::Status::IDLE); + + DEBUG_EXIT +} + +void NtpClient::Stop() { + DEBUG_ENTRY + + if (m_Status == ntp::Status::STOPPED) { + return; + } + + assert(m_nHandle != -1); + Network::Get()->End(ntp::UDP_PORT); + m_nHandle = -1; + + m_Status = ntp::Status::STOPPED; + + ntpclient::display_status(ntp::Status::STOPPED); + + DEBUG_EXIT +} + +void NtpClient::PrintNtpTime([[maybe_unused]] const char *pText, [[maybe_unused]] const struct ntp::TimeStamp *pNtpTime) { +#ifndef NDEBUG + const auto nSeconds = static_cast(pNtpTime->nSeconds - ntp::JAN_1970); + const auto *pTm = localtime(&nSeconds); + printf("%s %02d:%02d:%02d.%06d %04d [%u]\n", pText, pTm->tm_hour, pTm->tm_min, pTm->tm_sec, USEC(pNtpTime->nFraction), pTm->tm_year + 1900, pNtpTime->nSeconds); +#endif +} + +void NtpClient::Print() { + printf("NTP v%d Client [%s]\n", (ntp::VERSION >> 3), ntp::STATUS[static_cast(m_Status)]); + if (m_Status == ntp::Status::STOPPED) { + puts(" Not enabled"); + return; + } + printf(" Server : " IPSTR ":%d\n", IP2STR(m_nServerIp), ntp::UDP_PORT); +} diff --git a/lib-network/src/apps/tftp/tftpdaemon.cpp b/lib-network/src/net/apps/tftp/tftpdaemon.cpp similarity index 96% rename from lib-network/src/apps/tftp/tftpdaemon.cpp rename to lib-network/src/net/apps/tftp/tftpdaemon.cpp index ca311230..3d0c3d9d 100644 --- a/lib-network/src/apps/tftp/tftpdaemon.cpp +++ b/lib-network/src/net/apps/tftp/tftpdaemon.cpp @@ -2,7 +2,7 @@ * @file tftpdaemon.cpp * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,7 +31,7 @@ #include #include -#include "tftpdaemon.h" +#include "net/apps/tftpdaemon.h" #include "network.h" @@ -259,7 +259,7 @@ void TFTPDaemon::DoRead() { FileClose(); } - DEBUG_PRINTF("m_nDataLength=%ld, m_nPacketLength=%d, m_bIsLastBlock=%d", m_nDataLength, m_nPacketLength, m_bIsLastBlock); + DEBUG_PRINTF("m_nDataLength=%u, m_nPacketLength=%d, m_bIsLastBlock=%d", m_nDataLength, m_nPacketLength, m_bIsLastBlock); } DEBUG_PRINTF("Sending to " IPSTR ":%d", IP2STR(m_nFromIp), m_nFromPort); @@ -304,7 +304,7 @@ void TFTPDaemon::HandleRecvData() { m_nDataLength = m_nLength - 4; m_nBlockNumber = __builtin_bswap16(pDataPacket->BlockNumber); - DEBUG_PRINTF("Incoming from " IPSTR ", m_nLength=%u, m_nBlockNumber=%d, m_nDataLength=%u", IP2STR(m_nFromIp), static_cast(m_nLength), m_nBlockNumber, static_cast(m_nDataLength)); + DEBUG_PRINTF("Incoming from " IPSTR ", m_nLength=%u, m_nBlockNumber=%d, m_nDataLength=%u", IP2STR(m_nFromIp), m_nLength, m_nBlockNumber, m_nDataLength); if (m_nDataLength == FileWrite(pDataPacket->Data, m_nDataLength, m_nBlockNumber)) { diff --git a/lib-network/src/net/arp.cpp b/lib-network/src/net/arp.cpp old mode 100644 new mode 100755 index 1cb8e094..466e9235 --- a/lib-network/src/net/arp.cpp +++ b/lib-network/src/net/arp.cpp @@ -2,7 +2,7 @@ * @file arp.cpp * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,228 +22,497 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +/** + * https://datatracker.ietf.org/doc/html/rfc826 + * An Ethernet Address Resolution Protocol + * -- or -- + * Converting Network Protocol Addresses + */ + +#if defined (DEBUG_NET_ARP) +# undef NDEBUG +#endif + +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif #include #include +#include #include -#include "net.h" +#include "../../config/net_config.h" + +#include "net_memcpy.h" #include "net_private.h" -#include "../../config/net_config.h" +#include "net/arp.h" +#include "net/acd.h" +#include "net/protocol/arp.h" +#include "net/protocol/udp.h" +#include "netif.h" -namespace net { -namespace arp { -enum class RequestType { - REQUEST, - PROBE, - ANNNOUNCEMENT -}; -} // namespace arp -} // namespace net +#include "hardware.h" -static struct t_arp s_arp_request ALIGNED ; -static struct t_arp s_arp_reply ALIGNED; -static net::arp::RequestType s_requestType ALIGNED; -static bool s_isProbeReplyReceived ALIGNED; +#include "debug.h" + +#if !defined ARP_MAX_RECORDS +static constexpr auto MAX_RECORDS = 16; +#else +static constexpr auto MAX_RECORDS = ARP_MAX_RECORDS; +#endif namespace net { namespace globals { -extern struct IpInfo ipInfo; -extern uint8_t macAddress[ETH_ADDR_LEN]; +extern uint32_t nOnNetworkMask; } // namespace globals -} // namespace net -typedef union pcast32 { - uint32_t u32; - uint8_t u8[4]; -} _pcast32; +namespace arp { +static constexpr uint32_t TIMER_INTERVAL = 1000; ///< 1 second +static constexpr uint32_t MAX_PROBING = 2; ///< 2 * 1 second +static constexpr uint32_t MAX_REACHABLE = (10 * 60); ///< (10 * 60) * 1 second = 10 minutes +static constexpr uint32_t MAX_STALE = ( 5 * 60); ///< ( 5 * 60) * 1 second = 5 minutes -void __attribute__((cold)) arp_init() { - arp_cache_init(); +enum class State { + STATE_EMPTY, STATE_PROBE, STATE_REACHABLE, STATE_STALE, +}; - s_requestType = net::arp::RequestType::REQUEST; +struct Packet { + uint8_t *p; + uint32_t nSize; +#if defined CONFIG_ENET_ENABLE_PTP + bool isTimestamp; +#endif +}; - // ARP Request template - // Ethernet header - memcpy(s_arp_request.ether.src, net::globals::macAddress, ETH_ADDR_LEN); - memset(s_arp_request.ether.dst, 0xFF , ETH_ADDR_LEN); - s_arp_request.ether.type = __builtin_bswap16(ETHER_TYPE_ARP); +struct Record { + uint32_t nIp; + Packet packet; + uint8_t mac_address[ETH_ADDR_LEN]; + uint16_t nAge; + State state; +}; +} // namespace arp - // ARP Header - s_arp_request.arp.hardware_type = __builtin_bswap16(ARP_HWTYPE_ETHERNET); - s_arp_request.arp.protocol_type = __builtin_bswap16(ARP_PRTYPE_IPv4); - s_arp_request.arp.hardware_size = ARP_HARDWARE_SIZE; - s_arp_request.arp.protocol_size = ARP_PROTOCOL_SIZE; - s_arp_request.arp.opcode = __builtin_bswap16(ARP_OPCODE_RQST); +static net::arp::Record s_ArpRecords[MAX_RECORDS] SECTION_NETWORK ALIGNED; - memcpy(s_arp_request.arp.sender_mac, net::globals::macAddress, ETH_ADDR_LEN); - _pcast32 ip_addr; - ip_addr.u32 = net::globals::ipInfo.ip.addr; - memcpy(s_arp_request.arp.sender_ip, ip_addr.u8, IPv4_ADDR_LEN); - memset(s_arp_request.arp.target_mac, 0x00, ETH_ADDR_LEN); +static struct t_arp s_arp_request ALIGNED ; +static struct t_arp s_arp_reply ALIGNED; - // ARP Reply Template - // Ethernet header - memcpy(s_arp_reply.ether.src, net::globals::macAddress, ETH_ADDR_LEN); - s_arp_reply.ether.type = __builtin_bswap16(ETHER_TYPE_ARP); +#ifndef NDEBUG +static constexpr char STATE[4][12] = { "EMPTY", "PROBE", "REACHABLE", "STALE", }; - // ARP Header - s_arp_reply.arp.hardware_type = __builtin_bswap16(ARP_HWTYPE_ETHERNET); - s_arp_reply.arp.protocol_type = __builtin_bswap16(ARP_PRTYPE_IPv4); - s_arp_reply.arp.hardware_size = ARP_HARDWARE_SIZE; - s_arp_reply.arp.protocol_size = ARP_PROTOCOL_SIZE; - s_arp_reply.arp.opcode = __builtin_bswap16(ARP_OPCODE_REPLY); +void static arp_cache_record_dump(net::arp::Record *pRecord) { + printf("%p %-4d %c " MACSTR " %-10s " IPSTR "\n", pRecord, pRecord->nAge, pRecord->packet.p == nullptr ? '-' : 'Q' , MAC2STR(pRecord->mac_address), STATE[static_cast(pRecord->state)], IP2STR(pRecord->nIp)); +} - memcpy(s_arp_reply.arp.sender_mac, net::globals::macAddress, ETH_ADDR_LEN); +void static arp_cache_dump() { + uint32_t nIndex = 0; + for (auto &record : s_ArpRecords) { + printf("%p %02d %-4d" MACSTR " %-10s " IPSTR "\n", &record, nIndex++, record.nAge, MAC2STR(record.mac_address), STATE[static_cast(record.state)], IP2STR(record.nIp)); + if (nIndex ==6) { + return; + } + } } +#else +void static arp_cache_record_dump([[maybe_unused]] net::arp::Record *pRecord) {} +void static arp_cache_dump() {} +#endif -bool arp_do_probe() { - int32_t nTimeout; - auto nRetries = 3; +static net::arp::Record *arp_find_record(const uint32_t nDestinationIp, [[maybe_unused]] const arp::Flags flag) { + DEBUG_ENTRY - while (nRetries--) { - arp_send_probe(); + net::arp::Record *pStale = nullptr; + net::arp::Record *pReachable = nullptr; + uint32_t nAgeStale = 0; + uint32_t nAgeReachable = 0; - nTimeout = 0x1FFFF; -#ifndef NDEBUG - nTimeout+= 0x40000; -#endif + for (auto &record : s_ArpRecords) { + if (record.nIp == nDestinationIp) { + DEBUG_EXIT + return &record; + } + + if (flag == arp::Flags::FLAG_UPDATE) { + continue; + } - while ((nTimeout-- > 0) && !s_isProbeReplyReceived) { - net_handle(); + if (record.state == net::arp::State::STATE_EMPTY) { + record.nIp = nDestinationIp; + DEBUG_EXIT + return &record; } - if (s_isProbeReplyReceived) { - return true; + if (record.state == net::arp::State::STATE_REACHABLE) { + if (record.nAge > nAgeReachable) { + nAgeReachable = record.nAge; + pReachable = &record; + } + continue; } + + + if (record.state == net::arp::State::STATE_STALE) { + if (record.nAge > nAgeStale) { + nAgeStale = record.nAge; + pStale = &record; + } + continue; + } + } + + if (pStale != nullptr) { + DEBUG_EXIT + return pStale; } - return false; + if (pReachable != nullptr) { + DEBUG_EXIT + return pReachable; + } + + DEBUG_EXIT + return nullptr; } -void arp_send_request(uint32_t nIp) { +static void arp_cache_update(const uint8_t *pMacAddress, const uint32_t nIp, const arp::Flags flag) { DEBUG_ENTRY - DEBUG_PRINTF(IPSTR, IP2STR(nIp)); + DEBUG_PRINTF(MACSTR " " IPSTR " flag=%d", MAC2STR(pMacAddress), IP2STR(nIp), flag); - s_requestType = net::arp::RequestType::REQUEST; + auto *record = arp_find_record(nIp, flag); - _pcast32 ip_addr; - ip_addr.u32 = nIp; + if (record == nullptr) { + assert(flag == arp::Flags::FLAG_UPDATE); + DEBUG_EXIT + return; + } - memcpy(s_arp_request.arp.target_ip, ip_addr.u8, IPv4_ADDR_LEN); + record->state = net::arp::State::STATE_REACHABLE; + record->nAge = 0; + std::memcpy(record->mac_address, pMacAddress, ETH_ADDR_LEN); - emac_eth_send(reinterpret_cast(&s_arp_request), sizeof(struct t_arp)); + arp_cache_record_dump(record); + + if (record->packet.p != nullptr) { + auto *udp = reinterpret_cast(record->packet.p); + std::memcpy(udp->ether.dst, record->mac_address, ETH_ADDR_LEN); + udp->ip4.chksum = 0; +#if !defined (CHECKSUM_BY_HARDWARE) + udp->ip4.chksum = net_chksum(reinterpret_cast(&udp->ip4), sizeof(udp->ip4)); +#endif +#if defined CONFIG_ENET_ENABLE_PTP + if (!record->packet.isTimestamp) { +#endif + emac_eth_send(record->packet.p, record->packet.nSize); +#if defined CONFIG_ENET_ENABLE_PTP + } else { + emac_eth_send_timestamp(record->packet.p, record->packet.nSize); + } +#endif + delete [] record->packet.p; + record->packet.p = nullptr; + } DEBUG_EXIT } -/* - * The Sender IP is set to all zeros, - * which means it cannot map to the Sender MAC address. - * The Target MAC address is all zeros, - * which means it cannot map to the Target IP address. - */ -void arp_send_probe() { +static void arp_send_request(const uint32_t nIp) { + DEBUG_PRINTF(IPSTR, IP2STR(nIp)); + + net::memcpy_ip(s_arp_request.arp.target_ip, nIp); + + emac_eth_send(reinterpret_cast(&s_arp_request), sizeof(struct t_arp)); +} + +template +static void arp_query(const uint32_t nDestinationIp, struct t_udp *pPacket, const uint32_t nSize, [[maybe_unused]] const arp::Flags flag) { DEBUG_ENTRY + DEBUG_PRINTF(IPSTR " %c", IP2STR(nDestinationIp), flag == arp::Flags::FLAG_UPDATE ? 'U' : 'I'); - s_requestType = net::arp::RequestType::PROBE; - s_isProbeReplyReceived = false; + auto *recordFound = arp_find_record(nDestinationIp, flag); + assert(recordFound != nullptr); - memset(s_arp_request.arp.sender_ip, 0, IPv4_ADDR_LEN); + arp_cache_record_dump(recordFound); + + if (recordFound->state == net::arp::State::STATE_EMPTY) { + recordFound->state = net::arp::State::STATE_PROBE; + recordFound->nAge = 0; + arp_send_request(nDestinationIp); + } + + if (recordFound->state == net::arp::State::STATE_PROBE) { + if (recordFound->packet.p != nullptr) { + delete[] recordFound->packet.p; + } - arp_send_request(net::globals::ipInfo.ip.addr); + recordFound->packet.p = new uint8_t[nSize]; + assert(recordFound->packet.p != nullptr); - _pcast32 ip_addr; - ip_addr.u32 = net::globals::ipInfo.ip.addr; - memcpy(s_arp_request.arp.sender_ip, ip_addr.u8, IPv4_ADDR_LEN); + net::memcpy(recordFound->packet.p, pPacket, nSize); + recordFound->packet.nSize = nSize; +#if defined CONFIG_ENET_ENABLE_PTP + recordFound->packet.isTimestamp = (S != net::arp::EthSend::IS_NORMAL); +#endif + } DEBUG_EXIT } -/* - * The packet structure is identical to the ARP Probe above, - * with the exception that a complete mapping exists. - * Both the Sender MAC address and the Sender IP address create a complete ARP mapping, - * and hosts on the network can use this pair of addresses in their ARP table. - */ -void arp_send_announcement() { - DEBUG_ENTRY +static void arp_cache_clean_record(net::arp::Record& record) { + if (record.packet.p != nullptr) { + delete[] record.packet.p; + } + memset(&record, 0, sizeof(struct net::arp::Record)); +} - s_requestType = net::arp::RequestType::ANNNOUNCEMENT; +static void arp_send_request_unicast(const uint32_t nIp, const uint8_t *pMacAddress) { + DEBUG_PRINTF(IPSTR, IP2STR(nIp)); - arp_send_request(net::globals::ipInfo.ip.addr); + net::memcpy(s_arp_request.ether.dst, pMacAddress , ETH_ADDR_LEN); + net::memcpy_ip(s_arp_request.arp.target_ip, nIp); - DEBUG_EXIT + emac_eth_send(reinterpret_cast(&s_arp_request), sizeof(struct t_arp)); + + memset(s_arp_request.ether.dst, 0xFF , ETH_ADDR_LEN); +} + +static void arp_timer() { + for (auto &record : s_ArpRecords) { + const auto state = record.state; + if (state != net::arp::State::STATE_EMPTY) { + record.nAge++; + + switch (state) { + case net::arp::State::STATE_PROBE: + if (record.nAge > net::arp::MAX_PROBING) { + arp_cache_clean_record(record); + } + break; + + case net::arp::State::STATE_REACHABLE: + if (record.nAge > net::arp::MAX_REACHABLE) { + record.state = net::arp::State::STATE_STALE; + record.nAge = 0; + } + break; + + case net::arp::State::STATE_STALE: + if (record.nAge > net::arp::MAX_STALE) { + record.state = net::arp::State::STATE_PROBE; + arp_send_request_unicast(record.nIp, record.mac_address); + } + break; + + default: + break; + } + } + } + + arp_cache_dump(); } -void arp_handle_request(struct t_arp *p_arp) { +static void arp_send_reply(const struct t_arp *p_arp) { DEBUG_ENTRY - _pcast32 target; + // Ethernet header + std::memcpy(s_arp_reply.ether.dst, p_arp->ether.src, ETH_ADDR_LEN); + // ARP Header + const auto nIpTarget = net::memcpy_ip(p_arp->arp.target_ip); + std::memcpy(s_arp_reply.arp.target_mac, p_arp->arp.sender_mac, ETH_ADDR_LEN); + std::memcpy(s_arp_reply.arp.target_ip, p_arp->arp.sender_ip, IPv4_ADDR_LEN); + net::memcpy_ip(s_arp_reply.arp.sender_ip, nIpTarget); - memcpy(target.u8, p_arp->arp.target_ip, IPv4_ADDR_LEN); + emac_eth_send(reinterpret_cast(&s_arp_reply), sizeof(struct t_arp)); - _pcast32 sender; + DEBUG_EXIT +} - memcpy(sender.u8, p_arp->arp.sender_ip, IPv4_ADDR_LEN); +// Public interface - DEBUG_PRINTF("Sender " IPSTR " Target " IPSTR, IP2STR(sender.u32), IP2STR(target.u32)); +void __attribute__((cold)) arp_init() { + DEBUG_ENTRY - if (!((target.u32 == net::globals::ipInfo.ip.addr) || (target.u32 == net::globals::ipInfo.secondary_ip.addr) || (target.u32 == net::globals::ipInfo.broadcast_ip.addr))) { - DEBUG_PUTS("No for me."); - DEBUG_EXIT - return; + for (auto& record : s_ArpRecords) { + std::memset(&record, 0, sizeof(struct net::arp::Record)); } + // ARP Request template // Ethernet header - memcpy(s_arp_reply.ether.dst, p_arp->ether.src, ETH_ADDR_LEN); + std::memcpy(s_arp_request.ether.src, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); + std::memset(s_arp_request.ether.dst, 0xFF , ETH_ADDR_LEN); + s_arp_request.ether.type = __builtin_bswap16(ETHER_TYPE_ARP); + // ARP Header - memcpy(s_arp_reply.arp.target_mac, p_arp->arp.sender_mac, ETH_ADDR_LEN); - memcpy(s_arp_reply.arp.target_ip, p_arp->arp.sender_ip, IPv4_ADDR_LEN); - memcpy(s_arp_reply.arp.sender_ip, target.u8, IPv4_ADDR_LEN); + s_arp_request.arp.hardware_type = __builtin_bswap16(ARP_HWTYPE_ETHERNET); + s_arp_request.arp.protocol_type = __builtin_bswap16(ARP_PRTYPE_IPv4); + s_arp_request.arp.hardware_size = ARP_HARDWARE_SIZE; + s_arp_request.arp.protocol_size = ARP_PROTOCOL_SIZE; + s_arp_request.arp.opcode = __builtin_bswap16(ARP_OPCODE_RQST); - emac_eth_send(reinterpret_cast(&s_arp_reply), sizeof(struct t_arp)); + std::memcpy(s_arp_request.arp.sender_mac, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); + net::memcpy_ip(s_arp_request.arp.sender_ip, net::globals::netif_default.ip.addr); + std::memset(s_arp_request.arp.target_mac, 0x00, ETH_ADDR_LEN); + + // ARP Reply Template + // Ethernet header + std::memcpy(s_arp_reply.ether.src, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); + s_arp_reply.ether.type = __builtin_bswap16(ETHER_TYPE_ARP); + + // ARP Header + s_arp_reply.arp.hardware_type = __builtin_bswap16(ARP_HWTYPE_ETHERNET); + s_arp_reply.arp.protocol_type = __builtin_bswap16(ARP_PRTYPE_IPv4); + s_arp_reply.arp.hardware_size = ARP_HARDWARE_SIZE; + s_arp_reply.arp.protocol_size = ARP_PROTOCOL_SIZE; + s_arp_reply.arp.opcode = __builtin_bswap16(ARP_OPCODE_REPLY); + + std::memcpy(s_arp_reply.arp.sender_mac, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); + + Hardware::Get()->SoftwareTimerAdd(net::arp::TIMER_INTERVAL, arp_timer); DEBUG_EXIT } -void arp_handle_reply(struct t_arp *p_arp) { - DEBUG_ENTRY - - switch (s_requestType) { - case net::arp::RequestType::REQUEST: { - _pcast32 sender; - memcpy(sender.u8, p_arp->arp.sender_ip, IPv4_ADDR_LEN); - arp_cache_update(p_arp->arp.sender_mac, sender.u32); +__attribute__((hot)) void arp_handle(struct t_arp *pArp) { + /* + * RFC 826 Packet Reception: + */ + if (__builtin_expect(((pArp->arp.hardware_type != __builtin_bswap16(ARP_HWTYPE_ETHERNET)) + || (pArp->arp.protocol_type != __builtin_bswap16(ARP_PRTYPE_IPv4)) + || (pArp->arp.hardware_size != ARP_HARDWARE_SIZE) + || (pArp->arp.protocol_size != ARP_PROTOCOL_SIZE)), 0)) { + DEBUG_EXIT + return; } + + acd_arp_reply(pArp); + + /* ARP packet directed to us? */ + const auto nIpTarget = net::memcpy_ip(pArp->arp.target_ip); + const auto bToUs = ((nIpTarget == net::globals::netif_default.ip.addr) || (nIpTarget == net::globals::netif_default.secondary_ip.addr)); + /* ARP packet from us? */ + const auto bFromUs = (net::memcpy_ip(pArp->arp.sender_ip) == net::globals::netif_default.ip.addr); + + DEBUG_PRINTF("bToUs:%d, bFromUs:%d", bToUs, bFromUs); + + /* + * ARP message directed to us? + * -> add IP address in ARP cache; assume requester wants to talk to us, + * can result in directly sending the queued packets for this host. + * ARP message not directed to us? + * -> update the source IP address in the cache, if present + */ + arp_cache_update(pArp->arp.sender_mac, net::memcpy_ip(pArp->arp.sender_ip), bToUs ? arp::Flags::FLAG_INSERT : arp::Flags::FLAG_UPDATE); + + switch (pArp->arp.opcode) { + case __builtin_bswap16(ARP_OPCODE_RQST): + if (bToUs && !bFromUs) { + arp_send_reply(pArp); + } else { + DEBUG_PUTS("ARP request was not for us"); + } break; - case net::arp::RequestType::PROBE: - s_isProbeReplyReceived = true; + case __builtin_bswap16(ARP_OPCODE_REPLY): + /* Cache update is handled earlier */ break; default: - assert(0); - __builtin_unreachable(); + DEBUG_PRINTF("opcode %04x not handled", __builtin_bswap16(pArp->arp.opcode)); break; } +} + +template +static void arp_send_implementation(struct t_udp *pPacket, const uint32_t nSize, const uint32_t nRemoteIp) { + DEBUG_ENTRY + DEBUG_PRINTF(IPSTR, IP2STR(nRemoteIp)); + + net::memcpy_ip(pPacket->ip4.dst, nRemoteIp); + pPacket->ip4.chksum = 0; +#if !defined (CHECKSUM_BY_HARDWARE) + pPacket->ip4.chksum = net_chksum(reinterpret_cast(&pPacket->ip4), sizeof(pPacket->ip4)); +#endif + + auto nDestinationIp = nRemoteIp; + + if (__builtin_expect((net::globals::nOnNetworkMask != (nRemoteIp & net::globals::nOnNetworkMask)), 0)) { + /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with + a link-local source address must always be "directly to its destination + on the same physical link. The host MUST NOT send the packet to any + router for forwarding". */ + if (!network::is_linklocal_ip(nRemoteIp)) { + nDestinationIp = net::globals::netif_default.gw.addr; + DEBUG_PUTS(""); + } + } + + for (auto &record : s_ArpRecords) { + if (record.state >= net::arp::State::STATE_REACHABLE) { + if (record.nIp == nDestinationIp) { + std::memcpy(pPacket->ether.dst, record.mac_address, ETH_ADDR_LEN); + + if (S == net::arp::EthSend::IS_NORMAL) { + emac_eth_send(reinterpret_cast(pPacket), nSize); + } +#if defined CONFIG_ENET_ENABLE_PTP + else if (S == net::arp::EthSend::IS_TIMESTAMP) { + emac_eth_send_timestamp(reinterpret_cast(pPacket), nSize); + } +#endif + DEBUG_EXIT + return; + } + } + } + + arp_query(nDestinationIp, pPacket, nSize, arp::Flags::FLAG_INSERT); DEBUG_EXIT + return; } -__attribute__((hot)) void arp_handle(struct t_arp *pArp) { +void arp_send(struct t_udp *pPacket, const uint32_t nSize, const uint32_t nRemoteIp) { + arp_send_implementation(pPacket, nSize, nRemoteIp); +} + +#if defined CONFIG_ENET_ENABLE_PTP +void arp_send_timestamp(struct t_udp *pPacket, const uint32_t nSize, const uint32_t nRemoteIp) { + arp_send_implementation(pPacket, nSize, nRemoteIp); +} +#endif + +/* + * The Sender IP is set to all zeros, + * which means it cannot map to the Sender MAC address. + * The Target MAC address is all zeros, + * which means it cannot map to the Target IP address. + */ +void arp_acd_probe(const ip4_addr_t ipaddr) { DEBUG_ENTRY - switch (pArp->arp.opcode) { - case __builtin_bswap16(ARP_OPCODE_RQST): - arp_handle_request(pArp); - break; - case __builtin_bswap16(ARP_OPCODE_REPLY): - arp_handle_reply(pArp); - break; - default: - DEBUG_PRINTF("opcode %04x not handled", __builtin_bswap16(pArp->arp.opcode)); - break; - } + memset(s_arp_request.arp.sender_ip, 0, IPv4_ADDR_LEN); + net::memcpy_ip(s_arp_request.arp.target_ip, ipaddr.addr); + + emac_eth_send(reinterpret_cast(&s_arp_request), sizeof(struct t_arp)); + + net::memcpy_ip(s_arp_request.arp.sender_ip, net::globals::netif_default.ip.addr); DEBUG_EXIT } + +/* + * The packet structure is identical to the ARP Probe above, + * with the exception that a complete mapping exists. + * Both the Sender MAC address and the Sender IP address create a complete ARP mapping, + * and hosts on the network can use this pair of addresses in their ARP table. + */ +void arp_acd_send_announcement(const ip4_addr_t ipaddr) { + net::memcpy_ip(s_arp_request.arp.target_ip, ipaddr.addr); + net::memcpy_ip(s_arp_request.arp.sender_ip, ipaddr.addr); + + emac_eth_send(reinterpret_cast(&s_arp_request), sizeof(struct t_arp)); +} +} // namespace net diff --git a/lib-network/src/net/arp_cache.cpp b/lib-network/src/net/arp_cache.cpp deleted file mode 100644 index 97f2795b..00000000 --- a/lib-network/src/net/arp_cache.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/** - * @file arp_cache.cpp - * - */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "net_private.h" -#include "net_packets.h" -#include "net_platform.h" -#include "net_debug.h" - -#include "emac/net_link_check.h" - -#include "../../config/net_config.h" - -#if !defined ARP_MAX_RECORDS -static constexpr auto MAX_RECORDS = 32; -#else -static constexpr auto MAX_RECORDS = ARP_MAX_RECORDS; -#endif - -struct ArpRecord { - uint32_t nIp; - uint8_t mac_address[ETH_ADDR_LEN]; -}; - -typedef union pcast32 { - uint32_t u32; - uint8_t u8[4]; -} _pcast32; - -static ArpRecord s_ArpRecords[MAX_RECORDS] SECTION_NETWORK ALIGNED; -static uint16_t s_Entries SECTION_NETWORK ALIGNED; - -#ifndef NDEBUG -# define TICKER_COUNT 100 ///< 10 seconds - static volatile uint32_t s_ticker ; -#endif - -void __attribute__((cold)) arp_cache_init() { - s_Entries = 0; - - for (auto& record : s_ArpRecords) { - memset(&record, 0, sizeof(struct ArpRecord)); - } - -#ifndef NDEBUG - s_ticker = TICKER_COUNT; -#endif -} - -void arp_cache_update(const uint8_t *pMacAddress, uint32_t nIp) { - DEBUG_ENTRY - DEBUG_PRINTF(MACSTR " " IPSTR, MAC2STR(pMacAddress), IP2STR(nIp)); - - if (s_Entries == MAX_RECORDS) { - console_error("ARP cache is full\n"); - return; - } - - for (auto i = 0; i < s_Entries; i++) { - if (s_ArpRecords[i].nIp == nIp) { - DEBUG_EXIT - return; - } - } - - memcpy(s_ArpRecords[s_Entries].mac_address, pMacAddress, ETH_ADDR_LEN); - s_ArpRecords[s_Entries].nIp = nIp; - - s_Entries++; - - DEBUG_EXIT -} - -uint32_t arp_cache_lookup(uint32_t nIp, uint8_t *pMacAddress) { - DEBUG_ENTRY - DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(nIp), MAC2STR(pMacAddress)); - - uint32_t i; - - for (i = 0; i < MAX_RECORDS; i++) { - if (s_ArpRecords[i].nIp == nIp) { - memcpy(pMacAddress, s_ArpRecords[i].mac_address, ETH_ADDR_LEN); - DEBUG_EXIT - return nIp; - } - - if (s_ArpRecords[i].nIp == 0) { - break; - } - } - - if (net::link_status_read() == net::Link::STATE_DOWN) { - DEBUG_EXIT - return 0; - } - - const auto nEntries = s_Entries; - int32_t nTimeout; - auto nRetries = 3; - - while (nRetries--) { - arp_send_request(nIp); - - nTimeout = 0x1FFFF; -#ifndef NDEBUG - nTimeout+= 0x40000; -#endif - - while ((nTimeout-- > 0) && (nEntries == s_Entries)) { - net_handle(); - } - - if (nEntries != s_Entries) { - memcpy(pMacAddress, s_ArpRecords[nEntries].mac_address, ETH_ADDR_LEN); - DEBUG_PRINTF("timeout=%x", nTimeout); - DEBUG_EXIT - return nIp; - } - - DEBUG_PRINTF("timeout=%d, current_entry=%d, s_entry_current=%d", nTimeout, nEntries, s_Entries); - } - - DEBUG_EXIT - return 0; -} - -void arp_cache_dump() { -#ifndef NDEBUG - printf("ARP Cache size=%d\n", s_Entries); - - for (auto i = 0; i < s_Entries; i++) { - printf("%02d " IPSTR " " MACSTR "\n", i, IP2STR(s_ArpRecords[i].nIp),MAC2STR(s_ArpRecords[i].mac_address)); - } -#endif -} - -#ifndef NDEBUG -void arp_cache_timer(void) { - s_ticker--; - - if (s_ticker == 0) { - s_ticker = TICKER_COUNT; - arp_cache_dump(); - } -} -#endif diff --git a/lib-network/src/net/autoip.cpp b/lib-network/src/net/autoip.cpp new file mode 100755 index 00000000..cb2fedfd --- /dev/null +++ b/lib-network/src/net/autoip.cpp @@ -0,0 +1,172 @@ +/** + * @file autoip.cpp + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* This code is inspired by the lwIP TCP/IP stack. + * https://savannah.nongnu.org/projects/lwip/ + */ +/** + * The autoip.cpp aims to be conform to RFC 3927. + * https://datatracker.ietf.org/doc/html/rfc3927 + * Dynamic Configuration of IPv4 Link-Local Addresses + */ + +#ifdef DEBUG_AUTOIP +# undef NDEBUG +#endif + +#include +#include + +#include "netif.h" +#include "net/autoip.h" +#include "net/protocol/autoip.h" +#include "net/acd.h" +#include "net/arp.h" + +#include "debug.h" + +namespace net { +static void autoip_bind(){ + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + assert(autoip != nullptr); + + autoip->state = autoip::State::AUTOIP_STATE_BOUND; + + ip4_addr_t sn_mask, gw_addr; + + sn_mask.addr = network::convert_to_uint(255,255,0,0); + gw_addr.addr = 0; + + netif_set_addr(autoip->llipaddr, sn_mask, gw_addr); +} + +static void autoip_restart() { + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + assert(autoip != nullptr); + + autoip->tried_llipaddr++; + autoip_start(); +} + +static void autoip_conflict_callback(net::acd::Callback state) { + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + assert(autoip != nullptr); + + switch (state) { + case net::acd::Callback::ACD_IP_OK: + autoip_bind(); + netif_set_flags(netif::NETIF_FLAG_AUTOIP_OK); + break; + case net::acd::Callback::ACD_RESTART_CLIENT: + autoip_restart(); + break; + case net::acd::Callback::ACD_DECLINE: + /* "delete" conflicting address so a new one will be selected in autoip_start() */ + autoip->llipaddr.addr = network::IP4_ANY; + autoip_stop(); + netif_clear_flags(netif::NETIF_FLAG_AUTOIP_OK); + break; + default: + break; + } +} + +static void autoip_create_addr(uint32_t &ipaddr) { + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + assert(autoip != nullptr); + + /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * compliant to RFC 3927 Section 2.1 */ + const auto mask = globals::netif_default.hwaddr[3] + (globals::netif_default.hwaddr[4] << 8); + ipaddr = static_cast(mask << 16) | autoip::AUTOIP_RANGE_START; + ipaddr = __builtin_bswap32(ipaddr); + + ipaddr += autoip->tried_llipaddr; + ipaddr = __builtin_bswap32(autoip::AUTOIP_NET) | (ipaddr & 0xffff); + + if (ipaddr < __builtin_bswap32(autoip::AUTOIP_RANGE_START)) { + ipaddr += __builtin_bswap32(autoip::AUTOIP_RANGE_END) - __builtin_bswap32(autoip::AUTOIP_RANGE_START) + 1; + } + + if (ipaddr > __builtin_bswap32(autoip::AUTOIP_RANGE_END)) { + ipaddr -= __builtin_bswap32(autoip::AUTOIP_RANGE_END) - __builtin_bswap32(autoip::AUTOIP_RANGE_START) + 1; + } + + ipaddr = __builtin_bswap32(ipaddr); + + DEBUG_PRINTF(IPSTR, IP2STR(ipaddr)); +} + +/* + * Public interface + */ + +void autoip_start() { + DEBUG_ENTRY + + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + + if (autoip == nullptr) { + autoip = new (struct autoip::Autoip); + assert(autoip != nullptr); + memset(autoip, 0, sizeof(struct autoip::Autoip)); + } + + if (autoip->state == autoip::State::AUTOIP_STATE_OFF) { + acd_add(&autoip->acd, autoip_conflict_callback); + + /* In accordance to RFC3927 section 2.1: + * Keep using the same link local address as much as possible. + * Only when there is none or when there was a conflict, select a new one. + */ + if (!network::is_linklocal_ip(autoip->llipaddr.addr)) { + autoip_create_addr(autoip->llipaddr.addr); + } + + autoip->state = autoip::State::AUTOIP_STATE_CHECKING; + acd_start(&autoip->acd, autoip->llipaddr); + } else { + DEBUG_PUTS("Already started"); + } + + DEBUG_EXIT +} + +void autoip_stop() { + DEBUG_ENTRY + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + + if (autoip != nullptr) { + autoip->state = autoip::State::AUTOIP_STATE_OFF; + + ip4_addr_t any; + any.addr = network::IP4_ANY; + + if (network::is_linklocal_ip(globals::netif_default.ip.addr)) { + netif_set_addr(any, any, any); + } + } + + DEBUG_EXIT +} +} // namespace net diff --git a/lib-network/src/net/dhcp.cpp b/lib-network/src/net/dhcp.cpp old mode 100644 new mode 100755 index a160ece6..7bc1f309 --- a/lib-network/src/net/dhcp.cpp +++ b/lib-network/src/net/dhcp.cpp @@ -1,8 +1,7 @@ /** * @file dhcp.cpp - * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,372 +21,852 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +/* This code is inspired by the lwIP TCP/IP stack. + * https://savannah.nongnu.org/projects/lwip/ + */ + +#if defined (DEBUG_NET_DHCP) +# undef NDEBUG +#endif + +#pragma GCC push_options +#pragma GCC optimize ("Os") #include #include #include -#include "dhcp_internal.h" - #include "net.h" +#include "net_memcpy.h" #include "net_private.h" #include "hardware.h" +#include "network.h" #include "../../config/net_config.h" -namespace net { -namespace globals { -extern struct IpInfo ipInfo; -extern uint8_t macAddress[ETH_ADDR_LEN]; -} // namespace globals -} // namespace net +#include "net/dhcp.h" +#include "net/protocol/dhcp.h" +#include "net/protocol/iana.h" +#include "net/acd.h" +#include "net/autoip.h" +#include "netif.h" -typedef union pcast32 { - uint32_t u32; - uint8_t u8[4]; -} _pcast32; +#define REBOOT_TRIES 2 + +static int32_t nTimerId; // https://tools.ietf.org/html/rfc1541 +namespace net { +static dhcp::Message s_dhcp_message SECTION_NETWORK ALIGNED; + +static void message_init() { + memset(&s_dhcp_message, 0, sizeof(dhcp::Message)); -namespace dhcp { -struct Message { - uint8_t op; - uint8_t htype; - uint8_t hlen; - uint8_t hops; - uint32_t xid; - uint16_t secs; - uint16_t flags; - uint8_t ciaddr[IPv4_ADDR_LEN]; - uint8_t yiaddr[IPv4_ADDR_LEN]; - uint8_t siaddr[IPv4_ADDR_LEN]; - uint8_t giaddr[IPv4_ADDR_LEN]; - uint8_t chaddr[16]; - uint8_t sname[64]; - uint8_t file[128]; - uint8_t options[DHCP_OPT_SIZE]; -}PACKED; -} // namespace dhcp - -enum OPTIONS { - OPTIONS_PAD_OPTION = 0, - OPTIONS_SUBNET_MASK = 1, - OPTIONS_ROUTERS_ON_SUBNET = 3, - OPTIONS_DNS = 6, - OPTIONS_HOSTNAME = 12, - OPTIONS_DOMAIN_NAME = 15, - OPTIONS_REQUESTED_IP = 50, - OPTIONS_MESSAGE_TYPE = 53, - OPTIONS_SERVER_IDENTIFIER = 54, - OPTIONS_PARAM_REQUEST = 55, - OPTIONS_DHCP_T1_VALUE = 58, - OPTIONS_DHCP_T2_VALUE = 59, - OPTIONS_CLIENT_IDENTIFIER = 61, - OPTIONS_END_OPTION = 255 -}; - -static dhcp::Message s_dhcp_message ALIGNED; - -static uint8_t s_dhcp_server_ip[IPv4_ADDR_LEN] ALIGNED = { 0, }; -static uint8_t s_dhcp_allocated_ip[IPv4_ADDR_LEN] ALIGNED = { 0, }; -static uint8_t s_dhcp_allocated_gw[IPv4_ADDR_LEN] ALIGNED = { 0, }; -static uint8_t s_dhcp_allocated_netmask[IPv4_ADDR_LEN] ALIGNED = { 0, }; - -static void message_init(const uint8_t *pMacAddress) { - auto *p = reinterpret_cast(&s_dhcp_message); - - for (uint32_t i = 0; i < sizeof(dhcp::Message); i++) { - *p++ = 0; - } - - s_dhcp_message.op = DHCP_OP_BOOTREQUEST; - s_dhcp_message.htype = DHCP_HTYPE_10MB; // This is the current default - s_dhcp_message.hlen = ETH_ADDR_LEN; - memcpy(s_dhcp_message.chaddr, pMacAddress, ETH_ADDR_LEN); - - s_dhcp_message.options[0] = static_cast((MAGIC_COOKIE & 0xFF000000) >> 24); - s_dhcp_message.options[1] = static_cast((MAGIC_COOKIE & 0x00FF0000) >> 16); - s_dhcp_message.options[2] = static_cast((MAGIC_COOKIE & 0x0000FF00) >> 8); - s_dhcp_message.options[3] = static_cast(MAGIC_COOKIE & 0x000000FF) >> 0; - - s_dhcp_message.options[4] = OPTIONS_MESSAGE_TYPE; + s_dhcp_message.op = dhcp::OpCode::BOOTREQUEST; + s_dhcp_message.htype = dhcp::HardwareType::HTYPE_10MB; // This is the current default + s_dhcp_message.hlen = network::MAC_SIZE; + memcpy(s_dhcp_message.chaddr, net::globals::netif_default.hwaddr, network::MAC_SIZE); + + s_dhcp_message.options[0] = static_cast((dhcp::MAGIC_COOKIE & 0xFF000000) >> 24); + s_dhcp_message.options[1] = static_cast((dhcp::MAGIC_COOKIE & 0x00FF0000) >> 16); + s_dhcp_message.options[2] = static_cast((dhcp::MAGIC_COOKIE & 0x0000FF00) >> 8); + s_dhcp_message.options[3] = static_cast(dhcp::MAGIC_COOKIE & 0x000000FF) >> 0; + + s_dhcp_message.options[4] = dhcp::Options::OPTION_MESSAGE_TYPE; s_dhcp_message.options[5] = 0x01; } -static void send_discover(int nHandle, const uint8_t *pMacAddress) { +static void dhcp_update_msg(const uint8_t message_type) { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + + /* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */ + if ((message_type != dhcp::Type::REQUEST) || (dhcp->state == dhcp::State::STATE_REBOOTING)) { + /* reuse transaction identifier in retransmissions */ + if (dhcp->tries == 0) { + auto xid = __builtin_bswap32(dhcp->xid); + xid++; + dhcp->xid = __builtin_bswap32(xid); + } + } + + s_dhcp_message.xid = dhcp->xid; + + if ((message_type == dhcp::Type::INFORM) + || (message_type == dhcp::Type::DECLINE) + || (message_type == dhcp::Type::RELEASE) + || ((message_type == dhcp::Type::REQUEST) + && /* DHCP_STATE_BOUND not used for sending! */ + ((dhcp->state == dhcp::State::STATE_RENEWING) || dhcp->state == dhcp::State::STATE_REBINDING))) { + + const auto &netif = net::globals::netif_default; + net::memcpy_ip(s_dhcp_message.ciaddr, netif.ip.addr); + } +} + +static void send_discover() { DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + + dhcp_update_msg(dhcp::Type::DISCOVER); uint32_t k = 6; - s_dhcp_message.options[k++] = DCHP_TYPE_DISCOVER; + s_dhcp_message.options[k++] = dhcp::Type::DISCOVER; - s_dhcp_message.options[k++] = OPTIONS_CLIENT_IDENTIFIER; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_CLIENT_IDENTIFIER; s_dhcp_message.options[k++] = 0x07; s_dhcp_message.options[k++] = 0x01; - s_dhcp_message.options[k++] = pMacAddress[0]; - s_dhcp_message.options[k++] = pMacAddress[1]; - s_dhcp_message.options[k++] = pMacAddress[2]; - s_dhcp_message.options[k++] = pMacAddress[3]; - s_dhcp_message.options[k++] = pMacAddress[4]; - s_dhcp_message.options[k++] = pMacAddress[5]; - - s_dhcp_message.options[k++] = OPTIONS_PARAM_REQUEST; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[0]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[1]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[2]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[3]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[4]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[5]; + + s_dhcp_message.options[k++] = dhcp::Options::OPTION_PARAM_REQUEST; s_dhcp_message.options[k++] = 0x06; // length of request - s_dhcp_message.options[k++] = OPTIONS_SUBNET_MASK; - s_dhcp_message.options[k++] = OPTIONS_ROUTERS_ON_SUBNET; - s_dhcp_message.options[k++] = OPTIONS_DNS; - s_dhcp_message.options[k++] = OPTIONS_DOMAIN_NAME; - s_dhcp_message.options[k++] = OPTIONS_DHCP_T1_VALUE; - s_dhcp_message.options[k++] = OPTIONS_DHCP_T2_VALUE; - s_dhcp_message.options[k++] = OPTIONS_END_OPTION; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_SUBNET_MASK; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_ROUTER; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_DOMAIN_NAME; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_LEASE_TIME; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_DHCP_T1_VALUE; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_DHCP_T2_VALUE; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_END; - udp_send(nHandle, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - DHCP_OPT_SIZE), IP_BROADCAST, DHCP_PORT_SERVER); + udp_send(dhcp->nHandle, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - dhcp::OPT_SIZE), network::IP4_BROADCAST, net::iana::IANA_PORT_DHCP_SERVER); DEBUG_EXIT } -static void _send_request(int idx, const uint8_t *pMacAddress, const char *pHostname) { +static void send_request() { DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); uint32_t i; uint32_t k = 6; - s_dhcp_message.options[k++] = DCHP_TYPE_REQUEST; + s_dhcp_message.options[k++] = dhcp::Type::REQUEST; - s_dhcp_message.options[k++] = OPTIONS_CLIENT_IDENTIFIER; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_CLIENT_IDENTIFIER; s_dhcp_message.options[k++] = 0x07; s_dhcp_message.options[k++] = 0x01; - s_dhcp_message.options[k++] = pMacAddress[0]; - s_dhcp_message.options[k++] = pMacAddress[1]; - s_dhcp_message.options[k++] = pMacAddress[2]; - s_dhcp_message.options[k++] = pMacAddress[3]; - s_dhcp_message.options[k++] = pMacAddress[4]; - s_dhcp_message.options[k++] = pMacAddress[5]; - - s_dhcp_message.options[k++] = OPTIONS_REQUESTED_IP; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[0]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[1]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[2]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[3]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[4]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[5]; + + s_dhcp_message.options[k++] = dhcp::Options::OPTION_REQUESTED_IP; s_dhcp_message.options[k++] = 0x04; - s_dhcp_message.options[k++] = s_dhcp_allocated_ip[0]; - s_dhcp_message.options[k++] = s_dhcp_allocated_ip[1]; - s_dhcp_message.options[k++] = s_dhcp_allocated_ip[2]; - s_dhcp_message.options[k++] = s_dhcp_allocated_ip[3]; + memcpy_ip(&s_dhcp_message.options[k], dhcp->offered.offered_ip_addr.addr); + k = k + 4; - s_dhcp_message.options[k++] = OPTIONS_SERVER_IDENTIFIER; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_SERVER_IDENTIFIER; s_dhcp_message.options[k++] = 0x04; - s_dhcp_message.options[k++] = s_dhcp_server_ip[0]; - s_dhcp_message.options[k++] = s_dhcp_server_ip[1]; - s_dhcp_message.options[k++] = s_dhcp_server_ip[2]; - s_dhcp_message.options[k++] = s_dhcp_server_ip[3]; + memcpy_ip(&s_dhcp_message.options[k], dhcp->server_ip_addr.addr); + k = k + 4; - s_dhcp_message.options[k++] = OPTIONS_HOSTNAME; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_HOSTNAME; s_dhcp_message.options[k++] = 0; // length of hostname - for (i = 0; pHostname[i] != 0; i++) { - s_dhcp_message.options[k++] = pHostname[i]; + for (i = 0; net::globals::netif_default.hostname[i] != 0; i++) { + s_dhcp_message.options[k++] = net::globals::netif_default.hostname[i]; } s_dhcp_message.options[k - (i + 1)] = static_cast(i); // length of hostname - s_dhcp_message.options[k++] = OPTIONS_PARAM_REQUEST; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_PARAM_REQUEST; s_dhcp_message.options[k++] = 0x06; // length of request - s_dhcp_message.options[k++] = OPTIONS_SUBNET_MASK; - s_dhcp_message.options[k++] = OPTIONS_ROUTERS_ON_SUBNET; - s_dhcp_message.options[k++] = OPTIONS_DNS; - s_dhcp_message.options[k++] = OPTIONS_DOMAIN_NAME; - s_dhcp_message.options[k++] = OPTIONS_DHCP_T1_VALUE; - s_dhcp_message.options[k++] = OPTIONS_DHCP_T2_VALUE; - s_dhcp_message.options[k++] = OPTIONS_END_OPTION; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_SUBNET_MASK; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_ROUTER; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_DNS_SERVER; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_DOMAIN_NAME; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_DHCP_T1_VALUE; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_DHCP_T2_VALUE; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_END; - udp_send(idx, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - DHCP_OPT_SIZE), IP_BROADCAST, DHCP_PORT_SERVER); + udp_send(dhcp->nHandle, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - dhcp::OPT_SIZE), network::IP4_BROADCAST, net::iana::IANA_PORT_DHCP_SERVER); DEBUG_EXIT } -static int parse_response(int nHandle, const uint8_t *pMacAddress) { - uint8_t *pResponse; - const auto nMillis = Hardware::Get()->Millis(); - uint32_t nSize = 0; +static void dhcp_send_release(const uint32_t nDestinationIp) { + DEBUG_ENTRY + DEBUG_PRINTF(IPSTR, IP2STR(nDestinationIp)); + + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); - do { - net_handle(); + uint32_t k = 6; - uint32_t nFromIp; - uint16_t nFromPort; + s_dhcp_message.options[k++] = dhcp::Type::RELEASE; - nSize = udp_recv2(nHandle, const_cast(&pResponse), &nFromIp, &nFromPort); + s_dhcp_message.options[k++] = dhcp::Options::OPTION_SERVER_IDENTIFIER; + s_dhcp_message.options[k++] = 0x04; + net::memcpy_ip(&s_dhcp_message.options[k], dhcp->server_ip_addr.addr); + k = k + 4; - if ((nSize > 0) && (nFromPort == DHCP_PORT_SERVER)) { + s_dhcp_message.options[k++] = dhcp::Options::OPTION_END; - const auto *const pDhcpMessage = reinterpret_cast(pResponse); + udp_send(dhcp->nHandle, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - dhcp::OPT_SIZE), nDestinationIp, net::iana::IANA_PORT_DHCP_SERVER); - if (memcmp(pDhcpMessage->chaddr, pMacAddress, ETH_ADDR_LEN) == 0) { - break; - } - } - } while ((Hardware::Get()->Millis() - nMillis) < 500); + DEBUG_EXIT +} - DEBUG_PRINTF("timeout %u", Hardware::Get()->Millis() - nMillis); +void dhcp_inform() { + DEBUG_ENTRY - int type = 0; - uint8_t opt_len = 0; + const auto nHandle = udp_begin(net::iana::IANA_PORT_DHCP_CLIENT); +#ifndef NDEBUG + if (nHandle < 0) { + console_error("DHCP Inform\n"); + return; + } +#endif - if (nSize > 0) { - auto *p = pResponse; - p = p + sizeof(dhcp::Message) - DHCP_OPT_SIZE + 4; - auto *e = pResponse + nSize; - - while (p < e) { - switch (*p) { - case OPTIONS_END_OPTION: - p = e; - break; - case OPTIONS_PAD_OPTION: - p++; - break; - case OPTIONS_MESSAGE_TYPE: - p++; - p++; - type = *p++; - break; - case OPTIONS_SUBNET_MASK: - p++; - p++; - s_dhcp_allocated_netmask[0] = *p++; - s_dhcp_allocated_netmask[1] = *p++; - s_dhcp_allocated_netmask[2] = *p++; - s_dhcp_allocated_netmask[3] = *p++; - break; - case OPTIONS_ROUTERS_ON_SUBNET: - p++; - opt_len = *p++; - s_dhcp_allocated_gw[0] = *p++; - s_dhcp_allocated_gw[1] = *p++; - s_dhcp_allocated_gw[2] = *p++; - s_dhcp_allocated_gw[3] = *p++; - p = p + (opt_len - 4); - break; - case OPTIONS_SERVER_IDENTIFIER : - p++; - opt_len = *p++; - s_dhcp_server_ip[0] = *p++; - s_dhcp_server_ip[1] = *p++; - s_dhcp_server_ip[2] = *p++; - s_dhcp_server_ip[3] = *p++; - break; - default: - p++; - opt_len = *p++; - p += opt_len; - break; - } - } + message_init(); + net::memcpy_ip(&s_dhcp_message.ciaddr[0], net::globals::netif_default.ip.addr); + + uint32_t k = 6; + + s_dhcp_message.options[k++] = dhcp::Type::INFORM; + + s_dhcp_message.options[k++] = dhcp::Options::OPTION_CLIENT_IDENTIFIER; + s_dhcp_message.options[k++] = 0x07; + s_dhcp_message.options[k++] = 0x01; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[0]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[1]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[2]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[3]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[4]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[5]; + + s_dhcp_message.options[k++] = dhcp::Options::OPTION_END; + + udp_send(nHandle, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - dhcp::OPT_SIZE), network::IP4_BROADCAST, net::iana::IANA_PORT_DHCP_SERVER); + udp_end(net::iana::IANA_PORT_DHCP_CLIENT); + + DEBUG_EXIT +} + +#define SET_TIMEOUT_FROM_OFFERED(result, offered, min, max) do { \ + uint32_t timeout = (offered + dhcp::DHCP_COARSE_TIMER_SECS / 2) / dhcp::DHCP_COARSE_TIMER_SECS; \ + if (timeout > max) { \ + timeout = max; \ + } \ + if (timeout == min) { \ + timeout = 1; \ + } \ + result = static_cast(timeout); \ +} while(0) + +#define DHCP_SET_TIMEOUT_FROM_OFFERED_T0_LEASE(res, dhcp) SET_TIMEOUT_FROM_OFFERED(res, (dhcp)->offered.offered_t0_lease, 0, 0xffff) +#define DHCP_SET_TIMEOUT_FROM_OFFERED_T1_RENEW(res, dhcp) SET_TIMEOUT_FROM_OFFERED(res, (dhcp)->offered.offered_t1_renew, 0, 0xffff) +#define DHCP_SET_TIMEOUT_FROM_OFFERED_T2_REBIND(res, dhcp) SET_TIMEOUT_FROM_OFFERED(res, (dhcp)->offered.offered_t2_rebind, 0, 0xffff) + +#define DHCP_NEXT_TIMEOUT_THRESHOLD ((60 + net::dhcp::DHCP_COARSE_TIMER_SECS / 2) / net::dhcp::DHCP_COARSE_TIMER_SECS) +#define DHCP_REQUEST_BACKOFF_SEQUENCE(tries) (( (tries) < 6U ? 1U << (tries) : 60U) * 1000U) + +static void dhcp_set_state(struct dhcp::Dhcp *dhcp, dhcp::State new_state) { + if (new_state != dhcp->state) { + DEBUG_PRINTF("%u -> %u", static_cast(dhcp->state), static_cast(new_state)); + + dhcp->state = new_state; + dhcp->tries = 0; + dhcp->request_timeout = 0; + } +} + +static void dhcp_bind() { + DEBUG_ENTRY + + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + + /* reset time used of lease */ + dhcp->lease_used = 0; - if (type == DCHP_TYPE_OFFER) { - const auto *const pDhcpMessage = reinterpret_cast(pResponse); - s_dhcp_allocated_ip[0] = pDhcpMessage->yiaddr[0]; - s_dhcp_allocated_ip[1] = pDhcpMessage->yiaddr[1]; - s_dhcp_allocated_ip[2] = pDhcpMessage->yiaddr[2]; - s_dhcp_allocated_ip[3] = pDhcpMessage->yiaddr[3]; + if (dhcp->offered.offered_t0_lease != 0xffffffffUL) { + /* set renewal period timer */ + DHCP_SET_TIMEOUT_FROM_OFFERED_T0_LEASE(dhcp->t0_timeout, dhcp); + } + + /* temporary DHCP lease? */ + if (dhcp->offered.offered_t1_renew != 0xffffffffUL) { + /* set renewal period timer */ + DHCP_SET_TIMEOUT_FROM_OFFERED_T1_RENEW(dhcp->t1_timeout, dhcp); + dhcp->t1_renew_time = dhcp->t1_timeout; + } + /* set renewal period timer */ + if (dhcp->offered.offered_t2_rebind != 0xffffffffUL) { + DHCP_SET_TIMEOUT_FROM_OFFERED_T2_REBIND(dhcp->t2_timeout, dhcp); + dhcp->t2_rebind_time = dhcp->t2_timeout; + } + + /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */ + if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) { + dhcp->t1_timeout = 0; + } + + ip4_addr_t sn_mask; + + if (dhcp->flags & DHCP_FLAG_SUBNET_MASK_GIVEN) { + /* copy offered network mask */ + sn_mask.addr = dhcp->offered.offered_sn_mask.addr; + } else { + /* subnet mask not given, choose a safe subnet mask given the network class */ + const uint8_t first_octet = dhcp->offered.offered_ip_addr.addr & 0xFF; + if (first_octet <= 127) { + sn_mask.addr = 0xFF; + } else if (first_octet >= 192) { + sn_mask.addr = 0xFFFFFF; + } else { + sn_mask.addr = 0xFFFF; } + } + + ip4_addr_t gw_addr; + gw_addr.addr = dhcp->offered.offered_gw_addr.addr; + + dhcp_set_state(dhcp, dhcp::State::STATE_BOUND); + + netif_set_flags(netif::NETIF_FLAG_DHCP_OK); + netif_set_addr(dhcp->offered.offered_ip_addr, sn_mask, gw_addr); + + DEBUG_EXIT +} + +static void dhcp_rebind() { + DEBUG_ENTRY + + DEBUG_EXIT +} + +#if defined (CONFIG_NET_DHCP_USE_ACD) +static void dhcp_send_decline() { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + + dhcp_update_msg(dhcp::Type::DECLINE); + + uint32_t k = 6; + + s_dhcp_message.options[k++] = dhcp::Type::DECLINE; + + s_dhcp_message.options[k++] = dhcp::Options::OPTION_REQUESTED_IP; + s_dhcp_message.options[k++] = 0x04; + net::memcpy_ip(&s_dhcp_message.options[k], dhcp->offered.offered_ip_addr.addr); + k = k + 4; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_END; + + udp_send(dhcp->nHandle, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - dhcp::OPT_SIZE), network::IP4_BROADCAST, net::iana::IANA_PORT_DHCP_SERVER); + + DEBUG_EXIT +} + +static void dhcp_decline() { + DEBUG_ENTRY - return type; + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + + dhcp_set_state(dhcp, dhcp::State::STATE_BACKING_OFF); + /* per section 4.4.4, broadcast DECLINE messages */ + dhcp_send_decline(); + + DEBUG_EXIT + return; +} + +static void dhcp_conflict_callback(net::acd::Callback callback) { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + assert(dhcp->state != dhcp::State::STATE_OFF); + + uint16_t msecs; + + switch (callback) { + case net::acd::Callback::ACD_IP_OK: + dhcp_bind(); + break; + case net::acd::Callback::ACD_RESTART_CLIENT: + /* wait 10s before restarting + * According to RFC2131 section 3.1 point 5: + * If the client detects that the address is already in use (e.g., through + * the use of ARP), the client MUST send a DHCPDECLINE message to the + * server and restarts the configuration process. The client SHOULD wait + * a minimum of ten seconds before restarting the configuration process to + * avoid excessive network traffic in case of looping. */ + dhcp_set_state (dhcp, dhcp::State::STATE_BACKING_OFF); + msecs = 10U * 1000U; + dhcp->request_timeout = static_cast((msecs + dhcp::DHCP_FINE_TIMER_MSECS - 1) / dhcp::DHCP_FINE_TIMER_MSECS); + break; + case net::acd::Callback::ACD_DECLINE: + /* remove IP address from interface + * (prevents routing from selecting this interface) */ + ip4_addr_t any; + any.addr = 0; + netif_set_addr(any, any, any); + /* Let the DHCP server know we will not use the address */ + dhcp_decline(); + netif_clear_flags(netif::NETIF_FLAG_DHCP_OK); + break; + default: + break; } +} - return -1; +static void dhcp_check() { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + dhcp_set_state(dhcp, dhcp::State::STATE_CHECKING); + + acd_start(&dhcp->acd, dhcp->offered.offered_ip_addr); + + DEBUG_EXIT } +#endif -int dhcp_client(const char *pHostname) { +static void dhcp_discover() { DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); - auto bHaveIp = false; - int32_t retries = 20; +#if defined (CONFIG_NET_DHCP_USE_AUTOIP) + if (dhcp->tries >= DHCP_AUTOIP_COOP_TRIES) { + autoip_start(); + } +#endif - message_init(net::globals::macAddress); + dhcp->offered.offered_ip_addr.addr = 0; - auto nHandle = udp_begin(DHCP_PORT_CLIENT); + dhcp_set_state(dhcp, dhcp::State::STATE_SELECTING); - if (nHandle < 0) { - return -1; + send_discover(); + + if (dhcp->tries < 255) { + dhcp->tries++; } - net::globals::ipInfo.ip.addr = 0; - ip_set_ip(); + const auto msecs = DHCP_REQUEST_BACKOFF_SEQUENCE(dhcp->tries); + dhcp->request_timeout = static_cast((msecs + dhcp::DHCP_FINE_TIMER_MSECS - 1) / dhcp::DHCP_FINE_TIMER_MSECS); +} - while (!bHaveIp && (retries-- > 0)) { - DEBUG_PRINTF("retries=%d", retries); +static void dhcp_reboot() { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); - send_discover(static_cast(nHandle), net::globals::macAddress); + dhcp_set_state(dhcp, dhcp::State::STATE_REBOOTING); - int type; + send_request(); - if ((type = parse_response(static_cast(nHandle), net::globals::macAddress)) < 0) { - continue; - } + if (dhcp->tries < 255) { + dhcp->tries++; + } - DEBUG_PRINTF("type=%d", type); + const auto msecs = static_cast(dhcp->tries < 10U ? dhcp->tries * 1000U : 10U * 1000U); + dhcp->request_timeout = static_cast((msecs + dhcp::DHCP_FINE_TIMER_MSECS - 1) / dhcp::DHCP_FINE_TIMER_MSECS); - if (type != DCHP_TYPE_OFFER) { - continue; - } + DEBUG_EXIT +} + +static void dhcp_select() { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); - DEBUG_PRINTF(IPSTR, s_dhcp_server_ip[0],s_dhcp_server_ip[1],s_dhcp_server_ip[2],s_dhcp_server_ip[3]); + dhcp_set_state(dhcp, dhcp::State::STATE_REQUESTING); + + send_request(); + + if (dhcp->tries < 255) { + dhcp->tries++; + } + + const auto msecs = static_cast((dhcp->tries < 6 ? 1 << dhcp->tries : 60U) * 1000U); + dhcp->request_timeout = static_cast((msecs + dhcp::DHCP_FINE_TIMER_MSECS - 1) / dhcp::DHCP_FINE_TIMER_MSECS); +} + +static void dhcp_timeout() { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + + /* back-off period has passed, or server selection timed out */ + if ((dhcp->state == dhcp::State::STATE_BACKING_OFF) || (dhcp->state == dhcp::State::STATE_SELECTING)) { + dhcp_discover(); + /* receiving the requested lease timed out */ + } else if (dhcp->state == dhcp::State::STATE_REQUESTING) { + if (dhcp->tries <= 5) { + dhcp_select(); + } else { + dhcp_release_and_stop(); + dhcp_start(); + } + } else if (dhcp->state == dhcp::State::STATE_REBOOTING) { + if (dhcp->tries < REBOOT_TRIES) { + dhcp_reboot(); + } else { + dhcp_discover(); + } + } +} - _send_request(static_cast(nHandle), net::globals::macAddress, pHostname); +static void dhcp_t1_timeout() { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + if ((dhcp->state == dhcp::State::STATE_REQUESTING) + || (dhcp->state == dhcp::State::STATE_BOUND) + || (dhcp->state == dhcp::State::STATE_RENEWING)) { + /* just retry to renew - note that the rebind timer (t2) will + * eventually time-out if renew tries fail. */ + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */ + dhcp_renew(); + /* Calculate next timeout */ + if (static_cast((dhcp->t2_timeout - dhcp->lease_used) / 2) >= DHCP_NEXT_TIMEOUT_THRESHOLD) { + dhcp->t1_renew_time = static_cast((dhcp->t2_timeout - dhcp->lease_used) / 2); + } + } +} - if ((type =parse_response(static_cast(nHandle), net::globals::macAddress)) < 0) { - continue; +static void dhcp_t2_timeout() { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + if ((dhcp->state == dhcp::State::STATE_REQUESTING) + || (dhcp->state == dhcp::State::STATE_BOUND) + || (dhcp->state == dhcp::State::STATE_RENEWING) + || (dhcp->state == dhcp::State::STATE_REBINDING)) { + /* just retry to rebind */ + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */ + dhcp_rebind(); + /* Calculate next timeout */ + if (static_cast((dhcp->t0_timeout - dhcp->lease_used) / 2) >= DHCP_NEXT_TIMEOUT_THRESHOLD) { + dhcp->t2_rebind_time = static_cast((dhcp->t0_timeout - dhcp->lease_used) / 2); } + } +} - DEBUG_PRINTF("type=%d", type); +void dhcp_coarse_tmr() { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + if ((dhcp != nullptr) && (dhcp->state != dhcp::State::STATE_OFF)) { + /* compare lease time to expire timeout */ + if (dhcp->t0_timeout && (++dhcp->lease_used == dhcp->t0_timeout)) { + /* this clients' lease time has expired */ + dhcp_release_and_stop(); + dhcp_start(); + /* timer is active (non zero), and triggers (zeroes) now? */ + } else if (dhcp->t2_rebind_time && (dhcp->t2_rebind_time-- == 1)) { + /* this clients' rebind timeout triggered */ + dhcp_t2_timeout(); + /* timer is active (non zero), and triggers (zeroes) now */ + } else if (dhcp->t1_renew_time && (dhcp->t1_renew_time-- == 1)) { + /* this clients' renewal timeout triggered */ + dhcp_t1_timeout(); + } + } +} - if (type == DCHP_TYPE_ACK) { - bHaveIp = true; - break; +static void dhcp_fine_tmr() { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + if (dhcp != nullptr) { + /* timer is active (non zero), and is about to trigger now */ + if (dhcp->request_timeout > 1) { + dhcp->request_timeout--; + } else if (dhcp->request_timeout == 1) { + dhcp->request_timeout--; + /* this client's request timeout triggered */ + dhcp_timeout(); } } +} + +static void dhcp_handle_offer(const dhcp::Message *const pResponse) { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + if (dhcp->server_ip_addr.addr != 0) { + dhcp->request_timeout = 0; /* stop timer */ + dhcp->offered.offered_ip_addr.addr = net::memcpy_ip(pResponse->yiaddr); + DEBUG_PRINTF(IPSTR " -> " IPSTR, IP2STR(dhcp->server_ip_addr.addr), IP2STR(dhcp->offered.offered_ip_addr.addr)); + dhcp_select(); + } else { + DEBUG_PUTS("did not get server ID!"); + } + + DEBUG_EXIT +} - udp_end(DHCP_PORT_CLIENT); +static void dhcp_handle_ack(const dhcp::Message *const pResponse) { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); - if (bHaveIp) { - _pcast32 ip; + DEBUG_PRINTF("t0=%u, t1=%u, t2=%u", dhcp->offered.offered_t0_lease, dhcp->offered.offered_t1_renew, dhcp->offered.offered_t2_rebind); - memcpy(ip.u8, s_dhcp_allocated_ip, IPv4_ADDR_LEN); - net::globals::ipInfo.ip.addr = ip.u32; + if (dhcp->offered.offered_t1_renew == 0) { + /* calculate safe periods for renewal */ + dhcp->offered.offered_t1_renew = dhcp->offered.offered_t0_lease / 2; + } - memcpy(ip.u8, s_dhcp_allocated_gw, IPv4_ADDR_LEN); - net::globals::ipInfo.gw.addr = ip.u32; + if (dhcp->offered.offered_t2_rebind == 0) { + /* calculate safe periods for rebinding (offered_t0_lease * 0.875 -> 87.5%)*/ + dhcp->offered.offered_t2_rebind = (dhcp->offered.offered_t0_lease * 7U) / 8U; + } + + dhcp->offered.offered_ip_addr.addr = net::memcpy_ip(pResponse->yiaddr); - memcpy(ip.u8, s_dhcp_allocated_netmask, IPv4_ADDR_LEN); - net::globals::ipInfo.netmask.addr = ip.u32; + if (dhcp->offered.offered_sn_mask.addr != 0) { + dhcp->flags |= DHCP_FLAG_SUBNET_MASK_GIVEN; + } else { + dhcp->flags &= ~DHCP_FLAG_SUBNET_MASK_GIVEN; } + DEBUG_PRINTF("t0=%u, t1=%u, t2=%u", dhcp->offered.offered_t0_lease, dhcp->offered.offered_t1_renew, dhcp->offered.offered_t2_rebind); DEBUG_EXIT - return bHaveIp ? 0 : -2; } -void dhcp_client_release() { +static void dhcp_handle_nak() { DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + // Change to a defined state - set this before assigning the address + // to ensure the callback can use dhcp_supplied_address() + dhcp_set_state(dhcp, dhcp::State::STATE_BACKING_OFF); + // remove IP address from interface (must no longer be used, as per RFC2131) + ip4_addr_t any; + any.addr = 0; + netif_set_addr(any, any, any); + // We can immediately restart discovery + dhcp_discover(); - auto nHandle = udp_begin(DHCP_PORT_CLIENT); + DEBUG_EXIT +} - if (nHandle < 0) { - console_error("dhcp_client_release\n"); +bool dhcp_start() { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + if (dhcp == nullptr) { + dhcp = new (struct dhcp::Dhcp); + assert(dhcp != nullptr); + globals::netif_default.dhcp = dhcp; + + nTimerId = Hardware::Get()->SoftwareTimerAdd(dhcp::DHCP_FINE_TIMER_MSECS, dhcp_fine_tmr); + assert(nTimerId >= 0); + } + + memset(dhcp, 0, sizeof(struct dhcp::Dhcp)); + dhcp->nHandle = udp_begin(net::iana::IANA_PORT_DHCP_CLIENT); + +#ifndef NDEBUG + if (dhcp->nHandle < 0) { + console_error("DHCP Start\n"); + DEBUG_EXIT + return false; + } +#endif + + message_init(); + +#if defined (CONFIG_NET_DHCP_USE_ACD) + acd_add(&dhcp->acd, dhcp_conflict_callback); +#endif + + if (!netif_is_link_up()) { + dhcp_set_state(dhcp, dhcp::State::STATE_INIT); + return false; + } + + dhcp_discover(); + + DEBUG_EXIT + return true; +} + +void dhcp_release_and_stop() { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + if (dhcp == nullptr) { + DEBUG_EXIT return; } - uint32_t k = 6; + if (dhcp->state == dhcp::State::STATE_OFF) { + return; + } - s_dhcp_message.options[k++] = DCHP_TYPE_RELEASE; + ip4_addr_t server_ip_addr; - s_dhcp_message.options[k++] = OPTIONS_SERVER_IDENTIFIER; - s_dhcp_message.options[k++] = 0x04; - s_dhcp_message.options[k++] = s_dhcp_server_ip[0]; - s_dhcp_message.options[k++] = s_dhcp_server_ip[1]; - s_dhcp_message.options[k++] = s_dhcp_server_ip[2]; - s_dhcp_message.options[k++] = s_dhcp_server_ip[3]; + server_ip_addr.addr = dhcp->server_ip_addr.addr; + + /* clean old DHCP offer */ + dhcp->server_ip_addr.addr = 0; + memset(&dhcp->offered, 0, sizeof(struct dhcp::Dhcp::Offered)); + dhcp->t1_renew_time = dhcp->t2_rebind_time = dhcp->lease_used = dhcp->t0_timeout = 0; + + if (dhcp_supplied_address()) { + dhcp_set_state(dhcp, dhcp::State::STATE_OFF); + + dhcp_send_release(server_ip_addr.addr); + + udp_end(net::iana::IANA_PORT_DHCP_CLIENT); + + /* remove IP address from interface (prevents routing from selecting this interface) */ + ip4_addr_t any; + any.addr = 0; + netif_set_addr(any, any, any); + } + +#if defined (CONFIG_NET_DHCP_USE_ACD) + acd_remove(&dhcp->acd); +#endif + + delete reinterpret_cast(globals::netif_default.dhcp); + globals::netif_default.dhcp = nullptr; +} + +void dhcp_network_changed_link_up() { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); - s_dhcp_message.options[k++] = OPTIONS_END_OPTION; + if (dhcp == nullptr) { + DEBUG_EXIT + return; + } + + switch (dhcp->state) { + case dhcp::State::STATE_REBINDING: + case dhcp::State::STATE_RENEWING: + case dhcp::State::STATE_BOUND: + case dhcp::State::STATE_REBOOTING: + dhcp->tries = 0; + dhcp_reboot(); + break; + case dhcp::State::STATE_OFF: + break; + default: + dhcp->tries = 0; + dhcp_discover(); + break; + } +} + +void dhcp_process(const dhcp::Message *const pResponse, const uint32_t nSize) { + DEBUG_ENTRY + + assert(pResponse != nullptr); + + uint8_t msg_type = 0; + uint8_t opt_len = 0; - udp_send(static_cast(nHandle), reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - DHCP_OPT_SIZE), IP_BROADCAST, DHCP_PORT_SERVER); - udp_end(DHCP_PORT_CLIENT); + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + + memset(&dhcp->offered, 0, sizeof(struct dhcp::Dhcp::Offered)); + + dhcp->server_ip_addr.addr = 0; + + const auto *p = reinterpret_cast(pResponse); + p = p + sizeof(dhcp::Message) - dhcp::OPT_SIZE + 4; + auto *e = p + nSize; + + while (p < e) { + switch (*p) { + case dhcp::Options::OPTION_END: + p = e; + break; + case dhcp::Options::OPTION_PAD_OPTION: + p++; + break; + case dhcp::Options::OPTION_MESSAGE_TYPE: + p++; + p++; + msg_type = *p++; + break; + case dhcp::Options::OPTION_SUBNET_MASK: + p++; + p++; + dhcp->offered.offered_sn_mask.addr = net::memcpy_ip(p); + p = p + 4; + break; + case dhcp::Options::OPTION_ROUTER: + p++; + p++; + dhcp->offered.offered_gw_addr.addr = net::memcpy_ip(p); + p = p + 4; + break; + case dhcp::Options::OPTION_SERVER_IDENTIFIER: + p++; + p++; + dhcp->server_ip_addr.addr = net::memcpy_ip(p); + p += 4; + break; + case dhcp::Options::OPTION_LEASE_TIME: + p++; + p++; + dhcp->offered.offered_t0_lease = __builtin_bswap32(net::memcpy_ip(p)); + p += 4; + break; + case dhcp::Options::OPTION_DHCP_T1_VALUE: + p++; + p++; + dhcp->offered.offered_t1_renew = __builtin_bswap32(net::memcpy_ip(p)); + p += 4; + break; + case dhcp::Options::OPTION_DHCP_T2_VALUE: + p++; + p++; + dhcp->offered.offered_t2_rebind = __builtin_bswap32(net::memcpy_ip(p)); + p += 4; + break; + default: + p++; + opt_len = *p++; + p += opt_len; + break; + } + } + + if (msg_type == dhcp::Type::OFFER) { + dhcp->offered.offered_ip_addr.addr = net::memcpy_ip(pResponse->yiaddr); + } + + DEBUG_PRINTF("msg_type=%u", msg_type); + + if (msg_type == dhcp::Type::ACK) { + /* in requesting state or just reconnected to the network? */ + if ((dhcp->state == dhcp::State::STATE_REQUESTING) || + (dhcp->state == dhcp::State::STATE_REBOOTING)) { + dhcp_handle_ack(pResponse); +#if defined (CONFIG_NET_DHCP_USE_ACD) + dhcp_check(); +#else + dhcp_bind(); +#endif + } + else if ((dhcp->state == dhcp::State::STATE_REBINDING) || + (dhcp->state == dhcp::State::STATE_RENEWING)) { + dhcp_handle_ack(pResponse); + dhcp_bind(); + } + } + else if ((msg_type == dhcp::Type::NAK) && + ((dhcp->state == dhcp::State::STATE_REBOOTING) || (dhcp->state == dhcp::State::STATE_REQUESTING) || + (dhcp->state == dhcp::State::STATE_REBINDING) || (dhcp->state == dhcp::State::STATE_RENEWING ))) { + dhcp_handle_nak(); + } + else if ((msg_type == dhcp::Type::OFFER) && (dhcp->state == dhcp::State::STATE_SELECTING)) { + dhcp_handle_offer(pResponse); + } DEBUG_EXIT } +} // namespace net diff --git a/lib-network/src/net/icmp.cpp b/lib-network/src/net/icmp.cpp old mode 100644 new mode 100755 index 17afb636..51d8b235 --- a/lib-network/src/net/icmp.cpp +++ b/lib-network/src/net/icmp.cpp @@ -2,7 +2,7 @@ * @file icmp.cpp * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,39 +23,48 @@ * THE SOFTWARE. */ +#if defined (DEBUG_NET_ICMP) +# undef NDEBUG +#endif + +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif + #include #include -#include "net.h" -#include "net_private.h" - #include "../../config/net_config.h" -namespace net { -namespace globals { -extern struct IpInfo ipInfo; -extern uint8_t macAddress[ETH_ADDR_LEN]; -} // namespace globals -} // namespace net +#include "net_memcpy.h" +#include "net_private.h" -typedef union pcast32 { - uint32_t u32; - uint8_t u8[4]; -} _pcast32; +#include "net/protocol/icmp.h" +#include "debug.h" + +namespace net { __attribute__((hot)) void icmp_handle(struct t_icmp *p_icmp) { if (p_icmp->icmp.type == ICMP_TYPE_ECHO) { if (p_icmp->icmp.code == ICMP_CODE_ECHO) { // Ethernet - memcpy(p_icmp->ether.dst, p_icmp->ether.src, ETH_ADDR_LEN); - memcpy(p_icmp->ether.src, net::globals::macAddress, ETH_ADDR_LEN); - + std::memcpy(p_icmp->ether.dst, p_icmp->ether.src, ETH_ADDR_LEN); + std::memcpy(p_icmp->ether.src, globals::netif_default.hwaddr, ETH_ADDR_LEN); // IPv4 p_icmp->ip4.id = static_cast(~p_icmp->ip4.id); - uint8_t dst[IPv4_ADDR_LEN]; - memcpy(dst, p_icmp->ip4.dst, IPv4_ADDR_LEN); - memcpy(p_icmp->ip4.dst, p_icmp->ip4.src, IPv4_ADDR_LEN); - memcpy(p_icmp->ip4.src, dst, IPv4_ADDR_LEN); + + const auto nIpDestination = net::memcpy_ip(p_icmp->ip4.dst); + + std::memcpy(p_icmp->ip4.dst, p_icmp->ip4.src, IPv4_ADDR_LEN); + + if (nIpDestination == globals::netif_default.secondary_ip.addr) { + net::memcpy_ip(p_icmp->ip4.src, globals::netif_default.secondary_ip.addr); + } else { + net::memcpy_ip(p_icmp->ip4.src, globals::netif_default.ip.addr); + } + p_icmp->ip4.chksum = 0; #if !defined (CHECKSUM_BY_HARDWARE) p_icmp->ip4.chksum = net_chksum(reinterpret_cast(&p_icmp->ip4), 20); //TODO @@ -66,7 +75,8 @@ __attribute__((hot)) void icmp_handle(struct t_icmp *p_icmp) { #if !defined (CHECKSUM_BY_HARDWARE) p_icmp->icmp.checksum = net_chksum(reinterpret_cast(&p_icmp->ip4), static_cast(__builtin_bswap16(p_icmp->ip4.len))); #endif - emac_eth_send(reinterpret_cast(p_icmp), (sizeof(struct ether_header) + __builtin_bswap16(p_icmp->ip4.len))); + emac_eth_send(reinterpret_cast(p_icmp), static_cast(sizeof(struct ether_header) + __builtin_bswap16(p_icmp->ip4.len))); } } } +} // namespace net diff --git a/lib-network/src/net/igmp.cpp b/lib-network/src/net/igmp.cpp index ac58a969..35456eec 100644 --- a/lib-network/src/net/igmp.cpp +++ b/lib-network/src/net/igmp.cpp @@ -2,7 +2,7 @@ * @file igmp.cpp * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,20 +23,44 @@ * THE SOFTWARE. */ +#if defined (DEBUG_NET_IGMP) +# undef NDEBUG +#endif + +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif + #include -#include +#include #include +#include + +#include "../../config/net_config.h" #include "net.h" +#include "netif.h" +#include "net/igmp.h" +#include "net/protocol/igmp.h" + +#include "net_memcpy.h" #include "net_private.h" -#include "../../config/net_config.h" +#include "hardware.h" + +#include "debug.h" /* * https://www.rfc-editor.org/rfc/rfc2236.html * Internet Group Management Protocol, Version 2 */ +namespace net { +#define IGMP_TMR_INTERVAL 100 /* Milliseconds */ +#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL) + enum State { NON_MEMBER, DELAYING_MEMBER, IDLE_MEMBER }; @@ -57,23 +81,68 @@ static struct t_igmp s_leave SECTION_NETWORK ALIGNED; static uint8_t s_multicast_mac[ETH_ADDR_LEN] SECTION_NETWORK ALIGNED; static struct t_group_info s_groups[IGMP_MAX_JOINS_ALLOWED] SECTION_NETWORK ALIGNED; static uint16_t s_id SECTION_NETWORK ALIGNED; +static int32_t nTimerId; -namespace net { -namespace globals { -extern struct IpInfo ipInfo; -extern uint8_t macAddress[ETH_ADDR_LEN]; -} // namespace globals -} // namespace net +void igmp_set_ip() { + net::memcpy_ip(s_report.ip4.src, net::globals::netif_default.ip.addr); + net::memcpy_ip(s_leave.ip4.src, net::globals::netif_default.ip.addr); +} -static void _send_report(uint32_t nGroupAddress); +static void igmp_send_report(const uint32_t nGroupAddress) { + DEBUG_ENTRY + _pcast32 multicast_ip; -void igmp_set_ip() { - _pcast32 src; + multicast_ip.u32 = nGroupAddress; + + s_multicast_mac[3] = multicast_ip.u8[1] & 0x7F; + s_multicast_mac[4] = multicast_ip.u8[2]; + s_multicast_mac[5] = multicast_ip.u8[3]; - src.u32 = net::globals::ipInfo.ip.addr; + DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(nGroupAddress),MAC2STR(s_multicast_mac)); - memcpy(s_report.ip4.src, src.u8, IPv4_ADDR_LEN); - memcpy(s_leave.ip4.src, src.u8, IPv4_ADDR_LEN); + // Ethernet + std::memcpy(s_report.ether.dst, s_multicast_mac, ETH_ADDR_LEN); + // IPv4 + s_report.ip4.id = s_id; + std::memcpy(s_report.ip4.dst, multicast_ip.u8, IPv4_ADDR_LEN); + s_report.ip4.chksum = 0; + s_report.ip4.chksum = net_chksum(reinterpret_cast(&s_report.ip4), 24); //TODO + // IGMP + std::memcpy(s_report.igmp.report.igmp.group_address, multicast_ip.u8, IPv4_ADDR_LEN); + s_report.igmp.report.igmp.checksum = 0; + s_report.igmp.report.igmp.checksum = net_chksum(reinterpret_cast(&s_report.ip4), IPv4_IGMP_REPORT_HEADERS_SIZE); + + emac_eth_send(reinterpret_cast(&s_report), IGMP_REPORT_PACKET_SIZE); + + s_id++; + + DEBUG_EXIT +} + +static void igmp_start_timer(struct t_group_info &group, const uint32_t max_time) { + group.nTimer = (max_time > 2 ? (random() % max_time) : 1); + + if (group.nTimer == 0) { + group.nTimer = 1; + } +} + +static void igmp_timeout(struct t_group_info &group) { + if ((group.state == DELAYING_MEMBER) && (group.nGroupAddress != 0x010000e0)) { //FIXME all-systems + group.state = IDLE_MEMBER; + igmp_send_report(group.nGroupAddress); + } +} + +static void igmp_timer() { + for (auto &group : s_groups) { + if (group.nTimer > 0) { + group.nTimer--; + if (group.nTimer == 0) { + igmp_timeout(group); + } + } + } } void __attribute__((cold)) igmp_init() { @@ -84,7 +153,7 @@ void __attribute__((cold)) igmp_init() { s_multicast_mac[2] = 0x5E; // Ethernet - memcpy(s_report.ether.src, net::globals::macAddress, ETH_ADDR_LEN); + std::memcpy(s_report.ether.src, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); s_report.ether.type = __builtin_bswap16(ETHER_TYPE_IPv4); // IPv4 @@ -108,7 +177,7 @@ void __attribute__((cold)) igmp_init() { s_leave.ether.dst[3] = 0x00; s_leave.ether.dst[4] = 0x00; s_leave.ether.dst[5] = 0x02; - memcpy(s_leave.ether.src, net::globals::macAddress, ETH_ADDR_LEN); + std::memcpy(s_leave.ether.src, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); s_leave.ether.type = __builtin_bswap16(ETHER_TYPE_IPv4); // IPv4 @@ -129,14 +198,8 @@ void __attribute__((cold)) igmp_init() { s_leave.igmp.report.igmp.type = IGMP_TYPE_LEAVE; s_leave.igmp.report.igmp.max_resp_time = 0; - /* - * https://tldp.org/HOWTO/Multicast-HOWTO-2.html - * 224.0.0.1 is the all-hosts group. If you ping that group, - * all multicast capable hosts on the network should answer, - * as every multicast capable host must join that group - * at start-up on all it's multicast capable interfaces. - */ - _send_report(0x010000e0); + nTimerId = Hardware::Get()->SoftwareTimerAdd(IGMP_TMR_INTERVAL, igmp_timer); + assert(nTimerId >= 0); } void __attribute__((cold)) igmp_shutdown() { @@ -153,43 +216,8 @@ void __attribute__((cold)) igmp_shutdown() { DEBUG_EXIT } -static void _send_report(const uint32_t nGroupAddress) { - DEBUG_ENTRY - _pcast32 multicast_ip; - - multicast_ip.u32 = nGroupAddress; - - s_multicast_mac[3] = multicast_ip.u8[1] & 0x7F; - s_multicast_mac[4] = multicast_ip.u8[2]; - s_multicast_mac[5] = multicast_ip.u8[3]; - - DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(nGroupAddress),MAC2STR(s_multicast_mac)); - - // Ethernet - memcpy(s_report.ether.dst, s_multicast_mac, ETH_ADDR_LEN); - // IPv4 - s_report.ip4.id = s_id; - memcpy(s_report.ip4.dst, multicast_ip.u8, IPv4_ADDR_LEN); - s_report.ip4.chksum = 0; - s_report.ip4.chksum = net_chksum(reinterpret_cast(&s_report.ip4), 24); //TODO - // IGMP - memcpy(s_report.igmp.report.igmp.group_address, multicast_ip.u8, IPv4_ADDR_LEN); - s_report.igmp.report.igmp.checksum = 0; - s_report.igmp.report.igmp.checksum = net_chksum(reinterpret_cast(&s_report.ip4), IPv4_IGMP_REPORT_HEADERS_SIZE); - - emac_eth_send(reinterpret_cast(&s_report), IGMP_REPORT_PACKET_SIZE); - - s_id++; - - DEBUG_EXIT -} - -static void _send_leave(const uint32_t nGroupAddress) { +static void igmp_send_leave(const uint32_t nGroupAddress) { DEBUG_ENTRY - _pcast32 multicast_ip; - - multicast_ip.u32 = nGroupAddress; - DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(nGroupAddress), MAC2STR(s_multicast_mac)); // IPv4 @@ -199,7 +227,7 @@ static void _send_leave(const uint32_t nGroupAddress) { s_leave.ip4.chksum = net_chksum(reinterpret_cast(&s_leave.ip4), 24); //TODO #endif // IGMP - memcpy(s_leave.igmp.report.igmp.group_address, multicast_ip.u8, IPv4_ADDR_LEN); + net::memcpy_ip(s_leave.igmp.report.igmp.group_address, nGroupAddress); s_leave.igmp.report.igmp.checksum = 0; #if !defined (CHECKSUM_BY_HARDWARE) s_leave.igmp.report.igmp.checksum = net_chksum(reinterpret_cast(&s_leave.ip4), IPv4_IGMP_REPORT_HEADERS_SIZE); @@ -251,16 +279,11 @@ __attribute__((hot)) void igmp_handle(struct t_igmp *p_igmp) { DEBUG_EXIT } -void igmp_timer() { - for (auto& group : s_groups) { - if ((group.state == DELAYING_MEMBER) && (group.nTimer > 0)) { - group.nTimer--; - - if (group.nTimer == 0) { - _send_report(group.nGroupAddress); - group.state = IDLE_MEMBER; - } - } +static void igmp_delaying_member(struct t_group_info &group, const uint32_t maxresp) { + if ((group.state == IDLE_MEMBER) + || ((group.state == DELAYING_MEMBER) && ((group.nTimer == 0) || (maxresp < group.nTimer)))) { + igmp_start_timer(group, maxresp); + group.state = DELAYING_MEMBER; } } @@ -286,7 +309,7 @@ void igmp_join(uint32_t nGroupAddress) { s_groups[i].state = DELAYING_MEMBER; s_groups[i].nTimer = 2; // TODO - _send_report(nGroupAddress); + igmp_send_report(nGroupAddress); DEBUG_EXIT return; @@ -306,7 +329,7 @@ void igmp_leave(uint32_t nGroupAddress) { for (auto& group : s_groups) { if (group.nGroupAddress == nGroupAddress) { - _send_leave(group.nGroupAddress); + igmp_send_leave(group.nGroupAddress); group.nGroupAddress = 0; group.state = NON_MEMBER; @@ -324,4 +347,10 @@ void igmp_leave(uint32_t nGroupAddress) { DEBUG_EXIT } +void igmp_report_groups() { + for (auto& group : s_groups) { + igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); + } +} +} // namespace net // <--- diff --git a/lib-network/src/net/ip.cpp b/lib-network/src/net/ip.cpp index e697459c..b2f3c6bf 100644 --- a/lib-network/src/net/ip.cpp +++ b/lib-network/src/net/ip.cpp @@ -2,7 +2,7 @@ * @file ip.cpp * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,13 +23,26 @@ * THE SOFTWARE. */ +#if defined (DEBUG_NET_IP) +# undef NDEBUG +#endif + +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif + #include +#include "../../config/net_config.h" + #include "net.h" #include "net_private.h" -#include "../../config/net_config.h" +#include "debug.h" +namespace net { void ip_set_ip() { udp_set_ip(); igmp_set_ip(); @@ -40,16 +53,9 @@ void __attribute__((cold)) ip_init() { udp_init(); igmp_init(); +#if defined (ENABLE_HTTPD) tcp_init(); - - DEBUG_EXIT -} - -void __attribute__((cold)) ip_shutdown() { - DEBUG_ENTRY - - tcp_shutdown(); - igmp_shutdown(); +#endif DEBUG_EXIT } @@ -85,3 +91,4 @@ __attribute__((hot)) void ip_handle(struct t_ip4 *p_ip4) { break; } } +} // namespace net diff --git a/lib-network/src/net/net.cpp b/lib-network/src/net/net.cpp old mode 100644 new mode 100755 index 0afe1e2b..ae8402e2 --- a/lib-network/src/net/net.cpp +++ b/lib-network/src/net/net.cpp @@ -2,7 +2,7 @@ * @file net.cpp * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,200 +23,160 @@ * THE SOFTWARE. */ +#if defined (DEBUG_NET_NET) +# if defined (NDEBUG) +# undef NDEBUG +# endif +#endif + +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif + #include #include +#include "../../config/net_config.h" + #include "net.h" #include "net_private.h" -#include "net_packets.h" -#include "net_debug.h" -#include "../../config/net_config.h" +#include "netif.h" +#include "net/acd.h" +#include "net/dhcp.h" + +#include "debug.h" + +static struct net::acd::Acd s_acd; + +namespace network { +__attribute__((weak)) void mdns_shutdown() {} +} // namespace network namespace net { namespace globals { -struct IpInfo ipInfo ALIGNED; uint32_t nBroadcastMask; uint32_t nOnNetworkMask; -uint8_t macAddress[ETH_ADDR_LEN] ALIGNED; } // namespace globals -} // namespace net - -static uint8_t *s_p; -static bool s_isDhcp = false; - -static void refresh_and_init(struct IpInfo *pIpInfo, bool doInit) { - net::globals::ipInfo.broadcast_ip.addr = net::globals::ipInfo.ip.addr | ~net::globals::ipInfo.netmask.addr; - - net::globals::nBroadcastMask = ~(net::globals::ipInfo.netmask.addr); - net::globals::nOnNetworkMask = net::globals::ipInfo.ip.addr & net::globals::ipInfo.netmask.addr; - - if (doInit) { - arp_init(); - ip_set_ip(); - } - - const auto *pSrc = reinterpret_cast(&net::globals::ipInfo); - auto *pDst = reinterpret_cast(pIpInfo); - - memcpy(pDst, pSrc, sizeof(struct IpInfo)); -} - -void set_secondary_ip() { - net::globals::ipInfo.ip.addr = net::globals::ipInfo.secondary_ip.addr; - net::globals::ipInfo.netmask.addr = 255; - net::globals::ipInfo.gw.addr = net::globals::ipInfo.ip.addr; -} +#if defined (CONFIG_ENET_ENABLE_PTP) +void ptp_init(); +void ptp_handle(const uint8_t *, const uint32_t); +#endif -void __attribute__((cold)) net_init(const uint8_t *const pMacAddress, struct IpInfo *pIpInfo, const char *pHostname, bool *bUseDhcp, bool *isZeroconfUsed) { +void net_shutdown() { DEBUG_ENTRY - memcpy(net::globals::macAddress, pMacAddress, ETH_ADDR_LEN); - - const auto *pSrc = reinterpret_cast(pIpInfo); - auto *pDst = reinterpret_cast(&net::globals::ipInfo); - - memcpy(pDst, pSrc, sizeof(struct IpInfo)); - - net::globals::ipInfo.secondary_ip.addr = 2 - + ((static_cast(net::globals::macAddress[3])) << 8) - + ((static_cast(net::globals::macAddress[4])) << 16) - + ((static_cast(net::globals::macAddress[5])) << 24); - - - if (net::globals::ipInfo.ip.addr == 0) { - set_secondary_ip(); - } - /* - * The macAddress is set - */ - ip_init(); - - *isZeroconfUsed = false; - - if (*bUseDhcp) { - if (dhcp_client(pHostname) < 0) { - *bUseDhcp = false; - DEBUG_PUTS("DHCP Client failed"); - *isZeroconfUsed = rfc3927(); - } - } - - refresh_and_init(pIpInfo, true); - - s_isDhcp = *bUseDhcp; - - if (!arp_do_probe()) { - DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(net::globals::ipInfo.ip.addr), MAC2STR(net::globals::macAddress)); - arp_send_announcement(); - } else { - console_error("IP Conflict!\n"); - } + net::netif_set_link_down(); DEBUG_EXIT } -void __attribute__((cold)) net_shutdown() { - ip_shutdown(); +static void primary_ip_conflict_callback(net::acd::Callback callback) { + auto &netif = net::globals::netif_default; - if (s_isDhcp) { - dhcp_client_release(); + switch (callback) { + case net::acd::Callback::ACD_IP_OK: + if (s_acd.ipaddr.addr == netif.secondary_ip.addr) { + net_set_secondary_ip(); + } else { + net::netif_set_ipaddr(s_acd.ipaddr); + } + dhcp_inform(); + netif_set_flags(netif::NETIF_FLAG_STATICIP_OK); + break; + case net::acd::Callback::ACD_RESTART_CLIENT: + break; + case net::acd::Callback::ACD_DECLINE: + netif_clear_flags(netif::NETIF_FLAG_STATICIP_OK); + break; + default: + break; } } -void net_set_ip(struct IpInfo *pIpInfo) { - net::globals::ipInfo.ip.addr = pIpInfo->ip.addr; +void net_set_primary_ip(const ip4_addr_t ipaddr) { + auto &netif = net::globals::netif_default; - if (net::globals::ipInfo.ip.addr == 0) { - set_secondary_ip(); - } + net::dhcp_release_and_stop(); - refresh_and_init(pIpInfo, true); + acd_add(&s_acd, primary_ip_conflict_callback); - if (!arp_do_probe()) { - DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(net::globals::ipInfo.ip.addr), MAC2STR(net::globals::macAddress)); - arp_send_announcement(); + if (ipaddr.addr == 0) { + acd_start(&s_acd, netif.secondary_ip); } else { - console_error("IP Conflict!\n"); + acd_start(&s_acd, ipaddr); } } -void net_set_netmask(struct IpInfo *pIpInfo) { - net::globals::ipInfo.netmask.addr = pIpInfo->netmask.addr; - - refresh_and_init(pIpInfo, false); -} - -void net_set_gw(struct IpInfo *pIpInfo) { - net::globals::ipInfo.gw.addr = pIpInfo->gw.addr; - - ip_set_ip(); +void net_set_secondary_ip() { + auto &netif = net::globals::netif_default; + ip4_addr_t netmask; + netmask.addr = 255; + net::netif_set_addr(netif.secondary_ip, netmask, netif.secondary_ip); } -bool net_set_dhcp(struct IpInfo *pIpInfo, const char *const pHostname, bool *isZeroconfUsed) { - bool isDhcp = false; - *isZeroconfUsed = false; - - if (dhcp_client(pHostname) < 0) { - DEBUG_PUTS("DHCP Client failed"); - *isZeroconfUsed = rfc3927(); - } else { - isDhcp = true; - } +void __attribute__((cold)) net_init(const net::Link link, ip4_addr_t ipaddr, ip4_addr_t netmask, ip4_addr_t gw, bool &bUseDhcp) { + DEBUG_ENTRY + globals::netif_default.secondary_ip.addr = 2 + + ((static_cast(globals::netif_default.hwaddr[3])) << 8) + + ((static_cast(globals::netif_default.hwaddr[4])) << 16) + + ((static_cast(globals::netif_default.hwaddr[5])) << 24); - refresh_and_init(pIpInfo, true); + net::arp_init(); + ip_init(); - s_isDhcp = isDhcp; + if (net::Link::STATE_UP == link) { + net::netif_set_flags(net::netif::NETIF_FLAG_LINK_UP); - if (!arp_do_probe()) { - DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(net::globals::ipInfo.ip.addr), MAC2STR(net::globals::macAddress)); - arp_send_announcement(); + if (bUseDhcp) { + dhcp_start(); + } else { +// if (ipaddr.addr == 0) { +// net_set_secondary_ip(); +// } else { +// net::netif_set_addr(ipaddr, netmask, gw); +// } +// dhcp_inform(); + if (ipaddr.addr != 0) { + net::netif_set_netmask(netmask); + net::netif_set_gw(gw); + } + net_set_primary_ip(ipaddr); + } } else { - console_error("IP Conflict!\n"); + net::netif_clear_flags(net::netif::NETIF_FLAG_LINK_UP); } - return isDhcp; -} - -void net_dhcp_release() { - dhcp_client_release(); - s_isDhcp = false; -} - -bool net_set_zeroconf(struct IpInfo *pIpInfo) { - const auto b = rfc3927(); - - if (b) { - refresh_and_init(pIpInfo, true); - - s_isDhcp = false; - - DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(net::globals::ipInfo.ip.addr), MAC2STR(net::globals::macAddress)); - arp_send_announcement(); +#if defined (CONFIG_ENET_ENABLE_PTP) + net::ptp_init(); +#endif - return true; - } - - DEBUG_PUTS("Zeroconf failed"); - return false; + DEBUG_EXIT } __attribute__((hot)) void net_handle() { + uint8_t *s_p; const auto nLength = emac_eth_recv(&s_p); if (__builtin_expect((nLength > 0), 0)) { const auto *const eth = reinterpret_cast(s_p); - if (eth->type == __builtin_bswap16(ETHER_TYPE_IPv4)) { - ip_handle(reinterpret_cast(s_p)); - } else if (eth->type == __builtin_bswap16(ETHER_TYPE_ARP)) { - arp_handle(reinterpret_cast(s_p)); - } else { - DEBUG_PRINTF("type %04x is not implemented", __builtin_bswap16(eth->type)); - } +#if defined (CONFIG_ENET_ENABLE_PTP) + if (eth->type == __builtin_bswap16(ETHER_TYPE_PTP)) { + net::ptp_handle(const_cast(s_p), nLength); + } else +#endif + if (eth->type == __builtin_bswap16(ETHER_TYPE_IPv4)) { + ip_handle(reinterpret_cast(s_p)); + } else if (eth->type == __builtin_bswap16(ETHER_TYPE_ARP)) { + net::arp_handle(reinterpret_cast(s_p)); + } else { + DEBUG_PRINTF("type %04x is not implemented", __builtin_bswap16(eth->type)); + } emac_free_pkt(); } - - net_timers_run(); } +} // namespace net diff --git a/lib-network/src/net/net_chksum.cpp b/lib-network/src/net/net_chksum.cpp index 75fcb516..408ebaa7 100644 --- a/lib-network/src/net/net_chksum.cpp +++ b/lib-network/src/net/net_chksum.cpp @@ -2,7 +2,7 @@ * @file net_chksum.cpp * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,10 +23,13 @@ * THE SOFTWARE. */ -#include +#pragma GCC push_options +#pragma GCC optimize ("O2") +#pragma GCC optimize ("no-tree-loop-distribute-patterns") -#include "net_private.h" +#include +namespace net { uint16_t net_chksum(const void *data, uint32_t len) { auto *ptr = reinterpret_cast(data); uint32_t sum = 0; @@ -49,3 +52,4 @@ uint16_t net_chksum(const void *data, uint32_t len) { return static_cast(~sum); } +} // namespace net diff --git a/lib-network/src/net/net_memcpy.h b/lib-network/src/net/net_memcpy.h index c7a70bd0..ca4f1d55 100644 --- a/lib-network/src/net/net_memcpy.h +++ b/lib-network/src/net/net_memcpy.h @@ -2,7 +2,7 @@ * @file net_memcpy.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,19 +27,23 @@ #include #include -inline void *net_memcpy(void *__restrict__ dest, void const *__restrict__ src, size_t n) { - auto *plDst = reinterpret_cast(dest); - auto const *plSrc = reinterpret_cast(src); +#include "net/protocol/ip4.h" - if (((reinterpret_cast(src) & 0x3) == 0) && ((reinterpret_cast(dest) & 0x3) == 0)) { - while (n >= 4) { +namespace net { +inline void* memcpy(void *__restrict__ dest, void const *__restrict__ src, size_t n) { + auto *plDst = reinterpret_cast(dest); + auto const *plSrc = reinterpret_cast(src); + + if (((reinterpret_cast(src) & (sizeof(uintptr_t) - 1)) == 0) + && ((reinterpret_cast(dest) & (sizeof(uintptr_t) - 1)) == 0)) { + while (n >= sizeof(uintptr_t)) { *plDst++ = *plSrc++; - n -= 4; + n -= sizeof(uintptr_t); } } - auto *pcDst = reinterpret_cast(plDst); - auto const *pcSrc = reinterpret_cast(plSrc); + auto *pcDst = reinterpret_cast(plDst); + auto const *pcSrc = reinterpret_cast(plSrc); while (n--) { *pcDst++ = *pcSrc++; @@ -48,4 +52,64 @@ inline void *net_memcpy(void *__restrict__ dest, void const *__restrict__ src, s return dest; } +inline void memcpy_ip(uint8_t *pIpAddress, const uint32_t nIpAddress) { +#ifdef __ARM_ARCH_7A__ + // Ensure destination pointer is aligned + if ((reinterpret_cast(pIpAddress) & ((sizeof(uint32_t) - 1))) == 0) { + // Destination pointer is already aligned, perform fast copy + *reinterpret_cast(pIpAddress) = nIpAddress; + } else +#endif + { // Destination pointer is not aligned, copy byte by byte + typedef union pcast32 { + uint32_t u32; + uint8_t u8[4]; + } _pcast32; + + _pcast32 src; + src.u32 = nIpAddress; +#ifdef __ARM_ARCH_7A__ + volatile auto *pSrc = src.u8; + volatile auto *pDst = pIpAddress; +#else + auto *pSrc = src.u8; + auto *pDst = pIpAddress; +#endif + for (uint32_t i = 0; i < IPv4_ADDR_LEN; i++) { + pDst[i] = pSrc[i]; + } + } +} + +inline uint32_t memcpy_ip(const uint8_t *pIpAddress) { +#ifdef __ARM_ARCH_7A__ + // Ensure destination pointer is aligned + if ((reinterpret_cast(pIpAddress) & ((sizeof(uint32_t) - 1))) == 0) { + // Destination pointer is already aligned, perform fast copy + return *reinterpret_cast(pIpAddress); + } else +#endif + { // Destination pointer is not aligned, copy byte by byte + typedef union pcast32 { + uint32_t u32; + uint8_t u8[4]; + } _pcast32; + + _pcast32 src; +#ifdef __ARM_ARCH_7A__ + volatile auto *pSrc = pIpAddress; + volatile auto *pDst = src.u8; +#else + auto *pSrc = pIpAddress; + auto *pDst = src.u8; +#endif + for (uint32_t i = 0; i < IPv4_ADDR_LEN; i++) { + pDst[i] = pSrc[i]; + } + + return src.u32; + } +} +} // namespace net + #endif /* NET_MEMCPY_H_ */ diff --git a/lib-network/src/net/net_packets.h b/lib-network/src/net/net_packets.h deleted file mode 100644 index d3b0f3e9..00000000 --- a/lib-network/src/net/net_packets.h +++ /dev/null @@ -1,225 +0,0 @@ -/** - * @file net_packets.h - * - */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef NET_PACKETS_H_ -#define NET_PACKETS_H_ - -#include - -#if !defined (PACKED) -# define PACKED __attribute__((packed)) -#endif - -enum MTU { - MTU_SIZE = 1500 -}; - -enum ETHER_TYPE { - ETHER_TYPE_IPv4 = 0x0800, - ETHER_TYPE_ARP = 0x0806 -}; - -enum ETH_ADDR { - ETH_ADDR_LEN = 6 -}; - -enum IPv4_ADDR { - IPv4_ADDR_LEN = 4 -}; - -enum IPv4_PROTO { - IPv4_PROTO_ICMP = 1, - IPv4_PROTO_IGMP = 2, - IPv4_PROTO_TCP = 6, - IPv4_PROTO_UDP = 17 -}; - -enum IPv4_FLAG { - IPv4_FLAG_LF = 0x0000, - IPv4_FLAG_MF = 0x2000, - IPv4_FLAG_DF = 0x4000 -}; - -#define IPv4_BROADCAST 0xffffffff - -enum ARP_HARDWARE_TYPE { - ARP_HWTYPE_ETHERNET = 1 -}; - -enum ARP_PROTOCOL_TYPE { - ARP_PRTYPE_IPv4 = ETHER_TYPE_IPv4 -}; - -enum ARP_HARDWARE { - ARP_HARDWARE_SIZE = ETH_ADDR_LEN -}; - -enum ARP_PROTOCOL { - ARP_PROTOCOL_SIZE = IPv4_ADDR_LEN -}; - -enum ARP_OPCODE { - ARP_OPCODE_RQST = 1, - ARP_OPCODE_REPLY = 2 -}; - -enum IGMP_TYPE { - IGMP_TYPE_QUERY = 0x11, - IGMP_TYPE_REPORT = 0x16, - IGMP_TYPE_LEAVE = 0x17 -}; - -enum ICMP_TYPE { - ICMP_TYPE_ECHO_REPLY = 0, - ICMP_TYPE_ECHO = 8 -}; - -enum ICMP_CODE { - ICMP_CODE_ECHO = 0 -}; - -struct ether_header { - uint8_t dst[ETH_ADDR_LEN]; /* 6 */ - uint8_t src[ETH_ADDR_LEN]; /* 12 */ - uint16_t type; /* 14 */ -} PACKED; - -struct arp_packet { - uint16_t hardware_type; /* 2 */ - uint16_t protocol_type; /* 4 */ - uint8_t hardware_size; /* 5 */ - uint8_t protocol_size; /* 6 */ - uint16_t opcode; /* 8 */ - uint8_t sender_mac[ETH_ADDR_LEN];/*14 */ - uint8_t sender_ip[IPv4_ADDR_LEN];/* 18 */ - uint8_t target_mac[ETH_ADDR_LEN];/*24 */ - uint8_t target_ip[IPv4_ADDR_LEN];/* 28 */ - uint8_t padding[18]; /* 46 */ /* +14 = 60 */ -} PACKED; - -struct ip4_header { - uint8_t ver_ihl; /* 1 */ - uint8_t tos; /* 2 */ - uint16_t len; /* 4 */ - uint16_t id; /* 6 */ - uint16_t flags_froff; /* 8 */ - uint8_t ttl; /* 9 */ - uint8_t proto; /* 10 */ - uint16_t chksum; /* 12 */ - uint8_t src[IPv4_ADDR_LEN]; /* 16 */ - uint8_t dst[IPv4_ADDR_LEN]; /* 20 */ -} PACKED; - -struct t_igmp_packet { - uint8_t type; - uint8_t max_resp_time; - uint16_t checksum; - uint8_t group_address[IPv4_ADDR_LEN]; -} PACKED; - -struct t_icmp_packet { - uint8_t type; /* 1 */ - uint8_t code; /* 2 */ - uint16_t checksum; /* 4 */ - uint8_t parameter[4]; /* 8 */ -#define ICMP_HEADER_SIZE 8 -#define ICMP_PAYLOAD_SIZE (MTU_SIZE - ICMP_HEADER_SIZE - sizeof(struct ip4_header)) - uint8_t payload[ICMP_PAYLOAD_SIZE]; -} PACKED; - -struct t_udp_packet { - uint16_t source_port; /* 2 */ - uint16_t destination_port; /* 4 */ - uint16_t len; /* 6 */ - uint16_t checksum; /* 8 */ -#define UDP_HEADER_SIZE 8 -#define UDP_DATA_SIZE (MTU_SIZE - UDP_HEADER_SIZE - sizeof(struct ip4_header)) - uint8_t data[UDP_DATA_SIZE]; -}PACKED; - -struct t_tcp_packet { - uint16_t srcpt; /* 2 */ - uint16_t dstpt; /* 4 */ - uint32_t seqnum; /* 8 */ - uint32_t acknum; /* 12 */ - uint8_t offset; /* 13 */ - uint8_t control; /* 14 */ - uint16_t window; /* 16 */ - uint16_t checksum; /* 18 */ - uint16_t urgent; /* 20 */ -#define TCP_HEADER_SIZE 20 -#define TCP_DATA_SIZE (MTU_SIZE - TCP_HEADER_SIZE - sizeof(struct ip4_header) - 20U) - uint8_t data[TCP_DATA_SIZE]; -} PACKED; - -struct t_arp { - struct ether_header ether; - struct arp_packet arp; -} PACKED; - -struct t_ip4 { - struct ether_header ether; - struct ip4_header ip4; -} PACKED; - -struct t_igmp { - struct ether_header ether; - struct ip4_header ip4; - union { - struct { - uint32_t ip4_options; - struct t_igmp_packet igmp; - } report; - struct t_igmp_packet igmp; - } igmp; -} PACKED; - -struct t_icmp { - struct ether_header ether; - struct ip4_header ip4; - struct t_icmp_packet icmp; -} PACKED; - -struct t_udp { - struct ether_header ether; - struct ip4_header ip4; - struct t_udp_packet udp; -} PACKED; - -struct t_tcp { - struct ether_header ether; - struct ip4_header ip4; - struct t_tcp_packet tcp; -} PACKED; - -#define IPv4_UDP_HEADERS_SIZE (sizeof(struct ip4_header) + UDP_HEADER_SIZE) /* IP | UDP */ -#define UDP_PACKET_HEADERS_SIZE (sizeof(struct ether_header) + IPv4_UDP_HEADERS_SIZE) /* ETH | IP | UDP */ - -#define IPv4_IGMP_REPORT_HEADERS_SIZE (sizeof(struct t_igmp) - sizeof(struct ether_header)) -#define IGMP_REPORT_PACKET_SIZE (sizeof(struct t_igmp)) - -#define IPv4_ICMP_HEADERS_SIZE (sizeof(struct t_icmp) - sizeof(struct ether_header)) - -#endif /* NET_PACKETS_H_ */ diff --git a/lib-network/src/net/net_platform.h b/lib-network/src/net/net_platform.h index 79f9343c..8f5ce447 100644 --- a/lib-network/src/net/net_platform.h +++ b/lib-network/src/net/net_platform.h @@ -31,7 +31,7 @@ * https://www.gd32-dmx.org/memory.html */ # include "gd32.h" -# if defined (GD32F207RG) || defined (GD32F4XX) +# if defined (GD32F207RG) || defined (GD32F4XX) || defined(GD32H7XX) # define SECTION_NETWORK __attribute__ ((section (".network"))) # else # define SECTION_NETWORK diff --git a/lib-network/src/net/net_private.h b/lib-network/src/net/net_private.h old mode 100755 new mode 100644 index 93c4da72..336c4c58 --- a/lib-network/src/net/net_private.h +++ b/lib-network/src/net/net_private.h @@ -2,7 +2,7 @@ * @file net_private.h * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,50 +28,47 @@ #include -#include "net_packets.h" #include "net_platform.h" -#include "net_debug.h" -#include "dhcp_internal.h" -#include "tftp_internal.h" -#include "ntp_internal.h" +#include "net/arp.h" +#include "net/protocol/icmp.h" +#include "net/protocol/igmp.h" +#include "net/protocol/udp.h" +#include "net/protocol/tcp.h" #ifndef ALIGNED # define ALIGNED __attribute__ ((aligned (4))) #endif -extern "C" { -int console_error(const char *); -void emac_eth_send(void *, int); +namespace net::arp { +enum class EthSend { + IS_NORMAL +#if defined CONFIG_ENET_ENABLE_PTP + , IS_TIMESTAMP +#endif +}; +} // namespace net::arp + +extern "C" void console_error(const char *); + +void emac_eth_send(void *, uint32_t); +#if defined CONFIG_ENET_ENABLE_PTP +void emac_eth_send_timestamp(void *, uint32_t); +#endif int emac_eth_recv(uint8_t **); -void emac_free_pkt(void); -} +void emac_free_pkt(); +namespace net { void net_handle(); uint16_t net_chksum(const void *, uint32_t); void net_timers_run(); -void arp_init(); -void arp_handle(struct t_arp *); -bool arp_do_probe(); -void arp_cache_init(); -void arp_send_request(uint32_t); -void arp_send_probe(); -void arp_send_announcement(); -void arp_cache_update(const uint8_t *, uint32_t); -uint32_t arp_cache_lookup(uint32_t, uint8_t *); - void ip_init(); void ip_set_ip(); void ip_shutdown(); void ip_handle(struct t_ip4 *); -int dhcp_client(const char *); -void dhcp_client_release(); - -bool rfc3927(); - void udp_init(); void udp_set_ip(); void udp_handle(struct t_udp *); @@ -81,7 +78,6 @@ void igmp_init(); void igmp_set_ip(); void igmp_handle(struct t_igmp *); void igmp_shutdown(); -void igmp_timer(); void icmp_handle(struct t_icmp *); void icmp_shutdown(); @@ -90,5 +86,6 @@ void tcp_init(); void tcp_run(); void tcp_handle(struct t_tcp *); void tcp_shutdown(); +} // namespace net #endif /* NET_PRIVATE_H_ */ diff --git a/lib-network/src/net/net_ptp.cpp b/lib-network/src/net/net_ptp.cpp new file mode 100755 index 00000000..8a4b6951 --- /dev/null +++ b/lib-network/src/net/net_ptp.cpp @@ -0,0 +1,35 @@ +/** + * @file net_ptp.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +namespace net { +namespace globals { +uint32_t ptpTimestamp[2]; +} // namespace globals + +void __attribute__((weak)) ptp_handle([[maybe_unused]] const uint8_t *pBuffer, [[maybe_unused]] const uint32_t nLength) {} +void __attribute__((weak)) ptp_run() {} +} // namespace net diff --git a/lib-network/src/net/netif.cpp b/lib-network/src/net/netif.cpp new file mode 100755 index 00000000..975b1e6f --- /dev/null +++ b/lib-network/src/net/netif.cpp @@ -0,0 +1,306 @@ +/** + * @file netif.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if defined (DEBUG_NET_NETIF) +# undef NDEBUG +#endif + +#include + +#include "netif.h" +#include "net/acd.h" +#include "net/autoip.h" +#include "net/dhcp.h" +#include "net/igmp.h" + +#include "debug.h" + +namespace net { +namespace globals { +struct netif netif_default; +extern uint32_t nBroadcastMask; +extern uint32_t nOnNetworkMask; +} // namespace globals + +extern void arp_init(); +extern void ip_set_ip(); + +static netif_ext_callback_fn callback_fn; + +static void default_callback([[maybe_unused]] const uint16_t reason, [[maybe_unused]] const netif_ext_callback_args_t* args) { + DEBUG_PRINTF("%u", reason); +} + +void netif_init() { + auto &netif = net::globals::netif_default; + + netif.ip.addr = 0; + netif.netmask.addr = 0; + netif.gw.addr = 0; + netif.broadcast_ip.addr = 0; + netif.secondary_ip.addr = 2 + + ((static_cast(netif.hwaddr[3])) << 8) + + ((static_cast(netif.hwaddr[4])) << 16) + + ((static_cast(netif.hwaddr[5])) << 24); + netif.flags = 0; + netif.dhcp = nullptr; + netif.acd = nullptr; + netif.autoip = nullptr; + + callback_fn = &default_callback; + + net::arp_init(); +} + +static void netif_do_update_globals() { + auto &netif = net::globals::netif_default; + netif.broadcast_ip.addr = (netif.ip.addr | ~netif.netmask.addr); + + globals::nBroadcastMask = ~(netif.netmask.addr); + globals::nOnNetworkMask =netif.ip.addr & netif.netmask.addr; + + ip_set_ip(); +} + +static void netif_do_ip_addr_changed([[maybe_unused]] const ip4_addr_t old_addr,[[maybe_unused]] const ip4_addr_t new_addr) { +// tcp_netif_ip_addr_changed(old_addr, new_addr); +// udp_netif_ip_addr_changed(old_addr, new_addr); + ip_set_ip(); +} + +static void netif_issue_reports() { + const auto &netif = net::globals::netif_default; + + if (!(netif.flags & netif::NETIF_FLAG_LINK_UP)) { + return; + } + + if (netif.ip.addr != 0) { + igmp_report_groups(); + } +} + +static bool netif_do_set_ipaddr(const ip4_addr_t ipaddr, ip4_addr_t &old_addr) { + DEBUG_ENTRY + auto &netif = net::globals::netif_default; + + DEBUG_PRINTF(IPSTR " " IPSTR, IP2STR(ipaddr.addr), IP2STR(netif.ip.addr)); + + // Update the address if it's different + if (ipaddr.addr != netif.ip.addr) { + old_addr.addr = netif.ip.addr; + + netif_do_ip_addr_changed(old_addr, ipaddr); + acd_netif_ip_addr_changed(old_addr, ipaddr); + + netif.ip.addr = ipaddr.addr; + + netif_do_update_globals(); + netif_issue_reports(); + + DEBUG_EXIT + return true; // address changed + } + + DEBUG_EXIT + return false; // address unchanged +} + +static bool netif_do_set_netmask(const ip4_addr_t netmask, ip4_addr_t &old_nm) { + DEBUG_ENTRY + auto &netif = net::globals::netif_default; + + if (netmask.addr != netif.netmask.addr) { + old_nm.addr = netif.netmask.addr; + netif.netmask.addr = netmask.addr; + + netif_do_update_globals(); + + DEBUG_EXIT + return true; // netmask changed + } + + DEBUG_EXIT + return false; // netmask unchanged +} + +static bool netif_do_set_gw(const ip4_addr_t gw, ip4_addr_t &old_gw) { + DEBUG_ENTRY + auto &netif = net::globals::netif_default; + + if (gw.addr != netif.gw.addr) { + old_gw.addr = netif.gw.addr; + netif.gw.addr = gw.addr; + + DEBUG_EXIT + return true; // gateway changed + } + + DEBUG_EXIT + return false; // gateway unchanged +} + +void netif_set_ipaddr(const ip4_addr_t ipaddr) { + ip4_addr_t old_addr; + + if (netif_do_set_ipaddr(ipaddr, old_addr)) { + netif_ext_callback_args_t args; + args.ipv4_changed.old_address.addr = old_addr.addr; + callback_fn(NetifReason::NSC_IPV4_ADDRESS_CHANGED, &args); + } +} + +void netif_set_netmask(const ip4_addr_t netmask) { + ip4_addr_t old_nm; + + if (netif_do_set_netmask(netmask, old_nm)) { + netif_ext_callback_args_t args; + args.ipv4_changed.old_netmask = old_nm; + callback_fn(NetifReason::NSC_IPV4_NETMASK_CHANGED, &args); + } +} + +void netif_set_gw(const ip4_addr_t gw) { + ip4_addr_t old_gw; + + if (netif_do_set_gw(gw, old_gw)) { + netif_ext_callback_args_t args; + args.ipv4_changed.old_gw = old_gw; + callback_fn(NetifReason::NSC_IPV4_GATEWAY_CHANGED, &args); + } +} + +void netif_set_addr(const ip4_addr_t ipaddr, const ip4_addr_t netmask, const ip4_addr_t gw) { + DEBUG_ENTRY + DEBUG_PRINTF(IPSTR " " IPSTR " " IPSTR, IP2STR(ipaddr.addr), IP2STR(netmask.addr), IP2STR(gw.addr)); + + auto change_reason = NetifReason::NSC_NONE; + netif_ext_callback_args_t cb_args; + + ip4_addr_t old_addr; + ip4_addr_t old_nm; + ip4_addr_t old_gw; + + const auto remove = (ipaddr.addr == 0); + + if (remove) { + /* when removing an address, we have to remove it *before* changing netmask/gw + to ensure that tcp RST segment can be sent correctly */ + if (netif_do_set_ipaddr(ipaddr, old_addr)) { + change_reason |= NetifReason::NSC_IPV4_ADDRESS_CHANGED; + cb_args.ipv4_changed.old_address.addr = old_addr.addr; + } + } + + if (netif_do_set_netmask(netmask, old_nm)) { + change_reason |= NetifReason::NSC_IPV4_NETMASK_CHANGED; + cb_args.ipv4_changed.old_netmask.addr = old_nm.addr; + } + + if (netif_do_set_gw(gw, old_gw)) { + change_reason |= NetifReason::NSC_IPV4_GATEWAY_CHANGED; + cb_args.ipv4_changed.old_gw = old_gw; + } + + if (!remove) { + /* set ipaddr last to ensure netmask/gw have been set when status callback is called */ + if (netif_do_set_ipaddr(ipaddr, old_addr)) { + change_reason |= NetifReason::NSC_IPV4_ADDRESS_CHANGED; + cb_args.ipv4_changed.old_address.addr = old_addr.addr; + } + } + + if (change_reason != NetifReason::NSC_NONE) { + change_reason |= NetifReason::NSC_IPV4_SETTINGS_CHANGED; + } + + if (!remove) { + /* Issue a callback even if the address hasn't changed, eg. DHCP reboot */ + change_reason |= NetifReason::NSC_IPV4_ADDR_VALID; + } + + DEBUG_PRINTF("change_reason=%u", change_reason); + + if (change_reason != NetifReason::NSC_NONE) { + callback_fn(change_reason, &cb_args); + } + + DEBUG_EXIT +} + +void netif_add_ext_callback(netif_ext_callback_fn fn) { + callback_fn = fn; +} + +/* + * Link + */ + +void netif_set_link_up() { + DEBUG_ENTRY + const auto &netif = net::globals::netif_default; + + if (!(netif.flags & netif::NETIF_FLAG_LINK_UP)) { + netif_set_flags(netif::NETIF_FLAG_LINK_UP); + + dhcp_network_changed_link_up(); + + autoip_network_changed_link_up(); + + netif_issue_reports(); + + netif_ext_callback_args_t args; + args.link_changed.state = 1; + callback_fn(NetifReason::NSC_LINK_CHANGED, &args); + + DEBUG_EXIT + return; + } + + DEBUG_EXIT +} + +void netif_set_link_down() { + DEBUG_ENTRY + const auto &netif = net::globals::netif_default; + + if (netif.flags & netif::NETIF_FLAG_LINK_UP) { + netif_clear_flags(netif::NETIF_FLAG_LINK_UP); + + autoip_network_changed_link_down(); + + acd_network_changed_link_down(); + + netif_ext_callback_args_t args; + args.link_changed.state = 0; + callback_fn(NetifReason::NSC_LINK_CHANGED, &args); + + DEBUG_EXIT + return; + } + + DEBUG_EXIT +} +} // namespace net diff --git a/lib-network/src/net/rfc3927.cpp b/lib-network/src/net/rfc3927.cpp deleted file mode 100644 index ba7b9c4f..00000000 --- a/lib-network/src/net/rfc3927.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file rfc3927.cpp - * - */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "net.h" -#include "net_private.h" - -#include "hardware.h" - -#include "../../config/net_config.h" - -/* - * https://www.rfc-editor.org/rfc/rfc3927.html - * Dynamic Configuration of IPv4 Link-Local Addresses - */ - -static const uint32_t s_ip_begin = 0x0100FEA9; // 169.254.0.1 -static const uint32_t s_ip_end = 0xFFFEFEA9; // 169.254.254.255 - -namespace net { -namespace globals { -extern struct IpInfo ipInfo; -extern uint8_t macAddress[ETH_ADDR_LEN]; -} // namespace globals -} // namespace net - -bool rfc3927() { - DEBUG_ENTRY - - const auto mask = net::globals::macAddress[3] + (net::globals::macAddress[4] << 8); - auto ip = s_ip_begin | static_cast(mask << 16); - - DEBUG_PRINTF("ip=" IPSTR, IP2STR(ip)); - - auto nCount = 0; - const auto nMillis = Hardware::Get()->Millis(); - - do { - DEBUG_PRINTF(IPSTR, IP2STR(ip)); - - net::globals::ipInfo.ip.addr = ip; - - if (!arp_do_probe()) { - net::globals::ipInfo.gw.addr = ip; - net::globals::ipInfo.netmask.addr = 0x0000FFFF; - - DEBUG_EXIT - return true; - } - - ip = __builtin_bswap32(__builtin_bswap32(ip) + 1); - - if (ip == s_ip_end) { - ip = s_ip_begin; - } - - nCount++; - } while ((nCount < 0xFF) && ((Hardware::Get()->Millis() - nMillis) < 500)); - - net::globals::ipInfo.ip.addr = 0; - net::globals::ipInfo.gw.addr = 0; - net::globals::ipInfo.netmask.addr = 0; - - DEBUG_EXIT - return false; -} diff --git a/lib-network/src/net/tcp.cpp b/lib-network/src/net/tcp.cpp index 4dda2074..c219828b 100644 --- a/lib-network/src/net/tcp.cpp +++ b/lib-network/src/net/tcp.cpp @@ -2,7 +2,7 @@ * @file tcp.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,39 +29,43 @@ * LISTEN -> ESTABLISHED -> CLOSE_WAIT -> LAST_ACK -> CLOSED:LISTEN */ +#if defined (DEBUG_NET_TCP) +# undef NDEBUG +#endif + +#pragma GCC diagnostic push #if (__GNUC__ < 10) -# pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wsign-conversion" #endif +#pragma GCC push_options +#pragma GCC optimize ("O2") +#pragma GCC optimize ("no-tree-loop-distribute-patterns") #include #include #include #include +#include "../config/net_config.h" + #include "net.h" +#include "net/protocol/tcp.h" + +#include "net_memcpy.h" #include "net_private.h" #include "hardware.h" -#include "../config/net_config.h" +#include "debug.h" +namespace net { #define TCP_RX_MSS (TCP_DATA_SIZE) #define TCP_RX_MAX_ENTRIES (1U << 1) // Must always be a power of 2 #define TCP_RX_MAX_ENTRIES_MASK (TCP_RX_MAX_ENTRIES - 1) #define TCP_MAX_RX_WND (TCP_RX_MAX_ENTRIES * TCP_RX_MSS); - #define TCP_TX_MSS (TCP_DATA_SIZE) -#define MAX_TCBS_ALLOWED 6 - -namespace net { -namespace globals { -extern uint8_t macAddress[ETH_ADDR_LEN]; -} // namespace globals -} // namespace net - /** * Transmission control block (TCB) */ @@ -128,7 +132,7 @@ struct ReceiveQueue { }; struct Port { - tcb TCB[MAX_TCBS_ALLOWED]; + tcb TCB[TCP_MAX_TCBS_ALLOWED]; ReceiveQueue receiveQueue; uint16_t nLocalPort; }; @@ -253,13 +257,13 @@ static constexpr bool SEQ_GT(const uint32_t x, const uint32_t y) { return static_cast(x - y) > 0; } -static constexpr bool SEQ_GEQ(const uint32_t x, const uint32_t y) { - return static_cast(x - y) >= 0; -} - -static constexpr bool SEQ_BETWEEN(const uint32_t l, const uint32_t x, const uint32_t h) { - return SEQ_LT(l, x) && SEQ_LT(x, h); -} +//static constexpr bool SEQ_GEQ(const uint32_t x, const uint32_t y) { +// return static_cast(x - y) >= 0; +//} +// +//static constexpr bool SEQ_BETWEEN(const uint32_t l, const uint32_t x, const uint32_t h) { +// return SEQ_LT(l, x) && SEQ_LT(x, h); +//} static constexpr bool SEQ_BETWEEN_L(const uint32_t l, const uint32_t x, const uint32_t h) { return SEQ_LEQ(l, x) && SEQ_LT(x, h); // low border inclusive @@ -322,7 +326,7 @@ __attribute__((cold)) void tcp_init() { DEBUG_ENTRY /* Ethernet */ - memcpy(s_tcp.ether.src, net::globals::macAddress, ETH_ADDR_LEN); + std::memcpy(s_tcp.ether.src, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); s_tcp.ether.type = __builtin_bswap16(ETHER_TYPE_IPv4); /* IPv4 */ s_tcp.ip4.ver_ihl = 0x45; @@ -360,8 +364,8 @@ static uint16_t _chksum(struct t_tcp *pTcp, const struct tcb *pTcb, uint16_t nLe memcpy(buf, pseu, TCP_PSEUDO_LEN); // Generate TCP psuedo header - memcpy(pseu->srcIp, pTcb->localIp, IPv4_ADDR_LEN); - memcpy(pseu->dstIp, pTcb->remoteIp, IPv4_ADDR_LEN); + std::memcpy(pseu->srcIp, pTcb->localIp, IPv4_ADDR_LEN); + std::memcpy(pseu->dstIp, pTcb->remoteIp, IPv4_ADDR_LEN); pseu->zero = 0; pseu->proto = IPv4_PROTO_TCP; pseu->length = __builtin_bswap16(nLength); @@ -391,12 +395,12 @@ static void send_package(const struct tcb *pTcb, const struct SendInfo &sendInfo const auto tcplen = nHeaderLength + pTcb->TX.size; /* Ethernet */ - memcpy(s_tcp.ether.dst, pTcb->remoteEthAddr, ETH_ADDR_LEN); + std::memcpy(s_tcp.ether.dst, pTcb->remoteEthAddr, ETH_ADDR_LEN); /* IPv4 */ s_tcp.ip4.id = s_id++; s_tcp.ip4.len = __builtin_bswap16(static_cast(tcplen + sizeof(struct ip4_header))); - memcpy(s_tcp.ip4.src, pTcb->localIp, IPv4_ADDR_LEN); - memcpy(s_tcp.ip4.dst, pTcb->remoteIp, IPv4_ADDR_LEN); + std::memcpy(s_tcp.ip4.src, pTcb->localIp, IPv4_ADDR_LEN); + std::memcpy(s_tcp.ip4.dst, pTcb->remoteIp, IPv4_ADDR_LEN); s_tcp.ip4.chksum = 0; #if !defined (CHECKSUM_BY_HARDWARE) s_tcp.ip4.chksum = net_chksum(reinterpret_cast(&s_tcp.ip4), 20); @@ -545,26 +549,79 @@ static void scan_options(struct t_tcp *pTcp, struct tcb *pTcb, const int32_t nDa } __attribute__((hot)) void tcp_run() { - for (auto nIndexPort = 0; nIndexPort < TCP_MAX_PORTS_ALLOWED; nIndexPort++) { - for (auto nIndexTCB = 0; nIndexTCB < MAX_TCBS_ALLOWED; nIndexTCB++) { - auto *pTCB = &s_Port[nIndexPort].TCB[nIndexTCB]; - - if (pTCB->state == STATE_CLOSE_WAIT) { - struct SendInfo info; - info.SEQ = pTCB->SND.NXT; - info.ACK = pTCB->RCV.NXT; + for (auto& port : s_Port) { + for (auto& tcb : port.TCB) { + if (tcb.state == STATE_CLOSE_WAIT) { + SendInfo info; + info.SEQ = tcb.SND.NXT; + info.ACK = tcb.RCV.NXT; info.CTL = Control::FIN | Control::ACK; - send_package(pTCB, info); + send_package(&tcb, info); - NEW_STATE(pTCB, STATE_LAST_ACK); + NEW_STATE(&tcb, STATE_LAST_ACK); - pTCB->SND.NXT++; + tcb.SND.NXT++; } } } } +static bool find_matching_tcb(const t_tcp *pTcp, const uint32_t nIndexPort, uint32_t& nIndexTCB) { + for (nIndexTCB = 0; nIndexTCB < TCP_MAX_TCBS_ALLOWED; nIndexTCB++) { + auto *pTCB = &s_Port[nIndexPort].TCB[nIndexTCB]; + + if (pTCB->state == STATE_LISTEN) { + continue; + } + + if (pTCB->nRemotePort == pTcp->tcp.srcpt && memcmp(pTCB->remoteIp, pTcp->ip4.src, IPv4_ADDR_LEN) == 0) { + return true; + } + } + + return false; +} + +static bool find_available_tcb(const uint32_t nIndexPort, uint32_t& nIndexTCB) { + for (nIndexTCB = 0; nIndexTCB < TCP_MAX_TCBS_ALLOWED; nIndexTCB++) { + auto *pTCB = &s_Port[nIndexPort].TCB[nIndexTCB]; + + if (pTCB->state == STATE_LISTEN) { + DEBUG_PUTS("pTCB->state == STATE_LISTEN"); + return true; + } + } + + return false; +} + +static void find_tcb(const t_tcp *pTcp, uint32_t& nIndexPort, uint32_t& nIndexTCB) { + // Search each port for a match with the destination port + for (nIndexPort = 0; nIndexPort < TCP_MAX_PORTS_ALLOWED; nIndexPort++) { + if (s_Port[nIndexPort].nLocalPort != pTcp->tcp.dstpt) { + continue; + } + + // Search for an existing active TCB matching the source IP and port + if (find_matching_tcb(pTcp, nIndexPort, nIndexTCB)) { + DEBUG_EXIT + return; + } + + // If no matching TCB, find an available TCB in listening state + if (find_available_tcb(nIndexPort, nIndexTCB)) { + DEBUG_EXIT + return; + } + + // If no available TCB, trigger retransmission + DEBUG_PUTS("MAX_TCB_ALLOWED -> Force retransmission"); + DEBUG_EXIT + return; + } +} + /** * https://www.rfc-editor.org/rfc/rfc9293.html#name-segment-arrives */ @@ -576,69 +633,33 @@ __attribute__((hot)) void tcp_handle(struct t_tcp *pTcp) { DEBUG_PRINTF(IPSTR ":%d[%d] -> %d", pTcp->ip4.src[0], pTcp->ip4.src[1], pTcp->ip4.src[2], pTcp->ip4.src[3], pTcp->tcp.dstpt, pTcp->tcp.srcpt, tcplen); - uint32_t nIndexPort; - /* - src/net/tcp.cpp: In function 'void tcp_handle(t_tcp*)': -src/net/tcp.cpp:871:31: error: 'nIndexTCB' may be used uninitialized in this function [-Werror=maybe-uninitialized] - 871 | switch (pTCB->state) { - */ + uint32_t nIndexPort = 0; uint32_t nIndexTCB = 0; - - // Find a TCB - for (nIndexPort = 0; nIndexPort < TCP_MAX_PORTS_ALLOWED; nIndexPort++) { - if (s_Port[nIndexPort].nLocalPort == pTcp->tcp.dstpt) { - // Find an active TCB - for (nIndexTCB = 0; nIndexTCB < MAX_TCBS_ALLOWED; nIndexTCB++) { - auto *pTCB = &s_Port[nIndexPort].TCB[nIndexTCB]; - if (pTCB->state != STATE_LISTEN) { - if ((pTCB->nRemotePort == pTcp->tcp.srcpt) && (memcmp(pTCB->remoteIp, pTcp->ip4.src, IPv4_ADDR_LEN) == 0)) { - break; - } - } - } - - if (nIndexTCB == MAX_TCBS_ALLOWED) { - // Find an available TCB - for (nIndexTCB = 0; nIndexTCB < MAX_TCBS_ALLOWED; nIndexTCB++) { - auto *pTCB = &s_Port[nIndexPort].TCB[nIndexTCB]; - if (pTCB->state == STATE_LISTEN) { - break; - } - } - - if (nIndexTCB == MAX_TCBS_ALLOWED) { - DEBUG_PUTS("MAX_TCB_ALLOWED -> Force retransmission"); - DEBUG_EXIT - return; - } - } - - break; - } - } + find_tcb(pTcp, nIndexPort, nIndexTCB); + DEBUG_PRINTF("nIndexPort=%u, nIndexTCB=%u", nIndexPort, nIndexTCB); const auto nDataOffset = offset2octets(pTcp->tcp.offset); // https://www.rfc-editor.org/rfc/rfc9293.html#name-closed-state // CLOSED (i.e., TCB does not exist) if (nIndexPort == TCP_MAX_PORTS_ALLOWED) { - DEBUG_PUTS("TCP_MAX_PORTS_ALLOWED"); struct tcb TCB; - memset(&TCB, 0, sizeof(struct tcb)); + std::memset(&TCB, 0, sizeof(struct tcb)); TCB.nLocalPort = pTcp->tcp.dstpt; - memcpy(TCB.localIp, pTcp->ip4.dst, IPv4_ADDR_LEN); + std::memcpy(TCB.localIp, pTcp->ip4.dst, IPv4_ADDR_LEN); TCB.nRemotePort = pTcp->tcp.srcpt; - memcpy(TCB.remoteIp, pTcp->ip4.src, IPv4_ADDR_LEN); - memcpy(TCB.remoteEthAddr, pTcp->ether.src, ETH_ADDR_LEN); + std::memcpy(TCB.remoteIp, pTcp->ip4.src, IPv4_ADDR_LEN); + std::memcpy(TCB.remoteEthAddr, pTcp->ether.src, ETH_ADDR_LEN); _bswap32(pTcp); scan_options(pTcp, &TCB, nDataOffset); send_reset(pTcp, &TCB); + DEBUG_PUTS("TCP_MAX_PORTS_ALLOWED"); DEBUG_EXIT return; } @@ -649,19 +670,6 @@ src/net/tcp.cpp:871:31: error: 'nIndexTCB' may be used uninitialized in this fun pTcp->tcp.window = __builtin_bswap16(pTcp->tcp.window); pTcp->tcp.urgent = __builtin_bswap16(pTcp->tcp.urgent); - DEBUG_PRINTF("%c%c%c%c%c%c SEQ=%u, ACK=%u, tcplen=%u, data_offset=%u, data_length=%u", - pTcp->tcp.control & Control::URG ? 'U' : '-', - pTcp->tcp.control & Control::ACK ? 'A' : '-', - pTcp->tcp.control & Control::PSH ? 'P' : '-', - pTcp->tcp.control & Control::RST ? 'R' : '-', - pTcp->tcp.control & Control::SYN ? 'S' : '-', - pTcp->tcp.control & Control::FIN ? 'F' : '-', - _get_seqnum(pTcp), - _get_acknum(pTcp), - tcplen, - nDataOffset, - nDataLength); - SendInfo sendInfo; const auto SEG_LEN = nDataLength; @@ -691,11 +699,11 @@ src/net/tcp.cpp:871:31: error: 'nIndexTCB' may be used uninitialized in this fun // https://www.rfc-editor.org/rfc/rfc9293.html#name-listen-state if (pTCB->state == STATE_LISTEN) { - memcpy(pTCB->localIp, pTcp->ip4.dst, IPv4_ADDR_LEN); + std::memcpy(pTCB->localIp, pTcp->ip4.dst, IPv4_ADDR_LEN); pTCB->nRemotePort = pTcp->tcp.srcpt; - memcpy(pTCB->remoteIp, pTcp->ip4.src, IPv4_ADDR_LEN); - memcpy(pTCB->remoteEthAddr, pTcp->ether.src, ETH_ADDR_LEN); + std::memcpy(pTCB->remoteIp, pTcp->ip4.src, IPv4_ADDR_LEN); + std::memcpy(pTCB->remoteEthAddr, pTcp->ether.src, ETH_ADDR_LEN); // First, check for a RST // An incoming RST should be ignored. @@ -711,6 +719,7 @@ src/net/tcp.cpp:871:31: error: 'nIndexTCB' may be used uninitialized in this fun if (pTcp->tcp.control & Control::ACK) { send_reset(pTcp, pTCB); + DEBUG_PUTS("pTcp->tcp.control & Control::ACK"); DEBUG_EXIT return; } @@ -848,8 +857,9 @@ src/net/tcp.cpp:871:31: error: 'nIndexTCB' may be used uninitialized in this fun return; } - DEBUG_PUTS("_send_reset"); send_reset(pTcp, pTCB); + + DEBUG_PUTS("pTcp->tcp.control & Control::SYN"); } /* fifth check the ACK field, *//* Page 72 */ @@ -874,8 +884,9 @@ src/net/tcp.cpp:871:31: error: 'nIndexTCB' may be used uninitialized in this fun return; } else { // - DEBUG_PUTS("_send_reset"); send_reset(pTcp, pTCB); + + DEBUG_PUTS(""); } break; case STATE_ESTABLISHED: @@ -1083,7 +1094,7 @@ int tcp_begin(const uint16_t nLocalPort) { if (s_Port[i].nLocalPort == 0) { s_Port[i].nLocalPort = nLocalPort; - for (uint32_t nIndexTCB = 0; nIndexTCB < MAX_TCBS_ALLOWED; nIndexTCB++) { + for (uint32_t nIndexTCB = 0; nIndexTCB < TCP_MAX_TCBS_ALLOWED; nIndexTCB++) { // create transmission control block's (TCB) _init_tcb(&s_Port[i].TCB[nIndexTCB], nLocalPort); } @@ -1125,15 +1136,17 @@ uint16_t tcp_read(const int32_t nHandleListen, const uint8_t **pData, uint32_t & return pQueueEntry->nSize; } -void tcp_write(const int32_t nHandleListen, const uint8_t *pBuffer, uint16_t nLength, uint32_t nHandleConnection) { - assert(nHandleListen >= 0); - assert(nHandleListen < TCP_MAX_PORTS_ALLOWED); - assert(pBuffer != nullptr); - assert(nHandleConnection < MAX_TCBS_ALLOWED); +static void _write(struct tcb *pTCB, const uint8_t *pBuffer, const uint32_t nLength, const bool isLastSegment) { + assert(nLength != 0); + assert(nLength <= static_cast(TCP_DATA_SIZE)); - nLength = std::min(nLength, static_cast(TCP_DATA_SIZE)); + DEBUG_PRINTF("nLength=%u, pTCB->SND.WND=%u", nLength, pTCB->SND.WND); - auto *pTCB = &s_Port[nHandleListen].TCB[nHandleConnection]; + if (nLength > pTCB->SND.WND) { + console_error("Retry or queue the data for later transmission\n"); + // TODO retry or queue the data for later transmission. + return; + } pTCB->TX.data = const_cast(pBuffer); pTCB->TX.size = nLength; @@ -1141,14 +1154,38 @@ void tcp_write(const int32_t nHandleListen, const uint8_t *pBuffer, uint16_t nLe struct SendInfo info; info.SEQ = pTCB->SND.NXT; info.ACK = pTCB->RCV.NXT; - info.CTL = Control::ACK | Control::PSH; + info.CTL = Control::ACK; + if (isLastSegment) { + info.CTL |= Control::PSH; + } send_package(pTCB, info); pTCB->TX.data = nullptr; pTCB->TX.size = 0; - pTCB->SND.NXT += nLength; + pTCB->SND.NXT += nLength; + pTCB->SND.WND -= nLength; } +void tcp_write(const int32_t nHandleListen, const uint8_t *pBuffer, uint32_t nLength, uint32_t nHandleConnection) { + assert(nHandleListen >= 0); + assert(nHandleListen < TCP_MAX_PORTS_ALLOWED); + assert(pBuffer != nullptr); + assert(nHandleConnection < TCP_MAX_TCBS_ALLOWED); + + auto *pTCB = &s_Port[nHandleListen].TCB[nHandleConnection]; + assert(pTCB != nullptr); + + const auto *p = pBuffer; + + while (nLength > 0) { + const auto nWriteLength = (nLength > TCP_DATA_SIZE) ? TCP_DATA_SIZE : nLength; + const bool isLastSegment = (nLength < TCP_DATA_SIZE); + _write(pTCB, p, nWriteLength, isLastSegment); + p += nWriteLength; + nLength -= nWriteLength; + } +} +} // namespace net // <--- diff --git a/lib-network/src/net/udp.cpp b/lib-network/src/net/udp.cpp index 5def0c6a..f34f7688 100644 --- a/lib-network/src/net/udp.cpp +++ b/lib-network/src/net/udp.cpp @@ -2,7 +2,7 @@ * @file udp.cpp * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,50 +23,51 @@ * THE SOFTWARE. */ +#if defined (DEBUG_NET_UDP) +# undef NDEBUG +#endif + +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif + #include #include -#include #include #include +#include "../../config/net_config.h" + +#include "net/protocol/udp.h" + #include "net.h" #include "net_private.h" #include "net_memcpy.h" -#include "../../config/net_config.h" +#include "debug.h" + +namespace net { +namespace globals { +extern uint32_t nBroadcastMask; +} // namespace globals struct data_entry { uint32_t from_ip; + uint32_t size; uint16_t from_port; - uint16_t size; uint8_t data[UDP_DATA_SIZE]; } ALIGNED; -typedef union pcast32 { - uint32_t u32; - uint8_t u8[4]; -} _pcast32; - static uint16_t s_Port[UDP_MAX_PORTS_ALLOWED] SECTION_NETWORK ALIGNED; static struct data_entry s_data[UDP_MAX_PORTS_ALLOWED] SECTION_NETWORK ALIGNED; static struct t_udp s_send_packet SECTION_NETWORK ALIGNED; static uint16_t s_id SECTION_NETWORK ALIGNED; static uint8_t s_multicast_mac[ETH_ADDR_LEN] SECTION_NETWORK ALIGNED; -namespace net { -namespace globals { -extern struct IpInfo ipInfo; -extern uint32_t nBroadcastMask; -extern uint32_t nOnNetworkMask; -extern uint8_t macAddress[ETH_ADDR_LEN]; -} // namespace globals -} // namespace net - void udp_set_ip() { - _pcast32 src; - - src.u32 = net::globals::ipInfo.ip.addr; - memcpy(s_send_packet.ip4.src, src.u8, IPv4_ADDR_LEN); + net::memcpy_ip(s_send_packet.ip4.src, net::globals::netif_default.ip.addr); } void __attribute__((cold)) udp_init() { @@ -75,7 +76,7 @@ void __attribute__((cold)) udp_init() { s_multicast_mac[1] = 0x00; s_multicast_mac[2] = 0x5E; // Ethernet - memcpy(s_send_packet.ether.src, net::globals::macAddress, ETH_ADDR_LEN); + std::memcpy(s_send_packet.ether.src, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); s_send_packet.ether.type = __builtin_bswap16(ETHER_TYPE_IPv4); // IPv4 s_send_packet.ip4.ver_ihl = 0x45; @@ -107,21 +108,86 @@ __attribute__((hot)) void udp_handle(struct t_udp *pUdp) { const auto nDataLength = static_cast(__builtin_bswap16(pUdp->udp.len) - UDP_HEADER_SIZE); const auto i = std::min(static_cast(UDP_DATA_SIZE), nDataLength); - net_memcpy(p_queue_entry->data, pUdp->udp.data, i); + net::memcpy(p_queue_entry->data, pUdp->udp.data, i); - _pcast32 src; - - memcpy(src.u8, pUdp->ip4.src, IPv4_ADDR_LEN); - p_queue_entry->from_ip = src.u32; + p_queue_entry->from_ip = net::memcpy_ip(pUdp->ip4.src); p_queue_entry->from_port = __builtin_bswap16(pUdp->udp.source_port); p_queue_entry->size = static_cast(i); return; + } + } + DEBUG_PRINTF(IPSTR ":%d[%x] " MACSTR, pUdp->ip4.src[0],pUdp->ip4.src[1],pUdp->ip4.src[2],pUdp->ip4.src[3], nDestinationPort, nDestinationPort, MAC2STR(pUdp->ether.dst)); +} + +template +static void udp_send_implementation(int nIndex, const uint8_t *pData, uint32_t nSize, uint32_t nRemoteIp, uint16_t nRemotePort) { + assert(nIndex >= 0); + assert(nIndex < UDP_MAX_PORTS_ALLOWED); + assert(s_Port[nIndex] != 0); + + //IPv4 + s_send_packet.ip4.id = s_id++; + s_send_packet.ip4.len = __builtin_bswap16(static_cast(nSize + IPv4_UDP_HEADERS_SIZE)); + s_send_packet.ip4.chksum = 0; + + //UDP + s_send_packet.udp.source_port = __builtin_bswap16( s_Port[nIndex]); + s_send_packet.udp.destination_port = __builtin_bswap16(nRemotePort); + s_send_packet.udp.len = __builtin_bswap16(static_cast(nSize + UDP_HEADER_SIZE)); + + nSize = std::min(static_cast(UDP_DATA_SIZE), nSize); + + net::memcpy(s_send_packet.udp.data, pData, nSize); + + if (nRemoteIp == network::IP4_BROADCAST) { + memset(s_send_packet.ether.dst, 0xFF, ETH_ADDR_LEN); + memset(s_send_packet.ip4.dst, 0xFF, IPv4_ADDR_LEN); + } else if ((nRemoteIp & net::globals::nBroadcastMask) == net::globals::nBroadcastMask) { + memset(s_send_packet.ether.dst, 0xFF, ETH_ADDR_LEN); + net::memcpy_ip(s_send_packet.ip4.dst, nRemoteIp); + } else { + if ((nRemoteIp & 0xF0) == 0xE0) { // Multicast, we know the MAC Address + typedef union pcast32 { + uint32_t u32; + uint8_t u8[4]; + } _pcast32; + _pcast32 multicast_ip; + + multicast_ip.u32 = nRemoteIp; + s_multicast_mac[3] = multicast_ip.u8[1] & 0x7F; + s_multicast_mac[4] = multicast_ip.u8[2]; + s_multicast_mac[5] = multicast_ip.u8[3]; + + std::memcpy(s_send_packet.ether.dst, s_multicast_mac, ETH_ADDR_LEN); + net::memcpy_ip(s_send_packet.ip4.dst, nRemoteIp); + } else { + if (S == net::arp::EthSend::IS_NORMAL) { + net::arp_send(&s_send_packet, nSize + UDP_PACKET_HEADERS_SIZE, nRemoteIp); + } +#if defined CONFIG_ENET_ENABLE_PTP + else if (S == net::arp::EthSend::IS_TIMESTAMP) { + net::arp_send_timestamp(&s_send_packet, nSize + UDP_PACKET_HEADERS_SIZE, nRemoteIp); + } +#endif + return; } } - DEBUG_PRINTF(IPSTR ":%d[%x]", pUdp->ip4.src[0],pUdp->ip4.src[1],pUdp->ip4.src[2],pUdp->ip4.src[3], nDestinationPort, nDestinationPort); +#if !defined (CHECKSUM_BY_HARDWARE) + s_send_packet.ip4.chksum = net_chksum(reinterpret_cast(&s_send_packet.ip4), sizeof(s_send_packet.ip4)); +#endif + + if (S == net::arp::EthSend::IS_NORMAL) { + emac_eth_send(reinterpret_cast(&s_send_packet), nSize + UDP_PACKET_HEADERS_SIZE); + } +#if defined CONFIG_ENET_ENABLE_PTP + else if (S == net::arp::EthSend::IS_TIMESTAMP) { + emac_eth_send_timestamp(reinterpret_cast(&s_send_packet), nSize); + } +#endif + return; } // --> @@ -163,7 +229,7 @@ int udp_end(uint16_t nLocalPort) { return -1; } -uint16_t udp_recv1(int nIndex, uint8_t *pData, uint16_t nSize, uint32_t *pFromIp, uint16_t *FromPort) { +uint32_t udp_recv1(int nIndex, uint8_t *pData, uint32_t nSize, uint32_t *pFromIp, uint16_t *FromPort) { assert(nIndex >= 0); assert(nIndex < UDP_MAX_PORTS_ALLOWED); @@ -174,7 +240,7 @@ uint16_t udp_recv1(int nIndex, uint8_t *pData, uint16_t nSize, uint32_t *pFromIp auto *p_data = &s_data[nIndex]; const auto i = std::min(nSize, p_data->size); - net_memcpy(pData, p_data->data, i); + net::memcpy(pData, p_data->data, i); *pFromIp = p_data->from_ip; *FromPort = p_data->from_port; @@ -184,104 +250,35 @@ uint16_t udp_recv1(int nIndex, uint8_t *pData, uint16_t nSize, uint32_t *pFromIp return i; } -uint16_t udp_recv2(int nIndex, const uint8_t **pData, uint32_t *pFromIp, uint16_t *pFromPort) { +uint32_t udp_recv2(int nIndex, const uint8_t **pData, uint32_t *pFromIp, uint16_t *pFromPort) { assert(nIndex >= 0); assert(nIndex < UDP_MAX_PORTS_ALLOWED); - if (__builtin_expect((s_data[nIndex].size == 0), 1)) { + auto &p_data = s_data[nIndex]; + + if (__builtin_expect((p_data.size == 0), 1)) { return 0; } - auto *p_data = &s_data[nIndex]; - - *pData = p_data->data; - *pFromIp = p_data->from_ip; - *pFromPort = p_data->from_port; + *pData = p_data.data; + *pFromIp = p_data.from_ip; + *pFromPort = p_data.from_port; - const auto nSize = p_data->size; + const auto nSize = p_data.size; - p_data->size = 0; + p_data.size = 0; return nSize; } -int udp_send(int nIndex, const uint8_t *pData, uint16_t nSize, uint32_t RemoteIp, uint16_t RemotePort) { - assert(nIndex >= 0); - assert(nIndex < UDP_MAX_PORTS_ALLOWED); - _pcast32 dst; - - if (__builtin_expect ((s_Port[nIndex] == 0), 0)) { - DEBUG_PUTS("ports_allowed[idx] == 0"); - return -1; - } - - if (RemoteIp == IPv4_BROADCAST) { - memset(s_send_packet.ether.dst, 0xFF, ETH_ADDR_LEN); - memset(s_send_packet.ip4.dst, 0xFF, IPv4_ADDR_LEN); - } else if ((RemoteIp & net::globals::nBroadcastMask) == net::globals::nBroadcastMask) { - memset(s_send_packet.ether.dst, 0xFF, ETH_ADDR_LEN); - dst.u32 = RemoteIp; - memcpy(s_send_packet.ip4.dst, dst.u8, IPv4_ADDR_LEN); - } else { - if ((RemoteIp & 0xE0) == 0xE0) { // Multicast, we know the MAC Address - _pcast32 multicast_ip; - - multicast_ip.u32 = RemoteIp; - - s_multicast_mac[3] = multicast_ip.u8[1] & 0x7F; - s_multicast_mac[4] = multicast_ip.u8[2]; - s_multicast_mac[5] = multicast_ip.u8[3]; - - memcpy(s_send_packet.ether.dst, s_multicast_mac, ETH_ADDR_LEN); - - dst.u32 = RemoteIp; - memcpy(s_send_packet.ip4.dst, dst.u8, IPv4_ADDR_LEN); - } else { - if (__builtin_expect((net::globals::nOnNetworkMask != (RemoteIp & net::globals::nOnNetworkMask)), 0)) { - if (net::globals::ipInfo.gw.addr == arp_cache_lookup(net::globals::ipInfo.gw.addr, s_send_packet.ether.dst)) { - dst.u32 = RemoteIp; - memcpy(s_send_packet.ip4.dst, dst.u8, IPv4_ADDR_LEN); - } else { -#ifndef NDEBUG - console_error("ARP lookup failed -> default gateway :"); - printf(IPSTR " [%d]\n", IP2STR(RemoteIp), s_Port[nIndex]); -#endif - return -3; - } - } else { - if (RemoteIp == arp_cache_lookup(RemoteIp, s_send_packet.ether.dst)) { - dst.u32 = RemoteIp; - memcpy(s_send_packet.ip4.dst, dst.u8, IPv4_ADDR_LEN); - } else { -#ifndef NDEBUG - console_error("ARP lookup failed: "); - printf(IPSTR "\n", IP2STR(RemoteIp)); -#endif - return -2; - } - } - } - } - - //IPv4 - s_send_packet.ip4.id = s_id; - s_send_packet.ip4.len = __builtin_bswap16((nSize + IPv4_UDP_HEADERS_SIZE)); - s_send_packet.ip4.chksum = 0; -#if !defined (CHECKSUM_BY_HARDWARE) - s_send_packet.ip4.chksum = net_chksum(reinterpret_cast(&s_send_packet.ip4), sizeof(s_send_packet.ip4)); -#endif - //UDP - s_send_packet.udp.source_port = __builtin_bswap16( s_Port[nIndex]); - s_send_packet.udp.destination_port = __builtin_bswap16(RemotePort); - s_send_packet.udp.len = __builtin_bswap16((nSize + UDP_HEADER_SIZE)); - - net_memcpy(s_send_packet.udp.data, pData, std::min(static_cast(UDP_DATA_SIZE), nSize)); - - emac_eth_send(reinterpret_cast(&s_send_packet), nSize + UDP_PACKET_HEADERS_SIZE); - - s_id++; - - return 0; +void udp_send(int nIndex, const uint8_t *pData, uint32_t nSize, uint32_t nRemoteIp, uint16_t nRemotePort) { + udp_send_implementation(nIndex, pData, nSize, nRemoteIp, nRemotePort); } +#if defined CONFIG_ENET_ENABLE_PTP +void udp_send_timestamp(int nIndex, const uint8_t *pData, uint32_t nSize, uint32_t nRemoteIp, uint16_t nRemotePort) { + udp_send_implementation(nIndex, pData, nSize, nRemoteIp, nRemotePort); +} +#endif +} // namespace net // <--- diff --git a/lib-network/src/networkconst.cpp b/lib-network/src/networkconst.cpp index b70872ef..8775c8d6 100644 --- a/lib-network/src/networkconst.cpp +++ b/lib-network/src/networkconst.cpp @@ -2,7 +2,7 @@ * @file networkconst.cpp * */ -/* Copyright (C) 2019-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-network/src/params/networkparams.cpp b/lib-network/src/params/networkparams.cpp index 03d4eafb..76c9ebe1 100644 --- a/lib-network/src/params/networkparams.cpp +++ b/lib-network/src/params/networkparams.cpp @@ -2,7 +2,7 @@ * @file networkparams.cpp * */ -/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,6 +36,7 @@ #include "networkparams.h" #include "networkparamsconst.h" + #include "readconfigfile.h" #include "sscan.h" @@ -45,7 +46,7 @@ using namespace networkparams; -NetworkParams::NetworkParams(NetworkParamsStore *pNetworkParamsStore): m_pNetworkParamsStore(pNetworkParamsStore) { +NetworkParams::NetworkParams() { DEBUG_ENTRY memset(&m_Params, 0, sizeof(struct networkparams::Params)); @@ -55,7 +56,7 @@ NetworkParams::NetworkParams(NetworkParamsStore *pNetworkParamsStore): m_pNetwor DEBUG_EXIT } -bool NetworkParams::Load() { +void NetworkParams::Load() { DEBUG_ENTRY m_Params.nSetList = 0; @@ -63,20 +64,15 @@ bool NetworkParams::Load() { ReadConfigFile configfile(NetworkParams::staticCallbackFunction, this); if (configfile.Read(NetworkParamsConst::FILE_NAME)) { - if (m_pNetworkParamsStore != nullptr) { - m_pNetworkParamsStore->Update(&m_Params); - } + NetworkParamsStore::Update(&m_Params); } else #endif - if (m_pNetworkParamsStore != nullptr) { - m_pNetworkParamsStore->Copy(&m_Params); - } else { - DEBUG_EXIT - return false; - } + NetworkParamsStore::Copy(&m_Params); +#ifndef NDEBUG + Dump(); +#endif DEBUG_EXIT - return true; } void NetworkParams::Load(const char *pBuffer, uint32_t nLength) { @@ -91,9 +87,11 @@ void NetworkParams::Load(const char *pBuffer, uint32_t nLength) { config.Read(pBuffer, nLength); - assert(m_pNetworkParamsStore != nullptr); - m_pNetworkParamsStore->Update(&m_Params); + NetworkParamsStore::Update(&m_Params); +#ifndef NDEBUG + Dump(); +#endif DEBUG_EXIT } @@ -145,8 +143,13 @@ void NetworkParams::callbackFunction(const char *pLine) { } if (Sscan::IpAddress(pLine, NetworkParamsConst::DEFAULT_GATEWAY, nValue32) == Sscan::OK) { - m_Params.nGatewayIp = nValue32; - m_Params.nSetList |= networkparams::Mask::DEFAULT_GATEWAY; + if (nValue32 != 0) { + m_Params.nSetList |= networkparams::Mask::DEFAULT_GATEWAY; + m_Params.nGatewayIp = nValue32; + } else { + m_Params.nSetList &= ~networkparams::Mask::DEFAULT_GATEWAY; + } + return; } @@ -158,8 +161,6 @@ void NetworkParams::callbackFunction(const char *pLine) { return; } - -#if !defined(DISABLE_RTC) if (Sscan::IpAddress(pLine, NetworkParamsConst::NTP_SERVER, nValue32) == Sscan::OK) { if (nValue32 != 0) { m_Params.nSetList |= networkparams::Mask::NTP_SERVER; @@ -170,21 +171,6 @@ void NetworkParams::callbackFunction(const char *pLine) { return; } - float fValue; - - if (Sscan::Float(pLine, NetworkParamsConst::NTP_UTC_OFFSET, fValue) == Sscan::OK) { - // https://en.wikipedia.org/wiki/List_of_UTC_time_offsets - if ((static_cast(fValue) >= -12) && (static_cast(fValue) <= 14) && (static_cast(fValue) != 0)) { - m_Params.fNtpUtcOffset = fValue; - m_Params.nSetList |= networkparams::Mask::NTP_UTC_OFFSET; - } else { - m_Params.fNtpUtcOffset = 0; - m_Params.nSetList &= ~networkparams::Mask::NTP_UTC_OFFSET; - } - return; - } -#endif - #if defined (ESP8266) if (Sscan::IpAddress(pLine, NetworkParamsConst::NAME_SERVER, nValue32) == Sscan::OK) { m_Params.nNameServerIp = nValue32; @@ -223,8 +209,7 @@ void NetworkParams::Builder(const struct networkparams::Params *ptNetworkParams, if (ptNetworkParams != nullptr) { memcpy(&m_Params, ptNetworkParams, sizeof(struct networkparams::Params)); } else { - assert(m_pNetworkParamsStore != nullptr); - m_pNetworkParamsStore->Copy(&m_Params); + NetworkParamsStore::Copy(&m_Params); } PropertiesBuilder builder(NetworkParamsConst::FILE_NAME, pBuffer, nLength); @@ -259,14 +244,27 @@ void NetworkParams::Builder(const struct networkparams::Params *ptNetworkParams, #endif builder.Add(NetworkParamsConst::HOSTNAME, m_Params.aHostName, isMaskSet(networkparams::Mask::HOSTNAME)); -#if !defined(DISABLE_RTC) builder.AddComment("NTP Server"); builder.AddIpAddress(NetworkParamsConst::NTP_SERVER, m_Params.nNtpServerIp, isMaskSet(networkparams::Mask::NTP_SERVER)); - builder.Add(NetworkParamsConst::NTP_UTC_OFFSET, m_Params.fNtpUtcOffset, isMaskSet(networkparams::Mask::NTP_UTC_OFFSET)); -#endif nSize = builder.GetSize(); DEBUG_PRINTF("nSize=%d", nSize); DEBUG_EXIT } + +void NetworkParams::Dump() { + printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, NetworkParamsConst::FILE_NAME); + + printf(" %s=%d [%s]\n", NetworkParamsConst::USE_DHCP, static_cast(m_Params.bIsDhcpUsed), m_Params.bIsDhcpUsed != 0 ? "Yes" : "No"); + printf(" %s=" IPSTR "\n", NetworkParamsConst::IP_ADDRESS, IP2STR(m_Params.nLocalIp)); + printf(" %s=" IPSTR "\n", NetworkParamsConst::NET_MASK, IP2STR(m_Params.nNetmask)); + printf(" %s=" IPSTR "\n", NetworkParamsConst::DEFAULT_GATEWAY, IP2STR(m_Params.nGatewayIp)); + +#if defined (ESP8266) + printf(" %s=" IPSTR "\n", NetworkParamsConst::NAME_SERVER, IP2STR(m_Params.nNameServerIp)); +#endif + + printf(" %s=%s\n", NetworkParamsConst::HOSTNAME, m_Params.aHostName); + printf(" %s=" IPSTR "\n", NetworkParamsConst::NTP_SERVER, IP2STR(m_Params.nNtpServerIp)); +} diff --git a/lib-network/src/networkparamsconst.cpp b/lib-network/src/params/networkparamsconst.cpp old mode 100644 new mode 100755 similarity index 93% rename from lib-network/src/networkparamsconst.cpp rename to lib-network/src/params/networkparamsconst.cpp index 50811878..ae28a8d7 --- a/lib-network/src/networkparamsconst.cpp +++ b/lib-network/src/params/networkparamsconst.cpp @@ -2,7 +2,7 @@ * @file networkparamsconst.cpp * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,7 +36,6 @@ const char NetworkParamsConst::DEFAULT_GATEWAY[] = "default_gateway"; const char NetworkParamsConst::HOSTNAME[] = "hostname"; const char NetworkParamsConst::NTP_SERVER[] = "ntp_server"; -const char NetworkParamsConst::NTP_UTC_OFFSET[] = "ntp_utc_offset"; #if defined (ESP8266) const char NetworkParamsConst::NAME_SERVER[] = "name_server"; diff --git a/lib-network/src/params/networkparamsdump.cpp b/lib-network/src/params/networkparamsdump.cpp deleted file mode 100644 index ada0652d..00000000 --- a/lib-network/src/params/networkparamsdump.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file networkparamsdump.cpp - * - */ -/* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#if !defined(__clang__) // Needed for compiling on MacOS -# pragma GCC push_options -# pragma GCC optimize ("Os") -#endif - -#include - -#include "network.h" -#include "networkparams.h" -#include "networkparamsconst.h" - -#include "debug.h" - -void NetworkParams::Dump() { -#ifndef NDEBUG - printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, NetworkParamsConst::FILE_NAME); - - debug_print_bits(m_Params.nSetList); - - printf(" %s=%d [%s]\n", NetworkParamsConst::USE_DHCP, static_cast(m_Params.bIsDhcpUsed), m_Params.bIsDhcpUsed != 0 ? "Yes" : "No"); - printf(" %s=" IPSTR "\n", NetworkParamsConst::IP_ADDRESS, IP2STR(m_Params.nLocalIp)); - printf(" %s=" IPSTR "\n", NetworkParamsConst::NET_MASK, IP2STR(m_Params.nNetmask)); - -#if defined (ESP8266) - printf(" %s=" IPSTR "\n", NetworkParamsConst::DEFAULT_GATEWAY, IP2STR(m_Params.nGatewayIp)); - printf(" %s=" IPSTR "\n", NetworkParamsConst::NAME_SERVER, IP2STR(m_Params.nNameServerIp)); -#endif - - printf(" %s=%s\n", NetworkParamsConst::HOSTNAME, m_Params.aHostName); - printf(" %s=" IPSTR "\n", NetworkParamsConst::NTP_SERVER, IP2STR(m_Params.nNtpServerIp)); - printf(" %s=%1.1f\n", NetworkParamsConst::NTP_UTC_OFFSET, m_Params.fNtpUtcOffset); -#endif -} diff --git a/lib-osc/.cproject b/lib-osc/.cproject new file mode 100755 index 00000000..9b0f24de --- /dev/null +++ b/lib-osc/.cproject @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib-c++/.project b/lib-osc/.project old mode 100644 new mode 100755 similarity index 94% rename from lib-c++/.project rename to lib-osc/.project index bb75ddd3..573102de --- a/lib-c++/.project +++ b/lib-osc/.project @@ -1,6 +1,6 @@ - lib-c++ + lib-osc diff --git a/lib-rdmdiscovery/.settings/language.settings.xml b/lib-osc/.settings/language.settings.xml old mode 100644 new mode 100755 similarity index 93% rename from lib-rdmdiscovery/.settings/language.settings.xml rename to lib-osc/.settings/language.settings.xml index 4d2bde8f..a20879f9 --- a/lib-rdmdiscovery/.settings/language.settings.xml +++ b/lib-osc/.settings/language.settings.xml @@ -1,12 +1,12 @@ - - - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/lib-osc/.settings/org.eclipse.cdt.codan.core.prefs b/lib-osc/.settings/org.eclipse.cdt.codan.core.prefs new file mode 100755 index 00000000..a007028e --- /dev/null +++ b/lib-osc/.settings/org.eclipse.cdt.codan.core.prefs @@ -0,0 +1,107 @@ +eclipse.preferences.version=1 +org.eclipse.cdt.codan.checkers.errnoreturn=Warning +org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false} +org.eclipse.cdt.codan.checkers.errreturnvalue=Error +org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"} +org.eclipse.cdt.codan.checkers.localvarreturn=Warning +org.eclipse.cdt.codan.checkers.localvarreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Returning the address of a local variable\\")"} +org.eclipse.cdt.codan.checkers.nocommentinside=Error +org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"} +org.eclipse.cdt.codan.checkers.nolinecomment=Error +org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"} +org.eclipse.cdt.codan.checkers.noreturn=Error +org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false} +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"} +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"} +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"} +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"} +org.eclipse.cdt.codan.internal.checkers.BlacklistProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.BlacklistProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function or method is blacklisted\\")",blacklist\=>()} +org.eclipse.cdt.codan.internal.checkers.CStyleCastProblem=Warning +org.eclipse.cdt.codan.internal.checkers.CStyleCastProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"C-Style cast instead of C++ cast\\")",checkMacro\=>true} +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false,enable_fallthrough_quickfix_param\=>false} +org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning +org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"} +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true} +org.eclipse.cdt.codan.internal.checkers.CopyrightProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.CopyrightProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Lack of copyright information\\")",regex\=>".*Copyright.*"} +org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem=Error +org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid 'decltype(auto)' specifier\\")"} +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.FloatCompareProblem=Warning +org.eclipse.cdt.codan.internal.checkers.FloatCompareProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Direct float comparison\\")"} +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.GotoStatementProblem=Warning +org.eclipse.cdt.codan.internal.checkers.GotoStatementProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Goto statement used\\")"} +org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error +org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"} +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"} +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"} +org.eclipse.cdt.codan.internal.checkers.MagicNumberProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MagicNumberProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Avoid magic numbers\\")",checkArray\=>true,checkOperatorParen\=>true,exceptions\=>(1,0,-1,2,1.0,0.0,-1.0)} +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"} +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.MissCaseProblem=Warning +org.eclipse.cdt.codan.internal.checkers.MissCaseProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing cases in switch\\")"} +org.eclipse.cdt.codan.internal.checkers.MissDefaultProblem=Warning +org.eclipse.cdt.codan.internal.checkers.MissDefaultProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing default in switch\\")",defaultWithAllEnums\=>false} +org.eclipse.cdt.codan.internal.checkers.MissReferenceProblem=Warning +org.eclipse.cdt.codan.internal.checkers.MissReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing reference return value in assignment operator\\")"} +org.eclipse.cdt.codan.internal.checkers.MissSelfCheckProblem=Warning +org.eclipse.cdt.codan.internal.checkers.MissSelfCheckProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing self check in assignment operator\\")"} +org.eclipse.cdt.codan.internal.checkers.MultipleDeclarationsProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MultipleDeclarationsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Multiple variable declaration\\")"} +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"} +org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error +org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"} +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"} +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"} +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"} +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"} +org.eclipse.cdt.codan.internal.checkers.ShallowCopyProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ShallowCopyProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Miss copy constructor or assignment operator\\")",onlynew\=>false} +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.StaticVariableInHeaderProblem=Warning +org.eclipse.cdt.codan.internal.checkers.StaticVariableInHeaderProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Static variable in header file\\")"} +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false} +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false} +org.eclipse.cdt.codan.internal.checkers.SymbolShadowingProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.SymbolShadowingProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol shadowing\\")",paramFuncParameters\=>true} +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")} +org.eclipse.cdt.codan.internal.checkers.UsingInHeaderProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.UsingInHeaderProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Using directive in header\\")"} +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.VirtualMethodCallProblem=Error +org.eclipse.cdt.codan.internal.checkers.VirtualMethodCallProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Virtual method call in constructor/destructor\\")"} diff --git a/gd32_rdm_responder/.settings/org.eclipse.cdt.core.prefs b/lib-osc/.settings/org.eclipse.cdt.core.prefs old mode 100644 new mode 100755 similarity index 100% rename from gd32_rdm_responder/.settings/org.eclipse.cdt.core.prefs rename to lib-osc/.settings/org.eclipse.cdt.core.prefs diff --git a/lib-debug/.settings/org.eclipse.core.resources.prefs b/lib-osc/.settings/org.eclipse.core.resources.prefs similarity index 100% rename from lib-debug/.settings/org.eclipse.core.resources.prefs rename to lib-osc/.settings/org.eclipse.core.resources.prefs diff --git a/lib-rdmresponder/Makefile.GD32 b/lib-osc/Makefile.GD32 old mode 100644 new mode 100755 similarity index 86% rename from lib-rdmresponder/Makefile.GD32 rename to lib-osc/Makefile.GD32 index 5f6d2d93..710ad717 --- a/lib-rdmresponder/Makefile.GD32 +++ b/lib-osc/Makefile.GD32 @@ -2,5 +2,7 @@ DEFINES=NDEBUG EXTRA_INCLUDES= +EXTRA_SRCDIR= + include Rules.mk include ../firmware-template-gd32/lib/Rules.mk \ No newline at end of file diff --git a/lib-osc/Rules.mk b/lib-osc/Rules.mk new file mode 100755 index 00000000..20152ce3 --- /dev/null +++ b/lib-osc/Rules.mk @@ -0,0 +1,24 @@ +$(info [${CURDIR}]) +$(info $$MAKE_FLAGS [${MAKE_FLAGS}]) + +EXTRA_INCLUDES+=../lib-display/include ../lib-properties/include ../lib-network/include + +ifneq ($(MAKE_FLAGS),) + ifneq (,$(findstring NODE_OSC_CLIENT,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=src/client + DO_INCLUDE=1 + endif + ifneq (,$(findstring NODE_OSC_SERVER,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=src/server + EXTRA_INCLUDES+=../lib-lightset/include + DO_INCLUDE=1 + endif +else + EXTRA_SRCDIR+=src/client + EXTRA_SRCDIR+=src/server + DO_INCLUDE=1 +endif + +ifdef DO_INCLUDE + EXTRA_INCLUDES+=../lib-display/include ../lib-properties/include ../lib-network/include +endif \ No newline at end of file diff --git a/lib-osc/include/osc.h b/lib-osc/include/osc.h new file mode 100644 index 00000000..156f45b2 --- /dev/null +++ b/lib-osc/include/osc.h @@ -0,0 +1,93 @@ +/** + * @file osc.h + * + */ +/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef OSC_H_ +#define OSC_H_ + +#include + +namespace osc { +namespace validate { +static constexpr auto INVALID_SIZE = 1; +static constexpr auto NOT_TERMINATED = 2; +static constexpr auto NONE_ZERO_IN_PADDING = 3; +} // namespace validate +namespace type { +/* basic OSC types */ +/* 32 bit signed integer. */ +static constexpr char INT32 = 'i'; +/* 32 bit IEEE-754 float. */ +static constexpr char FLOAT = 'f'; +/* Standard C, NULL terminated string. */ +static constexpr char STRING = 's'; +/* OSC binary blob type. */ +static constexpr char BLOB = 'b'; +/* extended OSC types */ +/* 64 bit signed integer. */ +static constexpr char INT64 = 'h'; +/* OSC TimeTag type. */ +static constexpr char TIMETAG = 't'; +/* 64 bit IEEE-754 double. */ +static constexpr char DOUBLE = 'd'; +/* Standard C, NULL terminated, string. Used in systems which distinguish strings and symbols. */ +static constexpr char SYMBOL = 'S'; +/* Standard C, 8 bit, char variable. */ +static constexpr char CHAR = 'c'; +/* A 4 byte MIDI packet. */ +static constexpr char MIDI = 'm'; +/* Symbol representing the value True. */ +static constexpr char TRUE = 'T'; +/* Symbol representing the value False. */ +static constexpr char FALSE = 'F'; +/* Symbol representing the value Nil. */ +static constexpr char NIL = 'N'; +/* Symbol representing the value Infinitum. */ +static constexpr char INFINITUM = 'I'; +/* */ +static constexpr char UNKNOWN = '\0'; +} // namespace type +namespace port { +static constexpr uint16_t DEFAULT_INCOMING = 8000; +static constexpr uint16_t DEFAULT_OUTGOING = 9000; +} // namespace port +} // namespace osc + +extern "C" { +int lo_pattern_match(const char *, const char *); +} + +#include "oscstring.h" + +namespace osc { +inline static char *get_path(void *pPath, unsigned nSize) { + return (string_validate(pPath, nSize) >= 4) ? reinterpret_cast(pPath) : nullptr; +} + +inline static bool is_match(const char *str, const char *p) { + return lo_pattern_match(str, p) == 0 ? false : true; +} +} // namespace osc + +#endif /* OSC_H_ */ diff --git a/lib-rdmdiscovery/include/rdmdiscovery.h b/lib-osc/include/oscblob.h similarity index 57% rename from lib-rdmdiscovery/include/rdmdiscovery.h rename to lib-osc/include/oscblob.h index df7e6f90..fe0346ea 100644 --- a/lib-rdmdiscovery/include/rdmdiscovery.h +++ b/lib-osc/include/oscblob.h @@ -1,8 +1,8 @@ /** - * @file rdmddiscovery.h + * @file oscblob.h * */ -/* Copyright (C) 2017-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,39 +23,48 @@ * THE SOFTWARE. */ -#ifndef RDMDISCOVERY_H_ -#define RDMDISCOVERY_H_ +#ifndef OSCBLOB_H_ +#define OSCBLOB_H_ #include -#include "rdm.h" - -#include "rdmmessage.h" -#include "rdmtod.h" +/* + * OSC-blob + * An int32 size count, followed by that many 8-bit bytes of arbitrary binary data, + * followed by 0-3 additional zero bytes to make the total number of bits a multiple of 32. + */ -class RDMDiscovery { +class OSCBlob { public: - RDMDiscovery(const uint8_t *pUid); + OSCBlob(const uint8_t *pData, uint32_t nSize) : + m_pData(const_cast(pData)), m_nSize(nSize) { + } + ~OSCBlob() { + } - void Full(uint32_t m_nPortIndex, RDMTod *pRDMTod); + uint32_t GetDataSize() { + return m_nSize; + } -private: - bool FindDevices(uint64_t LowerBound, uint64_t UpperBound); - bool QuickFind(const uint8_t *pUid); + const uint8_t* GetDataPtr() { + return m_pData; + } - bool IsValidDiscoveryResponse(const uint8_t *pDiscResponse, uint8_t *pUid); + uint32_t GetSize() { + const uint32_t nBlobSize = sizeof(int32_t) + m_nSize; + return (4 * ((nBlobSize + 3) / 4)); + } - void PrintUid(uint64_t nUid); - void PrintUid(const uint8_t *pUid); - const uint8_t *ConvertUid(uint64_t nUid); - uint64_t ConvertUid(const uint8_t *pUid); + uint8_t GetByte(uint32_t nIndex) { + if (nIndex < m_nSize) { + return m_pData[nIndex]; + } + return 0; + } private: - RDMMessage m_Message; - uint32_t m_nPortIndex; - RDMTod *m_pRDMTod; - uint8_t m_Uid[RDM_UID_SIZE]; - uint8_t m_Pdl[2][RDM_UID_SIZE]; + uint8_t *m_pData; + uint32_t m_nSize; }; -#endif /* RDMDISCOVERY_H_ */ +#endif /* OSCBLOB_H_ */ diff --git a/lib-osc/include/oscclient.h b/lib-osc/include/oscclient.h new file mode 100755 index 00000000..de81dc8a --- /dev/null +++ b/lib-osc/include/oscclient.h @@ -0,0 +1,147 @@ +/** + * @file oscclient.h + * + */ +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef OSCCLIENT_H_ +#define OSCCLIENT_H_ + +#include +#include + +#include "oscclientled.h" + +namespace oscclient { +static constexpr auto STORE = 944; ///< Configuration store in bytes +namespace defaults { +static constexpr auto PORT_OUTGOING = 8000; +static constexpr auto PORT_INCOMING = 9000; +static constexpr auto PING_DELAY_SECONDS = 10; +} // namespace defaults +namespace max { +static constexpr uint32_t CMD_COUNT = 8; +static constexpr uint32_t CMD_PATH_LENGTH = 64; +static constexpr uint32_t LED_COUNT = 8; +static constexpr uint32_t LED_PATH_LENGTH = 48; +} // namespace max +namespace buffer { +namespace size { +static constexpr uint32_t CMD = oscclient::max::CMD_COUNT * oscclient::max::CMD_PATH_LENGTH; +static constexpr uint32_t LED = oscclient::max::LED_COUNT * oscclient::max::LED_PATH_LENGTH; +} // namespace size +} // namespace buffer +} // namespace oscclient + +class OscClient { +public: + OscClient(); + ~OscClient() { + Stop(); + } + + void Start(); + void Stop(); + + void Run(); + + void Send(const char *pPath); + void SendCmd(uint32_t nCmd); + + void Print(); + + void SetServerIP(uint32_t nServerIP) { + m_nServerIP = nServerIP; + } + + uint32_t GetServerIP() const { + return m_nServerIP; + } + + void SetPortOutgoing(uint16_t nPortOutgoing) { + assert(nPortOutgoing > 1023); + m_nPortOutgoing = nPortOutgoing; + } + + uint16_t GetPortOutgoing() const { + return m_nPortOutgoing; + } + + void SetPortIncoming(uint16_t nPortIncoming) { + assert(nPortIncoming > 1023); + m_nPortIncoming = nPortIncoming; + } + + uint16_t GetPortIncoming() const { + return m_nPortIncoming; + } + + void SetPingDisable(bool nPingDisable = true) { + m_bPingDisable = nPingDisable; + } + + bool GetPingDisable() const { + return m_bPingDisable; + } + + void SetPingDelay(uint32_t nPingDelay = oscclient::defaults::PING_DELAY_SECONDS) { + if ((nPingDelay >=2) && (nPingDelay <= 60)) { + m_nPingDelayMillis = nPingDelay * 1000; + } + } + + uint32_t GetPingDelay() const { + return m_nPingDelayMillis / 1000U; + } + + void CopyCmds(const char *pCmds, uint32_t nCount, uint32_t nLength); + void CopyLeds(const char *pLeds, uint32_t nCount, uint32_t nLength); + + void SetLedHandler(OscClientLed *pOscClientLed) { + assert(pOscClientLed != nullptr); + m_pOscClientLed = pOscClientLed; + } + +private: + bool HandleLedMessage(const uint16_t nBytesReceived); + +private: + uint32_t m_nServerIP { 0 }; + uint16_t m_nPortOutgoing; + uint16_t m_nPortIncoming; + int32_t m_nHandle { -1 }; + bool m_bPingDisable { false }; + uint32_t m_nPingDelayMillis; + bool m_bPingSent { false }; + bool m_bPongReceived { false }; + char *m_pBuffer { nullptr }; + uint32_t m_nCurrenMillis { 0 }; + uint32_t m_nPreviousMillis { 0 }; + uint32_t m_nPingTimeMillis { 0 }; + + OscClientLed *m_pOscClientLed { nullptr }; + + static char m_pCmds[oscclient::buffer::size::CMD]; + static char m_pLeds[oscclient::buffer::size::LED]; +}; + +#endif /* OSCCLIENT_H_ */ diff --git a/lib-osc/include/oscclientled.h b/lib-osc/include/oscclientled.h new file mode 100755 index 00000000..883921c4 --- /dev/null +++ b/lib-osc/include/oscclientled.h @@ -0,0 +1,36 @@ +/** + * @file oscclientled.h + * + */ +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef OSCCLIENTLED_H_ +#define OSCCLIENTLED_H_ + +class OscClientLed { +public: + virtual ~OscClientLed() {} + + virtual void SetLed(const uint32_t nLed, const bool bOn) = 0; +}; + +#endif /* OSCCLIENTLED_H_ */ diff --git a/lib-configstore/src/rdm/storerdmdevice.cpp b/lib-osc/include/oscclientmsgconst.h old mode 100644 new mode 100755 similarity index 78% rename from lib-configstore/src/rdm/storerdmdevice.cpp rename to lib-osc/include/oscclientmsgconst.h index f7232a9d..2af28069 --- a/lib-configstore/src/rdm/storerdmdevice.cpp +++ b/lib-osc/include/oscclientmsgconst.h @@ -1,5 +1,5 @@ /** - * @file storerdmdevice.cpp + * @file oscclientconst.h * */ /* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl @@ -23,21 +23,13 @@ * THE SOFTWARE. */ -#include +#ifndef OSCCLIENTMSGCONST_H_ +#define OSCCLIENTMSGCONST_H_ -#include "storerdmdevice.h" - -#include "debug.h" - -StoreRDMDevice *StoreRDMDevice::s_pThis = nullptr; - -StoreRDMDevice::StoreRDMDevice() { - DEBUG_ENTRY - - assert(s_pThis == nullptr); - s_pThis = this; - - DEBUG_PRINTF("%p", reinterpret_cast(s_pThis)); - DEBUG_EXIT -} +struct OscClientMsgConst { + static const char PARAMS[]; + static const char START[]; + static const char STARTED[]; +}; +#endif /* OSCCLIENTMSGCONST_H_ */ diff --git a/lib-osc/include/oscclientparams.h b/lib-osc/include/oscclientparams.h new file mode 100755 index 00000000..0a9b151b --- /dev/null +++ b/lib-osc/include/oscclientparams.h @@ -0,0 +1,119 @@ +/** + * @file oscclientparams.h + * + */ +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef OSCCLIENTPARAMS_H_ +#define OSCCLIENTPARAMS_H_ + +#include + +#include "oscclient.h" +#include "configstore.h" + +namespace oscclientparams { +struct ParamsMax { + static constexpr uint32_t CMD_COUNT = 8; + static constexpr uint32_t CMD_PATH_LENGTH = 64; + static constexpr uint32_t LED_COUNT = 8; + static constexpr uint32_t LED_PATH_LENGTH = 48; +}; + +struct Params { + uint32_t nSetList; + uint32_t nServerIp; + uint16_t nOutgoingPort; + uint16_t nIncomingPort; + uint8_t nPingDisable; + uint8_t nPingDelay; + char aCmd[ParamsMax::CMD_COUNT][ParamsMax::CMD_PATH_LENGTH]; + char aLed[ParamsMax::LED_COUNT][ParamsMax::LED_PATH_LENGTH]; +} __attribute__((packed)); + +static_assert(sizeof(struct oscclientparams::Params) <= oscclient::STORE, "struct Params is too large"); + +struct Mask { + static constexpr auto SERVER_IP = (1U << 0); + static constexpr auto OUTGOING_PORT = (1U << 1); + static constexpr auto INCOMING_PORT = (1U << 2); + static constexpr auto PING_DISABLE = (1U << 3); + static constexpr auto PING_DELAY = (1U << 4); + static constexpr auto CMD = (1U << 5); + static constexpr auto LED = (1U << 6); +}; +} // namespace oscclientparams + +class OscClientParamsStore { +public: + static void Update(const struct oscclientparams::Params *pParams) { + ConfigStore::Get()->Update(configstore::Store::OSC_CLIENT, pParams, sizeof(struct oscclientparams::Params)); + } + + static void Copy(struct oscclientparams::Params *pParams) { + ConfigStore::Get()->Copy(configstore::Store::OSC_CLIENT, pParams, sizeof(struct oscclientparams::Params)); + } +}; + +class OscClientParams { +public: + OscClientParams(); + + void Load(); + void Load(const char *pBuffer, uint32_t nLength); + + void Builder(const struct oscclientparams::Params *pParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); + void Save(char *pBuffer, uint32_t nLength, uint32_t& nSize) { + Builder(nullptr, pBuffer, nLength, nSize); + } + + void Set(OscClient *pOscClient); + + uint32_t GetServerIP() { + return m_Params.nServerIp; + } + + uint16_t GetOutgoingPort() { + return m_Params.nOutgoingPort; + } + + uint16_t GetIncomingPort() { + return m_Params.nIncomingPort; + } + +public: + static void staticCallbackFunction(void *p, const char *s); + +private: + void Dump(); + void callbackFunction(const char *s); + bool isMaskSet(uint32_t nMask) const { + return (m_Params.nSetList & nMask) == nMask; + } + +private: + oscclientparams::Params m_Params; + char m_aCmd[8]; + char m_aLed[8]; +}; + +#endif /* OSCCLIENTPARAMS_H_ */ diff --git a/lib-osc/include/oscclientparamsconst.h b/lib-osc/include/oscclientparamsconst.h new file mode 100755 index 00000000..0d0804d0 --- /dev/null +++ b/lib-osc/include/oscclientparamsconst.h @@ -0,0 +1,43 @@ +/** + * @file oscclientparamsconst.h + * + */ +/* Copyright (C) 2019 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef OSCCLIENTPARAMSCONST_H_ +#define OSCCLIENTPARAMSCONST_H_ + +#include + +struct OscClientParamsConst { + static const char FILE_NAME[]; + + static const char SERVER_IP[]; + + static const char PING_DISABLE[]; + static const char PING_DELAY[]; + + static const char CMD[]; + static const char LED[]; +}; + +#endif /* OSCCLIENTPARAMSCONST_H_ */ diff --git a/lib-osc/include/oscparamsconst.h b/lib-osc/include/oscparamsconst.h new file mode 100644 index 00000000..521ae0c6 --- /dev/null +++ b/lib-osc/include/oscparamsconst.h @@ -0,0 +1,34 @@ +/** + * @file oscconst.h + * + */ +/* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef OSCPARAMSCONST_H_ +#define OSCPARAMSCONST_H_ + +struct OscParamsConst { + static const char INCOMING_PORT[]; + static const char OUTGOING_PORT[]; +}; + +#endif /* OSCPARAMSCONST_H_ */ diff --git a/lib-osc/include/oscserver.h b/lib-osc/include/oscserver.h new file mode 100755 index 00000000..2f73c666 --- /dev/null +++ b/lib-osc/include/oscserver.h @@ -0,0 +1,165 @@ +/** + * @file oscserver.h + * + */ +/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef OSCSERVER_H_ +#define OSCSERVER_H_ + +#include +#include + +#include "lightset.h" + +namespace osc { +namespace server { +struct DefaultPort { + static constexpr auto INCOMING = 8000U; + static constexpr auto OUTGOING = 9000U; +}; + +struct Max { + static constexpr auto PATH_LENGTH = 128U; +}; +} // namespace server +} // namespace osc + +class OscServerHandler { +public: + virtual ~OscServerHandler() {} + virtual void Blackout()=0; + virtual void Update()=0; + virtual void Info(int32_t nHandle, uint32_t nRemoteIp, uint16_t nPortOutgoing)=0; +}; + +class OscServer { +public: + OscServer(); + ~OscServer(); + + void SetOutput(LightSet *pLightSet) { + assert(pLightSet != nullptr); + m_pLightSet = pLightSet; + } + + void SetOscServerHandler(OscServerHandler *pOscServerHandler) { + assert(pOscServerHandler != nullptr); + m_pOscServerHandler = pOscServerHandler; + } + + void SetPortIncoming(uint16_t nPortIncoming = osc::server::DefaultPort::INCOMING) { + assert(nPortIncoming > 1023); + m_nPortIncoming = nPortIncoming; + } + + uint16_t GetPortIncoming() const { + return m_nPortIncoming; + } + + void SetPortOutgoing(uint16_t nPortOutgoing) { + assert(nPortOutgoing > 1023); + m_nPortOutgoing = nPortOutgoing; + } + + uint16_t GetPortOutgoing() const { + return m_nPortOutgoing; + } + + void SetPath(const char *pPath); + + const char*GetPath() { + return s_aPath; + } + + void SetPathInfo(const char *pPathInfo); + + const char*GetPathInfo() { + return s_aPathInfo; + } + + void SetPathBlackOut(const char *pPathBlackOut); + + const char*GetPathBlackOut() { + return s_aPathBlackOut; + } + + void SetPartialTransmission(bool bPartialTransmission = false) { + m_bPartialTransmission = bPartialTransmission; + } + + bool IsPartialTransmission() const { + return m_bPartialTransmission; + } + + void SetEnableNoChangeUpdate(bool bEnableNoChangeUpdate) { + m_bEnableNoChangeUpdate = bEnableNoChangeUpdate; + } + bool GetEnableNoChangeUpdate() { + return m_bEnableNoChangeUpdate; + } + + void Print(); + + void Start(); + void Stop(); + + void Run(); + + static OscServer* Get() { + return s_pThis; + } + +private: + int GetChannel(const char *p); + bool IsDmxDataChanged(const uint8_t *pData, uint16_t nStartChannel, uint32_t nLength); + +private: + uint16_t m_nPortIncoming { osc::server::DefaultPort::INCOMING }; + uint16_t m_nPortOutgoing { osc::server::DefaultPort::OUTGOING }; + int32_t m_nHandle { -1 }; + uint16_t m_nLastChannel { 0 }; + + bool m_bPartialTransmission { false }; + bool m_bEnableNoChangeUpdate { false }; + bool m_bIsRunning { false }; + char m_Os[32]; + + OscServerHandler *m_pOscServerHandler { nullptr }; + LightSet *m_pLightSet { nullptr }; + + const char *m_pModel; + const char *m_pSoC; + + static char s_aPath[osc::server::Max::PATH_LENGTH]; + static char s_aPathSecond[osc::server::Max::PATH_LENGTH]; + static char s_aPathInfo[osc::server::Max::PATH_LENGTH]; + static char s_aPathBlackOut[osc::server::Max::PATH_LENGTH]; + + static uint8_t s_pData[lightset::dmx::UNIVERSE_SIZE]; + static uint8_t s_pOsc[lightset::dmx::UNIVERSE_SIZE]; + + static char *s_pUdpBuffer; + static OscServer *s_pThis; +}; + +#endif /* OSCSERVER_H_ */ diff --git a/lib-osc/include/oscserverconst.h b/lib-osc/include/oscserverconst.h new file mode 100755 index 00000000..863c6cc9 --- /dev/null +++ b/lib-osc/include/oscserverconst.h @@ -0,0 +1,35 @@ +/** + * @file oscserverconst.h + * + */ +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef OSCSERVERCONST_H_ +#define OSCSERVERCONST_H_ + +struct OSCServerConst { + static const char MSG_BRIDGE_PARAMS[]; + static const char MSG_BRIDGE_START[]; + static const char MSG_BRIDGE_STARTED[]; +}; + +#endif /* OSCSERVERCONST_H_ */ diff --git a/lib-configstore/src/rdm/storerdmsensors.cpp b/lib-osc/include/oscservermsgconst.h old mode 100644 new mode 100755 similarity index 78% rename from lib-configstore/src/rdm/storerdmsensors.cpp rename to lib-osc/include/oscservermsgconst.h index a4ff5058..46626238 --- a/lib-configstore/src/rdm/storerdmsensors.cpp +++ b/lib-osc/include/oscservermsgconst.h @@ -1,5 +1,5 @@ /** - * @file storerdmsensors.cpp + * @file oscservermsgconst.h * */ /* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl @@ -23,20 +23,13 @@ * THE SOFTWARE. */ -#include +#ifndef OSCSERVERMSGCONST_H_ +#define OSCSERVERMSGCONST_H_ -#include "storerdmsensors.h" +struct OscServerMsgConst { + static const char PARAMS[]; + static const char START[]; + static const char STARTED[]; +}; -#include "debug.h" - -StoreRDMSensors *StoreRDMSensors::s_pThis = nullptr; - -StoreRDMSensors::StoreRDMSensors() { - DEBUG_ENTRY - - assert(s_pThis == nullptr); - s_pThis = this; - - DEBUG_PRINTF("%p", reinterpret_cast(s_pThis)); - DEBUG_EXIT -} +#endif /* OSCSERVERMSGCONST_H_ */ diff --git a/lib-osc/include/oscserverparams.h b/lib-osc/include/oscserverparams.h new file mode 100755 index 00000000..1e08af7e --- /dev/null +++ b/lib-osc/include/oscserverparams.h @@ -0,0 +1,110 @@ +/** + * @file oscserverparams.h + * + */ +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef OSCSERVERPARAMS_H_ +#define OSCSERVERPARAMS_H_ + +#include + +#include "oscserver.h" +#include "configstore.h" +#include "lightset.h" + +namespace osc { +namespace server { +struct Params { + uint32_t nSetList; + uint16_t nIncomingPort; + uint16_t nOutgoingPort; + uint8_t tOutputType; + bool bPartialTransmission; + char aPath[osc::server::Max::PATH_LENGTH]; + char aPathInfo[osc::server::Max::PATH_LENGTH]; + char aPathBlackOut[osc::server::Max::PATH_LENGTH]; +} __attribute__((packed)); + +struct ParamsMask { + static constexpr uint32_t INCOMING_PORT = (1U << 0); + static constexpr uint32_t OUTGOING_PORT = (1U << 1); + static constexpr uint32_t PATH = (1U << 2); + static constexpr uint32_t TRANSMISSION = (1U << 3); + static constexpr uint32_t OUTPUT = (1U << 4); + static constexpr uint32_t PATH_INFO = (1U << 5); + static constexpr uint32_t PATH_BLACKOUT = (1U << 6); +}; +} // namespace server +} // namespace osc + +class StoreOscServer { +public: + static void Update(const struct osc::server::Params *pParams) { + ConfigStore::Get()->Update(configstore::Store::OSC, pParams, sizeof(struct osc::server::Params)); + } + + static void Copy(struct osc::server::Params *pParams) { + ConfigStore::Get()->Copy(configstore::Store::OSC, pParams, sizeof(struct osc::server::Params)); + } +}; + +class OSCServerParams { +public: + OSCServerParams(); + + void Load(); + void Load(const char *pBuffer, uint32_t nLength); + + void Builder(const osc::server::Params *pParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); + void Save(char *pBuffer, uint32_t nLength, uint32_t& nSize) { + Builder(nullptr, pBuffer, nLength, nSize); + } + + void Set(OscServer *pOscServer); + + uint16_t GetIncomingPort() const { + return m_Params.nIncomingPort; + } + + uint16_t GetOutgoingPort() const { + return m_Params.nOutgoingPort; + } + + bool GetPartialTransmission() const { + return m_Params.bPartialTransmission; + } + + static void staticCallbackFunction(void *p, const char *s); + +private: + void Dump(); + void callbackFunction(const char *s); + bool isMaskSet(uint32_t nMask) const { + return (m_Params.nSetList & nMask) == nMask; + } + +private: + osc::server::Params m_Params; +}; + +#endif /* OSCSERVERPARAMS_H_ */ diff --git a/lib-display/src/display_timeout.cpp b/lib-osc/include/oscserverparamsconst.h old mode 100644 new mode 100755 similarity index 77% rename from lib-display/src/display_timeout.cpp rename to lib-osc/include/oscserverparamsconst.h index 5b403dd1..5649e1d6 --- a/lib-display/src/display_timeout.cpp +++ b/lib-osc/include/oscserverparamsconst.h @@ -1,5 +1,5 @@ /** - * @file display_timeout.cpp + * @file oscserverparamsconst.h * */ /* Copyright (C) 2022 by Arjan van Vught mailto:info@orangepi-dmx.nl @@ -23,9 +23,17 @@ * THE SOFTWARE. */ -namespace display { -namespace timeout { -void __attribute__((weak)) gpio_init() {} -bool __attribute__((weak)) gpio_renew() { return false;} -} // namespace timeout -} // namespace display +#ifndef OSCSERVERPARAMSCONST_H_ +#define OSCSERVERPARAMSCONST_H_ + +struct OscServerParamsConst { + static const char FILE_NAME[]; + + static const char PATH[]; + static const char PATH_INFO[]; + static const char PATH_BLACKOUT[]; + + static const char TRANSMISSION[]; +}; + +#endif /* OSCSERVERPARAMSCONST_H_ */ diff --git a/lib-osc/include/oscsimplemessage.h b/lib-osc/include/oscsimplemessage.h new file mode 100644 index 00000000..fa15a01a --- /dev/null +++ b/lib-osc/include/oscsimplemessage.h @@ -0,0 +1,73 @@ +/** + * @file oscsimplemessage.h + * + */ +/* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef OSCSIMPLEMESSAGE_H_ +#define OSCSIMPLEMESSAGE_H_ + +#include + +#include "osc.h" +#include "oscblob.h" + +class OscSimpleMessage { +public: + OscSimpleMessage(void *pData, unsigned nLength); + + bool IsValid() { + return m_bIsValid; + } + + int GetArgc() { + if (m_bIsValid) { + return static_cast(m_nArgc); + } + + return -1; + } + + char GetType(unsigned argc) { + if (argc < m_nArgc) { + return static_cast(m_pArg[argc]); + } + + return osc::type::UNKNOWN; + } + + float GetFloat(unsigned argc); + int GetInt(unsigned argc); + char* GetString(unsigned argc); + OSCBlob GetBlob(unsigned argc); + +private: + uint8_t *m_pOscMessage; + uint32_t m_nLength; + bool m_bIsValid = false; + uint8_t *m_pArg; + uint32_t m_nArgc = 0; + uint8_t *m_pOscMessageData = nullptr; + uint32_t m_nOscMessageDataLength = 0; +}; + +#endif /* OSCSIMPLEMESSAGE_H_ */ diff --git a/lib-osc/include/oscsimplesend.h b/lib-osc/include/oscsimplesend.h new file mode 100644 index 00000000..912c8025 --- /dev/null +++ b/lib-osc/include/oscsimplesend.h @@ -0,0 +1,58 @@ +/** + * @file oscsimplesend.h + * + */ +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef OSCSIMPLESEND_H_ +#define OSCSIMPLESEND_H_ + +#include + +namespace osc { +namespace simple { +namespace send { +static constexpr auto BUFFER_SIZE = 512U; +} // namespace send +} // namespace simple +} // namespace osc + +class OscSimpleSend { +public: + // Support for path only + OscSimpleSend(int32_t nHandle, uint32_t nIpAddress , uint16_t nPort, const char *pPath, const char *pType); + // Support for 's' + OscSimpleSend(int32_t nHandle, uint32_t nIpAddress , uint16_t nPort, const char *pPath, const char *pType, const char *pString); + // Support for type 'i' + OscSimpleSend(int32_t nHandle, uint32_t nIpAddress , uint16_t nPort, const char *pPath, const char *pType, int nValue); + // Support for type 'f' + OscSimpleSend(int32_t nHandle, uint32_t nIpAddress , uint16_t nPort, const char *pPath, const char *pType, float fValue); + +private: + void UpdateMessage(const char *pPath, uint32_t nPathLength, char cType); + void Send(uint32_t nMessageLength, int32_t nHandle, uint32_t nIpAddress, uint16_t nPort); + +private: + static char s_Message[osc::simple::send::BUFFER_SIZE]; +}; + +#endif /* OSCSIMPLESEND_H_ */ diff --git a/lib-ws28xxdmx/include/ws28xxdmxstartstop.h b/lib-osc/include/oscstring.h similarity index 52% rename from lib-ws28xxdmx/include/ws28xxdmxstartstop.h rename to lib-osc/include/oscstring.h index ab14753f..5658cf38 100644 --- a/lib-ws28xxdmx/include/ws28xxdmxstartstop.h +++ b/lib-osc/include/oscstring.h @@ -1,8 +1,8 @@ /** - * @file pixeldmxstartstop.h + * @file oscstring.h * */ -/* Copyright (C) 2020-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,32 +23,53 @@ * THE SOFTWARE. */ -#ifndef WS28XXDMXSTARTSTOP_H_ -#define WS28XXDMXSTARTSTOP_H_ +#ifndef OSCSTRING_H_ +#define OSCSTRING_H_ -#include "pixeldmxhandler.h" +#include -#include "hal_gpio.h" +#include "osc.h" -#define GPIO_START_STOP GPIO_EXT_12 +/* + * OSC-string + * A sequence of non-null ASCII characters followed by a null, + * followed by 0-3 additional null characters to make the total number of bits a multiple of 32. + */ + +namespace osc { +inline static int string_validate(void *pData, unsigned nSize) { + unsigned nLength = 0; + char *pSrc = reinterpret_cast(pData); + + unsigned i = 0; -class PixelDmxStartStop final: public PixelDmxHandler { -public: - PixelDmxStartStop() { - FUNC_PREFIX(gpio_fsel(GPIO_START_STOP, GPIO_FSEL_OUTPUT)); - FUNC_PREFIX(gpio_clr(GPIO_START_STOP)); + for (i = 0; i < nSize; ++i) { + if (pSrc[i] == '\0') { + nLength = 4 * (i / 4 + 1); + break; + } } - ~PixelDmxStartStop() override { + if (0 == nLength) { + return -osc::validate::NOT_TERMINATED; } - void Start() override { - FUNC_PREFIX(gpio_set(GPIO_START_STOP)); + if (nLength > nSize) { + return -osc::validate::INVALID_SIZE; } - void Stop() override { - FUNC_PREFIX(gpio_clr(GPIO_START_STOP)); + for (; i < nLength; ++i) { + if (pSrc[i] != '\0') { + return -osc::validate::NONE_ZERO_IN_PADDING; + } } -}; -#endif /* WS28XXDMXSTARTSTOP_H_ */ + return static_cast(nLength); +} + +inline static unsigned string_size(const char *pString) { + return 4 * (strlen(pString) / 4 + 1); +} +} // namespace osc + +#endif /* OSCSTRING_H_ */ diff --git a/lib-osc/src/client/oscclient.cpp b/lib-osc/src/client/oscclient.cpp new file mode 100755 index 00000000..11e20383 --- /dev/null +++ b/lib-osc/src/client/oscclient.cpp @@ -0,0 +1,211 @@ +/** + * @file oscclient.cpp + * + */ +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include "oscclient.h" +#include "oscsimplesend.h" +#include "oscsimplemessage.h" +#include "osc.h" + +#include "hardware.h" +#include "network.h" +#include "display.h" + +#include "debug.h" + +char OscClient::m_pCmds[oscclient::buffer::size::CMD]; +char OscClient::m_pLeds[oscclient::buffer::size::LED]; + +OscClient::OscClient() : + m_nPortOutgoing(oscclient::defaults::PORT_OUTGOING), + m_nPortIncoming(oscclient::defaults::PORT_INCOMING), + m_nPingDelayMillis(oscclient::defaults::PING_DELAY_SECONDS * 1000) +{ + DEBUG_ENTRY + + DEBUG_EXIT +} + +void OscClient::Start() { + DEBUG_ENTRY + + m_nHandle = Network::Get()->Begin(m_nPortIncoming); + assert(m_nHandle != -1); + + DEBUG_EXIT +} + +void OscClient::Stop() { + m_nHandle = Network::Get()->End(m_nPortIncoming); +} + +void OscClient::Run() { + if (!m_bPingDisable) { + m_nCurrenMillis = Hardware::Get()->Millis(); + + if ((m_nCurrenMillis - m_nPreviousMillis) >= m_nPingDelayMillis) { + OscSimpleSend MsgSend(m_nHandle, m_nServerIP, m_nPortOutgoing, "/ping", nullptr); + m_bPingSent = true; + m_nPreviousMillis = m_nCurrenMillis; + m_nPingTimeMillis = m_nCurrenMillis; + DEBUG_PUTS("Ping sent"); + } + } + + uint32_t nRemoteIp; + uint16_t nRemotePort; + + const auto nBytesReceived = Network::Get()->RecvFrom(m_nHandle, const_cast(reinterpret_cast(&m_pBuffer)), &nRemoteIp, &nRemotePort); + + if (__builtin_expect((nBytesReceived == 0), 1)) { + if (m_bPingSent && ((m_nCurrenMillis - m_nPingTimeMillis) >= 1000)) { + if (m_bPongReceived) { + m_bPongReceived = false; + Display::Get()->TextStatus("No /Pong"); + DEBUG_PUTS("No /Pong"); + } + } + return; + } + + if (nRemoteIp != m_nServerIP) { + DEBUG_PRINTF("Data not received from server " IPSTR , IP2STR(nRemoteIp)); + return; + } + + if ((m_pOscClientLed != nullptr) && (HandleLedMessage(nBytesReceived))) { + DEBUG_EXIT + return; + } + + + if (!m_bPingDisable) { + if (!osc::is_match(m_pBuffer, "/pong")) { + DEBUG_PUTS(m_pBuffer); + return; + } + + + if (!m_bPongReceived) { + Display::Get()->TextStatus("Ping-Pong"); + DEBUG_PUTS("Ping-Pong"); + } + + m_bPongReceived = true; + m_bPingSent = false; + } +} + +void OscClient::CopyCmds(const char *pCmds, uint32_t nCount, uint32_t nLength) { + assert(pCmds != nullptr); + + for (uint32_t i = 0; i < std::min(nCount, oscclient::max::CMD_COUNT); i++) { + char *dst = &m_pCmds[i * oscclient::max::CMD_PATH_LENGTH]; + strncpy(dst, &pCmds[i * nLength], oscclient::max::CMD_PATH_LENGTH - 1); + dst[oscclient::max::CMD_PATH_LENGTH - 1] = '\0'; + } +} + +void OscClient::CopyLeds(const char *pLeds, uint32_t nCount, uint32_t nLength) { + assert(pLeds != nullptr); + + for (uint32_t i = 0; i < std::min(nCount, oscclient::max::LED_COUNT); i++) { + char *dst = &m_pLeds[i * oscclient::max::LED_PATH_LENGTH]; + strncpy(dst, &pLeds[i * nLength], oscclient::max::LED_PATH_LENGTH - 1); + dst[oscclient::max::LED_PATH_LENGTH - 1] = '\0'; + } +} + +bool OscClient::HandleLedMessage(const uint16_t nBytesReceived) { + DEBUG_ENTRY + + uint32_t i; + + for (i = 0; i < oscclient::max::LED_COUNT; i++) { + const char *src = &m_pLeds[i * oscclient::max::LED_PATH_LENGTH]; + if (osc::is_match(m_pBuffer, src)) { + DEBUG_PUTS(""); + break; + } + } + + if (i == oscclient::max::LED_COUNT) { + DEBUG_EXIT + return false; + } + + OscSimpleMessage Msg(m_pBuffer, nBytesReceived); + + const int nArgc = Msg.GetArgc(); + + if (nArgc != 1) { + DEBUG_EXIT + return false; + } + + if (Msg.GetType(0) == osc::type::INT32) { + m_pOscClientLed->SetLed(static_cast(i), static_cast(Msg.GetInt(0)) != 0); + DEBUG_PRINTF("%d", Msg.GetInt(0)); + } else if (Msg.GetType(0) == osc::type::FLOAT) { + m_pOscClientLed->SetLed(static_cast(i), static_cast(Msg.GetFloat(0)) != 0); + DEBUG_PRINTF("%f", Msg.GetFloat(0)); + } else { + return false; + } + + DEBUG_EXIT + return true; +} + +void OscClient::Print() { + puts("OSC Client"); + printf(" Server ip-address :" IPSTR "\n", IP2STR(m_nServerIP)); + printf(" Outgoing Port : %d\n", m_nPortOutgoing); + printf(" Incoming Port : %d\n", m_nPortIncoming); + printf(" Disable /ping : %s\n", m_bPingDisable ? "Yes" : "No"); + + if (!m_bPingDisable) { + printf(" Ping delay : %ds\n", m_nPingDelayMillis / 1000); + } + + for (uint32_t i = 0; i < oscclient::max::CMD_COUNT; i++) { + const char *p = &m_pCmds[i * oscclient::max::CMD_PATH_LENGTH]; + if (*p != '\0') { + printf(" cmd%c : [%s]\n", i + '0', p); + } + } + + for (uint32_t i = 0; i < oscclient::max::LED_COUNT; i++) { + const char *p = &m_pLeds[i * oscclient::max::LED_PATH_LENGTH]; + if (*p != '\0') { + printf(" led%c : [%s]\n", i + '0', p); + } + } +} diff --git a/lib-configstore/src/storedisplayudf.cpp b/lib-osc/src/client/oscclientmsgconst.cpp old mode 100644 new mode 100755 similarity index 78% rename from lib-configstore/src/storedisplayudf.cpp rename to lib-osc/src/client/oscclientmsgconst.cpp index ac5e8f22..7d56b151 --- a/lib-configstore/src/storedisplayudf.cpp +++ b/lib-osc/src/client/oscclientmsgconst.cpp @@ -1,5 +1,5 @@ /** - * @file storedisplayudf.cpp + * @file oscclientconst.cpp * */ /* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl @@ -23,20 +23,8 @@ * THE SOFTWARE. */ -#include +#include "oscclientmsgconst.h" -#include "storedisplayudf.h" - -#include "debug.h" - -StoreDisplayUdf *StoreDisplayUdf::s_pThis = nullptr; - -StoreDisplayUdf::StoreDisplayUdf() { - DEBUG_ENTRY - - assert(s_pThis == nullptr); - s_pThis = this; - - DEBUG_PRINTF("%p", reinterpret_cast(s_pThis)); - DEBUG_EXIT -} +const char OscClientMsgConst::PARAMS[] = "Setting Client parameters"; +const char OscClientMsgConst::START[] = "Starting the Client"; +const char OscClientMsgConst::STARTED[] = "Client started"; diff --git a/lib-osc/src/client/oscclientparams.cpp b/lib-osc/src/client/oscclientparams.cpp new file mode 100755 index 00000000..99b9a410 --- /dev/null +++ b/lib-osc/src/client/oscclientparams.cpp @@ -0,0 +1,292 @@ +/** + * @file oscclientparams.cpp + * + */ +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if !defined(__clang__) // Needed for compiling on MacOS +# pragma GCC push_options +# pragma GCC optimize ("Os") +#endif + +#include +#include +#ifndef NDEBUG +# include +#endif +#include + +#include "oscclientparams.h" +#include "oscclientparamsconst.h" +#include "oscparamsconst.h" + +#include "network.h" + +#include "readconfigfile.h" +#include "sscan.h" +#include "propertiesbuilder.h" + +#include "debug.h" + +OscClientParams::OscClientParams() { + DEBUG_ENTRY + + memset(&m_Params, 0, sizeof(struct oscclientparams::Params)); + m_Params.nOutgoingPort = oscclient::defaults::PORT_OUTGOING; + m_Params.nIncomingPort = oscclient::defaults::PORT_INCOMING; + m_Params.nPingDelay = oscclient::defaults::PING_DELAY_SECONDS; + + assert(sizeof(m_aCmd) > strlen(OscClientParamsConst::CMD)); + strncpy(m_aCmd, OscClientParamsConst::CMD, sizeof(m_aCmd)); + + assert(sizeof(m_aLed) > strlen(OscClientParamsConst::LED)); + strncpy(m_aLed, OscClientParamsConst::LED, sizeof(m_aLed)); + + DEBUG_EXIT +} + +void OscClientParams::Load() { + DEBUG_ENTRY + + m_Params.nSetList = 0; + +#if !defined(DISABLE_FS) + ReadConfigFile configfile(OscClientParams::staticCallbackFunction, this); + + if (configfile.Read(OscClientParamsConst::FILE_NAME)) { + OscClientParamsStore::Update(&m_Params); + } else +#endif + OscClientParamsStore::Copy(&m_Params); + +#ifndef NDEBUG + Dump(); +#endif + DEBUG_EXIT +} + +void OscClientParams::Load(const char *pBuffer, uint32_t nLength) { + DEBUG_ENTRY + + assert(pBuffer != nullptr); + assert(nLength != 0); + + m_Params.nSetList = 0; + + ReadConfigFile config(OscClientParams::staticCallbackFunction, this); + + config.Read(pBuffer, nLength); + + OscClientParamsStore::Update(&m_Params); + +#ifndef NDEBUG + Dump(); +#endif + DEBUG_EXIT +} + +void OscClientParams::callbackFunction(const char *pLine) { + assert(pLine != nullptr); + + uint32_t nValue32; + + if (Sscan::IpAddress(pLine, OscClientParamsConst::SERVER_IP, nValue32) == Sscan::OK) { + m_Params.nServerIp = nValue32; + m_Params.nSetList |= oscclientparams::Mask::SERVER_IP; + return; + } + + uint16_t nValue16; + + if (Sscan::Uint16(pLine, OscParamsConst::OUTGOING_PORT, nValue16) == Sscan::OK) { + if (nValue16 > 1023) { + m_Params.nOutgoingPort = nValue16; + m_Params.nSetList |= oscclientparams::Mask::OUTGOING_PORT; + } else { + m_Params.nSetList &= ~oscclientparams::Mask::OUTGOING_PORT; + } + return; + } + + if (Sscan::Uint16(pLine, OscParamsConst::INCOMING_PORT, nValue16) == Sscan::OK) { + if (nValue16 > 1023) { + m_Params.nIncomingPort = nValue16; + m_Params.nSetList |= oscclientparams::Mask::INCOMING_PORT; + } else { + m_Params.nSetList &= ~oscclientparams::Mask::INCOMING_PORT; + } + return; + } + + uint8_t nValue8; + + if (Sscan::Uint8(pLine, OscClientParamsConst::PING_DISABLE, nValue8) == Sscan::OK) { + m_Params.nPingDisable = (nValue8 != 0); + m_Params.nSetList |= oscclientparams::Mask::PING_DISABLE; + return; + } + + if (Sscan::Uint8(pLine, OscClientParamsConst::PING_DELAY, nValue8) == Sscan::OK) { + if ((nValue8 >= 2) && (nValue8 <= 60)) { + m_Params.nPingDelay = nValue8; + m_Params.nSetList |= oscclientparams::Mask::PING_DELAY; + } else { + m_Params.nSetList &= ~oscclientparams::Mask::PING_DELAY; + } + return; + } + + for (uint32_t i = 0; i < oscclientparams::ParamsMax::CMD_COUNT; i++) { + m_aCmd[strlen(OscClientParamsConst::CMD) - 1] = static_cast(i + '0'); + if (Sscan::Char(pLine, m_aCmd, reinterpret_cast(&m_Params.aCmd[i]), nValue32) == Sscan::OK) { + if (m_Params.aCmd[i][0] == '/') { + m_Params.nSetList |= oscclientparams::Mask::CMD; + } else { + m_Params.aCmd[i][0] = '\0'; + } + } + } + + for (uint32_t i = 0; i < oscclientparams::ParamsMax::LED_COUNT; i++) { + m_aLed[strlen(OscClientParamsConst::LED) - 1] = static_cast(i + '0'); + if (Sscan::Char(pLine, m_aLed, reinterpret_cast(&m_Params.aLed[i]), nValue32) == Sscan::OK) { + if (m_Params.aLed[i][0] == '/') { + m_Params.nSetList |= oscclientparams::Mask::LED; + } else { + m_Params.aLed[i][0] = '\0'; + } + } + } +} + +void OscClientParams::Builder(const struct oscclientparams::Params *pParams, char *pBuffer, uint32_t nLength, uint32_t& nSize) { + DEBUG_ENTRY + + assert(pBuffer != nullptr); + + if (pParams != nullptr) { + memcpy(&m_Params, pParams, sizeof(struct oscclientparams::Params)); + } else { + OscClientParamsStore::Copy(&m_Params); + } + + PropertiesBuilder builder(OscClientParamsConst::FILE_NAME, pBuffer, nLength); + + builder.AddIpAddress(OscClientParamsConst::SERVER_IP, m_Params.nServerIp, isMaskSet(oscclientparams::Mask::SERVER_IP)); + builder.Add(OscParamsConst::OUTGOING_PORT, m_Params.nOutgoingPort, isMaskSet(oscclientparams::Mask::OUTGOING_PORT)); + builder.Add(OscParamsConst::INCOMING_PORT, m_Params.nIncomingPort, isMaskSet(oscclientparams::Mask::INCOMING_PORT)); + builder.Add(OscClientParamsConst::PING_DISABLE, m_Params.nPingDisable, isMaskSet(oscclientparams::Mask::PING_DISABLE)); + builder.Add(OscClientParamsConst::PING_DELAY, m_Params.nPingDelay, isMaskSet(oscclientparams::Mask::PING_DELAY)); + + for (uint32_t i = 0; i < oscclientparams::ParamsMax::CMD_COUNT; i++) { + m_aCmd[strlen(OscClientParamsConst::CMD) - 1] = static_cast(i + '0'); + const char *cmd = reinterpret_cast(&m_Params.aCmd[i]); + builder.Add(m_aCmd, cmd, *cmd == '/'); + } + + for (uint32_t i = 0; i < oscclientparams::ParamsMax::LED_COUNT; i++) { + m_aLed[strlen(OscClientParamsConst::LED) - 1] = static_cast(i + '0'); + const char *led = reinterpret_cast(&m_Params.aLed[i]); + builder.Add(m_aLed, led, *led == '/'); + } + + nSize = builder.GetSize(); + + DEBUG_EXIT +} + +void OscClientParams::Set(OscClient* pOscClient) { + assert(pOscClient != nullptr); + + if (isMaskSet(oscclientparams::Mask::SERVER_IP)) { + pOscClient->SetServerIP(m_Params.nServerIp); + } + + if (isMaskSet(oscclientparams::Mask::OUTGOING_PORT)) { + pOscClient->SetPortOutgoing(m_Params.nOutgoingPort); + } + + if (isMaskSet(oscclientparams::Mask::INCOMING_PORT)) { + pOscClient->SetPortIncoming(m_Params.nIncomingPort); + } + + if (isMaskSet(oscclientparams::Mask::PING_DISABLE)) { + pOscClient->SetPingDisable(m_Params.nPingDisable); + } + + if (isMaskSet(oscclientparams::Mask::PING_DELAY)) { + pOscClient->SetPingDelay(m_Params.nPingDelay); + } + + if (isMaskSet(oscclientparams::Mask::CMD)) { + pOscClient->CopyCmds(reinterpret_cast(&m_Params.aCmd), oscclientparams::ParamsMax::CMD_COUNT, oscclientparams::ParamsMax::CMD_PATH_LENGTH); + } + + if (isMaskSet(oscclientparams::Mask::LED)) { + pOscClient->CopyLeds(reinterpret_cast(&m_Params.aLed), oscclientparams::ParamsMax::LED_COUNT, oscclientparams::ParamsMax::LED_PATH_LENGTH); + } +} + +void OscClientParams::staticCallbackFunction(void* p, const char* s) { + assert(p != nullptr); + assert(s != nullptr); + + (static_cast(p))->callbackFunction(s); +} + +void OscClientParams::Dump() { + printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, OscClientParamsConst::FILE_NAME); + + if (isMaskSet(oscclientparams::Mask::SERVER_IP)) { + printf(" %s=" IPSTR "\n", OscClientParamsConst::SERVER_IP, IP2STR(m_Params.nServerIp)); + } + + if (isMaskSet(oscclientparams::Mask::OUTGOING_PORT)) { + printf(" %s=%d\n", OscParamsConst::OUTGOING_PORT, m_Params.nOutgoingPort); + } + + if (isMaskSet(oscclientparams::Mask::INCOMING_PORT)) { + printf(" %s=%d\n", OscParamsConst::INCOMING_PORT, m_Params.nIncomingPort); + } + + if (isMaskSet(oscclientparams::Mask::PING_DISABLE)) { + printf(" %s=%d [%s]\n", OscClientParamsConst::PING_DISABLE, m_Params.nPingDisable, m_Params.nPingDisable == 0 ? "No" : "Yes"); + } + + if (isMaskSet(oscclientparams::Mask::PING_DELAY)) { + printf(" %s=%ds\n", OscClientParamsConst::PING_DELAY, m_Params.nPingDelay); + } + + if (isMaskSet(oscclientparams::Mask::CMD)) { + for (uint32_t i = 0; i < oscclientparams::ParamsMax::CMD_COUNT; i++) { + m_aCmd[strlen(OscClientParamsConst::CMD) - 1] = static_cast(i + '0'); + printf(" %s=[%s]\n", m_aCmd, reinterpret_cast(&m_Params.aCmd[i])); + } + } + + if (isMaskSet(oscclientparams::Mask::LED)) { + for (uint32_t i = 0; i < oscclientparams::ParamsMax::LED_COUNT; i++) { + m_aLed[strlen(OscClientParamsConst::LED) - 1] = static_cast(i + '0'); + printf(" %s=[%s]\n", m_aLed, reinterpret_cast(&m_Params.aLed[i])); + } + } +} diff --git a/lib-configstore/src/storeremoteconfig.cpp b/lib-osc/src/client/oscclientparamsconst.cpp old mode 100644 new mode 100755 similarity index 73% rename from lib-configstore/src/storeremoteconfig.cpp rename to lib-osc/src/client/oscclientparamsconst.cpp index 8c36decb..2c514027 --- a/lib-configstore/src/storeremoteconfig.cpp +++ b/lib-osc/src/client/oscclientparamsconst.cpp @@ -1,5 +1,5 @@ /** - * @file storeremoteconfig.cpp + * @file oscclientparamsconst.cpp * */ /* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl @@ -23,20 +23,14 @@ * THE SOFTWARE. */ -#include +#include "oscclientparamsconst.h" -#include "storeremoteconfig.h" +const char OscClientParamsConst::FILE_NAME[] = "oscclnt.txt"; -#include "debug.h" +const char OscClientParamsConst::SERVER_IP[] = "server_ip"; -StoreRemoteConfig *StoreRemoteConfig::s_pThis = nullptr; +const char OscClientParamsConst::PING_DISABLE[] = "ping_disable"; +const char OscClientParamsConst::PING_DELAY[] = "ping_delay"; -StoreRemoteConfig::StoreRemoteConfig() { - DEBUG_ENTRY - - assert(s_pThis == nullptr); - s_pThis = this; - - DEBUG_PRINTF("%p", reinterpret_cast(s_pThis)); - DEBUG_EXIT -} +const char OscClientParamsConst::CMD[] = "cmd?"; +const char OscClientParamsConst::LED[] = "led?"; diff --git a/lib-configstore/src/storedmxsend.cpp b/lib-osc/src/client/oscclientsend.cpp old mode 100644 new mode 100755 similarity index 67% rename from lib-configstore/src/storedmxsend.cpp rename to lib-osc/src/client/oscclientsend.cpp index 66ff9fdc..33c4e626 --- a/lib-configstore/src/storedmxsend.cpp +++ b/lib-osc/src/client/oscclientsend.cpp @@ -1,8 +1,8 @@ /** - * @file storedmxsend.cpp + * @file oscclient.cpp * */ -/* Copyright (C) 2018-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,20 +23,35 @@ * THE SOFTWARE. */ +#include +#include #include -#include "storedmxsend.h" +#include "oscclient.h" +#include "oscsimplesend.h" +#include "osc.h" #include "debug.h" -StoreDmxSend *StoreDmxSend::s_pThis = nullptr; +void OscClient::Send(const char *pPath) { + DEBUG_ENTRY + + assert(pPath != nullptr); -StoreDmxSend::StoreDmxSend() { + if (*pPath != 0) { + OscSimpleSend MsgSend(m_nHandle, m_nServerIP, m_nPortOutgoing, pPath, nullptr); + } + + DEBUG_EXIT +} + +void OscClient::SendCmd(uint32_t nCmd) { DEBUG_ENTRY + DEBUG_PRINTF("nCmd=%d", nCmd); + + assert(nCmd < oscclient::max::CMD_COUNT); - assert(s_pThis == nullptr); - s_pThis = this; + Send(&m_pCmds[nCmd * oscclient::max::CMD_PATH_LENGTH]); - DEBUG_PRINTF("%p", reinterpret_cast(s_pThis)); DEBUG_EXIT } diff --git a/lib-osc/src/oscparamsconst.cpp b/lib-osc/src/oscparamsconst.cpp new file mode 100644 index 00000000..cb5db092 --- /dev/null +++ b/lib-osc/src/oscparamsconst.cpp @@ -0,0 +1,29 @@ +/** + * @file oscconst.cpp + * + */ +/* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "oscparamsconst.h" + +const char OscParamsConst::INCOMING_PORT[] = "incoming_port"; +const char OscParamsConst::OUTGOING_PORT[] = "outgoing_port"; diff --git a/lib-osc/src/oscsimplemessage.cpp b/lib-osc/src/oscsimplemessage.cpp new file mode 100644 index 00000000..49737001 --- /dev/null +++ b/lib-osc/src/oscsimplemessage.cpp @@ -0,0 +1,106 @@ +/** + * @file oscsimplemessage.cpp + * + */ +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "oscsimplemessage.h" +#include "osc.h" + +OscSimpleMessage::OscSimpleMessage(void *pData, unsigned nLength) : m_pOscMessage(reinterpret_cast(pData)), m_nLength(nLength) { + auto nResult = osc::string_validate(m_pOscMessage, m_nLength); + + if (nResult < 0) { + return; + } + + m_pArg = &m_pOscMessage[nResult]; + auto nDataOffset = static_cast(nResult); + + nResult = osc::string_validate(m_pArg, m_nLength - static_cast(nResult)); + + if ((nResult < 0) || (m_pArg[0] != ',')) { + return; + } + + // Support for 1 osc-string or blob only + if (((m_pArg[1] == 's') || (m_pArg[1] == 'b')) && (m_pArg[2] != '\0')) { + return; + } + + m_pArg++; // Skip ',' + m_nArgc = strlen(reinterpret_cast(m_pArg)); + + nDataOffset += static_cast(nResult); + + m_pOscMessageData = &m_pOscMessage[nDataOffset]; + m_nOscMessageDataLength = m_nLength - nDataOffset; + + m_bIsValid = true; +} + +float OscSimpleMessage::GetFloat(unsigned argc) { + union pcast32 { + int32_t i; + float f; + } osc_pcast32; + + if ((m_nOscMessageDataLength >= 4 * (1 + argc)) && (m_pArg[argc] == osc::type::FLOAT)) { + osc_pcast32.i = static_cast(__builtin_bswap32(*reinterpret_cast((4 * argc) + m_pOscMessageData))); + return osc_pcast32.f; + } + + return 0; +} + +int OscSimpleMessage::GetInt(unsigned argc) { + if ((m_nOscMessageDataLength >= 4 * (1 + argc)) && (m_pArg[argc] == osc::type::INT32)) { + return static_cast(__builtin_bswap32(*reinterpret_cast((4 * argc) + m_pOscMessageData))); + } + + return 0; +} + +char* OscSimpleMessage::GetString(__attribute__ ((unused)) unsigned argc) { + if ((m_pArg[0] == osc::type::STRING) && (m_nOscMessageDataLength == osc::string_size(reinterpret_cast(m_pOscMessageData)))) { + return reinterpret_cast(m_pOscMessageData); + } + + return nullptr; +} + +OSCBlob OscSimpleMessage::GetBlob(__attribute__ ((unused)) unsigned argc) { + if (m_pArg[0] == osc::type::BLOB) { + + const uint32_t nSize = __builtin_bswap32(*reinterpret_cast(m_pOscMessageData)); + const uint8_t *pData = reinterpret_cast(m_pOscMessageData) + 4; + + if ((nSize + 4) <= m_nOscMessageDataLength) { + return OSCBlob(pData, nSize); + } + } + + return OSCBlob(nullptr, 0); +} diff --git a/lib-osc/src/oscsimplesend.cpp b/lib-osc/src/oscsimplesend.cpp new file mode 100644 index 00000000..1b20a4e3 --- /dev/null +++ b/lib-osc/src/oscsimplesend.cpp @@ -0,0 +1,126 @@ +/** + * @file oscsimplesend.cpp + * + */ +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "oscsimplesend.h" +#include "osc.h" +#include "oscstring.h" + +#include "network.h" + +#include "debug.h" + +char OscSimpleSend::s_Message[osc::simple::send::BUFFER_SIZE]; + +// Support for path only +OscSimpleSend::OscSimpleSend(int32_t nHandle, uint32_t nIpAddress , uint16_t nPort, const char *pPath, const char *pType) { + if (pType == nullptr) { + const auto nPathLength = osc::string_size(pPath); + const auto nMessageLength = nPathLength + 4U; + + assert(nMessageLength < sizeof(s_Message)); + + UpdateMessage(pPath, nPathLength, 0); + Send(nMessageLength, nHandle, nIpAddress, nPort); + } +} + +// Support for 's' +OscSimpleSend::OscSimpleSend(int32_t nHandle, uint32_t nIpAddress , uint16_t nPort, const char *pPath, const char *pType, const char *pString) { + if ((pType != nullptr) && (*pType == 's')) { + const auto nPathLength = osc::string_size(pPath); + const auto nMessageLength = nPathLength + 4U + osc::string_size(pString); + + assert(nMessageLength < sizeof(s_Message)); + + UpdateMessage(pPath, nPathLength, 's'); + + memset(s_Message + nMessageLength - 4, 0, 4); + + assert((nPathLength + 4) < sizeof(s_Message)); + strncpy(&s_Message[nPathLength + 4], pString, sizeof(s_Message) - (nPathLength + 4)); + + Send(nMessageLength, nHandle, nIpAddress, nPort); + } +} + +// Support for type 'i' +OscSimpleSend::OscSimpleSend(int32_t nHandle, uint32_t nIpAddress , uint16_t nPort, const char *pPath, const char *pType, int nValue) { + if ((pType != nullptr) && (*pType == 'i')) { + const auto nPathLength = osc::string_size(pPath); + const auto nMessageLength = nPathLength + 4U + 4U; + + assert(nMessageLength < sizeof(s_Message)); + + UpdateMessage(pPath, nPathLength, 'i'); + + *reinterpret_cast(&s_Message[nMessageLength - 4]) = static_cast(__builtin_bswap32(static_cast(nValue))); + + Send(nMessageLength, nHandle, nIpAddress, nPort); + } +} + +// Support for type 'f' +OscSimpleSend::OscSimpleSend(int32_t nHandle, uint32_t nIpAddress , uint16_t nPort, const char *pPath, const char *pType, float fValue) { + if ((pType != nullptr) && (*pType == 'f')) { + const auto nPathLength = osc::string_size(pPath); + const auto nMessageLength = nPathLength + 4U + 4U; + + assert(nMessageLength < sizeof(s_Message)); + + UpdateMessage(pPath, nPathLength, 'f'); + + union pcast32 { + uint32_t u; + float f; + } osc_pcast32; + + osc_pcast32.f = fValue; + + *reinterpret_cast(&s_Message[nMessageLength - 4]) = static_cast(__builtin_bswap32(osc_pcast32.u)); + + Send(nMessageLength, nHandle, nIpAddress, nPort); + } +} + +void OscSimpleSend::UpdateMessage(const char *pPath, uint32_t nPathLength, char cType) { + memset(s_Message + nPathLength - 4, 0, 4); + strncpy(s_Message, pPath, sizeof(s_Message)); + + assert(nPathLength < sizeof(s_Message)); + + s_Message[nPathLength++] = ','; + s_Message[nPathLength++] = cType; + s_Message[nPathLength++] = '\0'; + s_Message[nPathLength++] = '\0'; +} + +void OscSimpleSend::Send(uint32_t nMessageLength, int32_t nHandle, uint32_t nIpAddress, uint16_t nPort) { + debug_dump(s_Message, nMessageLength); + + Network::Get()->SendTo(nHandle, s_Message, nMessageLength, nIpAddress, nPort); +} diff --git a/lib-osc/src/pattern_match.c b/lib-osc/src/pattern_match.c new file mode 100644 index 00000000..2cfe925e --- /dev/null +++ b/lib-osc/src/pattern_match.c @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2014 Steve Harris et al. (see AUTHORS) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + * + * $Id$ + */ + +/* This code was originally forked from: */ + +/* Open SoundControl kit in C++ */ +/* Copyright (C) 2002-2004 libOSC++ contributors. See AUTHORS */ +/* */ +/* This library is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Lesser General Public */ +/* License as published by the Free Software Foundation; either */ +/* version 2.1 of the License, or (at your option) any later version. */ +/* */ +/* This library 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 */ +/* Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public */ +/* License along with this library; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* */ +/* For questions regarding this program contact */ +/* Daniel Holth or visit */ +/* http://wiretap.stetson.edu/ */ + +/* In the sprit of the public domain, my modifications to this file are also */ +/* dedicated to the public domain. Daniel Holth, Oct. 2004 */ + +/* ChangeLog: + * + * 2004-10-29 Import, convert to C++, begin OSC syntax changes. -dwh + * OSC syntax changes are now working, needs more testing. + * + */ + +// Original header and syntax: + +/* + * robust glob pattern matcher + * ozan s. yigit/dec 1994 + * public domain + * + * glob patterns: + * * matches zero or more characters + * ? matches any single character + * [set] matches any character in the set + * [^set] matches any character NOT in the set + * where a set is a group of characters or ranges. a range + * is written as two characters seperated with a hyphen: a-z denotes + * all characters between a to z inclusive. + * [-set] set matches a literal hypen and any character in the set + * []set] matches a literal close bracket and any character in the set + * + * char matches itself except where char is '*' or '?' or '[' + * \char matches char, including any pattern character + * + * examples: + * a*c ac abc abbc ... + * a?c acc abc aXc ... + * a[a-z]c aac abc acc ... + * a[-a-z]c a-c aac abc ... + * + * $Log$ + * Revision 1.1 2004/11/19 23:00:57 theno23 + * Added lo_send_timestamped + * + * Revision 1.3 1995/09/14 23:24:23 oz + * removed boring test/main code. + * + * Revision 1.2 94/12/11 10:38:15 oz + * cset code fixed. it is now robust and interprets all + * variations of cset [i think] correctly, including [z-a] etc. + * + * Revision 1.1 94/12/08 12:45:23 oz + * Initial revision + */ + +//#include "lo/lo.h" + +#ifndef NEGATE +#define NEGATE '!' +#endif + +#ifndef true +#define true 1 +#endif +#ifndef false +#define false 0 +#endif + +int lo_pattern_match(const char *str, const char *p) +{ + int negate; + int match; + char c; + + while (*p) { + if (!*str && *p != '*') + return false; + + switch (c = *p++) { + + case '*': + while (*p == '*' && *p != '/') + p++; + + if (!*p) + return true; + +// if (*p != '?' && *p != '[' && *p != '\\') + if (*p != '?' && *p != '[' && *p != '{') + while (*str && *p != *str) + str++; + + while (*str) { + if (lo_pattern_match(str, p)) + return true; + str++; + } + return false; + + case '?': + if (*str) + break; + return false; + /* + * set specification is inclusive, that is [a-z] is a, z and + * everything in between. this means [z-a] may be interpreted + * as a set that contains z, a and nothing in between. + */ + case '[': + if (*p != NEGATE) + negate = false; + else { + negate = true; + p++; + } + + match = false; + + while (!match && (c = *p++)) { + if (!*p) + return false; + if (*p == '-') { /* c-c */ + if (!*++p) + return false; + if (*p != ']') { + if (*str == c || *str == *p || + (*str > c && *str < *p)) + match = true; + } else { /* c-] */ + if (*str >= c) + match = true; + break; + } + } else { /* cc or c] */ + if (c == *str) + match = true; + if (*p != ']') { + if (*p == *str) + match = true; + } else + break; + } + } + + if (negate == match) + return false; + /* + * if there is a match, skip past the cset and continue on + */ + while (*p && *p != ']') + p++; + if (!*p++) /* oops! */ + return false; + break; + + /* + * {astring,bstring,cstring} + */ + case '{': + { + // *p is now first character in the {brace list} + const char *place = str; // to backtrack + const char *remainder = p; // to forwardtrack + + // find the end of the brace list + while (*remainder && *remainder != '}') + remainder++; + if (!*remainder++) /* oops! */ + return false; + + c = *p++; + + while (c) { + if (c == ',') { + if (lo_pattern_match(str, remainder)) { + return true; + } else { + // backtrack on test string + str = place; + // continue testing, + // skip comma + if (!*p++) // oops + return false; + } + } else if (c == '}') { + // continue normal pattern matching + if (!*p && !*str) + return true; + str--; // str is incremented again below + break; + } else if (c == *str) { + str++; + if (!*str && *remainder) + return false; + } else { // skip to next comma + str = place; + while (*p != ',' && *p != '}' && *p) + p++; + if (*p == ',') + p++; + else if (*p == '}') { + return false; + } + } + c = *p++; + } + } + + break; + + /* Not part of OSC pattern matching + case '\\': + if (*p) + c = *p++; + */ + + default: + if (c != *str) + return false; + break; + + } + str++; + } + + return !*str; +} diff --git a/lib-osc/src/server/oscserver.cpp b/lib-osc/src/server/oscserver.cpp new file mode 100755 index 00000000..e52041d4 --- /dev/null +++ b/lib-osc/src/server/oscserver.cpp @@ -0,0 +1,400 @@ +/** + * @file oscserver.cpp + * + */ +/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include "oscserver.h" +#include "osc.h" +#include "oscsimplemessage.h" +#include "oscsimplesend.h" +#include "oscblob.h" + +#include "lightset.h" +#include "network.h" + +#include "hardware.h" + +#include "debug.h" + +#define OSCSERVER_DEFAULT_PATH_PRIMARY "/dmx1" +#define OSCSERVER_DEFAULT_PATH_SECONDARY OSCSERVER_DEFAULT_PATH_PRIMARY"/*" +#define OSCSERVER_DEFAULT_PATH_INFO "/2" +#define OSCSERVER_DEFAULT_PATH_BLACKOUT OSCSERVER_DEFAULT_PATH_PRIMARY "/blackout" + +#define SOFTWARE_VERSION "1.0" + +char OscServer::s_aPath[osc::server::Max::PATH_LENGTH]; +char OscServer::s_aPathSecond[osc::server::Max::PATH_LENGTH]; +char OscServer::s_aPathInfo[osc::server::Max::PATH_LENGTH]; +char OscServer::s_aPathBlackOut[osc::server::Max::PATH_LENGTH]; + +char *OscServer::s_pUdpBuffer; +uint8_t OscServer::s_pData[lightset::dmx::UNIVERSE_SIZE]; +uint8_t OscServer::s_pOsc[lightset::dmx::UNIVERSE_SIZE]; + +OscServer *OscServer::s_pThis; + +OscServer::OscServer() { + DEBUG_ENTRY + assert(s_pThis == nullptr); + s_pThis = this; + + memset(s_aPath, 0, sizeof(s_aPath)); + strcpy(s_aPath, OSCSERVER_DEFAULT_PATH_PRIMARY); + + memset(s_aPathSecond, 0, sizeof(s_aPathSecond)); + strcpy(s_aPathSecond, OSCSERVER_DEFAULT_PATH_SECONDARY); + + memset(s_aPathInfo, 0, sizeof(s_aPathInfo)); + strcpy(s_aPathInfo, OSCSERVER_DEFAULT_PATH_INFO); + + memset(s_aPathBlackOut, 0, sizeof(s_aPathBlackOut)); + strcpy(s_aPathBlackOut, OSCSERVER_DEFAULT_PATH_BLACKOUT); + + snprintf(m_Os, sizeof(m_Os) - 1, "[V%s] %s", SOFTWARE_VERSION, __DATE__); + + uint8_t nHwTextLength; + m_pModel = Hardware::Get()->GetBoardName(nHwTextLength); + m_pSoC = Hardware::Get()->GetSocName(nHwTextLength); + + if (m_pSoC[0] == '\0') { + m_pSoC = Hardware::Get()->GetCpuName(nHwTextLength); + } + + DEBUG_EXIT +} + +OscServer::~OscServer() { + DEBUG_ENTRY + + DEBUG_EXIT +} + +void OscServer::Start() { + DEBUG_ENTRY + + m_nHandle = Network::Get()->Begin(m_nPortIncoming); + assert(m_nHandle != -1); + + OscSimpleSend MsgSend(m_nHandle, Network::Get()->GetIp() | ~(Network::Get()->GetNetmask()), m_nPortIncoming, "/ping", nullptr); + + Hardware::Get()->SetMode(hardware::ledblink::Mode::NORMAL); + + DEBUG_EXIT +} + +void OscServer::Stop() { + if (m_pLightSet != nullptr) { + m_pLightSet->Stop(0); + } +} + +void OscServer::SetPath(const char* pPath) { + if (*pPath == '/') { + auto nLength = sizeof(s_aPath) - 3; // We need space for '\0' and "/*" + strncpy(s_aPath, pPath, nLength); + s_aPath[sizeof(s_aPath) - 1] = '\0'; + + nLength = strlen(s_aPath); + + if (s_aPath[nLength - 1] == '/') { + s_aPath[nLength - 1] = '\0'; + } + + strncpy(s_aPathSecond, s_aPath, sizeof(s_aPathSecond) - 3); + + nLength = strlen(s_aPathSecond); + assert(nLength < (sizeof(s_aPathSecond) - 3)); + + s_aPathSecond[nLength++] = '/'; + s_aPathSecond[nLength++] = '*'; + s_aPathSecond[nLength] = '\0'; + } + + DEBUG_PUTS(s_aPath); + DEBUG_PUTS(s_aPathSecond); +} + +void OscServer::SetPathInfo(const char* pPathInfo) { + if (*pPathInfo == '/') { + strncpy(s_aPathInfo, pPathInfo, sizeof(s_aPathInfo)); + s_aPathInfo[sizeof(s_aPathInfo) - 1] = '\0'; + + auto nLength = strlen(s_aPathInfo); + + if (s_aPathInfo[nLength - 1] == '/') { + s_aPathInfo[nLength - 1] = '\0'; + } + } + + DEBUG_PUTS(s_aPathInfo); +} + +void OscServer::SetPathBlackOut(const char* pPathBlackOut) { + if (*pPathBlackOut == '/') { + strncpy(s_aPathBlackOut, pPathBlackOut, sizeof(s_aPathInfo)); + s_aPathBlackOut[sizeof(s_aPathInfo) - 1] = '\0'; + + auto nLength = strlen(s_aPathBlackOut); + + if (s_aPathBlackOut[nLength - 1] == '/') { + s_aPathBlackOut[nLength - 1] = '\0'; + } + } + + DEBUG_PUTS(s_aPathBlackOut); +} + +int OscServer::GetChannel(const char* p) { + assert(p != nullptr); + + auto *s = const_cast(p) + strlen(s_aPath) + 1; + int nChannel = 0; + int i; + + for (i = 0; (i < 3) && (*s != '\0'); i++) { + int c = *s; + + if ((c < '0') || (c > '9')) { + return -1; + } + + nChannel = nChannel * 10 + c - '0'; + s++; + } + + if (nChannel > static_cast(lightset::dmx::UNIVERSE_SIZE)) { + return -1; + } + + return nChannel; +} + +bool OscServer::IsDmxDataChanged(const uint8_t* pData, uint16_t nStartChannel, uint32_t nLength) { + assert(pData != nullptr); + assert(nLength <= lightset::dmx::UNIVERSE_SIZE); + + auto isChanged = false; + const auto *src = pData; + auto *dst = &s_pData[--nStartChannel]; + const auto nEnd = nStartChannel + nLength; + + assert(nEnd <= lightset::dmx::UNIVERSE_SIZE); + + for (uint32_t i = nStartChannel; i < nEnd; i++) { + if (*dst != *src) { + *dst = *src; + isChanged = true; + } + dst++; + src++; + } + + return isChanged; +} + +void OscServer::Run() { + uint32_t nRemoteIp; + uint16_t nRemotePort; + + const auto nBytesReceived = Network::Get()->RecvFrom(m_nHandle, const_cast(reinterpret_cast(&s_pUdpBuffer)), &nRemoteIp, &nRemotePort); + + if (__builtin_expect((nBytesReceived == 0), 1)) { + return; + } + + auto bIsDmxDataChanged = false; + + OscSimpleMessage Msg(s_pUdpBuffer, nBytesReceived); + + debug_dump(s_pUdpBuffer, nBytesReceived); + + DEBUG_PRINTF("[%d] path : %s", nBytesReceived, osc::get_path(s_pUdpBuffer, nBytesReceived)); + + if (osc::is_match(s_pUdpBuffer, s_aPath)) { + const auto nArgc = Msg.GetArgc(); + + if ((nArgc == 1) && (Msg.GetType(0) == osc::type::BLOB)) { + DEBUG_PUTS("Blob received"); + + OSCBlob blob = Msg.GetBlob(0); + const auto size = static_cast(blob.GetDataSize()); + + if (size <= lightset::dmx::UNIVERSE_SIZE) { + const auto *ptr = blob.GetDataPtr(); + + bIsDmxDataChanged = IsDmxDataChanged(ptr, 1, size); + + if (bIsDmxDataChanged || m_bEnableNoChangeUpdate) { + if ((!m_bPartialTransmission) || (size == lightset::dmx::UNIVERSE_SIZE)) { + m_pLightSet->SetData(0, s_pData, lightset::dmx::UNIVERSE_SIZE); + } else { + m_nLastChannel = static_cast(size > m_nLastChannel ? size : m_nLastChannel); + m_pLightSet->SetData(0, s_pData, m_nLastChannel); + } + + if (!m_bIsRunning) { + m_bIsRunning = true; + m_pLightSet->Start(0); + } + } + } else { + DEBUG_PUTS("Too many channels"); + return; + } + } else if ((nArgc == 2) && (Msg.GetType(0) == osc::type::INT32)) { + auto nChannel = static_cast(1 + Msg.GetInt(0)); + + if ((nChannel < 1) || (nChannel > lightset::dmx::UNIVERSE_SIZE)) { + DEBUG_PRINTF("Invalid channel [%d]", nChannel); + return; + } + + uint8_t nData; + + if (Msg.GetType(1) == osc::type::INT32) { + DEBUG_PUTS("ii received"); + nData = static_cast(Msg.GetInt(1)); + } else if (Msg.GetType(1) == osc::type::FLOAT) { + DEBUG_PUTS("if received"); + nData = static_cast(Msg.GetFloat(1) * lightset::dmx::MAX_VALUE); + } else { + return; + } + + DEBUG_PRINTF("Channel = %d, Data = %.2x", nChannel, nData); + + bIsDmxDataChanged = IsDmxDataChanged(&nData, nChannel, 1); + + if (bIsDmxDataChanged || m_bEnableNoChangeUpdate) { + if (!m_bPartialTransmission) { + m_pLightSet->SetData(0, s_pData, lightset::dmx::UNIVERSE_SIZE); + } else { + m_nLastChannel = nChannel > m_nLastChannel ? nChannel : m_nLastChannel; + m_pLightSet->SetData(0, s_pData, m_nLastChannel); + } + + if (!m_bIsRunning) { + m_bIsRunning = true; + m_pLightSet->Start(0); + } + } + } + + return; + } + + if ((m_pOscServerHandler != nullptr) && (osc::is_match(s_pUdpBuffer, s_aPathBlackOut))) { + OscSimpleMessage Msg(s_pUdpBuffer, nBytesReceived); + + if (Msg.GetType(0) != osc::type::FLOAT) { + DEBUG_PUTS("No float"); + return; + } + + if (Msg.GetFloat(0) != 0) { + m_pOscServerHandler->Blackout(); + DEBUG_PUTS("Blackout"); + } else { + m_pOscServerHandler->Update(); + DEBUG_PUTS("Update"); + } + + return; + } + + if (osc::is_match(s_pUdpBuffer, s_aPathSecond)) { + const auto nArgc = Msg.GetArgc(); + + if (nArgc == 1) { // /path/N 'i' or 'f' + const auto nChannel = static_cast(GetChannel(s_pUdpBuffer)); + + if (nChannel >= 1 && nChannel <= lightset::dmx::UNIVERSE_SIZE) { + uint8_t nData; + + if (Msg.GetType(0) == osc::type::INT32) { + DEBUG_PUTS("i received"); + nData = static_cast(Msg.GetInt(0)); + } else if (Msg.GetType(0) == osc::type::FLOAT) { + DEBUG_PRINTF("f received %f", Msg.GetFloat(0)); + nData = static_cast(Msg.GetFloat(0) * lightset::dmx::MAX_VALUE); + } else { + return; + } + + DEBUG_PRINTF("Channel = %d, Data = %.2x", nChannel, nData); + + bIsDmxDataChanged = IsDmxDataChanged(&nData, nChannel, 1); + + if (bIsDmxDataChanged || m_bEnableNoChangeUpdate) { + if (!m_bPartialTransmission) { + m_pLightSet->SetData(0, s_pData, lightset::dmx::UNIVERSE_SIZE); + } else { + m_nLastChannel = nChannel > m_nLastChannel ? nChannel : m_nLastChannel; + m_pLightSet->SetData(0, s_pData, m_nLastChannel); + } + + if (!m_bIsRunning) { + m_bIsRunning = true; + m_pLightSet->Start(0); + } + } + } + } + + return; + } + + if (osc::is_match(s_pUdpBuffer, "/ping")) { + DEBUG_PUTS("ping received"); + OscSimpleSend MsgSend(m_nHandle, nRemoteIp, m_nPortOutgoing, "/pong", nullptr); + + return; + } + + if (osc::is_match(s_pUdpBuffer, s_aPathInfo)) { + OscSimpleSend MsgSendInfo(m_nHandle, nRemoteIp, m_nPortOutgoing, "/info/os", "s", m_Os); + OscSimpleSend MsgSendModel(m_nHandle, nRemoteIp, m_nPortOutgoing, "/info/model", "s", m_pModel); + OscSimpleSend MsgSendSoc(m_nHandle, nRemoteIp, m_nPortOutgoing, "/info/soc", "s", m_pSoC); + + if (m_pOscServerHandler != nullptr) { + m_pOscServerHandler->Info(m_nHandle, nRemoteIp, m_nPortOutgoing); + } + + return; + } +} + +void OscServer::Print() { + puts("OSC Server"); + printf(" Incoming Port : %d\n", m_nPortIncoming); + printf(" Outgoing Port : %d\n", m_nPortOutgoing); + printf(" DMX Path : [%s][%s]\n", s_aPath, s_aPathSecond); + printf(" Blackout Path : [%s]\n", s_aPathBlackOut); + printf(" Partial Transmission : %s\n", m_bPartialTransmission ? "Yes" : "No"); +} diff --git a/lib-lightset/src/lightsetgetslotinfo.cpp b/lib-osc/src/server/oscserverconst.cpp old mode 100644 new mode 100755 similarity index 76% rename from lib-lightset/src/lightsetgetslotinfo.cpp rename to lib-osc/src/server/oscserverconst.cpp index 392fa6cc..0e1e17ac --- a/lib-lightset/src/lightsetgetslotinfo.cpp +++ b/lib-osc/src/server/oscserverconst.cpp @@ -1,8 +1,8 @@ /** - * @file lightset.cpp + * @file oscserverconst.cpp * */ -/* Copyright (C) 2016-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,12 +23,8 @@ * THE SOFTWARE. */ -#include "lightset.h" +#include "oscserverconst.h" -using namespace lightset; - -bool LightSet::GetSlotInfo(__attribute__((unused)) uint16_t nSlot, SlotInfo &tSlotInfo) { - tSlotInfo.nType = 0x00; // ST_PRIMARY - tSlotInfo.nCategory = 0x0001; // SD_INTENSITY - return true; -} +const char OSCServerConst::MSG_BRIDGE_PARAMS[] = "Setting Bridge parameters"; +const char OSCServerConst::MSG_BRIDGE_START[] = "Starting the Bridge"; +const char OSCServerConst::MSG_BRIDGE_STARTED[] = "Bridge started"; diff --git a/lib-osc/src/server/oscservermsgconst.cpp b/lib-osc/src/server/oscservermsgconst.cpp new file mode 100755 index 00000000..457c606d --- /dev/null +++ b/lib-osc/src/server/oscservermsgconst.cpp @@ -0,0 +1,30 @@ +/** + * @file oscclientconst.h + * + */ +/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "oscservermsgconst.h" + +const char OscServerMsgConst::PARAMS[] = "Configuring OSC Server"; +const char OscServerMsgConst::START[] = "Starting the OSC Server"; +const char OscServerMsgConst::STARTED[] = "OSC Server started"; diff --git a/lib-osc/src/server/oscserverparams.cpp b/lib-osc/src/server/oscserverparams.cpp new file mode 100755 index 00000000..27d93b40 --- /dev/null +++ b/lib-osc/src/server/oscserverparams.cpp @@ -0,0 +1,241 @@ +/** + * @file oscserverparams.cpp + * + */ +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if !defined(__clang__) // Needed for compiling on MacOS +# pragma GCC push_options +# pragma GCC optimize ("Os") +#endif + +#include +#include +#ifndef NDEBUG +# include +#endif +#include + +#include "oscserverparams.h" +#include "oscserverparamsconst.h" +#include "osc.h" +#include "oscparamsconst.h" + +#include "lightsetparamsconst.h" + +#include "readconfigfile.h" +#include "sscan.h" +#include "propertiesbuilder.h" + +#include "debug.h" + +using namespace osc::server; + +OSCServerParams::OSCServerParams() { + DEBUG_ENTRY + + memset(&m_Params, 0, sizeof(struct Params)); + m_Params.nIncomingPort = osc::port::DEFAULT_INCOMING; + m_Params.nOutgoingPort = osc::port::DEFAULT_OUTGOING; + + DEBUG_EXIT +} + +void OSCServerParams::Load() { + DEBUG_ENTRY + + m_Params.nSetList = 0; + +#if !defined(DISABLE_FS) + ReadConfigFile configfile(OSCServerParams::staticCallbackFunction, this); + + if (configfile.Read(OscServerParamsConst::FILE_NAME)) { + StoreOscServer::Update(&m_Params); + } else +#endif + StoreOscServer::Copy(&m_Params); + +#ifndef NDEBUG + Dump(); +#endif + DEBUG_EXIT +} + +void OSCServerParams::Load(const char* pBuffer, uint32_t nLength) { + DEBUG_ENTRY + + assert(pBuffer != nullptr); + assert(nLength != 0); + + m_Params.nSetList = 0; + + ReadConfigFile config(OSCServerParams::staticCallbackFunction, this); + + config.Read(pBuffer, nLength); + + StoreOscServer::Update(&m_Params); + +#ifndef NDEBUG + Dump(); +#endif + DEBUG_EXIT +} + +void OSCServerParams::callbackFunction(const char *pLine) { + assert(pLine != nullptr); + + uint16_t nValue16; + + if (Sscan::Uint16(pLine, OscParamsConst::INCOMING_PORT, nValue16) == Sscan::OK) { + if (nValue16 > 1023) { + m_Params.nIncomingPort = nValue16; + m_Params.nSetList |= ParamsMask::INCOMING_PORT; + } else { + m_Params.nIncomingPort = osc::port::DEFAULT_INCOMING; + m_Params.nSetList &= ~ParamsMask::INCOMING_PORT; + } + return; + } + + if (Sscan::Uint16(pLine, OscParamsConst::OUTGOING_PORT, nValue16) == Sscan::OK) { + if (nValue16 > 1023) { + m_Params.nOutgoingPort = nValue16; + m_Params.nSetList |= ParamsMask::OUTGOING_PORT; + } else { + m_Params.nOutgoingPort = osc::port::DEFAULT_OUTGOING; + m_Params.nSetList &= ~ParamsMask::OUTGOING_PORT; + } + return; + } + + uint8_t nValue8; + + if (Sscan::Uint8(pLine, OscServerParamsConst::TRANSMISSION, nValue8) == Sscan::OK) { + if (nValue8 != 0) { + m_Params.nSetList |= ParamsMask::TRANSMISSION; + } else { + m_Params.nSetList &= ~ParamsMask::TRANSMISSION; + } + m_Params.bPartialTransmission = (nValue8 != 0); + return; + } + + uint32_t nLength = sizeof(m_Params.aPath) - 1; + if (Sscan::Char(pLine, OscServerParamsConst::PATH, m_Params.aPath, nLength) == Sscan::OK) { + m_Params.nSetList |= ParamsMask::PATH; + return; + } + + nLength = sizeof(m_Params.aPathInfo) - 1; + if (Sscan::Char(pLine, OscServerParamsConst::PATH_INFO, m_Params.aPathInfo, nLength) == Sscan::OK) { + m_Params.nSetList |= ParamsMask::PATH_INFO; + return; + } + + nLength = sizeof(m_Params.aPathBlackOut) - 1; + if (Sscan::Char(pLine, OscServerParamsConst::PATH_INFO, m_Params.aPathBlackOut, nLength) == Sscan::OK) { + m_Params.nSetList |= ParamsMask::PATH_BLACKOUT; + return; + } +} + +void OSCServerParams::Set(OscServer *pOscServer) { + assert(pOscServer != nullptr); + + if (isMaskSet(ParamsMask::INCOMING_PORT)) { + pOscServer->SetPortIncoming(m_Params.nIncomingPort); + } + + if (isMaskSet(ParamsMask::OUTGOING_PORT)) { + pOscServer->SetPortOutgoing(m_Params.nOutgoingPort); + } + + if (isMaskSet(ParamsMask::PATH)) { + pOscServer->SetPath(m_Params.aPath); + } + + if (isMaskSet(ParamsMask::PATH_INFO)) { + pOscServer->SetPathInfo(m_Params.aPathInfo); + } + + if (isMaskSet(ParamsMask::PATH_BLACKOUT)) { + pOscServer->SetPathBlackOut(m_Params.aPathBlackOut); + } + + if (isMaskSet(ParamsMask::TRANSMISSION)) { + pOscServer->SetPartialTransmission(m_Params.bPartialTransmission); + } +} + +void OSCServerParams::Builder(const osc::server::Params *ptOSCServerParams, char *pBuffer, uint32_t nLength, uint32_t& nSize) { + DEBUG_ENTRY + + assert(pBuffer != nullptr); + + if (ptOSCServerParams != nullptr) { + memcpy(&m_Params, ptOSCServerParams, sizeof(osc::server::Params)); + } else { + StoreOscServer::Copy(&m_Params); + } + + PropertiesBuilder builder(OscServerParamsConst::FILE_NAME, pBuffer, nLength); + + if (!isMaskSet(ParamsMask::PATH)) { + strncpy(m_Params.aPath, OscServer::Get()->GetPath(), sizeof(m_Params.aPath) - 1); + } + + if (!isMaskSet(ParamsMask::PATH_INFO)) { + strncpy(m_Params.aPathInfo, OscServer::Get()->GetPathInfo(), sizeof(m_Params.aPathInfo) - 1); + } + + if (!isMaskSet(ParamsMask::PATH_BLACKOUT)) { + strncpy(m_Params.aPathBlackOut, OscServer::Get()->GetPathBlackOut(), sizeof(m_Params.aPathBlackOut) - 1); + } + + builder.Add(OscParamsConst::INCOMING_PORT, m_Params.nIncomingPort, isMaskSet(ParamsMask::INCOMING_PORT)); + builder.Add(OscParamsConst::OUTGOING_PORT, m_Params.nOutgoingPort, isMaskSet(ParamsMask::OUTGOING_PORT)); + builder.Add(OscServerParamsConst::PATH, m_Params.aPath, isMaskSet(ParamsMask::PATH)); + builder.Add(OscServerParamsConst::PATH_INFO, m_Params.aPathInfo, isMaskSet(ParamsMask::PATH_INFO)); + builder.Add(OscServerParamsConst::PATH_BLACKOUT, m_Params.aPathBlackOut, isMaskSet(ParamsMask::PATH_BLACKOUT)); + builder.Add(OscServerParamsConst::TRANSMISSION, m_Params.bPartialTransmission, isMaskSet(ParamsMask::TRANSMISSION)); + + nSize = builder.GetSize(); + + DEBUG_EXIT +} + +void OSCServerParams::staticCallbackFunction(void *p, const char *s) { + assert(p != nullptr); + assert(s != nullptr); + + (static_cast(p))->callbackFunction(s); +} + +void OSCServerParams::Dump() { + printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, OscServerParamsConst::FILE_NAME); + printf(" %s=%d\n", OscParamsConst::INCOMING_PORT, m_Params.nIncomingPort); + printf(" %s=%d\n", OscParamsConst::OUTGOING_PORT, m_Params.nOutgoingPort); + printf(" %s=%s\n", OscServerParamsConst::PATH, m_Params.aPath); + printf(" %s=%s\n", OscServerParamsConst::PATH_INFO, m_Params.aPathInfo); + printf(" %s=%s\n", OscServerParamsConst::PATH_BLACKOUT, m_Params.aPathBlackOut); + printf(" %s=%d\n", OscServerParamsConst::TRANSMISSION, m_Params.bPartialTransmission); +} diff --git a/lib-osc/src/server/oscserverparamsconst.cpp b/lib-osc/src/server/oscserverparamsconst.cpp new file mode 100755 index 00000000..e31ee24e --- /dev/null +++ b/lib-osc/src/server/oscserverparamsconst.cpp @@ -0,0 +1,34 @@ +/** + * @file oscserverparamsconst.cpp + * + */ +/* Copyright (C) 2022 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "oscserverparamsconst.h" + +const char OscServerParamsConst::FILE_NAME[] = "osc.txt"; + +const char OscServerParamsConst::PATH[] = "path"; +const char OscServerParamsConst::PATH_INFO[] = "path_info"; +const char OscServerParamsConst::PATH_BLACKOUT[] = "path_blackout"; + +const char OscServerParamsConst::TRANSMISSION[] = "partial_transmission"; diff --git a/lib-pp/.cproject b/lib-pp/.cproject index ef3f9a39..51a83123 100755 --- a/lib-pp/.cproject +++ b/lib-pp/.cproject @@ -33,11 +33,9 @@ - diff --git a/lib-pp/Rules.mk b/lib-pp/Rules.mk index a6be369d..5f30977a 100644 --- a/lib-pp/Rules.mk +++ b/lib-pp/Rules.mk @@ -6,5 +6,4 @@ else DEFINES+=LIGHTSET_PORTS=32 endif -EXTRA_INCLUDES =../lib-properties/include ../lib-hal/include ../lib-network/include -EXTRA_INCLUDES+=../lib-lightset/include +EXTRA_INCLUDES =../lib-properties/include ../lib-network/include ../lib-lightset/include diff --git a/lib-pp/src/pp.cpp b/lib-pp/src/pp.cpp index d255af4c..948e7810 100644 --- a/lib-pp/src/pp.cpp +++ b/lib-pp/src/pp.cpp @@ -195,7 +195,7 @@ void PixelPusher::Run() { #endif } -void PixelPusher::HandlePusherCommand(__attribute__((unused)) const uint8_t *pBuffer, __attribute__((unused)) uint32_t nSize) { +void PixelPusher::HandlePusherCommand([[maybe_unused]] const uint8_t *pBuffer, [[maybe_unused]] uint32_t nSize) { DEBUG_ENTRY DEBUG_PRINTF("pBuffer=%p, nSize=%u", reinterpret_cast(pBuffer), nSize); #if !defined(CONFIG_PP_16BITSTUFF) @@ -207,7 +207,7 @@ void PixelPusher::HandlePusherCommand(__attribute__((unused)) const uint8_t *pBu #include void PixelPusher::Print() { - puts("PixelPusher:"); + puts("PixelPusher"); printf(" Count : %u\n", m_nCount); printf(" Channels per pixel: %u\n", pp::configuration::CHANNELS_PER_PIXEL); printf(" Active ports : %u\n", m_nActivePorts); diff --git a/lib-properties/.cproject b/lib-properties/.cproject index d5f5c8c6..a24b26c9 100644 --- a/lib-properties/.cproject +++ b/lib-properties/.cproject @@ -30,11 +30,9 @@ - diff --git a/lib-properties/include/devicesparamsconst.h b/lib-properties/include/devicesparamsconst.h index 0d8059dc..2d65ff79 100644 --- a/lib-properties/include/devicesparamsconst.h +++ b/lib-properties/include/devicesparamsconst.h @@ -2,7 +2,7 @@ * @file devicesparamsconst.h * */ -/* Copyright (C) 2019-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,8 +36,6 @@ struct DevicesParamsConst { static const char LED_T1H[]; static const char COUNT[]; - - static const char GROUPING_ENABLED[]; static const char GROUPING_COUNT[]; static const char SPI_SPEED_HZ[]; diff --git a/lib-properties/include/propertiesbuilder.h b/lib-properties/include/propertiesbuilder.h index 0deb359f..79ca861b 100644 --- a/lib-properties/include/propertiesbuilder.h +++ b/lib-properties/include/propertiesbuilder.h @@ -2,7 +2,7 @@ * @file propertiesbuilder.h * */ -/* Copyright (C) 2019-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,7 +38,7 @@ class PropertiesBuilder { } template - bool Add(const char *pProperty, const T x, bool bIsSet, uint32_t nPrecision = 1) { + bool Add(const char *pProperty, const T x, bool bIsSet, int nPrecision = 1) { if (m_nSize >= m_nLength) { return false; } @@ -57,7 +57,7 @@ class PropertiesBuilder { return true; } - template int inline add_part(char *p, uint32_t nSize, const char *pProperty, const T x, bool bIsSet, __attribute__((unused)) uint32_t nPrecision) { + template int inline add_part(char *p, uint32_t nSize, const char *pProperty, const T x, bool bIsSet, [[maybe_unused]] int nPrecision) { if (bIsSet || m_bJson) { if (m_bJson) { return snprintf(p, nSize, "\"%s\":%d,", pProperty, static_cast(x)); @@ -88,8 +88,12 @@ class PropertiesBuilder { return AddHex(pProperty, nValue32, bIsSet, 6); } + bool AddUtcOffset(const char *pProperty, const int8_t nHours, const uint8_t nMinutes); + bool AddComment(const char *pComment); + bool AddRaw(const char *pRaw); + uint16_t GetSize() { if (m_bJson) { m_pBuffer[m_nSize - 1] = '}'; @@ -100,7 +104,7 @@ class PropertiesBuilder { } private: - bool AddHex(const char *pProperty, uint32_t nValue, const bool bIsSet, const uint32_t nWidth); + bool AddHex(const char *pProperty, uint32_t nValue, const bool bIsSet, const int nWidth); private: char *m_pBuffer; @@ -109,7 +113,7 @@ class PropertiesBuilder { bool m_bJson; }; -template<> int inline PropertiesBuilder::add_part(char *p, uint32_t nSize, const char *pProperty, const float x, bool bIsSet, uint32_t nPrecision) { +template<> int inline PropertiesBuilder::add_part(char *p, uint32_t nSize, const char *pProperty, const float x, bool bIsSet, int nPrecision) { if (bIsSet || m_bJson) { if (m_bJson) { return snprintf(p, nSize, "\"%s\":%.*f,", pProperty, nPrecision, x); @@ -121,7 +125,7 @@ template<> int inline PropertiesBuilder::add_part(char *p, uint32_t nSize return snprintf(p, nSize, "#%s=%.*f\n", pProperty, nPrecision, x); } -template<> int inline PropertiesBuilder::add_part(char *p, uint32_t nSize, const char *pProperty, char* x, bool bIsSet, __attribute__((unused)) uint32_t nPrecision) { +template<> int inline PropertiesBuilder::add_part(char *p, uint32_t nSize, const char *pProperty, char* x, bool bIsSet, [[maybe_unused]] int nPrecision) { if (bIsSet || m_bJson) { if (m_bJson) { return snprintf(p, nSize, "\"%s\":\"%s\",", pProperty, x); @@ -133,7 +137,7 @@ template<> int inline PropertiesBuilder::add_part(char *p, uint32_t nSize return snprintf(p, nSize, "#%s=%s\n", pProperty, x); } -template<> int inline PropertiesBuilder::add_part(char *p, uint32_t nSize, const char *pProperty, const char* x, bool bIsSet, uint32_t nPrecision) { +template<> int inline PropertiesBuilder::add_part(char *p, uint32_t nSize, const char *pProperty, const char* x, bool bIsSet, int nPrecision) { return PropertiesBuilder::add_part(p, nSize, pProperty, const_cast(x), bIsSet, nPrecision); } diff --git a/lib-properties/include/readconfigfile.h b/lib-properties/include/readconfigfile.h index 264c0906..76eeb645 100644 --- a/lib-properties/include/readconfigfile.h +++ b/lib-properties/include/readconfigfile.h @@ -1,7 +1,7 @@ /** * @file readconfigfile.h */ -/* Copyright (C) 2017-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-properties/include/sscan.h b/lib-properties/include/sscan.h index 6435a04c..928b73d2 100644 --- a/lib-properties/include/sscan.h +++ b/lib-properties/include/sscan.h @@ -2,7 +2,7 @@ * @file sscan.h * */ -/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -51,6 +51,7 @@ class Sscan { static ReturnCode I2c(const char *pBuffer, char *pName, uint8_t& nLength, uint8_t& nAddress, uint8_t& nReserved); static ReturnCode Spi(const char *pBuffer, char& nChipSelect, char *pName, uint8_t& nLength, uint8_t& nAddress, uint16_t &nDmxStartAddress, uint32_t &nSpeedHz); + static ReturnCode UtcOffset(const char *pBuffer, const char *pName, int8_t& nHours, uint8_t& nMinutes); private: static uint8_t fromHex(const char Hex[2]); static const char *checkName(const char *pBuffer, const char *pName); diff --git a/lib-properties/src/devicesparamsconst.cpp b/lib-properties/src/devicesparamsconst.cpp index d32e554a..039acff2 100644 --- a/lib-properties/src/devicesparamsconst.cpp +++ b/lib-properties/src/devicesparamsconst.cpp @@ -2,7 +2,7 @@ * @file devicesparamsconst.cpp * */ -/* Copyright (C) 2019-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,8 +35,6 @@ const char DevicesParamsConst::LED_T0H[] = "led_t0h"; const char DevicesParamsConst::LED_T1H[] = "led_t1h"; const char DevicesParamsConst::COUNT[] = "led_count"; - -const char DevicesParamsConst::GROUPING_ENABLED[] = "led_grouping"; const char DevicesParamsConst::GROUPING_COUNT[] = "led_group_count"; const char DevicesParamsConst::SPI_SPEED_HZ[] = "clock_speed_hz"; diff --git a/lib-properties/src/properties.cpp b/lib-properties/src/properties.cpp index 5aa4caa0..a9017b92 100644 --- a/lib-properties/src/properties.cpp +++ b/lib-properties/src/properties.cpp @@ -2,7 +2,7 @@ * @file properties.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -124,17 +124,17 @@ int convert_json_file(char *pBuffer, uint32_t nLength, const bool bSkipFileName) } if ((*pSrc == '"') || (*pSrc == ',') || (*pSrc == '}')) { - if (!bSkipFileName) { - *pDst++ = '\n'; - } else { - *pDst++ = '\0'; - } + *pDst++ = '\n'; nNewLength++; } pSrc++; } + if (bSkipFileName) { + nNewLength--; + } + debug_dump(pBuffer, static_cast(nNewLength)); DEBUG_EXIT return static_cast(nNewLength); diff --git a/lib-properties/src/propertiesbuilder.cpp b/lib-properties/src/propertiesbuilder.cpp index a2803a75..054f1c0c 100644 --- a/lib-properties/src/propertiesbuilder.cpp +++ b/lib-properties/src/propertiesbuilder.cpp @@ -100,6 +100,32 @@ bool PropertiesBuilder::AddIpAddress(const char *pProperty, uint32_t nValue, boo return true; } +bool PropertiesBuilder::AddUtcOffset(const char *pProperty, const int8_t nHours, const uint8_t nMinutes) { + if (m_nSize >= m_nLength) { + return false; + } + + auto *p = &m_pBuffer[m_nSize]; + const auto nSize = static_cast(m_nLength - m_nSize); + + int i; + + if (m_bJson) { + i = snprintf(p, nSize, "\"%s\":\"%s%.2d:%.2u\",", pProperty, nHours > 0 ? "+" : "", nHours, nMinutes); + } else { + i = snprintf(p, nSize, "%s=%s%.2d:%.2u", pProperty, nHours > 0 ? "+" : "", nHours, nMinutes); + } + + if (i > static_cast(nSize)) { + return false; + } + + m_nSize = static_cast(m_nSize + i); + + DEBUG_PRINTF("m_nLength=%d, m_nSize=%d", m_nLength, m_nSize); + return true; +} + bool PropertiesBuilder::AddComment(const char *pComment) { if (m_bJson) { return true; @@ -124,3 +150,28 @@ bool PropertiesBuilder::AddComment(const char *pComment) { return true; } + +bool PropertiesBuilder::AddRaw(const char *pRaw) { + if (m_bJson) { + return true; + } + + if (m_nSize >= m_nLength) { + return false; + } + + auto *p = &m_pBuffer[m_nSize]; + const auto nSize = static_cast(m_nLength - m_nSize); + + const auto i = snprintf(p, nSize, "%s\n", pRaw); + + if (i > static_cast(nSize)) { + return false; + } + + m_nSize = static_cast(m_nSize + i); + + DEBUG_PRINTF("pRaw=%s, m_nLength=%d, m_nSize=%d", pRaw, m_nLength, m_nSize); + + return true; +} diff --git a/lib-properties/src/propertiesbuilderaddhex.cpp b/lib-properties/src/propertiesbuilderaddhex.cpp index 1b30e950..da71d8fa 100644 --- a/lib-properties/src/propertiesbuilderaddhex.cpp +++ b/lib-properties/src/propertiesbuilderaddhex.cpp @@ -2,7 +2,7 @@ * @file propertiesbuilderaddhex.cpp * */ -/* Copyright (C) 2020-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,13 +30,14 @@ #include #include +#include #include #include "propertiesbuilder.h" #include "debug.h" -bool PropertiesBuilder::AddHex(const char *pProperty, uint32_t nValue, const bool bIsSet, const uint32_t nWidth) { +bool PropertiesBuilder::AddHex(const char *pProperty, uint32_t nValue, const bool bIsSet, const int nWidth) { if (m_nSize >= m_nLength) { return false; } @@ -48,12 +49,12 @@ bool PropertiesBuilder::AddHex(const char *pProperty, uint32_t nValue, const boo if (bIsSet || m_bJson) { if (m_bJson) { - i = snprintf(p, nSize, "\"%s\":\"%.*x\",", pProperty, nWidth, nValue); + i = snprintf(p, nSize, "\"%s\":\"%.*x\",", pProperty, static_cast(nWidth), static_cast(nValue)); } else { - i = snprintf(p, nSize, "%s=%.*x\n", pProperty, nWidth, nValue); + i = snprintf(p, nSize, "%s=%.*x\n", pProperty, static_cast(nWidth), static_cast(nValue)); } } else { - i = snprintf(p, nSize, "#%s=%.*x\n", pProperty, nWidth, nValue); + i = snprintf(p, nSize, "#%s=%.*x\n", pProperty, static_cast(nWidth), static_cast(nValue)); } if (i > static_cast(nSize)) { diff --git a/lib-properties/src/readconfigfile.cpp b/lib-properties/src/readconfigfile.cpp index a831c31d..2da2a35c 100644 --- a/lib-properties/src/readconfigfile.cpp +++ b/lib-properties/src/readconfigfile.cpp @@ -85,6 +85,8 @@ bool ReadConfigFile::Read(const char *pFileName) { #endif void ReadConfigFile::Read(const char *pBuffer, unsigned nLength) { + DEBUG_ENTRY + assert(pBuffer != nullptr); assert(nLength != 0); @@ -114,9 +116,12 @@ void ReadConfigFile::Read(const char *pBuffer, unsigned nLength) { nLength--; } - if (buffer[0] >= 'a') { + if (buffer[0] >= '0') { *pLine = '\0'; + DEBUG_PUTS(&buffer[0]); m_pCallBack(m_p, &buffer[0]); } } + + DEBUG_EXIT } diff --git a/lib-properties/src/sscanutcoffset.cpp b/lib-properties/src/sscanutcoffset.cpp new file mode 100755 index 00000000..ffd7c509 --- /dev/null +++ b/lib-properties/src/sscanutcoffset.cpp @@ -0,0 +1,101 @@ +/** + * @file sscanutcoffset.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if !defined(__clang__) // Needed for compiling on MacOS +# pragma GCC push_options +# pragma GCC optimize ("Os") +#endif + +#include +#include +#include + +#include "sscan.h" + +Sscan::ReturnCode Sscan::UtcOffset(const char *pBuffer, const char *pName, int8_t& nHours, uint8_t& nMinutes) { + assert(pBuffer != nullptr); + assert(pName != nullptr); + + const char *p; + + if ((p = checkName(pBuffer, pName)) == nullptr) { + return Sscan::NAME_ERROR; + } + + auto bIsNegatieve = false; + + if (*p == '-') { + p++; + bIsNegatieve = true; + } else if (*p == '+') { + p++; + } + + if ((*p == ' ') || (*p == 0)) { + return Sscan::VALUE_ERROR; + } + + nHours = 0; + + if ((*p == '0') || (*p == '1')) { + if (*p == '1') { + nHours = 10; + } + p++; + } else { + return Sscan::VALUE_ERROR; + } + + if (isdigit(*p) == 0) { + return Sscan::VALUE_ERROR; + } + + nHours = static_cast(nHours + (*p - '0')); + + p++; + + if (*p != ':') { + return Sscan::VALUE_ERROR; + } + + p++; + + if ((isdigit(p[0]) == 0) || (isdigit(p[1]) == 0)) { + return Sscan::VALUE_ERROR; + } + + if ((p[2] == ' ') || (p[2] == 0)) { + nMinutes = static_cast((p[0] - '0') * 10); + nMinutes = static_cast(nMinutes + (p[1] - '0')); + + if (bIsNegatieve) { + nHours = -nHours; + } + + return Sscan::OK; + } + + return Sscan::VALUE_ERROR; +} diff --git a/lib-rdm/.cproject b/lib-rdm/.cproject index 16617ad6..3be66702 100644 --- a/lib-rdm/.cproject +++ b/lib-rdm/.cproject @@ -30,11 +30,9 @@ - diff --git a/lib-rdm/Rules.mk b/lib-rdm/Rules.mk index 65108ca7..b87e2d93 100644 --- a/lib-rdm/Rules.mk +++ b/lib-rdm/Rules.mk @@ -1,11 +1,38 @@ EXTRA_INCLUDES=../lib-rdmsensor/include ../lib-rdmsubdevice/include ../lib-dmx/include ../lib-properties/include ../lib-lightset/include -EXTRA_INCLUDES+=../lib-hal/include ../lib-network/include ../lib-display/include +EXTRA_INCLUDES+=../lib-network/include ../lib-display/include +EXTRA_INCLUDES+=../lib-e131/include ifneq ($(MAKE_FLAGS),) + ifeq (,$(findstring NODE_ARTNET,$(MAKE_FLAGS))) + ifeq ($(findstring RDM_RESPONDER,$(MAKE_FLAGS)), RDM_RESPONDER) + EXTRA_SRCDIR+=src/responder + EXTRA_INCLUDES+=../lib-dmxreceiver/include + endif + endif + + ifeq ($(findstring RDM_CONTROLLER,$(MAKE_FLAGS)), RDM_CONTROLLER) + EXTRA_SRCDIR+=src/controller + endif + ifneq (,$(findstring NODE_RDMNET_LLRP_ONLY,$(MAKE_FLAGS))) - EXTRA_SRCDIR += src/llrp + EXTRA_SRCDIR+=src/llrp + EXTRA_SRCDIR+=src/rdmnet + endif + ifneq (,$(findstring CONFIG_STORE_USE_ROM,$(MAKE_FLAGS))) + EXTRA_INCLUDES+=../lib-flashcode/include endif else - DEFINES+=ENABLE_RDM_MANUFACTURER_PIDS - EXTRA_SRCDIR += src/llrp + ifneq (, $(shell test -d '../lib-network/src/noemac' && echo -n yes)) + DEFINES+=NO_EMAC + else + EXTRA_SRCDIR+=src/llrp src/rdmnet + endif + + ifneq (, $(shell test -d '../lib-dmxreceiver' && echo -n yes)) + EXTRA_INCLUDES+=../lib-dmxreceiver/include + EXTRA_SRCDIR+=src/responder + endif + DEFINES+=CONFIG_RDM_ENABLE_SUBDEVICES CONFIG_RDM_SUBDEVICES_USE_I2C CONFIG_RDM_SUBDEVICES_USE_SPI + DEFINES+=CONFIG_RDM_ENABLE_MANUFACTURER_PIDS CONFIG_RDM_MANUFACTURER_PIDS_SET + DEFINES+=RDM_RESPONDER endif \ No newline at end of file diff --git a/lib-rdmnet/include/e133.h b/lib-rdm/include/e133.h old mode 100644 new mode 100755 similarity index 89% rename from lib-rdmnet/include/e133.h rename to lib-rdm/include/e133.h index b086dafc..38fc2a3a --- a/lib-rdmnet/include/e133.h +++ b/lib-rdm/include/e133.h @@ -2,7 +2,7 @@ * @file e133.h * */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -54,6 +54,15 @@ */ #define VECTOR_RDM_CMD_RDM_DATA 0xCC +/** + * Table A.15 RDM Parameter ID + */ + +#define E133_COMPONENT_SCOPE 0x0800 +#define E133_SEARCH_DOMAIN 0x0801 +#define E133_TCP_COMMS_STATUS 0x0802 +#define E133_BROKER_STATUS 0x0803 + /** * Table A-23: LLRP Component Type Codes */ diff --git a/lib-rdmnet/include/llrp.h b/lib-rdm/include/llrp/llrp.h old mode 100644 new mode 100755 similarity index 100% rename from lib-rdmnet/include/llrp.h rename to lib-rdm/include/llrp/llrp.h diff --git a/lib-rdmnet/include/llrpdevice.h b/lib-rdm/include/llrp/llrpdevice.h old mode 100644 new mode 100755 similarity index 90% rename from lib-rdmnet/include/llrpdevice.h rename to lib-rdm/include/llrp/llrpdevice.h index b561563f..53dafb7a --- a/lib-rdmnet/include/llrpdevice.h +++ b/lib-rdm/include/llrp/llrpdevice.h @@ -30,8 +30,10 @@ #include #include -#include "llrppacket.h" +#include "llrp/llrppacket.h" #include "e133.h" +#include "rdmconst.h" +#include "rdmhandler.h" #include "network.h" @@ -49,16 +51,20 @@ class LLRPDevice { public: LLRPDevice() { DEBUG_ENTRY + s_nHandleLLRP = Network::Get()->Begin(llrp::device::LLRP_PORT); assert(s_nHandleLLRP != -1); Network::Get()->JoinGroup(s_nHandleLLRP, llrp::device::IPV4_LLRP_REQUEST); + DEBUG_EXIT } - virtual ~LLRPDevice() { + ~LLRPDevice() { DEBUG_ENTRY + Network::Get()->LeaveGroup(s_nHandleLLRP, llrp::device::IPV4_LLRP_REQUEST); Network::Get()->End(llrp::device::LLRP_PORT); + DEBUG_EXIT } @@ -108,21 +114,12 @@ class LLRPDevice { printf(" Multicast Response : " IPSTR "\n", IP2STR(llrp::device::IPV4_LLRP_RESPONSE)); } -protected: - virtual void CopyUID(__attribute__((unused)) uint8_t *pUID) { - // Override - } - - virtual void CopyCID(__attribute__((unused)) uint8_t *pCID) { - // Override - } - - virtual uint8_t *LLRPHandleRdmCommand(__attribute__((unused)) const uint8_t *pRDMCommand) { - // Override - return nullptr; +private: + uint8_t *LLRPHandleRdmCommand(const uint8_t *pRdmDataNoSC) { + m_RDMHandler.HandleData(pRdmDataNoSC, reinterpret_cast(&s_RdmCommand)); + return reinterpret_cast(&s_RdmCommand); } -private: void HandleRequestMessage(); void HandleRdmCommand(); // DEBUG subject for deletions @@ -131,9 +128,12 @@ class LLRPDevice { void DumpRdmMessageInNoSc(); private: + RDMHandler m_RDMHandler { false }; + static int32_t s_nHandleLLRP; static uint32_t s_nIpAddressFrom; static uint8_t *s_pLLRP; + static TRdmMessage s_RdmCommand; }; #endif /* LLRPDEVICE_H_ */ diff --git a/lib-rdmnet/include/llrppacket.h b/lib-rdm/include/llrp/llrppacket.h old mode 100644 new mode 100755 similarity index 98% rename from lib-rdmnet/include/llrppacket.h rename to lib-rdm/include/llrp/llrppacket.h index f9a1ec46..3be2b885 --- a/lib-rdmnet/include/llrppacket.h +++ b/lib-rdm/include/llrp/llrppacket.h @@ -2,7 +2,7 @@ * @file llrppacket.h * */ -/* Copyright (C) 2019-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-rdm/include/rdm.h b/lib-rdm/include/rdm.h index 49b81ba1..c760ec7b 100644 --- a/lib-rdm/include/rdm.h +++ b/lib-rdm/include/rdm.h @@ -27,131 +27,76 @@ #define RDM_H_ #include +#include -#define RDM_DATA_BUFFER_SIZE 512 ///< -#define RDM_DATA_BUFFER_INDEX_ENTRIES (1 << 4) ///< -#define RDM_DATA_BUFFER_INDEX_MASK (RDM_DATA_BUFFER_INDEX_ENTRIES - 1) ///< - -#define RDM_ROOT_DEVICE 0 ///< - -///< 3 Timing -#define RDM_TRANSMIT_BREAK_TIME 176 ///< Min 176us -#define RDM_TRANSMIT_MAB_TIME 12 ///< Min 12us - -///< 3.2.2 Responder Packet spacing -#define RDM_RESPONDER_PACKET_SPACING 200 ///< Min 176us, Max 2ms - -#define RDM_RESPONDER_DATA_DIRECTION_DELAY 4 ///< - -///< 5 Device Addressing -#define RDM_UID_SIZE 6 ///< 48-bit - -///< 6.2.3 Message Length -#define RDM_MESSAGE_MINIMUM_SIZE 24U ///< Minimum size of RDM message without the checksum -#define RDM_MESSAGE_CHECKSUM_SIZE 2U ///< Size of the checksum -#define RDM_MESSAGE_COUNT_MAX 255U ///< Message Count field for Responder Generated Messages - -///< 7.6 Discovery Mute/Un-Mute Messages -///< 7.6.1 Control Field -///< The Reserved bits (Bits 4-15) are reserved for future implementation and shall be set to 0. -#define RDM_CONTROL_FIELD_MANAGED_PROXY_FLAG (1 << 0) ///< The Managed Proxy Flag (Bit 0) shall be set to 1 when the responder is a Proxy device. -#define RDM_CONTROL_FIELD_SUB_DEVICE_FLAG (1 << 1) ///< The Sub-Device Flag (Bit 1) shall be set to 1 when the responder supports Sub-Devices. -#define RDM_CONTROL_FIELD_BOOTLOADER_FLAG (1 << 2) ///< The Boot-Loader Flag (Bit 2) shall only be set to 1 when the device is incapable of normal operation until receiving a firmware upload. -#define RDM_CONTROL_FIELD_PROXIED_DEVICE_FLAG (1 << 3) ///< The Proxied Device Flag (Bit 3) shall only be set to 1 when a Proxy is responding to Discovery on behalf of another device. This flag indicates that the response has come from a Proxy, rather than the actual device. - -#define RDM_DEVICE_MANUFACTURER_ID_LENGTH 2 ///< - -///< 10.5.4 Get Manufacturer Label (MANUFACTURER_LABEL) -#define RDM_MANUFACTURER_LABEL_MAX_LENGTH 32 ///< Manufacturer name for the device of up to 32 characters. - -///< 10.5.5 Get/Set Device Label (DEVICE_LABEL) -#define RDM_DEVICE_LABEL_MAX_LENGTH 32 - -///< 10.5.8 Get/Set Language (LANGUAGE) -#define RDM_DEVICE_SUPPORTED_LANGUAGE_LENGTH 2 ///< The Language Codes are 2 character alpha codes as defined by ISO 639-1. - -///< 10.5.9 Get Software Version Label (SOFTWARE_VERSION_LABEL) -#define RDM_SOFTWARE_VERSION_LABEL_MAX_LENGTH 32 - -///< 10.5.10 Get Boot Software Version ID (BOOT_SOFTWARE_VERSION_ID) -#define RDM_BOOT_SOFTWARE_VERSION_ID_LENGTH 4 ///< The Boot Software Version ID is a 32-bit value determined by the Manufacturer. - -///< 10.5.11 Get Boot Software Version Label (BOOT_SOFTWARE_VERSION_LABEL) -#define RDM_BOOT_SOFTWARE_VERSION_LABEL_MAX_LENGTH 32 - -///< 10.7.1 Get Sensor Definition (SENSOR_DEFINITION) -#define RDM_SENSORS_ALL 0xFF ///< The sensor number 0xFF is used to address all sensors. - -///< 10.8.1 Get/Set Device Hours (DEVICE_HOURS) -#define RDM_DEVICE_HOURS_SIZE 4 - -///< 10.11.1 Get/Set Identify Device (IDENTIFY_DEVICE) -#define RDM_IDENTIFY_STATE_OFF 0 -#define RDM_IDENTIFY_STATE_ON 1 - -#if ! defined (PACKED) -# define PACKED __attribute__((packed)) -#endif - -struct TRdmMessage { - uint8_t start_code; ///< 1 SC_RDM - uint8_t sub_start_code; ///< 2 SC_SUB_MESSAGE - uint8_t message_length; ///< 3 Range 24 to 255 - uint8_t destination_uid[RDM_UID_SIZE]; ///< 4,5,6,7,8,9 - uint8_t source_uid[RDM_UID_SIZE]; ///< 10,11,12,13,14,15 - uint8_t transaction_number; ///< 16 - union { - uint8_t port_id; ///< 17 - uint8_t response_type; ///< 17 - } slot16; - uint8_t message_count; ///< 18 - uint8_t sub_device[2]; ///< 19, 20 - uint8_t command_class; ///< 21 - uint8_t param_id[2]; ///< 22, 23 - uint8_t param_data_length; ///< 24 PDL Range 0 to 231 - uint8_t param_data[231]; ///< 25,,,, PD 6.2.3 Message Length - uint8_t checksum_filler[2]; -}PACKED; - -struct TRdmMessageNoSc { - uint8_t sub_start_code; ///< 2 SC_SUB_MESSAGE - uint8_t message_length; ///< 3 Range 24 to 255 - uint8_t destination_uid[RDM_UID_SIZE]; ///< 4,5,6,7,8,9 - uint8_t source_uid[RDM_UID_SIZE]; ///< 10,11,12,13,14,15 - uint8_t transaction_number; ///< 16 - union { - uint8_t port_id; ///< 17 - uint8_t response_type; ///< 17 - } slot16; - uint8_t message_count; ///< 18 - uint8_t sub_device[2]; ///< 19, 20 - uint8_t command_class; ///< 21 - uint8_t param_id[2]; ///< 22, 23 - uint8_t param_data_length; ///< 24 PDL Range 0 to 231 - uint8_t param_data[231]; ///< 25,,,, PD 6.2.3 Message Length - uint8_t checksum_filler[2]; -}PACKED; - -struct TRdmDiscoveryMsg { - uint8_t header_FE[7]; ///< - uint8_t header_AA; ///< - uint8_t masked_device_id[12]; ///< - uint8_t checksum[4]; ///< -}PACKED; - -// Unique identifier (UID) which consists of a 2 byte ESTA manufacturer ID, and a 4 byte device ID. -static const uint8_t UID_ALL[RDM_UID_SIZE] __attribute__((aligned(4))) = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +#include "rdmconst.h" +#include "dmx.h" + +#include "hal_api.h" class Rdm { public: - static void Send(uint32_t nPortIndex, struct TRdmMessage *, uint32_t nSpacingMicros = 0); - static void SendRaw(uint32_t nPortIndex, const uint8_t *pRdmData, uint32_t nLength); + static void SendRaw(const uint32_t nPortIndex, const uint8_t *pRdmData, const uint32_t nLength) { + assert(pRdmData != nullptr); + assert(nLength != 0); + + Dmx::Get()->SetPortDirection(nPortIndex, dmx::PortDirection::OUTP, false); + + Dmx::Get()->RdmSendRaw(nPortIndex, pRdmData, nLength); + + udelay(RDM_RESPONDER_DATA_DIRECTION_DELAY); + + Dmx::Get()->SetPortDirection(nPortIndex, dmx::PortDirection::INP, true); + } + + static void Send(const uint32_t nPortIndex, struct TRdmMessage *pRdmCommand) { + assert(nPortIndex < dmx::config::max::PORTS); + assert(pRdmCommand != nullptr); + + auto *pData = reinterpret_cast(pRdmCommand); + uint32_t i; + uint16_t nChecksum = 0; + + pRdmCommand->transaction_number = s_TransactionNumber[nPortIndex]; + + for (i = 0; i < pRdmCommand->message_length; i++) { + nChecksum = static_cast(nChecksum + pData[i]); + } + + pData[i++] = static_cast(nChecksum >> 8); + pData[i] = static_cast(nChecksum & 0XFF); + + SendRaw(nPortIndex, reinterpret_cast(pRdmCommand), pRdmCommand->message_length + RDM_MESSAGE_CHECKSUM_SIZE); + + s_TransactionNumber[nPortIndex]++; + } + + static void SendRawRespondMessage(const uint32_t nPortIndex, const uint8_t *pRdmData, const uint32_t nLength) { + assert(nPortIndex < dmx::config::max::PORTS); + assert(pRdmData != nullptr); + assert(nLength != 0); + + extern volatile uint32_t gsv_RdmDataReceiveEnd; + // 3.2.2 Responder Packet spacing + udelay(RDM_RESPONDER_PACKET_SPACING, gsv_RdmDataReceiveEnd); + + SendRaw(nPortIndex, pRdmData, nLength); + } + + static void SendDiscoveryRespondMessage(const uint32_t nPortIndex, const uint8_t *pRdmData, const uint32_t nLength) { + Dmx::Get()->RdmSendDiscoveryRespondMessage(nPortIndex, pRdmData, nLength); + } + + static const uint8_t *Receive(const uint32_t nPortIndex) { + return Dmx::Get()->RdmReceive(nPortIndex); + } - static void SendRawRespondMessage(uint32_t nPortIndex, const uint8_t *pRdmData, uint32_t nLength); - static void SendDiscoveryRespondMessage(uint32_t nPortIndex, const uint8_t *pRdmData, uint32_t nLength); + static const uint8_t *ReceiveTimeOut(const uint32_t nPortIndex, const uint16_t nTimeOut) { + return Dmx::Get()->RdmReceiveTimeOut(nPortIndex, nTimeOut); + } - static const uint8_t *Receive(uint32_t nPortIndex); - static const uint8_t *ReceiveTimeOut(uint32_t nPortIndex, uint16_t nTimeOut); +private: + static uint8_t s_TransactionNumber[dmx::config::max::PORTS]; }; #endif /* RDM_H_ */ diff --git a/lib-rdm/include/rdm_manufacturer_pid.h b/lib-rdm/include/rdm_manufacturer_pid.h index 23b0614a..d9a1293e 100755 --- a/lib-rdm/include/rdm_manufacturer_pid.h +++ b/lib-rdm/include/rdm_manufacturer_pid.h @@ -1,5 +1,26 @@ -/* - * rdm_manufacturer_pid.h +/** + * @file rdm_manufacturer_pid.h + * + */ +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. */ #ifndef RDM_MANUFACTURER_PID_H_ @@ -41,7 +62,7 @@ struct ManufacturerPid { template struct Description { - static constexpr size_t size = N - 1; + static constexpr auto size = N - 1U; static_assert(size <= DEVICE_DESCRIPTION_MAX_LENGTH, "Description is too long"); static constexpr char const* value = T::description; }; @@ -54,7 +75,7 @@ struct ManufacturerParamData { }; bool handle_manufactureer_pid_get(const uint16_t nPid, const ManufacturerParamData *pIn, ManufacturerParamData *pOut, uint16_t& nReason); - +bool handle_manufactureer_pid_set(const bool isBroadcast, const uint16_t nPid, const rdm::ParameterDescription ¶meterDescription, const ManufacturerParamData *pIn, ManufacturerParamData *pOut, uint16_t& nReason); } // namespace rdm #endif /* RDM_MANUFACTURER_PID_H_ */ diff --git a/lib-rdm/include/rdm_message_print.h b/lib-rdm/include/rdm_message_print.h new file mode 100755 index 00000000..e20798be --- /dev/null +++ b/lib-rdm/include/rdm_message_print.h @@ -0,0 +1,36 @@ +/** + * @file rdm_message_print.h + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef RDM_MESSAGE_PRINT_H_ +#define RDM_MESSAGE_PRINT_H_ + +#include + +namespace rdm { +void message_print(const uint8_t *pRdmData); +void message_print_no_sc(const uint8_t *pRdmDataNoSc); +} // namespace rdm + +#endif /* RDM_MESSAGE_PRINT_H_ */ diff --git a/lib-rdm/include/rdm_selftest.h b/lib-rdm/include/rdm_selftest.h index d3e76fe2..46ca352f 100644 --- a/lib-rdm/include/rdm_selftest.h +++ b/lib-rdm/include/rdm_selftest.h @@ -2,7 +2,7 @@ * @file rdm_selftest.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-rdm/include/rdmconst.h b/lib-rdm/include/rdmconst.h index 2813fb93..5ed73d7c 100644 --- a/lib-rdm/include/rdmconst.h +++ b/lib-rdm/include/rdmconst.h @@ -2,7 +2,7 @@ * @file rdmconst.h * */ -/* Copyright (C) 2019 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,6 +28,120 @@ #include +#define RDM_DATA_BUFFER_SIZE 512 ///< +#define RDM_DATA_BUFFER_INDEX_ENTRIES (1 << 4) ///< +#define RDM_DATA_BUFFER_INDEX_MASK (RDM_DATA_BUFFER_INDEX_ENTRIES - 1) ///< + +#define RDM_ROOT_DEVICE 0 ///< + +///< 3 Timing +#define RDM_TRANSMIT_BREAK_TIME 176 ///< Min 176us +#define RDM_TRANSMIT_MAB_TIME 12 ///< Min 12us + +///< 3.2.2 Responder Packet spacing +#define RDM_RESPONDER_PACKET_SPACING 200 ///< Min 176us, Max 2ms + +#define RDM_RESPONDER_DATA_DIRECTION_DELAY 4 ///< + +///< 5 Device Addressing +#define RDM_UID_SIZE 6 ///< 48-bit + +///< 6.2.3 Message Length +#define RDM_MESSAGE_MINIMUM_SIZE 24U ///< Minimum size of RDM message without the checksum +#define RDM_MESSAGE_CHECKSUM_SIZE 2U ///< Size of the checksum +#define RDM_MESSAGE_COUNT_MAX 255U ///< Message Count field for Responder Generated Messages + +///< 7.6 Discovery Mute/Un-Mute Messages +///< 7.6.1 Control Field +///< The Reserved bits (Bits 4-15) are reserved for future implementation and shall be set to 0. +#define RDM_CONTROL_FIELD_MANAGED_PROXY_FLAG (1 << 0) ///< The Managed Proxy Flag (Bit 0) shall be set to 1 when the responder is a Proxy device. +#define RDM_CONTROL_FIELD_SUB_DEVICE_FLAG (1 << 1) ///< The Sub-Device Flag (Bit 1) shall be set to 1 when the responder supports Sub-Devices. +#define RDM_CONTROL_FIELD_BOOTLOADER_FLAG (1 << 2) ///< The Boot-Loader Flag (Bit 2) shall only be set to 1 when the device is incapable of normal operation until receiving a firmware upload. +#define RDM_CONTROL_FIELD_PROXIED_DEVICE_FLAG (1 << 3) ///< The Proxied Device Flag (Bit 3) shall only be set to 1 when a Proxy is responding to Discovery on behalf of another device. This flag indicates that the response has come from a Proxy, rather than the actual device. + +#define RDM_DEVICE_MANUFACTURER_ID_LENGTH 2 ///< + +///< 10.5.4 Get Manufacturer Label (MANUFACTURER_LABEL) +#define RDM_MANUFACTURER_LABEL_MAX_LENGTH 32 ///< Manufacturer name for the device of up to 32 characters. + +///< 10.5.5 Get/Set Device Label (DEVICE_LABEL) +#define RDM_DEVICE_LABEL_MAX_LENGTH 32 + +///< 10.5.8 Get/Set Language (LANGUAGE) +#define RDM_DEVICE_SUPPORTED_LANGUAGE_LENGTH 2 ///< The Language Codes are 2 character alpha codes as defined by ISO 639-1. + +///< 10.5.9 Get Software Version Label (SOFTWARE_VERSION_LABEL) +#define RDM_SOFTWARE_VERSION_LABEL_MAX_LENGTH 32 + +///< 10.5.10 Get Boot Software Version ID (BOOT_SOFTWARE_VERSION_ID) +#define RDM_BOOT_SOFTWARE_VERSION_ID_LENGTH 4 ///< The Boot Software Version ID is a 32-bit value determined by the Manufacturer. + +///< 10.5.11 Get Boot Software Version Label (BOOT_SOFTWARE_VERSION_LABEL) +#define RDM_BOOT_SOFTWARE_VERSION_LABEL_MAX_LENGTH 32 + +///< 10.7.1 Get Sensor Definition (SENSOR_DEFINITION) +#define RDM_SENSORS_ALL 0xFF ///< The sensor number 0xFF is used to address all sensors. + +///< 10.8.1 Get/Set Device Hours (DEVICE_HOURS) +#define RDM_DEVICE_HOURS_SIZE 4 + +///< 10.11.1 Get/Set Identify Device (IDENTIFY_DEVICE) +#define RDM_IDENTIFY_STATE_OFF 0 +#define RDM_IDENTIFY_STATE_ON 1 + +#if ! defined (PACKED) +# define PACKED __attribute__((packed)) +#endif + +struct TRdmMessage { + uint8_t start_code; ///< 1 SC_RDM + uint8_t sub_start_code; ///< 2 SC_SUB_MESSAGE + uint8_t message_length; ///< 3 Range 24 to 255 + uint8_t destination_uid[RDM_UID_SIZE]; ///< 4,5,6,7,8,9 + uint8_t source_uid[RDM_UID_SIZE]; ///< 10,11,12,13,14,15 + uint8_t transaction_number; ///< 16 + union { + uint8_t port_id; ///< 17 + uint8_t response_type; ///< 17 + } slot16; + uint8_t message_count; ///< 18 + uint8_t sub_device[2]; ///< 19, 20 + uint8_t command_class; ///< 21 + uint8_t param_id[2]; ///< 22, 23 + uint8_t param_data_length; ///< 24 PDL Range 0 to 231 + uint8_t param_data[231]; ///< 25,,,, PD 6.2.3 Message Length + uint8_t checksum_filler[2]; +}PACKED; + +struct TRdmMessageNoSc { + uint8_t sub_start_code; ///< 2 SC_SUB_MESSAGE + uint8_t message_length; ///< 3 Range 24 to 255 + uint8_t destination_uid[RDM_UID_SIZE]; ///< 4,5,6,7,8,9 + uint8_t source_uid[RDM_UID_SIZE]; ///< 10,11,12,13,14,15 + uint8_t transaction_number; ///< 16 + union { + uint8_t port_id; ///< 17 + uint8_t response_type; ///< 17 + } slot16; + uint8_t message_count; ///< 18 + uint8_t sub_device[2]; ///< 19, 20 + uint8_t command_class; ///< 21 + uint8_t param_id[2]; ///< 22, 23 + uint8_t param_data_length; ///< 24 PDL Range 0 to 231 + uint8_t param_data[231]; ///< 25,,,, PD 6.2.3 Message Length + uint8_t checksum_filler[2]; +}PACKED; + +struct TRdmDiscoveryMsg { + uint8_t header_FE[7]; ///< + uint8_t header_AA; ///< + uint8_t masked_device_id[12]; ///< + uint8_t checksum[4]; ///< +}PACKED; + +// Unique identifier (UID) which consists of a 2 byte ESTA manufacturer ID, and a 4 byte device ID. +static constexpr uint8_t UID_ALL[RDM_UID_SIZE] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + struct RDMConst { static const char MANUFACTURER_NAME[]; static const uint8_t MANUFACTURER_ID[]; diff --git a/lib-rdm/include/rdmdevice.h b/lib-rdm/include/rdmdevice.h index 6d5e50ba..e0906778 100644 --- a/lib-rdm/include/rdmdevice.h +++ b/lib-rdm/include/rdmdevice.h @@ -2,7 +2,7 @@ * @file rdmdevice.h * */ -/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -42,23 +42,6 @@ struct TRDMDeviceInfoData { uint8_t length; }; -///< http://rdm.openlighting.org/pid/display?manufacturer=0&pid=96 -struct TRDMDeviceInfo { - uint8_t protocol_major; ///< The response for this field shall always be same regardless of whether this message is directed to the Root Device or a Sub-Device. - uint8_t protocol_minor; ///< The response for this field shall always be same regardless of whether this message is directed to the Root Device or a Sub-Device. - uint8_t device_model[2]; ///< This field identifies the Device Model ID of the Root Device or the Sub-Device. The Manufacturer shall not use the same ID to represent more than one unique model type. - uint8_t product_category[2]; ///< Devices shall report a Product Category based on the products primary function. - uint8_t software_version[4]; ///< This field indicates the Software Version ID for the device. The Software Version ID is a 32-bit value determined by the Manufacturer. - uint8_t dmx_footprint[2]; ///< If the DEVICE_INFO message is directed to a Sub-Device, then the response for this field contains the DMX512 Footprint for that Sub-Device. If the message is sent to the Root Device, it is the Footprint for the Root Device itself. If the Device or Sub-Device does not utilize Null Start Code packets for any control or functionality then it shall report a Footprint of 0x0000. - uint8_t current_personality; ///< - uint8_t personality_count; ///< - uint8_t dmx_start_address[2]; ///< If the Device or Sub-Device that this message is directed to has a DMX512 Footprint of 0, then this field shall be set to 0xFFFF. - uint8_t sub_device_count[2]; ///< The response for this field shall always be same regardless of whether this message is directed to the Root Device or a Sub-Device. - uint8_t sensor_count; ///< This field indicates the number of available sensors in a Root Device or Sub-Device. When this parameter is directed to a Sub-Device, the reply shall be identical for any Sub-Device owned by a specific Root Device. -}; - -#include "rdm.h" - class RDMDevice { public: RDMDevice(); @@ -72,10 +55,6 @@ class RDMDevice { void Print(); - void SetRDMDeviceStore(RDMDeviceStore *pRDMDeviceStore) { - m_pRDMDeviceStore = pRDMDeviceStore; - } - void SetFactoryDefaults() { DEBUG_ENTRY TRDMDeviceInfoData info = {m_aFactoryRootLabel, m_nFactoryRootLabelLength}; @@ -91,10 +70,33 @@ class RDMDevice { } const uint8_t *GetUID() const { +#if defined (NO_EMAC) || !defined(CONFIG_RDMDEVICE_UUID_IP) +#else + const auto nIp = Network::Get()->GetIp(); +# if !defined(CONFIG_RDMDEVICE_REVERSE_UID) + m_aUID[5] = static_cast(nIp >> 24); + m_aUID[4] = (nIp >> 16) & 0xFF; + m_aUID[3] = (nIp >> 8) & 0xFF; + m_aUID[2] = nIp & 0xFF; +# else + m_aUID[2] = static_cast(nIp >> 24); + m_aUID[3] = (nIp >> 16) & 0xFF; + m_aUID[4] = (nIp >> 8) & 0xFF; + m_aUID[5] = nIp & 0xFF; +# endif +#endif return m_aUID; } const uint8_t *GetSN() const { +#if defined (NO_EMAC) || !defined(CONFIG_RDMDEVICE_UUID_IP) +#else + GetUID(); + m_aSN[0] = m_aUID[5]; + m_aSN[1] = m_aUID[4]; + m_aSN[2] = m_aUID[3]; + m_aSN[3] = m_aUID[2]; +#endif return m_aSN; } @@ -115,9 +117,7 @@ class RDMDevice { memcpy(m_aRootLabel, pInfo->data, nLength); m_nRootLabelLength = nLength; - if (m_pRDMDeviceStore != nullptr) { - m_pRDMDeviceStore->SaveLabel(m_aRootLabel, m_nRootLabelLength); - } + RDMDeviceStore::SaveLabel(m_aRootLabel, m_nRootLabelLength); } else { memcpy(m_aFactoryRootLabel, pInfo->data, nLength); m_nFactoryRootLabelLength = nLength; @@ -143,6 +143,10 @@ class RDMDevice { return m_nProductDetail; } + static RDMDevice *Get() { + return s_pThis; + } + private: uint16_t CalculateChecksum() { uint16_t nChecksum = m_nFactoryRootLabelLength; @@ -158,8 +162,6 @@ class RDMDevice { char m_aFactoryRootLabel[RDM_DEVICE_LABEL_MAX_LENGTH]; char m_aRootLabel[RDM_DEVICE_LABEL_MAX_LENGTH]; - RDMDeviceStore *m_pRDMDeviceStore { nullptr }; - uint16_t m_nProductCategory { E120_PRODUCT_CATEGORY_OTHER }; uint16_t m_nProductDetail { E120_PRODUCT_DETAIL_OTHER }; uint16_t m_nCheckSum { 0 }; @@ -171,6 +173,8 @@ class RDMDevice { uint8_t m_nFactoryRootLabelLength { 0 }; bool m_IsInit { false }; + + static RDMDevice *s_pThis; }; #endif /* RDMDEVICE_H_ */ diff --git a/lib-rdm/include/rdmdevicecontroller.h b/lib-rdm/include/rdmdevicecontroller.h index bd4a1d64..b7454eb3 100644 --- a/lib-rdm/include/rdmdevicecontroller.h +++ b/lib-rdm/include/rdmdevicecontroller.h @@ -2,7 +2,7 @@ * @file rdmdevicecontroller.h * */ -/* Copyright (C) 2017-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -37,10 +37,7 @@ class RDMDeviceController: public RDMDevice { DEBUG_EXIT } - ~RDMDeviceController() { - DEBUG_ENTRY - DEBUG_EXIT - } + ~RDMDeviceController() = default; }; #endif /* RDMDEVICECONTROLLER_H_ */ diff --git a/lib-rdm/include/rdmdeviceparams.h b/lib-rdm/include/rdmdeviceparams.h index cd9e762e..dff15621 100644 --- a/lib-rdm/include/rdmdeviceparams.h +++ b/lib-rdm/include/rdmdeviceparams.h @@ -28,8 +28,8 @@ #include -#include "rdmdevice.h" -#include "rdm.h" +#include "rdmconst.h" +#include "configstore.h" namespace rdm { namespace deviceparams { @@ -49,19 +49,24 @@ struct Mask { } // namespace rdmdevice } // namespace rdm +class RDMDevice; + class RDMDeviceParamsStore { public: - virtual ~RDMDeviceParamsStore() {} + static void Update(const struct rdm::deviceparams::Params *pParams) { + ConfigStore::Get()->Update(configstore::Store::RDMDEVICE, pParams, sizeof(struct rdm::deviceparams::Params)); + } - virtual void Update(const struct rdm::deviceparams::Params *pParams)=0; - virtual void Copy(struct rdm::deviceparams::Params *pParams)=0; + static void Copy(struct rdm::deviceparams::Params *pParams) { + ConfigStore::Get()->Copy(configstore::Store::RDMDEVICE, pParams, sizeof(struct rdm::deviceparams::Params)); + } }; class RDMDeviceParams { public: - RDMDeviceParams(RDMDeviceParamsStore *pRDMDeviceParamsStore); + RDMDeviceParams(); - bool Load(); + void Load(); void Load(const char *pBuffer, uint32_t nLength); void Builder(const struct rdm::deviceparams::Params *pParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); @@ -71,19 +76,16 @@ class RDMDeviceParams { void Set(RDMDevice *pRDMDevice); - void Dump(); - -public: static void staticCallbackFunction(void *p, const char *s); private: + void Dump(); void callbackFunction(const char *s); bool isMaskSet(uint32_t nMask) const { return (m_Params.nSetList & nMask) == nMask; } private: - RDMDeviceParamsStore *m_pRDMDeviceParamsStore; rdm::deviceparams::Params m_Params; }; diff --git a/lib-rdm/include/rdmdeviceresponder.h b/lib-rdm/include/rdmdeviceresponder.h index 1345f907..ed36f5d7 100644 --- a/lib-rdm/include/rdmdeviceresponder.h +++ b/lib-rdm/include/rdmdeviceresponder.h @@ -2,7 +2,7 @@ * @file rdmdeviceresponder.h * */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,7 +29,7 @@ #include #include -#include "rdm.h" +#include "rdmconst.h" #include "rdmdevice.h" #include "rdmidentify.h" #include "rdmpersonality.h" @@ -42,6 +42,22 @@ namespace rdm { namespace device { namespace responder { static constexpr uint8_t DEFAULT_CURRENT_PERSONALITY = 1; + +///< http://rdm.openlighting.org/pid/display?manufacturer=0&pid=96 +struct DeviceInfo { + uint8_t protocol_major; ///< The response for this field shall always be same regardless of whether this message is directed to the Root Device or a Sub-Device. + uint8_t protocol_minor; ///< The response for this field shall always be same regardless of whether this message is directed to the Root Device or a Sub-Device. + uint8_t device_model[2]; ///< This field identifies the Device Model ID of the Root Device or the Sub-Device. The Manufacturer shall not use the same ID to represent more than one unique model type. + uint8_t product_category[2]; ///< Devices shall report a Product Category based on the products primary function. + uint8_t software_version[4]; ///< This field indicates the Software Version ID for the device. The Software Version ID is a 32-bit value determined by the Manufacturer. + uint8_t dmx_footprint[2]; ///< If the DEVICE_INFO message is directed to a Sub-Device, then the response for this field contains the DMX512 Footprint for that Sub-Device. If the message is sent to the Root Device, it is the Footprint for the Root Device itself. If the Device or Sub-Device does not utilize Null Start Code packets for any control or functionality then it shall report a Footprint of 0x0000. + uint8_t current_personality; ///< + uint8_t personality_count; ///< + uint8_t dmx_start_address[2]; ///< If the Device or Sub-Device that this message is directed to has a DMX512 Footprint of 0, then this field shall be set to 0xFFFF. + uint8_t sub_device_count[2]; ///< The response for this field shall always be same regardless of whether this message is directed to the Root Device or a Sub-Device. + uint8_t sensor_count; ///< This field indicates the number of available sensors in a Root Device or Sub-Device. When this parameter is directed to a Sub-Device, the reply shall be identical for any Sub-Device owned by a specific Root Device. +}; + void factorydefaults(); } // namespace responder } // namespace device @@ -49,31 +65,36 @@ void factorydefaults(); class RDMDeviceResponder: public RDMDevice { public: - RDMDeviceResponder(RDMPersonality **pRDMPersonalities, uint32_t nPersonalityCount); - virtual ~RDMDeviceResponder() {} + RDMDeviceResponder(RDMPersonality **pRDMPersonalities, const uint32_t nPersonalityCount, const uint32_t nCurrentPersonality = rdm::device::responder::DEFAULT_CURRENT_PERSONALITY); + virtual ~RDMDeviceResponder() = default; void Init(); void Print(); // E120_DEVICE_INFO 0x0060 - struct TRDMDeviceInfo *GetDeviceInfo(uint16_t nSubDevice = RDM_ROOT_DEVICE) { + struct rdm::device::responder::DeviceInfo *GetDeviceInfo(uint16_t nSubDevice = RDM_ROOT_DEVICE) { if (nSubDevice != RDM_ROOT_DEVICE) { const auto *sub_device_info = m_RDMSubDevices.GetInfo(nSubDevice); if (sub_device_info != nullptr) { - m_tRDMSubDeviceInfo.dmx_footprint[0] = static_cast(sub_device_info->dmx_footprint >> 8); - m_tRDMSubDeviceInfo.dmx_footprint[1] = static_cast(sub_device_info->dmx_footprint); - m_tRDMSubDeviceInfo.current_personality = sub_device_info->current_personality; - m_tRDMSubDeviceInfo.personality_count = sub_device_info->personality_count; - m_tRDMSubDeviceInfo.dmx_start_address[0] = static_cast(sub_device_info->dmx_start_address >> 8); - m_tRDMSubDeviceInfo.dmx_start_address[1] = static_cast(sub_device_info->dmx_start_address); - m_tRDMSubDeviceInfo.sensor_count = sub_device_info->sensor_count; + m_SubDeviceInfo.dmx_footprint[0] = static_cast(sub_device_info->dmx_footprint >> 8); + m_SubDeviceInfo.dmx_footprint[1] = static_cast(sub_device_info->dmx_footprint); + m_SubDeviceInfo.current_personality = sub_device_info->current_personality; + m_SubDeviceInfo.personality_count = sub_device_info->personality_count; + m_SubDeviceInfo.dmx_start_address[0] = static_cast(sub_device_info->dmx_start_address >> 8); + m_SubDeviceInfo.dmx_start_address[1] = static_cast(sub_device_info->dmx_start_address); + m_SubDeviceInfo.sensor_count = sub_device_info->sensor_count; } - return &m_tRDMSubDeviceInfo; + return &m_SubDeviceInfo; } - return &m_tRDMDeviceInfo; + //TODO FIXME Quick fix + const auto nProductCategory = RDMDevice::GetProductCategory(); + m_DeviceInfo.product_category[0] =static_cast( nProductCategory >> 8); + m_DeviceInfo.product_category[1] = static_cast(nProductCategory); + + return &m_DeviceInfo; } // E120_DEVICE_LABEL 0x0082 @@ -113,7 +134,7 @@ class RDMDeviceResponder: public RDMDevice { SetPersonalityCurrent(RDM_ROOT_DEVICE, rdm::device::responder::DEFAULT_CURRENT_PERSONALITY); SetDmxStartAddress(RDM_ROOT_DEVICE, m_nDmxStartAddressFactoryDefault); - memcpy(&m_tRDMSubDeviceInfo, &m_tRDMDeviceInfo, sizeof(struct TRDMDeviceInfo)); + memcpy(&m_SubDeviceInfo, &m_DeviceInfo, sizeof(struct rdm::device::responder::DeviceInfo)); m_RDMSubDevices.SetFactoryDefaults(); @@ -173,15 +194,15 @@ class RDMDeviceResponder: public RDMDevice { return; } - const auto *pPersonality = m_pRDMPersonalities[m_tRDMDeviceInfo.current_personality - 1]; + const auto *pPersonality = m_pRDMPersonalities[m_DeviceInfo.current_personality - 1]; assert(pPersonality != nullptr); auto *pLightSet = pPersonality->GetLightSet(); if (pLightSet != nullptr) { if (pLightSet->SetDmxStartAddress(nDmxStartAddress)) { - m_tRDMDeviceInfo.dmx_start_address[0] = static_cast(nDmxStartAddress >> 8); - m_tRDMDeviceInfo.dmx_start_address[1] = static_cast(nDmxStartAddress); + m_DeviceInfo.dmx_start_address[0] = static_cast(nDmxStartAddress >> 8); + m_DeviceInfo.dmx_start_address[1] = static_cast(nDmxStartAddress); } DmxStartAddressUpdate(); @@ -195,7 +216,7 @@ class RDMDeviceResponder: public RDMDevice { return m_RDMSubDevices.GetDmxStartAddress(nSubDevice); } - return static_cast((m_tRDMDeviceInfo.dmx_start_address[0] << 8) + m_tRDMDeviceInfo.dmx_start_address[1]); + return static_cast((m_DeviceInfo.dmx_start_address[0] << 8) + m_DeviceInfo.dmx_start_address[1]); } // E120_SLOT_INFO 0x0120 @@ -204,7 +225,7 @@ class RDMDeviceResponder: public RDMDevice { return false; // TODO GetSlotInfo SubDevice } - const auto *pPersonality = m_pRDMPersonalities[m_tRDMDeviceInfo.current_personality - 1]; + const auto *pPersonality = m_pRDMPersonalities[m_DeviceInfo.current_personality - 1]; auto *pLightSet = pPersonality->GetLightSet(); return pLightSet->GetSlotInfo(nSlotOffset, tSlotInfo); @@ -215,7 +236,7 @@ class RDMDeviceResponder: public RDMDevice { return m_RDMSubDevices.GetDmxFootPrint(nSubDevice); } - return static_cast((m_tRDMDeviceInfo.dmx_footprint[0] << 8) + m_tRDMDeviceInfo.dmx_footprint[1]); + return static_cast((m_DeviceInfo.dmx_footprint[0] << 8) + m_DeviceInfo.dmx_footprint[1]); } // Personalities @@ -226,7 +247,7 @@ class RDMDeviceResponder: public RDMDevice { return m_RDMSubDevices.GetPersonality(nSubDevice, nPersonality); } - assert(nPersonality <= m_tRDMDeviceInfo.personality_count); + assert(nPersonality <= m_DeviceInfo.personality_count); return m_pRDMPersonalities[nPersonality - 1]; } @@ -236,7 +257,7 @@ class RDMDeviceResponder: public RDMDevice { return m_RDMSubDevices.GetPersonalityCount(nSubDevice); } - return m_tRDMDeviceInfo.personality_count; + return m_DeviceInfo.personality_count; } void SetPersonalityCurrent(uint16_t nSubDevice, uint8_t nPersonality) { @@ -247,9 +268,9 @@ class RDMDeviceResponder: public RDMDevice { return; } - m_tRDMDeviceInfo.current_personality = nPersonality; + m_DeviceInfo.current_personality = nPersonality; - assert(nPersonality <= m_tRDMDeviceInfo.personality_count); + assert(nPersonality <= m_DeviceInfo.personality_count); const auto *pPersonality = m_pRDMPersonalities[nPersonality - 1]; assert(pPersonality != nullptr); @@ -257,10 +278,10 @@ class RDMDeviceResponder: public RDMDevice { auto *pLightSet = pPersonality->GetLightSet(); if (pLightSet != nullptr) { - m_tRDMDeviceInfo.dmx_footprint[0] = static_cast(pLightSet->GetDmxFootprint() >> 8); - m_tRDMDeviceInfo.dmx_footprint[1] = static_cast(pLightSet->GetDmxFootprint()); - m_tRDMDeviceInfo.dmx_start_address[0] = static_cast(pLightSet->GetDmxStartAddress() >> 8); - m_tRDMDeviceInfo.dmx_start_address[1] = static_cast(pLightSet->GetDmxStartAddress()); + m_DeviceInfo.dmx_footprint[0] = static_cast(pLightSet->GetDmxFootprint() >> 8); + m_DeviceInfo.dmx_footprint[1] = static_cast(pLightSet->GetDmxFootprint()); + m_DeviceInfo.dmx_start_address[0] = static_cast(pLightSet->GetDmxStartAddress() >> 8); + m_DeviceInfo.dmx_start_address[1] = static_cast(pLightSet->GetDmxStartAddress()); PersonalityUpdate(pLightSet); } @@ -271,7 +292,7 @@ class RDMDeviceResponder: public RDMDevice { return m_RDMSubDevices.GetPersonalityCurrent(nSubDevice); } - return m_tRDMDeviceInfo.current_personality; + return m_DeviceInfo.current_personality; } static RDMDeviceResponder* Get() { @@ -280,8 +301,8 @@ class RDMDeviceResponder: public RDMDevice { private: uint16_t CalculateChecksum() { - auto nChecksum = static_cast((m_tRDMDeviceInfo.dmx_start_address[0] >> 8) + m_tRDMDeviceInfo.dmx_start_address[1]); - nChecksum = static_cast(nChecksum + m_tRDMDeviceInfo.current_personality); + auto nChecksum = static_cast((m_DeviceInfo.dmx_start_address[0] >> 8) + m_DeviceInfo.dmx_start_address[1]); + nChecksum = static_cast(nChecksum + m_DeviceInfo.current_personality); return nChecksum; } @@ -295,8 +316,8 @@ class RDMDeviceResponder: public RDMDevice { RDMPersonality **m_pRDMPersonalities; char *m_pSoftwareVersion; uint8_t m_nSoftwareVersionLength; - TRDMDeviceInfo m_tRDMDeviceInfo; - TRDMDeviceInfo m_tRDMSubDeviceInfo; + rdm::device::responder::DeviceInfo m_DeviceInfo; + rdm::device::responder::DeviceInfo m_SubDeviceInfo; char m_aLanguage[2]; // bool m_IsFactoryDefaults { true }; diff --git a/lib-rdm/include/rdmdevicestore.h b/lib-rdm/include/rdmdevicestore.h index 30d7b0ee..31af1a28 100644 --- a/lib-rdm/include/rdmdevicestore.h +++ b/lib-rdm/include/rdmdevicestore.h @@ -2,7 +2,7 @@ * @file rdmdevicestore.h * */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,12 +27,17 @@ #define RDMDEVICESTORE_H_ #include +#include + +#include "rdmdeviceparams.h" +#include "configstore.h" class RDMDeviceStore { public: - virtual ~RDMDeviceStore() {} - - virtual void SaveLabel(const char *pLabel, uint8_t nLength)=0; + static void SaveLabel(const char *pLabel, uint8_t nLength) { + ConfigStore::Get()->Update(configstore::Store::RDMDEVICE, offsetof(struct rdm::deviceparams::Params, aDeviceRootLabel), pLabel, nLength, rdm::deviceparams::Mask::LABEL); + ConfigStore::Get()->Update(configstore::Store::RDMDEVICE, offsetof(struct rdm::deviceparams::Params, nDeviceRootLabelLength), &nLength, sizeof(uint8_t), rdm::deviceparams::Mask::LABEL); + } }; #endif /* RDMDEVICESTORE_H_ */ diff --git a/lib-rdm/include/rdmdiscovery.h b/lib-rdm/include/rdmdiscovery.h new file mode 100755 index 00000000..beac8fa6 --- /dev/null +++ b/lib-rdm/include/rdmdiscovery.h @@ -0,0 +1,220 @@ +/** + * @file rdmddiscovery.h + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef RDMDDISCOVERY_H_ +#define RDMDDISCOVERY_H_ + +#include +#include +#include + +#include "rdmmessage.h" +#include "debug.h" + +namespace rdmdiscovery { +#ifndef NDEBUG + static constexpr uint32_t RECEIVE_TIME_OUT = 58000; + static constexpr uint32_t LATE_RESPONSE_TIME_OUT = 40000; +#else + static constexpr uint32_t RECEIVE_TIME_OUT = 5800; + static constexpr uint32_t LATE_RESPONSE_TIME_OUT = 1000; +#endif +static constexpr uint32_t UNMUTE_COUNTER = 3; +static constexpr uint32_t MUTE_COUNTER = 10; +static constexpr uint32_t DISCOVERY_STACK_SIZE = rdmtod::TOD_TABLE_SIZE; +static constexpr uint32_t DISCOVERY_COUNTER = 3; +static constexpr uint32_t QUIKFIND_COUNTER = 5; +static constexpr uint32_t QUIKFIND_DISCOVERY_COUNTER = 5; + +enum class State { + IDLE, + UNMUTE, + MUTE, + DISCOVERY, + DISCOVERY_SINGLE_DEVICE, + DUB, + QUICKFIND, + QUICKFIND_DISCOVERY, + LATE_RESPONSE, + FINISHED +}; +} // namespace rdmdiscovery + +class RDMDiscovery { +public: + RDMDiscovery(const uint8_t *pUid); + + bool Full(const uint32_t nPortIndex, RDMTod *pRDMTod); + bool Incremental(const uint32_t nPortIndex, RDMTod *pRDMTod); + + bool Stop(); + + bool IsRunning(uint32_t& nPortIndex, bool& bIsIncremental) const { + nPortIndex = m_nPortIndex; + bIsIncremental = m_doIncremental; + return (m_State != rdmdiscovery::State::IDLE); + } + + bool IsFinished(uint32_t& nPortIndex, bool& bIsIncremental) { + nPortIndex = m_nPortIndex; + bIsIncremental = m_doIncremental; + + if (m_bIsFinished) { + m_bIsFinished = false; + return true; + } + + return false; + } + + uint32_t CopyWorkingQueue(char *pOutBuffer, const uint32_t nOutBufferSize); + + void Run() { + if (__builtin_expect((m_State == rdmdiscovery::State::IDLE), 1)) { + return; + } + + Process(); + } + +private: + void Process(); + bool Start(const uint32_t nPortIndex, RDMTod *pRDMTod, const bool doIncremental); + bool IsValidDiscoveryResponse(uint8_t *pUid); + + void SavedState([[maybe_unused]] const uint32_t nLine); + void NewState(const rdmdiscovery::State state, const bool doStateLateResponse, [[maybe_unused]] const uint32_t nLine); + +private: + RDMMessage m_Message; + uint8_t *m_pResponse { nullptr }; + uint8_t m_Uid[RDM_UID_SIZE]; + uint32_t m_nPortIndex { 0 }; + RDMTod *m_pRDMTod { nullptr }; + + bool m_bIsFinished { false }; + bool m_doIncremental { false }; + rdmdiscovery::State m_State { rdmdiscovery::State::IDLE }; + rdmdiscovery::State m_SavedState { rdmdiscovery::State::IDLE }; + + struct { + uint32_t nMicros; + } m_LateResponse; + + struct { + uint32_t nCounter; + uint32_t nMicros; + bool bCommandRunning; + } m_UnMute; + + struct { + uint32_t nTodEntries; + uint32_t nCounter; + uint32_t nMicros; + uint8_t uid[RDM_UID_SIZE]; + bool bCommandRunning; + } m_Mute; + + struct { + struct { + bool push(const uint64_t nLowerBound, const uint64_t nUpperBound) { + if (nTop == rdmdiscovery::DISCOVERY_STACK_SIZE - 1) { + assert(0); + return false; + } + + nTop++; + items[nTop].nLowerBound = nLowerBound; + items[nTop].nUpperBound = nUpperBound; + + nDebugStackTopMax = std::max(nDebugStackTopMax, nTop); + return true; + } + + bool pop(uint64_t &nLowerBound, uint64_t &nUpperBound) { + if (nTop == -1) { + return false; + } + + nLowerBound = items[nTop].nLowerBound; + nUpperBound = items[nTop].nUpperBound; + nTop--; + + return true; + } + + int32_t nTop; + + struct { + uint64_t nLowerBound; + uint64_t nUpperBound; + } items[rdmdiscovery::DISCOVERY_STACK_SIZE]; + + int32_t nDebugStackTopMax; + } stack; + + uint64_t nLowerBound; + uint64_t nMidPosition; + uint64_t nUpperBound; + uint32_t nCounter; + uint32_t nMicros; + uint8_t uid[RDM_UID_SIZE]; + uint8_t pdl[2][RDM_UID_SIZE]; + bool bCommandRunning; + } m_Discovery; + + struct { + uint32_t nCounter; + uint32_t nMicros; + bool bCommandRunning; + } m_DiscoverySingleDevice; + + struct { + uint32_t nCounter; + uint32_t nMicros; + bool bCommandRunning; + uint8_t uid[RDM_UID_SIZE]; + } m_QuikFind; + + struct { + uint32_t nCounter; + uint32_t nMicros; + bool bCommandRunning; + uint8_t uid[RDM_UID_SIZE]; + } m_QuikFindDiscovery; + +#ifndef NDEBUG + struct { + struct { + uint64_t nLowerBound; + uint64_t nUpperBound; + } tree[1024]; + + uint32_t nTreeIndex; + } debug; +#endif +}; + +#endif /* RDMDDISCOVERY_H_ */ diff --git a/lib-rdm/include/rdmhandler.h b/lib-rdm/include/rdmhandler.h index d411428f..fb4c0f7b 100644 --- a/lib-rdm/include/rdmhandler.h +++ b/lib-rdm/include/rdmhandler.h @@ -2,7 +2,7 @@ * @file rdmhandler.h * */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,17 +27,19 @@ #define RDMHANDLER_H_ #include +#include #if defined (NODE_RDMNET_LLRP_ONLY) -# if defined (ENABLE_RDM_MANUFACTURER_PIDS) -# undef ENABLE_RDM_MANUFACTURER_PIDS +# if defined (CONFIG_RDM_ENABLE_MANUFACTURER_PIDS) +# undef CONFIG_RDM_ENABLE_MANUFACTURER_PIDS # endif #endif -#include "rdmmessage.h" -#include "rdmqueuedmessage.h" +#if defined (ENABLE_RDM_QUEUED_MSG) +# include "rdmqueuedmessage.h" +#endif -#if defined (ENABLE_RDM_MANUFACTURER_PIDS) +#if defined (CONFIG_RDM_ENABLE_MANUFACTURER_PIDS) # include "rdm_manufacturer_pid.h" #endif @@ -48,10 +50,10 @@ class RDMHandler { void HandleData(const uint8_t *pRdmDataIn, uint8_t *pRdmDataOut); private: - void CreateRespondMessage(uint8_t nResponseType, uint16_t nReason = 0); + void CreateRespondMessage(const uint8_t nResponseType, const uint16_t nReason); void RespondMessageAck(); - void RespondMessageNack(uint16_t nReason); - void HandleString(const char *pString, uint32_t nLength); + void RespondMessageNack(const uint16_t nReason); + void HandleString(const char *pString, const uint32_t nLength); void Handlers(bool bIsBroadcast, uint8_t nCommandClass, uint16_t nParamId, uint8_t nParamDataLength, uint16_t nSubDevice); // Get @@ -59,7 +61,7 @@ class RDMHandler { void GetQueuedMessage(uint16_t nSubDevice); #endif void GetSupportedParameters(uint16_t nSubDevice); -#if defined (ENABLE_RDM_MANUFACTURER_PIDS) +#if defined (CONFIG_RDM_ENABLE_MANUFACTURER_PIDS) void GetParameterDescription(uint16_t nSubDevice); void GetManufacturerPid(uint16_t nSubDevice); #endif @@ -86,7 +88,7 @@ class RDMHandler { void GetIdentifyDevice(uint16_t nSubDevice); void GetRealTimeClock(uint16_t nSubDevice); void GetPowerState(uint16_t nSubDevice); -#if defined (ENABLE_RDM_SELF_TEST) +#if defined (CONFIG_RDM_ENABLE_SELF_TEST) void GetPerformSelfTest(uint16_t nSubDevice); void GetSelfTestDescription(uint16_t nSubDevice); #endif @@ -122,11 +124,14 @@ class RDMHandler { void SetRealTimeClock(bool IsBroadcast, uint16_t nSubDevice); void SetResetDevice(bool IsBroadcast, uint16_t nSubDevice); void SetPowerState(bool IsBroadcast, uint16_t nSubDevice); -#if defined (ENABLE_RDM_SELF_TEST) +#if defined (CONFIG_RDM_ENABLE_SELF_TEST) void SetPerformSelfTest(bool IsBroadcast, uint16_t nSubDevice); #endif #if defined (ENABLE_RDM_PRESET_PLAYBACK) void SetPresetPlayback(bool IsBroadcast, uint16_t nSubDevice); +#endif +#if defined (CONFIG_RDM_ENABLE_MANUFACTURER_PIDS) && defined (CONFIG_RDM_MANUFACTURER_PIDS_SET) + void SetManufacturerPid(bool IsBroadcast, uint16_t nSubDevice); #endif // ANSI E1.37-1 void SetIdentifyMode(bool IsBroadcast, uint16_t nSubDevice); @@ -163,7 +168,7 @@ class RDMHandler { static const PidDefinition PID_DEFINITIONS[]; static const PidDefinition PID_DEFINITIONS_SUB_DEVICES[]; -#if defined (ENABLE_RDM_MANUFACTURER_PIDS) +#if defined (CONFIG_RDM_ENABLE_MANUFACTURER_PIDS) static const PidDefinition PID_DEFINITION_MANUFACTURER_GENERAL; static const rdm::ParameterDescription PARAMETER_DESCRIPTIONS[]; diff --git a/lib-rdm/include/rdmidentify.h b/lib-rdm/include/rdmidentify.h index 7d1e3a45..6d9636e8 100644 --- a/lib-rdm/include/rdmidentify.h +++ b/lib-rdm/include/rdmidentify.h @@ -41,7 +41,7 @@ enum class Mode : uint8_t { class RDMIdentify { public: RDMIdentify(); - ~RDMIdentify() {} + ~RDMIdentify() = default; void On() { m_bIsEnabled = true; diff --git a/lib-rdm/include/rdmmessage.h b/lib-rdm/include/rdmmessage.h index 1492f7ec..970bb05e 100644 --- a/lib-rdm/include/rdmmessage.h +++ b/lib-rdm/include/rdmmessage.h @@ -29,6 +29,7 @@ #include #include +#include "rdm_message_print.h" #include "rdm.h" #include "rdm_e120.h" @@ -47,12 +48,10 @@ class RDMMessage final: public Rdm { m_message.param_data_length = 0; } -#if defined (RDM_CONTROLLER) void SetPortID(const uint8_t nPortID) { assert(nPortID > 0); m_message.slot16.port_id = nPortID; } -#endif void SetSrcUid(const uint8_t *SrcUid){ memcpy(m_message.source_uid, SrcUid, RDM_UID_SIZE); @@ -85,17 +84,13 @@ class RDMMessage final: public Rdm { m_message.message_length = static_cast(m_message.message_length + nLength); } - void Send(uint32_t nPortIndex, uint32_t nSpacingMicros = 0) { + void Send(const uint32_t nPortIndex) { #ifndef NDEBUG - RDMMessage::Print(reinterpret_cast(&m_message)); + rdm::message_print(reinterpret_cast(&m_message)); #endif - Rdm::Send(nPortIndex, &m_message, nSpacingMicros); + Rdm::Send(nPortIndex, &m_message); } -public: - static void Print(const uint8_t *pRdmData); - static void PrintNoSc(const uint8_t *pRdmDataNoSc); - private: TRdmMessage m_message; }; diff --git a/lib-rdmnet/include/rdmnet.h b/lib-rdm/include/rdmnet/rdmnet.h old mode 100644 new mode 100755 similarity index 100% rename from lib-rdmnet/include/rdmnet.h rename to lib-rdm/include/rdmnet/rdmnet.h diff --git a/lib-rdmnet/include/rdmnetconst.h b/lib-rdm/include/rdmnetconst.h old mode 100644 new mode 100755 similarity index 100% rename from lib-rdmnet/include/rdmnetconst.h rename to lib-rdm/include/rdmnetconst.h diff --git a/lib-rdmnet/include/rdmnetdevice.h b/lib-rdm/include/rdmnetdevice.h old mode 100644 new mode 100755 similarity index 70% rename from lib-rdmnet/include/rdmnetdevice.h rename to lib-rdm/include/rdmnetdevice.h index 6777fc26..42f572cb --- a/lib-rdmnet/include/rdmnetdevice.h +++ b/lib-rdm/include/rdmnetdevice.h @@ -2,7 +2,7 @@ * @file rdmnetdevice.h * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,49 +30,52 @@ #include #include "rdmdeviceresponder.h" -#include "llrpdevice.h" +#include "llrp/llrpdevice.h" #include "rdmhandler.h" - #include "e131.h" #include "hardware.h" +#include "debug.h" + #if defined (RDM_RESPONDER) # error "Cannot be both RDMNet Device and RDM Responder" #endif -class RDMNetDevice: public RDMDeviceResponder, public LLRPDevice { +class RDMNetDevice final: public RDMDeviceResponder, public LLRPDevice { public: RDMNetDevice(RDMPersonality **pRDMPersonalities, uint32_t nPersonalityCount) : RDMDeviceResponder(pRDMPersonalities, nPersonalityCount) { - Hardware::Get()->GetUuid(s_Cid); - } - - ~RDMNetDevice() override {}; + DEBUG_ENTRY - void CopyUID(uint8_t *pUID) override { - memcpy(pUID, RDMDeviceResponder::GetUID(), RDM_UID_SIZE); - } - void CopyCID(uint8_t *pCID) override { - memcpy(pCID, s_Cid, sizeof(s_Cid)); + DEBUG_EXIT } - uint8_t *LLRPHandleRdmCommand(const uint8_t *pRdmDataNoSC) override { - m_RDMHandler.HandleData(pRdmDataNoSC, reinterpret_cast(&s_RdmCommand)); - return reinterpret_cast(&s_RdmCommand); - } + ~RDMNetDevice() { + DEBUG_ENTRY + + DEBUG_EXIT + }; void Run() { LLRPDevice::Run(); } - void Print(); + void Print() { + static constexpr auto UUID_STRING_LENGTH = 36; + char uuid_str[UUID_STRING_LENGTH + 1]; + uuid_str[UUID_STRING_LENGTH] = '\0'; -private: - RDMHandler m_RDMHandler { false }; + uint8_t s_Cid[e131::CID_LENGTH]; + Hardware::Get()->GetUuid(s_Cid); + uuid_unparse(s_Cid, uuid_str); - static TRdmMessage s_RdmCommand; - static uint8_t s_Cid[e131::CID_LENGTH]; + printf("RDMNet\n"); + printf(" CID : %s\n", uuid_str); + + LLRPDevice::Print(); + RDMDeviceResponder::Print(); + } }; #endif /* RDMNETDEVICE_H_ */ diff --git a/lib-rdmnet/include/rdmnetllrponly.h b/lib-rdm/include/rdmnetllrponly.h old mode 100644 new mode 100755 similarity index 100% rename from lib-rdmnet/include/rdmnetllrponly.h rename to lib-rdm/include/rdmnetllrponly.h diff --git a/lib-rdm/include/rdmpersonality.h b/lib-rdm/include/rdmpersonality.h index f53209a9..92f76406 100644 --- a/lib-rdm/include/rdmpersonality.h +++ b/lib-rdm/include/rdmpersonality.h @@ -2,7 +2,7 @@ * @file rdmpersonality.h * */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-rdm/include/rdmqueuedmessage.h b/lib-rdm/include/rdmqueuedmessage.h index 3ce5fe17..b713a36b 100644 --- a/lib-rdm/include/rdmqueuedmessage.h +++ b/lib-rdm/include/rdmqueuedmessage.h @@ -28,8 +28,6 @@ #include -#include "rdmmessage.h" - struct TRdmQueuedMessage { uint8_t command_class; ///< 21 uint8_t param_id[2]; ///< 22, 23 diff --git a/lib-rdm/include/rdmresponder.h b/lib-rdm/include/rdmresponder.h new file mode 100644 index 00000000..b685dbdb --- /dev/null +++ b/lib-rdm/include/rdmresponder.h @@ -0,0 +1,192 @@ +/** + * @file rdmresponder.h + * + */ +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef RDMRESPONDER_H_ +#define RDMRESPONDER_H_ + +#include +#include +#include + +#include "rdm.h" +#include "rdmhandler.h" +#include "rdmdeviceresponder.h" +#include "rdmpersonality.h" + +#include "dmxreceiver.h" + +#include "lightset.h" + +#include "debug.h" + +#if defined (NODE_RDMNET_LLRP_ONLY) +# error "Cannot be both RDMNet Device and RDM Responder" +#endif + +namespace rdm { +namespace responder { +static constexpr int NO_DATA = 0; +static constexpr int DISCOVERY_RESPONSE = -1; +static constexpr int INVALID_DATA_RECEIVED = -2; +static constexpr int INVALID_RESPONSE = -3; +} // namespace responder +} // namespace rdm + +namespace configstore { +void delay(); +} // namespace configstore + +class RDMResponder final : DMXReceiver, public RDMDeviceResponder, RDMHandler { +public: + RDMResponder(RDMPersonality **pRDMPersonalities, uint32_t nPersonalityCount, const uint32_t nCurrentPersonality = rdm::device::responder::DEFAULT_CURRENT_PERSONALITY) : + DMXReceiver(pRDMPersonalities[nCurrentPersonality - 1]->GetLightSet()), + RDMDeviceResponder(pRDMPersonalities, nPersonalityCount, nCurrentPersonality) + { + assert(s_pThis == nullptr); + s_pThis = this; + } + + ~RDMResponder() override = default; + + void Init() { + RDMDeviceResponder::Init(); + // There is no DMXReceiver::Init() + } + + int Run() { + int16_t nLength; + +#if !defined (CONFIG_RDM_ENABLE_SUBDEVICES) + DMXReceiver::Run(nLength); +#else + const auto *pDmxDataIn = DMXReceiver::Run(nLength); + + if (RDMSubDevices::Get()->GetCount() != 0) { + if (nLength == -1) { + if (m_IsSubDeviceActive) { + RDMSubDevices::Get()->Stop(); + m_IsSubDeviceActive = false; + } + } else if (pDmxDataIn != nullptr) { + RDMSubDevices::Get()->SetData(pDmxDataIn, static_cast(nLength)); + if (!m_IsSubDeviceActive) { + RDMSubDevices::Get()->Start(); + m_IsSubDeviceActive = true; + } + } + } +#endif + + const auto *pRdmDataIn = Rdm::Receive(0); + + if (pRdmDataIn == nullptr) { + return rdm::responder::NO_DATA; + } + +#ifndef NDEBUG + rdm::message_print(pRdmDataIn); +#endif + + if (pRdmDataIn[0] == E120_SC_RDM) { + const auto *pRdmCommand = reinterpret_cast(pRdmDataIn); + + switch (pRdmCommand->command_class) { + case E120_DISCOVERY_COMMAND: + case E120_GET_COMMAND: + case E120_SET_COMMAND: + HandleData(&pRdmDataIn[1], reinterpret_cast(&s_RdmCommand)); + return HandleResponse(reinterpret_cast(&s_RdmCommand)); + break; + default: + DEBUG_PUTS("RDM_RESPONDER_INVALID_DATA_RECEIVED"); + return rdm::responder::INVALID_DATA_RECEIVED; + break; + } + } + + DEBUG_PUTS("RDM_RESPONDER_DISCOVERY_RESPONSE"); + return rdm::responder::DISCOVERY_RESPONSE; + } + + void Print() { + RDMDeviceResponder::Print(); + DMXReceiver::Print(); + } + + void Start() { + // There is no RDMDeviceResponder::Start() + DMXReceiver::Start(); + } + + void DmxDisableOutput(const bool bDisable) { + DMXReceiver::SetDisableOutput(bDisable); + } + + static RDMResponder *Get() { + return s_pThis; + } + + void PersonalityUpdate(uint32_t nPersonality) __attribute__((weak)); + void DmxStartAddressUpdate(uint16_t nDmxStartAddress) __attribute__((weak)); + +private: + int HandleResponse(const uint8_t *pResponse) { + auto nLength = rdm::responder::INVALID_RESPONSE; + + if (pResponse[0] == E120_SC_RDM) { + const auto *p = reinterpret_cast(pResponse); + nLength = static_cast(p->message_length + RDM_MESSAGE_CHECKSUM_SIZE); + Rdm::SendRawRespondMessage(0, pResponse, static_cast(nLength)); + } else if (pResponse[0] == 0xFE) { + nLength = sizeof(struct TRdmDiscoveryMsg); + Rdm::SendDiscoveryRespondMessage(0, pResponse, static_cast(nLength)); + } + +#ifndef NDEBUG + if (nLength != INVALID_RESPONSE) { + rdm::message_print(pResponse); + } +#endif + + configstore::delay(); + return nLength; + } + + void PersonalityUpdate(LightSet *pLightSet) override { + DMXReceiver::SetLightSet(pLightSet); + PersonalityUpdate(static_cast(RDMDeviceResponder::GetPersonalityCurrent(RDM_ROOT_DEVICE))); + } + + void DmxStartAddressUpdate() override { + DmxStartAddressUpdate(RDMDeviceResponder::GetDmxStartAddress(RDM_ROOT_DEVICE)); + } + +private: + static RDMResponder *s_pThis; + static TRdmMessage s_RdmCommand; + static bool m_IsSubDeviceActive; +}; + +#endif /* RDMRESPONDER_H_ */ diff --git a/lib-rdm/include/rdmsensor.h b/lib-rdm/include/rdmsensor.h new file mode 100644 index 00000000..41cb1ea7 --- /dev/null +++ b/lib-rdm/include/rdmsensor.h @@ -0,0 +1,206 @@ +/** + * @file rdmsensor.h + * + */ +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef RDMSENSOR_H_ +#define RDMSENSOR_H_ + +#include +#include +#include +#include + +#include "debug.h" + +namespace rdm { +namespace sensor { +struct Defintion { + uint8_t sensor; + uint8_t type; + uint8_t unit; + uint8_t prefix; + int16_t range_min; + int16_t range_max; + int16_t normal_min; + int16_t normal_max; + char description[32]; + uint8_t nLength; + uint8_t recorded_supported; +}; + +struct Values { + int16_t present; + int16_t lowest_detected; + int16_t highest_detected; + int16_t recorded; + uint8_t sensor_requested; +}; + +static constexpr int16_t RANGE_MIN = -32768; +static constexpr int16_t RANGE_MAX = +32767; +static constexpr int16_t NORMAL_MIN = -32768; +static constexpr int16_t NORMAL_MAX = +32767; +static constexpr int16_t TEMPERATURE_ABS_ZERO = -273; + +static constexpr uint8_t RECORDED_SUPPORTED = (1U << 0); +static constexpr uint8_t LOW_HIGH_DETECT = (1U << 1); + +template +constexpr int16_t safe_range_max(const T &a) { + static_assert(sizeof(int16_t) <= sizeof(T), "T"); + return (a > static_cast(INT16_MAX)) ? INT16_MAX : static_cast(a); +} + +template +constexpr int16_t safe_range_min(const T &a) { + static_assert(sizeof(int16_t) <= sizeof(T), "T"); + return (a < static_cast(INT16_MIN)) ? INT16_MIN : static_cast(a); +} +} // namespace rdm +} // namespace sensor + + +class RDMSensor { +public: + RDMSensor(const uint8_t nSensor) : m_nSensor(nSensor) { + DEBUG_ENTRY + + m_tRDMSensorDefintion.sensor = m_nSensor; + m_tRDMSensorDefintion.recorded_supported = rdm::sensor::RECORDED_SUPPORTED | rdm::sensor::LOW_HIGH_DETECT; + + m_tRDMSensorValues.sensor_requested = m_nSensor; + m_tRDMSensorValues.lowest_detected = rdm::sensor::RANGE_MAX; + m_tRDMSensorValues.highest_detected = rdm::sensor::RANGE_MIN; + + DEBUG_EXIT + } + + virtual ~RDMSensor() = default; + +public: + void SetType(const uint8_t nType) { + m_tRDMSensorDefintion.type = nType; + } + + void SetUnit(const uint8_t nUnit) { + m_tRDMSensorDefintion.unit = nUnit; + } + + void SetPrefix(const uint8_t nPrefix) { + m_tRDMSensorDefintion.prefix = nPrefix; + } + + void SetRangeMin(const int16_t nRangeMin) { + m_tRDMSensorDefintion.range_min = nRangeMin; + } + + void SetRangeMax(const int16_t nRangeMax) { + m_tRDMSensorDefintion.range_max = nRangeMax; + } + + void SetNormalMin(const int16_t nNormalMin) { + m_tRDMSensorDefintion.normal_min = nNormalMin; + } + + void SetNormalMax(const int16_t nNormalMax) { + m_tRDMSensorDefintion.normal_max = nNormalMax; + } + + void SetDescription(const char *pDescription) { + DEBUG_ENTRY + + assert(pDescription != nullptr); + uint32_t i; + + for (i = 0; i < 32 && pDescription[i] != 0; i++) { + m_tRDMSensorDefintion.description[i] = pDescription[i]; + } + + m_tRDMSensorDefintion.nLength = static_cast(i); + + DEBUG_EXIT + } + + void Print() { + printf("%d [%.*s]\n", m_tRDMSensorDefintion.sensor, m_tRDMSensorDefintion.nLength, m_tRDMSensorDefintion.description); + printf(" RangeMin %d\n", m_tRDMSensorDefintion.range_min); + printf(" RangeMax %d\n", m_tRDMSensorDefintion.range_max); + printf(" NormalMin %d\n", m_tRDMSensorDefintion.normal_min); + printf(" NormalMax %d\n", m_tRDMSensorDefintion.normal_max); + } + + uint8_t GetSensor() const { + return m_nSensor; + } + + const struct rdm::sensor::Defintion* GetDefintion() { + return &m_tRDMSensorDefintion; + } + + const struct rdm::sensor::Values *GetValues() { + DEBUG_ENTRY + const auto nValue = this->GetValue(); + + m_tRDMSensorValues.present = nValue; + m_tRDMSensorValues.lowest_detected = std::min(m_tRDMSensorValues.lowest_detected, nValue); + m_tRDMSensorValues.highest_detected = std::max(m_tRDMSensorValues.highest_detected, nValue); + + DEBUG_EXIT + return &m_tRDMSensorValues; + } + + void SetValues() { + DEBUG_ENTRY + const auto nValue = this->GetValue(); + + m_tRDMSensorValues.present = nValue; + m_tRDMSensorValues.lowest_detected = nValue; + m_tRDMSensorValues.highest_detected = nValue; + m_tRDMSensorValues.recorded = nValue; + + DEBUG_EXIT + } + + void Record() { + DEBUG_ENTRY + const auto nValue = this->GetValue(); + + m_tRDMSensorValues.present = nValue; + m_tRDMSensorValues.recorded = nValue; + m_tRDMSensorValues.lowest_detected = std::min(m_tRDMSensorValues.lowest_detected, nValue); + m_tRDMSensorValues.highest_detected = std::max(m_tRDMSensorValues.highest_detected, nValue); + + DEBUG_EXIT + } + + virtual bool Initialize()=0; + virtual int16_t GetValue()=0; + +private: + uint8_t m_nSensor; + rdm::sensor::Defintion m_tRDMSensorDefintion; + rdm::sensor::Values m_tRDMSensorValues; +}; + +#endif /* RDMSENSOR_H_ */ diff --git a/lib-rdm/include/rdmsensors.h b/lib-rdm/include/rdmsensors.h new file mode 100644 index 00000000..cea2b084 --- /dev/null +++ b/lib-rdm/include/rdmsensors.h @@ -0,0 +1,170 @@ +/** + * @file rdmsensors.h + * + */ +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef RDMSENSORS_H_ +#define RDMSENSORS_H_ + +#include +#include + +#include "rdmsensor.h" + +#include "debug.h" + +#if defined (__APPLE__) || (defined (__linux__) && !defined (RASPPI)) +#else +# define RDM_SENSORS_ENABLE +#endif + +#if !defined (__APPLE__) +# define RDMSENSOR_CPU_ENABLE +#endif + +#if defined (NODE_RDMNET_LLRP_ONLY) +# undef RDM_SENSORS_ENABLE +# undef RDMSENSOR_CPU_ENABLE +#endif + +#if defined (RDMSENSOR_CPU_ENABLE) +# include "sensor/cputemperature.h" +#endif + +namespace rdm { +namespace sensors { +static constexpr auto MAX = 16; +static constexpr auto STORE = 64; ///< Configuration store in bytes +namespace devices { +static constexpr auto MAX = 8; +} // namespace devices +} // namespace sensors +} // namespace rdm + +class RDMSensors { +public: + RDMSensors() { + DEBUG_ENTRY + assert(s_pThis == nullptr); + s_pThis = this; + +#if defined (RDM_SENSORS_ENABLE) || defined (RDMSENSOR_CPU_ENABLE) + m_pRDMSensor = new RDMSensor*[rdm::sensors::MAX]; + assert(m_pRDMSensor != nullptr); + +# if defined (RDMSENSOR_CPU_ENABLE) + Add(new CpuTemperature(m_nCount)); +# endif +#endif + DEBUG_EXIT + } + + ~RDMSensors() { + DEBUG_ENTRY + for (uint32_t i = 0; i < m_nCount; i++) { + if (m_pRDMSensor[i] != nullptr) { + delete m_pRDMSensor[i]; + m_pRDMSensor[i] = nullptr; + } + } + + delete [] m_pRDMSensor; + DEBUG_EXIT + } + + bool Add(RDMSensor *pRDMSensor) { + DEBUG_ENTRY + + assert(m_pRDMSensor != nullptr); + + if (m_pRDMSensor == nullptr) { + DEBUG_EXIT + return false; + } + + if (m_nCount == rdm::sensors::MAX) { + DEBUG_EXIT + return false; + } + + assert(pRDMSensor != nullptr); + m_pRDMSensor[m_nCount++] = pRDMSensor; + + DEBUG_PRINTF("m_nCount=%u", m_nCount); + DEBUG_EXIT + return true; + } + + uint8_t GetCount() const { + return m_nCount; + } + + const struct rdm::sensor::Defintion *GetDefintion(const uint8_t nSensor) { + assert(nSensor < m_nCount); + assert(m_pRDMSensor[nSensor] != nullptr); + return m_pRDMSensor[nSensor]->GetDefintion(); + } + + const struct rdm::sensor::Values *GetValues(const uint8_t nSensor) { + assert(nSensor < m_nCount); + + assert(m_pRDMSensor[nSensor] != nullptr); + return m_pRDMSensor[nSensor]->GetValues(); + } + + void SetValues(const uint8_t nSensor) { + if (nSensor == 0xFF) { + for (uint32_t i = 0; i < m_nCount; i++) { + m_pRDMSensor[i]->SetValues(); + } + } else { + m_pRDMSensor[nSensor]->SetValues(); + } + } + + void SetRecord(const uint8_t nSensor) { + if (nSensor == 0xFF) { + for (uint32_t i = 0; i < m_nCount; i++) { + m_pRDMSensor[i]->Record(); + } + } else { + m_pRDMSensor[nSensor]->Record(); + } + } + + RDMSensor *GetSensor(uint8_t nSensor) { + return m_pRDMSensor[nSensor]; + } + + static RDMSensors* Get() { + return s_pThis; + } + +private: + RDMSensor **m_pRDMSensor { nullptr }; + uint8_t m_nCount { 0 }; + + static RDMSensors *s_pThis; +}; + +#endif /* RDMSENSORS_H_ */ diff --git a/lib-rdm/include/rdmslotinfo.h b/lib-rdm/include/rdmslotinfo.h index 5c99e65b..5bbf0c08 100644 --- a/lib-rdm/include/rdmslotinfo.h +++ b/lib-rdm/include/rdmslotinfo.h @@ -2,7 +2,7 @@ * @file rdmslotinfo.h * */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-rdm/include/rdmsubdevice.h b/lib-rdm/include/rdmsubdevice.h new file mode 100644 index 00000000..32c50bef --- /dev/null +++ b/lib-rdm/include/rdmsubdevice.h @@ -0,0 +1,200 @@ +/** + * @file rdmsubdevice.h + * + */ +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef RDMSUBDEVICE_H_ +#define RDMSUBDEVICE_H_ + +#include "rdmdevice.h" +#include "rdmpersonality.h" + +struct TRDMSubDevicesInfo { + uint16_t dmx_footprint; + uint16_t dmx_start_address; + uint8_t current_personality; + uint8_t personality_count; + char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH]; + uint8_t nLabelLength; + uint8_t sensor_count; +}; + +enum TRDMSubDeviceUpdateEvent { + RDM_SUBDEVICE_UPDATE_EVENT_DMX_STARTADDRESS, + RDM_SUBDEVICE_UPDATE_EVENT_PERSONALITY +}; + +class RDMSubDevice { +public: + RDMSubDevice(const char* pLabel, uint16_t nDmxStartAddress = 1, uint8_t nPersonalityCurrent = 1): + m_nDmxStartAddressFactoryDefault(nDmxStartAddress), + m_nCurrentPersonalityFactoryDefault(nPersonalityCurrent) + { + for (uint32_t i = 0; (i < RDM_DEVICE_LABEL_MAX_LENGTH) && pLabel[i] != 0; i++) { + m_aLabelFactoryDefault[i] = pLabel[i]; + } + + SetLabel(pLabel); + + m_tSubDevicesInfo.dmx_start_address = nDmxStartAddress; + m_tSubDevicesInfo.current_personality = nPersonalityCurrent; + + m_tSubDevicesInfo.sensor_count = 0; + m_tSubDevicesInfo.personality_count = 0; + + m_nCheckSum = CalculateChecksum(); + } + + virtual ~RDMSubDevice() = default; + + void SetDmxStartAddress(uint16_t nDmxStartAddress) { + m_tSubDevicesInfo.dmx_start_address = nDmxStartAddress; + UpdateEvent(RDM_SUBDEVICE_UPDATE_EVENT_DMX_STARTADDRESS); + } + + uint16_t GetDmxStartAddress() const { + return m_tSubDevicesInfo.dmx_start_address; + } + + uint8_t GetPersonalityCurrent() const { + return m_tSubDevicesInfo.current_personality; + } + + void SetPersonalityCurrent(uint8_t nCurrent) { + m_tSubDevicesInfo.current_personality = nCurrent; + } + + void GetLabel(struct TRDMDeviceInfoData* pInfoData) { + assert(pInfoData != nullptr); + + pInfoData->data = m_tSubDevicesInfo.aLabel; + pInfoData->length = m_tSubDevicesInfo.nLabelLength; + } + + void SetLabel(const char *pLabel) { + assert(pLabel != nullptr); + uint32_t i; + + for (i = 0; (i < RDM_DEVICE_LABEL_MAX_LENGTH) && (pLabel[i] != 0); i++) { + m_tSubDevicesInfo.aLabel[i] = pLabel[i]; + } + + m_tSubDevicesInfo.nLabelLength = static_cast(i); + } + + void SetLabel(const char *pLabel, uint8_t nLabelLength) { + assert(pLabel != nullptr); + uint32_t i; + + for (i = 0; (i < RDM_DEVICE_LABEL_MAX_LENGTH) && (i < nLabelLength); i++) { + m_tSubDevicesInfo.aLabel[i] = pLabel[i]; + } + + m_tSubDevicesInfo.nLabelLength = static_cast(i); + } + + struct TRDMSubDevicesInfo* GetInfo() { + return &m_tSubDevicesInfo; + } + + RDMPersonality *GetPersonality(uint8_t nPersonality) { + assert(nPersonality != 0); + assert(nPersonality <= m_tSubDevicesInfo.personality_count); + + return m_pRDMPersonalities[nPersonality - 1]; + } + + uint8_t GetPersonalityCount() const { + return m_tSubDevicesInfo.personality_count; + } + + uint16_t GetDmxFootPrint() const { + return m_tSubDevicesInfo.dmx_footprint; + } + + bool GetFactoryDefaults() { + if (m_IsFactoryDefaults) { + if (m_nCheckSum != CalculateChecksum()) { + m_IsFactoryDefaults = false; + } + } + + return m_IsFactoryDefaults; + } + + void SetFactoryDefaults() { + if (m_IsFactoryDefaults) { + return; + } + + SetLabel(m_aLabelFactoryDefault); + + m_tSubDevicesInfo.dmx_start_address = m_nDmxStartAddressFactoryDefault; + m_tSubDevicesInfo.current_personality = m_nCurrentPersonalityFactoryDefault; + + m_IsFactoryDefaults = true; + } + + virtual bool Initialize()=0; + virtual void Start()= 0; + virtual void Stop()= 0; + virtual void Data(const uint8_t *pDdata, uint32_t nLength)=0; + +protected: + void SetDmxFootprint(uint16_t nDmxFootprint) { + m_tSubDevicesInfo.dmx_footprint = nDmxFootprint; + } + + void SetPersonalities(RDMPersonality **pRDMPersonalities, uint8_t nPersonalityCount) { + assert(pRDMPersonalities != nullptr); + + m_tSubDevicesInfo.personality_count = nPersonalityCount; + m_pRDMPersonalities = pRDMPersonalities; + + UpdateEvent(RDM_SUBDEVICE_UPDATE_EVENT_PERSONALITY); + } + +private: + virtual void UpdateEvent([[maybe_unused]] TRDMSubDeviceUpdateEvent tUpdateEvent) {} + uint16_t CalculateChecksum() { + uint16_t nChecksum = m_tSubDevicesInfo.dmx_start_address; + nChecksum = static_cast(nChecksum + m_tSubDevicesInfo.current_personality); + + for (uint32_t i = 0; i < m_tSubDevicesInfo.nLabelLength; i++) { + nChecksum = static_cast(nChecksum + m_tSubDevicesInfo.aLabel[i]); + } + + return nChecksum; + } + +private: + RDMPersonality **m_pRDMPersonalities { nullptr }; + bool m_IsFactoryDefaults { true }; + uint16_t m_nCheckSum { 0 }; + uint16_t m_nDmxStartAddressFactoryDefault; + uint8_t m_nCurrentPersonalityFactoryDefault; + TRDMSubDevicesInfo m_tSubDevicesInfo; + char m_aLabelFactoryDefault[RDM_DEVICE_LABEL_MAX_LENGTH]; +}; + +#endif /* RDMSUBDEVICE_H_ */ diff --git a/lib-rdm/include/rdmsubdevices.h b/lib-rdm/include/rdmsubdevices.h new file mode 100644 index 00000000..cb08b5dd --- /dev/null +++ b/lib-rdm/include/rdmsubdevices.h @@ -0,0 +1,248 @@ +/** + * @file rdmsubdevices.h + * + */ +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef RDMSUBDEVICES_H_ +#define RDMSUBDEVICES_H_ + +#include +#include + +#include "rdmsubdevice.h" + +#ifndef NDEBUG +# include "subdevice/rdmsubdevicedummy.h" +#endif + +#include "rdmpersonality.h" + +#include "debug.h" + +#if defined (NODE_RDMNET_LLRP_ONLY) +# undef CONFIG_RDM_ENABLE_SUBDEVICES +#endif + +namespace rdm { +namespace subdevices { +static constexpr auto MAX = 8; +static constexpr auto STORE = 96; ///< Configuration store in bytes +} // namespace subdevices +} // namespace rdm + +class RDMSubDevices { +public: + RDMSubDevices() { + DEBUG_ENTRY + assert(s_pThis == nullptr); + s_pThis = this; + +#if defined(CONFIG_RDM_ENABLE_SUBDEVICES) + m_pRDMSubDevice = new RDMSubDevice*[rdm::subdevices::MAX]; + assert(m_pRDMSubDevice != nullptr); + +# ifndef NDEBUG + Add(new RDMSubDeviceDummy); +# endif +#endif + DEBUG_EXIT + } + + ~RDMSubDevices() { + DEBUG_ENTRY + for (unsigned i = 0; i < m_nCount; i++) { + delete m_pRDMSubDevice[i]; + m_pRDMSubDevice[i] = nullptr; + } + + delete [] m_pRDMSubDevice; + + m_nCount = 0; + DEBUG_EXIT + } + +#undef UNUSED +#if defined (CONFIG_RDM_ENABLE_SUBDEVICES) +# define UNUSED +#else +# define UNUSED [[maybe_unused]] +#endif + + bool Add(UNUSED RDMSubDevice *pRDMSubDevice) { + DEBUG_ENTRY +#if defined(CONFIG_RDM_ENABLE_SUBDEVICES) + assert(m_pRDMSubDevice != nullptr); + + if (m_pRDMSubDevice == nullptr) { + return false; + } + + if (m_nCount == rdm::subdevices::MAX) { + DEBUG_EXIT + return false; + } + + assert(pRDMSubDevice != nullptr); + m_pRDMSubDevice[m_nCount++] = pRDMSubDevice; +#endif + DEBUG_EXIT + return true; + } + + uint16_t GetCount() const { + return m_nCount; + } + + struct TRDMSubDevicesInfo *GetInfo(const uint16_t nSubDevice) { + assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); + assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); + return m_pRDMSubDevice[nSubDevice - 1]->GetInfo(); + } + + uint16_t GetDmxFootPrint(const uint16_t nSubDevice) { + assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); + assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); + return m_pRDMSubDevice[nSubDevice - 1]->GetDmxFootPrint(); + } + + RDMPersonality *GetPersonality(const uint16_t nSubDevice, const uint8_t nPersonality) { + assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); + assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); + return m_pRDMSubDevice[nSubDevice - 1]->GetPersonality(nPersonality); + } + + uint8_t GetPersonalityCount(const uint16_t nSubDevice) { + assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); + assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); + return m_pRDMSubDevice[nSubDevice - 1]->GetPersonalityCount(); + } + + uint8_t GetPersonalityCurrent(const uint16_t nSubDevice) { + assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); + assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); + return m_pRDMSubDevice[nSubDevice - 1]->GetPersonalityCurrent(); + } + + void SetPersonalityCurrent(const uint16_t nSubDevice, const uint8_t nPersonality) { + assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); + assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); + m_pRDMSubDevice[nSubDevice - 1]->SetPersonalityCurrent(nPersonality); + } + + // E120_DEVICE_LABEL 0x0082 + void GetLabel(const uint16_t nSubDevice, struct TRDMDeviceInfoData* pInfoData) { + assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); + assert(pInfoData != nullptr); + + assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); + m_pRDMSubDevice[nSubDevice - 1]->GetLabel(pInfoData); + } + + void SetLabel(const uint16_t nSubDevice, const char *pLabel, uint8_t nLabelLength) { + assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); + assert(pLabel != nullptr); + + assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); + m_pRDMSubDevice[nSubDevice - 1]->SetLabel(pLabel,nLabelLength); + } + + // E120_FACTORY_DEFAULTS 0x0090 + bool GetFactoryDefaults() { + for (uint32_t i = 0; i < m_nCount; i++) { + if (m_pRDMSubDevice[i] != nullptr) { + if (!m_pRDMSubDevice[i]->GetFactoryDefaults()) { + return false; + } + } + } + + return true; + } + + void SetFactoryDefaults() { + for (uint32_t i = 0; i < m_nCount; i++) { + if (m_pRDMSubDevice[i] != nullptr) { + m_pRDMSubDevice[i]->SetFactoryDefaults(); + } + } + } + + // E120_DMX_START_ADDRESS 0x00F0 + uint16_t GetDmxStartAddress(const uint16_t nSubDevice) { + assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); + assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); + return m_pRDMSubDevice[nSubDevice - 1]->GetDmxStartAddress(); + } + + void SetDmxStartAddress(const uint16_t nSubDevice, const uint16_t nDmxStartAddress) { + assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); + assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); + m_pRDMSubDevice[nSubDevice - 1]->SetDmxStartAddress(nDmxStartAddress); + } + + + void Start() { + DEBUG_ENTRY + for (uint32_t i = 0; i < m_nCount; i++) { + if (m_pRDMSubDevice[i] != nullptr) { + m_pRDMSubDevice[i]->Start(); + } + } + DEBUG_EXIT + } + + void Stop() { + DEBUG_ENTRY + for (uint32_t i = 0; i < m_nCount; i++) { + if (m_pRDMSubDevice[i] != nullptr) { + m_pRDMSubDevice[i]->Stop(); + } + } + DEBUG_ENTRY + } + + void SetData(const uint8_t *pData, const uint32_t nLength) { + for (uint32_t i = 0; i < m_nCount; i++) { + if (m_pRDMSubDevice[i] != nullptr) { + if (nLength >= (static_cast(m_pRDMSubDevice[i]->GetDmxStartAddress() + m_pRDMSubDevice[i]->GetDmxFootPrint()) - 1U)) { + m_pRDMSubDevice[i]->Data(pData, nLength); + } + } + } + } + + static RDMSubDevices* Get() { + return s_pThis; + } + +private: + RDMSubDevice **m_pRDMSubDevice { nullptr }; + uint16_t m_nCount { 0 }; + + static RDMSubDevices *s_pThis; +}; + +#if defined (UNUSED) +# undef UNUSED +#endif +#endif /* RDMSUBDEVICES_H_ */ diff --git a/lib-rdmdiscovery/include/rdmtod.h b/lib-rdm/include/rdmtod.h similarity index 94% rename from lib-rdmdiscovery/include/rdmtod.h rename to lib-rdm/include/rdmtod.h index de0c09bb..04e1ecf3 100755 --- a/lib-rdmdiscovery/include/rdmtod.h +++ b/lib-rdm/include/rdmtod.h @@ -2,7 +2,7 @@ * @file rdmtod.h * */ -/* Copyright (C) 2017-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,7 +33,7 @@ # include #endif -#include "rdm.h" +#include "rdmconst.h" #include "debug.h" @@ -61,7 +61,7 @@ class RDMTod { } } - ~RDMTod() {} + ~RDMTod() = default; void Reset() { for (uint32_t i = 0; i < m_nEntries; i++) { @@ -105,7 +105,7 @@ class RDMTod { void Copy(uint8_t *pTable) { DEBUG_ENTRY - DEBUG_PRINTF("m_nEntries=%u", m_nEntries); + DEBUG_PRINTF("m_nEntries=%u", static_cast(m_nEntries)); assert(pTable != nullptr); const auto *pSrc = reinterpret_cast(m_Tod); @@ -208,13 +208,13 @@ class RDMTod { return (mutes & (1U << shift)) == (1U << shift); } - void Dump(__attribute__((unused)) uint32_t nCount) { + void Dump([[maybe_unused]] uint32_t nCount) { #ifndef NDEBUG if (nCount > rdmtod::TOD_TABLE_SIZE) { nCount = rdmtod::TOD_TABLE_SIZE; } - printf("[%u]\n", nCount); + printf("[%u]\n", static_cast(nCount)); for (uint32_t i = 0 ; i < nCount; i++) { printf("%.2x%.2x:%.2x%.2x%.2x%.2x\n", m_Tod[i].uid[0], m_Tod[i].uid[1], m_Tod[i].uid[2], m_Tod[i].uid[3], m_Tod[i].uid[4], m_Tod[i].uid[5]); } diff --git a/lib-rdmsensor/include/cputemperature.h b/lib-rdm/include/sensor/cputemperature.h old mode 100644 new mode 100755 similarity index 94% rename from lib-rdmsensor/include/cputemperature.h rename to lib-rdm/include/sensor/cputemperature.h index b25b3578..66e2aff9 --- a/lib-rdmsensor/include/cputemperature.h +++ b/lib-rdm/include/sensor/cputemperature.h @@ -2,7 +2,7 @@ * @file cputemperature.h * */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,6 +31,7 @@ #include "rdmsensor.h" #include "rdm_e120.h" #include "hardware.h" + #include "debug.h" class CpuTemperature final: public RDMSensor { @@ -48,7 +49,7 @@ class CpuTemperature final: public RDMSensor { bool Initialize() override { DEBUG_ENTRY - #if defined (__CYGWIN__) || defined (__APPLE__) + #if defined (__APPLE__) DEBUG_EXIT return false; #else diff --git a/lib-rdmsubdevice/include/rdmsubdevicedummy.h b/lib-rdm/include/subdevice/rdmsubdevicedummy.h old mode 100644 new mode 100755 similarity index 100% rename from lib-rdmsubdevice/include/rdmsubdevicedummy.h rename to lib-rdm/include/subdevice/rdmsubdevicedummy.h diff --git a/lib-dmx/src/emac/dmxconfigudp.cpp b/lib-rdm/src/controller/rdm.cpp old mode 100644 new mode 100755 similarity index 84% rename from lib-dmx/src/emac/dmxconfigudp.cpp rename to lib-rdm/src/controller/rdm.cpp index aaf1e8ca..547bd02a --- a/lib-dmx/src/emac/dmxconfigudp.cpp +++ b/lib-rdm/src/controller/rdm.cpp @@ -1,8 +1,8 @@ /** - * @file dmxconfigudp.cpp + * @file rdm.cpp * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,7 +25,8 @@ #include -#include "dmxconfigudp.h" +#include "rdm.h" +#include "dmx.h" + +uint8_t Rdm::s_TransactionNumber[dmx::config::max::PORTS]; -int32_t DmxConfigUdp::s_nHandle = -1; -char *DmxConfigUdp::s_pUdpBuffer = nullptr; diff --git a/lib-rdm/src/controller/rdmdiscovery.cpp b/lib-rdm/src/controller/rdmdiscovery.cpp new file mode 100755 index 00000000..e1a3a466 --- /dev/null +++ b/lib-rdm/src/controller/rdmdiscovery.cpp @@ -0,0 +1,615 @@ +/** + * @file rdmddiscovery.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include "rdmdiscovery.h" +#include "hardware.h" + +#include "debug.h" + +namespace rdmdiscovery { +#ifndef NDEBUG +const static char *StateName[] = { + "IDLE", + "UNMUTE", + "MUTE", + "DISCOVERY", + "DISCOVERY_SINGLE_DEVICE", + "DUB", + "QUICKFIND", + "QUICKFIND_DISCOVERY", + "LATE_RESPONSE", + "FINISHED" +}; +#endif + +typedef union cast { + uint64_t uint; + uint8_t uid[RDM_UID_SIZE]; +} _cast; + +static _cast uuid_cast; + +static const uint8_t *convert_uid(uint64_t nUid) { + uuid_cast.uint = __builtin_bswap64(nUid << 16); + return uuid_cast.uid; +} + +#ifndef NDEBUG +static void print_uid([[maybe_unused]] const uint8_t *pUid) { + printf("%.2x%.2x:%.2x%.2x%.2x%.2x", pUid[0], pUid[1], pUid[2], pUid[3], pUid[4], pUid[5]); +} + +static void print_uid([[maybe_unused]] uint64_t nUid) { + print_uid(convert_uid(nUid)); +} +#endif + +} // namespace rdmdiscovery + +#define NEW_STATE(state, late) NewState (state, late, __LINE__); +#define SAVED_STATE() SavedState (__LINE__); + +RDMDiscovery::RDMDiscovery(const uint8_t *pUid) { + memcpy(m_Uid, pUid, RDM_UID_SIZE); + m_Message.SetSrcUid(pUid); + +#ifndef NDEBUG + printf("Uid : "); + rdmdiscovery::print_uid(m_Uid); + puts(""); +#endif +} + +uint32_t RDMDiscovery::CopyWorkingQueue(char *pOutBuffer, const uint32_t nOutBufferSize) { + const auto nSize = static_cast(nOutBufferSize); + int32_t nIndex = 0; + int32_t nLength = 0; + uint8_t pLowerBound[RDM_UID_SIZE]; + uint8_t pUpperBound[RDM_UID_SIZE]; + + while (nIndex <= m_Discovery.stack.nTop) { + memcpy(pLowerBound, rdmdiscovery::convert_uid(m_Discovery.stack.items[nIndex].nLowerBound), RDM_UID_SIZE); + memcpy(pUpperBound, rdmdiscovery::convert_uid(m_Discovery.stack.items[nIndex].nUpperBound), RDM_UID_SIZE); + + nLength += snprintf(&pOutBuffer[nLength], static_cast(nSize - nLength), + "\"%.2x%.2x:%.2x%.2x%.2x%.2x-%.2x%.2x:%.2x%.2x%.2x%.2x\",", + pLowerBound[0], pLowerBound[1], pLowerBound[2], pLowerBound[3], pLowerBound[4], pLowerBound[5], + pUpperBound[0], pUpperBound[1], pUpperBound[2], pUpperBound[3], pUpperBound[4], pUpperBound[5]); + + nIndex++; + } + + if (nLength == 0) { + return 0; + } + + pOutBuffer[nLength - 1] = '\0'; + + return static_cast(nLength - 1); +} + +bool RDMDiscovery::Full(const uint32_t nPortIndex, RDMTod *pRDMTod) { + DEBUG_ENTRY + pRDMTod->Reset(); + const auto b = Start(nPortIndex, pRDMTod, false); + DEBUG_EXIT + return b; +} + +bool RDMDiscovery::Incremental(const uint32_t nPortIndex, RDMTod *pRDMTod) { + DEBUG_ENTRY + m_Mute.nTodEntries = pRDMTod->GetUidCount(); + const auto b = Start(nPortIndex, pRDMTod, true); + DEBUG_EXIT + return b; +} + +bool RDMDiscovery::Start(const uint32_t nPortIndex, RDMTod *pRDMTod, const bool doIncremental) { + DEBUG_ENTRY + + if (m_State != rdmdiscovery::State::IDLE) { + DEBUG_PUTS("Is already running."); + DEBUG_EXIT + return false; + } + + m_nPortIndex = nPortIndex; + m_pRDMTod = pRDMTod; + + m_doIncremental = doIncremental; + m_bIsFinished = false; + + m_UnMute.nCounter = rdmdiscovery::UNMUTE_COUNTER; + m_UnMute.bCommandRunning = false; + + m_Mute.nCounter = rdmdiscovery::MUTE_COUNTER; + m_Mute.bCommandRunning = false; + + m_Discovery.stack.nTop = -1; + m_Discovery.stack.push(0x000000000000, 0xfffffffffffe); + m_Discovery.nCounter = rdmdiscovery::DISCOVERY_COUNTER; + + m_Discovery.bCommandRunning = false; + + m_DiscoverySingleDevice.nCounter = rdmdiscovery::MUTE_COUNTER; + m_DiscoverySingleDevice.bCommandRunning = false; + + m_QuikFind.nCounter = rdmdiscovery::QUIKFIND_COUNTER; + m_QuikFind.bCommandRunning = false; + + m_QuikFindDiscovery.nCounter = rdmdiscovery::QUIKFIND_DISCOVERY_COUNTER; + m_QuikFindDiscovery.bCommandRunning = false; + + NEW_STATE(rdmdiscovery::State::UNMUTE, false); + +#ifndef NDEBUG + debug.nTreeIndex = 0; +#endif + DEBUG_EXIT + return true; +} + +bool RDMDiscovery::Stop() { + DEBUG_ENTRY + + if (m_State == rdmdiscovery::State::IDLE) { + DEBUG_PUTS("Not running."); + DEBUG_EXIT + return false; + } + + m_bIsFinished = false; + + NEW_STATE(rdmdiscovery::State::IDLE, true); + + DEBUG_EXIT + return true; +} + +bool RDMDiscovery::IsValidDiscoveryResponse(uint8_t *pUid) { + uint8_t checksum[2]; + uint16_t nRdmChecksum = 6 * 0xFF; + auto bIsValid = false; + + if (m_pResponse[0] == 0xFE) { + pUid[0] = m_pResponse[8] & m_pResponse[9]; + pUid[1] = m_pResponse[10] & m_pResponse[11]; + + pUid[2] = m_pResponse[12] & m_pResponse[13]; + pUid[3] = m_pResponse[14] & m_pResponse[15]; + pUid[4] = m_pResponse[16] & m_pResponse[17]; + pUid[5] = m_pResponse[18] & m_pResponse[19]; + + checksum[0] = m_pResponse[22] & m_pResponse[23]; + checksum[1] = m_pResponse[20] & m_pResponse[21]; + + for (uint32_t i = 0; i < 6; i++) { + nRdmChecksum = static_cast(nRdmChecksum + pUid[i]); + } + + if (((nRdmChecksum >> 8) == checksum[1]) && ((nRdmChecksum & 0xFF) == checksum[0])) { + bIsValid = true; + } + +#ifndef NDEBUG + rdmdiscovery::print_uid(pUid); + printf(", checksum %.2x%.2x -> %.4x {%c}\n", checksum[1], checksum[0], nRdmChecksum, bIsValid ? 'Y' : 'N'); +#endif + } + + return bIsValid; +} + +void RDMDiscovery::SavedState([[maybe_unused]] const uint32_t nLine) { + assert(m_SavedState != m_State); +#ifndef NDEBUG + printf("State %s->%s at line %u\n", rdmdiscovery::StateName[static_cast(m_State)], rdmdiscovery::StateName[static_cast(m_SavedState)], nLine); +#endif + m_State = m_SavedState; +} + +void RDMDiscovery::NewState(const rdmdiscovery::State state, const bool doStateLateResponse, [[maybe_unused]] const uint32_t nLine) { + assert(m_State != state); + + if (doStateLateResponse && (m_State != rdmdiscovery::State::LATE_RESPONSE)) { +#ifndef NDEBUG + assert(static_cast(state) < sizeof(rdmdiscovery::StateName) / sizeof(rdmdiscovery::StateName[0])); + printf("State %s->%s [%s] at line %u\n", rdmdiscovery::StateName[static_cast(m_State)], rdmdiscovery::StateName[static_cast(rdmdiscovery::State::LATE_RESPONSE)], rdmdiscovery::StateName[static_cast(state)], nLine); +#endif + m_LateResponse.nMicros = Hardware::Get()->Micros(); + m_SavedState = state; + m_State = rdmdiscovery::State::LATE_RESPONSE; + } else { +#ifndef NDEBUG + printf("State %s->%s at line %u\n", rdmdiscovery::StateName[static_cast(m_State)], rdmdiscovery::StateName[static_cast(state)], nLine); +#endif + m_State = state; + } +} + +void RDMDiscovery::Process() { + switch (m_State) { + case rdmdiscovery::State::LATE_RESPONSE: ///< LATE_RESPONSE + m_Message.Receive(m_nPortIndex); + + if ((Hardware::Get()->Micros() - m_LateResponse.nMicros) > rdmdiscovery::LATE_RESPONSE_TIME_OUT) { + SAVED_STATE(); + } + + return; + break; + case rdmdiscovery::State::UNMUTE: ///< UNMUTE + if (m_UnMute.nCounter == 0) { + m_UnMute.nCounter = rdmdiscovery::UNMUTE_COUNTER; + m_UnMute.bCommandRunning = false; + + if (m_doIncremental) { + NEW_STATE(rdmdiscovery::State::MUTE, false); + return; + } + + NEW_STATE(rdmdiscovery::State::DISCOVERY, false); + return; + } + + if (!m_UnMute.bCommandRunning) { + m_Message.SetPortID(static_cast(1 + m_nPortIndex)); + m_Message.SetDstUid(UID_ALL); + m_Message.SetCc(E120_DISCOVERY_COMMAND); + m_Message.SetPid(E120_DISC_UN_MUTE); + m_Message.SetPd(nullptr, 0); + m_Message.Send(m_nPortIndex); + + m_UnMute.nMicros = Hardware::Get()->Micros(); + m_UnMute.bCommandRunning = true; + return; + } + + m_Message.Receive(m_nPortIndex); + + if ((Hardware::Get()->Micros() - m_UnMute.nMicros) > rdmdiscovery::RECEIVE_TIME_OUT) { + assert(m_UnMute.nCounter > 0); + m_UnMute.nCounter--; + m_UnMute.bCommandRunning = false; + } + + return; + break; + case rdmdiscovery::State::MUTE: ///< MUTE + if (m_Mute.nTodEntries == 0) { + m_Mute.bCommandRunning = false; + NEW_STATE(rdmdiscovery::State::DISCOVERY, false); + return; + } + + if (m_Mute.nCounter == 0) { + m_Mute.nCounter = rdmdiscovery::MUTE_COUNTER; + m_Mute.bCommandRunning = false; +#ifndef NDEBUG + printf("Device is gone ");rdmdiscovery::print_uid(m_Mute.uid); puts(""); +#endif + m_pRDMTod->Delete(m_Mute.uid); + + if (m_Mute.nTodEntries > 0) { + m_Mute.nTodEntries--; + } + + return; + } + + if (!m_Mute.bCommandRunning) { + assert(m_Mute.nTodEntries > 0); + m_pRDMTod->CopyUidEntry(m_Mute.nTodEntries - 1, m_Mute.uid); + + m_Message.SetPortID(static_cast(1 + m_nPortIndex)); + m_Message.SetDstUid(m_Mute.uid); + m_Message.SetCc(E120_DISCOVERY_COMMAND); + m_Message.SetPid(E120_DISC_MUTE); + m_Message.SetPd(nullptr, 0); + m_Message.Send(m_nPortIndex); + + m_Mute.nMicros = Hardware::Get()->Micros(); + m_Mute.bCommandRunning = true; + return; + } + + m_pResponse = const_cast(m_Message.Receive(m_nPortIndex)); + + if (m_pResponse != nullptr) { + assert(m_Mute.nTodEntries > 0); + m_Mute.nTodEntries--; + m_Mute.bCommandRunning = false; + return; + } + + if ((Hardware::Get()->Micros() - m_Mute.nMicros) > rdmdiscovery::RECEIVE_TIME_OUT) { + assert(m_Mute.nCounter > 0); + m_Mute.nCounter--; + m_Message.Send(m_nPortIndex); + m_Mute.nMicros = Hardware::Get()->Micros(); + } + + return; + break; + case rdmdiscovery::State::DISCOVERY: ///< DISCOVERY + if (m_Discovery.bCommandRunning) { + m_pResponse = const_cast(m_Message.Receive(m_nPortIndex)); + + if ((m_pResponse != nullptr) || (m_Discovery.nCounter == 0)) { + m_Discovery.bCommandRunning = false; + NEW_STATE(rdmdiscovery::State::DUB, false); + return; + } + + if ((Hardware::Get()->Micros() - m_Discovery.nMicros) > rdmdiscovery::RECEIVE_TIME_OUT) { + assert(m_Discovery.nCounter > 0); + m_Discovery.nCounter--; + m_Message.Send(m_nPortIndex); + m_Discovery.nMicros = Hardware::Get()->Micros(); + } + + return; + } + + if (!m_Discovery.stack.pop(m_Discovery.nLowerBound, m_Discovery.nUpperBound)) { + m_Discovery.bCommandRunning = false; + NEW_STATE(rdmdiscovery::State::FINISHED, true); + return; + } + +#ifndef NDEBUG + debug.tree[debug.nTreeIndex].nLowerBound = m_Discovery.nLowerBound; + debug.tree[debug.nTreeIndex++].nUpperBound = m_Discovery.nUpperBound; +#endif + + if (m_Discovery.nLowerBound == m_Discovery.nUpperBound) { + m_QuikFindDiscovery.bCommandRunning = false; + NEW_STATE(rdmdiscovery::State::DISCOVERY_SINGLE_DEVICE, true); + return; + } + + memcpy(m_Discovery.pdl[0], rdmdiscovery::convert_uid(m_Discovery.nLowerBound), RDM_UID_SIZE); + memcpy(m_Discovery.pdl[1], rdmdiscovery::convert_uid(m_Discovery.nUpperBound), RDM_UID_SIZE); + +#ifndef NDEBUG + printf("DISC_UNIQUE_BRANCH -> "); rdmdiscovery::print_uid(m_Discovery.pdl[0]); printf(" "); rdmdiscovery::print_uid(m_Discovery.pdl[1]); puts(""); +#endif + + m_Message.SetDstUid(UID_ALL); + m_Message.SetCc(E120_DISCOVERY_COMMAND); + m_Message.SetPid(E120_DISC_UNIQUE_BRANCH); + m_Message.SetPd(reinterpret_cast(m_Discovery.pdl), 2 * RDM_UID_SIZE); + m_Message.Send(m_nPortIndex); + + m_Discovery.nCounter = rdmdiscovery::DISCOVERY_COUNTER; + m_Discovery.nMicros = Hardware::Get()->Micros(); + m_Discovery.bCommandRunning = true; + + return; + break; + case rdmdiscovery::State::DISCOVERY_SINGLE_DEVICE: ///< DISCOVERY_SINGLE_DEVICE + if (m_DiscoverySingleDevice.nCounter == 0) { + m_DiscoverySingleDevice.nCounter = rdmdiscovery::QUIKFIND_DISCOVERY_COUNTER; + m_DiscoverySingleDevice.bCommandRunning = false; + NEW_STATE(rdmdiscovery::State::DISCOVERY, true); + return; + } + + if (!m_DiscoverySingleDevice.bCommandRunning) { + memcpy(m_Discovery.uid, rdmdiscovery::convert_uid(m_Discovery.nLowerBound), RDM_UID_SIZE); + + m_Message.SetCc(E120_DISCOVERY_COMMAND); + m_Message.SetPid(E120_DISC_MUTE); + m_Message.SetDstUid(m_Discovery.uid); + m_Message.SetPd(nullptr, 0); + m_Message.Send(m_nPortIndex); + + m_DiscoverySingleDevice.nMicros = Hardware::Get()->Micros(); + m_DiscoverySingleDevice.bCommandRunning = true; + return; + } + + m_pResponse = const_cast(m_Message.Receive(m_nPortIndex)); + + if (m_pResponse != nullptr) { + const auto pResponse = reinterpret_cast(m_pResponse); + + if ((pResponse->command_class == E120_DISCOVERY_COMMAND_RESPONSE) && (memcmp(m_Discovery.uid, pResponse->source_uid, RDM_UID_SIZE) == 0)) { + m_pRDMTod->AddUid(m_Discovery.uid); +#ifndef NDEBUG + printf("AddUid : "); + rdmdiscovery::print_uid(m_Discovery.uid); + puts(""); +#endif + + m_DiscoverySingleDevice.nCounter = rdmdiscovery::QUIKFIND_DISCOVERY_COUNTER; + m_DiscoverySingleDevice.bCommandRunning = false; + NEW_STATE(rdmdiscovery::State::DISCOVERY, false); + } + + return; + } + + if ((Hardware::Get()->Micros() - m_DiscoverySingleDevice.nMicros) > rdmdiscovery::RECEIVE_TIME_OUT) { + assert(m_Mute.nCounter > 0); + m_DiscoverySingleDevice.nCounter--; + m_Message.Send(m_nPortIndex); + m_DiscoverySingleDevice.nMicros = Hardware::Get()->Micros(); + } + + return; + break; + case rdmdiscovery::State::DUB: ///< DUB + if (m_pResponse == nullptr) { +#ifndef NDEBUG + puts("No responses"); +#endif + NEW_STATE(rdmdiscovery::State::DISCOVERY, false); + return; + } + + if (IsValidDiscoveryResponse(m_QuikFind.uid)) { + NEW_STATE(rdmdiscovery::State::QUICKFIND, true); + return; + } + + m_Discovery.nMidPosition = ((m_Discovery.nLowerBound & (0x0000800000000000 - 1)) + (m_Discovery.nUpperBound & (0x0000800000000000 - 1))) / 2 + + (m_Discovery.nUpperBound & (0x0000800000000000) ? 0x0000400000000000 : 0 ) + + (m_Discovery.nLowerBound & (0x0000800000000000) ? 0x0000400000000000 : 0 ); + + + m_Discovery.stack.push(m_Discovery.nLowerBound, m_Discovery.nMidPosition); + m_Discovery.stack.push(m_Discovery.nMidPosition + 1, m_Discovery.nUpperBound); + + NEW_STATE(rdmdiscovery::State::DISCOVERY, true); + break; + case rdmdiscovery::State::QUICKFIND: ///< QUICKFIND + if (m_QuikFind.nCounter == 0) { + m_QuikFind.bCommandRunning = false; + NEW_STATE(rdmdiscovery::State::QUICKFIND_DISCOVERY, false); + return; + } + + if (!m_QuikFind.bCommandRunning) { +#ifndef NDEBUG + printf("QuickFind : "); + rdmdiscovery::print_uid(m_QuikFind.uid); + puts(""); +#endif + + m_Message.SetCc(E120_DISCOVERY_COMMAND); + m_Message.SetPid(E120_DISC_MUTE); + m_Message.SetDstUid(m_QuikFind.uid); + m_Message.SetPd(nullptr, 0); + m_Message.Send(m_nPortIndex); + + m_QuikFind.nCounter = rdmdiscovery::QUIKFIND_COUNTER; + m_QuikFind.nMicros = Hardware::Get()->Micros(); + m_QuikFind.bCommandRunning = true; + return; + } + + m_pResponse = const_cast(m_Message.Receive(m_nPortIndex)); + + if ((m_pResponse != nullptr)) { + const auto pResponse = reinterpret_cast(m_pResponse); + + if ((pResponse->command_class != E120_DISCOVERY_COMMAND_RESPONSE) || ((static_cast((pResponse->param_id[0] << 8) + pResponse->param_id[1])) != E120_DISC_MUTE)) { + puts("QUICKFIND invalid response"); + //assert(0); + return; + } + + if ((pResponse->command_class == E120_DISCOVERY_COMMAND_RESPONSE) && (memcmp(m_QuikFind.uid, pResponse->source_uid, RDM_UID_SIZE) == 0)) { + m_pRDMTod->AddUid(m_QuikFind.uid); +#ifndef NDEBUG + printf("AddUid : "); + rdmdiscovery::print_uid(m_QuikFind.uid); + puts(""); +#endif + } + + m_QuikFind.nCounter = rdmdiscovery::QUIKFIND_COUNTER; + m_QuikFind.bCommandRunning = false; + NEW_STATE(rdmdiscovery::State::QUICKFIND_DISCOVERY, false); + return; + } + + if ((Hardware::Get()->Micros() - m_QuikFind.nMicros) > rdmdiscovery::RECEIVE_TIME_OUT) { + assert(m_QuikFind.nCounter > 0); + m_QuikFind.nCounter--; + m_QuikFind.bCommandRunning = false; + } + + return; + break; + case rdmdiscovery::State::QUICKFIND_DISCOVERY: ///< QUICKFIND_DISCOVERY + if (m_QuikFindDiscovery.nCounter == 0) { + m_QuikFindDiscovery.nCounter = rdmdiscovery::QUIKFIND_DISCOVERY_COUNTER; + m_QuikFindDiscovery.bCommandRunning = false; + NEW_STATE(rdmdiscovery::State::DISCOVERY, true); + return; + } + + if (!m_QuikFindDiscovery.bCommandRunning) { + m_Message.SetDstUid(UID_ALL); + m_Message.SetCc(E120_DISCOVERY_COMMAND); + m_Message.SetPid(E120_DISC_UNIQUE_BRANCH); + m_Message.SetPd(reinterpret_cast(m_Discovery.pdl), 2 * RDM_UID_SIZE); + m_Message.Send(m_nPortIndex); + + m_QuikFindDiscovery.nMicros = Hardware::Get()->Micros(); + m_QuikFindDiscovery.bCommandRunning = true; + return; + } + + m_pResponse = const_cast(m_Message.Receive(m_nPortIndex)); + + if ((m_pResponse != nullptr) && (IsValidDiscoveryResponse(m_QuikFind.uid))) { + m_QuikFindDiscovery.nCounter = rdmdiscovery::QUIKFIND_DISCOVERY_COUNTER; + m_QuikFindDiscovery.bCommandRunning = false; + NEW_STATE(rdmdiscovery::State::QUICKFIND, true); + return; + } + + if ((m_pResponse != nullptr) && (!IsValidDiscoveryResponse(m_QuikFind.uid))) { + m_QuikFindDiscovery.nCounter = rdmdiscovery::QUIKFIND_DISCOVERY_COUNTER; + m_QuikFindDiscovery.bCommandRunning = false; + NEW_STATE(rdmdiscovery::State::DUB, false); + return; + } + + if ((Hardware::Get()->Micros() - m_QuikFindDiscovery.nMicros) > rdmdiscovery::RECEIVE_TIME_OUT) { + assert(m_QuikFind.nCounter > 0); + m_QuikFindDiscovery.nCounter--; + m_QuikFindDiscovery.bCommandRunning = false; + } + + return; + break; + case rdmdiscovery::State::FINISHED: ///< FINISHED + m_bIsFinished = true; + NEW_STATE(rdmdiscovery::State::IDLE, false); +#ifndef NDEBUG + m_pRDMTod->Dump(); + + printf("\nStack top %d\n\n", m_Discovery.stack.nDebugStackTopMax); + + for (uint32_t i = 0; i < debug.nTreeIndex; i++) { + rdmdiscovery::print_uid(debug.tree[i].nLowerBound); printf(" "); rdmdiscovery::print_uid(debug.tree[i].nUpperBound); puts(""); + } +#endif + break; + default: + assert(0); + __builtin_unreachable(); + break; + } +} diff --git a/lib-rdmnet/src/llrpdevice.cpp b/lib-rdm/src/llrp/llrpdevice.cpp old mode 100644 new mode 100755 similarity index 85% rename from lib-rdmnet/src/llrpdevice.cpp rename to lib-rdm/src/llrp/llrpdevice.cpp index 8825d1a1..e63664fb --- a/lib-rdmnet/src/llrpdevice.cpp +++ b/lib-rdm/src/llrp/llrpdevice.cpp @@ -2,7 +2,7 @@ * @file llrpdevice.cpp * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,18 +28,20 @@ #include #include -#include "llrpdevice.h" +#include "hardware.h" -#include "llrppacket.h" - -#include "rdmmessage.h" +#include "llrp/llrpdevice.h" +#include "llrp/llrppacket.h" #include "e133.h" +#include "rdmconst.h" #include "rdm_e120.h" +#include "rdmdeviceresponder.h" +#include "rdm_message_print.h" #include "debug.h" -#if !defined(BARE_METAL) +#if defined(__linux__) || defined (__APPLE__) # define SHOW_LLRP_MESSAGE # define SHOW_RDM_MESSAGE #endif @@ -47,6 +49,7 @@ int32_t LLRPDevice::s_nHandleLLRP ; uint32_t LLRPDevice::s_nIpAddressFrom; uint8_t *LLRPDevice::s_pLLRP; +TRdmMessage LLRPDevice::s_RdmCommand; void LLRPDevice::HandleRequestMessage() { DEBUG_ENTRY @@ -56,7 +59,7 @@ void LLRPDevice::HandleRequestMessage() { const auto nLength = (static_cast((pPdu[0] & 0x0fu) << 16) | static_cast(pPdu[1] << 8) | pPdu[2]); uint8_t uid[RDM_UID_SIZE]; - CopyUID(uid); + memcpy(uid, RDMDeviceResponder::Get()->GetUID(), RDM_UID_SIZE); if (nLength > 18) { const auto nKnownUIDs = (nLength - 18) / RDM_UID_SIZE; @@ -86,7 +89,7 @@ void LLRPDevice::HandleRequestMessage() { // Root Layer PDU pReply->Common.RootLayerPDU.FlagsLength[2] = 67; - CopyCID(pReply->Common.RootLayerPDU.SenderCid); + Hardware::Get()->GetUuid(pReply->Common.RootLayerPDU.SenderCid); // LLRP PDU pReply->Common.LlrpPDU.FlagsLength[2] = 44; pReply->Common.LlrpPDU.Vector = __builtin_bswap32(VECTOR_LLRP_PROBE_REPLY); @@ -94,7 +97,7 @@ void LLRPDevice::HandleRequestMessage() { // Probe Reply PDU pReply->ProbeReplyPDU.FlagsLength[2] = 17; pReply->ProbeReplyPDU.Vector = VECTOR_PROBE_REPLY_DATA; - CopyUID(pReply->ProbeReplyPDU.UID); + memcpy(pReply->ProbeReplyPDU.UID, RDMDeviceResponder::Get()->GetUID(), RDM_UID_SIZE); Network::Get()->MacAddressCopyTo(pReply->ProbeReplyPDU.HardwareAddress); #if defined (NODE_RDMNET_LLRP_ONLY) pReply->ProbeReplyPDU.ComponentType = LLRP_COMPONENT_TYPE_NON_RDMNET; @@ -117,7 +120,7 @@ void LLRPDevice::HandleRdmCommand() { #ifdef SHOW_RDM_MESSAGE const auto *pRdmDataInNoSc = const_cast(pRDMCommand->RDMCommandPDU.RDMData); - RDMMessage::PrintNoSc(pRdmDataInNoSc); + rdm::message_print_no_sc(pRdmDataInNoSc); #endif const auto *pReply = LLRPHandleRdmCommand(pRDMCommand->RDMCommandPDU.RDMData); @@ -128,13 +131,13 @@ void LLRPDevice::HandleRdmCommand() { } uint8_t DestinationCid[16]; - memcpy(DestinationCid, pRDMCommand->Common.RootLayerPDU.SenderCid, 16); // TODO Optimize / cleanup + memcpy(DestinationCid, pRDMCommand->Common.RootLayerPDU.SenderCid, 16); const auto nMessageLength = static_cast(pReply[2] + 1); // RDM Command length without SC // Root Layer PDU pRDMCommand->Common.RootLayerPDU.FlagsLength[2] = RDM_ROOT_LAYER_LENGTH(nMessageLength); - CopyCID(pRDMCommand->Common.RootLayerPDU.SenderCid); + Hardware::Get()->GetUuid(pRDMCommand->Common.RootLayerPDU.SenderCid); // LLRP PDU pRDMCommand->Common.LlrpPDU.FlagsLength[2] = RDM_LLRP_PDU_LENGHT(nMessageLength); memcpy(pRDMCommand->Common.LlrpPDU.DestinationCid, DestinationCid, 16); @@ -145,10 +148,10 @@ void LLRPDevice::HandleRdmCommand() { const auto nLength = sizeof(struct TRootLayerPreAmble) + RDM_ROOT_LAYER_LENGTH(nMessageLength); - Network::Get()->SendTo(s_nHandleLLRP, pRDMCommand, static_cast(nLength) , llrp::device::IPV4_LLRP_RESPONSE, llrp::device::LLRP_PORT); + Network::Get()->SendTo(s_nHandleLLRP, pRDMCommand, nLength , llrp::device::IPV4_LLRP_RESPONSE, llrp::device::LLRP_PORT); #ifdef SHOW_RDM_MESSAGE - RDMMessage::Print(pReply); + rdm::message_print(pReply); #endif #ifndef NDEBUG diff --git a/lib-rdmnet/src/llrpdevicedump.cpp b/lib-rdm/src/llrp/llrpdevicedump.cpp old mode 100644 new mode 100755 similarity index 86% rename from lib-rdmnet/src/llrpdevicedump.cpp rename to lib-rdm/src/llrp/llrpdevicedump.cpp index 7bc2c360..e108d7a3 --- a/lib-rdmnet/src/llrpdevicedump.cpp +++ b/lib-rdm/src/llrp/llrpdevicedump.cpp @@ -2,7 +2,7 @@ * @file dump.cpp * */ -/* Copyright (C) 2019-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,12 +28,12 @@ #include #include -#include "llrpdevice.h" +#include "llrp/llrpdevice.h" #include "e133.h" -#include "rdm_e120.h" -#include "rdmmessage.h" +#include "rdm_e120.h" +#include "rdm_message_print.h" #include "debug.h" @@ -55,19 +55,19 @@ void LLRPDevice::DumpCommon() { for (uint32_t i = 0; i < sizeof(pCommon->RootLayerPDU.SenderCid); i++) { printf("%.02X", pCommon->RootLayerPDU.SenderCid[i]); } - printf("\n"); + puts(""); - pPdu = (uint8_t *)pCommon->LlrpPDU.FlagsLength; - nLength = ((uint32_t)((pPdu[0] & 0x0fu) << 16) | (uint32_t)(pPdu[1] << 8) | (uint32_t)pPdu[2]); + pPdu = reinterpret_cast(pCommon->LlrpPDU.FlagsLength); + nLength = (((pPdu[0] & 0x0fu) << 16) | static_cast((pPdu[1] << 8)) | static_cast(pPdu[2])); printf("LlrpPDU PDU length=%d, High 4 bits=0x%.1x\n", nLength, static_cast(pCommon->LlrpPDU.FlagsLength[0]) >> 4); printf("LlrpPDU.Vector=0x%.8x\n", __builtin_bswap32(pCommon->LlrpPDU.Vector)); printf("LlrpPDU.DestinationCid="); for (uint32_t i = 0; i < sizeof(pCommon->LlrpPDU.DestinationCid); i++) { - printf("%.02X", pCommon->LlrpPDU.DestinationCid[i]); + printf("%.02X", pCommon->LlrpPDU.DestinationCid[i]); } - printf("\n"); + puts(""); printf("LlrpPDU.TransactionNumber=0x%.4x\n", __builtin_bswap32(pCommon->LlrpPDU.TransactionNumber)); @@ -76,7 +76,7 @@ void LLRPDevice::DumpCommon() { auto *pRequest = reinterpret_cast(s_pLLRP); pPdu = reinterpret_cast(pRequest->ProbeRequestPDU.FlagsLength); - nLength = ((uint32_t) ((pPdu[0] & 0x0fu) << 16) | (uint32_t) (pPdu[1] << 8) | (uint32_t) pPdu[2]); + nLength = (((pPdu[0] & 0x0fu) << 16) | static_cast((pPdu[1] << 8)) | static_cast(pPdu[2])); printf("Probe Request PDU length=%d, High 4 bits=%.1x\n", nLength, static_cast(pRequest->ProbeRequestPDU.FlagsLength[0]) >> 4); printf("ProbeRequestPDU.Vector=0x%.2x\n", static_cast(pRequest->ProbeRequestPDU.Vector)); @@ -87,7 +87,7 @@ void LLRPDevice::DumpCommon() { auto *pReply = reinterpret_cast(s_pLLRP); pPdu = reinterpret_cast(pReply->ProbeReplyPDU.FlagsLength); - nLength = ((uint32_t) ((pPdu[0] & 0x0fu) << 16) | (uint32_t) (pPdu[1] << 8) | (uint32_t) pPdu[2]); + nLength = (((pPdu[0] & 0x0fu) << 16) | static_cast((pPdu[1] << 8)) | static_cast(pPdu[2])); printf("Probe Request PDU length=%d, High 4 bits=%.1x\n", nLength, static_cast(pReply->ProbeReplyPDU.FlagsLength[0]) >> 4); printf("ProbeRequestPDU.Vector=0x%.2x\n", static_cast(pReply->ProbeReplyPDU.Vector)); @@ -96,26 +96,26 @@ void LLRPDevice::DumpCommon() { for (uint32_t i = 0; i < sizeof(pReply->ProbeReplyPDU.UID); i++) { printf("%.02X", pReply->ProbeReplyPDU.UID[i]); } - printf("\n"); + puts(""); printf("ProbeReplyPDU.HardwareAddress="); for (uint32_t i = 0; i < sizeof(pReply->ProbeReplyPDU.HardwareAddress); i++) { printf("%.02X", pReply->ProbeReplyPDU.HardwareAddress[i]); } - printf("\n"); + puts(""); } break; case VECTOR_LLRP_RDM_CMD: { auto *pRDMCommand = reinterpret_cast(s_pLLRP); pPdu = reinterpret_cast(pRDMCommand->RDMCommandPDU.FlagsLength); - nLength = ((uint32_t) ((pPdu[0] & 0x0fu) << 16) | (uint32_t) (pPdu[1] << 8) | (uint32_t) pPdu[2]); + nLength = (((pPdu[0] & 0x0fu) << 16) | static_cast((pPdu[1] << 8)) | static_cast(pPdu[2])); printf("RDM Command PDU length=%d, High 4 bits=0x%.1x\n", nLength, pRDMCommand->RDMCommandPDU.FlagsLength[0] >> 4); printf("RDMCommandPDU.Vector=0x%.2x\n", pRDMCommand->RDMCommandPDU.Vector); } - break; + break; default: break; } @@ -137,5 +137,5 @@ void LLRPDevice::DumpLLRP() { printf("%.02X", pCommon->LlrpPDU.DestinationCid[i]); } - printf("\n"); + puts(""); } diff --git a/lib-rdm/src/llrp/rdmhandlere1372.cpp b/lib-rdm/src/llrp/rdmhandlere1372.cpp old mode 100644 new mode 100755 index 2882b713..b2fa97c6 --- a/lib-rdm/src/llrp/rdmhandlere1372.cpp +++ b/lib-rdm/src/llrp/rdmhandlere1372.cpp @@ -2,7 +2,7 @@ * @file rdmhandlere137.cpp * */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,9 +23,14 @@ * THE SOFTWARE. */ +#if defined (DEBUG_RDM_LLRP) +# undef NDEBUG +#endif + #include #include "rdmhandler.h" +#include "rdmconst.h" #include "rdm_e120.h" #include "network.h" @@ -40,11 +45,11 @@ enum { * ANSI E1.37-2 */ -bool RDMHandler::CheckInterfaceID(__attribute__((unused)) const struct TRdmMessageNoSc *pRdmDataIn) { +bool RDMHandler::CheckInterfaceID([[maybe_unused]] const struct TRdmMessageNoSc *pRdmDataIn) { #if !defined(DMX_WORKSHOP_DEFECT) - const uint32_t nInterfaceID = (pRdmDataIn->param_data[0] << 24) + const auto nInterfaceID = static_cast((pRdmDataIn->param_data[0] << 24) + (pRdmDataIn->param_data[1] << 16) - + (pRdmDataIn->param_data[2] << 8) + pRdmDataIn->param_data[3]; + + (pRdmDataIn->param_data[2] << 8) + pRdmDataIn->param_data[3]); if (nInterfaceID != Network::Get()->GetIfIndex()) { RespondMessageNack(E120_NR_DATA_OUT_OF_RANGE); @@ -54,7 +59,7 @@ bool RDMHandler::CheckInterfaceID(__attribute__((unused)) const struct TRdmMessa return true; } -void RDMHandler::GetInterfaceList(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetInterfaceList([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY // https://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml const uint16_t nInterfaceHardwareType = 0x6; // IEEE 802 Networks @@ -77,10 +82,10 @@ void RDMHandler::GetInterfaceList(__attribute__((unused)) uint16_t nSubDevice) { DEBUG_EXIT } -void RDMHandler::GetInterfaceName(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetInterfaceName([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -100,10 +105,10 @@ void RDMHandler::GetInterfaceName(__attribute__((unused)) uint16_t nSubDevice) { DEBUG_EXIT } -void RDMHandler::GetHardwareAddress(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetHardwareAddress([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -123,10 +128,10 @@ void RDMHandler::GetHardwareAddress(__attribute__((unused)) uint16_t nSubDevice) DEBUG_EXIT } -void RDMHandler::GetDHCPMode(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetDHCPMode([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -146,10 +151,10 @@ void RDMHandler::GetDHCPMode(__attribute__((unused)) uint16_t nSubDevice) { DEBUG_EXIT } -void RDMHandler::SetDHCPMode(__attribute__((unused)) bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetDHCPMode([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -164,16 +169,10 @@ void RDMHandler::SetDHCPMode(__attribute__((unused)) bool IsBroadcast, __attribu return; } - if (pRdmDataIn->param_data[4] == static_cast(network::dhcp::Mode::ACTIVE)) { - Network::Get()->SetQueuedDhcp(); - RespondMessageAck(); - - DEBUG_EXIT - return; - } + const auto mode = static_cast(pRdmDataIn->param_data[4]); - if (pRdmDataIn->param_data[4] == static_cast(network::dhcp::Mode::INACTIVE)) { - Network::Get()->SetQueuedStaticIp(); + if ((mode == network::dhcp::Mode::ACTIVE) || mode == network::dhcp::Mode::INACTIVE) { + Network::Get()->SetQueuedDhcp(mode); RespondMessageAck(); DEBUG_EXIT @@ -185,24 +184,26 @@ void RDMHandler::SetDHCPMode(__attribute__((unused)) bool IsBroadcast, __attribu DEBUG_EXIT } -void RDMHandler::GetNameServers(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetNameServers([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); - const uint16_t nNameServerIndex = pRdmDataIn->param_data[0]; + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto nNameServerIndex = pRdmDataIn->param_data[0]; - if (nNameServerIndex > 2) { + if ((nNameServerIndex >= Network::Get()->GetNameServers()) || (nNameServerIndex > 2)) { RespondMessageNack(E120_NR_DATA_OUT_OF_RANGE); DEBUG_EXIT return; } - // TODO The Network class does not have GetNameServers - auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); - memset(&pRdmDataOut->param_data[1], 0, 4); + uint32_t nIpAddress = Network::Get()->GetNameServer(nNameServerIndex); + const auto *p = reinterpret_cast(&nIpAddress); + + pRdmDataOut->param_data[0] = nNameServerIndex; + memcpy(&pRdmDataOut->param_data[1], p, 4); pRdmDataOut->param_data_length = 5; @@ -211,10 +212,10 @@ void RDMHandler::GetNameServers(__attribute__((unused)) uint16_t nSubDevice) { DEBUG_EXIT } -void RDMHandler::GetZeroconf(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetZeroconf([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -234,10 +235,10 @@ void RDMHandler::GetZeroconf(__attribute__((unused)) uint16_t nSubDevice) { DEBUG_EXIT } -void RDMHandler::SetZeroconf(__attribute__((unused)) bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetZeroconf([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -261,7 +262,7 @@ void RDMHandler::SetZeroconf(__attribute__((unused)) bool IsBroadcast, __attribu } if (pRdmDataIn->param_data[4] == 0) { - Network::Get()->SetQueuedStaticIp(); + Network::Get()->SetQueuedStaticIp(0, 0); RespondMessageAck(); DEBUG_EXIT @@ -273,10 +274,10 @@ void RDMHandler::SetZeroconf(__attribute__((unused)) bool IsBroadcast, __attribu DEBUG_EXIT } -void RDMHandler::RenewDhcp(__attribute__((unused)) bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::RenewDhcp([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -298,17 +299,17 @@ void RDMHandler::RenewDhcp(__attribute__((unused)) bool IsBroadcast, __attribute return; } - Network::Get()->EnableDhcp(); // TODO This will cause a time-out -> queued message + Network::Get()->EnableDhcp(); RespondMessageAck(); DEBUG_EXIT } -void RDMHandler::GetAddressNetmask(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetAddressNetmask([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -333,10 +334,10 @@ void RDMHandler::GetAddressNetmask(__attribute__((unused)) uint16_t nSubDevice) DEBUG_EXIT } -void RDMHandler::GetStaticAddress(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetStaticAddress([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -360,10 +361,10 @@ void RDMHandler::GetStaticAddress(__attribute__((unused)) uint16_t nSubDevice) { DEBUG_EXIT } -void RDMHandler::SetStaticAddress(__attribute__((unused)) bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetStaticAddress([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 9) { RespondMessageNack(E120_NR_FORMAT_ERROR); @@ -389,10 +390,10 @@ void RDMHandler::SetStaticAddress(__attribute__((unused)) bool IsBroadcast, __at DEBUG_EXIT } -void RDMHandler::ApplyConfiguration(__attribute__((unused)) bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::ApplyConfiguration([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -412,10 +413,10 @@ void RDMHandler::ApplyConfiguration(__attribute__((unused)) bool IsBroadcast, __ DEBUG_EXIT } -void RDMHandler::GetDefaultRoute(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetDefaultRoute([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -438,24 +439,47 @@ void RDMHandler::GetDefaultRoute(__attribute__((unused)) uint16_t nSubDevice) { DEBUG_EXIT } -void RDMHandler::SetDefaultRoute(__attribute__((unused)) bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetDefaultRoute([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - RespondMessageNack(E137_2_NR_ACTION_NOT_SUPPORTED); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + + if (pRdmDataIn->param_data_length != 8) { + RespondMessageNack(E120_NR_FORMAT_ERROR); + + DEBUG_EXIT + return; + } + + if (!CheckInterfaceID(pRdmDataIn)) { + + DEBUG_EXIT + return; + } + + uint32_t nIpAddress; + auto *p = reinterpret_cast(&nIpAddress); + memcpy(p, &pRdmDataIn->param_data[4], 4); + + Network::Get()->SetQueuedDefaultRoute(nIpAddress); + + RespondMessageAck(); + + DEBUG_EXIT } -void RDMHandler::GetHostName(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetHostName([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY const auto *pHostName = Network::Get()->GetHostName(); - HandleString(pHostName, static_cast(strlen(pHostName))); + HandleString(pHostName, static_cast(strlen(pHostName))); RespondMessageAck(); DEBUG_EXIT } -void RDMHandler::SetHostName(__attribute__((unused)) bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetHostName([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); @@ -476,18 +500,18 @@ void RDMHandler::SetHostName(__attribute__((unused)) bool IsBroadcast, __attribu DEBUG_EXIT } -void RDMHandler::GetDomainName(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetDomainName([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY const auto *pDomainName = Network::Get()->GetDomainName(); - HandleString(pDomainName, static_cast(strlen(pDomainName))); + HandleString(pDomainName, static_cast(strlen(pDomainName))); RespondMessageAck(); DEBUG_EXIT } -void RDMHandler::SetDomainName(__attribute__((unused)) bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetDomainName([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY RespondMessageNack(E137_2_NR_ACTION_NOT_SUPPORTED); diff --git a/lib-rdm/src/rdmmessageprint.cpp b/lib-rdm/src/rdm_message_print.cpp similarity index 81% rename from lib-rdm/src/rdmmessageprint.cpp rename to lib-rdm/src/rdm_message_print.cpp index 83977827..a2071dc5 100644 --- a/lib-rdm/src/rdmmessageprint.cpp +++ b/lib-rdm/src/rdm_message_print.cpp @@ -1,5 +1,5 @@ /** - * @file rdmmessageprint.cpp + * @file rdm_message_print.cpp * */ /* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl @@ -26,28 +26,15 @@ #include #include #include +#include -#include "rdmmessage.h" - -#include "rdm.h" +#include "rdmconst.h" #include "rdm_e120.h" #include "debug.h" -void RDMMessage::PrintNoSc(const uint8_t *pRdmDataNoSc) { - assert(pRdmDataNoSc != nullptr); - - const auto *pData = reinterpret_cast(pRdmDataNoSc); - - uint8_t message[sizeof(struct TRdmMessage)]; - message[0] = E120_SC_RDM; - - memcpy(&message[1], pData, pData->message_length - 1U); - - Print(message); -} - -void RDMMessage::Print(const uint8_t *pRdmData) { +namespace rdm { +void message_print(const uint8_t *pRdmData) { if (pRdmData == nullptr) { DEBUG_PUTS("No RDM data"); return; @@ -87,13 +74,38 @@ void RDMMessage::Print(const uint8_t *pRdmData) { } const auto nSubDevice = static_cast((pRdmMessage->sub_device[0] << 8) + pRdmMessage->sub_device[1]); - printf(", sub-dev: %d, tn: %d, PID 0x%.2x%.2x, pdl: %d\n", nSubDevice, pRdmMessage->transaction_number, pRdmMessage->param_id[0], pRdmMessage->param_id[1], pRdmMessage->param_data_length); + printf(", sub-dev: %d, tn: %d, PID 0x%.2x%.2x, pdl: %d", nSubDevice, pRdmMessage->transaction_number, pRdmMessage->param_id[0], pRdmMessage->param_id[1], pRdmMessage->param_data_length); + + if (pRdmMessage->param_data_length != 0) { + printf(" -> "); + for (uint32_t i = 0 ; (i < 12) && (i < pRdmMessage->param_data_length) ; i++) { + printf("%.2x ", pRdmMessage->param_data[i]); + } + } + + puts(""); + } else if (pRdmData[0] == 0xFE) { for (uint32_t i = 0 ; i < 24; i++) { printf("%.2x ", pRdmData[i]); } - printf("\n"); + puts(""); } else { printf("Corrupted? RDM data [0-3]: %.2x:%.2x:%.2x:%.2x\n", pRdmData[0], pRdmData[1], pRdmData[2], pRdmData[3]); } } + +void message_print_no_sc(const uint8_t *pRdmDataNoSc) { + assert(pRdmDataNoSc != nullptr); + + const auto *pData = reinterpret_cast(pRdmDataNoSc); + + uint8_t message[sizeof(struct TRdmMessage)]; + message[0] = E120_SC_RDM; + + memcpy(&message[1], pData, pData->message_length - 1U); + + message_print(message); +} +} // namespace rdm + diff --git a/lib-rdm/src/rdmdevice.cpp b/lib-rdm/src/rdmdevice.cpp index 9df0cb0d..1b4d55a2 100644 --- a/lib-rdm/src/rdmdevice.cpp +++ b/lib-rdm/src/rdmdevice.cpp @@ -31,7 +31,6 @@ #include "rdmdevice.h" #include "rdmconst.h" -#include "rdm.h" #include "rdm_e120.h" #include "network.h" @@ -61,10 +60,17 @@ # endif #endif +RDMDevice *RDMDevice::s_pThis; + RDMDevice::RDMDevice() { DEBUG_ENTRY + assert(s_pThis == nullptr); + s_pThis = this; + + m_aUID[0] = RDMConst::MANUFACTURER_ID[0]; + m_aUID[1] = RDMConst::MANUFACTURER_ID[1]; -#if defined (NO_EMAC) +#if defined (NO_EMAC) || !defined(CONFIG_RDMDEVICE_UUID_IP) uint8_t aMacAddress[network::MAC_SIZE]; Network::Get()->MacAddressCopyTo(aMacAddress); @@ -72,28 +78,14 @@ RDMDevice::RDMDevice() { m_aUID[3] = aMacAddress[3]; m_aUID[4] = aMacAddress[4]; m_aUID[5] = aMacAddress[5]; -#else - const auto nIp = Network::Get()->GetIp(); -# if !defined(CONFIG_RDMDEVICE_REVERSE_UID) - m_aUID[5] = static_cast(nIp >> 24); - m_aUID[4] = (nIp >> 16) & 0xFF; - m_aUID[3] = (nIp >> 8) & 0xFF; - m_aUID[2] = nIp & 0xFF; -# else - m_aUID[2] = static_cast(nIp >> 24); - m_aUID[3] = (nIp >> 16) & 0xFF; - m_aUID[4] = (nIp >> 8) & 0xFF; - m_aUID[5] = nIp & 0xFF; -# endif -#endif - - m_aUID[0] = RDMConst::MANUFACTURER_ID[0]; - m_aUID[1] = RDMConst::MANUFACTURER_ID[1]; m_aSN[0] = m_aUID[5]; m_aSN[1] = m_aUID[4]; m_aSN[2] = m_aUID[3]; m_aSN[3] = m_aUID[2]; +#else + // Calculated with GetUID and GetSN +#endif m_nFactoryRootLabelLength = sizeof(DEVICE_LABEL) - 1; memcpy(m_aFactoryRootLabel, DEVICE_LABEL, m_nFactoryRootLabelLength); @@ -102,7 +94,7 @@ RDMDevice::RDMDevice() { } void RDMDevice::Print() { - printf("RDM Device configuration\n"); + puts("RDM Device configuration"); const auto nLength = static_cast(std::min(static_cast(RDM_MANUFACTURER_LABEL_MAX_LENGTH), strlen(RDMConst::MANUFACTURER_NAME))); printf(" Manufacturer Name : %.*s\n", nLength, const_cast(&RDMConst::MANUFACTURER_NAME[0])); printf(" Manufacturer ID : %.2X%.2X\n", m_aUID[0], m_aUID[1]); diff --git a/lib-rdm/src/rdmdeviceparams.cpp b/lib-rdm/src/rdmdeviceparams.cpp index 38485983..aa6644ff 100644 --- a/lib-rdm/src/rdmdeviceparams.cpp +++ b/lib-rdm/src/rdmdeviceparams.cpp @@ -2,7 +2,7 @@ * @file rdmdeviceparams.cpp * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,13 +30,12 @@ #include #include -#ifndef NDEBUG -# include -#endif +#include #include #include "rdmdeviceparams.h" #include "rdmdeviceparamsconst.h" +#include "rdmdevice.h" #include "rdm_e120.h" @@ -45,12 +44,11 @@ #include "readconfigfile.h" #include "sscan.h" - #include "propertiesbuilder.h" #include "debug.h" -RDMDeviceParams::RDMDeviceParams(RDMDeviceParamsStore *pRDMDeviceParamsStore): m_pRDMDeviceParamsStore(pRDMDeviceParamsStore) { +RDMDeviceParams::RDMDeviceParams() { DEBUG_ENTRY memset(&m_Params, 0, sizeof(struct rdm::deviceparams::Params)); @@ -61,7 +59,7 @@ RDMDeviceParams::RDMDeviceParams(RDMDeviceParamsStore *pRDMDeviceParamsStore): m DEBUG_EXIT } -bool RDMDeviceParams::Load() { +void RDMDeviceParams::Load() { DEBUG_ENTRY #if !defined(DISABLE_FS) @@ -70,20 +68,15 @@ bool RDMDeviceParams::Load() { ReadConfigFile configfile(RDMDeviceParams::staticCallbackFunction, this); if (configfile.Read(RDMDeviceParamsConst::FILE_NAME)) { - if (m_pRDMDeviceParamsStore != nullptr) { - m_pRDMDeviceParamsStore->Update(&m_Params); - } + RDMDeviceParamsStore::Update(&m_Params); } else #endif - if (m_pRDMDeviceParamsStore != nullptr) { - m_pRDMDeviceParamsStore->Copy(&m_Params); - } else { - DEBUG_EXIT - return false; - } + RDMDeviceParamsStore::Copy(&m_Params); +#ifndef NDEBUG + Dump(); +#endif DEBUG_EXIT - return true; } void RDMDeviceParams::Load(const char *pBuffer, uint32_t nLength) { @@ -98,9 +91,11 @@ void RDMDeviceParams::Load(const char *pBuffer, uint32_t nLength) { config.Read(pBuffer, nLength); - assert(m_pRDMDeviceParamsStore != nullptr); - m_pRDMDeviceParamsStore->Update(&m_Params); + RDMDeviceParamsStore::Update(&m_Params); +#ifndef NDEBUG + Dump(); +#endif DEBUG_EXIT } @@ -163,31 +158,6 @@ void RDMDeviceParams::Set(RDMDevice *pRDMDevice) { } } -void RDMDeviceParams::Dump() { -#ifndef NDEBUG - printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, RDMDeviceParamsConst::FILE_NAME); - - if (isMaskSet(rdm::deviceparams::Mask::LABEL)) { - printf(" %s=%.*s\n", RDMDeviceParamsConst::LABEL, m_Params.nDeviceRootLabelLength, m_Params.aDeviceRootLabel); - } - - if (isMaskSet(rdm::deviceparams::Mask::PRODUCT_CATEGORY)) { - printf(" %s=%.4x\n", RDMDeviceParamsConst::PRODUCT_CATEGORY, m_Params.nProductCategory); - } - - if (isMaskSet(rdm::deviceparams::Mask::PRODUCT_DETAIL)) { - printf(" %s=%.4x\n", RDMDeviceParamsConst::PRODUCT_DETAIL, m_Params.nProductDetail); - } -#endif -} - -void RDMDeviceParams::staticCallbackFunction(void *p, const char *s) { - assert(p != nullptr); - assert(s != nullptr); - - (static_cast(p))->callbackFunction(s); -} - void RDMDeviceParams::Builder(const struct rdm::deviceparams::Params *pParams, char *pBuffer, uint32_t nLength, uint32_t& nSize) { DEBUG_ENTRY @@ -196,17 +166,43 @@ void RDMDeviceParams::Builder(const struct rdm::deviceparams::Params *pParams, c if (pParams != nullptr) { memcpy(&m_Params, pParams, sizeof(struct rdm::deviceparams::Params)); } else { - assert(m_pRDMDeviceParamsStore != nullptr); - m_pRDMDeviceParamsStore->Copy(&m_Params); + RDMDeviceParamsStore::Copy(&m_Params); } PropertiesBuilder builder(RDMDeviceParamsConst::FILE_NAME, pBuffer, nLength); - builder.AddHex16(RDMDeviceParamsConst::PRODUCT_CATEGORY, m_Params.nProductCategory, isMaskSet(rdm::deviceparams::Mask::PRODUCT_CATEGORY)); - builder.AddHex16(RDMDeviceParamsConst::PRODUCT_DETAIL, m_Params.nProductDetail, isMaskSet(rdm::deviceparams::Mask::PRODUCT_DETAIL)); + const auto isProductCategory = isMaskSet(rdm::deviceparams::Mask::PRODUCT_CATEGORY); + + if (!isProductCategory) { + m_Params.nProductCategory = RDMDevice::Get()->GetProductCategory(); + } + + builder.AddHex16(RDMDeviceParamsConst::PRODUCT_CATEGORY, m_Params.nProductCategory, isProductCategory); + + const auto isProductDetail = isMaskSet(rdm::deviceparams::Mask::PRODUCT_DETAIL); + + if (!isProductDetail) { + m_Params.nProductDetail = RDMDevice::Get()->GetProductDetail(); + } + + builder.AddHex16(RDMDeviceParamsConst::PRODUCT_DETAIL, m_Params.nProductDetail, isProductDetail); nSize = builder.GetSize(); DEBUG_PRINTF("nSize=%d", nSize); DEBUG_EXIT } + +void RDMDeviceParams::staticCallbackFunction(void *p, const char *s) { + assert(p != nullptr); + assert(s != nullptr); + + (static_cast(p))->callbackFunction(s); +} + +void RDMDeviceParams::Dump() { + printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, RDMDeviceParamsConst::FILE_NAME); + printf(" %s=%.*s\n", RDMDeviceParamsConst::LABEL, m_Params.nDeviceRootLabelLength, m_Params.aDeviceRootLabel); + printf(" %s=%.4x\n", RDMDeviceParamsConst::PRODUCT_CATEGORY, m_Params.nProductCategory); + printf(" %s=%.4x\n", RDMDeviceParamsConst::PRODUCT_DETAIL, m_Params.nProductDetail); +} diff --git a/lib-rdm/src/rdmdeviceresponder.cpp b/lib-rdm/src/rdmdeviceresponder.cpp index 9620eebf..de51f5bc 100644 --- a/lib-rdm/src/rdmdeviceresponder.cpp +++ b/lib-rdm/src/rdmdeviceresponder.cpp @@ -47,9 +47,9 @@ static constexpr char LANGUAGE[2] = { 'e', 'n' }; -RDMDeviceResponder *RDMDeviceResponder::s_pThis = nullptr; +RDMDeviceResponder *RDMDeviceResponder::s_pThis; -RDMDeviceResponder::RDMDeviceResponder(RDMPersonality **pRDMPersonalities, uint32_t nPersonalityCount) : +RDMDeviceResponder::RDMDeviceResponder(RDMPersonality **pRDMPersonalities, const uint32_t nPersonalityCount, const uint32_t nCurrentPersonality) : m_pRDMPersonalities(pRDMPersonalities) { DEBUG_ENTRY @@ -60,15 +60,18 @@ RDMDeviceResponder::RDMDeviceResponder(RDMPersonality **pRDMPersonalities, uint3 m_aLanguage[0] = LANGUAGE[0]; m_aLanguage[1] = LANGUAGE[1]; - memset(&m_tRDMDeviceInfo, 0, sizeof (struct TRDMDeviceInfo)); - memset(&m_tRDMSubDeviceInfo, 0, sizeof (struct TRDMDeviceInfo)); + memset(&m_DeviceInfo, 0, sizeof (struct rdm::device::responder::DeviceInfo)); + memset(&m_SubDeviceInfo, 0, sizeof (struct rdm::device::responder::DeviceInfo)); - m_tRDMDeviceInfo.personality_count = static_cast(nPersonalityCount); + m_DeviceInfo.personality_count = static_cast(nPersonalityCount); + m_DeviceInfo.current_personality = static_cast(nCurrentPersonality); m_pSoftwareVersion = const_cast(RDMSoftwareVersion::GetVersion()); m_nSoftwareVersionLength = static_cast(RDMSoftwareVersion::GetVersionLength()); - const auto *pLightSet = m_pRDMPersonalities[rdm::device::responder::DEFAULT_CURRENT_PERSONALITY - 1]->GetLightSet(); + assert(nCurrentPersonality != 0); + + const auto *pLightSet = m_pRDMPersonalities[nCurrentPersonality - 1]->GetLightSet(); if (pLightSet == nullptr) { m_nDmxStartAddressFactoryDefault = lightset::dmx::ADDRESS_INVALID; @@ -87,37 +90,37 @@ void RDMDeviceResponder::Init() { const auto nProductCategory = RDMDevice::GetProductCategory(); const auto nSubDevices = m_RDMSubDevices.GetCount(); - m_tRDMDeviceInfo.protocol_major = (E120_PROTOCOL_VERSION >> 8); - m_tRDMDeviceInfo.protocol_minor = static_cast(E120_PROTOCOL_VERSION); - m_tRDMDeviceInfo.device_model[0] = static_cast(nDeviceModel >> 8); - m_tRDMDeviceInfo.device_model[1] = static_cast(nDeviceModel); - m_tRDMDeviceInfo.product_category[0] =static_cast( nProductCategory >> 8); - m_tRDMDeviceInfo.product_category[1] = static_cast(nProductCategory); - m_tRDMDeviceInfo.software_version[0] = static_cast(nSoftwareVersionId >> 24); - m_tRDMDeviceInfo.software_version[1] = static_cast(nSoftwareVersionId >> 16); - m_tRDMDeviceInfo.software_version[2] = static_cast(nSoftwareVersionId >> 8); - m_tRDMDeviceInfo.software_version[3] = static_cast(nSoftwareVersionId); + m_DeviceInfo.protocol_major = (E120_PROTOCOL_VERSION >> 8); + m_DeviceInfo.protocol_minor = static_cast(E120_PROTOCOL_VERSION); + m_DeviceInfo.device_model[0] = static_cast(nDeviceModel >> 8); + m_DeviceInfo.device_model[1] = static_cast(nDeviceModel); + m_DeviceInfo.product_category[0] =static_cast( nProductCategory >> 8); + m_DeviceInfo.product_category[1] = static_cast(nProductCategory); + m_DeviceInfo.software_version[0] = static_cast(nSoftwareVersionId >> 24); + m_DeviceInfo.software_version[1] = static_cast(nSoftwareVersionId >> 16); + m_DeviceInfo.software_version[2] = static_cast(nSoftwareVersionId >> 8); + m_DeviceInfo.software_version[3] = static_cast(nSoftwareVersionId); - auto *pLightSet = m_pRDMPersonalities[rdm::device::responder::DEFAULT_CURRENT_PERSONALITY - 1]->GetLightSet(); + assert(m_DeviceInfo.current_personality != 0); + auto *pLightSet = m_pRDMPersonalities[m_DeviceInfo.current_personality - 1]->GetLightSet(); if (pLightSet == nullptr) { - m_tRDMDeviceInfo.dmx_footprint[0] = 0; - m_tRDMDeviceInfo.dmx_footprint[1] = 0; - m_tRDMDeviceInfo.dmx_start_address[0] = static_cast(m_nDmxStartAddressFactoryDefault >> 8); - m_tRDMDeviceInfo.dmx_start_address[1] = static_cast(m_nDmxStartAddressFactoryDefault); + m_DeviceInfo.dmx_footprint[0] = 0; + m_DeviceInfo.dmx_footprint[1] = 0; + m_DeviceInfo.dmx_start_address[0] = static_cast(m_nDmxStartAddressFactoryDefault >> 8); + m_DeviceInfo.dmx_start_address[1] = static_cast(m_nDmxStartAddressFactoryDefault); } else { - m_tRDMDeviceInfo.dmx_footprint[0] = static_cast(pLightSet->GetDmxFootprint() >> 8); - m_tRDMDeviceInfo.dmx_footprint[1] = static_cast(pLightSet->GetDmxFootprint()); - m_tRDMDeviceInfo.dmx_start_address[0] = static_cast(pLightSet->GetDmxStartAddress() >> 8); - m_tRDMDeviceInfo.dmx_start_address[1] = static_cast(pLightSet->GetDmxStartAddress()); + m_DeviceInfo.dmx_footprint[0] = static_cast(pLightSet->GetDmxFootprint() >> 8); + m_DeviceInfo.dmx_footprint[1] = static_cast(pLightSet->GetDmxFootprint()); + m_DeviceInfo.dmx_start_address[0] = static_cast(pLightSet->GetDmxStartAddress() >> 8); + m_DeviceInfo.dmx_start_address[1] = static_cast(pLightSet->GetDmxStartAddress()); } - m_tRDMDeviceInfo.current_personality = rdm::device::responder::DEFAULT_CURRENT_PERSONALITY; - m_tRDMDeviceInfo.sub_device_count[0] = static_cast(nSubDevices >> 8); - m_tRDMDeviceInfo.sub_device_count[1] = static_cast(nSubDevices); - m_tRDMDeviceInfo.sensor_count = m_RDMSensors.GetCount(); + m_DeviceInfo.sub_device_count[0] = static_cast(nSubDevices >> 8); + m_DeviceInfo.sub_device_count[1] = static_cast(nSubDevices); + m_DeviceInfo.sensor_count = m_RDMSensors.GetCount(); - memcpy(&m_tRDMSubDeviceInfo, &m_tRDMDeviceInfo, sizeof(struct TRDMDeviceInfo)); + memcpy(&m_SubDeviceInfo, &m_DeviceInfo, sizeof(struct rdm::device::responder::DeviceInfo)); m_nCheckSum = CalculateChecksum(); @@ -127,21 +130,22 @@ void RDMDeviceResponder::Init() { void RDMDeviceResponder::Print() { RDMDevice::Print(); - const TRDMDeviceInfo *pDeviceInfo = GetDeviceInfo(); - const auto *pPersonality = m_pRDMPersonalities[rdm::device::responder::DEFAULT_CURRENT_PERSONALITY - 1]; + assert(m_DeviceInfo.current_personality != 0); + const auto *pPersonality = m_pRDMPersonalities[m_DeviceInfo.current_personality - 1]; + assert(pPersonality != nullptr); const char *pPersonalityDescription = pPersonality->GetDescription(); - const uint8_t nPersonalityDescriptionLength =pPersonality->GetDescriptionLength(); - - printf("RDM Responder configuration\n"); - printf(" Protocol Version %d.%d\n", pDeviceInfo->protocol_major, pDeviceInfo->protocol_minor); - printf(" DMX Address : %d\n", (pDeviceInfo->dmx_start_address[0] << 8) + pDeviceInfo->dmx_start_address[1]); - printf(" DMX Footprint : %d\n", (pDeviceInfo->dmx_footprint[0] << 8) + pDeviceInfo->dmx_footprint[1]); - printf(" Personality %d of %d [%.*s]\n", pDeviceInfo->current_personality, pDeviceInfo->personality_count, nPersonalityDescriptionLength, pPersonalityDescription); - printf(" Sub Devices : %d\n", (pDeviceInfo->sub_device_count[0] << 8) + pDeviceInfo->sub_device_count[1]); - printf(" Sensors : %d\n", pDeviceInfo->sensor_count); + const auto nPersonalityDescriptionLength = pPersonality->GetDescriptionLength(); + + puts("RDM Responder configuration"); + printf(" Protocol Version %d.%d\n", m_DeviceInfo.protocol_major, m_DeviceInfo.protocol_minor); + printf(" DMX Address : %d\n", (m_DeviceInfo.dmx_start_address[0] << 8) + m_DeviceInfo.dmx_start_address[1]); + printf(" DMX Footprint : %d\n", (m_DeviceInfo.dmx_footprint[0] << 8) + m_DeviceInfo.dmx_footprint[1]); + printf(" Personality %d of %d [%.*s]\n", m_DeviceInfo.current_personality, m_DeviceInfo.personality_count, nPersonalityDescriptionLength, pPersonalityDescription); + printf(" Sub Devices : %d\n", (m_DeviceInfo.sub_device_count[0] << 8) + m_DeviceInfo.sub_device_count[1]); + printf(" Sensors : %d\n", m_DeviceInfo.sensor_count); } -void RDMDeviceResponder::PersonalityUpdate(__attribute__((unused)) LightSet *pLightSet) { +void RDMDeviceResponder::PersonalityUpdate([[maybe_unused]] LightSet *pLightSet) { } void RDMDeviceResponder::DmxStartAddressUpdate() { diff --git a/lib-rdm/src/rdmhandler.cpp b/lib-rdm/src/rdmhandler.cpp index a700911c..8fafa51e 100644 --- a/lib-rdm/src/rdmhandler.cpp +++ b/lib-rdm/src/rdmhandler.cpp @@ -2,7 +2,7 @@ * @file rdmhandler.cpp * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,22 +31,18 @@ #include #include "rdmhandler.h" - #include "rdmdeviceresponder.h" #include "rdmsensors.h" #include "rdmsubdevices.h" - #include "rdmidentify.h" #include "rdmslotinfo.h" -#include "rdmmessage.h" - -#if defined (ENABLE_RDM_MANUFACTURER_PIDS) +#include "rdmconst.h" +#include "rdm_e120.h" +#include "rdm_message_print.h" +#if defined (CONFIG_RDM_ENABLE_MANUFACTURER_PIDS) # include "rdm_manufacturer_pid.h" #endif -#include "rdm.h" -#include "rdm_e120.h" - #include "hardware.h" #include "display.h" @@ -77,7 +73,7 @@ const RDMHandler::PidDefinition RDMHandler::PID_DEFINITIONS[] { {E120_QUEUED_MESSAGE, &RDMHandler::GetQueuedMessage, nullptr, 1, true , false}, #endif {E120_SUPPORTED_PARAMETERS, &RDMHandler::GetSupportedParameters, nullptr, 0, false, true , false}, -#if defined (ENABLE_RDM_MANUFACTURER_PIDS) +#if defined (CONFIG_RDM_ENABLE_MANUFACTURER_PIDS) {E120_PARAMETER_DESCRIPTION, &RDMHandler::GetParameterDescription, nullptr, 2, false, true , false}, #endif {E120_PRODUCT_DETAIL_ID_LIST, &RDMHandler::GetProductDetailIdList, nullptr, 0, true , true , false}, @@ -99,7 +95,7 @@ const RDMHandler::PidDefinition RDMHandler::PID_DEFINITIONS[] { {E120_DISPLAY_LEVEL, &RDMHandler::GetDisplayLevel, &RDMHandler::SetDisplayLevel, 0, true , true , false}, {E120_REAL_TIME_CLOCK, &RDMHandler::GetRealTimeClock, &RDMHandler::SetRealTimeClock, 0, true , true , false}, {E120_POWER_STATE, &RDMHandler::GetPowerState, &RDMHandler::SetPowerState, 0, true , true , false}, -#if defined (ENABLE_RDM_SELF_TEST) +#if defined (CONFIG_RDM_ENABLE_SELF_TEST) {E120_PERFORM_SELFTEST, &RDMHandler::GetPerformSelfTest, &RDMHandler::SetPerformSelfTest, 0, true , true , false}, {E120_SELF_TEST_DESCRIPTION, &RDMHandler::GetSelfTestDescription, nullptr, 1, true , true , false}, #endif @@ -138,23 +134,29 @@ const RDMHandler::PidDefinition RDMHandler::PID_DEFINITIONS_SUB_DEVICES[] { #endif }; -#if defined (ENABLE_RDM_MANUFACTURER_PIDS) -const RDMHandler::PidDefinition RDMHandler::PID_DEFINITION_MANUFACTURER_GENERAL { 0, &RDMHandler::GetManufacturerPid, nullptr, 0, false, true, false }; +#if defined (CONFIG_RDM_ENABLE_MANUFACTURER_PIDS) +# if defined (CONFIG_RDM_MANUFACTURER_PIDS_SET) +const RDMHandler::PidDefinition RDMHandler::PID_DEFINITION_MANUFACTURER_GENERAL { 0, &RDMHandler::GetManufacturerPid, &RDMHandler::SetManufacturerPid, 0, false, true, false }; +# else +const RDMHandler::PidDefinition RDMHandler::PID_DEFINITION_MANUFACTURER_GENERAL { 0, &RDMHandler::GetManufacturerPid, nullptr, 0, false, true, false }; +# endif #endif RDMHandler::RDMHandler(bool bIsRdm): m_bIsRDM(bIsRdm) { DEBUG_ENTRY -#if defined (ENABLE_RDM_MANUFACTURER_PIDS) +#if defined (CONFIG_RDM_ENABLE_MANUFACTURER_PIDS) +# ifndef NDEBUG for (uint32_t i = 0; i < GetParameterDescriptionCount(); i++) { printf("0x%.4x [%.*s]\n", __builtin_bswap16(PARAMETER_DESCRIPTIONS[i].pid), PARAMETER_DESCRIPTIONS[i].pdl-0x14, PARAMETER_DESCRIPTIONS[i].description); } +# endif #endif DEBUG_EXIT } -void RDMHandler::HandleString(const char *pString, uint32_t nLength) { +void RDMHandler::HandleString(const char *pString, const uint32_t nLength) { auto *RdmMessage = reinterpret_cast(m_pRdmDataOut); RdmMessage->param_data_length = static_cast(nLength); @@ -164,9 +166,7 @@ void RDMHandler::HandleString(const char *pString, uint32_t nLength) { } } -void RDMHandler::CreateRespondMessage(uint8_t nResponseType, uint16_t nReason) { - unsigned i; - +void RDMHandler::CreateRespondMessage(const uint8_t nResponseType, const uint16_t nReason) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); @@ -201,12 +201,13 @@ void RDMHandler::CreateRespondMessage(uint8_t nResponseType, uint16_t nReason) { const auto *pUID = RDMDeviceResponder::Get()->GetUID(); - for (i = 0; i < RDM_UID_SIZE; i++) { + for (uint32_t i = 0; i < RDM_UID_SIZE; i++) { pRdmDataOut->destination_uid[i] = pRdmDataIn->source_uid[i]; pRdmDataOut->source_uid[i] = pUID[i]; } uint16_t rdm_checksum = 0; + uint32_t i; for (i = 0; i < pRdmDataOut->message_length; i++) { rdm_checksum = static_cast(rdm_checksum + m_pRdmDataOut[i]); @@ -217,16 +218,10 @@ void RDMHandler::CreateRespondMessage(uint8_t nResponseType, uint16_t nReason) { } void RDMHandler::RespondMessageAck() { - auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); - - if(pRdmDataIn->param_data_length == 0) { - pRdmDataIn->message_length = RDM_MESSAGE_MINIMUM_SIZE; - } - - CreateRespondMessage(E120_RESPONSE_TYPE_ACK); + CreateRespondMessage(E120_RESPONSE_TYPE_ACK, 0); } -void RDMHandler::RespondMessageNack(uint16_t nReason) { +void RDMHandler::RespondMessageNack(const uint16_t nReason) { CreateRespondMessage(E120_RESPONSE_TYPE_NACK_REASON, nReason); } @@ -253,7 +248,7 @@ void RDMHandler::HandleData(const uint8_t *pRdmDataIn, uint8_t *pRdmDataOut) { } #ifndef NDEBUG - RDMMessage::PrintNoSc(pRdmDataIn); + rdm::message_print_no_sc(pRdmDataIn); #endif const auto *pUID = RDMDeviceResponder::Get()->GetUID(); @@ -274,7 +269,7 @@ void RDMHandler::HandleData(const uint8_t *pRdmDataIn, uint8_t *pRdmDataOut) { } } - DEBUG_PRINTF("bIsRdmPacketForMe=%d", bIsRdmPacketForMe); + DEBUG_PRINTF("ForMe=%d, Broadcast=%d, Muted=%d", bIsRdmPacketForMe, bIsRdmPacketBroadcast, m_IsMuted); const auto nCommandClass = pRdmRequest->command_class; const auto nParamId = static_cast((pRdmRequest->param_id[0] << 8) + pRdmRequest->param_id[1]); @@ -308,6 +303,7 @@ void RDMHandler::HandleData(const uint8_t *pRdmDataIn, uint8_t *pRdmDataOut) { p->checksum[2] = static_cast((rdm_checksum & 0xFF) | 0xAA); p->checksum[3] = static_cast((rdm_checksum & 0xFF) | 0x55); + DEBUG_EXIT return; } } @@ -375,11 +371,11 @@ void RDMHandler::HandleData(const uint8_t *pRdmDataIn, uint8_t *pRdmDataOut) { } void RDMHandler::Handlers(bool bIsBroadcast, uint8_t nCommandClass, uint16_t nParamId, uint8_t nParamDataLength, uint16_t nSubDevice) { - DEBUG1_ENTRY + DEBUG_ENTRY if (nCommandClass != E120_GET_COMMAND && nCommandClass != E120_SET_COMMAND) { RespondMessageNack(E120_NR_UNSUPPORTED_COMMAND_CLASS); - DEBUG1_EXIT + DEBUG_EXIT return; } @@ -387,7 +383,7 @@ void RDMHandler::Handlers(bool bIsBroadcast, uint8_t nCommandClass, uint16_t nPa if ((nSubDevice > sub_device_count) && (nSubDevice != E120_SUB_DEVICE_ALL_CALL)) { RespondMessageNack(E120_NR_SUB_DEVICE_OUT_OF_RANGE); - DEBUG1_EXIT + DEBUG_EXIT return; } @@ -404,7 +400,7 @@ void RDMHandler::Handlers(bool bIsBroadcast, uint8_t nCommandClass, uint16_t nPa } } -#if defined (ENABLE_RDM_MANUFACTURER_PIDS) +#if defined (CONFIG_RDM_ENABLE_MANUFACTURER_PIDS) if (!pid_handler) { for (uint32_t i = 0; i < GetParameterDescriptionCount(); i++) { if (PARAMETER_DESCRIPTIONS[i].pid == __builtin_bswap16(nParamId)) { @@ -419,45 +415,45 @@ void RDMHandler::Handlers(bool bIsBroadcast, uint8_t nCommandClass, uint16_t nPa if (!pid_handler) { RespondMessageNack(E120_NR_UNKNOWN_PID); - DEBUG1_EXIT + DEBUG_EXIT return; } if (m_bIsRDM) { if (!bRDM) { RespondMessageNack(E120_NR_UNKNOWN_PID); - DEBUG1_EXIT + DEBUG_EXIT return; } } else { if (!bRDMNet) { RespondMessageNack(E120_NR_UNKNOWN_PID); - DEBUG1_EXIT + DEBUG_EXIT return; } } if (nCommandClass == E120_GET_COMMAND) { if (bIsBroadcast) { - DEBUG1_EXIT + DEBUG_EXIT return; } if (nSubDevice == E120_SUB_DEVICE_ALL_CALL) { RespondMessageNack(E120_NR_SUB_DEVICE_OUT_OF_RANGE); - DEBUG1_EXIT + DEBUG_EXIT return; } if (!pid_handler->pGetHandler) { RespondMessageNack(E120_NR_UNSUPPORTED_COMMAND_CLASS); - DEBUG1_EXIT + DEBUG_EXIT return; } if (nParamDataLength != pid_handler->nGetArgumentSize) { RespondMessageNack(E120_NR_FORMAT_ERROR); - DEBUG1_EXIT + DEBUG_EXIT return; } @@ -466,18 +462,18 @@ void RDMHandler::Handlers(bool bIsBroadcast, uint8_t nCommandClass, uint16_t nPa if (!pid_handler->pSetHandler) { RespondMessageNack(E120_NR_UNSUPPORTED_COMMAND_CLASS); - DEBUG1_EXIT + DEBUG_EXIT return; } (this->*(pid_handler->pSetHandler))(bIsBroadcast, nSubDevice); } - DEBUG1_EXIT + DEBUG_EXIT } #if defined (ENABLE_RDM_QUEUED_MSG) -void RDMHandler::GetQueuedMessage(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetQueuedMessage([[maybe_unused]] uint16_t nSubDevice) { m_RDMQueuedMessage.Handler(m_pRdmDataOut); RespondMessageAck(); } @@ -490,10 +486,10 @@ void RDMHandler::GetSupportedParameters(uint16_t nSubDevice) { uint32_t nTableSize = 0; if (nSubDevice != 0) { - pPidDefinitions = const_cast(&PID_DEFINITIONS_SUB_DEVICES[0]); + pPidDefinitions = const_cast(&PID_DEFINITIONS_SUB_DEVICES[0]); nTableSize = sizeof(PID_DEFINITIONS_SUB_DEVICES) / sizeof(PID_DEFINITIONS_SUB_DEVICES[0]); } else { - pPidDefinitions = const_cast(&PID_DEFINITIONS[0]); + pPidDefinitions = const_cast(&PID_DEFINITIONS[0]); nTableSize = sizeof(PID_DEFINITIONS) / sizeof(PID_DEFINITIONS[0]); } @@ -509,13 +505,13 @@ void RDMHandler::GetSupportedParameters(uint16_t nSubDevice) { } } -#if defined (ENABLE_RDM_MANUFACTURER_PIDS) +#if defined (CONFIG_RDM_ENABLE_MANUFACTURER_PIDS) const auto nSupportedParamsManufacturer = GetParameterDescriptionCount(); nSupportedParams = static_cast(nSupportedParams + nSupportedParamsManufacturer); for (uint32_t i = 0; i < nSupportedParamsManufacturer; i++) { - pRdmDataOut->param_data[j + j] = static_cast(PARAMETER_DESCRIPTIONS[i].pid); + pRdmDataOut->param_data[j + j] = static_cast(PARAMETER_DESCRIPTIONS[i].pid); ///< The PIDs are swapped pRdmDataOut->param_data[j + j + 1] = static_cast(PARAMETER_DESCRIPTIONS[i].pid >> 8); j++; } @@ -526,12 +522,12 @@ void RDMHandler::GetSupportedParameters(uint16_t nSubDevice) { RespondMessageAck(); } -#if defined (ENABLE_RDM_MANUFACTURER_PIDS) -void RDMHandler::GetParameterDescription(__attribute__((unused)) uint16_t nSubDevice) { +# if defined (CONFIG_RDM_ENABLE_MANUFACTURER_PIDS) +void RDMHandler::GetParameterDescription([[maybe_unused]] uint16_t nSubDevice) { const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); - const auto nPid = static_cast((pRdmDataIn->param_data[0] << 8) + pRdmDataIn->param_data[1]); + const auto nPid = static_cast(pRdmDataIn->param_data[0] + (pRdmDataIn->param_data[1] << 8)); - if (!(nPid >= 0x8000 && nPid <= 0xFFDF)) { + if (!(nPid >= __builtin_bswap16(0x8000) && nPid <= __builtin_bswap16(0xFFDF))) { RespondMessageNack(E120_NR_DATA_OUT_OF_RANGE); return; } @@ -539,7 +535,7 @@ void RDMHandler::GetParameterDescription(__attribute__((unused)) uint16_t nSubDe const auto nSupportedParamsManufacturer = GetParameterDescriptionCount(); for (uint32_t i = 0; i < nSupportedParamsManufacturer; i++) { - if (PARAMETER_DESCRIPTIONS[i].pid == __builtin_bswap16(nPid)) { + if (PARAMETER_DESCRIPTIONS[i].pid == nPid) { auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); pRdmDataOut->param_data_length = PARAMETER_DESCRIPTIONS[i].pdl; @@ -554,7 +550,7 @@ void RDMHandler::GetParameterDescription(__attribute__((unused)) uint16_t nSubDe } -void RDMHandler::GetManufacturerPid(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetManufacturerPid([[maybe_unused]] uint16_t nSubDevice) { const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); @@ -571,22 +567,45 @@ void RDMHandler::GetManufacturerPid(__attribute__((unused)) uint16_t nSubDevice RespondMessageNack(nReason); } -#endif +# if defined (CONFIG_RDM_MANUFACTURER_PIDS_SET) +void RDMHandler::SetManufacturerPid(bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); + + const auto nPid = static_cast(pRdmDataIn->param_id[0] + (pRdmDataIn->param_id[1] << 8)); + const rdm::ManufacturerParamData pIn = { pRdmDataIn->param_data_length, const_cast(pRdmDataIn->param_data) }; + rdm::ManufacturerParamData pOut = { 0, pRdmDataOut->param_data }; + uint16_t nReason = E120_NR_UNKNOWN_PID; + + for (uint32_t nIndex = 0; nIndex < GetParameterDescriptionCount(); nIndex++) { + if (PARAMETER_DESCRIPTIONS[nIndex].pid == nPid) { + if (rdm::handle_manufactureer_pid_set(IsBroadcast, nPid, PARAMETER_DESCRIPTIONS[nIndex], &pIn, &pOut, nReason)) { + pRdmDataOut->param_data_length = pOut.nPdl; + RespondMessageAck(); + return; + } + } + } + + RespondMessageNack(nReason); +} +# endif // CONFIG_RDM_MANUFACTURER_PIDS_SET +# endif // CONFIG_RDM_ENABLE_MANUFACTURER_PIDS #endif void RDMHandler::GetDeviceInfo(uint16_t nSubDevice) { const auto *pRdmDeviceInfoRequested = RDMDeviceResponder::Get()->GetDeviceInfo(nSubDevice); auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); - auto *pDeviceInfoOut = reinterpret_cast(pRdmDataOut->param_data); + auto *pDeviceInfoOut = reinterpret_cast(pRdmDataOut->param_data); - pRdmDataOut->param_data_length = sizeof(struct TRDMDeviceInfo); - memcpy(pDeviceInfoOut, pRdmDeviceInfoRequested, sizeof(struct TRDMDeviceInfo)); + pRdmDataOut->param_data_length = sizeof(struct rdm::device::responder::DeviceInfo); + memcpy(pDeviceInfoOut, pRdmDeviceInfoRequested, sizeof(struct rdm::device::responder::DeviceInfo)); RespondMessageAck(); } -void RDMHandler::GetFactoryDefaults(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetFactoryDefaults([[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); pRdmDataOut->param_data_length = 1; @@ -595,7 +614,7 @@ void RDMHandler::GetFactoryDefaults(__attribute__((unused)) uint16_t nSubDevice) RespondMessageAck(); } -void RDMHandler::SetFactoryDefaults(bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetFactoryDefaults(bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 0) { @@ -616,7 +635,7 @@ void RDMHandler::SetFactoryDefaults(bool IsBroadcast, __attribute__((unused)) ui } #if !defined (NODE_RDMNET_LLRP_ONLY) -void RDMHandler::GetProductDetailIdList(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetProductDetailIdList([[maybe_unused]] uint16_t nSubDevice) { const auto nProductDetail = RDMDeviceResponder::Get()->GetProductDetail(); auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); @@ -629,7 +648,7 @@ void RDMHandler::GetProductDetailIdList(__attribute__((unused)) uint16_t nSubDev } #endif -void RDMHandler::GetDeviceModelDescription(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetDeviceModelDescription([[maybe_unused]] uint16_t nSubDevice) { uint8_t nBoardNameLength; const char *pBoardModel = Hardware::Get()->GetBoardName(nBoardNameLength); @@ -637,7 +656,7 @@ void RDMHandler::GetDeviceModelDescription(__attribute__((unused)) uint16_t nSub RespondMessageAck(); } -void RDMHandler::GetManufacturerLabel(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetManufacturerLabel([[maybe_unused]] uint16_t nSubDevice) { TRDMDeviceInfoData label; RDMDeviceResponder::Get()->GetManufacturerName(&label); @@ -674,7 +693,7 @@ void RDMHandler::SetDeviceLabel(bool IsBroadcast, uint16_t nSubDevice) { RespondMessageAck(); } -void RDMHandler::GetSoftwareVersionLabel(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetSoftwareVersionLabel([[maybe_unused]] uint16_t nSubDevice) { const auto *pSoftwareVersion = RDMDeviceResponder::Get()->GetSoftwareVersion(); const auto nSoftwareVersionLength = RDMDeviceResponder::Get()->GetSoftwareVersionLength(); @@ -682,7 +701,7 @@ void RDMHandler::GetSoftwareVersionLabel(__attribute__((unused)) uint16_t nSubDe RespondMessageAck(); } -void RDMHandler::SetResetDevice(__attribute__((unused)) bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetResetDevice([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 1) { @@ -710,7 +729,7 @@ void RDMHandler::SetResetDevice(__attribute__((unused)) bool IsBroadcast, __attr } } -void RDMHandler::GetIdentifyDevice(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetIdentifyDevice([[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); pRdmDataOut->param_data_length = 1; @@ -721,7 +740,7 @@ void RDMHandler::GetIdentifyDevice(__attribute__((unused)) uint16_t nSubDevice) RespondMessageAck(); } -void RDMHandler::SetIdentifyDevice(bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetIdentifyDevice(bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 1) { @@ -750,14 +769,14 @@ void RDMHandler::SetIdentifyDevice(bool IsBroadcast, __attribute__((unused)) uin } #if !defined (NODE_RDMNET_LLRP_ONLY) -void RDMHandler::GetLanguage(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetLanguage([[maybe_unused]] uint16_t nSubDevice) { const auto *pLanguage = RDMDeviceResponder::Get()->GetLanguage(); HandleString(pLanguage, RDM_DEVICE_SUPPORTED_LANGUAGE_LENGTH); RespondMessageAck(); } -void RDMHandler::SetLanguage(bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetLanguage(bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != RDM_DEVICE_SUPPORTED_LANGUAGE_LENGTH) { @@ -782,7 +801,7 @@ void RDMHandler::SetLanguage(bool IsBroadcast, __attribute__((unused)) uint16_t RespondMessageAck(); } -void RDMHandler::GetBootSoftwareVersionId(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetBootSoftwareVersionId([[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 0) { @@ -803,7 +822,7 @@ void RDMHandler::GetBootSoftwareVersionId(__attribute__((unused)) uint16_t nSubD RespondMessageAck(); } -void RDMHandler::GetBootSoftwareVersionLabel(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetBootSoftwareVersionLabel([[maybe_unused]] uint16_t nSubDevice) { uint8_t nSysNameLength; const auto *pSysName = Hardware::Get()->GetSysName(nSysNameLength); @@ -824,7 +843,7 @@ void RDMHandler::GetPersonality(uint16_t nSubDevice) { RespondMessageAck(); } -void RDMHandler::SetPersonality(__attribute__((unused)) bool IsBroadcast, uint16_t nSubDevice) { +void RDMHandler::SetPersonality([[maybe_unused]] bool IsBroadcast, uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 1) { @@ -915,7 +934,7 @@ void RDMHandler::SetDmxStartAddress(bool IsBroadcast, uint16_t nSubDevice) { RespondMessageAck(); } -void RDMHandler::GetSensorDefinition(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetSensorDefinition([[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); const auto nSensorRequested = pRdmDataIn->param_data[0]; @@ -958,7 +977,7 @@ void RDMHandler::GetSensorDefinition(__attribute__((unused)) uint16_t nSubDevice RespondMessageAck(); } -void RDMHandler::GetSensorValue(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetSensorValue([[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 1) { @@ -996,7 +1015,7 @@ void RDMHandler::GetSensorValue(__attribute__((unused)) uint16_t nSubDevice) { RespondMessageAck(); } -void RDMHandler::SetSensorValue(bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetSensorValue(bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 1) { @@ -1053,7 +1072,7 @@ void RDMHandler::SetSensorValue(bool IsBroadcast, __attribute__((unused)) uint16 RespondMessageAck(); } -void RDMHandler::SetRecordSensors(bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetRecordSensors(bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 1) { @@ -1085,7 +1104,7 @@ void RDMHandler::SetRecordSensors(bool IsBroadcast, __attribute__((unused)) uint RespondMessageAck(); } -void RDMHandler::GetDeviceHours(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetDeviceHours([[maybe_unused]] uint16_t nSubDevice) { uint64_t device_hours = Hardware::Get()->GetUpTime() / 3600; // The value for the Device Hours field shall be unsigned and not roll over when maximum value is reached. if (device_hours > UINT32_MAX) { @@ -1103,11 +1122,11 @@ void RDMHandler::GetDeviceHours(__attribute__((unused)) uint16_t nSubDevice) { RespondMessageAck(); } -void RDMHandler::SetDeviceHours(__attribute__((unused)) bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetDeviceHours([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { RespondMessageNack(E120_NR_WRITE_PROTECT); } -void RDMHandler::GetDisplayInvert(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetDisplayInvert([[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); pRdmDataOut->param_data_length = 1; @@ -1118,7 +1137,7 @@ void RDMHandler::GetDisplayInvert(__attribute__((unused)) uint16_t nSubDevice) { RespondMessageAck(); } -void RDMHandler::SetDisplayInvert(__attribute__((unused)) bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetDisplayInvert([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 1) { @@ -1141,7 +1160,7 @@ void RDMHandler::SetDisplayInvert(__attribute__((unused)) bool IsBroadcast, __at RespondMessageAck(); } -void RDMHandler::GetDisplayLevel(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetDisplayLevel([[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); pRdmDataOut->param_data_length = 1; @@ -1153,7 +1172,7 @@ void RDMHandler::GetDisplayLevel(__attribute__((unused)) uint16_t nSubDevice) { RespondMessageAck(); } -void RDMHandler::SetDisplayLevel(__attribute__((unused)) bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetDisplayLevel([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 1) { @@ -1179,28 +1198,27 @@ void RDMHandler::SetDisplayLevel(__attribute__((unused)) bool IsBroadcast, __att RespondMessageAck(); } -void RDMHandler::GetRealTimeClock(__attribute__((unused)) uint16_t nSubDevice) { - struct tm local_time; - Hardware::Get()->GetTime(&local_time); - - const auto year = static_cast(local_time.tm_year + 1900); +void RDMHandler::GetRealTimeClock([[maybe_unused]] uint16_t nSubDevice) { + const auto ltime = time(nullptr); + const auto *tm = localtime(<ime); + const auto year = static_cast(tm->tm_year + 1900); auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); pRdmDataOut->param_data[0] = static_cast(year >> 8); pRdmDataOut->param_data[1] = static_cast(year); - pRdmDataOut->param_data[2] = static_cast(local_time.tm_mon + 1); // 0..11 - pRdmDataOut->param_data[3] = static_cast(local_time.tm_mday); - pRdmDataOut->param_data[4] = static_cast(local_time.tm_hour); - pRdmDataOut->param_data[5] = static_cast(local_time.tm_min); - pRdmDataOut->param_data[6] = static_cast(local_time.tm_sec); + pRdmDataOut->param_data[2] = static_cast(tm->tm_mon + 1); // 0..11 + pRdmDataOut->param_data[3] = static_cast(tm->tm_mday); + pRdmDataOut->param_data[4] = static_cast(tm->tm_hour); + pRdmDataOut->param_data[5] = static_cast(tm->tm_min); + pRdmDataOut->param_data[6] = static_cast(tm->tm_sec); pRdmDataOut->param_data_length = 7; RespondMessageAck(); } -void RDMHandler::SetRealTimeClock(bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetRealTimeClock(bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 7) { @@ -1231,7 +1249,7 @@ void RDMHandler::SetRealTimeClock(bool IsBroadcast, __attribute__((unused)) uint RespondMessageAck(); } -void RDMHandler::GetPowerState(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetPowerState([[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); pRdmDataOut->param_data_length = 1; @@ -1240,7 +1258,7 @@ void RDMHandler::GetPowerState(__attribute__((unused)) uint16_t nSubDevice) { RespondMessageAck(); } -void RDMHandler::SetPowerState(__attribute__((unused)) bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetPowerState([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 1) { @@ -1276,10 +1294,10 @@ void RDMHandler::SetPowerState(__attribute__((unused)) bool IsBroadcast, __attri RespondMessageNack(E120_NR_WRITE_PROTECT); } -#if defined (ENABLE_RDM_SELF_TEST) +#if defined (CONFIG_RDM_ENABLE_SELF_TEST) #include "rdm_selftest.h" -void RDMHandler::GetPerformSelfTest(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetPerformSelfTest([[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); pRdmDataOut->param_data_length = 1; @@ -1288,7 +1306,7 @@ void RDMHandler::GetPerformSelfTest(__attribute__((unused)) uint16_t nSubDevice) RespondMessageAck(); } -void RDMHandler::SetPerformSelfTest(__attribute__((unused)) bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetPerformSelfTest([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 1) { @@ -1307,7 +1325,7 @@ void RDMHandler::SetPerformSelfTest(__attribute__((unused)) bool IsBroadcast, __ RespondMessageAck(); } -void RDMHandler::GetSelfTestDescription(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetSelfTestDescription([[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); uint32_t nLength; const auto *pText = rdm::selftest::GetDescription(pRdmDataIn->param_data[0], nLength); @@ -1333,12 +1351,12 @@ void RDMHandler::GetSelfTestDescription(__attribute__((unused)) uint16_t nSubDev RespondMessageAck(); } -#endif +#endif // CONFIG_RDM_ENABLE_SELF_TEST #if defined (ENABLE_RDM_PRESET_PLAYBACK) #include "rdm_preset_playback.h" -void RDMHandler::GetPresetPlayback(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetPresetPlayback([[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); uint16_t nMode; @@ -1354,7 +1372,7 @@ void RDMHandler::GetPresetPlayback(__attribute__((unused)) uint16_t nSubDevice) RespondMessageAck(); } -void RDMHandler::SetPresetPlayback(__attribute__((unused)) bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetPresetPlayback([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 3) { @@ -1375,7 +1393,7 @@ void RDMHandler::SetPresetPlayback(__attribute__((unused)) bool IsBroadcast, __a RespondMessageAck(); } -#endif +#endif // ENABLE_RDM_PRESET_PLAYBACK void RDMHandler::GetSlotInfo(uint16_t nSubDevice) { auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); diff --git a/lib-rdm/src/rdmhandlere1371.cpp b/lib-rdm/src/rdmhandlere1371.cpp index 898f9224..892e1843 100644 --- a/lib-rdm/src/rdmhandlere1371.cpp +++ b/lib-rdm/src/rdmhandlere1371.cpp @@ -26,7 +26,7 @@ #include #include "rdmhandler.h" - +#include "rdmconst.h" #include "rdmidentify.h" #include "rdm_e120.h" @@ -36,7 +36,7 @@ * ANSI E1.37-1 */ -void RDMHandler::GetIdentifyMode(__attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::GetIdentifyMode([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); @@ -49,7 +49,7 @@ void RDMHandler::GetIdentifyMode(__attribute__((unused)) uint16_t nSubDevice) { DEBUG_EXIT } -void RDMHandler::SetIdentifyMode(bool IsBroadcast, __attribute__((unused)) uint16_t nSubDevice) { +void RDMHandler::SetIdentifyMode(bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); diff --git a/lib-rdm/src/rdmidentify.cpp b/lib-rdm/src/rdmidentify.cpp index 70865455..aad55eb2 100644 --- a/lib-rdm/src/rdmidentify.cpp +++ b/lib-rdm/src/rdmidentify.cpp @@ -38,8 +38,8 @@ RDMIdentify::RDMIdentify() { s_pThis = this; } -void __attribute__((weak)) RDMIdentify::On(__attribute__((unused)) rdm::identify::Mode nMode) { +void __attribute__((weak)) RDMIdentify::On([[maybe_unused]] rdm::identify::Mode nMode) { } -void __attribute__((weak)) RDMIdentify::Off(__attribute__((unused)) rdm::identify::Mode nMode) { +void __attribute__((weak)) RDMIdentify::Off([[maybe_unused]] rdm::identify::Mode nMode) { } diff --git a/lib-rdmnet/src/rdmnetconst.cpp b/lib-rdm/src/rdmnet/rdmnetconst.cpp old mode 100644 new mode 100755 similarity index 100% rename from lib-rdmnet/src/rdmnetconst.cpp rename to lib-rdm/src/rdmnet/rdmnetconst.cpp diff --git a/lib-rdm/src/rdmqueuedmessage.cpp b/lib-rdm/src/rdmqueuedmessage.cpp index 43a60d4b..cd59cf63 100644 --- a/lib-rdm/src/rdmqueuedmessage.cpp +++ b/lib-rdm/src/rdmqueuedmessage.cpp @@ -2,7 +2,7 @@ * @file rdmqueuedmessage.cpp * */ -/* Copyright (C) 2017-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,13 +27,9 @@ #include #include "rdmqueuedmessage.h" - -#include "rdmmessage.h" - -#include "rdm.h" +#include "rdmconst.h" #include "rdm_e120.h" - RDMQueuedMessage::RDMQueuedMessage() { m_pQueue = new TRdmQueuedMessage[RDM_MESSAGE_COUNT_MAX]; assert(m_pQueue != nullptr); diff --git a/lib-network/src/net/tftp_internal.h b/lib-rdm/src/rdmsensors.cpp similarity index 83% rename from lib-network/src/net/tftp_internal.h rename to lib-rdm/src/rdmsensors.cpp index 13c9f056..24802710 100644 --- a/lib-network/src/net/tftp_internal.h +++ b/lib-rdm/src/rdmsensors.cpp @@ -1,8 +1,8 @@ /** - * @file tftp_internal.h + * @file rdmsensors.cpp * */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,11 +23,7 @@ * THE SOFTWARE. */ -#ifndef TFTP_INTERNAL_H_ -#define TFTP_INTERNAL_H_ +#include "rdmsensors.h" -enum { - TFTP_PORT_SERVER = 69 -}; +RDMSensors *RDMSensors::s_pThis = nullptr; -#endif /* TFTP_INTERNAL_H_ */ diff --git a/lib-rdm/src/rdmslotinfo.cpp b/lib-rdm/src/rdmslotinfo.cpp index 6fe9eeaf..8d94a601 100644 --- a/lib-rdm/src/rdmslotinfo.cpp +++ b/lib-rdm/src/rdmslotinfo.cpp @@ -139,7 +139,7 @@ const char *RDMSlotInfo::GetCategoryText(uint16_t nSlotOffset, uint16_t nId, uin return s_tTableC2[nIndex].pDescription; } -const char *RDMSlotInfo::GetCategoryTextUndefined(__attribute__((unused)) uint16_t nSlotOffset, uint32_t& nLength) { +const char *RDMSlotInfo::GetCategoryTextUndefined([[maybe_unused]] uint16_t nSlotOffset, uint32_t& nLength) { const auto nIndex = TABLE_C2_SIZE - 1; nLength = static_cast(strlen(s_tTableC2[nIndex].pDescription)); return s_tTableC2[nIndex].pDescription; diff --git a/lib-rdmsubdevice/src/spi/rdmsubdevicedummy.cpp b/lib-rdm/src/rdmsubdevicedummy.cpp similarity index 81% rename from lib-rdmsubdevice/src/spi/rdmsubdevicedummy.cpp rename to lib-rdm/src/rdmsubdevicedummy.cpp index 7ae825aa..24fa07ab 100644 --- a/lib-rdmsubdevice/src/spi/rdmsubdevicedummy.cpp +++ b/lib-rdm/src/rdmsubdevicedummy.cpp @@ -2,7 +2,7 @@ * @file rdmsubdevicedummy.cpp * */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,13 +27,13 @@ #include #include -#include "rdmsubdevicedummy.h" +#include "subdevice/rdmsubdevicedummy.h" #include "rdmpersonality.h" static constexpr uint32_t DMX_FOOTPRINT = 4; static RDMPersonality *s_RDMPersonalities[] = {new RDMPersonality("Dummy-H", DMX_FOOTPRINT), new RDMPersonality("Dummy-D", DMX_FOOTPRINT)}; -RDMSubDeviceDummy::RDMSubDeviceDummy(__attribute__((unused)) uint16_t nDmxStartAddress, __attribute__((unused)) char nChipSselect, __attribute__((unused)) uint8_t nSlaveAddress, __attribute__((unused)) uint32_t nSpiSpeed) : +RDMSubDeviceDummy::RDMSubDeviceDummy([[maybe_unused]] uint16_t nDmxStartAddress, [[maybe_unused]] char nChipSselect, [[maybe_unused]] uint8_t nSlaveAddress, [[maybe_unused]] uint32_t nSpiSpeed) : RDMSubDevice("SubDevice Dummy", nDmxStartAddress) { SetDmxFootprint(DMX_FOOTPRINT); @@ -58,8 +58,8 @@ void RDMSubDeviceDummy::Data(const uint8_t* pData, uint32_t nLength) { const auto nDmxStartAddress = GetDmxStartAddress(); - printf("RDMSubDeviceDummy::Data(*pData:%p, nLength:%d)\n", static_cast(pData), nLength); - printf("%d:%d:%d: ", nLength, DMX_FOOTPRINT, nDmxStartAddress); + printf("RDMSubDeviceDummy::Data(*pData:%p, nLength:%u)\n", static_cast(pData), static_cast(nLength)); + printf("%u:%u:%u: ", static_cast(nLength), static_cast(DMX_FOOTPRINT), static_cast(nDmxStartAddress)); for (uint32_t i = static_cast(nDmxStartAddress - 1), j = 0; (i < nLength) && (j < DMX_FOOTPRINT); i++, j++) { switch (GetPersonalityCurrent()) { @@ -74,7 +74,7 @@ void RDMSubDeviceDummy::Data(const uint8_t* pData, uint32_t nLength) { } } - printf("\n"); + puts(""); } void RDMSubDeviceDummy::UpdateEvent(TRDMSubDeviceUpdateEvent tUpdateEvent) { diff --git a/lib-rdm/src/rdmsubdevices.cpp b/lib-rdm/src/rdmsubdevices.cpp new file mode 100644 index 00000000..11887158 --- /dev/null +++ b/lib-rdm/src/rdmsubdevices.cpp @@ -0,0 +1,39 @@ +/** + * @file rdmsubdevices.cpp + * + */ +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "rdmsubdevices.h" + +RDMSubDevices *RDMSubDevices::s_pThis; + + + + + + + + + + + diff --git a/lib-rdm/src/responder/rdmresponder.cpp b/lib-rdm/src/responder/rdmresponder.cpp new file mode 100644 index 00000000..543266d4 --- /dev/null +++ b/lib-rdm/src/responder/rdmresponder.cpp @@ -0,0 +1,38 @@ +/** + * @file rdmresponder.cpp + * + */ +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "rdmresponder.h" + +RDMResponder *RDMResponder::s_pThis; +TRdmMessage RDMResponder::s_RdmCommand; +bool RDMResponder::m_IsSubDeviceActive; + +void __attribute__((weak)) RDMResponder::PersonalityUpdate([[maybe_unused]] uint32_t nPersonality) { +} + +void __attribute__((weak))DmxStartAddressUpdate([[maybe_unused]] uint16_t nDmxStartAddress) { +} diff --git a/lib-rdmdiscovery/.cproject b/lib-rdmdiscovery/.cproject deleted file mode 100644 index 46869eb5..00000000 --- a/lib-rdmdiscovery/.cproject +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-rdmdiscovery/.project b/lib-rdmdiscovery/.project deleted file mode 100644 index 86ac5f25..00000000 --- a/lib-rdmdiscovery/.project +++ /dev/null @@ -1,27 +0,0 @@ - - - lib-rdmdiscovery - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/lib-rdmdiscovery/.settings/org.eclipse.cdt.core.prefs b/lib-rdmdiscovery/.settings/org.eclipse.cdt.core.prefs deleted file mode 100644 index c8ec5df2..00000000 --- a/lib-rdmdiscovery/.settings/org.eclipse.cdt.core.prefs +++ /dev/null @@ -1,6 +0,0 @@ -doxygen/doxygen_new_line_after_brief=true -doxygen/doxygen_use_brief_tag=false -doxygen/doxygen_use_javadoc_tags=true -doxygen/doxygen_use_pre_tag=false -doxygen/doxygen_use_structural_commands=false -eclipse.preferences.version=1 diff --git a/lib-rdmdiscovery/.settings/org.eclipse.core.resources.prefs b/lib-rdmdiscovery/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 99f26c02..00000000 --- a/lib-rdmdiscovery/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -encoding/=UTF-8 diff --git a/lib-rdmdiscovery/Makefile b/lib-rdmdiscovery/Makefile deleted file mode 100644 index cd3e668b..00000000 --- a/lib-rdmdiscovery/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -DEFINES=#NDEBUG -EXTRA_INCLUDES=../lib-dmx/include ../lib-rdm/include ../lib-artnet/include ../lib-lightset/include ../lib-hal/include - -include ../firmware-template-gd32/lib/Rules.mk diff --git a/lib-rdmdiscovery/Makefile.GD32 b/lib-rdmdiscovery/Makefile.GD32 deleted file mode 100644 index d414e5f3..00000000 --- a/lib-rdmdiscovery/Makefile.GD32 +++ /dev/null @@ -1,6 +0,0 @@ -DEFINES=#NDEBUG - -EXTRA_INCLUDES=../lib-dmx/include ../lib-rdm/include ../lib-artnet/include ../lib-lightset/include ../lib-hal/include - -include Rules.mk -include ../firmware-template-gd32/lib/Rules.mk diff --git a/lib-rdmdiscovery/Rules.mk b/lib-rdmdiscovery/Rules.mk deleted file mode 100644 index b856ee07..00000000 --- a/lib-rdmdiscovery/Rules.mk +++ /dev/null @@ -1,27 +0,0 @@ -EXTRA_INCLUDES+=../lib-rdm/include ../lib-lightset/include ../lib-hal/include ../lib-network/include - -ifneq ($(MAKE_FLAGS),) - ifeq ($(findstring NODE_ARTNET,$(MAKE_FLAGS)), NODE_ARTNET) - EXTRA_INCLUDES+=../lib-artnet/include - EXTRA_SRCDIR+=src/artnet - ifeq ($(findstring ARTNET_VERSION=4,$(MAKE_FLAGS)), ARTNET_VERSION=4) - EXTRA_INCLUDES+=../lib-e131/include - endif - endif - ifeq ($(findstring NODE_NODE,$(MAKE_FLAGS)), NODE_NODE) - EXTRA_INCLUDES+=../lib-artnet/include - EXTRA_SRCDIR+=src/artnet - ifeq ($(findstring ARTNET_VERSION=4,$(MAKE_FLAGS)), ARTNET_VERSION=4) - EXTRA_INCLUDES+=../lib-e131/include - endif - endif - ifeq ($(findstring RDM_CONTROLLER,$(MAKE_FLAGS)), RDM_CONTROLLER) - EXTRA_INCLUDES+= - EXTRA_SRCDIR+=src/rdm - endif -else - EXTRA_INCLUDES+=../lib-artnet/include - EXTRA_SRCDIR+=src/rdm src/artnet - DEFINES+=RDM_CONTROLLER - DEFINES+=LIGHTSET_PORTS=4 -endif \ No newline at end of file diff --git a/lib-rdmdiscovery/include/artnetrdmcontroller.h b/lib-rdmdiscovery/include/artnetrdmcontroller.h deleted file mode 100755 index eb706cf3..00000000 --- a/lib-rdmdiscovery/include/artnetrdmcontroller.h +++ /dev/null @@ -1,112 +0,0 @@ -/** - * @file artnetrdmcontroller.h - * - */ -/* Copyright (C) 2017-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef ARTNETRDMCONTROLLER_H_ -#define ARTNETRDMCONTROLLER_H_ - -#include -#include -#include - -#include "artnetrdm.h" - -#include "rdmdiscovery.h" -#include "rdmdevicecontroller.h" -#include "rdm.h" - -#include "debug.h" - -class ArtNetRdmController final: public RDMDeviceController, public ArtNetRdm, RDMDiscovery { -public: - ArtNetRdmController(); - - ~ArtNetRdmController() override { - DEBUG_ENTRY - DEBUG_EXIT - } - - void Print() { - RDMDeviceController::Print(); - } - - const uint8_t *Handler(uint32_t nPortIndex, const uint8_t *pRdmData) override; - - // Discovery - - void Full(uint32_t nPortIndex) override { - DEBUG_ENTRY - assert(nPortIndex < artnetnode::MAX_PORTS); - RDMDiscovery::Full(nPortIndex, &m_pRDMTod[nPortIndex]); - DEBUG_EXIT - } - - uint32_t GetUidCount(uint32_t nPortIndex) override { - assert(nPortIndex < artnetnode::MAX_PORTS); - return m_pRDMTod[nPortIndex].GetUidCount(); - } - - void TodCopy(uint32_t nPortIndex, uint8_t *pTod) override { - DEBUG_ENTRY - assert(nPortIndex < artnetnode::MAX_PORTS); - m_pRDMTod[nPortIndex].Copy(pTod); - DEBUG_EXIT - } - - // Gateway - - bool RdmReceive(uint32_t nPortIndex, uint8_t *pRdmData) override; - - void TodReset(uint32_t nPortIndex) override { - assert(nPortIndex < artnetnode::MAX_PORTS); - m_pRDMTod[nPortIndex].Reset(); - } - - bool TodAddUid(uint32_t nPortIndex, const uint8_t *pUid) override { - return m_pRDMTod[nPortIndex].AddUid(pUid); - } - - // class Node - - bool CopyTodEntry(uint32_t nPortIndex, uint32_t nIndex, uint8_t uid[RDM_UID_SIZE]) { - assert(nPortIndex < artnetnode::MAX_PORTS); - return m_pRDMTod[nPortIndex].CopyUidEntry(nIndex, uid); - } - - // Generic - - void TodDump(uint32_t nPortIndex) { - assert(nPortIndex < artnetnode::MAX_PORTS); - m_pRDMTod[nPortIndex].Dump(); - } - -private: - void RespondMessageAck(uint32_t nPortIndex, const uint8_t *pUid, const struct TRdmMessage *pRdmMessage); - -private: - static RDMTod m_pRDMTod[artnetnode::MAX_PORTS]; - static TRdmMessage s_rdmMessage; -}; - -#endif /* ARTNETRDMCONTROLLER_H_ */ diff --git a/lib-rdmdiscovery/src/artnet/rdm_send.cpp b/lib-rdmdiscovery/src/artnet/rdm_send.cpp deleted file mode 100644 index 3fd1f7dc..00000000 --- a/lib-rdmdiscovery/src/artnet/rdm_send.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @file rdm_send.cpp - */ - -/* Copyright (C) 2022 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "artnetrdm.h" - -#include "rdm.h" -#include "rdmmessage.h" -#include "rdm_e120.h" - -#include "debug.h" - -namespace artnet { - -void rdm_send(uint32_t nPortIndex, const uint8_t *pRdmData) { - assert(pRdmData != nullptr); - - auto *pRdmMessage = reinterpret_cast(pRdmData); - - if ((pRdmMessage->command_class == E120_GET_COMMAND_RESPONSE) || (pRdmMessage->command_class == E120_SET_COMMAND_RESPONSE)) { - struct TRdmMessage rdmMessage; - - rdmMessage.start_code = E120_SC_RDM; - - auto *pData = reinterpret_cast(&rdmMessage); - - memcpy(&pData[1], pRdmData, pRdmMessage->message_length - 1U); - - uint32_t i; - uint16_t nChecksum = 0; - - for (i = 0; i < rdmMessage.message_length; i++) { - nChecksum = static_cast(nChecksum + pData[i]); - } - - pData[i++] = static_cast(nChecksum >> 8); - pData[i] = static_cast(nChecksum & 0XFF); - - Rdm::SendRaw(nPortIndex, reinterpret_cast(&rdmMessage), rdmMessage.message_length + RDM_MESSAGE_CHECKSUM_SIZE); - -#ifndef NDEBUG - RDMMessage::Print(reinterpret_cast(&rdmMessage)); -#endif - } -} - -} // namespace artnet diff --git a/lib-rdmdiscovery/src/rdm/rdmdiscovery.cpp b/lib-rdmdiscovery/src/rdm/rdmdiscovery.cpp deleted file mode 100755 index df8891d9..00000000 --- a/lib-rdmdiscovery/src/rdm/rdmdiscovery.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/** - * @file rdmddiscovery.cpp - * - */ -/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#ifndef NDEBUG -# include -#endif - -#include "rdm.h" -#include "rdm_e120.h" -#include "rdmdiscovery.h" - -#include "hardware.h" - -typedef union cast { - uint64_t uint; - uint8_t uid[RDM_UID_SIZE]; -} _cast; - -static _cast uuid_cast; - -static constexpr auto RECEIVE_TIME_OUT = 2800U; - -RDMDiscovery::RDMDiscovery(const uint8_t *pUid) { - memcpy(m_Uid, pUid, RDM_UID_SIZE); - m_Message.SetSrcUid(pUid); - -#ifndef NDEBUG - printf("Uid : "); - PrintUid(m_Uid); - printf("\n"); -#endif -} - -void RDMDiscovery::Full(uint32_t nPortIndex, RDMTod *pRDMTod){ - DEBUG_ENTRY - - m_nPortIndex = nPortIndex; - - m_pRDMTod = pRDMTod; - m_pRDMTod->Reset(); - - Hardware::Get()->WatchdogFeed(); - - m_Message.SetPortID(static_cast(1 + nPortIndex)); - m_Message.SetDstUid(UID_ALL); - m_Message.SetCc(E120_DISCOVERY_COMMAND); - m_Message.SetPid(E120_DISC_UN_MUTE); - m_Message.SetPd(nullptr, 0); - m_Message.Send(m_nPortIndex); - m_Message.ReceiveTimeOut(m_nPortIndex, RECEIVE_TIME_OUT); - - Hardware::Get()->WatchdogFeed(); - udelay(RECEIVE_TIME_OUT); - Hardware::Get()->WatchdogFeed(); - - m_Message.Send(m_nPortIndex); - m_Message.ReceiveTimeOut(m_nPortIndex, RECEIVE_TIME_OUT); - - Hardware::Get()->WatchdogFeed(); - udelay(RECEIVE_TIME_OUT); - Hardware::Get()->WatchdogFeed(); - - FindDevices(0x000000000000, 0xfffffffffffe); - - m_pRDMTod->Dump(); - DEBUG_EXIT -} - -bool RDMDiscovery::FindDevices(uint64_t LowerBound, uint64_t UpperBound) { - Hardware::Get()->WatchdogFeed(); - - auto *pLateResponse __attribute__((unused)) = m_Message.Receive(m_nPortIndex); -#ifndef NDEBUG - if (pLateResponse != nullptr) { - printf("%d ", __LINE__); - RDMMessage::Print(pLateResponse); - } -#endif - -#ifndef NDEBUG - printf("FindDevices : "); - PrintUid(LowerBound); - printf(" - "); - PrintUid(UpperBound); - printf("\n"); -#endif - - uint8_t uid[RDM_UID_SIZE]; - struct TRdmMessage *pResponse; - - if (LowerBound == UpperBound) { - memcpy(uid, ConvertUid(LowerBound), RDM_UID_SIZE); - - m_Message.SetCc(E120_DISCOVERY_COMMAND); - m_Message.SetPid(E120_DISC_MUTE); - m_Message.SetDstUid(uid); - m_Message.SetPd(nullptr, 0); - - auto nRetry = 0; - - do { - if (++nRetry == 10) { - break; - } - - Hardware::Get()->WatchdogFeed(); - - m_Message.Send(m_nPortIndex, 5800); - pResponse = reinterpret_cast(const_cast(m_Message.ReceiveTimeOut(m_nPortIndex, RECEIVE_TIME_OUT))); - - if (pResponse != nullptr) { - if ((pResponse->command_class != E120_DISCOVERY_COMMAND_RESPONSE) || ((static_cast((pResponse->param_id[0] << 8) + pResponse->param_id[1])) != E120_DISC_MUTE)) { - continue; - } - } - } while (pResponse == nullptr); - - if (pResponse != nullptr) { -#ifndef NDEBUG - RDMMessage::Print(reinterpret_cast(pResponse)); -#endif - if ((pResponse->command_class == E120_DISCOVERY_COMMAND_RESPONSE) && (memcmp(uid, pResponse->source_uid, RDM_UID_SIZE) == 0)) { - m_pRDMTod->AddUid(uid); - } else { - #ifndef NDEBUG - printf("%d ", __LINE__); - PrintUid(uid); - printf("\n"); - #endif - } - } else { - return true; - } - } else { - memcpy(m_Pdl[0], ConvertUid(LowerBound), RDM_UID_SIZE); - memcpy(m_Pdl[1], ConvertUid(UpperBound), RDM_UID_SIZE); - - m_Message.SetDstUid(UID_ALL); - m_Message.SetCc(E120_DISCOVERY_COMMAND); - m_Message.SetPid(E120_DISC_UNIQUE_BRANCH); - m_Message.SetPd(reinterpret_cast(m_Pdl), 2 * RDM_UID_SIZE); - - auto nRetry = 0; - - do { - if (++nRetry == 3) { - break; - } - - Hardware::Get()->WatchdogFeed(); - - m_Message.Send(m_nPortIndex, 5800); - pResponse = reinterpret_cast(const_cast(m_Message.ReceiveTimeOut(m_nPortIndex, RECEIVE_TIME_OUT))); - - } while (pResponse == nullptr); - - if (pResponse != nullptr) { - auto bDeviceFound = true; - - if (IsValidDiscoveryResponse(reinterpret_cast(pResponse), uid)) { - bDeviceFound = QuickFind(uid); - } - - if (bDeviceFound) { - const uint64_t MidPosition = ((LowerBound & (0x0000800000000000 - 1)) + (UpperBound & (0x0000800000000000 - 1))) / 2 - + (UpperBound & (0x0000800000000000) ? 0x0000400000000000 : 0 ) - + (LowerBound & (0x0000800000000000) ? 0x0000400000000000 : 0 ); - - bDeviceFound = FindDevices(LowerBound, MidPosition); - bDeviceFound |= FindDevices(MidPosition + 1, UpperBound); - - if (bDeviceFound) { - return true; - } - } - } - } - - return false; -} - -const uint8_t *RDMDiscovery::ConvertUid(uint64_t nUid) { - uuid_cast.uint = __builtin_bswap64(nUid << 16); - return uuid_cast.uid; -} - -uint64_t RDMDiscovery::ConvertUid(const uint8_t *pUid) { - memcpy(uuid_cast.uid, pUid, RDM_UID_SIZE); - return __builtin_bswap64(uuid_cast.uint << 16); -} - -void RDMDiscovery::PrintUid(__attribute__((unused)) uint64_t nUid) { -#ifndef NDEBUG - PrintUid(ConvertUid(nUid)); -#endif -} - -void RDMDiscovery::PrintUid(__attribute__((unused)) const uint8_t *pUid) { -#ifndef NDEBUG - printf("%.2x%.2x:%.2x%.2x%.2x%.2x", pUid[0], pUid[1], pUid[2], pUid[3], pUid[4], pUid[5]); -#endif -} - -bool RDMDiscovery::IsValidDiscoveryResponse(const uint8_t *pDiscResponse, uint8_t *pUid) { - uint8_t checksum[2]; - uint16_t nRdmChecksum = 6 * 0xFF; - auto bIsValid = false; - - if (pDiscResponse[0] == 0xFE) { - pUid[0] = pDiscResponse[8] & pDiscResponse[9]; - pUid[1] = pDiscResponse[10] & pDiscResponse[11]; - - pUid[2] = pDiscResponse[12] & pDiscResponse[13]; - pUid[3] = pDiscResponse[14] & pDiscResponse[15]; - pUid[4] = pDiscResponse[16] & pDiscResponse[17]; - pUid[5] = pDiscResponse[18] & pDiscResponse[19]; - - checksum[0] = pDiscResponse[22] & pDiscResponse[23]; - checksum[1] = pDiscResponse[20] & pDiscResponse[21]; - - for (uint32_t i = 0; i < 6; i++) { - nRdmChecksum = static_cast(nRdmChecksum + pUid[i]); - } - - if (((nRdmChecksum >> 8) == checksum[1]) && ((nRdmChecksum & 0xFF) == checksum[0])) { - bIsValid = true; - } - -#ifndef NDEBUG - PrintUid(pUid); - printf(", checksum %.2x%.2x -> %.4x {%c}\n", checksum[1], checksum[0], nRdmChecksum, bIsValid ? 'Y' : 'N'); -#endif - - } else { -#ifndef NDEBUG - printf("%d ", __LINE__); - RDMMessage::Print(pDiscResponse); -#endif - } - - return bIsValid; -} - -bool RDMDiscovery::QuickFind(const uint8_t *uid) { - uint8_t r_uid[RDM_UID_SIZE]; - -#ifndef NDEBUG - printf("QuickFind : "); - PrintUid(uid); - printf("\n"); -#endif - - m_Message.SetCc(E120_DISCOVERY_COMMAND); - m_Message.SetPid(E120_DISC_MUTE); - m_Message.SetDstUid(uid); - m_Message.SetPd(nullptr, 0); - - TRdmMessage *pResponse; - - auto nRetry = 0; - - do { - if (++nRetry == 10) { - break; - } - - Hardware::Get()->WatchdogFeed(); - - m_Message.Send(m_nPortIndex, 5800); - pResponse = reinterpret_cast(const_cast(m_Message.ReceiveTimeOut(m_nPortIndex, RECEIVE_TIME_OUT))); - - if (pResponse != nullptr) { - if ((pResponse->command_class != E120_DISCOVERY_COMMAND_RESPONSE) || ((static_cast((pResponse->param_id[0] << 8) + pResponse->param_id[1])) != E120_DISC_MUTE)) { - continue; - } - } - } while (pResponse == nullptr); - - if (pResponse != nullptr) { -#ifndef NDEBUG - RDMMessage::Print(reinterpret_cast(pResponse)); -#endif - if ((pResponse->command_class == E120_DISCOVERY_COMMAND_RESPONSE) && (memcmp(uid, pResponse->source_uid, RDM_UID_SIZE) == 0)) { - m_pRDMTod->AddUid(uid); - } else { -#ifndef NDEBUG - printf("%d ", __LINE__); - PrintUid(uid); - printf("\n"); -#endif - } - } - - m_Message.SetDstUid(UID_ALL); - m_Message.SetCc(E120_DISCOVERY_COMMAND); - m_Message.SetPid(E120_DISC_UNIQUE_BRANCH); - m_Message.SetPd(reinterpret_cast(m_Pdl), 2 * RDM_UID_SIZE); - - nRetry = 0; - - do { - if (++nRetry == 3) { - break; - } - - Hardware::Get()->WatchdogFeed(); - - m_Message.Send(m_nPortIndex, 5800); - pResponse = reinterpret_cast(const_cast(m_Message.ReceiveTimeOut(m_nPortIndex, RECEIVE_TIME_OUT))); - - } while (pResponse == nullptr); - - - if ((pResponse != nullptr) && (IsValidDiscoveryResponse(reinterpret_cast(pResponse), r_uid))) { - QuickFind(r_uid); - } else if ((pResponse != nullptr) && (!IsValidDiscoveryResponse(reinterpret_cast(pResponse), r_uid))) { - return true; - } - - return false; -} diff --git a/lib-rdmnet/.cproject b/lib-rdmnet/.cproject deleted file mode 100644 index e870192a..00000000 --- a/lib-rdmnet/.cproject +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-rdmnet/.project b/lib-rdmnet/.project deleted file mode 100644 index cd6d5119..00000000 --- a/lib-rdmnet/.project +++ /dev/null @@ -1,27 +0,0 @@ - - - lib-rdmnet - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/lib-rdmnet/.settings/language.settings.xml b/lib-rdmnet/.settings/language.settings.xml deleted file mode 100644 index 0a846f1f..00000000 --- a/lib-rdmnet/.settings/language.settings.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-rdmnet/.settings/org.eclipse.cdt.core.prefs b/lib-rdmnet/.settings/org.eclipse.cdt.core.prefs deleted file mode 100644 index c8ec5df2..00000000 --- a/lib-rdmnet/.settings/org.eclipse.cdt.core.prefs +++ /dev/null @@ -1,6 +0,0 @@ -doxygen/doxygen_new_line_after_brief=true -doxygen/doxygen_use_brief_tag=false -doxygen/doxygen_use_javadoc_tags=true -doxygen/doxygen_use_pre_tag=false -doxygen/doxygen_use_structural_commands=false -eclipse.preferences.version=1 diff --git a/lib-rdmnet/.settings/org.eclipse.core.resources.prefs b/lib-rdmnet/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 99f26c02..00000000 --- a/lib-rdmnet/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -encoding/=UTF-8 diff --git a/lib-rdmnet/Makefile.GD32 b/lib-rdmnet/Makefile.GD32 deleted file mode 100644 index b4683029..00000000 --- a/lib-rdmnet/Makefile.GD32 +++ /dev/null @@ -1,7 +0,0 @@ -DEFINES=NODE_RDMNET_LLRP_ONLY -DEFINES+=NDEBUG - - -EXTRA_INCLUDES=../lib-rdm/include ../lib-rdmsensor/include ../lib-rdmsubdevice/include ../lib-e131/include ../lib-network/include ../lib-lightset/include - -include ../firmware-template-gd32/lib/Rules.mk diff --git a/lib-rdmresponder/.cproject b/lib-rdmresponder/.cproject deleted file mode 100644 index 0fc7f3ce..00000000 --- a/lib-rdmresponder/.cproject +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-rdmresponder/.project b/lib-rdmresponder/.project deleted file mode 100644 index d5025250..00000000 --- a/lib-rdmresponder/.project +++ /dev/null @@ -1,27 +0,0 @@ - - - lib-rdmresponder - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/lib-rdmresponder/.settings/org.eclipse.cdt.core.prefs b/lib-rdmresponder/.settings/org.eclipse.cdt.core.prefs deleted file mode 100644 index c8ec5df2..00000000 --- a/lib-rdmresponder/.settings/org.eclipse.cdt.core.prefs +++ /dev/null @@ -1,6 +0,0 @@ -doxygen/doxygen_new_line_after_brief=true -doxygen/doxygen_use_brief_tag=false -doxygen/doxygen_use_javadoc_tags=true -doxygen/doxygen_use_pre_tag=false -doxygen/doxygen_use_structural_commands=false -eclipse.preferences.version=1 diff --git a/lib-rdmresponder/.settings/org.eclipse.core.resources.prefs b/lib-rdmresponder/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 99f26c02..00000000 --- a/lib-rdmresponder/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -encoding/=UTF-8 diff --git a/lib-rdmresponder/Rules.mk b/lib-rdmresponder/Rules.mk deleted file mode 100644 index 19d62872..00000000 --- a/lib-rdmresponder/Rules.mk +++ /dev/null @@ -1,14 +0,0 @@ -EXTRA_INCLUDES+=../lib-rdm/include ../lib-rdmsensor/include ../lib-rdmsubdevice/include ../lib-lightset/include - -ifneq ($(MAKE_FLAGS),) - ifneq (,$(findstring NODE_ARTNET,$(MAKE_FLAGS))) - EXTRA_INCLUDES+=../lib-artnet/include - EXTRA_SRCDIR+=src/artnet - else - EXTRA_INCLUDES+=../lib-dmx/include ../lib-dmxreceiver/include - EXTRA_SRCDIR+=src/rdm - endif -else - EXTRA_INCLUDES+=../lib-dmx/include ../lib-dmxreceiver/include ../lib-artnet/include - EXTRA_SRCDIR+=src/rdm src/artnet -endif \ No newline at end of file diff --git a/lib-rdmresponder/include/rdmresponder.h b/lib-rdmresponder/include/rdmresponder.h deleted file mode 100644 index 03181e01..00000000 --- a/lib-rdmresponder/include/rdmresponder.h +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @file rdmresponder.h - * - */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef RDMRESPONDER_H_ -#define RDMRESPONDER_H_ - -#include -#include - -#include "dmxreceiver.h" - -#include "rdmhandler.h" -#include "rdmdeviceresponder.h" -#include "rdmpersonality.h" - -#include "lightset.h" - -#if defined (NODE_RDMNET_LLRP_ONLY) -# error "Cannot be both RDMNet Device and RDM Responder" -#endif - -namespace rdm { -namespace responder { -static constexpr auto NO_DATA = 0; -static constexpr auto DISCOVERY_RESPONSE = -1; -static constexpr auto INVALID_DATA_RECEIVED = -2; -static constexpr auto INVALID_RESPONSE = -3; -} // namespace responder -} // namespace rdm - -class RDMResponder final : DMXReceiver, public RDMDeviceResponder, RDMHandler { -public: - RDMResponder(RDMPersonality **pRDMPersonalities, uint32_t nPersonalityCount) : - DMXReceiver(pRDMPersonalities[rdm::device::responder::DEFAULT_CURRENT_PERSONALITY - 1]->GetLightSet()), - RDMDeviceResponder(pRDMPersonalities, nPersonalityCount) - { - assert(s_pThis == nullptr); - s_pThis = this; - } - - ~RDMResponder() override {} - - void Init() { - RDMDeviceResponder::Init(); - // There is no DMXReceiver::Init() - } - - int Run(); - - void Print() { - RDMDeviceResponder::Print(); - DMXReceiver::Print(); - } - - void Start() { - // There is no RDMDeviceResponder::Start() - DMXReceiver::Start(); - } - - void DmxDisableOutput(bool bDisable) { - DMXReceiver::SetDisableOutput(bDisable); - } - - uint16_t GetDmxStartAddress(uint16_t nSubDevice = RDM_ROOT_DEVICE) { - return RDMDeviceResponder::GetDmxStartAddress(nSubDevice); - } - - uint16_t GetDmxFootPrint(uint16_t nSubDevice = RDM_ROOT_DEVICE) { - return RDMDeviceResponder::GetDmxFootPrint(nSubDevice); - } - - static RDMResponder* Get() { - return s_pThis; - } - - void PersonalityUpdate(uint32_t nPersonality) __attribute__((weak)); - void DmxStartAddressUpdate(uint16_t nDmxStartAddress) __attribute__((weak)); - -private: - int HandleResponse(uint8_t *pResponse); - - void PersonalityUpdate(LightSet *pLightSet) override { - DMXReceiver::SetLightSet(pLightSet); - PersonalityUpdate(static_cast(RDMDeviceResponder::GetPersonalityCurrent(RDM_ROOT_DEVICE))); - } - - void DmxStartAddressUpdate() override { - DmxStartAddressUpdate(RDMDeviceResponder::GetDmxStartAddress(RDM_ROOT_DEVICE)); - } - -private: - static RDMResponder *s_pThis; - static TRdmMessage s_RdmCommand; - static bool m_IsSubDeviceActive; -}; - -#endif /* RDMRESPONDER_H_ */ diff --git a/lib-rdmresponder/src/artnet/artnetrdmresponder.cpp b/lib-rdmresponder/src/artnet/artnetrdmresponder.cpp deleted file mode 100644 index b8676b1b..00000000 --- a/lib-rdmresponder/src/artnet/artnetrdmresponder.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/** - * @file artnetrdmresponder.cpp - * - */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "artnetrdmresponder.h" - -#include "rdmdeviceresponder.h" -#include "rdmhandler.h" -#include "rdmmessage.h" - -#include "lightset.h" - -#include "rdm.h" -#include "rdm_e120.h" - -#include "debug.h" - -namespace configstore { -void delay(); -} // namespace configstore - -ArtNetRdmResponder *ArtNetRdmResponder::s_pThis; -TRdmMessage ArtNetRdmResponder::s_RdmCommand; - -ArtNetRdmResponder::ArtNetRdmResponder(RDMPersonality **pRDMPersonalities, uint32_t nPersonalityCount) : - RDMDeviceResponder(pRDMPersonalities, nPersonalityCount) -{ - DEBUG_ENTRY - - assert(s_pThis == nullptr); - s_pThis = this; - - DEBUG_EXIT -} - -ArtNetRdmResponder::~ArtNetRdmResponder() { - DEBUG_ENTRY - - DEBUG_EXIT -} - -const uint8_t *ArtNetRdmResponder::Handler(uint32_t nPortIndex, const uint8_t *pRdmDataNoSC) { - DEBUG_ENTRY - - if (nPortIndex != 0) { - DEBUG_EXIT - return nullptr; - } - - if (pRdmDataNoSC == nullptr) { - DEBUG_EXIT - return nullptr; - } - -#ifndef NDEBUG - RDMMessage::PrintNoSc(pRdmDataNoSC); -#endif - - HandleData(pRdmDataNoSC, reinterpret_cast(&s_RdmCommand)); - - if (s_RdmCommand.start_code != E120_SC_RDM) { - DEBUG_EXIT - return nullptr; - } - -#ifndef NDEBUG - RDMMessage::Print(reinterpret_cast(&s_RdmCommand)); -#endif - - DEBUG_EXIT - return reinterpret_cast(&s_RdmCommand); -} diff --git a/lib-rdmresponder/src/rdm/rdmresponder.cpp b/lib-rdmresponder/src/rdm/rdmresponder.cpp deleted file mode 100644 index bd90fc6c..00000000 --- a/lib-rdmresponder/src/rdm/rdmresponder.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @file rdmresponder.cpp - * - */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include - -#include "rdmresponder.h" -#include "rdmdeviceresponder.h" -#include "rdmsubdevices.h" - -#include "dmxreceiver.h" - -#include "lightset.h" - -#include "rdm.h" -#include "rdm_e120.h" - -#include "debug.h" - -namespace configstore { -void delay(); -} // namespace configstore - -RDMResponder *RDMResponder::s_pThis; -TRdmMessage RDMResponder::s_RdmCommand; -bool RDMResponder::m_IsSubDeviceActive; - -using namespace rdm::responder; - -int RDMResponder::HandleResponse(uint8_t *pResponse) { - auto nLength = INVALID_RESPONSE; - - if (pResponse[0] == E120_SC_RDM) { - const auto *p = reinterpret_cast(pResponse); - nLength = static_cast(p->message_length + RDM_MESSAGE_CHECKSUM_SIZE); - Rdm::SendRawRespondMessage(0, pResponse, static_cast(nLength)); - } else if (pResponse[0] == 0xFE) { - nLength = sizeof(struct TRdmDiscoveryMsg); - Rdm::SendDiscoveryRespondMessage(0, pResponse, static_cast(nLength)); - } - -#ifndef NDEBUG - if (nLength != INVALID_RESPONSE) { - RDMMessage::Print(pResponse); - } -#endif - - configstore::delay(); - return nLength; -} - -int RDMResponder::Run() { - int16_t nLength; - - const auto *pDmxDataIn = DMXReceiver::Run(nLength); - - if (RDMSubDevices::Get()->GetCount() != 0) { - if (nLength == -1) { - if (m_IsSubDeviceActive) { - RDMSubDevices::Get()->Stop(); - m_IsSubDeviceActive = false; - } - } else if (pDmxDataIn != nullptr) { - RDMSubDevices::Get()->SetData(pDmxDataIn, static_cast(nLength)); - if (!m_IsSubDeviceActive) { - RDMSubDevices::Get()->Start(); - m_IsSubDeviceActive = true; - } - } - } - - const auto *pRdmDataIn = Rdm::Receive(0); - - if (pRdmDataIn == nullptr) { - return NO_DATA; - } - -#ifndef NDEBUG - RDMMessage::Print(pRdmDataIn); -#endif - - if (pRdmDataIn[0] == E120_SC_RDM) { - const auto *pRdmCommand = reinterpret_cast(pRdmDataIn); - - switch (pRdmCommand->command_class) { - case E120_DISCOVERY_COMMAND: - case E120_GET_COMMAND: - case E120_SET_COMMAND: - HandleData(&pRdmDataIn[1], reinterpret_cast(&s_RdmCommand)); - return HandleResponse(reinterpret_cast(&s_RdmCommand)); - break; - default: - DEBUG_PUTS("RDM_RESPONDER_INVALID_DATA_RECEIVED"); - return INVALID_DATA_RECEIVED; - break; - } - } - - DEBUG_PUTS("RDM_RESPONDER_DISCOVERY_RESPONSE"); - return DISCOVERY_RESPONSE; -} - -void __attribute__((weak)) RDMResponder::PersonalityUpdate(__attribute__((unused)) uint32_t nPersonality) { -} - -void __attribute__((weak))DmxStartAddressUpdate(__attribute__((unused)) uint16_t nDmxStartAddress) { -} diff --git a/lib-rdmsensor/.cproject b/lib-rdmsensor/.cproject index c5c68dc2..ea59a5fa 100644 --- a/lib-rdmsensor/.cproject +++ b/lib-rdmsensor/.cproject @@ -30,11 +30,9 @@ - diff --git a/lib-rdmsensor/Makefile.GD32 b/lib-rdmsensor/Makefile.GD32 index 38e2e7b6..5f6d2d93 100644 --- a/lib-rdmsensor/Makefile.GD32 +++ b/lib-rdmsensor/Makefile.GD32 @@ -1,5 +1,6 @@ DEFINES=NDEBUG -EXTRA_INCLUDES=../lib-rdm/include ../lib-properties/include ../lib-hal/include ../lib-device/include +EXTRA_INCLUDES= +include Rules.mk include ../firmware-template-gd32/lib/Rules.mk \ No newline at end of file diff --git a/lib-rdmsensor/Rules.mk b/lib-rdmsensor/Rules.mk new file mode 100755 index 00000000..fbe77089 --- /dev/null +++ b/lib-rdmsensor/Rules.mk @@ -0,0 +1,7 @@ +EXTRA_INCLUDES+=../lib-rdm/include ../lib-properties/include + +ifneq ($(MAKE_FLAGS),) + ifneq (,$(findstring CONFIG_STORE_USE_ROM,$(MAKE_FLAGS))) + EXTRA_INCLUDES+=../lib-flashcode/include + endif +endif \ No newline at end of file diff --git a/lib-ws28xxdmx/include/pixeldmxhandler.h b/lib-rdmsensor/include/rdm_sensors.h old mode 100644 new mode 100755 similarity index 71% rename from lib-ws28xxdmx/include/pixeldmxhandler.h rename to lib-rdmsensor/include/rdm_sensors.h index eed24e81..5bf8b044 --- a/lib-ws28xxdmx/include/pixeldmxhandler.h +++ b/lib-rdmsensor/include/rdm_sensors.h @@ -1,8 +1,8 @@ /** - * @file pixeldmxhandler.h + * @file rdm_sensors.h * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,16 +23,18 @@ * THE SOFTWARE. */ -#ifndef PIXELDMXHANDLER_H_ -#define PIXELDMXHANDLER_H_ +#ifndef RDM_SENSORS_H_ +#define RDM_SENSORS_H_ -class PixelDmxHandler { -public: - PixelDmxHandler() {} - virtual ~PixelDmxHandler() {} - - virtual void Start()=0; - virtual void Stop()=0; +namespace rdm { +namespace sensors { +enum class Types { + BH170, HTU21D, INA219, MCP9808, SI7021, MCP3424, UNDEFINED }; -#endif /* PIXELDMXHANDLER_H_ */ +const char *get_type_string(rdm::sensors::Types type); +rdm::sensors::Types get_type_string(const char *pValue); +} // namespace sensors +} // namespace rdm + +#endif /* RDM_SENSORS_H_ */ diff --git a/lib-rdmsensor/include/rdmsensor.h b/lib-rdmsensor/include/rdmsensor.h deleted file mode 100644 index 19fd433e..00000000 --- a/lib-rdmsensor/include/rdmsensor.h +++ /dev/null @@ -1,141 +0,0 @@ -/** - * @file rdmsensor.h - * - */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef RDMSENSOR_H_ -#define RDMSENSOR_H_ - -#include - -namespace rdm { -namespace sensor { -struct Defintion { - uint8_t sensor; - uint8_t type; - uint8_t unit; - uint8_t prefix; - int16_t range_min; - int16_t range_max; - int16_t normal_min; - int16_t normal_max; - char description[32]; - uint8_t nLength; - uint8_t recorded_supported; -}; - -struct Values { - int16_t present; - int16_t lowest_detected; - int16_t highest_detected; - int16_t recorded; - uint8_t sensor_requested; -}; -static constexpr int16_t RANGE_MIN = -32768; -static constexpr int16_t RANGE_MAX = +32767; -static constexpr int16_t NORMAL_MIN = -32768; -static constexpr int16_t NORMAL_MAX = +32767; -static constexpr int16_t TEMPERATURE_ABS_ZERO = -273; - -template -constexpr int16_t safe_range_max(const T& a) -{ - static_assert(sizeof(int16_t) <= sizeof(T), "T"); - - return (a > static_cast(INT16_MAX)) ? INT16_MAX : static_cast(a); -} - -template -constexpr int16_t safe_range_min(const T& a) -{ - static_assert(sizeof(int16_t) <= sizeof(T), "T"); - - return (a < static_cast(INT16_MIN)) ? INT16_MIN : static_cast(a); -} - -} // namespace rdm -} // namespace sensor - - -class RDMSensor { -public: - RDMSensor(uint8_t nSensor); - virtual ~RDMSensor() {} - -public: - void SetType(uint8_t nType) { - m_tRDMSensorDefintion.type = nType; - } - - void SetUnit(uint8_t nUnit) { - m_tRDMSensorDefintion.unit = nUnit; - } - - void SetPrefix(uint8_t nPrefix) { - m_tRDMSensorDefintion.prefix = nPrefix; - } - - void SetRangeMin(int16_t nRangeMin) { - m_tRDMSensorDefintion.range_min = nRangeMin; - } - - void SetRangeMax(int16_t nRangeMax) { - m_tRDMSensorDefintion.range_max = nRangeMax; - } - - void SetNormalMin(int16_t nNormalMin) { - m_tRDMSensorDefintion.normal_min = nNormalMin; - } - - void SetNormalMax(int16_t nNormalMax) { - m_tRDMSensorDefintion.normal_max = nNormalMax; - } - - void SetDescription(const char *pDescription); - - void Print(); - - uint8_t GetSensor() const { - return m_nSensor; - } - - const struct rdm::sensor::Defintion* GetDefintion() { - return &m_tRDMSensorDefintion; - } - - const struct rdm::sensor::Values* GetValues(); - - void SetValues(); - - void Record(); - - virtual bool Initialize()=0; - virtual int16_t GetValue()=0; - -private: - uint8_t m_nSensor; - rdm::sensor::Defintion m_tRDMSensorDefintion; - rdm::sensor::Values m_tRDMSensorValues; -}; - -#endif /* RDMSENSOR_H_ */ diff --git a/lib-rdmsensor/include/rdmsensors.h b/lib-rdmsensor/include/rdmsensors.h deleted file mode 100644 index cdd1489a..00000000 --- a/lib-rdmsensor/include/rdmsensors.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @file rdmsensors.h - * - */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef RDMSENSORS_H_ -#define RDMSENSORS_H_ - -#include - -#include "rdmsensor.h" -#include "rdmsensorsconst.h" - -#if defined (RASPPI) || defined(BARE_METAL) -# define RDM_SENSORS_ENABLE -#endif - -#if !defined (__CYGWIN__) && !defined (__APPLE__) -# define RDMSENSOR_CPU_ENABLE -#endif - -#if defined (NODE_RDMNET_LLRP_ONLY) -# undef RDM_SENSORS_ENABLE -# undef RDMSENSOR_CPU_ENABLE -#endif - -namespace rdm { -namespace sensors { -static constexpr auto MAX = 16; -static constexpr auto STORE = 64; ///< Configuration store in bytes -namespace devices { -static constexpr auto MAX = 8; -} // namespace devices -} // namespace sensors -} // namespace rdm - -class RDMSensors { -public: - RDMSensors(); - ~RDMSensors(); - - bool Add(RDMSensor *pRDMSensor); - - uint8_t GetCount() const { - return m_nCount; - } - - const struct rdm::sensor::Defintion* GetDefintion(uint8_t nSensor); - const struct rdm::sensor::Values* GetValues(uint8_t nSensor); - void SetValues(uint8_t nSensor); - void SetRecord(uint8_t nSensor); - - RDMSensor *GetSensor(uint8_t nSensor) { - return m_pRDMSensor[nSensor]; - } - - static const char *GetTypeString(rdm::sensors::Types type); - static rdm::sensors::Types GetTypeString(const char *pValue); - - static RDMSensors* Get() { - return s_pThis; - } - -private: - RDMSensor **m_pRDMSensor { nullptr }; - uint8_t m_nCount { 0 }; - - static RDMSensors *s_pThis; -}; - -#endif /* RDMSENSORS_H_ */ diff --git a/lib-rdmsensor/include/rdmsensorsconst.h b/lib-rdmsensor/include/rdmsensorsconst.h old mode 100644 new mode 100755 index eb3ef03f..436b6ebf --- a/lib-rdmsensor/include/rdmsensorsconst.h +++ b/lib-rdmsensor/include/rdmsensorsconst.h @@ -26,19 +26,8 @@ #ifndef RDMSENSORSCONST_H_ #define RDMSENSORSCONST_H_ -#include - -namespace rdm { -namespace sensors { -enum class Types { - BH170, HTU21D, INA219, MCP9808, SI7021, MCP3424, UNDEFINED -}; -} // namespace sensors -} // namespace rdmsensors - struct RDMSensorsConst { static const char PARAMS_FILE_NAME[]; - static const char TYPE[static_cast(rdm::sensors::Types::UNDEFINED)][8]; }; #endif /* RDMSENSORSCONST_H_ */ diff --git a/lib-rdmsensor/include/rdmsensorsparams.h b/lib-rdmsensor/include/rdmsensorsparams.h index c9a81b0a..1b117466 100644 --- a/lib-rdmsensor/include/rdmsensorsparams.h +++ b/lib-rdmsensor/include/rdmsensorsparams.h @@ -29,7 +29,7 @@ #include #include "rdmsensors.h" -#include "rdmsensorstore.h" +#include "configstore.h" namespace rdm { namespace sensorsparams { @@ -50,41 +50,37 @@ static_assert(sizeof(struct Params) <= rdm::sensors::STORE, "struct Params is to class RDMSensorsParamsStore { public: - virtual ~RDMSensorsParamsStore() {} + static void Update(const rdm::sensorsparams::Params *pParams) { + ConfigStore::Get()->Update(configstore::Store::RDMSENSORS, pParams, sizeof(struct rdm::sensorsparams::Params)); + } - virtual void Update(const rdm::sensorsparams::Params *pParams)=0; - virtual void Copy(rdm::sensorsparams::Params *pParams)=0; + static void Copy(rdm::sensorsparams::Params *pParams) { + ConfigStore::Get()->Copy(configstore::Store::RDMSENSORS, pParams, sizeof(struct rdm::sensorsparams::Params)); + } }; class RDMSensorsParams { public: - RDMSensorsParams(RDMSensorsParamsStore *pRDMSensorsParamsStore); + RDMSensorsParams(); - bool Load(); + void Load(); void Load(const char *pBuffer, uint32_t nLength); void Builder(const rdm::sensorsparams::Params *pParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); void Save(char *pBuffer, uint32_t nLength, uint32_t& nSize) { - if (m_pRDMSensorsParamsStore == nullptr) { - nSize = 0; - return; - } - Builder(nullptr, pBuffer, nLength, nSize); } - void Dump(); - - void Set(RDMSensorStore *pRDMSensorStore = nullptr); + void Set(); static void staticCallbackFunction(void *p, const char *s); private: + void Dump(); void callbackFunction(const char *pLine); bool Add(RDMSensor *pRDMSensor); private: - RDMSensorsParamsStore *m_pRDMSensorsParamsStore; rdm::sensorsparams::Params m_Params; }; diff --git a/lib-configstore/include/storemidi.h b/lib-rdmsensor/include/rdmsensorsstore.h old mode 100644 new mode 100755 similarity index 63% rename from lib-configstore/include/storemidi.h rename to lib-rdmsensor/include/rdmsensorsstore.h index 96709bb3..4f45732a --- a/lib-configstore/include/storemidi.h +++ b/lib-rdmsensor/include/rdmsensorsstore.h @@ -1,8 +1,8 @@ /** - * @file storemidi.h + * @file rdmsensorsstore.h * */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,31 +23,24 @@ * THE SOFTWARE. */ -#ifndef STOREMIDI_H_ -#define STOREMIDI_H_ +#ifndef RDMSENSORSSTORE_H_ +#define RDMSENSORSSTORE_H_ -#include "midiparams.h" +#include +#include +#include +#include "rdmsensorsparams.h" +#include "rdmsensors.h" #include "configstore.h" -class StoreMidi final: public MidiParamsStore { +class RDMSensorsStore { public: - StoreMidi(); - - void Update(const struct TMidiParams *pMidiParams) override { - ConfigStore::Get()->Update(configstore::Store::MIDI, pMidiParams, sizeof(struct TMidiParams)); - } - - void Copy(struct TMidiParams *pMidiParams) override { - ConfigStore::Get()->Copy(configstore::Store::MIDI, pMidiParams, sizeof(struct TMidiParams)); + static void SaveCalibration(const uint32_t nSensor, const int32_t nCalibration) { + assert(nSensor < rdm::sensors::MAX); + auto c = static_cast(nCalibration); + ConfigStore::Get()->Update(configstore::Store::RDMSENSORS, (nSensor * sizeof(int16_t)) + offsetof(struct rdm::sensorsparams::Params, nCalibrate), &c, sizeof(int16_t)); } - - static StoreMidi *Get() { - return s_pThis; - } - -private: - static StoreMidi *s_pThis; }; -#endif /* STOREMIDI_H_ */ +#endif /* RDMSENSORSSTORE_H_ */ diff --git a/lib-rdmsensor/include/rdmsensorthermistor.h b/lib-rdmsensor/include/rdmsensorthermistor.h index b9f528d0..b0b4ade4 100644 --- a/lib-rdmsensor/include/rdmsensorthermistor.h +++ b/lib-rdmsensor/include/rdmsensorthermistor.h @@ -29,25 +29,24 @@ #include #include "rdmsensor.h" -#include "rdmsensorstore.h" +#include "rdmsensorsstore.h" +#include "rdm_e120.h" + #include "mcp3424.h" #include "thermistor.h" -#include "rdm_e120.h" - #include "debug.h" class RDMSensorThermistor final: public RDMSensor, MCP3424 { public: - RDMSensorThermistor(uint8_t nSensor, uint8_t nAddress = 0, uint8_t nChannel = 0, int32_t nCalibration = 0, RDMSensorStore *pRDMSensorStore = nullptr) : + RDMSensorThermistor(uint8_t nSensor, uint8_t nAddress = 0, uint8_t nChannel = 0, int32_t nCalibration = 0) : RDMSensor(nSensor), MCP3424(nAddress), m_nCalibration(nCalibration), - m_pRDMSensorStore(pRDMSensorStore), m_nChannel(nChannel) { DEBUG_ENTRY - DEBUG_PRINTF("nSensor=%u, nAddress=0x%.2x, nChannel=%u, nCalibration=%d, pRDMSensorStore=%p", nSensor, nAddress, nChannel, nCalibration, reinterpret_cast(pRDMSensorStore)); + DEBUG_PRINTF("nSensor=%u, nAddress=0x%.2x, nChannel=%u, nCalibration=%d", nSensor, nAddress, nChannel, nCalibration); SetType(E120_SENS_TEMPERATURE); SetUnit(E120_UNITS_CENTIGRADE); @@ -87,9 +86,7 @@ class RDMSensorThermistor final: public RDMSensor, MCP3424 { const auto iMeasure = static_cast(GetValue(nResistor) * 10); DEBUG_PRINTF("iCalibrate=%d, iMeasure=%d, m_nOffset=%d, nResistor=%u", iCalibrate, iMeasure, m_nCalibration, nResistor); if (iCalibrate == iMeasure) { - if (m_pRDMSensorStore != nullptr) { - m_pRDMSensorStore->SaveCalibration(RDMSensor::GetSensor(), m_nCalibration); - } + RDMSensorsStore::SaveCalibration(RDMSensor::GetSensor(), m_nCalibration); return true; } } @@ -99,9 +96,7 @@ class RDMSensorThermistor final: public RDMSensor, MCP3424 { void ResetCalibration() { m_nCalibration = 0; - if (m_pRDMSensorStore != nullptr) { - m_pRDMSensorStore->SaveCalibration(RDMSensor::GetSensor(), m_nCalibration); - } + RDMSensorsStore::SaveCalibration(RDMSensor::GetSensor(), m_nCalibration); } int32_t GetCalibration() const { @@ -129,7 +124,6 @@ class RDMSensorThermistor final: public RDMSensor, MCP3424 { private: int32_t m_nCalibration; - RDMSensorStore *m_pRDMSensorStore; uint8_t m_nChannel; /* diff --git a/lib-rdmsensor/src/rdm_sensors.cpp b/lib-rdmsensor/src/rdm_sensors.cpp new file mode 100755 index 00000000..49613690 --- /dev/null +++ b/lib-rdmsensor/src/rdm_sensors.cpp @@ -0,0 +1,58 @@ +/** + * @file rdm_sensors.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "rdm_sensors.h" + +namespace rdm { +namespace sensors { +static constexpr char TYPE[static_cast(rdm::sensors::Types::UNDEFINED)][8] = { + "bh1750", "htu21d", "ina219", "mcp9808", "si7021", "mcp3424" }; + +const char *get_type_string(rdm::sensors::Types type) { + if (type < rdm::sensors::Types::UNDEFINED) { + return TYPE[static_cast(type)]; + } + + return "Unknown"; +} + +rdm::sensors::Types get_type_string(const char *pValue) { + assert(pValue != nullptr); + + for (uint32_t i = 0; i < static_cast(rdm::sensors::Types::UNDEFINED); i++) { + if (strcasecmp(pValue, TYPE[i]) == 0) { + return static_cast(i); + } + } + + return rdm::sensors::Types::UNDEFINED; +} +} // namespace sensors +} // namespace rdm + diff --git a/lib-rdmsensor/src/rdmsensor.cpp b/lib-rdmsensor/src/rdmsensor.cpp deleted file mode 100644 index d3e940c3..00000000 --- a/lib-rdmsensor/src/rdmsensor.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @file rdmsensor.cpp - * - */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "rdmsensor.h" - -#include "debug.h" - -static constexpr uint8_t RDM_SENSOR_RECORDED_SUPPORTED = (1U << 0); -static constexpr uint8_t RDM_SENSOR_LOW_HIGH_DETECT = (1U << 1); - -RDMSensor::RDMSensor(uint8_t nSensor) : m_nSensor(nSensor) { - DEBUG_ENTRY - - m_tRDMSensorDefintion.sensor = m_nSensor; - m_tRDMSensorDefintion.recorded_supported = RDM_SENSOR_RECORDED_SUPPORTED | RDM_SENSOR_LOW_HIGH_DETECT; - - m_tRDMSensorValues.sensor_requested = m_nSensor; - m_tRDMSensorValues.lowest_detected = rdm::sensor::RANGE_MAX; - m_tRDMSensorValues.highest_detected = rdm::sensor::RANGE_MIN; - - DEBUG_EXIT -} - -void RDMSensor::SetDescription(const char *pDescription) { - DEBUG_ENTRY - - assert(pDescription != nullptr); - uint32_t i; - - for (i = 0; i < 32 && pDescription[i] != 0; i++) { - m_tRDMSensorDefintion.description[i] = pDescription[i]; - } - - m_tRDMSensorDefintion.nLength = static_cast(i); - - DEBUG_EXIT -} - -const struct rdm::sensor::Values* RDMSensor::GetValues() { - DEBUG_ENTRY - - const auto nValue = this->GetValue(); - - m_tRDMSensorValues.present = nValue; - m_tRDMSensorValues.lowest_detected = std::min(m_tRDMSensorValues.lowest_detected, nValue); - m_tRDMSensorValues.highest_detected = std::max(m_tRDMSensorValues.highest_detected, nValue); - - DEBUG_EXIT - - return &m_tRDMSensorValues; -} - -void RDMSensor::SetValues() { - DEBUG_ENTRY - - const auto nValue = this->GetValue(); - - m_tRDMSensorValues.present = nValue; - m_tRDMSensorValues.lowest_detected = nValue; - m_tRDMSensorValues.highest_detected = nValue; - m_tRDMSensorValues.recorded = nValue; - - DEBUG_EXIT -} - -void RDMSensor::Record() { - DEBUG_ENTRY - - const auto nValue = this->GetValue(); - - m_tRDMSensorValues.present = nValue; - m_tRDMSensorValues.recorded = nValue; - m_tRDMSensorValues.lowest_detected = std::min(m_tRDMSensorValues.lowest_detected, nValue); - m_tRDMSensorValues.highest_detected = std::max(m_tRDMSensorValues.highest_detected, nValue); - - DEBUG_EXIT -} diff --git a/lib-rdmsensor/src/rdmsensors.cpp b/lib-rdmsensor/src/rdmsensors.cpp deleted file mode 100644 index 86cd1a46..00000000 --- a/lib-rdmsensor/src/rdmsensors.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/** - * @file rdmsensors.cpp - * - */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "rdmsensors.h" - -#include "debug.h" - -#if defined (RDMSENSOR_CPU_ENABLE) -# include "cputemperature.h" -#endif - -RDMSensors *RDMSensors::s_pThis = nullptr; - -RDMSensors::RDMSensors() { - DEBUG_ENTRY - - assert(s_pThis == nullptr); - s_pThis = this; - -#if defined (RDM_SENSORS_ENABLE) || defined (RDMSENSOR_CPU_ENABLE) - m_pRDMSensor = new RDMSensor*[rdm::sensors::MAX]; - assert(m_pRDMSensor != nullptr); - -# if defined (RDMSENSOR_CPU_ENABLE) - Add(new CpuTemperature(m_nCount)); -# endif -#endif - DEBUG_EXIT -} - -RDMSensors::~RDMSensors() { - DEBUG_ENTRY - - for (unsigned i = 0; i < m_nCount; i++) { - if (m_pRDMSensor[i] != nullptr) { - delete m_pRDMSensor[i]; - m_pRDMSensor[i] = nullptr; - } - } - - delete [] m_pRDMSensor; - - DEBUG_EXIT -} - -const struct rdm::sensor::Defintion* RDMSensors::GetDefintion(uint8_t nSensor) { - assert(nSensor < m_nCount); - - assert(m_pRDMSensor[nSensor] != nullptr); - return m_pRDMSensor[nSensor]->GetDefintion(); -} - -const struct rdm::sensor::Values* RDMSensors::GetValues(uint8_t nSensor) { - assert(nSensor < m_nCount); - - assert(m_pRDMSensor[nSensor] != nullptr); - return m_pRDMSensor[nSensor]->GetValues(); -} - -void RDMSensors::SetValues(uint8_t nSensor) { - if (nSensor == 0xFF) { - for (uint32_t i = 0; i < m_nCount; i++) { - m_pRDMSensor[i]->SetValues(); - } - } else { - m_pRDMSensor[nSensor]->SetValues(); - } -} - -void RDMSensors::SetRecord(uint8_t nSensor) { - if (nSensor == 0xFF) { - for (uint32_t i = 0; i < m_nCount; i++) { - m_pRDMSensor[i]->Record(); - } - } else { - m_pRDMSensor[nSensor]->Record(); - } -} - -bool RDMSensors::Add(RDMSensor *pRDMSensor) { - DEBUG_ENTRY - - assert(m_pRDMSensor != nullptr); - - if (m_pRDMSensor == nullptr) { - DEBUG_EXIT - return false; - } - - if (m_nCount == rdm::sensors::MAX) { - DEBUG_EXIT - return false; - } - - assert(pRDMSensor != nullptr); - m_pRDMSensor[m_nCount++] = pRDMSensor; - - DEBUG_PRINTF("m_nCount=%u", m_nCount); - DEBUG_EXIT - return true; -} - -// Static - -const char* RDMSensors::GetTypeString(rdm::sensors::Types type) { - if (type < rdm::sensors::Types::UNDEFINED) { - return RDMSensorsConst::TYPE[static_cast(type)]; - } - - return "Unknown"; -} - -rdm::sensors::Types RDMSensors::GetTypeString(const char *pValue) { - assert(pValue != nullptr); - - for (uint32_t i = 0; i < static_cast(rdm::sensors::Types::UNDEFINED); i++) { - if (strcasecmp(pValue, RDMSensorsConst::TYPE[i]) == 0) { - return static_cast(i); - } - } - - return rdm::sensors::Types::UNDEFINED; -} diff --git a/lib-rdmsensor/src/rdmsensorsconst.cpp b/lib-rdmsensor/src/rdmsensorsconst.cpp index 99b023c0..34c2bdcf 100644 --- a/lib-rdmsensor/src/rdmsensorsconst.cpp +++ b/lib-rdmsensor/src/rdmsensorsconst.cpp @@ -28,6 +28,3 @@ #include "rdmsensorsconst.h" const char RDMSensorsConst::PARAMS_FILE_NAME[] = "sensors.txt"; - -const char RDMSensorsConst::TYPE[static_cast(rdm::sensors::Types::UNDEFINED)][8] = { - "bh1750", "htu21d", "ina219", "mcp9808", "si7021", "mcp3424" }; diff --git a/lib-rdmsensor/src/rdmsensorsparams.cpp b/lib-rdmsensor/src/rdmsensorsparams.cpp index 9db6abc1..0c63adf0 100644 --- a/lib-rdmsensor/src/rdmsensorsparams.cpp +++ b/lib-rdmsensor/src/rdmsensorsparams.cpp @@ -2,7 +2,7 @@ * @file rdmsensorsparams.cpp * */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,28 +35,41 @@ #include "rdmsensorsparams.h" #include "rdmsensors.h" -#include "rdmsensorstore.h" +#include "rdmsensorsconst.h" +#include "rdm_sensors.h" #include "readconfigfile.h" #include "sscan.h" #include "propertiesbuilder.h" #if defined (RDM_SENSORS_ENABLE) -# include "rdmsensorbh1750.h" -# include "rdmsensormcp9808.h" -# include "rdmsensorhtu21dhumidity.h" -# include "rdmsensorhtu21dtemperature.h" -# include "rdmsensorina219current.h" -# include "rdmsensorina219power.h" -# include "rdmsensorina219voltage.h" -# include "rdmsensorsi7021humidity.h" -# include "rdmsensorsi7021temperature.h" -# include "rdmsensorthermistor.h" +# if !defined (CONFIG_RDM_SENSORS_DISABLE_BH170) +# include "rdmsensorbh1750.h" +# endif +# if !defined (CONFIG_RDM_SENSORS_DISABLE_MCP9808) +# include "rdmsensormcp9808.h" +# endif +# if !defined (CONFIG_RDM_SENSORS_DISABLE_HTU21D) +# include "rdmsensorhtu21dhumidity.h" +# include "rdmsensorhtu21dtemperature.h" +# endif +# if !defined (CONFIG_RDM_SENSORS_DISABLE_INA219) +# include "rdmsensorina219current.h" +# include "rdmsensorina219power.h" +# include "rdmsensorina219voltage.h" +# endif +# if !defined (CONFIG_RDM_SENSORS_DISABLE_SI7021) +# include "rdmsensorsi7021humidity.h" +# include "rdmsensorsi7021temperature.h" +# endif +# if !defined (CONFIG_RDM_SENSORS_DISABLE_THERMISTOR) +# include "rdmsensorthermistor.h" +# endif #endif #include "debug.h" -RDMSensorsParams::RDMSensorsParams(RDMSensorsParamsStore *pRDMSensorsParamsStore): m_pRDMSensorsParamsStore(pRDMSensorsParamsStore) { +RDMSensorsParams::RDMSensorsParams() { DEBUG_ENTRY memset(&m_Params, 0, sizeof(struct rdm::sensorsparams::Params)); @@ -64,7 +77,7 @@ RDMSensorsParams::RDMSensorsParams(RDMSensorsParamsStore *pRDMSensorsParamsStore DEBUG_EXIT } -bool RDMSensorsParams::Load() { +void RDMSensorsParams::Load() { DEBUG_ENTRY m_Params.nDevices = 0; @@ -73,24 +86,20 @@ bool RDMSensorsParams::Load() { ReadConfigFile configfile(RDMSensorsParams::staticCallbackFunction, this); if (configfile.Read(RDMSensorsConst::PARAMS_FILE_NAME)) { - if (m_pRDMSensorsParamsStore != nullptr) { - m_pRDMSensorsParamsStore->Update(&m_Params); - } + RDMSensorsParamsStore::Update(&m_Params); } else #endif - if (m_pRDMSensorsParamsStore != nullptr) { - m_pRDMSensorsParamsStore->Copy(&m_Params); - // Sanity check - if (m_Params.nDevices >= rdm::sensors::devices::MAX) { - memset(&m_Params, 0, sizeof(struct rdm::sensorsparams::Params)); - } - } else { - DEBUG_EXIT - return false; + RDMSensorsParamsStore::Copy(&m_Params); + + // Sanity check + if (m_Params.nDevices >= rdm::sensors::devices::MAX) { + memset(&m_Params, 0, sizeof(struct rdm::sensorsparams::Params)); } +#ifndef NDEBUG + Dump(); +#endif DEBUG_EXIT - return true; } void RDMSensorsParams::Load(const char *pBuffer, uint32_t nLength) { @@ -98,12 +107,6 @@ void RDMSensorsParams::Load(const char *pBuffer, uint32_t nLength) { assert(pBuffer != nullptr); assert(nLength != 0); - assert(m_pRDMSensorsParamsStore != nullptr); - - if (m_pRDMSensorsParamsStore == nullptr) { - DEBUG_EXIT - return; - } m_Params.nDevices = 0; @@ -111,8 +114,11 @@ void RDMSensorsParams::Load(const char *pBuffer, uint32_t nLength) { config.Read(pBuffer, nLength); - m_pRDMSensorsParamsStore->Update(&m_Params); + RDMSensorsParamsStore::Update(&m_Params); +#ifndef NDEBUG + Dump(); +#endif DEBUG_EXIT } @@ -124,20 +130,19 @@ void RDMSensorsParams::Builder(const rdm::sensorsparams::Params *pParams, char * if (pParams != nullptr) { memcpy(&m_Params, pParams, sizeof(struct rdm::sensorsparams::Params)); } else { - assert(m_pRDMSensorsParamsStore != nullptr); - m_pRDMSensorsParamsStore->Copy(&m_Params); + RDMSensorsParamsStore::Copy(&m_Params); } PropertiesBuilder builder(RDMSensorsConst::PARAMS_FILE_NAME, pBuffer, nLength); for (uint32_t i = 0; i < static_cast(rdm::sensors::Types::UNDEFINED); i++) { - builder.AddHex8(RDMSensors::GetTypeString(static_cast(i)), 0xFF, false); + builder.AddHex8(rdm::sensors::get_type_string(static_cast(i)), 0xFF, false); } for (uint32_t i = 0; i < m_Params.nDevices; i++) { const auto type = static_cast(m_Params.Entry[i].nType); if (type < rdm::sensors::Types::UNDEFINED) { - builder.AddHex8(RDMSensors::GetTypeString(type), m_Params.Entry[i].nAddress, true); + builder.AddHex8(rdm::sensors::get_type_string(type), m_Params.Entry[i].nAddress, true); } } @@ -147,20 +152,6 @@ void RDMSensorsParams::Builder(const rdm::sensorsparams::Params *pParams, char * DEBUG_EXIT } -void RDMSensorsParams::Dump() { -#ifndef NDEBUG - printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, RDMSensorsConst::PARAMS_FILE_NAME); - - for (uint32_t i = 0; i < m_Params.nDevices; i++) { - printf(" %s 0x%.2x\n", RDMSensors::GetTypeString(static_cast(m_Params.Entry[i].nType)), m_Params.Entry[i].nAddress); - } - - for (uint32_t i = 0; i < rdm::sensors::MAX; i++) { - printf("%2d %d\n", i, m_Params.nCalibrate[i]); - } -#endif -} - bool RDMSensorsParams::Add(RDMSensor *pRDMSensor) { DEBUG_ENTRY @@ -176,7 +167,7 @@ bool RDMSensorsParams::Add(RDMSensor *pRDMSensor) { return false; } -void RDMSensorsParams::Set(__attribute__((unused)) RDMSensorStore *pRDMSensorStore) { +void RDMSensorsParams::Set() { #if defined (RDM_SENSORS_ENABLE) DEBUG_ENTRY @@ -185,15 +176,20 @@ void RDMSensorsParams::Set(__attribute__((unused)) RDMSensorStore *pRDMSensorSto const auto nAddress = m_Params.Entry[i].nAddress; switch (static_cast(m_Params.Entry[i].nType)) { +#if !defined (CONFIG_RDM_SENSORS_DISABLE_BH170) case rdm::sensors::Types::BH170: Add(new RDMSensorBH170(nSensorNumber, nAddress)); break; +#endif +#if !defined (CONFIG_RDM_SENSORS_DISABLE_HTU21D) case rdm::sensors::Types::HTU21D: if (!Add(new RDMSensorHTU21DHumidity(nSensorNumber++, nAddress))) { continue; } Add(new RDMSensorHTU21DTemperature(nSensorNumber, nAddress)); break; +#endif +#if !defined (CONFIG_RDM_SENSORS_DISABLE_INA219) case rdm::sensors::Types::INA219: if (!Add(new RDMSensorINA219Current(nSensorNumber++, nAddress))) { continue; @@ -203,30 +199,37 @@ void RDMSensorsParams::Set(__attribute__((unused)) RDMSensorStore *pRDMSensorSto } Add(new RDMSensorINA219Voltage(nSensorNumber, nAddress)); break; +#endif +#if !defined (CONFIG_RDM_SENSORS_DISABLE_MCP9808) case rdm::sensors::Types::MCP9808: Add(new RDMSensorMCP9808(nSensorNumber, nAddress)); break; +#endif +#if !defined (CONFIG_RDM_SENSORS_DISABLE_SI7021) case rdm::sensors::Types::SI7021: if (!Add(new RDMSensorSI7021Humidity(nSensorNumber++, nAddress))) { continue; } Add(new RDMSensorSI7021Temperature(nSensorNumber, nAddress)); break; +#endif +#if !defined (CONFIG_RDM_SENSORS_DISABLE_THERMISTOR) case rdm::sensors::Types::MCP3424: - if (!Add(new RDMSensorThermistor(nSensorNumber, nAddress, 0, m_Params.nCalibrate[nSensorNumber], pRDMSensorStore))) { + if (!Add(new RDMSensorThermistor(nSensorNumber, nAddress, 0, m_Params.nCalibrate[nSensorNumber]))) { continue; } nSensorNumber++; - if (!Add(new RDMSensorThermistor(nSensorNumber, nAddress, 1, m_Params.nCalibrate[nSensorNumber], pRDMSensorStore))) { + if (!Add(new RDMSensorThermistor(nSensorNumber, nAddress, 1, m_Params.nCalibrate[nSensorNumber]))) { continue; } nSensorNumber++; - if (!Add(new RDMSensorThermistor(nSensorNumber, nAddress, 2, m_Params.nCalibrate[nSensorNumber], pRDMSensorStore))) { + if (!Add(new RDMSensorThermistor(nSensorNumber, nAddress, 2, m_Params.nCalibrate[nSensorNumber]))) { continue; } nSensorNumber++; - Add(new RDMSensorThermistor(nSensorNumber, nAddress, 3, m_Params.nCalibrate[nSensorNumber], pRDMSensorStore)); + Add(new RDMSensorThermistor(nSensorNumber, nAddress, 3, m_Params.nCalibrate[nSensorNumber])); break; +#endif default: break; } @@ -257,7 +260,7 @@ void RDMSensorsParams::callbackFunction(const char *pLine) { rdm::sensors::Types sensorType; - if ((sensorType = RDMSensors::GetTypeString(aSensorName)) == rdm::sensors::Types::UNDEFINED) { + if ((sensorType = rdm::sensors::get_type_string(aSensorName)) == rdm::sensors::Types::UNDEFINED) { return; } @@ -285,3 +288,15 @@ void RDMSensorsParams::staticCallbackFunction(void *p, const char *s) { (static_cast(p))->callbackFunction(s); } + +void RDMSensorsParams::Dump() { + printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, RDMSensorsConst::PARAMS_FILE_NAME); + + for (uint32_t i = 0; i < m_Params.nDevices; i++) { + printf(" %s 0x%.2x\n", rdm::sensors::get_type_string(static_cast(m_Params.Entry[i].nType)), m_Params.Entry[i].nAddress); + } + + for (uint32_t i = 0; i < rdm::sensors::MAX; i++) { + printf("%2u %u\n", static_cast(i), static_cast(m_Params.nCalibrate[i])); + } +} diff --git a/lib-rdmsubdevice/.cproject b/lib-rdmsubdevice/.cproject index fd0bdca1..ea7fb6f9 100644 --- a/lib-rdmsubdevice/.cproject +++ b/lib-rdmsubdevice/.cproject @@ -30,11 +30,9 @@ - diff --git a/lib-rdmsubdevice/Makefile.GD32 b/lib-rdmsubdevice/Makefile.GD32 index 09035619..d190dcc0 100644 --- a/lib-rdmsubdevice/Makefile.GD32 +++ b/lib-rdmsubdevice/Makefile.GD32 @@ -1,7 +1,8 @@ DEFINES=NDEBUG -EXTRA_INCLUDES=../lib-rdm/include ../lib-lightset/include ../lib-properties/include +EXTRA_INCLUDES= EXTRA_SRCDIR= +include Rules.mk include ../firmware-template-gd32/lib/Rules.mk diff --git a/lib-rdmsubdevice/Rules.mk b/lib-rdmsubdevice/Rules.mk new file mode 100755 index 00000000..9b5ba69b --- /dev/null +++ b/lib-rdmsubdevice/Rules.mk @@ -0,0 +1,18 @@ +EXTRA_INCLUDES+=../lib-rdm/include ../lib-lightset/include ../lib-properties/include + +ifneq ($(MAKE_FLAGS),) + ifeq ($(findstring CONFIG_RDM_ENABLE_SUBDEVICES,$(MAKE_FLAGS)), CONFIG_RDM_ENABLE_SUBDEVICES) + ifeq ($(findstring CONFIG_RDM_SUBDEVICES_USE_SPI,$(MAKE_FLAGS)), CONFIG_RDM_SUBDEVICES_USE_SPI) + EXTRA_SRCDIR+=src/spi + endif + ifeq ($(findstring CONFIG_RDM_SUBDEVICES_USE_I2C,$(MAKE_FLAGS)), CONFIG_RDM_SUBDEVICES_USE_I2C) + EXTRA_SRCDIR+=src/i2c + endif + endif + ifneq (,$(findstring CONFIG_STORE_USE_ROM,$(MAKE_FLAGS))) + EXTRA_INCLUDES+=../lib-flashcode/include + endif +else + DEFINES+=CONFIG_RDM_ENABLE_SUBDEVICES CONFIG_RDM_SUBDEVICES_USE_I2C CONFIG_RDM_SUBDEVICES_USE_SPI + EXTRA_SRCDIR+=src/i2c src/spi +endif \ No newline at end of file diff --git a/lib-rdmsubdevice/include/rdm _subdevices.h b/lib-rdmsubdevice/include/rdm _subdevices.h new file mode 100755 index 00000000..4dfe27f3 --- /dev/null +++ b/lib-rdmsubdevice/include/rdm _subdevices.h @@ -0,0 +1,43 @@ +/** + * @file rdm_subdevices.h + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef RDM_SUBDEVICES_H_ +#define RDM_SUBDEVICES_H_ + +namespace rdm { +namespace subdevices { +enum class Types { + BW7FETS, BWDIMMER, BWDIO, BWLCD, BWRELAY, // BitWizard + MCP23S08, MCP23S17, // GPIO + MCP4822, MCP4902, // DAC + UNDEFINED +}; + +const char* get_type_string(rdm::subdevices::Types type); +rdm::subdevices::Types get_type_string(const char *pValue); +} // namespace subdevices +} // namespace rdm + +#endif /* RDM_SUBDEVICES_H_ */ diff --git a/lib-rdmsubdevice/include/rdmsubdevice.h b/lib-rdmsubdevice/include/rdmsubdevice.h deleted file mode 100644 index fd76abd0..00000000 --- a/lib-rdmsubdevice/include/rdmsubdevice.h +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @file rdmsubdevice.h - * - */ -/* Copyright (C) 2018-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef RDMSUBDEVICE_H_ -#define RDMSUBDEVICE_H_ - -#include "rdmdevice.h" -#include "rdmpersonality.h" - -struct TRDMSubDevicesInfo { - uint16_t dmx_footprint; - uint16_t dmx_start_address; - uint8_t current_personality; - uint8_t personality_count; - char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH]; - uint8_t nLabelLength; - uint8_t sensor_count; -}; - -enum TRDMSubDeviceUpdateEvent { - RDM_SUBDEVICE_UPDATE_EVENT_DMX_STARTADDRESS, - RDM_SUBDEVICE_UPDATE_EVENT_PERSONALITY -}; - -class RDMSubDevice { -public: - RDMSubDevice(const char* pLabel, uint16_t nDmxStartAddress = 1, uint8_t PersonalitynCurrent = 1); - virtual ~RDMSubDevice(); - - void SetDmxStartAddress(uint16_t nDmxStartAddress); - - uint16_t GetDmxStartAddress() const { - return m_tSubDevicesInfo.dmx_start_address; - } - - uint8_t GetPersonalityCurrent() const { - return m_tSubDevicesInfo.current_personality; - } - void SetPersonalityCurrent(uint8_t nCurrent); - - void GetLabel(struct TRDMDeviceInfoData *pInfoData); - void SetLabel(const char *pLabel); - void SetLabel(const char *pLabel, uint8_t nLabelLength); - - struct TRDMSubDevicesInfo* GetInfo() { - return &m_tSubDevicesInfo; - } - - RDMPersonality* GetPersonality(uint8_t nPersonality); - - uint8_t GetPersonalityCount() const { - return m_tSubDevicesInfo.personality_count; - } - - uint16_t GetDmxFootPrint() const { - return m_tSubDevicesInfo.dmx_footprint; - } - - bool GetFactoryDefaults(); - void SetFactoryDefaults(); - - virtual bool Initialize()=0; - - virtual void Start()= 0; - virtual void Stop()= 0; - virtual void Data(const uint8_t *pDdata, uint32_t nLength)=0; - -protected: - void SetDmxFootprint(uint16_t nDmxFootprint); - void SetPersonalities(RDMPersonality **pRDMPersonalities, uint8_t nPersonalityCount); - -private: - virtual void UpdateEvent(TRDMSubDeviceUpdateEvent tUpdateEvent); - uint16_t CalculateChecksum(); - -private: - RDMPersonality **m_pRDMPersonalities { nullptr }; - bool m_IsFactoryDefaults { true }; - uint16_t m_nCheckSum { 0 }; - uint16_t m_nDmxStartAddressFactoryDefault; - uint8_t m_nCurrentPersonalityFactoryDefault; - TRDMSubDevicesInfo m_tSubDevicesInfo; - char m_aLabelFactoryDefault[RDM_DEVICE_LABEL_MAX_LENGTH]; -}; - -#endif /* RDMSUBDEVICE_H_ */ diff --git a/lib-rdmsubdevice/include/rdmsubdevices.h b/lib-rdmsubdevice/include/rdmsubdevices.h deleted file mode 100644 index e080bfd4..00000000 --- a/lib-rdmsubdevice/include/rdmsubdevices.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @file rdmsubdevices.h - * - */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef RDMSUBDEVICES_H_ -#define RDMSUBDEVICES_H_ - -#include - -#include "rdmsubdevice.h" -#include "rdmsubdevicesconst.h" - -#include "rdmpersonality.h" - -#if defined (NODE_RDMNET_LLRP_ONLY) -# undef ENABLE_RDM_SUBDEVICES -#endif - -namespace rdm { -namespace subdevices { -static constexpr auto MAX = 8; -static constexpr auto STORE = 96; ///< Configuration store in bytes -} // namespace subdevices -} // namespace rdm - -class RDMSubDevices { -public: - RDMSubDevices(); - ~RDMSubDevices(); - - bool Add(RDMSubDevice *pRDMSubDevice); - - uint16_t GetCount() const { - return m_nCount; - } - - TRDMSubDevicesInfo *GetInfo(uint16_t nSubDevice); - - uint16_t GetDmxFootPrint(uint16_t nSubDevice); - - RDMPersonality* GetPersonality(uint16_t nSubDevice , uint8_t nPersonality); - uint8_t GetPersonalityCount(uint16_t nSubDevice); - uint8_t GetPersonalityCurrent(uint16_t nSubDevice); - void SetPersonalityCurrent(uint16_t nSubDevice, uint8_t nPersonality); - - // E120_DEVICE_LABEL 0x0082 - void GetLabel(uint16_t nSubDevice, TRDMDeviceInfoData *pInfoData); - void SetLabel(uint16_t nSubDevice, const char *pLabel, uint8_t nLabelLength); - - // E120_FACTORY_DEFAULTS 0x0090 - bool GetFactoryDefaults(); - void SetFactoryDefaults(); - - // E120_DMX_START_ADDRESS 0x00F0 - uint16_t GetDmxStartAddress(uint16_t nSubDevice); - void SetDmxStartAddress(uint16_t nSubDevice, uint16_t nDmxStartAddress); - - void Start(); - void Stop(); - void SetData(const uint8_t *pData, uint32_t nLength); - - static const char *GetTypeString(rdm::subdevices::Types tType); - static rdm::subdevices::Types GetTypeString(const char *pValue); - - static RDMSubDevices* Get() { - return s_pThis; - } - -private: - RDMSubDevice **m_pRDMSubDevice { nullptr }; - uint16_t m_nCount { 0 }; - - static RDMSubDevices *s_pThis; -}; - -#endif /* RDMSUBDEVICES_H_ */ diff --git a/lib-rdmsubdevice/include/rdmsubdevicesconst.h b/lib-rdmsubdevice/include/rdmsubdevicesconst.h old mode 100644 new mode 100755 index 847e1e9a..3a234529 --- a/lib-rdmsubdevice/include/rdmsubdevicesconst.h +++ b/lib-rdmsubdevice/include/rdmsubdevicesconst.h @@ -26,22 +26,8 @@ #ifndef RDMSUBDEVICESCONST_H_ #define RDMSUBDEVICESCONST_H_ -#include - -namespace rdm { -namespace subdevices { -enum class Types { - BW7FETS, BWDIMMER, BWDIO, BWLCD, BWRELAY, // BitWizard - MCP23S08, MCP23S17, // GPIO - MCP4822, MCP4902, // DAC - UNDEFINED -}; -} // namespace subdevices -} // namespace rdm - struct RDMSubDevicesConst { static const char PARAMS_FILE_NAME[]; - static const char TYPE[static_cast(rdm::subdevices::Types::UNDEFINED)][9]; }; #endif /* RDMSUBDEVICESCONST_H_ */ diff --git a/lib-rdmsubdevice/include/rdmsubdevicesparams.h b/lib-rdmsubdevice/include/rdmsubdevicesparams.h index 92d3f30f..4906ee86 100644 --- a/lib-rdmsubdevice/include/rdmsubdevicesparams.h +++ b/lib-rdmsubdevice/include/rdmsubdevicesparams.h @@ -29,6 +29,7 @@ #include #include "rdmsubdevices.h" +#include "configstore.h" namespace rdm { namespace subdevicesparams { @@ -50,41 +51,37 @@ static_assert(sizeof(struct Params) <= rdm::subdevices::STORE, "struct Params is class RDMSubDevicesParamsStore { public: - virtual ~RDMSubDevicesParamsStore() {} + static void Update(const rdm::subdevicesparams::Params *pParams) { + ConfigStore::Get()->Update(configstore::Store::RDMSUBDEVICES, pParams, sizeof(struct rdm::subdevicesparams::Params)); + } - virtual void Update(const rdm::subdevicesparams::Params *pParams)=0; - virtual void Copy(rdm::subdevicesparams::Params *pParams)=0; + static void Copy(rdm::subdevicesparams::Params *pParams) { + ConfigStore::Get()->Copy(configstore::Store::RDMSUBDEVICES, pParams, sizeof(struct rdm::subdevicesparams::Params)); + } }; class RDMSubDevicesParams { public: - RDMSubDevicesParams(RDMSubDevicesParamsStore *pRDMSubDevicesParamsStore); + RDMSubDevicesParams(); - bool Load(); + void Load(); void Load(const char *pBuffer, uint32_t nLength); void Builder(const rdm::subdevicesparams::Params *pParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); void Save(char *pBuffer, uint32_t nLength, uint32_t& nSize) { - if (m_pRDMSubDevicesParamsStore == nullptr) { - nSize = 0; - return; - } - Builder(nullptr, pBuffer, nLength, nSize); } - void Dump(); - void Set(); static void staticCallbackFunction(void *p, const char *s); private: + void Dump(); void callbackFunction(const char *pLine); bool Add(RDMSubDevice *pRDMSubDevice); private: - RDMSubDevicesParamsStore *m_pRDMSubDevicesParamsStore; rdm::subdevicesparams::Params m_Params; }; diff --git a/lib-rdmsubdevice/include/rdmsubdevicebw7fets.h b/lib-rdmsubdevice/include/spi/rdmsubdevicebw7fets.h similarity index 100% rename from lib-rdmsubdevice/include/rdmsubdevicebw7fets.h rename to lib-rdmsubdevice/include/spi/rdmsubdevicebw7fets.h diff --git a/lib-rdmsubdevice/include/rdmsubdevicebwdimmer.h b/lib-rdmsubdevice/include/spi/rdmsubdevicebwdimmer.h similarity index 100% rename from lib-rdmsubdevice/include/rdmsubdevicebwdimmer.h rename to lib-rdmsubdevice/include/spi/rdmsubdevicebwdimmer.h diff --git a/lib-rdmsubdevice/include/rdmsubdevicebwdio.h b/lib-rdmsubdevice/include/spi/rdmsubdevicebwdio.h similarity index 100% rename from lib-rdmsubdevice/include/rdmsubdevicebwdio.h rename to lib-rdmsubdevice/include/spi/rdmsubdevicebwdio.h diff --git a/lib-rdmsubdevice/include/rdmsubdevicebwlcd.h b/lib-rdmsubdevice/include/spi/rdmsubdevicebwlcd.h similarity index 97% rename from lib-rdmsubdevice/include/rdmsubdevicebwlcd.h rename to lib-rdmsubdevice/include/spi/rdmsubdevicebwlcd.h index 9e16a2c4..62bb4676 100644 --- a/lib-rdmsubdevice/include/rdmsubdevicebwlcd.h +++ b/lib-rdmsubdevice/include/spi/rdmsubdevicebwlcd.h @@ -2,7 +2,7 @@ * @file rdmsubdevicebwlcd.h * */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-rdmsubdevice/include/rdmsubdevicebwrelay.h b/lib-rdmsubdevice/include/spi/rdmsubdevicebwrelay.h similarity index 100% rename from lib-rdmsubdevice/include/rdmsubdevicebwrelay.h rename to lib-rdmsubdevice/include/spi/rdmsubdevicebwrelay.h diff --git a/lib-rdmsubdevice/include/rdmsubdevicemcp23s08.h b/lib-rdmsubdevice/include/spi/rdmsubdevicemcp23s08.h similarity index 100% rename from lib-rdmsubdevice/include/rdmsubdevicemcp23s08.h rename to lib-rdmsubdevice/include/spi/rdmsubdevicemcp23s08.h diff --git a/lib-rdmsubdevice/include/rdmsubdevicemcp23s17.h b/lib-rdmsubdevice/include/spi/rdmsubdevicemcp23s17.h similarity index 100% rename from lib-rdmsubdevice/include/rdmsubdevicemcp23s17.h rename to lib-rdmsubdevice/include/spi/rdmsubdevicemcp23s17.h diff --git a/lib-rdmsubdevice/include/rdmsubdevicemcp4822.h b/lib-rdmsubdevice/include/spi/rdmsubdevicemcp4822.h similarity index 96% rename from lib-rdmsubdevice/include/rdmsubdevicemcp4822.h rename to lib-rdmsubdevice/include/spi/rdmsubdevicemcp4822.h index 7b4ef6b7..08690386 100644 --- a/lib-rdmsubdevice/include/rdmsubdevicemcp4822.h +++ b/lib-rdmsubdevice/include/spi/rdmsubdevicemcp4822.h @@ -2,7 +2,7 @@ * @file rdmsubdevicemcp4822.h * */ -/* Copyright (C) 2020-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-rdmsubdevice/include/rdmsubdevicemcp4902.h b/lib-rdmsubdevice/include/spi/rdmsubdevicemcp4902.h similarity index 96% rename from lib-rdmsubdevice/include/rdmsubdevicemcp4902.h rename to lib-rdmsubdevice/include/spi/rdmsubdevicemcp4902.h index d11ef53c..b81a79e7 100644 --- a/lib-rdmsubdevice/include/rdmsubdevicemcp4902.h +++ b/lib-rdmsubdevice/include/spi/rdmsubdevicemcp4902.h @@ -2,7 +2,7 @@ * @file rdmsubdevicemcp4902.h * */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-rdmsubdevice/src/rdm_subdevices.cpp b/lib-rdmsubdevice/src/rdm_subdevices.cpp new file mode 100755 index 00000000..dfe423dd --- /dev/null +++ b/lib-rdmsubdevice/src/rdm_subdevices.cpp @@ -0,0 +1,61 @@ +/** + * @file rdm_subdevices.cpp + * + */ +/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "rdm _subdevices.h" + +namespace rdm { +namespace subdevices { +static constexpr char TYPE[static_cast(rdm::subdevices::Types::UNDEFINED)][9] = { + "bw7fets", "bwdimmer", "bwdio", "bwlcd", "bwrelay", + "mcp23s08", "mcp23s17", + "mcp4822", "mcp4902" }; + + +const char* get_type_string(rdm::subdevices::Types type) { + if (type < rdm::subdevices::Types::UNDEFINED) { + return TYPE[static_cast(type)]; + } + + return "Unknown"; +} + +rdm::subdevices::Types get_type_string(const char *pValue) { + assert(pValue != nullptr); + + for (uint32_t i = 0; i < static_cast(rdm::subdevices::Types::UNDEFINED); i++) { + if (strcasecmp(pValue, TYPE[i]) == 0) { + return static_cast(i); + } + } + + return rdm::subdevices::Types::UNDEFINED; +} +} // namespace subdevices +} // namespace rdm + diff --git a/lib-rdmsubdevice/src/rdmsubdevice.cpp b/lib-rdmsubdevice/src/rdmsubdevice.cpp deleted file mode 100644 index 829eed5c..00000000 --- a/lib-rdmsubdevice/src/rdmsubdevice.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/** - * @file rdmsubdevice.cpp - * - */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "rdmsubdevice.h" - -RDMSubDevice::RDMSubDevice(const char* pLabel, uint16_t nDmxStartAddress, uint8_t nPersonalityCurrent): - - m_nDmxStartAddressFactoryDefault(nDmxStartAddress), - m_nCurrentPersonalityFactoryDefault(nPersonalityCurrent) -{ - for (uint32_t i = 0; (i < RDM_DEVICE_LABEL_MAX_LENGTH) && pLabel[i] != 0; i++) { - m_aLabelFactoryDefault[i] = pLabel[i]; - } - - SetLabel(pLabel); - - m_tSubDevicesInfo.dmx_start_address = nDmxStartAddress; - m_tSubDevicesInfo.current_personality = nPersonalityCurrent; - - m_tSubDevicesInfo.sensor_count = 0; - m_tSubDevicesInfo.personality_count = 0; - - m_nCheckSum = CalculateChecksum(); -} - -RDMSubDevice::~RDMSubDevice() { -} - -void RDMSubDevice::SetDmxStartAddress(uint16_t nDmxStartAddress) { - m_tSubDevicesInfo.dmx_start_address = nDmxStartAddress; - UpdateEvent(RDM_SUBDEVICE_UPDATE_EVENT_DMX_STARTADDRESS); -} - -void RDMSubDevice::SetDmxFootprint(uint16_t nDmxFootprint) { - m_tSubDevicesInfo.dmx_footprint = nDmxFootprint; -} - -void RDMSubDevice::SetPersonalities(RDMPersonality **pRDMPersonalities, uint8_t nPersonalityCount) { - assert(pRDMPersonalities != nullptr); - - m_tSubDevicesInfo.personality_count = nPersonalityCount; - m_pRDMPersonalities = pRDMPersonalities; - - UpdateEvent(RDM_SUBDEVICE_UPDATE_EVENT_PERSONALITY); -} - -RDMPersonality* RDMSubDevice::GetPersonality(uint8_t nPersonality) { - assert(nPersonality != 0); - assert(nPersonality <= m_tSubDevicesInfo.personality_count); - - return m_pRDMPersonalities[nPersonality - 1]; -} - -void RDMSubDevice::GetLabel(struct TRDMDeviceInfoData* pInfoData) { - assert(pInfoData != nullptr); - - pInfoData->data = m_tSubDevicesInfo.aLabel; - pInfoData->length = m_tSubDevicesInfo.nLabelLength; -} - -void RDMSubDevice::SetLabel(const char *pLabel) { - assert(pLabel != nullptr); - uint32_t i; - - for (i = 0; (i < RDM_DEVICE_LABEL_MAX_LENGTH) && (pLabel[i] != 0); i++) { - m_tSubDevicesInfo.aLabel[i] = pLabel[i]; - } - - m_tSubDevicesInfo.nLabelLength = static_cast(i); -} - -void RDMSubDevice::SetLabel(const char *pLabel, uint8_t nLabelLength) { - assert(pLabel != nullptr); - uint32_t i; - - for (i = 0; (i < RDM_DEVICE_LABEL_MAX_LENGTH) && (i < nLabelLength); i++) { - m_tSubDevicesInfo.aLabel[i] = pLabel[i]; - } - - m_tSubDevicesInfo.nLabelLength = static_cast(i); -} - -void RDMSubDevice::SetPersonalityCurrent(uint8_t nCurrent) { - m_tSubDevicesInfo.current_personality = nCurrent; -} - -bool RDMSubDevice::GetFactoryDefaults() { - if (m_IsFactoryDefaults) { - if (m_nCheckSum != CalculateChecksum()) { - m_IsFactoryDefaults = false; - } - } - - return m_IsFactoryDefaults; -} - -void RDMSubDevice::SetFactoryDefaults() { - if (m_IsFactoryDefaults) { - return; - } - - SetLabel(m_aLabelFactoryDefault); - - m_tSubDevicesInfo.dmx_start_address = m_nDmxStartAddressFactoryDefault; - m_tSubDevicesInfo.current_personality = m_nCurrentPersonalityFactoryDefault; - - m_IsFactoryDefaults = true; -} - -uint16_t RDMSubDevice::CalculateChecksum() { - uint16_t nChecksum = m_tSubDevicesInfo.dmx_start_address; - nChecksum = static_cast(nChecksum + m_tSubDevicesInfo.current_personality); - - for (uint32_t i = 0; i < m_tSubDevicesInfo.nLabelLength; i++) { - nChecksum = static_cast(nChecksum + m_tSubDevicesInfo.aLabel[i]); - } - - return nChecksum; -} - -void RDMSubDevice::UpdateEvent(__attribute__((unused)) TRDMSubDeviceUpdateEvent tUpdateEvent) { - // override -} diff --git a/lib-rdmsubdevice/src/rdmsubdevices.cpp b/lib-rdmsubdevice/src/rdmsubdevices.cpp deleted file mode 100644 index 180cb1c0..00000000 --- a/lib-rdmsubdevice/src/rdmsubdevices.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/** - * @file rdmsubdevices.cpp - * - */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "rdmsubdevices.h" -#include "rdmsubdevice.h" - -#include "rdmsubdevicedummy.h" - -#include "debug.h" - -RDMSubDevices *RDMSubDevices::s_pThis = nullptr; - -RDMSubDevices::RDMSubDevices() { - DEBUG_ENTRY - - assert(s_pThis == nullptr); - s_pThis = this; - -#if defined(ENABLE_RDM_SUBDEVICES) - m_pRDMSubDevice = new RDMSubDevice*[rdm::subdevices::MAX]; - assert(m_pRDMSubDevice != nullptr); - -# ifndef NDEBUG - Add(new RDMSubDeviceDummy); -# endif -#endif - - DEBUG_EXIT -} - -RDMSubDevices::~RDMSubDevices() { - DEBUG_ENTRY - - - for (unsigned i = 0; i < m_nCount; i++) { - delete m_pRDMSubDevice[i]; - m_pRDMSubDevice[i] = nullptr; - } - - delete [] m_pRDMSubDevice; - - m_nCount = 0; - - DEBUG_EXIT -} - -struct TRDMSubDevicesInfo* RDMSubDevices::GetInfo(uint16_t nSubDevice) { - assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); - - assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); - return m_pRDMSubDevice[nSubDevice - 1]->GetInfo(); -} - -void RDMSubDevices::GetLabel(uint16_t nSubDevice, struct TRDMDeviceInfoData* pInfoData) { - assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); - assert(pInfoData != nullptr); - - assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); - m_pRDMSubDevice[nSubDevice - 1]->GetLabel(pInfoData); -} - -void RDMSubDevices::SetLabel(uint16_t nSubDevice, const char *pLabel, uint8_t nLabelLength) { - assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); - assert(pLabel != nullptr); - - assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); - m_pRDMSubDevice[nSubDevice - 1]->SetLabel(pLabel,nLabelLength); -} - - -uint16_t RDMSubDevices::GetDmxStartAddress(uint16_t nSubDevice) { - assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); - - assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); - return m_pRDMSubDevice[nSubDevice - 1]->GetDmxStartAddress(); -} - -void RDMSubDevices::SetDmxStartAddress(uint16_t nSubDevice, uint16_t nDmxStartAddress) { - assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); - - assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); - m_pRDMSubDevice[nSubDevice - 1]->SetDmxStartAddress(nDmxStartAddress); -} - -uint16_t RDMSubDevices::GetDmxFootPrint(uint16_t nSubDevice) { - assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); - - assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); - return m_pRDMSubDevice[nSubDevice - 1]->GetDmxFootPrint(); -} - -uint8_t RDMSubDevices::GetPersonalityCurrent(uint16_t nSubDevice) { - assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); - - assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); - return m_pRDMSubDevice[nSubDevice - 1]->GetPersonalityCurrent(); -} - -void RDMSubDevices::SetPersonalityCurrent(uint16_t nSubDevice, uint8_t nPersonality) { - assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); - - assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); - m_pRDMSubDevice[nSubDevice - 1]->SetPersonalityCurrent(nPersonality); -} - -uint8_t RDMSubDevices::GetPersonalityCount(uint16_t nSubDevice) { - assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); - - assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); - return m_pRDMSubDevice[nSubDevice - 1]->GetPersonalityCount(); -} - -RDMPersonality* RDMSubDevices::GetPersonality(uint16_t nSubDevice, uint8_t nPersonality) { - assert((nSubDevice != 0) && (nSubDevice <= m_nCount)); - - assert(m_pRDMSubDevice[nSubDevice - 1] != nullptr); - return m_pRDMSubDevice[nSubDevice - 1]->GetPersonality(nPersonality); -} - -void RDMSubDevices::Start() { - DEBUG_ENTRY - - for (uint32_t i = 0; i < m_nCount; i++) { - if (m_pRDMSubDevice[i] != nullptr) { - m_pRDMSubDevice[i]->Start(); - } - } - - DEBUG_EXIT -} - -void RDMSubDevices::Stop() { - DEBUG_ENTRY - - for (uint32_t i = 0; i < m_nCount; i++) { - if (m_pRDMSubDevice[i] != nullptr) { - m_pRDMSubDevice[i]->Stop(); - } - } - - DEBUG_ENTRY -} - -void RDMSubDevices::SetData(const uint8_t* pData, uint32_t nLength) { - for (unsigned i = 0; i < m_nCount; i++) { - if (m_pRDMSubDevice[i] != nullptr) { - if (nLength >= (static_cast(m_pRDMSubDevice[i]->GetDmxStartAddress() + m_pRDMSubDevice[i]->GetDmxFootPrint()) - 1U)) { - m_pRDMSubDevice[i]->Data(pData, nLength); - } - } - } -} - -bool RDMSubDevices::GetFactoryDefaults() { - for (uint32_t i = 0; i < m_nCount; i++) { - if (m_pRDMSubDevice[i] != nullptr) { - if (!m_pRDMSubDevice[i]->GetFactoryDefaults()) { - return false; - } - } - } - - return true; -} - -void RDMSubDevices::SetFactoryDefaults() { - for (uint32_t i = 0; i < m_nCount; i++) { - if (m_pRDMSubDevice[i] != nullptr) { - m_pRDMSubDevice[i]->SetFactoryDefaults(); - } - } -} - -const char* RDMSubDevices::GetTypeString(rdm::subdevices::Types type) { - if (type < rdm::subdevices::Types::UNDEFINED) { - return RDMSubDevicesConst::TYPE[static_cast(type)]; - } - - return "Unknown"; -} - -rdm::subdevices::Types RDMSubDevices::GetTypeString(const char *pValue) { - assert(pValue != nullptr); - - for (uint32_t i = 0; i < static_cast(rdm::subdevices::Types::UNDEFINED); i++) { - if (strcasecmp(pValue, RDMSubDevicesConst::TYPE[i]) == 0) { - return static_cast(i); - } - } - - return rdm::subdevices::Types::UNDEFINED; -} diff --git a/lib-rdmsubdevice/src/rdmsubdevicesconst.cpp b/lib-rdmsubdevice/src/rdmsubdevicesconst.cpp index 8fded33f..0890ef36 100644 --- a/lib-rdmsubdevice/src/rdmsubdevicesconst.cpp +++ b/lib-rdmsubdevice/src/rdmsubdevicesconst.cpp @@ -29,8 +29,5 @@ const char RDMSubDevicesConst::PARAMS_FILE_NAME[] = "subdev.txt"; -const char RDMSubDevicesConst::TYPE[static_cast(rdm::subdevices::Types::UNDEFINED)][9] = { - "bw7fets", "bwdimmer", "bwdio", "bwlcd", "bwrelay", - "mcp23s08", "mcp23s17", - "mcp4822", "mcp4902" }; + diff --git a/lib-rdmsubdevice/src/rdmsubdevicesparams.cpp b/lib-rdmsubdevice/src/rdmsubdevicesparams.cpp index 96ac9167..82bdb0e9 100644 --- a/lib-rdmsubdevice/src/rdmsubdevicesparams.cpp +++ b/lib-rdmsubdevice/src/rdmsubdevicesparams.cpp @@ -2,7 +2,7 @@ * @file rdmsubdevicesparams.cpp * */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,30 +35,34 @@ #include "rdmsubdevicesparams.h" #include "rdmsubdevices.h" +#include "rdmsubdevicesconst.h" +#include "rdm _subdevices.h" #include "readconfigfile.h" #include "sscan.h" #include "propertiesbuilder.h" -#if defined(ENABLE_RDM_SUBDEVICES) -# include "rdmsubdevicebw7fets.h" -# include "rdmsubdevicebwdimmer.h" -# include "rdmsubdevicebwdio.h" -# include "rdmsubdevicebwlcd.h" -# include "rdmsubdevicebwrelay.h" -// -# include "rdmsubdevicemcp23s08.h" -# include "rdmsubdevicemcp23s17.h" -// -# include "rdmsubdevicemcp4822.h" -# include "rdmsubdevicemcp4902.h" +#if defined(CONFIG_RDM_ENABLE_SUBDEVICES) +# if defined(CONFIG_RDM_SUBDEVICES_USE_SPI) +# include "spi/rdmsubdevicebw7fets.h" +# include "spi/rdmsubdevicebwdimmer.h" +# include "spi/rdmsubdevicebwdio.h" +# include "spi/rdmsubdevicebwlcd.h" +# include "spi/rdmsubdevicebwrelay.h" +# include "spi/rdmsubdevicemcp23s08.h" +# include "spi/rdmsubdevicemcp23s17.h" +# include "spi/rdmsubdevicemcp4822.h" +# include "spi/rdmsubdevicemcp4902.h" +# endif +# if defined(CONFIG_RDM_SUBDEVICES_USE_I2C) +# endif #endif #include "debug.h" using namespace rdm::subdevices; -RDMSubDevicesParams::RDMSubDevicesParams(RDMSubDevicesParamsStore *pRDMSubDevicesParamsStore): m_pRDMSubDevicesParamsStore(pRDMSubDevicesParamsStore) { +RDMSubDevicesParams::RDMSubDevicesParams() { DEBUG_ENTRY memset(&m_Params, 0, sizeof(struct rdm::subdevicesparams::Params)); @@ -66,7 +70,7 @@ RDMSubDevicesParams::RDMSubDevicesParams(RDMSubDevicesParamsStore *pRDMSubDevice DEBUG_EXIT } -bool RDMSubDevicesParams::Load() { +void RDMSubDevicesParams::Load() { DEBUG_ENTRY m_Params.nCount = 0; @@ -75,24 +79,21 @@ bool RDMSubDevicesParams::Load() { ReadConfigFile configfile(RDMSubDevicesParams::staticCallbackFunction, this); if (configfile.Read(RDMSubDevicesConst::PARAMS_FILE_NAME)) { - if (m_pRDMSubDevicesParamsStore != nullptr) { - m_pRDMSubDevicesParamsStore->Update(&m_Params); - } + RDMSubDevicesParamsStore::Update(&m_Params); + } else #endif - if (m_pRDMSubDevicesParamsStore != nullptr) { - m_pRDMSubDevicesParamsStore->Copy(&m_Params); - // Sanity check - if (m_Params.nCount >= rdm::subdevices::MAX) { - memset(&m_Params, 0, sizeof(struct rdm::subdevicesparams::Params)); - } - } else { - DEBUG_EXIT - return false; + RDMSubDevicesParamsStore::Copy(&m_Params); + + // Sanity check + if (m_Params.nCount >= rdm::subdevices::MAX) { + memset(&m_Params, 0, sizeof(struct rdm::subdevicesparams::Params)); } +#ifndef NDEBUG + Dump(); +#endif DEBUG_EXIT - return true; } void RDMSubDevicesParams::Load(const char *pBuffer, uint32_t nLength) { @@ -100,12 +101,8 @@ void RDMSubDevicesParams::Load(const char *pBuffer, uint32_t nLength) { assert(pBuffer != nullptr); assert(nLength != 0); - assert(m_pRDMSubDevicesParamsStore != nullptr); - if (m_pRDMSubDevicesParamsStore == nullptr) { - DEBUG_EXIT - return; - } + debug_dump(pBuffer, nLength); m_Params.nCount = 0; @@ -113,8 +110,11 @@ void RDMSubDevicesParams::Load(const char *pBuffer, uint32_t nLength) { config.Read(pBuffer, nLength); - m_pRDMSubDevicesParamsStore->Update(&m_Params); + RDMSubDevicesParamsStore::Update(&m_Params); +#ifndef NDEBUG + Dump(); +#endif DEBUG_EXIT } @@ -126,28 +126,24 @@ void RDMSubDevicesParams::Builder(const rdm::subdevicesparams::Params *pParams, if (pParams != nullptr) { memcpy(&m_Params, pParams, sizeof(struct rdm::subdevicesparams::Params)); } else { - assert(m_pRDMSubDevicesParamsStore != nullptr); - m_pRDMSubDevicesParamsStore->Copy(&m_Params); + RDMSubDevicesParamsStore::Copy(&m_Params); } PropertiesBuilder builder(RDMSubDevicesConst::PARAMS_FILE_NAME, pBuffer, nLength); + for (uint32_t nCount = 0; nCount < m_Params.nCount; nCount++) { + char buffer[32]; + const auto *p = &m_Params.Entry[nCount]; + snprintf(buffer, sizeof(buffer) - 1, "%u,%s,%u,%u,%u", p->nChipSelect, rdm::subdevices::get_type_string(static_cast(p->nType)), p->nAddress, p->nDmxStartAddress, static_cast(p->nSpeedHz)); + builder.AddRaw(buffer); + } + nSize = builder.GetSize(); DEBUG_PRINTF("nSize=%d", nSize); DEBUG_EXIT } -void RDMSubDevicesParams::Dump() { -#ifndef NDEBUG - printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, RDMSubDevicesConst::PARAMS_FILE_NAME); - - for (uint32_t i = 0; i < m_Params.nCount; i++) { - printf(" %s 0x%.2x\n", RDMSubDevices::GetTypeString(static_cast(m_Params.Entry[i].nType)), m_Params.Entry[i].nAddress); - } -#endif -} - bool RDMSubDevicesParams::Add(RDMSubDevice *pRDMSubDevice) { DEBUG_ENTRY @@ -164,14 +160,16 @@ bool RDMSubDevicesParams::Add(RDMSubDevice *pRDMSubDevice) { } void RDMSubDevicesParams::Set() { -#if defined(ENABLE_RDM_SUBDEVICES) +#if defined(CONFIG_RDM_ENABLE_SUBDEVICES) for (uint32_t i = 0; i < m_Params.nCount; i++) { +# if defined(CONFIG_RDM_SUBDEVICES_USE_SPI) || defined(CONFIG_RDM_SUBDEVICES_USE_I2C) const auto nChipSelect = m_Params.Entry[i].nChipSelect; const auto nAddress = m_Params.Entry[i].nAddress; const auto nDmxStartAddress = m_Params.Entry[i].nDmxStartAddress; const auto nSpeedHz = m_Params.Entry[i].nSpeedHz; - +# endif switch (static_cast(m_Params.Entry[i].nType)) { +# if defined(CONFIG_RDM_SUBDEVICES_USE_SPI) case Types::BW7FETS: Add(new RDMSubDeviceBw7fets(nDmxStartAddress, nChipSelect, nAddress, nSpeedHz)); break; @@ -199,6 +197,9 @@ void RDMSubDevicesParams::Set() { case Types::MCP4902: Add(new RDMSubDeviceMCP4902(nDmxStartAddress, nChipSelect, nAddress, nSpeedHz)); break; +# endif +# if defined(CONFIG_RDM_SUBDEVICES_USE_I2C) +# endif default: break; } @@ -209,6 +210,8 @@ void RDMSubDevicesParams::Set() { void RDMSubDevicesParams::callbackFunction(const char *pLine) { assert(pLine != nullptr); + DEBUG_PUTS(pLine); + char aSubDeviceName[32]; memset(aSubDeviceName, 0, sizeof(aSubDeviceName)); @@ -220,12 +223,14 @@ void RDMSubDevicesParams::callbackFunction(const char *pLine) { const auto nReturnCode = Sscan::Spi(pLine, nChipSelect, aSubDeviceName, nLength, nAddress, nDmxStartAddress, nSpeedHz); + DEBUG_PRINTF("nReturnCode=%u", static_cast(nReturnCode)); + if ((nReturnCode == Sscan::OK) && (aSubDeviceName[0] != 0) && (nLength != 0)) { DEBUG_PRINTF("{%.*s}:%d, nChipSelect=%d, nAddress=%d, nDmxStartAddress=%d, nSpeedHz=%d", nLength, aSubDeviceName, static_cast(nLength), nChipSelect, nAddress, nDmxStartAddress, nSpeedHz); Types subDeviceType; - if ((subDeviceType = RDMSubDevices::GetTypeString(aSubDeviceName)) == Types::UNDEFINED) { + if ((subDeviceType = rdm::subdevices::get_type_string(aSubDeviceName)) == Types::UNDEFINED) { return; } @@ -258,3 +263,11 @@ void RDMSubDevicesParams::staticCallbackFunction(void *p, const char *s) { (static_cast(p))->callbackFunction(s); } + +void RDMSubDevicesParams::Dump() { + printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, RDMSubDevicesConst::PARAMS_FILE_NAME); + + for (uint32_t i = 0; i < m_Params.nCount; i++) { + printf(" %s 0x%.2x\n", rdm::subdevices::get_type_string(static_cast(m_Params.Entry[i].nType)), m_Params.Entry[i].nAddress); + } +} diff --git a/lib-rdmsubdevice/src/spi/rdmsubdevicebw7fets.cpp b/lib-rdmsubdevice/src/spi/rdmsubdevicebw7fets.cpp index 5bb41654..28f25b90 100644 --- a/lib-rdmsubdevice/src/spi/rdmsubdevicebw7fets.cpp +++ b/lib-rdmsubdevice/src/spi/rdmsubdevicebw7fets.cpp @@ -26,14 +26,14 @@ #include #include -#include "rdmsubdevicebw7fets.h" +#include "spi/rdmsubdevicebw7fets.h" #include "bwspi7fets.h" static constexpr uint32_t DMX_FOOTPRINT = 7; static RDMPersonality *s_RDMPersonalities[] = {new RDMPersonality("Digital output 7-lines", DMX_FOOTPRINT)}; -RDMSubDeviceBw7fets::RDMSubDeviceBw7fets(uint16_t nDmxStartAddress, char nChipSselect, uint8_t nSlaveAddress, __attribute__((unused)) uint32_t nSpiSpeed) : +RDMSubDeviceBw7fets::RDMSubDeviceBw7fets(uint16_t nDmxStartAddress, char nChipSselect, uint8_t nSlaveAddress, [[maybe_unused]] uint32_t nSpiSpeed) : RDMSubDevice("bw_spi_7fets", nDmxStartAddress), m_BwSpi7fets(nChipSselect, nSlaveAddress) { SetDmxFootprint(DMX_FOOTPRINT); diff --git a/lib-rdmsubdevice/src/spi/rdmsubdevicebwdimmer.cpp b/lib-rdmsubdevice/src/spi/rdmsubdevicebwdimmer.cpp index 1bb886c5..bf752946 100644 --- a/lib-rdmsubdevice/src/spi/rdmsubdevicebwdimmer.cpp +++ b/lib-rdmsubdevice/src/spi/rdmsubdevicebwdimmer.cpp @@ -26,14 +26,14 @@ #include #include -#include "rdmsubdevicebwdimmer.h" +#include "spi/rdmsubdevicebwdimmer.h" #include "bwspidimmer.h" static constexpr uint32_t DMX_FOOTPRINT = 1; static RDMPersonality *s_RDMPersonalities[] = {new RDMPersonality("Dimmer", DMX_FOOTPRINT)}; -RDMSubDeviceBwDimmer::RDMSubDeviceBwDimmer(uint16_t nDmxStartAddress, char nChipSselect, uint8_t nSlaveAddress, __attribute__((unused)) uint32_t nSpiSpeed) : +RDMSubDeviceBwDimmer::RDMSubDeviceBwDimmer(uint16_t nDmxStartAddress, char nChipSselect, uint8_t nSlaveAddress, [[maybe_unused]] uint32_t nSpiSpeed) : RDMSubDevice("bw_spi_dimmer", nDmxStartAddress), m_BwSpiDimmer(nChipSselect, nSlaveAddress) { SetDmxFootprint(DMX_FOOTPRINT); diff --git a/lib-rdmsubdevice/src/spi/rdmsubdevicebwdio.cpp b/lib-rdmsubdevice/src/spi/rdmsubdevicebwdio.cpp index d7319a5f..9e8c7e74 100644 --- a/lib-rdmsubdevice/src/spi/rdmsubdevicebwdio.cpp +++ b/lib-rdmsubdevice/src/spi/rdmsubdevicebwdio.cpp @@ -1,4 +1,3 @@ -#if defined (BARE_METAL) || defined (RASPPI) /** * @file rdmsubdevicebwdio.cpp * @@ -27,14 +26,14 @@ #include #include -#include "rdmsubdevicebwdio.h" +#include "spi/rdmsubdevicebwdio.h" #include "bwspidio.h" static constexpr uint32_t DMX_FOOTPRINT = 7; static RDMPersonality *s_RDMPersonalities[] = {new RDMPersonality("Digital output 7-lines", DMX_FOOTPRINT)}; -RDMSubDeviceBwDio::RDMSubDeviceBwDio(uint16_t nDmxStartAddress, char nChipSselect, uint8_t nSlaveAddress, __attribute__((unused)) uint32_t nSpiSpeed) : +RDMSubDeviceBwDio::RDMSubDeviceBwDio(uint16_t nDmxStartAddress, char nChipSselect, uint8_t nSlaveAddress, [[maybe_unused]] uint32_t nSpiSpeed) : RDMSubDevice("bw_spi_dio", nDmxStartAddress), m_BwSpiDio(nChipSselect, nSlaveAddress) { SetDmxFootprint(DMX_FOOTPRINT); @@ -62,4 +61,3 @@ void RDMSubDeviceBwDio::UpdateEvent(TRDMSubDeviceUpdateEvent tUpdateEvent) { Stop(); } } -#endif diff --git a/lib-rdmsubdevice/src/spi/rdmsubdevicebwlcd.cpp b/lib-rdmsubdevice/src/spi/rdmsubdevicebwlcd.cpp index 19af5bd1..f5350b66 100644 --- a/lib-rdmsubdevice/src/spi/rdmsubdevicebwlcd.cpp +++ b/lib-rdmsubdevice/src/spi/rdmsubdevicebwlcd.cpp @@ -1,4 +1,3 @@ -#if defined (BARE_METAL) || defined (RASPPI) /** * @file rdmsubdevicebwlcd.cpp * @@ -30,7 +29,7 @@ #include "cstdio" -#include "rdmsubdevicebwlcd.h" +#include "spi/rdmsubdevicebwlcd.h" #include "bwspilcd.h" @@ -42,7 +41,7 @@ static constexpr uint32_t DMX_FOOTPRINT = 4; static RDMPersonality *s_RDMPersonalities[] = {new RDMPersonality("LCD 4-slots H", DMX_FOOTPRINT), new RDMPersonality("LCD 4-slots D", DMX_FOOTPRINT), new RDMPersonality("LCD 4-slots %%", DMX_FOOTPRINT)}; static constexpr char s_aLine[bw::lcd::max_characters + 1] = "--- --- --- --- "; -RDMSubDeviceBwLcd::RDMSubDeviceBwLcd(uint16_t nDmxStartAddress, char nChipSselect, uint8_t nSlaveAddress, __attribute__((unused)) uint32_t nSpiSpeed): +RDMSubDeviceBwLcd::RDMSubDeviceBwLcd(uint16_t nDmxStartAddress, char nChipSselect, uint8_t nSlaveAddress, [[maybe_unused]] uint32_t nSpiSpeed): RDMSubDevice("bw_spi_lcd", nDmxStartAddress), m_BwSpiLcd(nChipSselect, nSlaveAddress) { SetDmxFootprint(DMX_FOOTPRINT); @@ -271,4 +270,3 @@ void RDMSubDeviceBwLcd::DisplayUpdatePersonality() { break; } } -#endif diff --git a/lib-rdmsubdevice/src/spi/rdmsubdevicebwrelay.cpp b/lib-rdmsubdevice/src/spi/rdmsubdevicebwrelay.cpp index 795c2a1a..26416bf4 100644 --- a/lib-rdmsubdevice/src/spi/rdmsubdevicebwrelay.cpp +++ b/lib-rdmsubdevice/src/spi/rdmsubdevicebwrelay.cpp @@ -1,4 +1,3 @@ -#if defined (BARE_METAL) || defined (RASPPI) /** * @file rdmsubdevicebwrelay.cpp * @@ -27,14 +26,14 @@ #include #include -#include "rdmsubdevicebwrelay.h" +#include "spi/rdmsubdevicebwrelay.h" #include "bwspirelay.h" static constexpr uint32_t DMX_FOOTPRINT = 2; static RDMPersonality *s_RDMPersonalities[] = {new RDMPersonality("Relays", DMX_FOOTPRINT)}; -RDMSubDeviceBwRelay::RDMSubDeviceBwRelay(uint16_t nDmxStartAddress, char nChipSselect, uint8_t nSlaveAddress, __attribute__((unused)) uint32_t nSpiSpeed) : +RDMSubDeviceBwRelay::RDMSubDeviceBwRelay(uint16_t nDmxStartAddress, char nChipSselect, uint8_t nSlaveAddress, [[maybe_unused]] uint32_t nSpiSpeed) : RDMSubDevice("bw_spi_relay", nDmxStartAddress), m_BwSpiRelay(nChipSselect, nSlaveAddress) { SetDmxFootprint(DMX_FOOTPRINT); @@ -62,4 +61,3 @@ void RDMSubDeviceBwRelay::UpdateEvent(TRDMSubDeviceUpdateEvent tUpdateEvent) { Stop(); } } -#endif diff --git a/lib-rdmsubdevice/src/spi/rdmsubdevicemcp23s08.cpp b/lib-rdmsubdevice/src/spi/rdmsubdevicemcp23s08.cpp index 98d5c295..976b41b6 100644 --- a/lib-rdmsubdevice/src/spi/rdmsubdevicemcp23s08.cpp +++ b/lib-rdmsubdevice/src/spi/rdmsubdevicemcp23s08.cpp @@ -26,7 +26,7 @@ #include #include -#include "rdmsubdevicemcp23s08.h" +#include "spi/rdmsubdevicemcp23s08.h" #include "mcp23s08.h" diff --git a/lib-rdmsubdevice/src/spi/rdmsubdevicemcp23s17.cpp b/lib-rdmsubdevice/src/spi/rdmsubdevicemcp23s17.cpp index 4e225906..127485a1 100644 --- a/lib-rdmsubdevice/src/spi/rdmsubdevicemcp23s17.cpp +++ b/lib-rdmsubdevice/src/spi/rdmsubdevicemcp23s17.cpp @@ -26,7 +26,7 @@ #include #include -#include "rdmsubdevicemcp23s17.h" +#include "spi/rdmsubdevicemcp23s17.h" #include "mcp23s17.h" diff --git a/lib-rdmsubdevice/src/spi/rdmsubdevicemcp4822.cpp b/lib-rdmsubdevice/src/spi/rdmsubdevicemcp4822.cpp index 2813bfd8..20a1e33c 100644 --- a/lib-rdmsubdevice/src/spi/rdmsubdevicemcp4822.cpp +++ b/lib-rdmsubdevice/src/spi/rdmsubdevicemcp4822.cpp @@ -30,14 +30,14 @@ * MCP4822: Dual 12-Bit Voltage Output DAC */ -#include "rdmsubdevicemcp4822.h" +#include "spi/rdmsubdevicemcp4822.h" #include "mcp48x2.h" static constexpr uint32_t DMX_FOOTPRINT = 2; static RDMPersonality *s_RDMPersonalities[] = {new RDMPersonality("Analog output 2-lines", DMX_FOOTPRINT)}; -RDMSubDeviceMCP4822::RDMSubDeviceMCP4822(uint16_t nDmxStartAddress, char nChipSselect, __attribute__((unused)) uint8_t nSlaveAddress, uint32_t nSpiSpeed): +RDMSubDeviceMCP4822::RDMSubDeviceMCP4822(uint16_t nDmxStartAddress, char nChipSselect, [[maybe_unused]] uint8_t nSlaveAddress, uint32_t nSpiSpeed): RDMSubDevice("mcp4822", nDmxStartAddress), m_MCP4822(nChipSselect, nSpiSpeed) { SetDmxFootprint(DMX_FOOTPRINT); diff --git a/lib-rdmsubdevice/src/spi/rdmsubdevicemcp4902.cpp b/lib-rdmsubdevice/src/spi/rdmsubdevicemcp4902.cpp index 3a8ab478..811e5de7 100644 --- a/lib-rdmsubdevice/src/spi/rdmsubdevicemcp4902.cpp +++ b/lib-rdmsubdevice/src/spi/rdmsubdevicemcp4902.cpp @@ -30,14 +30,14 @@ * MCP4902: Dual 8-Bit Voltage Output DAC */ -#include "rdmsubdevicemcp4902.h" +#include "spi/rdmsubdevicemcp4902.h" #include "mcp49x2.h" static constexpr uint32_t DMX_FOOTPRINT = 2; static RDMPersonality *s_RDMPersonalities[] = {new RDMPersonality("Analog output 2-lines", DMX_FOOTPRINT)}; -RDMSubDeviceMCP4902::RDMSubDeviceMCP4902(uint16_t nDmxStartAddress, char nChipSselect, __attribute__((unused)) uint8_t nSlaveAddress, uint32_t nSpiSpeed) : +RDMSubDeviceMCP4902::RDMSubDeviceMCP4902(uint16_t nDmxStartAddress, char nChipSselect, [[maybe_unused]] uint8_t nSlaveAddress, uint32_t nSpiSpeed) : RDMSubDevice("mcp4902",nDmxStartAddress), m_MCP4902(nChipSselect, nSpiSpeed) { SetDmxFootprint(DMX_FOOTPRINT); diff --git a/lib-remoteconfig/.cproject b/lib-remoteconfig/.cproject index b232e775..51fcd4cb 100644 --- a/lib-remoteconfig/.cproject +++ b/lib-remoteconfig/.cproject @@ -30,11 +30,9 @@ - diff --git a/lib-remoteconfig/Makefile.GD32 b/lib-remoteconfig/Makefile.GD32 index 2761a3d3..0a3f2559 100644 --- a/lib-remoteconfig/Makefile.GD32 +++ b/lib-remoteconfig/Makefile.GD32 @@ -1,5 +1,6 @@ DEFINES =DISABLE_FS DEFINES+=DISABLE_TFTP + DEFINES+=NDEBUG ifneq ($(MAKE_FLAGS),) diff --git a/lib-remoteconfig/Rules.mk b/lib-remoteconfig/Rules.mk old mode 100644 new mode 100755 index feb51f0f..edf9ee70 --- a/lib-remoteconfig/Rules.mk +++ b/lib-remoteconfig/Rules.mk @@ -1,13 +1,17 @@ $(info $$MAKE_FLAGS [${MAKE_FLAGS}]) -EXTRA_INCLUDES=../lib-hal/include ../lib-network/include ../lib-properties/include ../lib-display/include ../lib-lightset/include ../lib-configstore/include -EXTRA_INCLUDES+=../lib-flash/include ../lib-flashcode/include ../lib-flashcodeinstall/include +EXTRA_INCLUDES=../lib-network/include ../lib-properties/include ../lib-display/include ../lib-lightset/include +EXTRA_INCLUDES+=../lib-flashcode/include ../lib-flashcodeinstall/include ifneq ($(MAKE_FLAGS),) ifneq (,$(findstring ENABLE_HTTPD,$(MAKE_FLAGS))) EXTRA_SRCDIR+=src/httpd endif + ifneq (,$(findstring ENABLE_SHELL,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=src/shell src/uart + endif + ifeq ($(findstring NODE_ARTNET,$(MAKE_FLAGS)), NODE_ARTNET) EXTRA_INCLUDES+=../lib-artnet/include ifeq ($(findstring ARTNET_VERSION=4,$(MAKE_FLAGS)), ARTNET_VERSION=4) @@ -25,13 +29,28 @@ ifneq ($(MAKE_FLAGS),) ifeq ($(findstring NODE_LTC_SMPTE,$(MAKE_FLAGS)), NODE_LTC_SMPTE) EXTRA_INCLUDES+=../lib-ltc/include ../lib-tcnet/include ../lib-gps/include ../lib-midi/include EXTRA_INCLUDES+=../lib-rgbpanel/include ../lib-ws28xx/include - EXTRA_INCLUDES+=../lib-device/include endif ifeq ($(findstring NODE_OSC_CLIENT,$(MAKE_FLAGS)), NODE_OSC_CLIENT) - EXTRA_INCLUDES+=../lib-oscclient/include + EXTRA_INCLUDES+=../lib-osc/include endif ifeq ($(findstring NODE_OSC_SERVER,$(MAKE_FLAGS)), NODE_OSC_SERVER) - EXTRA_INCLUDES+=../lib-oscserver/include + EXTRA_INCLUDES+=../lib-osc/include + endif + ifeq ($(findstring NODE_SHOWFILE,$(MAKE_FLAGS)), NODE_SHOWFILE) + EXTRA_INCLUDES+=../lib-showfile/include + ifeq ($(findstring CONFIG_SHOWFILE_ENABLE_OSC,$(MAKE_FLAGS)), CONFIG_SHOWFILE_ENABLE_OSC) + EXTRA_INCLUDES+=../lib-osc/include + endif + ifeq ($(findstring CONFIG_SHOWFILE_PROTOCOL_E131,$(MAKE_FLAGS)), CONFIG_SHOWFILE_PROTOCOL_E131) + EXTRA_INCLUDES+=../lib-e131/include + endif + ifeq ($(findstring CONFIG_SHOWFILE_PROTOCOL_ARTNET,$(MAKE_FLAGS)), CONFIG_SHOWFILE_PROTOCOL_ARTNET) + EXTRA_INCLUDES+=../lib-artnet/include + endif + endif + + ifeq ($(findstring RDM_CONTROLLER,$(MAKE_FLAGS)), RDM_CONTROLLER) + EXTRA_INCLUDES+=../lib-rdm/include ../lib-dmx/include endif ifeq ($(findstring RDM_RESPONDER,$(MAKE_FLAGS)), RDM_RESPONDER) @@ -67,8 +86,12 @@ ifneq ($(MAKE_FLAGS),) ifeq ($(findstring OUTPUT_DMX_SHOWFILE,$(MAKE_FLAGS)), OUTPUT_DMX_SHOWFILE) EXTRA_INCLUDES+=../lib-showfile/include endif + ifeq ($(findstring OUTPUT_DMX_PCA9685,$(MAKE_FLAGS)), OUTPUT_DMX_PCA9685) + EXTRA_INCLUDES+=../lib-pca9685dmx/include ../lib-pca9685/include + endif else EXTRA_SRCDIR+=src/httpd + DEFINES+=ENABLE_CONTENT EXTRA_INCLUDES+=../lib-artnet/include ../lib-e131/include EXTRA_INCLUDES+=../lib-rdmdiscovery/include @@ -82,11 +105,15 @@ else EXTRA_INCLUDES+=../lib-ws28xxdmx/include ../lib-ws28xx/include EXTRA_INCLUDES+=../lib-tlc59711dmx/include ../lib-tlc59711/include EXTRA_INCLUDES+=../lib-dmxserial/include + EXTRA_INCLUDES+=../lib-pca9685dmx/include ../lib-pca9685/include EXTRA_INCLUDES+=../lib-midi/include EXTRA_INCLUDES+=../lib-rdmresponder/include ../lib-rdm/include EXTRA_INCLUDES+=../lib-rdmsensor/include ../lib-rdmsubdevice/include EXTRA_INCLUDES+=../lib-showfile/include EXTRA_INCLUDES+=../lib-dmxmonitor/include - EXTRA_INCLUDES+=../lib-device/include - EXTRA_INCLUDES+=../lib-oscclient/include ../lib-oscserver/include + EXTRA_INCLUDES+=../lib-osc/include + + DEFINES+=ARTNET_VERSION=4 + DEFINES+=RDM_CONTROLLER ENABLE_NET_PHYSTATUS CONFIG_USB_HOST_MSC ENABLE_PHY_SWITCH + DEFINES+=NODE_SHOWFILE CONFIG_SHOWFILE_FORMAT_OLA CONFIG_SHOWFILE_PROTOCOL_E131 endif diff --git a/lib-remoteconfig/http/content/Makefile b/lib-remoteconfig/http/content/Makefile index 38f00e4e..e13be575 100755 --- a/lib-remoteconfig/http/content/Makefile +++ b/lib-remoteconfig/http/content/Makefile @@ -7,15 +7,15 @@ LD = $(PREFIX)ld AR = $(PREFIX)ar ROOT = ./../../.. -INCLUDES := -I$(ROOT)/lib-network/include -I$(ROOT)/lib-remoteconfig/include +INCLUDES := -I$(ROOT)/lib-hal/include -I$(ROOT)/lib-network/include -I$(ROOT)/lib-remoteconfig/include -I$(ROOT)/lib-configstore/include -I$(ROOT)/lib-debug/include COPS := -std=c++11 -Wall -Werror all : content generate_json_switch clean : - rm generate_content - rm generate_json_switch - rm *.h + rm -rf generate_content + rm -rf generate_json_switch + rm -rf *.h generate_content : Makefile generate_content.cpp $(CPP) generate_content.cpp $(INCLUDES) $(COPS) -o generate_content diff --git a/lib-remoteconfig/http/content/content.h b/lib-remoteconfig/http/content/content.h index ed189abe..6625a8bc 100644 --- a/lib-remoteconfig/http/content/content.h +++ b/lib-remoteconfig/http/content/content.h @@ -5,16 +5,47 @@ #include "httpd/httpd.h" +#if !defined (CONFIG_HTTP_HTML_NO_DMX) && (defined(OUTPUT_DMX_SEND) || defined(OUTPUT_DMX_SEND_MULTI)) +# include "dmx.js.h" +#endif /* !defined (CONFIG_HTTP_HTML_NO_DMX) && (defined(OUTPUT_DMX_SEND) || defined(OUTPUT_DMX_SEND_MULTI)) */ +#if !defined (CONFIG_HTTP_HTML_NO_RTC) && !defined (DISABLE_RTC) +# include "rtc.html.h" +#endif /* !defined (CONFIG_HTTP_HTML_NO_RTC) && !defined (DISABLE_RTC) */ #include "static.js.h" #include "styles.css.h" #include "index.js.h" +#include "date.js.h" #if defined (ENABLE_PHY_SWITCH) -#include "dsa.js.h" +# include "dsa.js.h" #endif /* (ENABLE_PHY_SWITCH) */ +#if defined (NODE_SHOWFILE) +# include "showfile.html.h" +#endif /* (NODE_SHOWFILE) */ #include "default.js.h" +#if !defined (CONFIG_HTTP_HTML_NO_RTC) && !defined (DISABLE_RTC) +# include "rtc.js.h" +#endif /* !defined (CONFIG_HTTP_HTML_NO_RTC) && !defined (DISABLE_RTC) */ +#if !defined (CONFIG_HTTP_HTML_NO_RDM) && defined (RDM_CONTROLLER) +# include "rdm.js.h" +#endif /* !defined (CONFIG_HTTP_HTML_NO_RDM) && defined (RDM_CONTROLLER) */ +#if !defined (CONFIG_HTTP_HTML_NO_TIME) +# include "time.js.h" +#endif /* !defined (CONFIG_HTTP_HTML_NO_TIME) */ +#if !defined (CONFIG_HTTP_HTML_NO_RDM) && defined (RDM_CONTROLLER) +# include "rdm.html.h" +#endif /* !defined (CONFIG_HTTP_HTML_NO_RDM) && defined (RDM_CONTROLLER) */ #include "index.html.h" +#if defined (NODE_SHOWFILE) +# include "showfile.js.h" +#endif /* (NODE_SHOWFILE) */ +#if !defined (CONFIG_HTTP_HTML_NO_TIME) +# include "time.html.h" +#endif /* !defined (CONFIG_HTTP_HTML_NO_TIME) */ +#if !defined (CONFIG_HTTP_HTML_NO_DMX) && (defined(OUTPUT_DMX_SEND) || defined(OUTPUT_DMX_SEND_MULTI)) +# include "dmx.html.h" +#endif /* !defined (CONFIG_HTTP_HTML_NO_DMX) && (defined(OUTPUT_DMX_SEND) || defined(OUTPUT_DMX_SEND_MULTI)) */ #if defined (ENABLE_PHY_SWITCH) -#include "dsa.html.h" +# include "dsa.html.h" #endif /* (ENABLE_PHY_SWITCH) */ struct FilesContent { @@ -25,14 +56,45 @@ struct FilesContent { }; static constexpr struct FilesContent HttpContent[] = { - { "static.js", static_js, 1065, static_cast(2) }, +#if !defined (CONFIG_HTTP_HTML_NO_DMX) && (defined(OUTPUT_DMX_SEND) || defined(OUTPUT_DMX_SEND_MULTI)) + { "dmx.js", dmx_js, 1361, static_cast(2) }, +#endif /* !defined (CONFIG_HTTP_HTML_NO_DMX) && (defined(OUTPUT_DMX_SEND) || defined(OUTPUT_DMX_SEND_MULTI)) */ +#if !defined (CONFIG_HTTP_HTML_NO_RTC) && !defined (DISABLE_RTC) + { "rtc.html", rtc_html, 1013, static_cast(0) }, +#endif /* !defined (CONFIG_HTTP_HTML_NO_RTC) && !defined (DISABLE_RTC) */ + { "static.js", static_js, 1219, static_cast(2) }, { "styles.css", styles_css, 409, static_cast(1) }, { "index.js", index_js, 1140, static_cast(2) }, + { "date.js", date_js, 716, static_cast(2) }, #if defined (ENABLE_PHY_SWITCH) - { "dsa.js", dsa_js, 405, static_cast(2) }, + { "dsa.js", dsa_js, 613, static_cast(2) }, #endif /* (ENABLE_PHY_SWITCH) */ +#if defined (NODE_SHOWFILE) + { "showfile.html", showfile_html, 1305, static_cast(0) }, +#endif /* (NODE_SHOWFILE) */ { "default.js", default_js, 254, static_cast(2) }, +#if !defined (CONFIG_HTTP_HTML_NO_RTC) && !defined (DISABLE_RTC) + { "rtc.js", rtc_js, 843, static_cast(2) }, +#endif /* !defined (CONFIG_HTTP_HTML_NO_RTC) && !defined (DISABLE_RTC) */ +#if !defined (CONFIG_HTTP_HTML_NO_RDM) && defined (RDM_CONTROLLER) + { "rdm.js", rdm_js, 991, static_cast(2) }, +#endif /* !defined (CONFIG_HTTP_HTML_NO_RDM) && defined (RDM_CONTROLLER) */ +#if !defined (CONFIG_HTTP_HTML_NO_TIME) + { "time.js", time_js, 390, static_cast(2) }, +#endif /* !defined (CONFIG_HTTP_HTML_NO_TIME) */ +#if !defined (CONFIG_HTTP_HTML_NO_RDM) && defined (RDM_CONTROLLER) + { "rdm.html", rdm_html, 1142, static_cast(0) }, +#endif /* !defined (CONFIG_HTTP_HTML_NO_RDM) && defined (RDM_CONTROLLER) */ { "index.html", index_html, 669, static_cast(0) }, +#if defined (NODE_SHOWFILE) + { "showfile.js", showfile_js, 1425, static_cast(2) }, +#endif /* (NODE_SHOWFILE) */ +#if !defined (CONFIG_HTTP_HTML_NO_TIME) + { "time.html", time_html, 599, static_cast(0) }, +#endif /* !defined (CONFIG_HTTP_HTML_NO_TIME) */ +#if !defined (CONFIG_HTTP_HTML_NO_DMX) && (defined(OUTPUT_DMX_SEND) || defined(OUTPUT_DMX_SEND_MULTI)) + { "dmx.html", dmx_html, 538, static_cast(0) }, +#endif /* !defined (CONFIG_HTTP_HTML_NO_DMX) && (defined(OUTPUT_DMX_SEND) || defined(OUTPUT_DMX_SEND_MULTI)) */ #if defined (ENABLE_PHY_SWITCH) { "dsa.html", dsa_html, 447, static_cast(0) }, #endif /* (ENABLE_PHY_SWITCH) */ diff --git a/lib-remoteconfig/http/content/date.js b/lib-remoteconfig/http/content/date.js new file mode 100755 index 00000000..2c1ede40 --- /dev/null +++ b/lib-remoteconfig/http/content/date.js @@ -0,0 +1,18 @@ +function formatDateTime(date) { + const year = date.getFullYear(); + const mon = ('0' + (date.getMonth() + 1)).slice(-2); + const day = ('0' + date.getDate()).slice(-2); + const hour = ('0' + date.getHours()).slice(-2); + const min = ('0' + date.getMinutes()).slice(-2); + const sec = ('0' + date.getSeconds()).slice(-2); + const offset = date.getTimezoneOffset(); + const offsetHour = ('0' + Math.floor(Math.abs(offset) / 60)).slice(-2); + const offsetMin = ('0' + Math.abs(offset) % 60).slice(-2); + const sign = offset <= 0 ? '+' : '-'; + + if ((offsetHour == 0) && (offsetMin == 0)) { + return `${year}-${mon}-${day}T${hour}:${min}:${sec}Z`; + } + + return `${year}-${mon}-${day}T${hour}:${min}:${sec}${sign}${offsetHour}:${offsetMin}`; +} \ No newline at end of file diff --git a/lib-remoteconfig/http/content/date.js.h b/lib-remoteconfig/http/content/date.js.h new file mode 100644 index 00000000..47b9c51b --- /dev/null +++ b/lib-remoteconfig/http/content/date.js.h @@ -0,0 +1,47 @@ +static constexpr char date_js[] = { +0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x44, +0x61, 0x74, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x28, 0x64, 0x61, 0x74, 0x65, 0x29, 0x20, 0x7B, 0x0A, +0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x79, 0x65, 0x61, 0x72, 0x20, 0x3D, 0x20, 0x64, 0x61, 0x74, +0x65, 0x2E, 0x67, 0x65, 0x74, 0x46, 0x75, 0x6C, 0x6C, 0x59, 0x65, 0x61, 0x72, 0x28, 0x29, 0x3B, +0x0A, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x6D, 0x6F, 0x6E, 0x20, 0x3D, 0x20, 0x28, 0x27, 0x30, +0x27, 0x20, 0x2B, 0x20, 0x28, 0x64, 0x61, 0x74, 0x65, 0x2E, 0x67, 0x65, 0x74, 0x4D, 0x6F, 0x6E, +0x74, 0x68, 0x28, 0x29, 0x20, 0x2B, 0x20, 0x31, 0x29, 0x29, 0x2E, 0x73, 0x6C, 0x69, 0x63, 0x65, +0x28, 0x2D, 0x32, 0x29, 0x3B, 0x0A, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x64, 0x61, 0x79, 0x20, +0x3D, 0x20, 0x28, 0x27, 0x30, 0x27, 0x20, 0x2B, 0x20, 0x64, 0x61, 0x74, 0x65, 0x2E, 0x67, 0x65, +0x74, 0x44, 0x61, 0x74, 0x65, 0x28, 0x29, 0x29, 0x2E, 0x73, 0x6C, 0x69, 0x63, 0x65, 0x28, 0x2D, +0x32, 0x29, 0x3B, 0x0A, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x68, 0x6F, 0x75, 0x72, 0x20, 0x3D, +0x20, 0x28, 0x27, 0x30, 0x27, 0x20, 0x2B, 0x20, 0x64, 0x61, 0x74, 0x65, 0x2E, 0x67, 0x65, 0x74, +0x48, 0x6F, 0x75, 0x72, 0x73, 0x28, 0x29, 0x29, 0x2E, 0x73, 0x6C, 0x69, 0x63, 0x65, 0x28, 0x2D, +0x32, 0x29, 0x3B, 0x0A, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x6D, 0x69, 0x6E, 0x20, 0x3D, 0x20, +0x28, 0x27, 0x30, 0x27, 0x20, 0x2B, 0x20, 0x64, 0x61, 0x74, 0x65, 0x2E, 0x67, 0x65, 0x74, 0x4D, +0x69, 0x6E, 0x75, 0x74, 0x65, 0x73, 0x28, 0x29, 0x29, 0x2E, 0x73, 0x6C, 0x69, 0x63, 0x65, 0x28, +0x2D, 0x32, 0x29, 0x3B, 0x0A, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x73, 0x65, 0x63, 0x20, 0x3D, +0x20, 0x28, 0x27, 0x30, 0x27, 0x20, 0x2B, 0x20, 0x64, 0x61, 0x74, 0x65, 0x2E, 0x67, 0x65, 0x74, +0x53, 0x65, 0x63, 0x6F, 0x6E, 0x64, 0x73, 0x28, 0x29, 0x29, 0x2E, 0x73, 0x6C, 0x69, 0x63, 0x65, +0x28, 0x2D, 0x32, 0x29, 0x3B, 0x0A, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x6F, 0x66, 0x66, 0x73, +0x65, 0x74, 0x20, 0x3D, 0x20, 0x64, 0x61, 0x74, 0x65, 0x2E, 0x67, 0x65, 0x74, 0x54, 0x69, 0x6D, +0x65, 0x7A, 0x6F, 0x6E, 0x65, 0x4F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x28, 0x29, 0x3B, 0x0A, 0x63, +0x6F, 0x6E, 0x73, 0x74, 0x20, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x48, 0x6F, 0x75, 0x72, 0x20, +0x3D, 0x20, 0x28, 0x27, 0x30, 0x27, 0x20, 0x2B, 0x20, 0x4D, 0x61, 0x74, 0x68, 0x2E, 0x66, 0x6C, +0x6F, 0x6F, 0x72, 0x28, 0x4D, 0x61, 0x74, 0x68, 0x2E, 0x61, 0x62, 0x73, 0x28, 0x6F, 0x66, 0x66, +0x73, 0x65, 0x74, 0x29, 0x20, 0x2F, 0x20, 0x36, 0x30, 0x29, 0x29, 0x2E, 0x73, 0x6C, 0x69, 0x63, +0x65, 0x28, 0x2D, 0x32, 0x29, 0x3B, 0x0A, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x6F, 0x66, 0x66, +0x73, 0x65, 0x74, 0x4D, 0x69, 0x6E, 0x20, 0x3D, 0x20, 0x28, 0x27, 0x30, 0x27, 0x20, 0x2B, 0x20, +0x4D, 0x61, 0x74, 0x68, 0x2E, 0x61, 0x62, 0x73, 0x28, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x29, +0x20, 0x25, 0x20, 0x36, 0x30, 0x29, 0x2E, 0x73, 0x6C, 0x69, 0x63, 0x65, 0x28, 0x2D, 0x32, 0x29, +0x3B, 0x0A, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x20, 0x3D, 0x20, 0x6F, +0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3C, 0x3D, 0x20, 0x30, 0x20, 0x3F, 0x20, 0x27, 0x2B, 0x27, +0x20, 0x3A, 0x20, 0x27, 0x2D, 0x27, 0x3B, 0x0A, 0x69, 0x66, 0x20, 0x28, 0x28, 0x6F, 0x66, 0x66, +0x73, 0x65, 0x74, 0x48, 0x6F, 0x75, 0x72, 0x20, 0x3D, 0x3D, 0x20, 0x30, 0x29, 0x20, 0x26, 0x26, +0x20, 0x28, 0x6F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x4D, 0x69, 0x6E, 0x20, 0x3D, 0x3D, 0x20, 0x30, +0x29, 0x29, 0x20, 0x7B, 0x0A, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x60, 0x24, 0x7B, 0x79, +0x65, 0x61, 0x72, 0x7D, 0x2D, 0x24, 0x7B, 0x6D, 0x6F, 0x6E, 0x7D, 0x2D, 0x24, 0x7B, 0x64, 0x61, +0x79, 0x7D, 0x54, 0x24, 0x7B, 0x68, 0x6F, 0x75, 0x72, 0x7D, 0x3A, 0x24, 0x7B, 0x6D, 0x69, 0x6E, +0x7D, 0x3A, 0x24, 0x7B, 0x73, 0x65, 0x63, 0x7D, 0x5A, 0x60, 0x3B, 0x20, 0x20, 0x0A, 0x7D, 0x20, +0x0A, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x60, 0x24, 0x7B, 0x79, 0x65, 0x61, 0x72, 0x7D, +0x2D, 0x24, 0x7B, 0x6D, 0x6F, 0x6E, 0x7D, 0x2D, 0x24, 0x7B, 0x64, 0x61, 0x79, 0x7D, 0x54, 0x24, +0x7B, 0x68, 0x6F, 0x75, 0x72, 0x7D, 0x3A, 0x24, 0x7B, 0x6D, 0x69, 0x6E, 0x7D, 0x3A, 0x24, 0x7B, +0x73, 0x65, 0x63, 0x7D, 0x24, 0x7B, 0x73, 0x69, 0x67, 0x6E, 0x7D, 0x24, 0x7B, 0x6F, 0x66, 0x66, +0x73, 0x65, 0x74, 0x48, 0x6F, 0x75, 0x72, 0x7D, 0x3A, 0x24, 0x7B, 0x6F, 0x66, 0x66, 0x73, 0x65, +0x74, 0x4D, 0x69, 0x6E, 0x7D, 0x60, 0x3B, 0x20, 0x20, 0x20, 0x0A, 0x7D, 0x00 +}; diff --git a/lib-remoteconfig/http/content/dmx.html b/lib-remoteconfig/http/content/dmx.html new file mode 100755 index 00000000..86a3a0fe --- /dev/null +++ b/lib-remoteconfig/http/content/dmx.html @@ -0,0 +1,14 @@ + + +DMX + +
    +

    +
    +
    +
      + + + + + \ No newline at end of file diff --git a/lib-remoteconfig/http/content/dmx.html.h b/lib-remoteconfig/http/content/dmx.html.h new file mode 100644 index 00000000..e8f84a88 --- /dev/null +++ b/lib-remoteconfig/http/content/dmx.html.h @@ -0,0 +1,36 @@ +static constexpr char dmx_html[] = { +0x3C, 0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A, +0x3C, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x3C, 0x6C, 0x69, +0x6E, 0x6B, 0x20, 0x72, 0x65, 0x6C, 0x3D, 0x22, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x73, 0x68, 0x65, +0x65, 0x74, 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3D, 0x22, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x73, +0x2E, 0x63, 0x73, 0x73, 0x22, 0x20, 0x2F, 0x3E, 0x3C, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0x44, +0x4D, 0x58, 0x3C, 0x2F, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, +0x3E, 0x0A, 0x3C, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0A, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, +0x3E, 0x3C, 0x75, 0x6C, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x69, 0x64, 0x4C, 0x69, 0x73, 0x74, 0x22, +0x3E, 0x3C, 0x2F, 0x75, 0x6C, 0x3E, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3E, 0x0A, +0x3C, 0x70, 0x3E, 0x3C, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, +0x63, 0x6B, 0x3D, 0x22, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, 0x22, 0x3E, 0x52, +0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x3C, 0x2F, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x3E, 0x3C, +0x2F, 0x70, 0x3E, 0x0A, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, +0x73, 0x74, 0x61, 0x74, 0x73, 0x22, 0x3E, 0x3C, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x69, 0x64, +0x3D, 0x22, 0x69, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x22, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, +0x72, 0x3D, 0x27, 0x31, 0x27, 0x3E, 0x3C, 0x2F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x3C, 0x2F, +0x64, 0x69, 0x76, 0x3E, 0x0A, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, +0x22, 0x70, 0x6F, 0x72, 0x74, 0x73, 0x22, 0x3E, 0x3C, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x69, +0x64, 0x3D, 0x22, 0x69, 0x64, 0x50, 0x6F, 0x72, 0x74, 0x73, 0x22, 0x20, 0x62, 0x6F, 0x72, 0x64, +0x65, 0x72, 0x3D, 0x27, 0x31, 0x27, 0x3E, 0x3C, 0x2F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x3C, +0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0A, 0x3C, 0x66, 0x6F, 0x6F, 0x74, 0x65, 0x72, 0x3E, 0x3C, 0x75, +0x6C, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x69, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22, +0x3E, 0x3C, 0x2F, 0x75, 0x6C, 0x3E, 0x3C, 0x2F, 0x66, 0x6F, 0x6F, 0x74, 0x65, 0x72, 0x3E, 0x0A, +0x3C, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, 0x3D, 0x22, 0x73, 0x74, 0x61, +0x74, 0x69, 0x63, 0x2E, 0x6A, 0x73, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x74, 0x65, +0x78, 0x74, 0x2F, 0x6A, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x3E, 0x3C, +0x2F, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, +0x20, 0x73, 0x72, 0x63, 0x3D, 0x22, 0x64, 0x6D, 0x78, 0x2E, 0x6A, 0x73, 0x22, 0x20, 0x74, 0x79, +0x70, 0x65, 0x3D, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x6A, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, +0x69, 0x70, 0x74, 0x22, 0x3E, 0x3C, 0x2F, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, +0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x6C, 0x69, 0x73, 0x74, 0x28, 0x29, 0x3B, 0x76, 0x65, +0x72, 0x73, 0x69, 0x6F, 0x6E, 0x28, 0x29, 0x3B, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, +0x29, 0x3C, 0x2F, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x2F, 0x62, 0x6F, 0x64, +0x79, 0x3E, 0x0A, 0x3C, 0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x00 +}; diff --git a/lib-remoteconfig/http/content/dmx.js b/lib-remoteconfig/http/content/dmx.js new file mode 100755 index 00000000..8393b27f --- /dev/null +++ b/lib-remoteconfig/http/content/dmx.js @@ -0,0 +1,37 @@ +async function refresh() { + try { + let d=await getJSON('dmx/portstatus') + let hdrs='' + let tdd='' + + d.forEach(item => { + hdrs+=`${item.port}` + tdd+=`${item.direction}` + }); + + document.getElementById("idStats").innerHTML=hdrs+''+tdd+'' + + let tr = await Promise.all( + d.map(item => getJSON('dmx/status?' + item.port).then(resp => ({ + port: item.port, + d: { sent: resp.dmx.sent, received: resp.dmx.received }, + r: { + sent: { class: resp.rdm.sent.class, discovery: resp.rdm.sent.discovery }, + received: { good: resp.rdm.received.good, bad: resp.rdm.received.bad, discovery: resp.rdm.received.discovery + }}})))); + + tr.sort((a, b) => { + return d.findIndex(item => item.port === a.port) - d.findIndex(item => item.port === b.port) + }); + + hdrs='PortDMXRDMSentReceivedSentReceivedClassDiscoveryGoodBadDiscovery' + tdd='' + + tr.forEach(p => { + tdd+=`${p.port}${p.d.sent}${p.d.received}${p.r.sent.class}${p.r.sent.discovery}${p.r.received.good}${p.r.received.bad}${p.r.received.discovery}`; + }); + + document.getElementById("idPorts").innerHTML=hdrs+tdd + + } catch (error){} +} \ No newline at end of file diff --git a/lib-remoteconfig/http/content/dmx.js.h b/lib-remoteconfig/http/content/dmx.js.h new file mode 100644 index 00000000..546000ec --- /dev/null +++ b/lib-remoteconfig/http/content/dmx.js.h @@ -0,0 +1,88 @@ +static constexpr char dmx_js[] = { +0x61, 0x73, 0x79, 0x6E, 0x63, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x72, +0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, 0x20, 0x7B, 0x0A, 0x74, 0x72, 0x79, 0x20, 0x7B, +0x0A, 0x6C, 0x65, 0x74, 0x20, 0x64, 0x3D, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x67, 0x65, 0x74, +0x4A, 0x53, 0x4F, 0x4E, 0x28, 0x27, 0x64, 0x6D, 0x78, 0x2F, 0x70, 0x6F, 0x72, 0x74, 0x73, 0x74, +0x61, 0x74, 0x75, 0x73, 0x27, 0x29, 0x0A, 0x6C, 0x65, 0x74, 0x20, 0x68, 0x64, 0x72, 0x73, 0x3D, +0x27, 0x3C, 0x74, 0x72, 0x3E, 0x27, 0x0A, 0x6C, 0x65, 0x74, 0x20, 0x74, 0x64, 0x64, 0x3D, 0x27, +0x3C, 0x74, 0x72, 0x3E, 0x27, 0x0A, 0x64, 0x2E, 0x66, 0x6F, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, +0x69, 0x74, 0x65, 0x6D, 0x20, 0x3D, 0x3E, 0x20, 0x7B, 0x0A, 0x68, 0x64, 0x72, 0x73, 0x2B, 0x3D, +0x60, 0x3C, 0x74, 0x68, 0x3E, 0x24, 0x7B, 0x69, 0x74, 0x65, 0x6D, 0x2E, 0x70, 0x6F, 0x72, 0x74, +0x7D, 0x3C, 0x2F, 0x74, 0x68, 0x3E, 0x60, 0x0A, 0x74, 0x64, 0x64, 0x2B, 0x3D, 0x60, 0x3C, 0x74, +0x64, 0x3E, 0x24, 0x7B, 0x69, 0x74, 0x65, 0x6D, 0x2E, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, +0x6F, 0x6E, 0x7D, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x60, 0x0A, 0x7D, 0x29, 0x3B, 0x0A, 0x64, 0x6F, +0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, +0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x69, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x22, 0x29, +0x2E, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x48, 0x54, 0x4D, 0x4C, 0x3D, 0x68, 0x64, 0x72, 0x73, 0x2B, +0x27, 0x3C, 0x2F, 0x74, 0x72, 0x3E, 0x27, 0x2B, 0x74, 0x64, 0x64, 0x2B, 0x27, 0x3C, 0x2F, 0x74, +0x72, 0x3E, 0x27, 0x0A, 0x6C, 0x65, 0x74, 0x20, 0x74, 0x72, 0x20, 0x3D, 0x20, 0x61, 0x77, 0x61, +0x69, 0x74, 0x20, 0x50, 0x72, 0x6F, 0x6D, 0x69, 0x73, 0x65, 0x2E, 0x61, 0x6C, 0x6C, 0x28, 0x0A, +0x64, 0x2E, 0x6D, 0x61, 0x70, 0x28, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x3D, 0x3E, 0x20, 0x67, 0x65, +0x74, 0x4A, 0x53, 0x4F, 0x4E, 0x28, 0x27, 0x64, 0x6D, 0x78, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x75, +0x73, 0x3F, 0x27, 0x20, 0x2B, 0x20, 0x69, 0x74, 0x65, 0x6D, 0x2E, 0x70, 0x6F, 0x72, 0x74, 0x29, +0x2E, 0x74, 0x68, 0x65, 0x6E, 0x28, 0x72, 0x65, 0x73, 0x70, 0x20, 0x3D, 0x3E, 0x20, 0x28, 0x7B, +0x0A, 0x70, 0x6F, 0x72, 0x74, 0x3A, 0x20, 0x69, 0x74, 0x65, 0x6D, 0x2E, 0x70, 0x6F, 0x72, 0x74, +0x2C, 0x0A, 0x64, 0x3A, 0x20, 0x7B, 0x20, 0x73, 0x65, 0x6E, 0x74, 0x3A, 0x20, 0x72, 0x65, 0x73, +0x70, 0x2E, 0x64, 0x6D, 0x78, 0x2E, 0x73, 0x65, 0x6E, 0x74, 0x2C, 0x20, 0x72, 0x65, 0x63, 0x65, +0x69, 0x76, 0x65, 0x64, 0x3A, 0x20, 0x72, 0x65, 0x73, 0x70, 0x2E, 0x64, 0x6D, 0x78, 0x2E, 0x72, +0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x7D, 0x2C, 0x0A, 0x72, 0x3A, 0x20, 0x7B, 0x0A, +0x73, 0x65, 0x6E, 0x74, 0x3A, 0x20, 0x7B, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3A, 0x20, 0x72, +0x65, 0x73, 0x70, 0x2E, 0x72, 0x64, 0x6D, 0x2E, 0x73, 0x65, 0x6E, 0x74, 0x2E, 0x63, 0x6C, 0x61, +0x73, 0x73, 0x2C, 0x20, 0x64, 0x69, 0x73, 0x63, 0x6F, 0x76, 0x65, 0x72, 0x79, 0x3A, 0x20, 0x72, +0x65, 0x73, 0x70, 0x2E, 0x72, 0x64, 0x6D, 0x2E, 0x73, 0x65, 0x6E, 0x74, 0x2E, 0x64, 0x69, 0x73, +0x63, 0x6F, 0x76, 0x65, 0x72, 0x79, 0x20, 0x7D, 0x2C, 0x0A, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, +0x65, 0x64, 0x3A, 0x20, 0x7B, 0x20, 0x67, 0x6F, 0x6F, 0x64, 0x3A, 0x20, 0x72, 0x65, 0x73, 0x70, +0x2E, 0x72, 0x64, 0x6D, 0x2E, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x2E, 0x67, 0x6F, +0x6F, 0x64, 0x2C, 0x20, 0x62, 0x61, 0x64, 0x3A, 0x20, 0x72, 0x65, 0x73, 0x70, 0x2E, 0x72, 0x64, +0x6D, 0x2E, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x2E, 0x62, 0x61, 0x64, 0x2C, 0x20, +0x64, 0x69, 0x73, 0x63, 0x6F, 0x76, 0x65, 0x72, 0x79, 0x3A, 0x20, 0x72, 0x65, 0x73, 0x70, 0x2E, +0x72, 0x64, 0x6D, 0x2E, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x2E, 0x64, 0x69, 0x73, +0x63, 0x6F, 0x76, 0x65, 0x72, 0x79, 0x0A, 0x7D, 0x7D, 0x7D, 0x29, 0x29, 0x29, 0x29, 0x3B, 0x0A, +0x74, 0x72, 0x2E, 0x73, 0x6F, 0x72, 0x74, 0x28, 0x28, 0x61, 0x2C, 0x20, 0x62, 0x29, 0x20, 0x3D, +0x3E, 0x20, 0x7B, 0x0A, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x64, 0x2E, 0x66, 0x69, 0x6E, +0x64, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x28, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x3D, 0x3E, 0x20, 0x69, +0x74, 0x65, 0x6D, 0x2E, 0x70, 0x6F, 0x72, 0x74, 0x20, 0x3D, 0x3D, 0x3D, 0x20, 0x61, 0x2E, 0x70, +0x6F, 0x72, 0x74, 0x29, 0x20, 0x2D, 0x20, 0x64, 0x2E, 0x66, 0x69, 0x6E, 0x64, 0x49, 0x6E, 0x64, +0x65, 0x78, 0x28, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x3D, 0x3E, 0x20, 0x69, 0x74, 0x65, 0x6D, 0x2E, +0x70, 0x6F, 0x72, 0x74, 0x20, 0x3D, 0x3D, 0x3D, 0x20, 0x62, 0x2E, 0x70, 0x6F, 0x72, 0x74, 0x29, +0x0A, 0x7D, 0x29, 0x3B, 0x0A, 0x68, 0x64, 0x72, 0x73, 0x3D, 0x27, 0x3C, 0x74, 0x72, 0x3E, 0x3C, +0x74, 0x68, 0x20, 0x72, 0x6F, 0x77, 0x73, 0x70, 0x61, 0x6E, 0x3D, 0x22, 0x33, 0x22, 0x3E, 0x50, +0x6F, 0x72, 0x74, 0x3C, 0x2F, 0x74, 0x68, 0x3E, 0x3C, 0x74, 0x68, 0x20, 0x63, 0x6F, 0x6C, 0x73, +0x70, 0x61, 0x6E, 0x3D, 0x22, 0x32, 0x22, 0x3E, 0x44, 0x4D, 0x58, 0x3C, 0x2F, 0x74, 0x68, 0x3E, +0x3C, 0x74, 0x68, 0x20, 0x63, 0x6F, 0x6C, 0x73, 0x70, 0x61, 0x6E, 0x3D, 0x22, 0x35, 0x22, 0x3E, +0x52, 0x44, 0x4D, 0x3C, 0x2F, 0x74, 0x68, 0x3E, 0x3C, 0x2F, 0x74, 0x72, 0x3E, 0x3C, 0x74, 0x72, +0x3E, 0x3C, 0x74, 0x68, 0x20, 0x72, 0x6F, 0x77, 0x73, 0x70, 0x61, 0x6E, 0x3D, 0x22, 0x32, 0x22, +0x3E, 0x53, 0x65, 0x6E, 0x74, 0x3C, 0x2F, 0x74, 0x68, 0x3E, 0x3C, 0x74, 0x68, 0x20, 0x72, 0x6F, +0x77, 0x73, 0x70, 0x61, 0x6E, 0x3D, 0x22, 0x32, 0x22, 0x3E, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, +0x65, 0x64, 0x3C, 0x2F, 0x74, 0x68, 0x3E, 0x3C, 0x74, 0x68, 0x20, 0x63, 0x6F, 0x6C, 0x73, 0x70, +0x61, 0x6E, 0x3D, 0x22, 0x32, 0x22, 0x3E, 0x53, 0x65, 0x6E, 0x74, 0x3C, 0x2F, 0x74, 0x68, 0x3E, +0x3C, 0x74, 0x68, 0x20, 0x63, 0x6F, 0x6C, 0x73, 0x70, 0x61, 0x6E, 0x3D, 0x22, 0x33, 0x22, 0x3E, +0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x3C, 0x2F, 0x74, 0x68, 0x3E, 0x3C, 0x2F, 0x74, +0x72, 0x3E, 0x3C, 0x74, 0x72, 0x3E, 0x3C, 0x74, 0x68, 0x3E, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x3C, +0x2F, 0x74, 0x68, 0x3E, 0x3C, 0x74, 0x68, 0x3E, 0x44, 0x69, 0x73, 0x63, 0x6F, 0x76, 0x65, 0x72, +0x79, 0x3C, 0x2F, 0x74, 0x68, 0x3E, 0x3C, 0x74, 0x68, 0x3E, 0x47, 0x6F, 0x6F, 0x64, 0x3C, 0x2F, +0x74, 0x68, 0x3E, 0x3C, 0x74, 0x68, 0x3E, 0x42, 0x61, 0x64, 0x3C, 0x2F, 0x74, 0x68, 0x3E, 0x3C, +0x74, 0x68, 0x3E, 0x44, 0x69, 0x73, 0x63, 0x6F, 0x76, 0x65, 0x72, 0x79, 0x3C, 0x2F, 0x74, 0x68, +0x3E, 0x3C, 0x2F, 0x74, 0x72, 0x3E, 0x27, 0x0A, 0x74, 0x64, 0x64, 0x3D, 0x27, 0x27, 0x0A, 0x74, +0x72, 0x2E, 0x66, 0x6F, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x70, 0x20, 0x3D, 0x3E, 0x20, 0x7B, +0x0A, 0x74, 0x64, 0x64, 0x2B, 0x3D, 0x60, 0x3C, 0x74, 0x72, 0x3E, 0x3C, 0x74, 0x64, 0x3E, 0x24, +0x7B, 0x70, 0x2E, 0x70, 0x6F, 0x72, 0x74, 0x7D, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x3C, 0x74, 0x64, +0x3E, 0x24, 0x7B, 0x70, 0x2E, 0x64, 0x2E, 0x73, 0x65, 0x6E, 0x74, 0x7D, 0x3C, 0x2F, 0x74, 0x64, +0x3E, 0x3C, 0x74, 0x64, 0x3E, 0x24, 0x7B, 0x70, 0x2E, 0x64, 0x2E, 0x72, 0x65, 0x63, 0x65, 0x69, +0x76, 0x65, 0x64, 0x7D, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x3C, 0x74, 0x64, 0x3E, 0x24, 0x7B, 0x70, +0x2E, 0x72, 0x2E, 0x73, 0x65, 0x6E, 0x74, 0x2E, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x7D, 0x3C, 0x2F, +0x74, 0x64, 0x3E, 0x3C, 0x74, 0x64, 0x3E, 0x24, 0x7B, 0x70, 0x2E, 0x72, 0x2E, 0x73, 0x65, 0x6E, +0x74, 0x2E, 0x64, 0x69, 0x73, 0x63, 0x6F, 0x76, 0x65, 0x72, 0x79, 0x7D, 0x3C, 0x2F, 0x74, 0x64, +0x3E, 0x3C, 0x74, 0x64, 0x3E, 0x24, 0x7B, 0x70, 0x2E, 0x72, 0x2E, 0x72, 0x65, 0x63, 0x65, 0x69, +0x76, 0x65, 0x64, 0x2E, 0x67, 0x6F, 0x6F, 0x64, 0x7D, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x3C, 0x74, +0x64, 0x3E, 0x24, 0x7B, 0x70, 0x2E, 0x72, 0x2E, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, +0x2E, 0x62, 0x61, 0x64, 0x7D, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x3C, 0x74, 0x64, 0x3E, 0x24, 0x7B, +0x70, 0x2E, 0x72, 0x2E, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x2E, 0x64, 0x69, 0x73, +0x63, 0x6F, 0x76, 0x65, 0x72, 0x79, 0x7D, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x3C, 0x2F, 0x74, 0x72, +0x3E, 0x60, 0x3B, 0x0A, 0x7D, 0x29, 0x3B, 0x0A, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, +0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, +0x22, 0x69, 0x64, 0x50, 0x6F, 0x72, 0x74, 0x73, 0x22, 0x29, 0x2E, 0x69, 0x6E, 0x6E, 0x65, 0x72, +0x48, 0x54, 0x4D, 0x4C, 0x3D, 0x68, 0x64, 0x72, 0x73, 0x2B, 0x74, 0x64, 0x64, 0x0A, 0x7D, 0x20, +0x63, 0x61, 0x74, 0x63, 0x68, 0x20, 0x28, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x29, 0x7B, 0x7D, 0x0A, +0x7D, 0x00 +}; diff --git a/lib-remoteconfig/http/content/generate_content.cpp b/lib-remoteconfig/http/content/generate_content.cpp index aa2d43f4..66993e90 100755 --- a/lib-remoteconfig/http/content/generate_content.cpp +++ b/lib-remoteconfig/http/content/generate_content.cpp @@ -2,7 +2,7 @@ * @file generate_content.cpp * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -51,6 +51,21 @@ static constexpr char content_header[] = static constexpr char HAVE_DSA_BEGIN[] = "#if defined (ENABLE_PHY_SWITCH)\n"; static constexpr char HAVE_DSA_END[] = "#endif /* (ENABLE_PHY_SWITCH) */\n"; +static constexpr char HAVE_DMX_BEGIN[] = "#if !defined (CONFIG_HTTP_HTML_NO_DMX) && (defined(OUTPUT_DMX_SEND) || defined(OUTPUT_DMX_SEND_MULTI))\n"; +static constexpr char HAVE_DMX_END[] = "#endif /* !defined (CONFIG_HTTP_HTML_NO_DMX) && (defined(OUTPUT_DMX_SEND) || defined(OUTPUT_DMX_SEND_MULTI)) */\n"; + +static constexpr char HAVE_RDM_BEGIN[] = "#if !defined (CONFIG_HTTP_HTML_NO_RDM) && defined (RDM_CONTROLLER)\n"; +static constexpr char HAVE_RDM_END[] = "#endif /* !defined (CONFIG_HTTP_HTML_NO_RDM) && defined (RDM_CONTROLLER) */\n"; + +static constexpr char HAVE_SHOWFILE_BEGIN[] = "#if defined (NODE_SHOWFILE)\n"; +static constexpr char HAVE_SHOWFILE_END[] = "#endif /* (NODE_SHOWFILE) */\n"; + +static constexpr char HAVE_TIME_BEGIN[] = "#if !defined (CONFIG_HTTP_HTML_NO_TIME)\n"; +static constexpr char HAVE_TIME_END[] = "#endif /* !defined (CONFIG_HTTP_HTML_NO_TIME) */\n"; + +static constexpr char HAVE_RTC_BEGIN[] = "#if !defined (CONFIG_HTTP_HTML_NO_RTC) && !defined (DISABLE_RTC)\n"; +static constexpr char HAVE_RTC_END[] = "#endif /* !defined (CONFIG_HTTP_HTML_NO_RTC) && !defined (DISABLE_RTC) */\n"; + static FILE *pFileContent; static FILE *pFileIncludes; @@ -105,7 +120,37 @@ static int convert_to_h(const char *pFileName) { fwrite(HAVE_DSA_BEGIN, sizeof(char),sizeof(HAVE_DSA_BEGIN) - 1, pFileIncludes); } - auto i = snprintf(buffer, sizeof(buffer) - 1, "#include \"%s\"\n", pFileNameOut); + const auto bHasDMX = (strstr(pFileNameOut, "dmx") != nullptr); + + if (bHasDMX) { + fwrite(HAVE_DMX_BEGIN, sizeof(char),sizeof(HAVE_DMX_BEGIN) - 1, pFileIncludes); + } + + const auto bHasRDM = (strstr(pFileNameOut, "rdm") != nullptr); + + if (bHasRDM) { + fwrite(HAVE_RDM_BEGIN, sizeof(char),sizeof(HAVE_RDM_BEGIN) - 1, pFileIncludes); + } + + const auto bHasSHOWFILE = (strstr(pFileNameOut, "showfile") != nullptr); + + if (bHasSHOWFILE) { + fwrite(HAVE_SHOWFILE_BEGIN, sizeof(char),sizeof(HAVE_SHOWFILE_BEGIN) - 1, pFileIncludes); + } + + const auto bHasTIME = (strstr(pFileNameOut, "time") != nullptr); + + if (bHasTIME) { + fwrite(HAVE_TIME_BEGIN, sizeof(char),sizeof(HAVE_TIME_BEGIN) - 1, pFileIncludes); + } + + const auto bHasRTC = (strstr(pFileNameOut, "rtc") != nullptr); + + if (bHasRTC) { + fwrite(HAVE_RTC_BEGIN, sizeof(char),sizeof(HAVE_RTC_BEGIN) - 1, pFileIncludes); + } + + auto i = snprintf(buffer, sizeof(buffer) - 1, "#%sinclude \"%s\"\n", (bHasDSA || bHasDMX || bHasRDM || bHasSHOWFILE || bHasTIME || bHasRTC) ? " " : "" , pFileNameOut); assert(i < static_cast(sizeof(buffer))); fwrite(buffer, sizeof(char), i, pFileIncludes); @@ -114,6 +159,26 @@ static int convert_to_h(const char *pFileName) { fwrite(HAVE_DSA_END, sizeof(char),sizeof(HAVE_DSA_END) - 1, pFileIncludes); } + if (bHasDMX) { + fwrite(HAVE_DMX_END, sizeof(char),sizeof(HAVE_DMX_END) - 1, pFileIncludes); + } + + if (bHasRDM) { + fwrite(HAVE_RDM_END, sizeof(char),sizeof(HAVE_RDM_END) - 1, pFileIncludes); + } + + if (bHasSHOWFILE) { + fwrite(HAVE_SHOWFILE_END, sizeof(char),sizeof(HAVE_SHOWFILE_END) - 1, pFileIncludes); + } + + if (bHasTIME) { + fwrite(HAVE_TIME_END, sizeof(char),sizeof(HAVE_TIME_END) - 1, pFileIncludes); + } + + if (bHasRTC) { + fwrite(HAVE_RTC_END, sizeof(char),sizeof(HAVE_RTC_END) - 1, pFileIncludes); + } + fwrite("static constexpr char ", sizeof(char), 22, pFileOut); char *pConstantName = new char[nFileNameLength + 1]; @@ -200,11 +265,36 @@ int main() { assert(pFileName != nullptr); const auto bHasDSA = (strstr(pDirEntry->d_name, "dsa") != nullptr); + const auto bHasDMX = (strstr(pDirEntry->d_name, "dmx") != nullptr); + const auto bHasRDM = (strstr(pDirEntry->d_name, "rdm") != nullptr); + const auto bHasSHOWFILE = (strstr(pDirEntry->d_name, "showfile") != nullptr); + const auto bHasTIME = (strstr(pDirEntry->d_name, "time") != nullptr); + const auto bHasRTC = (strstr(pDirEntry->d_name, "rtc") != nullptr); if (bHasDSA) { fwrite(HAVE_DSA_BEGIN, sizeof(char),sizeof(HAVE_DSA_BEGIN) - 1, pFileContent); } + if (bHasDMX) { + fwrite(HAVE_DMX_BEGIN, sizeof(char),sizeof(HAVE_DMX_BEGIN) - 1, pFileContent); + } + + if (bHasRDM) { + fwrite(HAVE_RDM_BEGIN, sizeof(char),sizeof(HAVE_RDM_BEGIN) - 1, pFileContent); + } + + if (bHasSHOWFILE) { + fwrite(HAVE_SHOWFILE_BEGIN, sizeof(char),sizeof(HAVE_SHOWFILE_BEGIN) - 1, pFileContent); + } + + if (bHasTIME) { + fwrite(HAVE_TIME_BEGIN, sizeof(char),sizeof(HAVE_TIME_BEGIN) - 1, pFileContent); + } + + if (bHasRTC) { + fwrite(HAVE_RTC_BEGIN, sizeof(char),sizeof(HAVE_RTC_BEGIN) - 1, pFileContent); + } + auto i = snprintf(pFileName, strlen(pDirEntry->d_name) + 8, "\t{ \"%s\", ", pDirEntry->d_name); fwrite(pFileName, sizeof(char), i, pFileContent); delete[] pFileName; @@ -221,6 +311,26 @@ int main() { if (bHasDSA) { fwrite(HAVE_DSA_END, sizeof(char),sizeof(HAVE_DSA_END) - 1, pFileContent); } + + if (bHasDMX) { + fwrite(HAVE_DMX_END, sizeof(char),sizeof(HAVE_DMX_END) - 1, pFileContent); + } + + if (bHasRDM) { + fwrite(HAVE_RDM_END, sizeof(char),sizeof(HAVE_RDM_END) - 1, pFileContent); + } + + if (bHasSHOWFILE) { + fwrite(HAVE_SHOWFILE_END, sizeof(char),sizeof(HAVE_SHOWFILE_END) - 1, pFileContent); + } + + if (bHasTIME) { + fwrite(HAVE_TIME_END, sizeof(char),sizeof(HAVE_TIME_END) - 1, pFileContent); + } + + if (bHasRTC) { + fwrite(HAVE_RTC_END, sizeof(char),sizeof(HAVE_RTC_END) - 1, pFileContent); + } } } diff --git a/lib-remoteconfig/http/content/generate_json_switch b/lib-remoteconfig/http/content/generate_json_switch index 2a98dbc2b361d3d3bdc1ae53e95347b8db70ddc9..5972656aaa9c9817eae350b1472f38209f235026 100755 GIT binary patch delta 627 zcmbQx$T*>qaf1UR=MiQGFgUW=lTn{haE}s%3#TV{GQAfmp7TC2nQJ}&<4MW$bhj*% zp7VXd>&-pPa{N3&d<+a8oyRG_$F5iD>D9_JXctW@y+G~ z!XAu_TPAag`qWS00oi?g2gt=QZvFoMzq$1Y&^X5Cy&#I8zbygP4t69v!XbKJdSQ)fFmR3gM zF?pksIMatWlTRtB0XZL)#3dVm25bN-fB_jGqX&qqCo3w;Gd+B_*-3dH=jIGu1s28w zlN$}>IYFi|GKer7n7q-@opI0RpN8e!jC&>*+Uj#6Qq4+RbIu>owDe>1OWWm40CN%G AssI20 delta 547 zcmbQx$T*>qaf1URXACm~7{qM$WYlLA3{iq`;q>HAruQOm4)3^kcB1f&!fjt3Mhh?A z#$n_ku(^j>j-TflF9U-|=P{37)_c5@w+YEfp8*RT++_tc2Pk?1E`ObO@_Qjg)uUj6 z<1b47{r~UL-FgE=bspR$0aU(^5u#@o?_^V9MWzkBlOurCBHqc>!itO&C(jjDVrT8Ip|UvR + +RDM + +
        +

        +
        +
        Working Queue
        +
        +
        +
        Discovered devices
        +
          + + + + + + \ No newline at end of file diff --git a/lib-remoteconfig/http/content/rdm.html.h b/lib-remoteconfig/http/content/rdm.html.h new file mode 100644 index 00000000..1427ab82 --- /dev/null +++ b/lib-remoteconfig/http/content/rdm.html.h @@ -0,0 +1,74 @@ +static constexpr char rdm_html[] = { +0x3C, 0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A, +0x3C, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x3C, 0x6C, 0x69, +0x6E, 0x6B, 0x20, 0x72, 0x65, 0x6C, 0x3D, 0x22, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x73, 0x68, 0x65, +0x65, 0x74, 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3D, 0x22, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x73, +0x2E, 0x63, 0x73, 0x73, 0x22, 0x20, 0x2F, 0x3E, 0x3C, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0x52, +0x44, 0x4D, 0x3C, 0x2F, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, +0x3E, 0x0A, 0x3C, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0A, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, +0x3E, 0x3C, 0x75, 0x6C, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x69, 0x64, 0x4C, 0x69, 0x73, 0x74, 0x22, +0x3E, 0x3C, 0x2F, 0x75, 0x6C, 0x3E, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3E, 0x0A, +0x3C, 0x70, 0x3E, 0x3C, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, +0x63, 0x6B, 0x3D, 0x22, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, 0x22, 0x3E, 0x52, +0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x3C, 0x2F, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x3E, 0x3C, +0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x3D, 0x27, 0x6D, 0x61, +0x72, 0x67, 0x69, 0x6E, 0x2D, 0x6C, 0x65, 0x66, 0x74, 0x3A, 0x20, 0x32, 0x35, 0x70, 0x78, 0x3B, +0x27, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x62, 0x74, 0x6E, 0x22, 0x3E, 0x4C, 0x6F, 0x61, 0x64, 0x69, +0x6E, 0x67, 0x2E, 0x2E, 0x2E, 0x3C, 0x2F, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x3E, 0x3C, 0x2F, +0x70, 0x3E, 0x0A, 0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x63, +0x66, 0x67, 0x22, 0x3E, 0x3C, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x69, +0x64, 0x43, 0x66, 0x67, 0x22, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3D, 0x27, 0x31, 0x27, +0x3E, 0x3C, 0x2F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0A, +0x3C, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x3D, 0x22, 0x71, 0x75, 0x65, 0x22, +0x3E, 0x57, 0x6F, 0x72, 0x6B, 0x69, 0x6E, 0x67, 0x20, 0x51, 0x75, 0x65, 0x75, 0x65, 0x3C, 0x62, +0x72, 0x20, 0x2F, 0x3E, 0x0A, 0x3C, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x73, 0x74, 0x79, 0x6C, +0x65, 0x3D, 0x27, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x66, 0x61, 0x6D, 0x69, 0x6C, 0x79, 0x3A, 0x22, +0x43, 0x6F, 0x75, 0x72, 0x69, 0x65, 0x72, 0x20, 0x4E, 0x65, 0x77, 0x22, 0x2C, 0x20, 0x43, 0x6F, +0x75, 0x72, 0x69, 0x65, 0x72, 0x2C, 0x20, 0x6D, 0x6F, 0x6E, 0x6F, 0x73, 0x70, 0x61, 0x63, 0x65, +0x3B, 0x20, 0x66, 0x6F, 0x6E, 0x74, 0x2D, 0x73, 0x69, 0x7A, 0x65, 0x3A, 0x38, 0x30, 0x25, 0x27, +0x20, 0x69, 0x64, 0x3D, 0x22, 0x69, 0x64, 0x51, 0x75, 0x65, 0x22, 0x20, 0x62, 0x6F, 0x72, 0x64, +0x65, 0x72, 0x3D, 0x27, 0x30, 0x27, 0x3E, 0x3C, 0x2F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, +0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0A, 0x3C, 0x64, 0x69, 0x76, 0x3E, 0x44, 0x69, 0x73, 0x63, +0x6F, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3C, 0x62, +0x72, 0x20, 0x2F, 0x3E, 0x3C, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x69, +0x64, 0x44, 0x69, 0x73, 0x22, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3D, 0x27, 0x31, 0x27, +0x3E, 0x3C, 0x2F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0A, +0x3C, 0x66, 0x6F, 0x6F, 0x74, 0x65, 0x72, 0x3E, 0x3C, 0x75, 0x6C, 0x20, 0x69, 0x64, 0x3D, 0x22, +0x69, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x22, 0x3E, 0x3C, 0x2F, 0x75, 0x6C, 0x3E, +0x3C, 0x2F, 0x66, 0x6F, 0x6F, 0x74, 0x65, 0x72, 0x3E, 0x0A, 0x3C, 0x73, 0x63, 0x72, 0x69, 0x70, +0x74, 0x20, 0x73, 0x72, 0x63, 0x3D, 0x22, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x2E, 0x6A, 0x73, +0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x6A, 0x61, 0x76, +0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x3E, 0x3C, 0x2F, 0x73, 0x63, 0x72, 0x69, 0x70, +0x74, 0x3E, 0x0A, 0x3C, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, 0x3D, 0x22, +0x72, 0x64, 0x6D, 0x2E, 0x6A, 0x73, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x74, 0x65, +0x78, 0x74, 0x2F, 0x6A, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x3E, 0x3C, +0x2F, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, +0x3E, 0x0A, 0x61, 0x73, 0x79, 0x6E, 0x63, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, +0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28, 0x29, 0x20, 0x7B, 0x0A, 0x63, 0x6F, 0x6E, 0x73, +0x74, 0x20, 0x72, 0x20, 0x3D, 0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x67, 0x65, 0x74, 0x4A, +0x53, 0x4F, 0x4E, 0x28, 0x27, 0x72, 0x64, 0x6D, 0x27, 0x29, 0x3B, 0x0A, 0x63, 0x6F, 0x6E, 0x73, +0x74, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x3D, 0x20, 0x72, 0x2E, 0x72, 0x64, 0x6D, 0x3B, +0x0A, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x62, 0x74, 0x6E, 0x20, 0x3D, 0x20, 0x64, 0x6F, 0x63, +0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, +0x42, 0x79, 0x49, 0x64, 0x28, 0x27, 0x62, 0x74, 0x6E, 0x27, 0x29, 0x3B, 0x0A, 0x62, 0x74, 0x6E, +0x2E, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x54, 0x65, 0x78, 0x74, 0x20, 0x3D, 0x20, 0x76, 0x61, 0x6C, +0x75, 0x65, 0x20, 0x3D, 0x3D, 0x3D, 0x20, 0x27, 0x30, 0x27, 0x20, 0x3F, 0x20, 0x27, 0x45, 0x6E, +0x61, 0x62, 0x6C, 0x65, 0x27, 0x20, 0x3A, 0x20, 0x27, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6C, 0x65, +0x27, 0x3B, 0x0A, 0x62, 0x74, 0x6E, 0x2E, 0x6F, 0x6E, 0x63, 0x6C, 0x69, 0x63, 0x6B, 0x20, 0x3D, +0x20, 0x61, 0x73, 0x79, 0x6E, 0x63, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, +0x28, 0x29, 0x20, 0x7B, 0x0A, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x6E, 0x65, 0x77, 0x56, 0x61, +0x6C, 0x75, 0x65, 0x20, 0x3D, 0x20, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, 0x3D, 0x3D, 0x3D, 0x20, +0x27, 0x30, 0x27, 0x20, 0x3F, 0x20, 0x27, 0x31, 0x27, 0x20, 0x3A, 0x20, 0x27, 0x30, 0x27, 0x3B, +0x0A, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x6E, 0x65, 0x77, 0x20, 0x50, 0x72, 0x6F, 0x6D, 0x69, +0x73, 0x65, 0x28, 0x72, 0x65, 0x73, 0x6F, 0x6C, 0x76, 0x65, 0x20, 0x3D, 0x3E, 0x20, 0x7B, 0x0A, +0x70, 0x6F, 0x73, 0x74, 0x28, 0x7B, 0x20, 0x72, 0x64, 0x6D, 0x3A, 0x20, 0x6E, 0x65, 0x77, 0x56, +0x61, 0x6C, 0x75, 0x65, 0x20, 0x7D, 0x29, 0x2E, 0x74, 0x68, 0x65, 0x6E, 0x28, 0x28, 0x29, 0x20, +0x3D, 0x3E, 0x20, 0x7B, 0x0A, 0x72, 0x65, 0x73, 0x6F, 0x6C, 0x76, 0x65, 0x28, 0x29, 0x3B, 0x0A, +0x7D, 0x29, 0x3B, 0x0A, 0x7D, 0x29, 0x3B, 0x0A, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28, 0x29, +0x3B, 0x0A, 0x7D, 0x3B, 0x0A, 0x7D, 0x0A, 0x3C, 0x2F, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, +0x0A, 0x3C, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x6C, 0x69, 0x73, 0x74, 0x28, 0x29, 0x3B, +0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x28, 0x29, 0x3B, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, +0x68, 0x28, 0x29, 0x3B, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28, 0x29, 0x3B, 0x3C, 0x2F, 0x73, +0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x2F, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0A, 0x3C, +0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x00 +}; diff --git a/lib-remoteconfig/http/content/rdm.js b/lib-remoteconfig/http/content/rdm.js new file mode 100755 index 00000000..72d9a086 --- /dev/null +++ b/lib-remoteconfig/http/content/rdm.js @@ -0,0 +1,46 @@ +async function refresh() { + try { + let data=await getJSON('rdm/portstatus') + let h='PortDirectionStatus' + + data.forEach(item => { + h+=`${item.port}${item.direction}${item.status}` + }); + + document.getElementById("idCfg").innerHTML=h + + let tr=await Promise.all( + data.map(item => getJSON('rdm/tod?' + item.port).then(response => ({ port: item.port, tod: response.tod }))) + ); + + try { + let q=await getJSON('rdm/queue') + h=''; + q.uid.forEach(uid => { + h+=`${uid}` + }); + } catch (error){h=''} + + document.getElementById("idQue").innerHTML=h + + tr.sort((a, b) => { + return data.findIndex(item => item.port === a.port) - data.findIndex(item => item.port === b.port); + }); + + let hdrs='' + let tdd='' + + tr.forEach(r => { + hdrs+=`${r.port}`; + tdd+=''; + r.tod.forEach(tod => { + tdd+=`${tod}
          ` + }); + tdd+='' + }); + + hdrs+='' + tdd+='' + document.getElementById("idDis").innerHTML=hdrs + tdd + } catch (error){} +} \ No newline at end of file diff --git a/lib-remoteconfig/http/content/rdm.js.h b/lib-remoteconfig/http/content/rdm.js.h new file mode 100644 index 00000000..b0adbfda --- /dev/null +++ b/lib-remoteconfig/http/content/rdm.js.h @@ -0,0 +1,64 @@ +static constexpr char rdm_js[] = { +0x61, 0x73, 0x79, 0x6E, 0x63, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x72, +0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, 0x20, 0x7B, 0x0A, 0x74, 0x72, 0x79, 0x20, 0x7B, +0x0A, 0x6C, 0x65, 0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x3D, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, +0x67, 0x65, 0x74, 0x4A, 0x53, 0x4F, 0x4E, 0x28, 0x27, 0x72, 0x64, 0x6D, 0x2F, 0x70, 0x6F, 0x72, +0x74, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x27, 0x29, 0x0A, 0x6C, 0x65, 0x74, 0x20, 0x68, 0x3D, +0x27, 0x3C, 0x74, 0x72, 0x3E, 0x3C, 0x74, 0x68, 0x3E, 0x50, 0x6F, 0x72, 0x74, 0x3C, 0x2F, 0x74, +0x68, 0x3E, 0x3C, 0x74, 0x68, 0x3E, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3C, +0x2F, 0x74, 0x68, 0x3E, 0x3C, 0x74, 0x68, 0x3E, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, 0x2F, +0x74, 0x68, 0x3E, 0x3C, 0x2F, 0x74, 0x72, 0x3E, 0x27, 0x0A, 0x64, 0x61, 0x74, 0x61, 0x2E, 0x66, +0x6F, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x3D, 0x3E, 0x20, 0x7B, +0x0A, 0x68, 0x2B, 0x3D, 0x60, 0x3C, 0x74, 0x72, 0x3E, 0x3C, 0x74, 0x64, 0x3E, 0x24, 0x7B, 0x69, +0x74, 0x65, 0x6D, 0x2E, 0x70, 0x6F, 0x72, 0x74, 0x7D, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x3C, 0x74, +0x64, 0x3E, 0x24, 0x7B, 0x69, 0x74, 0x65, 0x6D, 0x2E, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, +0x6F, 0x6E, 0x7D, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x3C, 0x74, 0x64, 0x3E, 0x24, 0x7B, 0x69, 0x74, +0x65, 0x6D, 0x2E, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x7D, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x3C, +0x2F, 0x74, 0x72, 0x3E, 0x60, 0x0A, 0x7D, 0x29, 0x3B, 0x0A, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, +0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, +0x64, 0x28, 0x22, 0x69, 0x64, 0x43, 0x66, 0x67, 0x22, 0x29, 0x2E, 0x69, 0x6E, 0x6E, 0x65, 0x72, +0x48, 0x54, 0x4D, 0x4C, 0x3D, 0x68, 0x0A, 0x6C, 0x65, 0x74, 0x20, 0x74, 0x72, 0x3D, 0x61, 0x77, +0x61, 0x69, 0x74, 0x20, 0x50, 0x72, 0x6F, 0x6D, 0x69, 0x73, 0x65, 0x2E, 0x61, 0x6C, 0x6C, 0x28, +0x0A, 0x64, 0x61, 0x74, 0x61, 0x2E, 0x6D, 0x61, 0x70, 0x28, 0x69, 0x74, 0x65, 0x6D, 0x20, 0x3D, +0x3E, 0x20, 0x67, 0x65, 0x74, 0x4A, 0x53, 0x4F, 0x4E, 0x28, 0x27, 0x72, 0x64, 0x6D, 0x2F, 0x74, +0x6F, 0x64, 0x3F, 0x27, 0x20, 0x2B, 0x20, 0x69, 0x74, 0x65, 0x6D, 0x2E, 0x70, 0x6F, 0x72, 0x74, +0x29, 0x2E, 0x74, 0x68, 0x65, 0x6E, 0x28, 0x72, 0x65, 0x73, 0x70, 0x6F, 0x6E, 0x73, 0x65, 0x20, +0x3D, 0x3E, 0x20, 0x28, 0x7B, 0x20, 0x70, 0x6F, 0x72, 0x74, 0x3A, 0x20, 0x69, 0x74, 0x65, 0x6D, +0x2E, 0x70, 0x6F, 0x72, 0x74, 0x2C, 0x20, 0x74, 0x6F, 0x64, 0x3A, 0x20, 0x72, 0x65, 0x73, 0x70, +0x6F, 0x6E, 0x73, 0x65, 0x2E, 0x74, 0x6F, 0x64, 0x20, 0x7D, 0x29, 0x29, 0x29, 0x0A, 0x29, 0x3B, +0x0A, 0x74, 0x72, 0x79, 0x20, 0x7B, 0x0A, 0x6C, 0x65, 0x74, 0x20, 0x71, 0x3D, 0x61, 0x77, 0x61, +0x69, 0x74, 0x20, 0x67, 0x65, 0x74, 0x4A, 0x53, 0x4F, 0x4E, 0x28, 0x27, 0x72, 0x64, 0x6D, 0x2F, +0x71, 0x75, 0x65, 0x75, 0x65, 0x27, 0x29, 0x0A, 0x68, 0x3D, 0x27, 0x27, 0x3B, 0x0A, 0x71, 0x2E, +0x75, 0x69, 0x64, 0x2E, 0x66, 0x6F, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x75, 0x69, 0x64, 0x20, +0x3D, 0x3E, 0x20, 0x7B, 0x0A, 0x68, 0x2B, 0x3D, 0x60, 0x3C, 0x74, 0x72, 0x3E, 0x3C, 0x74, 0x64, +0x20, 0x63, 0x6F, 0x6C, 0x73, 0x70, 0x61, 0x6E, 0x3D, 0x22, 0x33, 0x22, 0x3E, 0x24, 0x7B, 0x75, +0x69, 0x64, 0x7D, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x3C, 0x2F, 0x74, 0x72, 0x3E, 0x60, 0x0A, 0x7D, +0x29, 0x3B, 0x0A, 0x7D, 0x20, 0x63, 0x61, 0x74, 0x63, 0x68, 0x20, 0x28, 0x65, 0x72, 0x72, 0x6F, +0x72, 0x29, 0x7B, 0x68, 0x3D, 0x27, 0x27, 0x7D, 0x0A, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, +0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, +0x28, 0x22, 0x69, 0x64, 0x51, 0x75, 0x65, 0x22, 0x29, 0x2E, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x48, +0x54, 0x4D, 0x4C, 0x3D, 0x68, 0x0A, 0x74, 0x72, 0x2E, 0x73, 0x6F, 0x72, 0x74, 0x28, 0x28, 0x61, +0x2C, 0x20, 0x62, 0x29, 0x20, 0x3D, 0x3E, 0x20, 0x7B, 0x0A, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, +0x20, 0x64, 0x61, 0x74, 0x61, 0x2E, 0x66, 0x69, 0x6E, 0x64, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x28, +0x69, 0x74, 0x65, 0x6D, 0x20, 0x3D, 0x3E, 0x20, 0x69, 0x74, 0x65, 0x6D, 0x2E, 0x70, 0x6F, 0x72, +0x74, 0x20, 0x3D, 0x3D, 0x3D, 0x20, 0x61, 0x2E, 0x70, 0x6F, 0x72, 0x74, 0x29, 0x20, 0x2D, 0x20, +0x64, 0x61, 0x74, 0x61, 0x2E, 0x66, 0x69, 0x6E, 0x64, 0x49, 0x6E, 0x64, 0x65, 0x78, 0x28, 0x69, +0x74, 0x65, 0x6D, 0x20, 0x3D, 0x3E, 0x20, 0x69, 0x74, 0x65, 0x6D, 0x2E, 0x70, 0x6F, 0x72, 0x74, +0x20, 0x3D, 0x3D, 0x3D, 0x20, 0x62, 0x2E, 0x70, 0x6F, 0x72, 0x74, 0x29, 0x3B, 0x0A, 0x7D, 0x29, +0x3B, 0x0A, 0x6C, 0x65, 0x74, 0x20, 0x68, 0x64, 0x72, 0x73, 0x3D, 0x27, 0x3C, 0x74, 0x72, 0x3E, +0x27, 0x0A, 0x6C, 0x65, 0x74, 0x20, 0x74, 0x64, 0x64, 0x3D, 0x27, 0x3C, 0x74, 0x72, 0x3E, 0x27, +0x0A, 0x74, 0x72, 0x2E, 0x66, 0x6F, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x72, 0x20, 0x3D, 0x3E, +0x20, 0x7B, 0x0A, 0x68, 0x64, 0x72, 0x73, 0x2B, 0x3D, 0x60, 0x3C, 0x74, 0x68, 0x3E, 0x24, 0x7B, +0x72, 0x2E, 0x70, 0x6F, 0x72, 0x74, 0x7D, 0x3C, 0x2F, 0x74, 0x68, 0x3E, 0x60, 0x3B, 0x0A, 0x74, +0x64, 0x64, 0x2B, 0x3D, 0x27, 0x3C, 0x74, 0x64, 0x3E, 0x27, 0x3B, 0x0A, 0x72, 0x2E, 0x74, 0x6F, +0x64, 0x2E, 0x66, 0x6F, 0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x74, 0x6F, 0x64, 0x20, 0x3D, 0x3E, +0x20, 0x7B, 0x0A, 0x74, 0x64, 0x64, 0x2B, 0x3D, 0x60, 0x24, 0x7B, 0x74, 0x6F, 0x64, 0x7D, 0x3C, +0x62, 0x72, 0x2F, 0x3E, 0x60, 0x0A, 0x7D, 0x29, 0x3B, 0x0A, 0x74, 0x64, 0x64, 0x2B, 0x3D, 0x27, +0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x27, 0x0A, 0x7D, 0x29, 0x3B, 0x0A, 0x68, 0x64, 0x72, 0x73, 0x2B, +0x3D, 0x27, 0x3C, 0x2F, 0x74, 0x72, 0x3E, 0x27, 0x0A, 0x74, 0x64, 0x64, 0x2B, 0x3D, 0x27, 0x3C, +0x2F, 0x74, 0x72, 0x3E, 0x27, 0x0A, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, +0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x69, +0x64, 0x44, 0x69, 0x73, 0x22, 0x29, 0x2E, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x48, 0x54, 0x4D, 0x4C, +0x3D, 0x68, 0x64, 0x72, 0x73, 0x20, 0x2B, 0x20, 0x74, 0x64, 0x64, 0x0A, 0x7D, 0x20, 0x63, 0x61, +0x74, 0x63, 0x68, 0x20, 0x28, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x29, 0x7B, 0x7D, 0x0A, 0x7D, 0x00 +}; diff --git a/lib-remoteconfig/http/content/rtc.html b/lib-remoteconfig/http/content/rtc.html new file mode 100755 index 00000000..a8027ee2 --- /dev/null +++ b/lib-remoteconfig/http/content/rtc.html @@ -0,0 +1,27 @@ + + +Real-time clock + +
            +

            +

            Node time will be displayed here

            +

            RTC time will be displayed here

            +
            + + +
            +

            +

            + + + + + +
            +
              + + + + + + \ No newline at end of file diff --git a/lib-remoteconfig/http/content/rtc.html.h b/lib-remoteconfig/http/content/rtc.html.h new file mode 100644 index 00000000..de317f42 --- /dev/null +++ b/lib-remoteconfig/http/content/rtc.html.h @@ -0,0 +1,66 @@ +static constexpr char rtc_html[] = { +0x3C, 0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A, +0x3C, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x3C, 0x6C, 0x69, +0x6E, 0x6B, 0x20, 0x72, 0x65, 0x6C, 0x3D, 0x22, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x73, 0x68, 0x65, +0x65, 0x74, 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3D, 0x22, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x73, +0x2E, 0x63, 0x73, 0x73, 0x22, 0x20, 0x2F, 0x3E, 0x3C, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0x52, +0x65, 0x61, 0x6C, 0x2D, 0x74, 0x69, 0x6D, 0x65, 0x20, 0x63, 0x6C, 0x6F, 0x63, 0x6B, 0x3C, 0x2F, +0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0A, 0x3C, 0x62, +0x6F, 0x64, 0x79, 0x3E, 0x0A, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3E, 0x3C, 0x75, 0x6C, +0x20, 0x69, 0x64, 0x3D, 0x22, 0x69, 0x64, 0x4C, 0x69, 0x73, 0x74, 0x22, 0x3E, 0x3C, 0x2F, 0x75, +0x6C, 0x3E, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3E, 0x0A, 0x3C, 0x70, 0x3E, 0x3C, +0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, 0x63, 0x6B, 0x3D, 0x22, +0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, 0x22, 0x3E, 0x52, 0x65, 0x66, 0x72, 0x65, +0x73, 0x68, 0x3C, 0x2F, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x3E, 0x3C, 0x2F, 0x70, 0x3E, 0x0A, +0x3C, 0x70, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x6E, 0x6F, 0x64, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x22, +0x3E, 0x4E, 0x6F, 0x64, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20, 0x77, 0x69, 0x6C, 0x6C, 0x20, +0x62, 0x65, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, +0x65, 0x3C, 0x2F, 0x70, 0x3E, 0x0A, 0x3C, 0x70, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x72, 0x74, 0x63, +0x54, 0x69, 0x6D, 0x65, 0x22, 0x3E, 0x52, 0x54, 0x43, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20, 0x77, +0x69, 0x6C, 0x6C, 0x20, 0x62, 0x65, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6C, 0x61, 0x79, 0x65, 0x64, +0x20, 0x68, 0x65, 0x72, 0x65, 0x3C, 0x2F, 0x70, 0x3E, 0x0A, 0x3C, 0x64, 0x69, 0x76, 0x3E, 0x0A, +0x3C, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, 0x63, 0x6B, 0x3D, +0x22, 0x68, 0x63, 0x54, 0x6F, 0x53, 0x79, 0x73, 0x28, 0x29, 0x22, 0x3E, 0x53, 0x65, 0x74, 0x20, +0x74, 0x68, 0x65, 0x20, 0x4E, 0x6F, 0x64, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20, 0x66, 0x72, +0x6F, 0x6D, 0x20, 0x74, 0x68, 0x65, 0x20, 0x52, 0x54, 0x43, 0x3C, 0x2F, 0x62, 0x75, 0x74, 0x74, +0x6F, 0x6E, 0x3E, 0x0A, 0x3C, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, 0x63, 0x6C, +0x69, 0x63, 0x6B, 0x3D, 0x22, 0x73, 0x79, 0x73, 0x54, 0x6F, 0x48, 0x63, 0x28, 0x29, 0x22, 0x3E, +0x53, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x52, 0x54, 0x43, 0x20, 0x66, 0x72, 0x6F, 0x6D, +0x20, 0x74, 0x68, 0x65, 0x20, 0x4E, 0x6F, 0x64, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x3C, 0x2F, +0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x3E, 0x0A, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0A, 0x3C, +0x70, 0x3E, 0x0A, 0x3C, 0x66, 0x6F, 0x72, 0x6D, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x66, 0x6F, 0x72, +0x6D, 0x22, 0x3E, 0x0A, 0x3C, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x66, 0x6F, 0x72, 0x3D, 0x22, +0x61, 0x6C, 0x61, 0x72, 0x6D, 0x49, 0x6E, 0x70, 0x75, 0x74, 0x22, 0x3E, 0x52, 0x54, 0x43, 0x20, +0x41, 0x6C, 0x61, 0x72, 0x6D, 0x3A, 0x3C, 0x2F, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x3E, 0x0A, 0x3C, +0x69, 0x6E, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x64, 0x61, 0x74, 0x65, +0x74, 0x69, 0x6D, 0x65, 0x2D, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x22, 0x20, 0x69, 0x64, 0x3D, 0x22, +0x61, 0x6C, 0x61, 0x72, 0x6D, 0x49, 0x6E, 0x70, 0x75, 0x74, 0x22, 0x20, 0x6E, 0x61, 0x6D, 0x65, +0x3D, 0x22, 0x61, 0x6C, 0x61, 0x72, 0x6D, 0x49, 0x6E, 0x70, 0x75, 0x74, 0x22, 0x20, 0x72, 0x65, +0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x3E, 0x0A, 0x3C, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x66, +0x6F, 0x72, 0x3D, 0x22, 0x63, 0x68, 0x6B, 0x62, 0x6F, 0x78, 0x22, 0x3E, 0x45, 0x6E, 0x61, 0x62, +0x6C, 0x65, 0x3C, 0x2F, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x3E, 0x0A, 0x3C, 0x69, 0x6E, 0x70, 0x75, +0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x62, 0x6F, 0x78, +0x22, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x63, 0x68, 0x6B, 0x62, 0x6F, 0x78, 0x22, 0x20, 0x6E, 0x61, +0x6D, 0x65, 0x3D, 0x22, 0x45, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x22, 0x3E, 0x0A, 0x3C, 0x62, 0x75, +0x74, 0x74, 0x6F, 0x6E, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x62, 0x75, 0x74, 0x74, 0x6F, +0x6E, 0x22, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, 0x63, 0x6B, 0x3D, 0x22, 0x61, 0x6C, 0x61, 0x72, +0x6D, 0x28, 0x29, 0x22, 0x3E, 0x53, 0x65, 0x74, 0x3C, 0x2F, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, +0x3E, 0x0A, 0x3C, 0x2F, 0x66, 0x6F, 0x72, 0x6D, 0x3E, 0x0A, 0x3C, 0x66, 0x6F, 0x6F, 0x74, 0x65, +0x72, 0x3E, 0x3C, 0x75, 0x6C, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x69, 0x64, 0x56, 0x65, 0x72, 0x73, +0x69, 0x6F, 0x6E, 0x22, 0x3E, 0x3C, 0x2F, 0x75, 0x6C, 0x3E, 0x3C, 0x2F, 0x66, 0x6F, 0x6F, 0x74, +0x65, 0x72, 0x3E, 0x0A, 0x3C, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, 0x3D, +0x22, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x2E, 0x6A, 0x73, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, +0x3D, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x6A, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, +0x74, 0x22, 0x3E, 0x3C, 0x2F, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x73, 0x63, +0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, 0x3D, 0x22, 0x64, 0x61, 0x74, 0x65, 0x2E, 0x6A, +0x73, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x6A, 0x61, +0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x3E, 0x3C, 0x2F, 0x73, 0x63, 0x72, 0x69, +0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, 0x3D, +0x22, 0x72, 0x74, 0x63, 0x2E, 0x6A, 0x73, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x74, +0x65, 0x78, 0x74, 0x2F, 0x6A, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x3E, +0x3C, 0x2F, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x73, 0x63, 0x72, 0x69, 0x70, +0x74, 0x3E, 0x6C, 0x69, 0x73, 0x74, 0x28, 0x29, 0x3B, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, +0x28, 0x29, 0x3B, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, 0x3C, 0x2F, 0x73, 0x63, +0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x2F, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0A, 0x3C, 0x2F, +0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x00 +}; diff --git a/lib-remoteconfig/http/content/rtc.js b/lib-remoteconfig/http/content/rtc.js new file mode 100755 index 00000000..a4fefd46 --- /dev/null +++ b/lib-remoteconfig/http/content/rtc.js @@ -0,0 +1,27 @@ +async function refresh() { + let d1=await getJSON('timedate') + const node = formatDateTime(new Date(d1.date)) + document.getElementById('nodeTime').textContent = `Node Time: ${node}` + let d2=await getJSON('rtcalarm') + const rtc = formatDateTime(new Date(d2.rtc)) + document.getElementById('rtcTime').textContent = `RTC Time: ${rtc}` + document.getElementById('alarmInput').value = formatDateTime(new Date(d2.alarm)) + document.getElementById('chkbox').checked = (d2.enabled === "1") +} + +async function hcToSys() { + await post({ rtc: "", action: "hctosys" }); + refresh(); +} + +async function sysToHc() { + await post({ rtc: "", action: "systohc" }); + refresh(); +} + +async function alarm() { + const a = document.getElementById('alarmInput').value; + const b = document.getElementById('chkbox').checked ? "1" : "0"; + await post({ rtc:"", alarm: a, enable: b }); + refresh(); +} diff --git a/lib-remoteconfig/http/content/rtc.js.h b/lib-remoteconfig/http/content/rtc.js.h new file mode 100644 index 00000000..8a80190b --- /dev/null +++ b/lib-remoteconfig/http/content/rtc.js.h @@ -0,0 +1,55 @@ +static constexpr char rtc_js[] = { +0x61, 0x73, 0x79, 0x6E, 0x63, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x72, +0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, 0x20, 0x7B, 0x0A, 0x6C, 0x65, 0x74, 0x20, 0x64, +0x31, 0x3D, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x67, 0x65, 0x74, 0x4A, 0x53, 0x4F, 0x4E, 0x28, +0x27, 0x74, 0x69, 0x6D, 0x65, 0x64, 0x61, 0x74, 0x65, 0x27, 0x29, 0x0A, 0x63, 0x6F, 0x6E, 0x73, +0x74, 0x20, 0x6E, 0x6F, 0x64, 0x65, 0x20, 0x3D, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x44, +0x61, 0x74, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x28, 0x6E, 0x65, 0x77, 0x20, 0x44, 0x61, 0x74, 0x65, +0x28, 0x64, 0x31, 0x2E, 0x64, 0x61, 0x74, 0x65, 0x29, 0x29, 0x0A, 0x64, 0x6F, 0x63, 0x75, 0x6D, +0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, +0x49, 0x64, 0x28, 0x27, 0x6E, 0x6F, 0x64, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x27, 0x29, 0x2E, 0x74, +0x65, 0x78, 0x74, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x20, 0x3D, 0x20, 0x60, 0x4E, 0x6F, +0x64, 0x65, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x3A, 0x20, 0x24, 0x7B, 0x6E, 0x6F, 0x64, 0x65, 0x7D, +0x60, 0x0A, 0x6C, 0x65, 0x74, 0x20, 0x64, 0x32, 0x3D, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x67, +0x65, 0x74, 0x4A, 0x53, 0x4F, 0x4E, 0x28, 0x27, 0x72, 0x74, 0x63, 0x61, 0x6C, 0x61, 0x72, 0x6D, +0x27, 0x29, 0x0A, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x72, 0x74, 0x63, 0x20, 0x3D, 0x20, 0x66, +0x6F, 0x72, 0x6D, 0x61, 0x74, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x28, 0x6E, 0x65, +0x77, 0x20, 0x44, 0x61, 0x74, 0x65, 0x28, 0x64, 0x32, 0x2E, 0x72, 0x74, 0x63, 0x29, 0x29, 0x0A, +0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, +0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x27, 0x72, 0x74, 0x63, 0x54, 0x69, 0x6D, 0x65, +0x27, 0x29, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x20, 0x3D, +0x20, 0x60, 0x52, 0x54, 0x43, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x3A, 0x20, 0x24, 0x7B, 0x72, 0x74, +0x63, 0x7D, 0x60, 0x0A, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, +0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x27, 0x61, 0x6C, 0x61, +0x72, 0x6D, 0x49, 0x6E, 0x70, 0x75, 0x74, 0x27, 0x29, 0x2E, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x20, +0x3D, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6D, 0x65, +0x28, 0x6E, 0x65, 0x77, 0x20, 0x44, 0x61, 0x74, 0x65, 0x28, 0x64, 0x32, 0x2E, 0x61, 0x6C, 0x61, +0x72, 0x6D, 0x29, 0x29, 0x0A, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, +0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x27, 0x63, 0x68, +0x6B, 0x62, 0x6F, 0x78, 0x27, 0x29, 0x2E, 0x63, 0x68, 0x65, 0x63, 0x6B, 0x65, 0x64, 0x20, 0x3D, +0x20, 0x28, 0x64, 0x32, 0x2E, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0x20, 0x3D, 0x3D, 0x3D, +0x20, 0x22, 0x31, 0x22, 0x29, 0x0A, 0x7D, 0x0A, 0x61, 0x73, 0x79, 0x6E, 0x63, 0x20, 0x66, 0x75, +0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x68, 0x63, 0x54, 0x6F, 0x53, 0x79, 0x73, 0x28, 0x29, +0x20, 0x7B, 0x0A, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x70, 0x6F, 0x73, 0x74, 0x28, 0x7B, 0x20, +0x72, 0x74, 0x63, 0x3A, 0x20, 0x22, 0x22, 0x2C, 0x20, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x3A, +0x20, 0x22, 0x68, 0x63, 0x74, 0x6F, 0x73, 0x79, 0x73, 0x22, 0x20, 0x7D, 0x29, 0x3B, 0x0A, 0x72, +0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, 0x3B, 0x0A, 0x7D, 0x0A, 0x61, 0x73, 0x79, 0x6E, +0x63, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x73, 0x79, 0x73, 0x54, 0x6F, +0x48, 0x63, 0x28, 0x29, 0x20, 0x7B, 0x0A, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x70, 0x6F, 0x73, +0x74, 0x28, 0x7B, 0x20, 0x72, 0x74, 0x63, 0x3A, 0x20, 0x22, 0x22, 0x2C, 0x20, 0x61, 0x63, 0x74, +0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x22, 0x73, 0x79, 0x73, 0x74, 0x6F, 0x68, 0x63, 0x22, 0x20, 0x7D, +0x29, 0x3B, 0x0A, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, 0x3B, 0x0A, 0x7D, 0x0A, +0x61, 0x73, 0x79, 0x6E, 0x63, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x61, +0x6C, 0x61, 0x72, 0x6D, 0x28, 0x29, 0x20, 0x7B, 0x0A, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x61, +0x20, 0x3D, 0x20, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, +0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x27, 0x61, 0x6C, 0x61, 0x72, +0x6D, 0x49, 0x6E, 0x70, 0x75, 0x74, 0x27, 0x29, 0x2E, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x3B, 0x0A, +0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x62, 0x20, 0x3D, 0x20, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, +0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, +0x64, 0x28, 0x27, 0x63, 0x68, 0x6B, 0x62, 0x6F, 0x78, 0x27, 0x29, 0x2E, 0x63, 0x68, 0x65, 0x63, +0x6B, 0x65, 0x64, 0x20, 0x3F, 0x20, 0x22, 0x31, 0x22, 0x20, 0x3A, 0x20, 0x22, 0x30, 0x22, 0x3B, +0x0A, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x70, 0x6F, 0x73, 0x74, 0x28, 0x7B, 0x20, 0x72, 0x74, +0x63, 0x3A, 0x22, 0x22, 0x2C, 0x20, 0x61, 0x6C, 0x61, 0x72, 0x6D, 0x3A, 0x20, 0x61, 0x2C, 0x20, +0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x3A, 0x20, 0x62, 0x20, 0x7D, 0x29, 0x3B, 0x0A, 0x72, 0x65, +0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, 0x3B, 0x0A, 0x7D, 0x0A, 0x00 +}; diff --git a/lib-remoteconfig/http/content/showfile.html b/lib-remoteconfig/http/content/showfile.html new file mode 100755 index 00000000..51d5b6b2 --- /dev/null +++ b/lib-remoteconfig/http/content/showfile.html @@ -0,0 +1,31 @@ + + + + + + + +
                +

                +
                +
                + + + + +
                +
                + +
                +

                Player Show

                +

                Set new recorder file

                +

                Delete Show

                +
                  + + + + + + \ No newline at end of file diff --git a/lib-remoteconfig/http/content/showfile.html.h b/lib-remoteconfig/http/content/showfile.html.h new file mode 100644 index 00000000..5dcd4b35 --- /dev/null +++ b/lib-remoteconfig/http/content/showfile.html.h @@ -0,0 +1,84 @@ +static constexpr char showfile_html[] = { +0x3C, 0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A, +0x3C, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0A, 0x3C, 0x6C, +0x69, 0x6E, 0x6B, 0x20, 0x72, 0x65, 0x6C, 0x3D, 0x22, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x73, 0x68, +0x65, 0x65, 0x74, 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3D, 0x22, 0x73, 0x74, 0x79, 0x6C, 0x65, +0x73, 0x2E, 0x63, 0x73, 0x73, 0x22, 0x20, 0x2F, 0x3E, 0x0A, 0x3C, 0x74, 0x69, 0x74, 0x6C, 0x65, +0x3E, 0x3C, 0x2F, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0x0A, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, +0x3E, 0x0A, 0x3C, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0A, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, +0x3E, 0x3C, 0x75, 0x6C, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x69, 0x64, 0x4C, 0x69, 0x73, 0x74, 0x22, +0x3E, 0x3C, 0x2F, 0x75, 0x6C, 0x3E, 0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3E, 0x0A, +0x3C, 0x70, 0x3E, 0x3C, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, +0x63, 0x6B, 0x3D, 0x22, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, 0x22, 0x3E, 0x52, +0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x3C, 0x2F, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x3E, 0x3C, +0x2F, 0x70, 0x3E, 0x0A, 0x3C, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x69, +0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x3D, +0x27, 0x31, 0x27, 0x3E, 0x3C, 0x2F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x3E, 0x0A, 0x3C, 0x64, 0x69, +0x76, 0x3E, 0x0A, 0x3C, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, +0x63, 0x6B, 0x3D, 0x22, 0x70, 0x6C, 0x61, 0x79, 0x28, 0x29, 0x22, 0x3E, 0x50, 0x6C, 0x61, 0x79, +0x3C, 0x2F, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x3E, 0x0A, 0x3C, 0x62, 0x75, 0x74, 0x74, 0x6F, +0x6E, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, 0x63, 0x6B, 0x3D, 0x22, 0x73, 0x74, 0x6F, 0x70, 0x28, +0x29, 0x22, 0x3E, 0x53, 0x74, 0x6F, 0x70, 0x3C, 0x2F, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x3E, +0x0A, 0x3C, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, 0x63, 0x6B, +0x3D, 0x22, 0x72, 0x65, 0x73, 0x75, 0x6D, 0x65, 0x28, 0x29, 0x22, 0x3E, 0x52, 0x65, 0x73, 0x75, +0x6D, 0x65, 0x3C, 0x2F, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x3E, 0x0A, 0x3C, 0x62, 0x75, 0x74, +0x74, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, 0x63, 0x6B, 0x3D, 0x22, 0x72, 0x65, 0x63, +0x6F, 0x72, 0x64, 0x28, 0x29, 0x22, 0x3E, 0x52, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x3C, 0x2F, 0x62, +0x75, 0x74, 0x74, 0x6F, 0x6E, 0x3E, 0x0A, 0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0A, 0x3C, 0x64, +0x69, 0x76, 0x3E, 0x0A, 0x3C, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x69, 0x64, 0x3D, 0x22, +0x69, 0x64, 0x34, 0x22, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, 0x63, 0x6B, 0x3D, 0x22, 0x6C, 0x6F, +0x6F, 0x70, 0x28, 0x29, 0x22, 0x3E, 0x3C, 0x2F, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x3E, 0x0A, +0x3C, 0x2F, 0x64, 0x69, 0x76, 0x3E, 0x0A, 0x3C, 0x70, 0x3E, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72, +0x20, 0x53, 0x68, 0x6F, 0x77, 0x20, 0x3C, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x20, 0x69, 0x64, +0x3D, 0x22, 0x69, 0x64, 0x31, 0x22, 0x3E, 0x3C, 0x2F, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x3E, +0x3C, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, 0x63, 0x6B, 0x3D, +0x22, 0x73, 0x65, 0x6C, 0x28, 0x29, 0x22, 0x3E, 0x53, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x3C, 0x2F, +0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x3E, 0x3C, 0x2F, 0x70, 0x3E, 0x0A, 0x3C, 0x70, 0x3E, 0x53, +0x65, 0x74, 0x20, 0x6E, 0x65, 0x77, 0x20, 0x72, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x65, 0x72, 0x20, +0x66, 0x69, 0x6C, 0x65, 0x20, 0x3C, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x69, 0x64, 0x3D, +0x22, 0x69, 0x64, 0x33, 0x22, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, 0x63, 0x6B, 0x3D, 0x22, 0x72, +0x65, 0x63, 0x28, 0x29, 0x22, 0x3E, 0x3C, 0x2F, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x3E, 0x3C, +0x2F, 0x70, 0x3E, 0x0A, 0x3C, 0x70, 0x3E, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x20, 0x53, 0x68, +0x6F, 0x77, 0x20, 0x3C, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x69, +0x64, 0x32, 0x22, 0x3E, 0x3C, 0x2F, 0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0x3E, 0x3C, 0x62, 0x75, +0x74, 0x74, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, 0x63, 0x6B, 0x3D, 0x22, 0x64, 0x65, +0x6C, 0x28, 0x29, 0x22, 0x3E, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x3C, 0x2F, 0x62, 0x75, 0x74, +0x74, 0x6F, 0x6E, 0x3E, 0x3C, 0x2F, 0x70, 0x3E, 0x0A, 0x3C, 0x66, 0x6F, 0x6F, 0x74, 0x65, 0x72, +0x3E, 0x3C, 0x75, 0x6C, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x69, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, +0x6F, 0x6E, 0x22, 0x3E, 0x3C, 0x2F, 0x75, 0x6C, 0x3E, 0x3C, 0x2F, 0x66, 0x6F, 0x6F, 0x74, 0x65, +0x72, 0x3E, 0x0A, 0x3C, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, 0x3D, 0x22, +0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x2E, 0x6A, 0x73, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, +0x22, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x6A, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, +0x22, 0x3E, 0x3C, 0x2F, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x73, 0x63, 0x72, +0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, 0x3D, 0x22, 0x73, 0x68, 0x6F, 0x77, 0x66, 0x69, 0x6C, +0x65, 0x2E, 0x6A, 0x73, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x74, 0x65, 0x78, 0x74, +0x2F, 0x6A, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x3E, 0x3C, 0x2F, 0x73, +0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x66, +0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x70, 0x6C, 0x61, 0x79, 0x28, 0x29, 0x7B, 0x73, +0x65, 0x6E, 0x64, 0x28, 0x22, 0x70, 0x6C, 0x61, 0x79, 0x22, 0x29, 0x3B, 0x7D, 0x66, 0x75, 0x6E, +0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x73, 0x74, 0x6F, 0x70, 0x28, 0x29, 0x7B, 0x73, 0x65, 0x6E, +0x64, 0x28, 0x22, 0x73, 0x74, 0x6F, 0x70, 0x22, 0x29, 0x3B, 0x7D, 0x66, 0x75, 0x6E, 0x63, 0x74, +0x69, 0x6F, 0x6E, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6D, 0x65, 0x28, 0x29, 0x20, 0x7B, 0x73, 0x65, +0x6E, 0x64, 0x28, 0x22, 0x72, 0x65, 0x73, 0x75, 0x6D, 0x65, 0x22, 0x29, 0x3B, 0x7D, 0x66, 0x75, +0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x72, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x28, 0x29, 0x20, +0x7B, 0x73, 0x65, 0x6E, 0x64, 0x28, 0x22, 0x72, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x22, 0x29, 0x3B, +0x7D, 0x0A, 0x61, 0x73, 0x79, 0x6E, 0x63, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, +0x20, 0x73, 0x65, 0x6E, 0x64, 0x28, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x29, 0x20, 0x7B, 0x61, +0x77, 0x61, 0x69, 0x74, 0x20, 0x70, 0x6F, 0x73, 0x74, 0x28, 0x7B, 0x20, 0x73, 0x68, 0x6F, 0x77, +0x3A, 0x20, 0x22, 0x22, 0x2C, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3A, 0x20, 0x73, 0x74, +0x61, 0x74, 0x75, 0x73, 0x20, 0x7D, 0x29, 0x3B, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, +0x29, 0x3B, 0x7D, 0x0A, 0x61, 0x73, 0x79, 0x6E, 0x63, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, +0x6F, 0x6E, 0x20, 0x6C, 0x6F, 0x6F, 0x70, 0x28, 0x29, 0x20, 0x7B, 0x63, 0x6F, 0x6E, 0x73, 0x74, +0x20, 0x76, 0x3D, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, +0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x27, 0x69, 0x64, 0x34, 0x27, +0x29, 0x2E, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x48, 0x54, 0x4D, 0x4C, 0x20, 0x3D, 0x3D, 0x20, 0x22, +0x4C, 0x6F, 0x6F, 0x70, 0x69, 0x6E, 0x67, 0x22, 0x20, 0x3F, 0x20, 0x22, 0x31, 0x22, 0x20, 0x3A, +0x20, 0x22, 0x30, 0x22, 0x3B, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x70, 0x6F, 0x73, 0x74, 0x28, +0x7B, 0x20, 0x73, 0x68, 0x6F, 0x77, 0x3A, 0x22, 0x22, 0x2C, 0x6C, 0x6F, 0x6F, 0x70, 0x3A, 0x60, +0x24, 0x7B, 0x76, 0x7D, 0x60, 0x20, 0x7D, 0x29, 0x3B, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, +0x28, 0x29, 0x3B, 0x7D, 0x3C, 0x2F, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x73, +0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x6C, 0x69, 0x73, 0x74, 0x28, 0x29, 0x3B, 0x76, 0x65, 0x72, +0x73, 0x69, 0x6F, 0x6E, 0x28, 0x29, 0x3B, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, +0x3C, 0x2F, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x2F, 0x62, 0x6F, 0x64, 0x79, +0x3E, 0x0A, 0x3C, 0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x00 +}; diff --git a/lib-remoteconfig/http/content/showfile.js b/lib-remoteconfig/http/content/showfile.js new file mode 100755 index 00000000..900098c6 --- /dev/null +++ b/lib-remoteconfig/http/content/showfile.js @@ -0,0 +1,58 @@ +async function refresh() { + try { + directory() + let d=await getJSON('showfile/status') + let s=(parseInt(d.show) >= 0 && parseInt(d.show) <= 99) ? d.show : 'None' + let loop=d.loop === "1" ? "Yes" : "No" + h=`Mode${d.mode} ` + h+=`Show${s} ` + h+=`Status${d.status}` + h+=`Looping${loop}` + document.getElementById("idStatus").innerHTML=''+h+'
                  ' + let b=d.loop === "1" ? "No loop" : "Looping" + document.getElementById("id4").innerHTML=b + } catch (error){} +} + +async function sel() { + const v=document.getElementById("id1").value + await post({ show:`${v}` }) + refresh() +} + +async function rec() { + const v=document.getElementById("id3").innerHTML + await post({ show:"",recorder:`${v}` }) + refresh() +} + +async function del() { + const v=document.getElementById("id2").value + await delet({ show:`${v}` }) + refresh() +} + +function ff(d) { + const s = d.shows.map(show => show.show) + let e = 0; + for (let n of s) { + if (n !== e) { return e;} + e++; + } + return e +} + +async function directory() { + try { + let d=await getJSON('showfile/directory') + let h="" + let f=Object.keys(d["shows"]) + f.forEach(function(key) { + var v = d["shows"][key] + h += "" + }); + document.getElementById("id1").innerHTML = h + document.getElementById("id2").innerHTML = h + document.getElementById("id3").innerHTML = ff(d) + } catch (error){} +} \ No newline at end of file diff --git a/lib-remoteconfig/http/content/showfile.js.h b/lib-remoteconfig/http/content/showfile.js.h new file mode 100644 index 00000000..73fa6ee1 --- /dev/null +++ b/lib-remoteconfig/http/content/showfile.js.h @@ -0,0 +1,92 @@ +static constexpr char showfile_js[] = { +0x61, 0x73, 0x79, 0x6E, 0x63, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x72, +0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, 0x20, 0x7B, 0x0A, 0x74, 0x72, 0x79, 0x20, 0x7B, +0x0A, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x79, 0x28, 0x29, 0x0A, 0x6C, 0x65, 0x74, +0x20, 0x64, 0x3D, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x67, 0x65, 0x74, 0x4A, 0x53, 0x4F, 0x4E, +0x28, 0x27, 0x73, 0x68, 0x6F, 0x77, 0x66, 0x69, 0x6C, 0x65, 0x2F, 0x73, 0x74, 0x61, 0x74, 0x75, +0x73, 0x27, 0x29, 0x0A, 0x6C, 0x65, 0x74, 0x20, 0x73, 0x3D, 0x28, 0x70, 0x61, 0x72, 0x73, 0x65, +0x49, 0x6E, 0x74, 0x28, 0x64, 0x2E, 0x73, 0x68, 0x6F, 0x77, 0x29, 0x20, 0x3E, 0x3D, 0x20, 0x30, +0x20, 0x26, 0x26, 0x20, 0x70, 0x61, 0x72, 0x73, 0x65, 0x49, 0x6E, 0x74, 0x28, 0x64, 0x2E, 0x73, +0x68, 0x6F, 0x77, 0x29, 0x20, 0x3C, 0x3D, 0x20, 0x39, 0x39, 0x29, 0x20, 0x3F, 0x20, 0x64, 0x2E, +0x73, 0x68, 0x6F, 0x77, 0x20, 0x3A, 0x20, 0x27, 0x4E, 0x6F, 0x6E, 0x65, 0x27, 0x0A, 0x6C, 0x65, +0x74, 0x20, 0x6C, 0x6F, 0x6F, 0x70, 0x3D, 0x64, 0x2E, 0x6C, 0x6F, 0x6F, 0x70, 0x20, 0x3D, 0x3D, +0x3D, 0x20, 0x22, 0x31, 0x22, 0x20, 0x3F, 0x20, 0x22, 0x59, 0x65, 0x73, 0x22, 0x20, 0x3A, 0x20, +0x22, 0x4E, 0x6F, 0x22, 0x0A, 0x68, 0x3D, 0x60, 0x3C, 0x74, 0x72, 0x3E, 0x3C, 0x74, 0x64, 0x3E, +0x4D, 0x6F, 0x64, 0x65, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x3C, 0x74, 0x64, 0x3E, 0x24, 0x7B, 0x64, +0x2E, 0x6D, 0x6F, 0x64, 0x65, 0x7D, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x20, 0x3C, 0x2F, 0x74, 0x72, +0x3E, 0x60, 0x0A, 0x68, 0x2B, 0x3D, 0x60, 0x3C, 0x74, 0x72, 0x3E, 0x3C, 0x74, 0x64, 0x3E, 0x53, +0x68, 0x6F, 0x77, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x3C, 0x74, 0x64, 0x3E, 0x24, 0x7B, 0x73, 0x7D, +0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x20, 0x3C, 0x2F, 0x74, 0x72, 0x3E, 0x60, 0x0A, 0x68, 0x2B, 0x3D, +0x60, 0x3C, 0x74, 0x72, 0x3E, 0x3C, 0x74, 0x64, 0x3E, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3C, +0x2F, 0x74, 0x64, 0x3E, 0x3C, 0x74, 0x64, 0x3E, 0x24, 0x7B, 0x64, 0x2E, 0x73, 0x74, 0x61, 0x74, +0x75, 0x73, 0x7D, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x3C, 0x2F, 0x74, 0x72, 0x3E, 0x60, 0x0A, 0x68, +0x2B, 0x3D, 0x60, 0x3C, 0x74, 0x72, 0x3E, 0x3C, 0x74, 0x64, 0x3E, 0x4C, 0x6F, 0x6F, 0x70, 0x69, +0x6E, 0x67, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x3C, 0x74, 0x64, 0x3E, 0x24, 0x7B, 0x6C, 0x6F, 0x6F, +0x70, 0x7D, 0x3C, 0x2F, 0x74, 0x64, 0x3E, 0x3C, 0x2F, 0x74, 0x72, 0x3E, 0x60, 0x0A, 0x64, 0x6F, +0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, +0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x69, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, +0x29, 0x2E, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x48, 0x54, 0x4D, 0x4C, 0x3D, 0x27, 0x3C, 0x74, 0x61, +0x62, 0x6C, 0x65, 0x3E, 0x27, 0x2B, 0x68, 0x2B, 0x27, 0x3C, 0x2F, 0x74, 0x61, 0x62, 0x6C, 0x65, +0x3E, 0x27, 0x0A, 0x6C, 0x65, 0x74, 0x20, 0x62, 0x3D, 0x64, 0x2E, 0x6C, 0x6F, 0x6F, 0x70, 0x20, +0x3D, 0x3D, 0x3D, 0x20, 0x22, 0x31, 0x22, 0x20, 0x3F, 0x20, 0x22, 0x4E, 0x6F, 0x20, 0x6C, 0x6F, +0x6F, 0x70, 0x22, 0x20, 0x3A, 0x20, 0x22, 0x4C, 0x6F, 0x6F, 0x70, 0x69, 0x6E, 0x67, 0x22, 0x0A, +0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, +0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x69, 0x64, 0x34, 0x22, 0x29, 0x2E, 0x69, +0x6E, 0x6E, 0x65, 0x72, 0x48, 0x54, 0x4D, 0x4C, 0x3D, 0x62, 0x0A, 0x7D, 0x20, 0x63, 0x61, 0x74, +0x63, 0x68, 0x20, 0x28, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x29, 0x7B, 0x7D, 0x0A, 0x7D, 0x0A, 0x61, +0x73, 0x79, 0x6E, 0x63, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x73, 0x65, +0x6C, 0x28, 0x29, 0x20, 0x7B, 0x0A, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x76, 0x3D, 0x64, 0x6F, +0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, +0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x69, 0x64, 0x31, 0x22, 0x29, 0x2E, 0x76, 0x61, 0x6C, +0x75, 0x65, 0x0A, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x70, 0x6F, 0x73, 0x74, 0x28, 0x7B, 0x20, +0x73, 0x68, 0x6F, 0x77, 0x3A, 0x60, 0x24, 0x7B, 0x76, 0x7D, 0x60, 0x20, 0x7D, 0x29, 0x0A, 0x72, +0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, 0x0A, 0x7D, 0x0A, 0x61, 0x73, 0x79, 0x6E, 0x63, +0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x72, 0x65, 0x63, 0x28, 0x29, 0x20, +0x7B, 0x0A, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x76, 0x3D, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, +0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, +0x64, 0x28, 0x22, 0x69, 0x64, 0x33, 0x22, 0x29, 0x2E, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x48, 0x54, +0x4D, 0x4C, 0x0A, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x70, 0x6F, 0x73, 0x74, 0x28, 0x7B, 0x20, +0x73, 0x68, 0x6F, 0x77, 0x3A, 0x22, 0x22, 0x2C, 0x72, 0x65, 0x63, 0x6F, 0x72, 0x64, 0x65, 0x72, +0x3A, 0x60, 0x24, 0x7B, 0x76, 0x7D, 0x60, 0x20, 0x7D, 0x29, 0x0A, 0x72, 0x65, 0x66, 0x72, 0x65, +0x73, 0x68, 0x28, 0x29, 0x0A, 0x7D, 0x0A, 0x61, 0x73, 0x79, 0x6E, 0x63, 0x20, 0x66, 0x75, 0x6E, +0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x64, 0x65, 0x6C, 0x28, 0x29, 0x20, 0x7B, 0x0A, 0x63, 0x6F, +0x6E, 0x73, 0x74, 0x20, 0x76, 0x3D, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, +0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x69, +0x64, 0x32, 0x22, 0x29, 0x2E, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x0A, 0x61, 0x77, 0x61, 0x69, 0x74, +0x20, 0x64, 0x65, 0x6C, 0x65, 0x74, 0x28, 0x7B, 0x20, 0x73, 0x68, 0x6F, 0x77, 0x3A, 0x60, 0x24, +0x7B, 0x76, 0x7D, 0x60, 0x20, 0x7D, 0x29, 0x0A, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, +0x29, 0x0A, 0x7D, 0x0A, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x66, 0x28, +0x64, 0x29, 0x20, 0x7B, 0x0A, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x73, 0x20, 0x3D, 0x20, 0x64, +0x2E, 0x73, 0x68, 0x6F, 0x77, 0x73, 0x2E, 0x6D, 0x61, 0x70, 0x28, 0x73, 0x68, 0x6F, 0x77, 0x20, +0x3D, 0x3E, 0x20, 0x73, 0x68, 0x6F, 0x77, 0x2E, 0x73, 0x68, 0x6F, 0x77, 0x29, 0x0A, 0x6C, 0x65, +0x74, 0x20, 0x65, 0x20, 0x3D, 0x20, 0x30, 0x3B, 0x0A, 0x66, 0x6F, 0x72, 0x20, 0x28, 0x6C, 0x65, +0x74, 0x20, 0x6E, 0x20, 0x6F, 0x66, 0x20, 0x73, 0x29, 0x20, 0x7B, 0x0A, 0x69, 0x66, 0x20, 0x28, +0x6E, 0x20, 0x21, 0x3D, 0x3D, 0x20, 0x65, 0x29, 0x20, 0x7B, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, +0x6E, 0x20, 0x65, 0x3B, 0x7D, 0x0A, 0x65, 0x2B, 0x2B, 0x3B, 0x0A, 0x7D, 0x0A, 0x72, 0x65, 0x74, +0x75, 0x72, 0x6E, 0x20, 0x65, 0x0A, 0x7D, 0x0A, 0x61, 0x73, 0x79, 0x6E, 0x63, 0x20, 0x66, 0x75, +0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x79, +0x28, 0x29, 0x20, 0x7B, 0x0A, 0x74, 0x72, 0x79, 0x20, 0x7B, 0x0A, 0x6C, 0x65, 0x74, 0x20, 0x64, +0x3D, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x67, 0x65, 0x74, 0x4A, 0x53, 0x4F, 0x4E, 0x28, 0x27, +0x73, 0x68, 0x6F, 0x77, 0x66, 0x69, 0x6C, 0x65, 0x2F, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, +0x72, 0x79, 0x27, 0x29, 0x0A, 0x6C, 0x65, 0x74, 0x20, 0x68, 0x3D, 0x22, 0x22, 0x0A, 0x6C, 0x65, +0x74, 0x20, 0x66, 0x3D, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x2E, 0x6B, 0x65, 0x79, 0x73, 0x28, +0x64, 0x5B, 0x22, 0x73, 0x68, 0x6F, 0x77, 0x73, 0x22, 0x5D, 0x29, 0x0A, 0x66, 0x2E, 0x66, 0x6F, +0x72, 0x45, 0x61, 0x63, 0x68, 0x28, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x28, 0x6B, +0x65, 0x79, 0x29, 0x20, 0x7B, 0x0A, 0x76, 0x61, 0x72, 0x20, 0x76, 0x20, 0x3D, 0x20, 0x64, 0x5B, +0x22, 0x73, 0x68, 0x6F, 0x77, 0x73, 0x22, 0x5D, 0x5B, 0x6B, 0x65, 0x79, 0x5D, 0x0A, 0x68, 0x20, +0x2B, 0x3D, 0x20, 0x22, 0x3C, 0x6F, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x76, 0x61, 0x6C, 0x75, +0x65, 0x3D, 0x22, 0x2B, 0x76, 0x2E, 0x73, 0x68, 0x6F, 0x77, 0x2B, 0x22, 0x3E, 0x22, 0x2B, 0x76, +0x2E, 0x73, 0x68, 0x6F, 0x77, 0x2B, 0x22, 0x20, 0x7C, 0x20, 0x22, 0x2B, 0x76, 0x2E, 0x73, 0x69, +0x7A, 0x65, 0x2B, 0x22, 0x3C, 0x2F, 0x6F, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x3E, 0x22, 0x0A, 0x7D, +0x29, 0x3B, 0x0A, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, +0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x69, 0x64, 0x31, 0x22, +0x29, 0x2E, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x48, 0x54, 0x4D, 0x4C, 0x20, 0x3D, 0x20, 0x68, 0x0A, +0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, +0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x69, 0x64, 0x32, 0x22, 0x29, 0x2E, 0x69, +0x6E, 0x6E, 0x65, 0x72, 0x48, 0x54, 0x4D, 0x4C, 0x20, 0x3D, 0x20, 0x68, 0x0A, 0x64, 0x6F, 0x63, +0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, +0x42, 0x79, 0x49, 0x64, 0x28, 0x22, 0x69, 0x64, 0x33, 0x22, 0x29, 0x2E, 0x69, 0x6E, 0x6E, 0x65, +0x72, 0x48, 0x54, 0x4D, 0x4C, 0x20, 0x3D, 0x20, 0x66, 0x66, 0x28, 0x64, 0x29, 0x0A, 0x7D, 0x20, +0x63, 0x61, 0x74, 0x63, 0x68, 0x20, 0x28, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x29, 0x7B, 0x7D, 0x0A, +0x7D, 0x00 +}; diff --git a/lib-remoteconfig/http/content/static.js b/lib-remoteconfig/http/content/static.js index 1856a910..d1665383 100644 --- a/lib-remoteconfig/http/content/static.js +++ b/lib-remoteconfig/http/content/static.js @@ -19,7 +19,7 @@ async function version() { } function post(s) { - fetch('/json/action', { + return fetch('/json/action', { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -28,6 +28,16 @@ function post(s) { }) } +function delet(s) { + return fetch('/json/action', { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(s) + }) +} + function reboot() { post({ reboot: 1 }) } diff --git a/lib-remoteconfig/http/content/static.js.h b/lib-remoteconfig/http/content/static.js.h index 245a4e4f..e0aea984 100644 --- a/lib-remoteconfig/http/content/static.js.h +++ b/lib-remoteconfig/http/content/static.js.h @@ -34,36 +34,46 @@ static constexpr char static_js[] = { 0x2E, 0x62, 0x75, 0x69, 0x6C, 0x64, 0x2E, 0x74, 0x69, 0x6D, 0x65, 0x2B, 0x22, 0x3C, 0x2F, 0x6C, 0x69, 0x3E, 0x3C, 0x6C, 0x69, 0x3E, 0x22, 0x2B, 0x76, 0x2E, 0x62, 0x6F, 0x61, 0x72, 0x64, 0x2B, 0x22, 0x3C, 0x2F, 0x6C, 0x69, 0x3E, 0x22, 0x0A, 0x7D, 0x0A, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, -0x6F, 0x6E, 0x20, 0x70, 0x6F, 0x73, 0x74, 0x28, 0x73, 0x29, 0x20, 0x7B, 0x0A, 0x66, 0x65, 0x74, -0x63, 0x68, 0x28, 0x27, 0x2F, 0x6A, 0x73, 0x6F, 0x6E, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, -0x27, 0x2C, 0x20, 0x7B, 0x0A, 0x6D, 0x65, 0x74, 0x68, 0x6F, 0x64, 0x3A, 0x20, 0x27, 0x50, 0x4F, -0x53, 0x54, 0x27, 0x2C, 0x0A, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x3A, 0x20, 0x7B, 0x0A, -0x27, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, 0x54, 0x79, 0x70, 0x65, 0x27, 0x3A, 0x20, -0x27, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x6A, 0x73, 0x6F, -0x6E, 0x27, 0x0A, 0x7D, 0x2C, 0x0A, 0x62, 0x6F, 0x64, 0x79, 0x3A, 0x20, 0x4A, 0x53, 0x4F, 0x4E, -0x2E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x69, 0x66, 0x79, 0x28, 0x73, 0x29, 0x0A, 0x7D, 0x29, -0x0A, 0x7D, 0x0A, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x72, 0x65, 0x62, 0x6F, -0x6F, 0x74, 0x28, 0x29, 0x20, 0x7B, 0x0A, 0x70, 0x6F, 0x73, 0x74, 0x28, 0x7B, 0x20, 0x72, 0x65, -0x62, 0x6F, 0x6F, 0x74, 0x3A, 0x20, 0x31, 0x20, 0x7D, 0x29, 0x0A, 0x7D, 0x0A, 0x66, 0x75, 0x6E, -0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x6C, 0x6F, 0x63, 0x61, 0x74, 0x65, 0x28, 0x29, 0x20, 0x7B, -0x0A, 0x76, 0x61, 0x72, 0x20, 0x62, 0x20, 0x3D, 0x20, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, -0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, -0x28, 0x27, 0x6C, 0x6F, 0x63, 0x61, 0x74, 0x65, 0x42, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x27, 0x29, -0x3B, 0x0A, 0x69, 0x66, 0x20, 0x28, 0x62, 0x2E, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x4C, 0x69, 0x73, -0x74, 0x2E, 0x63, 0x6F, 0x6E, 0x74, 0x61, 0x69, 0x6E, 0x73, 0x28, 0x27, 0x69, 0x6E, 0x61, 0x63, -0x74, 0x69, 0x76, 0x65, 0x27, 0x29, 0x29, 0x20, 0x7B, 0x0A, 0x62, 0x2E, 0x63, 0x6C, 0x61, 0x73, -0x73, 0x4C, 0x69, 0x73, 0x74, 0x2E, 0x72, 0x65, 0x6D, 0x6F, 0x76, 0x65, 0x28, 0x27, 0x69, 0x6E, -0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x27, 0x29, 0x0A, 0x62, 0x2E, 0x63, 0x6C, 0x61, 0x73, 0x73, -0x4C, 0x69, 0x73, 0x74, 0x2E, 0x61, 0x64, 0x64, 0x28, 0x27, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, -0x27, 0x29, 0x0A, 0x62, 0x2E, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x48, 0x54, 0x4D, 0x4C, 0x20, 0x3D, -0x20, 0x27, 0x4C, 0x6F, 0x63, 0x61, 0x74, 0x65, 0x20, 0x4F, 0x6E, 0x27, 0x0A, 0x70, 0x6F, 0x73, -0x74, 0x28, 0x7B, 0x20, 0x69, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x66, 0x79, 0x3A, 0x20, 0x31, 0x20, -0x7D, 0x29, 0x0A, 0x7D, 0x20, 0x65, 0x6C, 0x73, 0x65, 0x20, 0x7B, 0x0A, 0x62, 0x2E, 0x63, 0x6C, -0x61, 0x73, 0x73, 0x4C, 0x69, 0x73, 0x74, 0x2E, 0x72, 0x65, 0x6D, 0x6F, 0x76, 0x65, 0x28, 0x27, -0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x27, 0x29, 0x0A, 0x62, 0x2E, 0x63, 0x6C, 0x61, 0x73, 0x73, -0x4C, 0x69, 0x73, 0x74, 0x2E, 0x61, 0x64, 0x64, 0x28, 0x27, 0x69, 0x6E, 0x61, 0x63, 0x74, 0x69, -0x76, 0x65, 0x27, 0x29, 0x0A, 0x62, 0x2E, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x48, 0x54, 0x4D, 0x4C, -0x20, 0x3D, 0x20, 0x27, 0x4C, 0x6F, 0x63, 0x61, 0x74, 0x65, 0x20, 0x4F, 0x66, 0x66, 0x27, 0x0A, -0x70, 0x6F, 0x73, 0x74, 0x28, 0x7B, 0x20, 0x69, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x66, 0x79, 0x3A, -0x20, 0x30, 0x20, 0x7D, 0x29, 0x0A, 0x7D, 0x0A, 0x7D, 0x00 +0x6F, 0x6E, 0x20, 0x70, 0x6F, 0x73, 0x74, 0x28, 0x73, 0x29, 0x20, 0x7B, 0x0A, 0x72, 0x65, 0x74, +0x75, 0x72, 0x6E, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x27, 0x2F, 0x6A, 0x73, 0x6F, 0x6E, +0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x27, 0x2C, 0x20, 0x7B, 0x0A, 0x6D, 0x65, 0x74, 0x68, +0x6F, 0x64, 0x3A, 0x20, 0x27, 0x50, 0x4F, 0x53, 0x54, 0x27, 0x2C, 0x0A, 0x68, 0x65, 0x61, 0x64, +0x65, 0x72, 0x73, 0x3A, 0x20, 0x7B, 0x0A, 0x27, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x2D, +0x54, 0x79, 0x70, 0x65, 0x27, 0x3A, 0x20, 0x27, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, +0x69, 0x6F, 0x6E, 0x2F, 0x6A, 0x73, 0x6F, 0x6E, 0x27, 0x0A, 0x7D, 0x2C, 0x0A, 0x62, 0x6F, 0x64, +0x79, 0x3A, 0x20, 0x4A, 0x53, 0x4F, 0x4E, 0x2E, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x69, 0x66, +0x79, 0x28, 0x73, 0x29, 0x0A, 0x7D, 0x29, 0x0A, 0x7D, 0x0A, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, +0x6F, 0x6E, 0x20, 0x64, 0x65, 0x6C, 0x65, 0x74, 0x28, 0x73, 0x29, 0x20, 0x7B, 0x0A, 0x72, 0x65, +0x74, 0x75, 0x72, 0x6E, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28, 0x27, 0x2F, 0x6A, 0x73, 0x6F, +0x6E, 0x2F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x27, 0x2C, 0x20, 0x7B, 0x0A, 0x6D, 0x65, 0x74, +0x68, 0x6F, 0x64, 0x3A, 0x20, 0x27, 0x44, 0x45, 0x4C, 0x45, 0x54, 0x45, 0x27, 0x2C, 0x0A, 0x68, +0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x3A, 0x20, 0x7B, 0x0A, 0x27, 0x43, 0x6F, 0x6E, 0x74, 0x65, +0x6E, 0x74, 0x2D, 0x54, 0x79, 0x70, 0x65, 0x27, 0x3A, 0x20, 0x27, 0x61, 0x70, 0x70, 0x6C, 0x69, +0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x6A, 0x73, 0x6F, 0x6E, 0x27, 0x0A, 0x7D, 0x2C, 0x0A, +0x62, 0x6F, 0x64, 0x79, 0x3A, 0x20, 0x4A, 0x53, 0x4F, 0x4E, 0x2E, 0x73, 0x74, 0x72, 0x69, 0x6E, +0x67, 0x69, 0x66, 0x79, 0x28, 0x73, 0x29, 0x0A, 0x7D, 0x29, 0x0A, 0x7D, 0x0A, 0x66, 0x75, 0x6E, +0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x72, 0x65, 0x62, 0x6F, 0x6F, 0x74, 0x28, 0x29, 0x20, 0x7B, +0x0A, 0x70, 0x6F, 0x73, 0x74, 0x28, 0x7B, 0x20, 0x72, 0x65, 0x62, 0x6F, 0x6F, 0x74, 0x3A, 0x20, +0x31, 0x20, 0x7D, 0x29, 0x0A, 0x7D, 0x0A, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, +0x6C, 0x6F, 0x63, 0x61, 0x74, 0x65, 0x28, 0x29, 0x20, 0x7B, 0x0A, 0x76, 0x61, 0x72, 0x20, 0x62, +0x20, 0x3D, 0x20, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, +0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x27, 0x6C, 0x6F, 0x63, 0x61, +0x74, 0x65, 0x42, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x27, 0x29, 0x3B, 0x0A, 0x69, 0x66, 0x20, 0x28, +0x62, 0x2E, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x4C, 0x69, 0x73, 0x74, 0x2E, 0x63, 0x6F, 0x6E, 0x74, +0x61, 0x69, 0x6E, 0x73, 0x28, 0x27, 0x69, 0x6E, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x27, 0x29, +0x29, 0x20, 0x7B, 0x0A, 0x62, 0x2E, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x4C, 0x69, 0x73, 0x74, 0x2E, +0x72, 0x65, 0x6D, 0x6F, 0x76, 0x65, 0x28, 0x27, 0x69, 0x6E, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, +0x27, 0x29, 0x0A, 0x62, 0x2E, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x4C, 0x69, 0x73, 0x74, 0x2E, 0x61, +0x64, 0x64, 0x28, 0x27, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x27, 0x29, 0x0A, 0x62, 0x2E, 0x69, +0x6E, 0x6E, 0x65, 0x72, 0x48, 0x54, 0x4D, 0x4C, 0x20, 0x3D, 0x20, 0x27, 0x4C, 0x6F, 0x63, 0x61, +0x74, 0x65, 0x20, 0x4F, 0x6E, 0x27, 0x0A, 0x70, 0x6F, 0x73, 0x74, 0x28, 0x7B, 0x20, 0x69, 0x64, +0x65, 0x6E, 0x74, 0x69, 0x66, 0x79, 0x3A, 0x20, 0x31, 0x20, 0x7D, 0x29, 0x0A, 0x7D, 0x20, 0x65, +0x6C, 0x73, 0x65, 0x20, 0x7B, 0x0A, 0x62, 0x2E, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x4C, 0x69, 0x73, +0x74, 0x2E, 0x72, 0x65, 0x6D, 0x6F, 0x76, 0x65, 0x28, 0x27, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, +0x27, 0x29, 0x0A, 0x62, 0x2E, 0x63, 0x6C, 0x61, 0x73, 0x73, 0x4C, 0x69, 0x73, 0x74, 0x2E, 0x61, +0x64, 0x64, 0x28, 0x27, 0x69, 0x6E, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x27, 0x29, 0x0A, 0x62, +0x2E, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x48, 0x54, 0x4D, 0x4C, 0x20, 0x3D, 0x20, 0x27, 0x4C, 0x6F, +0x63, 0x61, 0x74, 0x65, 0x20, 0x4F, 0x66, 0x66, 0x27, 0x0A, 0x70, 0x6F, 0x73, 0x74, 0x28, 0x7B, +0x20, 0x69, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x66, 0x79, 0x3A, 0x20, 0x30, 0x20, 0x7D, 0x29, 0x0A, +0x7D, 0x0A, 0x7D, 0x00 }; diff --git a/lib-remoteconfig/http/content/styles.css b/lib-remoteconfig/http/content/styles.css index e5a7c32f..3aef44c6 100644 --- a/lib-remoteconfig/http/content/styles.css +++ b/lib-remoteconfig/http/content/styles.css @@ -24,7 +24,7 @@ footer { border-radius: 4px; border: solid grey 1px; } - + button { cursor: pointer; } diff --git a/lib-remoteconfig/http/content/time.html b/lib-remoteconfig/http/content/time.html new file mode 100755 index 00000000..4e60419b --- /dev/null +++ b/lib-remoteconfig/http/content/time.html @@ -0,0 +1,15 @@ + + +Node Time + +
                    +

                    +

                    Node time will be displayed here

                    +

                    +
                      + + + + + + \ No newline at end of file diff --git a/lib-remoteconfig/http/content/time.html.h b/lib-remoteconfig/http/content/time.html.h new file mode 100644 index 00000000..9e886ce7 --- /dev/null +++ b/lib-remoteconfig/http/content/time.html.h @@ -0,0 +1,40 @@ +static constexpr char time_html[] = { +0x3C, 0x21, 0x44, 0x4F, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A, +0x3C, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x0A, 0x3C, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x3C, 0x6C, 0x69, +0x6E, 0x6B, 0x20, 0x72, 0x65, 0x6C, 0x3D, 0x22, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x73, 0x68, 0x65, +0x65, 0x74, 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3D, 0x22, 0x73, 0x74, 0x79, 0x6C, 0x65, 0x73, +0x2E, 0x63, 0x73, 0x73, 0x22, 0x20, 0x2F, 0x3E, 0x3C, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, 0x4E, +0x6F, 0x64, 0x65, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x3C, 0x2F, 0x74, 0x69, 0x74, 0x6C, 0x65, 0x3E, +0x3C, 0x2F, 0x68, 0x65, 0x61, 0x64, 0x3E, 0x0A, 0x3C, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0A, 0x3C, +0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x3E, 0x3C, 0x75, 0x6C, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x69, +0x64, 0x4C, 0x69, 0x73, 0x74, 0x22, 0x3E, 0x3C, 0x2F, 0x75, 0x6C, 0x3E, 0x3C, 0x2F, 0x68, 0x65, +0x61, 0x64, 0x65, 0x72, 0x3E, 0x0A, 0x3C, 0x70, 0x3E, 0x3C, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, +0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, 0x63, 0x6B, 0x3D, 0x22, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, +0x68, 0x28, 0x29, 0x22, 0x3E, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x3C, 0x2F, 0x62, 0x75, +0x74, 0x74, 0x6F, 0x6E, 0x3E, 0x3C, 0x2F, 0x70, 0x3E, 0x0A, 0x3C, 0x70, 0x20, 0x69, 0x64, 0x3D, +0x22, 0x6E, 0x6F, 0x64, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x22, 0x3E, 0x4E, 0x6F, 0x64, 0x65, 0x20, +0x74, 0x69, 0x6D, 0x65, 0x20, 0x77, 0x69, 0x6C, 0x6C, 0x20, 0x62, 0x65, 0x20, 0x64, 0x69, 0x73, +0x70, 0x6C, 0x61, 0x79, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x65, 0x3C, 0x2F, 0x70, 0x3E, 0x0A, +0x3C, 0x70, 0x3E, 0x3C, 0x62, 0x75, 0x74, 0x74, 0x6F, 0x6E, 0x20, 0x6F, 0x6E, 0x63, 0x6C, 0x69, +0x63, 0x6B, 0x3D, 0x22, 0x73, 0x79, 0x6E, 0x63, 0x57, 0x69, 0x74, 0x68, 0x4C, 0x6F, 0x63, 0x61, +0x6C, 0x54, 0x69, 0x6D, 0x65, 0x28, 0x29, 0x22, 0x3E, 0x53, 0x79, 0x6E, 0x63, 0x20, 0x77, 0x69, +0x74, 0x68, 0x20, 0x4C, 0x6F, 0x63, 0x61, 0x6C, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x3C, 0x2F, 0x62, +0x75, 0x74, 0x74, 0x6F, 0x6E, 0x3E, 0x3C, 0x2F, 0x70, 0x3E, 0x0A, 0x3C, 0x66, 0x6F, 0x6F, 0x74, +0x65, 0x72, 0x3E, 0x3C, 0x75, 0x6C, 0x20, 0x69, 0x64, 0x3D, 0x22, 0x69, 0x64, 0x56, 0x65, 0x72, +0x73, 0x69, 0x6F, 0x6E, 0x22, 0x3E, 0x3C, 0x2F, 0x75, 0x6C, 0x3E, 0x3C, 0x2F, 0x66, 0x6F, 0x6F, +0x74, 0x65, 0x72, 0x3E, 0x0A, 0x3C, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, +0x3D, 0x22, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x2E, 0x6A, 0x73, 0x22, 0x20, 0x74, 0x79, 0x70, +0x65, 0x3D, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x6A, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, +0x70, 0x74, 0x22, 0x3E, 0x3C, 0x2F, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x73, +0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, 0x3D, 0x22, 0x64, 0x61, 0x74, 0x65, 0x2E, +0x6A, 0x73, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x6A, +0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x3E, 0x3C, 0x2F, 0x73, 0x63, 0x72, +0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x73, 0x72, 0x63, +0x3D, 0x22, 0x74, 0x69, 0x6D, 0x65, 0x2E, 0x6A, 0x73, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3D, +0x22, 0x74, 0x65, 0x78, 0x74, 0x2F, 0x6A, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, +0x22, 0x3E, 0x3C, 0x2F, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x73, 0x63, 0x72, +0x69, 0x70, 0x74, 0x3E, 0x6C, 0x69, 0x73, 0x74, 0x28, 0x29, 0x3B, 0x76, 0x65, 0x72, 0x73, 0x69, +0x6F, 0x6E, 0x28, 0x29, 0x3B, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, 0x3C, 0x2F, +0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x3E, 0x0A, 0x3C, 0x2F, 0x62, 0x6F, 0x64, 0x79, 0x3E, 0x0A, +0x3C, 0x2F, 0x68, 0x74, 0x6D, 0x6C, 0x3E, 0x00 +}; diff --git a/lib-remoteconfig/http/content/time.js b/lib-remoteconfig/http/content/time.js new file mode 100755 index 00000000..bfc584b2 --- /dev/null +++ b/lib-remoteconfig/http/content/time.js @@ -0,0 +1,13 @@ +async function refresh() { + let data = await getJSON('timedate') + const node = formatDateTime(new Date(data.date)) + document.getElementById('nodeTime').textContent = `Node Time: ${node}` +} + +async function syncWithLocalTime() { + const node = formatDateTime(new Date()) + document.getElementById('nodeTime').textContent = `Node Time: ${node}` + const data = { date: node } + await post(data) + refresh() +} \ No newline at end of file diff --git a/lib-remoteconfig/http/content/time.js.h b/lib-remoteconfig/http/content/time.js.h new file mode 100644 index 00000000..c372882e --- /dev/null +++ b/lib-remoteconfig/http/content/time.js.h @@ -0,0 +1,27 @@ +static constexpr char time_js[] = { +0x61, 0x73, 0x79, 0x6E, 0x63, 0x20, 0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x72, +0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x28, 0x29, 0x20, 0x7B, 0x0A, 0x6C, 0x65, 0x74, 0x20, 0x64, +0x61, 0x74, 0x61, 0x20, 0x3D, 0x20, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x67, 0x65, 0x74, 0x4A, +0x53, 0x4F, 0x4E, 0x28, 0x27, 0x74, 0x69, 0x6D, 0x65, 0x64, 0x61, 0x74, 0x65, 0x27, 0x29, 0x0A, +0x63, 0x6F, 0x6E, 0x73, 0x74, 0x20, 0x6E, 0x6F, 0x64, 0x65, 0x20, 0x3D, 0x20, 0x66, 0x6F, 0x72, +0x6D, 0x61, 0x74, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x28, 0x6E, 0x65, 0x77, 0x20, +0x44, 0x61, 0x74, 0x65, 0x28, 0x64, 0x61, 0x74, 0x61, 0x2E, 0x64, 0x61, 0x74, 0x65, 0x29, 0x29, +0x0A, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, +0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x27, 0x6E, 0x6F, 0x64, 0x65, 0x54, 0x69, +0x6D, 0x65, 0x27, 0x29, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x43, 0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, +0x20, 0x3D, 0x20, 0x60, 0x4E, 0x6F, 0x64, 0x65, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x3A, 0x20, 0x24, +0x7B, 0x6E, 0x6F, 0x64, 0x65, 0x7D, 0x60, 0x0A, 0x7D, 0x0A, 0x61, 0x73, 0x79, 0x6E, 0x63, 0x20, +0x66, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x73, 0x79, 0x6E, 0x63, 0x57, 0x69, 0x74, +0x68, 0x4C, 0x6F, 0x63, 0x61, 0x6C, 0x54, 0x69, 0x6D, 0x65, 0x28, 0x29, 0x20, 0x7B, 0x0A, 0x63, +0x6F, 0x6E, 0x73, 0x74, 0x20, 0x6E, 0x6F, 0x64, 0x65, 0x20, 0x3D, 0x20, 0x66, 0x6F, 0x72, 0x6D, +0x61, 0x74, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x28, 0x6E, 0x65, 0x77, 0x20, 0x44, +0x61, 0x74, 0x65, 0x28, 0x29, 0x29, 0x0A, 0x64, 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, +0x67, 0x65, 0x74, 0x45, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x42, 0x79, 0x49, 0x64, 0x28, 0x27, +0x6E, 0x6F, 0x64, 0x65, 0x54, 0x69, 0x6D, 0x65, 0x27, 0x29, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x43, +0x6F, 0x6E, 0x74, 0x65, 0x6E, 0x74, 0x20, 0x3D, 0x20, 0x60, 0x4E, 0x6F, 0x64, 0x65, 0x20, 0x54, +0x69, 0x6D, 0x65, 0x3A, 0x20, 0x24, 0x7B, 0x6E, 0x6F, 0x64, 0x65, 0x7D, 0x60, 0x0A, 0x63, 0x6F, +0x6E, 0x73, 0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x3D, 0x20, 0x7B, 0x20, 0x64, 0x61, 0x74, +0x65, 0x3A, 0x20, 0x6E, 0x6F, 0x64, 0x65, 0x20, 0x7D, 0x0A, 0x61, 0x77, 0x61, 0x69, 0x74, 0x20, +0x70, 0x6F, 0x73, 0x74, 0x28, 0x64, 0x61, 0x74, 0x61, 0x29, 0x0A, 0x72, 0x65, 0x66, 0x72, 0x65, +0x73, 0x68, 0x28, 0x29, 0x0A, 0x7D, 0x00 +}; diff --git a/gd32_emac_e131_pixel_multi/include/pixeldmxstartstop.h b/lib-remoteconfig/include/httpd/http.h old mode 100644 new mode 100755 similarity index 60% rename from gd32_emac_e131_pixel_multi/include/pixeldmxstartstop.h rename to lib-remoteconfig/include/httpd/http.h index bca3ee30..1e59cac9 --- a/gd32_emac_e131_pixel_multi/include/pixeldmxstartstop.h +++ b/lib-remoteconfig/include/httpd/http.h @@ -1,8 +1,8 @@ /** - * @file pixeldmxstartstop.h + * @file http.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,31 +23,30 @@ * THE SOFTWARE. */ -#ifndef PIXELDMXSTARTSTOP_H_ -#define PIXELDMXSTARTSTOP_H_ - -#include "pixeldmxhandler.h" - -#include "gd32.h" -#include "gd32_gpio.h" - -class PixelDmxStartStop final: public PixelDmxHandler { -public: - PixelDmxStartStop() { - gd32_gpio_fsel(GD32_BOARD_LED2, GPIO_FSEL_OUTPUT); - gd32_gpio_clr(GD32_BOARD_LED2); - } - - ~PixelDmxStartStop() override { - } - - void Start() override { - gd32_gpio_set(GD32_BOARD_LED2); - } +#ifndef HTTPD_HTTP_H_ +#define HTTPD_HTTP_H_ + +namespace http { +static constexpr uint32_t BUFSIZE = 1440; //TODO We need the TCP max segment size here +enum class Status { + OK = 200, + BAD_REQUEST = 400, + NOT_FOUND = 404, + REQUEST_TIMEOUT = 408, + REQUEST_ENTITY_TOO_LARGE = 413, + REQUEST_URI_TOO_LONG = 414, + INTERNAL_SERVER_ERROR = 500, + METHOD_NOT_IMPLEMENTED = 501, + VERSION_NOT_SUPPORTED = 505, + UNKNOWN_ERROR = 520 +}; +enum class RequestMethod { + GET, POST, DELETE, UNKNOWN +}; - void Stop() override { - gd32_gpio_clr(GD32_BOARD_LED2); - } +enum class contentTypes { + TEXT_HTML, TEXT_CSS, TEXT_JS, APPLICATION_JSON, APPLICATION_OCTET_STREAM, NOT_DEFINED }; +} // namespace http -#endif /* PIXELDMXSTARTSTOP_H_ */ +#endif /* HTTPD_HTTP_H_ */ diff --git a/lib-remoteconfig/include/httpd/httpd.h b/lib-remoteconfig/include/httpd/httpd.h index dee20a58..80517f3a 100755 --- a/lib-remoteconfig/include/httpd/httpd.h +++ b/lib-remoteconfig/include/httpd/httpd.h @@ -2,7 +2,7 @@ * @file httpd.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,79 +23,40 @@ * THE SOFTWARE. */ -#ifndef HTTPD_H_ -#define HTTPD_H_ +#ifndef HTTPD_HTTPD_H_ +#define HTTPD_HTTPD_H_ #include -#include "network.h" +#include "http.h" +#include "httpdhandlerequest.h" -namespace http { -static constexpr uint32_t BUFSIZE = 1440; -enum class Status { - OK = 200, - BAD_REQUEST = 400, - NOT_FOUND = 404, - REQUEST_TIMEOUT = 408, - REQUEST_ENTITY_TOO_LARGE = 413, - REQUEST_URI_TOO_LONG = 414, - INTERNAL_SERVER_ERROR = 500, - METHOD_NOT_IMPLEMENTED = 501, - VERSION_NOT_SUPPORTED = 505, - UNKNOWN_ERROR = 520 -}; -enum class RequestMethod { - GET, POST, UNKNOWN -}; +#include "network.h" -enum class contentTypes { - TEXT_HTML, TEXT_CSS, TEXT_JS, APPLICATION_JSON, NOT_DEFINED -}; -} // namespace http +#include "../../lib-network/config/net_config.h" class HttpDaemon { public: HttpDaemon(); + ~HttpDaemon(); + void Run() { uint32_t nConnectionHandle; - m_nBytesReceived = Network::Get()->TcpRead(m_nHandle, const_cast(reinterpret_cast(&m_RequestHeaderResponse)), nConnectionHandle); + const auto nBytesReceived = Network::Get()->TcpRead(m_nHandle, const_cast(reinterpret_cast(&m_RequestHeaderResponse)), nConnectionHandle); - if (__builtin_expect((m_nBytesReceived == 0), 1)) { + if (__builtin_expect((nBytesReceived == 0), 1)) { return; } - HandleRequest(nConnectionHandle); - } + DEBUG_PRINTF("nConnectionHandle=%u", nConnectionHandle); -private: - void HandleRequest(const uint32_t nConnectionHandle); - http::Status ParseRequest(); - http::Status ParseMethod(char *pLine); - http::Status ParseHeaderField(char *pLine); - http::Status HandleGet(); - http::Status HandlePost(bool hasDataOnly); - http::Status HandleGetTxt(); + pHandleRequest[nConnectionHandle]->HandleRequest(nBytesReceived, m_RequestHeaderResponse); + } private: - const char *m_pContentType; - char *m_pUri { nullptr }; - char *m_pFileData { nullptr }; - char *m_RequestHeaderResponse { nullptr }; - - uint32_t m_nContentLength { 0 }; - uint32_t m_nFileDataLength { 0 }; - uint32_t m_nRequestContentLength { 0 }; + HttpDeamonHandleRequest *pHandleRequest[TCP_MAX_TCBS_ALLOWED]; int32_t m_nHandle { -1 }; - - uint32_t m_nBytesReceived { 0 }; - - http::Status m_Status { http::Status::UNKNOWN_ERROR }; - http::RequestMethod m_RequestMethod { http::RequestMethod::UNKNOWN }; - - bool m_bContentTypeJson { false }; - bool m_IsAction { false }; - - static char m_Content[http::BUFSIZE]; + char *m_RequestHeaderResponse { nullptr }; }; -#endif /* HTTPD_H_ */ +#endif /* HTTPD_HTTPD_H_ */ diff --git a/lib-remoteconfig/include/httpd/httpdhandlerequest.h b/lib-remoteconfig/include/httpd/httpdhandlerequest.h new file mode 100755 index 00000000..ee1d7c1f --- /dev/null +++ b/lib-remoteconfig/include/httpd/httpdhandlerequest.h @@ -0,0 +1,77 @@ +/** + * @file httpdhandlerequest.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HTTPD_HTTPDHANDLEREQUEST_H_ +#define HTTPD_HTTPDHANDLEREQUEST_H_ + +#include + +#include "http.h" + +#include "debug.h" + +class HttpDeamonHandleRequest { +public: + HttpDeamonHandleRequest(uint32_t nConnectionHandle, int32_t nHandle) : m_nConnectionHandle(nConnectionHandle), m_nHandle(nHandle) { + DEBUG_ENTRY + DEBUG_PRINTF("m_nConnectionHandle=%u", m_nConnectionHandle); + DEBUG_EXIT + } + + void HandleRequest(const uint32_t nBytesReceived, char *pRequestHeaderResponse); + +private: + http::Status ParseRequest(); + http::Status ParseMethod(char *pLine); + http::Status ParseHeaderField(char *pLine); + http::Status HandleGet(); + http::Status HandleGetTxt(); + http::Status HandlePost(const bool hasDataOnly); + http::Status HandleDelete(const bool hasDataOnly); + +private: + uint32_t m_nConnectionHandle; + int32_t m_nHandle; + uint32_t m_nContentSize { 0 }; + uint32_t m_nFileDataLength { 0 }; + uint32_t m_nRequestContentSize { 0 }; + uint32_t m_nBytesReceived { 0 }; + + char *m_pUri { nullptr }; + char *m_pFileData { nullptr }; + const char *m_pContent { nullptr }; + char *m_RequestHeaderResponse { nullptr }; + + http::Status m_Status { http::Status::UNKNOWN_ERROR }; + http::RequestMethod m_RequestMethod { http::RequestMethod::UNKNOWN }; + http::contentTypes m_ContentType { http::contentTypes::NOT_DEFINED }; + + bool m_IsAction { false }; + + static char m_DynamicContent[http::BUFSIZE]; +}; + + +#endif /* HTTPD_HTTPDHANDLEREQUEST_H_ */ diff --git a/lib-remoteconfig/include/remoteconfig.h b/lib-remoteconfig/include/remoteconfig.h index 25d76f50..b851f56c 100644 --- a/lib-remoteconfig/include/remoteconfig.h +++ b/lib-remoteconfig/include/remoteconfig.h @@ -2,7 +2,7 @@ * @file remoteconfig.h * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,6 +27,7 @@ #define REMOTECONFIG_H_ #include +#include #if defined (NODE_ARTNET_MULTI) # define NODE_ARTNET @@ -48,17 +49,20 @@ # include "node.h" #endif -#include "configstore.h" - #if defined(ENABLE_TFTP_SERVER) # include "tftp/tftpfileserver.h" #endif +#if defined (ENABLE_HTTPD) +# include "httpd/httpd.h" +#endif + +#include "configstore.h" #include "network.h" namespace remoteconfig { namespace udp { -static constexpr auto BUFFER_SIZE = 1024; +static constexpr auto BUFFER_SIZE = 1420; } // namespace udp enum class Node { @@ -77,6 +81,7 @@ enum class Node { RDMRESPONDER, LAST }; + enum class Output { DMX, RDM, @@ -90,14 +95,10 @@ enum class Output { ARTNET, SERIAL, RGBPANEL, + PWM, LAST }; -enum { - DISPLAY_NAME_LENGTH = 24, - ID_LENGTH = (32 + remoteconfig::DISPLAY_NAME_LENGTH + 2) // +2, comma and \n -}; - enum class TxtFile { RCONFIG, NETWORK, @@ -127,13 +128,19 @@ enum class TxtFile { RGBPANEL, LTCETC, NODE, + ENV, LAST }; + +enum { + DISPLAY_NAME_LENGTH = 24, + ID_LENGTH = (32 + remoteconfig::DISPLAY_NAME_LENGTH + 2) // +2, comma and \n +}; } // namespace remoteconfig class RemoteConfig { public: - RemoteConfig(remoteconfig::Node tType, remoteconfig::Output tMode, uint32_t nOutputs = 0); + RemoteConfig(const remoteconfig::Node node, const remoteconfig::Output output, const uint32_t nActiveOutputs = 0); ~RemoteConfig(); const char *GetStringNode() const; @@ -209,6 +216,10 @@ class RemoteConfig { } #endif +#if defined (ENABLE_HTTPD) + m_pHttpDaemon->Run(); +#endif + uint16_t nForeignPort; m_nBytesReceived = Network::Get()->RecvFrom(m_nHandle, const_cast(reinterpret_cast(&s_pUdpBuffer)), &m_nIPAddressFrom, &nForeignPort); @@ -228,7 +239,9 @@ class RemoteConfig { void HandleReboot(); void HandleFactory(); void HandleList(); +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) void HandleUptime(); +#endif void HandleVersion(); void HandleGetNoParams() { @@ -236,6 +249,7 @@ class RemoteConfig { } void HandleGetRconfigTxt(uint32_t& nSize); + void HandleGetEnvTxt(uint32_t& nSize); void HandleGetNetworkTxt(uint32_t& nSize); #if defined (DISPLAY_UDF) @@ -286,7 +300,7 @@ class RemoteConfig { #if defined (RDM_RESPONDER) void HandleGetRdmDeviceTxt(uint32_t& nSize); void HandleGetRdmSensorsTxt(uint32_t& nSize); -# if defined (ENABLE_RDM_SUBDEVICES) +# if defined (CONFIG_RDM_ENABLE_SUBDEVICES) void HandleGetRdmSubdevTxt(uint32_t& nSize); # endif #endif @@ -340,7 +354,12 @@ class RemoteConfig { void HandleGetRgbPanelTxt(uint32_t& nSize); #endif - void HandleSetRconfig(); +#if defined (OUTPUT_DMX_PCA9685) + void HandleGetPca9685Txt(uint32_t& nSize); +#endif + + void HandleSetRconfigTxt(); + void HandleSetEnvTxt(); void HandleSetNetworkTxt(); #if defined (DISPLAY_UDF) @@ -391,7 +410,7 @@ class RemoteConfig { #if defined (RDM_RESPONDER) void HandleSetRdmDeviceTxt(); void HandleSetRdmSensorsTxt(); -# if defined (ENABLE_RDM_SUBDEVICES) +# if defined (CONFIG_RDM_ENABLE_SUBDEVICES) void HandleSetRdmSubdevTxt(); # endif #endif @@ -416,6 +435,10 @@ class RemoteConfig { void HandleSetRgbPanelTxt(); #endif +#if defined (OUTPUT_DMX_PCA9685) + void HandleSetPca9685Txt(); +#endif + #if defined (OUTPUT_DMX_STEPPER) void HandleSetSparkFunTxt(); void HandleSetMotorTxt(uint32_t nMotorIndex); @@ -449,6 +472,8 @@ class RemoteConfig { void HandleDisplayGet(); void HandleTftpSet(); void HandleTftpGet(); + void HandleRdmSet(); + void HandleRdmGet(); void PlatformHandleTftpSet(); void PlatformHandleTftpGet(); @@ -473,7 +498,6 @@ class RemoteConfig { void (RemoteConfig::*SetHandler)(); const char *pFileName; const uint8_t nFileNameLength; - const configstore::Store nStore; }; static const Txt s_TXT[]; @@ -505,6 +529,10 @@ class RemoteConfig { #endif bool m_bEnableTFTP { false }; +#if defined (ENABLE_HTTPD) + HttpDaemon *m_pHttpDaemon { nullptr }; +#endif + static char *s_pUdpBuffer; static RemoteConfig *s_pThis; diff --git a/lib-remoteconfig/include/remoteconfigconst.h b/lib-remoteconfig/include/remoteconfigconst.h index 553d5ec6..9a3da1d4 100644 --- a/lib-remoteconfig/include/remoteconfigconst.h +++ b/lib-remoteconfig/include/remoteconfigconst.h @@ -2,7 +2,7 @@ * @file remoteconfigconst.h * */ -/* Copyright (C) 2019-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-remoteconfig/include/remoteconfigjson.h b/lib-remoteconfig/include/remoteconfigjson.h index d959dbe0..1e9f99ea 100644 --- a/lib-remoteconfig/include/remoteconfigjson.h +++ b/lib-remoteconfig/include/remoteconfigjson.h @@ -2,7 +2,7 @@ * @file remoteconfig.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,17 +29,54 @@ #include namespace remoteconfig { -uint16_t json_get_list(char *pOutBuffer, const uint16_t nOutBufferSize); -uint16_t json_get_version(char *pOutBuffer, const uint16_t nOutBufferSize); -uint16_t json_get_uptime(char *pOutBuffer, const uint16_t nOutBufferSize); -uint16_t json_get_display(char *pOutBuffer, const uint16_t nOutBufferSize); -uint16_t json_get_directory(char *pOutBuffer, const uint16_t nOutBufferSize); +uint32_t json_get_list(char *pOutBuffer, const uint32_t nOutBufferSize); +uint32_t json_get_version(char *pOutBuffer, const uint32_t nOutBufferSize); +uint32_t json_get_uptime(char *pOutBuffer, const uint32_t nOutBufferSize); +uint32_t json_get_display(char *pOutBuffer, const uint32_t nOutBufferSize); +uint32_t json_get_directory(char *pOutBuffer, const uint32_t nOutBufferSize); namespace net { -uint16_t json_get_phystatus(char *pOutBuffer, const uint16_t nOutBufferSize); +uint32_t json_get_phystatus(char *pOutBuffer, const uint32_t nOutBufferSize); } // namespace net +namespace dmx { +uint32_t json_get_ports(char *pOutBuffer, const uint32_t nOutBufferSize); +uint32_t json_get_portstatus(const char cPort, char *pOutBuffer, const uint32_t nOutBufferSize); +} // namespace dmx +namespace rdm { +uint32_t json_get_rdm(char *pOutBuffer, const uint32_t nOutBufferSize); +uint32_t json_get_queue(char *pOutBuffer, const uint32_t nOutBufferSize); +uint32_t json_get_portstatus(char *pOutBuffer, const uint32_t nOutBufferSize); +uint32_t json_get_tod(const char cPort, char *pOutBuffer, const uint32_t nOutBufferSize); +} // namespace rdm +namespace storage { +uint32_t json_get_directory(char *pOutBuffer, const uint32_t nOutBufferSize); +} // namespace storage namespace dsa { -uint16_t json_get_portstatus(char *pOutBuffer, const uint16_t nOutBufferSize); +uint32_t json_get_portstatus(char *pOutBuffer, const uint32_t nOutBufferSize); +uint32_t json_get_vlantable(char *pOutBuffer, const uint32_t nOutBufferSize); } // namespace dsa +namespace showfile { +uint32_t json_get_status(char *pOutBuffer, const uint32_t nOutBufferSize); +uint32_t json_get_directory(char *pOutBuffer, const uint32_t nOutBufferSize); +void json_set_status(const char *pBuffer, const uint32_t nBufferSize); +void json_delete(const char *pBuffer, const uint32_t nBufferSize); +} // namespace showfile +namespace timedate { +uint32_t json_get_timeofday(char *pOutBuffer, const uint32_t nOutBufferSize); +void json_set_timeofday(const char *pBuffer, const uint32_t nBufferSize); +} // namespace timedate +namespace rtc { +uint32_t json_get_rtc(char *pOutBuffer, const uint32_t nOutBufferSize); +void json_set_rtc(const char *pBuffer, const uint32_t nBufferSize); +} // namespace rtc +namespace artnet { +namespace controller { +uint32_t json_get_polltable(char *pOutBuffer, const uint32_t nOutBufferSize); +} // namespace controller +} // namespace artnet +namespace pixel { +uint32_t json_get_types(char *pOutBuffer, const uint32_t nOutBufferSize); +uint32_t json_get_status(char *pOutBuffer, const uint32_t nOutBufferSize); +} // namespace pixel } // namespace remoteconfig #endif /* REMOTECONFIGJSON_H_ */ diff --git a/lib-remoteconfig/include/remoteconfigparams.h b/lib-remoteconfig/include/remoteconfigparams.h index ea161ed6..58ce482b 100644 --- a/lib-remoteconfig/include/remoteconfigparams.h +++ b/lib-remoteconfig/include/remoteconfigparams.h @@ -2,7 +2,7 @@ * @file remoteconfigparams.h * */ -/* Copyright (C) 2019-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,8 +29,10 @@ #include #include "remoteconfig.h" +#include "configstore.h" -struct TRemoteConfigParams { +namespace remoteconfigparams { +struct Params { uint32_t nSetList; uint8_t NotUsed0; uint8_t NotUsed1; @@ -39,34 +41,37 @@ struct TRemoteConfigParams { char aDisplayName[remoteconfig::DISPLAY_NAME_LENGTH]; } __attribute__((packed)); -static_assert(sizeof(struct TRemoteConfigParams) <= 48, "struct TRemoteConfigParams is too large"); +static_assert(sizeof(struct Params) <= 48, "struct Params is too large"); -struct RemoteConfigParamsMask { - static constexpr auto DISABLE = (1U << 0); - static constexpr auto DISABLE_WRITE = (1U << 1); - static constexpr auto ENABLE_REBOOT = (1U << 2); - static constexpr auto ENABLE_UPTIME = (1U << 3); - static constexpr auto DISPLAY_NAME = (1U << 4); - static constexpr auto ENABLE_FACTORY = (1U << 5); +struct Mask { + static constexpr uint32_t DISABLE = (1U << 0); + static constexpr uint32_t DISABLE_WRITE = (1U << 1); + static constexpr uint32_t ENABLE_REBOOT = (1U << 2); + static constexpr uint32_t ENABLE_UPTIME = (1U << 3); + static constexpr uint32_t DISPLAY_NAME = (1U << 4); + static constexpr uint32_t ENABLE_FACTORY = (1U << 5); }; +} // namespace remoteconfigparams class RemoteConfigParamsStore { public: - virtual ~RemoteConfigParamsStore() { + static void Update(const struct remoteconfigparams::Params *pParams) { + ConfigStore::Get()->Update(configstore::Store::RCONFIG, pParams, sizeof(struct remoteconfigparams::Params)); } - virtual void Update(const struct TRemoteConfigParams *pRemoteConfigParams)=0; - virtual void Copy(struct TRemoteConfigParams *pRemoteConfigParams)=0; + static void Copy(struct remoteconfigparams::Params *pParams) { + ConfigStore::Get()->Copy(configstore::Store::RCONFIG, pParams, sizeof(struct remoteconfigparams::Params)); + } }; class RemoteConfigParams { public: - RemoteConfigParams(RemoteConfigParamsStore *pRemoteConfigParamsStore); + RemoteConfigParams(); - bool Load(); + void Load(); void Load(const char *pBuffer, uint32_t nLength); - void Builder(const struct TRemoteConfigParams *pRemoteConfigParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); + void Builder(const struct remoteconfigparams::Params *pRemoteConfigParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); void Save(char *pBuffer, uint32_t nLength, uint32_t& nSize) { Builder(nullptr, pBuffer, nLength, nSize); } @@ -74,23 +79,21 @@ class RemoteConfigParams { void Set(RemoteConfig *); const char *GetDisplayName() const { - return m_tRemoteConfigParams.aDisplayName; + return m_Params.aDisplayName; } - void Dump(); - static void staticCallbackFunction(void *p, const char *s); private: + void Dump(); void callbackFunction(const char *pLine); void SetBool(const uint8_t nValue, const uint32_t nMask); bool isMaskSet(uint32_t nMask) const { - return (m_tRemoteConfigParams.nSetList & nMask) == nMask; + return (m_Params.nSetList & nMask) == nMask; } private: - RemoteConfigParamsStore *m_pRemoteConfigParamsStore; - TRemoteConfigParams m_tRemoteConfigParams; + remoteconfigparams::Params m_Params; }; #endif /* REMOTECONFIGPARAMS_H_ */ diff --git a/lib-remoteconfig/include/shell/shell.h b/lib-remoteconfig/include/shell/shell.h old mode 100644 new mode 100755 index c3fd3b3f..c8a5247c --- a/lib-remoteconfig/include/shell/shell.h +++ b/lib-remoteconfig/include/shell/shell.h @@ -3,7 +3,7 @@ * */ /* Copyright (C) 2020 by hippy mailto:dmxout@gmail.com - * Copyright (C) 2020-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl + * Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -44,18 +44,35 @@ enum class CmdIndex: uint32_t { GET, DHCP, DATE, + PHY, +#if !defined (DISABLE_RTC) HWCLOCK, -#ifndef NDEBUG +#endif +#if defined (DEBUG_I2C) I2CDETECT, +#endif DUMP, MEM, +#if defined (ENABLE_NTP_CLIENT) NTP, +#endif +#if defined (CONFIG_SHELL_GPS) GPS, +#endif +#if (PHY_TYPE == RTL8201F) + PHY_TYPE_RTL8201F, #endif HELP }; static constexpr auto BUFLEN = 196; static constexpr auto MAXARG = 4; + +namespace msg { +namespace error { +static constexpr char INVALID[] = "Invalid command.\n"; +static constexpr char INTERNAL[] = "Internal error.\n"; +} // namespace error +} // namespace msg } // namespace shell class Shell { @@ -75,34 +92,33 @@ class Shell { int Printf(const char* fmt, ...); // shell.cpp const char *ReadLine(uint32_t& nLength); - uint16_t ValidateCmd(uint32_t nLength, shell::CmdIndex &nCmdIndex); - void ValidateArg(uint16_t nOffset, uint32_t nLength); + uint32_t ValidateCmd(const uint32_t nLength, shell::CmdIndex &nCmdIndex); + void ValidateArg(uint32_t nOffset, const uint32_t nLength); // shellcmd.cpp - uint32_t hexadecimalToDecimal(const char *pHexValue, uint32_t nLength); void CmdReboot(); void CmdInfo(); void CmdSet(); void CmdGet(); void CmdDhcp(); void CmdDate(); + void CmdPhy(); void CmdHwClock(); -#ifndef NDEBUG void CmdI2cDetect(); void CmdDump(); void CmdMem(); void CmdNtp(); void CmdGps(); -#endif + void CmdPhyTypeRTL8201F(); void CmdHelp(); private: - bool m_bIsEndOfLine { false }; - uint16_t m_nLength { 0 }; char m_Buffer[shell::BUFLEN]; uint32_t m_Argc { 0 }; + uint32_t m_nLength { 0 }; char *m_Argv[shell::MAXARG] { nullptr }; uint16_t m_nArgvLength[shell::MAXARG]; bool m_bShownPrompt { false }; + bool m_bIsEndOfLine { false }; // Firmware specific BEGIN #if defined (LTC_READER) diff --git a/lib-remoteconfig/include/tftp/tftpfileserver.h b/lib-remoteconfig/include/tftp/tftpfileserver.h old mode 100644 new mode 100755 index e5c5e407..16a4c7d3 --- a/lib-remoteconfig/include/tftp/tftpfileserver.h +++ b/lib-remoteconfig/include/tftp/tftpfileserver.h @@ -2,7 +2,7 @@ * @file tftpfileserver.h * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,7 +29,7 @@ #include #include -#include "tftpdaemon.h" +#include "net/apps/tftpdaemon.h" #if defined (GD32) # include "gd32.h" @@ -37,7 +37,8 @@ namespace tftpfileserver { bool is_valid(const void *pBuffer); -#if defined (BARE_METAL) +#if defined(__linux__) || defined (__APPLE__) +#else # if defined (H3) # if defined(ORANGE_PI) static constexpr char FILE_NAME[] = "orangepi_zero.uImage"; @@ -51,8 +52,10 @@ namespace tftpfileserver { static constexpr char FILE_NAME[] = "gd32f207.bin"; # elif defined (GD32F4XX) static constexpr char FILE_NAME[] = "gd32f4xx.bin"; +# elif defined (GD32H7XX) + static constexpr char FILE_NAME[] = "gd32h7xx.bin"; # else -# error MCU is not defined +# error FAMILY is not defined # endif # endif #endif diff --git a/lib-remoteconfig/src/gd32/remoteconfig.cpp b/lib-remoteconfig/src/gd32/remoteconfig.cpp index 741a69bf..a6682792 100644 --- a/lib-remoteconfig/src/gd32/remoteconfig.cpp +++ b/lib-remoteconfig/src/gd32/remoteconfig.cpp @@ -35,10 +35,10 @@ void RemoteConfig::PlatformHandleTftpSet() { if (m_bEnableTFTP) { bkp_data_write(BKP_DATA_1, 0xA5A5); - Display::Get()->TextStatus("TFTP On ", Display7SegmentMessage::INFO_TFTP_ON, CONSOLE_GREEN); + Display::Get()->TextStatus("TFTP On ", CONSOLE_GREEN); } else { bkp_data_write(BKP_DATA_1, 0x0); - Display::Get()->TextStatus("TFTP Off", Display7SegmentMessage::INFO_TFTP_OFF, CONSOLE_GREEN); + Display::Get()->TextStatus("TFTP Off", CONSOLE_GREEN); } DEBUG_EXIT diff --git a/lib-remoteconfig/src/gd32/shellcmd.cpp b/lib-remoteconfig/src/gd32/shellcmd.cpp new file mode 100644 index 00000000..9fac3ea3 --- /dev/null +++ b/lib-remoteconfig/src/gd32/shellcmd.cpp @@ -0,0 +1,31 @@ +/** + * @file shellcmd.cpp + * + */ +/* Copyright (C) 2020 by hippy mailto:dmxout@gmail.com + * Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shell/shell.h" + +void Shell::CmdDump() { + Puts(shell::msg::error::INVALID); +} diff --git a/lib-remoteconfig/src/gd32/tftpfileserver.cpp b/lib-remoteconfig/src/gd32/tftpfileserver.cpp index 639f7280..9c2c2886 100644 --- a/lib-remoteconfig/src/gd32/tftpfileserver.cpp +++ b/lib-remoteconfig/src/gd32/tftpfileserver.cpp @@ -31,7 +31,7 @@ #include "debug.h" namespace tftpfileserver { -bool is_valid(__attribute__((unused)) const void *pBuffer) { +bool is_valid([[maybe_unused]] const void *pBuffer) { return true; } } // namespace tftpfileserver diff --git a/lib-remoteconfig/src/httpd/get_file_content.cpp b/lib-remoteconfig/src/httpd/get_file_content.cpp index 47b03edb..75ad6413 100755 --- a/lib-remoteconfig/src/httpd/get_file_content.cpp +++ b/lib-remoteconfig/src/httpd/get_file_content.cpp @@ -2,7 +2,7 @@ * @file get_file_content.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -59,12 +59,12 @@ static http::contentTypes getContentType(const char *pFileName) { return http::contentTypes::NOT_DEFINED; } -int get_file_content(const char *fileName, char *pDst, http::contentTypes& contentType) { +uint32_t get_file_content(const char *fileName, char *pDst, http::contentTypes& contentType) { auto *pFile = fopen(fileName, "r"); if (pFile == nullptr) { DEBUG_EXIT - return -1; + return 0; } contentType = getContentType(fileName); @@ -72,7 +72,7 @@ int get_file_content(const char *fileName, char *pDst, http::contentTypes& conte if (contentType == http::contentTypes::NOT_DEFINED) { DEBUG_EXIT fclose(pFile); - return -2; + return 0; } auto doRemoveWhiteSpaces = true; @@ -81,7 +81,7 @@ int get_file_content(const char *fileName, char *pDst, http::contentTypes& conte while ((c = fgetc(pFile)) != EOF) { if (doRemoveWhiteSpaces) { - if (c < ' ') { + if (c <= ' ') { continue; } else { doRemoveWhiteSpaces = false; @@ -101,22 +101,41 @@ int get_file_content(const char *fileName, char *pDst, http::contentTypes& conte fclose(pFile); DEBUG_PRINTF("%s -> %d", fileName, static_cast(p - pDst)); - return static_cast(p - pDst); + return static_cast(p - pDst); +} + +static char s_StaticContent[http::BUFSIZE]; + +const char *get_file_content(const char *pFileName, uint32_t& nSize, http::contentTypes& contentType) { + DEBUG_ENTRY + DEBUG_PUTS(pFileName); + + nSize = get_file_content(pFileName, s_StaticContent, contentType); + + if (nSize != 0) { + return s_StaticContent; + } + + DEBUG_EXIT + return nullptr; } #else -int get_file_content(const char *pFileName, char *pDst, http::contentTypes& contentType) { +const char *get_file_content(const char *pFileName, uint32_t& nSize, http::contentTypes& contentType) { + DEBUG_ENTRY + DEBUG_PUTS(pFileName); + for (auto& content : HttpContent) { if (strcmp(pFileName, content.pFileName) == 0) { - assert(content.nContentLength < http::BUFSIZE); - memcpy(pDst, content.pContent, content.nContentLength); - - DEBUG_PRINTF("%s -> %d", content.pFileName, content.nContentLength); + nSize = content.nContentLength; contentType = content.contentType; - return static_cast(content.nContentLength); + return content.pContent; } } + nSize = 0; + contentType = http::contentTypes::NOT_DEFINED; + DEBUG_EXIT - return -1; + return nullptr; } #endif diff --git a/lib-remoteconfig/src/httpd/httd.cpp b/lib-remoteconfig/src/httpd/httd.cpp deleted file mode 100755 index 9ef81762..00000000 --- a/lib-remoteconfig/src/httpd/httd.cpp +++ /dev/null @@ -1,471 +0,0 @@ -/** - * @file httd.cpp - * - */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "httpd/httpd.h" -#include "remoteconfig.h" -#include "remoteconfigjson.h" -#include "properties.h" -#include "sscan.h" -#include "propertiesconfig.h" -#include "../http/content/json_switch.h" - -#include "network.h" -#include "hardware.h" -#include "display.h" - -#include "debug.h" - -#if defined ENABLE_CONTENT -extern int get_file_content(const char *fileName, char *pDst, http::contentTypes& contentType); -#endif - -char HttpDaemon::m_Content[http::BUFSIZE]; - -using namespace http; - -static constexpr char s_contentType[static_cast(contentTypes::NOT_DEFINED)][32] = - { "text/html", "text/css", "text/javascript", "application/json" }; - -HttpDaemon::HttpDaemon() : m_pContentType(s_contentType[static_cast(contentTypes::TEXT_HTML)]) { - DEBUG_ENTRY - - assert(m_nHandle == -1); - m_nHandle = Network::Get()->TcpBegin(80); - assert(m_nHandle != -1); - - DEBUG_EXIT -} - -void HttpDaemon::HandleRequest(const uint32_t nConnectionHandle) { - const char *pStatusMsg = "OK"; - - DEBUG_PRINTF("%u: m_Status=%u, m_RequestMethod=%u", nConnectionHandle, static_cast(m_Status), static_cast(m_RequestMethod)); - - if (m_Status == Status::UNKNOWN_ERROR) { - m_Status = ParseRequest(); - if (m_Status == Status::OK) { - if (m_RequestMethod == RequestMethod::GET) { - m_Status = HandleGet(); - } else if (m_RequestMethod == RequestMethod::POST) { - m_Status = HandlePost(false); - if ((m_Status == Status::OK) && (m_nFileDataLength == 0)) { - DEBUG_PUTS("There is a POST header only -> no data"); - return; - } - } - } - } else if ((m_Status == Status::OK) && (m_RequestMethod == RequestMethod::POST)) { - m_Status = HandlePost(true); - } - - if (m_Status != Status::OK) { - switch (m_Status) { - case Status::BAD_REQUEST: - pStatusMsg = "Bad Request"; - break; - case Status::NOT_FOUND: - pStatusMsg = "Not Found"; - break; - case Status::REQUEST_ENTITY_TOO_LARGE: - pStatusMsg = "Request Entity Too Large"; - break; - case Status::REQUEST_URI_TOO_LONG: - pStatusMsg = "Request-URI Too Long"; - break; - case Status::INTERNAL_SERVER_ERROR: - pStatusMsg = "Internal Server Error"; - break; - case Status::METHOD_NOT_IMPLEMENTED: - pStatusMsg = "Method Not Implemented"; - break; - case Status::VERSION_NOT_SUPPORTED: - pStatusMsg = "Version Not Supported"; - break; - default: - pStatusMsg = "Unknown Error"; - break; - } - - m_pContentType = s_contentType[static_cast(contentTypes::TEXT_HTML)]; - m_nContentLength = static_cast(snprintf(m_Content, BUFSIZE - 1U, - "\n" - "\n" - "%u %s\n" - "

                      %s

                      \n" - "\n", static_cast(m_Status), pStatusMsg, pStatusMsg)); - } - - uint8_t nLength; - const int nHeaderLength = snprintf(m_RequestHeaderResponse, BUFSIZE - 1U, - "HTTP/1.1 %u %s\r\n" - "Server: %s\r\n" - "Content-Type: %s\r\n" - "Content-Length: %u\r\n" - "Connection: close\r\n" - "\r\n", static_cast(m_Status), pStatusMsg, Hardware::Get()->GetBoardName(nLength), m_pContentType, m_nContentLength); - - Network::Get()->TcpWrite(m_nHandle, reinterpret_cast(m_RequestHeaderResponse), static_cast(nHeaderLength), nConnectionHandle); - Network::Get()->TcpWrite(m_nHandle, reinterpret_cast(m_Content), static_cast(m_nContentLength), nConnectionHandle); - DEBUG_PRINTF("m_nContentLength=%u", m_nContentLength); - - m_Status = Status::UNKNOWN_ERROR; - m_RequestMethod = RequestMethod::UNKNOWN; -} - -Status HttpDaemon::ParseRequest() { - char *pLine = m_RequestHeaderResponse; - uint32_t nLine = 0; - Status status = Status::UNKNOWN_ERROR; - m_bContentTypeJson = false; - m_nRequestContentLength = 0; - m_nFileDataLength = 0; - - for (uint32_t i = 0; i < m_nBytesReceived; i++) { - if (m_RequestHeaderResponse[i] == '\n') { - assert(i > 1); - m_RequestHeaderResponse[i - 1] = '\0'; - - if (nLine++ == 0) { - status = ParseMethod(pLine); - } else { - if (pLine[0] == '\0') { - assert((i + 1) <= m_nBytesReceived); - m_nFileDataLength = static_cast(m_nBytesReceived - 1 - i); - if (m_nFileDataLength > 0) { - m_pFileData = &m_RequestHeaderResponse[i + 1]; - m_pFileData[m_nFileDataLength] = '\0'; - } - return Status::OK; - } - status = ParseHeaderField(pLine); - } - - if (status != Status::OK) { - return status; - } - - pLine = &m_RequestHeaderResponse[++i]; - } - } - - return Status::OK; -} - -/** - * Supported: "METHOD uri HTTP/1.1" - * Where METHOD is "GET" or "POST" - */ - -Status HttpDaemon::ParseMethod(char *pLine) { - assert(pLine != nullptr); - char *pToken; - - if ((pToken = strtok(pLine, " ")) == nullptr) { - return Status::METHOD_NOT_IMPLEMENTED; - } - - if (strcmp(pToken, "GET") == 0) { - m_RequestMethod = RequestMethod::GET; - } else if (strcmp(pToken, "POST") == 0) { - m_RequestMethod = RequestMethod::POST; - } else { - return Status::METHOD_NOT_IMPLEMENTED; - } - - if ((pToken = strtok(nullptr, " ")) == nullptr) { - return Status::BAD_REQUEST; - } - - m_pUri = pToken; - - if ((pToken = strtok(nullptr, "/")) == nullptr || strcmp(pToken, "HTTP") != 0) { - return Status::BAD_REQUEST; - } - - if ((pToken = strtok(nullptr, " \n")) == nullptr) { - return Status::BAD_REQUEST; - } - - if (strcmp(pToken, "1.1") != 0) { - return Status::VERSION_NOT_SUPPORTED; - } - - return Status::OK; -} - -/** - * Only interested in "Content-Type" and - * "Content-Length" - * Where we check for "Content-Type: application/json" - */ - -Status HttpDaemon::ParseHeaderField(char *pLine) { - char *pToken; - - assert(pLine != 0); - if ((pToken = strtok(pLine, ":")) == nullptr) { - return Status::BAD_REQUEST; - } - - if (strcasecmp(pToken, "Content-Type") == 0) { - if ((pToken = strtok(nullptr, " ;")) == nullptr) { - return Status::BAD_REQUEST; - } - if (strcmp(pToken, "application/json") == 0) { - m_bContentTypeJson = true; - } - } else if (strcasecmp(pToken, "Content-Length") == 0) { - if ((pToken = strtok(nullptr, " ")) == nullptr) { - return Status::BAD_REQUEST; - } - - uint32_t nTmp = 0; - while (*pToken != '\0') { - auto nDigit = static_cast(*pToken++ - '0'); - if (nDigit > 9) { - return Status::BAD_REQUEST; - } - - nTmp *= 10; - nTmp += nDigit; - - if (nTmp > BUFSIZE) { - return Status::REQUEST_ENTITY_TOO_LARGE; - } - } - - m_nRequestContentLength = nTmp; - } - - DEBUG_EXIT - return Status::OK; -} - -/** - * GET - */ - -Status HttpDaemon::HandleGet() { - int nLength = 0; - - if (memcmp(m_pUri, "/json/", 6) == 0) { - m_pContentType = s_contentType[static_cast(contentTypes::APPLICATION_JSON)]; - const auto *pGet = &m_pUri[6]; - switch (http::get_uint(pGet)) { - case http::json::get::LIST: - nLength = remoteconfig::json_get_list(m_Content, sizeof(m_Content)); - break; - case http::json::get::VERSION: - nLength = remoteconfig::json_get_version(m_Content, sizeof(m_Content)); - break; - case http::json::get::UPTIME: - if (!RemoteConfig::Get()->IsEnableUptime()) { - DEBUG_PUTS("Status::BAD_REQUEST"); - return Status::BAD_REQUEST; - } - nLength = remoteconfig::json_get_uptime(m_Content, sizeof(m_Content)); - break; - case http::json::get::DISPLAY: - nLength = remoteconfig::json_get_display(m_Content, sizeof(m_Content)); - break; - case http::json::get::DIRECTORY: - nLength = remoteconfig::json_get_directory(m_Content, sizeof(m_Content)); - break; -#if defined (ENABLE_NET_PHYSTATUS) - case http::json::get::PHYSTATUS: - nLength = remoteconfig::net::json_get_phystatus(m_Content, sizeof(m_Content)); - break; -#endif - default: -#if defined (ENABLE_PHY_SWITCH) - if (memcmp(pGet, "dsa/", 4) == 0) { - const auto *pDsa = &pGet[4]; - switch (http::get_uint(pDsa)) { - case http::json::get::PORTSTATUS: - nLength = remoteconfig::dsa::json_get_portstatus(m_Content, sizeof(m_Content)); - break; - default: - break; - } - } else { -#endif - return HandleGetTxt(); -#if defined (ENABLE_PHY_SWITCH) - } -#endif - break; - } - } -#if defined (ENABLE_CONTENT) - else if (strcmp(m_pUri, "/") == 0) { - http::contentTypes contentType; - nLength = get_file_content("index.html", m_Content, contentType); - m_pContentType = s_contentType[static_cast(contentType)]; - } -#if defined (ENABLE_PHY_SWITCH) - else if (strcmp(m_pUri, "/dsa") == 0) { - http::contentTypes contentType; - nLength = get_file_content("dsa.html", m_Content, contentType); - m_pContentType = s_contentType[static_cast(contentType)]; - } -#endif - else { - http::contentTypes contentType; - nLength = get_file_content(&m_pUri[1], m_Content, contentType); - m_pContentType = s_contentType[static_cast(contentType)]; - } -#endif - - if (nLength <= 0) { - DEBUG_EXIT - return Status::NOT_FOUND; - } - - m_nContentLength = static_cast(nLength); - - DEBUG_EXIT - return Status::OK; -} - -Status HttpDaemon::HandleGetTxt() { - auto *pFileName = &m_pUri[6]; - const auto nLength = strlen(pFileName); - - if (nLength <= 4) { - return Status::BAD_REQUEST; - } - - if (strcmp(&pFileName[nLength - 4], ".txt") != 0) { - return Status::BAD_REQUEST; - } - - const auto bIsJSON = PropertiesConfig::IsJSON(); - - PropertiesConfig::EnableJSON(true); - const auto nBytes = RemoteConfig::Get()->HandleGet(reinterpret_cast(pFileName), BUFSIZE - 5U); - - PropertiesConfig::EnableJSON(bIsJSON); - - DEBUG_PRINTF("nBytes=%d", nBytes); - - if (nBytes <= 0) { - return Status::BAD_REQUEST; - } - - m_nContentLength = static_cast(nBytes); - memcpy(m_Content, reinterpret_cast(pFileName), nBytes); - - return Status::OK; -} - -/** - * POST - */ - -Status HttpDaemon::HandlePost(bool hasDataOnly) { - DEBUG_PRINTF("m_nBytesReceived=%d, m_nFileDataLength=%u, m_nRequestContentLength=%u -> hasDataOnly=%c", m_nBytesReceived, m_nFileDataLength, m_nRequestContentLength, hasDataOnly ? 'Y' : 'N'); - - if (!hasDataOnly) { - if (!m_bContentTypeJson) { - return Status::BAD_REQUEST; - } - - m_IsAction = (strcmp(m_pUri, "/json/action") == 0); - - if (!m_IsAction && (strcmp(m_pUri, "/json") != 0)) { - return Status::NOT_FOUND; - } - } - - const auto hasHeadersOnly = (!hasDataOnly && ((m_nBytesReceived < m_nRequestContentLength) || m_nFileDataLength == 0)); - - if (hasHeadersOnly) { - DEBUG_PUTS("hasHeadersOnly"); - return Status::OK; - } - - - if (hasDataOnly) { - m_pFileData = m_RequestHeaderResponse; - m_nFileDataLength = static_cast(m_nBytesReceived); - } - - DEBUG_PRINTF("%d|%.*s|->%d", m_nFileDataLength, m_nFileDataLength, m_pFileData, m_IsAction); - - if (m_IsAction) { - if (properties::convert_json_file(m_pFileData, m_nFileDataLength, true) <= 0) { - DEBUG_PUTS("Status::BAD_REQUEST"); - return Status::BAD_REQUEST; - } - - uint8_t value8; - - if (Sscan::Uint8(m_pFileData, "reboot", value8) == Sscan::OK) { - if (value8 != 0) { - if (!RemoteConfig::Get()->IsEnableReboot()) { - DEBUG_PUTS("Status::BAD_REQUEST"); - return Status::BAD_REQUEST; - } - DEBUG_PUTS("Reboot!"); - RemoteConfig::Get()->Reboot(); - __builtin_unreachable(); - } - } else if (Sscan::Uint8(m_pFileData, "display", value8) == Sscan::OK) { - Display::Get()->SetSleep(value8 == 0); - DEBUG_PRINTF("Display::Get()->SetSleep(%d)", value8 == 0); - } else if (Sscan::Uint8(m_pFileData, "identify", value8) == Sscan::OK) { - if (value8 != 0) { - Hardware::Get()->SetMode(hardware::ledblink::Mode::FAST); - } else { - Hardware::Get()->SetMode(hardware::ledblink::Mode::NORMAL); - } - DEBUG_PRINTF("identify=%d", value8 != 0); - } else { - DEBUG_PUTS("Status::BAD_REQUEST"); - return Status::BAD_REQUEST; - } - } else { - const auto bIsJSON = PropertiesConfig::IsJSON(); - - PropertiesConfig::EnableJSON(true); - RemoteConfig::Get()->HandleSet(m_pFileData, m_nFileDataLength); - - PropertiesConfig::EnableJSON(bIsJSON); - } - - m_pContentType = s_contentType[static_cast(contentTypes::TEXT_HTML)]; - m_nContentLength = static_cast(snprintf(m_Content, BUFSIZE - 1U, - "\n" - "\n" - "Submit\n" - "

                      OK

                      \n" - "\n")); - - return Status::OK; -} diff --git a/gd32_rdm_responder/lib/rdmidentify.cpp b/lib-remoteconfig/src/httpd/httpd.cpp old mode 100644 new mode 100755 similarity index 54% rename from gd32_rdm_responder/lib/rdmidentify.cpp rename to lib-remoteconfig/src/httpd/httpd.cpp index 3d6eba71..a3f64361 --- a/gd32_rdm_responder/lib/rdmidentify.cpp +++ b/lib-remoteconfig/src/httpd/httpd.cpp @@ -1,8 +1,8 @@ /** - * @file rdmidentify.cpp + * @file httpd.cpp * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,40 +23,48 @@ * THE SOFTWARE. */ -#include "rdmidentify.h" -#include "rdmresponder.h" -#include "pixeltestpattern.h" +#include +#include +#include +#include -#include "debug.h" +#include "httpd/httpd.h" -static bool s_isOn = false; -static pixelpatterns::Pattern s_Pattern; +#include "network.h" +#include "net/apps/mdns.h" -using namespace rdm::identify; +#include "../../lib-network/config/net_config.h" -void RDMIdentify::On(rdm::identify::Mode nMode) { +HttpDaemon::HttpDaemon() { DEBUG_ENTRY - DEBUG_PRINTF("Mode=%u, s_isOn=%d", static_cast(nMode), s_isOn); - if ((nMode == rdm::identify::Mode::LOUD) && (!s_isOn)) { - s_isOn = true; - s_Pattern = PixelTestPattern::Get()->GetPattern(); - PixelTestPattern::Get()->SetPattern(pixelpatterns::Pattern::FADE); - RDMResponder::Get()->DmxDisableOutput(true); + assert(m_nHandle == -1); + m_nHandle = Network::Get()->TcpBegin(80); + assert(m_nHandle != -1); + + for (uint32_t nIndex = 0; nIndex < TCP_MAX_TCBS_ALLOWED; nIndex++) { + pHandleRequest[nIndex] = new HttpDeamonHandleRequest(nIndex, m_nHandle); + assert(pHandleRequest[nIndex] != nullptr); } + assert(MDNS::Get() != nullptr); + MDNS::Get()->ServiceRecordAdd(nullptr, mdns::Services::HTTP); + DEBUG_EXIT } -void RDMIdentify::Off(__attribute__((unused)) rdm::identify::Mode nMode) { +HttpDaemon::~HttpDaemon() { DEBUG_ENTRY - DEBUG_PRINTF("Mode=%u, s_isOn=%d", static_cast(nMode), s_isOn); - if (s_isOn) { - s_isOn = false; - PixelTestPattern::Get()->SetPattern(s_Pattern); - RDMResponder::Get()->DmxDisableOutput(pixelpatterns::Pattern::NONE != s_Pattern); + MDNS::Get()->ServiceRecordDelete(mdns::Services::HTTP); + + for (uint32_t nIndex = 0; nIndex < TCP_MAX_TCBS_ALLOWED; nIndex++) { + if (pHandleRequest[nIndex] != nullptr) { + delete pHandleRequest[nIndex]; + } } + Network::Get()->TcpEnd(m_nHandle); + DEBUG_EXIT } diff --git a/lib-remoteconfig/src/httpd/httpdhandlerequest.cpp b/lib-remoteconfig/src/httpd/httpdhandlerequest.cpp new file mode 100755 index 00000000..8e92aef1 --- /dev/null +++ b/lib-remoteconfig/src/httpd/httpdhandlerequest.cpp @@ -0,0 +1,758 @@ +/** + * @file httpdhandlerequest.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if !defined(__clang__) +# pragma GCC push_options +# pragma GCC optimize ("O2") +#endif + +#include +#include +#include +#include +#include + +#include "httpd/httpdhandlerequest.h" + +#include "../http/content/json_switch.h" + +#include "remoteconfig.h" +#include "remoteconfigjson.h" +#include "properties.h" +#include "sscan.h" +#include "propertiesconfig.h" + +#include "hardware.h" +#include "network.h" +#include "net/apps/mdns.h" +#include "display.h" + +#if defined(RDM_CONTROLLER) +# include "artnetnode.h" +#endif + +#if !defined (CONFIG_HTTP_HTML_NO_DMX) +# if defined(OUTPUT_DMX_SEND) || defined(OUTPUT_DMX_SEND_MULTI) +# define HAVE_DMX +# endif +# if defined(OUTPUT_DMX_PIXEL) || defined(OUTPUT_DMX_PIXEL_MULTI) +# define HAVE_PIXEL +# endif +#endif + +#if defined (NODE_SHOWFILE) +# define ENABLE_METHOD_DELETE +#endif + +#include "debug.h" + +#if defined ENABLE_CONTENT +//uint32_t get_file_content(const char *fileName, char *pDst, http::contentTypes& contentType); +const char *get_file_content(const char *fileName, uint32_t& nSize, http::contentTypes& contentType); +#endif + +char HttpDeamonHandleRequest::m_DynamicContent[http::BUFSIZE]; + +#ifndef NDEBUG +static constexpr char s_request_method[][8] = {"GET", "POST", "DELETE", "UNKNOWN" }; +#endif + +static constexpr char s_contentType[static_cast(http::contentTypes::NOT_DEFINED)][32] = +{ "text/html", "text/css", "text/javascript", "application/json", "application/octet-stream" }; + +void HttpDeamonHandleRequest::HandleRequest(const uint32_t nBytesReceived, char *pRequestHeaderResponse) { + DEBUG_ENTRY + + m_nBytesReceived = nBytesReceived; + m_RequestHeaderResponse = pRequestHeaderResponse; + + const char *pStatusMsg = "OK"; + + DEBUG_PRINTF("%u: m_Status=%u", m_nConnectionHandle, static_cast(m_Status)); + + if (m_Status == http::Status::UNKNOWN_ERROR) { + // This is an initial incoming HTTP request + m_Status = ParseRequest(); + + DEBUG_PRINTF("%s %s", s_request_method[static_cast(m_RequestMethod)], s_contentType[static_cast(m_ContentType)]); + + if (m_Status == http::Status::OK) { + // It is a supported request + + if (m_RequestMethod == http::RequestMethod::GET) { + m_Status = HandleGet(); + } else if (m_RequestMethod == http::RequestMethod::POST) { + m_Status = HandlePost(false); + + if ((m_Status == http::Status::OK) && (m_nFileDataLength == 0)) { + DEBUG_PUTS("There is a POST header only -> no data"); + DEBUG_EXIT + return; + } + } +#if defined (ENABLE_METHOD_DELETE) + else if (m_RequestMethod == http::RequestMethod::DELETE) { + m_Status = HandleDelete(false); + + if ((m_Status == http::Status::OK) && (m_nFileDataLength == 0)) { + DEBUG_PUTS("There is a DELETE header only -> no data"); + DEBUG_EXIT + return; + } + } +#endif + } + } else if ((m_Status == http::Status::OK) && (m_RequestMethod == http::RequestMethod::POST)) { + m_Status = HandlePost(true); + } +#if defined (ENABLE_METHOD_DELETE) + else if ((m_Status == http::Status::OK) && (m_RequestMethod == http::RequestMethod::DELETE)) { + m_Status = HandleDelete(true); + } +#endif + + if (m_Status != http::Status::OK) { + switch (m_Status) { + case http::Status::BAD_REQUEST: + pStatusMsg = "Bad Request"; + break; + case http::Status::NOT_FOUND: + pStatusMsg = "Not Found"; + break; + case http::Status::REQUEST_ENTITY_TOO_LARGE: + pStatusMsg = "Request Entity Too Large"; + break; + case http::Status::REQUEST_URI_TOO_LONG: + pStatusMsg = "Request-URI Too Long"; + break; + case http::Status::INTERNAL_SERVER_ERROR: + pStatusMsg = "Internal Server Error"; + break; + case http::Status::METHOD_NOT_IMPLEMENTED: + pStatusMsg = "Method Not Implemented"; + break; + case http::Status::VERSION_NOT_SUPPORTED: + pStatusMsg = "Version Not Supported"; + break; + default: + pStatusMsg = "Unknown Error"; + break; + } + + m_ContentType = http::contentTypes::TEXT_HTML; + m_pContent = m_DynamicContent; + m_nContentSize = static_cast(snprintf(m_DynamicContent, http::BUFSIZE - 1U, + "\n" + "\n" + "%u %s\n" + "

                      %s

                      \n" + "\n", static_cast(m_Status), pStatusMsg, pStatusMsg)); + } + + const auto nHeaderLength = snprintf(m_RequestHeaderResponse, http::BUFSIZE - 1U, + "HTTP/1.1 %u %s\r\n" + "Server: %s\r\n" + "Content-Type: %s\r\n" + "Content-Length: %u\r\n" + "Connection: close\r\n" + "\r\n", static_cast(m_Status), pStatusMsg, Network::Get()->GetHostName(), s_contentType[static_cast(m_ContentType)], static_cast(m_nContentSize)); + + Network::Get()->TcpWrite(m_nHandle, reinterpret_cast(m_RequestHeaderResponse), nHeaderLength, m_nConnectionHandle); + Network::Get()->TcpWrite(m_nHandle, reinterpret_cast(m_pContent), m_nContentSize, m_nConnectionHandle); + DEBUG_PRINTF("m_nContentLength=%u", m_nContentSize); + + m_Status = http::Status::UNKNOWN_ERROR; + m_RequestMethod = http::RequestMethod::UNKNOWN; + + DEBUG_EXIT +} + +http::Status HttpDeamonHandleRequest::ParseRequest() { + char *pLine = m_RequestHeaderResponse; + uint32_t nLine = 0; + http::Status status = http::Status::UNKNOWN_ERROR; + m_ContentType = http::contentTypes::NOT_DEFINED; + m_nRequestContentSize = 0; + m_nFileDataLength = 0; + + for (uint32_t i = 0; i < m_nBytesReceived; i++) { + if (m_RequestHeaderResponse[i] == '\n') { + assert(i > 1); + m_RequestHeaderResponse[i - 1] = '\0'; + + if (nLine++ == 0) { + status = ParseMethod(pLine); + } else { + if (pLine[0] == '\0') { + assert((i + 1) <= m_nBytesReceived); + m_nFileDataLength = static_cast(m_nBytesReceived - 1 - i); + if (m_nFileDataLength > 0) { + m_pFileData = &m_RequestHeaderResponse[i + 1]; + m_pFileData[m_nFileDataLength] = '\0'; + } + return http::Status::OK; + } + status = ParseHeaderField(pLine); + } + + if (status != http::Status::OK) { + return status; + } + + pLine = &m_RequestHeaderResponse[++i]; + } + } + + return http::Status::OK; +} + +/** + * Supported: "METHOD uri HTTP/1.1" + * Where METHOD is "GET", "POST" or "DELETE" + */ + +http::Status HttpDeamonHandleRequest::ParseMethod(char *pLine) { + assert(pLine != nullptr); + char *pToken; + + if ((pToken = strtok(pLine, " ")) == nullptr) { + return http::Status::METHOD_NOT_IMPLEMENTED; + } + + if (strcmp(pToken, "GET") == 0) { + m_RequestMethod = http::RequestMethod::GET; + } else if (strcmp(pToken, "POST") == 0) { + m_RequestMethod = http::RequestMethod::POST; + } +#if defined (ENABLE_METHOD_DELETE) + else if (strcmp(pToken, "DELETE") == 0) { + m_RequestMethod = http::RequestMethod::DELETE; + } +#endif + else { + return http::Status::METHOD_NOT_IMPLEMENTED; + } + + if ((pToken = strtok(nullptr, " ")) == nullptr) { + return http::Status::BAD_REQUEST; + } + + m_pUri = pToken; + + if ((pToken = strtok(nullptr, "/")) == nullptr || strcmp(pToken, "HTTP") != 0) { + return http::Status::BAD_REQUEST; + } + + if ((pToken = strtok(nullptr, " \n")) == nullptr) { + return http::Status::BAD_REQUEST; + } + + if (strcmp(pToken, "1.1") != 0) { + return http::Status::VERSION_NOT_SUPPORTED; + } + + return http::Status::OK; +} + +/** + * Only interested in "Content-Type" and "Content-Length" + * Where we check for "Content-Type: application/json" and "Content-Type: application/octet-stream" + */ + +http::Status HttpDeamonHandleRequest::ParseHeaderField(char *pLine) { + DEBUG_ENTRY + char *pToken; + + assert(pLine != nullptr); + + if ((pToken = strtok(pLine, ":")) == nullptr) { + return http::Status::BAD_REQUEST; + } + + if (strcasecmp(pToken, "Content-Type") == 0) { + if ((pToken = strtok(nullptr, " ;")) == nullptr) { + return http::Status::BAD_REQUEST; + } + if (memcmp(pToken, "application/", 12) == 0) { + if (strcmp(&pToken[12], "json") == 0) { + m_ContentType = http::contentTypes::APPLICATION_JSON; + DEBUG_ENTRY + return http::Status::OK; + } + if (strcmp(&pToken[12], "octet-stream") == 0) { + m_ContentType = http::contentTypes::APPLICATION_OCTET_STREAM; + DEBUG_ENTRY + return http::Status::OK; + } + } + } else if (strcasecmp(pToken, "Content-Length") == 0) { + if ((pToken = strtok(nullptr, " ")) == nullptr) { + return http::Status::BAD_REQUEST; + } + + uint32_t nTmp = 0; + while (*pToken != '\0') { + auto nDigit = static_cast(*pToken++ - '0'); + if (nDigit > 9) { + return http::Status::BAD_REQUEST; + } + + nTmp *= 10; + nTmp += nDigit; + } + + m_nRequestContentSize = nTmp; + } + + DEBUG_EXIT + return http::Status::OK; +} + +/** + * GET + */ + +http::Status HttpDeamonHandleRequest::HandleGet() { + DEBUG_ENTRY + + uint32_t nLength = 0; + m_pContent = &m_DynamicContent[0]; + + if (memcmp(m_pUri, "/json/", 6) == 0) { + m_ContentType = http::contentTypes::APPLICATION_JSON; + const auto *pGet = &m_pUri[6]; + switch (http::get_uint(pGet)) { + case http::json::get::LIST: + nLength = remoteconfig::json_get_list(m_DynamicContent, sizeof(m_DynamicContent)); + break; + case http::json::get::VERSION: + nLength = remoteconfig::json_get_version(m_DynamicContent, sizeof(m_DynamicContent)); + break; + case http::json::get::UPTIME: + if (!RemoteConfig::Get()->IsEnableUptime()) { + DEBUG_PUTS("Status::BAD_REQUEST"); + return http::Status::BAD_REQUEST; + } + nLength = remoteconfig::json_get_uptime(m_DynamicContent, sizeof(m_DynamicContent)); + break; + case http::json::get::DISPLAY: + nLength = remoteconfig::json_get_display(m_DynamicContent, sizeof(m_DynamicContent)); + break; + case http::json::get::DIRECTORY: + nLength = remoteconfig::json_get_directory(m_DynamicContent, sizeof(m_DynamicContent)); + break; + case http::json::get::TIMEDATE: + nLength = remoteconfig::timedate::json_get_timeofday(m_DynamicContent, sizeof(m_DynamicContent)); + break; +#if !defined (DISABLE_RTC) + case http::json::get::RTCALARM: + nLength = remoteconfig::rtc::json_get_rtc(m_DynamicContent, sizeof(m_DynamicContent)); + break; +#endif +#if defined (RDM_CONTROLLER) && !defined (CONFIG_HTTP_HTML_NO_RDM) + case http::json::get::RDM: + nLength = remoteconfig::rdm::json_get_rdm(m_DynamicContent, sizeof(m_DynamicContent)); + break; +#endif +#if defined (ARTNET_CONTROLLER) + case http::json::get::POLLTABLE: + nLength = remoteconfig::artnet::controller::json_get_polltable(m_DynamicContent, sizeof(m_DynamicContent)); + break; +#endif +#if defined (ENABLE_NET_PHYSTATUS) + case http::json::get::PHYSTATUS: + nLength = remoteconfig::net::json_get_phystatus(m_DynamicContent, sizeof(m_DynamicContent)); + break; +#endif + default: +#if defined (HAVE_DMX) + if (memcmp(pGet, "dmx/", 4) == 0) { + const auto *pDmx = &pGet[4]; + const bool isQuestionMark = (pDmx[6] == '?'); // Handle /dmx/status?X + if (isQuestionMark) { + auto *p = const_cast(pDmx); + p[6] = '\0'; + } + DEBUG_PRINTF("pDmx=[%s]", pDmx); + switch (http::get_uint(pDmx)) { + case http::json::get::PORTSTATUS: + nLength = remoteconfig::dmx::json_get_ports(m_DynamicContent, sizeof(m_DynamicContent)); + break; + case http::json::get::STATUS: { + const auto *pStatus = &pDmx[7]; + if (isQuestionMark && isalpha(static_cast(pStatus[0]))) { + nLength = remoteconfig::dmx::json_get_portstatus(pStatus[0], m_DynamicContent, sizeof(m_DynamicContent)); + } + } + default: + break; + } + } else +#endif +#if defined (HAVE_PIXEL) + if (memcmp(pGet, "pixel/", 6) == 0) { + const auto *pPixel = &pGet[6]; + switch (http::get_uint(pPixel)) { + case http::json::get::TYPES: + nLength = remoteconfig::pixel::json_get_types(m_DynamicContent, sizeof(m_DynamicContent)); + break; + case http::json::get::STATUS: + nLength = remoteconfig::pixel::json_get_status(m_DynamicContent, sizeof(m_DynamicContent)); + break; + default: + break; + } + } else +#endif +#if defined (RDM_CONTROLLER) && !defined (CONFIG_HTTP_HTML_NO_RDM) + if (memcmp(pGet, "rdm/", 4) == 0) { + const auto *pRdm = &pGet[4]; + const bool isQuestionMark = (pRdm[3] == '?'); // Handle /rdm/tod?X + if (isQuestionMark) { + auto *p = const_cast(pRdm); + p[3] = '\0'; + } + switch (http::get_uint(pRdm)) { + case http::json::get::QUEUE: + nLength = remoteconfig::rdm::json_get_queue(m_DynamicContent, sizeof(m_DynamicContent)); + break; + case http::json::get::PORTSTATUS: + nLength = remoteconfig::rdm::json_get_portstatus(m_DynamicContent, sizeof(m_DynamicContent)); + break; + case http::json::get::TOD: { + const auto *pTod = &pRdm[4]; + if (isQuestionMark && isalpha(static_cast(pTod[0]))) { + nLength = remoteconfig::rdm::json_get_tod(pTod[0], m_DynamicContent, sizeof(m_DynamicContent)); + } + } + break; + default: + break; + } + } else +#endif +#if !defined(DISABLE_FS) || defined (CONFIG_USB_HOST_MSC) + if (memcmp(pGet, "storage/", 8) == 0) { + const auto *pStorage = &pGet[8]; + switch (http::get_uint(pStorage)) { + case http::json::get::DIRECTORY: + nLength = remoteconfig::storage::json_get_directory(m_DynamicContent, sizeof(m_DynamicContent)); + break; + default: + break; + } + } else +#endif +#if defined (ENABLE_PHY_SWITCH) + if (memcmp(pGet, "dsa/", 4) == 0) { + const auto *pDsa = &pGet[4]; + switch (http::get_uint(pDsa)) { + case http::json::get::PORTSTATUS: + nLength = remoteconfig::dsa::json_get_portstatus(m_DynamicContent, sizeof(m_DynamicContent)); + break; + case http::json::get::VLANTABLE: + nLength = remoteconfig::dsa::json_get_vlantable(m_DynamicContent, sizeof(m_DynamicContent)); + break; + default: + break; + } + } else +#endif +#if defined (NODE_SHOWFILE) + if (memcmp(pGet, "showfile/", 9) == 0) { + const auto *pShowfile = &pGet[9]; + switch (http::get_uint(pShowfile)) { + case http::json::get::STATUS: + nLength = remoteconfig::showfile::json_get_status(m_DynamicContent, sizeof(m_DynamicContent)); + break; + case http::json::get::DIRECTORY: + nLength = remoteconfig::showfile::json_get_directory(m_DynamicContent, sizeof(m_DynamicContent)); + break; + default: + break; + } + } else +#endif + { + return HandleGetTxt(); + + } + break; + } + } +#if defined (ENABLE_CONTENT) + else if (strcmp(m_pUri, "/") == 0) { + m_pContent = get_file_content("index.html", nLength, m_ContentType); + } +#if defined (HAVE_DMX) + else if (strcmp(m_pUri, "/dmx") == 0) { + m_pContent = get_file_content("dmx.html", nLength, m_ContentType); + } +#endif +#if defined (RDM_CONTROLLER) && !defined (CONFIG_HTTP_HTML_NO_RDM) + else if (strcmp(m_pUri, "/rdm") == 0) { + m_pContent = get_file_content("rdm.html", nLength, m_ContentType); + } +#endif +#if defined (NODE_SHOWFILE) + else if (strcmp(m_pUri, "/showfile") == 0) { + m_pContent = get_file_content("showfile.html", nLength, m_ContentType); + } +#endif +#if defined (ENABLE_PHY_SWITCH) + else if (strcmp(m_pUri, "/dsa") == 0) { + m_pContent = get_file_content("dsa.html", nLength, m_ContentType); + } +#endif +#if !defined (CONFIG_HTTP_HTML_NO_TIME) + else if (strcmp(m_pUri, "/time") == 0) { + m_pContent = get_file_content("time.html", nLength, m_ContentType); + } +#endif +#if !defined (CONFIG_HTTP_HTML_NO_RTC) && !defined (DISABLE_RTC) + else if (strcmp(m_pUri, "/rtc") == 0) { + m_pContent = get_file_content("rtc.html", nLength, m_ContentType); + } +#endif + else { + m_pContent = get_file_content(&m_pUri[1], nLength, m_ContentType); + } +#endif + + if (nLength == 0) { + DEBUG_EXIT + return http::Status::NOT_FOUND; + } + + m_nContentSize = nLength; + + DEBUG_EXIT + return http::Status::OK; +} + +http::Status HttpDeamonHandleRequest::HandleGetTxt() { + auto *pFileName = &m_pUri[6]; + const auto nLength = strlen(pFileName); + + if (nLength <= 4) { + return http::Status::BAD_REQUEST; + } + + if (strcmp(&pFileName[nLength - 4], ".txt") != 0) { + return http::Status::BAD_REQUEST; + } + + const auto bIsJSON = PropertiesConfig::IsJSON(); + PropertiesConfig::EnableJSON(true); + + strncpy(m_DynamicContent, pFileName, nLength); + m_nContentSize = RemoteConfig::Get()->HandleGet(reinterpret_cast(m_DynamicContent), sizeof(m_DynamicContent)); + + PropertiesConfig::EnableJSON(bIsJSON); + + return http::Status::OK; +} + +/** + * POST + */ + +http::Status HttpDeamonHandleRequest::HandlePost(const bool hasDataOnly) { + DEBUG_ENTRY + DEBUG_PRINTF("m_nBytesReceived=%d, m_nFileDataLength=%u, m_nRequestContentLength=%u -> hasDataOnly=%c", m_nBytesReceived, m_nFileDataLength, m_nRequestContentSize, hasDataOnly ? 'Y' : 'N'); + + if (!hasDataOnly) { + if (m_ContentType != http::contentTypes::APPLICATION_JSON) { + DEBUG_EXIT + return http::Status::BAD_REQUEST; + } + + m_IsAction = (strcmp(m_pUri, "/json/action") == 0); + + if (!m_IsAction && (strcmp(m_pUri, "/json") != 0)) { + DEBUG_EXIT + return http::Status::NOT_FOUND; + } + } + + const auto hasHeadersOnly = (!hasDataOnly && ((m_nBytesReceived < m_nRequestContentSize) || m_nFileDataLength == 0)); + + if (hasHeadersOnly) { + DEBUG_PUTS("hasHeadersOnly"); + DEBUG_EXIT + return http::Status::OK; + } + + if (hasDataOnly) { + m_pFileData = m_RequestHeaderResponse; + m_nFileDataLength = static_cast(m_nBytesReceived); + } + + DEBUG_PRINTF("%d|%.*s|->%c", m_nFileDataLength, m_nFileDataLength, m_pFileData, m_IsAction ? 'Y' : 'N'); + + if (m_IsAction) { + auto const nJsonLength = properties::convert_json_file(m_pFileData, m_nFileDataLength, true); + + if (nJsonLength <= 0) { + DEBUG_PUTS("Status::BAD_REQUEST"); + DEBUG_EXIT + return http::Status::BAD_REQUEST; + } + + m_pFileData[nJsonLength - 1] = '\0'; + debug_dump(m_pFileData, nJsonLength); + + uint8_t value8; + + if (Sscan::Uint8(m_pFileData, "reboot", value8) == Sscan::OK) { + if (value8 != 0) { + if (!RemoteConfig::Get()->IsEnableReboot()) { + DEBUG_PUTS("Status::BAD_REQUEST"); + DEBUG_EXIT + return http::Status::BAD_REQUEST; + } + DEBUG_PUTS("Reboot!"); + RemoteConfig::Get()->Reboot(); + __builtin_unreachable(); + } + } else if (Sscan::Uint8(m_pFileData, "display", value8) == Sscan::OK) { + Display::Get()->SetSleep(value8 == 0); + DEBUG_PRINTF("Display::Get()->SetSleep(%d)", value8 == 0); + } else if (Sscan::Uint8(m_pFileData, "identify", value8) == Sscan::OK) { + if (value8 != 0) { + Hardware::Get()->SetMode(hardware::ledblink::Mode::FAST); + } else { + Hardware::Get()->SetMode(hardware::ledblink::Mode::NORMAL); + } + DEBUG_PRINTF("identify=%d", value8 != 0); + } else if (memcmp(m_pFileData, "date=", 5) == 0) { + remoteconfig::timedate::json_set_timeofday(m_pFileData, nJsonLength); + } +#if !defined (DISABLE_RTC) + else if (memcmp(m_pFileData, "rtc=", 4) == 0) { + remoteconfig::rtc::json_set_rtc(m_pFileData, nJsonLength); + } +#endif +#if defined (RDM_CONTROLLER) + else if (Sscan::Uint8(m_pFileData, "rdm", value8) == Sscan::OK) { + ArtNetNode::Get()->SetRdm(!(value8 != 1)); + DEBUG_PRINTF("rdm=%d", ArtNetNode::Get()->GetRdm()); + } +#endif +#if defined (NODE_SHOWFILE) + else if (memcmp(m_pFileData, "show=", 5) == 0) { + remoteconfig::showfile::json_set_status(m_pFileData, nJsonLength); + } +#endif + else { + DEBUG_PUTS("Status::BAD_REQUEST"); + DEBUG_EXIT + return http::Status::BAD_REQUEST; + } + } else { + const auto bIsJSON = PropertiesConfig::IsJSON(); + + PropertiesConfig::EnableJSON(true); + RemoteConfig::Get()->HandleSet(m_pFileData, m_nFileDataLength); + PropertiesConfig::EnableJSON(bIsJSON); + } + + m_ContentType = http::contentTypes::TEXT_HTML; + m_nContentSize = static_cast(snprintf(m_DynamicContent, http::BUFSIZE - 1U, + "\n" + "\n" + "Submit\n" + "

                      OK

                      \n" + "\n")); + + DEBUG_EXIT + return http::Status::OK; +} + +http::Status HttpDeamonHandleRequest::HandleDelete(const bool hasDataOnly) { + DEBUG_PRINTF("m_nBytesReceived=%d, m_nFileDataLength=%u, m_nRequestContentLength=%u -> hasDataOnly=%c", m_nBytesReceived, m_nFileDataLength, m_nRequestContentSize, hasDataOnly ? 'Y' : 'N'); + + if (!hasDataOnly) { + if (m_ContentType != http::contentTypes::APPLICATION_JSON) { + DEBUG_EXIT + return http::Status::BAD_REQUEST; + } + + m_IsAction = (strcmp(m_pUri, "/json/action") == 0); + + if (!m_IsAction) { + DEBUG_EXIT + return http::Status::NOT_FOUND; + } + } + + const auto hasHeadersOnly = (!hasDataOnly && ((m_nBytesReceived < m_nRequestContentSize) || m_nFileDataLength == 0)); + + if (hasHeadersOnly) { + DEBUG_PUTS("hasHeadersOnly"); + DEBUG_EXIT + return http::Status::OK; + } + + if (hasDataOnly) { + m_pFileData = m_RequestHeaderResponse; + m_nFileDataLength = static_cast(m_nBytesReceived); + } + + DEBUG_PRINTF("%d|%.*s|->%d", m_nFileDataLength, m_nFileDataLength, m_pFileData, m_IsAction); + + auto const nJsonLength = properties::convert_json_file(m_pFileData, m_nFileDataLength, true); + + if (nJsonLength <= 0) { + DEBUG_PUTS("Status::BAD_REQUEST"); + DEBUG_EXIT + return http::Status::BAD_REQUEST; + } + + m_pFileData[nJsonLength - 1] = '\0'; + debug_dump(m_pFileData, nJsonLength); + +#if defined (NODE_SHOWFILE) + if (memcmp(m_pFileData, "show=", 5) == 0) { + remoteconfig::showfile::json_delete(m_pFileData, nJsonLength); + } else +#endif + { + DEBUG_PUTS("Status::BAD_REQUEST"); + DEBUG_EXIT + return http::Status::BAD_REQUEST; + } + + m_ContentType = http::contentTypes::TEXT_HTML; + m_nContentSize = static_cast(snprintf(m_DynamicContent, http::BUFSIZE - 1U, + "\n" + "\n" + "Submit\n" + "

                      OK

                      \n" + "\n")); + + DEBUG_EXIT + return http::Status::OK; +} diff --git a/lib-remoteconfig/src/linux/tftpfileserver.cpp b/lib-remoteconfig/src/linux/tftpfileserver.cpp index 038aa344..00fcca79 100644 --- a/lib-remoteconfig/src/linux/tftpfileserver.cpp +++ b/lib-remoteconfig/src/linux/tftpfileserver.cpp @@ -41,13 +41,13 @@ void TFTPFileServer::Exit() { DEBUG_EXIT } -bool TFTPFileServer::FileOpen(__attribute__((unused)) const char* pFileName, __attribute__((unused)) tftp::Mode mode) { +bool TFTPFileServer::FileOpen([[maybe_unused]] const char* pFileName, [[maybe_unused]] tftp::Mode mode) { DEBUG_ENTRY DEBUG_EXIT return false; } -bool TFTPFileServer::FileCreate(__attribute__((unused)) const char* pFileName, __attribute__((unused)) tftp::Mode mode) { +bool TFTPFileServer::FileCreate([[maybe_unused]] const char* pFileName, [[maybe_unused]] tftp::Mode mode) { DEBUG_ENTRY DEBUG_EXIT return false; @@ -59,13 +59,13 @@ bool TFTPFileServer::FileClose() { return false; } -size_t TFTPFileServer::FileRead(__attribute__((unused)) void* pBuffer, __attribute__((unused)) size_t nCount, __attribute__((unused)) unsigned nBlockNumber) { +size_t TFTPFileServer::FileRead([[maybe_unused]] void* pBuffer, [[maybe_unused]] size_t nCount, [[maybe_unused]] unsigned nBlockNumber) { DEBUG_ENTRY DEBUG_EXIT return 0; } -size_t TFTPFileServer::FileWrite(__attribute__((unused)) const void *pBuffer, __attribute__((unused)) size_t nCount, __attribute__((unused)) unsigned nBlockNumber) { +size_t TFTPFileServer::FileWrite([[maybe_unused]] const void *pBuffer, [[maybe_unused]] size_t nCount, [[maybe_unused]] unsigned nBlockNumber) { DEBUG_ENTRY DEBUG_EXIT return 0; diff --git a/lib-remoteconfig/src/remoteconfig.cpp b/lib-remoteconfig/src/remoteconfig.cpp index b3f96859..dfa594cc 100644 --- a/lib-remoteconfig/src/remoteconfig.cpp +++ b/lib-remoteconfig/src/remoteconfig.cpp @@ -2,7 +2,7 @@ * @file remoteconfig.cpp * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -40,6 +40,9 @@ #include "hardware.h" #include "network.h" +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# include "net/apps/mdns.h" +#endif #include "display.h" #include "properties.h" @@ -51,15 +54,14 @@ /* rconfig.txt */ #include "remoteconfigparams.h" -#include "storeremoteconfig.h" +/* env.txt */ +#include "envparams.h" /* network.txt */ #include "networkparams.h" -#include "storenetwork.h" #if defined(DISPLAY_UDF) /* display.txt */ # include "displayudfparams.h" -# include "storedisplayudf.h" #endif /** @@ -68,57 +70,47 @@ #if defined (NODE_ARTNET) /* artnet.txt */ +# include "artnetnode.h" # include "artnetparams.h" -# include "storeartnet.h" #endif #if defined (NODE_E131) /* e131.txt */ # include "e131params.h" -# include "storee131.h" #endif #if defined (NODE_OSC_CLIENT) /* oscclnt.txt */ # include "oscclientparams.h" -# include "storeoscclient.h" #endif #if defined (NODE_OSC_SERVER) /* osc.txt */ # include "oscserverparams.h" -# include "storeoscserver.h" #endif #if defined (NODE_LTC_SMPTE) /* ltc.txt */ # include "ltcparams.h" -# include "storeltc.h" /* ldisplay.txt */ # include "ltcdisplayparams.h" -# include "storeltcdisplay.h" /* tcnet.txt */ # include "tcnetparams.h" -# include "storetcnet.h" /* gps.txt */ # include "gpsparams.h" -# include "storegps.h" /* etc.txt */ # include "ltcetcparams.h" -# include "storeltcetc.h" #endif #if defined(NODE_SHOWFILE) /* show.txt */ # include "showfileparams.h" -# include "storeshowfile.h" #endif #if defined(NODE_NODE) /* node.txt */ # include "node.h" # include "nodeparams.h" -# include "storenode.h" #endif /** @@ -128,47 +120,44 @@ #if defined (OUTPUT_DMX_SEND) /* params.txt */ # include "dmxparams.h" -# include "storedmxsend.h" #endif #if defined (OUTPUT_DMX_PIXEL) /* devices.txt */ # include "pixeldmxparams.h" -# include "storepixeldmx.h" #endif #if defined (OUTPUT_DMX_TLC59711) /* devices.txt */ # include "tlc59711dmxparams.h" -# include "storetlc59711.h" #endif #if defined (OUTPUT_DMX_MONITOR) /* mon.txt */ # include "dmxmonitorparams.h" -# include "storemonitor.h" #endif #if defined(OUTPUT_DMX_STEPPER) /* sparkfun.txt */ # include "sparkfundmxparams.h" -# include "storesparkfundmx.h" /* motor%.txt */ # include "modeparams.h" # include "motorparams.h" # include "l6470params.h" -# include "storemotors.h" #endif #if defined (OUTPUT_DMX_SERIAL) /* serial.txt */ # include "dmxserialparams.h" -# include "storedmxserial.h" #endif #if defined (OUTPUT_RGB_PANEL) /* rgbpanel.txt */ # include "rgbpanelparams.h" -# include "storergbpanel.h" +#endif + +#if defined (OUTPUT_DMX_PCA9685) +/* pca9685.txt */ +# include "pca9685dmxparams.h" #endif /** @@ -178,14 +167,11 @@ #if defined (RDM_RESPONDER) /* rdm_device.txt */ # include "rdmdeviceparams.h" -# include "storerdmdevice.h" /* sensors.txt */ # include "rdmsensorsparams.h" -# include "storerdmsensors.h" /* "subdev.txt" */ -# if defined (ENABLE_RDM_SUBDEVICES) +# if defined (CONFIG_RDM_ENABLE_SUBDEVICES) # include "rdmsubdevicesparams.h" -# include "storerdmsubdevices.h" # endif #endif @@ -198,10 +184,13 @@ namespace get { enum class Command { REBOOT, LIST, - UPTIME, VERSION, DISPLAY, #if !defined (CONFIG_REMOTECONFIG_MINIMUM) + UPTIME, +# if (defined (NODE_ARTNET) || defined (NODE_NODE)) && (defined (RDM_CONTROLLER) || defined (RDM_RESPONDER)) + RDM, +# endif GET, #endif TFTP, @@ -210,38 +199,52 @@ enum class Command { } // namespace get namespace set { enum class Command { - TFTP, DISPLAY +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# if (defined (NODE_ARTNET) || defined (NODE_NODE)) && (defined (RDM_CONTROLLER) || defined (RDM_RESPONDER)) + RDM, +# endif +#endif + TFTP, + DISPLAY }; } // namespace set } // namespace udp } // namespace remoteconfig -const struct RemoteConfig::Commands RemoteConfig::s_GET[] = { +constexpr struct RemoteConfig::Commands RemoteConfig::s_GET[] = { { &RemoteConfig::HandleReboot, "reboot##", 8, false }, { &RemoteConfig::HandleList, "list#", 5, false }, - { &RemoteConfig::HandleUptime, "uptime#", 7, false }, { &RemoteConfig::HandleVersion, "version#", 8, false }, { &RemoteConfig::HandleDisplayGet, "display#", 8, false }, #if !defined (CONFIG_REMOTECONFIG_MINIMUM) + { &RemoteConfig::HandleUptime, "uptime#", 7, false }, +# if (defined (NODE_ARTNET) || defined (NODE_NODE)) && (defined (RDM_CONTROLLER) || defined (RDM_RESPONDER)) + { &RemoteConfig::HandleRdmGet, "rdm#", 4, false }, +# endif { &RemoteConfig::HandleGetNoParams, "get#", 4, true }, #endif { &RemoteConfig::HandleTftpGet, "tftp#", 5, false }, { &RemoteConfig::HandleFactory, "factory##", 9, false } }; -const struct RemoteConfig::Commands RemoteConfig::s_SET[] = { +constexpr struct RemoteConfig::Commands RemoteConfig::s_SET[] = { +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# if (defined (NODE_ARTNET) || defined (NODE_NODE)) && (defined (RDM_CONTROLLER) || defined (RDM_RESPONDER)) + { &RemoteConfig::HandleRdmSet, "rdm#", 4, true }, +# endif +#endif { &RemoteConfig::HandleTftpSet, "tftp#", 5, true }, { &RemoteConfig::HandleDisplaySet, "display#", 8, true } }; static constexpr char s_Node[static_cast(remoteconfig::Node::LAST)][18] = { "Art-Net", "sACN E1.31", "OSC Server", "LTC", "OSC Client", "RDMNet LLRP Only", "Showfile", "MIDI", "DDP", "PixelPusher", "Node", "Bootloader TFTP", "RDM Responder" }; -static constexpr char s_Output[static_cast(remoteconfig::Output::LAST)][12] = { "DMX", "RDM", "Monitor", "Pixel", "TimeCode", "OSC", "Config", "Stepper", "Player", "Art-Net", "Serial", "RGB Panel" }; +static constexpr char s_Output[static_cast(remoteconfig::Output::LAST)][12] = { "DMX", "RDM", "Monitor", "Pixel", "TimeCode", "OSC", "Config", "Stepper", "Player", "Art-Net", "Serial", "RGB Panel", "PWM" }; RemoteConfig *RemoteConfig::s_pThis; RemoteConfig::ListBin RemoteConfig::s_RemoteConfigListBin; char *RemoteConfig::s_pUdpBuffer; -RemoteConfig::RemoteConfig(remoteconfig::Node node, remoteconfig::Output output, uint32_t nActiveOutputs): +RemoteConfig::RemoteConfig(const remoteconfig::Node node, const remoteconfig::Output output, const uint32_t nActiveOutputs): m_tNode(node), m_tOutput(output), m_nActiveOutputs(nActiveOutputs) @@ -263,12 +266,36 @@ RemoteConfig::RemoteConfig(remoteconfig::Node node, remoteconfig::Output output, m_nHandle = Network::Get()->Begin(remoteconfig::udp::PORT); assert(m_nHandle != -1); +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) + assert(MDNS::Get() != nullptr); + MDNS::Get()->ServiceRecordAdd(nullptr, mdns::Services::CONFIG); + +# if defined(ENABLE_TFTP_SERVER) + MDNS::Get()->ServiceRecordAdd(nullptr, mdns::Services::TFTP); +# endif + +# if defined (ENABLE_HTTPD) + m_pHttpDaemon = new HttpDaemon; + assert(m_pHttpDaemon != nullptr); +# endif +#endif + DEBUG_EXIT } RemoteConfig::~RemoteConfig() { DEBUG_ENTRY +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# if defined (ENABLE_HTTPD) + if (m_pHttpDaemon != nullptr) { + delete m_pHttpDaemon; + } +# endif + + MDNS::Get()->ServiceRecordDelete(mdns::Services::CONFIG); +#endif + Network::Get()->End(remoteconfig::udp::PORT); m_nHandle = -1; @@ -289,10 +316,16 @@ void RemoteConfig::SetDisable(bool bDisable) { if (bDisable && !m_bDisable) { Network::Get()->End(remoteconfig::udp::PORT); m_nHandle = -1; +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) + MDNS::Get()->ServiceRecordDelete(mdns::Services::CONFIG); +#endif m_bDisable = true; } else if (!bDisable && m_bDisable) { m_nHandle = Network::Get()->Begin(remoteconfig::udp::PORT); assert(m_nHandle != -1); +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) + MDNS::Get()->ServiceRecordAdd(nullptr, mdns::Services::CONFIG); +#endif m_bDisable = false; } @@ -380,6 +413,7 @@ void RemoteConfig::HandleRequest() { } } +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) void RemoteConfig::HandleUptime() { DEBUG_ENTRY @@ -389,29 +423,20 @@ void RemoteConfig::HandleUptime() { } const auto nUptime = Hardware::Get()->GetUpTime(); - const auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::UPTIME)].nLength; + const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "uptime: %us\n", static_cast(nUptime)); - if (m_nBytesReceived == nCmdLength) { - const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "uptime: %us\n", nUptime); - Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); - DEBUG_EXIT - return; - } + Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); DEBUG_EXIT } +#endif void RemoteConfig::HandleVersion() { DEBUG_ENTRY - const auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::VERSION)].nLength; - if (m_nBytesReceived == nCmdLength) { - const auto *p = FirmwareVersion::Get()->GetPrint(); - const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "version:%s", p); - Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); - DEBUG_EXIT - return; - } + const auto *p = FirmwareVersion::Get()->GetPrint(); + const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "version:%s", p); + Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); DEBUG_EXIT } @@ -419,33 +444,27 @@ void RemoteConfig::HandleVersion() { void RemoteConfig::HandleList() { DEBUG_ENTRY - const auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::LIST)].nLength; - - if (m_nBytesReceived != nCmdLength) { - DEBUG_EXIT - return; - } - + constexpr auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::LIST)].nLength; auto *pListResponse = &s_pUdpBuffer[nCmdLength + 2U]; const auto nListResponseBufferLength = remoteconfig::udp::BUFFER_SIZE - (nCmdLength + 2U); int32_t nListLength; if (s_RemoteConfigListBin.aDisplayName[0] != '\0') { - nListLength = snprintf(pListResponse, nListResponseBufferLength - 1, "" IPSTR ",%s,%s,%d,%s\n", + nListLength = snprintf(pListResponse, nListResponseBufferLength - 1, "" IPSTR ",%s,%s,%u,%s\n", IP2STR(Network::Get()->GetIp()), s_Node[static_cast(m_tNode)], s_Output[static_cast(m_tOutput)], - m_nActiveOutputs, + static_cast(m_nActiveOutputs), s_RemoteConfigListBin.aDisplayName); } else { - nListLength = snprintf(pListResponse, nListResponseBufferLength - 1, "" IPSTR ",%s,%s,%d\n", + nListLength = snprintf(pListResponse, nListResponseBufferLength - 1, "" IPSTR ",%s,%s,%u\n", IP2STR(Network::Get()->GetIp()), s_Node[static_cast(m_tNode)], s_Output[static_cast(m_tOutput)], - m_nActiveOutputs); + static_cast(m_nActiveOutputs)); } - Network::Get()->SendTo(m_nHandle, pListResponse, static_cast(nListLength), m_nIPAddressFrom, remoteconfig::udp::PORT); + Network::Get()->SendTo(m_nHandle, pListResponse, static_cast(nListLength), m_nIPAddressFrom, remoteconfig::udp::PORT); DEBUG_EXIT } @@ -453,14 +472,14 @@ void RemoteConfig::HandleList() { void RemoteConfig::HandleDisplaySet() { DEBUG_ENTRY - const auto nCmdLength = s_SET[static_cast(remoteconfig::udp::set::Command::DISPLAY)].nLength; + constexpr auto nCmdLength = s_SET[static_cast(remoteconfig::udp::set::Command::DISPLAY)].nLength; - if (m_nBytesReceived != (nCmdLength + 1)) { + if (m_nBytesReceived != (nCmdLength + 1U)) { DEBUG_EXIT return; } - Display::Get()->SetSleep(s_pUdpBuffer[nCmdLength + 1] == '0'); + Display::Get()->SetSleep(s_pUdpBuffer[nCmdLength + 1U] == '0'); DEBUG_PRINTF("%c", s_pUdpBuffer[nCmdLength + 1]); DEBUG_EXIT @@ -469,18 +488,43 @@ void RemoteConfig::HandleDisplaySet() { void RemoteConfig::HandleDisplayGet() { DEBUG_ENTRY - const auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::DISPLAY)].nLength; const bool isOn = !(Display::Get()->isSleep()); + const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "display:%s\n", isOn ? "On" : "Off"); - if (m_nBytesReceived == nCmdLength) { - const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "display:%s\n", isOn ? "On" : "Off"); - Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); - } + Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); DEBUG_EXIT } #if !defined (CONFIG_REMOTECONFIG_MINIMUM) +#if (defined (NODE_ARTNET) || defined (NODE_NODE)) && (defined (RDM_CONTROLLER) || defined (RDM_RESPONDER)) +void RemoteConfig::HandleRdmSet() { + DEBUG_ENTRY + + const auto nCmdLength = s_SET[static_cast(remoteconfig::udp::set::Command::RDM)].nLength; + + if (m_nBytesReceived != (nCmdLength + 1U)) { + DEBUG_EXIT + return; + } + + ArtNetNode::Get()->SetRdm(s_pUdpBuffer[nCmdLength + 1U] != '0'); + + DEBUG_PRINTF("%c", s_pUdpBuffer[nCmdLength + 1U]); + DEBUG_EXIT +} + +void RemoteConfig::HandleRdmGet() { + DEBUG_ENTRY + + const bool isOn = ArtNetNode::Get()->GetRdm(); + const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "rdm:%s\n", isOn ? "On" : "Off"); + + Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); + + DEBUG_EXIT +} +#endif /** * GET */ @@ -492,7 +536,7 @@ uint32_t RemoteConfig::HandleGet(void *pBuffer, uint32_t nBufferLength) { uint32_t nSize; int32_t nIndex; - const auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::GET)].nLength; + constexpr auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::GET)].nLength; if (pBuffer == nullptr) { nSize = remoteconfig::udp::BUFFER_SIZE - nCmdLength; @@ -518,7 +562,7 @@ uint32_t RemoteConfig::HandleGet(void *pBuffer, uint32_t nBufferLength) { (this->*(handler->GetHandler))(nSize); if (pBuffer == nullptr) { - Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nSize), m_nIPAddressFrom, remoteconfig::udp::PORT); + Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, nSize, m_nIPAddressFrom, remoteconfig::udp::PORT); } else { memcpy(pBuffer, s_pUdpBuffer, std::min(nSize, nBufferLength)); } @@ -530,16 +574,25 @@ uint32_t RemoteConfig::HandleGet(void *pBuffer, uint32_t nBufferLength) { void RemoteConfig::HandleGetRconfigTxt(uint32_t& nSize) { DEBUG_ENTRY - RemoteConfigParams remoteConfigParams(StoreRemoteConfig::Get()); + RemoteConfigParams remoteConfigParams; remoteConfigParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT } +void RemoteConfig::HandleGetEnvTxt(uint32_t& nSize) { + DEBUG_ENTRY + + EnvParams envParams; + envParams.Builder(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); + + DEBUG_EXIT +} + void RemoteConfig::HandleGetNetworkTxt(uint32_t& nSize) { DEBUG_ENTRY - NetworkParams networkParams(StoreNetwork::Get()); + NetworkParams networkParams; networkParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -549,8 +602,7 @@ void RemoteConfig::HandleGetNetworkTxt(uint32_t& nSize) { void RemoteConfig::HandleGetArtnetTxt(uint32_t& nSize) { DEBUG_ENTRY - assert(StoreArtNet::Get() != nullptr); - ArtNetParams artnetParams(StoreArtNet::Get()); + ArtNetParams artnetParams; artnetParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -561,8 +613,7 @@ void RemoteConfig::HandleGetArtnetTxt(uint32_t& nSize) { void RemoteConfig::HandleGetE131Txt(uint32_t& nSize) { DEBUG_ENTRY - assert(StoreE131::Get() != nullptr); - E131Params e131params(StoreE131::Get()); + E131Params e131params; e131params.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -573,7 +624,7 @@ void RemoteConfig::HandleGetE131Txt(uint32_t& nSize) { void RemoteConfig::HandleGetOscTxt(uint32_t& nSize) { DEBUG_ENTRY - OSCServerParams oscServerParams(StoreOscServer::Get()); + OSCServerParams oscServerParams; oscServerParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -584,7 +635,7 @@ void RemoteConfig::HandleGetOscTxt(uint32_t& nSize) { void RemoteConfig::HandleGetOscClntTxt(uint32_t& nSize) { DEBUG_ENTRY - OscClientParams oscClientParams(StoreOscClient::Get()); + OscClientParams oscClientParams; oscClientParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -595,7 +646,7 @@ void RemoteConfig::HandleGetOscClntTxt(uint32_t& nSize) { void RemoteConfig::HandleGetRdmDeviceTxt(uint32_t& nSize) { DEBUG_ENTRY - RDMDeviceParams rdmDeviceParams(StoreRDMDevice::Get()); + RDMDeviceParams rdmDeviceParams; rdmDeviceParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -604,17 +655,17 @@ void RemoteConfig::HandleGetRdmDeviceTxt(uint32_t& nSize) { void RemoteConfig::HandleGetRdmSensorsTxt(uint32_t& nSize) { DEBUG_ENTRY - RDMSensorsParams rdmSensorsParams(StoreRDMSensors::Get()); + RDMSensorsParams rdmSensorsParams; rdmSensorsParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT } -# if defined (ENABLE_RDM_SUBDEVICES) +# if defined (CONFIG_RDM_ENABLE_SUBDEVICES) void RemoteConfig::HandleGetRdmSubdevTxt(uint32_t& nSize) { DEBUG_ENTRY - RDMSubDevicesParams rdmSubDevicesParams(StoreRDMSubDevices::Get()); + RDMSubDevicesParams rdmSubDevicesParams; rdmSubDevicesParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -626,7 +677,7 @@ void RemoteConfig::HandleGetRdmSubdevTxt(uint32_t& nSize) { void RemoteConfig::HandleGetParamsTxt(uint32_t& nSize) { DEBUG_ENTRY - DmxParams dmxparams(StoreDmxSend::Get()); + DmxParams dmxparams; dmxparams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -640,22 +691,20 @@ void RemoteConfig::HandleGetDevicesTxt(uint32_t& nSize) { # if defined (OUTPUT_DMX_TLC59711) bool bIsSetLedType = false; - TLC59711DmxParams tlc5911params(StoreTLC59711::Get()); - - if (tlc5911params.Load()) { + TLC59711DmxParams tlc5911params; + tlc5911params.Load(); # if defined (OUTPUT_DMX_PIXEL) - if ((bIsSetLedType = tlc5911params.IsSetLedType()) == true) { + if ((bIsSetLedType = tlc5911params.IsSetLedType()) == true) { # endif - tlc5911params.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); + tlc5911params.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); # if defined (OUTPUT_DMX_PIXEL) - } -# endif } +# endif if (!bIsSetLedType) { # endif #if defined (OUTPUT_DMX_PIXEL) - PixelDmxParams pixelDmxParams(StorePixelDmx::Get()); + PixelDmxParams pixelDmxParams; pixelDmxParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); #endif # if defined (OUTPUT_DMX_TLC59711) @@ -670,7 +719,7 @@ void RemoteConfig::HandleGetDevicesTxt(uint32_t& nSize) { void RemoteConfig::HandleGetLtcTxt(uint32_t& nSize) { DEBUG_ENTRY - LtcParams ltcParams(StoreLtc::Get()); + LtcParams ltcParams; ltcParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -679,7 +728,7 @@ void RemoteConfig::HandleGetLtcTxt(uint32_t& nSize) { void RemoteConfig::HandleGetLdisplayTxt(uint32_t& nSize) { DEBUG_ENTRY - LtcDisplayParams ltcDisplayParams(StoreLtcDisplay::Get()); + LtcDisplayParams ltcDisplayParams; ltcDisplayParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -688,7 +737,7 @@ void RemoteConfig::HandleGetLdisplayTxt(uint32_t& nSize) { void RemoteConfig::HandleGetTCNetTxt(uint32_t& nSize) { DEBUG_ENTRY - TCNetParams tcnetParams(StoreTCNet::Get()); + TCNetParams tcnetParams; tcnetParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -697,7 +746,7 @@ void RemoteConfig::HandleGetTCNetTxt(uint32_t& nSize) { void RemoteConfig::HandleGetGpsTxt(uint32_t& nSize) { DEBUG_ENTRY - GPSParams gpsParams(StoreGPS::Get()); + GPSParams gpsParams; gpsParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -706,7 +755,7 @@ void RemoteConfig::HandleGetGpsTxt(uint32_t& nSize) { void RemoteConfig::HandleGetLtcEtcTxt(uint32_t& nSize) { DEBUG_ENTRY - LtcEtcParams ltcEtcParams(StoreLtcEtc::Get()); + LtcEtcParams ltcEtcParams; ltcEtcParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -717,7 +766,7 @@ void RemoteConfig::HandleGetLtcEtcTxt(uint32_t& nSize) { void RemoteConfig::HandleGetMonTxt(uint32_t& nSize) { DEBUG_ENTRY - DMXMonitorParams monitorParams(StoreMonitor::Get()); + DMXMonitorParams monitorParams; monitorParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -728,7 +777,7 @@ void RemoteConfig::HandleGetMonTxt(uint32_t& nSize) { void RemoteConfig::HandleGetDisplayTxt(uint32_t& nSize) { DEBUG_ENTRY - DisplayUdfParams displayParams(StoreDisplayUdf::Get()); + DisplayUdfParams displayParams; displayParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -739,7 +788,7 @@ void RemoteConfig::HandleGetDisplayTxt(uint32_t& nSize) { void RemoteConfig::HandleGetSparkFunTxt(uint32_t& nSize) { DEBUG_ENTRY - SparkFunDmxParams sparkFunParams(StoreSparkFunDmx::Get()); + SparkFunDmxParams sparkFunParams; sparkFunParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -751,28 +800,28 @@ void RemoteConfig::HandleGetMotorTxt(uint32_t nMotorIndex, uint32_t& nSize) { uint32_t nSizeSparkFun = 0; - SparkFunDmxParams sparkFunParams(StoreSparkFunDmx::Get()); + SparkFunDmxParams sparkFunParams; sparkFunParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSizeSparkFun, nMotorIndex); DEBUG_PRINTF("nSizeSparkFun=%d", nSizeSparkFun); uint32_t nSizeMode = 0; - ModeParams modeParams(StoreMotors::Get()); + ModeParams modeParams; modeParams.Save(nMotorIndex, s_pUdpBuffer + nSizeSparkFun, remoteconfig::udp::BUFFER_SIZE - nSizeSparkFun, nSizeMode); DEBUG_PRINTF("nSizeMode=%d", nSizeMode); uint32_t nSizeMotor = 0; - MotorParams motorParams(StoreMotors::Get()); + MotorParams motorParams; motorParams.Save(nMotorIndex, s_pUdpBuffer + nSizeSparkFun + nSizeMode, remoteconfig::udp::BUFFER_SIZE - nSizeSparkFun - nSizeMode, nSizeMotor); DEBUG_PRINTF("nSizeMotor=%d", nSizeMotor); uint32_t nSizeL6470 = 0; - L6470Params l6470Params(StoreMotors::Get()); + L6470Params l6470Params; l6470Params.Save(nMotorIndex, s_pUdpBuffer + nSizeSparkFun + nSizeMode + nSizeMotor, remoteconfig::udp::BUFFER_SIZE - nSizeSparkFun - nSizeMode - nSizeMotor, nSizeL6470); DEBUG_PRINTF("nSizeL6470=%d", nSizeL6470); @@ -787,7 +836,7 @@ void RemoteConfig::HandleGetMotorTxt(uint32_t nMotorIndex, uint32_t& nSize) { void RemoteConfig::HandleGetShowTxt(uint32_t& nSize) { DEBUG_ENTRY - ShowFileParams showFileParams(StoreShowFile::Get()); + ShowFileParams showFileParams; showFileParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -798,7 +847,7 @@ void RemoteConfig::HandleGetShowTxt(uint32_t& nSize) { void RemoteConfig::HandleGetNodeTxt(const node::Personality personality, uint32_t& nSize) { DEBUG_ENTRY - NodeParams nodeParams(StoreNode::Get(), personality); + NodeParams nodeParams(personality); nodeParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -809,7 +858,7 @@ void RemoteConfig::HandleGetNodeTxt(const node::Personality personality, uint32_ void RemoteConfig::HandleGetSerialTxt(uint32_t& nSize) { DEBUG_ENTRY - DmxSerialParams dmxSerialParams(StoreDmxSerial::Get()); + DmxSerialParams dmxSerialParams; dmxSerialParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT @@ -820,13 +869,24 @@ void RemoteConfig::HandleGetSerialTxt(uint32_t& nSize) { void RemoteConfig::HandleGetRgbPanelTxt(uint32_t& nSize) { DEBUG_ENTRY - RgbPanelParams rgbPanelParams(StoreRgbPanel::Get()); + RgbPanelParams rgbPanelParams; rgbPanelParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); DEBUG_EXIT } #endif +#if defined (OUTPUT_DMX_PCA9685) +void RemoteConfig::HandleGetPca9685Txt(uint32_t& nSize) { + DEBUG_ENTRY + + PCA9685DmxParams pca9685DmxParams; + pca9685DmxParams.Save(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE, nSize); + + DEBUG_EXIT +} +#endif + #endif /** @@ -872,31 +932,30 @@ void RemoteConfig::HandleSet(void *pBuffer, uint32_t nBufferLength) { DEBUG_EXIT } -void RemoteConfig::HandleSetRconfig() { +void RemoteConfig::HandleSetRconfigTxt() { DEBUG_ENTRY - assert(StoreRemoteConfig::Get() != nullptr); - RemoteConfigParams remoteConfigParams(StoreRemoteConfig::Get()); - + RemoteConfigParams remoteConfigParams; remoteConfigParams.Load(s_pUdpBuffer, m_nBytesReceived); remoteConfigParams.Set(this); -#ifndef NDEBUG - remoteConfigParams.Dump(); -#endif DEBUG_EXIT } -void RemoteConfig::HandleSetNetworkTxt() { +void RemoteConfig::HandleSetEnvTxt() { DEBUG_ENTRY - assert(StoreNetwork::Get() != nullptr); - NetworkParams params(StoreNetwork::Get()); + EnvParams params; + params.LoadAndSet(s_pUdpBuffer, m_nBytesReceived); + DEBUG_EXIT +} + +void RemoteConfig::HandleSetNetworkTxt() { + DEBUG_ENTRY + + NetworkParams params; params.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - params.Dump(); -#endif DEBUG_EXIT } @@ -905,13 +964,8 @@ void RemoteConfig::HandleSetNetworkTxt() { void RemoteConfig::HandleSetArtnetTxt() { DEBUG_ENTRY - assert(StoreArtNet::Get() != nullptr); - ArtNetParams artnetParams(StoreArtNet::Get()); - + ArtNetParams artnetParams; artnetParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - artnetParams.Dump(); -#endif DEBUG_EXIT } @@ -921,13 +975,9 @@ void RemoteConfig::HandleSetArtnetTxt() { void RemoteConfig::HandleSetE131Txt() { DEBUG_ENTRY - assert(StoreE131::Get() != nullptr); - E131Params e131params(StoreE131::Get()); - + E131Params e131params; e131params.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - e131params.Dump(); -#endif + DEBUG_EXIT } #endif @@ -936,13 +986,8 @@ void RemoteConfig::HandleSetE131Txt() { void RemoteConfig::HandleSetOscTxt() { DEBUG_ENTRY - assert(StoreOscServer::Get() != nullptr); - OSCServerParams oscServerParams(StoreOscServer::Get()); - + OSCServerParams oscServerParams; oscServerParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - oscServerParams.Dump(); -#endif DEBUG_EXIT } @@ -952,13 +997,8 @@ void RemoteConfig::HandleSetOscTxt() { void RemoteConfig::HandleSetOscClientTxt() { DEBUG_ENTRY - assert(StoreOscClient::Get() != nullptr); - OscClientParams oscClientParams(StoreOscClient::Get()); - + OscClientParams oscClientParams; oscClientParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - oscClientParams.Dump(); -#endif DEBUG_EXIT } @@ -968,13 +1008,8 @@ void RemoteConfig::HandleSetOscClientTxt() { void RemoteConfig::HandleSetParamsTxt() { DEBUG_ENTRY - assert(StoreDmxSend::Get() != nullptr); - DmxParams dmxparams(StoreDmxSend::Get()); - + DmxParams dmxparams; dmxparams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - dmxparams.Dump(); -#endif DEBUG_EXIT } @@ -985,25 +1020,16 @@ void RemoteConfig::HandleSetDevicesTxt() { DEBUG_ENTRY # if defined (OUTPUT_DMX_TLC59711) - assert(StoreTLC59711::Get() != nullptr); - TLC59711DmxParams tlc59711params(StoreTLC59711::Get()); - + TLC59711DmxParams tlc59711params; tlc59711params.Load(s_pUdpBuffer, m_nBytesReceived); -# ifndef NDEBUG - tlc59711params.Dump(); -# endif + DEBUG_PRINTF("tlc5911params.IsSetLedType()=%d", tlc59711params.IsSetLedType()); if (!tlc59711params.IsSetLedType()) { # endif #if defined (OUTPUT_DMX_PIXEL) - assert(StorePixelDmx::Get() != nullptr); - PixelDmxParams pixelDmxParams(StorePixelDmx::Get()); - + PixelDmxParams pixelDmxParams; pixelDmxParams.Load(s_pUdpBuffer, m_nBytesReceived); -# ifndef NDEBUG - pixelDmxParams.Dump(); -# endif # endif # if defined (OUTPUT_DMX_TLC59711) } @@ -1017,13 +1043,8 @@ void RemoteConfig::HandleSetDevicesTxt() { void RemoteConfig::HandleSetLtcTxt() { DEBUG_ENTRY - assert(StoreLtc::Get() != nullptr); - LtcParams ltcParams(StoreLtc::Get()); - + LtcParams ltcParams; ltcParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - ltcParams.Dump(); -#endif DEBUG_EXIT } @@ -1031,13 +1052,8 @@ void RemoteConfig::HandleSetLtcTxt() { void RemoteConfig::HandleSetLdisplayTxt() { DEBUG_ENTRY - assert(StoreLtcDisplay::Get() != nullptr); - LtcDisplayParams ltcDisplayParams(StoreLtcDisplay::Get()); - + LtcDisplayParams ltcDisplayParams; ltcDisplayParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - ltcDisplayParams.Dump(); -#endif DEBUG_EXIT } @@ -1045,13 +1061,8 @@ void RemoteConfig::HandleSetLdisplayTxt() { void RemoteConfig::HandleSetTCNetTxt() { DEBUG_ENTRY - assert(StoreTCNet::Get() != nullptr); - TCNetParams tcnetParams(StoreTCNet::Get()); - + TCNetParams tcnetParams; tcnetParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - tcnetParams.Dump(); -#endif DEBUG_EXIT } @@ -1059,13 +1070,8 @@ void RemoteConfig::HandleSetTCNetTxt() { void RemoteConfig::HandleSetGpsTxt() { DEBUG_ENTRY - assert(StoreGPS::Get() != nullptr); - GPSParams gpsParams(StoreGPS::Get()); - + GPSParams gpsParams; gpsParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - gpsParams.Dump(); -#endif DEBUG_EXIT } @@ -1073,13 +1079,8 @@ void RemoteConfig::HandleSetGpsTxt() { void RemoteConfig::HandleSetLtcEtcTxt() { DEBUG_ENTRY - assert(StoreLtcEtc::Get() != nullptr); - LtcEtcParams ltcEtcParams(StoreLtcEtc::Get()); - + LtcEtcParams ltcEtcParams; ltcEtcParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - ltcEtcParams.Dump(); -#endif DEBUG_EXIT } @@ -1089,13 +1090,8 @@ void RemoteConfig::HandleSetLtcEtcTxt() { void RemoteConfig::HandleSetMonTxt() { DEBUG_ENTRY - assert(StoreMonitor::Get() != nullptr); - DMXMonitorParams monitorParams(StoreMonitor::Get()); - + DMXMonitorParams monitorParams; monitorParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - monitorParams.Dump(); -#endif DEBUG_EXIT } @@ -1105,13 +1101,8 @@ void RemoteConfig::HandleSetMonTxt() { void RemoteConfig::HandleSetDisplayTxt() { DEBUG_ENTRY - assert(StoreDisplayUdf::Get() != nullptr); - DisplayUdfParams displayParams(StoreDisplayUdf::Get()); - + DisplayUdfParams displayParams; displayParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - displayParams.Dump(); -#endif DEBUG_EXIT } @@ -1121,13 +1112,8 @@ void RemoteConfig::HandleSetDisplayTxt() { void RemoteConfig::HandleSetSparkFunTxt() { DEBUG_ENTRY - assert(StoreSparkFunDmx::Get() != nullptr); - SparkFunDmxParams sparkFunDmxParams(StoreSparkFunDmx::Get()); - + SparkFunDmxParams sparkFunDmxParams; sparkFunDmxParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - sparkFunDmxParams.Dump(); -#endif DEBUG_EXIT } @@ -1136,35 +1122,17 @@ void RemoteConfig::HandleSetMotorTxt(uint32_t nMotorIndex) { DEBUG_ENTRY DEBUG_PRINTF("nMotorIndex=%d", nMotorIndex); - assert(StoreSparkFunDmx::Get() != nullptr); - SparkFunDmxParams sparkFunDmxParams(StoreSparkFunDmx::Get()); - + SparkFunDmxParams sparkFunDmxParams; sparkFunDmxParams.Load(nMotorIndex, s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - sparkFunDmxParams.Dump(); -#endif - - assert(StoreMotors::Get() != nullptr); - ModeParams modeParams(StoreMotors::Get()); + ModeParams modeParams; modeParams.Load(nMotorIndex, s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - modeParams.Dump(); -#endif - - MotorParams motorParams(StoreMotors::Get()); + MotorParams motorParams; motorParams.Load(nMotorIndex, s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - motorParams.Dump(); -#endif - - L6470Params l6470Params(StoreMotors::Get()); + L6470Params l6470Params; l6470Params.Load(nMotorIndex, s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - l6470Params.Dump(); -#endif DEBUG_EXIT } @@ -1174,13 +1142,8 @@ void RemoteConfig::HandleSetMotorTxt(uint32_t nMotorIndex) { void RemoteConfig::HandleSetShowTxt() { DEBUG_ENTRY - assert(StoreShowFile::Get() != nullptr); - ShowFileParams showFileParams(StoreShowFile::Get()); - + ShowFileParams showFileParams; showFileParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - showFileParams.Dump(); -#endif DEBUG_EXIT } @@ -1190,13 +1153,8 @@ void RemoteConfig::HandleSetShowTxt() { void RemoteConfig::HandleSetNodeTxt(const node::Personality personality) { DEBUG_ENTRY - assert(StoreNode::Get() != nullptr); - NodeParams nodeParams(StoreNode::Get(), personality); - + NodeParams nodeParams(personality); nodeParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - nodeParams.Dump(); -#endif DEBUG_EXIT } @@ -1206,13 +1164,8 @@ void RemoteConfig::HandleSetNodeTxt(const node::Personality personality) { void RemoteConfig::HandleSetRdmDeviceTxt() { DEBUG_ENTRY - assert(StoreRDMDevice::Get() != nullptr); - RDMDeviceParams rdmDeviceParams(StoreRDMDevice::Get()); - + RDMDeviceParams rdmDeviceParams; rdmDeviceParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - rdmDeviceParams.Dump(); -#endif DEBUG_EXIT } @@ -1220,28 +1173,18 @@ void RemoteConfig::HandleSetRdmDeviceTxt() { void RemoteConfig::HandleSetRdmSensorsTxt() { DEBUG_ENTRY - assert(StoreRDMSensors::Get() != nullptr); - RDMSensorsParams rdmSensorsParams(StoreRDMSensors::Get()); - + RDMSensorsParams rdmSensorsParams; rdmSensorsParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - rdmSensorsParams.Dump(); -#endif DEBUG_EXIT } -# if defined (ENABLE_RDM_SUBDEVICES) +# if defined (CONFIG_RDM_ENABLE_SUBDEVICES) void RemoteConfig::HandleSetRdmSubdevTxt() { DEBUG_ENTRY - assert(StoreRDMSubDevices::Get() != nullptr); - RDMSubDevicesParams rdmSubDevicesParams(StoreRDMSubDevices::Get()); - + RDMSubDevicesParams rdmSubDevicesParams; rdmSubDevicesParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - rdmSubDevicesParams.Dump(); -#endif DEBUG_EXIT } @@ -1252,13 +1195,8 @@ void RemoteConfig::HandleSetRdmSubdevTxt() { void RemoteConfig::HandleSetSerialTxt() { DEBUG_ENTRY - assert(StoreDmxSerial::Get() != nullptr); - DmxSerialParams dmxSerialParams(StoreDmxSerial::Get()); - + DmxSerialParams dmxSerialParams; dmxSerialParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - dmxSerialParams.Dump(); -#endif DEBUG_EXIT } @@ -1268,14 +1206,20 @@ void RemoteConfig::HandleSetSerialTxt() { void RemoteConfig::HandleSetRgbPanelTxt() { DEBUG_ENTRY - assert(StoreRgbPanel::Get() != nullptr); - RgbPanelParams rgbPanelParams(StoreRgbPanel::Get()); - + RgbPanelParams rgbPanelParams; rgbPanelParams.Load(s_pUdpBuffer, m_nBytesReceived); -#ifndef NDEBUG - rgbPanelParams.Dump(); + + DEBUG_EXIT +} #endif +#if defined (OUTPUT_DMX_PCA9685) +void RemoteConfig::HandleSetPca9685Txt() { + DEBUG_ENTRY + + PCA9685DmxParams pca9685DmxParams; + pca9685DmxParams.Load(s_pUdpBuffer, m_nBytesReceived); + DEBUG_EXIT } #endif @@ -1296,14 +1240,14 @@ void RemoteConfig::TftpExit() { void RemoteConfig::HandleTftpSet() { DEBUG_ENTRY - const auto nCmdLength = s_SET[static_cast(remoteconfig::udp::set::Command::TFTP)].nLength; + constexpr auto nCmdLength = s_SET[static_cast(remoteconfig::udp::set::Command::TFTP)].nLength; - if (m_nBytesReceived != (nCmdLength + 1)) { + if (m_nBytesReceived != (nCmdLength + 1U)) { DEBUG_EXIT return; } - m_bEnableTFTP = (s_pUdpBuffer[nCmdLength + 1] != '0'); + m_bEnableTFTP = (s_pUdpBuffer[nCmdLength + 1U] != '0'); if (m_bEnableTFTP) { Display::Get()->SetSleep(false); @@ -1319,14 +1263,8 @@ void RemoteConfig::HandleTftpGet() { PlatformHandleTftpGet(); - const auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::TFTP)].nLength; - - if (m_nBytesReceived == nCmdLength) { - const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "tftp:%s\n", m_bEnableTFTP ? "On" : "Off"); - Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); - DEBUG_EXIT - return; - } + const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "tftp:%s\n", m_bEnableTFTP ? "On" : "Off"); + Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); DEBUG_EXIT } diff --git a/lib-remoteconfig/src/remoteconfigfactory.cpp b/lib-remoteconfig/src/remoteconfigfactory.cpp index 0d70db95..1aa0d9b4 100644 --- a/lib-remoteconfig/src/remoteconfigfactory.cpp +++ b/lib-remoteconfig/src/remoteconfigfactory.cpp @@ -2,7 +2,7 @@ * @file remoteconfigfactory.cpp * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,9 +32,7 @@ void RemoteConfig::HandleFactory() { DEBUG_ENTRY - for (uint32_t i = 0; i < static_cast(configstore::Store::LAST); i++) { - ConfigStore::Get()->ResetSetList(static_cast(i)); - } + ConfigStore::Get()->ResetSetListAll(); DEBUG_EXIT } diff --git a/lib-remoteconfig/src/remoteconfigjson.cpp b/lib-remoteconfig/src/remoteconfigjson.cpp index 88103914..16a3d179 100644 --- a/lib-remoteconfig/src/remoteconfigjson.cpp +++ b/lib-remoteconfig/src/remoteconfigjson.cpp @@ -2,7 +2,7 @@ * @file remoteconfigjson.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,8 +34,8 @@ namespace remoteconfig { -uint16_t json_get_list(char *pOutBuffer, const uint16_t nOutBufferSize) { - const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, +uint32_t json_get_list(char *pOutBuffer, const uint32_t nOutBufferSize) { + const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, "{\"list\":{\"ip\":\"" IPSTR "\",\"name\":\"%s\",\"node\":{\"type\":\"%s\",\"port\":{\"type\":\"%s\",\"count\":%d}}}}", IP2STR(Network::Get()->GetIp()), RemoteConfig::Get()->GetDisplayName(), @@ -46,11 +46,11 @@ uint16_t json_get_list(char *pOutBuffer, const uint16_t nOutBufferSize) { return nLength; } -uint16_t json_get_version(char *pOutBuffer, const uint16_t nOutBufferSize) { +uint32_t json_get_version(char *pOutBuffer, const uint32_t nOutBufferSize) { const auto *pVersion = FirmwareVersion::Get()->GetVersion(); uint8_t nHwTextLength; - const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, + const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, "{\"version\":\"%.*s\",\"board\":\"%s\",\"build\":{\"date\":\"%.*s\",\"time\":\"%.*s\"}}", firmwareversion::length::SOFTWARE_VERSION, pVersion->SoftwareVersion, Hardware::Get()->GetBoardName(nHwTextLength), @@ -59,20 +59,20 @@ uint16_t json_get_version(char *pOutBuffer, const uint16_t nOutBufferSize) { return nLength; } -uint16_t json_get_uptime(char *pOutBuffer, const uint16_t nOutBufferSize) { +uint32_t json_get_uptime(char *pOutBuffer, const uint32_t nOutBufferSize) { const auto nUptime = Hardware::Get()->GetUpTime(); - const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, "{\"uptime\":%u}\n", nUptime)); + const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, "{\"uptime\":%u}\n", static_cast(nUptime))); return nLength; } -uint16_t json_get_display(char *pOutBuffer, const uint16_t nOutBufferSize) { +uint32_t json_get_display(char *pOutBuffer, const uint32_t nOutBufferSize) { const bool isOn = !(Display::Get()->isSleep()); - const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, "{\"display\":%d}", isOn)); + const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, "{\"display\":%d}", isOn)); return nLength; } -uint16_t json_get_directory(char *pOutBuffer, const uint16_t nOutBufferSize) { - const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, +uint32_t json_get_directory(char *pOutBuffer, const uint32_t nOutBufferSize) { + const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, "{\"files\":{" #if defined (NODE_ARTNET) "\"artnet.txt\":\"Art-Net\"," @@ -110,6 +110,9 @@ uint16_t json_get_directory(char *pOutBuffer, const uint16_t nOutBufferSize) { #if defined (OUTPUT_DMX_TLC59711) "\"devices.txt\":\"DMX TLC59711\"," #endif +#if defined (OUTPUT_DMX_PCA9685) + "\"pca9685.txt\":\"DMX PCA9685\"," +#endif #if defined (OUTPUT_DMX_MONITOR) "\"mon.txt\":\"DMX Monitor\"," #endif @@ -138,6 +141,7 @@ uint16_t json_get_directory(char *pOutBuffer, const uint16_t nOutBufferSize) { "\"display.txt\":\"Display UDF\"," #endif "\"network.txt\":\"Network\"," + "\"env.txt\":\"Environment\"," "\"rconfig.txt\":\"Remote configuration\"" "}}" )); diff --git a/lib-remoteconfig/src/remoteconfigparams.cpp b/lib-remoteconfig/src/remoteconfigparams.cpp index 89945d72..b78b2138 100644 --- a/lib-remoteconfig/src/remoteconfigparams.cpp +++ b/lib-remoteconfig/src/remoteconfigparams.cpp @@ -2,7 +2,7 @@ * @file remoteconfigparams.cpp * */ -/* Copyright (C) 2019-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,6 +30,7 @@ #include #include +#include #include #include "remoteconfigparams.h" @@ -42,117 +43,124 @@ #include "debug.h" -RemoteConfigParams::RemoteConfigParams(RemoteConfigParamsStore* pTRemoteConfigParamsStore): m_pRemoteConfigParamsStore(pTRemoteConfigParamsStore) { - memset(&m_tRemoteConfigParams, 0, sizeof(struct TRemoteConfigParams)); +struct ParamMask { + const char *pParam; + uint32_t nMask; +}; + +// Array of structs: parameter and corresponding mask +constexpr ParamMask paramMasks[] = { + { RemoteConfigConst::PARAMS_DISABLE, remoteconfigparams::Mask::DISABLE }, + { RemoteConfigConst::PARAMS_DISABLE_WRITE, remoteconfigparams::Mask::DISABLE_WRITE }, + { RemoteConfigConst::PARAMS_ENABLE_REBOOT, remoteconfigparams::Mask::ENABLE_REBOOT }, + { RemoteConfigConst::PARAMS_ENABLE_UPTIME, remoteconfigparams::Mask::ENABLE_UPTIME }, + { RemoteConfigConst::PARAMS_ENABLE_FACTORY, remoteconfigparams::Mask::ENABLE_FACTORY }, +}; + +RemoteConfigParams::RemoteConfigParams() { + DEBUG_ENTRY + + memset(&m_Params, 0, sizeof(struct remoteconfigparams::Params)); + + DEBUG_EXIT } -bool RemoteConfigParams::Load() { - m_tRemoteConfigParams.nSetList = 0; +void RemoteConfigParams::Load() { + DEBUG_ENTRY + + m_Params.nSetList = 0; #if !defined(DISABLE_FS) ReadConfigFile configfile(RemoteConfigParams::staticCallbackFunction, this); if (configfile.Read(RemoteConfigConst::PARAMS_FILE_NAME)) { - // There is a configuration file - if (m_pRemoteConfigParamsStore != nullptr) { - m_pRemoteConfigParamsStore->Update(&m_tRemoteConfigParams); - } + RemoteConfigParamsStore::Update(&m_Params); } else #endif - if (m_pRemoteConfigParamsStore != nullptr) { - m_pRemoteConfigParamsStore->Copy(&m_tRemoteConfigParams); - } else { - return false; - } + RemoteConfigParamsStore::Copy(&m_Params); - return true; +#ifndef NDEBUG + Dump(); +#endif + DEBUG_EXIT } -void RemoteConfigParams::Load(const char* pBuffer, uint32_t nLength) { +void RemoteConfigParams::Load(const char *pBuffer, uint32_t nLength) { DEBUG_ENTRY assert(pBuffer != nullptr); assert(nLength != 0); - m_tRemoteConfigParams.nSetList = 0; + m_Params.nSetList = 0; ReadConfigFile config(RemoteConfigParams::staticCallbackFunction, this); config.Read(pBuffer, nLength); - assert(m_pRemoteConfigParamsStore != nullptr); - m_pRemoteConfigParamsStore->Update(&m_tRemoteConfigParams); + RemoteConfigParamsStore::Update(&m_Params); +#ifndef NDEBUG + Dump(); +#endif DEBUG_EXIT } void RemoteConfigParams::SetBool(const uint8_t nValue, const uint32_t nMask) { if (nValue != 0) { - m_tRemoteConfigParams.nSetList |= nMask; + m_Params.nSetList |= nMask; } else { - m_tRemoteConfigParams.nSetList &= ~nMask; + m_Params.nSetList &= ~nMask; } } void RemoteConfigParams::callbackFunction(const char *pLine) { assert(pLine != nullptr); - uint8_t nValue8; - - if (Sscan::Uint8(pLine, RemoteConfigConst::PARAMS_DISABLE, nValue8) == Sscan::OK) { - SetBool(nValue8, RemoteConfigParamsMask::DISABLE); - return; - } - - if (Sscan::Uint8(pLine, RemoteConfigConst::PARAMS_DISABLE_WRITE, nValue8) == Sscan::OK) { - SetBool(nValue8, RemoteConfigParamsMask::DISABLE_WRITE); - return; - } - - if (Sscan::Uint8(pLine, RemoteConfigConst::PARAMS_ENABLE_REBOOT, nValue8) == Sscan::OK) { - SetBool(nValue8, RemoteConfigParamsMask::ENABLE_REBOOT); - return; - } - - if (Sscan::Uint8(pLine, RemoteConfigConst::PARAMS_ENABLE_UPTIME, nValue8) == Sscan::OK) { - SetBool(nValue8, RemoteConfigParamsMask::ENABLE_UPTIME); - return; - } - - if (Sscan::Uint8(pLine, RemoteConfigConst::PARAMS_ENABLE_FACTORY, nValue8) == Sscan::OK) { - SetBool(nValue8, RemoteConfigParamsMask::ENABLE_FACTORY); - return; - } + // Helper lambda for setting masks + auto trySetMask = [&](const char* param, const uint32_t mask) { + uint8_t nValue8; + if (Sscan::Uint8(pLine, param, nValue8) == Sscan::OK) { + SetBool(nValue8, mask); + return true; + } + return false; + }; + + // Loop through parameters and masks + for (const auto& paramMask : paramMasks) { + if (trySetMask(paramMask.pParam, paramMask.nMask)) { + return; + } + } uint32_t nLength = remoteconfig::DISPLAY_NAME_LENGTH - 1; - if (Sscan::Char(pLine, RemoteConfigConst::PARAMS_DISPLAY_NAME, m_tRemoteConfigParams.aDisplayName, nLength) == Sscan::OK) { - m_tRemoteConfigParams.aDisplayName[nLength] = '\0'; - m_tRemoteConfigParams.nSetList |= RemoteConfigParamsMask::DISPLAY_NAME; + + if (Sscan::Char(pLine, RemoteConfigConst::PARAMS_DISPLAY_NAME, m_Params.aDisplayName, nLength) == Sscan::OK) { + m_Params.aDisplayName[nLength] = '\0'; + m_Params.nSetList |= remoteconfigparams::Mask::DISPLAY_NAME; return; } } -void RemoteConfigParams::Builder(const struct TRemoteConfigParams *pRemoteConfigParams, char *pBuffer, uint32_t nLength, uint32_t& nSize) { +void RemoteConfigParams::Builder(const struct remoteconfigparams::Params *pRemoteConfigParams, char *pBuffer, uint32_t nLength, uint32_t& nSize) { DEBUG_ENTRY assert(pBuffer != nullptr); if (pRemoteConfigParams != nullptr) { - memcpy(&m_tRemoteConfigParams, pRemoteConfigParams, sizeof(struct TRemoteConfigParams)); + memcpy(&m_Params, pRemoteConfigParams, sizeof(struct remoteconfigparams::Params)); } else { - assert(m_pRemoteConfigParamsStore != nullptr); - m_pRemoteConfigParamsStore->Copy(&m_tRemoteConfigParams); + RemoteConfigParamsStore::Copy(&m_Params); } PropertiesBuilder builder(RemoteConfigConst::PARAMS_FILE_NAME, pBuffer, nLength); - builder.Add(RemoteConfigConst::PARAMS_DISABLE, isMaskSet(RemoteConfigParamsMask::DISABLE)); - builder.Add(RemoteConfigConst::PARAMS_DISABLE_WRITE, isMaskSet(RemoteConfigParamsMask::DISABLE_WRITE)); - builder.Add(RemoteConfigConst::PARAMS_ENABLE_REBOOT, isMaskSet(RemoteConfigParamsMask::ENABLE_REBOOT)); - builder.Add(RemoteConfigConst::PARAMS_ENABLE_UPTIME, isMaskSet(RemoteConfigParamsMask::ENABLE_UPTIME)); - builder.Add(RemoteConfigConst::PARAMS_ENABLE_FACTORY, isMaskSet(RemoteConfigParamsMask::ENABLE_FACTORY)); + // Loop through parameters and masks for building properties + for (const auto& paramMask : paramMasks) { + builder.Add(paramMask.pParam, isMaskSet(paramMask.nMask)); + } - builder.Add(RemoteConfigConst::PARAMS_DISPLAY_NAME, m_tRemoteConfigParams.aDisplayName, isMaskSet(RemoteConfigParamsMask::DISPLAY_NAME)); + builder.Add(RemoteConfigConst::PARAMS_DISPLAY_NAME, m_Params.aDisplayName, isMaskSet(remoteconfigparams::Mask::DISPLAY_NAME)); nSize = builder.GetSize(); @@ -160,17 +168,17 @@ void RemoteConfigParams::Builder(const struct TRemoteConfigParams *pRemoteConfig return; } -void RemoteConfigParams::Set(RemoteConfig* pRemoteConfig) { +void RemoteConfigParams::Set(RemoteConfig *pRemoteConfig) { assert(pRemoteConfig != nullptr); - pRemoteConfig->SetDisable(isMaskSet(RemoteConfigParamsMask::DISABLE)); - pRemoteConfig->SetDisableWrite(isMaskSet(RemoteConfigParamsMask::DISABLE_WRITE)); - pRemoteConfig->SetEnableReboot(isMaskSet(RemoteConfigParamsMask::ENABLE_REBOOT)); - pRemoteConfig->SetEnableUptime(isMaskSet(RemoteConfigParamsMask::ENABLE_UPTIME)); - pRemoteConfig->SetEnableFactory(isMaskSet(RemoteConfigParamsMask::ENABLE_FACTORY)); + pRemoteConfig->SetDisable(isMaskSet(remoteconfigparams::Mask::DISABLE)); + pRemoteConfig->SetDisableWrite(isMaskSet(remoteconfigparams::Mask::DISABLE_WRITE)); + pRemoteConfig->SetEnableReboot(isMaskSet(remoteconfigparams::Mask::ENABLE_REBOOT)); + pRemoteConfig->SetEnableUptime(isMaskSet(remoteconfigparams::Mask::ENABLE_UPTIME)); + pRemoteConfig->SetEnableFactory(isMaskSet(remoteconfigparams::Mask::ENABLE_FACTORY)); - if (isMaskSet(RemoteConfigParamsMask::DISPLAY_NAME)) { - pRemoteConfig->SetDisplayName(m_tRemoteConfigParams.aDisplayName); + if (isMaskSet(remoteconfigparams::Mask::DISPLAY_NAME)) { + pRemoteConfig->SetDisplayName(m_Params.aDisplayName); } } @@ -180,3 +188,13 @@ void RemoteConfigParams::staticCallbackFunction(void *p, const char *s) { (static_cast(p))->callbackFunction(s); } + +void RemoteConfigParams::Dump() { + printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, RemoteConfigConst::PARAMS_FILE_NAME); + + for (const auto& paramMask : paramMasks) { + printf(" %s=%d\n", paramMask.pParam, isMaskSet(paramMask.nMask)); + } + + printf(" %s=%s\n", RemoteConfigConst::PARAMS_DISPLAY_NAME, m_Params.aDisplayName); +} diff --git a/lib-remoteconfig/src/remoteconfigparamsdump.cpp b/lib-remoteconfig/src/remoteconfigparamsdump.cpp deleted file mode 100644 index c2bfee36..00000000 --- a/lib-remoteconfig/src/remoteconfigparamsdump.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @file remoteconfigparamsdump.cpp - * - */ -/* Copyright (C) 2020-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#if !defined(__clang__) // Needed for compiling on MacOS -# pragma GCC push_options -# pragma GCC optimize ("Os") -#endif - -#include - -#include "remoteconfigparams.h" -#include "remoteconfigconst.h" - -#include "debug.h" - -void RemoteConfigParams::Dump() { -#ifndef NDEBUG - printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, RemoteConfigConst::PARAMS_FILE_NAME); - - if (isMaskSet(RemoteConfigParamsMask::DISABLE)) { - printf(" %s=1 [Yes]\n", RemoteConfigConst::PARAMS_DISABLE); - } - - if (isMaskSet(RemoteConfigParamsMask::DISABLE_WRITE)) { - printf(" %s=1 [Yes]\n", RemoteConfigConst::PARAMS_DISABLE_WRITE); - } - - if (isMaskSet(RemoteConfigParamsMask::ENABLE_REBOOT)) { - printf(" %s=1 [Yes]\n", RemoteConfigConst::PARAMS_ENABLE_REBOOT); - } - - if (isMaskSet(RemoteConfigParamsMask::ENABLE_UPTIME)) { - printf(" %s=1 [Yes]\n", RemoteConfigConst::PARAMS_ENABLE_UPTIME); - } - - if (isMaskSet(RemoteConfigParamsMask::ENABLE_FACTORY)) { - printf(" %s=1 [Yes]\n", RemoteConfigConst::PARAMS_ENABLE_FACTORY); - } - - if (isMaskSet(RemoteConfigParamsMask::DISPLAY_NAME)) { - printf(" %s=%s\n", RemoteConfigConst::PARAMS_DISPLAY_NAME, m_tRemoteConfigParams.aDisplayName); - } -#endif -} diff --git a/lib-remoteconfig/src/remoteconfigreboot.cpp b/lib-remoteconfig/src/remoteconfigreboot.cpp index 4df71bc5..643f72b6 100644 --- a/lib-remoteconfig/src/remoteconfigreboot.cpp +++ b/lib-remoteconfig/src/remoteconfigreboot.cpp @@ -51,10 +51,8 @@ void RemoteConfig::HandleReboot() { while (ConfigStore::Get()->Flash()) ; - Network::Get()->Shutdown(); - Display::Get()->Cls(); - Display::Get()->TextStatus("Rebooting ...", Display7SegmentMessage::INFO_REBOOTING); + Display::Get()->TextStatus("Rebooting ..."); Hardware::Get()->Reboot(); __builtin_unreachable() ; diff --git a/lib-remoteconfig/src/remoteconfigstatic.cpp b/lib-remoteconfig/src/remoteconfigstatic.cpp index 8323572d..d3356fe6 100644 --- a/lib-remoteconfig/src/remoteconfigstatic.cpp +++ b/lib-remoteconfig/src/remoteconfigstatic.cpp @@ -2,7 +2,7 @@ * @file remoteconfigstatic.cpp * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,71 +38,75 @@ using namespace remoteconfig; #if !defined (CONFIG_REMOTECONFIG_MINIMUM) -const RemoteConfig::Txt RemoteConfig::s_TXT[] = { - { &RemoteConfig::HandleGetRconfigTxt, &RemoteConfig::HandleSetRconfig, "rconfig.txt", 11, Store::RCONFIG }, - { &RemoteConfig::HandleGetNetworkTxt, &RemoteConfig::HandleSetNetworkTxt, "network.txt", 11, Store::NETWORK }, +constexpr RemoteConfig::Txt RemoteConfig::s_TXT[] = { + { &RemoteConfig::HandleGetRconfigTxt, &RemoteConfig::HandleSetRconfigTxt, "rconfig.txt", 11}, + { &RemoteConfig::HandleGetEnvTxt, &RemoteConfig::HandleSetEnvTxt, "env.txt", 7 }, + { &RemoteConfig::HandleGetNetworkTxt, &RemoteConfig::HandleSetNetworkTxt, "network.txt", 11}, #if defined (DISPLAY_UDF) - { &RemoteConfig::HandleGetDisplayTxt, &RemoteConfig::HandleSetDisplayTxt, "display.txt", 11, Store::DISPLAYUDF }, + { &RemoteConfig::HandleGetDisplayTxt, &RemoteConfig::HandleSetDisplayTxt, "display.txt", 11}, #endif #if defined (NODE_ARTNET) - { &RemoteConfig::HandleGetArtnetTxt, &RemoteConfig::HandleSetArtnetTxt, "artnet.txt", 10, Store::NODE }, + { &RemoteConfig::HandleGetArtnetTxt, &RemoteConfig::HandleSetArtnetTxt, "artnet.txt", 10}, #endif #if defined (NODE_E131) - { &RemoteConfig::HandleGetE131Txt, &RemoteConfig::HandleSetE131Txt, "e131.txt", 8, Store::NODE }, + { &RemoteConfig::HandleGetE131Txt, &RemoteConfig::HandleSetE131Txt, "e131.txt", 8 }, #endif #if defined (NODE_LTC_SMPTE) - { &RemoteConfig::HandleGetLtcTxt, &RemoteConfig::HandleSetLtcTxt, "ltc.txt", 7, Store::LTC }, - { &RemoteConfig::HandleGetLdisplayTxt, &RemoteConfig::HandleSetLdisplayTxt, "ldisplay.txt", 12, Store::LTCDISPLAY }, - { &RemoteConfig::HandleGetTCNetTxt, &RemoteConfig::HandleSetTCNetTxt, "tcnet.txt", 9, Store::TCNET }, - { &RemoteConfig::HandleGetGpsTxt, &RemoteConfig::HandleSetGpsTxt, "gps.txt", 7, Store::GPS }, - { &RemoteConfig::HandleGetLtcEtcTxt, &RemoteConfig::HandleSetLtcEtcTxt, "etc.txt", 7, Store::LTCETC }, + { &RemoteConfig::HandleGetLtcTxt, &RemoteConfig::HandleSetLtcTxt, "ltc.txt", 7 }, + { &RemoteConfig::HandleGetLdisplayTxt, &RemoteConfig::HandleSetLdisplayTxt, "ldisplay.txt", 12}, + { &RemoteConfig::HandleGetTCNetTxt, &RemoteConfig::HandleSetTCNetTxt, "tcnet.txt", 9 }, + { &RemoteConfig::HandleGetGpsTxt, &RemoteConfig::HandleSetGpsTxt, "gps.txt", 7 }, + { &RemoteConfig::HandleGetLtcEtcTxt, &RemoteConfig::HandleSetLtcEtcTxt, "etc.txt", 7 }, #endif #if defined (NODE_OSC_SERVER) - { &RemoteConfig::HandleGetOscTxt, &RemoteConfig::HandleSetOscTxt, "osc.txt", 7, Store::OSC }, + { &RemoteConfig::HandleGetOscTxt, &RemoteConfig::HandleSetOscTxt, "osc.txt", 7 }, #endif #if defined (NODE_OSC_CLIENT) - { &RemoteConfig::HandleGetOscClntTxt, &RemoteConfig::HandleSetOscClientTxt, "oscclnt.txt", 11, Store::OSC_CLIENT }, + { &RemoteConfig::HandleGetOscClntTxt, &RemoteConfig::HandleSetOscClientTxt, "oscclnt.txt", 11}, #endif #if defined (NODE_SHOWFILE) - { &RemoteConfig::HandleGetShowTxt, &RemoteConfig::HandleSetShowTxt, "show.txt", 8, Store::SHOW }, + { &RemoteConfig::HandleGetShowTxt, &RemoteConfig::HandleSetShowTxt, "show.txt", 8 }, #endif #if defined (NODE_NODE) - { &RemoteConfig::HandleGetNodeNodeTxt, &RemoteConfig::HandleSetNodeNodeTxt, "node.txt", 8, Store::NODE }, - { &RemoteConfig::HandleGetNodeArtNetTxt, &RemoteConfig::HandleSetNodeArtNetTxt, "artnet.txt", 10, Store::NODE }, - { &RemoteConfig::HandleGetNodeE131Txt, &RemoteConfig::HandleSetNodeE131Txt, "e131.txt", 8, Store::NODE }, + { &RemoteConfig::HandleGetNodeNodeTxt, &RemoteConfig::HandleSetNodeNodeTxt, "node.txt", 8 }, + { &RemoteConfig::HandleGetNodeArtNetTxt, &RemoteConfig::HandleSetNodeArtNetTxt, "artnet.txt", 10}, + { &RemoteConfig::HandleGetNodeE131Txt, &RemoteConfig::HandleSetNodeE131Txt, "e131.txt", 8 }, #endif #if defined (RDM_RESPONDER) - { &RemoteConfig::HandleGetRdmDeviceTxt, &RemoteConfig::HandleSetRdmDeviceTxt, "rdm_device.txt", 14, Store::RDMDEVICE }, - { &RemoteConfig::HandleGetRdmSensorsTxt, &RemoteConfig::HandleSetRdmSensorsTxt, "sensors.txt", 11, Store::RDMSENSORS }, -# if defined (ENABLE_RDM_SUBDEVICES) - { &RemoteConfig::HandleGetRdmSubdevTxt, &RemoteConfig::HandleSetRdmSubdevTxt, "subdev.txt", 10, Store::RDMSUBDEVICES }, + { &RemoteConfig::HandleGetRdmDeviceTxt, &RemoteConfig::HandleSetRdmDeviceTxt, "rdm_device.txt", 14}, + { &RemoteConfig::HandleGetRdmSensorsTxt, &RemoteConfig::HandleSetRdmSensorsTxt, "sensors.txt", 11}, +# if defined (CONFIG_RDM_ENABLE_SUBDEVICES) + { &RemoteConfig::HandleGetRdmSubdevTxt, &RemoteConfig::HandleSetRdmSubdevTxt, "subdev.txt", 10}, # endif #endif #if defined (OUTPUT_DMX_SEND) - { &RemoteConfig::HandleGetParamsTxt, &RemoteConfig::HandleSetParamsTxt, "params.txt", 10, Store::DMXSEND }, + { &RemoteConfig::HandleGetParamsTxt, &RemoteConfig::HandleSetParamsTxt, "params.txt", 10}, #endif #if defined (OUTPUT_DMX_PIXEL) || defined(OUTPUT_DMX_TLC59711) - { &RemoteConfig::HandleGetDevicesTxt, &RemoteConfig::HandleSetDevicesTxt, "devices.txt", 11, Store::WS28XXDMX }, + { &RemoteConfig::HandleGetDevicesTxt, &RemoteConfig::HandleSetDevicesTxt, "devices.txt", 11}, #endif #if defined (OUTPUT_DMX_MONITOR) - { &RemoteConfig::HandleGetMonTxt, &RemoteConfig::HandleSetMonTxt, "mon.txt", 7, Store::MONITOR }, + { &RemoteConfig::HandleGetMonTxt, &RemoteConfig::HandleSetMonTxt, "mon.txt", 7 }, #endif #if defined (OUTPUT_DMX_SERIAL) - { &RemoteConfig::HandleGetSerialTxt, &RemoteConfig::HandleSetSerialTxt, "serial.txt", 10, Store::SERIAL }, + { &RemoteConfig::HandleGetSerialTxt, &RemoteConfig::HandleSetSerialTxt, "serial.txt", 10}, #endif #if defined (OUTPUT_RGB_PANEL) - { &RemoteConfig::HandleGetRgbPanelTxt, &RemoteConfig::HandleSetRgbPanelTxt, "rgbpanel.txt", 12, Store::RGBPANEL }, + { &RemoteConfig::HandleGetRgbPanelTxt, &RemoteConfig::HandleSetRgbPanelTxt, "rgbpanel.txt", 12}, +#endif +#if defined (OUTPUT_DMX_PCA9685) + { &RemoteConfig::HandleGetPca9685Txt, &RemoteConfig::HandleSetPca9685Txt, "pca9685.txt", 11}, #endif #if defined(OUTPUT_DMX_STEPPER) - { &RemoteConfig::HandleGetSparkFunTxt, &RemoteConfig::HandleSetSparkFunTxt, "sparkfun.txt", 12, Store::SPARKFUN }, - { &RemoteConfig::HandleGetMotor0Txt, &RemoteConfig::HandleSetMotor0Txt, "motor0.txt", 10, Store::MOTORS }, - { &RemoteConfig::HandleGetMotor1Txt, &RemoteConfig::HandleSetMotor1Txt, "motor1.txt", 10, Store::MOTORS }, - { &RemoteConfig::HandleGetMotor2Txt, &RemoteConfig::HandleSetMotor2Txt, "motor2.txt", 10, Store::MOTORS }, - { &RemoteConfig::HandleGetMotor3Txt, &RemoteConfig::HandleSetMotor3Txt, "motor3.txt", 10, Store::MOTORS }, - { &RemoteConfig::HandleGetMotor4Txt, &RemoteConfig::HandleSetMotor4Txt, "motor4.txt", 10, Store::MOTORS }, - { &RemoteConfig::HandleGetMotor5Txt, &RemoteConfig::HandleSetMotor5Txt, "motor5.txt", 10, Store::MOTORS }, - { &RemoteConfig::HandleGetMotor6Txt, &RemoteConfig::HandleSetMotor6Txt, "motor6.txt", 10, Store::MOTORS }, - { &RemoteConfig::HandleGetMotor7Txt, &RemoteConfig::HandleSetMotor7Txt, "motor7.txt", 10, Store::MOTORS } + { &RemoteConfig::HandleGetSparkFunTxt, &RemoteConfig::HandleSetSparkFunTxt, "sparkfun.txt", 12}, + { &RemoteConfig::HandleGetMotor0Txt, &RemoteConfig::HandleSetMotor0Txt, "motor0.txt", 10}, + { &RemoteConfig::HandleGetMotor1Txt, &RemoteConfig::HandleSetMotor1Txt, "motor1.txt", 10}, + { &RemoteConfig::HandleGetMotor2Txt, &RemoteConfig::HandleSetMotor2Txt, "motor2.txt", 10}, + { &RemoteConfig::HandleGetMotor3Txt, &RemoteConfig::HandleSetMotor3Txt, "motor3.txt", 10}, + { &RemoteConfig::HandleGetMotor4Txt, &RemoteConfig::HandleSetMotor4Txt, "motor4.txt", 10}, + { &RemoteConfig::HandleGetMotor5Txt, &RemoteConfig::HandleSetMotor5Txt, "motor5.txt", 10}, + { &RemoteConfig::HandleGetMotor6Txt, &RemoteConfig::HandleSetMotor6Txt, "motor6.txt", 10}, + { &RemoteConfig::HandleGetMotor7Txt, &RemoteConfig::HandleSetMotor7Txt, "motor7.txt", 10} #endif }; diff --git a/lib-remoteconfig/src/shell/shell.cpp b/lib-remoteconfig/src/shell/shell.cpp old mode 100644 new mode 100755 index 238e7adb..845b27ed --- a/lib-remoteconfig/src/shell/shell.cpp +++ b/lib-remoteconfig/src/shell/shell.cpp @@ -3,7 +3,7 @@ * */ /* Copyright (C) 2020 by hippy mailto:dmxout@gmail.com - * Copyright (C) 2020-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl + * Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,30 +31,43 @@ #include "shell/shell.h" +#if defined (GD32) // PHY_TYPE is defined here +# include "gd32.h" +#endif + #include "debug.h" -struct TCommands { +struct ShellCommands { const char *pName; const uint32_t nArgc; }; -static constexpr TCommands cmd_table[] = { +static constexpr ShellCommands cmd_table[] = { { "reboot", 0 }, { "info", 0 }, - { "set", 2}, - { "get", 2}, - { "dhcp", 0}, - { "date", 0}, - { "hwclock", 1}, -#ifndef NDEBUG - { "i2cdetect" , 0}, - { "dump" , 1}, - { "mem" , 2}, - { "ntp" , 1}, - { "gps" , 1}, + { "set", 2 }, + { "get", 2 }, + { "dhcp", 0 }, + { "date", 0 }, + { "phy", 0 }, +#if !defined (DISABLE_RTC) + { "hwclock", 1 }, #endif - { "?", 0 } -}; +#if defined (DEBUG_I2C) + { "i2cdetect", 0 }, +#endif + { "dump", 1 }, + { "mem", 2 }, +#if defined (ENABLE_NTP_CLIENT) + { "ntp", 1 }, +#endif +#if defined (CONFIG_SHELL_GPS) + { "gps", 1 }, +#endif +#if (PHY_TYPE == RTL8201F) + { "rtl8201f" , 2}, +#endif + { "?", 0 } }; namespace shell { static constexpr auto TABLE_SIZE = sizeof(cmd_table) / sizeof(cmd_table[0]); @@ -65,10 +78,8 @@ static constexpr char CMD_WRONG_ARGUMENTS[] = "Wrong arguments\n"; } // namespace msg } // namespace shell -using namespace shell; - Shell::Shell() { - DEBUG_PRINTF("TABLE_SIZE=%d", TABLE_SIZE); + DEBUG_PRINTF("TABLE_SIZE=%d", shell::TABLE_SIZE); } int Shell::Printf(const char* fmt, ...) { @@ -86,8 +97,8 @@ int Shell::Printf(const char* fmt, ...) { return i; } -uint16_t Shell::ValidateCmd(uint32_t nLength, CmdIndex &nCmdIndex) { - uint16_t i; +uint32_t Shell::ValidateCmd(const uint32_t nLength, shell::CmdIndex &nCmdIndex) { + uint32_t i; m_Argc = 0; @@ -98,17 +109,17 @@ uint16_t Shell::ValidateCmd(uint32_t nLength, CmdIndex &nCmdIndex) { } } - for (uint32_t j = 0; j < TABLE_SIZE; j++) { + for (uint32_t j = 0; j < shell::TABLE_SIZE; j++) { if (0 == strcmp(m_Buffer, cmd_table[j].pName)) { - nCmdIndex = static_cast(j); - return static_cast(i + 1); + nCmdIndex = static_cast< shell::CmdIndex>(j); + return i + 1; } } return 0; } -void Shell::ValidateArg(uint16_t nOffset, uint32_t nLength) { +void Shell::ValidateArg(uint32_t nOffset, const uint32_t nLength) { if (nOffset > nLength) { return; } @@ -121,11 +132,11 @@ void Shell::ValidateArg(uint16_t nOffset, uint32_t nLength) { return; } - uint16_t nArgvStart = nOffset; + auto nArgvStart = nOffset; m_Argv[0] = &m_Buffer[nOffset++]; m_Argc = 1; - uint16_t i, j = 1; + uint32_t i, j = 1; for (i = nOffset; i < nLength; i++) { if ((m_Buffer[i] > ' ') && (m_Buffer[i] < 127)) { @@ -133,13 +144,13 @@ void Shell::ValidateArg(uint16_t nOffset, uint32_t nLength) { } if ((m_Buffer[i] == ' ') || (m_Buffer[i] == '\t')) { - if (j < MAXARG) { + if (j < shell::MAXARG) { m_nArgvLength[j - 1] = static_cast(i - nArgvStart); } while (i < nLength && ((m_Buffer[i] == ' ') || (m_Buffer[i] == '\t'))) { m_Buffer[i++] = '\0'; } - if (j < MAXARG) { + if (j < shell::MAXARG) { nArgvStart = i; m_Argv[j++] = &m_Buffer[i]; } @@ -147,7 +158,7 @@ void Shell::ValidateArg(uint16_t nOffset, uint32_t nLength) { } } - if (j < MAXARG) { + if (j < shell::MAXARG) { m_nArgvLength[j - 1] = static_cast(i - nArgvStart); } @@ -161,11 +172,18 @@ void Shell::ValidateArg(uint16_t nOffset, uint32_t nLength) { void Shell::CmdHelp() { Puts("http://www.orangepi-dmx.org/orange-pi-dmx512-rdm/uart0-shell\n"); + + uint32_t i = 0; + for (auto& cmd : cmd_table) { + Printf("%2u: %s <%u>\n", i++, cmd.pName, cmd.nArgc); + } + + Puts(""); } void Shell::Run() { if (__builtin_expect((!m_bShownPrompt), 1)) { - Puts(msg::CMD_PROMPT); + Puts(shell::msg::CMD_PROMPT); m_bShownPrompt = true; } @@ -179,64 +197,78 @@ void Shell::Run() { m_bShownPrompt = false; // next time round, we show the prompt. - uint16_t nOffset; - CmdIndex nCmdIndex; + uint32_t nOffset; + shell::CmdIndex nCmdIndex; if ((nOffset = ValidateCmd(nLength, nCmdIndex)) == 0) { - Printf("%s %s\n", msg::CMD_NOT_FOUND, m_Buffer); + Printf("%s %s\n", shell::msg::CMD_NOT_FOUND, m_Buffer); return; } ValidateArg(nOffset, nLength); if (m_Argc != cmd_table[static_cast(nCmdIndex)].nArgc) { - Puts(msg::CMD_WRONG_ARGUMENTS); + Puts( shell::msg::CMD_WRONG_ARGUMENTS); return; } switch (nCmdIndex) { - case CmdIndex::REBOOT: - CmdReboot(); - break; - case CmdIndex::INFO: - CmdInfo(); - break; - case CmdIndex::SET: - CmdSet(); - break; - case CmdIndex::GET: - CmdGet(); - break; - case CmdIndex::DHCP: - CmdDhcp(); - break; - case CmdIndex::DATE: - CmdDate(); - break; - case CmdIndex::HWCLOCK: - CmdHwClock(); - break; -#ifndef NDEBUG - case CmdIndex::I2CDETECT: - CmdI2cDetect(); - break; - case CmdIndex::DUMP: - CmdDump(); - break; - case CmdIndex::MEM: - CmdMem(); - break; - case CmdIndex::NTP: - CmdNtp(); - break; - case CmdIndex::GPS: - CmdGps(); - break; + case shell::CmdIndex::REBOOT: + CmdReboot(); + break; + case shell::CmdIndex::INFO: + CmdInfo(); + break; + case shell::CmdIndex::SET: + CmdSet(); + break; + case shell::CmdIndex::GET: + CmdGet(); + break; + case shell::CmdIndex::DHCP: + CmdDhcp(); + break; + case shell::CmdIndex::DATE: + CmdDate(); + break; + case shell::CmdIndex::PHY: + CmdPhy(); + break; +#if !defined(DISABLE_RTC) + case shell::CmdIndex::HWCLOCK: + CmdHwClock(); + break; #endif - case CmdIndex::HELP: - CmdHelp(); - break; - default: - break; +#if defined (DEBUG_I2C) + case shell::CmdIndex::I2CDETECT: + CmdI2cDetect(); + break; +#endif + case shell::CmdIndex::DUMP: + CmdDump(); + break; + case shell::CmdIndex::MEM: + CmdMem(); + break; +#if defined (ENABLE_NTP_CLIENT) + case shell::CmdIndex::NTP: + CmdNtp(); + break; +#endif +#if defined (CONFIG_SHELL_GPS) + case shell::CmdIndex::GPS: + CmdGps(); + break; +#endif +#if (PHY_TYPE == RTL8201F) + case shell::CmdIndex::PHY_TYPE_RTL8201F: + CmdPhyTypeRTL8201F(); + break; +#endif + case shell::CmdIndex::HELP: + CmdHelp(); + break; + default: + break; } } diff --git a/lib-remoteconfig/src/shell/shellcmd.cpp b/lib-remoteconfig/src/shell/shellcmd.cpp old mode 100644 new mode 100755 index 723353a3..f82b55cd --- a/lib-remoteconfig/src/shell/shellcmd.cpp +++ b/lib-remoteconfig/src/shell/shellcmd.cpp @@ -3,7 +3,7 @@ * */ /* Copyright (C) 2020 by hippy mailto:dmxout@gmail.com - * Copyright (C) 2020-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl + * Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,6 +35,7 @@ #include "remoteconfig.h" #include "network.h" +#include "emac/phy.h" #include "hardware.h" #include "firmwareversion.h" @@ -49,87 +50,118 @@ #endif // Firmware specific BEGIN -#include "debug.h" +#if defined (DEBUG_I2C) +# include "../lib-hal/debug/i2c/i2cdetect.h" +#endif -#ifndef NDEBUG -# include "../debug/i2cdetect.h" -# include "ntpclient.h" +#if defined (ENABLE_NTP_CLIENT) +# include "net/apps/ntpclient.h" +#endif + +#if defined (CONFIG_SHELL_GPS) # include "gps.h" -extern "C" { -void h3_board_dump(void); -void h3_dump_memory_mapping(void); -void h3_ccu_pll_dump(void); -void arm_dump_memmap(void); -void arm_dump_page_table(void); -} #endif -// TODO We can reshuffle namespaces here for removing duplicates? +#if (PHY_TYPE == RTL8201F) +# include "emac/phy/rtl8201f.h" +#endif + +#if defined (GD32) // PHY_TYPE is defined here +# include "gd32.h" +#endif + +#include "debug.h" namespace shell { +// Centralize common arguments and lengths +namespace common_args { +static constexpr char PRINT[] = "print"; +} // namespace common_args + +namespace common_lengths { +static constexpr auto PRINT = sizeof(common_args::PRINT) - 1; +} // namespace common_lengths namespace set { namespace arg { static constexpr char IP[] = "ip"; static constexpr char HOSTNAME[] = "hostname"; +#if defined (LTC_READER) static constexpr char LTC[] = "ltc"; +#endif } // namespace arg namespace length { static constexpr auto IP = sizeof(arg::IP) - 1; static constexpr auto HOSTNAME = sizeof(arg::HOSTNAME) - 1; +#if defined (LTC_READER) static constexpr auto LTC = sizeof(arg::LTC) - 1; +#endif } // namespace length } // namespace set -namespace dump { -namespace arg { -static constexpr char BOARD[] = "board"; -static constexpr char MMAP[] = "mmap"; -static constexpr char PLL[] = "pll"; -static constexpr char LINKER[] = "linker"; -} // namespace arg -namespace length { -static constexpr auto BOARD = sizeof(arg::BOARD) - 1; -static constexpr auto MMAP = sizeof(arg::MMAP) - 1; -static constexpr auto PLL = sizeof(arg::PLL) - 1; -static constexpr auto LINKER = sizeof(arg::LINKER) - 1; -} // namespace length -} // namespace dump - namespace networktime { namespace arg { -static constexpr char PRINT[] = "print"; +// Reuse common_args::PRINT +using common_args::PRINT; } // namespace arg namespace length { -static constexpr auto PRINT = sizeof(arg::PRINT) - 1; +// Reuse common_lengths::PRINT +using common_lengths::PRINT; } // namespace length } // namespace networktime +#if !defined(DISABLE_RTC) namespace hwclock { namespace arg { -static constexpr char HCTOSYS[] = "hctosys"; // Set the System Clock from the Hardware Clock -static constexpr char SYSTOHC[] = "systohc"; // Set the Hardware Clock from the System Clock -static constexpr char PRINT[] = "print"; +static constexpr char HCTOSYS[] = "hctosys"; // Set the System Clock from the Hardware Clock +static constexpr char SYSTOHC[] = "systohc"; // Set the Hardware Clock from the System Clock +// Reuse common_args::PRINT +using common_args::PRINT; } // namespace arg namespace length { static constexpr auto HCTOSYS = sizeof(arg::HCTOSYS) - 1; static constexpr auto SYSTOHC = sizeof(arg::SYSTOHC) - 1; -static constexpr auto PRINT = sizeof(arg::PRINT) - 1; +// Reuse common_lengths::PRINT +using common_lengths::PRINT; } // namespace length } // namespace hwclock +#endif +#if defined (CONFIG_SHELL_GPS) namespace gps { namespace arg { static constexpr char DATE[] = "date"; static constexpr char LOCALTIME[] = "localtime"; -static constexpr char PRINT[] = "print"; +// Reuse common_args::PRINT +using common_args::PRINT; } // namespace arg namespace length { static constexpr auto DATE = sizeof(arg::DATE) - 1; static constexpr auto LOCALTIME = sizeof(arg::LOCALTIME) - 1; -static constexpr auto PRINT = sizeof(arg::PRINT) - 1; +// Reuse common_lengths::PRINT +using common_lengths::PRINT; } // namespace length } // namespace gps +#endif + +#if (PHY_TYPE == RTL8201F) +namespace rtl8201f { +namespace arg { +static constexpr char RXTIMING[] = "rxtiming"; +static constexpr char TXTIMING[] = "txtiming"; +static constexpr char TIMING[] = "timing"; +// Reuse common_args::PRINT +using common_args::PRINT; +} // namespace arg +namespace length { +static constexpr auto RXTIMING = sizeof(arg::RXTIMING) - 1; +static constexpr auto TXTIMING = sizeof(arg::TXTIMING) - 1; +static constexpr auto TIMING = sizeof(arg::TIMING) - 1; +// Reuse common_lengths::PRINT +using common_lengths::PRINT; +} // namespace length +} // namespace rtl8201f +#endif namespace file { static constexpr char EXT[] = ".txt"; @@ -148,38 +180,17 @@ static constexpr char DHCP[] = "DHCP enabled\n"; static constexpr char STORED[] = "Stored\n"; } // namespace info namespace error { -static constexpr char INVALID[] = "Invalid command.\n"; -static constexpr char INTERNAL[] = "Internal error.\n"; -static constexpr char DHCP[] = "DHCP failed.\n"; static constexpr char TXT[] = ".txt not found\n"; static constexpr char PROPERTY[] = "Property not found.\n"; +#if defined (LTC_READER) static constexpr char LTC[] = "This source does not support the set command.\n"; +#endif } // namespace error } // namespace msg - } // namespace shell using namespace shell; -uint32_t Shell::hexadecimalToDecimal(const char *pHexValue, uint32_t nLength) { - const auto *pSrc = pHexValue; - uint32_t nValue = 0; - - while (nLength-- > 0) { - const auto c = *pSrc; - - if (isxdigit(c) == 0) { - break; - } - - const auto nNibble = c > '9' ? static_cast((c | 0x20) - 'a' + 10) : static_cast(c - '0'); - nValue = (nValue << 4) | nNibble; - pSrc++; - } - - return nValue; -} - void Shell::CmdReboot() { RemoteConfig::Get()->Reboot(); } @@ -336,11 +347,8 @@ void Shell::CmdGet() { } void Shell::CmdDhcp() { - if (Network::Get()->EnableDhcp()) { - Puts(msg::info::DHCP); - } else { - Puts(msg::error::DHCP); - } + Network::Get()->EnableDhcp(); + Puts(msg::info::DHCP); } void Shell::CmdDate() { @@ -350,69 +358,76 @@ void Shell::CmdDate() { Puts(asctime(localtime(&rawtime))); } -void Shell::CmdHwClock() { - const auto nArgv0Length = m_nArgvLength[0]; +void Shell::CmdPhy() { + net::PhyStatus phyStatus; + phy_customized_status(phyStatus); - if ((nArgv0Length == hwclock::length::HCTOSYS) && (memcmp(m_Argv[0], hwclock::arg::HCTOSYS, hwclock::length::HCTOSYS) == 0)) { - HwClock::Get()->HcToSys(); - return; - } + Printf("Link %s, %d, %s\n", + phyStatus.link == net::Link::STATE_UP ? "Up" : "Down", + phyStatus.speed == net::Speed::SPEED10 ? 10 : 100, + phyStatus.duplex == net::Duplex::DUPLEX_HALF ? "HALF" : "FULL"); +} - if ((nArgv0Length == hwclock::length::SYSTOHC) && (memcmp(m_Argv[0], hwclock::arg::SYSTOHC, hwclock::length::SYSTOHC) == 0)) { - HwClock::Get()->SysToHc(); - return; - } +#ifndef NDEBUG +static uint32_t hexadecimal_to_decimal(const char *pHexValue, uint32_t nLength) { + const auto *pSrc = pHexValue; + uint32_t nValue = 0; - if ((nArgv0Length == hwclock::length::PRINT) && (memcmp(m_Argv[0], hwclock::arg::PRINT, hwclock::length::PRINT) == 0)) { - HwClock::Get()->Print(); - return; + while (nLength-- > 0) { + const auto c = *pSrc; + + if (isxdigit(c) == 0) { + break; + } + + const auto nNibble = c > '9' ? static_cast((c | 0x20) - 'a' + 10) : static_cast(c - '0'); + nValue = (nValue << 4) | nNibble; + pSrc++; } - Puts(msg::error::INVALID); + return nValue; } +#endif -/* - * Debug commands - */ - +void Shell::CmdMem() { #ifndef NDEBUG -void Shell::CmdI2cDetect() { - I2cDetect i2cdetect; + const auto pAddress = reinterpret_cast(hexadecimal_to_decimal(m_Argv[0], m_nArgvLength[0])); + const auto nSize = hexadecimal_to_decimal(m_Argv[1], m_nArgvLength[1]); + + debug_dump(pAddress, nSize); +#endif } -void Shell::CmdDump() { +#if !defined(DISABLE_RTC) +void Shell::CmdHwClock() { const auto nArgv0Length = m_nArgvLength[0]; - if ((nArgv0Length == dump::length::BOARD) && (memcmp(m_Argv[0], dump::arg::BOARD, dump::length::BOARD) == 0)) { - h3_board_dump(); - return; - } - - if ((nArgv0Length == dump::length::MMAP) && (memcmp(m_Argv[0], dump::arg::MMAP, dump::length::MMAP) == 0)) { - h3_dump_memory_mapping(); + if ((nArgv0Length == hwclock::length::HCTOSYS) && (memcmp(m_Argv[0], hwclock::arg::HCTOSYS, hwclock::length::HCTOSYS) == 0)) { + HwClock::Get()->HcToSys(); return; } - if ((nArgv0Length == dump::length::PLL) && (memcmp(m_Argv[0], dump::arg::PLL, dump::length::PLL) == 0)) { - h3_ccu_pll_dump(); + if ((nArgv0Length == hwclock::length::SYSTOHC) && (memcmp(m_Argv[0], hwclock::arg::SYSTOHC, hwclock::length::SYSTOHC) == 0)) { + HwClock::Get()->SysToHc(); return; } - if ((nArgv0Length == dump::length::LINKER) && (memcmp(m_Argv[0], dump::arg::LINKER, dump::length::LINKER) == 0)) { - arm_dump_memmap(); + if ((nArgv0Length == hwclock::length::PRINT) && (memcmp(m_Argv[0], hwclock::arg::PRINT, hwclock::length::PRINT) == 0)) { + HwClock::Get()->Print(); return; } Puts(msg::error::INVALID); } +#endif -void Shell::CmdMem() { - const auto pAddress = reinterpret_cast(hexadecimalToDecimal(m_Argv[0], m_nArgvLength[0])); - const auto nSize = hexadecimalToDecimal(m_Argv[1], m_nArgvLength[1]); - - debug_dump(pAddress, static_cast(nSize)); +#if defined (DEBUG_I2C) +void Shell::CmdI2cDetect() { + I2cDetect i2cdetect; } +#endif +#if defined (ENABLE_NTP_CLIENT) void Shell::CmdNtp() { const auto nArgv0Length = m_nArgvLength[0]; @@ -423,7 +438,9 @@ void Shell::CmdNtp() { Puts(msg::error::INVALID); } +#endif +#if defined (CONFIG_SHELL_GPS) void Shell::CmdGps() { const auto nArgv0Length = m_nArgvLength[0]; @@ -447,3 +464,43 @@ void Shell::CmdGps() { Puts(msg::error::INVALID); } #endif + +#if (PHY_TYPE == RTL8201F) +void Shell::CmdPhyTypeRTL8201F() { + const auto nArgv0Length = m_nArgvLength[0]; + + if ((nArgv0Length == rtl8201f::length::RXTIMING) && (memcmp(m_Argv[0], rtl8201f::arg::RXTIMING, rtl8201f::length::RXTIMING) == 0)) { + if (m_nArgvLength[1] == 1) { + const auto c = m_Argv[1][0]; + if (isxdigit(c) != 0) { + const uint32_t nRxTiming = c > '9' ? ((c | 0x20) - 'a' + 10) : (c - '0'); + net::phy::rtl8201f_set_rxtiming(nRxTiming); + return; + } + } + } + + if ((nArgv0Length == rtl8201f::length::TXTIMING) && (memcmp(m_Argv[0], rtl8201f::arg::TXTIMING, rtl8201f::length::TXTIMING) == 0)) { + if (m_nArgvLength[1] == 1) { + const auto c = m_Argv[1][0]; + if (isxdigit(c) != 0) { + const uint32_t nTxTiming = c > '9' ? ((c | 0x20) - 'a' + 10) : (c - '0'); + net::phy::rtl8201f_set_txtiming(nTxTiming); + return; + } + } + } + + if ((nArgv0Length == rtl8201f::length::PRINT) && (memcmp(m_Argv[0], rtl8201f::arg::PRINT, rtl8201f::length::PRINT) == 0)) { + if ((m_nArgvLength[1] == rtl8201f::length::TIMING) && (memcmp(m_Argv[1], rtl8201f::arg::TIMING, rtl8201f::length::TIMING) == 0)) { + uint32_t nRxTiming; + uint32_t nTxTiming; + net::phy::rtl8201f_get_timings(nRxTiming, nTxTiming); + Printf("RX: 0x%X, TX: 0x%X\n", nRxTiming, nTxTiming); + return; + } + } + + Puts(msg::error::INVALID); +} +#endif diff --git a/lib-remoteconfig/src/tftp/remoteconfig.cpp b/lib-remoteconfig/src/tftp/remoteconfig.cpp index 57c3a0ec..eee8894f 100644 --- a/lib-remoteconfig/src/tftp/remoteconfig.cpp +++ b/lib-remoteconfig/src/tftp/remoteconfig.cpp @@ -52,7 +52,7 @@ void RemoteConfig::PlatformHandleTftpSet() { if (m_bEnableTFTP && (m_pTFTPFileServer == nullptr)) { m_pTFTPFileServer = new TFTPFileServer(s_TFTPBuffer, FIRMWARE_MAX_SIZE); assert(m_pTFTPFileServer != nullptr); - Display::Get()->TextStatus("TFTP On", Display7SegmentMessage::INFO_TFTP_ON, CONSOLE_GREEN); + Display::Get()->TextStatus("TFTP On", CONSOLE_GREEN); } else if (!m_bEnableTFTP && (m_pTFTPFileServer != nullptr)) { const uint32_t nFileSize = m_pTFTPFileServer->GetFileSize(); DEBUG_PRINTF("nFileSize=%d, %d", nFileSize, m_pTFTPFileServer->isDone()); @@ -63,7 +63,7 @@ void RemoteConfig::PlatformHandleTftpSet() { bSucces = FlashCodeInstall::Get()->WriteFirmware(s_TFTPBuffer, nFileSize); if (!bSucces) { - Display::Get()->TextStatus("Error: TFTP", Display7SegmentMessage::ERROR_TFTP, CONSOLE_RED); + Display::Get()->TextStatus("Error: TFTP", CONSOLE_RED); } } @@ -71,7 +71,7 @@ void RemoteConfig::PlatformHandleTftpSet() { m_pTFTPFileServer = nullptr; if (bSucces) { // Keep error message - Display::Get()->TextStatus("TFTP Off", Display7SegmentMessage::INFO_TFTP_OFF, CONSOLE_GREEN); + Display::Get()->TextStatus("TFTP Off", CONSOLE_GREEN); } } diff --git a/lib-remoteconfig/src/tftp/tftpfileserver.cpp b/lib-remoteconfig/src/tftp/tftpfileserver.cpp index 75d9b540..ccc09447 100644 --- a/lib-remoteconfig/src/tftp/tftpfileserver.cpp +++ b/lib-remoteconfig/src/tftp/tftpfileserver.cpp @@ -56,7 +56,7 @@ void TFTPFileServer::Exit() { } -bool TFTPFileServer::FileOpen(__attribute__((unused)) const char* pFileName, __attribute__((unused)) tftp::Mode tMode) { +bool TFTPFileServer::FileOpen([[maybe_unused]] const char *pFileName, [[maybe_unused]] tftp::Mode tMode) { DEBUG_ENTRY DEBUG_EXIT @@ -78,7 +78,7 @@ bool TFTPFileServer::FileCreate(const char* pFileName, tftp::Mode mode) { return false; } - Display::Get()->TextStatus("TFTP Started", Display7SegmentMessage::INFO_TFTP_STARTED, CONSOLE_GREEN); + Display::Get()->TextStatus("TFTP Started", CONSOLE_GREEN); m_nFileSize = 0; @@ -91,13 +91,13 @@ bool TFTPFileServer::FileClose() { m_bDone = true; - Display::Get()->TextStatus("TFTP Ended", Display7SegmentMessage::INFO_TFTP_ENDED, CONSOLE_GREEN); + Display::Get()->TextStatus("TFTP Ended", CONSOLE_GREEN); DEBUG_EXIT return true; } -size_t TFTPFileServer::FileRead(__attribute__((unused)) void* pBuffer, __attribute__((unused)) size_t nCount, __attribute__((unused)) unsigned nBlockNumber) { +size_t TFTPFileServer::FileRead([[maybe_unused]] void* pBuffer, [[maybe_unused]] size_t nCount, [[maybe_unused]] unsigned nBlockNumber) { DEBUG_ENTRY DEBUG_EXIT diff --git a/lib-remoteconfig/src/uart/shell.cpp b/lib-remoteconfig/src/uart/shell.cpp index af803365..c14ade80 100644 --- a/lib-remoteconfig/src/uart/shell.cpp +++ b/lib-remoteconfig/src/uart/shell.cpp @@ -3,7 +3,7 @@ * */ /* Copyright (C) 2020 by hippy mailto:dmxout@gmail.com - * Copyright (C) 2020-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl + * Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-showfile/.cproject b/lib-showfile/.cproject new file mode 100755 index 00000000..a6cabe01 --- /dev/null +++ b/lib-showfile/.cproject @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib-debug/.project b/lib-showfile/.project old mode 100644 new mode 100755 similarity index 96% rename from lib-debug/.project rename to lib-showfile/.project index fbef8b1f..0a5805fc --- a/lib-debug/.project +++ b/lib-showfile/.project @@ -1,6 +1,6 @@ - lib-debug + lib-showfile diff --git a/lib-rdmresponder/.settings/language.settings.xml b/lib-showfile/.settings/language.settings.xml old mode 100644 new mode 100755 similarity index 87% rename from lib-rdmresponder/.settings/language.settings.xml rename to lib-showfile/.settings/language.settings.xml index 0af5aaae..46128a64 --- a/lib-rdmresponder/.settings/language.settings.xml +++ b/lib-showfile/.settings/language.settings.xml @@ -1,12 +1,12 @@ - - - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/lib-showfile/.settings/org.eclipse.cdt.codan.core.prefs b/lib-showfile/.settings/org.eclipse.cdt.codan.core.prefs new file mode 100755 index 00000000..300bb148 --- /dev/null +++ b/lib-showfile/.settings/org.eclipse.cdt.codan.core.prefs @@ -0,0 +1,107 @@ +eclipse.preferences.version=1 +org.eclipse.cdt.codan.checkers.errnoreturn=Warning +org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false} +org.eclipse.cdt.codan.checkers.errreturnvalue=Error +org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"} +org.eclipse.cdt.codan.checkers.localvarreturn=Warning +org.eclipse.cdt.codan.checkers.localvarreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Returning the address of a local variable\\")"} +org.eclipse.cdt.codan.checkers.nocommentinside=Error +org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"} +org.eclipse.cdt.codan.checkers.nolinecomment=Error +org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"} +org.eclipse.cdt.codan.checkers.noreturn=Error +org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false} +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error +org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"} +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error +org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"} +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"} +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error +org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"} +org.eclipse.cdt.codan.internal.checkers.BlacklistProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.BlacklistProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function or method is blacklisted\\")",blacklist\=>()} +org.eclipse.cdt.codan.internal.checkers.CStyleCastProblem=Warning +org.eclipse.cdt.codan.internal.checkers.CStyleCastProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"C-Style cast instead of C++ cast\\")",checkMacro\=>true} +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning +org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false,enable_fallthrough_quickfix_param\=>false} +org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning +org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error +org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"} +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning +org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true} +org.eclipse.cdt.codan.internal.checkers.CopyrightProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.CopyrightProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Lack of copyright information\\")",regex\=>".*Copyright.*"} +org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem=Error +org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid 'decltype(auto)' specifier\\")"} +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.FloatCompareProblem=Warning +org.eclipse.cdt.codan.internal.checkers.FloatCompareProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Direct float comparison\\")"} +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.GotoStatementProblem=Warning +org.eclipse.cdt.codan.internal.checkers.GotoStatementProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Goto statement used\\")"} +org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error +org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"} +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error +org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"} +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"} +org.eclipse.cdt.codan.internal.checkers.MagicNumberProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MagicNumberProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Avoid magic numbers\\")",checkArray\=>true,checkOperatorParen\=>true,exceptions\=>(1,0,-1,2,1.0,0.0,-1.0)} +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error +org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"} +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.MissCaseProblem=Warning +org.eclipse.cdt.codan.internal.checkers.MissCaseProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing cases in switch\\")"} +org.eclipse.cdt.codan.internal.checkers.MissDefaultProblem=Warning +org.eclipse.cdt.codan.internal.checkers.MissDefaultProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing default in switch\\")",defaultWithAllEnums\=>false} +org.eclipse.cdt.codan.internal.checkers.MissReferenceProblem=Warning +org.eclipse.cdt.codan.internal.checkers.MissReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing reference return value in assignment operator\\")"} +org.eclipse.cdt.codan.internal.checkers.MissSelfCheckProblem=Warning +org.eclipse.cdt.codan.internal.checkers.MissSelfCheckProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Missing self check in assignment operator\\")"} +org.eclipse.cdt.codan.internal.checkers.MultipleDeclarationsProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.MultipleDeclarationsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Multiple variable declaration\\")"} +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info +org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning +org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"} +org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error +org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"} +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"} +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error +org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"} +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"} +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=Warning +org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"} +org.eclipse.cdt.codan.internal.checkers.ShallowCopyProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.ShallowCopyProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Miss copy constructor or assignment operator\\")",onlynew\=>false} +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning +org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()} +org.eclipse.cdt.codan.internal.checkers.StaticVariableInHeaderProblem=Warning +org.eclipse.cdt.codan.internal.checkers.StaticVariableInHeaderProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Static variable in header file\\")"} +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false} +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning +org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false} +org.eclipse.cdt.codan.internal.checkers.SymbolShadowingProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.SymbolShadowingProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol shadowing\\")",paramFuncParameters\=>true} +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true} +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning +org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")} +org.eclipse.cdt.codan.internal.checkers.UsingInHeaderProblem=-Warning +org.eclipse.cdt.codan.internal.checkers.UsingInHeaderProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Using directive in header\\")"} +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error +org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"} +org.eclipse.cdt.codan.internal.checkers.VirtualMethodCallProblem=Error +org.eclipse.cdt.codan.internal.checkers.VirtualMethodCallProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Virtual method call in constructor/destructor\\")"} diff --git a/lib-c++/.settings/org.eclipse.cdt.core.prefs b/lib-showfile/.settings/org.eclipse.cdt.core.prefs old mode 100644 new mode 100755 similarity index 100% rename from lib-c++/.settings/org.eclipse.cdt.core.prefs rename to lib-showfile/.settings/org.eclipse.cdt.core.prefs diff --git a/lib-dmxreceiver/.settings/org.eclipse.core.resources.prefs b/lib-showfile/.settings/org.eclipse.core.resources.prefs old mode 100644 new mode 100755 similarity index 100% rename from lib-dmxreceiver/.settings/org.eclipse.core.resources.prefs rename to lib-showfile/.settings/org.eclipse.core.resources.prefs diff --git a/lib-showfile/Makefile.GD32 b/lib-showfile/Makefile.GD32 new file mode 100644 index 00000000..93df14ad --- /dev/null +++ b/lib-showfile/Makefile.GD32 @@ -0,0 +1,7 @@ +DEFINES=NDEBUG + +EXTRA_INCLUDES= + +include Rules.mk +include ../firmware-template-gd32/lib/Rules.mk + diff --git a/lib-showfile/Rules.mk b/lib-showfile/Rules.mk new file mode 100755 index 00000000..21bb2b9f --- /dev/null +++ b/lib-showfile/Rules.mk @@ -0,0 +1,57 @@ +$(info [${CURDIR}]) +$(info $$MAKE_FLAGS [${MAKE_FLAGS}]) + +EXTRA_INCLUDES+=../lib-properties/include ../lib-lightset/include ../lib-network/include + +ifneq ($(MAKE_FLAGS),) + ifeq (,$(findstring CONFIG_SHOWFILE_USE_CUSTOM_DISPLAY,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=src/display + EXTRA_INCLUDES+=../lib-display/include + endif + ifneq (,$(findstring CONFIG_SHOWFILE_ENABLE_OSC,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=src/osc + EXTRA_INCLUDES+=../lib-osc/include + endif + ifneq (,$(findstring CONFIG_SHOWFILE_FORMAT_OLA,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=src/formats/ola + endif + ifneq (,$(findstring CONFIG_SHOWFILE_PROTOCOL_E131,$(MAKE_FLAGS))) + E131=1 + endif + ifneq (,$(findstring CONFIG_SHOWFILE_PROTOCOL_NODE_E131,$(MAKE_FLAGS))) + E131=1 + endif + ifneq (,$(findstring CONFIG_SHOWFILE_PROTOCOL_ARTNET,$(MAKE_FLAGS))) + ARTNET=1 + endif + ifneq (,$(findstring CONFIG_SHOWFILE_PROTOCOL_NODE_ARTNET,$(MAKE_FLAGS))) + ARTNET=1 + endif + ifdef E131 + EXTRA_INCLUDES+=../lib-e131/include + EXTRA_INCLUDES+=../lib-dmx/include + endif + ifdef ARTNET + EXTRA_SRCDIR+=src/protocols/artnet + EXTRA_INCLUDES+=../lib-artnet/include ../lib-e131/include + ifneq (,$(findstring RDM,$(MAKE_FLAGS))) + EXTRA_INCLUDES+=../lib-rdm/include ../lib-dmx/include + endif + endif +else + EXTRA_SRCDIR+=src/display + EXTRA_SRCDIR+=src/formats/ola + EXTRA_SRCDIR+=src/protocols/artnet + EXTRA_INCLUDES+=../lib-display/include + EXTRA_INCLUDES+=../lib-osc/include + EXTRA_INCLUDES+=../lib-e131/include + EXTRA_INCLUDES+=../lib-artnet/include + DEFINES+=NODE_SHOWFILE + DEFINES+=CONFIG_SHOWFILE_FORMAT_OLA +# DEFINES+=CONFIG_SHOWFILE_PROTOCOL_E131 + DEFINES+=CONFIG_SHOWFILE_PROTOCOL_NODE_E131 + DEFINES+=CONFIG_SHOWFILE_ENABLE_OSC +endif + +$(info $$EXTRA_SRCDIR [${EXTRA_SRCDIR}]) +$(info $$EXTRA_INCLUDES [${EXTRA_INCLUDES}]) \ No newline at end of file diff --git a/lib-showfile/include/formats/showfileformatola.h b/lib-showfile/include/formats/showfileformatola.h new file mode 100755 index 00000000..3290d9b1 --- /dev/null +++ b/lib-showfile/include/formats/showfileformatola.h @@ -0,0 +1,311 @@ +/** + * @file showfileformatola.h + * + */ +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef FORMATS_SHOWFILEFORMATOLA_H_ +#define FORMATS_SHOWFILEFORMATOLA_H_ + +#if !defined(__clang__) +# pragma GCC push_options +# pragma GCC optimize ("O2") +#endif + +#include +#include + +#include "showfileprotocol.h" +#include "showfileconst.h" + +#include "debug.h" + +#define SHOWFILE_PREFIX "show" +#define SHOWFILE_SUFFIX ".txt" + +namespace showfile { +static constexpr uint32_t FILE_NAME_LENGTH = sizeof(SHOWFILE_PREFIX "NN" SHOWFILE_SUFFIX) - 1U; +static constexpr uint32_t FILE_MAX_NUMBER = 99; +} // namespace showfile + +class ShowFileFormat: ShowFileProtocol { +public: + ShowFileFormat() { + DEBUG_ENTRY + + assert(s_pThis == nullptr); + s_pThis = this; + + for (uint32_t nIndex = 0; nIndex < sizeof(m_digitsTable); nIndex = nIndex + 2) { + const auto nValue = nIndex / 2; + m_digitsTable[nIndex] = '0' + static_cast(nValue / 10U); + m_digitsTable[nIndex + 1] = '0' + static_cast(nValue % 10U); + } + + ShowFileProtocol::Start(); + + DEBUG_EXIT + } + + void ShowFileStart() { + DEBUG_ENTRY + + m_nDelayMillis = 0; + m_nLastMillis = 0; + + fseek(m_pShowFile, 0L, SEEK_SET); + + m_OlaState = OlaState::IDLE; + + DEBUG_EXIT + } + + void ShowFileStop() { + DEBUG_ENTRY + + DEBUG_EXIT + } + + void ShowFileResume() { + DEBUG_ENTRY + + m_nDelayMillis = 0; + m_nLastMillis = 0; + + DEBUG_EXIT + } + + void ShowFileRecord() { + DEBUG_ENTRY + DEBUG_PRINTF("m_pShowFile%snullptr", m_pShowFile != nullptr ? "!=" : "=="); + + if (m_pShowFile != nullptr) { + fputs("OLA Show\n", m_pShowFile); +#ifndef NDEBUG + perror("fputs"); +#endif + m_OlaState = OlaState::RECORD_FIRST; + } else { + m_OlaState = OlaState::IDLE; + } + + ShowFileProtocol::Record(); + + DEBUG_EXIT + } + + void ShowFilePrint() { + puts(" Format: OLA"); + ShowFileProtocol::Print(); + } + + void ShowFileRun(const bool doRun) { + if (doRun) { + Run(); + } + + ShowFileProtocol::Run(); + } + + void DoRunCleanupProcess(const bool bDoRun) { + ShowFileProtocol::DoRunCleanupProcess(bDoRun); + } + + void ShowfileWrite(const uint8_t *pDmxData,const uint32_t nSize, const uint32_t nUniverse, const uint32_t nMillis) { + if (m_OlaState == OlaState::RECORD_FIRST) { + m_OlaState = OlaState::RECORDING; + } else { + auto *p = m_buffer; + p += fast_itoa_universe(nMillis - m_nLastMillis, p); + *p++ = '\n'; + *p = '\0'; + fputs(m_buffer, m_pShowFile); +#ifndef NDEBUG + perror("fputs"); + printf("[%s]", m_buffer); +#endif + } + + m_nLastMillis = nMillis; + + auto *p = m_buffer; + + p += fast_itoa_universe(nUniverse & 0xFFFF, p); + *p++ = ' '; + + for (uint32_t nIndex = 0; nIndex < nSize; nIndex++) { + p += fast_itoa_dmx(pDmxData[nIndex] & 0xFF, p); + *p++ = ','; + } + + *--p = '\n'; + *++p = '\0'; + + fputs(m_buffer, m_pShowFile); +#ifndef NDEBUG + perror("fputs"); + printf("[%s]", m_buffer); +#endif + } + + void BlackOut() { +#if defined (CONFIG_SHOWFILE_ENABLE_MASTER) + ShowFileProtocol::DmxBlackout(); +#endif + } + + void SetMaster([[maybe_unused]] const uint32_t nMaster) { +#if defined (CONFIG_SHOWFILE_ENABLE_MASTER) + ShowFileProtocol::DmxMaster(nMaster); +#endif + } + + bool IsSyncDisabled() { + return ShowFileProtocol::IsSyncDisabled(); + } + + static ShowFileFormat *Get() { + return s_pThis; + } + +private: + void Run(); + /* + * Using a lookup table to convert binary numbers from 0 to 99 + * into ascii characters as described by Andrei Alexandrescu in + * https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920/ + */ + uint32_t fast_itoa_universe(uint32_t nUniverse, char *pDestination) { + uint32_t n = 0; + + if (nUniverse >= 10000) { + const auto nIndex = (nUniverse % 100) * 2; + pDestination[3] = m_digitsTable[nIndex]; + pDestination[4] = m_digitsTable[nIndex + 1]; + nUniverse /= 100; + n = 5; + } else if (nUniverse >= 1000) { + const auto nIndex = (nUniverse % 100) * 2; + pDestination[2] = m_digitsTable[nIndex]; + pDestination[3] = m_digitsTable[nIndex + 1]; + nUniverse /= 100; + n = 4; + } + + if (nUniverse >= 100) { + const auto nIndex = (nUniverse % 100) * 2; + pDestination[1] = m_digitsTable[nIndex]; + pDestination[2] = m_digitsTable[nIndex + 1]; + nUniverse /= 100; + if (n == 0) { + n = 2; + } + } + + if (nUniverse < 10) { + pDestination[0] = '0' + static_cast(nUniverse); + n++; + } else { + const auto nIndex = nUniverse * 2; + pDestination[0] = m_digitsTable[nIndex]; + pDestination[1] = m_digitsTable[nIndex + 1]; + if (n == 0) { + n = 2; + } + } + + return n; + } + + uint32_t fast_itoa_dmx(uint32_t nDmxValue, char *pDestination) { + uint32_t n = 0; + + if (nDmxValue >= 100) { + const auto nIndex = (nDmxValue % 100) * 2; + pDestination[1] = m_digitsTable[nIndex]; + pDestination[2] = m_digitsTable[nIndex + 1]; + nDmxValue /= 100; + n = 2; + } + + if (nDmxValue < 10) { + pDestination[0] = '0' + static_cast(nDmxValue); + n++; + } else { + const auto nIndex = nDmxValue * 2; + pDestination[0] = m_digitsTable[nIndex]; + pDestination[1] = m_digitsTable[nIndex + 1]; + n = 2; + } + + return n; + } + +#define UINT_DIGITS 12 + char *itoa_with_linefeed(uint32_t i) { + m_buffer[UINT_DIGITS + 1] = '\n'; + m_buffer[UINT_DIGITS + 2] = '\0'; + char *p = m_buffer + UINT_DIGITS; + do { + *--p = '0' + static_cast(i % 10); + i /= 10; + } while (i != 0); + return p; + } + +protected: + uint32_t m_nShowFileCurrent { showfile::FILE_MAX_NUMBER + 1 }; + bool m_bDoLoop { false }; + FILE *m_pShowFile { nullptr }; + +private: + enum class OlaState { + IDLE, PARSING_DMX, TIME_WAITING, RECORD_FIRST, RECORDING + }; + + enum class OlaParseCode { + FAILED, TIME, DMX, NONE, EOFILE + }; + + OlaParseCode GetNextLine(); + OlaParseCode ParseLine(const char *pLine); + OlaParseCode ParseDmxData(const char *pLine); + +private: + OlaParseCode m_OlaParseCode { OlaParseCode::FAILED }; + OlaState m_OlaState { OlaState::IDLE }; + char m_buffer[2048]; + char m_digitsTable[200]; + uint32_t m_nDelayMillis { 0 }; + uint32_t m_nLastMillis { 0 }; + uint32_t m_nDmxDataLength { 0 }; + uint16_t m_nUniverse { 0 }; + uint8_t m_DmxData[512]; + + static ShowFileFormat *s_pThis; +}; + +#if !defined(__clang__) +# pragma GCC pop_options +#endif + +#endif /* FORMATS_SHOWFILEFORMATOLA_H_ */ diff --git a/lib-showfile/include/protocols/showfileprotocolartnet.h b/lib-showfile/include/protocols/showfileprotocolartnet.h new file mode 100755 index 00000000..174bfadd --- /dev/null +++ b/lib-showfile/include/protocols/showfileprotocolartnet.h @@ -0,0 +1,110 @@ +/** + * @file showfileprotocolartnet.h + * + */ +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PROTOCOLS_SHOWFILEPROTOCOLARTNET_H_ +#define PROTOCOLS_SHOWFILEPROTOCOLARTNET_H_ + +#include +#include + +#include "artnetcontroller.h" +#include "showfileprotocolartnettrigger.h" + +#include "debug.h" + +class ShowFileProtocol { +public: + ShowFileProtocol() { + DEBUG_ENTRY + + DEBUG_EXIT + } + + ~ShowFileProtocol() { + m_ArtNetController.Stop(); + } + + void Start() { + DEBUG_ENTRY + + m_ArtNetController.Start(); + + DEBUG_EXIT + } + + void Stop() { + DEBUG_ENTRY + + m_ArtNetController.Stop(); + + DEBUG_EXIT + } + + void Record() { + DEBUG_ENTRY + + DEBUG_EXIT + } + + void DmxOut(uint16_t nUniverse, const uint8_t *pDmxData, uint32_t nLength) { + m_ArtNetController.HandleDmxOut(nUniverse, pDmxData, nLength); + } + + void DmxSync() { + m_ArtNetController.HandleSync(); + } + + void DmxBlackout() { + m_ArtNetController.HandleBlackout(); + } + + void DmxMaster([[maybe_unused]] const uint32_t nMaster) { +#if defined(CONFIG_ARTNET_CONTROLLER_ENABLE_MASTER) + m_ArtNetController.SetMaster(nMaster); +#endif + } + + void DoRunCleanupProcess(const bool bDoRun) { + m_ArtNetController.SetRunTableCleanup(bDoRun); + } + + void Run() { + m_ArtNetController.Run(); + } + + bool IsSyncDisabled() { + return !m_ArtNetController.GetSynchronization(); + } + + void Print() { + m_ArtNetController.Print(); + } + +private: + ArtNetController m_ArtNetController; + ShowFileProtocolArtNetTrigger m_ShowFileProtocolArtNetTrigger; +}; + +#endif /* PROTOCOLS_SHOWFILEPROTOCOLARTNET_H_ */ diff --git a/lib-showfile/include/protocols/showfileprotocolartnettrigger.h b/lib-showfile/include/protocols/showfileprotocolartnettrigger.h new file mode 100755 index 00000000..9f655a8c --- /dev/null +++ b/lib-showfile/include/protocols/showfileprotocolartnettrigger.h @@ -0,0 +1,50 @@ +/** + * @file showfileprotocolartnettrigger.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PROTOCOLS_SHOWFILEPROTOCOLARTNETTRIGGER_H_ +#define PROTOCOLS_SHOWFILEPROTOCOLARTNETTRIGGER_H_ + +#include +#include + +#include "artnetcontroller.h" +#include "artnettrigger.h" + +#include "debug.h" + +class ShowFileProtocolArtNetTrigger: public ArtNetTrigger { +public: + ShowFileProtocolArtNetTrigger() { + DEBUG_ENTRY + + ArtNetController::Get()->SetArtNetTrigger(this); + + DEBUG_EXIT + } + + void Handler(const struct TArtNetTrigger *ptArtNetTrigger) override; +}; + +#endif /* PROTOCOLS_SHOWFILEPROTOCOLARTNETTRIGGER_H_ */ diff --git a/lib-showfile/include/protocols/showfileprotocole131.h b/lib-showfile/include/protocols/showfileprotocole131.h new file mode 100755 index 00000000..975ac7fb --- /dev/null +++ b/lib-showfile/include/protocols/showfileprotocole131.h @@ -0,0 +1,105 @@ +/** + * @file showfileprotocole131.h + * + */ +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PROTOCOLS_SHOWFILEPROTOCOLE131_H_ +#define PROTOCOLS_SHOWFILEPROTOCOLE131_H_ + +#include +#include + +#include "e131controller.h" + +#include "debug.h" + +class ShowFileProtocol { +public: + ShowFileProtocol() { + DEBUG_ENTRY + + DEBUG_EXIT + } + + void SetSynchronizationAddress(const uint16_t SynchronizationAddress) { + m_E131Controller.SetSynchronizationAddress(SynchronizationAddress); + } + + void Start() { + DEBUG_ENTRY + + m_E131Controller.Start(); + + DEBUG_EXIT + } + + void Stop() { + DEBUG_ENTRY + + m_E131Controller.Stop(); + + DEBUG_EXIT + } + + void Record() { + DEBUG_ENTRY + + DEBUG_EXIT + } + + void DmxOut(const uint16_t nUniverse, const uint8_t *pDmxData, const uint32_t nLength) { + m_E131Controller.HandleDmxOut(nUniverse, pDmxData, nLength); + } + + void DmxSync() { + m_E131Controller.HandleSync(); + } + + void DmxBlackout() { + m_E131Controller.HandleBlackout(); + } + + void DmxMaster(const uint32_t nMaster) { + m_E131Controller.SetMaster(nMaster); + } + + void DoRunCleanupProcess([[maybe_unused]] bool bDoRun) { + } + + void Run() { + m_E131Controller.Run(); + } + + bool IsSyncDisabled() { + return (m_E131Controller.GetSynchronizationAddress() == 0); + } + + void Print() { + m_E131Controller.Print(); + } + +private: + E131Controller m_E131Controller; +}; + +#endif /* PROTOCOLS_SHOWFILEPROTOCOLE131_H_ */ diff --git a/lib-showfile/include/protocols/showfileprotocolnodeartnet.h b/lib-showfile/include/protocols/showfileprotocolnodeartnet.h new file mode 100755 index 00000000..004f58fc --- /dev/null +++ b/lib-showfile/include/protocols/showfileprotocolnodeartnet.h @@ -0,0 +1,118 @@ +/** + * @file showfileprotocolnodeartnet.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PROTOCOLS_SHOWFILEPROTOCOLNODEARTNET_H_ +#define PROTOCOLS_SHOWFILEPROTOCOLNODEARTNET_H_ + +#include +#include + +#include "artnetnode.h" +#include "artnet.h" + +#include "debug.h" + +class ShowFileProtocol { +public: + ShowFileProtocol() { + DEBUG_ENTRY + + memcpy(m_ArtDmx.Id, artnet::NODE_ID, sizeof(m_ArtDmx.Id)); + m_ArtDmx.OpCode = static_cast(artnet::OpCodes::OP_DMX); + m_ArtDmx.ProtVerHi = 0; + m_ArtDmx.ProtVerLo = artnet::PROTOCOL_REVISION; + + DEBUG_EXIT + } + + void SetSynchronizationAddress([[maybe_unused]] const uint16_t SynchronizationAddress) { + } + + void Start() { + DEBUG_ENTRY + + DEBUG_EXIT + } + + void Stop() { + DEBUG_ENTRY + + ArtNetNode::Get()->SetRecordShowfile(false); + + DEBUG_EXIT + } + + void Record() { + DEBUG_ENTRY + + ArtNetNode::Get()->SetRecordShowfile(true); + + DEBUG_EXIT + } + + void DmxOut(const uint16_t nUniverse, const uint8_t *pDmxData, uint32_t nLength) { + memcpy(m_ArtDmx.Data, pDmxData, nLength); + + if ((nLength & 0x1) == 0x1) { + m_ArtDmx.Data[nLength] = 0x00; + nLength++; + } + + m_ArtDmx.Sequence = m_nSequence++; + m_ArtDmx.Physical = static_cast(artnetnode::MAX_PORTS + 1U); + m_ArtDmx.PortAddress = nUniverse; + m_ArtDmx.LengthHi = static_cast((nLength & 0xFF00) >> 8); + m_ArtDmx.Length = static_cast(nLength & 0xFF); + + ArtNetNode::Get()->HandleShowFile(&m_ArtDmx); + } + + void DmxSync() { + } + + void DmxBlackout() { + } + + void DmxMaster([[maybe_unused]] const uint32_t nMaster) { + } + + void DoRunCleanupProcess([[maybe_unused]] bool bDoRun) { + } + + void Run() { + } + + bool IsSyncDisabled() { + return false; + } + + void Print() {} + +private: + artnet::ArtDmx m_ArtDmx; + uint8_t m_nSequence { 0 }; +}; + +#endif /* PROTOCOLS_SHOWFILEPROTOCOLNODEARTNET_H_ */ diff --git a/lib-showfile/include/protocols/showfileprotocolnodee131.h b/lib-showfile/include/protocols/showfileprotocolnodee131.h new file mode 100755 index 00000000..491325bd --- /dev/null +++ b/lib-showfile/include/protocols/showfileprotocolnodee131.h @@ -0,0 +1,129 @@ +/** + * @file showfileprotocolnodee131.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PROTOCOLS_SHOWFILEPROTOCOLNODEE131_H_ +#define PROTOCOLS_SHOWFILEPROTOCOLNODEE131_H_ + +#include +#include + +#include "e131bridge.h" +#include "e131.h" +#include "e117const.h" + +#include "hardware.h" + +#include "debug.h" + +class ShowFileProtocol { +public: + ShowFileProtocol() { + DEBUG_ENTRY + // Root Layer (See Section 5) + m_E131DataPacket.RootLayer.PreAmbleSize = __builtin_bswap16(0x0010); + m_E131DataPacket.RootLayer.PostAmbleSize = __builtin_bswap16(0x0000); + memcpy(m_E131DataPacket.RootLayer.ACNPacketIdentifier, E117Const::ACN_PACKET_IDENTIFIER, e117::PACKET_IDENTIFIER_LENGTH); + m_E131DataPacket.RootLayer.Vector = __builtin_bswap32(e131::vector::root::DATA); + Hardware::Get()->GetUuid(m_E131DataPacket.RootLayer.Cid); + // E1.31 Framing Layer (See Section 6) + m_E131DataPacket.FrameLayer.Vector = __builtin_bswap32(e131::vector::data::PACKET); + memcpy(m_E131DataPacket.FrameLayer.SourceName, E131Bridge::Get()->GetSourceName(), e131::SOURCE_NAME_LENGTH); + m_E131DataPacket.FrameLayer.SynchronizationAddress = __builtin_bswap16(0); + m_E131DataPacket.FrameLayer.Priority = e131::priority::DEFAULT; + m_E131DataPacket.FrameLayer.Options = 0; + // Data Layer + m_E131DataPacket.DMPLayer.Vector = e131::vector::dmp::SET_PROPERTY; + m_E131DataPacket.DMPLayer.Type = 0xa1; + m_E131DataPacket.DMPLayer.FirstAddressProperty = __builtin_bswap16(0x0000); + m_E131DataPacket.DMPLayer.AddressIncrement = __builtin_bswap16(0x0001); + m_E131DataPacket.DMPLayer.PropertyValues[0] = 0; + + DEBUG_EXIT + } + + void SetSynchronizationAddress([[maybe_unused]] const uint16_t SynchronizationAddress) { + } + + void Start() { + DEBUG_ENTRY + + DEBUG_EXIT + } + + void Stop() { + DEBUG_ENTRY + + DEBUG_EXIT + } + + void Record() { + DEBUG_ENTRY + + DEBUG_EXIT + } + + void DmxOut(const uint16_t nUniverse, const uint8_t *pDmxData, uint32_t nLength) { + nLength++; // Add 1 for SC + // Root Layer (See Section 5) + m_E131DataPacket.RootLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_ROOT_LAYER_LENGTH(nLength)))); + // E1.31 Framing Layer (See Section 6) + m_E131DataPacket.FrameLayer.FLagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_FRAME_LAYER_LENGTH(nLength)))); + m_E131DataPacket.FrameLayer.SequenceNumber = m_nSequenceNumber++; + m_E131DataPacket.FrameLayer.Universe = __builtin_bswap16(nUniverse); + // Data Layer + m_E131DataPacket.DMPLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_LAYER_LENGTH(nLength)))); + memcpy(m_E131DataPacket.DMPLayer.PropertyValues, &pDmxData[1], nLength - 1); + m_E131DataPacket.DMPLayer.PropertyValueCount = __builtin_bswap16(static_cast(nLength)); + + E131Bridge::Get()->HandleShowFile(&m_E131DataPacket); + } + + void DmxSync() { + } + + void DmxBlackout() { + } + + void DmxMaster([[maybe_unused]] const uint32_t nMaster) { + } + + void DoRunCleanupProcess([[maybe_unused]] bool bDoRun) { + } + + void Run() { + } + + bool IsSyncDisabled() { + return false; + } + + void Print() {} + +private: + TE131DataPacket m_E131DataPacket; + uint8_t m_nSequenceNumber { 0 }; +}; + +#endif /* PROTOCOLS_SHOWFILEPROTOCOLNODEE131_H_ */ diff --git a/lib-showfile/include/showfile.h b/lib-showfile/include/showfile.h new file mode 100644 index 00000000..834a8a44 --- /dev/null +++ b/lib-showfile/include/showfile.h @@ -0,0 +1,312 @@ +/** + * @file showfile.h + * + */ +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef SHOWFILE_H_ +#define SHOWFILE_H_ + +#include + +#include "showfileconst.h" +#include "showfiletftp.h" +#include "showfileformat.h" +#include "showfileprotocol.h" + +#if defined (CONFIG_SHOWFILE_ENABLE_OSC) +# include "showfileosc.h" +#endif + +#if defined (OUTPUT_DMX_PIXEL) || defined (OUTPUT_DMX_PIXEL_MULTI) +# define CONFIG_SHOWFILE_ENABLE_MASTER +#endif + +#include "debug.h" + +namespace showfile { +bool filename_copyto(char *pShowFileName, const uint32_t nLength, const uint32_t nShowFileNumber); +bool filename_check(const char *pShowFileName, uint32_t &nShowFileNumber); +} // namespace showfile + +class ShowFile final: public ShowFileFormat { +public: +#if defined (CONFIG_SHOWFILE_ENABLE_OSC) + ShowFile(uint16_t nPortIncoming = osc::port::DEFAULT_INCOMING, uint16_t nPortOutgoing = osc::port::DEFAULT_OUTGOING); +#else + ShowFile(); +#endif + + void Play() { + DEBUG_ENTRY + + if ((m_Mode == showfile::Mode::RECORDER) || (m_Status == showfile::Status::PLAYING) || (m_Status == showfile::Status::RECORDING)) { + DEBUG_EXIT + return; + } + + EnableTFTP(false); + + if (m_pShowFile != nullptr) { + ShowFileFormat::ShowFileStart(); + SetStatus(showfile::Status::PLAYING); + } else { + SetStatus(showfile::Status::IDLE); + } + + DEBUG_EXIT + } + + void Stop() { + DEBUG_ENTRY + + if (m_pShowFile != nullptr) { + ShowFileFormat::ShowFileStop(); + + if ((m_Status == showfile::Status::STOPPED) || (m_Status == showfile::Status::RECORDING)) { + if (m_Status == showfile::Status::RECORDING) { + fclose(m_pShowFile); + } + SetStatus(showfile::Status::IDLE); + } else { + SetStatus(showfile::Status::STOPPED); + } + } + + DEBUG_EXIT + } + + void Resume() { + DEBUG_ENTRY + + if (m_Status != showfile::Status::STOPPED) { + DEBUG_EXIT + return; + } + + if (m_pShowFile != nullptr) { + ShowFileFormat::ShowFileResume(); + SetStatus(showfile::Status::PLAYING); + } + + DEBUG_EXIT + } + +#if !defined (CONFIG_SHOWFILE_DISABLE_RECORD) + void Record() { + DEBUG_ENTRY + + if ((m_Mode == showfile::Mode::PLAYER) || (m_Status != showfile::Status::IDLE)) { + DEBUG_EXIT + return; + } + + if (m_pShowFile != nullptr) { + ShowFileFormat::ShowFileRecord(); + SetStatus(showfile::Status::RECORDING); + } else { + SetStatus(showfile::Status::IDLE); + } + + DEBUG_EXIT + } +#endif + + void Run() { + ShowFileFormat::ShowFileRun(m_Status == showfile::Status::PLAYING); +#if defined (CONFIG_SHOWFILE_ENABLE_OSC) + m_showFileOSC.Run(); +#endif +#if !defined(CONFIG_SHOWFILE_DISABLE_TFTP) + if (m_pShowFileTFTP != nullptr) { + m_pShowFileTFTP->Run(); + } +#endif + } + + void Print() { + puts("Showfile"); + if (m_aShowFileNameCurrent[0] != '\0') { + printf(" %s\n", m_aShowFileNameCurrent); + } + if (m_bAutoPlay) { + puts(" Auto play"); + } + printf(" %s\n", m_bDoLoop ? "Looping" : "Not looping"); +#if defined (CONFIG_SHOWFILE_DISABLE_RECORD) + puts(" Recorder is disabled."); +#endif + ShowFileFormat::ShowFilePrint(); +#if defined (CONFIG_SHOWFILE_ENABLE_OSC) + m_showFileOSC.Print(); +#endif + } + + showfile::Mode GetMode() const { + return m_Mode; + } + + void SetStatus(const showfile::Status Status); + + showfile::Status GetStatus() const { + return m_Status; + } + + void LoadShows(); + + void UnloadShows() { + m_nShows = 0; + + for (auto &FileIndex : m_nShowFileNumber) { + FileIndex = -1; + } + + m_nShowFileCurrent = showfile::FILE_MAX_NUMBER + 1U; + } + + void SetPlayerShowFileCurrent(const uint32_t nShowFileNumber); + +#if !defined (CONFIG_SHOWFILE_DISABLE_RECORD) + void SetRecorderShowFileCurrent(const uint32_t nShowFileNumber); +#endif + + const char *GetShowFileNameCurrent() const { + return static_cast(m_aShowFileNameCurrent); + } + + uint32_t GetShowFileCurrent() const { + return m_nShowFileCurrent; + } + + uint32_t GetShows() { + if (m_nShows == 0) { + LoadShows(); + } + return m_nShows; + } + + int32_t GetPlayerShowFile(const uint32_t nIndex) const { + if (nIndex < sizeof(m_nShowFileNumber) / sizeof(m_nShowFileNumber[0]) ) { + return m_nShowFileNumber[nIndex]; + } + + return -1; + } + + bool DeleteShowFile(const uint32_t nShowFileNumber); + + bool GetShowFileSize(const uint32_t nShowFileNumber, uint32_t &nSize); + + void DoLoop(const bool bDoLoop) { + m_bDoLoop = bDoLoop; + } + + bool GetDoLoop() const { + return m_bDoLoop; + } + + void SetAutoStart(const bool bAutoPlay) { + m_bAutoPlay = bAutoPlay; + } + + bool IsAutoStart() const { + return m_bAutoPlay; + } + + bool IsSyncDisabled() { + return ShowFileFormat::IsSyncDisabled(); + } + + void BlackOut() { +#if defined (CONFIG_SHOWFILE_ENABLE_MASTER) + Stop(); + ShowFileFormat::BlackOut(); +#endif + } + + void SetMaster([[maybe_unused]] const uint32_t nMaster) { +#if defined (CONFIG_SHOWFILE_ENABLE_MASTER) + ShowFileFormat::SetMaster(nMaster); +#endif + } + + /* + * TFTP + */ + + void EnableTFTP(bool bEnableTFTP); + + bool IsTFTPEnabled() const { +#if !defined(CONFIG_SHOWFILE_DISABLE_TFTP) + return m_bEnableTFTP; +#else + return false; +#endif + } + + /* + * OSC + */ + +#if defined (CONFIG_SHOWFILE_ENABLE_OSC) + void SetOscPortIncoming(const uint16_t nPortIncoming) { + m_showFileOSC.SetPortIncoming(nPortIncoming); + } + uint16_t GetOscPortIncoming() const { + return m_showFileOSC.GetPortIncoming(); + } + + void SetOscPortOutgoing(const uint16_t nPortOutgoing) { + m_showFileOSC.SetPortOutgoing(nPortOutgoing); + } + + uint16_t GetOscPortOutgoing() const { + return m_showFileOSC.GetPortOutgoing(); + } +#endif + + static ShowFile *Get() { + return s_pThis; + } + +private: + void OpenFile(const showfile::Mode mode, const uint32_t nShowFileNumber); + bool AddShow(const uint32_t nShowFileNumber); + +private: +#if defined (CONFIG_SHOWFILE_ENABLE_OSC) + ShowFileOSC m_showFileOSC; +#endif + showfile::Mode m_Mode {showfile::Mode::PLAYER }; + showfile::Status m_Status { showfile::Status::IDLE }; + char m_aShowFileNameCurrent[showfile::FILE_NAME_LENGTH + 1]; // Including '\0' + uint32_t m_nShows { 0 }; + int32_t m_nShowFileNumber[showfile::FILE_MAX_NUMBER + 1]; + bool m_bAutoPlay { false }; +#if !defined(CONFIG_SHOWFILE_DISABLE_TFTP) + bool m_bEnableTFTP { false }; + ShowFileTFTP *m_pShowFileTFTP { nullptr }; +#endif + static ShowFile *s_pThis; +}; + +#endif /* SHOWFILE_H_ */ diff --git a/lib-network/src/net/net_timers.cpp b/lib-showfile/include/showfileconst.h old mode 100644 new mode 100755 similarity index 65% rename from lib-network/src/net/net_timers.cpp rename to lib-showfile/include/showfileconst.h index ef8a35c7..fab1f111 --- a/lib-network/src/net/net_timers.cpp +++ b/lib-showfile/include/showfileconst.h @@ -1,8 +1,8 @@ /** - * @file net_timers.cpp + * @file showfileconst.h * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,30 +23,23 @@ * THE SOFTWARE. */ -#include - -#include "net_private.h" +#ifndef SHOWFILECONST_H_ +#define SHOWFILECONST_H_ -#include "hardware.h" - -#include "../../config/net_config.h" +#include -#ifndef NDEBUG - extern void arp_cache_timer(void); -#endif +namespace showfile { +enum class Status { + IDLE, PLAYING, STOPPED, ENDED, RECORDING, UNDEFINED +}; -static volatile uint32_t s_ticker; +static constexpr char STATUS[static_cast(showfile::Status::UNDEFINED)][12] = { "Idle", "Playing", "Stopped", "Ended", "Recording" }; -#define INTERVAL_MS (100) // 100 msec, 1/10 second +enum class Mode { + PLAYER, RECORDER, UNDEFINED +}; -void net_timers_run() { - const auto nMillis = Hardware::Get()->Millis(); +static constexpr char MODE[static_cast(showfile::Mode::UNDEFINED)][10] = { "Player", "Recorder" }; +} // namespace showfile - if (__builtin_expect((nMillis >= s_ticker), 0)) { - s_ticker = nMillis + INTERVAL_MS; - igmp_timer(); -#ifndef NDEBUG - arp_cache_timer(); -#endif - } -} +#endif /* SHOWFILECONST_H_ */ diff --git a/lib-showfile/include/showfiledisplay.h b/lib-showfile/include/showfiledisplay.h new file mode 100644 index 00000000..977230b3 --- /dev/null +++ b/lib-showfile/include/showfiledisplay.h @@ -0,0 +1,36 @@ +/** + * @file showfiledisplay.h + * + */ +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef SHOWFILEDISPLAY_H_ +#define SHOWFILEDISPLAY_H_ + +#include + +namespace showfile { +void display_filename(const char *pFileName, const uint32_t nShow); +void display_status(); +} // namespace showfile + +#endif /* SHOWFILEDISPLAY_H_ */ diff --git a/lib-showfile/include/showfileformat.h b/lib-showfile/include/showfileformat.h new file mode 100755 index 00000000..8e5737f0 --- /dev/null +++ b/lib-showfile/include/showfileformat.h @@ -0,0 +1,35 @@ +/** + * @file showfileformat.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef SHOWFILEFORMAT_H_ +#define SHOWFILEFORMAT_H_ + +#if defined (CONFIG_SHOWFILE_FORMAT_OLA) +# include "formats/showfileformatola.h" +#else +# error Format is not supported +#endif + +#endif /* SHOWFILEFORMAT_H_ */ diff --git a/lib-showfile/include/showfileosc.h b/lib-showfile/include/showfileosc.h new file mode 100644 index 00000000..66056394 --- /dev/null +++ b/lib-showfile/include/showfileosc.h @@ -0,0 +1,108 @@ +/** + * @file showfileosc.h + * + */ +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef SHOWFILEOSC_H_ +#define SHOWFILEOSC_H_ + +#if !defined (CONFIG_SHOWFILE_ENABLE_OSC) +# error This file should not be included +#endif + +#include +#include +#include + +#include "showfiledisplay.h" +#include "osc.h" + +#include "network.h" + +namespace cmd { +static constexpr char PATH[] = "/showfile/"; +} +namespace length { +static constexpr uint32_t PATH = sizeof(cmd::PATH) - 1; +} // namespace length + +struct ShowFileOSCMax { + static constexpr auto CMD_LENGTH = 128; + static constexpr auto FILES_ENTRIES = 10; +}; + +class ShowFileOSC { +public: + ShowFileOSC(uint16_t nPortIncoming = osc::port::DEFAULT_INCOMING, uint16_t nPortOutgoing = osc::port::DEFAULT_OUTGOING); + ~ShowFileOSC(); + + void Run() { + m_nBytesReceived = Network::Get()->RecvFrom(m_nHandle, const_cast(reinterpret_cast(&m_pBuffer)), &m_nRemoteIp, &m_nRemotePort); + + if (__builtin_expect((m_nBytesReceived <= length::PATH), 1)) { + return; + } + + if (memcmp(m_pBuffer, cmd::PATH, length::PATH) == 0) { + Process(); + } + } + + void Print() { + puts("OSC Server"); + printf(" Path : [%s]\n", cmd::PATH); + printf(" Incoming port : %u\n", m_nPortIncoming); + printf(" Outgoing port : %u\n", m_nPortOutgoing); + } + + void SetPortIncoming(const uint16_t nPortIncoming) { + m_nPortIncoming = nPortIncoming; + } + uint16_t GetPortIncoming() const { + return m_nPortIncoming; + } + + void SetPortOutgoing(const uint16_t nPortOutgoing) { + m_nPortOutgoing = nPortOutgoing; + } + + uint16_t GetPortOutgoing() const { + return m_nPortOutgoing; + } + +private: + void Process(); + void SendStatus(); + void ShowFiles(); + +private: + int32_t m_nHandle { -1 }; + char *m_pBuffer { nullptr }; + uint32_t m_nRemoteIp { 0 }; + uint32_t m_nBytesReceived; + uint16_t m_nRemotePort { 0 }; + uint16_t m_nPortIncoming; + uint16_t m_nPortOutgoing; +}; + +#endif /* SHOWFILEOSC_H_ */ diff --git a/lib-showfile/include/showfileparams.h b/lib-showfile/include/showfileparams.h new file mode 100644 index 00000000..e4a0bb87 --- /dev/null +++ b/lib-showfile/include/showfileparams.h @@ -0,0 +1,103 @@ +/** + * @file showfileparams.h + * + */ +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef SHOWFILEPARAMS_H_ +#define SHOWFILEPARAMS_H_ + +#include + +#include "showfile.h" +#include "configstore.h" + +namespace showfileparams { +struct Params { + uint32_t nSetList; + uint8_t nShow; + uint16_t nOscPortIncoming; + uint16_t nOscPortOutgoing; + uint16_t nUniverse; + uint8_t nDisableUnicast; + uint8_t nDmxMaster; +} __attribute__((packed)); + +struct Mask { + static constexpr uint32_t SHOW = (1U << 0); + static constexpr uint32_t OSC_PORT_INCOMING = (1U << 1); + static constexpr uint32_t OSC_PORT_OUTGOING = (1U << 2); + static constexpr uint32_t PROTOCOL = (1U << 3); + static constexpr uint32_t SACN_UNIVERSE = (1U << 4); + static constexpr uint32_t ARTNET_UNICAST_DISABLED = (1U << 5); + static constexpr uint32_t DMX_MASTER = (1U << 6); + static constexpr uint32_t OPTION_AUTO_PLAY = (1U << 7); + static constexpr uint32_t OPTION_LOOP = (1U << 8); + static constexpr uint32_t OPTION_DISABLE_SYNC = (1U << 9); +}; +} // namespace showfileparams + +class ShowFileParamsStore { +public: + static void Update(const struct showfileparams::Params *ptShowFileParams) { + ConfigStore::Get()->Update(configstore::Store::SHOW, ptShowFileParams, sizeof(struct showfileparams::Params)); + } + + static void Copy(struct showfileparams::Params *ptShowFileParams) { + ConfigStore::Get()->Copy(configstore::Store::SHOW, ptShowFileParams, sizeof(struct showfileparams::Params)); + } +}; + +class ShowFileParams { +public: + ShowFileParams(); + + void Load(); + void Load(const char *pBuffer, uint32_t nLength); + + void Builder(const struct TShowFileParams *ptShowFileParamss, char *pBuffer, uint32_t nLength, uint32_t& nSize); + void Save(char *pBuffer, uint32_t nLength, uint32_t& nSize) { + Builder(nullptr, pBuffer, nLength, nSize); + } + + void Set(); + + bool IsArtNetBroadcast() const { + return isMaskSet(showfileparams::Mask::ARTNET_UNICAST_DISABLED); + } + + static void staticCallbackFunction(void *p, const char *s); + +private: + void Dump(); + void HandleOptions(const char *pLine, const char *pKeyword, uint16_t nMask); + void callbackFunction(const char *s); + bool isMaskSet(uint32_t nMask) const { + return (m_Params.nSetList & nMask) == nMask; + } + void SetBool(const uint8_t nValue, const uint32_t nMask); + +private: + showfileparams::Params m_Params; +}; + +#endif /* SHOWFILEPARAMS_H_ */ diff --git a/lib-rdmsensor/src/rmdsensorprint.cpp b/lib-showfile/include/showfileparamsconst.h similarity index 71% rename from lib-rdmsensor/src/rmdsensorprint.cpp rename to lib-showfile/include/showfileparamsconst.h index 369ea0dc..f403b9d1 100644 --- a/lib-rdmsensor/src/rmdsensorprint.cpp +++ b/lib-showfile/include/showfileparamsconst.h @@ -1,5 +1,5 @@ /** - * @file rdmsensorprint.cpp + * @file showfileparamsconst.h * */ /* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl @@ -23,14 +23,22 @@ * THE SOFTWARE. */ -#include +#ifndef SHOWFILEPARAMSCONST_H_ +#define SHOWFILEPARAMSCONST_H_ -#include "rdmsensor.h" +struct ShowFileParamsConst { + static const char FILE_NAME[]; -void RDMSensor::Print() { - printf("%d [%.*s]\n", m_tRDMSensorDefintion.sensor, m_tRDMSensorDefintion.nLength, m_tRDMSensorDefintion.description); - printf(" RangeMin %d\n", m_tRDMSensorDefintion.range_min); - printf(" RangeMax %d\n", m_tRDMSensorDefintion.range_max); - printf(" NormalMin %d\n", m_tRDMSensorDefintion.normal_min); - printf(" NormalMax %d\n", m_tRDMSensorDefintion.normal_max); -} + static const char SHOW[]; + + static const char DMX_MASTER[]; + + static const char OPTION_AUTO_PLAY[]; + static const char OPTION_LOOP[]; + static const char OPTION_DISABLE_SYNC[]; + + static const char SACN_SYNC_UNIVERSE[]; + static const char ARTNET_DISABLE_UNICAST[]; +}; + +#endif /* SHOWFILEPARAMSCONST_H_ */ diff --git a/lib-showfile/include/showfileprotocol.h b/lib-showfile/include/showfileprotocol.h new file mode 100755 index 00000000..feba3cc2 --- /dev/null +++ b/lib-showfile/include/showfileprotocol.h @@ -0,0 +1,51 @@ +/** + * @file showfileprotocol.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef SHOWFILEPROTOCOL_H_ +#define SHOWFILEPROTOCOL_H_ + +#if defined (CONFIG_SHOWFILE_PROTOCOL_E131) +# include "protocols/showfileprotocole131.h" +#elif defined (CONFIG_SHOWFILE_PROTOCOL_ARTNET) +# include "protocols/showfileprotocolartnet.h" +#elif defined (CONFIG_SHOWFILE_PROTOCOL_NODE_E131) +# define CONFIG_SHOWFILE_PROTOCOL_INTERNAL +# include "protocols/showfileprotocolnodee131.h" +#elif defined (CONFIG_SHOWFILE_PROTOCOL_NODE_ARTNET) +# define CONFIG_SHOWFILE_PROTOCOL_INTERNAL +# include "protocols/showfileprotocolnodeartnet.h" +#else +# error Protocol is not supported +#endif + +#if defined(CONFIG_SHOWFILE_PROTOCOL_E131) && defined(CONFIG_SHOWFILE_PROTOCOL_ARTNET) +# error Protocol configuration error +#endif + +#if defined(CONFIG_SHOWFILE_PROTOCOL_NODE_E131) && defined(CONFIG_SHOWFILE_PROTOCOL_NODE_ARTNET) +# error Protocol node configuration error +#endif + +#endif /* SHOWFILEPROTOCOL_H_ */ diff --git a/lib-configstore/include/storerdmsubdevices.h b/lib-showfile/include/showfiletftp.h similarity index 57% rename from lib-configstore/include/storerdmsubdevices.h rename to lib-showfile/include/showfiletftp.h index cdd4c1c6..95467850 100644 --- a/lib-configstore/include/storerdmsubdevices.h +++ b/lib-showfile/include/showfiletftp.h @@ -1,5 +1,5 @@ /** - * @file storerdmsubdevices.h + * @file showfiletftp.h * */ /* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl @@ -23,31 +23,50 @@ * THE SOFTWARE. */ -#ifndef STORERDMSUBDEVICES_H_ -#define STORERDMSUBDEVICES_H_ +#ifndef SHOWFILETFTP_H_ +#define SHOWFILETFTP_H_ -#include "rdmsubdevicesparams.h" +#include -#include "configstore.h" +#include "net/apps/tftpdaemon.h" -class StoreRDMSubDevices final: public RDMSubDevicesParamsStore { +#include "debug.h" + +class ShowFileTFTP final: public TFTPDaemon { public: - StoreRDMSubDevices(); + ShowFileTFTP() { + DEBUG_ENTRY - void Update(const rdm::subdevicesparams::Params *pParams) override { - ConfigStore::Get()->Update(configstore::Store::RDMSUBDEVICES, pParams, sizeof(struct rdm::subdevicesparams::Params)); + DEBUG_EXIT } - void Copy(rdm::subdevicesparams::Params *pParams) override { - ConfigStore::Get()->Copy(configstore::Store::RDMSUBDEVICES, pParams, sizeof(struct rdm::subdevicesparams::Params)); + bool FileOpen(const char *pFileName, tftp::Mode mode) override; + bool FileCreate(const char *pFileName, tftp::Mode mode) override; + + bool FileClose() override { + DEBUG_ENTRY + + if (m_pFile != nullptr) { + fclose(m_pFile); + m_pFile = nullptr; + } + + DEBUG_EXIT + return true; } - static StoreRDMSubDevices *Get() { - return s_pThis; + size_t FileRead(void *pBuffer, size_t nCount, [[maybe_unused]] unsigned nBlockNumber) override { + return fread(pBuffer, 1, nCount, m_pFile); } + size_t FileWrite(const void *pBuffer, size_t nCount, [[maybe_unused]] unsigned nBlockNumber) override { + return fwrite(pBuffer, 1, nCount, m_pFile); + } + + void Exit() override; + private: - static StoreRDMSubDevices *s_pThis; + FILE *m_pFile { nullptr }; }; -#endif /* STORERDMSUBDEVICES_H_ */ +#endif /* SHOWFILETFTP_H_ */ diff --git a/lib-showfile/src/display/showfiledisplay.cpp b/lib-showfile/src/display/showfiledisplay.cpp new file mode 100755 index 00000000..88300534 --- /dev/null +++ b/lib-showfile/src/display/showfiledisplay.cpp @@ -0,0 +1,88 @@ +/** + * @file showfiledisplay.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "showfile.h" +#include "showfiledisplay.h" + +#include "display.h" + +namespace showfile { +void display_filename(const char *pFileName, const uint32_t nShow) { + assert(pFileName != nullptr); + + if (pFileName[0] != 0) { + Display::Get()->TextStatus(pFileName, static_cast(nShow)); + } else { + Display::Get()->TextStatus("No showfile"); + } +} + +void display_status() { + Display::Get()->SetCursorPos(0, 6); + + switch (ShowFile::Get()->GetStatus()) { + case showfile::Status::IDLE: + Display::Get()->PutString("Idle "); + break; + case showfile::Status::PLAYING: + Display::Get()->PutString("Running "); + break; + case showfile::Status::STOPPED: + Display::Get()->PutString("Stopped "); + break; + case showfile::Status::ENDED: + Display::Get()->PutString("Ended "); + break; + case showfile::Status::RECORDING: + Display::Get()->PutString("Recording "); + break; + case showfile::Status::UNDEFINED: + default: + Display::Get()->PutString("No Status"); + break; + } + + Display::Get()->SetCursorPos(11, 7); + + if (ShowFile::Get()->IsTFTPEnabled()) { + Display::Get()->PutString("[TFTP On]"); + } else if (ShowFile::Get()->GetDoLoop()) { + Display::Get()->PutString("[Looping]"); + } else { + Display::Get()->PutString(" "); + } +} +} // namespace showfile + + + + + + + + diff --git a/lib-showfile/src/formats/ola/showfile_record.cpp b/lib-showfile/src/formats/ola/showfile_record.cpp new file mode 100755 index 00000000..263540ce --- /dev/null +++ b/lib-showfile/src/formats/ola/showfile_record.cpp @@ -0,0 +1,64 @@ +/** + * @file showfile_record.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if !defined(__clang__) +# pragma GCC push_options +# pragma GCC optimize ("O2") +#endif + +#include +#include "formats/showfileformatola.h" + +#if defined (CONFIG_SHOWFILE_PROTOCOL_NODE_ARTNET) +#include "artnet.h" + +namespace showfile { +void record(const struct artnet::ArtDmx *pArtDmx, const uint32_t nMillis) { + const auto nDmxSlots = static_cast(((pArtDmx->LengthHi << 8) & 0xff00) | pArtDmx->Length); + ShowFileFormat::Get()->ShowfileWrite(pArtDmx->Data, nDmxSlots, pArtDmx->PortAddress, nMillis); +} + +void record([[maybe_unused]] const struct artnet::ArtSync *pArtSync, [[maybe_unused]] const uint32_t nMillis) { + // Nothng to do here +} +} // namespace showfile +#endif + +#if defined (CONFIG_SHOWFILE_PROTOCOL_NODE_E131) +#include "e131packets.h" + +namespace showfile { +void record(const struct TE131DataPacket *pE131DataPacket, const uint32_t nMillis) { + const auto *const pDmxData = &pE131DataPacket->DMPLayer.PropertyValues[1]; + const auto nLength = __builtin_bswap16(pE131DataPacket->DMPLayer.PropertyValueCount) - 1U; + const auto Universe = __builtin_bswap16(pE131DataPacket->FrameLayer.Universe); + ShowFileFormat::Get()->ShowfileWrite(pDmxData, nLength, Universe, nMillis); +} + +void record([[maybe_unused]] const struct TE131SynchronizationPacket *pE131SynchronizationPacke, [[maybe_unused]] const uint32_t nMillis) { + // Nothing to do here +} +} // namespace showfile +#endif diff --git a/lib-showfile/src/formats/ola/showfileformatola.cpp b/lib-showfile/src/formats/ola/showfileformatola.cpp new file mode 100644 index 00000000..63b91f83 --- /dev/null +++ b/lib-showfile/src/formats/ola/showfileformatola.cpp @@ -0,0 +1,143 @@ +/** + * @file showfileformatola.cpp + * + */ +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include "formats/showfileformatola.h" +#include "showfile.h" + +#include "hardware.h" + +#include "debug.h" + +ShowFileFormat *ShowFileFormat::s_pThis; + +void ShowFileFormat::Run() { + if (m_OlaState != OlaState::TIME_WAITING) { + m_OlaParseCode = GetNextLine(); + + if (m_OlaParseCode == OlaParseCode::DMX) { + if (m_nDmxDataLength != 0) { + ShowFileProtocol::DmxOut(m_nUniverse, m_DmxData, m_nDmxDataLength); + } + } else if (m_OlaParseCode == OlaParseCode::TIME) { + if (m_nDelayMillis != 0) { + if (m_nDmxDataLength != 0) { + ShowFileProtocol::DmxSync(); + } + } + m_OlaState = OlaState::TIME_WAITING; + } else if (m_OlaParseCode == OlaParseCode::EOFILE) { + if (m_bDoLoop) { + fseek(m_pShowFile, 0L, SEEK_SET); + } else { + ShowFile::Get()->SetStatus(showfile::Status::ENDED); + } + } + } + + const auto nMillis = Hardware::Get()->Millis(); + + if ((nMillis - m_nLastMillis) >= m_nDelayMillis) { + m_nLastMillis = nMillis; + m_OlaState = OlaState::PARSING_DMX; + } +} + +ShowFileFormat::OlaParseCode ShowFileFormat::ParseDmxData(const char *pLine) { + char *p = const_cast(pLine); + int64_t k = 0; + uint32_t nLength = 0; + + while (isdigit(*p) == 1) { + k = k * 10 + *p - '0'; + + if (k > 255) { + DEBUG_EXIT + return OlaParseCode::FAILED; + } + + p++; + + if (*p == ',' || (isdigit(*p) == 0)) { + + if (nLength > 512) { + DEBUG_EXIT + return OlaParseCode::FAILED; + } + + m_DmxData[nLength] = static_cast(k); + + k = 0; + nLength++; + p++; + } + } + + m_nDmxDataLength = nLength; + + return OlaParseCode::DMX; +} + +ShowFileFormat::OlaParseCode ShowFileFormat::ParseLine(const char *pLine) { + char *p = const_cast(pLine); + int32_t k = 0; + + while (isdigit(*p) == 1) { + k = k * 10 + *p - '0'; + p++; + } + + if (k > static_cast((static_cast(~0)))) { + return OlaParseCode::FAILED; + } + + if (*p++ == ' ') { + m_nDelayMillis = 0; + m_nUniverse = static_cast(k); + return ParseDmxData(p); + } + + m_nDelayMillis = static_cast(k); + + return OlaParseCode::TIME; +} + +ShowFileFormat::OlaParseCode ShowFileFormat::GetNextLine() { + if (m_pShowFile != nullptr) { + if (fgets(m_buffer, (sizeof(m_buffer) - 1), m_pShowFile) != m_buffer) { + return OlaParseCode::EOFILE; + } + + if (isdigit(m_buffer[0])) { + return ParseLine(m_buffer); + } + } + + return OlaParseCode::FAILED; +} diff --git a/lib-showfile/src/json_delete.cpp b/lib-showfile/src/json_delete.cpp new file mode 100755 index 00000000..86700064 --- /dev/null +++ b/lib-showfile/src/json_delete.cpp @@ -0,0 +1,65 @@ +/** + * @file json_delete.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "showfile.h" +#include "showfileconst.h" +#include "showfileparamsconst.h" + +#include "sscan.h" + +#include "debug.h" + +namespace remoteconfig { +namespace showfile { +void json_delete(const char *pBuffer, const uint32_t nBufferSize) { + DEBUG_ENTRY + + if (nBufferSize < sizeof("show=x")) { + DEBUG_EXIT + return; + } + + uint8_t nValue8; + + if (Sscan::Uint8(pBuffer, ShowFileParamsConst::SHOW, nValue8) == Sscan::OK) { + if (nValue8 <= ::showfile::FILE_MAX_NUMBER) { + ShowFile::Get()->DeleteShowFile(nValue8); + + DEBUG_EXIT + return; + } + + DEBUG_EXIT + return; + } + + DEBUG_EXIT +} +} // namespace showfile +} // namespace remoteconfig diff --git a/lib-showfile/src/json_get_directory.cpp b/lib-showfile/src/json_get_directory.cpp new file mode 100755 index 00000000..6d174c14 --- /dev/null +++ b/lib-showfile/src/json_get_directory.cpp @@ -0,0 +1,72 @@ +/** + * @file json_get_directory.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include "showfile.h" + +namespace remoteconfig { +namespace showfile { + +uint32_t json_get_directory(char *pOutBuffer, const uint32_t nOutBufferSize) { + const auto nBufferSize = nOutBufferSize - 2U; + auto nLength = static_cast(snprintf(pOutBuffer, nBufferSize, "{\"shows\":[")); + + for (uint32_t nShowIndex = 0; nShowIndex < ShowFile::Get()->GetShows(); nShowIndex++) { + const auto nShow = ShowFile::Get()->GetPlayerShowFile(nShowIndex); + if (nShow >= 0) { + uint32_t nFileSize; + if (ShowFile::Get()->GetShowFileSize(static_cast(nShow), nFileSize)) { + const auto nSize = nBufferSize - nLength; + const auto nCharacters = static_cast(snprintf(&pOutBuffer[nLength], nSize, "{\"show\":%d,\"size\":%u},", nShow, nFileSize)); + + if (nCharacters > nSize) { + break; + } + + nLength+=nCharacters; + + if (nLength >= nBufferSize) { + break; + } + } + } + } + + if (pOutBuffer[nLength - 1] == ',') { + nLength--; + } + + pOutBuffer[nLength++] = ']'; + pOutBuffer[nLength++] = '}'; + + assert(nLength <= nOutBufferSize); + return nLength; +} +} // namespace showfile +} // namespace remoteconfig diff --git a/lib-showfile/src/json_status.cpp b/lib-showfile/src/json_status.cpp new file mode 100755 index 00000000..0eec9c86 --- /dev/null +++ b/lib-showfile/src/json_status.cpp @@ -0,0 +1,118 @@ +/** + * @file json_status.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "showfile.h" +#include "showfileconst.h" +#include "showfileparamsconst.h" +#include "showfiledisplay.h" + +#include "readconfigfile.h" +#include "sscan.h" + +static void staticCallbackFunction([[maybe_unused]] void *p, const char *s) { + assert(p == nullptr); + assert(s != nullptr); + + uint8_t nValue8; + + if (Sscan::Uint8(s, ShowFileParamsConst::SHOW, nValue8) == Sscan::OK) { + if (nValue8 <= showfile::FILE_MAX_NUMBER) { + ShowFile::Get()->SetPlayerShowFileCurrent(nValue8); + } + return; + } + +#if !defined (CONFIG_SHOWFILE_DISABLE_RECORD) + if (Sscan::Uint8(s, "recorder", nValue8) == Sscan::OK) { + if (nValue8 <= showfile::FILE_MAX_NUMBER) { + ShowFile::Get()->SetRecorderShowFileCurrent(nValue8); + } + return; + } +#endif + + if (Sscan::Uint8(s, ShowFileParamsConst::OPTION_LOOP, nValue8) == Sscan::OK) { + ShowFile::Get()->DoLoop(nValue8 != 0); + return; + } + + char action[8]; + uint32_t nLength = sizeof(action) - 1; + + if (Sscan::Char(s, "status" , action, nLength) == Sscan::OK) { + if (strncmp(action, "play", nLength) == 0) { + ShowFile::Get()->Play(); + return; + } + + if (strncmp(action, "stop", nLength) == 0) { + ShowFile::Get()->Stop(); + return; + } + + if (strncmp(action, "resume", nLength) == 0) { + ShowFile::Get()->Resume(); + return; + } + +#if !defined (CONFIG_SHOWFILE_DISABLE_RECORD) + if (strncmp(action, "record", nLength) == 0) { + ShowFile::Get()->Record(); + return; + } +#endif + + return; + } +} + +namespace remoteconfig { +namespace showfile { +uint32_t json_get_status(char *pOutBuffer, const uint32_t nOutBufferSize) { + const auto status = ShowFile::Get()->GetStatus(); + assert(status != ::showfile::Status::UNDEFINED); + + const auto nLength = static_cast(snprintf(pOutBuffer, nOutBufferSize, + "{\"mode\":\"%s\",\"%s\":\"%u\",\"status\":\"%s\",\"%s\":\"%s\"}", + ShowFile::Get()->GetMode() == ::showfile::Mode::RECORDER ? "Recorder" : "Player", + ShowFileParamsConst::SHOW, + static_cast(ShowFile::Get()->GetShowFileCurrent()), + ::showfile::STATUS[static_cast(status)], + ShowFileParamsConst::OPTION_LOOP, + ShowFile::Get()->GetDoLoop() ? "1" : "0")); + return nLength; +} + +void json_set_status(const char *pBuffer, const uint32_t nBufferSize) { + ReadConfigFile config(staticCallbackFunction, nullptr); + config.Read(pBuffer, nBufferSize); + ::showfile::display_status(); +} +} // namespace showfile +} // namespace remoteconfig diff --git a/lib-showfile/src/osc/showfileosc.cpp b/lib-showfile/src/osc/showfileosc.cpp new file mode 100644 index 00000000..4e597bbc --- /dev/null +++ b/lib-showfile/src/osc/showfileosc.cpp @@ -0,0 +1,296 @@ +/** + * @file showfileosc.cpp + * + */ +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include "showfileosc.h" +#include "showfile.h" + +#include "oscsimplemessage.h" +#include "oscsimplesend.h" + +#include "network.h" + +#include "debug.h" + +namespace cmd { + static constexpr char START[] = "start"; + static constexpr char STOP[] = "stop"; + static constexpr char RESUME[] = "resume"; + static constexpr char SHOW[] = "show"; + static constexpr char LOOP[] = "loop"; + static constexpr char BO[] = "blackout"; +#if defined (CONFIG_SHOWFILE_ENABLE_MASTER) + static constexpr char MASTER[] = "master"; +#endif + static constexpr char TFTP[] = "tftp"; + static constexpr char DELETE[] = "delete"; + // TouchOSC specific + static constexpr char RELOAD[] = "reload"; + static constexpr char INDEX[] = "index"; +} + +namespace length { + static constexpr uint32_t START = sizeof(cmd::START) - 1; + static constexpr uint32_t STOP = sizeof(cmd::STOP) - 1; + static constexpr uint32_t RESUME = sizeof(cmd::RESUME) - 1; + static constexpr uint32_t SHOW = sizeof(cmd::SHOW) - 1; + static constexpr uint32_t LOOP = sizeof(cmd::LOOP) - 1; + static constexpr uint32_t BO = sizeof(cmd::BO) - 1; +#if defined (CONFIG_SHOWFILE_ENABLE_MASTER) + static constexpr uint32_t MASTER = sizeof(cmd::MASTER) - 1; +#endif + static constexpr uint32_t TFTP = sizeof(cmd::TFTP) - 1; + static constexpr uint32_t DELETE = sizeof(cmd::DELETE) - 1; + // TouchOSC specific + static constexpr uint32_t RELOAD = sizeof(cmd::RELOAD) - 1; + static constexpr uint32_t INDEX = sizeof(cmd::INDEX) - 1; +} + +ShowFileOSC::ShowFileOSC(uint16_t nPortIncoming, uint16_t nPortOutgoing) : m_nPortIncoming(nPortIncoming), m_nPortOutgoing(nPortOutgoing) { + DEBUG_ENTRY + + m_nHandle = Network::Get()->Begin(m_nPortIncoming); + assert(m_nHandle != -1); + + DEBUG_EXIT +} + +ShowFileOSC::~ShowFileOSC() { + DEBUG_ENTRY + + Network::Get()->End(m_nPortIncoming); + + DEBUG_EXIT +} + +void ShowFileOSC::Process() { + DEBUG_PRINTF("[%s] %d,%d %s", m_pBuffer, static_cast(strlen(m_pBuffer)), static_cast(length::PATH), &m_pBuffer[length::PATH]); + + if (memcmp(&m_pBuffer[length::PATH], cmd::START, length::START) == 0) { + ShowFile::Get()->Play(); + SendStatus(); + DEBUG_PUTS("ActionStart"); + return; + } + + if (memcmp(&m_pBuffer[length::PATH], cmd::STOP, length::STOP) == 0){ + ShowFile::Get()->Stop(); + SendStatus(); + DEBUG_PUTS("ActionStop"); + return; + } + + if (memcmp(&m_pBuffer[length::PATH], cmd::RESUME, length::RESUME) == 0) { + ShowFile::Get()->Resume(); + SendStatus(); + DEBUG_PUTS("ActionResume"); + return; + } + + if (memcmp(&m_pBuffer[length::PATH], cmd::SHOW, length::SHOW) == 0) { + OscSimpleMessage Msg(m_pBuffer, m_nBytesReceived); + + const auto nValue = static_cast(Msg.GetInt(0)); + + if (nValue <= showfile::FILE_MAX_NUMBER) { + ShowFile::Get()->SetPlayerShowFileCurrent(nValue); + SendStatus(); + } + + DEBUG_PRINTF("Show %d", nValue); + return; + } + + if (memcmp(&m_pBuffer[length::PATH], cmd::LOOP, length::LOOP) == 0) { + OscSimpleMessage Msg(m_pBuffer, m_nBytesReceived); + + int nValue; + + if (Msg.GetType(0) == osc::type::INT32) { + nValue = Msg.GetInt(0); + } else if (Msg.GetType(0) == osc::type::FLOAT) { // TouchOSC + nValue = static_cast(Msg.GetFloat(0)); + } else { + return; + } + + ShowFile::Get()->DoLoop(nValue != 0); + SendStatus(); + showfile::display_status(); + + DEBUG_PRINTF("Loop %d", nValue != 0); + return; + } + + if (memcmp(&m_pBuffer[length::PATH], cmd::BO, length::BO) == 0) { + ShowFile::Get()->BlackOut(); + SendStatus(); + DEBUG_PUTS("Blackout"); + return; + } + +#if defined (CONFIG_SHOWFILE_ENABLE_MASTER) + if (memcmp(&m_pBuffer[length::PATH], cmd::MASTER, length::MASTER) == 0) { + OscSimpleMessage Msg(m_pBuffer, m_nBytesReceived); + + int nValue; + + if (Msg.GetType(0) == osc::type::INT32) { + nValue = Msg.GetInt(0); + } else if (Msg.GetType(0) == osc::type::FLOAT) { // TouchOSC + nValue = static_cast(Msg.GetFloat(0)); + } else { + return; + } + + if ((nValue >= 0) && (nValue <= 255)) { + ShowFile::Get()->SetMaster(static_cast(nValue)); + } + + DEBUG_PRINTF("Master %d", nValue); + return; + } +#endif + + if (memcmp(&m_pBuffer[length::PATH], cmd::TFTP, length::TFTP) == 0) { + OscSimpleMessage Msg(m_pBuffer, m_nBytesReceived); + + int nValue; + + if (Msg.GetType(0) == osc::type::INT32) { + nValue = Msg.GetInt(0); + } else if (Msg.GetType(0) == osc::type::FLOAT) { // TouchOSC + nValue = static_cast(Msg.GetFloat(0)); + } else { + return; + } + + ShowFile::Get()->EnableTFTP(nValue != 0); + SendStatus(); + + DEBUG_PRINTF("TFTP %d", nValue != 0); + return; + } + + + if (memcmp(&m_pBuffer[length::PATH], cmd::DELETE, length::DELETE) == 0) { + OscSimpleMessage Msg(m_pBuffer, m_nBytesReceived); + + uint32_t nValue = 255; + + if (Msg.GetType(0) == osc::type::INT32){ + nValue = static_cast(Msg.GetInt(0)); + } else { + return; + } + + DEBUG_PRINTF("nValue=%d", nValue); + + if (nValue <= showfile::FILE_MAX_NUMBER) { + char aShowFileName[showfile::FILE_NAME_LENGTH + 1]; + + showfile::filename_copyto(aShowFileName, sizeof(aShowFileName), nValue); + + OscSimpleSend MsgName(m_nHandle, m_nRemoteIp, m_nPortOutgoing, "/showfile/name", "s", aShowFileName); + + if (ShowFile::Get()->DeleteShowFile(nValue)) { + OscSimpleSend MsgStatus(m_nHandle, m_nRemoteIp, m_nPortOutgoing, "/showfile/status", "s", "Deleted"); + } else { + OscSimpleSend MsgStatus(m_nHandle, m_nRemoteIp, m_nPortOutgoing, "/showfile/status", "s", "Not deleted"); + } + } + + DEBUG_PRINTF("Delete %d", nValue); + return; + } + + if (memcmp(&m_pBuffer[length::PATH], cmd::INDEX, length::INDEX) == 0) { + OscSimpleMessage Msg(m_pBuffer, m_nBytesReceived); + + if (Msg.GetType(0) != osc::type::FLOAT){ + return; + } + + const auto nIndex = static_cast(Msg.GetFloat(0)); + + DEBUG_PRINTF("Index %u", nIndex); + + const auto nShow = ShowFile::Get()->GetPlayerShowFile(nIndex); + + if (nShow < 0) { + return; + } + + DEBUG_PRINTF("nShow %d", nShow); + + ShowFile::Get()->SetPlayerShowFileCurrent(static_cast(nShow)); + SendStatus(); + + return; + } + + // TouchOSC + if (memcmp(&m_pBuffer[length::PATH], cmd::RELOAD, length::RELOAD) == 0) { + ShowFiles(); + DEBUG_PUTS("Reload"); + return; + } +} + +// TouchOSC +void ShowFileOSC::SendStatus() { + OscSimpleSend MsgName(m_nHandle, m_nRemoteIp, m_nPortOutgoing, "/showfile/name", "s", ShowFile::Get()->GetShowFileNameCurrent()); + + const auto status = ShowFile::Get()->GetStatus(); + assert(status != showfile::Status::UNDEFINED); + + OscSimpleSend MsgStatus(m_nHandle, m_nRemoteIp, m_nPortOutgoing, "/showfile/status", "s", showfile::STATUS[static_cast(status)]); +} + +// TouchOSC +void ShowFileOSC::ShowFiles() { + char aPath[64]; + char aValue[4]; + + uint32_t i; + + for (i = 0; i < ShowFile::Get()->GetShows(); i++) { + snprintf(aPath, sizeof(aPath) - 1, "/showfile/%u/show", static_cast(i)); + snprintf(aValue, sizeof(aValue) - 1, "%.2u", static_cast(ShowFile::Get()->GetPlayerShowFile(i))); + OscSimpleSend MsgStatus(m_nHandle, m_nRemoteIp, m_nPortOutgoing, aPath, "s", aValue); + } + + for (; i < ShowFileOSCMax::FILES_ENTRIES; i++) { + snprintf(aPath, sizeof(aPath) - 1, "/showfile/%u/show", static_cast(i)); + OscSimpleSend MsgStatus(m_nHandle, m_nRemoteIp, m_nPortOutgoing, aPath, "s", " "); + } + + SendStatus(); +} diff --git a/lib-showfile/src/protocols/artnet/showfileprotocolartnettrigger.cpp b/lib-showfile/src/protocols/artnet/showfileprotocolartnettrigger.cpp new file mode 100755 index 00000000..845df047 --- /dev/null +++ b/lib-showfile/src/protocols/artnet/showfileprotocolartnettrigger.cpp @@ -0,0 +1,59 @@ +/** + * @file showfileprotocolartnettrigger.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "protocols/showfileprotocolartnettrigger.h" +#include "showfile.h" + +#include "debug.h" + +void ShowFileProtocolArtNetTrigger::Handler(const struct TArtNetTrigger *ptArtNetTrigger) { + DEBUG_ENTRY + DEBUG_PRINTF("Key=%d, SubKey=%d", ptArtNetTrigger->Key, ptArtNetTrigger->SubKey); + + if (ptArtNetTrigger->Key == ART_TRIGGER_KEY_SOFT) { + switch (ptArtNetTrigger->SubKey) { + case 'B': + ShowFile::Get()->BlackOut(); + break; + case 'G': + ShowFile::Get()->Play(); + break; + case 'R': + ShowFile::Get()->Resume(); + break; + case 'S': + ShowFile::Get()->Stop(); + break; + default: + break; + } + } + + if (ptArtNetTrigger->Key == ART_TRIGGER_KEY_SHOW) { + ShowFile::Get()->SetPlayerShowFileCurrent(ptArtNetTrigger->SubKey); + } + + DEBUG_EXIT +} diff --git a/lib-showfile/src/showfile.cpp b/lib-showfile/src/showfile.cpp new file mode 100644 index 00000000..af0af912 --- /dev/null +++ b/lib-showfile/src/showfile.cpp @@ -0,0 +1,338 @@ +/** + * @file showfile.cpp + * + */ +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include "showfile.h" +#include "showfiletftp.h" +#include "showfiledisplay.h" + +#if defined CONFIG_USB_HOST_MSC +# include "device/usb/host.h" +#endif + +#include "hardware.h" + +#include "debug.h" + +ShowFile *ShowFile::s_pThis; + +#if defined (CONFIG_SHOWFILE_ENABLE_OSC) +ShowFile::ShowFile(uint16_t nPortIncoming, uint16_t nPortOutgoing): m_showFileOSC(nPortIncoming, nPortOutgoing) { +#else +ShowFile::ShowFile() { +#endif + DEBUG_ENTRY + + assert(s_pThis == nullptr); + s_pThis = this; + + m_aShowFileNameCurrent[0] = '\0'; + + DEBUG_EXIT +} + +void ShowFile::OpenFile(const showfile::Mode mode, const uint32_t nShowFileNumber) { + DEBUG_ENTRY + + if (showfile::filename_copyto(m_aShowFileNameCurrent, sizeof(m_aShowFileNameCurrent), nShowFileNumber)) { +#if defined CONFIG_USB_HOST_MSC + if (usb::host::get_status() != usb::host::Status::READY) { + DEBUG_EXIT + return; + } +#endif + + if (m_pShowFile != nullptr) { + if (fclose(m_pShowFile) != 0) { + perror("fclose()"); + } + m_pShowFile = nullptr; + } + + m_pShowFile = fopen(m_aShowFileNameCurrent, mode == showfile::Mode::RECORDER ? "w" : "r"); + + if (m_pShowFile == nullptr) { + perror(const_cast(m_aShowFileNameCurrent)); + m_aShowFileNameCurrent[0] = '\0'; + } else { + m_nShowFileCurrent = nShowFileNumber; + m_Mode = mode; + } + + showfile::display_filename(m_aShowFileNameCurrent, m_nShowFileCurrent); + showfile::display_status(); + + DEBUG_EXIT + return; + } + + DEBUG_EXIT + return; +} + +void ShowFile::SetPlayerShowFileCurrent(const uint32_t nShowFileNumber) { + DEBUG_ENTRY + if (m_Status != showfile::Status::IDLE) { + DEBUG_EXIT + return; + } + + DEBUG_PRINTF("nShowFileNumber=%u", nShowFileNumber); + + OpenFile(showfile::Mode::PLAYER, nShowFileNumber); + + DEBUG_EXIT +} + +#if !defined (CONFIG_SHOWFILE_DISABLE_RECORD) +void ShowFile::SetRecorderShowFileCurrent(const uint32_t nShowFileNumber) { + DEBUG_ENTRY + + if (m_Status != showfile::Status::IDLE) { + DEBUG_EXIT + return; + } + + DEBUG_PRINTF("nShowFileNumber=%u", nShowFileNumber); + + if (AddShow(nShowFileNumber)) { + OpenFile(showfile::Mode::RECORDER, nShowFileNumber); + + DEBUG_EXIT + return; + } + + DEBUG_EXIT +} +#endif + +bool ShowFile::DeleteShowFile(const uint32_t nShowFileNumber) { + DEBUG_ENTRY + DEBUG_PRINTF("nShowFileNumber=%u", nShowFileNumber); + + char aFileName[showfile::FILE_NAME_LENGTH + 1U]; + + if (showfile::filename_copyto(aFileName, sizeof(aFileName), nShowFileNumber)) { + if (nShowFileNumber == m_nShowFileCurrent) { + if (fclose(m_pShowFile) != 0) { + perror("fclose()"); + } + m_pShowFile = nullptr; + m_nShowFileCurrent = -1; + } + const auto nResult = unlink(aFileName); + DEBUG_PRINTF("nResult=%d", nResult); + DEBUG_EXIT + return (nResult == 0); + } + + DEBUG_EXIT + return false; +} + +bool ShowFile::GetShowFileSize(const uint32_t nShowFileNumber, uint32_t &nSize) { + DEBUG_ENTRY + DEBUG_PRINTF("nShowFileNumber=%u", nShowFileNumber); + + char aFileName[showfile::FILE_NAME_LENGTH + 1U]; + + if (showfile::filename_copyto(aFileName, sizeof(aFileName), nShowFileNumber)) { + auto *pFile = fopen(aFileName, "r"); + if (pFile != nullptr) { + if (fseek(pFile, 0L, SEEK_END) == 0) { + nSize = ftell(pFile); + fclose(pFile); + DEBUG_PRINTF("nSize=%u", nSize); + DEBUG_EXIT + return true; + } + } else { + perror("fopen()"); + } + } + + DEBUG_EXIT + return false; +} + +bool ShowFile::AddShow(const uint32_t nShowFileNumber) { + DEBUG_ENTRY + + if (m_nShows == (showfile::FILE_MAX_NUMBER)) { + DEBUG_EXIT + return false; + } + + if (m_nShows == 0) { + m_nShowFileNumber[0] = static_cast(nShowFileNumber); + } else { + for (auto &Show : m_nShowFileNumber) { + if (Show == static_cast(nShowFileNumber)) { + DEBUG_EXIT + return true; + } + } + + int32_t i = m_nShows - 1; + while ((static_cast(nShowFileNumber) < m_nShowFileNumber[i]) && i >= 0) { + m_nShowFileNumber[i + 1] = m_nShowFileNumber[i]; + i--; + } + + m_nShowFileNumber[i + 1] = static_cast(nShowFileNumber); + } + + m_nShows++; + + DEBUG_EXIT + return true; +} + +void ShowFile::LoadShows() { + DEBUG_ENTRY + +#if defined (CONFIG_USB_HOST_MSC) + auto *dirp = opendir("0:/"); +#else + auto *dirp = opendir("."); +#endif + + if (dirp == nullptr) { + perror("opendir"); + DEBUG_EXIT + return; + } + + for (auto &FileIndex : m_nShowFileNumber) { + FileIndex = -1; + } + + m_nShows = 0; + + struct dirent *dp; + + do { + if ((dp = readdir(dirp)) != nullptr) { + if (dp->d_type == DT_DIR) { + continue; + } + + uint32_t nShowFileNumber; + if (!showfile::filename_check(dp->d_name, nShowFileNumber)) { + continue; + } + + DEBUG_PRINTF("Found %s", dp->d_name); + + if (!AddShow(nShowFileNumber)) { + break; + } + } + } while (dp != nullptr); + + closedir(dirp); + + DEBUG_EXIT +} + +void ShowFile::EnableTFTP([[maybe_unused]] bool bEnableTFTP) { + DEBUG_ENTRY + +#if !defined(CONFIG_SHOWFILE_DISABLE_TFTP) + if (bEnableTFTP == m_bEnableTFTP) { + DEBUG_EXIT + return; + } + + m_bEnableTFTP = bEnableTFTP; + + if (m_bEnableTFTP) { + assert(m_pShowFileTFTP == nullptr); + + Stop(); + + if (m_pShowFile != nullptr) { + if (fclose(m_pShowFile) != 0) { + perror("fclose(m_pShowFile)"); + } + m_pShowFile = nullptr; + } + + m_pShowFileTFTP = new ShowFileTFTP; + assert(m_pShowFileTFTP != nullptr); + } else { + assert(m_pShowFileTFTP != nullptr); + + delete m_pShowFileTFTP; + m_pShowFileTFTP = nullptr; + + LoadShows(); + SetPlayerShowFileCurrent(m_nShowFileCurrent); + SetStatus(showfile::Status::IDLE); + } + + showfile::display_status(); +#endif + + DEBUG_EXIT +} + +void ShowFile::SetStatus(const showfile::Status Status) { + DEBUG_ENTRY + + if (Status == m_Status) { + DEBUG_EXIT + return; + } + + m_Status = Status; + + switch (m_Status) { + case showfile::Status::IDLE: + ShowFileFormat::DoRunCleanupProcess(true); + Hardware::Get()->SetMode(hardware::ledblink::Mode::NORMAL); + break; + case showfile::Status::PLAYING: + case showfile::Status::RECORDING: + ShowFileFormat::DoRunCleanupProcess(false); + Hardware::Get()->SetMode(hardware::ledblink::Mode::DATA); + break; + case showfile::Status::STOPPED: + case showfile::Status::ENDED: + ShowFileFormat::DoRunCleanupProcess(true); + Hardware::Get()->SetMode(hardware::ledblink::Mode::NORMAL); + break; + default: + break; + } + + showfile::display_status(); + + DEBUG_EXIT +} diff --git a/lib-showfile/src/showfile_filename.cpp b/lib-showfile/src/showfile_filename.cpp new file mode 100755 index 00000000..7059402b --- /dev/null +++ b/lib-showfile/src/showfile_filename.cpp @@ -0,0 +1,91 @@ +/** + * @file showfile_filename.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include "showfile.h" + +#include "debug.h" + +namespace showfile { +bool filename_copyto(char *pShowFileName, const uint32_t nLength, const uint32_t nShowFileNumber) { + assert(nLength == showfile::FILE_NAME_LENGTH + 1); + + if (nShowFileNumber <= showfile::FILE_MAX_NUMBER) { + snprintf(pShowFileName, nLength, "show%.2u.txt", static_cast(nShowFileNumber)); + return true; + } + + return false; +} + +bool filename_check(const char *pShowFileName, uint32_t &nShowFileNumber) { + DEBUG_PRINTF("pShowFileName=[%s]", pShowFileName); + + if ((pShowFileName == nullptr) || (strlen(pShowFileName) != showfile::FILE_NAME_LENGTH)) { + DEBUG_EXIT + return false; + } + + if (memcmp(pShowFileName, SHOWFILE_PREFIX, sizeof(SHOWFILE_PREFIX) - 1) != 0) { + DEBUG_EXIT + return false; + } + + if (memcmp(&pShowFileName[showfile::FILE_NAME_LENGTH - sizeof(SHOWFILE_SUFFIX) + 1], SHOWFILE_SUFFIX, sizeof(SHOWFILE_SUFFIX) - 1) != 0) { + DEBUG_EXIT + return false; + } + + char cDigit = pShowFileName[sizeof(SHOWFILE_PREFIX) - 1]; + DEBUG_PRINTF("cDigit=%c", cDigit); + + if (!isdigit(cDigit)) { + DEBUG_EXIT + return false; + } + + nShowFileNumber = static_cast(10 * (cDigit - '0')); + + cDigit = pShowFileName[sizeof(SHOWFILE_PREFIX)]; + DEBUG_PRINTF("cDigit=%c", cDigit); + + if (!isdigit(cDigit)) { + DEBUG_EXIT + return false; + } + + nShowFileNumber += static_cast(cDigit - '0'); + + DEBUG_EXIT + return true; +} + + +} // namespace showfile diff --git a/lib-showfile/src/showfileparams.cpp b/lib-showfile/src/showfileparams.cpp new file mode 100644 index 00000000..c4b73eb8 --- /dev/null +++ b/lib-showfile/src/showfileparams.cpp @@ -0,0 +1,389 @@ +/** + * @file showfileparams.cpp + * + */ +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if !defined(__clang__) // Needed for compiling on MacOS + #pragma GCC push_options + #pragma GCC optimize ("Os") +#endif + +#include +#include +#ifndef NDEBUG +# include +#endif +#include + +#include "showfileparams.h" +#include "showfileparamsconst.h" +#include "showfile.h" +#if defined (CONFIG_SHOWFILE_ENABLE_OSC) +# include "showfileosc.h" +# include "osc.h" +# include "oscparamsconst.h" +#endif + +#include "readconfigfile.h" +#include "sscan.h" +#include "propertiesbuilder.h" + +// Protocols +#if !defined (CONFIG_SHOWFILE_PROTOCOL_INTERNAL) +# if defined (CONFIG_SHOWFILE_PROTOCOL_E131) +# include "e131controller.h" +# endif +# if defined (CONFIG_SHOWFILE_PROTOCOL_ARTNET) +# include "artnetcontroller.h" +# endif +#endif + +#include "debug.h" + +ShowFileParams::ShowFileParams() { + DEBUG_ENTRY + + memset(&m_Params, 0, sizeof(m_Params)); + +#if defined (CONFIG_SHOWFILE_ENABLE_OSC) + m_Params.nOscPortIncoming = osc::port::DEFAULT_INCOMING; + m_Params.nOscPortOutgoing = osc::port::DEFAULT_OUTGOING; +#endif +#if !defined (CONFIG_SHOWFILE_PROTOCOL_INTERNAL) +# if defined (CONFIG_SHOWFILE_PROTOCOL_E131) + m_Params.nUniverse = DEFAULT_SYNCHRONIZATION_ADDRESS; +# else +# endif +#else +#endif + m_Params.nDmxMaster = UINT8_MAX; + + DEBUG_EXIT +} + +void ShowFileParams::Load() { + DEBUG_ENTRY + + m_Params.nSetList = 0; + +#if !defined(DISABLE_FS) + ReadConfigFile configfile(ShowFileParams::staticCallbackFunction, this); + + if (configfile.Read(ShowFileParamsConst::FILE_NAME)) { + ShowFileParamsStore::Update(&m_Params); + } else +#endif + ShowFileParamsStore::Copy(&m_Params); + +#ifndef NDEBUG + Dump(); +#endif + DEBUG_EXIT +} + +void ShowFileParams::Load(const char *pBuffer, uint32_t nLength) { + DEBUG_ENTRY + + assert(pBuffer != nullptr); + assert(nLength != 0); + + m_Params.nSetList = 0; + + ReadConfigFile config(ShowFileParams::staticCallbackFunction, this); + + config.Read(pBuffer, nLength); + + ShowFileParamsStore::Update(&m_Params); + +#ifndef NDEBUG + Dump(); +#endif + DEBUG_EXIT +} + +void ShowFileParams::SetBool(const uint8_t nValue, const uint32_t nMask) { + if (nValue != 0) { + m_Params.nSetList |= nMask; + } else { + m_Params.nSetList &= ~nMask; + } +} + +void ShowFileParams::callbackFunction(const char *pLine) { + assert(pLine != nullptr); + +#if defined (CONFIG_SHOWFILE_ENABLE_OSC) + uint16_t nValue16; + + if (Sscan::Uint16(pLine, OscParamsConst::INCOMING_PORT, nValue16) == Sscan::OK) { + if ((nValue16 != osc::port::DEFAULT_INCOMING) && (nValue16 > 1023)) { + m_Params.nOscPortIncoming = nValue16; + m_Params.nSetList |= showfileparams::Mask::OSC_PORT_INCOMING; + } else { + m_Params.nOscPortIncoming = osc::port::DEFAULT_INCOMING; + m_Params.nSetList &= ~showfileparams::Mask::OSC_PORT_INCOMING; + } + return; + } + + if (Sscan::Uint16(pLine, OscParamsConst::OUTGOING_PORT, nValue16) == Sscan::OK) { + if ((nValue16 != osc::port::DEFAULT_OUTGOING) && (nValue16 > 1023)) { + m_Params.nOscPortOutgoing = nValue16; + m_Params.nSetList |= showfileparams::Mask::OSC_PORT_OUTGOING; + } else { + m_Params.nOscPortOutgoing = osc::port::DEFAULT_OUTGOING; + m_Params.nSetList &= ~showfileparams::Mask::OSC_PORT_OUTGOING; + } + return; + } +#endif + + uint8_t nValue8; + + if (Sscan::Uint8(pLine, ShowFileParamsConst::SHOW, nValue8) == Sscan::OK) { + if (nValue8 < showfile::FILE_MAX_NUMBER) { + m_Params.nShow = nValue8; + m_Params.nSetList |= showfileparams::Mask::SHOW; + } else { + m_Params.nShow = 0; + m_Params.nSetList &= ~showfileparams::Mask::SHOW; + } + return; + } + +#if !defined (CONFIG_SHOWFILE_PROTOCOL_INTERNAL) +# if defined (CONFIG_SHOWFILE_PROTOCOL_E131) + if (Sscan::Uint16(pLine, ShowFileParamsConst::SACN_SYNC_UNIVERSE, nValue16) == Sscan::OK) { + if (nValue16 > e131::universe::MAX) { + m_Params.nUniverse = DEFAULT_SYNCHRONIZATION_ADDRESS; + m_Params.nSetList &= ~showfileparams::Mask::SACN_UNIVERSE; + } else { + m_Params.nUniverse = nValue16; + m_Params.nSetList |= showfileparams::Mask::SACN_UNIVERSE; + } + return; + } +# endif +# if defined (CONFIG_SHOWFILE_PROTOCOL_ARTNET) + if (Sscan::Uint8(pLine, ShowFileParamsConst::ARTNET_DISABLE_UNICAST, nValue8) == Sscan::OK) { + if (nValue8 != 0) { + m_Params.nDisableUnicast = 1; + m_Params.nSetList |= showfileparams::Mask::ARTNET_UNICAST_DISABLED; + } else { + m_Params.nDisableUnicast = 0; + m_Params.nSetList &= ~showfileparams::Mask::ARTNET_UNICAST_DISABLED; + } + return; + } +# endif +#endif + +#if defined (CONFIG_SHOWFILE_ENABLE_MASTER) + if (Sscan::Uint8(pLine, ShowFileParamsConst::DMX_MASTER, nValue8) == Sscan::OK) { + if (nValue8 < UINT8_MAX) { + m_Params.nDmxMaster = nValue8; + m_Params.nSetList |= showfileparams::Mask::DMX_MASTER; + } else { + m_Params.nDmxMaster = UINT8_MAX; + m_Params.nSetList &= ~showfileparams::Mask::DMX_MASTER; + } + return; + } +#endif + + if (Sscan::Uint8(pLine, ShowFileParamsConst::OPTION_AUTO_PLAY, nValue8) == Sscan::OK) { + SetBool(nValue8, showfileparams::Mask::OPTION_AUTO_PLAY); + return; + } + + if (Sscan::Uint8(pLine, ShowFileParamsConst::OPTION_LOOP, nValue8) == Sscan::OK) { + SetBool(nValue8, showfileparams::Mask::OPTION_LOOP); + return; + } + + if (Sscan::Uint8(pLine, ShowFileParamsConst::OPTION_DISABLE_SYNC, nValue8) == Sscan::OK) { + SetBool(nValue8, showfileparams::Mask::OPTION_DISABLE_SYNC); + return; + } +} + +void ShowFileParams::Builder(const struct TShowFileParams *ptShowFileParamss, char *pBuffer, uint32_t nLength, uint32_t& nSize) { + DEBUG_ENTRY + + if (ptShowFileParamss != nullptr) { + memcpy(&m_Params, ptShowFileParamss, sizeof(struct showfileparams::Params)); + } else { + ShowFileParamsStore::Copy(&m_Params); + } + + PropertiesBuilder builder(ShowFileParamsConst::FILE_NAME, pBuffer, nLength); + + builder.Add(ShowFileParamsConst::SHOW, static_cast(m_Params.nShow), isMaskSet(showfileparams::Mask::SHOW)); + +#if defined (CONFIG_SHOWFILE_ENABLE_MASTER) + builder.AddComment("Pixel"); + builder.Add(ShowFileParamsConst::DMX_MASTER, static_cast(m_Params.nDmxMaster), isMaskSet(showfileparams::Mask::DMX_MASTER)); +#endif + +#if !defined (CONFIG_SHOWFILE_PROTOCOL_INTERNAL) +# if defined (CONFIG_SHOWFILE_PROTOCOL_E131) + builder.AddComment("sACN"); + builder.Add(ShowFileParamsConst::SACN_SYNC_UNIVERSE, static_cast(m_Params.nUniverse), isMaskSet(showfileparams::Mask::SACN_UNIVERSE)); +# endif +# if defined (CONFIG_SHOWFILE_PROTOCOL_ARTNET) + builder.AddComment("Art-Net"); + builder.Add(ShowFileParamsConst::ARTNET_DISABLE_UNICAST, static_cast(m_Params.nDisableUnicast), isMaskSet(showfileparams::Mask::ARTNET_UNICAST_DISABLED)); +# endif +#endif + + builder.AddComment("Options"); + builder.Add(ShowFileParamsConst::OPTION_AUTO_PLAY, isMaskSet(showfileparams::Mask::OPTION_AUTO_PLAY), isMaskSet(showfileparams::Mask::OPTION_AUTO_PLAY)); + builder.Add(ShowFileParamsConst::OPTION_LOOP, isMaskSet(showfileparams::Mask::OPTION_LOOP), isMaskSet(showfileparams::Mask::OPTION_LOOP)); +#if !defined (CONFIG_SHOWFILE_PROTOCOL_INTERNAL) + builder.Add(ShowFileParamsConst::OPTION_DISABLE_SYNC, isMaskSet(showfileparams::Mask::OPTION_DISABLE_SYNC), isMaskSet(showfileparams::Mask::OPTION_DISABLE_SYNC)); +#endif + +#if defined (CONFIG_SHOWFILE_ENABLE_OSC) + builder.AddComment("OSC Server"); + builder.Add(OscParamsConst::INCOMING_PORT, static_cast(m_Params.nOscPortIncoming), isMaskSet(showfileparams::Mask::OSC_PORT_INCOMING)); + builder.Add(OscParamsConst::OUTGOING_PORT, static_cast(m_Params.nOscPortOutgoing), isMaskSet(showfileparams::Mask::OSC_PORT_OUTGOING)); +#endif + + nSize = builder.GetSize(); + + DEBUG_EXIT +} + +void ShowFileParams::Set() { + DEBUG_ENTRY + + if (isMaskSet(showfileparams::Mask::SHOW)) { + ShowFile::Get()->SetPlayerShowFileCurrent(m_Params.nShow); + } + +#if defined (CONFIG_SHOWFILE_ENABLE_MASTER) + if (isMaskSet(showfileparams::Mask::DMX_MASTER)) { + ShowFile::Get()->SetMaster(m_Params.nDmxMaster); + } +#endif + +#if defined (CONFIG_SHOWFILE_ENABLE_OSC) + if (isMaskSet(showfileparams::Mask::OSC_PORT_INCOMING)) { + ShowFile::Get()->SetOscPortIncoming(m_Params.nOscPortIncoming); + } + + if (isMaskSet(showfileparams::Mask::OSC_PORT_OUTGOING)) { + ShowFile::Get()->SetOscPortOutgoing(m_Params.nOscPortOutgoing); + } +#endif + +#if !defined (CONFIG_SHOWFILE_PROTOCOL_INTERNAL) +# if defined (CONFIG_SHOWFILE_PROTOCOL_E131) + if (isMaskSet(showfileparams::Mask::SACN_UNIVERSE)) { + if (E131Controller::Get() != nullptr) { + E131Controller::Get()->SetSynchronizationAddress(m_Params.nUniverse); + } + } +# endif +# if defined (CONFIG_SHOWFILE_PROTOCOL_ARTNET) + if (isMaskSet(showfileparams::Mask::ARTNET_UNICAST_DISABLED)) { + if (ArtNetController::Get() != nullptr) { + ArtNetController::Get()->SetUnicast(false); + } + } +# endif +#endif + + // Options + + if (isMaskSet(showfileparams::Mask::OPTION_AUTO_PLAY)) { + ShowFile::Get()->SetAutoStart(true); + } + + if (isMaskSet(showfileparams::Mask::OPTION_LOOP)) { + ShowFile::Get()->DoLoop(true); + } + +#if !defined (CONFIG_SHOWFILE_PROTOCOL_INTERNAL) + if (isMaskSet(showfileparams::Mask::OPTION_DISABLE_SYNC)) { +# if defined (CONFIG_SHOWFILE_PROTOCOL_E131) + if (E131Controller::Get() != nullptr) { + E131Controller::Get()->SetSynchronizationAddress(0); + } +# endif +# if defined (CONFIG_SHOWFILE_PROTOCOL_ARTNET) + if (ArtNetController::Get() != nullptr) { + ArtNetController::Get()->SetSynchronization(false); + } +# endif + } +#endif + + DEBUG_EXIT +} + +void ShowFileParams::staticCallbackFunction(void *p, const char *s) { + assert(p != nullptr); + assert(s != nullptr); + + (static_cast(p))->callbackFunction(s); +} + +void ShowFileParams::Dump() { + printf("%s::%s \'%s\':\n", __FILE__, __FUNCTION__, ShowFileParamsConst::FILE_NAME); + printf(" %s=%u\n", ShowFileParamsConst::SHOW, m_Params.nShow); + +#if defined (CONFIG_SHOWFILE_ENABLE_MASTER) + printf(" %s=%u\n", ShowFileParamsConst::DMX_MASTER, m_Params.nDmxMaster); +#endif + +#if !defined (CONFIG_SHOWFILE_PROTOCOL_INTERNAL) +# if defined (CONFIG_SHOWFILE_PROTOCOL_E131) + if (isMaskSet(showfileparams::Mask::SACN_UNIVERSE)) { + printf(" %s=%u\n", ShowFileParamsConst::SACN_SYNC_UNIVERSE, m_Params.nUniverse); + } +# endif +# if defined (CONFIG_SHOWFILE_PROTOCOL_ARTNET) + if (isMaskSet(showfileparams::Mask::ARTNET_UNICAST_DISABLED)) { + printf(" %s=%u [%s]\n", ShowFileParamsConst::ARTNET_DISABLE_UNICAST, m_Params.nDisableUnicast, m_Params.nDisableUnicast == 0 ? "No" : "Yes"); + } +# endif +#endif + + if (isMaskSet(showfileparams::Mask::OPTION_AUTO_PLAY)) { + printf(" Auto start is enabled\n"); + } + + if (isMaskSet(showfileparams::Mask::OPTION_LOOP)) { + printf(" Loop is enabled\n"); + } +#if !defined (CONFIG_SHOWFILE_PROTOCOL_INTERNAL) + if (isMaskSet(showfileparams::Mask::OPTION_DISABLE_SYNC)) { + printf(" Synchronization is disabled\n"); + } +#endif +#if defined (CONFIG_SHOWFILE_ENABLE_OSC) + printf(" %s=%u\n", OscParamsConst::INCOMING_PORT, m_Params.nOscPortIncoming); + printf(" %s=%u\n", OscParamsConst::OUTGOING_PORT, m_Params.nOscPortOutgoing); +#endif +} diff --git a/lib-configstore/src/e131/storee131.cpp b/lib-showfile/src/showfileparamsconst.cpp similarity index 63% rename from lib-configstore/src/e131/storee131.cpp rename to lib-showfile/src/showfileparamsconst.cpp index 718153d5..00c17a47 100644 --- a/lib-configstore/src/e131/storee131.cpp +++ b/lib-showfile/src/showfileparamsconst.cpp @@ -1,8 +1,8 @@ /** - * @file storee131.cpp + * @file showfileparamsconst.cpp * */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,19 +23,17 @@ * THE SOFTWARE. */ -#include +#include "showfileparamsconst.h" -#include "storee131.h" -#include "debug.h" +const char ShowFileParamsConst::FILE_NAME[] = "show.txt"; -StoreE131 *StoreE131::s_pThis; +const char ShowFileParamsConst::SHOW[] = "show"; -StoreE131::StoreE131() { - DEBUG_ENTRY +const char ShowFileParamsConst::DMX_MASTER[] = "dmx_master"; - assert(s_pThis == nullptr); - s_pThis = this; +const char ShowFileParamsConst::OPTION_AUTO_PLAY[] = "auto_play"; +const char ShowFileParamsConst::OPTION_LOOP[] = "loop"; +const char ShowFileParamsConst::OPTION_DISABLE_SYNC[] = "disable_sync"; - DEBUG_PRINTF("%p", reinterpret_cast(s_pThis)); - DEBUG_EXIT -} +const char ShowFileParamsConst::SACN_SYNC_UNIVERSE[] = "sync_universe"; +const char ShowFileParamsConst::ARTNET_DISABLE_UNICAST[] = "disable_unicast"; diff --git a/lib-showfile/src/showfiletftp.cpp b/lib-showfile/src/showfiletftp.cpp new file mode 100644 index 00000000..ddb4f377 --- /dev/null +++ b/lib-showfile/src/showfiletftp.cpp @@ -0,0 +1,65 @@ +/** + * @file showfiletftp.cpp + * + */ +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "showfiletftp.h" +#include "showfile.h" + +#include "debug.h" + +void ShowFileTFTP::Exit() { + DEBUG_ENTRY + + ShowFile::Get()->EnableTFTP(false); + + DEBUG_EXIT +} + +bool ShowFileTFTP::FileOpen(const char *pFileName, [[maybe_unused]] tftp::Mode mode) { + DEBUG_PRINTF("pFileName=%s, mode=%d", pFileName, static_cast(mode)); + + uint32_t nShowFileNumber; + if (!showfile::filename_check(pFileName, nShowFileNumber)) { + DEBUG_EXIT + return false; + } + + m_pFile = fopen(pFileName, "r"); + return (m_pFile != nullptr); +} + +bool ShowFileTFTP::FileCreate(const char *pFileName, [[maybe_unused]] tftp::Mode mode) { + DEBUG_PRINTF("pFileName=%s, mode=%d", pFileName, static_cast(mode)); + + uint32_t nShowFileNumber; + if (!showfile::filename_check(pFileName, nShowFileNumber)) { + DEBUG_EXIT + return false; + } + + m_pFile = fopen(pFileName, "w+"); + return (m_pFile != nullptr); +} diff --git a/lib-uuid/.cproject b/lib-uuid/.cproject deleted file mode 100644 index 679fa1fe..00000000 --- a/lib-uuid/.cproject +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-uuid/.settings/language.settings.xml b/lib-uuid/.settings/language.settings.xml deleted file mode 100644 index d37297d8..00000000 --- a/lib-uuid/.settings/language.settings.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-uuid/.settings/org.eclipse.core.resources.prefs b/lib-uuid/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 99f26c02..00000000 --- a/lib-uuid/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -encoding/=UTF-8 diff --git a/lib-uuid/Makefile.GD32 b/lib-uuid/Makefile.GD32 deleted file mode 100644 index 61d90bdb..00000000 --- a/lib-uuid/Makefile.GD32 +++ /dev/null @@ -1,4 +0,0 @@ -DEFINES=NDEBUG -EXTRA_INCLUDES= - -include ../firmware-template-gd32/lib/Rules.mk \ No newline at end of file diff --git a/lib-ws28xx/.cproject b/lib-ws28xx/.cproject index 2161333a..7a474aa2 100644 --- a/lib-ws28xx/.cproject +++ b/lib-ws28xx/.cproject @@ -5,7 +5,7 @@ - + @@ -14,15 +14,87 @@ - + - - - + + + + + @@ -113,6 +196,7 @@ + @@ -125,28 +209,34 @@ - + - + - + - + - + - + - + + + + + + + diff --git a/lib-ws28xx/Makefile.GD32 b/lib-ws28xx/Makefile.GD32 index 25d2acc4..de713c39 100644 --- a/lib-ws28xx/Makefile.GD32 +++ b/lib-ws28xx/Makefile.GD32 @@ -1,8 +1,17 @@ -DEFINES=USE_SPI_DMA -DEFINES+=NDEBUG +#DEFINES=NDEBUG -EXTRA_INCLUDES=../lib-device/include ../lib-hal/include +EXTRA_INCLUDES= -EXTRA_SRCDIR=src/patterns src/pixel src/gpio src/i2s +EXTRA_SRCDIR=src/patterns src/pixel + +ifneq ($(MAKE_FLAGS),) + ifeq ($(findstring OUTPUT_DMX_PIXEL_MULTI,$(MAKE_FLAGS)), OUTPUT_DMX_PIXEL_MULTI) + EXTRA_SRCDIR+=src/gd32/gpio + else + EXTRA_SRCDIR+=src/gd32/i2s + endif +else + EXTRA_SRCDIR+=src/gd32/gpio src/gd32/i2s +endif include ../firmware-template-gd32/lib/Rules.mk diff --git a/lib-ws28xx/Rules.mk b/lib-ws28xx/Rules.mk old mode 100755 new mode 100644 index 7c4c20d3..3263c056 --- a/lib-ws28xx/Rules.mk +++ b/lib-ws28xx/Rules.mk @@ -1 +1 @@ -EXTRA_INCLUDES+=../lib-hal/include \ No newline at end of file +EXTRA_INCLUDES+= \ No newline at end of file diff --git a/lib-ws28xx/include/gpio/board_gd32f207rg.h b/lib-ws28xx/include/gd32/gpio/board_gd32f207rg.h similarity index 100% rename from lib-ws28xx/include/gpio/board_gd32f207rg.h rename to lib-ws28xx/include/gd32/gpio/board_gd32f207rg.h diff --git a/lib-ws28xx/include/gpio/pixelmulti_config.h b/lib-ws28xx/include/gd32/gpio/pixelmulti_config.h similarity index 88% rename from lib-ws28xx/include/gpio/pixelmulti_config.h rename to lib-ws28xx/include/gd32/gpio/pixelmulti_config.h index 2ec4316d..a6bf29c1 100644 --- a/lib-ws28xx/include/gpio/pixelmulti_config.h +++ b/lib-ws28xx/include/gd32/gpio/pixelmulti_config.h @@ -2,7 +2,7 @@ * @file pixelmulti_config.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,14 +28,18 @@ #if defined (BOARD_GD32F207RG) # include "board_gd32f207rg.h" -#elif defined (BOARD_GD32F207C_EVAL) -# include "board_gd32f207c_eval.h" #elif defined (BOARD_GD32F407RE) # include "board_gd32f407re.h" #elif defined (BOARD_GD32F450VI) # include "board_gd32f450vi.h" #elif defined (BOARD_16X4U_PIXEL) # include "board_gd32f450vi.h" +#elif defined (BOARD_GD32F470VG) +# include "board_gd32f470vg.h" +#elif defined (BOARD_GD32F207C_EVAL) +# include "board_gd32f207c_eval.h" +#elif defined (BOARD_GD32F470Z_EVAL) +# include "board_gd32f470z_eval.h" #else # error Board is not supported #endif diff --git a/lib-ws28xx/include/gpio/ws28xxmulti.h b/lib-ws28xx/include/gd32/gpio/ws28xxmulti.h similarity index 76% rename from lib-ws28xx/include/gpio/ws28xxmulti.h rename to lib-ws28xx/include/gd32/gpio/ws28xxmulti.h index 91a532f9..444d5744 100644 --- a/lib-ws28xx/include/gpio/ws28xxmulti.h +++ b/lib-ws28xx/include/gd32/gpio/ws28xxmulti.h @@ -2,7 +2,7 @@ * @file ws28xxmulti.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,13 +32,13 @@ class WS28xxMulti { public: - WS28xxMulti(PixelConfiguration& pixelConfiguration); + WS28xxMulti(); ~WS28xxMulti(); - void Print(); - - void SetPixel(const uint32_t nPortIndex, const uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue); - void SetPixel(const uint32_t nPortIndex, const uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue, uint8_t nWhite); + void SetColourRTZ(const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint8_t nColour1, const uint8_t nColour2, const uint8_t nColour3); + void SetColourRTZ(const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint8_t nRed, const uint8_t nGreen, const uint8_t nBlue, const uint8_t nWhite); + void SetColourWS2801(const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint8_t nColour1, const uint8_t nColour2, const uint8_t nColour3); + void SetPixel4Bytes(const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint8_t nCtrl, const uint8_t nColour1, const uint8_t nColour2, const uint8_t nColour3); bool IsUpdating(); @@ -46,17 +46,7 @@ class WS28xxMulti { void Blackout(); void FullOn(); - pixel::Type GetType() const { - return m_PixelConfiguration.GetType(); - } - - uint32_t GetCount() const { - return m_PixelConfiguration.GetCount(); - } - - pixel::Map GetMap() const { - return m_PixelConfiguration.GetMap(); - } + void Print(); static WS28xxMulti *Get() { return s_pThis; @@ -65,12 +55,8 @@ class WS28xxMulti { private: void Setup(uint8_t nLowCode, uint8_t nHighCode); void Setup(uint32_t nFrequency); - void SetColourRTZ(const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint8_t nColour1, const uint8_t nColour2, const uint8_t nColour3); - void SetColourWS2801(const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint8_t nColour1, const uint8_t nColour2, const uint8_t nColour3); - void SetPixel4Bytes(const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint8_t nCtrl, const uint8_t nColour1, const uint8_t nColour2, const uint8_t nColour3); private: - PixelConfiguration m_PixelConfiguration; uint32_t m_nBufSize { 0 }; static WS28xxMulti *s_pThis; diff --git a/lib-ws28xx/include/pixelconfiguration.h b/lib-ws28xx/include/pixelconfiguration.h old mode 100644 new mode 100755 index 25ecdda4..044db4ab --- a/lib-ws28xx/include/pixelconfiguration.h +++ b/lib-ws28xx/include/pixelconfiguration.h @@ -2,7 +2,7 @@ * @file pixelconfiguration.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,18 +22,40 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +/** + * Static Local Variables: + * Since C++11, the initialization of function-local static variables, is guaranteed to be thread-safe. + * This means that even if multiple threads attempt to access Get() simultaneously, + * the C++ runtime ensures that the instance is initialized only once. + */ #ifndef PIXELCONFIGURATION_H_ #define PIXELCONFIGURATION_H_ #include +#include +#include #include "pixeltype.h" -#include "gamma/gamma_tables.h" + +#if defined (CONFIG_PIXELDMX_ENABLE_GAMMATABLE) +# include "gamma/gamma_tables.h" +#endif + +#include "debug.h" class PixelConfiguration { public: - void SetType(pixel::Type Type) { + PixelConfiguration() { + DEBUG_ENTRY + + assert(s_pThis == nullptr); + s_pThis = this; + + DEBUG_EXIT + } + + void SetType(const pixel::Type Type) { m_type = Type; } @@ -41,15 +63,15 @@ class PixelConfiguration { return m_type; } - void SetCount(uint32_t nCount) { - m_nCount = nCount == 0 ? pixel::defaults::COUNT : nCount; + void SetCount(const uint32_t nCount) { + m_nCount = (nCount == 0 ? pixel::defaults::COUNT : nCount); } uint32_t GetCount() const { return m_nCount; } - void SetMap(pixel::Map tMap) { + void SetMap(const pixel::Map tMap) { m_map = tMap; } @@ -57,7 +79,7 @@ class PixelConfiguration { return m_map; } - void SetLowCode(uint8_t nLowCode) { + void SetLowCode(const uint8_t nLowCode) { m_nLowCode = nLowCode; } @@ -65,7 +87,7 @@ class PixelConfiguration { return m_nLowCode; } - void SetHighCode(uint8_t nHighCode) { + void SetHighCode(const uint8_t nHighCode) { m_nHighCode = nHighCode; } @@ -73,7 +95,7 @@ class PixelConfiguration { return m_nHighCode; } - void SetClockSpeedHz(uint32_t nClockSpeedHz) { + void SetClockSpeedHz(const uint32_t nClockSpeedHz) { m_nClockSpeedHz = nClockSpeedHz; } @@ -81,7 +103,7 @@ class PixelConfiguration { return m_nClockSpeedHz; } - void SetGlobalBrightness(uint8_t nGlobalBrightness) { + void SetGlobalBrightness(const uint8_t nGlobalBrightness) { m_nGlobalBrightness = nGlobalBrightness; } @@ -93,7 +115,16 @@ class PixelConfiguration { return m_bIsRTZProtocol; } - void SetEnableGammaCorrection(bool doEnable) { + uint32_t GetLedsPerPixel() const { + return m_nLedsPerPixel; + } + + uint32_t GetRefreshRate() const { + return m_nRefreshRate; + } + +#if defined (CONFIG_PIXELDMX_ENABLE_GAMMATABLE) + void SetEnableGammaCorrection(const bool doEnable) { m_bEnableGammaCorrection = doEnable; } @@ -101,38 +132,162 @@ class PixelConfiguration { return m_bEnableGammaCorrection; } - void SetGammaTable(uint32_t nValue) { + void SetGammaTable(const uint32_t nValue) { m_nGammaValue = static_cast(nValue); } const uint8_t *GetGammaTable() const { return m_pGammaTable; } +#endif + + void GetTxH(const pixel::Type type, uint8_t &nLowCode, uint8_t &nHighCode) { + nLowCode = 0xC0; + nHighCode = (type == pixel::Type::WS2812B ? 0xF8 : + (((type == pixel::Type::UCS1903) || (type == pixel::Type::UCS2903) || (type == pixel::Type::CS8812)) ? 0xFC : 0xF0)); + } + + void Validate() { + DEBUG_ENTRY + + if (m_type == pixel::Type::SK6812W) { + m_nCount = m_nCount <= static_cast(pixel::max::ledcount::RGBW) ? m_nCount : static_cast(pixel::max::ledcount::RGBW); + m_nLedsPerPixel = 4; + } else { + m_nCount = m_nCount <= static_cast(pixel::max::ledcount::RGB) ? m_nCount : static_cast(pixel::max::ledcount::RGB); + m_nLedsPerPixel = 3; + } + + if ((m_type == pixel::Type::APA102) || (m_type == pixel::Type::SK9822)){ + if (m_nGlobalBrightness > 0x1F) { + m_nGlobalBrightness = 0xFF; + } else { + m_nGlobalBrightness = 0xE0 | (m_nGlobalBrightness & 0x1F); + } + } + + if ((m_type == pixel::Type::WS2801) || (m_type == pixel::Type::APA102) || (m_type == pixel::Type::SK9822) || (m_type == pixel::Type::P9813)) { + m_bIsRTZProtocol = false; + + if (m_map == pixel::Map::UNDEFINED) { + m_map = pixel::Map::RGB; + } + + if (m_type == pixel::Type::P9813) { + if (m_nClockSpeedHz == 0) { + m_nClockSpeedHz = pixel::spi::speed::p9813::default_hz; + } else if (m_nClockSpeedHz > pixel::spi::speed::p9813::max_hz) { + m_nClockSpeedHz = pixel::spi::speed::p9813::max_hz; + } + } else { + if (m_nClockSpeedHz == 0) { + m_nClockSpeedHz = pixel::spi::speed::ws2801::default_hz; + } else if (m_nClockSpeedHz > pixel::spi::speed::ws2801::max_hz) { + m_nClockSpeedHz = pixel::spi::speed::ws2801::max_hz; + } + } + + const auto nLedTime = (8U * 1000000U) / m_nClockSpeedHz; + const auto nLedsTime = nLedTime * m_nCount * m_nLedsPerPixel; + m_nRefreshRate = 1000000U / nLedsTime; + } else { + m_bIsRTZProtocol = true; + + if (m_type == pixel::Type::UNDEFINED) { + m_type = pixel::Type::WS2812B; + } - void Validate(uint32_t& nLedsPerPixel); + if (m_map == pixel::Map::UNDEFINED) { + m_map = pixel::pixel_get_map(m_type); + } - void Print(); + if (m_nLowCode >= m_nHighCode) { + m_nLowCode = 0; + m_nHighCode = 0; + } - void Dump() { -#ifndef NDEBUG - Print(); + uint8_t nLowCode, nHighCode; + + GetTxH(m_type, nLowCode, nHighCode); + + if (m_nLowCode == 0) { + m_nLowCode = nLowCode; + } + + if (m_nHighCode == 0) { + m_nHighCode = nHighCode; + } + + m_nClockSpeedHz = 6400000; // 6.4MHz / 8 bits = 800Hz + + // 8 * 1000.000 + // led time (us) = ------------ * 8 = 10 us + // 6.400.000 + const auto nLedsTime = 10U * m_nCount * m_nLedsPerPixel; + m_nRefreshRate = 1000000U / nLedsTime; + } + +#if defined (CONFIG_PIXELDMX_ENABLE_GAMMATABLE) + if (m_bEnableGammaCorrection) { + if (m_nGammaValue == 0) { + m_pGammaTable = gamma::get_table_default(m_type); + } else { + m_pGammaTable = gamma::get_table(m_nGammaValue); + } + } else { + m_pGammaTable = gamma10_0; + } +#endif + + DEBUG_EXIT + } + + void Print() { + puts("Pixel configuration"); + printf(" Type : %s [%d] <%d leds/pixel>\n", pixel::pixel_get_type(m_type), static_cast(m_type), static_cast(m_nLedsPerPixel)); + printf(" Count : %d\n", m_nCount); + + if (m_bIsRTZProtocol) { + printf(" Mapping : %s [%d]\n", pixel::pixel_get_map(m_map), static_cast(m_map)); + printf(" T0H : %.2f [0x%X]\n", pixel::pixel_convert_TxH(m_nLowCode), m_nLowCode); + printf(" T1H : %.2f [0x%X]\n", pixel::pixel_convert_TxH(m_nHighCode), m_nHighCode); + } else { + if ((m_type == pixel::Type::APA102) || (m_type == pixel::Type::SK9822)){ + printf(" GlobalBrightness: %u\n", m_nGlobalBrightness); + } + } + + printf(" Clock : %u Hz\n", static_cast(m_nClockSpeedHz)); + printf(" Refresh : %u Hz\n", static_cast(m_nRefreshRate)); + +#if defined (CONFIG_PIXELDMX_ENABLE_GAMMATABLE) + printf(" Gamma correction %s\n", m_bEnableGammaCorrection ? "Yes" : "No"); #endif } - static void GetTxH(pixel::Type tType, uint8_t &nLowCode, uint8_t &nHighCode); + static PixelConfiguration& Get() { + assert(s_pThis != nullptr); // Ensure that s_pThis is valid + return *s_pThis; + } private: - pixel::Type m_type { pixel::defaults::TYPE }; uint32_t m_nCount { pixel::defaults::COUNT }; - pixel::Map m_map { pixel::Map::UNDEFINED }; uint32_t m_nClockSpeedHz { 0 }; + uint32_t m_nLedsPerPixel { 3 }; + pixel::Type m_type { pixel::defaults::TYPE }; + pixel::Map m_map { pixel::Map::UNDEFINED }; + bool m_bIsRTZProtocol { true }; uint8_t m_nLowCode { 0 }; uint8_t m_nHighCode { 0 }; uint8_t m_nGlobalBrightness { 0xFF }; + uint32_t m_nRefreshRate { 0 }; +#if defined (CONFIG_PIXELDMX_ENABLE_GAMMATABLE) uint8_t m_nGammaValue { 0 }; bool m_bEnableGammaCorrection { false }; - bool m_bIsRTZProtocol { true }; const uint8_t *m_pGammaTable { gamma10_0 }; +#endif + + static inline PixelConfiguration *s_pThis { nullptr }; }; #endif /* PIXELCONFIGURATION_H_ */ diff --git a/lib-ws28xx/include/pixelpatterns.h b/lib-ws28xx/include/pixelpatterns.h index 5fe2558d..a100e991 100644 --- a/lib-ws28xx/include/pixelpatterns.h +++ b/lib-ws28xx/include/pixelpatterns.h @@ -2,7 +2,7 @@ * @file pixelpatterns.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -56,8 +56,8 @@ enum class Direction { class PixelPatterns { public: - PixelPatterns(uint32_t nActivePorts); - ~PixelPatterns() {} + PixelPatterns(const uint32_t nActivePorts); + ~PixelPatterns() = default; static const char* GetName(pixelpatterns::Pattern pattern); @@ -66,16 +66,31 @@ class PixelPatterns { void ColourWipe(uint32_t nPortIndex, uint32_t nColour, uint32_t nInterval, pixelpatterns::Direction dir = pixelpatterns::Direction::FORWARD); void Scanner(uint32_t nPortIndex, uint32_t nColour1, uint32_t nInterval) ; void Fade(uint32_t nPortIndex, uint32_t nColour1, uint32_t nColour2, uint32_t nSteps, uint32_t nInterval, pixelpatterns::Direction dir = pixelpatterns::Direction::FORWARD); - void None(uint32_t nPortIndex) { - m_PortConfig[nPortIndex].ActivePattern = pixelpatterns::Pattern::NONE; + void None(const uint32_t nPortIndex) { + s_PortConfig[nPortIndex].ActivePattern = pixelpatterns::Pattern::NONE; Clear(nPortIndex); - while (m_pOutput->IsUpdating()) { + while (s_pOutput->IsUpdating()) { } - m_pOutput->Update(); + s_pOutput->Update(); } - void Run(); + void Run() { + if (s_pOutput->IsUpdating()) { + return; + } + + auto bIsUpdated = false; + const auto nMillis = Hardware::Get()->Millis(); + + for (uint32_t i = 0; i < s_nActivePorts; i++) { + bIsUpdated |= PortUpdate(i, nMillis); + } + + if (bIsUpdated) { + s_pOutput->Update(); + } + } uint32_t Colour(uint8_t nRed, uint8_t nGreen, uint8_t nBlue) { return static_cast(nRed << 16) | static_cast(nGreen << 8) | nBlue; @@ -94,67 +109,84 @@ class PixelPatterns { void Increment(uint32_t nPortIndex); void Reverse(uint32_t nPortIndex); - void SetPixelColour(__attribute__((unused)) uint32_t nPortIndex, uint32_t nPixelIndex, uint32_t nColour) { + void SetPixelColour([[maybe_unused]] uint32_t nPortIndex, const uint32_t nPixelIndex, const uint32_t nColour) { const auto nRed = Red(nColour); const auto nGreen = Green(nColour); const auto nBlue = Blue(nColour); #if defined (PIXELPATTERNS_MULTI) - if (m_pOutput->GetType() != pixel::Type::SK6812W) { - m_pOutput->SetPixel(nPortIndex, nPixelIndex, nRed, nGreen, nBlue); - } else { + switch (PixelConfiguration::Get().GetType()) { + case pixel::Type::WS2801: + s_pOutput->SetColourWS2801(nPortIndex, nPixelIndex, nRed, nGreen, nBlue); + break; + case pixel::Type::APA102: + case pixel::Type::SK9822: + s_pOutput->SetPixel4Bytes(nPortIndex, nPixelIndex, 0xFF, nRed, nGreen, nBlue); + break; + case pixel::Type::P9813: { + const auto nFlag = static_cast(0xC0 | ((~nBlue & 0xC0) >> 2) | ((~nRed & 0xC0) >> 4) | ((~nRed & 0xC0) >> 6)); + s_pOutput->SetPixel4Bytes(nPortIndex, nPixelIndex, nFlag, nBlue, nGreen, nRed); + } + break; + case pixel::Type::SK6812W: if ((nRed == nGreen) && (nGreen == nBlue)) { - m_pOutput->SetPixel(nPortIndex, nPixelIndex, 0x00, 0x00, 0x00, nRed); + s_pOutput->SetColourRTZ(nPortIndex, nPixelIndex, 0x00, 0x00, 0x00, nRed); } else { - m_pOutput->SetPixel(nPortIndex, nPixelIndex, nRed, nGreen, nBlue, 0x00); + s_pOutput->SetColourRTZ(nPortIndex, nPixelIndex, nRed, nGreen, nBlue, 0x00); } + break; + default: + s_pOutput->SetColourRTZ(nPortIndex, nPixelIndex, nRed, nGreen, nBlue); + break; } #else - if (m_pOutput->GetType() != pixel::Type::SK6812W) { - m_pOutput->SetPixel(nPixelIndex, nRed, nGreen, nBlue); + auto& pixelConfiguration = PixelConfiguration::Get(); + const auto type = pixelConfiguration.GetType(); + + if (type != pixel::Type::SK6812W) { + s_pOutput->SetPixel(nPixelIndex, nRed, nGreen, nBlue); } else { if ((nRed == nGreen) && (nGreen == nBlue)) { - m_pOutput->SetPixel(nPixelIndex, 0x00, 0x00, 0x00, nRed); + s_pOutput->SetPixel(nPixelIndex, 0x00, 0x00, 0x00, nRed); } else { - m_pOutput->SetPixel(nPixelIndex, nRed, nGreen, nBlue, 0x00); + s_pOutput->SetPixel(nPixelIndex, nRed, nGreen, nBlue, 0x00); } } #endif } - void ColourSet(uint32_t nPortIndex, uint32_t nColour) { - for (uint32_t i = 0; i < m_nCount; i++) { + void ColourSet(const uint32_t nPortIndex, const uint32_t nColour) { + for (uint32_t i = 0; i < PixelConfiguration::Get().GetCount(); i++) { SetPixelColour(nPortIndex, i, nColour); } } - uint32_t DimColour(uint32_t nColour) { + uint32_t DimColour(const uint32_t nColour) { return Colour(static_cast(Red(nColour) >> 1), static_cast(Green(nColour) >> 1), static_cast(Blue(nColour) >> 1)); } - uint8_t Red(uint32_t nColour) { + uint8_t Red(const uint32_t nColour) { return (nColour >> 16) & 0xFF; } - uint8_t Green(uint32_t nColour) { + uint8_t Green(const uint32_t nColour) { return (nColour >> 8) & 0xFF; } - uint8_t Blue(uint32_t nColour) { + uint8_t Blue(const uint32_t nColour) { return nColour & 0xFF; } - void Clear(uint32_t nPortIndex) { + void Clear(const uint32_t nPortIndex) { ColourSet(nPortIndex, 0); } private: #if defined (PIXELPATTERNS_MULTI) - static WS28xxMulti *m_pOutput; + static WS28xxMulti *s_pOutput; #else - static WS28xx *m_pOutput; + static WS28xx *s_pOutput; #endif - static uint32_t m_nActivePorts; - static uint32_t m_nCount; + static uint32_t s_nActivePorts; struct PortConfig { uint32_t nLastUpdate; @@ -167,9 +199,9 @@ class PixelPatterns { pixelpatterns::Pattern ActivePattern; }; - static PortConfig m_PortConfig[pixelpatterns::MAX_PORTS]; + static PortConfig s_PortConfig[pixelpatterns::MAX_PORTS]; - static uint32_t *m_pScannerColours; + static uint32_t *s_pScannerColours; }; #endif /* PIXELPATTERNS_H_ */ diff --git a/lib-ws28xx/include/pixelreboot.h b/lib-ws28xx/include/pixelreboot.h index 382e17ef..bc9cc8ad 100644 --- a/lib-ws28xx/include/pixelreboot.h +++ b/lib-ws28xx/include/pixelreboot.h @@ -2,7 +2,7 @@ * @file pixelreboot.h * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-ws28xx/include/pixeltestpattern.h b/lib-ws28xx/include/pixeltestpattern.h index 052fc1b7..93aa8f95 100644 --- a/lib-ws28xx/include/pixeltestpattern.h +++ b/lib-ws28xx/include/pixeltestpattern.h @@ -2,7 +2,7 @@ * @file pixeltestpattern.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,17 +33,18 @@ class PixelTestPattern: PixelPatterns { public: - PixelTestPattern(pixelpatterns::Pattern Pattern, uint32_t OutputPorts) : PixelPatterns(OutputPorts) { - s_Pattern = Pattern; + PixelTestPattern(const pixelpatterns::Pattern Pattern, const uint32_t OutputPorts) : PixelPatterns(OutputPorts) { + assert(s_pThis == nullptr); + s_pThis = this; SetPattern(Pattern); } - bool SetPattern(pixelpatterns::Pattern Pattern) { + bool SetPattern(const pixelpatterns::Pattern Pattern) { if (Pattern >= pixelpatterns::Pattern::LAST) { return false; } - s_Pattern = Pattern; + m_Pattern = Pattern; const auto nColour1 = PixelPatterns::Colour(0, 0, 0); const auto nColour2 = PixelPatterns::Colour(100, 100, 100); @@ -80,21 +81,21 @@ class PixelTestPattern: PixelPatterns { } void Run() { - if (s_Pattern != pixelpatterns::Pattern::NONE) { + if (__builtin_expect((m_Pattern != pixelpatterns::Pattern::NONE), 0)) { PixelPatterns::Run(); } } - static pixelpatterns::Pattern GetPattern() { - return s_Pattern; + pixelpatterns::Pattern GetPattern() { + return m_Pattern; } - static PixelTestPattern* Get() { + static PixelTestPattern *Get() { return s_pThis; } private: - static pixelpatterns::Pattern s_Pattern; + pixelpatterns::Pattern m_Pattern; static PixelTestPattern *s_pThis; }; diff --git a/lib-ws28xx/include/pixeltype.h b/lib-ws28xx/include/pixeltype.h index cc476e57..9cf8ff2d 100644 --- a/lib-ws28xx/include/pixeltype.h +++ b/lib-ws28xx/include/pixeltype.h @@ -2,7 +2,7 @@ * @file pixeltype.h * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,6 +27,7 @@ #define PIXELTYPE_H_ #include +#include namespace pixel { enum class Type { @@ -77,23 +78,98 @@ static constexpr auto TYPE = Type::WS2812B; static constexpr auto COUNT = 170; static constexpr auto OUTPUT_PORTS = 1; } // namespace defaults -} // namespace pixel -class PixelType { -public: - static const char *GetType(pixel::Type type); - static pixel::Type GetType(const char *pString); +inline Map pixel_get_map(const pixel::Type type) { + if ((type == pixel::Type::WS2811) || (type == pixel::Type::UCS2903)) { + return pixel::Map::RGB; + } - static const char *GetMap(pixel::Map map); - static pixel::Map GetMap(const char *pString); - static pixel::Map GetMap(pixel::Type type); + if (type == pixel::Type::UCS1903) { + return pixel::Map::BRG; + } - static float ConvertTxH(uint8_t nCode); - static uint8_t ConvertTxH(float fTxH); + if (type == pixel::Type::CS8812) { + return pixel::Map::BGR; + } -private: - static const char TYPES[static_cast(pixel::Type::UNDEFINED)][pixel::TYPES_MAX_NAME_LENGTH]; - static const char MAPS[static_cast(pixel::Map::UNDEFINED)][4]; -}; + return pixel::Map::GRB; +} + +static constexpr auto F_INTERVAL = 0.15625f; + +inline float pixel_convert_TxH(const uint8_t nCode) { + switch (nCode) { + case 0x80: + return F_INTERVAL * 1; + break; + case 0xC0: + return F_INTERVAL * 2; + break; + case 0xE0: + return F_INTERVAL * 3; + break; + case 0xF0: + return F_INTERVAL * 4; + break; + case 0xF8: + return F_INTERVAL * 5; + break; + case 0xFC: + return F_INTERVAL * 6; + break; + case 0xFE: + return F_INTERVAL * 7; + break; + default: + return 0; + break; + } + + assert(0); + __builtin_unreachable(); +} + +inline uint8_t pixel_convert_TxH(const float fTxH) { + if (fTxH < 0.5f * F_INTERVAL) { + return 0x00; + } + + if (fTxH < 1.5f * F_INTERVAL) { + return 0x80; + } + + if (fTxH < 2.5f * F_INTERVAL) { + return 0xC0; + } + + if (fTxH < 3.5f * F_INTERVAL) { + return 0xE0; + } + + if (fTxH < 4.5f * F_INTERVAL) { + return 0xF0; + } + + if (fTxH < 5.5f * F_INTERVAL) { + return 0xF8; + } + + if (fTxH < 6.5f * F_INTERVAL) { + return 0xFC; + } + + if (fTxH < 7.5f * F_INTERVAL) { + return 0xFE; + } + + return 0x00; +} + +const char* pixel_get_type(pixel::Type); +pixel::Type pixel_get_type(const char *); + +const char* pixel_get_map(pixel::Map); +pixel::Map pixel_get_map(const char *); +} // namespace pixel #endif /* PIXELTYPE_H_ */ diff --git a/lib-ws28xx/include/spi/ws28xxmulti.h b/lib-ws28xx/include/spi/ws28xxmulti.h deleted file mode 100644 index fe6bf8b7..00000000 --- a/lib-ws28xx/include/spi/ws28xxmulti.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file ws28xxmulti.h - * - */ -/* Copyright (C) 2019-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef SPI_WS28XXMULTI_H_ -#define SPI_WS28XXMULTI_H_ - -#include - -#include "pixelconfiguration.h" - -#if defined (H3) -# include "h3_spi.h" -#endif - -struct JamSTAPLDisplay; - -class WS28xxMulti { -public: - WS28xxMulti(PixelConfiguration& pixelConfiguration); - ~WS28xxMulti(); - - void Print(); - - void SetPixel(uint32_t nPortIndex, uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue); - void SetPixel(uint32_t nPortIndex, uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue, uint8_t nWhite); - - bool IsUpdating() { - return h3_spi_dma_tx_is_active(); // returns TRUE while DMA operation is active - } - - void Update(); - void Blackout(); - void FullOn(); - - pixel::Type GetType() const { - return m_Type; - } - - uint32_t GetCount() const { - return m_nCount; - } - - pixel::Map GetMap() const { - return m_Map; - } - - void SetJamSTAPLDisplay(JamSTAPLDisplay *pJamSTAPLDisplay) { - m_pJamSTAPLDisplay = pJamSTAPLDisplay; - } - - static WS28xxMulti *Get() { - return s_pThis; - } - -private: - uint8_t ReverseBits(uint8_t nBits); - void SetupHC595(uint8_t nT0H, uint8_t nT1H); - void SetupSPI(uint32_t nSpeedHz); - bool SetupCPLD(); - void SetupBuffers(); - void SetColour(uint32_t nPortIndex, uint32_t nPixelIndex, uint8_t nColour1, uint8_t nColour2, uint8_t nColour3); - -private: - bool m_hasCPLD { false }; - pixel::Type m_Type { pixel::defaults::TYPE }; - uint32_t m_nCount { pixel::defaults::COUNT }; - pixel::Map m_Map { pixel::Map::UNDEFINED }; - bool m_bIsRTZProtocol { true }; - uint8_t m_nGlobalBrightness { 0xFF }; - uint32_t m_nBufSize { 0 }; - uint8_t *m_pBuffer { nullptr }; - uint8_t *m_pBlackoutBuffer { nullptr }; - JamSTAPLDisplay *m_pJamSTAPLDisplay { nullptr }; - - static WS28xxMulti *s_pThis; -}; - -#endif /* SPI_WS28XXMULTI_H_ */ diff --git a/lib-ws28xx/include/ws28xx.h b/lib-ws28xx/include/ws28xx.h index 3361780d..d3fb8ef5 100644 --- a/lib-ws28xx/include/ws28xx.h +++ b/lib-ws28xx/include/ws28xx.h @@ -2,7 +2,7 @@ * @file ws28xx.h * */ -/* Copyright (C) 2017-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,44 +30,30 @@ #include "pixelconfiguration.h" -#if defined (USE_SPI_DMA) -# include "hal_spi.h" -#endif +#include "hal_spi.h" class WS28xx { public: - WS28xx(PixelConfiguration& pixelConfiguration); + WS28xx(); ~WS28xx(); void SetPixel(uint32_t nIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue); void SetPixel(uint32_t nIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue, uint8_t nWhite); -#if defined ( USE_SPI_DMA ) bool IsUpdating () { - return FUNC_PREFIX (spi_dma_tx_is_active()); - } +#if defined (GD32) + return i2s::gd32_spi_dma_tx_is_active(); +#elif defined (H3) + return h3_spi_dma_tx_is_active(); #else - bool IsUpdating() const { return false; - } #endif + } void Update(); void Blackout(); void FullOn(); - pixel::Type GetType() const { - return m_PixelConfiguration.GetType(); - } - - uint32_t GetCount() const { - return m_PixelConfiguration.GetCount(); - } - - pixel::Map GetMap() const { - return m_PixelConfiguration.GetMap(); - } - static WS28xx *Get() { return s_pThis; } @@ -77,7 +63,6 @@ class WS28xx { void SetColorWS28xx(uint32_t nOffset, uint8_t nValue); private: - PixelConfiguration m_PixelConfiguration; uint32_t m_nBufSize; uint8_t *m_pBuffer { nullptr }; uint8_t *m_pBlackoutBuffer { nullptr }; diff --git a/lib-ws28xx/include/ws28xxmulti.h b/lib-ws28xx/include/ws28xxmulti.h index 794a4bee..3872f7a2 100644 --- a/lib-ws28xx/include/ws28xxmulti.h +++ b/lib-ws28xx/include/ws28xxmulti.h @@ -2,7 +2,7 @@ * @file ws28xxmulti.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,11 +27,11 @@ #define WS28XXMULTI_H_ #if defined (H3) -# include "spi/ws28xxmulti.h" +# include "h3/ws28xxmulti.h" #elif defined (GD32) -# include "gpio/ws28xxmulti.h" +# include "gd32/gpio/ws28xxmulti.h" #else -# error +# error Platform is not supported #endif #endif /* WS28XXMULTI_H_ */ diff --git a/lib-ws28xx/src/gpio/ws28xxmulti.cpp b/lib-ws28xx/src/gd32/gpio/ws28xxmulti.cpp similarity index 88% rename from lib-ws28xx/src/gpio/ws28xxmulti.cpp rename to lib-ws28xx/src/gd32/gpio/ws28xxmulti.cpp index 2cc2e127..f0ee9c99 100644 --- a/lib-ws28xx/src/gpio/ws28xxmulti.cpp +++ b/lib-ws28xx/src/gd32/gpio/ws28xxmulti.cpp @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#if defined (DEBUG_PIXEL) +# undef NDEBUG +#endif + #pragma GCC push_options #pragma GCC optimize ("O3") #pragma GCC optimize ("-funroll-loops") @@ -36,9 +40,10 @@ #include "ws28xxmulti.h" #include "pixelconfiguration.h" #include "pixeltype.h" -#include "gpio/pixelmulti_config.h" +#include "gd32/gpio/pixelmulti_config.h" #include "gd32.h" +#include "gd32_dma_memcpy32.h" #include "debug.h" @@ -76,12 +81,13 @@ namespace pixel { static constexpr auto PORT_COUNT = __builtin_popcount(GPIO_PINx); static_assert(PORT_COUNT <= 16, "Too many ports"); // -static uint16_t s_DmaBuffer[1024 * 16] __attribute__ ((aligned (4))) SECTION_DMA_BUFFER; +static uint16_t s_DmaBuffer[2 * 1024 * 16] __attribute__ ((aligned (4))) SECTION_DMA_BUFFER; static constexpr auto DMA_BUFFER_SIZE = sizeof(pixel::s_DmaBuffer) / sizeof(s_DmaBuffer[0]); +const auto *const s_pBuffer = reinterpret_cast(pixel::s_DmaBuffer + pixel::DMA_BUFFER_SIZE / 2); // RTZ static const uint16_t s_GPIO_PINs[] __attribute__ ((aligned (4))) = { GPIO_PINx } ; -static const auto *s_pGPIO_PINs = reinterpret_cast(&s_GPIO_PINs[0]); -static auto *s_pT0H = reinterpret_cast(&s_DmaBuffer[0]); +static const auto *const s_pGPIO_PINs = reinterpret_cast(&s_GPIO_PINs[0]); +static auto *const s_pT0H = reinterpret_cast(&s_DmaBuffer[0]); static constexpr uint32_t RTZ_TIMER_PERIOD = (0.00000125f * MASTER_TIMER_CLOCK) - 1U; // Clock based static constexpr auto MAX_APA102 = ((DMA_BUFFER_SIZE / 8) - 8 ) / 4; @@ -91,7 +97,6 @@ static volatile bool sv_isRunning; extern "C" { void TIMER3_IRQHandler() { // Slave - __DMB(); const auto nIntFlag = TIMER_INTF(TIMER3); if ((nIntFlag & TIMER_INT_FLAG_CH0) == TIMER_INT_FLAG_CH0) { @@ -104,21 +109,18 @@ void TIMER3_IRQHandler() { // Slave sv_isRunning = false; GPIO_BC(GPIOx) = GPIO_PINx; - #ifndef NDEBUG +#ifndef NDEBUG GPIO_BOP(DEBUG_CS_GPIOx) = DEBUG_CS_GPIO_PINx; - #endif - } else { - assert(0); +#endif } TIMER_INTF(TIMER3) = ~nIntFlag; - __DMB(); } } -WS28xxMulti *WS28xxMulti::s_pThis = nullptr; +WS28xxMulti *WS28xxMulti::s_pThis; -WS28xxMulti::WS28xxMulti(PixelConfiguration& pixelConfiguration): m_PixelConfiguration(pixelConfiguration) { +WS28xxMulti::WS28xxMulti() { DEBUG_ENTRY assert(s_pThis == nullptr); @@ -126,30 +128,32 @@ WS28xxMulti::WS28xxMulti(PixelConfiguration& pixelConfiguration): m_PixelConfigu DEBUG_PRINTF("PORT_COUNT=%u", pixel::PORT_COUNT); - uint32_t nLedsPerPixel; - pixelConfiguration.Validate(nLedsPerPixel); + auto& pixelConfiguration = PixelConfiguration::Get(); - const auto Type = m_PixelConfiguration.GetType(); + pixelConfiguration.Validate(); - if ((Type == pixel::Type::APA102) || (Type == pixel::Type::SK9822) || (Type == pixel::Type::P9813)) { + const auto type = pixelConfiguration.GetType(); + const auto nLedsPerPixel = pixelConfiguration.GetLedsPerPixel(); + + if ((type == pixel::Type::APA102) || (type == pixel::Type::SK9822) || (type == pixel::Type::P9813)) { DEBUG_PRINTF("MAX_APA102=%u", pixel::MAX_APA102); if (pixelConfiguration.GetCount() > pixel::MAX_APA102) { pixelConfiguration.SetCount(pixel::MAX_APA102); - pixelConfiguration.Validate(nLedsPerPixel); - pixelConfiguration.Dump(); + pixelConfiguration.Validate(); } } - const auto nCount = m_PixelConfiguration.GetCount(); + const auto nCount = pixelConfiguration.GetCount(); m_nBufSize = nCount * nLedsPerPixel; - if ((Type == pixel::Type::APA102) || (Type == pixel::Type::SK9822) || (Type == pixel::Type::P9813)) { + if ((type == pixel::Type::APA102) || (type == pixel::Type::SK9822) || (type == pixel::Type::P9813)) { m_nBufSize += nCount; m_nBufSize += 8; } m_nBufSize *= 8; + DEBUG_PRINTF("s_DmaBuffer=%p, s_pBuffer=%p", pixel::s_DmaBuffer, pixel::s_pBuffer); DEBUG_PRINTF("m_nBufSize=%u [%u]", m_nBufSize, (m_nBufSize + 1024) / 1024); assert(m_nBufSize <= pixel::DMA_BUFFER_SIZE); @@ -161,7 +165,6 @@ WS28xxMulti::WS28xxMulti(PixelConfiguration& pixelConfiguration): m_PixelConfigu #if !defined (GD32F4XX) gpio_init(GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PINx); #else - gpio_af_set(GPIOx, GPIO_AF_0, GPIO_PINx); gpio_mode_set(GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, GPIO_PINx); gpio_output_options_set(GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PINx); #endif @@ -173,7 +176,6 @@ WS28xxMulti::WS28xxMulti(PixelConfiguration& pixelConfiguration): m_PixelConfigu #if !defined (GD32F4XX) gpio_init(DEBUG_CS_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, DEBUG_CS_GPIO_PINx); #else - gpio_af_set(DEBUG_CS_GPIOx, GPIO_AF_0, DEBUG_CS_GPIO_PINx); gpio_mode_set(DEBUG_CS_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, DEBUG_CS_GPIO_PINx); gpio_output_options_set(DEBUG_CS_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, DEBUG_CS_GPIO_PINx); #endif @@ -187,6 +189,8 @@ WS28xxMulti::WS28xxMulti(PixelConfiguration& pixelConfiguration): m_PixelConfigu Setup(pixelConfiguration.GetClockSpeedHz()); } + dma::memcpy32_init(); + DEBUG_EXIT } @@ -563,10 +567,11 @@ void WS28xxMulti::Setup(uint32_t nFrequency) { * BEGIN Buffer setup */ - const auto Type = m_PixelConfiguration.GetType(); + auto& pixelConfiguration = PixelConfiguration::Get(); + const auto Type = pixelConfiguration.GetType(); if ((Type == pixel::Type::APA102) || (Type == pixel::Type::SK9822) || (Type == pixel::Type::P9813)) { - const auto nCount = m_PixelConfiguration.GetCount(); + const auto nCount = pixelConfiguration.GetCount(); for (auto nPortIndex = 0; nPortIndex < pixel::PORT_COUNT; nPortIndex++) { SetPixel4Bytes(nPortIndex, 0, 0, 0, 0, 0); @@ -586,28 +591,34 @@ void WS28xxMulti::Setup(uint32_t nFrequency) { } void WS28xxMulti::Print() { - const auto Type = m_PixelConfiguration.GetType(); + auto& pixelConfiguration = PixelConfiguration::Get(); + const auto Type = pixelConfiguration.GetType(); printf("Pixel\n"); - printf(" Type : %s [%d]\n", PixelType::GetType(Type), static_cast(Type)); - printf(" Count : %d\n", m_PixelConfiguration.GetCount()); + printf(" Type : %s [%d]\n", pixel::pixel_get_type(Type), static_cast(Type)); + printf(" Count : %d\n", pixelConfiguration.GetCount()); - if (!m_PixelConfiguration.IsRTZProtocol()) { - printf(" Clock : %u Hz\n", m_PixelConfiguration.GetClockSpeedHz()); + if (!pixelConfiguration.IsRTZProtocol()) { + printf(" Clock : %u Hz\n", pixelConfiguration.GetClockSpeedHz()); } else { - const auto Map = m_PixelConfiguration.GetMap(); - const auto nLowCode = m_PixelConfiguration.GetLowCode(); - const auto nHighCode = m_PixelConfiguration.GetHighCode(); + const auto Map = pixelConfiguration.GetMap(); + const auto nLowCode = pixelConfiguration.GetLowCode(); + const auto nHighCode = pixelConfiguration.GetHighCode(); - printf(" Mapping : %s [%d]\n", PixelType::GetMap(Map), static_cast(Map)); - printf(" T0H : %.2f [0x%X]\n", PixelType::ConvertTxH(nLowCode), nLowCode); - printf(" T1H : %.2f [0x%X]\n", PixelType::ConvertTxH(nHighCode), nHighCode); + printf(" Mapping : %s [%d]\n", pixel::pixel_get_map(Map), static_cast(Map)); + printf(" T0H : %.2f [0x%X]\n", pixel::pixel_convert_TxH(nLowCode), nLowCode); + printf(" T1H : %.2f [0x%X]\n", pixel::pixel_convert_TxH(nHighCode), nHighCode); } } void WS28xxMulti::Update() { assert(!sv_isRunning); + dma::memcpy32(reinterpret_cast(pixel::s_DmaBuffer), reinterpret_cast(pixel::s_DmaBuffer + pixel::DMA_BUFFER_SIZE / 2), m_nBufSize / 2); + + while (dma::memcpy32_is_active()) + ; + #ifndef NDEBUG GPIO_BC(DEBUG_CS_GPIOx) = DEBUG_CS_GPIO_PINx; #endif @@ -620,7 +631,9 @@ void WS28xxMulti::Update() { TIMER_CTL0(TIMER2) &= (~TIMER_CTL0_CEN); TIMER_CNT(TIMER2) = 0; - if (m_PixelConfiguration.IsRTZProtocol()) { + auto& pixelConfiguration = PixelConfiguration::Get(); + + if (pixelConfiguration.IsRTZProtocol()) { DMA_CHCTL(TIMER2_DMAx, TIMER2_CH0_DMA_CHx) &= ~DMA_CHXCTL_CHEN; dma_interrupt_flag_clear(TIMER2_DMAx, TIMER2_CH0_DMA_CHx, DMA_INTF_FTFIF); DMA_CHMADDR(TIMER2_DMAx, TIMER2_CH0_DMA_CHx) = reinterpret_cast(pixel::s_pGPIO_PINs); @@ -674,14 +687,16 @@ void WS28xxMulti::Blackout() { __DMB(); } while (sv_isRunning); - if (m_PixelConfiguration.IsRTZProtocol()) { + auto& pixelConfiguration = PixelConfiguration::Get(); + + if (pixelConfiguration.IsRTZProtocol()) { for (uint32_t i = 0; i < pixel::DMA_BUFFER_SIZE / 2; i++) { pixel::s_pT0H[i] = GPIO_PINx | (static_cast(GPIO_PINx) << 16); } } else { - const auto Type = m_PixelConfiguration.GetType(); + const auto Type = pixelConfiguration.GetType(); if ((Type == pixel::Type::APA102) || (Type == pixel::Type::SK9822) || (Type == pixel::Type::P9813)) { - const auto nCount = m_PixelConfiguration.GetCount(); + const auto nCount = pixelConfiguration.GetCount(); for (auto nPortIndex = 0; nPortIndex < pixel::PORT_COUNT; nPortIndex++) { SetPixel4Bytes(nPortIndex, 0, 0, 0, 0, 0); @@ -729,14 +744,16 @@ void WS28xxMulti::FullOn() { __DMB(); } while (sv_isRunning); - if (m_PixelConfiguration.IsRTZProtocol()) { + auto& pixelConfiguration = PixelConfiguration::Get(); + + if (pixelConfiguration.IsRTZProtocol()) { for (uint32_t i = 0; i < pixel::DMA_BUFFER_SIZE / 2; i++) { pixel::s_pT0H[i] = 0; } } else { - const auto Type = m_PixelConfiguration.GetType(); + const auto Type = pixelConfiguration.GetType(); if ((Type == pixel::Type::APA102) || (Type == pixel::Type::SK9822) || (Type == pixel::Type::P9813)) { - const auto nCount = m_PixelConfiguration.GetCount(); + const auto nCount = pixelConfiguration.GetCount(); for (auto nPortIndex = 0; nPortIndex < pixel::PORT_COUNT; nPortIndex++) { SetPixel4Bytes(nPortIndex, 0, 0, 0, 0, 0); @@ -786,13 +803,12 @@ bool WS28xxMulti::IsUpdating() { } void WS28xxMulti::SetColourRTZ(const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint8_t nColour1, const uint8_t nColour2, const uint8_t nColour3) { - assert(nPortIndex < 16); - assert(nPixelIndex < m_nBufSize / 8); //FIXME 8 + assert(nPortIndex < pixel::PORT_COUNT); uint32_t j = 0; const auto k = nPixelIndex * pixel::single::RGB; const auto nBit = nPortIndex + GPIO_PIN_OFFSET; - auto *p = &pixel::s_DmaBuffer[k]; + auto *p = &pixel::s_pBuffer[k]; for (uint8_t mask = 0x80; mask != 0; mask = static_cast(mask >> 1)) { if (!(mask & nColour1)) { @@ -883,51 +899,18 @@ void WS28xxMulti::SetPixel4Bytes(const uint32_t nPortIndex, const uint32_t nPixe } } -void WS28xxMulti::SetPixel(const uint32_t nPortIndex, const uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue) { - const auto pGammaTable = m_PixelConfiguration.GetGammaTable(); - - nRed = pGammaTable[nRed]; - nGreen = pGammaTable[nGreen]; - nBlue = pGammaTable[nBlue]; - - if (m_PixelConfiguration.IsRTZProtocol()) { - SetColourRTZ(nPortIndex, nPixelIndex, nRed, nGreen, nBlue); - return; - } - - const auto type = m_PixelConfiguration.GetType(); - - if (type == pixel::Type::WS2801) { - SetColourWS2801(nPortIndex, nPixelIndex, nRed, nGreen, nBlue); - return; - } - - if ((type == pixel::Type::APA102) || (type == pixel::Type::SK9822)) { - SetPixel4Bytes(nPortIndex, 1 + nPixelIndex, m_PixelConfiguration.GetGlobalBrightness(), nBlue, nGreen, nRed); - return; - } - - if (type == pixel::Type::P9813) { - const auto nFlag = static_cast(0xC0 | ((~nBlue & 0xC0) >> 2) | ((~nGreen & 0xC0) >> 4) | ((~nRed & 0xC0) >> 6)); - SetPixel4Bytes(nPortIndex, 1 + nPixelIndex, nFlag, nBlue, nGreen, nRed); - return; - } - - assert(0); - __builtin_unreachable(); - return; -} - -void WS28xxMulti::SetPixel(const uint32_t nPortIndex, const uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue, uint8_t nWhite) { +void WS28xxMulti::SetColourRTZ(const uint32_t nPortIndex, const uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue, uint8_t nWhite) { assert(nPortIndex < 16); assert(nPixelIndex < m_nBufSize / 8); //FIXME 8 - const auto pGammaTable = m_PixelConfiguration.GetGammaTable(); +#if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) + const auto pGammaTable = pixelConfiguration.GetGammaTable(); nRed = pGammaTable[nRed]; nGreen = pGammaTable[nGreen]; nBlue = pGammaTable[nBlue]; nWhite = pGammaTable[nWhite]; +#endif const auto k = nPixelIndex * pixel::single::RGBW; const auto nBit = nPortIndex + GPIO_PIN_OFFSET; diff --git a/lib-ws28xx/src/i2s/ws28xx.cpp b/lib-ws28xx/src/gd32/i2s/ws28xx.cpp similarity index 66% rename from lib-ws28xx/src/i2s/ws28xx.cpp rename to lib-ws28xx/src/gd32/i2s/ws28xx.cpp index 1a742179..865034ff 100644 --- a/lib-ws28xx/src/i2s/ws28xx.cpp +++ b/lib-ws28xx/src/gd32/i2s/ws28xx.cpp @@ -2,7 +2,7 @@ * @file ws28xx.cpp * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#if defined (DEBUG_PIXELDMX) +# undef NDEBUG +#endif + #include #include #include @@ -30,48 +34,44 @@ #include "ws28xx.h" #include "pixelconfiguration.h" -#include "hal_spi.h" +#include "gd32_spi.h" #include "debug.h" -using namespace pixel; - static uint32_t s_tmp; WS28xx *WS28xx::s_pThis; -WS28xx::WS28xx(PixelConfiguration& pixelConfiguration) { +WS28xx::WS28xx() { DEBUG_ENTRY assert(s_pThis == nullptr); s_pThis = this; - m_PixelConfiguration = pixelConfiguration; + auto& pixelConfiguration = PixelConfiguration::Get(); - uint32_t nLedsPerPixel; - pixelConfiguration.Validate(nLedsPerPixel); - pixelConfiguration.Dump(); + pixelConfiguration.Validate(); - const auto nCount = m_PixelConfiguration.GetCount(); + const auto nCount = pixelConfiguration.GetCount(); - m_nBufSize = nCount * nLedsPerPixel; + m_nBufSize = nCount * pixelConfiguration.GetLedsPerPixel(); - if (m_PixelConfiguration.IsRTZProtocol()) { + if (pixelConfiguration.IsRTZProtocol()) { m_nBufSize *= 8; m_nBufSize += 1; } - const auto type = m_PixelConfiguration.GetType(); + const auto type = pixelConfiguration.GetType(); - if ((type == Type::APA102) || (type == Type::SK9822) || (type == Type::P9813)) { + if ((type == pixel::Type::APA102) || (type == pixel::Type::SK9822) || (type == pixel::Type::P9813)) { m_nBufSize += nCount; m_nBufSize += 8; } SetupBuffers(); - FUNC_PREFIX(spi_dma_begin()); - FUNC_PREFIX(spi_dma_set_speed_hz(pixelConfiguration.GetClockSpeedHz())); + i2s::gd32_spi_dma_begin(); + i2s::gd32_spi_dma_set_speed_hz(pixelConfiguration.GetClockSpeedHz()); DEBUG_EXIT } @@ -87,7 +87,7 @@ void WS28xx::SetupBuffers() { uint32_t nSize; - m_pBuffer = const_cast(FUNC_PREFIX (spi_dma_tx_prepare(&nSize))); + m_pBuffer = const_cast(i2s::gd32_spi_dma_tx_prepare(&nSize)); assert(m_pBuffer != nullptr); const auto nSizeHalf = nSize / 2; @@ -118,7 +118,7 @@ void WS28xx::Update() { pDst[i] = __builtin_bswap16(pSrc[i]); } - FUNC_PREFIX(spi_dma_tx_start(m_pBlackoutBuffer, m_nBufSize)); + i2s::gd32_spi_dma_tx_start(m_pBlackoutBuffer, m_nBufSize); } void WS28xx::Blackout() { @@ -127,29 +127,31 @@ void WS28xx::Blackout() { // A blackout can be called any time. Make sure the previous transmit is ended. do { __ISB(); - } while (FUNC_PREFIX(spi_dma_tx_is_active())); + } while (i2s::gd32_spi_dma_tx_is_active()); auto *pBuffer = m_pBuffer; m_pBuffer = m_pBlackoutBuffer; - const auto type = m_PixelConfiguration.GetType(); - const auto nCount = m_PixelConfiguration.GetCount(); + auto& pixelConfiguration = PixelConfiguration::Get(); - if ((type == Type::APA102) || (type == Type::SK9822) || (type == Type::P9813)) { + const auto type = pixelConfiguration.GetType(); + const auto nCount = pixelConfiguration.GetCount(); + + if ((type == pixel::Type::APA102) || (type == pixel::Type::SK9822) || (type == pixel::Type::P9813)) { memset(m_pBuffer, 0, 4); for (uint32_t nPixelIndex = 0; nPixelIndex < nCount; nPixelIndex++) { SetPixel(nPixelIndex, 0, 0, 0); } - if ((type == Type::APA102) || (type == Type::SK9822)) { + if ((type == pixel::Type::APA102) || (type == pixel::Type::SK9822)) { memset(&m_pBuffer[m_nBufSize - 4], 0xFF, 4); } else { memset(&m_pBuffer[m_nBufSize - 4], 0, 4); } } else { m_pBuffer[0] = 0x00; - memset(&m_pBuffer[1], type == Type::WS2801 ? 0 : m_PixelConfiguration.GetLowCode(), m_nBufSize); + memset(&m_pBuffer[1], type == pixel::Type::WS2801 ? 0 : pixelConfiguration.GetLowCode(), m_nBufSize); } Update(); @@ -157,7 +159,7 @@ void WS28xx::Blackout() { // A blackout may not be interrupted. do { __ISB(); - } while (FUNC_PREFIX(spi_dma_tx_is_active())); + } while (i2s::gd32_spi_dma_tx_is_active()); m_pBuffer = pBuffer; @@ -170,29 +172,31 @@ void WS28xx::FullOn() { // Can be called any time. Make sure the previous transmit is ended. do { __ISB(); - } while (FUNC_PREFIX(spi_dma_tx_is_active())); + } while (i2s::gd32_spi_dma_tx_is_active()); auto *pBuffer = m_pBuffer; m_pBuffer = m_pBlackoutBuffer; - const auto type = m_PixelConfiguration.GetType(); - const auto nCount = m_PixelConfiguration.GetCount(); + auto& pixelConfiguration = PixelConfiguration::Get(); + + const auto type = pixelConfiguration.GetType(); + const auto nCount = pixelConfiguration.GetCount(); - if ((type == Type::APA102) || (type == Type::SK9822) || (type == Type::P9813)) { + if ((type == pixel::Type::APA102) || (type == pixel::Type::SK9822) || (type == pixel::Type::P9813)) { memset(m_pBuffer, 0, 4); for (uint32_t nPixelIndex = 0; nPixelIndex < nCount; nPixelIndex++) { SetPixel(nPixelIndex, 0xFF, 0xFF, 0xFF); } - if ((type == Type::APA102) || (type == Type::SK9822)) { + if ((type == pixel::Type::APA102) || (type == pixel::Type::SK9822)) { memset(&m_pBuffer[m_nBufSize - 4], 0xFF, 4); } else { memset(&m_pBuffer[m_nBufSize - 4], 0, 4); } } else { m_pBuffer[0] = 0x00; - memset(&m_pBuffer[1], type == Type::WS2801 ? 0xFF : m_PixelConfiguration.GetHighCode(), m_nBufSize); + memset(&m_pBuffer[1], type == pixel::Type::WS2801 ? 0xFF : pixelConfiguration.GetHighCode(), m_nBufSize); } Update(); @@ -200,7 +204,7 @@ void WS28xx::FullOn() { // May not be interrupted. do { __ISB(); - } while (FUNC_PREFIX(spi_dma_tx_is_active())); + } while (i2s::gd32_spi_dma_tx_is_active()); m_pBuffer = pBuffer; diff --git a/lib-ws28xx/src/json_get_satus.cpp b/lib-ws28xx/src/json_get_satus.cpp new file mode 100755 index 00000000..080a5681 --- /dev/null +++ b/lib-ws28xx/src/json_get_satus.cpp @@ -0,0 +1,36 @@ +/** + * @file json_get.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include + +#include "pixelconfiguration.h" + +namespace remoteconfig::pixel { +uint32_t json_get_status(char *pOutBuffer, const uint32_t nOutBufferSize) { + auto& pixelConfiguration = PixelConfiguration::Get(); + return static_cast(snprintf(pOutBuffer, nOutBufferSize, "{\"refresh_rate\":\"%u\"}", pixelConfiguration.GetRefreshRate())); +} +} // namespace remoteconfig::pixel diff --git a/lib-ws28xx/src/patterns/pixelpatterns.cpp b/lib-ws28xx/src/patterns/pixelpatterns.cpp index 9d3d09d7..0128bf9d 100644 --- a/lib-ws28xx/src/patterns/pixelpatterns.cpp +++ b/lib-ws28xx/src/patterns/pixelpatterns.cpp @@ -2,7 +2,7 @@ * @file pixelpatterns.cpp * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -46,34 +46,33 @@ using namespace pixelpatterns; static constexpr char s_patternName[static_cast(Pattern::LAST)][14] = { "None", "Rainbow cycle", "Theater chase", "Colour wipe", "Scanner", "Fade" }; #if defined (PIXELPATTERNS_MULTI) -WS28xxMulti *PixelPatterns::m_pOutput; +WS28xxMulti *PixelPatterns::s_pOutput; #else -WS28xx *PixelPatterns::m_pOutput; +WS28xx *PixelPatterns::s_pOutput; #endif -uint32_t PixelPatterns::m_nActivePorts; -uint32_t PixelPatterns::m_nCount; -PixelPatterns::PortConfig PixelPatterns::m_PortConfig[pixelpatterns::MAX_PORTS]; -uint32_t *PixelPatterns::m_pScannerColours; +uint32_t PixelPatterns::s_nActivePorts; +PixelPatterns::PortConfig PixelPatterns::s_PortConfig[pixelpatterns::MAX_PORTS]; +uint32_t *PixelPatterns::s_pScannerColours; -PixelPatterns::PixelPatterns(uint32_t nActivePorts) { +PixelPatterns::PixelPatterns(const uint32_t nActivePorts) { DEBUG_ENTRY DEBUG_PRINTF("nActivePorts=%u", nActivePorts); #if defined (PIXELPATTERNS_MULTI) - m_pOutput = WS28xxMulti::Get(); + s_pOutput = WS28xxMulti::Get(); #else - m_pOutput = WS28xx::Get(); + s_pOutput = WS28xx::Get(); #endif - assert(m_pOutput != nullptr); + assert(s_pOutput != nullptr); + + s_nActivePorts = std::min(MAX_PORTS, nActivePorts); - m_nActivePorts = std::min(MAX_PORTS, nActivePorts); - m_nCount = m_pOutput->GetCount(); const auto nMillis = Hardware::Get()->Millis(); for (uint32_t i = 0; i < MAX_PORTS; i++) { - m_PortConfig[i].ActivePattern = Pattern::NONE; - m_PortConfig[i].nLastUpdate = nMillis; - m_PortConfig[i].Direction = Direction::FORWARD; + s_PortConfig[i].ActivePattern = Pattern::NONE; + s_PortConfig[i].nLastUpdate = nMillis; + s_PortConfig[i].Direction = Direction::FORWARD; } DEBUG_EXIT @@ -87,31 +86,14 @@ const char* PixelPatterns::GetName(Pattern pattern) { return "Unknown"; } -void PixelPatterns::Run() { - if (m_pOutput->IsUpdating()) { - return; - } - - auto bIsUpdated = false; - const auto nMillis = Hardware::Get()->Millis(); - - for (uint32_t i = 0; i < m_nActivePorts; i++) { - bIsUpdated |= PortUpdate(i, nMillis); - } - - if (bIsUpdated) { - m_pOutput->Update(); - } -} - bool PixelPatterns::PortUpdate(uint32_t nPortIndex, uint32_t nMillis) { - if ((nMillis - m_PortConfig[nPortIndex].nLastUpdate) < m_PortConfig[nPortIndex].nInterval) { + if ((nMillis - s_PortConfig[nPortIndex].nLastUpdate) < s_PortConfig[nPortIndex].nInterval) { return false; } - m_PortConfig[nPortIndex].nLastUpdate = nMillis; + s_PortConfig[nPortIndex].nLastUpdate = nMillis; - switch (m_PortConfig[nPortIndex].ActivePattern) { + switch (s_PortConfig[nPortIndex].ActivePattern) { case Pattern::RAINBOW_CYCLE: RainbowCycleUpdate(nPortIndex); break; @@ -138,18 +120,18 @@ bool PixelPatterns::PortUpdate(uint32_t nPortIndex, uint32_t nMillis) { void PixelPatterns::RainbowCycle(uint32_t nPortIndex, uint32_t nInterval, pixelpatterns::Direction Direction) { Clear(nPortIndex); - m_PortConfig[nPortIndex].ActivePattern = Pattern::RAINBOW_CYCLE; - m_PortConfig[nPortIndex].nInterval = nInterval; - m_PortConfig[nPortIndex].nTotalSteps= 255; - m_PortConfig[nPortIndex].nPixelIndex = 0; - m_PortConfig[nPortIndex].Direction = Direction; + s_PortConfig[nPortIndex].ActivePattern = Pattern::RAINBOW_CYCLE; + s_PortConfig[nPortIndex].nInterval = nInterval; + s_PortConfig[nPortIndex].nTotalSteps= 255; + s_PortConfig[nPortIndex].nPixelIndex = 0; + s_PortConfig[nPortIndex].Direction = Direction; } void PixelPatterns::RainbowCycleUpdate(uint32_t nPortIndex) { - const auto nIndex = m_PortConfig[nPortIndex].nPixelIndex; + const auto nIndex = s_PortConfig[nPortIndex].nPixelIndex; - for (uint32_t i = 0; i < m_nCount; i++) { - SetPixelColour(nPortIndex, i, Wheel(((i * 256U / m_nCount) + nIndex) & 0xFF)); + for (uint32_t i = 0; i < PixelConfiguration::Get().GetCount(); i++) { + SetPixelColour(nPortIndex, i, Wheel(((i * 256U / PixelConfiguration::Get().GetCount()) + nIndex) & 0xFF)); } Increment(nPortIndex); @@ -158,21 +140,21 @@ void PixelPatterns::RainbowCycleUpdate(uint32_t nPortIndex) { void PixelPatterns::TheaterChase(uint32_t nPortIndex, uint32_t nColour1, uint32_t nColour2, uint32_t nInterval, pixelpatterns::Direction Direction){ Clear(nPortIndex); - m_PortConfig[nPortIndex].ActivePattern = Pattern::THEATER_CHASE; - m_PortConfig[nPortIndex].nInterval = nInterval; - m_PortConfig[nPortIndex].nTotalSteps= m_nCount; - m_PortConfig[nPortIndex].nColour1 = nColour1; - m_PortConfig[nPortIndex].nColour2 = nColour2; - m_PortConfig[nPortIndex].nPixelIndex = 0; - m_PortConfig[nPortIndex].Direction = Direction; + s_PortConfig[nPortIndex].ActivePattern = Pattern::THEATER_CHASE; + s_PortConfig[nPortIndex].nInterval = nInterval; + s_PortConfig[nPortIndex].nTotalSteps= PixelConfiguration::Get().GetCount(); + s_PortConfig[nPortIndex].nColour1 = nColour1; + s_PortConfig[nPortIndex].nColour2 = nColour2; + s_PortConfig[nPortIndex].nPixelIndex = 0; + s_PortConfig[nPortIndex].Direction = Direction; } void PixelPatterns::TheaterChaseUpdate(uint32_t nPortIndex) { - const auto Colour1 = m_PortConfig[nPortIndex].nColour1; - const auto Colour2 = m_PortConfig[nPortIndex].nColour2; - const auto Index = m_PortConfig[nPortIndex].nPixelIndex; + const auto Colour1 = s_PortConfig[nPortIndex].nColour1; + const auto Colour2 = s_PortConfig[nPortIndex].nColour2; + const auto Index = s_PortConfig[nPortIndex].nPixelIndex; - for (uint32_t i = 0; i < m_nCount; i++) { + for (uint32_t i = 0; i < PixelConfiguration::Get().GetCount(); i++) { if ((i + Index) % 3 == 0) { SetPixelColour(nPortIndex, i, Colour1); } else { @@ -186,17 +168,17 @@ void PixelPatterns::TheaterChaseUpdate(uint32_t nPortIndex) { void PixelPatterns::ColourWipe(uint32_t nPortIndex, uint32_t nColour, uint32_t nInterval, pixelpatterns::Direction Direction) { Clear(nPortIndex); - m_PortConfig[nPortIndex].ActivePattern = Pattern::COLOR_WIPE; - m_PortConfig[nPortIndex].nInterval = nInterval; - m_PortConfig[nPortIndex].nTotalSteps= m_nCount; - m_PortConfig[nPortIndex].nColour1 = nColour; - m_PortConfig[nPortIndex].nPixelIndex = 0; - m_PortConfig[nPortIndex].Direction = Direction; + s_PortConfig[nPortIndex].ActivePattern = Pattern::COLOR_WIPE; + s_PortConfig[nPortIndex].nInterval = nInterval; + s_PortConfig[nPortIndex].nTotalSteps= PixelConfiguration::Get().GetCount(); + s_PortConfig[nPortIndex].nColour1 = nColour; + s_PortConfig[nPortIndex].nPixelIndex = 0; + s_PortConfig[nPortIndex].Direction = Direction; } void PixelPatterns::ColourWipeUpdate(uint32_t nPortIndex) { - const auto nColour1 = m_PortConfig[nPortIndex].nColour1; - const auto nIndex = m_PortConfig[nPortIndex].nPixelIndex; + const auto nColour1 = s_PortConfig[nPortIndex].nColour1; + const auto nIndex = s_PortConfig[nPortIndex].nPixelIndex; SetPixelColour(nPortIndex, nIndex, nColour1); Increment(nPortIndex); @@ -205,38 +187,40 @@ void PixelPatterns::ColourWipeUpdate(uint32_t nPortIndex) { void PixelPatterns::Scanner(uint32_t nPortIndex, uint32_t nColour1, uint32_t nInterval) { Clear(nPortIndex); - m_PortConfig[nPortIndex].ActivePattern = Pattern::SCANNER; - m_PortConfig[nPortIndex].nInterval = nInterval; - m_PortConfig[nPortIndex].nTotalSteps= static_cast((m_nCount - 1U) * 2); - m_PortConfig[nPortIndex].nColour1 = nColour1; - m_PortConfig[nPortIndex].nPixelIndex = 0; + const auto nCount = PixelConfiguration::Get().GetCount(); + + s_PortConfig[nPortIndex].ActivePattern = Pattern::SCANNER; + s_PortConfig[nPortIndex].nInterval = nInterval; + s_PortConfig[nPortIndex].nTotalSteps= static_cast((nCount - 1U) * 2); + s_PortConfig[nPortIndex].nColour1 = nColour1; + s_PortConfig[nPortIndex].nPixelIndex = 0; - if (m_pScannerColours == nullptr) { - m_pScannerColours = new uint32_t[m_nCount]; - assert(m_pScannerColours != nullptr); - for (uint32_t i = 0; i < m_nCount; i++) { - m_pScannerColours[i] = 0; + if (s_pScannerColours == nullptr) { + s_pScannerColours = new uint32_t[nCount]; + assert(s_pScannerColours != nullptr); + for (uint32_t i = 0; i < nCount; i++) { + s_pScannerColours[i] = 0; } } } void PixelPatterns::ScannerUpdate(uint32_t nPortIndex) { - const auto nColour1 = m_PortConfig[nPortIndex].nColour1; - const auto nTotalSteps = m_PortConfig[nPortIndex].nTotalSteps; - const auto nIndex = m_PortConfig[nPortIndex].nPixelIndex; + const auto nColour1 = s_PortConfig[nPortIndex].nColour1; + const auto nTotalSteps = s_PortConfig[nPortIndex].nTotalSteps; + const auto nIndex = s_PortConfig[nPortIndex].nPixelIndex; - for (uint32_t i = 0; i < m_nCount; i++) { + for (uint32_t i = 0; i < PixelConfiguration::Get().GetCount(); i++) { if (i == nIndex) { SetPixelColour(nPortIndex, i, nColour1); - m_pScannerColours[i] = nColour1; + s_pScannerColours[i] = nColour1; } else if (i == nTotalSteps - nIndex) { SetPixelColour(nPortIndex, i, nColour1); - m_pScannerColours[i] = nColour1; + s_pScannerColours[i] = nColour1; } else { - const auto nDimColour = DimColour(m_pScannerColours[i]); + const auto nDimColour = DimColour(s_pScannerColours[i]); SetPixelColour(nPortIndex, i, nDimColour); - m_pScannerColours[i] = nDimColour; + s_pScannerColours[i] = nDimColour; } } @@ -246,20 +230,20 @@ void PixelPatterns::ScannerUpdate(uint32_t nPortIndex) { void PixelPatterns::Fade(uint32_t nPortIndex, uint32_t nColour1, uint32_t nColour2, uint32_t nSteps, uint32_t nInterval, pixelpatterns::Direction Direction) { Clear(nPortIndex); - m_PortConfig[nPortIndex].ActivePattern = Pattern::FADE; - m_PortConfig[nPortIndex].nInterval = nInterval; - m_PortConfig[nPortIndex].nTotalSteps= nSteps; - m_PortConfig[nPortIndex].nColour1 = nColour1; - m_PortConfig[nPortIndex].nColour2 = nColour2; - m_PortConfig[nPortIndex].nPixelIndex = 0; - m_PortConfig[nPortIndex].Direction = Direction; + s_PortConfig[nPortIndex].ActivePattern = Pattern::FADE; + s_PortConfig[nPortIndex].nInterval = nInterval; + s_PortConfig[nPortIndex].nTotalSteps= nSteps; + s_PortConfig[nPortIndex].nColour1 = nColour1; + s_PortConfig[nPortIndex].nColour2 = nColour2; + s_PortConfig[nPortIndex].nPixelIndex = 0; + s_PortConfig[nPortIndex].Direction = Direction; } void PixelPatterns::FadeUpdate(uint32_t nPortIndex) { - const auto nColour1 = m_PortConfig[nPortIndex].nColour1; - const auto nColour2 = m_PortConfig[nPortIndex].nColour2; - const auto nTotalSteps = m_PortConfig[nPortIndex].nTotalSteps; - const auto nIndex = m_PortConfig[nPortIndex].nPixelIndex; + const auto nColour1 = s_PortConfig[nPortIndex].nColour1; + const auto nColour2 = s_PortConfig[nPortIndex].nColour2; + const auto nTotalSteps = s_PortConfig[nPortIndex].nTotalSteps; + const auto nIndex = s_PortConfig[nPortIndex].nPixelIndex; const auto nRed = static_cast(((Red(nColour1) * (nTotalSteps - nIndex)) + (Red(nColour2) * nIndex)) / nTotalSteps); const auto nGreen = static_cast(((Green(nColour1) * (nTotalSteps - nIndex)) + (Green(nColour2) * nIndex)) / nTotalSteps); @@ -284,27 +268,27 @@ uint32_t PixelPatterns::Wheel(uint8_t nWheelPos) { } void PixelPatterns::Increment(uint32_t nPortIndex) { - if (m_PortConfig[nPortIndex].Direction == Direction::FORWARD) { - m_PortConfig[nPortIndex].nPixelIndex++; - if (m_PortConfig[nPortIndex].nPixelIndex == m_PortConfig[nPortIndex].nTotalSteps) { - m_PortConfig[nPortIndex].nPixelIndex = 0; + if (s_PortConfig[nPortIndex].Direction == Direction::FORWARD) { + s_PortConfig[nPortIndex].nPixelIndex++; + if (s_PortConfig[nPortIndex].nPixelIndex == s_PortConfig[nPortIndex].nTotalSteps) { + s_PortConfig[nPortIndex].nPixelIndex = 0; } } else { - if (m_PortConfig[nPortIndex].nPixelIndex > 0) { - --m_PortConfig[nPortIndex].nPixelIndex; + if (s_PortConfig[nPortIndex].nPixelIndex > 0) { + --s_PortConfig[nPortIndex].nPixelIndex; } - if (m_PortConfig[nPortIndex].nPixelIndex == 0) { - m_PortConfig[nPortIndex].nPixelIndex = static_cast(m_PortConfig[nPortIndex].nTotalSteps - 1); + if (s_PortConfig[nPortIndex].nPixelIndex == 0) { + s_PortConfig[nPortIndex].nPixelIndex = static_cast(s_PortConfig[nPortIndex].nTotalSteps - 1); } } } void PixelPatterns::Reverse(uint32_t nPortIndex) { - if (m_PortConfig[nPortIndex].Direction == Direction::FORWARD) { - m_PortConfig[nPortIndex].Direction = Direction::REVERSE; - m_PortConfig[nPortIndex].nPixelIndex = static_cast(m_PortConfig[nPortIndex].nTotalSteps - 1); + if (s_PortConfig[nPortIndex].Direction == Direction::FORWARD) { + s_PortConfig[nPortIndex].Direction = Direction::REVERSE; + s_PortConfig[nPortIndex].nPixelIndex = static_cast(s_PortConfig[nPortIndex].nTotalSteps - 1); } else { - m_PortConfig[nPortIndex].Direction = Direction::FORWARD; - m_PortConfig[nPortIndex].nPixelIndex = 0; + s_PortConfig[nPortIndex].Direction = Direction::FORWARD; + s_PortConfig[nPortIndex].nPixelIndex = 0; } } diff --git a/lib-ws28xx/src/patterns/pixeltestpattern.cpp b/lib-ws28xx/src/patterns/pixeltestpattern.cpp index 792750bd..3c98e082 100644 --- a/lib-ws28xx/src/patterns/pixeltestpattern.cpp +++ b/lib-ws28xx/src/patterns/pixeltestpattern.cpp @@ -2,7 +2,7 @@ * @file pixeltestpattern.cpp * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,5 +25,4 @@ #include "pixeltestpattern.h" -pixelpatterns::Pattern PixelTestPattern::s_Pattern; -PixelTestPattern *PixelTestPattern::s_pThis = nullptr; +PixelTestPattern *PixelTestPattern::s_pThis; diff --git a/lib-ws28xx/src/pixel/ws28xx.cpp b/lib-ws28xx/src/pixel/ws28xx.cpp index 3dd73aa0..4db2cd30 100644 --- a/lib-ws28xx/src/pixel/ws28xx.cpp +++ b/lib-ws28xx/src/pixel/ws28xx.cpp @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#if defined (DEBUG_PIXEL) +# undef NDEBUG +#endif + #if !defined(__clang__) // Needed for compiling on MacOS # pragma GCC push_options # pragma GCC optimize ("O3") @@ -40,14 +44,15 @@ #include "gamma/gamma_tables.h" void WS28xx::SetColorWS28xx(uint32_t nOffset, uint8_t nValue) { - assert(m_PixelConfiguration.GetType() != pixel::Type::WS2801); + auto& pixelConfiguration = PixelConfiguration::Get(); + assert(pixelConfiguration.GetType() != pixel::Type::WS2801); assert(m_pBuffer != nullptr); assert(nOffset + 7 < m_nBufSize); nOffset += 1; - const auto nLowCode = m_PixelConfiguration.GetLowCode(); - const auto nHighCode = m_PixelConfiguration.GetHighCode(); + const auto nLowCode = pixelConfiguration.GetLowCode(); + const auto nHighCode = pixelConfiguration.GetHighCode(); for (uint8_t mask = 0x80; mask != 0; mask = static_cast(mask >> 1)) { if (nValue & mask) { @@ -60,15 +65,18 @@ void WS28xx::SetColorWS28xx(uint32_t nOffset, uint8_t nValue) { } void WS28xx::SetPixel(uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue) { - assert(nPixelIndex < m_PixelConfiguration.GetCount()); + auto& pixelConfiguration = PixelConfiguration::Get(); + assert(nPixelIndex < pixelConfiguration.GetCount()); - const auto pGammaTable = m_PixelConfiguration.GetGammaTable(); +#if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) + const auto pGammaTable = pixelConfiguration.GetGammaTable(); nRed = pGammaTable[nRed]; nGreen = pGammaTable[nGreen]; nBlue = pGammaTable[nBlue]; +#endif - if (m_PixelConfiguration.IsRTZProtocol()) { + if (pixelConfiguration.IsRTZProtocol()) { const auto nOffset = nPixelIndex * 24U; SetColorWS28xx(nOffset, nRed); @@ -79,7 +87,7 @@ void WS28xx::SetPixel(uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_ assert(m_pBuffer != nullptr); - const auto type = m_PixelConfiguration.GetType(); + const auto type = pixelConfiguration.GetType(); if (type == pixel::Type::WS2801) { const auto nOffset = nPixelIndex * 3U; @@ -96,7 +104,7 @@ void WS28xx::SetPixel(uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_ const auto nOffset = 4U + (nPixelIndex * 4U); assert(nOffset + 3U < m_nBufSize); - m_pBuffer[nOffset] = m_PixelConfiguration.GetGlobalBrightness(); + m_pBuffer[nOffset] = pixelConfiguration.GetGlobalBrightness(); m_pBuffer[nOffset + 1] = nRed; m_pBuffer[nOffset + 2] = nGreen; m_pBuffer[nOffset + 3] = nBlue; @@ -123,15 +131,17 @@ void WS28xx::SetPixel(uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_ } void WS28xx::SetPixel(uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue, uint8_t nWhite) { - assert(nPixelIndex < m_PixelConfiguration.GetCount()); - assert(m_PixelConfiguration.GetType() == pixel::Type::SK6812W); + assert(nPixelIndex < PixelConfiguration::Get().GetCount()); + assert(PixelConfiguration::Get().GetType() == pixel::Type::SK6812W); - const auto pGammaTable = m_PixelConfiguration.GetGammaTable(); +#if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) + const auto pGammaTable = pixelConfiguration.GetGammaTable(); nRed = pGammaTable[nRed]; nGreen = pGammaTable[nGreen]; nBlue = pGammaTable[nBlue]; nWhite = pGammaTable[nWhite]; +#endif const auto nOffset = nPixelIndex * 32U; diff --git a/lib-ws28xx/src/pixelconfiguration.cpp b/lib-ws28xx/src/pixelconfiguration.cpp deleted file mode 100644 index bf079081..00000000 --- a/lib-ws28xx/src/pixelconfiguration.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/** - * @file pixelconfiguration.cpp - * - */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#if !defined(__clang__) // Needed for compiling on MacOS -# pragma GCC push_options -# pragma GCC optimize ("Os") -#endif - -#include - -#include "pixelconfiguration.h" -#include "pixeltype.h" -#include "gamma/gamma_tables.h" - -#include "debug.h" - -using namespace pixel; - -void PixelConfiguration::Validate(uint32_t& nLedsPerPixel) { - DEBUG_ENTRY - - if (m_type == Type::SK6812W) { - m_nCount = m_nCount <= static_cast(max::ledcount::RGBW) ? m_nCount : static_cast(max::ledcount::RGBW); - nLedsPerPixel = 4; - } else { - m_nCount = m_nCount <= static_cast(max::ledcount::RGB) ? m_nCount : static_cast(max::ledcount::RGB); - nLedsPerPixel = 3; - } - - if ((m_type == Type::APA102) || (m_type == Type::SK9822)){ - if (m_nGlobalBrightness > 0x1F) { - m_nGlobalBrightness = 0xFF; - } else { - m_nGlobalBrightness = 0xE0 | (m_nGlobalBrightness & 0x1F); - } - } - - if ((m_type == Type::WS2801) || (m_type == Type::APA102) || (m_type == Type::SK9822) || (m_type == Type::P9813)) { - m_bIsRTZProtocol = false; - - if (m_map == Map::UNDEFINED) { - m_map = Map::RGB; - } - - if (m_type == Type::P9813) { - if (m_nClockSpeedHz == 0) { - m_nClockSpeedHz = spi::speed::p9813::default_hz; - } else if (m_nClockSpeedHz > spi::speed::p9813::max_hz) { - m_nClockSpeedHz = spi::speed::p9813::max_hz; - } - } else { - if (m_nClockSpeedHz == 0) { - m_nClockSpeedHz = spi::speed::ws2801::default_hz; - } else if (m_nClockSpeedHz > spi::speed::ws2801::max_hz) { - m_nClockSpeedHz = spi::speed::ws2801::max_hz; - } - } - } else { - m_bIsRTZProtocol = true; - - if (m_map == Map::UNDEFINED) { - m_map = PixelType::GetMap(m_type); - } - - if (m_nLowCode >= m_nHighCode) { - m_nLowCode = 0; - m_nHighCode = 0; - } - - uint8_t nLowCode, nHighCode; - - GetTxH(m_type, nLowCode, nHighCode); - - if (m_nLowCode == 0) { - m_nLowCode = nLowCode; - } - - if (m_nHighCode == 0) { - m_nHighCode = nHighCode; - } - - m_nClockSpeedHz = 6400000; // 6.4MHz / 8 bits = 800Hz - } - - if (m_bEnableGammaCorrection) { - if (m_nGammaValue == 0) { - m_pGammaTable = gamma::get_table_default(m_type); - } else { - m_pGammaTable = gamma::get_table(m_nGammaValue); - } - } else { - m_pGammaTable = gamma10_0; - } - - DEBUG_EXIT -} - -void PixelConfiguration::GetTxH(Type type, uint8_t &nLowCode, uint8_t &nHighCode) { - nLowCode = 0xC0; - nHighCode = (type == Type::WS2812B ? 0xF8 : - (((type == Type::UCS1903) || (type == Type::UCS2903) || (type == Type::CS8812)) ? 0xFC : 0xF0)); -} - -#include - -void PixelConfiguration::Print() { - printf("Pixel configuration\n"); - printf(" Type : %s [%d]\n", PixelType::GetType(m_type), static_cast(m_type)); - printf(" Count : %d\n", m_nCount); - - if (m_bIsRTZProtocol) { - printf(" Mapping : %s [%d]\n", PixelType::GetMap(m_map), static_cast(m_map)); - printf(" T0H : %.2f [0x%X]\n", PixelType::ConvertTxH(m_nLowCode), m_nLowCode); - printf(" T1H : %.2f [0x%X]\n", PixelType::ConvertTxH(m_nHighCode), m_nHighCode); - } else { - if ((m_type == Type::APA102) || (m_type == Type::SK9822)){ - printf(" GlobalBrightness: %u\n", m_nGlobalBrightness); - } - } - - printf(" Gamma correction %s\n", m_bEnableGammaCorrection ? "Yes" : "No"); - printf(" Clock: %u Hz\n", m_nClockSpeedHz); -} diff --git a/lib-ws28xx/src/pixeltype.cpp b/lib-ws28xx/src/pixeltype.cpp index 37be1cfb..a4351151 100644 --- a/lib-ws28xx/src/pixeltype.cpp +++ b/lib-ws28xx/src/pixeltype.cpp @@ -2,7 +2,7 @@ * @file pixeltype.cpp * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,20 +23,20 @@ * THE SOFTWARE. */ -#if !defined(__clang__) // Needed for compiling on MacOS +#if defined(__GNUC__) && !defined(__clang__) ///< Needed for macOS # pragma GCC push_options # pragma GCC optimize ("Os") #endif #include #include +#include #include #include "pixeltype.h" -using namespace pixel; - -const char PixelType::TYPES[static_cast(Type::UNDEFINED)][TYPES_MAX_NAME_LENGTH] = +namespace pixel { +const char TYPES[static_cast(pixel::Type::UNDEFINED)][pixel::TYPES_MAX_NAME_LENGTH] = { "WS2801\0", // 1 "WS2811\0", "WS2812\0", "WS2812B", "WS2813\0", "WS2815\0", // 5 "SK6812\0", "SK6812W", // 2 @@ -46,130 +46,68 @@ const char PixelType::TYPES[static_cast(Type::UNDEFINED)][TYPES_MAX_NA "P9813", // 1 }; // = 14 -const char PixelType::MAPS[static_cast(Map::UNDEFINED)][4] = { "RGB", "RBG", "GRB", "GBR", "BRG", "BGR"}; +const char MAPS[static_cast(pixel::Map::UNDEFINED)][4] = { "RGB", "RBG", "GRB", "GBR", "BRG", "BGR"}; -const char *PixelType::GetType(Type type) { - if (type < Type::UNDEFINED) { +const char *pixel_get_type(pixel::Type type) { + if (type < pixel::Type::UNDEFINED) { return TYPES[static_cast(type)]; } return "Unknown"; } -Type PixelType::GetType(const char *pString) { +pixel::Type pixel_get_type(const char *pString) { assert(pString != nullptr); + uint32_t index = 0; - for (uint32_t i = 0; i < static_cast(Type::UNDEFINED); i++) { - if (strcasecmp(pString, TYPES[i]) == 0) { - return static_cast(i); + for (const char (&type)[pixel::TYPES_MAX_NAME_LENGTH] : TYPES) { + if (strcasecmp(pString, type) == 0) { + return static_cast(index); } + ++index; } - return Type::UNDEFINED; + return pixel::Type::UNDEFINED; } -Map PixelType::GetMap(const char *pString) { +pixel::Map pixel_get_map(const char *pString) { assert(pString != nullptr); + uint32_t index = 0; - for (uint32_t nIndex = 0; nIndex < static_cast(Map::UNDEFINED); nIndex++) { - if (strncasecmp(MAPS[nIndex], pString, 3) == 0) { - return static_cast(nIndex); + for (const char (&map)[4] : MAPS) { + if (strncasecmp(map, pString, 3) == 0) { + return static_cast(index); } + ++index; } - return Map::UNDEFINED; + return pixel::Map::UNDEFINED; } -const char *PixelType::GetMap(Map map) { - if (map < Map::UNDEFINED) { +const char *pixel_get_map(pixel::Map map) { + if (map < pixel::Map::UNDEFINED) { return MAPS[static_cast(map)]; } return "Undefined"; } +} // namespace pixel -Map PixelType::GetMap(Type type) { - if ((type == Type::WS2811) || (type == Type::UCS2903)) { - return Map::RGB; - } - - if (type == Type::UCS1903) { - return Map::BRG; - } - - if (type == Type::CS8812) { - return Map::BGR; - } - - return Map::GRB; -} - -static constexpr auto F_INTERVAL = 0.15625f; - -float PixelType::ConvertTxH(uint8_t nCode) { - switch (nCode) { - case 0x80: - return F_INTERVAL * 1; - break; - case 0xC0: - return F_INTERVAL * 2; - break; - case 0xE0: - return F_INTERVAL * 3; - break; - case 0xF0: - return F_INTERVAL * 4; - break; - case 0xF8: - return F_INTERVAL * 5; - break; - case 0xFC: - return F_INTERVAL * 6; - break; - case 0xFE: - return F_INTERVAL * 7; - break; - default: - return 0; - break; - } - - assert(0); - __builtin_unreachable(); -} - -uint8_t PixelType::ConvertTxH(float fTxH) { - if (fTxH < 0.5f * F_INTERVAL) { - return 0x00; - } - - if (fTxH < 1.5f * F_INTERVAL) { - return 0x80; - } - - if (fTxH < 2.5f * F_INTERVAL) { - return 0xC0; - } - - if (fTxH < 3.5f * F_INTERVAL) { - return 0xE0; - } - - if (fTxH < 4.5f * F_INTERVAL) { - return 0xF0; - } +namespace remoteconfig::pixel { +uint32_t json_get_types(char *pOutBuffer, const uint32_t nOutBufferSize) { + const auto nBufferSize = nOutBufferSize - 2U; + auto nLength = static_cast(snprintf(pOutBuffer, nBufferSize, "{\"types\":[" )); - if (fTxH < 5.5f * F_INTERVAL) { - return 0xF8; + for (const char (&type)[::pixel::TYPES_MAX_NAME_LENGTH] : ::pixel::TYPES) { + nLength += static_cast(snprintf(&pOutBuffer[nLength], nBufferSize - nLength, "\"%s\",", type)); } - if (fTxH < 6.5f * F_INTERVAL) { - return 0xFC; - } + nLength--; - if (fTxH < 7.5f * F_INTERVAL) { - return 0xFE; - } + pOutBuffer[nLength++] = ']'; + pOutBuffer[nLength++] = '}'; - return 0x00; + assert(nLength <= nOutBufferSize); + return nLength; } +} // namespace remoteconfig::pixel diff --git a/lib-ws28xxdmx/.cproject b/lib-ws28xxdmx/.cproject index 8dfc395b..4d2fb955 100644 --- a/lib-ws28xxdmx/.cproject +++ b/lib-ws28xxdmx/.cproject @@ -30,11 +30,9 @@ - diff --git a/lib-ws28xxdmx/Makefile.GD32 b/lib-ws28xxdmx/Makefile.GD32 index 4fe9d4a3..1d567e48 100644 --- a/lib-ws28xxdmx/Makefile.GD32 +++ b/lib-ws28xxdmx/Makefile.GD32 @@ -1,5 +1,4 @@ -DEFINES=USE_SPI_DMA -DEFINES+=NDEBUG +DEFINES=NDEBUG EXTRA_INCLUDES=../lib-ws28xx/include ../lib-lightset/include ../lib-properties/include diff --git a/lib-ws28xxdmx/Rules.mk b/lib-ws28xxdmx/Rules.mk index 63080529..4d22bc10 100644 --- a/lib-ws28xxdmx/Rules.mk +++ b/lib-ws28xxdmx/Rules.mk @@ -5,14 +5,21 @@ EXTRA_INCLUDES+=../lib-properties/include EXTRA_SRCDIR+=src/params ifneq ($(MAKE_FLAGS),) - ifneq (,$(findstring ENABLE_RDM_MANUFACTURER_PIDS,$(MAKE_FLAGS))) + ifneq (,$(findstring OUTPUT_DMX_PIXEL,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=src/dmx + endif + ifneq (,$(findstring OUTPUT_DMX_PIXEL_MULTI,$(MAKE_FLAGS))) + EXTRA_SRCDIR+=src/dmxmulti + endif + ifneq (,$(findstring CONFIG_RDM_ENABLE_MANUFACTURER_PIDS,$(MAKE_FLAGS))) EXTRA_INCLUDES+=../lib-rdm/include EXTRA_SRCDIR+=src/rdm endif else DEFINES+=CONFIG_PIXELDMX_MAX_PORTS=8 - DEFINES+=ENABLE_RDM_MANUFACTURER_PIDS + DEFINES+=LIGHTSET_PORTS=32 + DEFINES+=CONFIG_RDM_ENABLE_MANUFACTURER_PIDS CONFIG_RDM_MANUFACTURER_PIDS_SET DEFINES+=OUTPUT_DMX_PIXEL EXTRA_INCLUDES+=../lib-rdm/include - EXTRA_SRCDIR+=src/rdm + EXTRA_SRCDIR+=src/dmx src/dmxmulti src/rdm endif \ No newline at end of file diff --git a/lib-ws28xxdmx/include/pixeldmxconfiguration.h b/lib-ws28xxdmx/include/pixeldmxconfiguration.h index 5a24a343..49bfbb19 100644 --- a/lib-ws28xxdmx/include/pixeldmxconfiguration.h +++ b/lib-ws28xxdmx/include/pixeldmxconfiguration.h @@ -2,7 +2,7 @@ * @file pixeldmxconfiguration.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,24 +22,44 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +/** + * Static Local Variables: + * Since C++11, the initialization of function-local static variables, is guaranteed to be thread-safe. + * This means that even if multiple threads attempt to access Get() simultaneously, + * the C++ runtime ensures that the instance is initialized only once. + */ #ifndef PIXELDMXCONFIGURATION_H_ #define PIXELDMXCONFIGURATION_H_ #include +#include +#include +#include #include "pixelconfiguration.h" +#include "debug.h" + namespace pixeldmxconfiguration { struct PortInfo { - uint32_t nBeginIndexPort[4]; - uint32_t nProtocolPortIndexLast; + uint16_t nBeginIndexPort[4]; + uint16_t nProtocolPortIndexLast; }; } // namespace pixeldmxconfiguration class PixelDmxConfiguration: public PixelConfiguration { public: - void SetOutputPorts(uint32_t nOutputPorts) { + PixelDmxConfiguration() { + DEBUG_ENTRY + + assert(s_pThis == nullptr); + s_pThis = this; + + DEBUG_EXIT + } + + void SetOutputPorts(const uint16_t nOutputPorts) { m_nOutputPorts = nOutputPorts; } @@ -47,7 +67,7 @@ class PixelDmxConfiguration: public PixelConfiguration { return m_nOutputPorts; } - void SetGroupingCount(uint16_t nGroupingCount) { + void SetGroupingCount(const uint16_t nGroupingCount) { m_nGroupingCount = nGroupingCount; } @@ -63,24 +83,98 @@ class PixelDmxConfiguration: public PixelConfiguration { return m_nUniverses; } - void SetDmxStartAddress(uint16_t nDmxStartAddress) { + pixeldmxconfiguration::PortInfo& GetPortInfo() { + return m_portInfo; + } + + void SetDmxStartAddress(const uint16_t nDmxStartAddress) { m_nDmxStartAddress = nDmxStartAddress; } - uint16_t GetDmxStartAddress() const { + uint32_t GetDmxStartAddress() const { return m_nDmxStartAddress; } - void Validate(uint32_t nPortsMax, uint32_t& nLedsPerPixel, pixeldmxconfiguration::PortInfo& portInfo); + uint32_t GetDmxFootprint() const { + return m_nDmxFootprint; + } + + void Validate(const uint32_t nPortsMax) { + DEBUG_ENTRY + + PixelConfiguration::Validate(); + + if (!PixelConfiguration::IsRTZProtocol()) { + if (!((PixelConfiguration::GetType() == pixel::Type::WS2801) || (PixelConfiguration::GetType() == pixel::Type::APA102) || (PixelConfiguration::GetType() == pixel::Type::SK9822))) { + PixelConfiguration::SetType(pixel::Type::WS2801); + } + + PixelConfiguration::Validate(); + } + + m_portInfo.nBeginIndexPort[0] = 0; + + if (PixelConfiguration::GetType() == pixel::Type::SK6812W) { + m_portInfo.nBeginIndexPort[1] = 128; + m_portInfo.nBeginIndexPort[2] = 256; + m_portInfo.nBeginIndexPort[3] = 384; + } else { + m_portInfo.nBeginIndexPort[1] = 170; + m_portInfo.nBeginIndexPort[2] = 340; + m_portInfo.nBeginIndexPort[3] = 510; + } + + if ((m_nGroupingCount == 0) || (m_nGroupingCount > PixelConfiguration::GetCount())) { + m_nGroupingCount = PixelConfiguration::GetCount(); + } + + m_nGroups = PixelConfiguration::GetCount() / m_nGroupingCount; + m_nOutputPorts = std::min(nPortsMax, m_nOutputPorts); + m_nUniverses = (1U + (m_nGroups / (1U + m_portInfo.nBeginIndexPort[1]))); + m_nDmxFootprint = PixelConfiguration::GetLedsPerPixel() * m_nGroups; + + if (nPortsMax == 1) { + m_portInfo.nProtocolPortIndexLast = static_cast(m_nGroups / (1U + m_portInfo.nBeginIndexPort[1])); + } else { +#if defined (NODE_DDP_DISPLAY) + m_portInfo.nProtocolPortIndexLast = static_cast(((m_nOutputPorts - 1U) * 4U) + m_nUniverses - 1U); +#else + m_portInfo.nProtocolPortIndexLast = static_cast((m_nOutputPorts * m_nUniverses) - 1U); +#endif + } + + DEBUG_EXIT + } + + void Print() { + PixelConfiguration::Print(); + puts("Pixel DMX configuration"); + printf(" Outputs : %u\n", m_nOutputPorts); + printf(" Grouping count : %u [Groups : %u]\n", m_nGroupingCount, m_nGroups); + printf(" Universes : %u\n", m_nUniverses); + printf(" DmxFootprint : %u\n", m_nDmxFootprint); + +#ifndef NDEBUG + const auto& beginIndexPort = m_portInfo.nBeginIndexPort; + printf(" %u:%u:%u:%u -> %u\n", beginIndexPort[0], beginIndexPort[1], beginIndexPort[2], beginIndexPort[3], m_portInfo.nProtocolPortIndexLast); +#endif + } - void Print(); + static PixelDmxConfiguration& Get() { + assert(s_pThis != nullptr); // Ensure that s_pThis is valid + return *s_pThis; + } private: uint32_t m_nOutputPorts { 1 }; uint32_t m_nGroupingCount { 1 }; uint32_t m_nGroups { pixel::defaults::COUNT }; - uint32_t m_nUniverses; - uint16_t m_nDmxStartAddress { 1 }; + uint32_t m_nUniverses { 0 }; + uint32_t m_nDmxStartAddress { 1 }; + uint32_t m_nDmxFootprint { 0 }; + pixeldmxconfiguration::PortInfo m_portInfo; + + static inline PixelDmxConfiguration *s_pThis { nullptr }; }; #endif /* PIXELDMXCONFIGURATION_H_ */ diff --git a/lib-ws28xxdmx/include/pixeldmxparams.h b/lib-ws28xxdmx/include/pixeldmxparams.h index 59eab6c4..9257d6c0 100644 --- a/lib-ws28xxdmx/include/pixeldmxparams.h +++ b/lib-ws28xxdmx/include/pixeldmxparams.h @@ -2,7 +2,7 @@ * @file pixeldmxparams.h * */ -/* Copyright (C) 2017-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"); to deal @@ -29,6 +29,7 @@ #include #include "pixeldmxconfiguration.h" +#include "configstore.h" #if !defined (CONFIG_PIXELDMX_MAX_PORTS) # error CONFIG_PIXELDMX_MAX_PORTS is not defined @@ -71,24 +72,25 @@ struct Mask { static constexpr auto HIGH_CODE = (1U << 11); static constexpr auto START_UNI_PORT_1 = (1U << 12); }; -} // pixeldmxparams name +} // pixeldmxparams class PixelDmxParamsStore { public: - virtual ~PixelDmxParamsStore() { + static void Update(const struct pixeldmxparams::Params *pParams) { + ConfigStore::Get()->Update(configstore::Store::WS28XXDMX, pParams, sizeof(struct pixeldmxparams::Params)); } - virtual void Update(const struct pixeldmxparams::Params *pWS28xxDmxParams)=0; - virtual void Copy(struct pixeldmxparams::Params *pWS28xxDmxParams)=0; + static void Copy(struct pixeldmxparams::Params *pParams) { + ConfigStore::Get()->Copy(configstore::Store::WS28XXDMX, pParams, sizeof(struct pixeldmxparams::Params)); + } }; class PixelDmxParams { public: - PixelDmxParams(PixelDmxParamsStore *pPixelDmxParamsStore); - ~PixelDmxParams() { - } + PixelDmxParams(); + ~PixelDmxParams() = default; - bool Load(); + void Load(); void Load(const char *pBuffer, uint32_t nLength); void Builder(const struct pixeldmxparams::Params *pParams, char *pBuffer, uint32_t nLength, uint32_t& nSize); @@ -96,14 +98,12 @@ class PixelDmxParams { Builder(nullptr, pBuffer, nLength, nSize); } - void Set(PixelDmxConfiguration *pPixelDmxConfiguration); - - void Dump(); + void Set(); uint16_t GetStartUniversePort(uint32_t nOutputPortIndex, bool& isSet) const { if (nOutputPortIndex < pixeldmxparams::MAX_PORTS) { isSet = isMaskSet(pixeldmxparams::Mask::START_UNI_PORT_1 << nOutputPortIndex); - return m_pixelDmxParams.nStartUniverse[nOutputPortIndex]; + return m_Params.nStartUniverse[nOutputPortIndex]; } isSet = false; @@ -111,20 +111,20 @@ class PixelDmxParams { } uint8_t GetTestPattern() const { - return m_pixelDmxParams.nTestPattern; + return m_Params.nTestPattern; } static void staticCallbackFunction(void *p, const char *s); private: + void Dump(); void callbackFunction(const char *pLine); bool isMaskSet(uint32_t nMask) const { - return (m_pixelDmxParams.nSetList & nMask) == nMask; + return (m_Params.nSetList & nMask) == nMask; } private: - PixelDmxParamsStore *m_pPixelDmxParamsStore; - pixeldmxparams::Params m_pixelDmxParams; + pixeldmxparams::Params m_Params; }; #endif /* PIXELDMXPARAMS_H_ */ diff --git a/lib-ws28xxdmx/include/pixeldmxparamsrdm.h b/lib-ws28xxdmx/include/pixeldmxparamsrdm.h index 5cac0228..6edc66eb 100644 --- a/lib-ws28xxdmx/include/pixeldmxparamsrdm.h +++ b/lib-ws28xxdmx/include/pixeldmxparamsrdm.h @@ -2,7 +2,7 @@ * @file pixeldmxparamsrdm.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,10 +27,12 @@ #define PIXELDMXPARAMSRDM_H_ #include +#include -#include "pixeldmxstore.h" #include "lightset.h" +#include "debug.h" + namespace pixeldmx { namespace paramsdmx { enum class SlotInfo { @@ -40,17 +42,31 @@ static constexpr auto DMX_FOOTPRINT = static_cast(SlotInfo::LAST); } // namespace paramsdmx } // namespace pixeldmx -class PixelDmxParamsRdm: public LightSet { +class PixelDmxParamsRdm final: public LightSet { public: - PixelDmxParamsRdm(PixelDmxStore *pWS28xxDmxStore); + PixelDmxParamsRdm() { + DEBUG_ENTRY + DEBUG_EXIT + } + + void Start([[maybe_unused]] uint32_t nPortIndex) override { + DEBUG_ENTRY + assert(nPortIndex == 0); + DEBUG_EXIT + } + + void Stop([[maybe_unused]] uint32_t nPortIndex) override { + DEBUG_ENTRY + assert(nPortIndex == 0); + DEBUG_EXIT + } + + void SetData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate = true) override; - void Start(const uint32_t nPortIndex) override; - void Stop(const uint32_t nPortIndex) override; - void SetData(uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate = true) override; - void Sync(__attribute__((unused)) const uint32_t nPortIndex) override {} - void Sync(__attribute__((unused)) const bool doForce) override {} + void Sync([[maybe_unused]] const uint32_t nPortIndex) override {} + void Sync() override {} - bool SetDmxStartAddress(__attribute__((unused)) uint16_t nDmxStartAddress) override { + bool SetDmxStartAddress([[maybe_unused]] uint16_t nDmxStartAddress) override { return false; } @@ -62,13 +78,21 @@ class PixelDmxParamsRdm: public LightSet { return pixeldmx::paramsdmx::DMX_FOOTPRINT; } - bool GetSlotInfo(uint16_t nSlotOffset, lightset::SlotInfo &tSlotInfo) override; + bool GetSlotInfo(uint16_t nSlotOffset, lightset::SlotInfo &slotInfo) override { + if (nSlotOffset >= pixeldmx::paramsdmx::DMX_FOOTPRINT) { + return false; + } + + slotInfo.nType = 0x00; // ST_PRIMARY + slotInfo.nCategory = 0xFFFF; // SD_UNDEFINED; + + return true; + } void Display(const uint8_t *pData) __attribute__((weak)); private: - static PixelDmxStore *s_pWS28xxDmxStore; - static uint8_t s_Data; + uint8_t m_Data { 0 }; }; #endif /* PIXELDMXPARAMSRDM_H_ */ diff --git a/lib-ws28xxdmx/include/pixeldmxstore.h b/lib-ws28xxdmx/include/pixeldmxstore.h old mode 100644 new mode 100755 index 58476b9e..b9af4ef5 --- a/lib-ws28xxdmx/include/pixeldmxstore.h +++ b/lib-ws28xxdmx/include/pixeldmxstore.h @@ -2,7 +2,7 @@ * @file pixeldmxstore.h * */ -/* Copyright (C) 2019-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,19 +26,37 @@ #ifndef PIXELDMXSTORE_H_ #define PIXELDMXSTORE_H_ +#include #include +#include "pixeldmxparams.h" +#include "configstore.h" + class PixelDmxStore { public: - virtual ~PixelDmxStore() { + static void SaveType(uint8_t nType) { + ConfigStore::Get()->Update(configstore::Store::WS28XXDMX, offsetof(struct pixeldmxparams::Params, nType), &nType, sizeof(uint8_t), pixeldmxparams::Mask::TYPE); + } + + static void SaveCount(uint16_t nCount) { + ConfigStore::Get()->Update(configstore::Store::WS28XXDMX, offsetof(struct pixeldmxparams::Params, nCount), &nCount, sizeof(uint16_t), pixeldmxparams::Mask::COUNT); + } + + static void SaveGroupingCount(uint16_t nGroupingCount) { + ConfigStore::Get()->Update(configstore::Store::WS28XXDMX, offsetof(struct pixeldmxparams::Params, nGroupingCount), &nGroupingCount, sizeof(uint16_t), pixeldmxparams::Mask::GROUPING_COUNT); } - virtual void SaveType(uint8_t nType)=0; - virtual void SaveCount(uint16_t nCount)=0; - virtual void SaveGroupingCount(uint16_t nGroupingCount)=0; - virtual void SaveMap(uint8_t nMap)=0; - virtual void SaveTestPattern(uint8_t nTestPattern)=0; - virtual void SaveDmxStartAddress(uint16_t nDmxStartAddress)=0; + static void SaveMap(uint8_t nMap) { + ConfigStore::Get()->Update(configstore::Store::WS28XXDMX, offsetof(struct pixeldmxparams::Params, nMap), &nMap, sizeof(uint8_t), pixeldmxparams::Mask::MAP); + } + + static void SaveTestPattern(uint8_t nTestPattern) { + ConfigStore::Get()->Update(configstore::Store::WS28XXDMX, offsetof(struct pixeldmxparams::Params, nTestPattern), &nTestPattern, sizeof(uint8_t), pixeldmxparams::Mask::TEST_PATTERN); + } + + static void SaveDmxStartAddress(uint16_t nDmxStartAddress) { + ConfigStore::Get()->Update(configstore::Store::WS28XXDMX, offsetof(struct pixeldmxparams::Params, nDmxStartAddress), &nDmxStartAddress, sizeof(uint16_t), pixeldmxparams::Mask::DMX_START_ADDRESS); + } }; #endif /* PIXELDMXSTORE_H_ */ diff --git a/lib-ws28xxdmx/include/ws28xxdmx.h b/lib-ws28xxdmx/include/ws28xxdmx.h index b131d398..80f0fe42 100644 --- a/lib-ws28xxdmx/include/ws28xxdmx.h +++ b/lib-ws28xxdmx/include/ws28xxdmx.h @@ -2,7 +2,7 @@ * @file ws28xxdmx.h * */ -/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,31 +32,28 @@ #include "lightset.h" #include "ws28xx.h" + #include "pixeldmxconfiguration.h" #include "pixelpatterns.h" -#include "pixeldmxstore.h" -#include "pixeldmxhandler.h" class WS28xxDmx final: public LightSet { public: - WS28xxDmx(PixelDmxConfiguration& pixelDmxConfiguration); + WS28xxDmx(); ~WS28xxDmx() override; void Start(const uint32_t nPortIndex) override; void Stop(const uint32_t nPortIndex) override; - void SetData(uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate = true) override; - void Sync(__attribute__((unused)) const uint32_t nPortIndex) override {} - void Sync(const bool doForce) override { - if (__builtin_expect((!doForce), 1)) { - assert(m_pWS28xx != nullptr); - m_pWS28xx->Update(); - } + void SetData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate = true) override; + void Sync([[maybe_unused]] const uint32_t nPortIndex) override {} + void Sync() override { + assert(m_pWS28xx != nullptr); + m_pWS28xx->Update(); } #if defined (OUTPUT_HAVE_STYLESWITCH) - void SetOutputStyle(__attribute__((unused)) const uint32_t nPortIndex, __attribute__((unused)) const lightset::OutputStyle outputStyle) override {} - lightset::OutputStyle GetOutputStyle(__attribute__((unused)) const uint32_t nPortIndex) const override { + void SetOutputStyle([[maybe_unused]] const uint32_t nPortIndex, [[maybe_unused]] const lightset::OutputStyle outputStyle) override {} + lightset::OutputStyle GetOutputStyle([[maybe_unused]] const uint32_t nPortIndex) const override { return lightset::OutputStyle::DELTA; } #endif @@ -65,50 +62,18 @@ class WS28xxDmx final: public LightSet { void FullOn() override; void Print() override { - m_pixelDmxConfiguration.Print(); - } - - void SetWS28xxDmxStore(PixelDmxStore *pWS28xxDmxStore) { - m_pWS28xxDmxStore = pWS28xxDmxStore; - } - - void SetPixelDmxHandler(PixelDmxHandler *pPixelDmxHandler) { - m_pPixelDmxHandler = pPixelDmxHandler; - } - - pixel::Type GetType() const { - return m_pixelDmxConfiguration.GetType(); - } - - pixel::Map GetMap() const { - return m_pixelDmxConfiguration.GetMap(); - } - - uint32_t GetCount() const { - return m_pixelDmxConfiguration.GetCount(); - } - - uint32_t GetGroups() const { - return m_pixelDmxConfiguration.GetGroups(); - } - - uint32_t GetGroupingCount() const { - return m_pixelDmxConfiguration.GetGroupingCount(); - } - - uint32_t GetUniverses() const { - return m_pixelDmxConfiguration.GetUniverses(); + PixelDmxConfiguration::Get().Print(); } // RDM bool SetDmxStartAddress(uint16_t nDmxStartAddress) override; uint16_t GetDmxStartAddress() override { - return m_nDmxStartAddress; + return PixelDmxConfiguration::Get().GetDmxStartAddress(); } uint16_t GetDmxFootprint() override { - return m_nDmxFootprint; + return PixelDmxConfiguration::Get().GetDmxFootprint(); } bool GetSlotInfo(uint16_t nSlotOffset, lightset::SlotInfo &tSlotInfo) override; @@ -118,16 +83,7 @@ class WS28xxDmx final: public LightSet { } private: - PixelDmxConfiguration m_pixelDmxConfiguration; - pixeldmxconfiguration::PortInfo m_PortInfo; - uint32_t m_nChannelsPerPixel; - - uint16_t m_nDmxStartAddress; - uint16_t m_nDmxFootprint; - WS28xx *m_pWS28xx { nullptr }; - PixelDmxStore *m_pWS28xxDmxStore { nullptr }; - PixelDmxHandler *m_pPixelDmxHandler { nullptr }; bool m_bIsStarted { false }; bool m_bBlackout { false }; diff --git a/lib-ws28xxdmx/include/ws28xxdmxmulti.h b/lib-ws28xxdmx/include/ws28xxdmxmulti.h index 4c34ccf4..ebbf1809 100644 --- a/lib-ws28xxdmx/include/ws28xxdmxmulti.h +++ b/lib-ws28xxdmx/include/ws28xxdmxmulti.h @@ -2,7 +2,7 @@ * @file ws28xxdmxmulti.h * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -30,87 +30,107 @@ #include #include "lightset.h" +#include "lightsetdata.h" #include "ws28xxmulti.h" #include "pixeldmxconfiguration.h" #include "pixelpatterns.h" -#include "pixeldmxhandler.h" +#include "logic_analyzer.h" namespace ws28xxdmxmulti { - +#if !defined (CONFIG_PIXELDMX_MAX_PORTS) +# define CONFIG_PIXELDMX_MAX_PORTS 8 +#endif +static constexpr auto MAX_PORTS = CONFIG_PIXELDMX_MAX_PORTS; } // namespace ws28xxdmxmulti class WS28xxDmxMulti final: public LightSet { public: - WS28xxDmxMulti(PixelDmxConfiguration& pixelDmxConfiguration); + WS28xxDmxMulti(); ~WS28xxDmxMulti() override; void Start(const uint32_t nPortIndex) override; void Stop(const uint32_t nPortIndex) override; - void SetData(uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate = true) override; - void Sync(__attribute__((unused)) const uint32_t nPortIndex) override {} - void Sync(const bool doForce) override { - if (__builtin_expect((!doForce), 1)) { - assert(m_pWS28xxMulti != nullptr); - m_pWS28xxMulti->Update(); + void SetData(const uint32_t nPortIndex, [[maybe_unused]] const uint8_t *pData, [[maybe_unused]] uint32_t nLength, const bool doUpdate) override { + logic_analyzer::ch0_set(); + + if (!doUpdate) { + logic_analyzer::ch0_clear(); + return; } - } -#if defined (OUTPUT_HAVE_STYLESWITCH) - void SetOutputStyle(__attribute__((unused)) const uint32_t nPortIndex, __attribute__((unused)) const lightset::OutputStyle outputStyle) override {} - lightset::OutputStyle GetOutputStyle(__attribute__((unused)) const uint32_t nPortIndex) const override { - return lightset::OutputStyle::DELTA; - } + auto &pixelDmxConfiguration = PixelDmxConfiguration::Get(); + auto &portInfo = pixelDmxConfiguration.GetPortInfo(); + + if (nPortIndex == portInfo.nProtocolPortIndexLast) { + logic_analyzer::ch1_set(); + + for (uint32_t nIndex = 0 ; nIndex <= portInfo.nProtocolPortIndexLast;nIndex++) { + logic_analyzer::ch2_set(); + SetData(nIndex, lightset::Data::Backup(nIndex), lightset::Data::GetLength(nIndex)); + logic_analyzer::ch2_clear(); + } + +#if defined (H3) + logic_analyzer::ch3_set(); + + while (m_pWS28xxMulti->IsUpdating()) { + // wait for completion + } + + logic_analyzer::ch3_clear(); #endif - void Blackout(bool bBlackout) override; - void FullOn() override; + m_pWS28xxMulti->Update(); - void Print() override { - m_pixelDmxConfiguration.Print(); - } + logic_analyzer::ch1_clear(); + } - pixel::Type GetType() const { - return m_pixelDmxConfiguration.GetType(); + logic_analyzer::ch0_clear(); } - pixel::Map GetMap() const { - return m_pixelDmxConfiguration.GetMap(); - } + void Sync(const uint32_t nPortIndex) override { + logic_analyzer::ch2_set(); - uint32_t GetCount() const { - return m_pixelDmxConfiguration.GetCount(); - } + SetData(nPortIndex, lightset::Data::Backup(nPortIndex), lightset::Data::GetLength(nPortIndex)); - uint32_t GetGroups() const { - return m_pixelDmxConfiguration.GetGroups(); + logic_analyzer::ch2_clear(); } - uint32_t GetGroupingCount() const { - return m_pixelDmxConfiguration.GetGroupingCount(); - } + void Sync() override { + logic_analyzer::ch1_set(); + logic_analyzer::ch3_set(); - uint32_t GetUniverses() const { - return m_pixelDmxConfiguration.GetUniverses(); - } + while (m_pWS28xxMulti->IsUpdating()) { + // wait for completion + } + + logic_analyzer::ch3_clear(); + + m_pWS28xxMulti->Update(); - uint32_t GetOutputPorts() const { - return m_pixelDmxConfiguration.GetOutputPorts(); + logic_analyzer::ch1_clear(); } - uint32_t GetChannelsPerPixel() const { - return m_nChannelsPerPixel; +#if defined (OUTPUT_HAVE_STYLESWITCH) + void SetOutputStyle([[maybe_unused]] const uint32_t nPortIndex, [[maybe_unused]] const lightset::OutputStyle outputStyle) override {} + lightset::OutputStyle GetOutputStyle([[maybe_unused]] const uint32_t nPortIndex) const override { + return lightset::OutputStyle::DELTA; } +#endif + + void Blackout(bool bBlackout) override; + void FullOn() override; - void SetPixelDmxHandler(PixelDmxHandler *pPixelDmxHandler) { - m_pPixelDmxHandler = pPixelDmxHandler; + void Print() override { + PixelDmxConfiguration::Get().Print(); } // RDMNet LLRP Device Only - bool SetDmxStartAddress(__attribute__((unused)) uint16_t nDmxStartAddress) override { + bool SetDmxStartAddress([[maybe_unused]] uint16_t nDmxStartAddress) override { return false; } @@ -123,12 +143,10 @@ class WS28xxDmxMulti final: public LightSet { } private: - PixelDmxConfiguration m_pixelDmxConfiguration; - pixeldmxconfiguration::PortInfo m_PortInfo; - uint32_t m_nChannelsPerPixel; + void SetData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength); +private: WS28xxMulti *m_pWS28xxMulti { nullptr }; - PixelDmxHandler *m_pPixelDmxHandler { nullptr }; uint32_t m_bIsStarted { 0 }; bool m_bBlackout { false }; diff --git a/lib-ws28xxdmx/src/dmx/ws28xxdmx.cpp b/lib-ws28xxdmx/src/dmx/ws28xxdmx.cpp index 5c39c61e..a7bdc0d5 100755 --- a/lib-ws28xxdmx/src/dmx/ws28xxdmx.cpp +++ b/lib-ws28xxdmx/src/dmx/ws28xxdmx.cpp @@ -2,7 +2,7 @@ * @file ws28xxdmx.cpp * */ -/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#if defined (DEBUG_PIXELDMX) +# undef NDEBUG +#endif + #pragma GCC push_options #pragma GCC optimize ("O3") #pragma GCC optimize ("-funroll-loops") @@ -38,26 +42,32 @@ #include "lightset.h" #include "pixeldmxconfiguration.h" +#include "pixeldmxstore.h" + +#if defined (PIXELDMXSTARTSTOP_GPIO) +# include "hal_gpio.h" +#endif #include "debug.h" WS28xxDmx *WS28xxDmx::s_pThis; -WS28xxDmx::WS28xxDmx(PixelDmxConfiguration& pixelDmxConfiguration): m_pixelDmxConfiguration(pixelDmxConfiguration) { +WS28xxDmx::WS28xxDmx() { DEBUG_ENTRY assert(s_pThis == nullptr); s_pThis = this; - m_pixelDmxConfiguration.Validate(1 , m_nChannelsPerPixel, m_PortInfo); + PixelDmxConfiguration::Get().Validate(1); - m_pWS28xx = new WS28xx(m_pixelDmxConfiguration); + m_pWS28xx = new WS28xx(); assert(m_pWS28xx != nullptr); - m_pWS28xx->Blackout(); - m_nDmxStartAddress = m_pixelDmxConfiguration.GetDmxStartAddress(); - m_nDmxFootprint = static_cast(m_nChannelsPerPixel * m_pixelDmxConfiguration.GetGroups()); +#if defined (PIXELDMXSTARTSTOP_GPIO) + FUNC_PREFIX(gpio_fsel(PIXELDMXSTARTSTOP_GPIO, GPIO_FSEL_OUTPUT)); + FUNC_PREFIX(gpio_clr(PIXELDMXSTARTSTOP_GPIO)); +#endif DEBUG_EXIT } @@ -71,31 +81,31 @@ WS28xxDmx::~WS28xxDmx() { DEBUG_EXIT } -void WS28xxDmx::Start(__attribute__((unused)) uint32_t nPortIndex) { +void WS28xxDmx::Start([[maybe_unused]] uint32_t nPortIndex) { if (m_bIsStarted) { return; } m_bIsStarted = true; - if (m_pPixelDmxHandler != nullptr) { - m_pPixelDmxHandler->Start(); - } +#if defined (PIXELDMXSTARTSTOP_GPIO) + FUNC_PREFIX(gpio_set(PIXELDMXSTARTSTOP_GPIO)); +#endif } -void WS28xxDmx::Stop(__attribute__((unused)) uint32_t nPortIndex) { +void WS28xxDmx::Stop([[maybe_unused]] uint32_t nPortIndex) { if (!m_bIsStarted) { return; } m_bIsStarted = false; - if (m_pPixelDmxHandler != nullptr) { - m_pPixelDmxHandler->Stop(); - } +#if defined (PIXELDMXSTARTSTOP_GPIO) + FUNC_PREFIX(gpio_clr(PIXELDMXSTARTSTOP_GPIO)); +#endif } -void WS28xxDmx::SetData(uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate) { +void WS28xxDmx::SetData([[maybe_unused]] uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate) { assert(pData != nullptr); assert(nLength <= lightset::dmx::UNIVERSE_SIZE); @@ -103,21 +113,32 @@ void WS28xxDmx::SetData(uint32_t nPortIndex, const uint8_t *pData, uint32_t nLen return; } + auto &pixelDmxConfiguration = PixelDmxConfiguration::Get(); + auto &portInfo = pixelDmxConfiguration.GetPortInfo(); uint32_t d = 0; +#if !defined(LIGHTSET_PORTS) + static constexpr uint32_t nSwitch = 0; +#else const auto nSwitch = nPortIndex & 0x03; - const auto nGroups = m_pixelDmxConfiguration.GetGroups(); - const auto beginIndex = m_PortInfo.nBeginIndexPort[nSwitch]; - const auto endIndex = std::min(nGroups, (beginIndex + (nLength / m_nChannelsPerPixel))); - - if ((nSwitch == 0) && (nGroups < m_PortInfo.nBeginIndexPort[1])) { - d = static_cast(m_pixelDmxConfiguration.GetDmxStartAddress() - 1); +#endif + const auto nGroups = pixelDmxConfiguration.GetGroups(); +#if !defined(LIGHTSET_PORTS) + static constexpr uint32_t beginIndex = 0; +#else + const auto beginIndex = portInfo.nBeginIndexPort[nSwitch]; +#endif + const auto nChannelsPerPixel = pixelDmxConfiguration.GetLedsPerPixel(); + const auto endIndex = std::min(nGroups, (beginIndex + (nLength / nChannelsPerPixel))); + + if ((nSwitch == 0) && (nGroups < portInfo.nBeginIndexPort[1])) { + d = (pixelDmxConfiguration.GetDmxStartAddress() - 1U); } - const auto nGroupingCount = m_pixelDmxConfiguration.GetGroupingCount(); + const auto nGroupingCount = pixelDmxConfiguration.GetGroupingCount(); - if (m_nChannelsPerPixel == 3) { - switch (m_pixelDmxConfiguration.GetMap()) { + if (nChannelsPerPixel == 3) { + switch (pixelDmxConfiguration.GetMap()) { case pixel::Map::RGB: for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { auto const nPixelIndexStart = (j * nGroupingCount); @@ -178,7 +199,7 @@ void WS28xxDmx::SetData(uint32_t nPortIndex, const uint8_t *pData, uint32_t nLen break; } } else { - assert(m_nChannelsPerPixel == 4); + assert(nChannelsPerPixel == 4); for (auto j = beginIndex; (j < endIndex) && (d < nLength); j++) { auto const nPixelIndexStart = (j * nGroupingCount); for (uint32_t k = 0; k < nGroupingCount; k++) { @@ -188,7 +209,11 @@ void WS28xxDmx::SetData(uint32_t nPortIndex, const uint8_t *pData, uint32_t nLen } } - if ((doUpdate) && (nPortIndex == m_PortInfo.nProtocolPortIndexLast)) { +#if !defined(LIGHTSET_PORTS) + if (doUpdate) { +#else + if ((doUpdate) && (nPortIndex == portInfo.nProtocolPortIndexLast)) { +#endif if (__builtin_expect((m_bBlackout), 0)) { return; } @@ -223,21 +248,19 @@ void WS28xxDmx::FullOn() { bool WS28xxDmx::SetDmxStartAddress(uint16_t nDmxStartAddress) { assert((nDmxStartAddress != 0) && (nDmxStartAddress <= lightset::dmx::UNIVERSE_SIZE)); - if (nDmxStartAddress == m_nDmxStartAddress) { + auto &pixelDmxConfiguration = PixelDmxConfiguration::Get(); + + if (nDmxStartAddress == pixelDmxConfiguration.GetDmxStartAddress()) { return true; } - if ((nDmxStartAddress + m_nDmxFootprint) > lightset::dmx::UNIVERSE_SIZE) { + if ((nDmxStartAddress + pixelDmxConfiguration.GetDmxFootprint()) > lightset::dmx::UNIVERSE_SIZE) { return false; } if ((nDmxStartAddress != 0) && (nDmxStartAddress <= lightset::dmx::UNIVERSE_SIZE)) { - m_nDmxStartAddress = nDmxStartAddress; - - if (m_pWS28xxDmxStore != nullptr) { - m_pWS28xxDmxStore->SaveDmxStartAddress(m_nDmxStartAddress); - } - + pixelDmxConfiguration.SetDmxStartAddress(nDmxStartAddress); + PixelDmxStore::SaveDmxStartAddress(nDmxStartAddress); return true; } @@ -247,13 +270,15 @@ bool WS28xxDmx::SetDmxStartAddress(uint16_t nDmxStartAddress) { // RDM bool WS28xxDmx::GetSlotInfo(uint16_t nSlotOffset, lightset::SlotInfo& slotInfo) { - if (nSlotOffset > m_nDmxFootprint) { + auto &pixelDmxConfiguration = PixelDmxConfiguration::Get(); + + if (nSlotOffset > pixelDmxConfiguration.GetDmxFootprint()) { return false; } slotInfo.nType = 0x00; // ST_PRIMARY - switch (nSlotOffset % m_nChannelsPerPixel) { + switch (nSlotOffset % pixelDmxConfiguration.GetLedsPerPixel()) { case 0: slotInfo.nCategory = 0x0205; // SD_COLOR_ADD_RED break; diff --git a/lib-ws28xxdmx/src/dmx/ws28xxdmxmulti.cpp b/lib-ws28xxdmx/src/dmx/ws28xxdmxmulti.cpp deleted file mode 100755 index 4a1a8ecb..00000000 --- a/lib-ws28xxdmx/src/dmx/ws28xxdmxmulti.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/** - * @file ws28xxdmxmulti.cpp - * - */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#pragma GCC push_options -#pragma GCC optimize ("O3") -#pragma GCC optimize ("-funroll-loops") -#pragma GCC optimize ("-fprefetch-loop-arrays") - -#include -#include -#include - -#include "ws28xxdmxmulti.h" -#include "ws28xxmulti.h" -#include "ws28xx.h" - -#include "pixeldmxparams.h" -#include "pixeldmxconfiguration.h" - -#include "debug.h" - -namespace ws28xxdmxmulti { -#if !defined (CONFIG_PIXELDMX_MAX_PORTS) -# define CONFIG_PIXELDMX_MAX_PORTS 8 -#endif -static constexpr auto MAX_PORTS = CONFIG_PIXELDMX_MAX_PORTS; -} // namespace ws28xxdmxmulti - -WS28xxDmxMulti::WS28xxDmxMulti(PixelDmxConfiguration& pixelDmxConfiguration): m_pixelDmxConfiguration(pixelDmxConfiguration) { - DEBUG_ENTRY - - m_pixelDmxConfiguration.Validate(ws28xxdmxmulti::MAX_PORTS , m_nChannelsPerPixel, m_PortInfo); - - DEBUG_PRINTF("m_PortInfo.nProtocolPortIndexLast=%u", m_PortInfo.nProtocolPortIndexLast); - - m_pWS28xxMulti = new WS28xxMulti(pixelDmxConfiguration); - assert(m_pWS28xxMulti != nullptr); - - m_pWS28xxMulti->Blackout(); - - DEBUG_EXIT -} - -WS28xxDmxMulti::~WS28xxDmxMulti() { - delete m_pWS28xxMulti; - m_pWS28xxMulti = nullptr; -} - -void WS28xxDmxMulti::Start(const uint32_t nPortIndex) { - DEBUG_PRINTF("%u", nPortIndex); - - if (m_bIsStarted == 0) { - if (m_pPixelDmxHandler != nullptr) { - m_pPixelDmxHandler->Start(); - } - } - m_bIsStarted |= (1U << nPortIndex); -} - -void WS28xxDmxMulti::Stop(const uint32_t nPortIndex) { - DEBUG_PRINTF("%u", nPortIndex); - - if (m_bIsStarted & (1U << nPortIndex)) { - m_bIsStarted &= ~(1U << nPortIndex); - } - - if (m_bIsStarted == 0) { - if (m_pPixelDmxHandler != nullptr) { - m_pPixelDmxHandler->Stop(); - } - } -} - -void WS28xxDmxMulti::SetData(uint32_t nPortIndex, const uint8_t* pData, uint32_t nLength, const bool doUpdate) { - assert(pData != nullptr); - assert(nLength <= lightset::dmx::UNIVERSE_SIZE); - -#if defined (NODE_DDP_DISPLAY) - const auto nOutIndex = (nPortIndex / 4); - const auto nSwitch = nPortIndex - (nOutIndex * 4); -#else - const auto nUniverses = m_pixelDmxConfiguration.GetUniverses(); - const auto nOutIndex = (nPortIndex / nUniverses); - const auto nSwitch = nPortIndex - (nOutIndex * nUniverses); -#endif - - const auto nGroups = m_pixelDmxConfiguration.GetGroups(); - const auto beginIndex = m_PortInfo.nBeginIndexPort[nSwitch]; - const auto endIndex = std::min(nGroups, (beginIndex + (nLength / m_nChannelsPerPixel))); - - while (m_pWS28xxMulti->IsUpdating()) { - // wait for completion - } - - uint32_t d = 0; - - const auto nGroupingCount = m_pixelDmxConfiguration.GetGroupingCount(); - - if (m_nChannelsPerPixel == 3) { - switch (m_pixelDmxConfiguration.GetMap()) { - case pixel::Map::RGB: - for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { - auto const nPixelIndexStart = (j * nGroupingCount); - for (uint32_t k = 0; k < nGroupingCount; k++) { - m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, pData[d + 0], pData[d + 1], pData[d + 2]); - } - d = d + 3; - } - break; - case pixel::Map::RBG: - for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { - auto const nPixelIndexStart = (j * nGroupingCount); - for (uint32_t k = 0; k < nGroupingCount; k++) { - m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, pData[d + 0], pData[d + 2], pData[d + 1]); - } - d = d + 3; - } - break; - case pixel::Map::GRB: - for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { - auto const nPixelIndexStart = (j * nGroupingCount); - for (uint32_t k = 0; k < nGroupingCount; k++) { - m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, pData[d + 1], pData[d + 0], pData[d + 2]); - } - d = d + 3; - } - break; - case pixel::Map::GBR: - for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { - auto const nPixelIndexStart = (j * nGroupingCount); - for (uint32_t k = 0; k < nGroupingCount; k++) { - m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, pData[d + 2], pData[d + 0], pData[d + 1]); - } - d = d + 3; - } - break; - case pixel::Map::BRG: - for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { - auto const nPixelIndexStart = (j * nGroupingCount); - for (uint32_t k = 0; k < nGroupingCount; k++) { - m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, pData[d + 1], pData[d + 2], pData[d + 0]); - } - d = d + 3; - } - break; - case pixel::Map::BGR: - for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { - auto const nPixelIndexStart = (j * nGroupingCount); - for (uint32_t k = 0; k < nGroupingCount; k++) { - m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, pData[d + 2], pData[d + 1], pData[d + 0]); - } - d = d + 3; - } - break; - default: - assert(0); - __builtin_unreachable(); - break; - } - } else { - assert(m_nChannelsPerPixel == 4); - for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { - auto const nPixelIndexStart = (j * nGroupingCount); - for (uint32_t k = 0; k < nGroupingCount; k++) { - m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, pData[d], pData[d + 1], pData[d + 2], pData[d + 3]); - } - d = d + 4; - } - } - - if ((doUpdate) && (nPortIndex == m_PortInfo.nProtocolPortIndexLast)) { - m_pWS28xxMulti->Update(); - } -} - -void WS28xxDmxMulti::Blackout(bool bBlackout) { - m_bBlackout = bBlackout; - - while (m_pWS28xxMulti->IsUpdating()) { - // wait for completion - } - - if (bBlackout) { - m_pWS28xxMulti->Blackout(); - } else { - m_pWS28xxMulti->Update(); - } -} - -void WS28xxDmxMulti::FullOn() { - while (m_pWS28xxMulti->IsUpdating()) { - // wait for completion - } - - m_pWS28xxMulti->FullOn(); -} diff --git a/lib-ws28xxdmx/src/dmxmulti/ws28xxdmxmulti.cpp b/lib-ws28xxdmx/src/dmxmulti/ws28xxdmxmulti.cpp new file mode 100755 index 00000000..66a7cc08 --- /dev/null +++ b/lib-ws28xxdmx/src/dmxmulti/ws28xxdmxmulti.cpp @@ -0,0 +1,232 @@ +/** + * @file ws28xxdmxmulti.cpp + * + */ +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if defined (DEBUG_PIXELDMX) +# undef NDEBUG +#endif + +#pragma GCC push_options +#pragma GCC optimize ("O3") +#pragma GCC optimize ("-funroll-loops") +#pragma GCC optimize ("-fprefetch-loop-arrays") + +#include +#include +#include + +#include "ws28xxdmxmulti.h" +#include "ws28xxmulti.h" +#include "ws28xx.h" + +#include "pixeldmxparams.h" +#include "pixeldmxconfiguration.h" + +#if defined (PIXELDMXSTARTSTOP_GPIO) +# include "hal_gpio.h" +#endif + +#include "debug.h" + +WS28xxDmxMulti::WS28xxDmxMulti() { + DEBUG_ENTRY + + PixelDmxConfiguration::Get().Validate(ws28xxdmxmulti::MAX_PORTS); + + m_pWS28xxMulti = new WS28xxMulti(); + assert(m_pWS28xxMulti != nullptr); + m_pWS28xxMulti->Blackout(); + +#if defined (PIXELDMXSTARTSTOP_GPIO) + FUNC_PREFIX(gpio_fsel(PIXELDMXSTARTSTOP_GPIO, GPIO_FSEL_OUTPUT)); + FUNC_PREFIX(gpio_clr(PIXELDMXSTARTSTOP_GPIO)); +#endif + + DEBUG_EXIT +} + +WS28xxDmxMulti::~WS28xxDmxMulti() { + delete m_pWS28xxMulti; + m_pWS28xxMulti = nullptr; +} + +void WS28xxDmxMulti::Start(const uint32_t nPortIndex) { + DEBUG_PRINTF("%u", nPortIndex); + + if (m_bIsStarted == 0) { +#if defined (PIXELDMXSTARTSTOP_GPIO) + FUNC_PREFIX(gpio_set(PIXELDMXSTARTSTOP_GPIO)); +#endif + } + + m_bIsStarted |= (1U << nPortIndex); +} + +void WS28xxDmxMulti::Stop(const uint32_t nPortIndex) { + DEBUG_PRINTF("%u", nPortIndex); + + if (m_bIsStarted & (1U << nPortIndex)) { + m_bIsStarted &= ~(1U << nPortIndex); + } + + if (m_bIsStarted == 0) { +#if defined (PIXELDMXSTARTSTOP_GPIO) + FUNC_PREFIX(gpio_clr(PIXELDMXSTARTSTOP_GPIO)); +#endif + } +} + +void WS28xxDmxMulti::SetData(const uint32_t nPortIndex, const uint8_t* pData, uint32_t nLength) { + assert(pData != nullptr); + assert(nLength <= lightset::dmx::UNIVERSE_SIZE); + + auto &pixelDmxConfiguration = PixelDmxConfiguration::Get(); + +#if defined (NODE_DDP_DISPLAY) + const auto nOutIndex = (nPortIndex / 4); + const auto nSwitch = nPortIndex - (nOutIndex * 4); +#else + const auto nUniverses = pixelDmxConfiguration.GetUniverses(); + const auto nOutIndex = (nPortIndex / nUniverses); + const auto nSwitch = nPortIndex - (nOutIndex * nUniverses); +#endif + + auto &portInfo = pixelDmxConfiguration.GetPortInfo(); + + const auto nGroups = pixelDmxConfiguration.GetGroups(); + const auto beginIndex = portInfo.nBeginIndexPort[nSwitch]; + const auto nChannelsPerPixel = pixelDmxConfiguration.GetLedsPerPixel(); + const auto endIndex = std::min(nGroups, (beginIndex + (nLength / nChannelsPerPixel))); + const auto nGroupingCount = pixelDmxConfiguration.GetGroupingCount(); + const auto pixelType = pixelDmxConfiguration.GetType(); + const auto isRTZProtocol = pixelDmxConfiguration.IsRTZProtocol(); + + uint32_t d = 0; + + if (nChannelsPerPixel == 3) { + // Define a lambda to handle pixel setting based on color order + auto setPixelsColourRTZ = [&](const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint32_t r, const uint32_t g, const uint32_t b) { +#if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) + const auto pGammaTable = m_pWS28xxMulti->m_PixelConfiguration.GetGammaTable(); + r = pGammaTable[r]; + g = pGammaTable[g]; + b = pGammaTable[b]; +#endif + m_pWS28xxMulti->SetColourRTZ(nPortIndex, nPixelIndex, r, g, b); + }; + + // Define a lambda to handle pixel setting based on color order + auto setPixelsColour3 = [&](const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint32_t r, const uint32_t g, const uint32_t b) { +#if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) + const auto pGammaTable = m_pWS28xxMulti->m_PixelConfiguration.GetGammaTable(); + r = pGammaTable[r]; + g = pGammaTable[g]; + b = pGammaTable[b]; +#endif + + switch (pixelType) { + case pixel::Type::WS2801: + m_pWS28xxMulti->SetColourWS2801(nPortIndex, nPixelIndex, r, g, b); + break; + case pixel::Type::APA102: + case pixel::Type::SK9822: + m_pWS28xxMulti->SetPixel4Bytes(nPortIndex, 1 + nPixelIndex, pixelDmxConfiguration.GetGlobalBrightness(), b, g, r); + break; + case pixel::Type::P9813: { + const auto nFlag = static_cast(0xC0 | ((~b & 0xC0) >> 2) | ((~r & 0xC0) >> 4) | ((~r & 0xC0) >> 6)); + m_pWS28xxMulti->SetPixel4Bytes(nPortIndex, 1 + nPixelIndex, nFlag, b, g, r); + } + break; + default: + assert(0); + __builtin_unreachable(); + break; + } + }; + + constexpr uint32_t channelMap[6][3] = { + {0, 1, 2}, // RGB + {0, 2, 1}, // RBG + {1, 0, 2}, // GRB + {2, 0, 1}, // GBR + {1, 2, 0}, // BRG + {2, 1, 0} // BGR + }; + + const auto mapIndex = static_cast(pixelDmxConfiguration.GetMap()); + // Ensure mapIndex is within valid bounds + assert(mapIndex < sizeof(channelMap) / sizeof(channelMap[0])); // Runtime check + auto const& map = channelMap[mapIndex]; + + if (isRTZProtocol) { + for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { + auto const nPixelIndexStart = j * nGroupingCount; + for (uint32_t k = 0; k < nGroupingCount; k++) { + setPixelsColourRTZ(nOutIndex, nPixelIndexStart + k, pData[d + map[0]], pData[d + map[1]], pData[d + map[2]]); + } + d += 3; // Increment by 3 since we're processing 3 channels per pixel + } + } else { + for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { + auto const nPixelIndexStart = j * nGroupingCount; + for (uint32_t k = 0; k < nGroupingCount; k++) { + setPixelsColour3(nOutIndex, nPixelIndexStart + k, pData[d + map[0]], pData[d + map[1]], pData[d + map[2]]); + } + d += 3; // Increment by 3 since we're processing 3 channels per pixel + } + } + } else { + assert(nChannelsPerPixel == 4); + assert(isRTZProtocol); + for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { + auto const nPixelIndexStart = (j * nGroupingCount); + for (uint32_t k = 0; k < nGroupingCount; k++) { + m_pWS28xxMulti->SetColourRTZ(nOutIndex, nPixelIndexStart + k, pData[d], pData[d + 1], pData[d + 2], pData[d + 3]); + } + d = d + 4; // Increment by 4 since we're processing 4 channels per pixel + } + } +} + +void WS28xxDmxMulti::Blackout(bool bBlackout) { + m_bBlackout = bBlackout; + + while (m_pWS28xxMulti->IsUpdating()) { + // wait for completion + } + + if (bBlackout) { + m_pWS28xxMulti->Blackout(); + } else { + m_pWS28xxMulti->Update(); + } +} + +void WS28xxDmxMulti::FullOn() { + while (m_pWS28xxMulti->IsUpdating()) { + // wait for completion + } + + m_pWS28xxMulti->FullOn(); +} diff --git a/lib-ws28xxdmx/src/params/pixeldmxparams.cpp b/lib-ws28xxdmx/src/params/pixeldmxparams.cpp index 55c512b6..6cdd42cc 100644 --- a/lib-ws28xxdmx/src/params/pixeldmxparams.cpp +++ b/lib-ws28xxdmx/src/params/pixeldmxparams.cpp @@ -2,7 +2,7 @@ * @file pixeldmxparams.cpp * */ -/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#if defined (DEBUG_PIXELDMX) +# undef NDEBUG +#endif + #if !defined(__clang__) // Needed for compiling on MacOS # pragma GCC push_options # pragma GCC optimize ("Os") @@ -37,6 +41,7 @@ #include "pixeltype.h" #include "pixelpatterns.h" #include "pixelconfiguration.h" + #include "gamma/gamma_tables.h" #include "lightset.h" @@ -53,58 +58,64 @@ using namespace pixel; using namespace lightset; -PixelDmxParams::PixelDmxParams(PixelDmxParamsStore *pPixelDmxParamsStore): m_pPixelDmxParamsStore(pPixelDmxParamsStore) { - m_pixelDmxParams.nSetList = 0; - m_pixelDmxParams.nType = static_cast(pixel::defaults::TYPE); - m_pixelDmxParams.nCount = defaults::COUNT; - m_pixelDmxParams.nDmxStartAddress = dmx::START_ADDRESS_DEFAULT; - m_pixelDmxParams.nSpiSpeedHz = spi::speed::ws2801::default_hz; - m_pixelDmxParams.nGlobalBrightness = 0xFF; - m_pixelDmxParams.nActiveOutputs = defaults::OUTPUT_PORTS; - m_pixelDmxParams.nGroupingCount = 1; - m_pixelDmxParams.nMap = static_cast(Map::UNDEFINED); - m_pixelDmxParams.nLowCode = 0; - m_pixelDmxParams.nHighCode = 0; - m_pixelDmxParams.nGammaValue = 0; - m_pixelDmxParams.nTestPattern = 0; +PixelDmxParams::PixelDmxParams() { + m_Params.nSetList = 0; + m_Params.nType = static_cast(pixel::defaults::TYPE); + m_Params.nCount = defaults::COUNT; + m_Params.nDmxStartAddress = dmx::START_ADDRESS_DEFAULT; + m_Params.nSpiSpeedHz = spi::speed::ws2801::default_hz; + m_Params.nGlobalBrightness = 0xFF; + m_Params.nActiveOutputs = defaults::OUTPUT_PORTS; + m_Params.nGroupingCount = 1; + m_Params.nMap = static_cast(Map::UNDEFINED); + m_Params.nLowCode = 0; + m_Params.nHighCode = 0; + m_Params.nGammaValue = 0; + m_Params.nTestPattern = 0; for (uint32_t nPortIndex = 0; nPortIndex < pixeldmxparams::MAX_PORTS; nPortIndex++) { - m_pixelDmxParams.nStartUniverse[nPortIndex] = static_cast(1 + (nPortIndex * 4)); + m_Params.nStartUniverse[nPortIndex] = static_cast(1 + (nPortIndex * 4)); } } -bool PixelDmxParams::Load() { - m_pixelDmxParams.nSetList = 0; +void PixelDmxParams::Load() { + DEBUG_ENTRY + + m_Params.nSetList = 0; #if !defined(DISABLE_FS) ReadConfigFile configfile(PixelDmxParams::staticCallbackFunction, this); if (configfile.Read(DevicesParamsConst::FILE_NAME)) { - if (m_pPixelDmxParamsStore != nullptr) { - m_pPixelDmxParamsStore->Update(&m_pixelDmxParams); - } + PixelDmxParamsStore::Update(&m_Params); } else #endif - if (m_pPixelDmxParamsStore != nullptr) { - m_pPixelDmxParamsStore->Copy(&m_pixelDmxParams); - } else { - return false; - } + PixelDmxParamsStore::Copy(&m_Params); - return true; +#ifndef NDEBUG + Dump(); +#endif + DEBUG_EXIT } void PixelDmxParams::Load(const char *pBuffer, uint32_t nLength) { + DEBUG_ENTRY + assert(pBuffer != nullptr); assert(nLength != 0); - m_pixelDmxParams.nSetList = 0; + m_Params.nSetList = 0; ReadConfigFile config(PixelDmxParams::staticCallbackFunction, this); config.Read(pBuffer, nLength); - m_pPixelDmxParamsStore->Update(&m_pixelDmxParams); + PixelDmxParamsStore::Update(&m_Params); + +#ifndef NDEBUG + Dump(); +#endif + DEBUG_EXIT } void PixelDmxParams::callbackFunction(const char *pLine) { @@ -119,25 +130,25 @@ void PixelDmxParams::callbackFunction(const char *pLine) { if (Sscan::Char(pLine, DevicesParamsConst::TYPE, cBuffer, nLength) == Sscan::OK) { cBuffer[nLength] = '\0'; - const auto type = PixelType::GetType(cBuffer); + const auto type = pixel::pixel_get_type(cBuffer); if (type != pixel::Type::UNDEFINED) { - m_pixelDmxParams.nType = static_cast(type); - m_pixelDmxParams.nSetList |= pixeldmxparams::Mask::TYPE; + m_Params.nType = static_cast(type); + m_Params.nSetList |= pixeldmxparams::Mask::TYPE; } else { - m_pixelDmxParams.nType = static_cast(pixel::defaults::TYPE); - m_pixelDmxParams.nSetList &= ~pixeldmxparams::Mask::TYPE; + m_Params.nType = static_cast(pixel::defaults::TYPE); + m_Params.nSetList &= ~pixeldmxparams::Mask::TYPE; } return; } if (Sscan::Uint16(pLine, DevicesParamsConst::COUNT, nValue16) == Sscan::OK) { if (nValue16 != 0 && nValue16 <= std::max(max::ledcount::RGB, max::ledcount::RGBW)) { - m_pixelDmxParams.nCount = nValue16; - m_pixelDmxParams.nSetList |= pixeldmxparams::Mask::COUNT; + m_Params.nCount = nValue16; + m_Params.nSetList |= pixeldmxparams::Mask::COUNT; } else { - m_pixelDmxParams.nCount = defaults::COUNT; - m_pixelDmxParams.nSetList &= ~pixeldmxparams::Mask::COUNT; + m_Params.nCount = defaults::COUNT; + m_Params.nSetList &= ~pixeldmxparams::Mask::COUNT; } return; } @@ -146,47 +157,47 @@ void PixelDmxParams::callbackFunction(const char *pLine) { if (Sscan::Char(pLine, DevicesParamsConst::MAP, cBuffer, nLength) == Sscan::OK) { cBuffer[nLength] = '\0'; - const auto map = PixelType::GetMap(cBuffer); + const auto map = pixel::pixel_get_map(cBuffer); if (map != Map::UNDEFINED) { - m_pixelDmxParams.nSetList |= pixeldmxparams::Mask::MAP; + m_Params.nSetList |= pixeldmxparams::Mask::MAP; } else { - m_pixelDmxParams.nSetList &= ~pixeldmxparams::Mask::MAP; + m_Params.nSetList &= ~pixeldmxparams::Mask::MAP; } - m_pixelDmxParams.nMap = static_cast(map); + m_Params.nMap = static_cast(map); return; } if (Sscan::Float(pLine, DevicesParamsConst::LED_T0H, fValue) == Sscan::OK) { - if ((nValue8 = PixelType::ConvertTxH(fValue)) != 0) { - m_pixelDmxParams.nSetList |= pixeldmxparams::Mask::LOW_CODE; + if ((nValue8 = pixel::pixel_convert_TxH(fValue)) != 0) { + m_Params.nSetList |= pixeldmxparams::Mask::LOW_CODE; } else { - m_pixelDmxParams.nSetList &= ~pixeldmxparams::Mask::LOW_CODE; + m_Params.nSetList &= ~pixeldmxparams::Mask::LOW_CODE; } - m_pixelDmxParams.nLowCode = nValue8; + m_Params.nLowCode = nValue8; return; } if (Sscan::Float(pLine, DevicesParamsConst::LED_T1H, fValue) == Sscan::OK) { - if ((nValue8 = PixelType::ConvertTxH(fValue)) != 0) { - m_pixelDmxParams.nSetList |= pixeldmxparams::Mask::HIGH_CODE; + if ((nValue8 = pixel::pixel_convert_TxH(fValue)) != 0) { + m_Params.nSetList |= pixeldmxparams::Mask::HIGH_CODE; } else { - m_pixelDmxParams.nSetList &= ~pixeldmxparams::Mask::HIGH_CODE; + m_Params.nSetList &= ~pixeldmxparams::Mask::HIGH_CODE; } - m_pixelDmxParams.nHighCode = nValue8; + m_Params.nHighCode = nValue8; return; } if (Sscan::Uint16(pLine, DevicesParamsConst::GROUPING_COUNT, nValue16) == Sscan::OK) { if (nValue16 > 1 && nValue16 <= std::max(max::ledcount::RGB, max::ledcount::RGBW)) { - m_pixelDmxParams.nGroupingCount = nValue16; - m_pixelDmxParams.nSetList |= pixeldmxparams::Mask::GROUPING_COUNT; + m_Params.nGroupingCount = nValue16; + m_Params.nSetList |= pixeldmxparams::Mask::GROUPING_COUNT; } else { - m_pixelDmxParams.nGroupingCount = 1; - m_pixelDmxParams.nSetList &= ~pixeldmxparams::Mask::GROUPING_COUNT; + m_Params.nGroupingCount = 1; + m_Params.nSetList &= ~pixeldmxparams::Mask::GROUPING_COUNT; } return; } @@ -195,33 +206,33 @@ void PixelDmxParams::callbackFunction(const char *pLine) { if (Sscan::Uint32(pLine, DevicesParamsConst::SPI_SPEED_HZ, nValue32) == Sscan::OK) { if (nValue32 != pixel::spi::speed::ws2801::default_hz) { - m_pixelDmxParams.nSetList |= pixeldmxparams::Mask::SPI_SPEED; + m_Params.nSetList |= pixeldmxparams::Mask::SPI_SPEED; } else { - m_pixelDmxParams.nSetList &= ~pixeldmxparams::Mask::SPI_SPEED; + m_Params.nSetList &= ~pixeldmxparams::Mask::SPI_SPEED; } - m_pixelDmxParams.nSpiSpeedHz = nValue32; + m_Params.nSpiSpeedHz = nValue32; return; } if (Sscan::Uint8(pLine, DevicesParamsConst::GLOBAL_BRIGHTNESS, nValue8) == Sscan::OK) { if ((nValue8 != 0) && (nValue8 != 0xFF)) { - m_pixelDmxParams.nSetList |= pixeldmxparams::Mask::GLOBAL_BRIGHTNESS; - m_pixelDmxParams.nGlobalBrightness = nValue8; + m_Params.nSetList |= pixeldmxparams::Mask::GLOBAL_BRIGHTNESS; + m_Params.nGlobalBrightness = nValue8; } else { - m_pixelDmxParams.nSetList &= ~pixeldmxparams::Mask::GLOBAL_BRIGHTNESS; - m_pixelDmxParams.nGlobalBrightness = 0xFF; + m_Params.nSetList &= ~pixeldmxparams::Mask::GLOBAL_BRIGHTNESS; + m_Params.nGlobalBrightness = 0xFF; } return; } -#if defined (PARAMS_INLCUDE_ALL) || !defined(OUTPUT_DMX_PIXEL_MULTI) +#if !defined(OUTPUT_DMX_PIXEL_MULTI) if (Sscan::Uint16(pLine, LightSetParamsConst::DMX_START_ADDRESS, nValue16) == Sscan::OK) { if ((nValue16 != 0) && nValue16 <= (dmx::UNIVERSE_SIZE) && (nValue16 != dmx::START_ADDRESS_DEFAULT)) { - m_pixelDmxParams.nDmxStartAddress = nValue16; - m_pixelDmxParams.nSetList |= pixeldmxparams::Mask::DMX_START_ADDRESS; + m_Params.nDmxStartAddress = nValue16; + m_Params.nSetList |= pixeldmxparams::Mask::DMX_START_ADDRESS; } else { - m_pixelDmxParams.nDmxStartAddress = dmx::START_ADDRESS_DEFAULT; - m_pixelDmxParams.nSetList &= ~pixeldmxparams::Mask::DMX_START_ADDRESS; + m_Params.nDmxStartAddress = dmx::START_ADDRESS_DEFAULT; + m_Params.nSetList &= ~pixeldmxparams::Mask::DMX_START_ADDRESS; } return; } @@ -230,23 +241,23 @@ void PixelDmxParams::callbackFunction(const char *pLine) { for (uint32_t i = 0; i < pixeldmxparams::MAX_PORTS; i++) { if (Sscan::Uint16(pLine, LightSetParamsConst::START_UNI_PORT[i], nValue16) == Sscan::OK) { if (nValue16 > 0) { - m_pixelDmxParams.nStartUniverse[i] = nValue16; - m_pixelDmxParams.nSetList |= (pixeldmxparams::Mask::START_UNI_PORT_1 << i); + m_Params.nStartUniverse[i] = nValue16; + m_Params.nSetList |= (pixeldmxparams::Mask::START_UNI_PORT_1 << i); } else { - m_pixelDmxParams.nStartUniverse[i] = static_cast(1 + (i * 4)); - m_pixelDmxParams.nSetList &= ~(pixeldmxparams::Mask::START_UNI_PORT_1 << i); + m_Params.nStartUniverse[i] = static_cast(1 + (i * 4)); + m_Params.nSetList &= ~(pixeldmxparams::Mask::START_UNI_PORT_1 << i); } } } -#if defined (PARAMS_INLCUDE_ALL) || defined(OUTPUT_DMX_PIXEL_MULTI) +#if defined(OUTPUT_DMX_PIXEL_MULTI) if (Sscan::Uint8(pLine, DevicesParamsConst::ACTIVE_OUT, nValue8) == Sscan::OK) { if ((nValue8 > 0) && (nValue8 <= pixeldmxparams::MAX_PORTS) && (nValue8 != pixel::defaults::OUTPUT_PORTS)) { - m_pixelDmxParams.nActiveOutputs = nValue8; - m_pixelDmxParams.nSetList |= pixeldmxparams::Mask::ACTIVE_OUT; + m_Params.nActiveOutputs = nValue8; + m_Params.nSetList |= pixeldmxparams::Mask::ACTIVE_OUT; } else { - m_pixelDmxParams.nActiveOutputs = pixel::defaults::OUTPUT_PORTS; - m_pixelDmxParams.nSetList &= ~pixeldmxparams::Mask::ACTIVE_OUT; + m_Params.nActiveOutputs = pixel::defaults::OUTPUT_PORTS; + m_Params.nSetList &= ~pixeldmxparams::Mask::ACTIVE_OUT; } return; } @@ -254,20 +265,21 @@ void PixelDmxParams::callbackFunction(const char *pLine) { if (Sscan::Uint8(pLine, DevicesParamsConst::TEST_PATTERN, nValue8) == Sscan::OK) { if ((nValue8 != static_cast(pixelpatterns::Pattern::NONE)) && (nValue8 < static_cast(pixelpatterns::Pattern::LAST))) { - m_pixelDmxParams.nTestPattern = nValue8; - m_pixelDmxParams.nSetList |= pixeldmxparams::Mask::TEST_PATTERN; + m_Params.nTestPattern = nValue8; + m_Params.nSetList |= pixeldmxparams::Mask::TEST_PATTERN; } else { - m_pixelDmxParams.nTestPattern = static_cast(pixelpatterns::Pattern::NONE); - m_pixelDmxParams.nSetList &= ~pixeldmxparams::Mask::TEST_PATTERN; + m_Params.nTestPattern = static_cast(pixelpatterns::Pattern::NONE); + m_Params.nSetList &= ~pixeldmxparams::Mask::TEST_PATTERN; } return; } +#if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) if (Sscan::Uint8(pLine, DevicesParamsConst::GAMMA_CORRECTION, nValue8) == Sscan::OK) { if (nValue8 != 0) { - m_pixelDmxParams.nSetList |= pixeldmxparams::Mask::GAMMA_CORRECTION; + m_Params.nSetList |= pixeldmxparams::Mask::GAMMA_CORRECTION; } else { - m_pixelDmxParams.nSetList &= ~pixeldmxparams::Mask::GAMMA_CORRECTION; + m_Params.nSetList &= ~pixeldmxparams::Mask::GAMMA_CORRECTION; } return; } @@ -275,148 +287,179 @@ void PixelDmxParams::callbackFunction(const char *pLine) { if (Sscan::Float(pLine, DevicesParamsConst::GAMMA_VALUE, fValue) == Sscan::OK) { const auto nValue = static_cast(fValue * 10); if ((nValue < gamma::MIN) || (nValue > gamma::MAX)) { - m_pixelDmxParams.nGammaValue = 0; + m_Params.nGammaValue = 0; } else { - m_pixelDmxParams.nGammaValue = nValue; + m_Params.nGammaValue = nValue; } + return; } -} - -void PixelDmxParams::staticCallbackFunction(void *p, const char *s) { - assert(p != nullptr); - assert(s != nullptr); - - (static_cast(p))->callbackFunction(s); +#endif } void PixelDmxParams::Builder(const struct pixeldmxparams::Params *ptWS28xxParams, char *pBuffer, uint32_t nLength, uint32_t& nSize) { assert(pBuffer != nullptr); if (ptWS28xxParams != nullptr) { - memcpy(&m_pixelDmxParams, ptWS28xxParams, sizeof(struct pixeldmxparams::Params)); + memcpy(&m_Params, ptWS28xxParams, sizeof(struct pixeldmxparams::Params)); } else { - m_pPixelDmxParamsStore->Copy(&m_pixelDmxParams); + PixelDmxParamsStore::Copy(&m_Params); } PropertiesBuilder builder(DevicesParamsConst::FILE_NAME, pBuffer, nLength); - builder.Add(DevicesParamsConst::TYPE, PixelType::GetType(static_cast(m_pixelDmxParams.nType)), isMaskSet(pixeldmxparams::Mask::TYPE)); - builder.Add(DevicesParamsConst::COUNT, m_pixelDmxParams.nCount, isMaskSet(pixeldmxparams::Mask::COUNT)); + builder.Add(DevicesParamsConst::TYPE, pixel::pixel_get_type(static_cast(m_Params.nType)), isMaskSet(pixeldmxparams::Mask::TYPE)); + builder.Add(DevicesParamsConst::COUNT, m_Params.nCount, isMaskSet(pixeldmxparams::Mask::COUNT)); + +#if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) builder.Add(DevicesParamsConst::GAMMA_CORRECTION, isMaskSet(pixeldmxparams::Mask::GAMMA_CORRECTION)); - if (m_pixelDmxParams.nGammaValue == 0) { + if (m_Params.nGammaValue == 0) { builder.Add(DevicesParamsConst::GAMMA_VALUE, "", false); } else { - builder.Add(DevicesParamsConst::GAMMA_VALUE, static_cast(m_pixelDmxParams.nGammaValue) / 10, true); + builder.Add(DevicesParamsConst::GAMMA_VALUE, static_cast(m_Params.nGammaValue) / 10, true); } +#endif builder.AddComment("Overwrite datasheet"); if (!isMaskSet(pixeldmxparams::Mask::MAP)) { - m_pixelDmxParams.nMap = static_cast(PixelType::GetMap(static_cast(m_pixelDmxParams.nType))); + m_Params.nMap = static_cast(pixel::pixel_get_map(static_cast(m_Params.nType))); } - builder.Add(DevicesParamsConst::MAP, PixelType::GetMap(static_cast(m_pixelDmxParams.nMap)), isMaskSet(pixeldmxparams::Mask::MAP)); + builder.Add(DevicesParamsConst::MAP, pixel::pixel_get_map(static_cast(m_Params.nMap)), isMaskSet(pixeldmxparams::Mask::MAP)); if (!isMaskSet(pixeldmxparams::Mask::LOW_CODE) || !isMaskSet(pixeldmxparams::Mask::HIGH_CODE)) { uint8_t nLowCode; uint8_t nHighCode; - PixelConfiguration::GetTxH(static_cast(m_pixelDmxParams.nType), nLowCode, nHighCode); + PixelConfiguration::Get().GetTxH(static_cast(m_Params.nType), nLowCode, nHighCode); if (!isMaskSet(pixeldmxparams::Mask::LOW_CODE)) { - m_pixelDmxParams.nLowCode = nLowCode; + m_Params.nLowCode = nLowCode; } if (!isMaskSet(pixeldmxparams::Mask::HIGH_CODE)) { - m_pixelDmxParams.nHighCode = nHighCode; + m_Params.nHighCode = nHighCode; } } builder.AddComment("Overwrite timing (us)"); - builder.Add(DevicesParamsConst::LED_T0H, PixelType::ConvertTxH(m_pixelDmxParams.nLowCode), isMaskSet(pixeldmxparams::Mask::LOW_CODE), 2); - builder.Add(DevicesParamsConst::LED_T1H, PixelType::ConvertTxH(m_pixelDmxParams.nHighCode), isMaskSet(pixeldmxparams::Mask::HIGH_CODE), 2); + builder.Add(DevicesParamsConst::LED_T0H, pixel::pixel_convert_TxH(m_Params.nLowCode), isMaskSet(pixeldmxparams::Mask::LOW_CODE), 2); + builder.Add(DevicesParamsConst::LED_T1H, pixel::pixel_convert_TxH(m_Params.nHighCode), isMaskSet(pixeldmxparams::Mask::HIGH_CODE), 2); builder.AddComment("Grouping"); - builder.Add(DevicesParamsConst::GROUPING_COUNT, m_pixelDmxParams.nGroupingCount, isMaskSet(pixeldmxparams::Mask::GROUPING_COUNT)); + builder.Add(DevicesParamsConst::GROUPING_COUNT, m_Params.nGroupingCount, isMaskSet(pixeldmxparams::Mask::GROUPING_COUNT)); builder.AddComment("Clock based chips"); - builder.Add(DevicesParamsConst::SPI_SPEED_HZ, m_pixelDmxParams.nSpiSpeedHz, isMaskSet(pixeldmxparams::Mask::SPI_SPEED)); + builder.Add(DevicesParamsConst::SPI_SPEED_HZ, m_Params.nSpiSpeedHz, isMaskSet(pixeldmxparams::Mask::SPI_SPEED)); builder.AddComment("APA102/SK9822"); - builder.Add(DevicesParamsConst::GLOBAL_BRIGHTNESS, m_pixelDmxParams.nGlobalBrightness, isMaskSet(pixeldmxparams::Mask::GLOBAL_BRIGHTNESS)); + builder.Add(DevicesParamsConst::GLOBAL_BRIGHTNESS, m_Params.nGlobalBrightness, isMaskSet(pixeldmxparams::Mask::GLOBAL_BRIGHTNESS)); -#if defined (PARAMS_INLCUDE_ALL) || !defined(OUTPUT_DMX_PIXEL_MULTI) +#if !defined(OUTPUT_DMX_PIXEL_MULTI) builder.AddComment("DMX"); - builder.Add(LightSetParamsConst::DMX_START_ADDRESS, m_pixelDmxParams.nDmxStartAddress, isMaskSet(pixeldmxparams::Mask::DMX_START_ADDRESS)); + builder.Add(LightSetParamsConst::DMX_START_ADDRESS, m_Params.nDmxStartAddress, isMaskSet(pixeldmxparams::Mask::DMX_START_ADDRESS)); #endif for (uint32_t i = 0; i < pixeldmxparams::MAX_PORTS; i++) { - builder.Add(LightSetParamsConst::START_UNI_PORT[i],m_pixelDmxParams.nStartUniverse[i], isMaskSet(pixeldmxparams::Mask::START_UNI_PORT_1 << i)); + builder.Add(LightSetParamsConst::START_UNI_PORT[i],m_Params.nStartUniverse[i], isMaskSet(pixeldmxparams::Mask::START_UNI_PORT_1 << i)); } -#if defined (PARAMS_INLCUDE_ALL) || defined(OUTPUT_DMX_PIXEL_MULTI) - builder.Add(DevicesParamsConst::ACTIVE_OUT, m_pixelDmxParams.nActiveOutputs, isMaskSet(pixeldmxparams::Mask::ACTIVE_OUT)); +#if defined(OUTPUT_DMX_PIXEL_MULTI) + builder.Add(DevicesParamsConst::ACTIVE_OUT, m_Params.nActiveOutputs, isMaskSet(pixeldmxparams::Mask::ACTIVE_OUT)); #endif builder.AddComment("Test pattern"); - builder.Add(DevicesParamsConst::TEST_PATTERN, m_pixelDmxParams.nTestPattern, isMaskSet(pixeldmxparams::Mask::TEST_PATTERN)); + builder.Add(DevicesParamsConst::TEST_PATTERN, m_Params.nTestPattern, isMaskSet(pixeldmxparams::Mask::TEST_PATTERN)); nSize = builder.GetSize(); DEBUG_PRINTF("nSize=%d", nSize); } -void PixelDmxParams::Set(PixelDmxConfiguration *pPixelDmxConfiguration) { - assert(pPixelDmxConfiguration != nullptr); - +void PixelDmxParams::Set() { // Pixel + auto& pixelConfiguration = PixelConfiguration::Get(); if (isMaskSet(pixeldmxparams::Mask::TYPE)) { - pPixelDmxConfiguration->SetType(static_cast(m_pixelDmxParams.nType)); + pixelConfiguration.SetType(static_cast(m_Params.nType)); } if (isMaskSet(pixeldmxparams::Mask::COUNT)) { - pPixelDmxConfiguration->SetCount(m_pixelDmxParams.nCount); + pixelConfiguration.SetCount(m_Params.nCount); } if (isMaskSet(pixeldmxparams::Mask::MAP)) { - pPixelDmxConfiguration->SetMap(static_cast(m_pixelDmxParams.nMap)); + pixelConfiguration.SetMap(static_cast(m_Params.nMap)); } if (isMaskSet(pixeldmxparams::Mask::LOW_CODE)) { - pPixelDmxConfiguration->SetLowCode(m_pixelDmxParams.nLowCode); + pixelConfiguration.SetLowCode(m_Params.nLowCode); } if (isMaskSet(pixeldmxparams::Mask::HIGH_CODE)) { - pPixelDmxConfiguration->SetHighCode(m_pixelDmxParams.nHighCode); + pixelConfiguration.SetHighCode(m_Params.nHighCode); } if (isMaskSet(pixeldmxparams::Mask::SPI_SPEED)) { - pPixelDmxConfiguration->SetClockSpeedHz(m_pixelDmxParams.nSpiSpeedHz); + pixelConfiguration.SetClockSpeedHz(m_Params.nSpiSpeedHz); } if (isMaskSet(pixeldmxparams::Mask::GLOBAL_BRIGHTNESS)) { - pPixelDmxConfiguration->SetGlobalBrightness(m_pixelDmxParams.nGlobalBrightness); + pixelConfiguration.SetGlobalBrightness(m_Params.nGlobalBrightness); } +#if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) if (isMaskSet(pixeldmxparams::Mask::GAMMA_CORRECTION)) { - pPixelDmxConfiguration->SetEnableGammaCorrection(true); - if (m_pixelDmxParams.nGammaValue != 0) { - pPixelDmxConfiguration->SetGammaTable(m_pixelDmxParams.nGammaValue); + pixelConfiguration.SetEnableGammaCorrection(true); + if (m_Params.nGammaValue != 0) { + pixelConfiguration.SetGammaTable(m_Params.nGammaValue); } } +#endif // Dmx + auto& pixelDmxConfiguration = PixelDmxConfiguration::Get(); if (isMaskSet(pixeldmxparams::Mask::DMX_START_ADDRESS)) { - pPixelDmxConfiguration->SetDmxStartAddress(m_pixelDmxParams.nDmxStartAddress); + pixelDmxConfiguration.SetDmxStartAddress(m_Params.nDmxStartAddress); } if (isMaskSet(pixeldmxparams::Mask::GROUPING_COUNT)) { - pPixelDmxConfiguration->SetGroupingCount(m_pixelDmxParams.nGroupingCount); + pixelDmxConfiguration.SetGroupingCount(m_Params.nGroupingCount); } -#if defined (PARAMS_INLCUDE_ALL) || defined(OUTPUT_DMX_PIXEL_MULTI) +#if defined(OUTPUT_DMX_PIXEL_MULTI) if (isMaskSet(pixeldmxparams::Mask::ACTIVE_OUT)) { - pPixelDmxConfiguration->SetOutputPorts(m_pixelDmxParams.nActiveOutputs); + pixelDmxConfiguration.SetOutputPorts(m_Params.nActiveOutputs); } #endif } + +void PixelDmxParams::staticCallbackFunction(void *p, const char *s) { + assert(p != nullptr); + assert(s != nullptr); + + (static_cast(p))->callbackFunction(s); +} + +void PixelDmxParams::Dump() { + printf("%s::%s \'%s\':\n", __FILE__,__FUNCTION__, DevicesParamsConst::FILE_NAME); + printf(" %s=%s [%d]\n", DevicesParamsConst::TYPE, pixel::pixel_get_type(static_cast(m_Params.nType)), static_cast(m_Params.nType)); + printf(" %s=%d [%s]\n", DevicesParamsConst::MAP, static_cast(m_Params.nMap), pixel::pixel_get_map(static_cast(m_Params.nMap))); + printf(" %s=%.2f [0x%X]\n", DevicesParamsConst::LED_T0H, pixel::pixel_convert_TxH(m_Params.nLowCode), m_Params.nLowCode); + printf(" %s=%.2f [0x%X]\n", DevicesParamsConst::LED_T1H, pixel::pixel_convert_TxH(m_Params.nHighCode), m_Params.nHighCode); + printf(" %s=%d\n", DevicesParamsConst::COUNT, m_Params.nCount); + + for (uint32_t i = 0; i < std::min(static_cast(pixelpatterns::MAX_PORTS), sizeof(LightSetParamsConst::START_UNI_PORT) / sizeof(LightSetParamsConst::START_UNI_PORT[0])); i++) { + printf(" %s=%d\n", LightSetParamsConst::START_UNI_PORT[i], m_Params.nStartUniverse[i]); + } + + printf(" %s=%d\n", DevicesParamsConst::ACTIVE_OUT, m_Params.nActiveOutputs); + printf(" %s=%d\n", DevicesParamsConst::GROUPING_COUNT, m_Params.nGroupingCount); + printf(" %s=%u\n", DevicesParamsConst::SPI_SPEED_HZ, static_cast(m_Params.nSpiSpeedHz)); + printf(" %s=%d\n", DevicesParamsConst::GLOBAL_BRIGHTNESS, m_Params.nGlobalBrightness); + printf(" %s=%d\n", LightSetParamsConst::DMX_START_ADDRESS, m_Params.nDmxStartAddress); + printf(" %s=%d\n", DevicesParamsConst::TEST_PATTERN, m_Params.nTestPattern); +#if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) + printf(" %s=%d\n", DevicesParamsConst::GAMMA_CORRECTION, isMaskSet(pixeldmxparams::Mask::GAMMA_CORRECTION)); + printf(" %s=%1.1f [%u]\n", DevicesParamsConst::GAMMA_VALUE, static_cast(m_Params.nGammaValue) / 10, m_Params.nGammaValue); +#endif +} diff --git a/lib-ws28xxdmx/src/params/pixeldmxparamsdump.cpp b/lib-ws28xxdmx/src/params/pixeldmxparamsdump.cpp deleted file mode 100644 index d882256e..00000000 --- a/lib-ws28xxdmx/src/params/pixeldmxparamsdump.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file pixeldmxparamsdump.cpp - * - */ -/* Copyright (C) 2016-2022 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#if !defined(__clang__) // Needed for compiling on MacOS -# pragma GCC push_options -# pragma GCC optimize ("Os") -#endif - -#ifndef NDEBUG -# include -# include -# include - -# include "pixeltype.h" - -# include "devicesparamsconst.h" -# include "lightsetparamsconst.h" -#endif - -#include "pixeldmxparams.h" - -using namespace pixeldmxparams; - -void PixelDmxParams::Dump() { -#ifndef NDEBUG - printf("%s::%s \'%s\':\n", __FILE__,__FUNCTION__, DevicesParamsConst::FILE_NAME); - - if (isMaskSet(Mask::TYPE)) { - printf(" %s=%s [%d]\n", DevicesParamsConst::TYPE, PixelType::GetType(static_cast(m_pixelDmxParams.nType)), static_cast(m_pixelDmxParams.nType)); - } - - if (isMaskSet(Mask::MAP)) { - printf(" %s=%d [%s]\n", DevicesParamsConst::MAP, static_cast(m_pixelDmxParams.nMap), PixelType::GetMap(static_cast(m_pixelDmxParams.nMap))); - } - - if (isMaskSet(Mask::LOW_CODE)) { - printf(" %s=%.2f [0x%X]\n", DevicesParamsConst::LED_T0H, PixelType::ConvertTxH(m_pixelDmxParams.nLowCode), m_pixelDmxParams.nLowCode); - } - - if (isMaskSet(Mask::HIGH_CODE)) { - printf(" %s=%.2f [0x%X]\n", DevicesParamsConst::LED_T1H, PixelType::ConvertTxH(m_pixelDmxParams.nHighCode), m_pixelDmxParams.nHighCode); - } - - if (isMaskSet(Mask::COUNT)) { - printf(" %s=%d\n", DevicesParamsConst::COUNT, m_pixelDmxParams.nCount); - } - - for (uint32_t i = 0; i < std::min(static_cast(MAX_PORTS), sizeof(LightSetParamsConst::START_UNI_PORT) / sizeof(LightSetParamsConst::START_UNI_PORT[0])); i++) { - if (isMaskSet(Mask::START_UNI_PORT_1 << i)) { - printf(" %s=%d\n", LightSetParamsConst::START_UNI_PORT[i], m_pixelDmxParams.nStartUniverse[i]); - } - } - - if (isMaskSet(Mask::ACTIVE_OUT)) { - printf(" %s=%d\n", DevicesParamsConst::ACTIVE_OUT, m_pixelDmxParams.nActiveOutputs); - } - - if (isMaskSet(Mask::GROUPING_COUNT)) { - printf(" %s=%d\n", DevicesParamsConst::GROUPING_COUNT, m_pixelDmxParams.nGroupingCount); - } - - if (isMaskSet(Mask::SPI_SPEED)) { - printf(" %s=%d\n", DevicesParamsConst::SPI_SPEED_HZ, m_pixelDmxParams.nSpiSpeedHz); - } - - if (isMaskSet(Mask::GLOBAL_BRIGHTNESS)) { - printf(" %s=%d\n", DevicesParamsConst::GLOBAL_BRIGHTNESS, m_pixelDmxParams.nGlobalBrightness); - } - - if (isMaskSet(Mask::DMX_START_ADDRESS)) { - printf(" %s=%d\n", LightSetParamsConst::DMX_START_ADDRESS, m_pixelDmxParams.nDmxStartAddress); - } - - if (isMaskSet(Mask::TEST_PATTERN)) { - printf(" %s=%d\n", DevicesParamsConst::TEST_PATTERN, m_pixelDmxParams.nTestPattern); - } - - if (isMaskSet(Mask::GAMMA_CORRECTION)) { - printf(" %s=1 [Yes]\n", DevicesParamsConst::GAMMA_CORRECTION); - printf(" %s=%1.1f [%u]\n", DevicesParamsConst::GAMMA_VALUE, static_cast(m_pixelDmxParams.nGammaValue) / 10, m_pixelDmxParams.nGammaValue); - } -#endif -} diff --git a/lib-ws28xxdmx/src/params/pixeldmxparamsrdm.cpp b/lib-ws28xxdmx/src/params/pixeldmxparamsrdm.cpp index 139be731..13fadf64 100644 --- a/lib-ws28xxdmx/src/params/pixeldmxparamsrdm.cpp +++ b/lib-ws28xxdmx/src/params/pixeldmxparamsrdm.cpp @@ -2,7 +2,7 @@ * @file pixeldmxparamsdmx.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,48 +23,25 @@ * THE SOFTWARE. */ +#if defined (DEBUG_PIXELDMX) +# undef NDEBUG +#endif + #include #include #include "pixeldmxparamsrdm.h" -#include "pixeltype.h" #include "pixeldmxstore.h" +#include "pixeltype.h" #include "lightset.h" #include "debug.h" -using namespace pixeldmx::paramsdmx; - -PixelDmxStore *PixelDmxParamsRdm::s_pWS28xxDmxStore; -uint8_t PixelDmxParamsRdm::s_Data; - -PixelDmxParamsRdm::PixelDmxParamsRdm(PixelDmxStore *pWS28xxDmxStore) { - DEBUG_ENTRY - - s_pWS28xxDmxStore = pWS28xxDmxStore; - - DEBUG_EXIT -} - -void PixelDmxParamsRdm::Start(__attribute__((unused)) uint32_t nPortIndex) { - DEBUG_ENTRY - assert(nPortIndex == 0); - - DEBUG_EXIT -} - -void PixelDmxParamsRdm::Stop(__attribute__((unused)) uint32_t nPortIndex) { - DEBUG_ENTRY - assert(nPortIndex == 0); - - DEBUG_EXIT -} - -void PixelDmxParamsRdm::SetData(__attribute__((unused)) uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, __attribute__((unused)) const bool doUpdate) { +void PixelDmxParamsRdm::SetData([[maybe_unused]] uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, [[maybe_unused]] const bool doUpdate) { assert(nPortIndex == 0); - if (nLength < DMX_FOOTPRINT) { + if (nLength < pixeldmx::paramsdmx::DMX_FOOTPRINT) { return; } @@ -77,30 +54,32 @@ void PixelDmxParamsRdm::SetData(__attribute__((unused)) uint32_t nPortIndex, con * Slot 6: Program; */ - assert(DMX_FOOTPRINT == 6); + assert(pixeldmx::paramsdmx::DMX_FOOTPRINT == 6); - const auto nLastIndex = DMX_FOOTPRINT - 1U; + const auto nLastIndex = pixeldmx::paramsdmx::DMX_FOOTPRINT - 1U; if (pData[nLastIndex] == 0x00) { - s_Data = 0x00; + m_Data = 0x00; } else { - if ((pData[nLastIndex] == 0xFF) && (s_Data == 0x00)) { + if ((pData[nLastIndex] == 0xFF) && (m_Data == 0x00)) { DEBUG_PUTS("Program"); - s_Data = 0xFF; + m_Data = 0xFF; - auto nData = pData[static_cast(SlotInfo::TYPE)]; + auto nData = pData[static_cast(pixeldmx::paramsdmx::SlotInfo::TYPE)]; auto nUndefined = static_cast(pixel::Type::UNDEFINED); - s_pWS28xxDmxStore->SaveType(nData < nUndefined ? nData : nUndefined); + const auto nType = nData < nUndefined ? nData : nUndefined; + PixelDmxStore::SaveType(nType); // Validation takes place in class PixelDmxConfiguration - s_pWS28xxDmxStore->SaveCount(pData[static_cast(SlotInfo::COUNT)]); - s_pWS28xxDmxStore->SaveGroupingCount(pData[static_cast(SlotInfo::GROUPING_COUNT)]); + PixelDmxStore::SaveCount(pData[static_cast(pixeldmx::paramsdmx::SlotInfo::COUNT)]); + PixelDmxStore::SaveGroupingCount(pData[static_cast(pixeldmx::paramsdmx::SlotInfo::GROUPING_COUNT)]); - nData = pData[static_cast(SlotInfo::MAP)]; + nData = pData[static_cast(pixeldmx::paramsdmx::SlotInfo::MAP)]; nUndefined = static_cast(pixel::Map::UNDEFINED); - s_pWS28xxDmxStore->SaveMap(nData < nUndefined ? nData : nUndefined); + const auto nMap = nData < nUndefined ? nData : nUndefined; + PixelDmxStore::SaveMap(nMap); - s_pWS28xxDmxStore->SaveTestPattern(pData[static_cast(SlotInfo::TEST_PATTERN)]); + PixelDmxStore::SaveTestPattern(pData[static_cast(pixeldmx::paramsdmx::SlotInfo::TEST_PATTERN)]); } } @@ -109,17 +88,6 @@ void PixelDmxParamsRdm::SetData(__attribute__((unused)) uint32_t nPortIndex, con } } -bool PixelDmxParamsRdm::GetSlotInfo(uint16_t nSlotOffset, lightset::SlotInfo &slotInfo) { - if (nSlotOffset >= DMX_FOOTPRINT) { - return false; - } - - slotInfo.nType = 0x00; // ST_PRIMARY - slotInfo.nCategory = 0xFFFF; // SD_UNDEFINED; - - return true; -} - -void PixelDmxParamsRdm::Display(__attribute__((unused)) const uint8_t *pData) { +void PixelDmxParamsRdm::Display([[maybe_unused]] const uint8_t *pData) { // Weak } diff --git a/lib-ws28xxdmx/src/pixeldmxconfiguration.cpp b/lib-ws28xxdmx/src/pixeldmxconfiguration.cpp deleted file mode 100644 index f55f0eec..00000000 --- a/lib-ws28xxdmx/src/pixeldmxconfiguration.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @file pixeldmxconfiguration.cpp - * - */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#if !defined(__clang__) // Needed for compiling on MacOS -# pragma GCC push_options -# pragma GCC optimize ("Os") -#endif - -#include -#include -#include - -#include "pixeldmxconfiguration.h" - -#include "debug.h" - -#if defined (NODE_ARTNET_MULTI) -# define NODE_ARTNET -#endif - -using namespace pixel; - -void PixelDmxConfiguration::Validate(uint32_t nPortsMax, uint32_t& nLedsPerPixel, pixeldmxconfiguration::PortInfo& portInfo) { - DEBUG_ENTRY - - PixelConfiguration::Validate(nLedsPerPixel); - - if (!IsRTZProtocol()) { - const auto type = GetType(); - if (!((type == Type::WS2801) || (type == Type::APA102) || (type == Type::SK9822))) { - SetType(Type::WS2801); - } - - PixelConfiguration::Validate(nLedsPerPixel); - } - - portInfo.nBeginIndexPort[0] = 0; - - if (GetType() == Type::SK6812W) { - portInfo.nBeginIndexPort[1] = 128; - portInfo.nBeginIndexPort[2] = 256; - portInfo.nBeginIndexPort[3] = 384; - } else { - portInfo.nBeginIndexPort[1] = 170; - portInfo.nBeginIndexPort[2] = 340; - portInfo.nBeginIndexPort[3] = 510; - } - - if ((m_nGroupingCount == 0) || (m_nGroupingCount > GetCount())) { - m_nGroupingCount = GetCount(); - } - - m_nGroups = GetCount() / m_nGroupingCount; - - m_nOutputPorts = std::min(nPortsMax, m_nOutputPorts); - m_nUniverses = (1U + (m_nGroups / (1U + portInfo.nBeginIndexPort[1]))); - - if (nPortsMax == 1) { - portInfo.nProtocolPortIndexLast = (m_nGroups / (1U + portInfo.nBeginIndexPort[1])); - } else { -#if defined (NODE_DDP_DISPLAY) - portInfo.nProtocolPortIndexLast = (((m_nOutputPorts - 1U) * 4U) + m_nUniverses - 1U); -#else - portInfo.nProtocolPortIndexLast = ((m_nOutputPorts * m_nUniverses) - 1U); -#endif - } - - DEBUG_PRINTF("portInfo.nProtocolPortIndexLast=%u", portInfo.nProtocolPortIndexLast); - DEBUG_EXIT -} - -#include - -void PixelDmxConfiguration::Print() { - PixelConfiguration::Print(); - - printf("Pixel DMX configuration\n"); - printf(" Outputs : %d\n", m_nOutputPorts); - printf(" Grouping count : %d [Groups : %d]\n", m_nGroupingCount, m_nGroups); -} diff --git a/lib-ws28xxdmx/src/rdm/rdm_manufacturer_pid.cpp b/lib-ws28xxdmx/src/rdm/rdm_manufacturer_pid.cpp index a80e6084..9d0f4d3f 100755 --- a/lib-ws28xxdmx/src/rdm/rdm_manufacturer_pid.cpp +++ b/lib-ws28xxdmx/src/rdm/rdm_manufacturer_pid.cpp @@ -2,7 +2,7 @@ * @file rdm_manufacturer_pid.cpp * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#if defined (DEBUG_PIXELDMX) +# undef NDEBUG +#endif + #include #include #include @@ -33,6 +37,7 @@ #include "rdm_e120.h" #include "pixeltype.h" +#include "pixeldmxstore.h" #include "debug.h" @@ -72,7 +77,11 @@ const rdm::ParameterDescription RDMHandler::PARAMETER_DESCRIPTIONS[] = { { rdm::E120_MANUFACTURER_PIXEL_TYPE::code, rdm::DEVICE_DESCRIPTION_MAX_LENGTH, E120_DS_ASCII, +#if defined (CONFIG_RDM_MANUFACTURER_PIDS_SET) + E120_CC_GET_SET, +#else E120_CC_GET, +#endif 0, E120_UNITS_NONE, E120_PREFIX_NONE, @@ -84,8 +93,12 @@ const rdm::ParameterDescription RDMHandler::PARAMETER_DESCRIPTIONS[] = { }, { rdm::E120_MANUFACTURER_PIXEL_COUNT::code, 2, - E120_DS_UNSIGNED_DWORD, + E120_DS_UNSIGNED_WORD, +#if defined (CONFIG_RDM_MANUFACTURER_PIDS_SET) + E120_CC_GET_SET, +#else E120_CC_GET, +#endif 0, E120_UNITS_NONE, E120_PREFIX_NONE, @@ -97,8 +110,12 @@ const rdm::ParameterDescription RDMHandler::PARAMETER_DESCRIPTIONS[] = { }, { rdm::E120_MANUFACTURER_PIXEL_GROUPING_COUNT::code, 2, - E120_DS_UNSIGNED_DWORD, + E120_DS_UNSIGNED_WORD, +#if defined (CONFIG_RDM_MANUFACTURER_PIDS_SET) + E120_CC_GET_SET, +#else E120_CC_GET, +#endif 0, E120_UNITS_NONE, E120_PREFIX_NONE, @@ -111,7 +128,11 @@ const rdm::ParameterDescription RDMHandler::PARAMETER_DESCRIPTIONS[] = { { rdm::E120_MANUFACTURER_PIXEL_MAP::code, rdm::DEVICE_DESCRIPTION_MAX_LENGTH, E120_DS_ASCII, +#if defined (CONFIG_RDM_MANUFACTURER_PIDS_SET) + E120_CC_GET_SET, +#else E120_CC_GET, +#endif 0, E120_UNITS_NONE, E120_PREFIX_NONE, @@ -130,34 +151,35 @@ uint32_t RDMHandler::GetParameterDescriptionCount() const { #include "ws28xxdmx.h" namespace rdm { -bool handle_manufactureer_pid_get(const uint16_t nPid, __attribute__((unused)) const ManufacturerParamData *pIn, ManufacturerParamData *pOut, uint16_t& nReason) { +bool handle_manufactureer_pid_get(const uint16_t nPid, [[maybe_unused]] const ManufacturerParamData *pIn, ManufacturerParamData *pOut, uint16_t& nReason) { + DEBUG_PRINTF("nPid=%x", __builtin_bswap16(nPid)); + + auto &pixelConfiguration = PixelConfiguration::Get(); + auto &pixelDmxConfiguration = PixelDmxConfiguration::Get(); + switch (nPid) { case rdm::E120_MANUFACTURER_PIXEL_TYPE::code: { - const auto *pString = ::PixelType::GetType(WS28xxDmx::Get()->GetType()); + const auto *pString = ::pixel::pixel_get_type(pixelConfiguration.GetType()); pOut->nPdl = static_cast(strlen(pString)); memcpy(pOut->pParamData, pString, pOut->nPdl); return true; } case rdm::E120_MANUFACTURER_PIXEL_COUNT::code: { - const auto nCount = WS28xxDmx::Get()->GetCount(); - pOut->nPdl = 4; - pOut->pParamData[0] = static_cast(nCount >> 24); - pOut->pParamData[1] = static_cast(nCount >> 16); - pOut->pParamData[2] = static_cast(nCount >> 8); - pOut->pParamData[3] = static_cast(nCount); + const auto nCount = pixelConfiguration.GetCount(); + pOut->nPdl = 2; + pOut->pParamData[0] = static_cast(nCount >> 8); + pOut->pParamData[1] = static_cast(nCount); return true; } case rdm::E120_MANUFACTURER_PIXEL_GROUPING_COUNT::code: { - const auto nGroupingCount = WS28xxDmx::Get()->GetGroupingCount(); - pOut->nPdl = 4; - pOut->pParamData[0] = static_cast(nGroupingCount >> 24); - pOut->pParamData[1] = static_cast(nGroupingCount >> 16); - pOut->pParamData[2] = static_cast(nGroupingCount >> 8); - pOut->pParamData[3] = static_cast(nGroupingCount); + const auto nGroupingCount = pixelDmxConfiguration.GetGroupingCount(); + pOut->nPdl = 2; + pOut->pParamData[0] = static_cast(nGroupingCount >> 8); + pOut->pParamData[1] = static_cast(nGroupingCount); return true; } case rdm::E120_MANUFACTURER_PIXEL_MAP::code: { - const auto *pString = ::PixelType::GetMap(WS28xxDmx::Get()->GetMap()); + const auto *pString = ::pixel::pixel_get_map(pixelConfiguration.GetMap()); pOut->nPdl = static_cast(strlen(pString)); memcpy(pOut->pParamData, pString, pOut->nPdl); return true; @@ -169,4 +191,71 @@ bool handle_manufactureer_pid_get(const uint16_t nPid, __attribute__((unused)) c nReason = E120_NR_UNKNOWN_PID; return false; } +#if defined (CONFIG_RDM_MANUFACTURER_PIDS_SET) +// C++ attribute: maybe_unused (since C++17) +bool handle_manufactureer_pid_set(const bool isBroadcast, const uint16_t nPid, const rdm::ParameterDescription ¶meterDescription, const ManufacturerParamData *pIn, [[maybe_unused]] ManufacturerParamData *pOut, uint16_t& nReason) { + DEBUG_PRINTF("nPid=%x", __builtin_bswap16(nPid)); + + if (isBroadcast) { + return false; + } + + switch (nPid) { + case rdm::E120_MANUFACTURER_PIXEL_COUNT::code: { + if (pIn->nPdl == 2) { + const uint16_t nCount = pIn->pParamData[1] | pIn->pParamData[0] << 8; + + if ((nCount < parameterDescription.min_value) && (nCount > parameterDescription.max_value)) { + nReason = E120_NR_DATA_OUT_OF_RANGE; + return false; + } + + PixelDmxStore::SaveCount(nCount); + return true; + } + + nReason = E120_NR_FORMAT_ERROR; + return false; + } + case rdm::E120_MANUFACTURER_PIXEL_GROUPING_COUNT::code: { + if (pIn->nPdl == 2) { + const uint16_t nGroupingCount = pIn->pParamData[1] | pIn->pParamData[0] << 8; + + if ((nGroupingCount < parameterDescription.min_value) && (nGroupingCount > parameterDescription.max_value)) { + nReason = E120_NR_DATA_OUT_OF_RANGE; + return false; + } + + PixelDmxStore::SaveGroupingCount(nGroupingCount); + return true; + } + + nReason = E120_NR_FORMAT_ERROR; + return false; + } + case rdm::E120_MANUFACTURER_PIXEL_MAP::code: { + if (pIn->nPdl == 3) { + const auto map = ::pixel::pixel_get_map(reinterpret_cast(pIn->pParamData)); + + if (map == pixel::Map::UNDEFINED) { + nReason = E120_NR_DATA_OUT_OF_RANGE; + return false; + } + + PixelDmxStore::SaveMap(static_cast(map)); + return true; + } + + nReason = E120_NR_FORMAT_ERROR; + return false; + } + default: + break; + } + + nReason = E120_NR_UNKNOWN_PID; + return false; + +} +#endif } // namespace rdm diff --git a/scripts/build_all.sh b/scripts/build_all.sh index 0c9959e2..b2473252 100755 --- a/scripts/build_all.sh +++ b/scripts/build_all.sh @@ -1,14 +1,4 @@ #!/bin/bash -NPROC=2 - -if [ "$(uname)" == "Darwin" ]; then - NPROC=$(sysctl -a | grep machdep.cpu.core_count | cut -d ':' -f 2) -elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then - NPROC=$(nproc) -fi - -let NPROC-- - cd .. DIR=gd32_* @@ -37,8 +27,8 @@ do for m in $MAKEFILE do - make -f $m -j $NPROC clean - make -f $m -j $NPROC ENET_PHY=$i + make -f $m -j clean + make -f $m ENET_PHY=$i retVal=$? if [ $retVal -ne 0 ]; then